From 2094a27d628d9bc6dace92ad28d4b116d8e895bf Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Tue, 13 Feb 2024 12:19:44 -0800 Subject: [PATCH] Add support for datetime columns declared with a precision --- sqlite3.go | 4 ++++ sqlite3_test.go | 19 +++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/sqlite3.go b/sqlite3.go index 4b3b6cab..274b9bc3 100644 --- a/sqlite3.go +++ b/sqlite3.go @@ -212,6 +212,7 @@ import ( "io" "net/url" "reflect" + "regexp" "runtime" "strconv" "strings" @@ -2145,11 +2146,14 @@ func (rc *SQLiteRows) Columns() []string { return rc.cols } +var lengthSuffixRegexp = regexp.MustCompile(`\(\d+\)\z`) + func (rc *SQLiteRows) declTypes() []string { if rc.s.s != nil && rc.decltype == nil { rc.decltype = make([]string, rc.nc) for i := 0; i < rc.nc; i++ { rc.decltype[i] = strings.ToLower(C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i)))) + rc.decltype[i] = lengthSuffixRegexp.ReplaceAllString(rc.decltype[i], "") } } return rc.decltype diff --git a/sqlite3_test.go b/sqlite3_test.go index 63c939d3..d5a2eb20 100644 --- a/sqlite3_test.go +++ b/sqlite3_test.go @@ -615,7 +615,7 @@ func TestTimestamp(t *testing.T) { defer db.Close() _, err = db.Exec("DROP TABLE foo") - _, err = db.Exec("CREATE TABLE foo(id INTEGER, ts timeSTAMP, dt DATETIME)") + _, err = db.Exec("CREATE TABLE foo(id INTEGER, ts timeSTAMP, dt DATETIME, dt6 DATETIME(6))") if err != nil { t.Fatal("Failed to create table:", err) } @@ -660,13 +660,13 @@ func TestTimestamp(t *testing.T) { {"2012-11-04T00:00:00.000Z", timestamp3}, } for i := range tests { - _, err = db.Exec("INSERT INTO foo(id, ts, dt) VALUES(?, ?, ?)", i, tests[i].value, tests[i].value) + _, err = db.Exec("INSERT INTO foo(id, ts, dt, dt6) VALUES(?, ?, ?, ?)", i, tests[i].value, tests[i].value, tests[i].value) if err != nil { t.Fatal("Failed to insert timestamp:", err) } } - rows, err := db.Query("SELECT id, ts, dt FROM foo ORDER BY id ASC") + rows, err := db.Query("SELECT id, ts, dt, dt6 FROM foo ORDER BY id ASC") if err != nil { t.Fatal("Unable to query foo table:", err) } @@ -675,9 +675,9 @@ func TestTimestamp(t *testing.T) { seen := 0 for rows.Next() { var id int - var ts, dt time.Time + var ts, dt, dt6 time.Time - if err := rows.Scan(&id, &ts, &dt); err != nil { + if err := rows.Scan(&id, &ts, &dt, &dt6); err != nil { t.Error("Unable to scan results:", err) continue } @@ -687,11 +687,14 @@ func TestTimestamp(t *testing.T) { } seen++ if !tests[id].expected.Equal(ts) { - t.Errorf("Timestamp value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, dt) + t.Errorf("Timestamp value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, ts) } if !tests[id].expected.Equal(dt) { t.Errorf("Datetime value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, dt) } + if !tests[id].expected.Equal(dt6) { + t.Errorf("Datetime(6) value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, dt6) + } if timezone(tests[id].expected) != timezone(ts) { t.Errorf("Timezone for id %v (%v) should be %v, not %v", id, tests[id].value, timezone(tests[id].expected), timezone(ts)) @@ -700,6 +703,10 @@ func TestTimestamp(t *testing.T) { t.Errorf("Timezone for id %v (%v) should be %v, not %v", id, tests[id].value, timezone(tests[id].expected), timezone(dt)) } + if timezone(tests[id].expected) != timezone(dt6) { + t.Errorf("Timezone for id %v (%v) should be %v, not %v", id, tests[id].value, + timezone(tests[id].expected), timezone(dt6)) + } } if seen != len(tests) {