Example #1
0
    def get_value(self, var, pos):
        """Returns the value stored at the given array position."""
        if not python3_or_better():
            types = (vt_Boolean, vt_Integer)
        else:
            types = (vt_Boolean,)

        typed_data = self.get_typed_data(var)

        if var.type in types:
            c_integer_value = ctypes.c_long()
            status = oci.OCINumberToInt(
                var.environment.error_handle,
                byref(typed_data[pos]),
                ctypes.sizeof(c_integer_value),
                oci.OCI_NUMBER_SIGNED,
                byref(c_integer_value),
            )
            integer_value = c_integer_value.value
            var.environment.check_for_error(status, "NumberVar_GetValue(): as integer")

            if not python3_or_better():
                if var.type is vt_Integer:
                    return integer_value

            return bool(integer_value)

        if var.type in (vt_NumberAsString, vt_LongInteger):
            c_string = ctypes.create_string_buffer(200)
            cast_c_string = ctypes.cast(c_string, oci.POINTER(oci.ub1))

            c_string_length = oci.ub4()
            c_string_length.value = ctypes.sizeof(c_string)

            typed_data = self.get_typed_data(var)
            status = oci.OCINumberToText(
                var.environment.error_handle,
                byref(typed_data[pos]),
                var.environment.numberToStringFormatBuffer.cast_ptr,
                var.environment.numberToStringFormatBuffer.size,
                None,
                0,
                byref(c_string_length),
                cast_c_string,
            )
            var.environment.check_for_error(status, "NumberVar_GetValue(): as string")

            python_string = c_string.value

            unicode_str = cxString_from_encoded_string(python_string, var.environment.encoding)

            if var.type is vt_NumberAsString:
                return unicode_str

            try:
                return int(unicode_str)
            except ValueError:
                pass

        return oracle_number_to_python_float(var.environment, byref(typed_data[pos]))
 def set_max_data_size(self):
     if (self.type == vt_String or self.type == vt_FixedChar) and self.size > self.type.size:
         c_size = oci.ub4()
         status = oci.OCIAttrSet(self.bind_handle, oci.OCI_HTYPE_BIND,
                 byref(c_size), 0, oci.OCI_ATTR_MAXDATA_SIZE,
                 self.environment.error_handle)
         self.type.size = c_size.value
         self.environment.check_for_error(status, "Variable_InternalBind(): set max data size")
Example #3
0
    def get_value(self, var, pos):
        """Returns the value stored at the given array position."""
        if not python3_or_better():
            types = (vt_Boolean, vt_Integer)
        else:
            types = (vt_Boolean, )

        typed_data = self.get_typed_data(var)

        if var.type in types:
            c_integer_value = ctypes.c_long()
            status = oci.OCINumberToInt(var.environment.error_handle,
                                        byref(typed_data[pos]),
                                        ctypes.sizeof(c_integer_value),
                                        oci.OCI_NUMBER_SIGNED,
                                        byref(c_integer_value))
            integer_value = c_integer_value.value
            var.environment.check_for_error(
                status, "NumberVar_GetValue(): as integer")

            if not python3_or_better():
                if var.type is vt_Integer:
                    return integer_value

            return bool(integer_value)

        if var.type in (vt_NumberAsString, vt_LongInteger):
            c_string = ctypes.create_string_buffer(200)
            cast_c_string = ctypes.cast(c_string, oci.POINTER(oci.ub1))

            c_string_length = oci.ub4()
            c_string_length.value = ctypes.sizeof(c_string)

            typed_data = self.get_typed_data(var)
            status = oci.OCINumberToText(
                var.environment.error_handle, byref(typed_data[pos]),
                var.environment.numberToStringFormatBuffer.cast_ptr,
                var.environment.numberToStringFormatBuffer.size, None, 0,
                byref(c_string_length), cast_c_string)
            var.environment.check_for_error(status,
                                            "NumberVar_GetValue(): as string")

            python_string = c_string.value

            unicode_str = cxString_from_encoded_string(
                python_string, var.environment.encoding)

            if var.type is vt_NumberAsString:
                return unicode_str

            try:
                return int(unicode_str)
            except ValueError:
                pass

        return oracle_number_to_python_float(var.environment,
                                             byref(typed_data[pos]))
