Files
sqlite3/vtab_test.go

121 lines
2.3 KiB
Go
Raw Permalink Normal View History

2023-11-17 19:06:10 +00:00
package sqlite3_test
import (
2023-11-17 22:39:00 +00:00
"fmt"
2023-11-17 19:06:10 +00:00
"log"
"github.com/ncruces/go-sqlite3"
_ "github.com/ncruces/go-sqlite3/embed"
)
func ExampleCreateModule() {
db, err := sqlite3.Open(":memory:")
if err != nil {
log.Fatal(err)
}
defer db.Close()
2023-11-22 13:11:23 +00:00
err = sqlite3.CreateModule[seriesTable](db, "generate_series", nil,
2023-11-29 00:46:27 +00:00
func(db *sqlite3.Conn, module, schema, table string, arg ...string) (seriesTable, error) {
2024-01-08 19:23:32 +00:00
err := db.DeclareVTab(`CREATE TABLE x(value, start HIDDEN, stop HIDDEN, step HIDDEN)`)
2023-11-22 13:11:23 +00:00
return seriesTable{}, err
})
2023-11-17 19:06:10 +00:00
if err != nil {
log.Fatal(err)
}
2023-11-17 22:39:00 +00:00
stmt, _, err := db.Prepare(`SELECT rowid, value FROM generate_series(2, 10, 3)`)
2023-11-17 19:06:10 +00:00
if err != nil {
log.Fatal(err)
}
defer stmt.Close()
2023-11-17 22:39:00 +00:00
for stmt.Step() {
fmt.Println(stmt.ColumnInt(0), stmt.ColumnInt(1))
}
if err := stmt.Err(); err != nil {
log.Fatal(err)
}
2023-11-17 19:06:10 +00:00
// Output:
2023-11-17 22:39:00 +00:00
// 2 2
// 5 5
// 8 8
2023-11-17 19:06:10 +00:00
}
2023-11-20 13:37:25 +00:00
type seriesTable struct{}
2023-11-17 19:06:10 +00:00
2023-11-20 13:37:25 +00:00
func (seriesTable) BestIndex(idx *sqlite3.IndexInfo) error {
2023-11-17 19:06:10 +00:00
for i, cst := range idx.Constraint {
2023-11-20 13:37:25 +00:00
switch cst.Column {
case 1, 2, 3: // start, stop, step
if cst.Op == sqlite3.INDEX_CONSTRAINT_EQ && cst.Usable {
idx.ConstraintUsage[i] = sqlite3.IndexConstraintUsage{
ArgvIndex: cst.Column,
Omit: true,
}
2023-11-17 19:06:10 +00:00
}
}
}
2023-11-23 09:54:18 +00:00
idx.IdxNum = 1
idx.IdxStr = "idx"
2023-11-17 19:06:10 +00:00
return nil
}
2023-11-20 13:37:25 +00:00
func (seriesTable) Open() (sqlite3.VTabCursor, error) {
return &seriesCursor{}, nil
2023-11-17 22:39:00 +00:00
}
type seriesCursor struct {
2023-11-20 13:37:25 +00:00
start int64
stop int64
step int64
2023-11-17 22:39:00 +00:00
value int64
}
func (cur *seriesCursor) Filter(idxNum int, idxStr string, arg ...sqlite3.Value) error {
2023-11-23 09:54:18 +00:00
if idxNum != 1 || idxStr != "idx" {
return nil
}
2023-11-20 13:37:25 +00:00
cur.start = 0
cur.stop = 1000
cur.step = 1
if len(arg) > 0 {
cur.start = arg[0].Int64()
}
if len(arg) > 1 {
cur.stop = arg[1].Int64()
}
if len(arg) > 2 {
cur.step = arg[2].Int64()
2023-11-17 22:39:00 +00:00
}
2023-11-20 13:37:25 +00:00
cur.value = cur.start
2023-11-17 22:39:00 +00:00
return nil
}
func (cur *seriesCursor) Column(ctx *sqlite3.Context, col int) error {
switch col {
case 0:
ctx.ResultInt64(cur.value)
case 1:
ctx.ResultInt64(cur.start)
case 2:
ctx.ResultInt64(cur.stop)
case 3:
ctx.ResultInt64(cur.step)
}
return nil
}
func (cur *seriesCursor) Next() error {
cur.value += cur.step
return nil
}
func (cur *seriesCursor) EOF() bool {
return cur.value > cur.stop
}
func (cur *seriesCursor) RowID() (int64, error) {
return int64(cur.value), nil
}