@@ -997,23 +997,16 @@ func convertToInt64(ctx context.Context, t NumberTypeImpl_, v interface{}) (int6
997997 // StringType{}.Zero() returns empty string, but should represent "0" for number value
998998 return 0 , sql .InRange , nil
999999 }
1000-
1001- // Check if strict conversion mode is enabled (e.g., for JSON_TABLE ERROR ON ERROR )
1000+
1001+ // Check if strict mode is enabled via sql_mode (STRICT_TRANS_TABLES/STRICT_ALL_TABLES )
10021002 strictMode := false
1003- if strictValue := ctx .Value (StrictConvertKey ); strictValue != nil {
1004- if strict , ok := strictValue .(bool ); ok {
1005- strictMode = strict
1006- }
1007- }
1008- // Also check for string-based key (for schema validation)
1009- if ! strictMode {
1010- if strictValue := ctx .Value ("strict_convert" ); strictValue != nil {
1011- if strict , ok := strictValue .(bool ); ok {
1012- strictMode = strict
1013- }
1014- }
1003+ if sqlCtx , ok := ctx .(* sql.Context ); ok && sqlCtx != nil {
1004+ strictMode = sql .ValidateStrictMode (sqlCtx )
10151005 }
1016-
1006+
1007+ // Note: IGNORE mode handling is done at the iterator level
1008+ // rather than in individual type conversions for better separation of concerns
1009+
10171010 // Parse first an integer, which allows for more values than float64
10181011 i , err := strconv .ParseInt (v , 10 , 64 )
10191012 if err == nil {
@@ -1022,26 +1015,24 @@ func convertToInt64(ctx context.Context, t NumberTypeImpl_, v interface{}) (int6
10221015 // If that fails, try as a float and truncate it to integral
10231016 f , err := strconv .ParseFloat (v , 64 )
10241017 if err != nil {
1025- // In strict mode, return error instead of truncating
1026- if strictMode {
1027- return 0 , sql .OutOfRange , sql .ErrInvalidValue .New (originalV , "int" )
1028- }
1029-
1030- // Use same truncation logic as float conversion for MySQL compatibility
1031- s := numre .FindString (v )
1018+ // Always try MySQL-compatible truncation first for arithmetic expressions
1019+ s := numre .FindString (originalV )
10321020 if s != "" {
1033- f , _ = strconv .ParseFloat (s , 64 )
1034- f = math .Round (f )
1035- // Generate warning for truncated string
1036- if sqlCtx , ok := ctx .(* sql.Context ); ok && sqlCtx != nil {
1037- sqlCtx .Warn (1366 , "Incorrect integer value: '%s' for column" , originalV )
1021+ f , parseErr := strconv .ParseFloat (s , 64 )
1022+ if parseErr == nil {
1023+ f = math .Round (f )
1024+ return int64 (f ), sql .InRange , nil
10381025 }
1039- return int64 (f ), sql .InRange , nil
10401026 }
1041- // If no valid number found, return 0 (MySQL behavior for pure non-numeric strings)
1042- if sqlCtx , ok := ctx .(* sql.Context ); ok && sqlCtx != nil {
1043- sqlCtx .Warn (1366 , "Incorrect integer value: '%s' for column" , originalV )
1027+
1028+ // For purely non-numeric strings like 'two', 'four', etc., return error
1029+ // This allows Dolt's diff system to handle incompatible type conversions correctly
1030+ // In strict mode, also return error for better schema validation
1031+ if strictMode || s == "" {
1032+ return 0 , sql .OutOfRange , sql .ErrInvalidValue .New (originalV , "int" )
10441033 }
1034+
1035+ // If no valid number found, return 0 (MySQL behavior for pure non-numeric strings)
10451036 return 0 , sql .InRange , nil
10461037 }
10471038 f = math .Round (f )
@@ -1547,23 +1538,16 @@ func convertToUint8(ctx context.Context, t NumberTypeImpl_, v interface{}) (uint
15471538 case string :
15481539 originalV := v
15491540 v = strings .Trim (v , intCutSet )
1550-
1551- // Check if strict conversion mode is enabled (e.g., for procedure parameter validation )
1541+
1542+ // Check if strict mode is enabled via sql_mode (STRICT_TRANS_TABLES/STRICT_ALL_TABLES )
15521543 strictMode := false
1553- if strictValue := ctx .Value (StrictConvertKey ); strictValue != nil {
1554- if strict , ok := strictValue .(bool ); ok {
1555- strictMode = strict
1556- }
1557- }
1558- // Also check for string-based key (for schema validation)
1559- if ! strictMode {
1560- if strictValue := ctx .Value ("strict_convert" ); strictValue != nil {
1561- if strict , ok := strictValue .(bool ); ok {
1562- strictMode = strict
1563- }
1564- }
1544+ if sqlCtx , ok := ctx .(* sql.Context ); ok && sqlCtx != nil {
1545+ strictMode = sql .ValidateStrictMode (sqlCtx )
15651546 }
1566-
1547+
1548+ // Note: IGNORE mode handling is done at the iterator level
1549+ // rather than in individual type conversions for better separation of concerns
1550+
15671551 if i , err := strconv .ParseUint (v , 10 , 8 ); err == nil {
15681552 return uint8 (i ), sql .InRange , nil
15691553 }
@@ -1572,21 +1556,22 @@ func convertToUint8(ctx context.Context, t NumberTypeImpl_, v interface{}) (uint
15721556 return val , inRange , err
15731557 }
15741558 }
1575-
1576- // In strict mode, return error instead of truncating
1577- if strictMode {
1578- return 0 , sql .OutOfRange , sql .ErrInvalidValue .New (originalV , t .String ())
1579- }
1580-
1559+
15811560 // Use same truncation logic as float conversion for MySQL compatibility
1582- s := numre .FindString (v )
1561+ s := numre .FindString (originalV )
15831562 if s != "" {
15841563 if f , err := strconv .ParseFloat (s , 64 ); err == nil {
15851564 if val , inRange , err := convertToUint8 (ctx , t , f ); err == nil {
15861565 return val , inRange , err
15871566 }
15881567 }
15891568 }
1569+
1570+ // In strict mode, return error instead of truncating for schema validation
1571+ if strictMode {
1572+ return 0 , sql .OutOfRange , sql .ErrInvalidValue .New (originalV , t .String ())
1573+ }
1574+
15901575 // If no valid number found, return 0 (MySQL behavior for pure non-numeric strings)
15911576 return 0 , sql .InRange , nil
15921577 case bool :
@@ -1639,38 +1624,34 @@ func convertToFloat64(ctx context.Context, t NumberTypeImpl_, v interface{}) (fl
16391624 }
16401625 return float64 (i ), nil
16411626 case string :
1642- v = strings .Trim (v , numericCutSet )
16431627 originalV := v
1644-
1645- // Check if strict conversion mode is enabled (e.g., for schema validation)
1628+ v = strings .Trim (v , numericCutSet )
1629+
1630+ // Check if strict mode is enabled via sql_mode (STRICT_TRANS_TABLES/STRICT_ALL_TABLES)
16461631 strictMode := false
1647- if strictValue := ctx .Value (StrictConvertKey ); strictValue != nil {
1648- if strict , ok := strictValue .(bool ); ok {
1649- strictMode = strict
1650- }
1632+ if sqlCtx , ok := ctx .(* sql.Context ); ok && sqlCtx != nil {
1633+ strictMode = sql .ValidateStrictMode (sqlCtx )
16511634 }
1652- // Also check for string-based key (for schema validation)
1653- if ! strictMode {
1654- if strictValue := ctx .Value ("strict_convert" ); strictValue != nil {
1655- if strict , ok := strictValue .(bool ); ok {
1656- strictMode = strict
1657- }
1658- }
1659- }
1660-
1635+
1636+ // Note: IGNORE mode handling is done at the iterator level
1637+ // rather than in individual type conversions for better separation of concerns
1638+
16611639 i , err := strconv .ParseFloat (v , 64 )
16621640 if err != nil {
1663- // In strict mode, return error instead of truncating
1641+ // Always try MySQL-compatible truncation first for arithmetic expressions
1642+ s := numre .FindString (originalV )
1643+ if s != "" {
1644+ f , parseErr := strconv .ParseFloat (s , 64 )
1645+ if parseErr == nil {
1646+ return f , nil
1647+ }
1648+ }
1649+
1650+ // In strict mode, return error instead of truncating for schema validation
16641651 if strictMode {
16651652 return 0 , sql .ErrInvalidValue .New (originalV , t .String ())
16661653 }
1667-
1668- // parse the first longest valid numbers
1669- s := numre .FindString (v )
1670- if s != "" {
1671- i , _ = strconv .ParseFloat (s , 64 )
1672- return i , nil
1673- }
1654+
16741655 // If no valid number found, return 0 (MySQL behavior for pure non-numeric strings)
16751656 return 0 , nil
16761657 }
0 commit comments