Skip to content

Commit

Permalink
sync_diff_inspector: fix return err when float/double is zero (#700)
Browse files Browse the repository at this point in the history
close #699
  • Loading branch information
erwadba authored Mar 6, 2023
1 parent 2218c40 commit 12273bb
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 22 deletions.
32 changes: 12 additions & 20 deletions sync_diff_inspector/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,15 +143,7 @@ func GetTableRowsQueryFormat(schema, table string, tableInfo *model.TableInfo, c

columnNames := make([]string, 0, len(tableInfo.Columns))
for _, col := range tableInfo.Columns {
name := dbutil.ColumnName(col.Name.O)
// When col value is 0, the result is NULL.
// But we can use ISNULL to distinguish between null and 0.
if col.FieldType.GetType() == mysql.TypeFloat {
name = fmt.Sprintf("round(%s, 5-floor(log10(abs(%s)))) as %s", name, name, name)
} else if col.FieldType.GetType() == mysql.TypeDouble {
name = fmt.Sprintf("round(%s, 14-floor(log10(abs(%s)))) as %s", name, name, name)
}
columnNames = append(columnNames, name)
columnNames = append(columnNames, dbutil.ColumnName(col.Name.O))
}
columns := strings.Join(columnNames, ", ")
if collation != "" {
Expand Down Expand Up @@ -539,18 +531,18 @@ func CompareData(map1, map2 map[string]*dbutil.ColumnData, orderKeyCols, columns
str1 = string(data1.Data)
str2 = string(data2.Data)
if column.FieldType.GetType() == mysql.TypeFloat || column.FieldType.GetType() == mysql.TypeDouble {
if data1.IsNull == data2.IsNull && data1.IsNull {
continue
}

num1, err1 := strconv.ParseFloat(str1, 64)
num2, err2 := strconv.ParseFloat(str2, 64)
if err1 != nil || err2 != nil {
err = errors.Errorf("convert %s, %s to float failed, err1: %v, err2: %v", str1, str2, err1, err2)
return
}
if math.Abs(num1-num2) <= 1e-6 {
if data1.IsNull && data2.IsNull {
continue
} else if !data1.IsNull && !data2.IsNull {
num1, err1 := strconv.ParseFloat(str1, 64)
num2, err2 := strconv.ParseFloat(str2, 64)
if err1 != nil || err2 != nil {
err = errors.Errorf("convert %s, %s to float failed, err1: %v, err2: %v", str1, str2, err1, err2)
return
}
if math.Abs(num1-num2) <= 1e-6 {
continue
}
}
} else if column.FieldType.GetType() == mysql.TypeJSON {
if (str1 == str2) || (data1.IsNull && data2.IsNull) {
Expand Down
32 changes: 30 additions & 2 deletions sync_diff_inspector/utils/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func TestBasicTableUtilOperation(t *testing.T) {
require.NoError(t, err)

query, orderKeyCols := GetTableRowsQueryFormat("test", "test", tableInfo, "123")
require.Equal(t, query, "SELECT /*!40001 SQL_NO_CACHE */ `a`, `b`, round(`c`, 5-floor(log10(abs(`c`)))) as `c`, `d` FROM `test`.`test` WHERE %s ORDER BY `a`,`b` COLLATE '123'")
require.Equal(t, query, "SELECT /*!40001 SQL_NO_CACHE */ `a`, `b`, `c`, `d` FROM `test`.`test` WHERE %s ORDER BY `a`,`b` COLLATE '123'")
expectName := []string{"a", "b"}
for i, col := range orderKeyCols {
require.Equal(t, col.Name.O, expectName[i])
Expand Down Expand Up @@ -126,17 +126,30 @@ func TestBasicTableUtilOperation(t *testing.T) {
"c": {Data: []byte("0.2221"), IsNull: false},
"d": {Data: []byte("asdf"), IsNull: false},
}

data7 := map[string]*dbutil.ColumnData{
"a": {Data: []byte("1"), IsNull: true},
"b": {Data: []byte("a"), IsNull: false},
"c": {Data: []byte("0.2221"), IsNull: false},
"d": {Data: []byte("asdf"), IsNull: false},
}
data8 := map[string]*dbutil.ColumnData{
"a": {Data: []byte("1"), IsNull: false},
"b": {Data: []byte("a"), IsNull: false},
"c": {Data: []byte(""), IsNull: true},
"d": {Data: []byte("sdf"), IsNull: false},
}
data9 := map[string]*dbutil.ColumnData{
"a": {Data: []byte("1"), IsNull: false},
"b": {Data: []byte("a"), IsNull: false},
"c": {Data: []byte("0"), IsNull: false},
"d": {Data: []byte("sdf"), IsNull: false},
}

columns := tableInfo.Columns

require.Equal(t, GenerateReplaceDML(data1, tableInfo, "schema"), "REPLACE INTO `schema`.`test`(`a`,`b`,`c`,`d`) VALUES (1,'a',1.22,'sdf');")
require.Equal(t, GenerateDeleteDML(data8, tableInfo, "schema"), "DELETE FROM `schema`.`test` WHERE `a` = 1 AND `b` = 'a' AND `c` is NULL AND `d` = 'sdf' LIMIT 1;")
require.Equal(t, GenerateDeleteDML(data9, tableInfo, "schema"), "DELETE FROM `schema`.`test` WHERE `a` = 1 AND `b` = 'a' AND `c` = 0 AND `d` = 'sdf' LIMIT 1;")
require.Equal(t, GenerateReplaceDMLWithAnnotation(data1, data2, tableInfo, "schema"),
"/*\n"+
" DIFF COLUMNS ╏ `B` ╏ `C` \n"+
Expand Down Expand Up @@ -212,6 +225,21 @@ func TestBasicTableUtilOperation(t *testing.T) {
require.Equal(t, cmp, int32(0))
require.True(t, equal)

equal, cmp, err = CompareData(data1, data8, orderKeyCols, columns)
require.NoError(t, err)
require.Equal(t, cmp, int32(0))
require.False(t, equal)

equal, cmp, err = CompareData(data8, data1, orderKeyCols, columns)
require.NoError(t, err)
require.Equal(t, cmp, int32(0))
require.False(t, equal)

equal, cmp, err = CompareData(data8, data9, orderKeyCols, columns)
require.NoError(t, err)
require.Equal(t, cmp, int32(0))
require.False(t, equal)

// Test ignore columns
createTableSQL = "create table `test`.`test`(`a` int, `c` float, `b` varchar(10), `d` datetime, `e` timestamp, primary key(`a`, `b`), key(`c`, `d`))"
tableInfo, err = dbutil.GetTableInfoBySQL(createTableSQL, parser.New())
Expand Down

0 comments on commit 12273bb

Please sign in to comment.