Commit c22f0a7c authored by gwenn's avatar gwenn

Fails to add support to sqlite3_set_authorizer.

parent 89b245d6
......@@ -9,6 +9,7 @@ TARG=github.com/gwenn/sqlite
CGOFILES=\
sqlite.go\
backup.go\
meta.go
meta.go\
trace.go
include $(GOROOT)/src/Make.pkg
......@@ -17,6 +17,7 @@ import (
"unsafe"
)
// Calls sqlite3_backup_init
func NewBackup(dst *Conn, dstTable string, src *Conn, srcTable string) (*Backup, os.Error) {
dname := C.CString(dstTable)
sname := C.CString(srcTable)
......@@ -35,6 +36,7 @@ type Backup struct {
dst, src *Conn
}
// Calls sqlite3_backup_step
func (b *Backup) Step(npage int) os.Error {
rv := C.sqlite3_backup_step(b.sb, C.int(npage))
if rv == C.SQLITE_OK || Errno(rv) == ErrBusy || Errno(rv) == ErrLocked {
......@@ -48,10 +50,12 @@ type BackupStatus struct {
PageCount int
}
// Calls sqlite3_backup_remaining and sqlite3_backup_pagecount
func (b *Backup) Status() BackupStatus {
return BackupStatus{int(C.sqlite3_backup_remaining(b.sb)), int(C.sqlite3_backup_pagecount(b.sb))}
}
// Calls sqlite3_backup_step, sqlite3_backup_remaining and sqlite3_backup_pagecount
func (b *Backup) Run(npage int, sleepNs int64, c chan<- BackupStatus) os.Error {
var err os.Error
for {
......@@ -67,6 +71,7 @@ func (b *Backup) Run(npage int, sleepNs int64, c chan<- BackupStatus) os.Error {
return b.dst.error(C.sqlite3_errcode(b.dst.db))
}
// Calls sqlite3_backup_finish
func (b *Backup) Close() os.Error {
if b.sb == nil {
return os.EINVAL
......
......@@ -21,6 +21,7 @@ import (
"unsafe"
)
// Selects tables (no view) from 'sqlite_master' and filters system tables out.
func (c *Conn) Tables() ([]string, os.Error) {
s, err := c.Prepare("SELECT name FROM sqlite_master WHERE type IN ('table') AND name NOT LIKE 'sqlite_%'")
if err != nil {
......@@ -48,6 +49,7 @@ type Column struct {
Pk bool
}
// Executes pragma 'table_info'
func (c *Conn) Columns(table string) ([]Column, os.Error) {
s, err := c.Prepare(Mprintf("pragma table_info(%Q)", table))
if err != nil {
......@@ -75,6 +77,7 @@ type ForeignKey struct {
To []string
}
// Executes pragma 'foreign_key_list'
func (c *Conn) ForeignKeys(table string) (map[int]*ForeignKey, os.Error) {
s, err := c.Prepare(Mprintf("pragma foreign_key_list(%Q)", table))
if err != nil {
......@@ -104,6 +107,7 @@ func (c *Conn) ForeignKeys(table string) (map[int]*ForeignKey, os.Error) {
return fks, nil
}
// Calls 'sqlite3_mprintf'
func Mprintf(format string, arg string) string {
cf := C.CString(format)
defer C.free(unsafe.Pointer(cf))
......
......@@ -124,15 +124,18 @@ func (c *Conn) error(rv C.int) os.Error {
return os.NewError(Errno(rv).String() + ": " + C.GoString(C.sqlite3_errmsg(c.db)))
}
// Connection
type Conn struct {
db *C.sqlite3
}
// Calls sqlite3_libversion
func Version() string {
p := C.sqlite3_libversion()
return C.GoString(p)
}
// Calls sqlite3_enable_shared_cache
func EnableSharedCache(b bool) os.Error {
rv := C.sqlite3_enable_shared_cache(btocint(b))
if rv != C.SQLITE_OK {
......@@ -143,6 +146,7 @@ func EnableSharedCache(b bool) os.Error {
// ':memory:' for memory db
// '' for temp db
// Calls sqlite3_open_v2
func Open(filename string) (*Conn, os.Error) {
if C.sqlite3_threadsafe() == 0 {
return nil, os.NewError("sqlite library was not compiled for thread-safe operation")
......@@ -166,9 +170,10 @@ func Open(filename string) (*Conn, os.Error) {
if db == nil {
return nil, os.NewError("sqlite succeeded without returning a database")
}
return &Conn{db}, nil
return &Conn{db: db}, nil
}
// Calls sqlite3_busy_timeout
func (c *Conn) BusyTimeout(ms int) os.Error {
rv := C.sqlite3_busy_timeout(c.db, C.int(ms))
if rv == C.SQLITE_OK {
......@@ -177,9 +182,11 @@ func (c *Conn) BusyTimeout(ms int) os.Error {
return Errno(rv)
}
// Calls sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, b)
func (c *Conn) EnableFKey(b bool) (bool, os.Error) {
return c.queryOrSetEnableFKey(btocint(b))
}
// Calls sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, -1)
func (c *Conn) IsFKeyEnabled() (bool, os.Error) {
return c.queryOrSetEnableFKey(-1)
}
......@@ -193,6 +200,7 @@ func (c *Conn) queryOrSetEnableFKey(i C.int) (bool, os.Error) {
}
// Don't use it with SELECT or anything that returns data.
// Calls sqlite3_prepare_v2, sqlite3_bind_*, sqlite3_step and sqlite3_finalize
func (c *Conn) Exec(cmd string, args ...interface{}) os.Error {
for len(cmd) > 0 {
s, err := c.Prepare(cmd)
......@@ -221,18 +229,22 @@ func (c *Conn) Exec(cmd string, args ...interface{}) os.Error {
return nil
}
// Calls sqlite3_changes
func (c *Conn) Changes() int {
return int(C.sqlite3_changes(c.db))
}
// Calls sqlite3_last_insert_rowid
func (c *Conn) LastInsertRowid() int64 {
return int64(C.sqlite3_last_insert_rowid(c.db))
}
// Calls sqlite3_interrupt
func (c *Conn) Interrupt() {
C.sqlite3_interrupt(c.db)
}
// Prepared Statement (sqlite3_stmt)
type Stmt struct {
c *Conn
stmt *C.sqlite3_stmt
......@@ -240,6 +252,7 @@ type Stmt struct {
cols map[string]int // cached columns index by name
}
// Calls sqlite3_prepare_v2 and sqlite3_bind_*
func (c *Conn) Prepare(cmd string, args ...interface{}) (*Stmt, os.Error) {
if c == nil || c.db == nil {
return nil, os.NewError("nil sqlite database")
......@@ -267,6 +280,7 @@ func (c *Conn) Prepare(cmd string, args ...interface{}) (*Stmt, os.Error) {
}
// Don't use it with SELECT or anything that returns data.
// Calls sqlite3_bind_* and sqlite3_step
func (s *Stmt) Exec(args ...interface{}) os.Error {
err := s.Bind(args...)
if err != nil {
......@@ -279,16 +293,19 @@ func (s *Stmt) Exec(args ...interface{}) os.Error {
return nil
}
// Calls sqlite3_bind_parameter_count
func (s *Stmt) BindParameterCount() int {
return int(C.sqlite3_bind_parameter_count(s.stmt))
}
// Calls sqlite3_bind_parameter_index
func (s *Stmt) BindParameterIndex(name string) int {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
return int(C.sqlite3_bind_parameter_index(s.stmt, cname))
}
// Calls sqlite3_bind_parameter_count and sqlite3_bind_(blob|double|int|int64|null|text) depending on args type.
func (s *Stmt) Bind(args ...interface{}) os.Error {
err := s.Reset()
if err != nil {
......@@ -336,6 +353,7 @@ func (s *Stmt) Bind(args ...interface{}) os.Error {
return nil
}
// Calls sqlite3_step
func (s *Stmt) Next() (bool, os.Error) {
rv := C.sqlite3_step(s.stmt)
err := Errno(rv)
......@@ -348,6 +366,7 @@ func (s *Stmt) Next() (bool, os.Error) {
return false, nil
}
// Calls sqlite3_reset
func (s *Stmt) Reset() os.Error {
rv := C.sqlite3_reset(s.stmt)
if rv != C.SQLITE_OK {
......@@ -356,15 +375,18 @@ func (s *Stmt) Reset() os.Error {
return nil
}
// Calls sqlite3_column_count
func (s *Stmt) ColumnCount() int {
return int(C.sqlite3_column_count(s.stmt))
}
// The leftmost column is number 0.
// Calls sqlite3_column_name
func (s *Stmt) ColumnName(index int) string {
return C.GoString(C.sqlite3_column_name(s.stmt, C.int(index)))
}
// Calls sqlite3_column_count, sqlite3_column_name and sqlite3_column_(blob|double|int|int64|text) depending on args type.
func (s *Stmt) NamedScan(args ...interface{}) os.Error {
if len(args)%2 != 0 {
return os.NewError("Expected an even number of arguments")
......@@ -387,6 +409,7 @@ func (s *Stmt) NamedScan(args ...interface{}) os.Error {
return nil
}
// Calls sqlite3_column_count and sqlite3_column_(blob|double|int|int64|text) depending on args type.
func (s *Stmt) Scan(args ...interface{}) os.Error {
n := s.ColumnCount()
if n != len(args) {
......@@ -450,6 +473,8 @@ func (s *Stmt) scanField(index int, value interface{}) os.Error {
}
return nil
}
// Calls sqlite3_finalize
func (s *Stmt) Finalize() os.Error {
rv := C.sqlite3_finalize(s.stmt)
if rv != C.SQLITE_OK {
......@@ -459,6 +484,7 @@ func (s *Stmt) Finalize() os.Error {
return nil
}
// Calls sqlite3_close
func (c *Conn) Close() os.Error {
if c == nil || c.db == nil {
return os.NewError("nil sqlite database")
......
package sqlite
import (
"fmt"
"strings"
"testing"
"os"
)
func trace(d interface{}, t string) {
fmt.Printf("%s: %s\n", d, t)
}
func authorizer(d interface{}, action int, arg1, arg2, arg3, arg4 string) int {
fmt.Printf("%s: %d, %s, %s, %s, %s\n", d, action, arg1, arg2, arg3, arg4)
return 0
}
func open(t *testing.T) *Conn {
db, err := Open("")
if err != nil {
......@@ -14,6 +24,8 @@ func open(t *testing.T) *Conn {
if db == nil {
t.Fatal("opened database is nil")
}
//db.Trace(trace, "TRACE")
//db.SetAuthorizer(authorizer, "AUTH") FIXME panic
return db
}
......@@ -35,6 +47,8 @@ func TestVersion(t *testing.T) {
func TestOpen(t *testing.T) {
db := open(t)
db.Trace(nil, nil)
db.SetAuthorizer(nil, nil)
db.Close()
}
......@@ -138,6 +152,7 @@ func TestInsertWithStatement(t *testing.T) {
t.Errorf("insert error: %d <> 1", c)
}
}
s.Finalize()
cs, _ := db.Prepare("SELECT COUNT(*) FROM test")
defer cs.Finalize()
......
......@@ -14,10 +14,17 @@ extern void goXTrace(void *pArg, const char *t);
static void goSqlite3Trace(sqlite3 *db, void *pArg) {
sqlite3_trace(db, goXTrace, pArg);
}
extern int goXAuth(void *pUserData, int action, const char *arg1, const char *arg2, const char *arg3, const char *arg4);
static int goSqlite3SetAuthorizer(sqlite3 *db, void *pUserData) {
return sqlite3_set_authorizer(db, goXAuth, pUserData);
}
*/
import "C"
import (
"fmt"
"unsafe"
)
......@@ -34,7 +41,42 @@ func goXTrace(pArg unsafe.Pointer, t *C.char) {
arg.f(arg.d, C.GoString(t))
}
// Calls sqlite3_trace
func (c *Conn) Trace(f SqliteTrace, arg interface{}) {
if f == nil {
C.sqlite3_trace(c.db, nil, nil)
return
}
pArg := unsafe.Pointer(&sqliteTrace{f, arg})
C.goSqlite3Trace(c.db, pArg)
}
type SqliteAuthorizer func(d interface{}, action int, arg1, arg2, arg3, arg4 string) int
type sqliteAuthorizer struct {
f SqliteAuthorizer
d interface{}
}
//export goXAuth
func goXAuth(pUserData unsafe.Pointer, action C.int, arg1, arg2, arg3, arg4 *C.char) C.int {
var result int
if pUserData != nil {
arg := (*sqliteAuthorizer)(pUserData)
result = arg.f(arg.d, int(action), C.GoString(arg1), C.GoString(arg2), C.GoString(arg3), C.GoString(arg4))
} else {
fmt.Printf("ERROR - %v\n", pUserData)
result = 0
}
return C.int(result)
}
// Calls sqlite3_set_authorizer
func (c *Conn) SetAuthorizer(f SqliteAuthorizer, arg interface{}) int {
// c.authorizer = f
if f == nil {
return int(C.sqlite3_set_authorizer(c.db, nil, nil))
}
pArg := unsafe.Pointer(&sqliteAuthorizer{f, arg})
return int(C.goSqlite3SetAuthorizer(c.db, pArg))
}
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