Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gosqlite
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
gosqlite
Commits
c1df3127
Commit
c1df3127
authored
Dec 22, 2012
by
gwenn
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adds contextual details to errors when possible.
parent
bedc25eb
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
51 additions
and
41 deletions
+51
-41
blob.go
blob.go
+7
-6
function.go
function.go
+8
-4
meta.go
meta.go
+5
-2
pragma.go
pragma.go
+2
-2
sqlite.go
sqlite.go
+5
-5
stmt.go
stmt.go
+16
-16
trace.go
trace.go
+4
-4
vtab.go
vtab.go
+4
-2
No files found.
blob.go
View file @
c1df3127
...
...
@@ -12,6 +12,7 @@ import "C"
import
(
"errors"
"fmt"
"io"
"unsafe"
)
...
...
@@ -68,7 +69,7 @@ func (c *Conn) blob_open(db, table, column string, row int64, write bool) (*C.sq
if
bl
!=
nil
{
C
.
sqlite3_blob_close
(
bl
)
}
return
nil
,
c
.
error
(
rv
)
return
nil
,
c
.
error
(
rv
,
fmt
.
Sprintf
(
"Conn.blob_open(db: %q, tbl: %q, col: %q, row: %d)"
,
db
,
table
,
column
,
row
)
)
}
if
bl
==
nil
{
return
nil
,
errors
.
New
(
"sqlite succeeded without returning a blob"
)
...
...
@@ -80,11 +81,11 @@ func (c *Conn) blob_open(db, table, column string, row int64, write bool) (*C.sq
// (See http://sqlite.org/c3ref/blob_close.html)
func
(
r
*
BlobReader
)
Close
()
error
{
if
r
==
nil
{
return
errors
.
New
(
"nil sqlite blob
reader
"
)
return
errors
.
New
(
"nil sqlite blob"
)
}
rv
:=
C
.
sqlite3_blob_close
(
r
.
bl
)
if
rv
!=
C
.
SQLITE_OK
{
return
r
.
c
.
error
(
rv
)
return
r
.
c
.
error
(
rv
,
"BlobReader.Close"
)
}
r
.
bl
=
nil
return
nil
...
...
@@ -110,7 +111,7 @@ func (r *BlobReader) Read(v []byte) (int, error) {
n
:=
len
(
v
)
rv
:=
C
.
sqlite3_blob_read
(
r
.
bl
,
unsafe
.
Pointer
(
p
),
C
.
int
(
n
),
C
.
int
(
r
.
ReadOffset
))
if
rv
!=
C
.
SQLITE_OK
{
return
0
,
r
.
c
.
error
(
rv
)
return
0
,
r
.
c
.
error
(
rv
,
"BlobReader.Read"
)
}
r
.
ReadOffset
+=
n
return
n
,
nil
...
...
@@ -150,7 +151,7 @@ func (w *BlobReadWriter) Write(v []byte) (int, error) {
n
:=
len
(
v
)
rv
:=
C
.
sqlite3_blob_write
(
w
.
bl
,
unsafe
.
Pointer
(
p
),
C
.
int
(
n
),
C
.
int
(
w
.
WriteOffset
))
if
rv
!=
C
.
SQLITE_OK
{
return
0
,
w
.
c
.
error
(
rv
)
return
0
,
w
.
c
.
error
(
rv
,
"BlobReadWiter.Write"
)
}
w
.
WriteOffset
+=
n
return
n
,
err
...
...
@@ -161,7 +162,7 @@ func (w *BlobReadWriter) Write(v []byte) (int, error) {
func
(
r
*
BlobReader
)
Reopen
(
rowid
int64
)
error
{
rv
:=
C
.
sqlite3_blob_reopen
(
r
.
bl
,
C
.
sqlite3_int64
(
rowid
))
if
rv
!=
C
.
SQLITE_OK
{
return
r
.
c
.
error
(
rv
)
return
r
.
c
.
error
(
rv
,
fmt
.
Sprintf
(
"BlobReader.Reopen(%d)"
,
rowid
)
)
}
r
.
size
=
-
1
r
.
ReadOffset
=
0
...
...
function.go
View file @
c1df3127
...
...
@@ -421,7 +421,8 @@ func (c *Conn) CreateScalarFunction(functionName string, nArg int, pApp interfac
if
len
(
c
.
udfs
)
>
0
{
delete
(
c
.
udfs
,
functionName
)
}
return
c
.
error
(
C
.
sqlite3_create_function_v2
(
c
.
db
,
fname
,
C
.
int
(
nArg
),
C
.
SQLITE_UTF8
,
nil
,
nil
,
nil
,
nil
,
nil
))
return
c
.
error
(
C
.
sqlite3_create_function_v2
(
c
.
db
,
fname
,
C
.
int
(
nArg
),
C
.
SQLITE_UTF8
,
nil
,
nil
,
nil
,
nil
,
nil
),
fmt
.
Sprintf
(
"<Conn.CreateScalarFunction(%q)"
,
functionName
))
}
// To make sure it is not gced, keep a reference in the connection.
udf
:=
&
sqliteFunction
{
f
,
nil
,
nil
,
d
,
pApp
,
make
(
map
[
*
ScalarContext
]
bool
),
nil
}
...
...
@@ -429,7 +430,8 @@ func (c *Conn) CreateScalarFunction(functionName string, nArg int, pApp interfac
c
.
udfs
=
make
(
map
[
string
]
*
sqliteFunction
)
}
c
.
udfs
[
functionName
]
=
udf
// FIXME same function name with different args is not supported
return
c
.
error
(
C
.
goSqlite3CreateScalarFunction
(
c
.
db
,
fname
,
C
.
int
(
nArg
),
C
.
SQLITE_UTF8
,
unsafe
.
Pointer
(
udf
)))
return
c
.
error
(
C
.
goSqlite3CreateScalarFunction
(
c
.
db
,
fname
,
C
.
int
(
nArg
),
C
.
SQLITE_UTF8
,
unsafe
.
Pointer
(
udf
)),
fmt
.
Sprintf
(
"Conn.CreateScalarFunction(%q)"
,
functionName
))
}
// CreateAggregateFunction creates or redefines SQL aggregate functions.
...
...
@@ -443,7 +445,8 @@ func (c *Conn) CreateAggregateFunction(functionName string, nArg int, pApp inter
if
len
(
c
.
udfs
)
>
0
{
delete
(
c
.
udfs
,
functionName
)
}
return
c
.
error
(
C
.
sqlite3_create_function_v2
(
c
.
db
,
fname
,
C
.
int
(
nArg
),
C
.
SQLITE_UTF8
,
nil
,
nil
,
nil
,
nil
,
nil
))
return
c
.
error
(
C
.
sqlite3_create_function_v2
(
c
.
db
,
fname
,
C
.
int
(
nArg
),
C
.
SQLITE_UTF8
,
nil
,
nil
,
nil
,
nil
,
nil
),
fmt
.
Sprintf
(
"<Conn.CreateAggregateFunction(%q)"
,
functionName
))
}
// To make sure it is not gced, keep a reference in the connection.
udf
:=
&
sqliteFunction
{
nil
,
step
,
final
,
d
,
pApp
,
nil
,
make
(
map
[
*
AggregateContext
]
bool
)}
...
...
@@ -451,5 +454,6 @@ func (c *Conn) CreateAggregateFunction(functionName string, nArg int, pApp inter
c
.
udfs
=
make
(
map
[
string
]
*
sqliteFunction
)
}
c
.
udfs
[
functionName
]
=
udf
// FIXME same function name with different args is not supported
return
c
.
error
(
C
.
goSqlite3CreateAggregateFunction
(
c
.
db
,
fname
,
C
.
int
(
nArg
),
C
.
SQLITE_UTF8
,
unsafe
.
Pointer
(
udf
)))
return
c
.
error
(
C
.
goSqlite3CreateAggregateFunction
(
c
.
db
,
fname
,
C
.
int
(
nArg
),
C
.
SQLITE_UTF8
,
unsafe
.
Pointer
(
udf
)),
fmt
.
Sprintf
(
"Conn.CreateAggregateFunction(%q)"
,
functionName
))
}
meta.go
View file @
c1df3127
...
...
@@ -35,7 +35,10 @@ static int my_table_column_metadata(
*/
import
"C"
import
"unsafe"
import
(
"fmt"
"unsafe"
)
// Databases returns one couple (name, file) for each database attached to the current database connection.
// (See http://www.sqlite.org/pragma.html#pragma_database_list)
...
...
@@ -146,7 +149,7 @@ func (c *Conn) Column(dbName, tableName, columnName string) (*Column, error) {
rv
:=
C
.
my_table_column_metadata
(
c
.
db
,
zDbName
,
zTableName
,
zColumnName
,
&
zDataType
,
&
zCollSeq
,
&
notNull
,
&
primaryKey
,
&
autoinc
)
if
rv
!=
C
.
SQLITE_OK
{
return
nil
,
c
.
error
(
rv
)
return
nil
,
c
.
error
(
rv
,
fmt
.
Sprintf
(
"Conn.Column(db: %q, tbl: %q, col: %q)"
,
dbName
,
tableName
,
columnName
)
)
}
return
&
Column
{
-
1
,
columnName
,
C
.
GoString
(
zDataType
),
notNull
==
1
,
""
,
primaryKey
==
1
,
autoinc
==
1
,
C
.
GoString
(
zCollSeq
)},
nil
...
...
pragma.go
View file @
c1df3127
...
...
@@ -32,7 +32,7 @@ func (c *Conn) IntegrityCheck(dbName string, max int, quick bool) error {
return
err
}
if
msg
!=
"ok"
{
return
c
.
specificError
(
"Integrity check failed
(%s)"
,
msg
)
return
c
.
specificError
(
"Integrity check failed
on %q (%s)"
,
dbName
,
msg
)
}
return
nil
}
...
...
@@ -155,5 +155,5 @@ func (c *Conn) oneValue(query string, value interface{}) error { // no cache
}
else
if
err
==
Done
{
return
io
.
EOF
}
return
s
.
error
(
rv
)
return
s
.
error
(
rv
,
fmt
.
Sprintf
(
"Conn.oneValue(%q)"
,
query
)
)
}
sqlite.go
View file @
c1df3127
...
...
@@ -243,7 +243,7 @@ func OpenVfs(filename string, vfsname string, flags ...OpenFlag) (*Conn, error)
// BusyTimeout sets a busy timeout.
// (See http://sqlite.org/c3ref/busy_timeout.html)
func
(
c
*
Conn
)
BusyTimeout
(
ms
int
)
error
{
// TODO time.Duration ?
return
c
.
error
(
C
.
sqlite3_busy_timeout
(
c
.
db
,
C
.
int
(
ms
)))
return
c
.
error
(
C
.
sqlite3_busy_timeout
(
c
.
db
,
C
.
int
(
ms
))
,
"Conn.BusyTimeout"
)
}
// EnableFKey enables or disables the enforcement of foreign key constraints.
...
...
@@ -292,7 +292,7 @@ func (c *Conn) queryOrSetEnableDbConfig(key, i C.int) (bool, error) {
// EnableExtendedResultCodes enables or disables the extended result codes feature of SQLite.
// (See http://sqlite.org/c3ref/extended_result_codes.html)
func
(
c
*
Conn
)
EnableExtendedResultCodes
(
b
bool
)
error
{
return
c
.
error
(
C
.
sqlite3_extended_result_codes
(
c
.
db
,
btocint
(
b
)))
return
c
.
error
(
C
.
sqlite3_extended_result_codes
(
c
.
db
,
btocint
(
b
))
,
"Conn.EnableExtendedResultCodes"
)
}
// Readonly determines if a database is read-only.
...
...
@@ -335,7 +335,7 @@ func (c *Conn) Exec(cmd string, args ...interface{}) error {
if
len
(
s
.
tail
)
>
0
{
if
len
(
args
)
>
0
{
s
.
finalize
()
return
c
.
specificError
(
"
Cannot execute multiple statements when args are specified"
)
return
c
.
specificError
(
"
cannot execute multiple statements when args are specified: %q"
,
cmd
)
}
}
cmd
=
s
.
tail
...
...
@@ -478,7 +478,7 @@ func (c *Conn) exec(cmd string) error {
defer
s
.
finalize
()
rv
:=
C
.
sqlite3_step
(
s
.
stmt
)
if
Errno
(
rv
)
!=
Done
{
return
s
.
error
(
rv
)
return
s
.
error
(
rv
,
"Conn.exec(%q)"
,
cmd
)
}
return
nil
}
...
...
@@ -511,7 +511,7 @@ func (c *Conn) Close() error {
c
.
db
=
nil
if
rv
!=
C
.
SQLITE_OK
{
Log
(
int
(
rv
),
"error while closing Conn"
)
return
c
.
error
(
rv
)
return
c
.
error
(
rv
,
"Conn.Close"
)
}
return
nil
}
...
...
stmt.go
View file @
c1df3127
...
...
@@ -34,7 +34,6 @@ import "C"
import
(
"errors"
"fmt"
"reflect"
"time"
"unsafe"
)
...
...
@@ -150,7 +149,7 @@ func (s *Stmt) exec() error {
rv
:=
C
.
sqlite3_step
(
s
.
stmt
)
C
.
sqlite3_reset
(
s
.
stmt
)
if
Errno
(
rv
)
!=
Done
{
return
s
.
error
(
rv
)
return
s
.
error
(
rv
,
"Stmt.exec"
)
}
return
nil
}
...
...
@@ -228,6 +227,7 @@ func (s *Stmt) SelectOneRow(args ...interface{}) (bool, error) {
}
// BindParameterCount returns the number of SQL parameters.
// FIXME If parameters of the ?NNN form are used, there may be gaps in the list.
// (See http://sqlite.org/c3ref/bind_parameter_count.html)
func
(
s
*
Stmt
)
BindParameterCount
()
int
{
if
s
.
bindParameterCount
==
-
1
{
...
...
@@ -252,7 +252,7 @@ func (s *Stmt) BindParameterIndex(name string) (int, error) {
defer
C
.
free
(
unsafe
.
Pointer
(
cname
))
index
=
int
(
C
.
sqlite3_bind_parameter_index
(
s
.
stmt
,
cname
))
if
index
==
0
{
return
index
,
s
.
specificError
(
"invalid parameter name: %
s
"
,
name
)
return
index
,
s
.
specificError
(
"invalid parameter name: %
q
"
,
name
)
}
s
.
params
[
name
]
=
index
return
index
,
nil
...
...
@@ -273,12 +273,12 @@ func (s *Stmt) BindParameterName(i int) (string, error) {
// NamedBind binds parameters by their name (name1, value1, ...)
func
(
s
*
Stmt
)
NamedBind
(
args
...
interface
{})
error
{
if
len
(
args
)
%
2
!=
0
{
return
s
.
specificError
(
"
Expected an even number of arguments"
)
return
s
.
specificError
(
"
expected an even number of arguments: %d"
,
len
(
args
)
)
}
for
i
:=
0
;
i
<
len
(
args
);
i
+=
2
{
name
,
ok
:=
args
[
i
]
.
(
string
)
if
!
ok
{
return
s
.
specificError
(
"non-string param name
"
)
return
s
.
specificError
(
"non-string param name
at %d: %T"
,
i
,
args
[
i
]
)
}
index
,
err
:=
s
.
BindParameterIndex
(
name
)
// How to look up only once for one statement ?
if
err
!=
nil
{
...
...
@@ -346,9 +346,9 @@ func (s *Stmt) BindByIndex(index int, value interface{}) error {
case
ZeroBlobLength
:
rv
=
C
.
sqlite3_bind_zeroblob
(
s
.
stmt
,
i
,
C
.
int
(
value
))
default
:
return
s
.
specificError
(
"unsupported type in Bind: %
s"
,
reflect
.
TypeOf
(
value
)
)
return
s
.
specificError
(
"unsupported type in Bind: %
T"
,
value
)
}
return
s
.
error
(
rv
)
return
s
.
error
(
rv
,
"Stmt.Bind"
)
}
// Next evaluates an SQL statement
...
...
@@ -376,7 +376,7 @@ func (s *Stmt) Next() (bool, error) {
}
C
.
sqlite3_reset
(
s
.
stmt
)
if
err
!=
Done
{
return
false
,
s
.
error
(
rv
)
return
false
,
s
.
error
(
rv
,
"Stmt.Next"
)
}
// TODO Check column count > 0
return
false
,
nil
...
...
@@ -386,13 +386,13 @@ func (s *Stmt) Next() (bool, error) {
// and reset it back to its starting state so that it can be reused.
// (See http://sqlite.org/c3ref/reset.html)
func
(
s
*
Stmt
)
Reset
()
error
{
return
s
.
error
(
C
.
sqlite3_reset
(
s
.
stmt
))
return
s
.
error
(
C
.
sqlite3_reset
(
s
.
stmt
)
,
"Stmt.Reset"
)
}
// ClearBindings resets all bindings on a prepared statement.
// (See http://sqlite.org/c3ref/clear_bindings.html)
func
(
s
*
Stmt
)
ClearBindings
()
error
{
return
s
.
error
(
C
.
sqlite3_clear_bindings
(
s
.
stmt
))
return
s
.
error
(
C
.
sqlite3_clear_bindings
(
s
.
stmt
)
,
"Stmt.ClearBindings"
)
}
// ColumnCount returns the number of columns in the result set for the statement (with or without row).
...
...
@@ -470,12 +470,12 @@ func (s *Stmt) ColumnType(index int) Type {
// (See http://sqlite.org/c3ref/column_blob.html)
func
(
s
*
Stmt
)
NamedScan
(
args
...
interface
{})
error
{
if
len
(
args
)
%
2
!=
0
{
return
s
.
specificError
(
"
Expected an even number of arguments"
)
return
s
.
specificError
(
"
expected an even number of arguments: %d"
,
len
(
args
)
)
}
for
i
:=
0
;
i
<
len
(
args
);
i
+=
2
{
name
,
ok
:=
args
[
i
]
.
(
string
)
if
!
ok
{
return
s
.
specificError
(
"non-string field name
"
)
return
s
.
specificError
(
"non-string field name
at %d: %T"
,
i
,
args
[
i
]
)
}
index
,
err
:=
s
.
ColumnIndex
(
name
)
// How to look up only once for one statement ?
if
err
!=
nil
{
...
...
@@ -660,7 +660,7 @@ func (s *Stmt) ScanByIndex(index int, value interface{}) (bool, error) {
case
func
(
interface
{})
(
bool
,
error
)
:
isNull
,
err
=
value
(
s
.
ScanValue
(
index
))
default
:
return
false
,
s
.
specificError
(
"unsupported type in Scan: %
s"
,
reflect
.
TypeOf
(
value
)
)
return
false
,
s
.
specificError
(
"unsupported type in Scan: %
T"
,
value
)
}
return
isNull
,
err
}
...
...
@@ -885,14 +885,14 @@ func (s *Stmt) checkTypeMismatch(source, target Type) error {
case
Text
:
fallthrough
case
Blob
:
return
s
.
specificError
(
"
T
ype mismatch, source %s vs target %s"
,
source
,
target
)
return
s
.
specificError
(
"
t
ype mismatch, source %s vs target %s"
,
source
,
target
)
}
case
Float
:
switch
source
{
case
Text
:
fallthrough
case
Blob
:
return
s
.
specificError
(
"
T
ype mismatch, source %s vs target %s"
,
source
,
target
)
return
s
.
specificError
(
"
t
ype mismatch, source %s vs target %s"
,
source
,
target
)
}
}
return
nil
...
...
@@ -923,7 +923,7 @@ func (s *Stmt) finalize() error {
s
.
stmt
=
nil
if
rv
!=
C
.
SQLITE_OK
{
Log
(
int
(
rv
),
"error while finalizing Stmt"
)
return
s
.
error
(
rv
)
return
s
.
error
(
rv
,
"Stmt.finalize"
)
}
return
nil
}
...
...
trace.go
View file @
c1df3127
...
...
@@ -226,11 +226,11 @@ func goXAuth(udp unsafe.Pointer, action int, arg1, arg2, dbName, triggerName *C.
func
(
c
*
Conn
)
SetAuthorizer
(
f
Authorizer
,
udp
interface
{})
error
{
if
f
==
nil
{
c
.
authorizer
=
nil
return
c
.
error
(
C
.
sqlite3_set_authorizer
(
c
.
db
,
nil
,
nil
))
return
c
.
error
(
C
.
sqlite3_set_authorizer
(
c
.
db
,
nil
,
nil
)
,
"<Conn.SetAuthorizer"
)
}
// To make sure it is not gced, keep a reference in the connection.
c
.
authorizer
=
&
sqliteAuthorizer
{
f
,
udp
}
return
c
.
error
(
C
.
goSqlite3SetAuthorizer
(
c
.
db
,
unsafe
.
Pointer
(
c
.
authorizer
)))
return
c
.
error
(
C
.
goSqlite3SetAuthorizer
(
c
.
db
,
unsafe
.
Pointer
(
c
.
authorizer
))
,
"Conn.SetAuthorizer"
)
}
// Returns true to try again.
...
...
@@ -254,11 +254,11 @@ func goXBusy(udp unsafe.Pointer, count int) C.int {
func
(
c
*
Conn
)
BusyHandler
(
f
BusyHandler
,
udp
interface
{})
error
{
if
f
==
nil
{
c
.
busyHandler
=
nil
return
c
.
error
(
C
.
sqlite3_busy_handler
(
c
.
db
,
nil
,
nil
))
return
c
.
error
(
C
.
sqlite3_busy_handler
(
c
.
db
,
nil
,
nil
)
,
"<Conn.BusyHandler"
)
}
// To make sure it is not gced, keep a reference in the connection.
c
.
busyHandler
=
&
sqliteBusyHandler
{
f
,
udp
}
return
c
.
error
(
C
.
goSqlite3BusyHandler
(
c
.
db
,
unsafe
.
Pointer
(
c
.
busyHandler
)))
return
c
.
error
(
C
.
goSqlite3BusyHandler
(
c
.
db
,
unsafe
.
Pointer
(
c
.
busyHandler
))
,
"Conn.BusyHandler"
)
}
// Returns true to interrupt.
...
...
vtab.go
View file @
c1df3127
...
...
@@ -13,6 +13,7 @@ int goSqlite3CreateModule(sqlite3 *db, const char *zName, void *pClientData);
import
"C"
import
(
"fmt"
"reflect"
"unsafe"
)
...
...
@@ -223,7 +224,7 @@ type VTabCursor interface {
func
(
c
*
Conn
)
DeclareVTab
(
sql
string
)
error
{
zSQL
:=
C
.
CString
(
sql
)
defer
C
.
free
(
unsafe
.
Pointer
(
zSQL
))
return
c
.
error
(
C
.
sqlite3_declare_vtab
(
c
.
db
,
zSQL
))
return
c
.
error
(
C
.
sqlite3_declare_vtab
(
c
.
db
,
zSQL
)
,
fmt
.
Sprintf
(
"Conn.DeclareVTab(%q)"
,
sql
)
)
}
// CreateModule registers a virtual table implementation.
...
...
@@ -237,7 +238,8 @@ func (c *Conn) CreateModule(moduleName string, module Module) error {
c
.
modules
=
make
(
map
[
string
]
*
sqliteModule
)
}
c
.
modules
[
moduleName
]
=
udm
// FIXME What happens if different modules are registered with the same name?
return
c
.
error
(
C
.
goSqlite3CreateModule
(
c
.
db
,
mname
,
unsafe
.
Pointer
(
udm
)))
return
c
.
error
(
C
.
goSqlite3CreateModule
(
c
.
db
,
mname
,
unsafe
.
Pointer
(
udm
)),
fmt
.
Sprintf
(
"Conn.CreateModule(%q)"
,
moduleName
))
}
/*
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment