diff options
author | 2025-03-09 17:47:56 +0100 | |
---|---|---|
committer | 2025-03-10 01:59:49 +0100 | |
commit | 3ac1ee16f377d31a0fb80c8dae28b6239ac4229e (patch) | |
tree | f61faa581feaaeaba2542b9f2b8234a590684413 /vendor/github.com/ncruces/go-sqlite3/vtab.go | |
parent | [chore] update URLs to forked source (diff) | |
download | gotosocial-3ac1ee16f377d31a0fb80c8dae28b6239ac4229e.tar.xz |
[chore] remove vendor
Diffstat (limited to 'vendor/github.com/ncruces/go-sqlite3/vtab.go')
-rw-r--r-- | vendor/github.com/ncruces/go-sqlite3/vtab.go | 682 |
1 files changed, 0 insertions, 682 deletions
diff --git a/vendor/github.com/ncruces/go-sqlite3/vtab.go b/vendor/github.com/ncruces/go-sqlite3/vtab.go deleted file mode 100644 index 278195e92..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vtab.go +++ /dev/null @@ -1,682 +0,0 @@ -package sqlite3 - -import ( - "context" - "errors" - "reflect" - - "github.com/tetratelabs/wazero/api" - - "github.com/ncruces/go-sqlite3/internal/util" -) - -// CreateModule registers a new virtual table module name. -// If create is nil, the virtual table is eponymous. -// -// https://sqlite.org/c3ref/create_module.html -func CreateModule[T VTab](db *Conn, name string, create, connect VTabConstructor[T]) error { - var flags int - - const ( - VTAB_CREATOR = 0x001 - VTAB_DESTROYER = 0x002 - VTAB_UPDATER = 0x004 - VTAB_RENAMER = 0x008 - VTAB_OVERLOADER = 0x010 - VTAB_CHECKER = 0x020 - VTAB_TXN = 0x040 - VTAB_SAVEPOINTER = 0x080 - VTAB_SHADOWTABS = 0x100 - ) - - if create != nil { - flags |= VTAB_CREATOR - } - - vtab := reflect.TypeOf(connect).Out(0) - if implements[VTabDestroyer](vtab) { - flags |= VTAB_DESTROYER - } - if implements[VTabUpdater](vtab) { - flags |= VTAB_UPDATER - } - if implements[VTabRenamer](vtab) { - flags |= VTAB_RENAMER - } - if implements[VTabOverloader](vtab) { - flags |= VTAB_OVERLOADER - } - if implements[VTabChecker](vtab) { - flags |= VTAB_CHECKER - } - if implements[VTabTxn](vtab) { - flags |= VTAB_TXN - } - if implements[VTabSavepointer](vtab) { - flags |= VTAB_SAVEPOINTER - } - if implements[VTabShadowTabler](vtab) { - flags |= VTAB_SHADOWTABS - } - - var modulePtr ptr_t - defer db.arena.mark()() - namePtr := db.arena.string(name) - if connect != nil { - modulePtr = util.AddHandle(db.ctx, module[T]{create, connect}) - } - rc := res_t(db.call("sqlite3_create_module_go", stk_t(db.handle), - stk_t(namePtr), stk_t(flags), stk_t(modulePtr))) - return db.error(rc) -} - -func implements[T any](typ reflect.Type) bool { - var ptr *T - return typ.Implements(reflect.TypeOf(ptr).Elem()) -} - -// DeclareVTab declares the schema of a virtual table. -// -// https://sqlite.org/c3ref/declare_vtab.html -func (c *Conn) DeclareVTab(sql string) error { - defer c.arena.mark()() - sqlPtr := c.arena.string(sql) - rc := res_t(c.call("sqlite3_declare_vtab", stk_t(c.handle), stk_t(sqlPtr))) - return c.error(rc) -} - -// VTabConflictMode is a virtual table conflict resolution mode. -// -// https://sqlite.org/c3ref/c_fail.html -type VTabConflictMode uint8 - -const ( - VTAB_ROLLBACK VTabConflictMode = 1 - VTAB_IGNORE VTabConflictMode = 2 - VTAB_FAIL VTabConflictMode = 3 - VTAB_ABORT VTabConflictMode = 4 - VTAB_REPLACE VTabConflictMode = 5 -) - -// VTabOnConflict determines the virtual table conflict policy. -// -// https://sqlite.org/c3ref/vtab_on_conflict.html -func (c *Conn) VTabOnConflict() VTabConflictMode { - return VTabConflictMode(c.call("sqlite3_vtab_on_conflict", stk_t(c.handle))) -} - -// VTabConfigOption is a virtual table configuration option. -// -// https://sqlite.org/c3ref/c_vtab_constraint_support.html -type VTabConfigOption uint8 - -const ( - VTAB_CONSTRAINT_SUPPORT VTabConfigOption = 1 - VTAB_INNOCUOUS VTabConfigOption = 2 - VTAB_DIRECTONLY VTabConfigOption = 3 - VTAB_USES_ALL_SCHEMAS VTabConfigOption = 4 -) - -// VTabConfig configures various facets of the virtual table interface. -// -// https://sqlite.org/c3ref/vtab_config.html -func (c *Conn) VTabConfig(op VTabConfigOption, args ...any) error { - var i int32 - if op == VTAB_CONSTRAINT_SUPPORT && len(args) > 0 { - if b, ok := args[0].(bool); ok && b { - i = 1 - } - } - rc := res_t(c.call("sqlite3_vtab_config_go", stk_t(c.handle), stk_t(op), stk_t(i))) - return c.error(rc) -} - -// VTabConstructor is a virtual table constructor function. -type VTabConstructor[T VTab] func(db *Conn, module, schema, table string, arg ...string) (T, error) - -type module[T VTab] [2]VTabConstructor[T] - -type vtabConstructor int - -const ( - xCreate vtabConstructor = 0 - xConnect vtabConstructor = 1 -) - -// A VTab describes a particular instance of the virtual table. -// A VTab may optionally implement [io.Closer] to free resources. -// -// https://sqlite.org/c3ref/vtab.html -type VTab interface { - // https://sqlite.org/vtab.html#xbestindex - BestIndex(*IndexInfo) error - // https://sqlite.org/vtab.html#xopen - Open() (VTabCursor, error) -} - -// A VTabDestroyer allows a virtual table to drop persistent state. -type VTabDestroyer interface { - VTab - // https://sqlite.org/vtab.html#sqlite3_module.xDestroy - Destroy() error -} - -// A VTabUpdater allows a virtual table to be updated. -type VTabUpdater interface { - VTab - // https://sqlite.org/vtab.html#xupdate - Update(arg ...Value) (rowid int64, err error) -} - -// A VTabRenamer allows a virtual table to be renamed. -type VTabRenamer interface { - VTab - // https://sqlite.org/vtab.html#xrename - Rename(new string) error -} - -// A VTabOverloader allows a virtual table to overload SQL functions. -type VTabOverloader interface { - VTab - // https://sqlite.org/vtab.html#xfindfunction - FindFunction(arg int, name string) (ScalarFunction, IndexConstraintOp) -} - -// A VTabShadowTabler allows a virtual table to protect the content -// of shadow tables from being corrupted by hostile SQL. -// -// Implementing this interface signals that a virtual table named -// "mumble" reserves all table names starting with "mumble_". -type VTabShadowTabler interface { - VTab - // https://sqlite.org/vtab.html#the_xshadowname_method - ShadowTables() -} - -// A VTabChecker allows a virtual table to report errors -// to the PRAGMA integrity_check and PRAGMA quick_check commands. -// -// Integrity should return an error if it finds problems in the content of the virtual table, -// but should avoid returning a (wrapped) [Error], [ErrorCode] or [ExtendedErrorCode], -// as those indicate the Integrity method itself encountered problems -// while trying to evaluate the virtual table content. -type VTabChecker interface { - VTab - // https://sqlite.org/vtab.html#xintegrity - Integrity(schema, table string, flags int) error -} - -// A VTabTxn allows a virtual table to implement -// transactions with two-phase commit. -// -// Anything that is required as part of a commit that may fail -// should be performed in the Sync() callback. -// Current versions of SQLite ignore any errors -// returned by Commit() and Rollback(). -type VTabTxn interface { - VTab - // https://sqlite.org/vtab.html#xBegin - Begin() error - // https://sqlite.org/vtab.html#xsync - Sync() error - // https://sqlite.org/vtab.html#xcommit - Commit() error - // https://sqlite.org/vtab.html#xrollback - Rollback() error -} - -// A VTabSavepointer allows a virtual table to implement -// nested transactions. -// -// https://sqlite.org/vtab.html#xsavepoint -type VTabSavepointer interface { - VTabTxn - Savepoint(id int) error - Release(id int) error - RollbackTo(id int) error -} - -// A VTabCursor describes cursors that point -// into the virtual table and are used -// to loop through the virtual table. -// A VTabCursor may optionally implement -// [io.Closer] to free resources. -// -// https://sqlite.org/c3ref/vtab_cursor.html -type VTabCursor interface { - // https://sqlite.org/vtab.html#xfilter - Filter(idxNum int, idxStr string, arg ...Value) error - // https://sqlite.org/vtab.html#xnext - Next() error - // https://sqlite.org/vtab.html#xeof - EOF() bool - // https://sqlite.org/vtab.html#xcolumn - Column(ctx Context, n int) error - // https://sqlite.org/vtab.html#xrowid - RowID() (int64, error) -} - -// An IndexInfo describes virtual table indexing information. -// -// https://sqlite.org/c3ref/index_info.html -type IndexInfo struct { - // Inputs - Constraint []IndexConstraint - OrderBy []IndexOrderBy - ColumnsUsed uint64 - // Outputs - ConstraintUsage []IndexConstraintUsage - IdxNum int - IdxStr string - IdxFlags IndexScanFlag - OrderByConsumed bool - EstimatedCost float64 - EstimatedRows int64 - // Internal - c *Conn - handle ptr_t -} - -// An IndexConstraint describes virtual table indexing constraint information. -// -// https://sqlite.org/c3ref/index_info.html -type IndexConstraint struct { - Column int - Op IndexConstraintOp - Usable bool -} - -// An IndexOrderBy describes virtual table indexing order by information. -// -// https://sqlite.org/c3ref/index_info.html -type IndexOrderBy struct { - Column int - Desc bool -} - -// An IndexConstraintUsage describes how virtual table indexing constraints will be used. -// -// https://sqlite.org/c3ref/index_info.html -type IndexConstraintUsage struct { - ArgvIndex int - Omit bool -} - -// RHSValue returns the value of the right-hand operand of a constraint -// if the right-hand operand is known. -// -// https://sqlite.org/c3ref/vtab_rhs_value.html -func (idx *IndexInfo) RHSValue(column int) (Value, error) { - defer idx.c.arena.mark()() - valPtr := idx.c.arena.new(ptrlen) - rc := res_t(idx.c.call("sqlite3_vtab_rhs_value", stk_t(idx.handle), - stk_t(column), stk_t(valPtr))) - if err := idx.c.error(rc); err != nil { - return Value{}, err - } - return Value{ - c: idx.c, - handle: util.Read32[ptr_t](idx.c.mod, valPtr), - }, nil -} - -// Collation returns the name of the collation for a virtual table constraint. -// -// https://sqlite.org/c3ref/vtab_collation.html -func (idx *IndexInfo) Collation(column int) string { - ptr := ptr_t(idx.c.call("sqlite3_vtab_collation", stk_t(idx.handle), - stk_t(column))) - return util.ReadString(idx.c.mod, ptr, _MAX_NAME) -} - -// Distinct determines if a virtual table query is DISTINCT. -// -// https://sqlite.org/c3ref/vtab_distinct.html -func (idx *IndexInfo) Distinct() int { - i := int32(idx.c.call("sqlite3_vtab_distinct", stk_t(idx.handle))) - return int(i) -} - -// In identifies and handles IN constraints. -// -// https://sqlite.org/c3ref/vtab_in.html -func (idx *IndexInfo) In(column, handle int) bool { - b := int32(idx.c.call("sqlite3_vtab_in", stk_t(idx.handle), - stk_t(column), stk_t(handle))) - return b != 0 -} - -func (idx *IndexInfo) load() { - // https://sqlite.org/c3ref/index_info.html - mod := idx.c.mod - ptr := idx.handle - - nConstraint := util.Read32[int32](mod, ptr+0) - idx.Constraint = make([]IndexConstraint, nConstraint) - idx.ConstraintUsage = make([]IndexConstraintUsage, nConstraint) - idx.OrderBy = make([]IndexOrderBy, util.Read32[int32](mod, ptr+8)) - - constraintPtr := util.Read32[ptr_t](mod, ptr+4) - constraint := idx.Constraint - for i := range idx.Constraint { - constraint[i] = IndexConstraint{ - Column: int(util.Read32[int32](mod, constraintPtr+0)), - Op: util.Read[IndexConstraintOp](mod, constraintPtr+4), - Usable: util.Read[byte](mod, constraintPtr+5) != 0, - } - constraintPtr += 12 - } - - orderByPtr := util.Read32[ptr_t](mod, ptr+12) - orderBy := idx.OrderBy - for i := range orderBy { - orderBy[i] = IndexOrderBy{ - Column: int(util.Read32[int32](mod, orderByPtr+0)), - Desc: util.Read[byte](mod, orderByPtr+4) != 0, - } - orderByPtr += 8 - } - - idx.EstimatedCost = util.ReadFloat64(mod, ptr+40) - idx.EstimatedRows = util.Read64[int64](mod, ptr+48) - idx.ColumnsUsed = util.Read64[uint64](mod, ptr+64) -} - -func (idx *IndexInfo) save() { - // https://sqlite.org/c3ref/index_info.html - mod := idx.c.mod - ptr := idx.handle - - usagePtr := util.Read32[ptr_t](mod, ptr+16) - for _, usage := range idx.ConstraintUsage { - util.Write32(mod, usagePtr+0, int32(usage.ArgvIndex)) - if usage.Omit { - util.Write(mod, usagePtr+4, int8(1)) - } - usagePtr += 8 - } - - util.Write32(mod, ptr+20, int32(idx.IdxNum)) - if idx.IdxStr != "" { - util.Write32(mod, ptr+24, idx.c.newString(idx.IdxStr)) - util.Write32(mod, ptr+28, int32(1)) // needToFreeIdxStr - } - if idx.OrderByConsumed { - util.Write32(mod, ptr+32, int32(1)) - } - util.WriteFloat64(mod, ptr+40, idx.EstimatedCost) - util.Write64(mod, ptr+48, idx.EstimatedRows) - util.Write32(mod, ptr+56, idx.IdxFlags) -} - -// IndexConstraintOp is a virtual table constraint operator code. -// -// https://sqlite.org/c3ref/c_index_constraint_eq.html -type IndexConstraintOp uint8 - -const ( - INDEX_CONSTRAINT_EQ IndexConstraintOp = 2 - INDEX_CONSTRAINT_GT IndexConstraintOp = 4 - INDEX_CONSTRAINT_LE IndexConstraintOp = 8 - INDEX_CONSTRAINT_LT IndexConstraintOp = 16 - INDEX_CONSTRAINT_GE IndexConstraintOp = 32 - INDEX_CONSTRAINT_MATCH IndexConstraintOp = 64 - INDEX_CONSTRAINT_LIKE IndexConstraintOp = 65 - INDEX_CONSTRAINT_GLOB IndexConstraintOp = 66 - INDEX_CONSTRAINT_REGEXP IndexConstraintOp = 67 - INDEX_CONSTRAINT_NE IndexConstraintOp = 68 - INDEX_CONSTRAINT_ISNOT IndexConstraintOp = 69 - INDEX_CONSTRAINT_ISNOTNULL IndexConstraintOp = 70 - INDEX_CONSTRAINT_ISNULL IndexConstraintOp = 71 - INDEX_CONSTRAINT_IS IndexConstraintOp = 72 - INDEX_CONSTRAINT_LIMIT IndexConstraintOp = 73 - INDEX_CONSTRAINT_OFFSET IndexConstraintOp = 74 - INDEX_CONSTRAINT_FUNCTION IndexConstraintOp = 150 -) - -// IndexScanFlag is a virtual table scan flag. -// -// https://sqlite.org/c3ref/c_index_scan_unique.html -type IndexScanFlag uint32 - -const ( - INDEX_SCAN_UNIQUE IndexScanFlag = 1 -) - -func vtabModuleCallback(i vtabConstructor) func(_ context.Context, _ api.Module, _ ptr_t, _ int32, _, _, _ ptr_t) res_t { - return func(ctx context.Context, mod api.Module, pMod ptr_t, nArg int32, pArg, ppVTab, pzErr ptr_t) res_t { - arg := make([]reflect.Value, 1+nArg) - arg[0] = reflect.ValueOf(ctx.Value(connKey{})) - - for i := range nArg { - ptr := util.Read32[ptr_t](mod, pArg+ptr_t(i)*ptrlen) - arg[i+1] = reflect.ValueOf(util.ReadString(mod, ptr, _MAX_SQL_LENGTH)) - } - - module := vtabGetHandle(ctx, mod, pMod) - val := reflect.ValueOf(module).Index(int(i)).Call(arg) - err, _ := val[1].Interface().(error) - if err == nil { - vtabPutHandle(ctx, mod, ppVTab, val[0].Interface()) - } - - return vtabError(ctx, mod, pzErr, _PTR_ERROR, err) - } -} - -func vtabDisconnectCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t { - err := vtabDelHandle(ctx, mod, pVTab) - return vtabError(ctx, mod, 0, _PTR_ERROR, err) -} - -func vtabDestroyCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabDestroyer) - err := errors.Join(vtab.Destroy(), vtabDelHandle(ctx, mod, pVTab)) - return vtabError(ctx, mod, 0, _PTR_ERROR, err) -} - -func vtabBestIndexCallback(ctx context.Context, mod api.Module, pVTab, pIdxInfo ptr_t) res_t { - var info IndexInfo - info.handle = pIdxInfo - info.c = ctx.Value(connKey{}).(*Conn) - info.load() - - vtab := vtabGetHandle(ctx, mod, pVTab).(VTab) - err := vtab.BestIndex(&info) - - info.save() - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func vtabUpdateCallback(ctx context.Context, mod api.Module, pVTab ptr_t, nArg int32, pArg, pRowID ptr_t) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabUpdater) - - db := ctx.Value(connKey{}).(*Conn) - args := make([]Value, nArg) - callbackArgs(db, args, pArg) - rowID, err := vtab.Update(args...) - if err == nil { - util.Write64(mod, pRowID, rowID) - } - - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func vtabRenameCallback(ctx context.Context, mod api.Module, pVTab, zNew ptr_t) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabRenamer) - err := vtab.Rename(util.ReadString(mod, zNew, _MAX_NAME)) - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func vtabFindFuncCallback(ctx context.Context, mod api.Module, pVTab ptr_t, nArg int32, zName, pxFunc ptr_t) int32 { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabOverloader) - f, op := vtab.FindFunction(int(nArg), util.ReadString(mod, zName, _MAX_NAME)) - if op != 0 { - var wrapper ptr_t - wrapper = util.AddHandle(ctx, func(c Context, arg ...Value) { - defer util.DelHandle(ctx, wrapper) - f(c, arg...) - }) - util.Write32(mod, pxFunc, wrapper) - } - return int32(op) -} - -func vtabIntegrityCallback(ctx context.Context, mod api.Module, pVTab, zSchema, zTabName ptr_t, mFlags uint32, pzErr ptr_t) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabChecker) - schema := util.ReadString(mod, zSchema, _MAX_NAME) - table := util.ReadString(mod, zTabName, _MAX_NAME) - err := vtab.Integrity(schema, table, int(mFlags)) - // xIntegrity should return OK - even if it finds problems in the content of the virtual table. - // https://sqlite.org/vtab.html#xintegrity - vtabError(ctx, mod, pzErr, _PTR_ERROR, err) - _, code := errorCode(err, _OK) - return code -} - -func vtabBeginCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn) - err := vtab.Begin() - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func vtabSyncCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn) - err := vtab.Sync() - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func vtabCommitCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn) - err := vtab.Commit() - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func vtabRollbackCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn) - err := vtab.Rollback() - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func vtabSavepointCallback(ctx context.Context, mod api.Module, pVTab ptr_t, id int32) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabSavepointer) - err := vtab.Savepoint(int(id)) - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func vtabReleaseCallback(ctx context.Context, mod api.Module, pVTab ptr_t, id int32) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabSavepointer) - err := vtab.Release(int(id)) - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func vtabRollbackToCallback(ctx context.Context, mod api.Module, pVTab ptr_t, id int32) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabSavepointer) - err := vtab.RollbackTo(int(id)) - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func cursorOpenCallback(ctx context.Context, mod api.Module, pVTab, ppCur ptr_t) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTab) - - cursor, err := vtab.Open() - if err == nil { - vtabPutHandle(ctx, mod, ppCur, cursor) - } - - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func cursorCloseCallback(ctx context.Context, mod api.Module, pCur ptr_t) res_t { - err := vtabDelHandle(ctx, mod, pCur) - return vtabError(ctx, mod, 0, _VTAB_ERROR, err) -} - -func cursorFilterCallback(ctx context.Context, mod api.Module, pCur ptr_t, idxNum int32, idxStr ptr_t, nArg int32, pArg ptr_t) res_t { - cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor) - db := ctx.Value(connKey{}).(*Conn) - args := make([]Value, nArg) - callbackArgs(db, args, pArg) - var idxName string - if idxStr != 0 { - idxName = util.ReadString(mod, idxStr, _MAX_LENGTH) - } - err := cursor.Filter(int(idxNum), idxName, args...) - return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err) -} - -func cursorEOFCallback(ctx context.Context, mod api.Module, pCur ptr_t) int32 { - cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor) - if cursor.EOF() { - return 1 - } - return 0 -} - -func cursorNextCallback(ctx context.Context, mod api.Module, pCur ptr_t) res_t { - cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor) - err := cursor.Next() - return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err) -} - -func cursorColumnCallback(ctx context.Context, mod api.Module, pCur, pCtx ptr_t, n int32) res_t { - cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor) - db := ctx.Value(connKey{}).(*Conn) - err := cursor.Column(Context{db, pCtx}, int(n)) - return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err) -} - -func cursorRowIDCallback(ctx context.Context, mod api.Module, pCur, pRowID ptr_t) res_t { - cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor) - - rowID, err := cursor.RowID() - if err == nil { - util.Write64(mod, pRowID, rowID) - } - - return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err) -} - -const ( - _PTR_ERROR = iota - _VTAB_ERROR - _CURSOR_ERROR -) - -func vtabError(ctx context.Context, mod api.Module, ptr ptr_t, kind uint32, err error) res_t { - const zErrMsgOffset = 8 - msg, code := errorCode(err, ERROR) - if msg != "" && ptr != 0 { - switch kind { - case _VTAB_ERROR: - ptr = ptr + zErrMsgOffset // zErrMsg - case _CURSOR_ERROR: - ptr = util.Read32[ptr_t](mod, ptr) + zErrMsgOffset // pVTab->zErrMsg - } - db := ctx.Value(connKey{}).(*Conn) - if ptr := util.Read32[ptr_t](mod, ptr); ptr != 0 { - db.free(ptr) - } - util.Write32(mod, ptr, db.newString(msg)) - } - return code -} - -func vtabGetHandle(ctx context.Context, mod api.Module, ptr ptr_t) any { - const handleOffset = 4 - handle := util.Read32[ptr_t](mod, ptr-handleOffset) - return util.GetHandle(ctx, handle) -} - -func vtabDelHandle(ctx context.Context, mod api.Module, ptr ptr_t) error { - const handleOffset = 4 - handle := util.Read32[ptr_t](mod, ptr-handleOffset) - return util.DelHandle(ctx, handle) -} - -func vtabPutHandle(ctx context.Context, mod api.Module, pptr ptr_t, val any) { - const handleOffset = 4 - handle := util.AddHandle(ctx, val) - ptr := util.Read32[ptr_t](mod, pptr) - util.Write32(mod, ptr-handleOffset, handle) -} |