mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-11 21:49:13 +00:00
Add test.
This commit is contained in:
31
.github/workflows/go.yml
vendored
Normal file
31
.github/workflows/go.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# This workflow will build a golang project
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
|
||||
|
||||
name: Go
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
|
||||
- name: Build
|
||||
run: go build -v ./...
|
||||
|
||||
- name: Test
|
||||
run: go test -v ./...
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -16,5 +16,4 @@
|
||||
tools
|
||||
|
||||
# Project
|
||||
sqlite3/sqlite3*
|
||||
embed/sqlite3.wasm
|
||||
sqlite3/sqlite3*
|
||||
@@ -1,86 +0,0 @@
|
||||
package bench_test
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"crawshaw.io/sqlite"
|
||||
)
|
||||
|
||||
func BenchmarkCrawshaw(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
crawshawTest()
|
||||
}
|
||||
}
|
||||
|
||||
func crawshawTest() {
|
||||
db, err := sqlite.OpenConn(":memory:", 0)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
exec := func(sql string) error {
|
||||
stmt, _, err := db.PrepareTransient(sql)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = stmt.Step()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return stmt.Finalize()
|
||||
}
|
||||
|
||||
err = exec(`CREATE TABLE users (id INTEGER PRIMARY KEY NOT NULL, name VARCHAR, age INTEGER, rating REAL)`)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
func() {
|
||||
const N = 1_000_000
|
||||
|
||||
exec(`BEGIN`)
|
||||
defer exec(`END`)
|
||||
|
||||
stmt, _, err := db.PrepareTransient(`INSERT INTO users (id, name, age, rating) VALUES (?, ?, ?, ?)`)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer stmt.Finalize()
|
||||
|
||||
for i := 0; i < N; i++ {
|
||||
id := i + 1
|
||||
name := "user " + strconv.Itoa(id)
|
||||
age := 33 + id
|
||||
rating := 0.13 * float64(id)
|
||||
stmt.BindInt64(1, int64(id))
|
||||
stmt.BindText(2, name)
|
||||
stmt.BindInt64(3, int64(age))
|
||||
stmt.BindFloat(4, rating)
|
||||
}
|
||||
}()
|
||||
|
||||
func() {
|
||||
stmt, _, err := db.PrepareTransient(`SELECT id, name, age, rating FROM users ORDER BY id`)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer stmt.Finalize()
|
||||
|
||||
for {
|
||||
if row, err := stmt.Step(); err != nil {
|
||||
panic(err)
|
||||
} else if !row {
|
||||
break
|
||||
}
|
||||
id := stmt.ColumnInt(0)
|
||||
name := stmt.ColumnText(1)
|
||||
age := stmt.ColumnInt64(2)
|
||||
rating := stmt.ColumnFloat(3)
|
||||
if id < 1 || len(name) < 5 || age < 33 || rating < 0.13 {
|
||||
panic("wrong row values")
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
package bench_test
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
_ "github.com/ncruces/go-sqlite3/embed"
|
||||
)
|
||||
|
||||
func init() {
|
||||
db, err := sqlite3.Open(":memory:")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = db.Close()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkWasm(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
wasmTest()
|
||||
}
|
||||
}
|
||||
|
||||
func wasmTest() {
|
||||
db, err := sqlite3.Open(":memory:")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
err = db.Exec(`CREATE TABLE users (id INTEGER PRIMARY KEY NOT NULL, name VARCHAR, age INTEGER, rating REAL)`)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
func() {
|
||||
const N = 1_000_000
|
||||
|
||||
db.Exec(`BEGIN`)
|
||||
defer db.Exec(`END`)
|
||||
|
||||
stmt, _, err := db.Prepare(`INSERT INTO users (id, name, age, rating) VALUES (?, ?, ?, ?)`)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
for i := 0; i < N; i++ {
|
||||
id := i + 1
|
||||
name := "user " + strconv.Itoa(id)
|
||||
age := 33 + id
|
||||
rating := 0.13 * float64(id)
|
||||
stmt.BindInt(1, id)
|
||||
stmt.BindText(2, name)
|
||||
stmt.BindInt64(3, int64(age))
|
||||
stmt.BindFloat(4, rating)
|
||||
}
|
||||
}()
|
||||
|
||||
func() {
|
||||
stmt, _, err := db.Prepare(`SELECT id, name, age, rating FROM users ORDER BY id`)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
for stmt.Step() {
|
||||
id := stmt.ColumnInt(0)
|
||||
name := stmt.ColumnText(1)
|
||||
age := stmt.ColumnInt64(2)
|
||||
rating := stmt.ColumnFloat(3)
|
||||
if id < 1 || len(name) < 5 || age < 33 || rating < 0.13 {
|
||||
panic("wrong row values")
|
||||
}
|
||||
}
|
||||
if stmt.Err() != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
@@ -14,7 +14,7 @@ func main() {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = db.Exec(`CREATE TABLE IF NOT EXISTS users (id int, name varchar(10))`)
|
||||
err = db.Exec(`CREATE TABLE IF NOT EXISTS users (id INT, name VARCHAR(10))`)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -32,7 +32,7 @@ func main() {
|
||||
for stmt.Step() {
|
||||
fmt.Println(stmt.ColumnInt(0), stmt.ColumnText(1))
|
||||
}
|
||||
if stmt.Err() != nil {
|
||||
if err := stmt.Err(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
|
||||
76
conn_test.go
Normal file
76
conn_test.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package sqlite3_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
_ "github.com/ncruces/go-sqlite3/embed"
|
||||
)
|
||||
|
||||
func TestOpen_memory(t *testing.T) {
|
||||
testOpen(t, ":memory:")
|
||||
}
|
||||
|
||||
func TestOpen_file(t *testing.T) {
|
||||
dir, err := os.MkdirTemp("", "sqlite3-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
testOpen(t, filepath.Join(dir, "test.db"))
|
||||
}
|
||||
|
||||
func testOpen(t *testing.T, name string) {
|
||||
db, err := sqlite3.Open(name)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
err = db.Exec(`CREATE TABLE IF NOT EXISTS users (id INT, name VARCHAR(10))`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = db.Exec(`INSERT INTO users(id, name) VALUES(0, 'go'), (1, 'zig'), (2, 'whatever')`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
stmt, _, err := db.Prepare(`SELECT id, name FROM users`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ids := []int{0, 1, 2}
|
||||
names := []string{"go", "zig", "whatever"}
|
||||
|
||||
idx := 0
|
||||
for ; stmt.Step(); idx++ {
|
||||
if ids[idx] != stmt.ColumnInt(0) {
|
||||
t.Errorf("expected %d got %d", ids[idx], stmt.ColumnInt(0))
|
||||
}
|
||||
if names[idx] != stmt.ColumnText(1) {
|
||||
t.Errorf("expected %q got %q", names[idx], stmt.ColumnText(1))
|
||||
}
|
||||
}
|
||||
if err := stmt.Err(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if idx != 3 {
|
||||
t.Errorf("expected %d rows got %d", len(ids), idx)
|
||||
}
|
||||
|
||||
err = stmt.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = db.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ cd -P -- "$(dirname -- "$0")"
|
||||
../sqlite3/download.sh
|
||||
|
||||
# build SQLite
|
||||
zig cc --target=wasm32-wasi -flto -g0 -O2 \
|
||||
zig cc --target=wasm32-wasi -flto -g0 -Os \
|
||||
-o sqlite3.wasm ../sqlite3/*.c \
|
||||
-mmutable-globals \
|
||||
-mbulk-memory -mreference-types \
|
||||
|
||||
BIN
embed/sqlite3.wasm
Executable file
BIN
embed/sqlite3.wasm
Executable file
Binary file not shown.
@@ -2,6 +2,7 @@ package sqlite3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
)
|
||||
@@ -70,6 +71,11 @@ type vfsLocker interface {
|
||||
CheckReservedLock() (bool, xErrorCode)
|
||||
}
|
||||
|
||||
type vfsFileLocker struct {
|
||||
*os.File
|
||||
state vfsLockState
|
||||
}
|
||||
|
||||
func vfsLock(ctx context.Context, mod api.Module, pFile uint32, eLock vfsLockState) uint32 {
|
||||
if assert && (eLock == _NO_LOCK || eLock == _PENDING_LOCK) {
|
||||
panic(assertErr + " [d4oxww]")
|
||||
|
||||
@@ -12,11 +12,6 @@ func deleteOnClose(f *os.File) {
|
||||
_ = os.Remove(f.Name())
|
||||
}
|
||||
|
||||
type vfsFileLocker struct {
|
||||
*os.File
|
||||
state vfsLockState
|
||||
}
|
||||
|
||||
func (l *vfsFileLocker) LockState() vfsLockState {
|
||||
return l.state
|
||||
}
|
||||
|
||||
@@ -1,5 +1,46 @@
|
||||
package sqlite3
|
||||
|
||||
import "os"
|
||||
|
||||
func deleteOnClose(f *os.File) {}
|
||||
|
||||
type vfsFileLocker = vfsNoopLocker
|
||||
func (l *vfsFileLocker) LockState() vfsLockState {
|
||||
return l.state
|
||||
}
|
||||
|
||||
func (l *vfsFileLocker) LockShared() xErrorCode {
|
||||
l.state = _SHARED_LOCK
|
||||
return _OK
|
||||
}
|
||||
|
||||
func (l *vfsFileLocker) LockReserved() xErrorCode {
|
||||
l.state = _RESERVED_LOCK
|
||||
return _OK
|
||||
}
|
||||
|
||||
func (l *vfsFileLocker) LockPending() xErrorCode {
|
||||
l.state = _PENDING_LOCK
|
||||
return _OK
|
||||
}
|
||||
|
||||
func (l *vfsFileLocker) LockExclusive() xErrorCode {
|
||||
l.state = _EXCLUSIVE_LOCK
|
||||
return _OK
|
||||
}
|
||||
|
||||
func (l *vfsFileLocker) DowngradeLock() xErrorCode {
|
||||
l.state = _SHARED_LOCK
|
||||
return _OK
|
||||
}
|
||||
|
||||
func (l *vfsFileLocker) Unlock() xErrorCode {
|
||||
l.state = _NO_LOCK
|
||||
return _OK
|
||||
}
|
||||
|
||||
func (l *vfsFileLocker) CheckReservedLock() (bool, xErrorCode) {
|
||||
if l.state >= _RESERVED_LOCK {
|
||||
return true, _OK
|
||||
}
|
||||
return false, _OK
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user