mirror of
https://github.com/glebarez/go-sqlite.git
synced 2025-10-04 23:42:40 +08:00
rows.Next: support scanning of time values, fixes #35
This commit is contained in:
48
all_test.go
48
all_test.go
@@ -923,3 +923,51 @@ Col 3: DatabaseTypeName "DATE", DecimalSize 0 0 false, Length 922337203685477580
|
|||||||
}
|
}
|
||||||
t.Log(b.String())
|
t.Log(b.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://gitlab.com/cznic/sqlite/-/issues/35
|
||||||
|
func TestTime(t *testing.T) {
|
||||||
|
types := []string{
|
||||||
|
"DATE",
|
||||||
|
"DATETIME",
|
||||||
|
"Date",
|
||||||
|
"DateTime",
|
||||||
|
"TIMESTAMP",
|
||||||
|
"TimeStamp",
|
||||||
|
"date",
|
||||||
|
"datetime",
|
||||||
|
"timestamp",
|
||||||
|
}
|
||||||
|
db, err := sql.Open(driverName, "file::memory:")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
db.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
for _, typ := range types {
|
||||||
|
if _, err := db.Exec(fmt.Sprintf(`
|
||||||
|
drop table if exists mg;
|
||||||
|
create table mg (applied_at %s);
|
||||||
|
`, typ)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
_, err = db.Exec(`INSERT INTO mg (applied_at) VALUES (?)`, &now)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var appliedAt time.Time
|
||||||
|
err = db.QueryRow("SELECT applied_at FROM mg").Scan(&appliedAt)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if g, e := appliedAt, now; !g.Equal(e) {
|
||||||
|
t.Fatal(g, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
34
sqlite.go
34
sqlite.go
@@ -277,7 +277,12 @@ func (r *rows) Next(dest []driver.Value) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
dest[i] = v
|
switch r.ColumnTypeDatabaseTypeName(i) {
|
||||||
|
case "DATE", "DATETIME", "TIMESTAMP":
|
||||||
|
dest[i], _ = r.c.parseTime(v)
|
||||||
|
default:
|
||||||
|
dest[i] = v
|
||||||
|
}
|
||||||
case sqlite3.SQLITE_BLOB:
|
case sqlite3.SQLITE_BLOB:
|
||||||
v, err := r.c.columnBlob(r.pstmt, i)
|
v, err := r.c.columnBlob(r.pstmt, i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -299,6 +304,33 @@ func (r *rows) Next(dest []driver.Value) (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attempt to parse s as a time. Return (s, false) if s is not
|
||||||
|
// recognized as a valid time encoding.
|
||||||
|
func (c *conn) parseTime(s string) (interface{}, bool) {
|
||||||
|
if v, ok := c.parseTimeString(s, strings.Index(s, "m=")); ok {
|
||||||
|
return v, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Add URI select time storage format and handle more formats
|
||||||
|
return s, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to parse s as a time string produced by t.String(). If x > 0 it's
|
||||||
|
// the index of substring "m=" within s. Return (s, false) if s is
|
||||||
|
// not recognized as a valid time encoding.
|
||||||
|
func (c *conn) parseTimeString(s0 string, x int) (interface{}, bool) {
|
||||||
|
s := s0
|
||||||
|
if x > 0 {
|
||||||
|
s = s[:x] // "2006-01-02 15:04:05.999999999 -0700 MST m=+9999" -> "2006-01-02 15:04:05.999999999 -0700 MST "
|
||||||
|
}
|
||||||
|
s = strings.TrimSpace(s)
|
||||||
|
if t, err := time.Parse("2006-01-02 15:04:05.999999999 -0700 MST", s); err == nil {
|
||||||
|
return t, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return s0, false
|
||||||
|
}
|
||||||
|
|
||||||
// RowsColumnTypeDatabaseTypeName may be implemented by Rows. It should return
|
// RowsColumnTypeDatabaseTypeName may be implemented by Rows. It should return
|
||||||
// the database system type name without the length. Type names should be
|
// the database system type name without the length. Type names should be
|
||||||
// uppercase. Examples of returned types: "VARCHAR", "NVARCHAR", "VARCHAR2",
|
// uppercase. Examples of returned types: "VARCHAR", "NVARCHAR", "VARCHAR2",
|
||||||
|
Reference in New Issue
Block a user