diff --git a/expression/integration_test/integration_test.go b/expression/integration_test/integration_test.go index 7f3537f53b56a..a571a662efe9c 100644 --- a/expression/integration_test/integration_test.go +++ b/expression/integration_test/integration_test.go @@ -938,11 +938,20 @@ func TestStringBuiltin(t *testing.T) { result.Check(testkit.Rows("114.57011441 38.04620115 114.57011441,38.04620115", "-38.04620119 38.04620115 -38.04620119,38.04620115")) +<<<<<<< HEAD // For issue 31603, only affects unistore. tk.MustExec("drop table if exists t1;") tk.MustExec("create table t1(c1 varbinary(100));") tk.MustExec("insert into t1 values('abc');") tk.MustQuery("select 1 from t1 where char_length(c1) = 10;").Check(testkit.Rows()) +======= + // issue 44359 + tk.MustExec("drop table if exists t1") + tk.MustExec("CREATE TABLE t1 (c1 INT UNSIGNED NOT NULL )") + tk.MustExec("INSERT INTO t1 VALUES (0)") + tk.MustQuery("SELECT c1 FROM t1 WHERE c1 <> CAST(POW(-'0', 1) AS BINARY)").Check(testkit.Rows()) + tk.MustQuery("SELECT c1 FROM t1 WHERE c1 = CAST('-000' AS BINARY)").Check(testkit.Rows("0")) +>>>>>>> 6397d4753f4 (types: fix convert str `-00*` to uint (#46721)) } func TestInvalidStrings(t *testing.T) { diff --git a/types/convert.go b/types/convert.go index 862997c2319a1..c5028641538bf 100644 --- a/types/convert.go +++ b/types/convert.go @@ -296,11 +296,26 @@ func StrToInt(sc *stmtctx.StatementContext, str string, isFuncCast bool) (int64, func StrToUint(sc *stmtctx.StatementContext, str string, isFuncCast bool) (uint64, error) { str = strings.TrimSpace(str) validPrefix, err := getValidIntPrefix(sc, str, isFuncCast) - if validPrefix[0] == '+' { - validPrefix = validPrefix[1:] + uVal := uint64(0) + hasParseErr := false + + if validPrefix[0] == '-' { + // only `-000*` is valid to be converted into unsigned integer + for _, v := range validPrefix[1:] { + if v != '0' { + hasParseErr = true + break + } + } + } else { + if validPrefix[0] == '+' { + validPrefix = validPrefix[1:] + } + v, e := strconv.ParseUint(validPrefix, 10, 64) + uVal, hasParseErr = v, e != nil } - uVal, err1 := strconv.ParseUint(validPrefix, 10, 64) - if err1 != nil { + + if hasParseErr { return uVal, ErrOverflow.GenWithStackByArgs("BIGINT UNSIGNED", validPrefix) } return uVal, errors.Trace(err) diff --git a/types/convert_test.go b/types/convert_test.go index 2794f33f944cf..4ffb956b40d83 100644 --- a/types/convert_test.go +++ b/types/convert_test.go @@ -533,6 +533,9 @@ func TestStrToNum(t *testing.T) { testStrToUint(t, "11xx", 11, true, ErrTruncatedWrongVal) testStrToUint(t, "xx11", 0, true, ErrTruncatedWrongVal) + // for issue #44359 + testStrToUint(t, "-00", 0, true, nil) + // TODO: makes StrToFloat return truncated value instead of zero to make it pass. testStrToFloat(t, "", 0, true, ErrTruncatedWrongVal) testStrToFloat(t, "-1", -1.0, true, nil)