diff --git a/enginetest/queries/variable_queries.go b/enginetest/queries/variable_queries.go index f530e216e3..2d38a0c36d 100644 --- a/enginetest/queries/variable_queries.go +++ b/enginetest/queries/variable_queries.go @@ -633,6 +633,153 @@ var VariableQueries = []ScriptTest{ }, }, }, + { + Name: "mysql_string_to_number system variable", + Assertions: []ScriptTestAssertion{ + { + Query: "SELECT @@mysql_string_to_number", + Expected: []sql.Row{{int8(0)}}, + }, + { + Query: "SET @@mysql_string_to_number = 1", + Expected: []sql.Row{{types.NewOkResult(0)}}, + }, + { + Query: "SELECT @@mysql_string_to_number", + Expected: []sql.Row{{int8(1)}}, + }, + { + Query: "SET @@mysql_string_to_number = 0", + Expected: []sql.Row{{types.NewOkResult(0)}}, + }, + { + Query: "SELECT @@mysql_string_to_number", + Expected: []sql.Row{{int8(0)}}, + }, + { + Query: "SET @@session.mysql_string_to_number = 1", + Expected: []sql.Row{{types.NewOkResult(0)}}, + }, + { + Query: "SELECT @@session.mysql_string_to_number", + Expected: []sql.Row{{int8(1)}}, + }, + { + Query: "SET @@global.mysql_string_to_number = 0", + Expected: []sql.Row{{types.NewOkResult(0)}}, + }, + { + Query: "SELECT @@global.mysql_string_to_number", + Expected: []sql.Row{{int8(0)}}, + }, + }, + }, + { + Name: "mysql_string_to_number conversion behavior", + SetUpScript: []string{ + "CREATE TABLE test_table (id INT PRIMARY KEY, int_col INT, float_col FLOAT)", + "INSERT INTO test_table VALUES (1, 10, 10.5)", + }, + Assertions: []ScriptTestAssertion{ + // Variable disabled - original behavior + { + Query: "SET @@mysql_string_to_number = 0", + Expected: []sql.Row{{types.NewOkResult(0)}}, + }, + { + Query: "SELECT CAST('123abc' AS SIGNED)", + Expected: []sql.Row{{int64(0)}}, + }, + { + Query: "SELECT CAST('_123_' AS SIGNED)", + Expected: []sql.Row{{int64(0)}}, + }, + { + Query: "SELECT CAST('abc123' AS SIGNED)", + Expected: []sql.Row{{int64(0)}}, + }, + // Variable enabled - extract numeric prefixes + { + Query: "SET @@mysql_string_to_number = 1", + Expected: []sql.Row{{types.NewOkResult(0)}}, + }, + { + Query: "SELECT CAST('123abc' AS SIGNED)", + Expected: []sql.Row{{int64(123)}}, + }, + { + Query: "SELECT CAST('_123_' AS SIGNED)", + Expected: []sql.Row{{int64(0)}}, + }, + { + Query: "SELECT CAST('123_' AS SIGNED)", + Expected: []sql.Row{{int64(123)}}, + }, + { + Query: "SELECT CAST('abc123' AS SIGNED)", + Expected: []sql.Row{{int64(0)}}, + }, + { + Query: "SELECT CAST(' 123 ' AS SIGNED)", + Expected: []sql.Row{{int64(123)}}, + }, + { + Query: "SELECT CAST(' +45.67e2' AS SIGNED)", + Expected: []sql.Row{{int64(45)}}, + }, + { + Query: "SELECT CAST('-789.123' AS SIGNED)", + Expected: []sql.Row{{int64(-789)}}, + }, + { + Query: "SELECT CAST('123%' AS SIGNED)", + Expected: []sql.Row{{int64(123)}}, + }, + { + Query: "SELECT CAST('#123' AS SIGNED)", + Expected: []sql.Row{{int64(0)}}, + }, + { + Query: "SELECT CAST('123.456' AS SIGNED)", + Expected: []sql.Row{{int64(123)}}, + }, + // Test decimal conversions + { + Query: "SELECT CAST('123.456abc' AS DECIMAL(10,3))", + Expected: []sql.Row{{"123.456"}}, + }, + { + Query: "SELECT CAST('_123.456_' AS DECIMAL(10,3))", + Expected: []sql.Row{{"0.000"}}, + }, + { + Query: "SELECT CAST('45.67e2' AS DECIMAL(10,2))", + Expected: []sql.Row{{"4567.00"}}, + }, + // Test unsigned type handling + { + Query: "SELECT CAST('123abc' AS UNSIGNED)", + Expected: []sql.Row{{uint64(123)}}, + }, + { + Query: "SELECT CAST('-123abc' AS UNSIGNED)", + Expected: []sql.Row{{uint64(18446744073709551493)}}, + }, + // Test comparison operations from issue #7128 + { + Query: "SELECT * FROM test_table WHERE int_col = '10abc'", + Expected: []sql.Row{{1, 10, float32(10.5)}}, + }, + { + Query: "SELECT * FROM test_table WHERE float_col = '10.5xyz'", + Expected: []sql.Row{{1, 10, float32(10.5)}}, + }, + { + Query: "SELECT * FROM test_table WHERE int_col = '_10_'", + Expected: []sql.Row{}, + }, + }, + }, //TODO: do not override tables with user-var-like names...but why would you do this?? //{ // Name: "user var table name no conflict", diff --git a/sql/expression/convert.go b/sql/expression/convert.go index 6a07498e3d..69da36dff4 100644 --- a/sql/expression/convert.go +++ b/sql/expression/convert.go @@ -339,11 +339,24 @@ func convertValue(ctx *sql.Context, val interface{}, castTo string, originType s } return d, nil case ConvertToDecimal: + dt := createConvertedDecimalType(typeLength, typeScale, false) + + // Handle string-to-decimal conversion for mysql_string_to_number mode + if strVal, ok := val.(string); ok && sql.ValidateStringToNumberMode(ctx) { + if convertedVal, _, err := types.Float64.Convert(ctx, strVal); err == nil { + d, _, err := dt.Convert(ctx, convertedVal) + if err != nil { + return dt.Zero(), nil + } + return d, nil + } + } + value, err := convertHexBlobToDecimalForNumericContext(val, originType) if err != nil { return nil, err } - dt := createConvertedDecimalType(typeLength, typeScale, false) + d, _, err := dt.Convert(ctx, value) if err != nil { return dt.Zero(), nil diff --git a/sql/sql_mode.go b/sql/sql_mode.go index 51407aae2f..359f2adb90 100644 --- a/sql/sql_mode.go +++ b/sql/sql_mode.go @@ -128,3 +128,16 @@ func ValidateStrictMode(ctx *Context) bool { sqlMode := LoadSqlMode(ctx) return sqlMode.ModeEnabled("STRICT_TRANS_TABLES") || sqlMode.ModeEnabled("STRICT_ALL_TABLES") } + +// ValidateStringToNumberMode returns true if mysql_string_to_number is enabled +func ValidateStringToNumberMode(ctx *Context) bool { + if ctx == nil { + return false + } + if val, err := ctx.GetSessionVariable(ctx, "mysql_string_to_number"); err == nil { + if mysqlCompat, ok := val.(int8); ok { + return mysqlCompat != 0 + } + } + return false +} diff --git a/sql/types/number.go b/sql/types/number.go index af0d6a498f..192ad5404a 100644 --- a/sql/types/number.go +++ b/sql/types/number.go @@ -85,6 +85,10 @@ var ( numberFloat64ValueType = reflect.TypeOf(float64(0)) numre = regexp.MustCompile(`^[ ]*[0-9]*\.?[0-9]+`) + // For integer types: supports whitespace, signs, decimals (no scientific notation) + mysqlIntNumre = regexp.MustCompile(`^[ \t\n\r]*[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)`) + // For float/decimal types: supports whitespace, signs, decimals, scientific notation + mysqlFloatNumre = regexp.MustCompile(`^[ \t\n\r]*[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?`) ) const ( @@ -189,11 +193,11 @@ func (t NumberTypeImpl_) Compare(s context.Context, a interface{}, b interface{} switch t.baseType { case sqltypes.Uint8, sqltypes.Uint16, sqltypes.Uint24, sqltypes.Uint32, sqltypes.Uint64: - ca, _, err := convertToUint64(t, a) + ca, _, err := convertToUint64(s, t, a) if err != nil { return 0, err } - cb, _, err := convertToUint64(t, b) + cb, _, err := convertToUint64(s, t, b) if err != nil { return 0, err } @@ -206,11 +210,11 @@ func (t NumberTypeImpl_) Compare(s context.Context, a interface{}, b interface{} } return +1, nil case sqltypes.Float32, sqltypes.Float64: - ca, err := convertToFloat64(t, a) + ca, err := convertToFloat64(s, t, a) if err != nil { return 0, err } - cb, err := convertToFloat64(t, b) + cb, err := convertToFloat64(s, t, b) if err != nil { return 0, err } @@ -223,11 +227,11 @@ func (t NumberTypeImpl_) Compare(s context.Context, a interface{}, b interface{} } return +1, nil default: - ca, _, err := convertToInt64(t, a) + ca, _, err := convertToInt64(s, t, a) if err != nil { ca = 0 } - cb, _, err := convertToInt64(t, b) + cb, _, err := convertToInt64(s, t, b) if err != nil { cb = 0 } @@ -262,7 +266,7 @@ func (t NumberTypeImpl_) Convert(ctx context.Context, v interface{}) (interface{ switch t.baseType { case sqltypes.Int8: - num, _, err := convertToInt64(t, v) + num, _, err := convertToInt64(ctx, t, v) if err != nil { return nil, sql.OutOfRange, err } @@ -273,9 +277,9 @@ func (t NumberTypeImpl_) Convert(ctx context.Context, v interface{}) (interface{ } return int8(num), sql.InRange, nil case sqltypes.Uint8: - return convertToUint8(t, v) + return convertToUint8(ctx, t, v) case sqltypes.Int16: - num, _, err := convertToInt64(t, v) + num, _, err := convertToInt64(ctx, t, v) if err != nil { return nil, sql.OutOfRange, err } @@ -286,9 +290,9 @@ func (t NumberTypeImpl_) Convert(ctx context.Context, v interface{}) (interface{ } return int16(num), sql.InRange, nil case sqltypes.Uint16: - return convertToUint16(t, v) + return convertToUint16(ctx, t, v) case sqltypes.Int24: - num, _, err := convertToInt64(t, v) + num, _, err := convertToInt64(ctx, t, v) if err != nil { return nil, sql.OutOfRange, err } @@ -299,7 +303,7 @@ func (t NumberTypeImpl_) Convert(ctx context.Context, v interface{}) (interface{ } return int32(num), sql.InRange, nil case sqltypes.Uint24: - num, _, err := convertToInt64(t, v) + num, _, err := convertToInt64(ctx, t, v) if err != nil { return nil, sql.OutOfRange, err } @@ -310,7 +314,7 @@ func (t NumberTypeImpl_) Convert(ctx context.Context, v interface{}) (interface{ } return uint32(num), sql.InRange, nil case sqltypes.Int32: - num, _, err := convertToInt64(t, v) + num, _, err := convertToInt64(ctx, t, v) if err != nil { return nil, sql.OutOfRange, err } @@ -321,13 +325,13 @@ func (t NumberTypeImpl_) Convert(ctx context.Context, v interface{}) (interface{ } return int32(num), sql.InRange, nil case sqltypes.Uint32: - return convertToUint32(t, v) + return convertToUint32(ctx, t, v) case sqltypes.Int64: - return convertToInt64(t, v) + return convertToInt64(ctx, t, v) case sqltypes.Uint64: - return convertToUint64(t, v) + return convertToUint64(ctx, t, v) case sqltypes.Float32: - num, err := convertToFloat64(t, v) + num, err := convertToFloat64(ctx, t, v) if err != nil { return nil, sql.OutOfRange, err } @@ -338,7 +342,7 @@ func (t NumberTypeImpl_) Convert(ctx context.Context, v interface{}) (interface{ } return float32(num), sql.InRange, nil case sqltypes.Float64: - ret, err := convertToFloat64(t, v) + ret, err := convertToFloat64(ctx, t, v) return ret, sql.InRange, err default: return nil, sql.OutOfRange, sql.ErrInvalidType.New(t.baseType.String()) @@ -399,7 +403,7 @@ func (t NumberTypeImpl_) Promote() sql.Type { } func (t NumberTypeImpl_) SQLInt8(ctx *sql.Context, dest []byte, v interface{}) ([]byte, error) { - num, _, err := convertToInt64(t, v) + num, _, err := convertToInt64(ctx, t, v) if err != nil { return nil, err } @@ -413,7 +417,7 @@ func (t NumberTypeImpl_) SQLInt8(ctx *sql.Context, dest []byte, v interface{}) ( } func (t NumberTypeImpl_) SQLInt16(ctx *sql.Context, dest []byte, v interface{}) ([]byte, error) { - num, _, err := convertToInt64(t, v) + num, _, err := convertToInt64(ctx, t, v) if err != nil { return nil, err } @@ -427,7 +431,7 @@ func (t NumberTypeImpl_) SQLInt16(ctx *sql.Context, dest []byte, v interface{}) } func (t NumberTypeImpl_) SQLInt24(ctx *sql.Context, dest []byte, v interface{}) ([]byte, error) { - num, _, err := convertToInt64(t, v) + num, _, err := convertToInt64(ctx, t, v) if err != nil { return nil, err } @@ -441,7 +445,7 @@ func (t NumberTypeImpl_) SQLInt24(ctx *sql.Context, dest []byte, v interface{}) } func (t NumberTypeImpl_) SQLInt32(ctx *sql.Context, dest []byte, v interface{}) ([]byte, error) { - num, _, err := convertToInt64(t, v) + num, _, err := convertToInt64(ctx, t, v) if err != nil { return nil, err } @@ -455,7 +459,7 @@ func (t NumberTypeImpl_) SQLInt32(ctx *sql.Context, dest []byte, v interface{}) } func (t NumberTypeImpl_) SQLInt64(ctx *sql.Context, dest []byte, v interface{}) ([]byte, error) { - vt, _, err := convertToInt64(t, v) + vt, _, err := convertToInt64(ctx, t, v) if err != nil { return nil, err } @@ -464,7 +468,7 @@ func (t NumberTypeImpl_) SQLInt64(ctx *sql.Context, dest []byte, v interface{}) } func (t NumberTypeImpl_) SQLUint8(ctx *sql.Context, dest []byte, v interface{}) ([]byte, error) { - num, _, err := convertToUint64(t, v) + num, _, err := convertToUint64(ctx, t, v) if err != nil { return nil, err } @@ -477,7 +481,7 @@ func (t NumberTypeImpl_) SQLUint8(ctx *sql.Context, dest []byte, v interface{}) } func (t NumberTypeImpl_) SQLUint16(ctx *sql.Context, dest []byte, v interface{}) ([]byte, error) { - num, _, err := convertToUint64(t, v) + num, _, err := convertToUint64(ctx, t, v) if err != nil { return nil, err } @@ -490,7 +494,7 @@ func (t NumberTypeImpl_) SQLUint16(ctx *sql.Context, dest []byte, v interface{}) } func (t NumberTypeImpl_) SQLUint24(ctx *sql.Context, dest []byte, v interface{}) ([]byte, error) { - num, _, err := convertToUint64(t, v) + num, _, err := convertToUint64(ctx, t, v) if err != nil { return nil, err } @@ -503,7 +507,7 @@ func (t NumberTypeImpl_) SQLUint24(ctx *sql.Context, dest []byte, v interface{}) } func (t NumberTypeImpl_) SQLUint32(ctx *sql.Context, dest []byte, v interface{}) ([]byte, error) { - num, _, err := convertToUint64(t, v) + num, _, err := convertToUint64(ctx, t, v) if err != nil { return nil, err } @@ -516,7 +520,7 @@ func (t NumberTypeImpl_) SQLUint32(ctx *sql.Context, dest []byte, v interface{}) } func (t NumberTypeImpl_) SQLUint64(ctx *sql.Context, dest []byte, v interface{}) ([]byte, error) { - num, _, err := convertToUint64(t, v) + num, _, err := convertToUint64(ctx, t, v) if err != nil { return nil, err } @@ -529,7 +533,7 @@ func (t NumberTypeImpl_) SQLUint64(ctx *sql.Context, dest []byte, v interface{}) } func (t NumberTypeImpl_) SQLFloat64(ctx *sql.Context, dest []byte, v interface{}) ([]byte, error) { - num, err := convertToFloat64(t, v) + num, err := convertToFloat64(ctx, t, v) if err != nil { return nil, err } @@ -538,7 +542,7 @@ func (t NumberTypeImpl_) SQLFloat64(ctx *sql.Context, dest []byte, v interface{} } func (t NumberTypeImpl_) SQLFloat32(ctx *sql.Context, dest []byte, v interface{}) ([]byte, error) { - num, err := convertToFloat64(t, v) + num, err := convertToFloat64(ctx, t, v) if err != nil { return nil, err } @@ -936,7 +940,7 @@ func (t NumberTypeImpl_) DisplayWidth() int { return t.displayWidth } -func convertToInt64(t NumberTypeImpl_, v interface{}) (int64, sql.ConvertInRange, error) { +func convertToInt64(ctx context.Context, t NumberTypeImpl_, v interface{}) (int64, sql.ConvertInRange, error) { switch v := v.(type) { case time.Time: return v.UTC().Unix(), sql.InRange, nil @@ -991,20 +995,36 @@ func convertToInt64(t NumberTypeImpl_, v interface{}) (int64, sql.ConvertInRange } return i, sql.InRange, nil case string: + originalV := v v = strings.Trim(v, intCutSet) if v == "" { // StringType{}.Zero() returns empty string, but should represent "0" for number value return 0, sql.InRange, nil } + // Parse first an integer, which allows for more values than float64 i, err := strconv.ParseInt(v, 10, 64) if err == nil { return i, sql.InRange, nil } - // If that fails, try as a float and truncate it to integral + + // Check if MySQL string-to-number mode is enabled before trying full float parsing + if sqlCtx, ok := ctx.(*sql.Context); ok && sql.ValidateStringToNumberMode(sqlCtx) { + // Use MySQL-compatible integer parsing (no scientific notation) + s := mysqlIntNumre.FindString(originalV) + if s != "" { + if extractedFloat, parseErr := strconv.ParseFloat(strings.TrimSpace(s), 64); parseErr == nil { + // Truncate toward zero (like MySQL), don't round + return int64(extractedFloat), sql.InRange, nil + } + } + return 0, sql.InRange, nil + } + + // If that fails, try as a float and truncate it to integral (original behavior) f, err := strconv.ParseFloat(v, 64) if err != nil { - return 0, sql.OutOfRange, sql.ErrInvalidValue.New(v, t.String()) + return 0, sql.OutOfRange, sql.ErrInvalidValue.New(originalV, t.String()) } f = math.Round(f) return int64(f), sql.InRange, nil @@ -1108,7 +1128,7 @@ func convertValueToUint64(t NumberTypeImpl_, v sql.Value) (uint64, error) { } } -func convertToUint64(t NumberTypeImpl_, v interface{}) (uint64, sql.ConvertInRange, error) { +func convertToUint64(ctx context.Context, t NumberTypeImpl_, v interface{}) (uint64, sql.ConvertInRange, error) { switch v := v.(type) { case time.Time: return uint64(v.UTC().Unix()), sql.InRange, nil @@ -1186,7 +1206,7 @@ func convertToUint64(t NumberTypeImpl_, v interface{}) (uint64, sql.ConvertInRan return math.MaxUint64, sql.OutOfRange, nil } if f, err := strconv.ParseFloat(v, 64); err == nil { - if val, inRange, err := convertToUint64(t, f); err == nil && inRange { + if val, inRange, err := convertToUint64(ctx, t, f); err == nil && inRange { return val, inRange, err } } @@ -1203,7 +1223,7 @@ func convertToUint64(t NumberTypeImpl_, v interface{}) (uint64, sql.ConvertInRan } } -func convertToUint32(t NumberTypeImpl_, v interface{}) (uint32, sql.ConvertInRange, error) { +func convertToUint32(ctx context.Context, t NumberTypeImpl_, v interface{}) (uint32, sql.ConvertInRange, error) { switch v := v.(type) { case int: if v < 0 { @@ -1286,7 +1306,7 @@ func convertToUint32(t NumberTypeImpl_, v interface{}) (uint32, sql.ConvertInRan return uint32(i), sql.InRange, nil } if f, err := strconv.ParseFloat(v, 64); err == nil { - if val, inRange, err := convertToUint32(t, f); err == nil && inRange { + if val, inRange, err := convertToUint32(ctx, t, f); err == nil && inRange { return val, inRange, err } } @@ -1303,7 +1323,7 @@ func convertToUint32(t NumberTypeImpl_, v interface{}) (uint32, sql.ConvertInRan } } -func convertToUint16(t NumberTypeImpl_, v interface{}) (uint16, sql.ConvertInRange, error) { +func convertToUint16(ctx context.Context, t NumberTypeImpl_, v interface{}) (uint16, sql.ConvertInRange, error) { switch v := v.(type) { case int: if v < 0 { @@ -1382,7 +1402,7 @@ func convertToUint16(t NumberTypeImpl_, v interface{}) (uint16, sql.ConvertInRan return uint16(i), sql.InRange, nil } if f, err := strconv.ParseFloat(v, 64); err == nil { - if val, inRange, err := convertToUint16(t, f); err == nil && inRange { + if val, inRange, err := convertToUint16(ctx, t, f); err == nil && inRange { return val, inRange, err } } @@ -1399,7 +1419,7 @@ func convertToUint16(t NumberTypeImpl_, v interface{}) (uint16, sql.ConvertInRan } } -func convertToUint8(t NumberTypeImpl_, v interface{}) (uint8, sql.ConvertInRange, error) { +func convertToUint8(ctx context.Context, t NumberTypeImpl_, v interface{}) (uint8, sql.ConvertInRange, error) { switch v := v.(type) { case int: if v < 0 { @@ -1482,7 +1502,7 @@ func convertToUint8(t NumberTypeImpl_, v interface{}) (uint8, sql.ConvertInRange return uint8(i), sql.InRange, nil } if f, err := strconv.ParseFloat(v, 64); err == nil { - if val, inRange, err := convertToUint8(t, f); err == nil && inRange { + if val, inRange, err := convertToUint8(ctx, t, f); err == nil && inRange { return val, inRange, err } } @@ -1499,7 +1519,7 @@ func convertToUint8(t NumberTypeImpl_, v interface{}) (uint8, sql.ConvertInRange } } -func convertToFloat64(t NumberTypeImpl_, v interface{}) (float64, error) { +func convertToFloat64(ctx context.Context, t NumberTypeImpl_, v interface{}) (float64, error) { switch v := v.(type) { case time.Time: return float64(v.UTC().Unix()), nil @@ -1537,13 +1557,30 @@ func convertToFloat64(t NumberTypeImpl_, v interface{}) (float64, error) { } return float64(i), nil case string: + originalV := v v = strings.Trim(v, numericCutSet) i, err := strconv.ParseFloat(v, 64) if err != nil { - // parse the first longest valid numbers - s := numre.FindString(v) - i, _ = strconv.ParseFloat(s, 64) - return i, sql.ErrInvalidValue.New(v, t.String()) + // Extract numeric prefix using appropriate regex + var extractedFloat float64 + var s string + + if sqlCtx, ok := ctx.(*sql.Context); ok && sql.ValidateStringToNumberMode(sqlCtx) { + s = mysqlFloatNumre.FindString(originalV) + } else { + s = numre.FindString(originalV) + } + + if s != "" { + if f, parseErr := strconv.ParseFloat(strings.TrimSpace(s), 64); parseErr == nil { + extractedFloat = f + if sqlCtx, ok := ctx.(*sql.Context); ok && sql.ValidateStringToNumberMode(sqlCtx) { + return extractedFloat, nil + } + return extractedFloat, sql.ErrInvalidValue.New(originalV, t.String()) + } + } + return 0, sql.ErrInvalidValue.New(originalV, t.String()) } return i, nil case bool: diff --git a/sql/types/strings.go b/sql/types/strings.go index 96fadd5498..bac8e8ce22 100644 --- a/sql/types/strings.go +++ b/sql/types/strings.go @@ -725,13 +725,13 @@ func (t StringType) SQL(ctx *sql.Context, dest []byte, v interface{}) (sqltypes. dest = append(dest, v...) valueBytes = dest[start:] case int, int8, int16, int32, int64: - num, _, err := convertToInt64(Int64.(NumberTypeImpl_), v) + num, _, err := convertToInt64(ctx, Int64.(NumberTypeImpl_), v) if err != nil { return sqltypes.Value{}, err } valueBytes = strconv.AppendInt(dest, num, 10) case uint, uint8, uint16, uint32, uint64: - num, _, err := convertToUint64(Int64.(NumberTypeImpl_), v) + num, _, err := convertToUint64(ctx, Int64.(NumberTypeImpl_), v) if err != nil { return sqltypes.Value{}, err } diff --git a/sql/variables/system_variables.go b/sql/variables/system_variables.go index 9839455b81..32abcb0049 100644 --- a/sql/variables/system_variables.go +++ b/sql/variables/system_variables.go @@ -2603,6 +2603,14 @@ var systemVars = map[string]sql.SystemVariable{ Type: types.NewSystemBoolType("strict_mysql_compatibility"), Default: int8(0), }, + "mysql_string_to_number": &sql.MysqlSystemVariable{ + Name: "mysql_string_to_number", + Scope: sql.GetMysqlScope(sql.SystemVariableScope_Both), + Dynamic: true, + SetVarHintApplies: false, + Type: types.NewSystemBoolType("mysql_string_to_number"), + Default: int8(0), + }, "super_read_only": &sql.MysqlSystemVariable{ Name: "super_read_only", Scope: sql.GetMysqlScope(sql.SystemVariableScope_Global),