Commit 702122fc authored by gwenn's avatar gwenn

Improved doc

parent 6393481f
...@@ -11,6 +11,12 @@ See [package documentation](http://godoc.org/github.com/gwenn/gosqlite). ...@@ -11,6 +11,12 @@ See [package documentation](http://godoc.org/github.com/gwenn/gosqlite).
[1]: https://secure.travis-ci.org/gwenn/gosqlite.png [1]: https://secure.travis-ci.org/gwenn/gosqlite.png
[2]: http://www.travis-ci.org/gwenn/gosqlite [2]: http://www.travis-ci.org/gwenn/gosqlite
### Features (not supported by database/sql/driver):
* Dynamic type: currently, the SQLite3 manifest typing is respected. There is no use of the column declared type to guess the target/go type when scanning. On your side, you should try to not break column affinity rules (such as declaring a column with TIMESTAMP type (NUMERIC affinity) storing values with '2006-01-02T15:04:05.999Z07:00' format (TEXT type))...
* Partial scan: scan values may be partially scanned (by index or name) or skipped/ignored by passing nil pointer(s).
* Null value: by default, empty string and zero time are bound to null for prepared statement's parameters (no need for NullString, NullTime but still supported).
### Changes: ### Changes:
Open supports flags. Open supports flags.
...@@ -84,6 +90,7 @@ Time: ...@@ -84,6 +90,7 @@ Time:
JulianDay JulianDay
JulianDayToUTC JulianDayToUTC
JulianDayToLocalTime JulianDayToLocalTime
UnixTime, JulianTime and TimeStamp used to persist go time in formats supported by SQLite3 date functions.
Trace: Trace:
Conn.BusyHandler Conn.BusyHandler
......
...@@ -46,6 +46,7 @@ type rowsImpl struct { ...@@ -46,6 +46,7 @@ type rowsImpl struct {
// ":memory:" for memory db, // ":memory:" for memory db,
// "" for temp file db // "" for temp file db
func (d *impl) Open(name string) (driver.Conn, error) { func (d *impl) Open(name string) (driver.Conn, error) {
// OpenNoMutex == multi-thread mode (http://sqlite.org/compile.html#threadsafe and http://sqlite.org/threadsafe.html)
c, err := Open(name, OpenUri, OpenNoMutex, OpenReadWrite, OpenCreate) c, err := Open(name, OpenUri, OpenNoMutex, OpenReadWrite, OpenCreate)
if err != nil { if err != nil {
return nil, err return nil, err
......
...@@ -8,14 +8,6 @@ package sqlite ...@@ -8,14 +8,6 @@ package sqlite
#include <sqlite3.h> #include <sqlite3.h>
#include <stdlib.h> #include <stdlib.h>
// cgo doesn't support varargs
static char *my_mprintf(char *zFormat, char *arg) {
return sqlite3_mprintf(zFormat, arg);
}
static char *my_mprintf2(char *zFormat, char *arg1, char *arg2) {
return sqlite3_mprintf(zFormat, arg1, arg2);
}
// just to get ride of warning // just to get ride of warning
static int my_table_column_metadata( static int my_table_column_metadata(
sqlite3 *db, sqlite3 *db,
...@@ -299,34 +291,3 @@ func (c *Conn) IndexColumns(dbName, index string) ([]Column, error) { ...@@ -299,34 +291,3 @@ func (c *Conn) IndexColumns(dbName, index string) ([]Column, error) {
} }
return columns, nil return columns, nil
} }
// Mprintf is like fmt.Printf but implements some additional formatting options
// that are useful for constructing SQL statements.
// (See http://sqlite.org/c3ref/mprintf.html)
func Mprintf(format string, arg string) string {
zSQL := mPrintf(format, arg)
defer C.sqlite3_free(unsafe.Pointer(zSQL))
return C.GoString(zSQL)
}
func mPrintf(format, arg string) *C.char {
cf := C.CString(format)
defer C.free(unsafe.Pointer(cf))
ca := C.CString(arg)
defer C.free(unsafe.Pointer(ca))
return C.my_mprintf(cf, ca)
}
// Mprintf2 is like fmt.Printf but implements some additional formatting options
// that are useful for constructing SQL statements.
// (See http://sqlite.org/c3ref/mprintf.html)
func Mprintf2(format string, arg1, arg2 string) string {
cf := C.CString(format)
defer C.free(unsafe.Pointer(cf))
ca1 := C.CString(arg1)
defer C.free(unsafe.Pointer(ca1))
ca2 := C.CString(arg2)
defer C.free(unsafe.Pointer(ca2))
zSQL := C.my_mprintf2(cf, ca1, ca2)
defer C.sqlite3_free(unsafe.Pointer(zSQL))
return C.GoString(zSQL)
}
...@@ -23,7 +23,6 @@ import ( ...@@ -23,7 +23,6 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"reflect"
"strconv" "strconv"
"time" "time"
"unsafe" "unsafe"
...@@ -202,14 +201,14 @@ func OpenVfs(filename string, vfsname string, flags ...OpenFlag) (*Conn, error) ...@@ -202,14 +201,14 @@ func OpenVfs(filename string, vfsname string, flags ...OpenFlag) (*Conn, error)
} }
var db *C.sqlite3 var db *C.sqlite3
name := C.CString(filename) cname := C.CString(filename)
defer C.free(unsafe.Pointer(name)) defer C.free(unsafe.Pointer(cname))
var vfs *C.char var vfs *C.char
if len(vfsname) > 0 { if len(vfsname) > 0 {
vfs = C.CString(vfsname) vfs = C.CString(vfsname)
defer C.free(unsafe.Pointer(vfs)) defer C.free(unsafe.Pointer(vfs))
} }
rv := C.sqlite3_open_v2(name, &db, C.int(openFlags), vfs) rv := C.sqlite3_open_v2(cname, &db, C.int(openFlags), vfs)
if rv != C.SQLITE_OK { if rv != C.SQLITE_OK {
if db != nil { if db != nil {
C.sqlite3_close(db) C.sqlite3_close(db)
...@@ -352,6 +351,7 @@ func (c *Conn) Exists(query string, args ...interface{}) (bool, error) { ...@@ -352,6 +351,7 @@ func (c *Conn) Exists(query string, args ...interface{}) (bool, error) {
// OneValue is used with SELECT that returns only one row with only one column. // OneValue is used with SELECT that returns only one row with only one column.
// Returns io.EOF when there is no row. // Returns io.EOF when there is no row.
// No check is performed to ensure that there is no more than one row.
func (c *Conn) OneValue(query string, value interface{}, args ...interface{}) error { func (c *Conn) OneValue(query string, value interface{}, args ...interface{}) error {
s, err := c.Prepare(query, args...) s, err := c.Prepare(query, args...)
if err != nil { if err != nil {
...@@ -591,23 +591,3 @@ func EnableSharedCache(b bool) error { ...@@ -591,23 +591,3 @@ func EnableSharedCache(b bool) error {
} }
return Errno(rv) return Errno(rv)
} }
// Must is a helper that wraps a call to a function returning (bool, os.Error)
// and panics if the error is non-nil.
func Must(b bool, err error) bool {
if err != nil {
panic(err)
}
return b
}
func btocint(b bool) C.int {
if b {
return 1
}
return 0
}
func cstring(s string) (*C.char, C.int) {
cs := *(*reflect.StringHeader)(unsafe.Pointer(&s))
return (*C.char)(unsafe.Pointer(cs.Data)), C.int(cs.Len)
}
...@@ -297,7 +297,7 @@ func (s *Stmt) NamedBind(args ...interface{}) error { ...@@ -297,7 +297,7 @@ func (s *Stmt) NamedBind(args ...interface{}) error {
} }
// Bind binds parameters by their index. // Bind binds parameters by their index.
// Calls sqlite3_bind_parameter_count and sqlite3_bind_(blob|double|int|int64|null|text) depending on args type. // Calls sqlite3_bind_parameter_count and sqlite3_bind_(blob|double|int|int64|null|text) depending on args type/kind.
// (See http://sqlite.org/c3ref/bind_blob.html) // (See http://sqlite.org/c3ref/bind_blob.html)
func (s *Stmt) Bind(args ...interface{}) error { func (s *Stmt) Bind(args ...interface{}) error {
n := s.BindParameterCount() n := s.BindParameterCount()
...@@ -321,6 +321,7 @@ var NullIfEmptyString = true ...@@ -321,6 +321,7 @@ var NullIfEmptyString = true
var NullIfZeroTime = true var NullIfZeroTime = true
// BindByIndex binds value to the specified host parameter of the prepared statement. // BindByIndex binds value to the specified host parameter of the prepared statement.
// Value's type/kind is used to find the storage class.
// 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 {
i := C.int(index) i := C.int(index)
...@@ -373,6 +374,9 @@ func (s *Stmt) BindByIndex(index int, value interface{}) error { ...@@ -373,6 +374,9 @@ func (s *Stmt) BindByIndex(index int, value interface{}) error {
return s.error(rv, "Stmt.Bind") return s.error(rv, "Stmt.Bind")
} }
// BindReflect binds value to the specified host parameter of the prepared statement.
// Value's (reflect) Kind is used to find the storage class.
// The leftmost SQL parameter has an index of 1.
func (s *Stmt) BindReflect(index int, value interface{}) error { func (s *Stmt) BindReflect(index int, value interface{}) error {
i := C.int(index) i := C.int(index)
var rv C.int var rv C.int
...@@ -423,7 +427,7 @@ func (s *Stmt) Next() (bool, error) { ...@@ -423,7 +427,7 @@ func (s *Stmt) Next() (bool, error) {
if err == Row { if err == Row {
return true, nil return true, nil
} }
C.sqlite3_reset(s.stmt) C.sqlite3_reset(s.stmt) // Release implicit lock as soon as possible (see dbEvalStep in tclsqlite3.c)
if err != Done { if err != Done {
return false, s.error(rv, "Stmt.Next") return false, s.error(rv, "Stmt.Next")
} }
...@@ -543,7 +547,7 @@ func (s *Stmt) NamedScan(args ...interface{}) error { ...@@ -543,7 +547,7 @@ func (s *Stmt) NamedScan(args ...interface{}) error {
// //
// NULL value is converted to 0 if arg type is *int,*int64,*float,*float64, to "" for *string, to []byte{} for *[]byte and to false for *bool. // NULL value is converted to 0 if arg type is *int,*int64,*float,*float64, to "" for *string, to []byte{} for *[]byte and to false for *bool.
// To avoid NULL conversion, arg type must be **T. // To avoid NULL conversion, arg type must be **T.
// Calls sqlite3_column_(blob|double|int|int64|text) depending on args type. // Calls sqlite3_column_(blob|double|int|int64|text) depending on args type/kind.
// (See http://sqlite.org/c3ref/column_blob.html) // (See http://sqlite.org/c3ref/column_blob.html)
func (s *Stmt) Scan(args ...interface{}) error { func (s *Stmt) Scan(args ...interface{}) error {
n := s.ColumnCount() n := s.ColumnCount()
...@@ -590,7 +594,7 @@ func (s *Stmt) ColumnIndex(name string) (int, error) { ...@@ -590,7 +594,7 @@ func (s *Stmt) ColumnIndex(name string) (int, error) {
// ScanByName scans result value from a query. // ScanByName scans result value from a query.
// Returns true when column is null. // Returns true when column is null.
// Calls sqlite3_column_(blob|double|int|int64|text) depending on arg type. // Calls sqlite3_column_(blob|double|int|int64|text) depending on arg type/kind.
// (See http://sqlite.org/c3ref/column_blob.html) // (See http://sqlite.org/c3ref/column_blob.html)
func (s *Stmt) ScanByName(name string, value interface{}) (bool, error) { func (s *Stmt) ScanByName(name string, value interface{}) (bool, error) {
index, err := s.ColumnIndex(name) index, err := s.ColumnIndex(name)
...@@ -604,18 +608,19 @@ func (s *Stmt) ScanByName(name string, value interface{}) (bool, error) { ...@@ -604,18 +608,19 @@ func (s *Stmt) ScanByName(name string, value interface{}) (bool, error) {
// The leftmost column/index is number 0. // The leftmost column/index is number 0.
// //
// Destination type is specified by the caller (except when value type is *interface{}). // Destination type is specified by the caller (except when value type is *interface{}).
// The value must be of one of the following types: // The value must be of one of the following types/kinds:
// (*)*string, // (*)*string
// (*)*int, (*)*int64, (*)*byte, // (*)*int,int8,int16,int32,int64
// (*)*uint,uint8,uint16,uint32,uint64
// (*)*bool // (*)*bool
// (*)*float64 // (*)*float32,float64
// (*)*[]byte // (*)*[]byte
// *time.Time // *time.Time
// sql.Scanner // sql.Scanner
// *interface{} // *interface{}
// //
// Returns true when column is null. // Returns true when column is null.
// Calls sqlite3_column_(blob|double|int|int64|text) depending on arg type. // Calls sqlite3_column_(blob|double|int|int64|text) depending on arg type/kind.
// (See http://sqlite.org/c3ref/column_blob.html) // (See http://sqlite.org/c3ref/column_blob.html)
func (s *Stmt) ScanByIndex(index int, value interface{}) (bool, error) { func (s *Stmt) ScanByIndex(index int, value interface{}) (bool, error) {
var isNull bool var isNull bool
...@@ -716,6 +721,18 @@ func (s *Stmt) ScanByIndex(index int, value interface{}) (bool, error) { ...@@ -716,6 +721,18 @@ func (s *Stmt) ScanByIndex(index int, value interface{}) (bool, error) {
return isNull, err return isNull, err
} }
// ScanReflect scans result value from a query.
// The leftmost column/index is number 0.
//
// Destination type is specified by the caller.
// The value must be of one of the following kinds:
// *string
// *int,int8,int16,int32,int64
// *uint,uint8,uint16,uint32,uint64
// *bool
// *float32,float64
//
// Returns true when column is null.
func (s *Stmt) ScanReflect(index int, v interface{}) (bool, error) { func (s *Stmt) ScanReflect(index int, v interface{}) (bool, error) {
rv := reflect.ValueOf(v) rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr || rv.IsNil() { if rv.Kind() != reflect.Ptr || rv.IsNil() {
......
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package sqlite
/*
#include <sqlite3.h>
#include <stdlib.h>
// cgo doesn't support varargs
static char *my_mprintf(char *zFormat, char *arg) {
return sqlite3_mprintf(zFormat, arg);
}
static char *my_mprintf2(char *zFormat, char *arg1, char *arg2) {
return sqlite3_mprintf(zFormat, arg1, arg2);
}
*/
import "C"
import (
"reflect"
"unsafe"
)
// Mprintf is like fmt.Printf but implements some additional formatting options
// that are useful for constructing SQL statements.
// (See http://sqlite.org/c3ref/mprintf.html)
func Mprintf(format string, arg string) string {
zSQL := mPrintf(format, arg)
defer C.sqlite3_free(unsafe.Pointer(zSQL))
return C.GoString(zSQL)
}
func mPrintf(format, arg string) *C.char {
cf := C.CString(format)
defer C.free(unsafe.Pointer(cf))
ca := C.CString(arg)
defer C.free(unsafe.Pointer(ca))
return C.my_mprintf(cf, ca)
}
// Mprintf2 is like fmt.Printf but implements some additional formatting options
// that are useful for constructing SQL statements.
// (See http://sqlite.org/c3ref/mprintf.html)
func Mprintf2(format string, arg1, arg2 string) string {
cf := C.CString(format)
defer C.free(unsafe.Pointer(cf))
ca1 := C.CString(arg1)
defer C.free(unsafe.Pointer(ca1))
ca2 := C.CString(arg2)
defer C.free(unsafe.Pointer(ca2))
zSQL := C.my_mprintf2(cf, ca1, ca2)
defer C.sqlite3_free(unsafe.Pointer(zSQL))
return C.GoString(zSQL)
}
// Must is a helper that wraps a call to a function returning (bool, os.Error)
// and panics if the error is non-nil.
func Must(b bool, err error) bool {
if err != nil {
panic(err)
}
return b
}
func btocint(b bool) C.int {
if b {
return 1
}
return 0
}
func cstring(s string) (*C.char, C.int) {
cs := *(*reflect.StringHeader)(unsafe.Pointer(&s))
return (*C.char)(unsafe.Pointer(cs.Data)), C.int(cs.Len)
}
/*
func gostring(cs *C.char) string {
var x reflect.StringHeader
x.Data = uintptr(unsafe.Pointer(cs))
x.Len = int(C.strlen(cs))
return *(*string)(unsafe.Pointer(&x))
}
*/
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