96 lines
3.0 KiB
Go
96 lines
3.0 KiB
Go
|
|
package binlog
|
||
|
|
|
||
|
|
import (
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"github.com/starainrt/go-mysql/mysql"
|
||
|
|
"github.com/starainrt/go-mysql/replication"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestNormalizeRowsByUnsigned_AllIntegerKinds(t *testing.T) {
|
||
|
|
event := &replication.RowsEvent{
|
||
|
|
Table: &replication.TableMapEvent{
|
||
|
|
ColumnCount: 5,
|
||
|
|
ColumnType: []byte{mysql.MYSQL_TYPE_TINY, mysql.MYSQL_TYPE_SHORT, mysql.MYSQL_TYPE_INT24, mysql.MYSQL_TYPE_LONG, mysql.MYSQL_TYPE_LONGLONG},
|
||
|
|
SignednessBitmap: []byte{0xF8},
|
||
|
|
},
|
||
|
|
Rows: [][]interface{}{{int8(-1), int16(-2), int32(-1), int32(-1), int64(-1)}},
|
||
|
|
}
|
||
|
|
|
||
|
|
got := normalizeRowsByUnsigned(event)
|
||
|
|
row := got[0]
|
||
|
|
|
||
|
|
if v, ok := row[0].(uint8); !ok || v != 255 {
|
||
|
|
t.Fatalf("tiny unsigned mismatch: %T %v", row[0], row[0])
|
||
|
|
}
|
||
|
|
if v, ok := row[1].(uint16); !ok || v != 65534 {
|
||
|
|
t.Fatalf("short unsigned mismatch: %T %v", row[1], row[1])
|
||
|
|
}
|
||
|
|
if v, ok := row[2].(uint32); !ok || v != 16777215 {
|
||
|
|
t.Fatalf("int24 unsigned mismatch: %T %v", row[2], row[2])
|
||
|
|
}
|
||
|
|
if v, ok := row[3].(uint32); !ok || v != 4294967295 {
|
||
|
|
t.Fatalf("long unsigned mismatch: %T %v", row[3], row[3])
|
||
|
|
}
|
||
|
|
if v, ok := row[4].(uint64); !ok || v != 18446744073709551615 {
|
||
|
|
t.Fatalf("longlong unsigned mismatch: %T %v", row[4], row[4])
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestNormalizeRowsByUnsigned_NoSignednessMetadata(t *testing.T) {
|
||
|
|
event := &replication.RowsEvent{
|
||
|
|
Table: &replication.TableMapEvent{
|
||
|
|
ColumnCount: 1,
|
||
|
|
ColumnType: []byte{mysql.MYSQL_TYPE_LONGLONG},
|
||
|
|
},
|
||
|
|
Rows: [][]interface{}{{int64(-1)}},
|
||
|
|
}
|
||
|
|
|
||
|
|
got := normalizeRowsByUnsigned(event)
|
||
|
|
if v, ok := got[0][0].(int64); !ok || v != -1 {
|
||
|
|
t.Fatalf("value should remain signed when metadata missing: %T %v", got[0][0], got[0][0])
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestParseBinlogEvent_IncludeColumnMetadata(t *testing.T) {
|
||
|
|
event := &replication.RowsEvent{
|
||
|
|
Table: &replication.TableMapEvent{
|
||
|
|
ColumnCount: 3,
|
||
|
|
ColumnType: []byte{mysql.MYSQL_TYPE_VAR_STRING, mysql.MYSQL_TYPE_LONG, mysql.MYSQL_TYPE_VAR_STRING},
|
||
|
|
DefaultCharset: []uint64{45}, // utf8mb4_general_ci
|
||
|
|
},
|
||
|
|
Rows: [][]interface{}{{"name", int32(1), "desc"}},
|
||
|
|
}
|
||
|
|
|
||
|
|
ev := &replication.BinlogEvent{
|
||
|
|
Header: &replication.EventHeader{EventType: replication.WRITE_ROWS_EVENTv2},
|
||
|
|
Event: event,
|
||
|
|
}
|
||
|
|
|
||
|
|
events := ParseBinlogEvent(ev)
|
||
|
|
if len(events) != 1 {
|
||
|
|
t.Fatalf("expected 1 event, got %d", len(events))
|
||
|
|
}
|
||
|
|
got := events[0]
|
||
|
|
|
||
|
|
if len(got.ColumnTypes) != 3 {
|
||
|
|
t.Fatalf("unexpected column type length: %d", len(got.ColumnTypes))
|
||
|
|
}
|
||
|
|
if got.ColumnTypes[0] != int(mysql.MYSQL_TYPE_VAR_STRING) || got.ColumnTypes[1] != int(mysql.MYSQL_TYPE_LONG) {
|
||
|
|
t.Fatalf("unexpected column types: %v", got.ColumnTypes)
|
||
|
|
}
|
||
|
|
|
||
|
|
if len(got.ColumnCollationIDs) != 3 {
|
||
|
|
t.Fatalf("unexpected column collation length: %d", len(got.ColumnCollationIDs))
|
||
|
|
}
|
||
|
|
if got.ColumnCollationIDs[0] != 45 {
|
||
|
|
t.Fatalf("unexpected collation for column 0: %d", got.ColumnCollationIDs[0])
|
||
|
|
}
|
||
|
|
if got.ColumnCollationIDs[2] != 45 {
|
||
|
|
t.Fatalf("unexpected collation for column 2: %d", got.ColumnCollationIDs[2])
|
||
|
|
}
|
||
|
|
if got.ColumnCollationIDs[1] != 0 {
|
||
|
|
t.Fatalf("non-character column should keep zero collation: %d", got.ColumnCollationIDs[1])
|
||
|
|
}
|
||
|
|
}
|