Files
sqlite3/tests/conn_test.go

205 lines
3.8 KiB
Go
Raw Normal View History

2023-02-22 14:19:56 +00:00
package tests
import (
"context"
"errors"
"strings"
"testing"
"github.com/ncruces/go-sqlite3"
_ "github.com/ncruces/go-sqlite3/embed"
)
func TestConn_Open_dir(t *testing.T) {
t.Parallel()
2023-03-16 12:27:44 +00:00
_, err := sqlite3.OpenFlags(".", 0)
2023-02-22 14:19:56 +00:00
if err == nil {
t.Fatal("want error")
}
2023-02-25 15:11:07 +00:00
if !errors.Is(err, sqlite3.CANTOPEN) {
t.Errorf("got %v, want sqlite3.CANTOPEN", err)
2023-02-22 14:19:56 +00:00
}
}
func TestConn_Close(t *testing.T) {
var conn *sqlite3.Conn
conn.Close()
}
func TestConn_Close_BUSY(t *testing.T) {
t.Parallel()
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
stmt, _, err := db.Prepare(`BEGIN`)
if err != nil {
t.Fatal(err)
}
defer stmt.Close()
err = db.Close()
if err == nil {
t.Fatal("want error")
}
2023-02-25 15:11:07 +00:00
if !errors.Is(err, sqlite3.BUSY) {
t.Errorf("got %v, want sqlite3.BUSY", err)
2023-02-22 14:19:56 +00:00
}
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` {
2023-02-28 14:50:15 +00:00
t.Error("got message:", got)
2023-02-22 14:19:56 +00:00
}
}
func TestConn_SetInterrupt(t *testing.T) {
2023-02-27 12:07:48 +00:00
t.Parallel()
2023-02-22 14:19:56 +00:00
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
ctx, cancel := context.WithCancel(context.Background())
2023-02-24 14:56:49 +00:00
db.SetInterrupt(ctx)
2023-02-22 14:19:56 +00:00
// Interrupt doesn't interrupt this.
err = db.Exec(`SELECT 1`)
if err != nil {
t.Fatal(err)
}
2023-02-25 15:11:07 +00:00
db.SetInterrupt(context.Background())
2023-02-22 14:19:56 +00:00
stmt, _, err := db.Prepare(`
WITH RECURSIVE
fibonacci (curr, next)
AS (
SELECT 0, 1
UNION ALL
SELECT next, curr + next FROM fibonacci
LIMIT 1e6
)
SELECT min(curr) FROM fibonacci
`)
if err != nil {
t.Fatal(err)
}
defer stmt.Close()
2023-02-24 14:56:49 +00:00
db.SetInterrupt(ctx)
2023-02-24 14:31:41 +00:00
cancel()
2023-02-22 14:19:56 +00:00
// Interrupting works.
err = stmt.Exec()
2023-02-25 15:11:07 +00:00
if !errors.Is(err, sqlite3.INTERRUPT) {
t.Errorf("got %v, want sqlite3.INTERRUPT", err)
2023-02-22 14:19:56 +00:00
}
// Interrupting sticks.
err = db.Exec(`SELECT 1`)
2023-02-25 15:11:07 +00:00
if !errors.Is(err, sqlite3.INTERRUPT) {
t.Errorf("got %v, want sqlite3.INTERRUPT", err)
2023-02-22 14:19:56 +00:00
}
2023-02-24 14:31:41 +00:00
ctx, cancel = context.WithCancel(context.Background())
defer cancel()
2023-02-24 14:56:49 +00:00
db.SetInterrupt(ctx)
2023-02-22 14:19:56 +00:00
// Interrupting can be cleared.
err = db.Exec(`SELECT 1`)
if err != nil {
t.Fatal(err)
}
}
func TestConn_Prepare_empty(t *testing.T) {
t.Parallel()
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
stmt, _, err := db.Prepare(``)
if err != nil {
t.Fatal(err)
}
defer stmt.Close()
if stmt != nil {
t.Error("want nil")
}
}
func TestConn_Prepare_tail(t *testing.T) {
t.Parallel()
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
stmt, tail, err := db.Prepare(`SELECT 1; -- HERE`)
if err != nil {
t.Fatal(err)
}
defer stmt.Close()
if !strings.Contains(tail, "-- HERE") {
t.Errorf("got %q", tail)
}
}
func TestConn_Prepare_invalid(t *testing.T) {
t.Parallel()
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
var serr *sqlite3.Error
_, _, err = db.Prepare(`SELECT`)
if err == nil {
t.Fatal("want error")
}
if !errors.As(err, &serr) {
t.Fatalf("got %T, want sqlite3.Error", err)
}
if rc := serr.Code(); rc != sqlite3.ERROR {
t.Errorf("got %d, want sqlite3.ERROR", rc)
}
if got := err.Error(); got != `sqlite3: SQL logic error: incomplete input` {
2023-02-28 14:50:15 +00:00
t.Error("got message:", got)
2023-02-22 14:19:56 +00:00
}
_, _, err = db.Prepare(`SELECT * FRM sqlite_schema`)
if err == nil {
t.Fatal("want error")
}
if !errors.As(err, &serr) {
t.Fatalf("got %T, want sqlite3.ERROR", err)
}
if rc := serr.Code(); rc != sqlite3.ERROR {
t.Errorf("got %d, want sqlite3.ERROR", rc)
}
if got := serr.SQL(); got != `FRM sqlite_schema` {
2023-02-28 14:50:15 +00:00
t.Error("got SQL:", got)
2023-02-22 14:19:56 +00:00
}
if got := serr.Error(); got != `sqlite3: SQL logic error: near "FRM": syntax error` {
2023-02-28 14:50:15 +00:00
t.Error("got message:", got)
2023-02-22 14:19:56 +00:00
}
}