Skip to content

Commit c66d0a6

Browse files
committed
Make TableMapEvent's Dump prettier
1 parent c61b8a9 commit c66d0a6

File tree

1 file changed

+60
-50
lines changed

1 file changed

+60
-50
lines changed

replication/row_event.go

Lines changed: 60 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@ type TableMapEvent struct {
3232
ColumnType []byte
3333
ColumnMeta []uint16
3434

35-
NullBitmap []byte // len = (ColumnCount + 7) / 8
35+
//len = (ColumnCount + 7) / 8
36+
NullBitmap []byte
3637

3738
// The followings are available only after MySQL-8.0.1, see: `--binlog_row_metadata` and
3839
// https://mysqlhighavailability.com/more-metadata-is-written-into-binary-log/
3940

40-
optionalMeta []byte
41-
4241
SignednessBitmap []byte
42+
4343
ColumnName [][]byte
4444
PrimaryKey []uint64 // A sequence of column indexes
4545
PrimaryKeyPrefix []uint64 // Prefix length 0 means that the whole column value is used
@@ -99,12 +99,12 @@ func (e *TableMapEvent) Decode(data []byte) error {
9999

100100
pos += nullBitmapSize
101101

102-
e.optionalMeta = data[pos:]
103-
if len(e.optionalMeta) == 0 {
102+
optionalMeta := data[pos:]
103+
if len(optionalMeta) == 0 {
104104
return nil
105105
}
106106

107-
if err = e.decodeOptionalMeta(e.optionalMeta); err != nil {
107+
if err = e.decodeOptionalMeta(optionalMeta); err != nil {
108108
return err
109109
}
110110

@@ -276,78 +276,88 @@ func (e *TableMapEvent) Dump(w io.Writer) {
276276
fmt.Fprintf(w, "Column count: %d\n", e.ColumnCount)
277277
fmt.Fprintf(w, "Column type: \n%s", hex.Dump(e.ColumnType))
278278
fmt.Fprintf(w, "NULL bitmap: \n%s", hex.Dump(e.NullBitmap))
279-
fmt.Fprintf(w, "Optional meta: \n%s", hex.Dump(e.optionalMeta))
279+
280280
fmt.Fprintf(w, "Signedness bitmap: \n%s", hex.Dump(e.SignednessBitmap))
281281
fmt.Fprintf(w, "Primary key: %v\n", e.PrimaryKey)
282282
fmt.Fprintf(w, "Primary key prefix: %v\n", e.PrimaryKeyPrefix)
283283

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+
287302
fmt.Fprintf(w, "Columns: \n")
288303
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>")
291306
} else {
292-
fmt.Fprintf(w, " <noname>")
307+
fmt.Fprintf(w, nameFmt, e.ColumnName[i])
293308
}
294309

295-
fmt.Fprintf(w, " type:%d", e.ColumnType[i])
310+
fmt.Fprintf(w, " type=%-3d", e.ColumnType[i])
296311

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")
304317
} else {
305-
fmt.Fprintf(w, " notnull")
318+
fmt.Fprintf(w, " unsigned=no ")
306319
}
307320
}
308321

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+
309335
fmt.Fprintf(w, "\n")
310336
}
311337
fmt.Fprintln(w)
312338
}
313339

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) {
317344
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
332346
}
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
338348
}
339349

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 {
343354
if len(e.SignednessBitmap) == 0 {
344355
return nil
345356
}
346357
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++ {
349360
if !IsNumericType(e.ColumnType[i]) {
350-
ret[i] = false
351361
continue
352362
}
353363
ret[i] = e.SignednessBitmap[p/8]&(1<<(7-p%8)) != 0

0 commit comments

Comments
 (0)