forked from mirror/go-sqlcipher
Add support for extracting 2006-01-02 formatted timestamps.
SQLite3 stores timestamps very naively -- they're completely untyped, and can contain any value. The previous implementation always inserts values in the 'datetime' format, and returns an error when attempting to extract a field with a different format. Some legacy databases, unfortunately, were generated using the 'date' SQLite3 function, which produces rows in the '2006-01-02' format. This patch adds a special case so that these rows can be extracted without error.
This commit is contained in:
parent
76996feb52
commit
dcd44f5118
|
@ -27,6 +27,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const SQLiteTimestampFormat = "2006-01-02 15:04:05"
|
const SQLiteTimestampFormat = "2006-01-02 15:04:05"
|
||||||
|
const SQLiteDateFormat = "2006-01-02"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
sql.Register("sqlite3", &SQLiteDriver{})
|
sql.Register("sqlite3", &SQLiteDriver{})
|
||||||
|
@ -312,9 +313,12 @@ func (rc *SQLiteRows) Next(dest []driver.Value) error {
|
||||||
s := C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i)))))
|
s := C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i)))))
|
||||||
if rc.decltype[i] == "timestamp" {
|
if rc.decltype[i] == "timestamp" {
|
||||||
dest[i], err = time.Parse(SQLiteTimestampFormat, s)
|
dest[i], err = time.Parse(SQLiteTimestampFormat, s)
|
||||||
|
if err != nil {
|
||||||
|
dest[i], err = time.Parse(SQLiteDateFormat, s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
dest[i] = s
|
dest[i] = s
|
||||||
}
|
}
|
||||||
|
|
|
@ -400,3 +400,63 @@ func TestBoolean(t *testing.T) {
|
||||||
t.Error("Expected error from \"nonsense\" bool")
|
t.Error("Expected error from \"nonsense\" bool")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDateOnlyTimestamp(t *testing.T) {
|
||||||
|
// make sure that timestamps without times are extractable. these are generated when
|
||||||
|
// e.g., you use the sqlite `DATE()` built-in.
|
||||||
|
|
||||||
|
db, er := sql.Open("sqlite3", "db.sqlite")
|
||||||
|
if er != nil {
|
||||||
|
t.Fatal(er)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
db.Close()
|
||||||
|
os.Remove("db.sqlite")
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, er = db.Exec(`
|
||||||
|
CREATE TABLE test
|
||||||
|
( entry_id INTEGER PRIMARY KEY AUTOINCREMENT
|
||||||
|
, entry_published TIMESTAMP NOT NULL
|
||||||
|
)
|
||||||
|
`)
|
||||||
|
if er != nil {
|
||||||
|
t.Fatal(er)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, er = db.Exec(`
|
||||||
|
INSERT INTO test VALUES ( 1, '2012-11-04')
|
||||||
|
`)
|
||||||
|
if er != nil {
|
||||||
|
t.Fatal(er)
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, er := db.Query("SELECT entry_id, entry_published FROM test")
|
||||||
|
if er != nil {
|
||||||
|
t.Fatal(er)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
if !rows.Next() {
|
||||||
|
if er := rows.Err() ; er != nil {
|
||||||
|
t.Fatal(er)
|
||||||
|
} else {
|
||||||
|
t.Fatalf("Unable to extract row containing date-only timestamp")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var entryId int64
|
||||||
|
var entryPublished time.Time
|
||||||
|
|
||||||
|
if er := rows.Scan(&entryId, &entryPublished) ; er != nil {
|
||||||
|
t.Fatal(er)
|
||||||
|
}
|
||||||
|
|
||||||
|
if entryId != 1 {
|
||||||
|
t.Errorf("EntryId does not match inserted value")
|
||||||
|
}
|
||||||
|
|
||||||
|
if entryPublished.Year() != 2012 || entryPublished.Month() != 11 || entryPublished.Day() != 4 {
|
||||||
|
t.Errorf("Extracted time does not match inserted value")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue