func (rc *SQLiteRows) Next(dest []driver.Value) error { rv := C.sqlite3_step(rc.s.s) if rv == C.SQLITE_DONE { return io.EOF } if rv != C.SQLITE_ROW { return errors.New(C.GoString(C.sqlite3_errmsg(rc.s.c.db))) } for i := range dest { switch C.sqlite3_column_type(rc.s.s, C.int(i)) { case C.SQLITE_INTEGER: dest[i] = int64(C.sqlite3_column_int64(rc.s.s, C.int(i))) case C.SQLITE_FLOAT: dest[i] = float64(C.sqlite3_column_double(rc.s.s, C.int(i))) case C.SQLITE_BLOB: n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i))) p := C.sqlite3_column_blob(rc.s.s, C.int(i)) dest[i] = (*[1 << 30]byte)(unsafe.Pointer(p))[0:n] case C.SQLITE_NULL: dest[i] = nil case C.SQLITE_TEXT: dest[i] = C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i))))) } } return nil }
// scanDynamic scans the value of column i (starting at 0) into v, using the // column's data type and declaration to select an appropriate representation. // If driverValue is true, the range of possible representations is restricted // to those allowed by driver.Value. func (s *Stmt) scanDynamic(i C.int, v *interface{}, driverValue bool) error { switch typ := s.colType(i); typ { case INTEGER: n := int64(C.sqlite3_column_int64(s.stmt, i)) *v = n if decl := s.DeclTypes()[i]; len(decl) >= 4 { switch decl[:4] { case "DATE", "TIME": *v = time.Unix(n, 0) case "BOOL": *v = n != 0 } } case FLOAT: *v = float64(C.sqlite3_column_double(s.stmt, i)) case TEXT: if driverValue { *v = []byte(text(s.stmt, i, false)) } else { *v = text(s.stmt, i, true) } case BLOB: *v = blob(s.stmt, i, true) case NULL: *v = nil default: *v = nil return pkgErr(ERROR, "unknown column type (%d)", typ) } return nil }
func (rows Rows) Next(dest []driver.Value) error { r := C.sqlite3_step(rows.stmt) if r == C.SQLITE_DONE { return io.EOF } if r != C.SQLITE_ROW { return stmtError(rows.stmt) } count := len(dest) for i := 0; i < count; i++ { t := C.sqlite3_column_type(rows.stmt, C.int(i)) switch t { case C.SQLITE_INTEGER: dest[i] = int64(C.sqlite3_column_int64(rows.stmt, C.int(i))) case C.SQLITE_FLOAT: dest[i] = float64(C.sqlite3_column_double(rows.stmt, C.int(i))) case C.SQLITE_NULL: dest[i] = nil case C.SQLITE_TEXT: n := C.sqlite3_column_bytes(rows.stmt, C.int(i)) blob := C.sqlite3_column_blob(rows.stmt, C.int(i)) dest[i] = C.GoBytes(blob, n) default: panic("unsupported type") } } return nil }
func (r *rows) Next(dst []driver.Value) error { if r.s == nil { panic("database/sql/driver: misuse of sqlite driver: Next of closed Rows") } rv := C.sqlite3_step(r.s.stmt) if errno(rv) != stepRow { if errno(rv) == stepDone { return io.EOF } if rv == 0 { rv = 21 } return r.s.c.error(rv) } for i := range dst { switch typ := C.sqlite3_column_type(r.s.stmt, C.int(i)); typ { default: return fmt.Errorf("unexpected sqlite3 column type %d", typ) case C.SQLITE_INTEGER: val := int64(C.sqlite3_column_int64(r.s.stmt, C.int(i))) switch r.s.coltypes[i] { case "timestamp", "datetime": dst[i] = time.Unix(val, 0).UTC() case "boolean": dst[i] = val > 0 default: dst[i] = val } case C.SQLITE_FLOAT: dst[i] = float64(C.sqlite3_column_double(r.s.stmt, C.int(i))) case C.SQLITE_BLOB, C.SQLITE_TEXT: n := int(C.sqlite3_column_bytes(r.s.stmt, C.int(i))) var b []byte if n > 0 { p := C.sqlite3_column_blob(r.s.stmt, C.int(i)) b = (*[maxslice]byte)(unsafe.Pointer(p))[:n] } dst[i] = b switch r.s.coltypes[i] { case "timestamp", "datetime": dst[i] = time.Time{} s := string(b) for _, f := range timefmt { if t, err := time.Parse(f, s); err == nil { dst[i] = t break } } } case C.SQLITE_NULL: dst[i] = nil } } return nil }
func (rc *SQLiteRows) Next(dest []driver.Value) error { rv := C.sqlite3_step(rc.s.s) if rv == C.SQLITE_DONE { return io.EOF } if rv != C.SQLITE_ROW { return errors.New(C.GoString(C.sqlite3_errmsg(rc.s.c.db))) } if rc.decltype == nil { rc.decltype = make([]string, rc.nc) for i := 0; i < rc.nc; i++ { rc.decltype[i] = strings.ToLower(C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i)))) } } for i := range dest { switch C.sqlite3_column_type(rc.s.s, C.int(i)) { case C.SQLITE_INTEGER: val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i))) switch rc.decltype[i] { case "timestamp": dest[i] = time.Unix(val, 0) case "boolean": dest[i] = val > 0 default: dest[i] = val } case C.SQLITE_FLOAT: dest[i] = float64(C.sqlite3_column_double(rc.s.s, C.int(i))) case C.SQLITE_BLOB: n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i))) p := C.sqlite3_column_blob(rc.s.s, C.int(i)) switch dest[i].(type) { case sql.RawBytes: dest[i] = (*[1 << 30]byte)(unsafe.Pointer(p))[0:n] default: slice := make([]byte, n) copy(slice[:], (*[1 << 30]byte)(unsafe.Pointer(p))[0:n]) dest[i] = slice } case C.SQLITE_NULL: dest[i] = nil case C.SQLITE_TEXT: var err error s := C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i))))) if rc.decltype[i] == "timestamp" { dest[i], err = time.Parse(SQLiteTimestampFormat, s) if err != nil { return err } } else { dest[i] = s } } } return nil }
// ScanTime scans result value from a query. // If time is persisted as string without timezone, UTC is used. // If time is persisted as numeric, local is used. // The leftmost column/index is number 0. // Returns true when column is null. // The column type affinity must be consistent with the format used (INTEGER or NUMERIC or NONE for unix time, REAL or NONE for julian day). func (s *Stmt) ScanTime(index int) (value time.Time, isNull bool, err error) { ctype := s.ColumnType(index) switch ctype { case Null: isNull = true case Text: // does not work as expected if column type affinity is TEXT but inserted value was a numeric p := C.sqlite3_column_text(s.stmt, C.int(index)) txt := C.GoString((*C.char)(unsafe.Pointer(p))) var layout string switch len(txt) { case 5: // HH:MM layout = "15:04" case 8: // HH:MM:SS layout = "15:04:05" case 10: // YYYY-MM-DD layout = "2006-01-02" case 12: // HH:MM:SS.SSS layout = "15:04:05.000" case 16: // YYYY-MM-DDTHH:MM if txt[10] == 'T' { layout = "2006-01-02T15:04" } else { layout = "2006-01-02 15:04" } case 19: // YYYY-MM-DDTHH:MM:SS if txt[10] == 'T' { layout = "2006-01-02T15:04:05" } else { layout = "2006-01-02 15:04:05" } case 23: // YYYY-MM-DDTHH:MM:SS.SSS if txt[10] == 'T' { layout = "2006-01-02T15:04:05.000" } else { layout = "2006-01-02 15:04:05.000" } default: // YYYY-MM-DDTHH:MM:SS.SSSZhh:mm or parse error if len(txt) > 10 && txt[10] == 'T' { layout = "2006-01-02T15:04:05.000Z07:00" } else { layout = "2006-01-02 15:04:05.000Z07:00" } } value, err = time.Parse(layout, txt) // UTC except when timezone is specified case Integer: unixepoch := int64(C.sqlite3_column_int64(s.stmt, C.int(index))) value = time.Unix(unixepoch, 0) // local time case Float: // does not work as expected if column affinity is REAL but inserted value was an integer jd := float64(C.sqlite3_column_double(s.stmt, C.int(index))) value = JulianDayToLocalTime(jd) // local time default: err = s.specificError("unexpected column type affinity for time persistence: %q", ctype) } return }
// ScanTime scans result value from a query. // If time is persisted as string without timezone, UTC is used. // If time is persisted as numeric, local is used. // The leftmost column/index is number 0. // Returns true when column is null. func (s *Stmt) ScanTime(index int) (value time.Time, isNull bool, err error) { switch s.ColumnType(index) { case Null: isNull = true case Text: p := C.sqlite3_column_text(s.stmt, C.int(index)) txt := C.GoString((*C.char)(unsafe.Pointer(p))) var layout string switch len(txt) { case 5: // HH:MM layout = "15:04" case 8: // HH:MM:SS layout = "15:04:05" case 10: // YYYY-MM-DD layout = "2006-01-02" case 12: // HH:MM:SS.SSS layout = "15:04:05.000" case 16: // YYYY-MM-DDTHH:MM if txt[10] == 'T' { layout = "2006-01-02T15:04" } else { layout = "2006-01-02 15:04" } case 19: // YYYY-MM-DDTHH:MM:SS if txt[10] == 'T' { layout = "2006-01-02T15:04:05" } else { layout = "2006-01-02 15:04:05" } case 23: // YYYY-MM-DDTHH:MM:SS.SSS if txt[10] == 'T' { layout = "2006-01-02T15:04:05.999" } else { layout = "2006-01-02 15:04:05.999" } default: // YYYY-MM-DDTHH:MM:SS.SSSZhh:mm or parse error if len(txt) > 10 && txt[10] == 'T' { layout = "2006-01-02T15:04:05.999Z07:00" } else { layout = "2006-01-02 15:04:05.999Z07:00" } } value, err = time.Parse(layout, txt) // UTC except when timezone is specified case Integer: unixepoch := int64(C.sqlite3_column_int64(s.stmt, C.int(index))) value = time.Unix(unixepoch, 0) // local time case Float: jd := float64(C.sqlite3_column_double(s.stmt, C.int(index))) value = JulianDayToLocalTime(jd) // local time default: panic("The column type is not one of SQLITE_INTEGER, SQLITE_FLOAT, SQLITE_TEXT, or SQLITE_NULL") } return }
// ScanDouble scans result value from a query. // The leftmost column/index is number 0. // Returns true when column is null. // (See sqlite3_column_double: http://sqlite.org/c3ref/column_blob.html) func (s *Stmt) ScanDouble(index int) (value float64, isNull bool, err error) { ctype := s.ColumnType(index) if ctype == Null { isNull = true } else { if CheckTypeMismatch { err = s.checkTypeMismatch(ctype, Float) } value = float64(C.sqlite3_column_double(s.stmt, C.int(index))) } return }
func (s *Stmt) Scan2(args ...interface{}) os.Error { n := int(C.sqlite3_column_count(s.stmt)) if n != len(args) { return os.NewError(fmt.Sprintf("incorrect argument count for Stmt.Scan: have %d want %d", len(args), n)) } for i, v := range args { /* n := C.sqlite3_column_bytes(s.stmt, C.int(i)) p := C.sqlite3_column_blob(s.stmt, C.int(i)) if p == nil && n > 0 { return os.NewError("got nil blob") } var data []byte if n > 0 { data = (*[1 << 30]byte)(unsafe.Pointer(p))[0:n] } */ switch v := v.(type) { /* case *[]byte: *v = data case *string: *v = string(data) case *bool: *v = string(data) == "1" case *int: x, err := strconv.Atoi(string(data)) if err != nil { return os.NewError("arg " + strconv.Itoa(i) + " as int: " + err.String()) } *v = x */ case *int64: x := C.sqlite3_column_int64(s.stmt, C.int(i)) *v = int64(x) case *float64: x := C.sqlite3_column_double(s.stmt, C.int(i)) *v = float64(x) default: return os.NewError("unsupported type in Scan: " + reflect.Typeof(v).String()) } } return nil }
func (c ResultColumn) Value(s *Statement) (value interface{}) { switch c.Type(s) { case INTEGER: value = int64(C.sqlite3_int64(C.sqlite3_column_int64(s.cptr, C.int(c)))) case FLOAT: value = float64(C.sqlite3_column_double(s.cptr, C.int(c))) case TEXT: value = c.make_buffer(s, C.sqlite3_column_text(s.cptr, C.int(c))) case BLOB: buffer := c.make_buffer(s, C.sqlite3_column_blob(s.cptr, C.int(c))) value = gob.NewDecoder(bytes.NewBuffer([]byte(buffer))) case NULL: value = nil default: panic("unknown column type") } return }
// ScanValue scans result value from a query. // The leftmost column/index is number 0. // // Destination type is decided by SQLite. // The returned value will be of one of the following types: // nil // string // int64 // float64 // []byte // // Calls sqlite3_column_(blob|double|int|int64|text) depending on columns type. // (See http://sqlite.org/c3ref/column_blob.html) func (s *Stmt) ScanValue(index int) (value interface{}) { switch s.ColumnType(index) { case Null: value = nil case Text: p := C.sqlite3_column_text(s.stmt, C.int(index)) value = C.GoString((*C.char)(unsafe.Pointer(p))) case Integer: value = int64(C.sqlite3_column_int64(s.stmt, C.int(index))) case Float: value = float64(C.sqlite3_column_double(s.stmt, C.int(index))) case Blob: p := C.sqlite3_column_blob(s.stmt, C.int(index)) n := C.sqlite3_column_bytes(s.stmt, C.int(index)) // value = (*[1 << 30]byte)(unsafe.Pointer(p))[:n] value = C.GoBytes(p, n) // The memory space used to hold strings and BLOBs is freed automatically. default: panic("The column type is not one of SQLITE_INTEGER, SQLITE_FLOAT, SQLITE_TEXT, SQLITE_BLOB, or SQLITE_NULL") } return }
// ScanValue scans result value from a query. // The leftmost column/index is number 0. // // Destination type is decided by SQLite. // The returned value will be of one of the following types: // nil // string (exception if blob is true) // int64 // float64 // []byte // // Calls sqlite3_column_(blob|double|int|int64|text) depending on columns type. // (See http://sqlite.org/c3ref/column_blob.html) func (s *Stmt) ScanValue(index int, blob bool) (value interface{}, isNull bool) { if index < 0 || index >= s.ColumnCount() { panic(fmt.Sprintf("column index %d out of range [0,%d[.", index, s.ColumnCount())) } switch s.ColumnType(index) { case Null: return nil, true case Text: // does not work as expected if column type affinity is TEXT but inserted value was a numeric if s.c.ScanNumericalAsTime && s.c.DefaultTimeLayout != "" && s.ColumnTypeAffinity(index) == Numerical { p := C.sqlite3_column_text(s.stmt, C.int(index)) txt := C.GoString((*C.char)(unsafe.Pointer(p))) value, err := time.Parse(s.c.DefaultTimeLayout, txt) if err == nil { return value, false } Log(-1, err.Error()) } if blob { p := C.sqlite3_column_blob(s.stmt, C.int(index)) n := C.sqlite3_column_bytes(s.stmt, C.int(index)) return C.GoBytes(p, n), false } p := C.sqlite3_column_text(s.stmt, C.int(index)) return C.GoString((*C.char)(unsafe.Pointer(p))), false case Integer: value := int64(C.sqlite3_column_int64(s.stmt, C.int(index))) if s.c.ScanNumericalAsTime && s.c.DefaultTimeLayout == "" && s.ColumnTypeAffinity(index) == Numerical { return time.Unix(value, 0), false } return value, false case Float: // does not work as expected if column type affinity is REAL but inserted value was an integer return float64(C.sqlite3_column_double(s.stmt, C.int(index))), false case Blob: p := C.sqlite3_column_blob(s.stmt, C.int(index)) n := C.sqlite3_column_bytes(s.stmt, C.int(index)) // value = (*[1 << 30]byte)(unsafe.Pointer(p))[:n] return C.GoBytes(p, n), false // The memory space used to hold strings and BLOBs is freed automatically. } panic("The column type is not one of SQLITE_INTEGER, SQLITE_FLOAT, SQLITE_TEXT, SQLITE_BLOB, or SQLITE_NULL") }
// scan scans the value of column i (starting at 0) into v. func (s *Stmt) scan(i C.int, v interface{}) error { if typ := s.colType(i); typ == NULL { return s.scanZero(i, v) } switch v := v.(type) { case *interface{}: return s.scanDynamic(i, v, false) case *int: *v = int(C.sqlite3_column_int64(s.stmt, i)) case *int64: *v = int64(C.sqlite3_column_int64(s.stmt, i)) case *float64: *v = float64(C.sqlite3_column_double(s.stmt, i)) case *bool: *v = C.sqlite3_column_int64(s.stmt, i) != 0 case *string: *v = text(s.stmt, i, true) case *[]byte: *v = blob(s.stmt, i, true) case *time.Time: *v = time.Unix(int64(C.sqlite3_column_int64(s.stmt, i)), 0) case *RawString: *v = RawString(text(s.stmt, i, false)) case *RawBytes: *v = RawBytes(blob(s.stmt, i, false)) case io.Writer: if _, err := v.Write(blob(s.stmt, i, false)); err != nil { return err } default: return pkgErr(MISUSE, "unscannable type for column %d (%T)", int(i), v) } // BUG(mxk): If a SQLite memory allocation fails while scanning column // values, the error is not reported until the next call to Stmt.Next or // Stmt.Close. This behavior may change in the future to check for and // return the error immediately from Stmt.Scan. return nil }
// ScanValue scans result value from a query. // The leftmost column/index is number 0. // // Destination type is decided by SQLite. // The returned value will be of one of the following types: // nil // string (exception if blob is true) // int64 // float64 // []byte // // Calls sqlite3_column_(blob|double|int|int64|text) depending on columns type. // (See http://sqlite.org/c3ref/column_blob.html) func (s *Stmt) ScanValue(index int, blob bool) (interface{}, bool) { switch s.ColumnType(index) { case Null: return nil, true case Text: if blob { p := C.sqlite3_column_blob(s.stmt, C.int(index)) n := C.sqlite3_column_bytes(s.stmt, C.int(index)) return C.GoBytes(p, n), false } p := C.sqlite3_column_text(s.stmt, C.int(index)) return C.GoString((*C.char)(unsafe.Pointer(p))), false case Integer: return int64(C.sqlite3_column_int64(s.stmt, C.int(index))), false case Float: return float64(C.sqlite3_column_double(s.stmt, C.int(index))), false case Blob: p := C.sqlite3_column_blob(s.stmt, C.int(index)) n := C.sqlite3_column_bytes(s.stmt, C.int(index)) // value = (*[1 << 30]byte)(unsafe.Pointer(p))[:n] return C.GoBytes(p, n), false // The memory space used to hold strings and BLOBs is freed automatically. } panic("The column type is not one of SQLITE_INTEGER, SQLITE_FLOAT, SQLITE_TEXT, SQLITE_BLOB, or SQLITE_NULL") }
// Move cursor to next. func (rc *SQLiteRows) Next(dest []driver.Value) error { rv := C.sqlite3_step(rc.s.s) if rv == C.SQLITE_DONE { return io.EOF } if rv != C.SQLITE_ROW { rv = C.sqlite3_reset(rc.s.s) if rv != C.SQLITE_OK { return rc.s.c.lastError() } return nil } if rc.decltype == nil { rc.decltype = make([]string, rc.nc) for i := 0; i < rc.nc; i++ { rc.decltype[i] = strings.ToLower(C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i)))) } } for i := range dest { switch C.sqlite3_column_type(rc.s.s, C.int(i)) { case C.SQLITE_INTEGER: val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i))) switch rc.decltype[i] { case "timestamp", "datetime", "date": unixTimestamp := strconv.FormatInt(val, 10) var t time.Time if len(unixTimestamp) == 13 { duration, err := time.ParseDuration(unixTimestamp + "ms") if err != nil { return fmt.Errorf("error parsing %s value %d, %s", rc.decltype[i], val, err) } epoch := time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC) t = epoch.Add(duration) } else { t = time.Unix(val, 0) } if rc.s.c.loc != nil { t = t.In(rc.s.c.loc) } dest[i] = t case "boolean": dest[i] = val > 0 default: dest[i] = val } case C.SQLITE_FLOAT: dest[i] = float64(C.sqlite3_column_double(rc.s.s, C.int(i))) case C.SQLITE_BLOB: p := C.sqlite3_column_blob(rc.s.s, C.int(i)) if p == nil { dest[i] = nil continue } n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i))) switch dest[i].(type) { case sql.RawBytes: dest[i] = (*[1 << 30]byte)(unsafe.Pointer(p))[0:n] default: slice := make([]byte, n) copy(slice[:], (*[1 << 30]byte)(unsafe.Pointer(p))[0:n]) dest[i] = slice } case C.SQLITE_NULL: dest[i] = nil case C.SQLITE_TEXT: var err error var timeVal time.Time n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i))) s := C.GoStringN((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i)))), C.int(n)) switch rc.decltype[i] { case "timestamp", "datetime", "date": var t time.Time s = strings.TrimSuffix(s, "Z") for _, format := range SQLiteTimestampFormats { if timeVal, err = time.ParseInLocation(format, s, time.UTC); err == nil { t = timeVal break } } if err != nil { // The column is a time value, so return the zero time on parse failure. t = time.Time{} } if rc.s.c.loc != nil { t = t.In(rc.s.c.loc) } dest[i] = t default: dest[i] = []byte(s) } } } return nil }
func (self *sqlStatement) sqlColumnFloat64(col int) float64 { return float64(C.sqlite3_column_double(self.handle, C.int(col))) }
// Move cursor to next. func (rc *SQLiteRows) Next(dest []driver.Value) error { rv := C.sqlite3_step(rc.s.s) if rv == C.SQLITE_DONE { return io.EOF } if rv != C.SQLITE_ROW { return errors.New(C.GoString(C.sqlite3_errmsg(rc.s.c.db))) } if rc.decltype == nil { rc.decltype = make([]string, rc.nc) for i := 0; i < rc.nc; i++ { rc.decltype[i] = strings.ToLower(C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i)))) } } for i := range dest { switch C.sqlite3_column_type(rc.s.s, C.int(i)) { case C.SQLITE_INTEGER: val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i))) switch rc.decltype[i] { case "timestamp", "datetime": dest[i] = time.Unix(val, 0) case "boolean": dest[i] = val > 0 default: dest[i] = val } case C.SQLITE_FLOAT: dest[i] = float64(C.sqlite3_column_double(rc.s.s, C.int(i))) case C.SQLITE_BLOB: n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i))) p := C.sqlite3_column_blob(rc.s.s, C.int(i)) switch dest[i].(type) { case sql.RawBytes: dest[i] = (*[1 << 30]byte)(unsafe.Pointer(p))[0:n] default: slice := make([]byte, n) copy(slice[:], (*[1 << 30]byte)(unsafe.Pointer(p))[0:n]) dest[i] = slice } case C.SQLITE_NULL: dest[i] = nil case C.SQLITE_TEXT: var err error s := C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i))))) switch rc.decltype[i] { case "timestamp", "datetime": for _, format := range SQLiteTimestampFormats { if dest[i], err = time.Parse(format, s); err == nil { break } } if err != nil { // The column is a time value, so return the zero time on parse failure. dest[i] = time.Time{} } default: // NOTE(bradfitz): local hack, without internet access. I imagine // this has been fixed upstream properly. (the database/sql/driver // docs say that you can't return strings here) dest[i] = []byte(s) } } } return nil }
func (h *Statement) ColumnDouble(column int) float64 { rv := C.sqlite3_column_double(h.cptr, C.int(column)) return float64(rv) }
// Move cursor to next. func (rc *SQLiteRows) Next(dest []driver.Value) error { rv := C.sqlite3_step(rc.s.s) if rv == C.SQLITE_DONE { return io.EOF } if rv != C.SQLITE_ROW { rv = C.sqlite3_reset(rc.s.s) if rv != C.SQLITE_OK { return rc.s.c.lastError() } return nil } if rc.decltype == nil { rc.decltype = make([]string, rc.nc) for i := 0; i < rc.nc; i++ { rc.decltype[i] = strings.ToLower(C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i)))) } } for i := range dest { switch C.sqlite3_column_type(rc.s.s, C.int(i)) { case C.SQLITE_INTEGER: val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i))) switch rc.decltype[i] { case "timestamp", "datetime", "date": var t time.Time // Assume a millisecond unix timestamp if it's 13 digits -- too // large to be a reasonable timestamp in seconds. if val > 1e12 || val < -1e12 { val *= int64(time.Millisecond) // convert ms to nsec } else { val *= int64(time.Second) // convert sec to nsec } t = time.Unix(0, val).UTC() if rc.s.c.loc != nil { t = t.In(rc.s.c.loc) } dest[i] = t case "boolean": dest[i] = val > 0 default: dest[i] = val } case C.SQLITE_FLOAT: dest[i] = float64(C.sqlite3_column_double(rc.s.s, C.int(i))) case C.SQLITE_BLOB: p := C.sqlite3_column_blob(rc.s.s, C.int(i)) if p == nil { dest[i] = nil continue } n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i))) switch dest[i].(type) { case sql.RawBytes: dest[i] = (*[1 << 30]byte)(unsafe.Pointer(p))[0:n] default: slice := make([]byte, n) copy(slice[:], (*[1 << 30]byte)(unsafe.Pointer(p))[0:n]) dest[i] = slice } case C.SQLITE_NULL: dest[i] = nil case C.SQLITE_TEXT: var err error var timeVal time.Time n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i))) s := C.GoStringN((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i)))), C.int(n)) switch rc.decltype[i] { case "timestamp", "datetime", "date": var t time.Time s = strings.TrimSuffix(s, "Z") for _, format := range SQLiteTimestampFormats { if timeVal, err = time.ParseInLocation(format, s, time.UTC); err == nil { t = timeVal break } } if err != nil { // The column is a time value, so return the zero time on parse failure. t = time.Time{} } if rc.s.c.loc != nil { t = t.In(rc.s.c.loc) } dest[i] = t default: dest[i] = []byte(s) } } } return nil }
// Move cursor to next. func (rc *SQLiteRows) Next(dest []driver.Value) error { rv := C.sqlite3_step(rc.s.s) if rv == C.SQLITE_DONE { return io.EOF } if rv != C.SQLITE_ROW { rv = C.sqlite3_reset(rc.s.s) if rv != C.SQLITE_OK { return rc.s.c.lastError() } return nil } if rc.decltype == nil { rc.decltype = make([]string, rc.nc) for i := 0; i < rc.nc; i++ { rc.decltype[i] = strings.ToLower(C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i)))) } } for i := range dest { switch C.sqlite3_column_type(rc.s.s, C.int(i)) { case C.SQLITE_INTEGER: val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i))) switch rc.decltype[i] { case "timestamp", "datetime": dest[i] = time.Unix(val, 0) case "boolean": dest[i] = val > 0 default: dest[i] = val } case C.SQLITE_FLOAT: dest[i] = float64(C.sqlite3_column_double(rc.s.s, C.int(i))) case C.SQLITE_BLOB: p := C.sqlite3_column_blob(rc.s.s, C.int(i)) if p == nil { dest[i] = nil continue } n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i))) switch dest[i].(type) { case sql.RawBytes: dest[i] = (*[1 << 30]byte)(unsafe.Pointer(p))[0:n] default: slice := make([]byte, n) copy(slice[:], (*[1 << 30]byte)(unsafe.Pointer(p))[0:n]) dest[i] = slice } case C.SQLITE_NULL: dest[i] = nil case C.SQLITE_TEXT: var err error s := C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i))))) switch rc.decltype[i] { case "timestamp", "datetime": for _, format := range SQLiteTimestampFormats { if dest[i], err = time.Parse(format, s); err == nil { break } } if err != nil { // The column is a time value, so return the zero time on parse failure. dest[i] = time.Time{} } default: dest[i] = s } } } return nil }