コード例 #1
0
ファイル: driver.go プロジェクト: rsc/sqlite
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
}
コード例 #2
0
ファイル: sqlite3.go プロジェクト: jackc/go-sql-test
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
}
コード例 #3
0
ファイル: sqlite.go プロジェクト: kazyk/go-sqlite
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
}
コード例 #4
0
ファイル: sqlite3.go プロジェクト: seacoastboy/go-sqlite3
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
}
コード例 #5
0
ファイル: sqlite3.go プロジェクト: gidden/cloudlus
// 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
}
コード例 #6
0
ファイル: stmt.go プロジェクト: pkf/gosqlite
// 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
}
コード例 #7
0
ファイル: stmt.go プロジェクト: brandondyck/gosqlite
// 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")
}
コード例 #8
0
ファイル: stmt.go プロジェクト: brandondyck/gosqlite
// 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
}
コード例 #9
0
ファイル: stmt.go プロジェクト: brandondyck/gosqlite
// 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
}
コード例 #10
0
ファイル: stmt.go プロジェクト: npowern/gosqlite
// 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")
}
コード例 #11
0
ファイル: sqlite.go プロジェクト: vaibhav2800/forge
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
}
コード例 #12
0
ファイル: result_column.go プロジェクト: rwj/gosqlite3
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
}
コード例 #13
0
ファイル: stmt.go プロジェクト: pkf/gosqlite
// 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
}
コード例 #14
0
ファイル: sqlite3.go プロジェクト: Wishing-Wall/wishingwall
// 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
}
コード例 #15
0
ファイル: sqlite3.go プロジェクト: rfistman/camlistore
// 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
}
コード例 #16
0
ファイル: sqlite.go プロジェクト: aganno2/gosqlite
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
}
コード例 #17
0
ファイル: sqlite.go プロジェクト: welterde/mudkip
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
}
コード例 #18
0
ファイル: sqlite3.go プロジェクト: ntsh/go-sqlite3
// 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
}
コード例 #19
0
ファイル: sqlite3.go プロジェクト: C0rWin/fabric
// 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
}