2023-02-22 14:19:56 +00:00
|
|
|
package tests
|
2023-02-08 00:00:53 +00:00
|
|
|
|
|
|
|
|
import (
|
2023-10-13 17:06:05 +01:00
|
|
|
"encoding/json"
|
2023-02-08 00:00:53 +00:00
|
|
|
"math"
|
2024-06-05 00:43:49 +01:00
|
|
|
"math/bits"
|
2023-02-08 00:00:53 +00:00
|
|
|
"testing"
|
2023-02-21 04:30:24 +00:00
|
|
|
"time"
|
2023-02-22 14:19:56 +00:00
|
|
|
|
|
|
|
|
"github.com/ncruces/go-sqlite3"
|
2023-11-23 03:28:56 +00:00
|
|
|
_ "github.com/ncruces/go-sqlite3/embed"
|
2024-06-02 10:33:20 +01:00
|
|
|
_ "github.com/ncruces/go-sqlite3/internal/testcfg"
|
2023-02-08 00:00:53 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func TestStmt(t *testing.T) {
|
2023-02-15 16:24:34 +00:00
|
|
|
t.Parallel()
|
|
|
|
|
|
2023-02-22 14:19:56 +00:00
|
|
|
db, err := sqlite3.Open(":memory:")
|
2023-02-08 00:00:53 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
defer db.Close()
|
|
|
|
|
|
2024-05-24 11:27:03 +01:00
|
|
|
err = db.Exec(`CREATE TABLE test (col ANY) STRICT`)
|
2023-02-08 00:00:53 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-27 12:07:48 +00:00
|
|
|
stmt, _, err := db.Prepare(`INSERT INTO test VALUES (?)`)
|
2023-02-08 00:00:53 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
defer stmt.Close()
|
|
|
|
|
|
2023-12-05 16:11:56 +00:00
|
|
|
if got := stmt.ReadOnly(); got != false {
|
|
|
|
|
t.Error("got true, want false")
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-14 18:21:18 +00:00
|
|
|
if got := stmt.BindCount(); got != 1 {
|
|
|
|
|
t.Errorf("got %d, want 1", got)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := stmt.BindBool(1, false); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := stmt.Exec(); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := stmt.BindBool(1, true); err != nil {
|
2023-02-10 14:14:19 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := stmt.Exec(); err != nil {
|
2023-02-10 14:14:19 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := stmt.BindInt(1, 2); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
2023-02-22 14:19:56 +00:00
|
|
|
if err = stmt.Exec(); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := stmt.BindFloat(1, math.Pi); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := stmt.Exec(); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := stmt.BindNull(1); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := stmt.Exec(); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := stmt.BindText(1, ""); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := stmt.Exec(); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := stmt.BindText(1, "text"); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := stmt.Exec(); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-31 16:33:31 +01:00
|
|
|
if err := stmt.BindRawText(1, nil); err != nil {
|
2023-10-13 17:06:05 +01:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
if err := stmt.Exec(); err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-31 16:33:31 +01:00
|
|
|
if err := stmt.BindBlob(1, []byte("")); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := stmt.Exec(); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-31 16:33:31 +01:00
|
|
|
if err := stmt.BindBlob(1, []byte("blob")); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := stmt.Exec(); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := stmt.BindZeroBlob(1, 4); err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
if err := stmt.Exec(); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-13 17:06:05 +01:00
|
|
|
if err := stmt.BindJSON(1, true); err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
if err := stmt.Exec(); err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := stmt.ClearBindings(); err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
if err := stmt.Exec(); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = stmt.Close()
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-13 17:06:05 +01:00
|
|
|
// The table should have: 0, 1, 2, π, NULL, "", "text", "", "blob", NULL, "\0\0\0\0", "true", NULL
|
2024-05-24 11:27:03 +01:00
|
|
|
stmt, _, err = db.Prepare(`SELECT col AS c FROM test`)
|
2023-02-08 00:00:53 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
2023-02-13 15:57:32 +00:00
|
|
|
defer stmt.Close()
|
2023-02-08 00:00:53 +00:00
|
|
|
|
2023-12-05 16:11:56 +00:00
|
|
|
if got := stmt.ReadOnly(); got != true {
|
|
|
|
|
t.Error("got false, want true")
|
|
|
|
|
}
|
2024-10-04 13:31:53 +01:00
|
|
|
if got := stmt.DataCount(); got != 0 {
|
|
|
|
|
t.Errorf("got %d, want 0", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnCount(); got != 1 {
|
|
|
|
|
t.Errorf("got %d, want 1", got)
|
|
|
|
|
}
|
2024-05-24 11:27:03 +01:00
|
|
|
if got := stmt.ColumnName(0); got != "c" {
|
|
|
|
|
t.Errorf(`got %q, want "c"`, got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnDeclType(0); got != "ANY" {
|
|
|
|
|
t.Errorf(`got %q, want "ANY"`, got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnOriginName(0); got != "col" {
|
|
|
|
|
t.Errorf(`got %q, want "col"`, got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnTableName(0); got != "test" {
|
|
|
|
|
t.Errorf(`got %q, want "test"`, got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnDatabaseName(0); got != "main" {
|
|
|
|
|
t.Errorf(`got %q, want "main"`, got)
|
|
|
|
|
}
|
2023-12-05 16:11:56 +00:00
|
|
|
|
2025-07-17 01:11:16 +01:00
|
|
|
if !stmt.Step() {
|
|
|
|
|
t.Fatal(stmt.Err())
|
|
|
|
|
} else {
|
2023-02-22 14:19:56 +00:00
|
|
|
if got := stmt.ColumnType(0); got != sqlite3.INTEGER {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Errorf("got %v, want INTEGER", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBool(0); got != false {
|
|
|
|
|
t.Errorf("got %v, want false", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnInt(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnFloat(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnText(0); got != "0" {
|
|
|
|
|
t.Errorf("got %q, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBlob(0, nil); string(got) != "0" {
|
|
|
|
|
t.Errorf("got %q, want zero", got)
|
|
|
|
|
}
|
2023-10-13 17:06:05 +01:00
|
|
|
var got int
|
|
|
|
|
if err := stmt.ColumnJSON(0, &got); err != nil {
|
|
|
|
|
t.Error(err)
|
|
|
|
|
} else if got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
2023-02-08 00:00:53 +00:00
|
|
|
}
|
|
|
|
|
|
2025-07-17 01:11:16 +01:00
|
|
|
if !stmt.Step() {
|
|
|
|
|
t.Fatal(stmt.Err())
|
|
|
|
|
} else {
|
2023-02-22 14:19:56 +00:00
|
|
|
if got := stmt.ColumnType(0); got != sqlite3.INTEGER {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Errorf("got %v, want INTEGER", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBool(0); got != true {
|
|
|
|
|
t.Errorf("got %v, want true", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnInt(0); got != 1 {
|
|
|
|
|
t.Errorf("got %v, want one", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnFloat(0); got != 1 {
|
|
|
|
|
t.Errorf("got %v, want one", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnText(0); got != "1" {
|
|
|
|
|
t.Errorf("got %q, want one", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBlob(0, nil); string(got) != "1" {
|
|
|
|
|
t.Errorf("got %q, want one", got)
|
|
|
|
|
}
|
2023-10-13 17:06:05 +01:00
|
|
|
var got float32
|
|
|
|
|
if err := stmt.ColumnJSON(0, &got); err != nil {
|
|
|
|
|
t.Error(err)
|
|
|
|
|
} else if got != 1 {
|
|
|
|
|
t.Errorf("got %v, want one", got)
|
|
|
|
|
}
|
2023-02-08 00:00:53 +00:00
|
|
|
}
|
|
|
|
|
|
2025-07-17 01:11:16 +01:00
|
|
|
if !stmt.Step() {
|
|
|
|
|
t.Fatal(stmt.Err())
|
|
|
|
|
} else {
|
2023-02-22 14:19:56 +00:00
|
|
|
if got := stmt.ColumnType(0); got != sqlite3.INTEGER {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Errorf("got %v, want INTEGER", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBool(0); got != true {
|
|
|
|
|
t.Errorf("got %v, want true", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnInt(0); got != 2 {
|
|
|
|
|
t.Errorf("got %v, want two", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnFloat(0); got != 2 {
|
|
|
|
|
t.Errorf("got %v, want two", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnText(0); got != "2" {
|
|
|
|
|
t.Errorf("got %q, want two", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBlob(0, nil); string(got) != "2" {
|
|
|
|
|
t.Errorf("got %q, want two", got)
|
|
|
|
|
}
|
2023-10-13 17:06:05 +01:00
|
|
|
var got json.Number
|
|
|
|
|
if err := stmt.ColumnJSON(0, &got); err != nil {
|
|
|
|
|
t.Error(err)
|
|
|
|
|
} else if got != "2" {
|
|
|
|
|
t.Errorf("got %v, want two", got)
|
|
|
|
|
}
|
2023-02-08 00:00:53 +00:00
|
|
|
}
|
|
|
|
|
|
2025-07-17 01:11:16 +01:00
|
|
|
if !stmt.Step() {
|
|
|
|
|
t.Fatal(stmt.Err())
|
|
|
|
|
} else {
|
2023-02-22 14:19:56 +00:00
|
|
|
if got := stmt.ColumnType(0); got != sqlite3.FLOAT {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Errorf("got %v, want FLOAT", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBool(0); got != true {
|
|
|
|
|
t.Errorf("got %v, want true", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnInt(0); got != 3 {
|
|
|
|
|
t.Errorf("got %v, want three", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnFloat(0); got != math.Pi {
|
|
|
|
|
t.Errorf("got %v, want π", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnText(0); got != "3.14159265358979" {
|
|
|
|
|
t.Errorf("got %q, want π", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBlob(0, nil); string(got) != "3.14159265358979" {
|
|
|
|
|
t.Errorf("got %q, want π", got)
|
|
|
|
|
}
|
2023-10-13 17:06:05 +01:00
|
|
|
var got float64
|
|
|
|
|
if err := stmt.ColumnJSON(0, &got); err != nil {
|
|
|
|
|
t.Error(err)
|
|
|
|
|
} else if got != math.Pi {
|
|
|
|
|
t.Errorf("got %v, want π", got)
|
|
|
|
|
}
|
2023-02-08 00:00:53 +00:00
|
|
|
}
|
|
|
|
|
|
2025-07-17 01:11:16 +01:00
|
|
|
if !stmt.Step() {
|
|
|
|
|
t.Fatal(stmt.Err())
|
|
|
|
|
} else {
|
2023-02-22 14:19:56 +00:00
|
|
|
if got := stmt.ColumnType(0); got != sqlite3.NULL {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Errorf("got %v, want NULL", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBool(0); got != false {
|
|
|
|
|
t.Errorf("got %v, want false", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnInt(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnFloat(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnText(0); got != "" {
|
|
|
|
|
t.Errorf("got %q, want empty", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBlob(0, nil); got != nil {
|
|
|
|
|
t.Errorf("got %q, want nil", got)
|
|
|
|
|
}
|
2023-10-13 17:06:05 +01:00
|
|
|
var got any = 1
|
|
|
|
|
if err := stmt.ColumnJSON(0, &got); err != nil {
|
|
|
|
|
t.Error(err)
|
|
|
|
|
} else if got != nil {
|
|
|
|
|
t.Errorf("got %v, want NULL", got)
|
|
|
|
|
}
|
2023-02-08 00:00:53 +00:00
|
|
|
}
|
|
|
|
|
|
2025-07-17 01:11:16 +01:00
|
|
|
if !stmt.Step() {
|
|
|
|
|
t.Fatal(stmt.Err())
|
|
|
|
|
} else {
|
2023-02-22 14:19:56 +00:00
|
|
|
if got := stmt.ColumnType(0); got != sqlite3.TEXT {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Errorf("got %v, want TEXT", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBool(0); got != false {
|
|
|
|
|
t.Errorf("got %v, want false", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnInt(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnFloat(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnText(0); got != "" {
|
|
|
|
|
t.Errorf("got %q, want empty", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBlob(0, nil); got != nil {
|
|
|
|
|
t.Errorf("got %q, want nil", got)
|
|
|
|
|
}
|
2023-10-13 17:06:05 +01:00
|
|
|
var got any
|
|
|
|
|
if err := stmt.ColumnJSON(0, &got); err == nil {
|
|
|
|
|
t.Errorf("got %v, want error", got)
|
|
|
|
|
}
|
2023-02-08 00:00:53 +00:00
|
|
|
}
|
|
|
|
|
|
2025-07-17 01:11:16 +01:00
|
|
|
if !stmt.Step() {
|
|
|
|
|
t.Fatal(stmt.Err())
|
|
|
|
|
} else {
|
2023-02-22 14:19:56 +00:00
|
|
|
if got := stmt.ColumnType(0); got != sqlite3.TEXT {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Errorf("got %v, want TEXT", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBool(0); got != false {
|
|
|
|
|
t.Errorf("got %v, want false", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnInt(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnFloat(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnText(0); got != "text" {
|
|
|
|
|
t.Errorf(`got %q, want "text"`, got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBlob(0, nil); string(got) != "text" {
|
|
|
|
|
t.Errorf(`got %q, want "text"`, got)
|
|
|
|
|
}
|
2023-10-13 17:06:05 +01:00
|
|
|
var got any
|
|
|
|
|
if err := stmt.ColumnJSON(0, &got); err == nil {
|
|
|
|
|
t.Errorf("got %v, want error", got)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-17 01:11:16 +01:00
|
|
|
if !stmt.Step() {
|
|
|
|
|
t.Fatal(stmt.Err())
|
|
|
|
|
} else {
|
2025-03-31 16:33:31 +01:00
|
|
|
if got := stmt.ColumnType(0); got != sqlite3.TEXT {
|
|
|
|
|
t.Errorf("got %v, want TEXT", got)
|
2023-10-13 17:06:05 +01:00
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBool(0); got != false {
|
|
|
|
|
t.Errorf("got %v, want false", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnInt(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnFloat(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnText(0); got != "" {
|
|
|
|
|
t.Errorf("got %q, want empty", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBlob(0, nil); got != nil {
|
|
|
|
|
t.Errorf("got %q, want nil", got)
|
|
|
|
|
}
|
|
|
|
|
var got any
|
|
|
|
|
if err := stmt.ColumnJSON(0, &got); err == nil {
|
|
|
|
|
t.Errorf("got %v, want error", got)
|
|
|
|
|
}
|
2023-02-08 00:00:53 +00:00
|
|
|
}
|
|
|
|
|
|
2025-07-17 01:11:16 +01:00
|
|
|
if !stmt.Step() {
|
|
|
|
|
t.Fatal(stmt.Err())
|
|
|
|
|
} else {
|
2023-02-22 14:19:56 +00:00
|
|
|
if got := stmt.ColumnType(0); got != sqlite3.BLOB {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Errorf("got %v, want BLOB", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBool(0); got != false {
|
|
|
|
|
t.Errorf("got %v, want false", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnInt(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnFloat(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
2025-03-31 16:33:31 +01:00
|
|
|
if got := stmt.ColumnText(0); got != "" {
|
|
|
|
|
t.Errorf("got %q, want empty", got)
|
2023-02-08 00:00:53 +00:00
|
|
|
}
|
2025-03-31 16:33:31 +01:00
|
|
|
if got := stmt.ColumnBlob(0, nil); got != nil {
|
|
|
|
|
t.Errorf("got %q, want nil", got)
|
2023-02-08 00:00:53 +00:00
|
|
|
}
|
2023-10-13 17:06:05 +01:00
|
|
|
var got any
|
|
|
|
|
if err := stmt.ColumnJSON(0, &got); err == nil {
|
|
|
|
|
t.Errorf("got %v, want error", got)
|
|
|
|
|
}
|
2023-02-08 00:00:53 +00:00
|
|
|
}
|
|
|
|
|
|
2025-07-17 01:11:16 +01:00
|
|
|
if !stmt.Step() {
|
|
|
|
|
t.Fatal(stmt.Err())
|
|
|
|
|
} else {
|
2025-03-31 16:33:31 +01:00
|
|
|
if got := stmt.ColumnType(0); got != sqlite3.BLOB {
|
|
|
|
|
t.Errorf("got %v, want BLOB", got)
|
2023-02-08 00:00:53 +00:00
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBool(0); got != false {
|
|
|
|
|
t.Errorf("got %v, want false", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnInt(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnFloat(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
2025-03-31 16:33:31 +01:00
|
|
|
if got := stmt.ColumnText(0); got != "blob" {
|
|
|
|
|
t.Errorf(`got %q, want "blob"`, got)
|
2023-02-08 00:00:53 +00:00
|
|
|
}
|
2025-03-31 16:33:31 +01:00
|
|
|
if got := stmt.ColumnBlob(0, nil); string(got) != "blob" {
|
|
|
|
|
t.Errorf(`got %q, want "blob"`, got)
|
2023-02-08 00:00:53 +00:00
|
|
|
}
|
2025-03-31 16:33:31 +01:00
|
|
|
var got any
|
|
|
|
|
if err := stmt.ColumnJSON(0, &got); err == nil {
|
|
|
|
|
t.Errorf("got %v, want error", got)
|
2023-10-13 17:06:05 +01:00
|
|
|
}
|
2023-02-08 00:00:53 +00:00
|
|
|
}
|
|
|
|
|
|
2025-07-17 01:11:16 +01:00
|
|
|
if !stmt.Step() {
|
|
|
|
|
t.Fatal(stmt.Err())
|
|
|
|
|
} else {
|
2023-02-22 14:19:56 +00:00
|
|
|
if got := stmt.ColumnType(0); got != sqlite3.BLOB {
|
|
|
|
|
t.Errorf("got %v, want BLOB", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBool(0); got != false {
|
|
|
|
|
t.Errorf("got %v, want false", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnInt(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnFloat(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnText(0); got != "\x00\x00\x00\x00" {
|
|
|
|
|
t.Errorf(`got %q, want "\x00\x00\x00\x00"`, got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBlob(0, nil); string(got) != "\x00\x00\x00\x00" {
|
|
|
|
|
t.Errorf(`got %q, want "\x00\x00\x00\x00"`, got)
|
|
|
|
|
}
|
2023-10-13 17:06:05 +01:00
|
|
|
var got any
|
|
|
|
|
if err := stmt.ColumnJSON(0, &got); err == nil {
|
|
|
|
|
t.Errorf("got %v, want error", got)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-17 01:11:16 +01:00
|
|
|
if !stmt.Step() {
|
|
|
|
|
t.Fatal(stmt.Err())
|
|
|
|
|
} else {
|
2023-10-13 17:06:05 +01:00
|
|
|
if got := stmt.ColumnType(0); got != sqlite3.TEXT {
|
|
|
|
|
t.Errorf("got %v, want TEXT", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBool(0); got != false {
|
|
|
|
|
t.Errorf("got %v, want false", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnInt(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnFloat(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnText(0); got != "true" {
|
|
|
|
|
t.Errorf("got %q, want true", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBlob(0, nil); string(got) != "true" {
|
|
|
|
|
t.Errorf("got %q, want true", got)
|
|
|
|
|
}
|
2025-09-23 13:36:31 +01:00
|
|
|
var got any
|
2023-10-13 17:06:05 +01:00
|
|
|
if err := stmt.ColumnJSON(0, &got); err != nil {
|
|
|
|
|
t.Error(err)
|
|
|
|
|
} else if got != true {
|
|
|
|
|
t.Errorf("got %v, want true", got)
|
|
|
|
|
}
|
2023-02-22 14:19:56 +00:00
|
|
|
}
|
|
|
|
|
|
2025-07-17 01:11:16 +01:00
|
|
|
if !stmt.Step() {
|
|
|
|
|
t.Fatal(stmt.Err())
|
|
|
|
|
} else {
|
2023-02-22 14:19:56 +00:00
|
|
|
if got := stmt.ColumnType(0); got != sqlite3.NULL {
|
|
|
|
|
t.Errorf("got %v, want NULL", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBool(0); got != false {
|
|
|
|
|
t.Errorf("got %v, want false", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnInt(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnFloat(0); got != 0 {
|
|
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnText(0); got != "" {
|
|
|
|
|
t.Errorf("got %q, want empty", got)
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.ColumnBlob(0, nil); got != nil {
|
|
|
|
|
t.Errorf("got %q, want nil", got)
|
|
|
|
|
}
|
2023-10-13 17:06:05 +01:00
|
|
|
var got any = 1
|
|
|
|
|
if err := stmt.ColumnJSON(0, &got); err != nil {
|
|
|
|
|
t.Error(err)
|
|
|
|
|
} else if got != nil {
|
|
|
|
|
t.Errorf("got %v, want NULL", got)
|
|
|
|
|
}
|
2023-02-22 14:19:56 +00:00
|
|
|
}
|
|
|
|
|
|
2024-10-04 13:31:53 +01:00
|
|
|
if got := stmt.DataCount(); got != 1 {
|
|
|
|
|
t.Errorf("got %d, want 1", got)
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-31 12:15:08 +01:00
|
|
|
db.Stmts()(func(s *sqlite3.Stmt) bool {
|
|
|
|
|
if s != stmt {
|
|
|
|
|
t.Error()
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
})
|
|
|
|
|
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := stmt.Close(); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-22 14:19:56 +00:00
|
|
|
if err := db.Close(); err != nil {
|
2023-02-08 00:00:53 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-02-10 14:14:19 +00:00
|
|
|
|
|
|
|
|
func TestStmt_Close(t *testing.T) {
|
2023-02-22 14:19:56 +00:00
|
|
|
var stmt *sqlite3.Stmt
|
2023-02-10 14:14:19 +00:00
|
|
|
stmt.Close()
|
|
|
|
|
}
|
2023-02-18 00:47:56 +00:00
|
|
|
|
|
|
|
|
func TestStmt_BindName(t *testing.T) {
|
2023-02-22 14:19:56 +00:00
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
db, err := sqlite3.Open(":memory:")
|
2023-02-18 00:47:56 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
defer db.Close()
|
|
|
|
|
|
|
|
|
|
want := []string{"", "", "", "", "?5", ":AAA", "@AAA", "$AAA"}
|
|
|
|
|
stmt, _, err := db.Prepare(`SELECT ?, ?5, :AAA, @AAA, $AAA`)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
defer stmt.Close()
|
|
|
|
|
|
|
|
|
|
if got := stmt.BindCount(); got != len(want) {
|
|
|
|
|
t.Errorf("got %d, want %d", got, len(want))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for i, name := range want {
|
|
|
|
|
id := i + 1
|
|
|
|
|
if got := stmt.BindName(id); got != name {
|
|
|
|
|
t.Errorf("got %q, want %q", got, name)
|
|
|
|
|
}
|
|
|
|
|
if name == "" {
|
|
|
|
|
id = 0
|
|
|
|
|
}
|
|
|
|
|
if got := stmt.BindIndex(name); got != id {
|
|
|
|
|
t.Errorf("got %d, want %d", got, id)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-02-21 04:30:24 +00:00
|
|
|
|
2023-02-24 10:50:16 +00:00
|
|
|
func TestStmt_ColumnTime(t *testing.T) {
|
2023-02-22 14:19:56 +00:00
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
db, err := sqlite3.Open(":memory:")
|
2023-02-21 04:30:24 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
defer db.Close()
|
|
|
|
|
|
|
|
|
|
stmt, _, err := db.Prepare(`SELECT ?, ?, ?, datetime(), unixepoch(), julianday(), NULL, 'abc'`)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
defer stmt.Close()
|
|
|
|
|
|
|
|
|
|
reference := time.Date(2013, 10, 7, 4, 23, 19, 120_000_000, time.FixedZone("", -4*3600))
|
2023-02-22 14:19:56 +00:00
|
|
|
err = stmt.BindTime(1, reference, sqlite3.TimeFormat4)
|
2023-02-21 04:30:24 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
2023-02-22 14:19:56 +00:00
|
|
|
err = stmt.BindTime(2, reference, sqlite3.TimeFormatUnixMilli)
|
2023-02-21 04:30:24 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
2023-02-22 14:19:56 +00:00
|
|
|
err = stmt.BindTime(3, reference, sqlite3.TimeFormatJulianDay)
|
2023-02-21 04:30:24 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if now := time.Now(); stmt.Step() {
|
2023-02-24 10:50:16 +00:00
|
|
|
if got := stmt.ColumnTime(0, sqlite3.TimeFormatAuto); !got.Equal(reference) {
|
2023-02-21 04:30:24 +00:00
|
|
|
t.Errorf("got %v, want %v", got, reference)
|
|
|
|
|
}
|
2023-02-24 10:50:16 +00:00
|
|
|
if got := stmt.ColumnTime(1, sqlite3.TimeFormatAuto); !got.Equal(reference) {
|
2023-02-21 04:30:24 +00:00
|
|
|
t.Errorf("got %v, want %v", got, reference)
|
|
|
|
|
}
|
2023-02-24 10:50:16 +00:00
|
|
|
if got := stmt.ColumnTime(2, sqlite3.TimeFormatAuto); got.Sub(reference).Abs() > time.Millisecond {
|
2023-02-21 04:30:24 +00:00
|
|
|
t.Errorf("got %v, want %v", got, reference)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-24 10:50:16 +00:00
|
|
|
if got := stmt.ColumnTime(3, sqlite3.TimeFormatAuto); got.Sub(now).Abs() > time.Second {
|
2023-02-21 04:30:24 +00:00
|
|
|
t.Errorf("got %v, want %v", got, now)
|
|
|
|
|
}
|
2023-02-24 10:50:16 +00:00
|
|
|
if got := stmt.ColumnTime(4, sqlite3.TimeFormatAuto); got.Sub(now).Abs() > time.Second {
|
2023-02-21 04:30:24 +00:00
|
|
|
t.Errorf("got %v, want %v", got, now)
|
|
|
|
|
}
|
2023-02-24 10:50:16 +00:00
|
|
|
if got := stmt.ColumnTime(5, sqlite3.TimeFormatAuto); got.Sub(now).Abs() > time.Second/10 {
|
2023-02-21 04:30:24 +00:00
|
|
|
t.Errorf("got %v, want %v", got, now)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-22 14:19:56 +00:00
|
|
|
if got := stmt.ColumnTime(6, sqlite3.TimeFormatAuto); got != (time.Time{}) {
|
2023-02-21 04:30:24 +00:00
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
2023-02-22 14:19:56 +00:00
|
|
|
if got := stmt.ColumnTime(7, sqlite3.TimeFormatAuto); got != (time.Time{}) {
|
2023-02-21 04:30:24 +00:00
|
|
|
t.Errorf("got %v, want zero", got)
|
|
|
|
|
}
|
|
|
|
|
if stmt.Err() == nil {
|
|
|
|
|
t.Errorf("want error")
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-07-09 22:13:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestStmt_ColumnValue(t *testing.T) {
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
db, err := sqlite3.Open(":memory:")
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
defer db.Close()
|
|
|
|
|
|
|
|
|
|
stmt, _, err := db.Prepare(`SELECT 1`)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
defer stmt.Close()
|
|
|
|
|
|
2025-07-17 01:11:16 +01:00
|
|
|
if !stmt.Step() {
|
|
|
|
|
t.Fatal(stmt.Err())
|
|
|
|
|
} else {
|
2024-07-09 22:13:14 +01:00
|
|
|
val := stmt.ColumnValue(0)
|
|
|
|
|
if _, err := val.InFirst(); err == nil {
|
|
|
|
|
t.Error("want error")
|
|
|
|
|
}
|
|
|
|
|
if _, err := val.InNext(); err == nil {
|
|
|
|
|
t.Error("want error")
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-12-04 12:37:53 +00:00
|
|
|
|
|
|
|
|
if got := stmt.Status(sqlite3.STMTSTATUS_RUN, true); got != 1 {
|
|
|
|
|
t.Errorf("got %d, want 1", got)
|
|
|
|
|
}
|
2024-07-09 22:13:14 +01:00
|
|
|
|
|
|
|
|
if got := stmt.Status(math.MaxUint32, false); got != 0 {
|
|
|
|
|
t.Errorf("got %d, want 0", got)
|
|
|
|
|
}
|
2023-02-21 04:30:24 +00:00
|
|
|
}
|
2023-11-24 17:25:02 +00:00
|
|
|
|
2025-03-31 13:02:41 +01:00
|
|
|
func TestStmt_Columns(t *testing.T) {
|
|
|
|
|
db, err := sqlite3.Open(":memory:")
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
defer db.Close()
|
|
|
|
|
|
|
|
|
|
stmt, _, err := db.Prepare(`SELECT 0, 0.5, 'abc', x'cafe', NULL`)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
defer stmt.Close()
|
|
|
|
|
|
2025-07-17 01:11:16 +01:00
|
|
|
if !stmt.Step() {
|
|
|
|
|
t.Fatal(stmt.Err())
|
|
|
|
|
} else {
|
2025-03-31 13:02:41 +01:00
|
|
|
var dest [5]any
|
|
|
|
|
if err := stmt.Columns(dest[:]...); err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
if got := dest[0]; got != int64(0) {
|
|
|
|
|
t.Errorf("got %d, want 0", got)
|
|
|
|
|
}
|
|
|
|
|
if got := dest[1]; got != float64(0.5) {
|
|
|
|
|
t.Errorf("got %f, want 0.5", got)
|
|
|
|
|
}
|
|
|
|
|
if got := dest[2]; got != "abc" {
|
|
|
|
|
t.Errorf("got %q, want 'abc'", got)
|
|
|
|
|
}
|
|
|
|
|
if got := dest[3]; string(got.([]byte)) != "\xCA\xFE" {
|
|
|
|
|
t.Errorf("got %q, want x'cafe'", got)
|
|
|
|
|
}
|
|
|
|
|
if got := dest[4]; got != nil {
|
|
|
|
|
t.Errorf("got %q, want nil", got)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 17:25:02 +00:00
|
|
|
func TestStmt_Error(t *testing.T) {
|
2024-06-26 13:52:38 +01:00
|
|
|
if testing.Short() {
|
|
|
|
|
t.Skip("skipping in short mode")
|
|
|
|
|
}
|
2024-06-05 00:43:49 +01:00
|
|
|
if bits.UintSize < 64 {
|
|
|
|
|
t.Skip("skipping on 32-bit")
|
|
|
|
|
}
|
2023-11-24 17:25:02 +00:00
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
db, err := sqlite3.Open(":memory:")
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
defer db.Close()
|
|
|
|
|
|
|
|
|
|
var blob [1e9 + 1]byte
|
|
|
|
|
|
|
|
|
|
_, _, err = db.Prepare(string(blob[:]))
|
|
|
|
|
if err == nil {
|
|
|
|
|
t.Errorf("want error")
|
|
|
|
|
} else {
|
|
|
|
|
t.Log(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stmt, _, err := db.Prepare(`SELECT ?`)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
defer stmt.Close()
|
|
|
|
|
|
|
|
|
|
err = stmt.BindText(1, string(blob[:]))
|
|
|
|
|
if err == nil {
|
|
|
|
|
t.Errorf("want error")
|
|
|
|
|
} else {
|
|
|
|
|
t.Log(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = stmt.BindBlob(1, blob[:])
|
|
|
|
|
if err == nil {
|
|
|
|
|
t.Errorf("want error")
|
|
|
|
|
} else {
|
|
|
|
|
t.Log(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = stmt.BindRawText(1, blob[:])
|
|
|
|
|
if err == nil {
|
|
|
|
|
t.Errorf("want error")
|
|
|
|
|
} else {
|
|
|
|
|
t.Log(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = stmt.BindZeroBlob(1, 1e9+1)
|
|
|
|
|
if err == nil {
|
|
|
|
|
t.Errorf("want error")
|
|
|
|
|
} else {
|
|
|
|
|
t.Log(err)
|
|
|
|
|
}
|
|
|
|
|
}
|