diff --git a/driver/driver.go b/driver/driver.go index b8bf3f8..eb29891 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -543,7 +543,7 @@ func (r *rows) Next(dest []driver.Value) error { } func (s *stmt) decodeTime(i int) (_ time.Time, _ bool) { - if s.tmRead == "" { + if s.tmRead == sqlite3.TimeFormatDefault { return } switch s.Stmt.ColumnType(i) { diff --git a/driver/driver_test.go b/driver/driver_test.go index 2b09930..9cfcea7 100644 --- a/driver/driver_test.go +++ b/driver/driver_test.go @@ -6,6 +6,7 @@ import ( "database/sql" "errors" "math" + "net/url" "path/filepath" "testing" "time" @@ -295,3 +296,39 @@ func Test_QueryRow_blob_null(t *testing.T) { } } } + +func Test_time(t *testing.T) { + t.Parallel() + + for _, fmt := range []string{"auto", "sqlite", "rfc3339", time.ANSIC} { + t.Run(fmt, func(t *testing.T) { + db, err := sql.Open("sqlite3", "file::memory:?_timefmt="+url.QueryEscape(fmt)) + if err != nil { + t.Fatal(err) + } + defer db.Close() + + twosday := time.Date(2022, 2, 22, 22, 22, 22, 0, time.UTC) + + _, err = db.Exec(`CREATE TABLE IF NOT EXISTS test (at DATETIME)`) + if err != nil { + t.Fatal(err) + } + + _, err = db.Exec(`INSERT INTO test VALUES (?)`, twosday) + if err != nil { + t.Fatal(err) + } + + var got time.Time + err = db.QueryRow(`SELECT * FROM test`).Scan(&got) + if err != nil { + t.Fatal(err) + } + + if !got.Equal(twosday) { + t.Errorf("got: %v", got) + } + }) + } +} diff --git a/ext/fileio/write_test.go b/ext/fileio/write_test.go index f39d304..c81a205 100644 --- a/ext/fileio/write_test.go +++ b/ext/fileio/write_test.go @@ -60,7 +60,7 @@ func Test_writefile(t *testing.T) { if err != nil { t.Fatal(err) } - if mode.IsDir() && mtime != twosday { + if mode.IsDir() && !mtime.Equal(twosday) { t.Errorf("got: %v", mtime) } if mode.IsRegular() && data.String != "Hello world!" { diff --git a/ext/pivot/op_test.go b/ext/pivot/op_test.go new file mode 100644 index 0000000..987466b --- /dev/null +++ b/ext/pivot/op_test.go @@ -0,0 +1,34 @@ +package pivot + +import ( + "testing" + + "github.com/ncruces/go-sqlite3" +) + +func Test_operator(t *testing.T) { + tests := []struct { + op sqlite3.IndexConstraintOp + want string + }{ + {sqlite3.INDEX_CONSTRAINT_EQ, "="}, + {sqlite3.INDEX_CONSTRAINT_LT, "<"}, + {sqlite3.INDEX_CONSTRAINT_GT, ">"}, + {sqlite3.INDEX_CONSTRAINT_LE, "<="}, + {sqlite3.INDEX_CONSTRAINT_GE, ">="}, + {sqlite3.INDEX_CONSTRAINT_NE, "<>"}, + {sqlite3.INDEX_CONSTRAINT_IS, "IS"}, + {sqlite3.INDEX_CONSTRAINT_ISNOT, "IS NOT"}, + {sqlite3.INDEX_CONSTRAINT_REGEXP, "REGEXP"}, + {sqlite3.INDEX_CONSTRAINT_MATCH, "MATCH"}, + {sqlite3.INDEX_CONSTRAINT_GLOB, "GLOB"}, + {sqlite3.INDEX_CONSTRAINT_LIKE, "LIKE"}, + } + for _, tt := range tests { + t.Run(tt.want, func(t *testing.T) { + if got := operator(tt.op); got != tt.want { + t.Errorf("operator() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/ext/pivot/pivot.go b/ext/pivot/pivot.go index f9b20b6..523d9f0 100644 --- a/ext/pivot/pivot.go +++ b/ext/pivot/pivot.go @@ -114,34 +114,8 @@ func (t *table) BestIndex(idx *sqlite3.IndexInfo) error { if !cst.Usable || !(0 <= cst.Column && cst.Column < len(t.keys)) { continue } - - var op string - switch cst.Op { - case sqlite3.INDEX_CONSTRAINT_EQ: - op = "=" - case sqlite3.INDEX_CONSTRAINT_LT: - op = "<" - case sqlite3.INDEX_CONSTRAINT_GT: - op = ">" - case sqlite3.INDEX_CONSTRAINT_LE: - op = "<=" - case sqlite3.INDEX_CONSTRAINT_GE: - op = ">=" - case sqlite3.INDEX_CONSTRAINT_NE: - op = "<>" - case sqlite3.INDEX_CONSTRAINT_MATCH: - op = "MATCH" - case sqlite3.INDEX_CONSTRAINT_LIKE: - op = "LIKE" - case sqlite3.INDEX_CONSTRAINT_GLOB: - op = "GLOB" - case sqlite3.INDEX_CONSTRAINT_REGEXP: - op = "REGEXP" - case sqlite3.INDEX_CONSTRAINT_IS, sqlite3.INDEX_CONSTRAINT_ISNULL: - op = "IS" - case sqlite3.INDEX_CONSTRAINT_ISNOT, sqlite3.INDEX_CONSTRAINT_ISNOTNULL: - op = "IS NOT" - default: + op := operator(cst.Op) + if op == "" { continue } @@ -265,3 +239,34 @@ func (c *cursor) Column(ctx *sqlite3.Context, col int) error { } return c.cell.Reset() } + +func operator(op sqlite3.IndexConstraintOp) string { + switch op { + case sqlite3.INDEX_CONSTRAINT_EQ: + return "=" + case sqlite3.INDEX_CONSTRAINT_LT: + return "<" + case sqlite3.INDEX_CONSTRAINT_GT: + return ">" + case sqlite3.INDEX_CONSTRAINT_LE: + return "<=" + case sqlite3.INDEX_CONSTRAINT_GE: + return ">=" + case sqlite3.INDEX_CONSTRAINT_NE: + return "<>" + case sqlite3.INDEX_CONSTRAINT_MATCH: + return "MATCH" + case sqlite3.INDEX_CONSTRAINT_LIKE: + return "LIKE" + case sqlite3.INDEX_CONSTRAINT_GLOB: + return "GLOB" + case sqlite3.INDEX_CONSTRAINT_REGEXP: + return "REGEXP" + case sqlite3.INDEX_CONSTRAINT_IS, sqlite3.INDEX_CONSTRAINT_ISNULL: + return "IS" + case sqlite3.INDEX_CONSTRAINT_ISNOT, sqlite3.INDEX_CONSTRAINT_ISNOTNULL: + return "IS NOT" + default: + return "" + } +}