Skip to content

Commit 41ecfa6

Browse files
committed
Fix CollationMap error when the table contains enum or set fields
1 parent 52c09af commit 41ecfa6

File tree

1 file changed

+52
-4
lines changed

1 file changed

+52
-4
lines changed

replication/row_event.go

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ func (e *TableMapEvent) Dump(w io.Writer) {
330330
fmt.Fprintf(w, nameFmt, e.ColumnName[i])
331331
}
332332

333-
fmt.Fprintf(w, " type=%-3d", e.ColumnType[i])
333+
fmt.Fprintf(w, " type=%-3d", e.realType(i))
334334

335335
if IsNumericType(e.ColumnType[i]) {
336336
if len(unsignedMap) == 0 {
@@ -340,7 +340,7 @@ func (e *TableMapEvent) Dump(w io.Writer) {
340340
} else {
341341
fmt.Fprintf(w, " unsigned=no ")
342342
}
343-
} else if IsCharacterType(e.ColumnType[i]) {
343+
} else if e.isCharacterField(i) {
344344
if len(collationMap) == 0 {
345345
fmt.Fprintf(w, " collation=<n/a>")
346346
} else {
@@ -413,7 +413,7 @@ func (e *TableMapEvent) CollationMap() map[int]uint64 {
413413
p := 0
414414
ret := make(map[int]uint64)
415415
for i := 0; i < int(e.ColumnCount); i++ {
416-
if !IsCharacterType(e.ColumnType[i]) {
416+
if !e.isCharacterField(i) {
417417
continue
418418
}
419419

@@ -433,7 +433,7 @@ func (e *TableMapEvent) CollationMap() map[int]uint64 {
433433
p := 0
434434
ret := make(map[int]uint64)
435435
for i := 0; i < int(e.ColumnCount); i++ {
436-
if !IsCharacterType(e.ColumnType[i]) {
436+
if !e.isCharacterField(i) {
437437
continue
438438
}
439439

@@ -447,6 +447,54 @@ func (e *TableMapEvent) CollationMap() map[int]uint64 {
447447
return nil
448448
}
449449

450+
// Get the `real_type` of column i. Note that types stored in ColumnType are the `binlog_type`.
451+
// See: mysql-8.0/sql/rpl_utility.h table_def::type
452+
// Also see: notes/field_type.md
453+
func (e *TableMapEvent) realType(i int) byte {
454+
455+
typ := e.ColumnType[i]
456+
meta := e.ColumnMeta[i]
457+
458+
switch typ {
459+
case MYSQL_TYPE_STRING:
460+
realTyp := byte(meta >> 8)
461+
if realTyp == MYSQL_TYPE_ENUM || realTyp == MYSQL_TYPE_SET {
462+
return realTyp
463+
}
464+
465+
case MYSQL_TYPE_DATE:
466+
return MYSQL_TYPE_NEWDATE
467+
468+
}
469+
470+
return typ
471+
472+
}
473+
474+
// Returns true if the i-th column is numeric field.
475+
// See: mysql-8.0/sql/log_event.cc is_numeric_field
476+
func (e *TableMapEvent) isNumericField(i int) bool {
477+
return IsNumericType(e.ColumnType[i])
478+
}
479+
480+
// Returns true if the i-th column is character field.
481+
// See: mysql-8.0/sql/log_event.cc is_character_field
482+
func (e *TableMapEvent) isCharacterField(i int) bool {
483+
return IsCharacterType(e.realType(i))
484+
}
485+
486+
// Returns true if the i-th column is enum field.
487+
// See: mysql-8.0/sql/log_event.cc is_enum_field
488+
func (e *TableMapEvent) isEnumField(i int) bool {
489+
return e.realType(i) == MYSQL_TYPE_ENUM
490+
}
491+
492+
// Returns true if the i-th column is set field.
493+
// See: mysql-8.0/sql/log_event.cc is_set_field
494+
func (e *TableMapEvent) isSetField(i int) bool {
495+
return e.realType(i) == MYSQL_TYPE_SET
496+
}
497+
450498
// RowsEventStmtEndFlag is set in the end of the statement.
451499
const RowsEventStmtEndFlag = 0x01
452500

0 commit comments

Comments
 (0)