Example #4
0
    def internal_bind(self):
        """Allocate a variable and bind it to the given statement."""

        if self.is_array:
            alloc_elems = self.allocelems
            actual_elements_ref = byref(self.c_actual_elements)
        else:
            alloc_elems = 0
            actual_elements_ref = oci.POINTER(oci.ub4)()

        # perform the bind
        if self.bound_name:
            buffer = cxBuffer.new_from_object(self.bound_name,
                                              self.environment.encoding)
            status = oci.OCIBindByName(self.bound_cursor_handle,
                                       byref(self.bind_handle),
                                       self.environment.error_handle,
                                       buffer.cast_ptr, buffer.size, self.data,
                                       self.bufferSize, self.type.oracle_type,
                                       self.indicator, self.actual_length,
                                       self.return_code, alloc_elems,
                                       actual_elements_ref, oci.OCI_DEFAULT)
        else:
            status = oci.OCIBindByPos(self.bound_cursor_handle,
                                      byref(self.bind_handle),
                                      self.environment.error_handle,
                                      self.bound_pos, self.data,
                                      self.bufferSize, self.type.oracle_type,
                                      self.indicator, self.actual_length,
                                      self.return_code, alloc_elems,
                                      actual_elements_ref, oci.OCI_DEFAULT)

        self.environment.check_for_error(status, "Variable_InternalBind()")

        if not python3_or_better():
            # set the charset form and id if applicable
            if self.type.charset_form != oci.SQLCS_IMPLICIT:
                c_charset_form = oci.ub1(self.type.charset_form)
                status = oci.OCIAttrSet(self.bind_handle, oci.OCI_HTYPE_BIND,
                                        byref(c_charset_form), 0,
                                        oci.OCI_ATTR_CHARSET_FORM,
                                        self.environment.error_handle)
                self.environment.check_for_error(
                    status, "Variable_InternalBind(): set charset form")
                self.type.charset_form = c_charset_form.value

                c_buffer_size = oci.ub4(self.bufferSize)
                status = oci.OCIAttrSet(self.bind_handle, oci.OCI_HTYPE_BIND,
                                        byref(c_buffer_size), 0,
                                        oci.OCI_ATTR_MAXDATA_SIZE,
                                        self.environment.error_handle)
                self.environment.check_for_error(
                    status, "Variable_InternalBind(): set max data size")
                self.bufferSize = self.maxlength = c_buffer_size.value

        # set the max data size for strings
        self.set_max_data_size()
 def set_max_data_size(self):
     # TODO: well, self.type here always is vt_FixedChar. But we can refactor this better, the code in the if is the same for strings
     if (self.type == vt_String or self.type == vt_FixedChar) and self.size > self.type.size:
         c_size = oci.ub4()
         status = oci.OCIAttrSet(self.bind_handle, oci.OCI_HTYPE_BIND,
                 byref(c_size), 0, oci.OCI_ATTR_MAXDATA_SIZE,
                 self.environment.error_handle)
         self.type.size = c_size.value
         self.environment.check_for_error(status, "Variable_InternalBind(): set max data size")
    def _internal_size(self, ):
        c_length = oci.ub4()
        typed_data = self._get_lobvar_typed_data()
        status = oci.OCILobGetLength(self.lob_var.connection.handle, self.lob_var.environment.error_handle,
                                     typed_data[self.pos], byref(c_length))
    
        self.lob_var.environment.check_for_error(status, "ExternalLobVar_InternalSize()")

        return c_length.value
    def _internal_size(self, ):
        c_length = oci.ub4()
        typed_data = self._get_lobvar_typed_data()
        status = oci.OCILobGetLength(self.lob_var.connection.handle,
                                     self.lob_var.environment.error_handle,
                                     typed_data[self.pos], byref(c_length))

        self.lob_var.environment.check_for_error(
            status, "ExternalLobVar_InternalSize()")

        return c_length.value
Example #8
0
 def set_max_data_size(self):
     if (self.type == vt_String
             or self.type == vt_FixedChar) and self.size > self.type.size:
         c_size = oci.ub4()
         status = oci.OCIAttrSet(self.bind_handle, oci.OCI_HTYPE_BIND,
                                 byref(c_size), 0,
                                 oci.OCI_ATTR_MAXDATA_SIZE,
                                 self.environment.error_handle)
         self.type.size = c_size.value
         self.environment.check_for_error(
             status, "Variable_InternalBind(): set max data size")
Example #9
0
 def set_max_data_size(self):
     # TODO: well, self.type here always is vt_FixedChar. But we can refactor this better, the code in the if is the same for strings
     if (self.type == vt_String
             or self.type == vt_FixedChar) and self.size > self.type.size:
         c_size = oci.ub4()
         status = oci.OCIAttrSet(self.bind_handle, oci.OCI_HTYPE_BIND,
                                 byref(c_size), 0,
                                 oci.OCI_ATTR_MAXDATA_SIZE,
                                 self.environment.error_handle)
         self.type.size = c_size.value
         self.environment.check_for_error(
             status, "Variable_InternalBind(): set max data size")
Example #10
0
    def __init__(self, cursor, num_elements, type, size):
        self.environment = cursor.connection.environment

        self.bind_handle = oci.POINTER(oci.OCIBind)()
        self.define_handle = oci.POINTER(oci.OCIDefine)()
        self.bound_cursor_handle = oci.POINTER(oci.OCIStmt)()
        self.bound_name = None
        self.inconverter = None  # public
        self.outconverter = None  # public
        self.bound_pos = 0

        if num_elements < 1:
            self.numElements = self.allocelems = 1
        else:
            self.numElements = self.allocelems = num_elements

        # the OCI will keep a ref to this across multiple calls, so we have to keep one too.
        # to avoid duplication of python-level vs c-level fields, self.actual_elements is a property
        self.c_actual_elements = oci.ub4(0)
        self.internal_fetch_num = 0
        self.is_array = False
        self.is_allocated_internally = True
        self.type = type
        self.actual_length = oci.POINTER(oci.ub2)()
        self.return_code = oci.POINTER(oci.ub2)()

        # set the maximum length of the variable, ensure that a minimum of
        # 2 bytes is allocated to ensure that the array size check works
        self.size = type.size
        if type.is_variable_length:
            if size < ctypes.sizeof(oci.ub2):
                size = ctypes.sizeof(oci.ub2)
            self.size = size

        # allocate the data for the variable
        self.allocate_data()

        # allocate the indicator for the variable
        self.indicator = (self.numElements * oci.sb2)()

        # ensure that all variable values start out NULL
        for i in xrange(self.numElements):
            self.indicator[i] = oci.OCI_IND_NULL

        # for variable length data, also allocate the return code
        if type.is_variable_length:
            self.return_code = (self.numElements * oci.ub2)()

        # perform extended initialization
        if self.type.initialize_proc:
            self.type.initialize_proc(self, cursor)
    def __init__(self, cursor, num_elements, type, size):
        self.environment = cursor.connection.environment

        self.bind_handle = oci.POINTER(oci.OCIBind)()
        self.define_handle = oci.POINTER(oci.OCIDefine)()
        self.bound_cursor_handle = oci.POINTER(oci.OCIStmt)()
        self.bound_name = None
        self.inconverter = None # public
        self.outconverter = None  # public
        self.bound_pos = 0

        if num_elements < 1:
            self.numElements = self.allocelems = 1
        else:
            self.numElements = self.allocelems = num_elements
        
        # the OCI will keep a ref to this across multiple calls, so we have to keep one too.
        # to avoid duplication of python-level vs c-level fields, self.actual_elements is a property
        self.c_actual_elements = oci.ub4(0)
        self.internal_fetch_num = 0
        self.is_array = False
        self.is_allocated_internally = True
        self.type = type
        self.actual_length = oci.POINTER(oci.ub2)()
        self.return_code = oci.POINTER(oci.ub2)()

        # set the maximum length of the variable, ensure that a minimum of
        # 2 bytes is allocated to ensure that the array size check works
        self.size = type.size
        if type.is_variable_length:
            if size < ctypes.sizeof(oci.ub2):
                size = ctypes.sizeof(oci.ub2)
            self.size = size

        # allocate the data for the variable
        self.allocate_data()

        # allocate the indicator for the variable
        self.indicator = (self.numElements * oci.sb2)()

        # ensure that all variable values start out NULL
        for i in xrange(self.numElements):
            self.indicator[i] = oci.OCI_IND_NULL

        # for variable length data, also allocate the return code
        if type.is_variable_length:
            self.return_code = (self.numElements * oci.ub2)()

        # perform extended initialization
        if self.type.initialize_proc:
            self.type.initialize_proc(self, cursor)
    def internal_bind(self):
        """Allocate a variable and bind it to the given statement."""

        if self.is_array:
            alloc_elems = self.allocelems
            actual_elements_ref = byref(self.c_actual_elements)
        else:
            alloc_elems = 0
            actual_elements_ref = oci.POINTER(oci.ub4)()
        
        # perform the bind
        if self.bound_name:
            buffer = cxBuffer.new_from_object(self.bound_name, self.environment.encoding)
            status = oci.OCIBindByName(self.bound_cursor_handle, byref(self.bind_handle),
                        self.environment.error_handle, buffer.cast_ptr,
                        buffer.size, self.data, self.bufferSize,
                        self.type.oracle_type, self.indicator, self.actual_length,
                        self.return_code, alloc_elems,
                        actual_elements_ref, oci.OCI_DEFAULT)
        else:
            status = oci.OCIBindByPos(self.bound_cursor_handle, byref(self.bind_handle),
                        self.environment.error_handle, self.bound_pos, self.data,
                        self.bufferSize, self.type.oracle_type, self.indicator,
                        self.actual_length, self.return_code, alloc_elems,
                        actual_elements_ref, oci.OCI_DEFAULT)
        
        self.environment.check_for_error(status, "Variable_InternalBind()")

        if not python3_or_better():
            # set the charset form and id if applicable
            if self.type.charset_form != oci.SQLCS_IMPLICIT:
                c_charset_form = oci.ub1(self.type.charset_form)
                status = oci.OCIAttrSet(self.bind_handle, oci.OCI_HTYPE_BIND,
                        byref(c_charset_form), 0, oci.OCI_ATTR_CHARSET_FORM,
                        self.environment.error_handle)
                self.environment.check_for_error(status, "Variable_InternalBind(): set charset form")
                self.type.charset_form = c_charset_form.value
                
                c_buffer_size = oci.ub4(self.bufferSize)
                status = oci.OCIAttrSet(self.bind_handle, oci.OCI_HTYPE_BIND,
                        byref(c_buffer_size), 0, oci.OCI_ATTR_MAXDATA_SIZE,
                        self.environment.error_handle)
                self.environment.check_for_error(status, "Variable_InternalBind(): set max data size")
                self.bufferSize = self.maxlength = c_buffer_size.value

        # set the max data size for strings
        self.set_max_data_size()
    def _internal_read(self, offset, amount):
        from lobvar import vt_CLOB, vt_NCLOB
        lob_type = self.lob_var.type

        if self.lob_var.is_file:
            self._internal_open(oci.OCI_FILE_READONLY,
                                "ExternalLobVar_FileOpen()")

        if lob_type == vt_CLOB:
            buffer_size = amount * self.lob_var.environment.maxBytesPerCharacter
        elif lob_type == vt_NCLOB:
            buffer_size = amount * 2
        else:
            buffer_size = amount

        buffer = ctypes.create_string_buffer(buffer_size)

        typed_data = self._get_lobvar_typed_data()
        c_length = oci.ub4(amount)
        arg8 = oci.OCILobRead.argtypes[8]()
        status = oci.OCILobRead(self.lob_var.connection.handle,
                                self.lob_var.environment.error_handle,
                                typed_data[self.pos], byref(c_length), offset,
                                buffer, buffer_size, None, arg8, 0,
                                self.lob_var.type.charset_form)

        length = c_length.value  # unused?

        try:
            self.lob_var.environment.check_for_error(
                status, "ExternalLobVar_LobRead()")
        except DatabaseError:
            # don't know why cx oracle does not try to catch the error in the close. but if we do, there are 2 errors to report.
            try:
                self._internal_close("ExternalLobVar_FileClose()")
            except DatabaseError:
                pass
            raise

        if self.lob_var.is_file:
            self._internal_close("ExternalLobVar_FileClose()")

        return buffer.value
Example #14
0
def oracle_timestamp_to_python_date(environment, value):
    """Return a Python date object given an Oracle timestamp."""
    year = oci.sb2()
    month = oci.ub1()
    day = oci.ub1()
    hour = oci.ub1()
    minute = oci.ub1()
    second = oci.ub1()
    fsecond = oci.ub4()
    
    status = oci.OCIDateTimeGetDate(environment.handle, environment.error_handle,
                                    value, byref(year), byref(month), byref(day))
    environment.check_for_error(status, "OracleTimestampToPythonDate(): date portion")
    
    status = oci.OCIDateTimeGetTime(environment.handle, environment.error_handle,
                                    value, byref(hour), byref(minute), byref(second), byref(fsecond))
    environment.check_for_error(status, "OracleTimestampToPythonDate(): time portion")
    
    return datetime(year.value, month.value, day.value, hour.value, minute.value, second.value, fsecond.value / 1000)
Example #15
0
    def _write(self, var, pos, data_obj, offset):
        """Write data to the LOB variable."""

        # verify the data type
        var_type = var.type
        if var_type == vt_BFILE:
            raise TypeError("BFILEs are read only")

        if var_type == vt_BLOB:
            buffer = cxBuffer.new_from_object(data_obj,
                                              var.environment.encoding)
            amount = buffer.size
        elif not python3_or_better() and var_type == vt_NCLOB:
            buffer = cxBuffer.new_from_object(data_obj,
                                              var.environment.nencoding)
            amount = buffer.size
        else:
            buffer = cxBuffer.new_from_object(data_obj,
                                              var.environment.encoding)
            if var.environment.fixedWidth and var.environment.maxBytesPerCharacter > 1:
                amount = buffer.size / var.environment.maxBytesPerCharacter
            else:
                amount = buffer.size

        # nothing to do if no data to write
        if amount == 0:
            return amount

        typed_data = self.get_typed_data(var)
        c_amount = oci.ub4(amount)
        callback_lob_write_type = oci.OCILobWrite.argtypes[9]
        null_oci_callback = callback_lob_write_type()
        status = oci.OCILobWrite(var.connection.handle,
                                 var.environment.error_handle, typed_data[pos],
                                 byref(c_amount), offset, buffer.ptr,
                                 buffer.size, oci.OCI_ONE_PIECE, None,
                                 null_oci_callback, 0, var.type.charset_form)

        var.environment.check_for_error(status, "LobVar_Write()")
        amount = c_amount.value  # not sure if the write can change it, i dont think so, but just for correctness

        return amount
