mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-12 05:59:14 +00:00
Tests.
This commit is contained in:
@@ -49,6 +49,10 @@ func (s *sqlite3Runtime) compileModule(ctx context.Context) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if bin == nil {
|
||||
s.err = binaryErr
|
||||
return
|
||||
}
|
||||
|
||||
s.compiled, s.err = s.runtime.CompileModule(ctx, bin)
|
||||
}
|
||||
|
||||
@@ -40,6 +40,10 @@ func TestConn_Close_BUSY(t *testing.T) {
|
||||
if rc := serr.Code(); rc != BUSY {
|
||||
t.Errorf("got %d, want sqlite3.BUSY", rc)
|
||||
}
|
||||
var terr interface{ Temporary() bool }
|
||||
if !errors.As(err, &terr) || !terr.Temporary() {
|
||||
t.Error("not temporary", err)
|
||||
}
|
||||
if got := err.Error(); got != `sqlite3: database is locked: unable to close due to unfinalized statements or unfinished backups` {
|
||||
t.Error("got message: ", got)
|
||||
}
|
||||
|
||||
@@ -26,14 +26,18 @@ func (sqlite) Open(name string) (driver.Conn, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var txBegin = "BEGIN "
|
||||
var txBegin string
|
||||
var pragmas strings.Builder
|
||||
if _, after, ok := strings.Cut(name, "?"); ok {
|
||||
query, _ := url.ParseQuery(after)
|
||||
|
||||
switch v := query.Get("_txlock"); v {
|
||||
switch s := query.Get("_txlock"); s {
|
||||
case "":
|
||||
txBegin = "BEGIN"
|
||||
case "deferred", "immediate", "exclusive":
|
||||
txBegin += v
|
||||
txBegin = "BEGIN " + s
|
||||
default:
|
||||
return nil, fmt.Errorf("sqlite3: invalid _txlock: %s", s)
|
||||
}
|
||||
|
||||
for _, p := range query["_pragma"] {
|
||||
@@ -219,6 +223,8 @@ func (s stmt) Query(args []driver.Value) (driver.Rows, error) {
|
||||
}
|
||||
|
||||
func (s stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
|
||||
// Use QueryContext to setup bindings.
|
||||
// No need to close rows: that simply resets the statement, exec does the same.
|
||||
_, err := s.QueryContext(ctx, args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -78,7 +78,8 @@ func Test_Open_pragma_invalid(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_Open_txLock(t *testing.T) {
|
||||
db, err := sql.Open("sqlite3", filepath.Join(t.TempDir(), "test.db")+
|
||||
db, err := sql.Open("sqlite3", "file:"+
|
||||
filepath.Join(t.TempDir(), "test.db")+
|
||||
"?_txlock=exclusive&_pragma=busy_timeout(0)")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -101,6 +102,10 @@ func Test_Open_txLock(t *testing.T) {
|
||||
if rc := serr.Code(); rc != sqlite3.BUSY {
|
||||
t.Errorf("got %d, want sqlite3.BUSY", rc)
|
||||
}
|
||||
var terr interface{ Temporary() bool }
|
||||
if !errors.As(err, &terr) || !terr.Temporary() {
|
||||
t.Error("not temporary", err)
|
||||
}
|
||||
if got := err.Error(); got != `sqlite3: database is locked` {
|
||||
t.Error("got message: ", got)
|
||||
}
|
||||
@@ -111,6 +116,22 @@ func Test_Open_txLock(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Open_txLock_invalid(t *testing.T) {
|
||||
db, err := sql.Open("sqlite3", "file::memory:?_txlock=xclusive")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
_, err = db.Conn(context.TODO())
|
||||
if err == nil {
|
||||
t.Fatal("want error")
|
||||
}
|
||||
if got := err.Error(); got != `sqlite3: invalid _txlock: xclusive` {
|
||||
t.Error("got message: ", got)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_BeginTx(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
@@ -122,7 +143,7 @@ func Test_BeginTx(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
_, err = db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelReadCommitted})
|
||||
if err != isolationErr {
|
||||
if err.Error() != string(isolationErr) {
|
||||
t.Error("want isolationErr")
|
||||
}
|
||||
|
||||
@@ -205,7 +226,7 @@ func Test_Prepare(t *testing.T) {
|
||||
}
|
||||
|
||||
_, err = db.Prepare(`SELECT 1; SELECT 2`)
|
||||
if err != tailErr {
|
||||
if err.Error() != string(tailErr) {
|
||||
t.Error("want tailErr")
|
||||
}
|
||||
}
|
||||
|
||||
6
error.go
6
error.go
@@ -50,6 +50,11 @@ func (e *Error) Error() string {
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// Temporary returns true for [BUSY] errors.
|
||||
func (e *Error) Temporary() bool {
|
||||
return e.Code() == BUSY
|
||||
}
|
||||
|
||||
// SQL returns the SQL starting at the token that triggered a syntax error.
|
||||
func (e *Error) SQL() string {
|
||||
return e.sql
|
||||
@@ -60,6 +65,7 @@ type errorString string
|
||||
func (e errorString) Error() string { return string(e) }
|
||||
|
||||
const (
|
||||
binaryErr = errorString("sqlite3: no SQLite binary embed/set/loaded")
|
||||
nilErr = errorString("sqlite3: invalid memory address or null pointer dereference")
|
||||
oomErr = errorString("sqlite3: out of memory")
|
||||
rangeErr = errorString("sqlite3: index out of range")
|
||||
|
||||
14
tests/compile/nil/compile_test.go
Normal file
14
tests/compile/nil/compile_test.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package compile_empty
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
)
|
||||
|
||||
func TestCompile_empty(t *testing.T) {
|
||||
_, err := sqlite3.Open(":memory:")
|
||||
if err == nil {
|
||||
t.Error("want error")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user