def make_auth( self, seed, username=None, password=None, database=None, charset=33, client_flags=0, max_allowed_packet=1073741824, ): """Make a MySQL Authentication packet""" if not seed: raise errors.ProgrammingError("Seed missing") auth = self._prepare_auth(username, password, database, client_flags, seed) data = ( utils.int4store(client_flags) + utils.int4store(max_allowed_packet) + utils.int1store(charset) + b"\x00" * 23 + auth[0] + auth[1] + auth[2] ) return data
def make_auth_ssl(self, charset=33, client_flags=0, max_allowed_packet=1073741824): """Make a SSL authentication packet""" return utils.int4store(client_flags) +\ utils.int4store(max_allowed_packet) +\ utils.int1store(charset) +\ b'\x00' * 23
def binlog_dump(self, log_file, offset): """ COM_BINLOG_DUMP +=============================================+ | packet header | packet length 0 : 3 | | +-------------------------+ | | sequence number 3 : 1 | +============================================+ | command packet | command code 4 : 1 | COM_BINLOG_DUMP | +------------------------―+ | | offset 5 : 4 | | +-------------------------+ | | flags 9 : 2 | | +-------------------------+ | | server id 11 : 4| | +-------------------------+ | | log name 15 : x| +============================================+ """ payload = '' payload += utils.int1store(ServerCmd.BINLOG_DUMP) payload += utils.int4store(offset) payload += utils.int2store(0) payload += utils.int4store(self.get_server_id()) payload += log_file payload += '\x00' log.debug("len(payload) = %d" % len(payload)) # send BIGLOGDUMP command and parse ok packet response. self._socket.send(payload, 0) ok_packet = self._socket.recv() parser = MySQLProtocol() ok_packet = parser.parse_ok(ok_packet) print ok_packet
def make_auth_ssl(self, charset=33, client_flags=0, max_allowed_packet=1073741824): """Make a SSL authentication packet""" return utils.int4store(client_flags) + \ utils.int4store(max_allowed_packet) + \ utils.int1store(charset) + \ '\x00' * 23
def binlog_dump(self, log_file, offset): """ COM_BINLOG_DUMP +=============================================+ | packet header | packet length 0 : 3 | | +-------------------------+ | | sequence number 3 : 1 | +============================================+ | command packet | command code 4 : 1 | COM_BINLOG_DUMP | +------------------------―+ | | offset 5 : 4 | | +-------------------------+ | | flags 9 : 2 | | +-------------------------+ | | server id 11 : 4| | +-------------------------+ | | log name 15 : x| +============================================+ """ payload = "" payload += utils.int1store(ServerCmd.BINLOG_DUMP) payload += utils.int4store(offset) payload += utils.int2store(0) payload += utils.int4store(self.get_server_id()) payload += log_file payload += "\x00" log.debug("len(payload) = %d" % len(payload)) # send BIGLOGDUMP command and parse ok packet response. self._socket.send(payload, 0) ok_packet = self._socket.recv() parser = MySQLProtocol() ok_packet = parser.parse_ok(ok_packet) print ok_packet
def make_auth(self, seed, username=None, password=None, database=None, charset=33, client_flags=0, max_allowed_packet=1073741824): """Make a MySQL Authentication packet""" if not seed: raise errors.ProgrammingError('Seed missing') auth = self._prepare_auth(username, password, database, client_flags, seed) return utils.int4store(client_flags) +\ utils.int4store(max_allowed_packet) +\ utils.int1store(charset) +\ '\x00' * 23 + auth[0] + auth[1] + auth[2]
def _prepare_stmt_send_long_data(self, statement, param, data): """Prepare long data for prepared statments Returns a string. """ packet = (utils.int4store(statement) + utils.int2store(param) + data) return packet
def _prepare_binary_timestamp(self, value): """Prepare a timestamp object for the MySQL binary protocol This method prepares a timestamp of type datetime.datetime or datetime.date for sending over the MySQL binary protocol. A tuple is returned with the prepared value and field type as elements. Raises ValueError when the argument value is of invalid type. Returns a tuple. """ if isinstance(value, datetime.datetime): field_type = FieldType.DATETIME elif isinstance(value, datetime.date): field_type = FieldType.DATE else: raise ValueError( "Argument must a datetime.datetime or datetime.date") packed = (utils.int2store(value.year) + utils.int1store(value.month) + utils.int1store(value.day)) if isinstance(value, datetime.datetime): packed = (packed + utils.int1store(value.hour) + utils.int1store(value.minute) + utils.int1store(value.second)) if value.microsecond > 0: packed += utils.int4store(value.microsecond) packed = utils.int1store(len(packed)) + packed return (packed, field_type)
def _prepare_stmt_send_long_data(self, statement, param, data): """Prepare long data for prepared statements Returns a string. """ packet = utils.int4store(statement) + utils.int2store(param) + data return packet
def _prepare_binary_time(self, value): """Prepare a time object for the MySQL binary protocol This method prepares a time object of type datetime.timedelta or datetime.time for sending over the MySQL binary protocol. A tuple is returned with the prepared value and field type as elements. Raises ValueError when the argument value is of invalid type. Returns a tuple. """ if not isinstance(value, (datetime.timedelta, datetime.time)): raise ValueError("Argument must a datetime.timedelta or datetime.time") field_type = FieldType.TIME negative = 0 mcs = None packed = b"" if isinstance(value, datetime.timedelta): if value.days < 0: negative = 1 (hours, remainder) = divmod(value.seconds, 3600) (mins, secs) = divmod(remainder, 60) packed += ( utils.int4store(abs(value.days)) + utils.int1store(hours) + utils.int1store(mins) + utils.int1store(secs) ) mcs = value.microseconds else: packed += ( utils.int4store(0) + utils.int1store(value.hour) + utils.int1store(value.minute) + utils.int1store(value.second) ) mcs = value.microsecond if mcs: packed += utils.int4store(mcs) packed = utils.int1store(negative) + packed packed = utils.int1store(len(packed)) + packed return (packed, field_type)
def cmd_stmt_reset(self, statement_id): """Reset data for prepared statement sent as long data The result is a dictionary with OK packet information. Returns a dict() """ self._handle_ok((yield from self._send_cmd(ServerCmd.STMT_RESET,int4store(statement_id))))
def cmd_stmt_close(self, statement_id): """Deallocate a prepared MySQL statement This method deallocates the prepared statement using the statement_id. Note that the MySQL server does not return anything. """ self._send_cmd(ServerCmd.STMT_CLOSE, int4store(statement_id), expect_response=False)
def test_int4store(self): """Use int4store to pack an integer (2^32) as a string.""" data = 2**(32-1) exp = struct.pack('<I',data) try: result = utils.int4store(data) except ValueError, e: self.fail("int4store failed: %s" % e)
def cmd_stmt_close(self, statement_id): """Deallocate a prepared MySQL statement This method deallocates the prepared statement using the statement_id. Note that the MySQL server does not return anything. """ rd = yield from self._send_cmd(ServerCmd.STMT_CLOSE, int4store(statement_id), expect_response=False)
def test_int4store(self): """Use int4store to pack an integer (2^32) as a string.""" data = 2**(32 - 1) exp = struct.pack('<I', data) try: result = utils.int4store(data) except ValueError, e: self.fail("int4store failed: %s" % e)
def _prepare_binary_time(self, value): """Prepare a time object for the MySQL binary protocol This method prepares a time object of type datetime.timedelta or datetime.time for sending over the MySQL binary protocol. A tuple is returned with the prepared value and field type as elements. Raises ValueError when the argument value is of invalid type. Returns a tuple. """ if not isinstance(value, (datetime.timedelta, datetime.time)): raise ValueError( "Argument must a datetime.timedelta or datetime.time") field_type = FieldType.TIME negative = 0 mcs = None packed = '' if isinstance(value, datetime.timedelta): if value.days < 0: negative = 1 (hours, remainder) = divmod(value.seconds, 3600) (mins, secs) = divmod(remainder, 60) packed += (utils.int4store(abs(value.days)) + utils.int1store(hours) + utils.int1store(mins) + utils.int1store(secs)) mcs = value.microseconds else: packed += (utils.int4store(0) + utils.int1store(value.hour) + utils.int1store(value.minute) + utils.int1store(value.second)) mcs = value.microsecond if mcs: packed += utils.int4store(mcs) packed = utils.int1store(negative) + packed packed = utils.int1store(len(packed)) + packed return (packed, field_type)
def cmd_process_kill(self, mysql_pid): """Kill a MySQL process This method send the PROCESS_KILL command to the server along with the process ID. The result is a dictionary with the OK packet information. Returns a dict() """ return self._handle_ok((yield from self._send_cmd(ServerCmd.PROCESS_KILL, int4store(mysql_pid))))
def test_int4store(self): """Use int4store to pack an integer (2^32) as a string.""" data = 2 ** (32 - 1) exp = struct.pack('<I', data) try: result = utils.int4store(data) except ValueError as err: self.fail("int4store failed: {0}".format(str(err))) else: self._check_int_result(result, exp, data)
def test_int4store(self): """Use int4store to pack an integer (2^32) as a string.""" data = 2**(32 - 1) exp = struct.pack('<I', data) try: result = utils.int4store(data) except ValueError as err: self.fail("int4store failed: {0}".format(str(err))) else: self._check_int_result(result, exp, data)
def cmd_refresh(self, options): """Send the Refresh command to the MySQL server This method sends the Refresh command to the MySQL server. The options argument should be a bitwise value using constants.RefreshOption. Usage example: RefreshOption = mysql.connector.RefreshOption refresh = RefreshOption.LOG | RefreshOption.THREADS cnx.cmd_refresh(refresh) The result is a dictionary with the OK packet information. Returns a dict() """ return self._handle_ok((yield from self._send_cmd(ServerCmd.REFRESH, int4store(options))))
def test_int4store(self): """Use int4store to pack an integer (2^32) as a string.""" data = 2**(32 - 1) exp = struct.pack('<I', data) try: result = utils.int4store(data) except ValueError as e: self.fail("int4store failed: %s" % e) else: if not isinstance(result, bytes): self.fail("Wrong result. Expected %s, we got %s" %\ (type(exp), type(result))) elif exp != result: self.fail("Wrong result. Expected %s, we got %s" %\ (data, result))
def test_int4store(self): """Use int4store to pack an integer (2^32) as a string.""" data = 2**(32-1) exp = struct.pack('<I',data) try: result = utils.int4store(data) except ValueError as e: self.fail("int4store failed: %s" % e) else: if not isinstance(result, str): self.fail("Wrong result. Expected %s, we got %s" %\ (type(exp), type(result))) elif exp != result: self.fail("Wrong result. Expected %s, we got %s" %\ (data, result))
def make_stmt_execute(self, statement_id, data=(), parameters=(), flags=0, long_data_used=None, charset='utf8'): """Make a MySQL packet with the Statement Execute command""" iteration_count = 1 null_bitmap = [0] * ((len(data) + 7) // 8) values = [] types = [] packed = b'' if long_data_used is None: long_data_used = {} if parameters and data: if len(data) != len(parameters): raise errors.InterfaceError( "Failed executing prepared statement: data values does not" " match number of parameters") for pos, _ in enumerate(parameters): value = data[pos] flags = 0 if value is None: null_bitmap[(pos // 8)] |= 1 << (pos % 8) continue elif pos in long_data_used: if long_data_used[pos][0]: # We suppose binary data field_type = FieldType.BLOB else: # We suppose text data field_type = FieldType.STRING elif isinstance(value, int): (packed, field_type, flags) = self._prepare_binary_integer(value) values.append(packed) elif isinstance(value, str): value = value.encode(charset) values.append( utils.intstore(len(value)) + value) field_type = FieldType.VARCHAR elif isinstance(value, bytes): values.append(utils.intstore(len(value)) + value) field_type = FieldType.BLOB elif isinstance(value, Decimal): values.append( utils.intstore(len(str(value).encode(charset))) + str(value).encode(charset)) field_type = FieldType.DECIMAL elif isinstance(value, float): values.append(struct.pack('d', value)) field_type = FieldType.DOUBLE elif isinstance(value, (datetime.datetime, datetime.date)): (packed, field_type) = self._prepare_binary_timestamp( value) values.append(packed) elif isinstance(value, (datetime.timedelta, datetime.time)): (packed, field_type) = self._prepare_binary_time(value) values.append(packed) else: raise errors.ProgrammingError( "MySQL binary protocol can not handle " "'{classname}' objects".format( classname=value.__class__.__name__)) types.append(utils.int1store(field_type) + utils.int1store(flags)) packet = ( utils.int4store(statement_id), utils.int1store(flags), utils.int4store(iteration_count), b''.join([struct.pack('B', bit) for bit in null_bitmap]), utils.int1store(1), b''.join(types), b''.join(values) ) return b''.join(packet)
def make_stmt_execute(self, statement_id, data=(), parameters=(), flags=0, long_data_used=None, charset='utf8'): """Make a MySQL packet with the Statement Execute command""" iteration_count = 1 null_bitmap = [0] * ((len(data) + 7) // 8) values = [] types = [] packed = '' if long_data_used is None: long_data_used = {} if parameters and data: if len(data) != len(parameters): raise errors.InterfaceError( "Failed executing prepared statement: data values does not" " match number of parameters") for pos, _ in enumerate(parameters): value = data[pos] flags = 0 if value is None: null_bitmap[(pos // 8)] |= 1 << (pos % 8) continue elif pos in long_data_used: if long_data_used[pos][0]: # We suppose binary data field_type = FieldType.BLOB else: # We suppose text data field_type = FieldType.STRING elif isinstance(value, (int, long)): (packed, field_type, flags) = self._prepare_binary_integer(value) values.append(packed) elif isinstance(value, str): values.append(utils.intstore(len(value)) + value) field_type = FieldType.VARCHAR elif isinstance(value, unicode): value = value.encode(charset) values.append(utils.intstore(len(value)) + value) field_type = FieldType.VARCHAR elif isinstance(value, Decimal): values.append(utils.intstore(len(str(value))) + str(value)) field_type = FieldType.DECIMAL elif isinstance(value, float): values.append(struct.pack('d', value)) field_type = FieldType.DOUBLE elif isinstance(value, (datetime.datetime, datetime.date)): (packed, field_type) = self._prepare_binary_timestamp( value) values.append(packed) elif isinstance(value, (datetime.timedelta, datetime.time)): (packed, field_type) = self._prepare_binary_time(value) values.append(packed) else: raise errors.ProgrammingError( "MySQL binary protocol can not handle " "'{classname}' objects".format( classname=value.__class__.__name__)) types.append(utils.int1store(field_type) + utils.int1store(flags)) packet = ( utils.int4store(statement_id), utils.int1store(flags), utils.int4store(iteration_count), ''.join([struct.pack('B', bit) for bit in null_bitmap]), utils.int1store(1), ''.join(types), ''.join(values) ) return ''.join(packet)