|
84 | 84 | numberFloat32ValueType = reflect.TypeOf(float32(0))
|
85 | 85 | numberFloat64ValueType = reflect.TypeOf(float64(0))
|
86 | 86 |
|
87 |
| - numre = regexp.MustCompile(`^[ ]*[0-9]*\.?[0-9]+`) |
| 87 | + numre = regexp.MustCompile(`^[ \t\n\r]*[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?`) |
88 | 88 | )
|
89 | 89 |
|
90 | 90 | const (
|
@@ -1004,7 +1004,15 @@ func convertToInt64(t NumberTypeImpl_, v interface{}) (int64, sql.ConvertInRange
|
1004 | 1004 | // If that fails, try as a float and truncate it to integral
|
1005 | 1005 | f, err := strconv.ParseFloat(v, 64)
|
1006 | 1006 | if err != nil {
|
1007 |
| - return 0, sql.OutOfRange, sql.ErrInvalidValue.New(v, t.String()) |
| 1007 | + // Use same truncation logic as float conversion for MySQL compatibility |
| 1008 | + s := numre.FindString(v) |
| 1009 | + if s != "" { |
| 1010 | + f, _ = strconv.ParseFloat(s, 64) |
| 1011 | + f = math.Round(f) |
| 1012 | + return int64(f), sql.InRange, nil |
| 1013 | + } |
| 1014 | + // If no valid number found, return 0 (MySQL behavior for pure non-numeric strings) |
| 1015 | + return 0, sql.InRange, nil |
1008 | 1016 | }
|
1009 | 1017 | f = math.Round(f)
|
1010 | 1018 | return int64(f), sql.InRange, nil
|
@@ -1190,7 +1198,17 @@ func convertToUint64(t NumberTypeImpl_, v interface{}) (uint64, sql.ConvertInRan
|
1190 | 1198 | return val, inRange, err
|
1191 | 1199 | }
|
1192 | 1200 | }
|
1193 |
| - return 0, sql.OutOfRange, sql.ErrInvalidValue.New(v, t.String()) |
| 1201 | + // Use same truncation logic as float conversion for MySQL compatibility |
| 1202 | + s := numre.FindString(v) |
| 1203 | + if s != "" { |
| 1204 | + if f, err := strconv.ParseFloat(s, 64); err == nil { |
| 1205 | + if val, inRange, err := convertToUint64(t, f); err == nil { |
| 1206 | + return val, inRange, err |
| 1207 | + } |
| 1208 | + } |
| 1209 | + } |
| 1210 | + // If no valid number found, return 0 (MySQL behavior for pure non-numeric strings) |
| 1211 | + return 0, sql.InRange, nil |
1194 | 1212 | case bool:
|
1195 | 1213 | if v {
|
1196 | 1214 | return 1, sql.InRange, nil
|
@@ -1290,7 +1308,17 @@ func convertToUint32(t NumberTypeImpl_, v interface{}) (uint32, sql.ConvertInRan
|
1290 | 1308 | return val, inRange, err
|
1291 | 1309 | }
|
1292 | 1310 | }
|
1293 |
| - return 0, sql.OutOfRange, sql.ErrInvalidValue.New(v, t.String()) |
| 1311 | + // Use same truncation logic as float conversion for MySQL compatibility |
| 1312 | + s := numre.FindString(v) |
| 1313 | + if s != "" { |
| 1314 | + if f, err := strconv.ParseFloat(s, 64); err == nil { |
| 1315 | + if val, inRange, err := convertToUint32(t, f); err == nil { |
| 1316 | + return val, inRange, err |
| 1317 | + } |
| 1318 | + } |
| 1319 | + } |
| 1320 | + // If no valid number found, return 0 (MySQL behavior for pure non-numeric strings) |
| 1321 | + return 0, sql.InRange, nil |
1294 | 1322 | case bool:
|
1295 | 1323 | if v {
|
1296 | 1324 | return 1, sql.InRange, nil
|
@@ -1386,7 +1414,17 @@ func convertToUint16(t NumberTypeImpl_, v interface{}) (uint16, sql.ConvertInRan
|
1386 | 1414 | return val, inRange, err
|
1387 | 1415 | }
|
1388 | 1416 | }
|
1389 |
| - return 0, sql.OutOfRange, sql.ErrInvalidValue.New(v, t.String()) |
| 1417 | + // Use same truncation logic as float conversion for MySQL compatibility |
| 1418 | + s := numre.FindString(v) |
| 1419 | + if s != "" { |
| 1420 | + if f, err := strconv.ParseFloat(s, 64); err == nil { |
| 1421 | + if val, inRange, err := convertToUint16(t, f); err == nil { |
| 1422 | + return val, inRange, err |
| 1423 | + } |
| 1424 | + } |
| 1425 | + } |
| 1426 | + // If no valid number found, return 0 (MySQL behavior for pure non-numeric strings) |
| 1427 | + return 0, sql.InRange, nil |
1390 | 1428 | case bool:
|
1391 | 1429 | if v {
|
1392 | 1430 | return 1, sql.InRange, nil
|
@@ -1486,7 +1524,17 @@ func convertToUint8(t NumberTypeImpl_, v interface{}) (uint8, sql.ConvertInRange
|
1486 | 1524 | return val, inRange, err
|
1487 | 1525 | }
|
1488 | 1526 | }
|
1489 |
| - return 0, sql.OutOfRange, sql.ErrInvalidValue.New(v, t.String()) |
| 1527 | + // Use same truncation logic as float conversion for MySQL compatibility |
| 1528 | + s := numre.FindString(v) |
| 1529 | + if s != "" { |
| 1530 | + if f, err := strconv.ParseFloat(s, 64); err == nil { |
| 1531 | + if val, inRange, err := convertToUint8(t, f); err == nil { |
| 1532 | + return val, inRange, err |
| 1533 | + } |
| 1534 | + } |
| 1535 | + } |
| 1536 | + // If no valid number found, return 0 (MySQL behavior for pure non-numeric strings) |
| 1537 | + return 0, sql.InRange, nil |
1490 | 1538 | case bool:
|
1491 | 1539 | if v {
|
1492 | 1540 | return 1, sql.InRange, nil
|
@@ -1542,8 +1590,12 @@ func convertToFloat64(t NumberTypeImpl_, v interface{}) (float64, error) {
|
1542 | 1590 | if err != nil {
|
1543 | 1591 | // parse the first longest valid numbers
|
1544 | 1592 | s := numre.FindString(v)
|
1545 |
| - i, _ = strconv.ParseFloat(s, 64) |
1546 |
| - return i, sql.ErrInvalidValue.New(v, t.String()) |
| 1593 | + if s != "" { |
| 1594 | + i, _ = strconv.ParseFloat(s, 64) |
| 1595 | + return i, nil |
| 1596 | + } |
| 1597 | + // If no valid number found, return 0 (MySQL behavior for pure non-numeric strings) |
| 1598 | + return 0, nil |
1547 | 1599 | }
|
1548 | 1600 | return i, nil
|
1549 | 1601 | case bool:
|
|
0 commit comments