Skip to content

Commit ff94dbd

Browse files
committed
Use TableMapEvent's new helper methods: go-mysql-org/go-mysql#482
1 parent e2786c8 commit ff94dbd

File tree

2 files changed

+86
-120
lines changed

2 files changed

+86
-120
lines changed

mycanal/incrdump/meta.go

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package incrdump
2+
3+
import (
4+
. "github.com/siddontang/go-mysql/mysql"
5+
"github.com/siddontang/go-mysql/replication"
6+
)
7+
8+
var (
9+
emptyUnsignedMap = map[int]bool{}
10+
emptyEnumStrValueMap = map[int][]string{}
11+
emptySetStrValueMap = map[int][]string{}
12+
)
13+
14+
type tableMeta struct {
15+
*replication.TableMapEvent
16+
// cache fields
17+
unsignedMap map[int]bool
18+
enumStrValueMap map[int][]string
19+
setStrValueMap map[int][]string
20+
}
21+
22+
func newTableMeta(table *replication.TableMapEvent) *tableMeta {
23+
return &tableMeta{
24+
TableMapEvent: table,
25+
}
26+
}
27+
28+
func (meta *tableMeta) UnsignedMap() map[int]bool {
29+
if meta.unsignedMap == nil {
30+
meta.unsignedMap = meta.TableMapEvent.UnsignedMap()
31+
if meta.unsignedMap == nil {
32+
meta.unsignedMap = emptyUnsignedMap
33+
}
34+
}
35+
return meta.unsignedMap
36+
}
37+
38+
func (meta *tableMeta) EnumStrValueMap() map[int][]string {
39+
if meta.enumStrValueMap == nil {
40+
meta.enumStrValueMap = meta.TableMapEvent.EnumStrValueMap()
41+
if meta.enumStrValueMap == nil {
42+
meta.enumStrValueMap = emptyEnumStrValueMap
43+
}
44+
}
45+
return meta.enumStrValueMap
46+
}
47+
48+
func (meta *tableMeta) SetStrValueMap() map[int][]string {
49+
if meta.setStrValueMap == nil {
50+
meta.setStrValueMap = meta.TableMapEvent.SetStrValueMap()
51+
if meta.setStrValueMap == nil {
52+
meta.setStrValueMap = emptySetStrValueMap
53+
}
54+
}
55+
return meta.setStrValueMap
56+
}
57+
58+
// I didn't export TableMapEvent.realType in go-mysql but need to use it here ....
59+
// So copy https://github.com/siddontang/go-mysql/replication/row_event.go
60+
func (meta *tableMeta) RealType(i int) byte {
61+
typ := meta.TableMapEvent.ColumnType[i]
62+
63+
switch typ {
64+
case MYSQL_TYPE_STRING:
65+
rtyp := byte(meta.TableMapEvent.ColumnMeta[i] >> 8)
66+
if rtyp == MYSQL_TYPE_ENUM || rtyp == MYSQL_TYPE_SET {
67+
return rtyp
68+
}
69+
70+
case MYSQL_TYPE_DATE:
71+
return MYSQL_TYPE_NEWDATE
72+
}
73+
74+
return typ
75+
76+
}

mycanal/incrdump/util.go

+10-120
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ func normalizeRowData(
3030
data []interface{},
3131
meta *tableMeta,
3232
) {
33+
3334
for i, val := range data {
3435

3536
// No need to handle nil.
@@ -39,17 +40,16 @@ func normalizeRowData(
3940

4041
// NOTE: go-mysql stores int as signed values since before MySQL-8, no signedness
4142
// information is presents in binlog. So we need to convert here if it is unsigned.
42-
if isNumericColumn(meta.Table, i) {
43+
if meta.IsNumericColumn(i) {
4344
if v, ok := val.(decimal.Decimal); ok {
4445
data[i] = v.String()
4546
continue
4647
}
4748

48-
if !meta.UnsignedMap[i] {
49+
if !meta.UnsignedMap()[i] {
4950
continue
5051
}
5152

52-
typ := realType(meta.Table, i)
5353
// Copy from go-mysql/canal/rows.go
5454
switch v := val.(type) {
5555
case int8:
@@ -59,7 +59,7 @@ func normalizeRowData(
5959
data[i] = uint16(v)
6060

6161
case int32:
62-
if v < 0 && typ == MYSQL_TYPE_INT24 {
62+
if v < 0 && meta.RealType(i) == MYSQL_TYPE_INT24 {
6363
// 16777215 is the maximum value of mediumint
6464
data[i] = uint32(16777215 + v + 1)
6565
} else {
@@ -78,21 +78,21 @@ func normalizeRowData(
7878
continue
7979
}
8080

81-
if isEnumColumn(meta.Table, i) {
81+
if meta.IsEnumColumn(i) {
8282
v, ok := val.(int64)
8383
if !ok {
8484
panic(fmt.Errorf("Expect int64 for enum (MYSQL_TYPE_ENUM) field but got %T %#v", val, val))
8585
}
86-
data[i] = meta.EnumStrValueMap[i][int(v)-1]
86+
data[i] = meta.EnumStrValueMap()[i][int(v)-1]
8787
continue
8888
}
8989

90-
if isSetColumn(meta.Table, i) {
90+
if meta.IsSetColumn(i) {
9191
v, ok := val.(int64)
9292
if !ok {
9393
panic(fmt.Errorf("Expect int64 for set (MYSQL_TYPE_SET) field but got %T %#v", val, val))
9494
}
95-
setStrValue := meta.SetStrValueMap[i]
95+
setStrValue := meta.SetStrValueMap()[i]
9696
vals := []string{}
9797
for j := 0; j < 64; j++ {
9898
if (v & (1 << uint(j))) != 0 {
@@ -103,7 +103,7 @@ func normalizeRowData(
103103
continue
104104
}
105105

106-
if realType(meta.Table, i) == MYSQL_TYPE_YEAR {
106+
if meta.RealType(i) == MYSQL_TYPE_YEAR {
107107
v, ok := val.(int)
108108
if !ok {
109109
panic(fmt.Errorf("Expect int for year (MYSQL_TYPE_YEAR) field but got %T %#v", val, val))
@@ -113,7 +113,7 @@ func normalizeRowData(
113113
continue
114114
}
115115

116-
if realType(meta.Table, i) == MYSQL_TYPE_NEWDATE {
116+
if meta.RealType(i) == MYSQL_TYPE_NEWDATE {
117117
v, ok := val.(string)
118118
if !ok {
119119
panic(fmt.Errorf("Expect string for date (MYSQL_TYPE_NEWDATE) field but got %T %#v", val, val))
@@ -136,113 +136,3 @@ func normalizeRowData(
136136
}
137137
}
138138
}
139-
140-
/*
141-
TODO:
142-
My PR has not merged yet: https://github.com/siddontang/go-mysql/pull/482
143-
So copy here.
144-
*/
145-
146-
type tableMeta struct {
147-
Table *replication.TableMapEvent
148-
UnsignedMap map[int]bool
149-
EnumStrValueMap map[int][]string
150-
SetStrValueMap map[int][]string
151-
}
152-
153-
func newTableMeta(e *replication.TableMapEvent) *tableMeta {
154-
return &tableMeta{
155-
Table: e,
156-
UnsignedMap: unsignedMap(e),
157-
EnumStrValueMap: enumStrValueMap(e),
158-
SetStrValueMap: setStrValueMap(e),
159-
}
160-
}
161-
162-
func enumStrValueMap(e *replication.TableMapEvent) map[int][]string {
163-
return strValueMap(e, isEnumColumn, e.EnumStrValueString())
164-
}
165-
166-
func setStrValueMap(e *replication.TableMapEvent) map[int][]string {
167-
return strValueMap(e, isSetColumn, e.SetStrValueString())
168-
}
169-
170-
func strValueMap(
171-
e *replication.TableMapEvent,
172-
includeType func(*replication.TableMapEvent, int) bool,
173-
strValue [][]string,
174-
) map[int][]string {
175-
176-
if len(strValue) == 0 {
177-
return nil
178-
}
179-
p := 0
180-
ret := make(map[int][]string)
181-
for i := 0; i < int(e.ColumnCount); i++ {
182-
if !includeType(e, i) {
183-
continue
184-
}
185-
ret[i] = strValue[p]
186-
p++
187-
}
188-
return ret
189-
}
190-
191-
func unsignedMap(e *replication.TableMapEvent) map[int]bool {
192-
if len(e.SignednessBitmap) == 0 {
193-
return nil
194-
}
195-
p := 0
196-
ret := make(map[int]bool)
197-
for i := 0; i < int(e.ColumnCount); i++ {
198-
if !isNumericColumn(e, i) {
199-
continue
200-
}
201-
ret[i] = e.SignednessBitmap[p/8]&(1<<uint(7-p%8)) != 0
202-
p++
203-
}
204-
return ret
205-
}
206-
207-
func isNumericColumn(e *replication.TableMapEvent, i int) bool {
208-
switch realType(e, i) {
209-
case MYSQL_TYPE_TINY,
210-
MYSQL_TYPE_SHORT,
211-
MYSQL_TYPE_INT24,
212-
MYSQL_TYPE_LONG,
213-
MYSQL_TYPE_LONGLONG,
214-
MYSQL_TYPE_NEWDECIMAL,
215-
MYSQL_TYPE_FLOAT,
216-
MYSQL_TYPE_DOUBLE:
217-
return true
218-
219-
default:
220-
return false
221-
}
222-
}
223-
224-
func isEnumColumn(e *replication.TableMapEvent, i int) bool {
225-
return realType(e, i) == MYSQL_TYPE_ENUM
226-
}
227-
228-
func isSetColumn(e *replication.TableMapEvent, i int) bool {
229-
return realType(e, i) == MYSQL_TYPE_SET
230-
}
231-
232-
func realType(e *replication.TableMapEvent, i int) byte {
233-
typ := e.ColumnType[i]
234-
meta := e.ColumnMeta[i]
235-
236-
switch typ {
237-
case MYSQL_TYPE_STRING:
238-
rtyp := byte(meta >> 8)
239-
if rtyp == MYSQL_TYPE_ENUM || rtyp == MYSQL_TYPE_SET {
240-
return rtyp
241-
}
242-
243-
case MYSQL_TYPE_DATE:
244-
return MYSQL_TYPE_NEWDATE
245-
}
246-
247-
return typ
248-
}

0 commit comments

Comments
 (0)