mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-12 05:59:14 +00:00
Fixes.
This commit is contained in:
@@ -87,6 +87,9 @@ func create(db *sqlite3.Conn, _, schema, table string, arg ...string) (_ *bloom,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
id := db.LastInsertRowID()
|
||||
defer db.SetLastInsertRowID(id)
|
||||
|
||||
err = db.Exec(fmt.Sprintf(
|
||||
`INSERT INTO %s.%s (rowid, data, p, n, m, k)
|
||||
VALUES (1, zeroblob(%d), %f, %d, %d, %d)`,
|
||||
@@ -163,13 +166,14 @@ func (b *bloom) BestIndex(idx *sqlite3.IndexInfo) error {
|
||||
if cst.Usable && cst.Column == 1 &&
|
||||
cst.Op == sqlite3.INDEX_CONSTRAINT_EQ {
|
||||
idx.ConstraintUsage[n].ArgvIndex = 1
|
||||
idx.OrderByConsumed = true
|
||||
idx.EstimatedRows = 1
|
||||
idx.EstimatedCost = float64(b.hashes)
|
||||
idx.IdxFlags = sqlite3.INDEX_SCAN_UNIQUE
|
||||
return nil
|
||||
}
|
||||
}
|
||||
idx.OrderByConsumed = true
|
||||
idx.EstimatedRows = 1
|
||||
idx.EstimatedCost = float64(b.hashes)
|
||||
idx.IdxFlags = sqlite3.INDEX_SCAN_UNIQUE
|
||||
return nil
|
||||
return sqlite3.CONSTRAINT
|
||||
}
|
||||
|
||||
func (b *bloom) Update(arg ...sqlite3.Value) (rowid int64, err error) {
|
||||
|
||||
@@ -96,7 +96,11 @@ func RegisterFS(db *sqlite3.Conn, fsys fs.FS) {
|
||||
}
|
||||
schema = getSchema(header, columns, row)
|
||||
} else {
|
||||
table.typs = getColumnAffinities(schema)
|
||||
defer func() {
|
||||
if err == nil {
|
||||
table.typs, err = getColumnAffinities(schema)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
err = db.DeclareVTab(schema)
|
||||
|
||||
@@ -17,10 +17,10 @@ const (
|
||||
real affinity = 4
|
||||
)
|
||||
|
||||
func getColumnAffinities(schema string) []affinity {
|
||||
func getColumnAffinities(schema string) ([]affinity, error) {
|
||||
tab, err := vtabutil.Parse(schema)
|
||||
if err != nil {
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
defer tab.Close()
|
||||
|
||||
@@ -29,7 +29,7 @@ func getColumnAffinities(schema string) []affinity {
|
||||
col := tab.Column(i)
|
||||
types[i] = getAffinity(col.Type())
|
||||
}
|
||||
return types
|
||||
return types, nil
|
||||
}
|
||||
|
||||
func getAffinity(declType string) affinity {
|
||||
|
||||
@@ -12,8 +12,13 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
code = 4
|
||||
base = 8
|
||||
_NONE = iota
|
||||
_MEMORY
|
||||
_SYNTAX
|
||||
_UNSUPPORTEDSQL
|
||||
|
||||
codeptr = 4
|
||||
baseptr = 8
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -22,6 +27,7 @@ var (
|
||||
ctx context.Context
|
||||
once sync.Once
|
||||
runtime wazero.Runtime
|
||||
module wazero.CompiledModule
|
||||
)
|
||||
|
||||
// Table holds metadata about a table.
|
||||
@@ -35,32 +41,38 @@ type Table struct {
|
||||
//
|
||||
// [CREATE]: https://sqlite.org/lang_createtable.html
|
||||
// [ALTER TABLE]: https://sqlite.org/lang_altertable.html
|
||||
func Parse(sql string) (*Table, error) {
|
||||
func Parse(sql string) (_ *Table, err error) {
|
||||
once.Do(func() {
|
||||
ctx = context.Background()
|
||||
cfg := wazero.NewRuntimeConfigInterpreter().WithDebugInfoEnabled(false)
|
||||
runtime = wazero.NewRuntimeWithConfig(ctx, cfg)
|
||||
module, err = runtime.CompileModule(ctx, binary)
|
||||
})
|
||||
|
||||
mod, err := runtime.InstantiateWithConfig(ctx, binary, wazero.NewModuleConfig().WithName(""))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if buf, ok := mod.Memory().Read(base, uint32(len(sql))); ok {
|
||||
mod, err := runtime.InstantiateModule(ctx, module, wazero.NewModuleConfig().WithName(""))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if buf, ok := mod.Memory().Read(baseptr, uint32(len(sql))); ok {
|
||||
copy(buf, sql)
|
||||
}
|
||||
r, err := mod.ExportedFunction("sql3parse_table").Call(ctx, base, uint64(len(sql)), code)
|
||||
r, err := mod.ExportedFunction("sql3parse_table").Call(ctx, baseptr, uint64(len(sql)), codeptr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, _ := mod.Memory().ReadUint32Le(code)
|
||||
if c == uint32(_MEMORY) {
|
||||
c, _ := mod.Memory().ReadUint32Le(codeptr)
|
||||
switch c {
|
||||
case _MEMORY:
|
||||
panic(util.OOMErr)
|
||||
}
|
||||
if c != uint32(_NONE) {
|
||||
return nil, ecode(c)
|
||||
case _SYNTAX:
|
||||
return nil, util.ErrorString("sql3parse: invalid syntax")
|
||||
case _UNSUPPORTEDSQL:
|
||||
return nil, util.ErrorString("sql3parse: unsupported SQL")
|
||||
}
|
||||
if r[0] == 0 {
|
||||
return nil, nil
|
||||
@@ -102,6 +114,15 @@ func (t *Table) Column(i int) Column {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Table) string(ptr uint32) string {
|
||||
if ptr == 0 {
|
||||
return ""
|
||||
}
|
||||
off, _ := t.mod.Memory().ReadUint32Le(ptr + 0)
|
||||
len, _ := t.mod.Memory().ReadUint32Le(ptr + 4)
|
||||
return t.sql[off-baseptr : off+len-baseptr]
|
||||
}
|
||||
|
||||
// Column holds metadata about a column.
|
||||
type Column struct {
|
||||
tab *Table
|
||||
@@ -116,30 +137,5 @@ func (c Column) Type() string {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if r[0] == 0 {
|
||||
return ""
|
||||
}
|
||||
off, _ := c.tab.mod.Memory().ReadUint32Le(uint32(r[0]) + 0)
|
||||
len, _ := c.tab.mod.Memory().ReadUint32Le(uint32(r[0]) + 4)
|
||||
return c.tab.sql[off-base : off+len-base]
|
||||
}
|
||||
|
||||
type ecode uint32
|
||||
|
||||
const (
|
||||
_NONE ecode = iota
|
||||
_MEMORY
|
||||
_SYNTAX
|
||||
_UNSUPPORTEDSQL
|
||||
)
|
||||
|
||||
func (e ecode) Error() string {
|
||||
switch e {
|
||||
case _SYNTAX:
|
||||
return "sql3parse: invalid syntax"
|
||||
case _UNSUPPORTEDSQL:
|
||||
return "sql3parse: unsupported SQL"
|
||||
default:
|
||||
panic(util.AssertErr())
|
||||
}
|
||||
return c.tab.string(uint32(r[0]))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user