From 10974a14c15ff076144e3a19976a224550083911 Mon Sep 17 00:00:00 2001 From: mirageoasis Date: Mon, 14 Aug 2023 16:37:26 +0900 Subject: [PATCH] refactor : refactor loop inside _read_column_data method --- pymysqlreplication/row_event.py | 226 +++++++++++++++++--------------- 1 file changed, 118 insertions(+), 108 deletions(-) diff --git a/pymysqlreplication/row_event.py b/pymysqlreplication/row_event.py index cfbfbd21..00b37279 100644 --- a/pymysqlreplication/row_event.py +++ b/pymysqlreplication/row_event.py @@ -102,7 +102,7 @@ def _read_column_data(self, cols_bitmap): # See http://dev.mysql.com/doc/internals/en/rows-event.html null_bitmap = self.packet.read((BitCount(cols_bitmap) + 7) / 8) - nullBitmapIndex = 0 + null_bitmap_index = 0 nb_columns = len(self.columns) for i in range(0, nb_columns): column = self.columns[i] @@ -111,117 +111,127 @@ def _read_column_data(self, cols_bitmap): zerofill = self.table_map[self.table_id].columns[i].zerofill fixed_binary_length = self.table_map[self.table_id].columns[i].fixed_binary_length - if BitGet(cols_bitmap, i) == 0: - values[name] = None - continue - - if self._is_null(null_bitmap, nullBitmapIndex): - values[name] = None - elif column.type == FIELD_TYPE.TINY: - if unsigned: - values[name] = struct.unpack(" 255: - values[name] = self.__read_string(2, column) - else: - values[name] = self.__read_string(1, column) - - if fixed_binary_length and len(values[name]) < fixed_binary_length: - # Fixed-length binary fields are stored in the binlog - # without trailing zeros and must be padded with zeros up - # to the specified length at read time. - nr_pad = fixed_binary_length - len(values[name]) - values[name] += b'\x00' * nr_pad - - elif column.type == FIELD_TYPE.NEWDECIMAL: - values[name] = self.__read_new_decimal(column) - elif column.type == FIELD_TYPE.BLOB: - values[name] = self.__read_string(column.length_size, column) - elif column.type == FIELD_TYPE.DATETIME: - values[name] = self.__read_datetime() - elif column.type == FIELD_TYPE.TIME: - values[name] = self.__read_time() - elif column.type == FIELD_TYPE.DATE: - values[name] = self.__read_date() - elif column.type == FIELD_TYPE.TIMESTAMP: - values[name] = datetime.datetime.fromtimestamp( - self.packet.read_uint32()) - - # For new date format: - elif column.type == FIELD_TYPE.DATETIME2: - values[name] = self.__read_datetime2(column) - elif column.type == FIELD_TYPE.TIME2: - values[name] = self.__read_time2(column) - elif column.type == FIELD_TYPE.TIMESTAMP2: - values[name] = self.__add_fsp_to_time( - datetime.datetime.fromtimestamp( - self.packet.read_int_be_by_size(4)), column) - elif column.type == FIELD_TYPE.LONGLONG: - if unsigned: - values[name] = self.packet.read_uint64() - if zerofill: - values[name] = format(values[name], '020d') - else: - values[name] = self.packet.read_int64() - elif column.type == FIELD_TYPE.YEAR: - values[name] = self.packet.read_uint8() + 1900 - elif column.type == FIELD_TYPE.ENUM: - values[name] = column.enum_values[ - self.packet.read_uint_by_size(column.size)] - elif column.type == FIELD_TYPE.SET: - # We read set columns as a bitmap telling us which options - # are enabled - bit_mask = self.packet.read_uint_by_size(column.size) - values[name] = set( - val for idx, val in enumerate(column.set_values) - if bit_mask & 2 ** idx - ) or None - - elif column.type == FIELD_TYPE.BIT: - values[name] = self.__read_bit(column) - elif column.type == FIELD_TYPE.GEOMETRY: - values[name] = self.packet.read_length_coded_pascal_string( - column.length_size) - elif column.type == FIELD_TYPE.JSON: - values[name] = self.packet.read_binary_json(column.length_size) - else: - raise NotImplementedError("Unknown MySQL column type: %d" % - (column.type)) + values[name] = self.__read_values_name(column, null_bitmap, null_bitmap_index, + cols_bitmap, unsigned, zerofill, + fixed_binary_length, i) - nullBitmapIndex += 1 + if BitGet(cols_bitmap, i) != 0: + null_bitmap_index += 1 return values + def __read_values_name(self, column, null_bitmap, null_bitmap_index, cols_bitmap, unsigned, zerofill, + fixed_binary_length, i): + + if BitGet(cols_bitmap, i) == 0: + return None + + if self._is_null(null_bitmap, null_bitmap_index): + return None + + if column.type == FIELD_TYPE.TINY: + if unsigned: + ret = struct.unpack(" 255 else self.__read_string(1, column) + + if fixed_binary_length and len(ret) < fixed_binary_length: + # Fixed-length binary fields are stored in the binlog + # without trailing zeros and must be padded with zeros up + # to the specified length at read time. + nr_pad = fixed_binary_length - len(ret) + ret += b'\x00' * nr_pad + return ret + elif column.type == FIELD_TYPE.NEWDECIMAL: + return self.__read_new_decimal(column) + elif column.type == FIELD_TYPE.BLOB: + return self.__read_string(column.length_size, column) + elif column.type == FIELD_TYPE.DATETIME: + return self.__read_datetime() + elif column.type == FIELD_TYPE.TIME: + return self.__read_time() + elif column.type == FIELD_TYPE.DATE: + return self.__read_date() + elif column.type == FIELD_TYPE.TIMESTAMP: + return datetime.datetime.fromtimestamp( + self.packet.read_uint32()) + + # For new date format: + elif column.type == FIELD_TYPE.DATETIME2: + return self.__read_datetime2(column) + elif column.type == FIELD_TYPE.TIME2: + return self.__read_time2(column) + elif column.type == FIELD_TYPE.TIMESTAMP2: + return self.__add_fsp_to_time( + datetime.datetime.fromtimestamp( + self.packet.read_int_be_by_size(4)), column) + elif column.type == FIELD_TYPE.LONGLONG: + if unsigned: + ret = self.packet.read_uint64() + if zerofill: + ret = format(ret, '020d') + return ret + else: + return self.packet.read_int64() + elif column.type == FIELD_TYPE.YEAR: + return self.packet.read_uint8() + 1900 + elif column.type == FIELD_TYPE.ENUM: + return column.enum_values[ + self.packet.read_uint_by_size(column.size)] + elif column.type == FIELD_TYPE.SET: + # We read set columns as a bitmap telling us which options + # are enabled + bit_mask = self.packet.read_uint_by_size(column.size) + return set( + val for idx, val in enumerate(column.set_values) + if bit_mask & 2 ** idx + ) or None + + elif column.type == FIELD_TYPE.BIT: + return self.__read_bit(column) + elif column.type == FIELD_TYPE.GEOMETRY: + return self.packet.read_length_coded_pascal_string( + column.length_size) + elif column.type == FIELD_TYPE.JSON: + return self.packet.read_binary_json(column.length_size) + else: + raise NotImplementedError("Unknown MySQL column type: %d" % + (column.type)) + def __add_fsp_to_time(self, time, column): """Read and add the fractional part of time For more details about new date format: