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))) } 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 }
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 (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 }
// blob returns the value of column i as a []byte. If copy is false, the []byte // will point to memory allocated by SQLite. func blob(stmt *C.sqlite3_stmt, i C.int, copy bool) []byte { if p := C.sqlite3_column_blob(stmt, i); p != nil { n := C.sqlite3_column_bytes(stmt, i) if copy { return C.GoBytes(p, n) } return goBytes(p, n) } return nil }
// ScanBlob scans result value from a query. // The leftmost column/index is number 0. // Returns true when column is null. // (See sqlite3_column_blob: http://sqlite.org/c3ref/column_blob.html) func (s *Stmt) ScanBlob(index int) (value []byte, isNull bool) { p := C.sqlite3_column_blob(s.stmt, C.int(index)) if p == nil { isNull = true } else { 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. } 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") }
// ScanRawBytes scans result value from a query without making any copy. // The leftmost column/index is number 0. // Returns true when column is null. // (See sqlite3_column_blob: http://sqlite.org/c3ref/column_blob.html) func (s *Stmt) ScanRawBytes(index int) (value []byte, isNull bool) { if index < 0 || index >= s.ColumnCount() { panic(fmt.Sprintf("column index %d out of range [0,%d[.", index, s.ColumnCount())) } p := C.sqlite3_column_blob(s.stmt, C.int(index)) if p == nil { isNull = true } else { n := C.sqlite3_column_bytes(s.stmt, C.int(index)) value = (*[1 << 30]byte)(unsafe.Pointer(p))[:n:n] } return }
// ScanBlob scans result value from a query. // The leftmost column/index is number 0. // Returns true when column is null. // (See sqlite3_column_blob: http://sqlite.org/c3ref/column_blob.html) func (s *Stmt) ScanBlob(index int) (value []byte, isNull bool) { if index < 0 || index >= s.ColumnCount() { panic(fmt.Sprintf("column index %d out of range [0,%d[.", index, s.ColumnCount())) } p := C.sqlite3_column_blob(s.stmt, C.int(index)) if p == nil { isNull = true } else { 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. } 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) (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") }
func (s *Stmt) Scan(args ...interface{}) error { n := int(C.sqlite3_column_count(s.stmt)) if n != len(args) { return errors.New(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 errors.New("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 errors.New("arg " + strconv.Itoa(i) + " as int: " + err.Error()) } *v = x case *int64: x, err := strconv.ParseInt(string(data), 10, 64) if err != nil { return errors.New("arg " + strconv.Itoa(i) + " as int64: " + err.Error()) } *v = x case *float64: x, err := strconv.ParseFloat(string(data), 64) if err != nil { return errors.New("arg " + strconv.Itoa(i) + " as float64: " + err.Error()) } *v = x default: return errors.New("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 }
// 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 }
// 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 (s *Stmt) Scan(args ...interface{}) error { n := int(C.sqlite3_column_count(s.stmt)) if n != len(args) { return errors.New(fmt.Sprintf("incorrect argument count for Stmt.Scan: have %d want %d", len(args), n)) } for i, v := range args { if C.sqlite3_column_type(s.stmt, C.int(i)) == C.SQLITE_NULL { switch v := v.(type) { case *[]byte: *v = nil case *string: *v = "" case *bool: *v = false case *int: *v = 0 case *int64: *v = 0 case *uint64: *v = 0 case *uint32: *v = 0 case *float64: *v = 0.0 case *NullTime: *v = NullTime{Valid: false} default: return errors.New("unsupported type in Scan: " + reflect.TypeOf(v).String()) } } else { 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 errors.New("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 errors.New("arg " + strconv.Itoa(i) + " as int: " + err.Error()) } *v = x case *int64: x, err := strconv.ParseInt(string(data), 10, 64) if err != nil { return errors.New("arg " + strconv.Itoa(i) + " as int64: " + err.Error()) } *v = x case *uint64: x, err := strconv.ParseUint(string(data), 10, 64) if err != nil { return errors.New("arg " + strconv.Itoa(i) + " as int64: " + err.Error()) } *v = x case *uint32: x, err := strconv.ParseUint(string(data), 10, 32) if err != nil { return errors.New("arg " + strconv.Itoa(i) + " as int64: " + err.Error()) } *v = uint32(x) case *float64: x, err := strconv.ParseFloat(string(data), 64) if err != nil { return errors.New("arg " + strconv.Itoa(i) + " as float64: " + err.Error()) } *v = x case *NullTime: x, err := time.Parse(ISO8601, string(data)) if err != nil { return errors.New("arg " + strconv.Itoa(i) + " as time: " + err.Error()) } *v = NullTime{Time: x, Valid: true} case *time.Time: x, err := time.Parse(ISO8601, string(data)) if err != nil { return errors.New("arg " + strconv.Itoa(i) + " as time: " + err.Error()) } *v = x default: return errors.New("unsupported type in Scan: " + reflect.TypeOf(v).String()) } } } return nil }
func (s *Stmt) Scan(args ...interface{}) os.Error { n := int(C.sqlite3_column_count(s.stmt)) if n != len(args) { return os.NewError("incorrect argument count") } 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 { // fix(jimt): Must make a copy here. Once Stmt.Finalize() is called, // this memory becomes invalid. This was done on purpose according // to Russ: http://code.google.com/p/gosqlite/issues/detail?id=1 // I prefer it with the copy statement here. Behaviour otherwise is // misleading and cost me 3 hours of hair pulling. data = make([]byte, n) copy(data, (*[1<<31 - 1]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 *int8: x, err := strconv.Atoi(string(data)) if err != nil { return os.NewError("arg " + strconv.Itoa(i) + " as int: " + err.String()) } *v = int8(x) case *int16: x, err := strconv.Atoi(string(data)) if err != nil { return os.NewError("arg " + strconv.Itoa(i) + " as int: " + err.String()) } *v = int16(x) case *int32: x, err := strconv.Atoi(string(data)) if err != nil { return os.NewError("arg " + strconv.Itoa(i) + " as int: " + err.String()) } *v = int32(x) case *int64: x, err := strconv.Atoi64(string(data)) if err != nil { return os.NewError("arg " + strconv.Itoa(i) + " as int64: " + err.String()) } *v = x case *uint: x, err := strconv.Atoui(string(data)) if err != nil { return os.NewError("arg " + strconv.Itoa(i) + " as int: " + err.String()) } *v = x case *uint8: x, err := strconv.Atoui(string(data)) if err != nil { return os.NewError("arg " + strconv.Itoa(i) + " as int: " + err.String()) } *v = uint8(x) case *uint16: x, err := strconv.Atoui(string(data)) if err != nil { return os.NewError("arg " + strconv.Itoa(i) + " as int: " + err.String()) } *v = uint16(x) case *uint32: x, err := strconv.Atoui(string(data)) if err != nil { return os.NewError("arg " + strconv.Itoa(i) + " as int: " + err.String()) } *v = uint32(x) case *uint64: x, err := strconv.Atoui64(string(data)) if err != nil { return os.NewError("arg " + strconv.Itoa(i) + " as int64: " + err.String()) } *v = x case *float: x, err := strconv.Atof(string(data)) if err != nil { return os.NewError("arg " + strconv.Itoa(i) + " as float64: " + err.String()) } *v = x case *float32: x, err := strconv.Atof32(string(data)) if err != nil { return os.NewError("arg " + strconv.Itoa(i) + " as float64: " + err.String()) } *v = x case *float64: x, err := strconv.Atof64(string(data)) if err != nil { return os.NewError("arg " + strconv.Itoa(i) + " as float64: " + err.String()) } *v = x default: return os.NewError("unsupported type in Scan: " + reflect.Typeof(v).String()) } } 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 }
// 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 }