Skip to content

Commit a19a5a5

Browse files
authored
refactor : refactor loop inside _read_column_data method (julien-duponchelle#418)
1 parent d6c5f92 commit a19a5a5

File tree

1 file changed

+118
-108
lines changed

1 file changed

+118
-108
lines changed

Diff for: pymysqlreplication/row_event.py

+118-108
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def _read_column_data(self, cols_bitmap):
103103
# See http://dev.mysql.com/doc/internals/en/rows-event.html
104104
null_bitmap = self.packet.read((BitCount(cols_bitmap) + 7) / 8)
105105

106-
nullBitmapIndex = 0
106+
null_bitmap_index = 0
107107
nb_columns = len(self.columns)
108108
for i in range(0, nb_columns):
109109
column = self.columns[i]
@@ -112,117 +112,127 @@ def _read_column_data(self, cols_bitmap):
112112
zerofill = self.table_map[self.table_id].columns[i].zerofill
113113
fixed_binary_length = self.table_map[self.table_id].columns[i].fixed_binary_length
114114

115-
if BitGet(cols_bitmap, i) == 0:
116-
values[name] = None
117-
continue
118-
119-
if self._is_null(null_bitmap, nullBitmapIndex):
120-
values[name] = None
121-
elif column.type == FIELD_TYPE.TINY:
122-
if unsigned:
123-
values[name] = struct.unpack("<B", self.packet.read(1))[0]
124-
if zerofill:
125-
values[name] = format(values[name], '03d')
126-
else:
127-
values[name] = struct.unpack("<b", self.packet.read(1))[0]
128-
elif column.type == FIELD_TYPE.SHORT:
129-
if unsigned:
130-
values[name] = struct.unpack("<H", self.packet.read(2))[0]
131-
if zerofill:
132-
values[name] = format(values[name], '05d')
133-
else:
134-
values[name] = struct.unpack("<h", self.packet.read(2))[0]
135-
elif column.type == FIELD_TYPE.LONG:
136-
if unsigned:
137-
values[name] = struct.unpack("<I", self.packet.read(4))[0]
138-
if zerofill:
139-
values[name] = format(values[name], '010d')
140-
else:
141-
values[name] = struct.unpack("<i", self.packet.read(4))[0]
142-
elif column.type == FIELD_TYPE.INT24:
143-
if unsigned:
144-
values[name] = self.packet.read_uint24()
145-
if zerofill:
146-
values[name] = format(values[name], '08d')
147-
else:
148-
values[name] = self.packet.read_int24()
149-
elif column.type == FIELD_TYPE.FLOAT:
150-
values[name] = struct.unpack("<f", self.packet.read(4))[0]
151-
elif column.type == FIELD_TYPE.DOUBLE:
152-
values[name] = struct.unpack("<d", self.packet.read(8))[0]
153-
elif column.type == FIELD_TYPE.VARCHAR or \
154-
column.type == FIELD_TYPE.STRING:
155-
if column.max_length > 255:
156-
values[name] = self.__read_string(2, column)
157-
else:
158-
values[name] = self.__read_string(1, column)
159-
160-
if fixed_binary_length and len(values[name]) < fixed_binary_length:
161-
# Fixed-length binary fields are stored in the binlog
162-
# without trailing zeros and must be padded with zeros up
163-
# to the specified length at read time.
164-
nr_pad = fixed_binary_length - len(values[name])
165-
values[name] += b'\x00' * nr_pad
166-
167-
elif column.type == FIELD_TYPE.NEWDECIMAL:
168-
values[name] = self.__read_new_decimal(column)
169-
elif column.type == FIELD_TYPE.BLOB:
170-
values[name] = self.__read_string(column.length_size, column)
171-
elif column.type == FIELD_TYPE.DATETIME:
172-
values[name] = self.__read_datetime()
173-
elif column.type == FIELD_TYPE.TIME:
174-
values[name] = self.__read_time()
175-
elif column.type == FIELD_TYPE.DATE:
176-
values[name] = self.__read_date()
177-
elif column.type == FIELD_TYPE.TIMESTAMP:
178-
values[name] = datetime.datetime.utcfromtimestamp(
179-
self.packet.read_uint32())
180-
181-
# For new date format:
182-
elif column.type == FIELD_TYPE.DATETIME2:
183-
values[name] = self.__read_datetime2(column)
184-
elif column.type == FIELD_TYPE.TIME2:
185-
values[name] = self.__read_time2(column)
186-
elif column.type == FIELD_TYPE.TIMESTAMP2:
187-
values[name] = self.__add_fsp_to_time(
188-
datetime.datetime.utcfromtimestamp(
189-
self.packet.read_int_be_by_size(4)), column)
190-
elif column.type == FIELD_TYPE.LONGLONG:
191-
if unsigned:
192-
values[name] = self.packet.read_uint64()
193-
if zerofill:
194-
values[name] = format(values[name], '020d')
195-
else:
196-
values[name] = self.packet.read_int64()
197-
elif column.type == FIELD_TYPE.YEAR:
198-
values[name] = self.packet.read_uint8() + 1900
199-
elif column.type == FIELD_TYPE.ENUM:
200-
values[name] = column.enum_values[
201-
self.packet.read_uint_by_size(column.size)]
202-
elif column.type == FIELD_TYPE.SET:
203-
# We read set columns as a bitmap telling us which options
204-
# are enabled
205-
bit_mask = self.packet.read_uint_by_size(column.size)
206-
values[name] = set(
207-
val for idx, val in enumerate(column.set_values)
208-
if bit_mask & 2 ** idx
209-
) or None
210-
211-
elif column.type == FIELD_TYPE.BIT:
212-
values[name] = self.__read_bit(column)
213-
elif column.type == FIELD_TYPE.GEOMETRY:
214-
values[name] = self.packet.read_length_coded_pascal_string(
215-
column.length_size)
216-
elif column.type == FIELD_TYPE.JSON:
217-
values[name] = self.packet.read_binary_json(column.length_size)
218-
else:
219-
raise NotImplementedError("Unknown MySQL column type: %d" %
220-
(column.type))
115+
values[name] = self.__read_values_name(column, null_bitmap, null_bitmap_index,
116+
cols_bitmap, unsigned, zerofill,
117+
fixed_binary_length, i)
221118

222-
nullBitmapIndex += 1
119+
if BitGet(cols_bitmap, i) != 0:
120+
null_bitmap_index += 1
223121

224122
return values
225123

124+
def __read_values_name(self, column, null_bitmap, null_bitmap_index, cols_bitmap, unsigned, zerofill,
125+
fixed_binary_length, i):
126+
127+
if BitGet(cols_bitmap, i) == 0:
128+
return None
129+
130+
if self._is_null(null_bitmap, null_bitmap_index):
131+
return None
132+
133+
if column.type == FIELD_TYPE.TINY:
134+
if unsigned:
135+
ret = struct.unpack("<B", self.packet.read(1))[0]
136+
if zerofill:
137+
ret = format(ret, '03d')
138+
return ret
139+
else:
140+
return struct.unpack("<b", self.packet.read(1))[0]
141+
elif column.type == FIELD_TYPE.SHORT:
142+
if unsigned:
143+
ret = struct.unpack("<H", self.packet.read(2))[0]
144+
if zerofill:
145+
ret = format(ret, '05d')
146+
return ret
147+
else:
148+
return struct.unpack("<h", self.packet.read(2))[0]
149+
elif column.type == FIELD_TYPE.LONG:
150+
if unsigned:
151+
ret = struct.unpack("<I", self.packet.read(4))[0]
152+
if zerofill:
153+
ret = format(ret, '010d')
154+
return ret
155+
else:
156+
return struct.unpack("<i", self.packet.read(4))[0]
157+
elif column.type == FIELD_TYPE.INT24:
158+
if unsigned:
159+
ret = self.packet.read_uint24()
160+
if zerofill:
161+
ret = format(ret, '08d')
162+
return ret
163+
else:
164+
return self.packet.read_int24()
165+
elif column.type == FIELD_TYPE.FLOAT:
166+
return struct.unpack("<f", self.packet.read(4))[0]
167+
elif column.type == FIELD_TYPE.DOUBLE:
168+
return struct.unpack("<d", self.packet.read(8))[0]
169+
elif column.type == FIELD_TYPE.VARCHAR or \
170+
column.type == FIELD_TYPE.STRING:
171+
ret = self.__read_string(2, column) if column.max_length > 255 else self.__read_string(1, column)
172+
173+
if fixed_binary_length and len(ret) < fixed_binary_length:
174+
# Fixed-length binary fields are stored in the binlog
175+
# without trailing zeros and must be padded with zeros up
176+
# to the specified length at read time.
177+
nr_pad = fixed_binary_length - len(ret)
178+
ret += b'\x00' * nr_pad
179+
return ret
180+
elif column.type == FIELD_TYPE.NEWDECIMAL:
181+
return self.__read_new_decimal(column)
182+
elif column.type == FIELD_TYPE.BLOB:
183+
return self.__read_string(column.length_size, column)
184+
elif column.type == FIELD_TYPE.DATETIME:
185+
return self.__read_datetime()
186+
elif column.type == FIELD_TYPE.TIME:
187+
return self.__read_time()
188+
elif column.type == FIELD_TYPE.DATE:
189+
return self.__read_date()
190+
elif column.type == FIELD_TYPE.TIMESTAMP:
191+
return datetime.datetime.fromtimestamp(
192+
self.packet.read_uint32())
193+
194+
# For new date format:
195+
elif column.type == FIELD_TYPE.DATETIME2:
196+
return self.__read_datetime2(column)
197+
elif column.type == FIELD_TYPE.TIME2:
198+
return self.__read_time2(column)
199+
elif column.type == FIELD_TYPE.TIMESTAMP2:
200+
return self.__add_fsp_to_time(
201+
datetime.datetime.fromtimestamp(
202+
self.packet.read_int_be_by_size(4)), column)
203+
elif column.type == FIELD_TYPE.LONGLONG:
204+
if unsigned:
205+
ret = self.packet.read_uint64()
206+
if zerofill:
207+
ret = format(ret, '020d')
208+
return ret
209+
else:
210+
return self.packet.read_int64()
211+
elif column.type == FIELD_TYPE.YEAR:
212+
return self.packet.read_uint8() + 1900
213+
elif column.type == FIELD_TYPE.ENUM:
214+
return column.enum_values[
215+
self.packet.read_uint_by_size(column.size)]
216+
elif column.type == FIELD_TYPE.SET:
217+
# We read set columns as a bitmap telling us which options
218+
# are enabled
219+
bit_mask = self.packet.read_uint_by_size(column.size)
220+
return set(
221+
val for idx, val in enumerate(column.set_values)
222+
if bit_mask & 2 ** idx
223+
) or None
224+
225+
elif column.type == FIELD_TYPE.BIT:
226+
return self.__read_bit(column)
227+
elif column.type == FIELD_TYPE.GEOMETRY:
228+
return self.packet.read_length_coded_pascal_string(
229+
column.length_size)
230+
elif column.type == FIELD_TYPE.JSON:
231+
return self.packet.read_binary_json(column.length_size)
232+
else:
233+
raise NotImplementedError("Unknown MySQL column type: %d" %
234+
(column.type))
235+
226236
def __add_fsp_to_time(self, time, column):
227237
"""Read and add the fractional part of time
228238
For more details about new date format:

0 commit comments

Comments
 (0)