summaryrefslogtreecommitdiff
path: root/vendor/modernc.org/sqlite/sqlite.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/modernc.org/sqlite/sqlite.go')
-rw-r--r--vendor/modernc.org/sqlite/sqlite.go88
1 files changed, 83 insertions, 5 deletions
diff --git a/vendor/modernc.org/sqlite/sqlite.go b/vendor/modernc.org/sqlite/sqlite.go
index 39675a68b..a0b6ca4eb 100644
--- a/vendor/modernc.org/sqlite/sqlite.go
+++ b/vendor/modernc.org/sqlite/sqlite.go
@@ -254,7 +254,30 @@ func (r *rows) Next(dest []driver.Value) (err error) {
return err
}
- dest[i] = v
+ if !r.c.intToTime {
+ dest[i] = v
+ } else {
+ // Inspired by mattn/go-sqlite3:
+ // https://github.com/mattn/go-sqlite3/blob/f76bae4b0044cbba8fb2c72b8e4559e8fbcffd86/sqlite3.go#L2254-L2262
+ // but we put make this compatibility optional behind a DSN
+ // query parameter, because this changes API behavior, so an
+ // opt-in is needed.
+ switch r.ColumnTypeDatabaseTypeName(i) {
+ case "DATE", "DATETIME", "TIMESTAMP":
+ // Is it a seconds timestamp or a milliseconds
+ // timestamp?
+ if v > 1e12 || v < -1e12 {
+ // time.Unix expects nanoseconds, but this is a
+ // milliseconds timestamp, so convert ms->ns.
+ v *= int64(time.Millisecond)
+ dest[i] = time.Unix(0, v).UTC()
+ } else {
+ dest[i] = time.Unix(v, 0)
+ }
+ default:
+ dest[i] = v
+ }
+ }
case sqlite3.SQLITE_FLOAT:
v, err := r.c.columnDouble(r.pstmt, i)
if err != nil {
@@ -752,8 +775,10 @@ type conn struct {
db uintptr // *sqlite3.Xsqlite3
tls *libc.TLS
- writeTimeFormat string
- beginMode string
+ writeTimeFormat string
+ beginMode string
+ intToTime bool
+ integerTimeFormat string
}
func newConn(dsn string) (*conn, error) {
@@ -858,6 +883,17 @@ func applyQueryParams(c *conn, query string) error {
}
c.writeTimeFormat = f
}
+ if v := q.Get("_time_integer_format"); v != "" {
+ switch v {
+ case "unix":
+ case "unix_milli":
+ case "unix_micro":
+ case "unix_nano":
+ default:
+ return fmt.Errorf("unknown _time_integer_format %q", v)
+ }
+ c.integerTimeFormat = v
+ }
if v := q.Get("_txlock"); v != "" {
lower := strings.ToLower(v)
@@ -867,6 +903,15 @@ func applyQueryParams(c *conn, query string) error {
c.beginMode = v
}
+ if v := q.Get("_inttotime"); v != "" {
+ onoff, err := strconv.ParseBool(v)
+ if err != nil {
+ return fmt.Errorf("unknown _inttotime %q, must be 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False",
+ v)
+ }
+ c.intToTime = onoff
+ }
+
return nil
}
@@ -1117,9 +1162,29 @@ func (c *conn) bind(pstmt uintptr, n int, args []driver.NamedValue) (allocs []ui
return allocs, err
}
case time.Time:
- if p, err = c.bindText(pstmt, i, c.formatTime(x)); err != nil {
- return allocs, err
+ switch c.integerTimeFormat {
+ case "unix":
+ if err := c.bindInt64(pstmt, i, x.Unix()); err != nil {
+ return allocs, err
+ }
+ case "unix_milli":
+ if err := c.bindInt64(pstmt, i, x.UnixMilli()); err != nil {
+ return allocs, err
+ }
+ case "unix_micro":
+ if err := c.bindInt64(pstmt, i, x.UnixMicro()); err != nil {
+ return allocs, err
+ }
+ case "unix_nano":
+ if err := c.bindInt64(pstmt, i, x.UnixNano()); err != nil {
+ return allocs, err
+ }
+ default:
+ if p, err = c.bindText(pstmt, i, c.formatTime(x)); err != nil {
+ return allocs, err
+ }
}
+
case nil:
if p, err = c.bindNull(pstmt, i); err != nil {
return allocs, err
@@ -1913,6 +1978,19 @@ func newDriver() *Driver { return d }
// including the timezone specifier. If this parameter is not specified, then
// the default String() format will be used.
//
+// _time_integer_format: The name of a integer format to use when writing time values.
+// By default, the time is stored as string and the format can be set with _time_format
+// parameter. If _time_integer_format is set, the time will be stored as an integer and
+// the integer value will depend on the integer format.
+// If you decide to set both _time_format and _time_integer_format, the time will be
+// converted as integer and the _time_format value will be ignored.
+// Currently the supported value are "unix","unix_milli", "unix_micro" and "unix_nano",
+// which corresponds to seconds, milliseconds, microseconds or nanoseconds
+// since unixepoch (1 January 1970 00:00:00 UTC).
+//
+// _inttotime: Enable conversion of time column (DATE, DATETIME,TIMESTAMP) from integer
+// to time if the field contain integer (int64).
+//
// _txlock: The locking behavior to use when beginning a transaction. May be
// "deferred" (the default), "immediate", or "exclusive" (case insensitive). See:
// https://www.sqlite.org/lang_transaction.html#deferred_immediate_and_exclusive_transactions