Example #16
0
def oracle_timestamp_to_python_date(environment, value):
    """Return a Python date object given an Oracle timestamp."""
    year = oci.sb2()
    month = oci.ub1()
    day = oci.ub1()
    hour = oci.ub1()
    minute = oci.ub1()
    second = oci.ub1()
    fsecond = oci.ub4()

    status = oci.OCIDateTimeGetDate(
        environment.handle, environment.error_handle, value, byref(year), byref(month), byref(day)
    )
    environment.check_for_error(status, "OracleTimestampToPythonDate(): date portion")

    status = oci.OCIDateTimeGetTime(
        environment.handle, environment.error_handle, value, byref(hour), byref(minute), byref(second), byref(fsecond)
    )
    environment.check_for_error(status, "OracleTimestampToPythonDate(): time portion")

    return datetime(year.value, month.value, day.value, hour.value, minute.value, second.value, fsecond.value / 1000)
    def _internal_read(self, offset, amount):
        from lobvar import vt_CLOB, vt_NCLOB
        lob_type = self.lob_var.type
        
        if self.lob_var.is_file:
            self._internal_open(oci.OCI_FILE_READONLY, "ExternalLobVar_FileOpen()")
        
        if lob_type == vt_CLOB:
            buffer_size = amount * self.lob_var.environment.maxBytesPerCharacter
        elif lob_type == vt_NCLOB:
            buffer_size = amount * 2
        else:
            buffer_size = amount

        buffer = ctypes.create_string_buffer(buffer_size)
        
        typed_data = self._get_lobvar_typed_data()
        c_length = oci.ub4(amount)
        arg8 = oci.OCILobRead.argtypes[8]()
        status = oci.OCILobRead(self.lob_var.connection.handle,
                self.lob_var.environment.error_handle,
                typed_data[self.pos], byref(c_length), offset, buffer,
                buffer_size, None, arg8, 0, self.lob_var.type.charset_form)
        
        length = c_length.value # unused?
        
        try:
            self.lob_var.environment.check_for_error(status, "ExternalLobVar_LobRead()")
        except DatabaseError:
            # don't know why cx oracle does not try to catch the error in the close. but if we do, there are 2 errors to report.
            try:
                self._internal_close("ExternalLobVar_FileClose()")
            except DatabaseError:
                pass
            raise
    
        if self.lob_var.is_file:
            self._internal_close("ExternalLobVar_FileClose()")
            
        return buffer.value
Example #18
0
    def _write(self, var, pos, data_obj, offset):
        """Write data to the LOB variable."""
        
        # verify the data type
        var_type = var.type
        if var_type == vt_BFILE:
            raise TypeError("BFILEs are read only")
        
        if var_type == vt_BLOB:
            buffer = cxBuffer.new_from_object(data_obj, var.environment.encoding)
            amount = buffer.size
        elif not python3_or_better() and var_type == vt_NCLOB:
            buffer = cxBuffer.new_from_object(data_obj, var.environment.nencoding)
            amount = buffer.size
        else:
            buffer = cxBuffer.new_from_object(data_obj, var.environment.encoding)
            if var.environment.fixedWidth and var.environment.maxBytesPerCharacter > 1:
                amount = buffer.size / var.environment.maxBytesPerCharacter
            else:
                amount = buffer.size
    
        # nothing to do if no data to write
        if amount == 0:
            return amount
        
        typed_data = self.get_typed_data(var)
        c_amount = oci.ub4(amount)
        callback_lob_write_type = oci.OCILobWrite.argtypes[9]
        null_oci_callback = callback_lob_write_type()
        status = oci.OCILobWrite(var.connection.handle,
                var.environment.error_handle, typed_data[pos], byref(c_amount), offset,
                buffer.ptr, buffer.size, oci.OCI_ONE_PIECE, None, null_oci_callback, 0,
                var.type.charset_form)

        var.environment.check_for_error(status, "LobVar_Write()")
        amount = c_amount.value # not sure if the write can change it, i dont think so, but just for correctness
        
        return amount