@@ -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