Commit eb6ac024 authored by gwenn's avatar gwenn

Add support to standard database/sql/driver/Valuer.

parent d7bba9c3
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
package sqlite package sqlite
import ( import (
"database/sql/driver"
"fmt"
"time" "time"
) )
...@@ -35,3 +37,73 @@ func JulianDay(t time.Time) float64 { ...@@ -35,3 +37,73 @@ func JulianDay(t time.Time) float64 {
} }
return ns/dayInSeconds + julianDay return ns/dayInSeconds + julianDay
} }
// UnixTime is an alias used to persist time as int64 (max precision is 1s and timezone is lost) (default)
type UnixTime time.Time
func (t *UnixTime) Scan(src interface{}) error {
if src == nil {
t = nil
return nil
} else if unixepoch, ok := src.(int64); ok {
*t = UnixTime(time.Unix(unixepoch, 0)) // local time
return nil
} else {
return fmt.Errorf("Unsupported UnixTime src: %T", src)
}
}
func (t UnixTime) Value() (driver.Value, error) {
if (time.Time)(t).IsZero() {
return nil, nil
} else {
return (time.Time)(t).Unix(), nil
}
}
// JulianTime is an alias used to persist time as float64 (max precision is 1s and timezone is lost)
type JulianTime time.Time
func (t *JulianTime) Scan(src interface{}) error {
if src == nil {
t = nil
return nil
} else if jd, ok := src.(float64); ok {
*t = JulianTime(JulianDayToLocalTime(jd)) // local time
return nil
} else {
return fmt.Errorf("Unsupported JulianTime src: %T", src)
}
}
func (t JulianTime) Value() (driver.Value, error) {
if (time.Time)(t).IsZero() {
return nil, nil
} else {
return JulianDay((time.Time)(t)), nil
}
}
// TimeStamp is an alias used to persist time as '2006-01-02T15:04:05.999Z07:00' string
type TimeStamp time.Time
func (t *TimeStamp) Scan(src interface{}) error {
if src == nil {
t = nil
return nil
} else if txt, ok := src.(string); ok {
v, err := time.Parse("2006-01-02T15:04:05.999Z07:00", txt)
if err != nil {
return err
}
*t = TimeStamp(v)
return nil
} else {
return fmt.Errorf("Unsupported TimeStamp src: %T", src)
}
}
func (t TimeStamp) Value() (driver.Value, error) {
if (time.Time)(t).IsZero() {
return nil, nil
} else {
return (time.Time)(t).Format("2006-01-02T15:04:05.999Z07:00"), nil
}
}
...@@ -33,6 +33,7 @@ import "C" ...@@ -33,6 +33,7 @@ import "C"
import ( import (
"database/sql" "database/sql"
"database/sql/driver"
"errors" "errors"
"fmt" "fmt"
"time" "time"
...@@ -311,21 +312,6 @@ func (s *Stmt) Bind(args ...interface{}) error { ...@@ -311,21 +312,6 @@ func (s *Stmt) Bind(args ...interface{}) error {
return nil return nil
} }
// UnixTime is an alias used to persist time as int64 (max precision is 1s and timezone is lost) (default)
type UnixTime time.Time
// JulianTime is an alias used to persist time as float64 (max precision is 1s and timezone is lost)
type JulianTime time.Time
// YearMonthDay is an alias used to persist time as 'YYYY-MM-DD' string
//type YearMonthDay time.Time
// TimeOfDay is an alias used to persist time as 'HH:MM:SS.SSS' string
//type TimeOfDay time.Time versus Duration
// TimeStamp is an alias used to persist time as '2006-01-02T15:04:05.999Z07:00' string
type TimeStamp time.Time
// BindByIndex binds value to the specified host parameter of the prepared statement. // BindByIndex binds value to the specified host parameter of the prepared statement.
// The leftmost SQL parameter has an index of 1. // The leftmost SQL parameter has an index of 1.
func (s *Stmt) BindByIndex(index int, value interface{}) error { func (s *Stmt) BindByIndex(index int, value interface{}) error {
...@@ -355,24 +341,16 @@ func (s *Stmt) BindByIndex(index int, value interface{}) error { ...@@ -355,24 +341,16 @@ func (s *Stmt) BindByIndex(index int, value interface{}) error {
p = &value[0] p = &value[0]
} }
rv = C.my_bind_blob(s.stmt, i, unsafe.Pointer(p), C.int(len(value))) rv = C.my_bind_blob(s.stmt, i, unsafe.Pointer(p), C.int(len(value)))
case JulianTime:
rv = C.sqlite3_bind_double(s.stmt, i, C.double(JulianDay(time.Time(value))))
/*case YearMonthDay:
cs, l := cstring((time.Time)(value).Format("2006-01-02"))
rv = C.my_bind_text(s.stmt, i, cs, l)
case TimeOfDay:
cs, l := cstring((time.Time)(value).Format("15:04:05.000"))
rv = C.my_bind_text(s.stmt, i, cs, l)
*/
case TimeStamp:
cs, l := cstring((time.Time)(value).Format("2006-01-02T15:04:05.999Z07:00"))
rv = C.my_bind_text(s.stmt, i, cs, l)
case UnixTime:
rv = C.sqlite3_bind_int64(s.stmt, i, C.sqlite3_int64((time.Time)(value).Unix()))
case time.Time: case time.Time:
rv = C.sqlite3_bind_int64(s.stmt, i, C.sqlite3_int64(value.Unix())) rv = C.sqlite3_bind_int64(s.stmt, i, C.sqlite3_int64(value.Unix()))
case ZeroBlobLength: case ZeroBlobLength:
rv = C.sqlite3_bind_zeroblob(s.stmt, i, C.int(value)) rv = C.sqlite3_bind_zeroblob(s.stmt, i, C.int(value))
case driver.Valuer:
v, err := value.Value()
if err != nil {
return err
}
return s.BindByIndex(index, v)
default: default:
name, _ := s.BindParameterName(index) name, _ := s.BindParameterName(index)
return s.specificError("unsupported type in Bind: %T (index: %d, name: %q)", value, index, name) return s.specificError("unsupported type in Bind: %T (index: %d, name: %q)", value, index, name)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment