From 064acea5f43e44ae4cd4d0ed90c436fb3a83d89f Mon Sep 17 00:00:00 2001 From: arvenil Date: Sun, 1 Feb 2015 18:18:49 +0100 Subject: [PATCH 1/9] Test case for wrong float64 value after selecting it from FLOAT table field --- driver_test.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/driver_test.go b/driver_test.go index a52cc5cd0..5c6496e11 100644 --- a/driver_test.go +++ b/driver_test.go @@ -1245,6 +1245,39 @@ func TestTimezoneConversion(t *testing.T) { } } +func TestSelectFloatToFloat64(t *testing.T) { + createTest := func(query string, args ...interface{}) func(dbt *DBTest) { + return func(dbt *DBTest) { + v := float64(0.050551) + + // Create table + dbt.mustExec("CREATE TABLE test (f FLOAT)") + dbt.mustExec("INSERT INTO test VALUE (?)", v) + + // Retrieve + rows := dbt.mustQuery(query, args...) + if !rows.Next() { + dbt.Fatal("Didn't get any rows out") + } + + var f float64 + err := rows.Scan(&f) + if err != nil { + dbt.Fatal("Err", err) + } + + // Check that dates match + if f != v { + dbt.Errorf("Float values don't match.\n") + dbt.Errorf(" Inserted: %v\n", v) + dbt.Errorf(" Selected: %v\n", f) + } + } + } + + runTests(t, dsn, createTest("SELECT f FROM test WHERE 1=?", 1)) +} + // Special cases func TestRowsClose(t *testing.T) { From fc1c08e81ac71ce81c9309e92d749171ca6cd174 Mon Sep 17 00:00:00 2001 From: arvenil Date: Sun, 1 Feb 2015 18:21:24 +0100 Subject: [PATCH 2/9] Bugfix for selecting FLOAT to float64 --- packets.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packets.go b/packets.go index 255301e81..98e5e3bc0 100644 --- a/packets.go +++ b/packets.go @@ -1037,7 +1037,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error { continue case fieldTypeFloat: - dest[i] = float64(math.Float32frombits(binary.LittleEndian.Uint32(data[pos : pos+4]))) + dest[i] = float32(math.Float32frombits(binary.LittleEndian.Uint32(data[pos : pos+4]))) pos += 4 continue From 38e6bd4733d71e727d50cc7a7e066b9890542f45 Mon Sep 17 00:00:00 2001 From: arvenil Date: Sun, 1 Feb 2015 18:29:52 +0100 Subject: [PATCH 3/9] Another failing case is for non-prepared queries with parseTime=true --- driver_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/driver_test.go b/driver_test.go index 5c6496e11..d4cfbd9e2 100644 --- a/driver_test.go +++ b/driver_test.go @@ -1276,6 +1276,7 @@ func TestSelectFloatToFloat64(t *testing.T) { } runTests(t, dsn, createTest("SELECT f FROM test WHERE 1=?", 1)) + runTests(t, dsn+"&parseTime=true", createTest("SELECT IFNULL(f, 0) f FROM test")) } // Special cases From af12796884060cd3e62b8695408f6e5af4afa58a Mon Sep 17 00:00:00 2001 From: arvenil Date: Sun, 1 Feb 2015 18:35:19 +0100 Subject: [PATCH 4/9] And fix for it --- packets.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packets.go b/packets.go index 98e5e3bc0..436312322 100644 --- a/packets.go +++ b/packets.go @@ -16,6 +16,7 @@ import ( "fmt" "io" "math" + "strconv" "time" ) @@ -629,6 +630,12 @@ func (rows *textRows) readRow(dest []driver.Value) error { if err == nil { continue } + case fieldTypeFloat: + val, err := strconv.ParseFloat(string(dest[i].([]byte)), 32) + dest[i] = float32(val) + if err == nil { + continue + } default: continue } From 855d2cf33cc444a225a3409270c20acb791d8571 Mon Sep 17 00:00:00 2001 From: arvenil Date: Sun, 1 Feb 2015 18:37:47 +0100 Subject: [PATCH 5/9] Well without &parseTime=true it doesn't work too --- driver_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/driver_test.go b/driver_test.go index d4cfbd9e2..649db6887 100644 --- a/driver_test.go +++ b/driver_test.go @@ -1277,6 +1277,7 @@ func TestSelectFloatToFloat64(t *testing.T) { runTests(t, dsn, createTest("SELECT f FROM test WHERE 1=?", 1)) runTests(t, dsn+"&parseTime=true", createTest("SELECT IFNULL(f, 0) f FROM test")) + runTests(t, dsn, createTest("SELECT IFNULL(f, 0) f FROM test")) } // Special cases From 0a6d62a21e8cfa41189aa2323f7a98a20c932d1e Mon Sep 17 00:00:00 2001 From: arvenil Date: Sun, 1 Feb 2015 18:40:20 +0100 Subject: [PATCH 6/9] And hacky fix for it --- packets.go | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/packets.go b/packets.go index 436312322..77ac87d6b 100644 --- a/packets.go +++ b/packets.go @@ -617,28 +617,31 @@ func (rows *textRows) readRow(dest []driver.Value) error { pos += n if err == nil { if !isNull { - if !mc.parseTime { + // @todo hacky fix, please make it better + if i > len(rows.columns)-1 { continue - } else { - switch rows.columns[i].fieldType { - case fieldTypeTimestamp, fieldTypeDateTime, - fieldTypeDate, fieldTypeNewDate: - dest[i], err = parseDateTime( - string(dest[i].([]byte)), - mc.cfg.loc, - ) - if err == nil { - continue - } - case fieldTypeFloat: - val, err := strconv.ParseFloat(string(dest[i].([]byte)), 32) - dest[i] = float32(val) - if err == nil { - continue - } - default: + } + switch rows.columns[i].fieldType { + case fieldTypeTimestamp, fieldTypeDateTime, + fieldTypeDate, fieldTypeNewDate: + if !mc.parseTime { continue } + dest[i], err = parseDateTime( + string(dest[i].([]byte)), + mc.cfg.loc, + ) + if err == nil { + continue + } + case fieldTypeFloat: + val, err := strconv.ParseFloat(string(dest[i].([]byte)), 32) + dest[i] = float32(val) + if err == nil { + continue + } + default: + continue } } else { From ab09bce3a0a9e9ebe6cd3af87c9bdf991fac308a Mon Sep 17 00:00:00 2001 From: arvenil Date: Sun, 1 Feb 2015 18:42:23 +0100 Subject: [PATCH 7/9] Funny thing, that not prepared statement without IFNULL workerd without problems from the begining, but just in case let's place it here --- driver_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/driver_test.go b/driver_test.go index 649db6887..95dd0736d 100644 --- a/driver_test.go +++ b/driver_test.go @@ -1275,6 +1275,7 @@ func TestSelectFloatToFloat64(t *testing.T) { } } + runTests(t, dsn, createTest("SELECT f FROM test")) runTests(t, dsn, createTest("SELECT f FROM test WHERE 1=?", 1)) runTests(t, dsn+"&parseTime=true", createTest("SELECT IFNULL(f, 0) f FROM test")) runTests(t, dsn, createTest("SELECT IFNULL(f, 0) f FROM test")) From 89b0d92f463ef8fe1e7b379b687f72060c388fc9 Mon Sep 17 00:00:00 2001 From: arvenil Date: Sun, 1 Feb 2015 18:45:12 +0100 Subject: [PATCH 8/9] Let's be sure prepared statements also work with parseTime=true --- driver_test.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/driver_test.go b/driver_test.go index 95dd0736d..f9cf1ebb6 100644 --- a/driver_test.go +++ b/driver_test.go @@ -1275,10 +1275,15 @@ func TestSelectFloatToFloat64(t *testing.T) { } } - runTests(t, dsn, createTest("SELECT f FROM test")) - runTests(t, dsn, createTest("SELECT f FROM test WHERE 1=?", 1)) - runTests(t, dsn+"&parseTime=true", createTest("SELECT IFNULL(f, 0) f FROM test")) - runTests(t, dsn, createTest("SELECT IFNULL(f, 0) f FROM test")) + dsns := []string{ + dsn + "&parseTime=true", + dsn + "&parseTime=false", + } + for _, testdsn := range dsns { + runTests(t, testdsn, createTest("SELECT f FROM test")) // not prepared statement + runTests(t, testdsn, createTest("SELECT f FROM test WHERE 1=?", 1)) // prepared statement + runTests(t, testdsn, createTest("SELECT IFNULL(f, 0) f FROM test")) // not prepared statement with IFNULL + } } // Special cases From 6b012d36422ce11e7279db564a15b5c6d91f55a2 Mon Sep 17 00:00:00 2001 From: arvenil Date: Mon, 9 Feb 2015 19:16:06 +0100 Subject: [PATCH 9/9] Don't convert float32 to float32 --- packets.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packets.go b/packets.go index 77ac87d6b..b2cebef3c 100644 --- a/packets.go +++ b/packets.go @@ -1047,7 +1047,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error { continue case fieldTypeFloat: - dest[i] = float32(math.Float32frombits(binary.LittleEndian.Uint32(data[pos : pos+4]))) + dest[i] = math.Float32frombits(binary.LittleEndian.Uint32(data[pos : pos+4])) pos += 4 continue