Skip to content

Commit

Permalink
Coverage, docs.
Browse files Browse the repository at this point in the history
  • Loading branch information
ncruces committed Sep 22, 2024
1 parent 2526fc8 commit 44c3f9b
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 31 deletions.
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ as well as direct access to most of the [C SQLite API](https://sqlite.org/cintro

It wraps a [Wasm](https://webassembly.org/) [build](embed/) of SQLite,
and uses [wazero](https://wazero.io/) as the runtime.\
Go, wazero and [`x/sys`](https://pkg.go.dev/golang.org/x/sys) are the _only_ runtime dependencies [^1].
Go, wazero and [`x/sys`](https://pkg.go.dev/golang.org/x/sys) are the _only_ runtime dependencies.

### Getting started

Expand Down Expand Up @@ -49,6 +49,8 @@ db.QueryRow(`SELECT sqlite_version()`).Scan(&version)
simplifies [incremental BLOB I/O](https://sqlite.org/c3ref/blob_open.html).
- [`github.com/ncruces/go-sqlite3/ext/bloom`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/bloom)
provides a [Bloom filter](https://github.com/nalgeon/sqlean/issues/27#issuecomment-1002267134) virtual table.
- [`github.com/ncruces/go-sqlite3/ext/closure`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/closure)
provides a transitive closure virtual table.
- [`github.com/ncruces/go-sqlite3/ext/csv`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/csv)
reads [comma-separated values](https://sqlite.org/csv.html).
- [`github.com/ncruces/go-sqlite3/ext/fileio`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/fileio)
Expand Down Expand Up @@ -128,7 +130,4 @@ The Wasm and VFS layers are also tested by running SQLite's
- [`modernc.org/sqlite`](https://pkg.go.dev/modernc.org/sqlite)
- [`crawshaw.io/sqlite`](https://pkg.go.dev/crawshaw.io/sqlite)
- [`github.com/mattn/go-sqlite3`](https://pkg.go.dev/github.com/mattn/go-sqlite3)
- [`github.com/zombiezen/go-sqlite`](https://pkg.go.dev/github.com/zombiezen/go-sqlite)

[^1]: anything else you find in `go.mod` is either a test dependency,
or needed by one of the extensions.
- [`github.com/zombiezen/go-sqlite`](https://pkg.go.dev/github.com/zombiezen/go-sqlite)
4 changes: 0 additions & 4 deletions ext/bloom/bloom.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,6 @@ type cursor struct {
}

func (c *cursor) Filter(idxNum int, idxStr string, arg ...sqlite3.Value) error {
if len(arg) != 1 {
return nil
}

c.eof = false
c.arg = &arg[0]
blob := arg[0].RawBlob()
Expand Down
25 changes: 9 additions & 16 deletions ext/closure/closure.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Package closure provides a transitive closure virtual table.
//
// The "transitive_closure" virtual table finds the transitive closure of
// The transitive_closure virtual table finds the transitive closure of
// a parent/child relationship in a real table.
//
// https://sqlite.org/src/doc/tip/ext/misc/closure.c
Expand All @@ -24,6 +24,9 @@ const (
_COL_PARENTCOLUMN = 5
)

// Register registers the transitive_closure virtual table:
//
// CREATE VIRTUAL TABLE temp.closure USING transitive_closure;
func Register(db *sqlite3.Conn) error {
return sqlite3.CreateModule(db, "transitive_closure", nil,
func(db *sqlite3.Conn, _, _, _ string, arg ...string) (*closure, error) {
Expand Down Expand Up @@ -76,9 +79,9 @@ type closure struct {
func (c *closure) Destroy() error { return nil }

func (c *closure) BestIndex(idx *sqlite3.IndexInfo) error {
posi := 1
plan := 0
cost := 10000000.0
posi := 1
cost := 1e7

for i, cst := range idx.Constraint {
if !cst.Usable {
Expand Down Expand Up @@ -140,17 +143,11 @@ func (c *closure) BestIndex(idx *sqlite3.IndexInfo) error {
}
}

if c.table == "" && plan&0xf00 == 0 ||
if plan&1 == 0 ||
c.table == "" && plan&0xf00 == 0 ||
c.column == "" && plan&0xf000 == 0 ||
c.parent == "" && plan&0xf0000 == 0 {
plan = 0
}
if plan&1 == 0 {
plan = 0
cost *= 1e30
for i := range idx.Constraint {
idx.ConstraintUsage[i].ArgvIndex = 0
}
return sqlite3.CONSTRAINT
}

idx.EstimatedCost = cost
Expand All @@ -173,10 +170,6 @@ type node struct {
}

func (c *cursor) Filter(idxNum int, idxStr string, arg ...sqlite3.Value) error {
if idxNum&1 == 0 {
return nil
}

root := arg[0].Int64()
maxDepth := math.MaxInt
if idxNum&0xf0 != 0 {
Expand Down
32 changes: 32 additions & 0 deletions ext/closure/closure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ func Example() {
}
defer db.Close()

closure.Register(db)

err = db.Exec(`
CREATE TABLE employees (
id INTEGER PRIMARY KEY,
Expand Down Expand Up @@ -150,3 +152,33 @@ func TestRegister(t *testing.T) {
t.Fatal(err)
}
}

func Test_errors(t *testing.T) {
t.Parallel()

db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()

err = db.Exec(`CREATE VIRTUAL TABLE hierarchy USING transitive_closure(table='employees')`)
if err == nil {
t.Error("want error")
}

err = db.Exec(`CREATE VIRTUAL TABLE hierarchy USING transitive_closure(tablename='employees', tablename="employees")`)
if err == nil {
t.Error("want error")
}

err = db.Exec("CREATE VIRTUAL TABLE hierarchy USING transitive_closure(tablename=`employees`)")
if err != nil {
t.Error(err)
}

err = db.Exec(`SELECT * FROM hierarchy`)
if err == nil {
t.Error("want error")
}
}
21 changes: 15 additions & 6 deletions ext/fileio/fsdir.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,22 @@ import (
"github.com/ncruces/go-sqlite3"
)

const (
_COL_NAME = 0
_COL_MODE = 1
_COL_TIME = 2
_COL_DATA = 3
_COL_ROOT = 4
_COL_BASE = 5
)

type fsdir struct{ fsys fs.FS }

func (d fsdir) BestIndex(idx *sqlite3.IndexInfo) error {
var root, base bool
for i, cst := range idx.Constraint {
switch cst.Column {
case 4: // root
case _COL_ROOT:
if !cst.Usable || cst.Op != sqlite3.INDEX_CONSTRAINT_EQ {
return sqlite3.CONSTRAINT
}
Expand All @@ -25,7 +34,7 @@ func (d fsdir) BestIndex(idx *sqlite3.IndexInfo) error {
ArgvIndex: 1,
}
root = true
case 5: // base
case _COL_BASE:
if !cst.Usable || cst.Op != sqlite3.INDEX_CONSTRAINT_EQ {
return sqlite3.CONSTRAINT
}
Expand Down Expand Up @@ -116,25 +125,25 @@ func (c *cursor) RowID() (int64, error) {

func (c *cursor) Column(ctx sqlite3.Context, n int) error {
switch n {
case 0: // name
case _COL_NAME:
name := strings.TrimPrefix(c.curr.path, c.base)
ctx.ResultText(name)

case 1: // mode
case _COL_MODE:
i, err := c.curr.Info()
if err != nil {
return err
}
ctx.ResultInt64(int64(i.Mode()))

case 2: // mtime
case _COL_TIME:
i, err := c.curr.Info()
if err != nil {
return err
}
ctx.ResultTime(i.ModTime(), sqlite3.TimeFormatUnixFrac)

case 3: // data
case _COL_DATA:
switch typ := c.curr.Type(); {
case typ.IsRegular():
var data []byte
Expand Down
2 changes: 2 additions & 0 deletions util/vtabutil/arg.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ func Unquote(val string) string {
return val
case '"':
old, new = `""`, `"`
case '`':
old, new = "``", "`"
case '\'':
old, new = `''`, `'`
}
Expand Down

0 comments on commit 44c3f9b

Please sign in to comment.