@@ -32,14 +32,14 @@ type TableMapEvent struct {
32
32
ColumnType []byte
33
33
ColumnMeta []uint16
34
34
35
- NullBitmap []byte // len = (ColumnCount + 7) / 8
35
+ //len = (ColumnCount + 7) / 8
36
+ NullBitmap []byte
36
37
37
38
// The followings are available only after MySQL-8.0.1, see: `--binlog_row_metadata` and
38
39
// https://mysqlhighavailability.com/more-metadata-is-written-into-binary-log/
39
40
40
- optionalMeta []byte
41
-
42
41
SignednessBitmap []byte
42
+
43
43
ColumnName [][]byte
44
44
PrimaryKey []uint64 // A sequence of column indexes
45
45
PrimaryKeyPrefix []uint64 // Prefix length 0 means that the whole column value is used
@@ -99,12 +99,12 @@ func (e *TableMapEvent) Decode(data []byte) error {
99
99
100
100
pos += nullBitmapSize
101
101
102
- e . optionalMeta = data [pos :]
103
- if len (e . optionalMeta ) == 0 {
102
+ optionalMeta : = data [pos :]
103
+ if len (optionalMeta ) == 0 {
104
104
return nil
105
105
}
106
106
107
- if err = e .decodeOptionalMeta (e . optionalMeta ); err != nil {
107
+ if err = e .decodeOptionalMeta (optionalMeta ); err != nil {
108
108
return err
109
109
}
110
110
@@ -276,78 +276,88 @@ func (e *TableMapEvent) Dump(w io.Writer) {
276
276
fmt .Fprintf (w , "Column count: %d\n " , e .ColumnCount )
277
277
fmt .Fprintf (w , "Column type: \n %s" , hex .Dump (e .ColumnType ))
278
278
fmt .Fprintf (w , "NULL bitmap: \n %s" , hex .Dump (e .NullBitmap ))
279
- fmt . Fprintf ( w , "Optional meta: \n %s" , hex . Dump ( e . optionalMeta ))
279
+
280
280
fmt .Fprintf (w , "Signedness bitmap: \n %s" , hex .Dump (e .SignednessBitmap ))
281
281
fmt .Fprintf (w , "Primary key: %v\n " , e .PrimaryKey )
282
282
fmt .Fprintf (w , "Primary key prefix: %v\n " , e .PrimaryKeyPrefix )
283
283
284
- colNameArr := e .ColumnNameArray ()
285
- nullArr := e .NullableArray ()
286
- unsignedArr := e .UnsignedArray ()
284
+ unsignedMap := e .UnsignedMap ()
285
+
286
+ nameMaxLen := 0
287
+ for _ , name := range e .ColumnName {
288
+ if len (name ) > nameMaxLen {
289
+ nameMaxLen = len (name )
290
+ }
291
+ }
292
+ nameFmt := " %s"
293
+ if nameMaxLen > 0 {
294
+ nameFmt = fmt .Sprintf (" %%-%ds" , nameMaxLen )
295
+ }
296
+
297
+ primaryKey := map [int ]struct {}{}
298
+ for _ , pk := range e .PrimaryKey {
299
+ primaryKey [int (pk )] = struct {}{}
300
+ }
301
+
287
302
fmt .Fprintf (w , "Columns: \n " )
288
303
for i := 0 ; i < int (e .ColumnCount ); i ++ {
289
- if colNameArr != nil {
290
- fmt .Fprintf (w , " %s" , colNameArr [ i ] )
304
+ if len ( e . ColumnName ) == 0 {
305
+ fmt .Fprintf (w , nameFmt , "<n/a>" )
291
306
} else {
292
- fmt .Fprintf (w , " <noname>" )
307
+ fmt .Fprintf (w , nameFmt , e . ColumnName [ i ] )
293
308
}
294
309
295
- fmt .Fprintf (w , " type:%d " , e .ColumnType [i ])
310
+ fmt .Fprintf (w , " type=%-3d " , e .ColumnType [i ])
296
311
297
- if unsignedArr != nil && unsignedArr [i ] {
298
- fmt .Fprintf (w , " unsigned" )
299
- }
300
-
301
- if nullArr != nil {
302
- if nullArr [i ] {
303
- fmt .Fprintf (w , " null" )
312
+ if IsNumericType (e .ColumnType [i ]) {
313
+ if unsignedMap == nil {
314
+ fmt .Fprintf (w , " unsigned=<n/a>" )
315
+ } else if unsignedMap [i ] {
316
+ fmt .Fprintf (w , " unsigned=yes" )
304
317
} else {
305
- fmt .Fprintf (w , " notnull " )
318
+ fmt .Fprintf (w , " unsigned=no " )
306
319
}
307
320
}
308
321
322
+ available , nullable := e .Nullable (i )
323
+ if ! available {
324
+ fmt .Fprintf (w , " null=<n/a>" )
325
+ } else if nullable {
326
+ fmt .Fprintf (w , " null=yes" )
327
+ } else {
328
+ fmt .Fprintf (w , " null=no " )
329
+ }
330
+
331
+ if _ , ok := primaryKey [i ]; ok {
332
+ fmt .Fprintf (w , " pri" )
333
+ }
334
+
309
335
fmt .Fprintf (w , "\n " )
310
336
}
311
337
fmt .Fprintln (w )
312
338
}
313
339
314
- // NullableArray returns an array of nullablity for each column: true if the column is nullable.
315
- // It returns nil if not available.
316
- func (e * TableMapEvent ) NullableArray () []bool {
340
+ // Nullable returns the nullablity of the i-th column.
341
+ // If null bits are not available, available is false.
342
+ // i must be in range [0, ColumnCount).
343
+ func (e * TableMapEvent ) Nullable (i int ) (available , nullable bool ) {
317
344
if len (e .NullBitmap ) == 0 {
318
- return nil
319
- }
320
- ret := make ([]bool , e .ColumnCount )
321
- for i := 0 ; i < len (ret ); i ++ {
322
- ret [i ] = e .NullBitmap [i / 8 ]& (1 << (i % 8 )) != 0
323
- }
324
- return ret
325
- }
326
-
327
- // ColumnNameArray returns an array of column names.
328
- // It returns nil if not available.
329
- func (e * TableMapEvent ) ColumnNameArray () []string {
330
- if len (e .ColumnName ) == 0 {
331
- return nil
345
+ return
332
346
}
333
- ret := make ([]string , e .ColumnCount )
334
- for i := 0 ; i < len (ret ); i ++ {
335
- ret [i ] = string (e .ColumnName [i ])
336
- }
337
- return ret
347
+ return true , e .NullBitmap [i / 8 ]& (1 << (i % 8 )) != 0
338
348
}
339
349
340
- // UnsignedArray returns an array of signedness for each column: true if the column is numeric and it's unsigned.
341
- // It returns nil if not available.
342
- func (e * TableMapEvent ) UnsignedArray () []bool {
350
+ // UnsignedMap returns a map: column index -> unsigned.
351
+ // Note that only numeric columns will be returned.
352
+ // If signedness bits are not available, nil is returned.
353
+ func (e * TableMapEvent ) UnsignedMap () map [int ]bool {
343
354
if len (e .SignednessBitmap ) == 0 {
344
355
return nil
345
356
}
346
357
p := 0
347
- ret := make ([ ]bool , e . ColumnCount )
348
- for i := 0 ; i < len ( ret ); i ++ {
358
+ ret := make (map [ int ]bool )
359
+ for i := 0 ; i < int ( e . ColumnCount ); i ++ {
349
360
if ! IsNumericType (e .ColumnType [i ]) {
350
- ret [i ] = false
351
361
continue
352
362
}
353
363
ret [i ] = e .SignednessBitmap [p / 8 ]& (1 << (7 - p % 8 )) != 0
0 commit comments