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_value_from_decimal(self, var, pos, value): tuple_value = value.as_tuple() text_value, format = self.get_format_and_text_from_decimal(tuple_value) text_buffer = cxBuffer.new_from_object(text_value, var.environment.encoding) format_buffer = cxBuffer.new_from_object(format, var.environment.encoding) typed_data = self.get_typed_data(var) status = oci.OCINumberFromText( var.environment.error_handle, text_buffer.cast_ptr, text_buffer.size, format_buffer.cast_ptr, format_buffer.size, var.environment.nlsNumericCharactersBuffer.cast_ptr, var.environment.nlsNumericCharactersBuffer.size, byref(typed_data[pos])) return var.environment.check_for_error( status, "NumberVar_SetValueFromDecimal()")
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
def set_value_from_decimal(self, var, pos, value): tuple_value = value.as_tuple() text_value, format = self.get_format_and_text_from_decimal(tuple_value) text_buffer = cxBuffer.new_from_object(text_value, var.environment.encoding) format_buffer = cxBuffer.new_from_object(format, var.environment.encoding) typed_data = self.get_typed_data(var) status = oci.OCINumberFromText( var.environment.error_handle, text_buffer.cast_ptr, text_buffer.size, format_buffer.cast_ptr, format_buffer.size, var.environment.nlsNumericCharactersBuffer.cast_ptr, var.environment.nlsNumericCharactersBuffer.size, byref(typed_data[pos]), ) return var.environment.check_for_error(status, "NumberVar_SetValueFromDecimal()")
def set_value_from_long(self, var, pos, value): text_value = str(value) text_buffer = cxBuffer.new_from_object(text_value, var.environment.encoding) typed_data = self.get_typed_data(var) status = oci.OCINumberFromText( var.environment.error_handle, text_buffer.cast_ptr, text_buffer.size, var.environment.numberFromStringFormatBuffer.cast_ptr, var.environment.numberFromStringFormatBuffer.size, None, 0, byref(typed_data[pos])) return var.environment.check_for_error(status, "NumberVar_SetValueFromLong()")
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_value_from_long(self, var, pos, value): text_value = str(value) text_buffer = cxBuffer.new_from_object(text_value, var.environment.encoding) typed_data = self.get_typed_data(var) status = oci.OCINumberFromText( var.environment.error_handle, text_buffer.cast_ptr, text_buffer.size, var.environment.numberFromStringFormatBuffer.cast_ptr, var.environment.numberFromStringFormatBuffer.size, None, 0, byref(typed_data[pos]), ) return var.environment.check_for_error(status, "NumberVar_SetValueFromLong()")
def set_value(self, var, pos, value): # get the buffer data and size for binding buffer = cxBuffer.new_from_object(value, var.environment.encoding) # verify there is enough space to store the value if buffer.num_characters > var.size: var.resize(buffer.num_characters) # copy the string to the Oracle buffer # TODO: can't we do better than this pointer arithmetic here?! base_ptr_address = ctypes.addressof(var.data) + var.bufferSize * pos c_length = oci.ub4.from_address(base_ptr_address) c_length.value = buffer.size string_address = base_ptr_address + ctypes.sizeof(oci.ub4) string_ptr = ctypes.c_void_p(string_address) if buffer.size: ctypes.memmove(string_ptr, buffer.ptr, buffer.size)
def set_value(self, var, pos, value): # populate the buffer and confirm the maximum size is not exceeded buffer = cxBuffer.new_from_object(value, var.environment.encoding) if var.type.is_character_data and buffer.num_characters > MAX_STRING_CHARS: raise ValueError("string data too large") elif not var.type.is_character_data and buffer.size > MAX_BINARY_BYTES: raise ValueError("binary data too large") # ensure that the buffer is large enough if buffer.size > var.bufferSize: var.resize(buffer.num_characters) # keep a copy of the string var.actual_length[pos] = buffer.size if buffer.size: pointer_to_pos = ctypes.c_void_p(ctypes.addressof(var.data) + var.bufferSize * pos) #start_index = var.bufferSize * pos #var.data[start_index:start_index+buffer.size] = buffer.ptr.raw[:buffer.size] #ctypes.memmove(byref(var.data, var.bufferSize * pos), buffer.ptr, buffer.size) ctypes.memmove(pointer_to_pos, buffer.ptr, buffer.size)
def set_value(self, var, pos, value): # populate the buffer and confirm the maximum size is not exceeded buffer = cxBuffer.new_from_object(value, var.environment.encoding) if var.type.is_character_data and buffer.num_characters > MAX_STRING_CHARS: raise ValueError("string data too large") elif not var.type.is_character_data and buffer.size > MAX_BINARY_BYTES: raise ValueError("binary data too large") # ensure that the buffer is large enough if buffer.size > var.bufferSize: var.resize(buffer.num_characters) # keep a copy of the string var.actual_length[pos] = buffer.size if buffer.size: pointer_to_pos = ctypes.c_void_p( ctypes.addressof(var.data) + var.bufferSize * pos) #start_index = var.bufferSize * pos #var.data[start_index:start_index+buffer.size] = buffer.ptr.raw[:buffer.size] #ctypes.memmove(byref(var.data, var.bufferSize * pos), buffer.ptr, buffer.size) ctypes.memmove(pointer_to_pos, buffer.ptr, buffer.size)
def connect(self, mode, twophase, newpassword): """Create a new connection object by connecting to the database.""" credential_type = oci.OCI_CRED_EXT # allocate the server handle self.server_handle = oci.POINTER(oci.OCIServer)() OCIHandleAlloc( self.environment, self.server_handle, oci.OCI_HTYPE_SERVER, "Connection_Connect(): allocate server handle" ) buffer = cxBuffer.new_from_object(self.dsn, self.environment.encoding) # attach to the server status = oci.OCIServerAttach( self.server_handle, self.environment.error_handle, buffer.cast_ptr, buffer.size, oci.OCI_DEFAULT ) self.environment.check_for_error(status, "Connection_Connect(): server attach") # allocate the service context handle self.handle = oci.POINTER(oci.OCISvcCtx)() OCIHandleAlloc( self.environment, self.handle, oci.OCI_HTYPE_SVCCTX, "Connection_Connect(): allocate service context handle" ) # set attribute for server handle status = oci.OCIAttrSet( self.handle, oci.OCI_HTYPE_SVCCTX, self.server_handle, 0, oci.OCI_ATTR_SERVER, self.environment.error_handle ) self.environment.check_for_error(status, "Connection_Connect(): set server handle") # set the internal and external names; these are needed for global # transactions but are limited in terms of the lengths of the strings if twophase: status = oci.OCIAttrSet( self.server_handle, oci.OCI_HTYPE_SERVER, "cx_Oracle", 0, oci.OCI_ATTR_INTERNAL_NAME, self.environment.error_handle, ) self.environment.check_for_error(status, "Connection_Connect(): set internal name") status = oci.OCIAttrSet( self.server_handle, oci.OCI_HTYPE_SERVER, "cx_Oracle", 0, oci.OCI_ATTR_EXTERNAL_NAME, self.environment.error_handle, ) self.environment.check_for_error(status, "Connection_Connect(): set external name") # allocate session handle self.session_handle = oci.POINTER(oci.OCISession)() OCIHandleAlloc( self.environment, self.session_handle, oci.OCI_HTYPE_SESSION, "Connection_Connect(): allocate session handle", ) # set user name in session handle buffer = cxBuffer.new_from_object(self.username, self.environment.encoding) if buffer.size > 0: credential_type = oci.OCI_CRED_RDBMS status = oci.OCIAttrSet( self.session_handle, oci.OCI_HTYPE_SESSION, buffer.ptr, buffer.size, oci.OCI_ATTR_USERNAME, self.environment.error_handle, ) self.environment.check_for_error(status, "Connection_Connect(): set user name") # set password in session handle buffer = cxBuffer.new_from_object(self.password, self.environment.encoding) if buffer.size > 0: credential_type = oci.OCI_CRED_RDBMS status = oci.OCIAttrSet( self.session_handle, oci.OCI_HTYPE_SESSION, buffer.ptr, buffer.size, oci.OCI_ATTR_PASSWORD, self.environment.error_handle, ) self.environment.check_for_error(status, "Connection_Connect(): set password") if hasattr(oci, "OCI_ATTR_DRIVER_NAME"): buffer = cxBuffer.new_from_object(DRIVER_NAME, self.environment.encoding) status = oci.OCIAttrSet( self.session_handle, oci.OCI_HTYPE_SESSION, buffer.ptr, buffer.size, oci.OCI_ATTR_DRIVER_NAME, self.environment.error_handle, ) self.environment.check_for_error(status, "Connection_Connect(): set driver name") # set the session handle on the service context handle status = oci.OCIAttrSet( self.handle, oci.OCI_HTYPE_SVCCTX, self.session_handle, 0, oci.OCI_ATTR_SESSION, self.environment.error_handle, ) self.environment.check_for_error(status, "Connection_Connect(): set session handle") # if a new password has been specified, change it which will also # establish the session # TODO: implement change_password if newpassword: return self.change_password(self.password) # TODO: removed one arg, what about the new password?!?! # begin the session status = oci.OCISessionBegin( self.handle, self.environment.error_handle, self.session_handle, credential_type, mode ) try: self.environment.check_for_error(status, "Connection_Connect(): begin session") except Error: self.session_handle = oci.POINTER( oci.OCISession )() # who frees the session handle? the failed session begin call? raise
def set_buffer(value, encoding): if value is None: raise # TODO: what? return cxBuffer.new_from_object(value, encoding)
def connect(self, mode, twophase, newpassword): """Create a new connection object by connecting to the database.""" credential_type = oci.OCI_CRED_EXT # allocate the server handle self.server_handle = oci.POINTER(oci.OCIServer)() OCIHandleAlloc(self.environment, self.server_handle, oci.OCI_HTYPE_SERVER, "Connection_Connect(): allocate server handle") buffer = cxBuffer.new_from_object(self.dsn, self.environment.encoding) # attach to the server status = oci.OCIServerAttach(self.server_handle, self.environment.error_handle, buffer.cast_ptr, buffer.size, oci.OCI_DEFAULT) self.environment.check_for_error( status, "Connection_Connect(): server attach") # allocate the service context handle self.handle = oci.POINTER(oci.OCISvcCtx)() OCIHandleAlloc( self.environment, self.handle, oci.OCI_HTYPE_SVCCTX, "Connection_Connect(): allocate service context handle") # set attribute for server handle status = oci.OCIAttrSet(self.handle, oci.OCI_HTYPE_SVCCTX, self.server_handle, 0, oci.OCI_ATTR_SERVER, self.environment.error_handle) self.environment.check_for_error( status, "Connection_Connect(): set server handle") # set the internal and external names; these are needed for global # transactions but are limited in terms of the lengths of the strings if twophase: status = oci.OCIAttrSet(self.server_handle, oci.OCI_HTYPE_SERVER, "cx_Oracle", 0, oci.OCI_ATTR_INTERNAL_NAME, self.environment.error_handle) self.environment.check_for_error( status, "Connection_Connect(): set internal name") status = oci.OCIAttrSet(self.server_handle, oci.OCI_HTYPE_SERVER, "cx_Oracle", 0, oci.OCI_ATTR_EXTERNAL_NAME, self.environment.error_handle) self.environment.check_for_error( status, "Connection_Connect(): set external name") # allocate session handle self.session_handle = oci.POINTER(oci.OCISession)() OCIHandleAlloc(self.environment, self.session_handle, oci.OCI_HTYPE_SESSION, "Connection_Connect(): allocate session handle") # set user name in session handle buffer = cxBuffer.new_from_object(self.username, self.environment.encoding) if buffer.size > 0: credential_type = oci.OCI_CRED_RDBMS status = oci.OCIAttrSet(self.session_handle, oci.OCI_HTYPE_SESSION, buffer.ptr, buffer.size, oci.OCI_ATTR_USERNAME, self.environment.error_handle) self.environment.check_for_error( status, "Connection_Connect(): set user name") # set password in session handle buffer = cxBuffer.new_from_object(self.password, self.environment.encoding) if buffer.size > 0: credential_type = oci.OCI_CRED_RDBMS status = oci.OCIAttrSet(self.session_handle, oci.OCI_HTYPE_SESSION, buffer.ptr, buffer.size, oci.OCI_ATTR_PASSWORD, self.environment.error_handle) self.environment.check_for_error( status, "Connection_Connect(): set password") if hasattr(oci, 'OCI_ATTR_DRIVER_NAME'): buffer = cxBuffer.new_from_object(DRIVER_NAME, self.environment.encoding) status = oci.OCIAttrSet(self.session_handle, oci.OCI_HTYPE_SESSION, buffer.ptr, buffer.size, oci.OCI_ATTR_DRIVER_NAME, self.environment.error_handle) self.environment.check_for_error( status, "Connection_Connect(): set driver name") # set the session handle on the service context handle status = oci.OCIAttrSet(self.handle, oci.OCI_HTYPE_SVCCTX, self.session_handle, 0, oci.OCI_ATTR_SESSION, self.environment.error_handle) self.environment.check_for_error( status, "Connection_Connect(): set session handle") # if a new password has been specified, change it which will also # establish the session #TODO: implement change_password if newpassword: return self.change_password( self.password ) # TODO: removed one arg, what about the new password?!?! # begin the session status = oci.OCISessionBegin(self.handle, self.environment.error_handle, self.session_handle, credential_type, mode) try: self.environment.check_for_error( status, "Connection_Connect(): begin session") except Error: self.session_handle = oci.POINTER(oci.OCISession)( ) # who frees the session handle? the failed session begin call? raise