Files
sift/vendor/modernc.org/sqlite/lib/sqlite_g_000000000001deab.go
T
kyle 2f9d3d97e6 p2: digest with in-sift FIFO, SQLite caches, Honcho context, recover
Dixie is capped (max_inflight 2, queue_depth 8, queue_wait 20s) and
never queued on llama-server. Streaming chat, thinking off, 45s
fallback to clean. Digest and chunk-embedding caches are
content-addressed SQLite (Honcho context is not cached). Recover
uses the guarded Fetcher. guardian-star is refused in code.
2026-09-22 23:54:49 -07:00

6017 lines
261 KiB
Go

// Code generated by modernc.org/undup from the per-target sqlite_*.go files; DO NOT EDIT.
//go:build (darwin && amd64) || (darwin && arm64) || (freebsd && amd64) || (freebsd && arm64) || (linux && amd64) || (linux && arm64) || (linux && loong64) || (linux && ppc64le) || (linux && riscv64) || (netbsd && amd64) || (openbsd && amd64) || (openbsd && arm64)
package sqlite3
import (
"unsafe"
"modernc.org/libc"
)
// C documentation
//
// /*
// ** Set the explain mode for a statement.
// */
func Xsqlite3_stmt_explain(tls *libc.TLS, pStmt uintptr, eMode int32) (r int32) {
var rc int32
var v uintptr
_, _ = rc, v
v = pStmt
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer((*TVdbe)(unsafe.Pointer(v)).Fdb)).Fmutex)
if int32(Tbft(*(*uint16)(unsafe.Pointer(v + 200))&0xc>>2)) == eMode {
rc = SQLITE_OK
} else {
if eMode < 0 || eMode > int32(2) {
rc = int32(SQLITE_ERROR)
} else {
if libc.Int32FromUint8((*TVdbe)(unsafe.Pointer(v)).FprepFlags)&int32(SQLITE_PREPARE_SAVESQL) == 0 {
rc = int32(SQLITE_ERROR)
} else {
if libc.Int32FromUint8((*TVdbe)(unsafe.Pointer(v)).FeVdbeState) != int32(VDBE_READY_STATE) {
rc = int32(SQLITE_BUSY)
} else {
if (*TVdbe)(unsafe.Pointer(v)).FnMem >= int32(10) && (eMode != int32(2) || int32(Tbft(*(*uint16)(unsafe.Pointer(v + 200))&0x100>>8)) != 0) {
/* No reprepare necessary */
libc.SetBitFieldPtr16Uint32(v+200, libc.Uint32FromInt32(eMode), 2, 0xc)
rc = SQLITE_OK
} else {
libc.SetBitFieldPtr16Uint32(v+200, libc.Uint32FromInt32(eMode), 2, 0xc)
rc = _sqlite3Reprepare(tls, v)
libc.SetBitFieldPtr16Uint32(v+200, libc.BoolUint32(eMode == libc.Int32FromInt32(2)), 8, 0x100)
}
}
}
}
}
if int32(Tbft(*(*uint16)(unsafe.Pointer(v + 200))&0xc>>2)) != 0 {
(*TVdbe)(unsafe.Pointer(v)).FnResColumn = libc.Uint16FromInt32(int32(12) - int32(4)*int32(Tbft(*(*uint16)(unsafe.Pointer(v + 200))&0xc>>2)))
} else {
(*TVdbe)(unsafe.Pointer(v)).FnResColumn = (*TVdbe)(unsafe.Pointer(v)).FnResAlloc
}
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer((*TVdbe)(unsafe.Pointer(v)).Fdb)).Fmutex)
return rc
}
// C documentation
//
// /*
// ** Interface to the testing logic.
// */
func Xsqlite3_test_control(tls *libc.TLS, op int32, va uintptr) (r int32) {
var aProg, db, db1, db2, db3, db4, db5, db6, db7, pCtx, pI1, pI2, pN, pR, pU64, pn, ptr, xBenignBegin, xBenignEnd, z uintptr
var ap Tva_list
var b, iDb, opTrace, rc, sz, x, x1, x2, y, v1 int32
var newVal uint32
var rIn float64
var rLogEst TLogEst
var v2 bool
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = aProg, ap, b, db, db1, db2, db3, db4, db5, db6, db7, iDb, newVal, opTrace, pCtx, pI1, pI2, pN, pR, pU64, pn, ptr, rIn, rLogEst, rc, sz, x, x1, x2, xBenignBegin, xBenignEnd, y, z, v1, v2
rc = 0
ap = va
switch op {
/*
** Save the current state of the PRNG.
*/
case int32(SQLITE_TESTCTRL_PRNG_SAVE):
_sqlite3PrngSaveState(tls)
break
/*
** Restore the state of the PRNG to the last state saved using
** PRNG_SAVE. If PRNG_SAVE has never before been called, then
** this verb acts like PRNG_RESET.
*/
fallthrough
case int32(SQLITE_TESTCTRL_PRNG_RESTORE):
_sqlite3PrngRestoreState(tls)
break
/* sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, int x, sqlite3 *db);
**
** Control the seed for the pseudo-random number generator (PRNG) that
** is built into SQLite. Cases:
**
** x!=0 && db!=0 Seed the PRNG to the current value of the
** schema cookie in the main database for db, or
** x if the schema cookie is zero. This case
** is convenient to use with database fuzzers
** as it allows the fuzzer some control over the
** the PRNG seed.
**
** x!=0 && db==0 Seed the PRNG to the value of x.
**
** x==0 && db==0 Revert to default behavior of using the
** xRandomness method on the primary VFS.
**
** This test-control also resets the PRNG so that the new seed will
** be used for the next call to sqlite3_randomness().
*/
fallthrough
case int32(SQLITE_TESTCTRL_PRNG_SEED):
x = libc.VaInt32(&ap)
db = libc.VaUintptr(&ap)
if v2 = db != 0; v2 {
v1 = (*TSchema)(unsafe.Pointer((**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb))).FpSchema)).Fschema_cookie
y = v1
}
if v2 && v1 != 0 {
x = y
}
_sqlite3Config.FiPrngSeed = libc.Uint32FromInt32(x)
Xsqlite3_randomness(tls, 0, uintptr(0))
break
/* sqlite3_test_control(SQLITE_TESTCTRL_FK_NO_ACTION, sqlite3 *db, int b);
**
** If b is true, then activate the SQLITE_FkNoAction setting. If b is
** false then clear that setting. If the SQLITE_FkNoAction setting is
** enabled, all foreign key ON DELETE and ON UPDATE actions behave as if
** they were NO ACTION, regardless of how they are defined.
**
** NB: One must usually run "PRAGMA writable_schema=RESET" after
** using this test-control, before it will take full effect. failing
** to reset the schema can result in some unexpected behavior.
*/
fallthrough
case int32(SQLITE_TESTCTRL_FK_NO_ACTION):
db1 = libc.VaUintptr(&ap)
b = libc.VaInt32(&ap)
if b != 0 {
**(**Tu64)(__ccgo_up(db1 + 48)) |= libc.Uint64FromInt32(libc.Int32FromInt32(0x00008)) << libc.Int32FromInt32(32)
} else {
**(**Tu64)(__ccgo_up(db1 + 48)) &= ^(libc.Uint64FromInt32(libc.Int32FromInt32(0x00008)) << libc.Int32FromInt32(32))
}
break
/*
** sqlite3_test_control(BITVEC_TEST, size, program)
**
** Run a test against a Bitvec object of size. The program argument
** is an array of integers that defines the test. Return -1 on a
** memory allocation error, 0 on success, or non-zero for an error.
** See the sqlite3BitvecBuiltinTest() for additional information.
*/
fallthrough
case int32(SQLITE_TESTCTRL_BITVEC_TEST):
sz = libc.VaInt32(&ap)
aProg = libc.VaUintptr(&ap)
rc = _sqlite3BitvecBuiltinTest(tls, sz, aProg)
break
/*
** sqlite3_test_control(FAULT_INSTALL, xCallback)
**
** Arrange to invoke xCallback() whenever sqlite3FaultSim() is called,
** if xCallback is not NULL.
**
** As a test of the fault simulator mechanism itself, sqlite3FaultSim(0)
** is called immediately after installing the new callback and the return
** value from sqlite3FaultSim(0) becomes the return from
** sqlite3_test_control().
*/
fallthrough
case int32(SQLITE_TESTCTRL_FAULT_INSTALL):
_sqlite3Config.FxTestCallback = libc.VaUintptr(&ap)
rc = _sqlite3FaultSim(tls, 0)
break
/*
** sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd)
**
** Register hooks to call to indicate which malloc() failures
** are benign.
*/
fallthrough
case int32(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS):
xBenignBegin = libc.VaUintptr(&ap)
xBenignEnd = libc.VaUintptr(&ap)
_sqlite3BenignMallocHooks(tls, xBenignBegin, xBenignEnd)
break
/*
** sqlite3_test_control(SQLITE_TESTCTRL_PENDING_BYTE, unsigned int X)
**
** Set the PENDING byte to the value in the argument, if X>0.
** Make no changes if X==0. Return the value of the pending byte
** as it existing before this routine was called.
**
** IMPORTANT: Changing the PENDING byte from 0x40000000 results in
** an incompatible database file format. Changing the PENDING byte
** while any database connection is open results in undefined and
** deleterious behavior.
*/
fallthrough
case int32(SQLITE_TESTCTRL_PENDING_BYTE):
rc = _sqlite3PendingByte
newVal = libc.VaUint32(&ap)
if newVal != 0 {
_sqlite3PendingByte = libc.Int32FromUint32(newVal)
}
break
/*
** sqlite3_test_control(SQLITE_TESTCTRL_ASSERT, int X)
**
** This action provides a run-time test to see whether or not
** assert() was enabled at compile-time. If X is true and assert()
** is enabled, then the return value is true. If X is true and
** assert() is disabled, then the return value is zero. If X is
** false and assert() is enabled, then the assertion fires and the
** process aborts. If X is false and assert() is disabled, then the
** return value is zero.
*/
fallthrough
case int32(SQLITE_TESTCTRL_ASSERT):
x1 = 0
rc = x1
break
/*
** sqlite3_test_control(SQLITE_TESTCTRL_ALWAYS, int X)
**
** This action provides a run-time test to see how the ALWAYS and
** NEVER macros were defined at compile-time.
**
** The return value is ALWAYS(X) if X is true, or 0 if X is false.
**
** The recommended test is X==2. If the return value is 2, that means
** ALWAYS() and NEVER() are both no-op pass-through macros, which is the
** default setting. If the return value is 1, then ALWAYS() is either
** hard-coded to true or else it asserts if its argument is false.
** The first behavior (hard-coded to true) is the case if
** SQLITE_TESTCTRL_ASSERT shows that assert() is disabled and the second
** behavior (assert if the argument to ALWAYS() is false) is the case if
** SQLITE_TESTCTRL_ASSERT shows that assert() is enabled.
**
** The run-time test procedure might look something like this:
**
** if( sqlite3_test_control(SQLITE_TESTCTRL_ALWAYS, 2)==2 ){
** // ALWAYS() and NEVER() are no-op pass-through macros
** }else if( sqlite3_test_control(SQLITE_TESTCTRL_ASSERT, 1) ){
** // ALWAYS(x) asserts that x is true. NEVER(x) asserts x is false.
** }else{
** // ALWAYS(x) is a constant 1. NEVER(x) is a constant 0.
** }
*/
fallthrough
case int32(SQLITE_TESTCTRL_ALWAYS):
x2 = libc.VaInt32(&ap)
if x2 != 0 {
v1 = x2
} else {
v1 = 0
}
rc = v1
break
/*
** sqlite3_test_control(SQLITE_TESTCTRL_BYTEORDER);
**
** The integer returned reveals the byte-order of the computer on which
** SQLite is running:
**
** 1 big-endian, determined at run-time
** 10 little-endian, determined at run-time
** 432101 big-endian, determined at compile-time
** 123410 little-endian, determined at compile-time
*/
fallthrough
case int32(SQLITE_TESTCTRL_BYTEORDER):
rc = libc.Int32FromInt32(SQLITE_BYTEORDER)*libc.Int32FromInt32(100) + libc.Int32FromInt32(SQLITE_LITTLEENDIAN)*libc.Int32FromInt32(10) + libc.Int32FromInt32(SQLITE_BIGENDIAN)
break
/* sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, sqlite3 *db, int N)
**
** Enable or disable various optimizations for testing purposes. The
** argument N is a bitmask of optimizations to be disabled. For normal
** operation N should be 0. The idea is that a test program (like the
** SQL Logic Test or SLT test module) can run the same SQL multiple times
** with various optimizations disabled to verify that the same answer
** is obtained in every case.
*/
fallthrough
case int32(SQLITE_TESTCTRL_OPTIMIZATIONS):
db2 = libc.VaUintptr(&ap)
(*Tsqlite3)(unsafe.Pointer(db2)).FdbOptFlags = libc.VaUint32(&ap)
break
/* sqlite3_test_control(SQLITE_TESTCTRL_GETOPT, sqlite3 *db, int *N)
**
** Write the current optimization settings into *N. A zero bit means that
** the optimization is on, and a 1 bit means that the optimization is off.
*/
fallthrough
case int32(SQLITE_TESTCTRL_GETOPT):
db3 = libc.VaUintptr(&ap)
pN = libc.VaUintptr(&ap)
**(**int32)(__ccgo_up(pN)) = libc.Int32FromUint32((*Tsqlite3)(unsafe.Pointer(db3)).FdbOptFlags)
break
/* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, onoff, xAlt);
**
** If parameter onoff is 1, subsequent calls to localtime() fail.
** If 2, then invoke xAlt() instead of localtime(). If 0, normal
** processing.
**
** xAlt arguments are void pointers, but they really want to be:
**
** int xAlt(const time_t*, struct tm*);
**
** xAlt should write results in to struct tm object of its 2nd argument
** and return zero on success, or return non-zero on failure.
*/
fallthrough
case int32(SQLITE_TESTCTRL_LOCALTIME_FAULT):
_sqlite3Config.FbLocaltimeFault = libc.VaInt32(&ap)
if _sqlite3Config.FbLocaltimeFault == int32(2) {
_sqlite3Config.FxAltLocaltime = libc.VaUintptr(&ap)
} else {
_sqlite3Config.FxAltLocaltime = uintptr(0)
}
break
/* sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, sqlite3*);
**
** Toggle the ability to use internal functions on or off for
** the database connection given in the argument.
*/
fallthrough
case int32(SQLITE_TESTCTRL_INTERNAL_FUNCTIONS):
db4 = libc.VaUintptr(&ap)
**(**Tu32)(__ccgo_up(db4 + 44)) ^= uint32(DBFLAG_InternalFunc)
break
/* sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int);
**
** Set or clear a flag that indicates that the database file is always well-
** formed and never corrupt. This flag is clear by default, indicating that
** database files might have arbitrary corruption. Setting the flag during
** testing causes certain assert() statements in the code to be activated
** that demonstrate invariants on well-formed database files.
*/
fallthrough
case int32(SQLITE_TESTCTRL_NEVER_CORRUPT):
_sqlite3Config.FneverCorrupt = libc.VaInt32(&ap)
break
/* sqlite3_test_control(SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS, int);
**
** Set or clear a flag that causes SQLite to verify that type, name,
** and tbl_name fields of the sqlite_schema table. This is normally
** on, but it is sometimes useful to turn it off for testing.
**
** 2020-07-22: Disabling EXTRA_SCHEMA_CHECKS also disables the
** verification of rootpage numbers when parsing the schema. This
** is useful to make it easier to reach strange internal error states
** during testing. The EXTRA_SCHEMA_CHECKS setting is always enabled
** in production.
*/
fallthrough
case int32(SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS):
_sqlite3Config.FbExtraSchemaChecks = libc.Uint8FromInt32(libc.VaInt32(&ap))
break
/* Set the threshold at which OP_Once counters reset back to zero.
** By default this is 0x7ffffffe (over 2 billion), but that value is
** too big to test in a reasonable amount of time, so this control is
** provided to set a small and easily reachable reset value.
*/
fallthrough
case int32(SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD):
_sqlite3Config.FiOnceResetThreshold = libc.VaInt32(&ap)
break
/* sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE, xCallback, ptr);
**
** Set the VDBE coverage callback function to xCallback with context
** pointer ptr.
*/
fallthrough
case int32(SQLITE_TESTCTRL_VDBE_COVERAGE):
break
/* sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, nMax); */
fallthrough
case int32(SQLITE_TESTCTRL_SORTER_MMAP):
db5 = libc.VaUintptr(&ap)
(*Tsqlite3)(unsafe.Pointer(db5)).FnMaxSorterMmap = libc.VaInt32(&ap)
break
/* sqlite3_test_control(SQLITE_TESTCTRL_ISINIT);
**
** Return SQLITE_OK if SQLite has been initialized and SQLITE_ERROR if
** not.
*/
fallthrough
case int32(SQLITE_TESTCTRL_ISINIT):
if libc.AtomicLoadPInt32(uintptr(unsafe.Pointer(&_sqlite3Config))+340) == 0 {
rc = int32(SQLITE_ERROR)
}
break
/* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, mode, tnum);
**
** This test control is used to create imposter tables. "db" is a pointer
** to the database connection. dbName is the database name (ex: "main" or
** "temp") which will receive the imposter. "mode" turns imposter mode on
** or off. mode==0 means imposter mode is off. mode==1 means imposter mode
** is on. mode==2 means imposter mode is on but results in an imposter
** table that is read-only unless writable_schema is on. "tnum" is the
** root page of the b-tree to which the imposter table should connect.
**
** Enable imposter mode only when the schema has already been parsed. Then
** run a single CREATE TABLE statement to construct the imposter table in
** the parsed schema. Then turn imposter mode back off again.
**
** If onOff==0 and tnum>0 then reset the schema for all databases, causing
** the schema to be reparsed the next time it is needed. This has the
** effect of erasing all imposter tables.
*/
fallthrough
case int32(SQLITE_TESTCTRL_IMPOSTER):
db6 = libc.VaUintptr(&ap)
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db6)).Fmutex)
iDb = _sqlite3FindDbName(tls, db6, libc.VaUintptr(&ap))
if iDb >= 0 {
(*Tsqlite3)(unsafe.Pointer(db6)).Finit1.FiDb = libc.Uint8FromInt32(iDb)
(*Tsqlite3)(unsafe.Pointer(db6)).Finit1.Fbusy = uint8(libc.AssignBitFieldPtr8Uint32(db6+192+8, libc.Uint32FromInt32(libc.VaInt32(&ap)), 2, 1, 0x6))
(*Tsqlite3)(unsafe.Pointer(db6)).Finit1.FnewTnum = libc.Uint32FromInt32(libc.VaInt32(&ap))
if libc.Int32FromUint8((*Tsqlite3)(unsafe.Pointer(db6)).Finit1.Fbusy) == 0 && (*Tsqlite3)(unsafe.Pointer(db6)).Finit1.FnewTnum > uint32(0) {
_sqlite3ResetAllSchemasOfConnection(tls, db6)
}
}
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db6)).Fmutex)
break
/* sqlite3_test_control(SQLITE_TESTCTRL_RESULT_INTREAL, sqlite3_context*);
**
** This test-control causes the most recent sqlite3_result_int64() value
** to be interpreted as a MEM_IntReal instead of as an MEM_Int. Normally,
** MEM_IntReal values only arise during an INSERT operation of integer
** values into a REAL column, so they can be challenging to test. This
** test-control enables us to write an intreal() SQL function that can
** inject an intreal() value at arbitrary places in an SQL statement,
** for testing purposes.
*/
fallthrough
case int32(SQLITE_TESTCTRL_RESULT_INTREAL):
pCtx = libc.VaUintptr(&ap)
_sqlite3ResultIntReal(tls, pCtx)
break
/* sqlite3_test_control(SQLITE_TESTCTRL_SEEK_COUNT,
** sqlite3 *db, // Database connection
** u64 *pnSeek // Write seek count here
** );
**
** This test-control queries the seek-counter on the "main" database
** file. The seek-counter is written into *pnSeek and is then reset.
** The seek-count is only available if compiled with SQLITE_DEBUG.
*/
fallthrough
case int32(SQLITE_TESTCTRL_SEEK_COUNT):
db7 = libc.VaUintptr(&ap)
pn = libc.VaUintptr(&ap)
**(**Tu64)(__ccgo_up(pn)) = uint64(0)
_ = db7 /* Silence harmless unused variable warning */
break
/* sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, op, ptr)
**
** "ptr" is a pointer to a u32.
**
** op==0 Store the current sqlite3TreeTrace in *ptr
** op==1 Set sqlite3TreeTrace to the value *ptr
** op==2 Store the current sqlite3WhereTrace in *ptr
** op==3 Set sqlite3WhereTrace to the value *ptr
*/
fallthrough
case int32(SQLITE_TESTCTRL_TRACEFLAGS):
opTrace = libc.VaInt32(&ap)
ptr = libc.VaUintptr(&ap)
switch opTrace {
case 0:
**(**Tu32)(__ccgo_up(ptr)) = _sqlite3TreeTrace
case int32(1):
_sqlite3TreeTrace = **(**Tu32)(__ccgo_up(ptr))
case int32(2):
**(**Tu32)(__ccgo_up(ptr)) = _sqlite3WhereTrace
case int32(3):
_sqlite3WhereTrace = **(**Tu32)(__ccgo_up(ptr))
break
}
break
/* sqlite3_test_control(SQLITE_TESTCTRL_LOGEST,
** double fIn, // Input value
** int *pLogEst, // sqlite3LogEstFromDouble(fIn)
** u64 *pInt, // sqlite3LogEstToInt(*pLogEst)
** int *pLogEst2 // sqlite3LogEst(*pInt)
** );
**
** Test access for the LogEst conversion routines.
*/
fallthrough
case int32(SQLITE_TESTCTRL_LOGEST):
rIn = libc.VaFloat64(&ap)
rLogEst = _sqlite3LogEstFromDouble(tls, rIn)
pI1 = libc.VaUintptr(&ap)
pU64 = libc.VaUintptr(&ap)
pI2 = libc.VaUintptr(&ap)
**(**int32)(__ccgo_up(pI1)) = int32(rLogEst)
**(**Tu64)(__ccgo_up(pU64)) = _sqlite3LogEstToInt(tls, rLogEst)
**(**int32)(__ccgo_up(pI2)) = int32(_sqlite3LogEst(tls, **(**Tu64)(__ccgo_up(pU64))))
break
/* sqlite3_test_control(SQLITE_TESTCTRL_ATOF, const char *z, double *p);
**
** Test access to the sqlite3AtoF() routine.
*/
fallthrough
case int32(SQLITE_TESTCTRL_ATOF):
z = libc.VaUintptr(&ap)
pR = libc.VaUintptr(&ap)
rc = _sqlite3AtoF(tls, z, pR)
break
/* sqlite3_test_control(SQLITE_TESTCTRL_JSON_SELFCHECK, &onOff);
**
** Activate or deactivate validation of JSONB that is generated from
** text. Off by default, as the validation is slow. Validation is
** only available if compiled using SQLITE_DEBUG.
**
** If onOff is initially 1, then turn it on. If onOff is initially
** off, turn it off. If onOff is initially -1, then change onOff
** to be the current setting.
*/
fallthrough
case int32(SQLITE_TESTCTRL_JSON_SELFCHECK):
break
}
_ = ap
return rc
}
// C documentation
//
// /*
// ** This callback is invoked once for each index when reading the
// ** sqlite_stat1 table.
// **
// ** argv[0] = name of the table
// ** argv[1] = name of the index (might be NULL)
// ** argv[2] = results of analysis - on integer for each column
// **
// ** Entries for which argv[1]==NULL simply record the number of rows in
// ** the table.
// */
func _analysisLoader(tls *libc.TLS, pData uintptr, argc int32, argv uintptr, NotUsed uintptr) (r int32) {
bp := tls.Alloc(160)
defer tls.Free(160)
var aiRowEst, pIndex, pInfo, pTable, z uintptr
var nCol int32
var _ /* fakeIdx at bp+0 */ TIndex
_, _, _, _, _, _ = aiRowEst, nCol, pIndex, pInfo, pTable, z
pInfo = pData
_ = NotUsed
_ = argc
if argv == uintptr(0) || **(**uintptr)(__ccgo_up(argv)) == uintptr(0) || **(**uintptr)(__ccgo_up(argv + 2*8)) == uintptr(0) {
return 0
}
pTable = _sqlite3FindTable(tls, (*TanalysisInfo)(unsafe.Pointer(pInfo)).Fdb, **(**uintptr)(__ccgo_up(argv)), (*TanalysisInfo)(unsafe.Pointer(pInfo)).FzDatabase)
if pTable == uintptr(0) {
return 0
}
if **(**uintptr)(__ccgo_up(argv + 1*8)) == uintptr(0) {
pIndex = uintptr(0)
} else {
if Xsqlite3_stricmp(tls, **(**uintptr)(__ccgo_up(argv)), **(**uintptr)(__ccgo_up(argv + 1*8))) == 0 {
pIndex = _sqlite3PrimaryKeyIndex(tls, pTable)
} else {
pIndex = _sqlite3FindIndex(tls, (*TanalysisInfo)(unsafe.Pointer(pInfo)).Fdb, **(**uintptr)(__ccgo_up(argv + 1*8)), (*TanalysisInfo)(unsafe.Pointer(pInfo)).FzDatabase)
}
}
z = **(**uintptr)(__ccgo_up(argv + 2*8))
if pIndex != 0 {
aiRowEst = uintptr(0)
nCol = libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIndex)).FnKeyCol) + int32(1)
/* Index.aiRowEst may already be set here if there are duplicate
** sqlite_stat1 entries for this index. In that case just clobber
** the old data with the new instead of allocating a new array. */
if (*TIndex)(unsafe.Pointer(pIndex)).FaiRowEst == uintptr(0) {
(*TIndex)(unsafe.Pointer(pIndex)).FaiRowEst = _sqlite3MallocZero(tls, uint64(uint64(8)*libc.Uint64FromInt32(nCol)))
if (*TIndex)(unsafe.Pointer(pIndex)).FaiRowEst == uintptr(0) {
_sqlite3OomFault(tls, (*TanalysisInfo)(unsafe.Pointer(pInfo)).Fdb)
}
}
aiRowEst = (*TIndex)(unsafe.Pointer(pIndex)).FaiRowEst
libc.SetBitFieldPtr16Uint32(pIndex+100, libc.Uint32FromInt32(0), 2, 0x4)
_decodeIntArray(tls, z, nCol, aiRowEst, (*TIndex)(unsafe.Pointer(pIndex)).FaiRowLogEst, pIndex)
libc.SetBitFieldPtr16Uint32(pIndex+100, libc.Uint32FromInt32(1), 7, 0x80)
if (*TIndex)(unsafe.Pointer(pIndex)).FpPartIdxWhere == uintptr(0) {
(*TTable)(unsafe.Pointer(pTable)).FnRowLogEst = **(**TLogEst)(__ccgo_up((*TIndex)(unsafe.Pointer(pIndex)).FaiRowLogEst))
**(**Tu32)(__ccgo_up(pTable + 48)) |= uint32(TF_HasStat1)
}
} else {
(**(**TIndex)(__ccgo_up(bp))).FszIdxRow = (*TTable)(unsafe.Pointer(pTable)).FszTabRow
_decodeIntArray(tls, z, int32(1), uintptr(0), pTable+58, bp)
(*TTable)(unsafe.Pointer(pTable)).FszTabRow = (**(**TIndex)(__ccgo_up(bp))).FszIdxRow
**(**Tu32)(__ccgo_up(pTable + 48)) |= uint32(TF_HasStat1)
}
return 0
}
// C documentation
//
// /*
// ** This version of balance() handles the common special case where
// ** a new entry is being inserted on the extreme right-end of the
// ** tree, in other words, when the new entry will become the largest
// ** entry in the tree.
// **
// ** Instead of trying to balance the 3 right-most leaf pages, just add
// ** a new page to the right-hand side and put the one new entry in
// ** that page. This leaves the right side of the tree somewhat
// ** unbalanced. But odds are that we will be inserting new entries
// ** at the end soon afterwards so the nearly empty page will quickly
// ** fill up. On average.
// **
// ** pPage is the leaf page which is the right-most page in the tree.
// ** pParent is its parent. pPage must have a single overflow entry
// ** which is also the right-most entry on the page.
// **
// ** The pSpace buffer is used to store a temporary copy of the divider
// ** cell that will be inserted into pParent. Such a cell consists of a 4
// ** byte page number followed by a variable length integer. In other
// ** words, at most 13 bytes. Hence the pSpace buffer must be at
// ** least 13 bytes in size.
// */
func _balance_quick(tls *libc.TLS, pParent uintptr, pPage uintptr, pSpace uintptr) (r int32) {
bp := tls.Alloc(144)
defer tls.Free(144)
var pBt, pOut, pStop, v1, v3 uintptr
var v2 Tu8
var _ /* b at bp+32 */ TCellArray
var _ /* pCell at bp+16 */ uintptr
var _ /* pNew at bp+0 */ uintptr
var _ /* pgnoNew at bp+12 */ TPgno
var _ /* rc at bp+8 */ int32
var _ /* szCell at bp+24 */ Tu16
_, _, _, _, _, _ = pBt, pOut, pStop, v1, v2, v3
pBt = (*TMemPage)(unsafe.Pointer(pPage)).FpBt /* Page number of pNew */
if libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(pPage)).FnCell) == 0 {
return _sqlite3CorruptError(tls, int32(81392))
} /* dbfuzz001.test */
/* Allocate a new page. This page will become the right-sibling of
** pPage. Make the parent page writable, so that the new divider cell
** may be inserted. If both these operations are successful, proceed.
*/
**(**int32)(__ccgo_up(bp + 8)) = _allocateBtreePage(tls, pBt, bp, bp+12, uint32(0), uint8(0))
if **(**int32)(__ccgo_up(bp + 8)) == SQLITE_OK {
pOut = pSpace + 4
**(**uintptr)(__ccgo_up(bp + 16)) = **(**uintptr)(__ccgo_up(pPage + 40))
**(**Tu16)(__ccgo_up(bp + 24)) = (*(*func(*libc.TLS, uintptr, uintptr) Tu16)(unsafe.Pointer(&struct{ uintptr }{(*TMemPage)(unsafe.Pointer(pPage)).FxCellSize})))(tls, pPage, **(**uintptr)(__ccgo_up(bp + 16)))
_zeroPage(tls, **(**uintptr)(__ccgo_up(bp)), libc.Int32FromInt32(PTF_INTKEY)|libc.Int32FromInt32(PTF_LEAFDATA)|libc.Int32FromInt32(PTF_LEAF))
(**(**TCellArray)(__ccgo_up(bp + 32))).FnCell = int32(1)
(**(**TCellArray)(__ccgo_up(bp + 32))).FpRef = pPage
(**(**TCellArray)(__ccgo_up(bp + 32))).FapCell = bp + 16
(**(**TCellArray)(__ccgo_up(bp + 32))).FszCell = bp + 24
**(**uintptr)(__ccgo_up(bp + 32 + 32)) = (*TMemPage)(unsafe.Pointer(pPage)).FaDataEnd
**(**int32)(__ccgo_up(bp + 32 + 80)) = int32(2)
**(**int32)(__ccgo_up(bp + 32 + 80 + uintptr(libc.Int32FromInt32(NB)*libc.Int32FromInt32(2)-libc.Int32FromInt32(1))*4)) = int32(0x7fffffff)
**(**int32)(__ccgo_up(bp + 8)) = _rebuildPage(tls, bp+32, 0, int32(1), **(**uintptr)(__ccgo_up(bp)))
if **(**int32)(__ccgo_up(bp + 8)) != 0 {
_releasePage(tls, **(**uintptr)(__ccgo_up(bp)))
return **(**int32)(__ccgo_up(bp + 8))
}
(*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FnFree = libc.Int32FromUint32((*TBtShared)(unsafe.Pointer(pBt)).FusableSize - uint32((*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FcellOffset) - uint32(2) - uint32(**(**Tu16)(__ccgo_up(bp + 24))))
/* If this is an auto-vacuum database, update the pointer map
** with entries for the new page, and any pointer from the
** cell on the page to an overflow page. If either of these
** operations fails, the return code is set, but the contents
** of the parent page are still manipulated by the code below.
** That is Ok, at this point the parent page is guaranteed to
** be marked as dirty. Returning an error code will cause a
** rollback, undoing any changes made to the parent page.
*/
if (*TBtShared)(unsafe.Pointer(pBt)).FautoVacuum != 0 {
_ptrmapPut(tls, pBt, **(**TPgno)(__ccgo_up(bp + 12)), uint8(PTRMAP_BTREE), (*TMemPage)(unsafe.Pointer(pParent)).Fpgno, bp+8)
if libc.Int32FromUint16(**(**Tu16)(__ccgo_up(bp + 24))) > libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FminLocal) {
_ptrmapPutOvflPtr(tls, **(**uintptr)(__ccgo_up(bp)), **(**uintptr)(__ccgo_up(bp)), **(**uintptr)(__ccgo_up(bp + 16)), bp+8)
}
}
/* Create a divider cell to insert into pParent. The divider cell
** consists of a 4-byte page number (the page number of pPage) and
** a variable length key value (which must be the same value as the
** largest key on pPage).
**
** To find the largest key value on pPage, first find the right-most
** cell on pPage. The first two fields of this cell are the
** record-length (a variable length integer at most 32-bits in size)
** and the key value (a variable length integer, may have any value).
** The first of the while(...) loops below skips over the record-length
** field. The second while(...) loop copies the key value from the
** cell on pPage into the pSpace buffer.
*/
**(**uintptr)(__ccgo_up(bp + 16)) = (*TMemPage)(unsafe.Pointer(pPage)).FaData + uintptr(libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(pPage)).FmaskPage)&(libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TMemPage)(unsafe.Pointer(pPage)).FaCellIdx + uintptr(int32(2)*(libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(pPage)).FnCell)-int32(1))))))<<libc.Int32FromInt32(8)|libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TMemPage)(unsafe.Pointer(pPage)).FaCellIdx + uintptr(int32(2)*(libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(pPage)).FnCell)-int32(1))) + 1)))))
pStop = **(**uintptr)(__ccgo_up(bp + 16)) + 9
for {
v1 = **(**uintptr)(__ccgo_up(bp + 16))
**(**uintptr)(__ccgo_up(bp + 16)) = **(**uintptr)(__ccgo_up(bp + 16)) + 1
if !(libc.Int32FromUint8(**(**Tu8)(__ccgo_up(v1)))&int32(0x80) != 0 && **(**uintptr)(__ccgo_up(bp + 16)) < pStop) {
break
}
}
pStop = **(**uintptr)(__ccgo_up(bp + 16)) + 9
for {
v1 = **(**uintptr)(__ccgo_up(bp + 16))
**(**uintptr)(__ccgo_up(bp + 16)) = **(**uintptr)(__ccgo_up(bp + 16)) + 1
v2 = **(**Tu8)(__ccgo_up(v1))
v3 = pOut
pOut = pOut + 1
**(**Tu8)(__ccgo_up(v3)) = v2
if !(libc.Int32FromUint8(v2)&int32(0x80) != 0 && **(**uintptr)(__ccgo_up(bp + 16)) < pStop) {
break
}
}
/* Insert the new divider cell into pParent. */
if **(**int32)(__ccgo_up(bp + 8)) == SQLITE_OK {
**(**int32)(__ccgo_up(bp + 8)) = _insertCell(tls, pParent, libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(pParent)).FnCell), pSpace, int32(int64(pOut)-int64(pSpace)), uintptr(0), (*TMemPage)(unsafe.Pointer(pPage)).Fpgno)
}
/* Set the right-child pointer of pParent to point to the new page. */
_sqlite3Put4byte(tls, (*TMemPage)(unsafe.Pointer(pParent)).FaData+uintptr(libc.Int32FromUint8((*TMemPage)(unsafe.Pointer(pParent)).FhdrOffset)+int32(8)), **(**TPgno)(__ccgo_up(bp + 12)))
/* Release the reference to the new page. */
_releasePage(tls, **(**uintptr)(__ccgo_up(bp)))
}
return **(**int32)(__ccgo_up(bp + 8))
}
// C documentation
//
// /*
// ** Erase the given database page and all its children. Return
// ** the page to the freelist.
// */
func _clearDatabasePage(tls *libc.TLS, pBt uintptr, pgno TPgno, freePageFlag int32, pnChange uintptr) (r int32) {
bp := tls.Alloc(48)
defer tls.Free(48)
var hdr, i, v2 int32
var pCell uintptr
var _ /* info at bp+16 */ TCellInfo
var _ /* pPage at bp+0 */ uintptr
var _ /* rc at bp+8 */ int32
_, _, _, _ = hdr, i, pCell, v2
if pgno > _btreePagecount(tls, pBt) {
return _sqlite3CorruptError(tls, int32(83601))
}
**(**int32)(__ccgo_up(bp + 8)) = _getAndInitPage(tls, pBt, pgno, bp, 0)
if **(**int32)(__ccgo_up(bp + 8)) != 0 {
return **(**int32)(__ccgo_up(bp + 8))
}
if libc.Int32FromUint8((*TBtShared)(unsafe.Pointer(pBt)).FopenFlags)&int32(BTREE_SINGLE) == 0 && _sqlite3PagerPageRefcount(tls, (*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FpDbPage) != int32(1)+libc.BoolInt32(pgno == uint32(1)) {
**(**int32)(__ccgo_up(bp + 8)) = _sqlite3CorruptError(tls, int32(83608))
goto cleardatabasepage_out
}
hdr = libc.Int32FromUint8((*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FhdrOffset)
i = 0
for {
if !(i < libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FnCell)) {
break
}
pCell = (*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FaData + uintptr(libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FmaskPage)&(libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FaCellIdx + uintptr(int32(2)*i))))<<libc.Int32FromInt32(8)|libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FaCellIdx + uintptr(int32(2)*i) + 1)))))
if !((*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).Fleaf != 0) {
**(**int32)(__ccgo_up(bp + 8)) = _clearDatabasePage(tls, pBt, _sqlite3Get4byte(tls, pCell), int32(1), pnChange)
if **(**int32)(__ccgo_up(bp + 8)) != 0 {
goto cleardatabasepage_out
}
}
(*(*func(*libc.TLS, uintptr, uintptr, uintptr))(unsafe.Pointer(&struct{ uintptr }{(*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FxParseCell})))(tls, **(**uintptr)(__ccgo_up(bp)), pCell, bp+16)
if uint32((**(**TCellInfo)(__ccgo_up(bp + 16))).FnLocal) != (**(**TCellInfo)(__ccgo_up(bp + 16))).FnPayload {
**(**int32)(__ccgo_up(bp + 8)) = _clearCellOverflow(tls, **(**uintptr)(__ccgo_up(bp)), pCell, bp+16)
} else {
**(**int32)(__ccgo_up(bp + 8)) = SQLITE_OK
}
if **(**int32)(__ccgo_up(bp + 8)) != 0 {
goto cleardatabasepage_out
}
goto _1
_1:
;
i = i + 1
}
if !((*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).Fleaf != 0) {
**(**int32)(__ccgo_up(bp + 8)) = _clearDatabasePage(tls, pBt, _sqlite3Get4byte(tls, (*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FaData+uintptr(hdr+int32(8))), int32(1), pnChange)
if **(**int32)(__ccgo_up(bp + 8)) != 0 {
goto cleardatabasepage_out
}
if (*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FintKey != 0 {
pnChange = uintptr(0)
}
}
if pnChange != 0 {
**(**Ti64)(__ccgo_up(pnChange)) += libc.Int64FromUint16((*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FnCell)
}
if freePageFlag != 0 {
_freePage(tls, **(**uintptr)(__ccgo_up(bp)), bp+8)
} else {
v2 = _sqlite3PagerWrite(tls, (*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FpDbPage)
**(**int32)(__ccgo_up(bp + 8)) = v2
if v2 == 0 {
_zeroPage(tls, **(**uintptr)(__ccgo_up(bp)), libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FaData + uintptr(hdr))))|int32(PTF_LEAF))
}
}
goto cleardatabasepage_out
cleardatabasepage_out:
;
_releasePage(tls, **(**uintptr)(__ccgo_up(bp)))
return **(**int32)(__ccgo_up(bp + 8))
}
// C documentation
//
// /*
// ** Cursor iCur is open on an intkey b-tree (a table). Register iRowid contains
// ** a rowid value just read from cursor iIdxCur, open on index pIdx. This
// ** function generates code to do a deferred seek of cursor iCur to the
// ** rowid stored in register iRowid.
// **
// ** Normally, this is just:
// **
// ** OP_DeferredSeek $iCur $iRowid
// **
// ** Which causes a seek on $iCur to the row with rowid $iRowid.
// **
// ** However, if the scan currently being coded is a branch of an OR-loop and
// ** the statement currently being coded is a SELECT, then additional information
// ** is added that might allow OP_Column to omit the seek and instead do its
// ** lookup on the index, thus avoiding an expensive seek operation. To
// ** enable this optimization, the P3 of OP_DeferredSeek is set to iIdxCur
// ** and P4 is set to an array of integers containing one entry for each column
// ** in the table. For each table column, if the column is the i'th
// ** column of the index, then the corresponding array entry is set to (i+1).
// ** If the column does not appear in the index at all, the array entry is set
// ** to 0. The OP_Column opcode can check this array to see if the column it
// ** wants is in the index and if it is, it will substitute the index cursor
// ** and column number and continue with those new values, rather than seeking
// ** the table cursor.
// */
func _codeDeferredSeek(tls *libc.TLS, pWInfo uintptr, pIdx uintptr, iCur int32, iIdxCur int32) {
var ai, pParse, pTab, v, v1 uintptr
var i, x1, x2 int32
var v2 bool
_, _, _, _, _, _, _, _, _ = ai, i, pParse, pTab, v, x1, x2, v1, v2
pParse = (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpParse /* Parse context */
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe /* Vdbe to generate code within */
libc.SetBitFieldPtr8Uint32(pWInfo+68, libc.Uint32FromInt32(1), 0, 0x1)
_sqlite3VdbeAddOp3(tls, v, int32(OP_DeferredSeek), iIdxCur, 0, iCur)
if v2 = libc.Int32FromUint16((*TWhereInfo)(unsafe.Pointer(pWInfo)).FwctrlFlags)&(libc.Int32FromInt32(WHERE_OR_SUBCLAUSE)|libc.Int32FromInt32(WHERE_RIGHT_JOIN)) != 0; v2 {
if (*TParse)(unsafe.Pointer(pParse)).FpToplevel != 0 {
v1 = (*TParse)(unsafe.Pointer(pParse)).FpToplevel
} else {
v1 = pParse
}
}
if v2 && (*TParse)(unsafe.Pointer(v1)).FwriteMask == uint32(0) {
pTab = (*TIndex)(unsafe.Pointer(pIdx)).FpTable
ai = _sqlite3DbMallocZero(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, uint64(uint64(4)*libc.Uint64FromInt32(int32((*TTable)(unsafe.Pointer(pTab)).FnCol)+libc.Int32FromInt32(1))))
if ai != 0 {
**(**Tu32)(__ccgo_up(ai)) = libc.Uint32FromInt16((*TTable)(unsafe.Pointer(pTab)).FnCol)
i = 0
for {
if !(i < libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnColumn)-int32(1)) {
break
}
x1 = int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(i)*2)))
x2 = int32(_sqlite3TableColumnToStorage(tls, pTab, int16(x1)))
if x1 >= 0 {
**(**Tu32)(__ccgo_up(ai + uintptr(x2+int32(1))*4)) = libc.Uint32FromInt32(i + int32(1))
}
goto _3
_3:
;
i = i + 1
}
_sqlite3VdbeChangeP4(tls, v, -int32(1), ai, -int32(15))
}
}
}
// C documentation
//
// /*
// ** Return true if column iCol of table pTab seem like it might be a
// ** good column to use as part of a query-time index.
// **
// ** Current algorithm (subject to improvement!):
// **
// ** 1. If iCol is already the left-most column of some other index,
// ** then return false.
// **
// ** 2. If iCol is part of an existing index that has an aiRowLogEst of
// ** more than 20, then return false.
// **
// ** 3. If no disqualifying conditions above are found, return true.
// **
// ** 2025-01-03: I experimented with a new rule that returns false if the
// ** the datatype of the column is "BOOLEAN". This did not improve
// ** performance on any queries at hand, but it did burn CPU cycles, so the
// ** idea was not committed.
// */
func _columnIsGoodIndexCandidate(tls *libc.TLS, pTab uintptr, iCol int32) (r int32) {
var j int32
var pIdx uintptr
_, _ = j, pIdx
pIdx = (*TTable)(unsafe.Pointer(pTab)).FpIndex
for {
if !(pIdx != uintptr(0)) {
break
}
j = 0
for {
if !(j < libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnKeyCol)) {
break
}
if int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(j)*2))) == iCol {
if j == 0 {
return 0
}
if int32(uint32(*(*uint16)(unsafe.Pointer(pIdx + 100))&0x80>>7)) != 0 && int32(**(**TLogEst)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiRowLogEst + uintptr(j+int32(1))*2))) > int32(20) {
return 0
}
break
}
goto _2
_2:
;
j = j + 1
}
goto _1
_1:
;
pIdx = (*TIndex)(unsafe.Pointer(pIdx)).FpNext
}
return int32(1)
}
// C documentation
//
// /*
// ** Convert the N-th element of pStmt->pColName[] into a string using
// ** xFunc() then return that string. If N is out of range, return 0.
// **
// ** There are up to 5 names for each column. useType determines which
// ** name is returned. Here are the names:
// **
// ** 0 The column name as it should be displayed for output
// ** 1 The datatype name for the column
// ** 2 The name of the database that the column derives from
// ** 3 The name of the table that the column derives from
// ** 4 The name of the table column that the result column derives from
// **
// ** If the result is not a simple column reference (if it is an expression
// ** or a constant) then useTypes 2, 3, and 4 return NULL.
// */
func _columnName(tls *libc.TLS, pStmt uintptr, N int32, useUtf16 int32, useType int32) (r uintptr) {
var db, p, ret uintptr
var i, n, v1 int32
var prior_mallocFailed Tu8
_, _, _, _, _, _, _ = db, i, n, p, prior_mallocFailed, ret, v1
if N < 0 {
return uintptr(0)
}
ret = uintptr(0)
p = pStmt
db = (*TVdbe)(unsafe.Pointer(p)).Fdb
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
if int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0xc>>2)) != 0 {
if useType > 0 {
goto columnName_end
}
if int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0xc>>2)) == int32(1) {
v1 = int32(8)
} else {
v1 = int32(4)
}
n = v1
if N >= n {
goto columnName_end
}
if useUtf16 != 0 {
i = libc.Int32FromUint8(_iExplainColNames16[N+int32(8)*int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0xc>>2))-int32(8)])
ret = uintptr(unsafe.Pointer(&_azExplainColNames16data)) + uintptr(i)*2
} else {
ret = _azExplainColNames8[N+int32(8)*int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0xc>>2))-int32(8)]
}
goto columnName_end
}
n = libc.Int32FromUint16((*TVdbe)(unsafe.Pointer(p)).FnResColumn)
if N < n {
prior_mallocFailed = (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed
N = N + useType*n
if useUtf16 != 0 {
ret = Xsqlite3_value_text16(tls, (*TVdbe)(unsafe.Pointer(p)).FaColName+uintptr(N)*56)
} else {
ret = Xsqlite3_value_text(tls, (*TVdbe)(unsafe.Pointer(p)).FaColName+uintptr(N)*56)
}
/* A malloc may have failed inside of the _text() call. If this
** is the case, clear the mallocFailed flag and return NULL.
*/
if libc.Int32FromUint8((*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed) > libc.Int32FromUint8(prior_mallocFailed) {
_sqlite3OomClear(tls, db)
ret = uintptr(0)
}
}
goto columnName_end
columnName_end:
;
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
return ret
}
// C documentation
//
// /*
// ** Compute the maximum number of paths in the solver algorithm, for
// ** queries that have three or more terms in the FROM clause. Queries with
// ** two or fewer FROM clause terms are handled by the caller.
// **
// ** Query planning is NP-hard. We must limit the number of paths at
// ** each step of the solver search algorithm to avoid exponential behavior.
// **
// ** The value returned is a tuning parameter. Currently the value is:
// **
// ** 18 for star queries
// ** 12 otherwise
// **
// ** For the purposes of this heuristic, a star-query is defined as a query
// ** with a central "fact" table that is joined against multiple
// ** "dimension" tables, subject to the following constraints:
// **
// ** (aa) Only a five-way or larger join is considered for this
// ** optimization. If there are fewer than four terms in the FROM
// ** clause, this heuristic does not apply.
// **
// ** (bb) The join between the fact table and the dimension tables must
// ** be an INNER join. CROSS and OUTER JOINs do not qualify.
// **
// ** (cc) A table must have 3 or more dimension tables in order to be
// ** considered a fact table. (Was 4 prior to 2026-02-10.)
// **
// ** (dd) A table that is a self-join cannot be a dimension table.
// ** Dimension tables are joined against fact tables.
// **
// ** SIDE EFFECT: (and really the whole point of this subroutine)
// **
// ** If pWInfo describes a star-query, then the cost for SCANs of dimension
// ** WhereLoops is increased to be slightly larger than the cost of a SCAN
// ** in the fact table. Only SCAN costs are increased. SEARCH costs are
// ** unchanged. This heuristic helps keep fact tables in outer loops. Without
// ** this heuristic, paths with fact tables in outer loops tend to get pruned
// ** by the mxChoice limit on the number of paths, resulting in poor query
// ** plans. See the starschema1.test test module for examples of queries
// ** that need this heuristic to find good query plans.
// **
// ** This heuristic can be completely disabled, so that no query is
// ** considered a star-query, using SQLITE_TESTCTRL_OPTIMIZATION to
// ** disable the SQLITE_StarQuery optimization. In the CLI, the command
// ** to do that is: ".testctrl opt -starquery".
// **
// ** HISTORICAL NOTES:
// **
// ** This optimization was first added on 2024-05-09 by check-in 38db9b5c83d.
// ** The original optimization reduced the cost and output size estimate for
// ** fact tables to help them move to outer loops. But months later (as people
// ** started upgrading) performance regression reports started caming in,
// ** including:
// **
// ** forum post b18ef983e68d06d1 (2024-12-21)
// ** forum post 0025389d0860af82 (2025-01-14)
// ** forum post d87570a145599033 (2025-01-17)
// **
// ** To address these, the criteria for a star-query was tightened to exclude
// ** cases where the fact and dimensions are separated by an outer join, and
// ** the affect of star-schema detection was changed to increase the rRun cost
// ** on just full table scans of dimension tables, rather than reducing costs
// ** in the all access methods of the fact table.
// */
func _computeMxChoice(tls *libc.TLS, pWInfo uintptr) (r int32) {
var aFromTabs, pFactTab, pStart, pWLoop uintptr
var iFromIdx, nDep, nLoop, v5 int32
var m, mSeen, mSelfJoin TBitmask
var mxRun TLogEst
_, _, _, _, _, _, _, _, _, _, _, _ = aFromTabs, iFromIdx, m, mSeen, mSelfJoin, mxRun, nDep, nLoop, pFactTab, pStart, pWLoop, v5
nLoop = libc.Int32FromUint8((*TWhereInfo)(unsafe.Pointer(pWInfo)).FnLevel) /* For looping over WhereLoops */
if nLoop >= int32(4) && !(int32(uint32(*(*uint8)(unsafe.Pointer(pWInfo + 68))&0x10>>4)) != 0) && (*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer((*TWhereInfo)(unsafe.Pointer(pWInfo)).FpParse)).Fdb)).FdbOptFlags&libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_StarQuery)) == uint32(0) { /* Bitmask for candidate fact-table */
mSelfJoin = uint64(0) /* Where to start searching for dimension-tables */
libc.SetBitFieldPtr8Uint32(pWInfo+68, libc.Uint32FromInt32(1), 4, 0x10) /* Only do this computation once */
/* Look for fact tables with three or more dimensions where the
** dimension tables are not separately from the fact tables by an outer
** or cross join. Adjust cost weights if found.
*/
aFromTabs = (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpTabList + 8
pStart = (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpLoops
iFromIdx = 0
m = libc.Uint64FromInt32(1)
for {
if !(iFromIdx < nLoop) {
break
}
nDep = 0 /* Maximum SCAN cost of a fact table */
mSeen = uint64(0) /* The candidate fact table */
pFactTab = aFromTabs + uintptr(iFromIdx)*80
if libc.Int32FromUint8((*TSrcItem)(unsafe.Pointer(pFactTab)).Ffg.Fjointype)&(libc.Int32FromInt32(JT_OUTER)|libc.Int32FromInt32(JT_CROSS)) != 0 {
/* If the candidate fact-table is the right table of an outer join
** restrict the search for dimension-tables to be tables to the right
** of the fact-table. Constraint (bb) */
if iFromIdx+int32(3) > nLoop {
break /* ^-- Impossible to reach nDep>=2 - Constraint (cc) */
}
for pStart != 0 && libc.Int32FromUint8((*TWhereLoop)(unsafe.Pointer(pStart)).FiTab) <= iFromIdx {
pStart = (*TWhereLoop)(unsafe.Pointer(pStart)).FpNextLoop
}
}
pWLoop = pStart
for {
if !(pWLoop != 0) {
break
}
if libc.Int32FromUint8((**(**TSrcItem)(__ccgo_up(aFromTabs + uintptr((*TWhereLoop)(unsafe.Pointer(pWLoop)).FiTab)*80))).Ffg.Fjointype)&(libc.Int32FromInt32(JT_OUTER)|libc.Int32FromInt32(JT_CROSS)) != 0 {
break /* Constraint (bb) */
}
if (*TWhereLoop)(unsafe.Pointer(pWLoop)).Fprereq&m != uint64(0) && (*TWhereLoop)(unsafe.Pointer(pWLoop)).FmaskSelf&mSeen == uint64(0) && (*TWhereLoop)(unsafe.Pointer(pWLoop)).FmaskSelf&mSelfJoin == uint64(0) {
if (**(**TSrcItem)(__ccgo_up(aFromTabs + uintptr((*TWhereLoop)(unsafe.Pointer(pWLoop)).FiTab)*80))).FpSTab == (*TSrcItem)(unsafe.Pointer(pFactTab)).FpSTab {
mSelfJoin = mSelfJoin | m
} else {
nDep = nDep + 1
mSeen = mSeen | (*TWhereLoop)(unsafe.Pointer(pWLoop)).FmaskSelf
}
}
goto _2
_2:
;
pWLoop = (*TWhereLoop)(unsafe.Pointer(pWLoop)).FpNextLoop
}
if nDep <= int32(2) {
goto _1 /* Constraint (cc) */
}
/* If we reach this point, it means that pFactTab is a fact table
** with four or more dimensions connected by inner joins. Proceed
** to make cost adjustments. */
libc.SetBitFieldPtr8Uint32(pWInfo+68, libc.Uint32FromInt32(1), 5, 0x20)
/* Compute the maximum cost of any WhereLoop for the
** fact table plus one epsilon */
mxRun = int16(-libc.Int32FromInt32(32768))
pWLoop = pStart
for {
if !(pWLoop != 0) {
break
}
if libc.Int32FromUint8((*TWhereLoop)(unsafe.Pointer(pWLoop)).FiTab) < iFromIdx {
goto _3
}
if libc.Int32FromUint8((*TWhereLoop)(unsafe.Pointer(pWLoop)).FiTab) > iFromIdx {
break
}
if int32((*TWhereLoop)(unsafe.Pointer(pWLoop)).FrRun) > int32(mxRun) {
mxRun = (*TWhereLoop)(unsafe.Pointer(pWLoop)).FrRun
}
goto _3
_3:
;
pWLoop = (*TWhereLoop)(unsafe.Pointer(pWLoop)).FpNextLoop
}
if int32(mxRun) < int32(LOGEST_MAX) {
mxRun = mxRun + 1
}
/* Increase the cost of table scans for dimension tables to be
** slightly more than the maximum cost of the fact table */
pWLoop = pStart
for {
if !(pWLoop != 0) {
break
}
if (*TWhereLoop)(unsafe.Pointer(pWLoop)).FmaskSelf&mSeen == uint64(0) {
goto _4
}
if (*TWhereLoop)(unsafe.Pointer(pWLoop)).FnLTerm != 0 {
goto _4
}
if int32((*TWhereLoop)(unsafe.Pointer(pWLoop)).FrRun) < int32(mxRun) {
(*TWhereLoop)(unsafe.Pointer(pWLoop)).FrRun = mxRun
}
goto _4
_4:
;
pWLoop = (*TWhereLoop)(unsafe.Pointer(pWLoop)).FpNextLoop
}
goto _1
_1:
;
iFromIdx = iFromIdx + 1
m = m << uint64(1)
}
}
if int32(uint32(*(*uint8)(unsafe.Pointer(pWInfo + 68))&0x20>>5)) != 0 {
v5 = int32(18)
} else {
v5 = int32(12)
}
return v5
}
// C documentation
//
// /*
// ** This routine runs at the end of parsing a CREATE TABLE statement that
// ** has a WITHOUT ROWID clause. The job of this routine is to convert both
// ** internal schema data structures and the generated VDBE code so that they
// ** are appropriate for a WITHOUT ROWID table instead of a rowid table.
// ** Changes include:
// **
// ** (1) Set all columns of the PRIMARY KEY schema object to be NOT NULL.
// ** (2) Convert P3 parameter of the OP_CreateBtree from BTREE_INTKEY
// ** into BTREE_BLOBKEY.
// ** (3) Bypass the creation of the sqlite_schema table entry
// ** for the PRIMARY KEY as the primary key index is now
// ** identified by the sqlite_schema table entry of the table itself.
// ** (4) Set the Index.tnum of the PRIMARY KEY Index object in the
// ** schema to the rootpage from the main table.
// ** (5) Add all table columns to the PRIMARY KEY Index object
// ** so that the PRIMARY KEY is a covering index. The surplus
// ** columns are part of KeyInfo.nAllField and are not used for
// ** sorting or lookup or uniqueness checks.
// ** (6) Replace the rowid tail on all automatically generated UNIQUE
// ** indices with the PRIMARY KEY columns.
// **
// ** For virtual tables, only (1) is performed.
// */
func _convertToWithoutRowidTable(tls *libc.TLS, pParse uintptr, pTab uintptr) {
bp := tls.Alloc(16)
defer tls.Free(16)
var db, pIdx, pList, pPk, v, zColl, v12 uintptr
var i, j, n, nExtra, nPk, v3 int32
var v5 Tu16
var _ /* ipkToken at bp+0 */ TToken
_, _, _, _, _, _, _, _, _, _, _, _, _, _ = db, i, j, n, nExtra, nPk, pIdx, pList, pPk, v, zColl, v12, v3, v5
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
/* Mark every PRIMARY KEY column as NOT NULL (except for imposter tables)
*/
if !(int32(uint32(*(*uint8)(unsafe.Pointer(db + 192 + 8))&0x6>>1)) != 0) {
i = 0
for {
if !(i < int32((*TTable)(unsafe.Pointer(pTab)).FnCol)) {
break
}
if libc.Int32FromUint16((**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(i)*16))).FcolFlags)&int32(COLFLAG_PRIMKEY) != 0 && int32(uint32(*(*uint8)(unsafe.Pointer((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(i)*16 + 8))&0xf>>0)) == OE_None {
libc.SetBitFieldPtr8Uint32((*TTable)(unsafe.Pointer(pTab)).FaCol+uintptr(i)*16+8, libc.Uint32FromInt32(OE_Abort), 0, 0xf)
}
goto _1
_1:
;
i = i + 1
}
**(**Tu32)(__ccgo_up(pTab + 48)) |= uint32(TF_HasNotNull)
}
/* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY
** into BTREE_BLOBKEY.
*/
if (*(*struct {
FaddrCrTab int32
FregRowid int32
FregRoot int32
FconstraintName TToken
})(unsafe.Pointer(pParse + 256))).FaddrCrTab != 0 {
_sqlite3VdbeChangeP3(tls, v, (*(*struct {
FaddrCrTab int32
FregRowid int32
FregRoot int32
FconstraintName TToken
})(unsafe.Pointer(pParse + 256))).FaddrCrTab, int32(BTREE_BLOBKEY))
}
/* Locate the PRIMARY KEY index. Or, if this table was originally
** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index.
*/
if int32((*TTable)(unsafe.Pointer(pTab)).FiPKey) >= 0 {
_sqlite3TokenInit(tls, bp, (**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr((*TTable)(unsafe.Pointer(pTab)).FiPKey)*16))).FzCnName)
pList = _sqlite3ExprListAppend(tls, pParse, uintptr(0), _sqlite3ExprAlloc(tls, db, int32(TK_ID), bp, 0))
if pList == uintptr(0) {
**(**Tu32)(__ccgo_up(pTab + 48)) &= libc.Uint32FromInt32(^libc.Int32FromInt32(TF_WithoutRowid))
return
}
if libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= int32(PARSE_MODE_RENAME) {
_sqlite3RenameTokenRemap(tls, pParse, (*(*TExprList_item)(unsafe.Pointer(pList + 8))).FpExpr, pTab+52)
}
(*(*TExprList_item)(unsafe.Pointer(pList + 8))).Ffg.FsortFlags = (*TParse)(unsafe.Pointer(pParse)).FiPkSortOrder
(*TTable)(unsafe.Pointer(pTab)).FiPKey = int16(-int32(1))
_sqlite3CreateIndex(tls, pParse, uintptr(0), uintptr(0), uintptr(0), pList, libc.Int32FromUint8((*TTable)(unsafe.Pointer(pTab)).FkeyConf), uintptr(0), uintptr(0), 0, 0, uint8(SQLITE_IDXTYPE_PRIMARYKEY))
if (*TParse)(unsafe.Pointer(pParse)).FnErr != 0 {
**(**Tu32)(__ccgo_up(pTab + 48)) &= libc.Uint32FromInt32(^libc.Int32FromInt32(TF_WithoutRowid))
return
}
pPk = _sqlite3PrimaryKeyIndex(tls, pTab)
} else {
pPk = _sqlite3PrimaryKeyIndex(tls, pTab)
/*
** Remove all redundant columns from the PRIMARY KEY. For example, change
** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)". Later
** code assumes the PRIMARY KEY contains no repeated columns.
*/
v3 = libc.Int32FromInt32(1)
j = v3
i = v3
for {
if !(i < libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pPk)).FnKeyCol)) {
break
}
if _isDupColumn(tls, pPk, j, pPk, i) != 0 {
(*TIndex)(unsafe.Pointer(pPk)).FnColumn = (*TIndex)(unsafe.Pointer(pPk)).FnColumn - 1
} else {
**(**uintptr)(__ccgo_up((*TIndex)(unsafe.Pointer(pPk)).FazColl + uintptr(j)*8)) = **(**uintptr)(__ccgo_up((*TIndex)(unsafe.Pointer(pPk)).FazColl + uintptr(i)*8))
**(**Tu8)(__ccgo_up((*TIndex)(unsafe.Pointer(pPk)).FaSortOrder + uintptr(j))) = **(**Tu8)(__ccgo_up((*TIndex)(unsafe.Pointer(pPk)).FaSortOrder + uintptr(i)))
v3 = j
j = j + 1
**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pPk)).FaiColumn + uintptr(v3)*2)) = **(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pPk)).FaiColumn + uintptr(i)*2))
}
goto _2
_2:
;
i = i + 1
}
(*TIndex)(unsafe.Pointer(pPk)).FnKeyCol = libc.Uint16FromInt32(j)
}
libc.SetBitFieldPtr16Uint32(pPk+100, libc.Uint32FromInt32(1), 5, 0x20)
if !(int32(uint32(*(*uint8)(unsafe.Pointer(db + 192 + 8))&0x6>>1)) != 0) {
libc.SetBitFieldPtr16Uint32(pPk+100, libc.Uint32FromInt32(1), 3, 0x8)
}
v5 = (*TIndex)(unsafe.Pointer(pPk)).FnKeyCol
(*TIndex)(unsafe.Pointer(pPk)).FnColumn = v5
nPk = libc.Int32FromUint16(v5)
/* Bypass the creation of the PRIMARY KEY btree and the sqlite_schema
** table entry. This is only required if currently generating VDBE
** code for a CREATE TABLE (not when parsing one as part of reading
** a database schema). */
if v != 0 && (*TIndex)(unsafe.Pointer(pPk)).Ftnum > uint32(0) {
_sqlite3VdbeChangeOpcode(tls, v, libc.Int32FromUint32((*TIndex)(unsafe.Pointer(pPk)).Ftnum), uint8(OP_Goto))
}
/* The root page of the PRIMARY KEY is the table root page */
(*TIndex)(unsafe.Pointer(pPk)).Ftnum = (*TTable)(unsafe.Pointer(pTab)).Ftnum
/* Update the in-memory representation of all UNIQUE indices by converting
** the final rowid column into one or more columns of the PRIMARY KEY.
*/
pIdx = (*TTable)(unsafe.Pointer(pTab)).FpIndex
for {
if !(pIdx != 0) {
break
}
if int32(uint32(*(*uint16)(unsafe.Pointer(pIdx + 100))&0x3>>0)) == int32(SQLITE_IDXTYPE_PRIMARYKEY) {
goto _6
}
v3 = libc.Int32FromInt32(0)
n = v3
i = v3
for {
if !(i < nPk) {
break
}
if !(_isDupColumn(tls, pIdx, libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnKeyCol), pPk, i) != 0) {
n = n + 1
}
goto _7
_7:
;
i = i + 1
}
if n == 0 {
/* This index is a superset of the primary key */
(*TIndex)(unsafe.Pointer(pIdx)).FnColumn = (*TIndex)(unsafe.Pointer(pIdx)).FnKeyCol
goto _6
}
if _resizeIndexObject(tls, pParse, pIdx, libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnKeyCol)+n) != 0 {
return
}
i = 0
j = libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnKeyCol)
for {
if !(i < nPk) {
break
}
if !(_isDupColumn(tls, pIdx, libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnKeyCol), pPk, i) != 0) {
**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(j)*2)) = **(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pPk)).FaiColumn + uintptr(i)*2))
**(**uintptr)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FazColl + uintptr(j)*8)) = **(**uintptr)(__ccgo_up((*TIndex)(unsafe.Pointer(pPk)).FazColl + uintptr(i)*8))
if **(**Tu8)(__ccgo_up((*TIndex)(unsafe.Pointer(pPk)).FaSortOrder + uintptr(i))) != 0 {
/* See ticket https://sqlite.org/src/info/bba7b69f9849b5bf */
libc.SetBitFieldPtr16Uint32(pIdx+100, libc.Uint32FromInt32(1), 9, 0x200)
}
j = j + 1
}
goto _9
_9:
;
i = i + 1
}
goto _6
_6:
;
pIdx = (*TIndex)(unsafe.Pointer(pIdx)).FpNext
}
/* Add all table columns to the PRIMARY KEY index
*/
nExtra = 0
i = 0
for {
if !(i < int32((*TTable)(unsafe.Pointer(pTab)).FnCol)) {
break
}
if !(_hasColumn(tls, (*TIndex)(unsafe.Pointer(pPk)).FaiColumn, nPk, i) != 0) && libc.Int32FromUint16((**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(i)*16))).FcolFlags)&int32(COLFLAG_VIRTUAL) == 0 {
nExtra = nExtra + 1
}
goto _10
_10:
;
i = i + 1
}
if _resizeIndexObject(tls, pParse, pPk, nPk+nExtra) != 0 {
return
}
i = 0
j = nPk
for {
if !(i < int32((*TTable)(unsafe.Pointer(pTab)).FnCol)) {
break
}
if !(_hasColumn(tls, (*TIndex)(unsafe.Pointer(pPk)).FaiColumn, j, i) != 0) && libc.Int32FromUint16((**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(i)*16))).FcolFlags)&int32(COLFLAG_VIRTUAL) == 0 {
zColl = _sqlite3ColumnColl(tls, (*TTable)(unsafe.Pointer(pTab)).FaCol+uintptr(i)*16)
**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pPk)).FaiColumn + uintptr(j)*2)) = int16(i)
if zColl != 0 {
v12 = zColl
} else {
v12 = uintptr(unsafe.Pointer(&_sqlite3StrBINARY))
}
**(**uintptr)(__ccgo_up((*TIndex)(unsafe.Pointer(pPk)).FazColl + uintptr(j)*8)) = v12
j = j + 1
}
goto _11
_11:
;
i = i + 1
}
_recomputeColumnsNotIndexed(tls, pPk)
}
// C documentation
//
// /*
// ** Check to see if a subquery contains result-set columns that are
// ** never used. If it does, change the value of those result-set columns
// ** to NULL so that they do not cause unnecessary work to compute.
// **
// ** Return the number of column that were changed to NULL.
// */
func _disableUnusedSubqueryResultColumns(tls *libc.TLS, pItem uintptr) (r int32) {
var colUsed, m TBitmask
var iCol Tu16
var j, nChng, nCol, v3 int32
var pList, pSub, pTab, pX, pY uintptr
var v5 uint64
_, _, _, _, _, _, _, _, _, _, _, _, _ = colUsed, iCol, j, m, nChng, nCol, pList, pSub, pTab, pX, pY, v3, v5 /* Column number */
nChng = 0 /* Columns that may not be NULLed out */
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x10>>4) != 0 || int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x200>>9) != 0 {
return 0
}
pTab = (*TSrcItem)(unsafe.Pointer(pItem)).FpSTab
pSub = (*TSubquery)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pItem + 72)))).FpSelect
pX = pSub
for {
if !(pX != 0) {
break
}
if (*TSelect)(unsafe.Pointer(pX)).FselFlags&libc.Uint32FromInt32(libc.Int32FromInt32(SF_Distinct)|libc.Int32FromInt32(SF_Aggregate)) != uint32(0) {
return 0
}
if (*TSelect)(unsafe.Pointer(pX)).FpPrior != 0 && libc.Int32FromUint8((*TSelect)(unsafe.Pointer(pX)).Fop) != int32(TK_ALL) {
/* This optimization does not work for compound subqueries that
** use UNION, INTERSECT, or EXCEPT. Only UNION ALL is allowed. */
return 0
}
if (*TSelect)(unsafe.Pointer(pX)).FpWin != 0 {
/* This optimization does not work for subqueries that use window
** functions. */
return 0
}
goto _1
_1:
;
pX = (*TSelect)(unsafe.Pointer(pX)).FpPrior
}
colUsed = (*TSrcItem)(unsafe.Pointer(pItem)).FcolUsed
if (*TSelect)(unsafe.Pointer(pSub)).FpOrderBy != 0 {
pList = (*TSelect)(unsafe.Pointer(pSub)).FpOrderBy
j = 0
for {
if !(j < (*TExprList)(unsafe.Pointer(pList)).FnExpr) {
break
}
iCol = *(*Tu16)(unsafe.Pointer(pList + 8 + uintptr(j)*32 + 24))
if libc.Int32FromUint16(iCol) > 0 {
iCol = iCol - 1
if libc.Int32FromUint16(iCol) >= libc.Int32FromUint64(libc.Uint64FromInt64(8)*libc.Uint64FromInt32(8)) {
v3 = libc.Int32FromUint64(libc.Uint64FromInt64(8)*libc.Uint64FromInt32(8)) - libc.Int32FromInt32(1)
} else {
v3 = libc.Int32FromUint16(iCol)
}
colUsed = colUsed | libc.Uint64FromInt32(1)<<v3
}
goto _2
_2:
;
j = j + 1
}
}
nCol = int32((*TTable)(unsafe.Pointer(pTab)).FnCol)
j = 0
for {
if !(j < nCol) {
break
}
if j < libc.Int32FromUint64(libc.Uint64FromInt64(8)*libc.Uint64FromInt32(8))-libc.Int32FromInt32(1) {
v5 = libc.Uint64FromInt32(1) << j
} else {
v5 = libc.Uint64FromInt32(1) << (libc.Int32FromUint64(libc.Uint64FromInt64(8)*libc.Uint64FromInt32(8)) - libc.Int32FromInt32(1))
}
m = v5
if m&colUsed != uint64(0) {
goto _4
}
pX = pSub
for {
if !(pX != 0) {
break
}
pY = (*(*TExprList_item)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pX)).FpEList + 8 + uintptr(j)*32))).FpExpr
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pY)).Fop) == int32(TK_NULL) {
goto _6
}
(*TExpr)(unsafe.Pointer(pY)).Fop = uint8(TK_NULL)
**(**Tu32)(__ccgo_up(pY + 4)) &= ^libc.Uint32FromInt32(libc.Int32FromInt32(EP_Skip) | libc.Int32FromInt32(EP_Unlikely))
**(**Tu32)(__ccgo_up(pX + 4)) |= uint32(SF_PushDown)
nChng = nChng + 1
goto _6
_6:
;
pX = (*TSelect)(unsafe.Pointer(pX)).FpPrior
}
goto _4
_4:
;
j = j + 1
}
return nChng
}
// C documentation
//
// /*
// ** Return TRUE (non-zero) if the i-th entry in the pTabList SrcList can
// ** be implemented as a co-routine. The i-th entry is guaranteed to be
// ** a subquery.
// **
// ** The subquery is implemented as a co-routine if all of the following are
// ** true:
// **
// ** (1) The subquery will likely be implemented in the outer loop of
// ** the query. This will be the case if any one of the following
// ** conditions hold:
// ** (a) The subquery is the only term in the FROM clause
// ** (b) The subquery is the left-most term and a CROSS JOIN or similar
// ** requires it to be the outer loop
// ** (c) All of the following are true:
// ** (i) The subquery is the left-most subquery in the FROM clause
// ** (ii) There is nothing that would prevent the subquery from
// ** being used as the outer loop if the sqlite3WhereBegin()
// ** routine nominates it to that position.
// ** (iii) The query is not a UPDATE ... FROM
// ** (2) The subquery is not a CTE that should be materialized because
// ** (a) the AS MATERIALIZED keyword is used, or
// ** (b) the CTE is used multiple times and does not have the
// ** NOT MATERIALIZED keyword
// ** (3) The subquery is not part of a left operand for a RIGHT JOIN
// ** (4) The SQLITE_Coroutine optimization disable flag is not set
// ** (5) The subquery is not self-joined
// */
func _fromClauseTermCanBeCoroutine(tls *libc.TLS, pParse uintptr, pTabList uintptr, i int32, selFlags int32) (r int32) {
var pCteUse, pItem uintptr
_, _ = pCteUse, pItem
pItem = pTabList + 8 + uintptr(i)*80
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x200>>9) != 0 {
pCteUse = *(*uintptr)(unsafe.Pointer(pItem + 56))
if libc.Int32FromUint8((*TCteUse)(unsafe.Pointer(pCteUse)).FeM10d) == M10d_Yes {
return 0
} /* (2a) */
if (*TCteUse)(unsafe.Pointer(pCteUse)).FnUse >= int32(2) && libc.Int32FromUint8((*TCteUse)(unsafe.Pointer(pCteUse)).FeM10d) != int32(M10d_No) {
return 0
} /* (2b) */
}
if libc.Int32FromUint8((*(*TSrcItem)(unsafe.Pointer(pTabList + 8))).Ffg.Fjointype)&int32(JT_LTORJ) != 0 {
return 0
} /* (3) */
if (*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer(pParse)).Fdb)).FdbOptFlags&libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_Coroutines)) != uint32(0) {
return 0
} /* (4) */
if _isSelfJoinView(tls, pTabList, pItem, i+int32(1), (*TSrcList)(unsafe.Pointer(pTabList)).FnSrc) != uintptr(0) {
return 0 /* (5) */
}
if i == 0 {
if (*TSrcList)(unsafe.Pointer(pTabList)).FnSrc == int32(1) {
return int32(1)
} /* (1a) */
if libc.Int32FromUint8((*(*TSrcItem)(unsafe.Pointer(pTabList + 8 + 1*80))).Ffg.Fjointype)&int32(JT_CROSS) != 0 {
return int32(1)
} /* (1b) */
if selFlags&int32(SF_UpdateFrom) != 0 {
return 0
} /* (1c-iii) */
return int32(1)
}
if selFlags&int32(SF_UpdateFrom) != 0 {
return 0
} /* (1c-iii) */
for int32(1) != 0 {
if libc.Int32FromUint8((*TSrcItem)(unsafe.Pointer(pItem)).Ffg.Fjointype)&(libc.Int32FromInt32(JT_OUTER)|libc.Int32FromInt32(JT_CROSS)) != 0 {
return 0
} /* (1c-ii) */
if i == 0 {
break
}
i = i - 1
pItem -= 80
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x4>>2) != 0 {
return 0
} /* (1c-i) */
}
return int32(1)
}
// C documentation
//
// /*
// ** Return True if it is possible that pIndex might be useful in
// ** implementing the ORDER BY clause in pBuilder.
// **
// ** Return False if pBuilder does not contain an ORDER BY clause or
// ** if there is no way for pIndex to be useful in implementing that
// ** ORDER BY clause.
// */
func _indexMightHelpWithOrderBy(tls *libc.TLS, pBuilder uintptr, pIndex uintptr, iCursor int32) (r int32) {
var aColExpr, pExpr, pOB, v1 uintptr
var ii, jj int32
_, _, _, _, _, _ = aColExpr, ii, jj, pExpr, pOB, v1
if int32(uint32(*(*uint16)(unsafe.Pointer(pIndex + 100))&0x4>>2)) != 0 {
return 0
}
v1 = (*TWhereInfo)(unsafe.Pointer((*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FpWInfo)).FpOrderBy
pOB = v1
if v1 == uintptr(0) {
return 0
}
ii = 0
for {
if !(ii < (*TExprList)(unsafe.Pointer(pOB)).FnExpr) {
break
}
pExpr = _sqlite3ExprSkipCollateAndLikely(tls, (*(*TExprList_item)(unsafe.Pointer(pOB + 8 + uintptr(ii)*32))).FpExpr)
if pExpr == uintptr(0) {
goto _2
}
if (libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_COLUMN) || libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_AGG_COLUMN)) && (*TExpr)(unsafe.Pointer(pExpr)).FiTable == iCursor {
if int32((*TExpr)(unsafe.Pointer(pExpr)).FiColumn) < 0 {
return int32(1)
}
jj = 0
for {
if !(jj < libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIndex)).FnKeyCol)) {
break
}
if int32((*TExpr)(unsafe.Pointer(pExpr)).FiColumn) == int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIndex)).FaiColumn + uintptr(jj)*2))) {
return int32(1)
}
goto _3
_3:
;
jj = jj + 1
}
} else {
v1 = (*TIndex)(unsafe.Pointer(pIndex)).FaColExpr
aColExpr = v1
if v1 != uintptr(0) {
jj = 0
for {
if !(jj < libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIndex)).FnKeyCol)) {
break
}
if int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIndex)).FaiColumn + uintptr(jj)*2))) != -int32(2) {
goto _5
}
if _sqlite3ExprCompareSkip(tls, pExpr, (*(*TExprList_item)(unsafe.Pointer(aColExpr + 8 + uintptr(jj)*32))).FpExpr, iCursor) == 0 {
return int32(1)
}
goto _5
_5:
;
jj = jj + 1
}
}
}
goto _2
_2:
;
ii = ii + 1
}
return 0
}
// C documentation
//
// /*
// ** pX is the RHS of an IN operator. If pX is a SELECT statement
// ** that can be simplified to a direct table access, then return
// ** a pointer to the SELECT statement. If pX is not a SELECT statement,
// ** or if the SELECT statement needs to be materialized into a transient
// ** table, then return NULL.
// */
func _isCandidateForInOpt(tls *libc.TLS, pX uintptr) (r uintptr) {
var i int32
var p, pEList, pRes, pSrc, pTab uintptr
_, _, _, _, _, _ = i, p, pEList, pRes, pSrc, pTab
if !((*TExpr)(unsafe.Pointer(pX)).Fflags&libc.Uint32FromInt32(EP_xIsSelect) != libc.Uint32FromInt32(0)) {
return uintptr(0)
} /* Not a subquery */
if (*TExpr)(unsafe.Pointer(pX)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_VarSelect)) != uint32(0) {
return uintptr(0)
} /* Correlated subq */
p = *(*uintptr)(unsafe.Pointer(pX + 32))
if (*TSelect)(unsafe.Pointer(p)).FpPrior != 0 {
return uintptr(0)
} /* Not a compound SELECT */
if (*TSelect)(unsafe.Pointer(p)).FselFlags&libc.Uint32FromInt32(libc.Int32FromInt32(SF_Distinct)|libc.Int32FromInt32(SF_Aggregate)) != 0 {
return uintptr(0) /* No DISTINCT keyword and no aggregate functions */
}
/* Has no GROUP BY clause */
if (*TSelect)(unsafe.Pointer(p)).FpLimit != 0 {
return uintptr(0)
} /* Has no LIMIT clause */
if (*TSelect)(unsafe.Pointer(p)).FpWhere != 0 {
return uintptr(0)
} /* Has no WHERE clause */
pSrc = (*TSelect)(unsafe.Pointer(p)).FpSrc
if (*TSrcList)(unsafe.Pointer(pSrc)).FnSrc != int32(1) {
return uintptr(0)
} /* Single term in FROM clause */
if int32(*(*uint32)(unsafe.Pointer(pSrc + 8 + 24 + 4))&0x4>>2) != 0 {
return uintptr(0)
} /* FROM is not a subquery or view */
pTab = (*(*TSrcItem)(unsafe.Pointer(pSrc + 8))).FpSTab
/* FROM clause is not a view */
if libc.Int32FromUint8((*TTable)(unsafe.Pointer(pTab)).FeTabType) == int32(TABTYP_VTAB) {
return uintptr(0)
} /* FROM clause not a virtual table */
pEList = (*TSelect)(unsafe.Pointer(p)).FpEList
/* All SELECT results must be columns. */
i = 0
for {
if !(i < (*TExprList)(unsafe.Pointer(pEList)).FnExpr) {
break
}
pRes = (*(*TExprList_item)(unsafe.Pointer(pEList + 8 + uintptr(i)*32))).FpExpr
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pRes)).Fop) != int32(TK_COLUMN) {
return uintptr(0)
}
/* Not a correlated subquery */
goto _1
_1:
;
i = i + 1
}
return p
}
// C documentation
//
// /*
// ** The select statement passed as the first argument is an aggregate query.
// ** The second argument is the associated aggregate-info object. This
// ** function tests if the SELECT is of the form:
// **
// ** SELECT count(*) FROM <tbl>
// **
// ** where table is a database table, not a sub-select or view. If the query
// ** does match this pattern, then a pointer to the Table object representing
// ** <tbl> is returned. Otherwise, NULL is returned.
// **
// ** This routine checks to see if it is safe to use the count optimization.
// ** A correct answer is still obtained (though perhaps more slowly) if
// ** this routine returns NULL when it could have returned a table pointer.
// ** But returning the pointer when NULL should have been returned can
// ** result in incorrect answers and/or crashes. So, when in doubt, return NULL.
// */
func _isSimpleCount(tls *libc.TLS, p uintptr, pAggInfo uintptr) (r uintptr) {
var pExpr, pTab uintptr
_, _ = pExpr, pTab
if (*TSelect)(unsafe.Pointer(p)).FpWhere != 0 || (*TExprList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(p)).FpEList)).FnExpr != int32(1) || (*TSrcList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(p)).FpSrc)).FnSrc != int32(1) || int32(*(*uint32)(unsafe.Pointer((*TSelect)(unsafe.Pointer(p)).FpSrc + 8 + 24 + 4))&0x4>>2) != 0 || (*TAggInfo)(unsafe.Pointer(pAggInfo)).FnFunc != int32(1) || (*TSelect)(unsafe.Pointer(p)).FpHaving != 0 {
return uintptr(0)
}
pTab = (*(*TSrcItem)(unsafe.Pointer((*TSelect)(unsafe.Pointer(p)).FpSrc + 8))).FpSTab
if !(libc.Int32FromUint8((*TTable)(unsafe.Pointer(pTab)).FeTabType) == libc.Int32FromInt32(TABTYP_NORM)) {
return uintptr(0)
}
pExpr = (*(*TExprList_item)(unsafe.Pointer((*TSelect)(unsafe.Pointer(p)).FpEList + 8))).FpExpr
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) != int32(TK_AGG_FUNCTION) {
return uintptr(0)
}
if (*TExpr)(unsafe.Pointer(pExpr)).FpAggInfo != pAggInfo {
return uintptr(0)
}
if (*TFuncDef)(unsafe.Pointer((**(**TAggInfo_func)(__ccgo_up((*TAggInfo)(unsafe.Pointer(pAggInfo)).FaFunc))).FpFunc)).FfuncFlags&uint32(SQLITE_FUNC_COUNT) == uint32(0) {
return uintptr(0)
}
if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Distinct)|libc.Int32FromInt32(EP_WinFunc)) != uint32(0) {
return uintptr(0)
}
return pTab
}
// C documentation
//
// /*
// ** Set all pEList->a[].fg.eEName fields in the expression-list to val.
// */
func _renameSetENames(tls *libc.TLS, pEList uintptr, val int32) {
var i int32
_ = i
if pEList != 0 {
i = 0
for {
if !(i < (*TExprList)(unsafe.Pointer(pEList)).FnExpr) {
break
}
libc.SetBitFieldPtr16Uint32(pEList+8+uintptr(i)*32+16+4, libc.Uint32FromInt32(val&libc.Int32FromInt32(0x3)), 0, 0x3)
goto _1
_1:
;
i = i + 1
}
}
}
// C documentation
//
// /*
// ** Walker callback used by sqlite3RenameExprUnmap().
// */
func _renameUnmapSelectCb(tls *libc.TLS, pWalker uintptr, p uintptr) (r int32) {
var i int32
var pList, pParse, pSrc uintptr
_, _, _, _ = i, pList, pParse, pSrc
pParse = (*TWalker)(unsafe.Pointer(pWalker)).FpParse
if (*TParse)(unsafe.Pointer(pParse)).FnErr != 0 {
return int32(WRC_Abort)
}
if (*TSelect)(unsafe.Pointer(p)).FselFlags&libc.Uint32FromInt32(libc.Int32FromInt32(SF_View)|libc.Int32FromInt32(SF_CopyCte)) != 0 {
return int32(WRC_Prune)
}
if (*TSelect)(unsafe.Pointer(p)).FpEList != 0 {
pList = (*TSelect)(unsafe.Pointer(p)).FpEList
i = 0
for {
if !(i < (*TExprList)(unsafe.Pointer(pList)).FnExpr) {
break
}
if (*(*TExprList_item)(unsafe.Pointer(pList + 8 + uintptr(i)*32))).FzEName != 0 && int32(uint32(*(*uint16)(unsafe.Pointer(pList + 8 + uintptr(i)*32 + 16 + 4))&0x3>>0)) == ENAME_NAME {
_sqlite3RenameTokenRemap(tls, pParse, uintptr(0), (*(*TExprList_item)(unsafe.Pointer(pList + 8 + uintptr(i)*32))).FzEName)
}
goto _1
_1:
;
i = i + 1
}
}
if (*TSelect)(unsafe.Pointer(p)).FpSrc != 0 { /* Every Select as a SrcList, even if it is empty */
pSrc = (*TSelect)(unsafe.Pointer(p)).FpSrc
i = 0
for {
if !(i < (*TSrcList)(unsafe.Pointer(pSrc)).FnSrc) {
break
}
_sqlite3RenameTokenRemap(tls, pParse, uintptr(0), (*(*TSrcItem)(unsafe.Pointer(pSrc + 8 + uintptr(i)*80))).FzName)
if int32(*(*uint32)(unsafe.Pointer(pSrc + 8 + uintptr(i)*80 + 24 + 4))&0x800>>11) == 0 {
_sqlite3WalkExpr(tls, pWalker, *(*uintptr)(unsafe.Pointer(pSrc + 8 + uintptr(i)*80 + 64)))
} else {
_unmapColumnIdlistNames(tls, pParse, *(*uintptr)(unsafe.Pointer(pSrc + 8 + uintptr(i)*80 + 64)))
}
goto _2
_2:
;
i = i + 1
}
}
_renameWalkWith(tls, pWalker, p)
return WRC_Continue
}
// C documentation
//
// /*
// ** pEList is a list of expressions which are really the result set of the
// ** a SELECT statement. pE is a term in an ORDER BY or GROUP BY clause.
// ** This routine checks to see if pE is a simple identifier which corresponds
// ** to the AS-name of one of the terms of the expression list. If it is,
// ** this routine return an integer between 1 and N where N is the number of
// ** elements in pEList, corresponding to the matching entry. If there is
// ** no match, or if pE is not a simple identifier, then this routine
// ** return 0.
// **
// ** pEList has been resolved. pE has not.
// */
func _resolveAsName(tls *libc.TLS, pParse uintptr, pEList uintptr, pE uintptr) (r int32) {
var i int32
var zCol uintptr
_, _ = i, zCol /* Loop counter */
_ = pParse
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pE)).Fop) == int32(TK_ID) {
zCol = *(*uintptr)(unsafe.Pointer(pE + 8))
i = 0
for {
if !(i < (*TExprList)(unsafe.Pointer(pEList)).FnExpr) {
break
}
if int32(uint32(*(*uint16)(unsafe.Pointer(pEList + 8 + uintptr(i)*32 + 16 + 4))&0x3>>0)) == ENAME_NAME && Xsqlite3_stricmp(tls, (*(*TExprList_item)(unsafe.Pointer(pEList + 8 + uintptr(i)*32))).FzEName, zCol) == 0 {
return i + int32(1)
}
goto _1
_1:
;
i = i + 1
}
}
return 0
}
// C documentation
//
// /*
// ** This routine is called after all opcodes have been inserted. It loops
// ** through all the opcodes and fixes up some details.
// **
// ** (1) For each jump instruction with a negative P2 value (a label)
// ** resolve the P2 value to an actual address.
// **
// ** (2) Compute the maximum number of arguments used by the xUpdate/xFilter
// ** methods of any virtual table and store that value in *pMaxVtabArgs.
// **
// ** (3) Update the Vdbe.readOnly and Vdbe.bIsReader flags to accurately
// ** indicate what the prepared statement actually does.
// **
// ** (4) (discontinued)
// **
// ** (5) Reclaim the memory allocated for storing labels.
// **
// ** This routine will only function correctly if the mkopcodeh.tcl generator
// ** script numbers the opcodes correctly. Changes to this routine must be
// ** coordinated with changes to mkopcodeh.tcl.
// */
func _resolveP2Values(tls *libc.TLS, p uintptr, pMaxVtabArgs uintptr) {
var aLabel, pOp, pParse uintptr
var n, nMaxVtabArgs int32
_, _, _, _, _ = aLabel, n, nMaxVtabArgs, pOp, pParse
nMaxVtabArgs = **(**int32)(__ccgo_up(pMaxVtabArgs))
pParse = (*TVdbe)(unsafe.Pointer(p)).FpParse
aLabel = (*TParse)(unsafe.Pointer(pParse)).FaLabel
/* tag-20230419-1 */
libc.SetBitFieldPtr16Uint32(p+200, libc.Uint32FromInt32(1), 6, 0x40)
libc.SetBitFieldPtr16Uint32(p+200, libc.Uint32FromInt32(0), 7, 0x80)
pOp = (*TVdbe)(unsafe.Pointer(p)).FaOp + uintptr((*TVdbe)(unsafe.Pointer(p)).FnOp-int32(1))*24
for int32(1) != 0 {
/* Only JUMP opcodes and the short list of special opcodes in the switch
** below need to be considered. The mkopcodeh.tcl generator script groups
** all these opcodes together near the front of the opcode list. Skip
** any opcode that does not need processing by virtual of the fact that
** it is larger than SQLITE_MX_JUMP_OPCODE, as a performance optimization.
*/
if libc.Int32FromUint8((*TOp)(unsafe.Pointer(pOp)).Fopcode) <= int32(SQLITE_MX_JUMP_OPCODE) {
/* NOTE: Be sure to update mkopcodeh.tcl when adding or removing
** cases from this switch! */
switch libc.Int32FromUint8((*TOp)(unsafe.Pointer(pOp)).Fopcode) {
case int32(OP_Transaction):
if (*TOp)(unsafe.Pointer(pOp)).Fp2 != 0 {
libc.SetBitFieldPtr16Uint32(p+200, libc.Uint32FromInt32(0), 6, 0x40)
}
fallthrough
case int32(OP_AutoCommit):
fallthrough
case OP_Savepoint:
libc.SetBitFieldPtr16Uint32(p+200, libc.Uint32FromInt32(1), 7, 0x80)
case int32(OP_Checkpoint):
fallthrough
case int32(OP_Vacuum):
fallthrough
case int32(OP_JournalMode):
libc.SetBitFieldPtr16Uint32(p+200, libc.Uint32FromInt32(0), 6, 0x40)
libc.SetBitFieldPtr16Uint32(p+200, libc.Uint32FromInt32(1), 7, 0x80)
case int32(OP_Init):
goto resolve_p2_values_loop_exit
case int32(OP_VUpdate):
if (*TOp)(unsafe.Pointer(pOp)).Fp2 > nMaxVtabArgs {
nMaxVtabArgs = (*TOp)(unsafe.Pointer(pOp)).Fp2
}
case int32(OP_VFilter):
/* The instruction immediately prior to VFilter will be an
** OP_Integer that sets the "argc" value for the VFilter. See
** the code where OP_VFilter is generated at tag-20250207a. */
n = (**(**TOp)(__ccgo_up(pOp + uintptr(-libc.Int32FromInt32(1))*24))).Fp1
if n > nMaxVtabArgs {
nMaxVtabArgs = n
}
/* Fall through into the default case */
fallthrough
default:
if (*TOp)(unsafe.Pointer(pOp)).Fp2 < 0 {
/* The mkopcodeh.tcl script has so arranged things that the only
** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to
** have non-negative values for P2. */
/* True because of tag-20230419-1 */
(*TOp)(unsafe.Pointer(pOp)).Fp2 = **(**int32)(__ccgo_up(aLabel + uintptr(^(*TOp)(unsafe.Pointer(pOp)).Fp2)*4))
}
/* OPFLG_JUMP opcodes never have P2==0, though OPFLG_JUMP0 opcodes
** might */
/* Jumps never go off the end of the bytecode array */
break
}
/* The mkopcodeh.tcl script has so arranged things that the only
** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to
** have non-negative values for P2. */
}
pOp -= 24
}
goto resolve_p2_values_loop_exit
resolve_p2_values_loop_exit:
;
if aLabel != 0 {
_sqlite3DbNNFreeNN(tls, (*TVdbe)(unsafe.Pointer(p)).Fdb, (*TParse)(unsafe.Pointer(pParse)).FaLabel)
(*TParse)(unsafe.Pointer(pParse)).FaLabel = uintptr(0)
}
(*TParse)(unsafe.Pointer(pParse)).FnLabel = 0
**(**int32)(__ccgo_up(pMaxVtabArgs)) = nMaxVtabArgs
}
// C documentation
//
// /*
// ** This routine is called by the parser while in the middle of
// ** parsing a CREATE TABLE statement. A "NOT NULL" constraint has
// ** been seen on a column. This routine sets the notNull flag on
// ** the column currently under construction.
// */
func _sqlite3AddNotNull(tls *libc.TLS, pParse uintptr, onError int32) {
var p, pCol, pIdx uintptr
_, _, _ = p, pCol, pIdx
p = (*TParse)(unsafe.Pointer(pParse)).FpNewTable
if p == uintptr(0) || int32((*TTable)(unsafe.Pointer(p)).FnCol) < int32(1) {
return
}
pCol = (*TTable)(unsafe.Pointer(p)).FaCol + uintptr(int32((*TTable)(unsafe.Pointer(p)).FnCol)-int32(1))*16
libc.SetBitFieldPtr8Uint32(pCol+8, uint32(libc.Uint8FromInt32(onError)), 0, 0xf)
**(**Tu32)(__ccgo_up(p + 48)) |= uint32(TF_HasNotNull)
/* Set the uniqNotNull flag on any UNIQUE or PK indexes already created
** on this column. */
if libc.Int32FromUint16((*TColumn)(unsafe.Pointer(pCol)).FcolFlags)&int32(COLFLAG_UNIQUE) != 0 {
pIdx = (*TTable)(unsafe.Pointer(p)).FpIndex
for {
if !(pIdx != 0) {
break
}
if int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn))) == int32((*TTable)(unsafe.Pointer(p)).FnCol)-int32(1) {
libc.SetBitFieldPtr16Uint32(pIdx+100, libc.Uint32FromInt32(1), 3, 0x8)
}
goto _1
_1:
;
pIdx = (*TIndex)(unsafe.Pointer(pIdx)).FpNext
}
}
}
// C documentation
//
// /*
// ** The first argument, pCur, is a cursor opened on some b-tree. Count the
// ** number of entries in the b-tree and write the result to *pnEntry.
// **
// ** SQLITE_OK is returned if the operation is successfully executed.
// ** Otherwise, if an error is encountered (i.e. an IO error or database
// ** corruption) an SQLite error code is returned.
// */
func _sqlite3BtreeCount(tls *libc.TLS, db uintptr, pCur uintptr, pnEntry uintptr) (r int32) {
var iIdx, rc int32
var nEntry Ti64
var pPage uintptr
_, _, _, _ = iIdx, nEntry, pPage, rc
nEntry = 0 /* Return code */
rc = _moveToRoot(tls, pCur)
if rc == int32(SQLITE_EMPTY) {
**(**Ti64)(__ccgo_up(pnEntry)) = 0
return SQLITE_OK
}
/* Unless an error occurs, the following loop runs one iteration for each
** page in the B-Tree structure (not including overflow pages).
*/
for rc == SQLITE_OK && !(libc.AtomicLoadNInt32(db+432, libc.Int32FromInt32(__ATOMIC_RELAXED)) != 0) { /* Current page of the b-tree */
/* If this is a leaf page or the tree is not an int-key tree, then
** this page contains countable entries. Increment the entry counter
** accordingly.
*/
pPage = (*TBtCursor)(unsafe.Pointer(pCur)).FpPage
if (*TMemPage)(unsafe.Pointer(pPage)).Fleaf != 0 || !((*TMemPage)(unsafe.Pointer(pPage)).FintKey != 0) {
nEntry = nEntry + libc.Int64FromUint16((*TMemPage)(unsafe.Pointer(pPage)).FnCell)
}
/* pPage is a leaf node. This loop navigates the cursor so that it
** points to the first interior cell that it points to the parent of
** the next page in the tree that has not yet been visited. The
** pCur->aiIdx[pCur->iPage] value is set to the index of the parent cell
** of the page, or to the number of cells in the page if the next page
** to visit is the right-child of its parent.
**
** If all pages in the tree have been visited, return SQLITE_OK to the
** caller.
*/
if (*TMemPage)(unsafe.Pointer(pPage)).Fleaf != 0 {
for cond := true; cond; cond = libc.Int32FromUint16((*TBtCursor)(unsafe.Pointer(pCur)).Fix) >= libc.Int32FromUint16((*TMemPage)(unsafe.Pointer((*TBtCursor)(unsafe.Pointer(pCur)).FpPage)).FnCell) {
if int32((*TBtCursor)(unsafe.Pointer(pCur)).FiPage) == 0 {
/* All pages of the b-tree have been visited. Return successfully. */
**(**Ti64)(__ccgo_up(pnEntry)) = nEntry
return _moveToRoot(tls, pCur)
}
_moveToParent(tls, pCur)
}
(*TBtCursor)(unsafe.Pointer(pCur)).Fix = (*TBtCursor)(unsafe.Pointer(pCur)).Fix + 1
pPage = (*TBtCursor)(unsafe.Pointer(pCur)).FpPage
}
/* Descend to the child node of the cell that the cursor currently
** points at. This is the right-child if (iIdx==pPage->nCell).
*/
iIdx = libc.Int32FromUint16((*TBtCursor)(unsafe.Pointer(pCur)).Fix)
if iIdx == libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(pPage)).FnCell) {
rc = _moveToChild(tls, pCur, _sqlite3Get4byte(tls, (*TMemPage)(unsafe.Pointer(pPage)).FaData+uintptr(libc.Int32FromUint8((*TMemPage)(unsafe.Pointer(pPage)).FhdrOffset)+int32(8))))
} else {
rc = _moveToChild(tls, pCur, _sqlite3Get4byte(tls, (*TMemPage)(unsafe.Pointer(pPage)).FaData+uintptr(libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(pPage)).FmaskPage)&(libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TMemPage)(unsafe.Pointer(pPage)).FaCellIdx + uintptr(int32(2)*iIdx))))<<libc.Int32FromInt32(8)|libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TMemPage)(unsafe.Pointer(pPage)).FaCellIdx + uintptr(int32(2)*iIdx) + 1)))))))
}
}
/* An error has occurred. Return an error code. */
return rc
}
// C documentation
//
// /*
// ** Delete the entry that the cursor is pointing to.
// **
// ** If the BTREE_SAVEPOSITION bit of the flags parameter is zero, then
// ** the cursor is left pointing at an arbitrary location after the delete.
// ** But if that bit is set, then the cursor is left in a state such that
// ** the next call to BtreeNext() or BtreePrev() moves it to the same row
// ** as it would have been on if the call to BtreeDelete() had been omitted.
// **
// ** The BTREE_AUXDELETE bit of flags indicates that is one of several deletes
// ** associated with a single table entry and its indexes. Only one of those
// ** deletes is considered the "primary" delete. The primary delete occurs
// ** on a cursor that is not a BTREE_FORDELETE cursor. All but one delete
// ** operation on non-FORDELETE cursors is tagged with the AUXDELETE flag.
// ** The BTREE_AUXDELETE bit is a hint that is not used by this implementation,
// ** but which might be used by alternative storage engines.
// */
func _sqlite3BtreeDelete(tls *libc.TLS, pCur uintptr, flags Tu8) (r int32) {
bp := tls.Alloc(32)
defer tls.Free(32)
var bPreserve Tu8
var iCellDepth, iCellIdx, nCell int32
var n TPgno
var p, pBt, pCell, pLeaf, pPage, pTmp, v2 uintptr
var v1 Ti8
var _ /* info at bp+8 */ TCellInfo
var _ /* rc at bp+0 */ int32
_, _, _, _, _, _, _, _, _, _, _, _, _ = bPreserve, iCellDepth, iCellIdx, n, nCell, p, pBt, pCell, pLeaf, pPage, pTmp, v1, v2
p = (*TBtCursor)(unsafe.Pointer(pCur)).FpBtree
pBt = (*TBtree)(unsafe.Pointer(p)).FpBt /* Keep cursor valid. 2 for CURSOR_SKIPNEXT */
if libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCur)).FeState) != CURSOR_VALID {
if libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCur)).FeState) >= int32(CURSOR_REQUIRESEEK) {
**(**int32)(__ccgo_up(bp)) = _btreeRestoreCursorPosition(tls, pCur)
if **(**int32)(__ccgo_up(bp)) != 0 || libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCur)).FeState) != CURSOR_VALID {
return **(**int32)(__ccgo_up(bp))
}
} else {
return _sqlite3CorruptError(tls, int32(83240))
}
}
iCellDepth = int32((*TBtCursor)(unsafe.Pointer(pCur)).FiPage)
iCellIdx = libc.Int32FromUint16((*TBtCursor)(unsafe.Pointer(pCur)).Fix)
pPage = (*TBtCursor)(unsafe.Pointer(pCur)).FpPage
if libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(pPage)).FnCell) <= iCellIdx {
return _sqlite3CorruptError(tls, int32(83249))
}
pCell = (*TMemPage)(unsafe.Pointer(pPage)).FaData + uintptr(libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(pPage)).FmaskPage)&(libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TMemPage)(unsafe.Pointer(pPage)).FaCellIdx + uintptr(int32(2)*iCellIdx))))<<libc.Int32FromInt32(8)|libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TMemPage)(unsafe.Pointer(pPage)).FaCellIdx + uintptr(int32(2)*iCellIdx) + 1)))))
if (*TMemPage)(unsafe.Pointer(pPage)).FnFree < 0 && _btreeComputeFreeSpace(tls, pPage) != 0 {
return _sqlite3CorruptError(tls, int32(83253))
}
if pCell < (*TMemPage)(unsafe.Pointer(pPage)).FaCellIdx+uintptr((*TMemPage)(unsafe.Pointer(pPage)).FnCell) {
return _sqlite3CorruptError(tls, int32(83256))
}
/* If the BTREE_SAVEPOSITION bit is on, then the cursor position must
** be preserved following this delete operation. If the current delete
** will cause a b-tree rebalance, then this is done by saving the cursor
** key and leaving the cursor in CURSOR_REQUIRESEEK state before
** returning.
**
** If the current delete will not cause a rebalance, then the cursor
** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately
** before or after the deleted entry.
**
** The bPreserve value records which path is required:
**
** bPreserve==0 Not necessary to save the cursor position
** bPreserve==1 Use CURSOR_REQUIRESEEK to save the cursor position
** bPreserve==2 Cursor won't move. Set CURSOR_SKIPNEXT.
*/
bPreserve = libc.BoolUint8(libc.Int32FromUint8(flags)&int32(BTREE_SAVEPOSITION) != 0)
if bPreserve != 0 {
if !((*TMemPage)(unsafe.Pointer(pPage)).Fleaf != 0) || (*TMemPage)(unsafe.Pointer(pPage)).FnFree+libc.Int32FromUint16((*(*func(*libc.TLS, uintptr, uintptr) Tu16)(unsafe.Pointer(&struct{ uintptr }{(*TMemPage)(unsafe.Pointer(pPage)).FxCellSize})))(tls, pPage, pCell))+int32(2) > libc.Int32FromUint32((*TBtShared)(unsafe.Pointer(pBt)).FusableSize*libc.Uint32FromInt32(2)/libc.Uint32FromInt32(3)) || libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(pPage)).FnCell) == int32(1) {
/* A b-tree rebalance will be required after deleting this entry.
** Save the cursor key. */
**(**int32)(__ccgo_up(bp)) = _saveCursorKey(tls, pCur)
if **(**int32)(__ccgo_up(bp)) != 0 {
return **(**int32)(__ccgo_up(bp))
}
} else {
bPreserve = uint8(2)
}
}
/* If the page containing the entry to delete is not a leaf page, move
** the cursor to the largest entry in the tree that is smaller than
** the entry being deleted. This cell will replace the cell being deleted
** from the internal node. The 'previous' entry is used for this instead
** of the 'next' entry, as the previous entry is always a part of the
** sub-tree headed by the child page of the cell being deleted. This makes
** balancing the tree following the delete operation easier. */
if !((*TMemPage)(unsafe.Pointer(pPage)).Fleaf != 0) {
**(**int32)(__ccgo_up(bp)) = _sqlite3BtreePrevious(tls, pCur, 0)
if **(**int32)(__ccgo_up(bp)) != 0 {
return **(**int32)(__ccgo_up(bp))
}
}
/* Save the positions of any other cursors open on this table before
** making any modifications. */
if libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCur)).FcurFlags)&int32(BTCF_Multiple) != 0 {
**(**int32)(__ccgo_up(bp)) = _saveAllCursors(tls, pBt, (*TBtCursor)(unsafe.Pointer(pCur)).FpgnoRoot, pCur)
if **(**int32)(__ccgo_up(bp)) != 0 {
return **(**int32)(__ccgo_up(bp))
}
}
/* If this is a delete operation to remove a row from a table b-tree,
** invalidate any incrblob cursors open on the row being deleted. */
if (*TBtCursor)(unsafe.Pointer(pCur)).FpKeyInfo == uintptr(0) && (*TBtree)(unsafe.Pointer(p)).FhasIncrblobCur != 0 {
_invalidateIncrblobCursors(tls, p, (*TBtCursor)(unsafe.Pointer(pCur)).FpgnoRoot, (*TBtCursor)(unsafe.Pointer(pCur)).Finfo.FnKey, 0)
}
/* Make the page containing the entry to be deleted writable. Then free any
** overflow pages associated with the entry and finally remove the cell
** itself from within the page. */
**(**int32)(__ccgo_up(bp)) = _sqlite3PagerWrite(tls, (*TMemPage)(unsafe.Pointer(pPage)).FpDbPage)
if **(**int32)(__ccgo_up(bp)) != 0 {
return **(**int32)(__ccgo_up(bp))
}
(*(*func(*libc.TLS, uintptr, uintptr, uintptr))(unsafe.Pointer(&struct{ uintptr }{(*TMemPage)(unsafe.Pointer(pPage)).FxParseCell})))(tls, pPage, pCell, bp+8)
if uint32((**(**TCellInfo)(__ccgo_up(bp + 8))).FnLocal) != (**(**TCellInfo)(__ccgo_up(bp + 8))).FnPayload {
**(**int32)(__ccgo_up(bp)) = _clearCellOverflow(tls, pPage, pCell, bp+8)
} else {
**(**int32)(__ccgo_up(bp)) = SQLITE_OK
}
_dropCell(tls, pPage, iCellIdx, libc.Int32FromUint16((**(**TCellInfo)(__ccgo_up(bp + 8))).FnSize), bp)
if **(**int32)(__ccgo_up(bp)) != 0 {
return **(**int32)(__ccgo_up(bp))
}
/* If the cell deleted was not located on a leaf page, then the cursor
** is currently pointing to the largest entry in the sub-tree headed
** by the child-page of the cell that was just deleted from an internal
** node. The cell from the leaf node needs to be moved to the internal
** node to replace the deleted cell. */
if !((*TMemPage)(unsafe.Pointer(pPage)).Fleaf != 0) {
pLeaf = (*TBtCursor)(unsafe.Pointer(pCur)).FpPage
if (*TMemPage)(unsafe.Pointer(pLeaf)).FnFree < 0 {
**(**int32)(__ccgo_up(bp)) = _btreeComputeFreeSpace(tls, pLeaf)
if **(**int32)(__ccgo_up(bp)) != 0 {
return **(**int32)(__ccgo_up(bp))
}
}
if iCellDepth < int32((*TBtCursor)(unsafe.Pointer(pCur)).FiPage)-int32(1) {
n = (*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(pCur + 144 + uintptr(iCellDepth+int32(1))*8)))).Fpgno
} else {
n = (*TMemPage)(unsafe.Pointer((*TBtCursor)(unsafe.Pointer(pCur)).FpPage)).Fpgno
}
pCell = (*TMemPage)(unsafe.Pointer(pLeaf)).FaData + uintptr(libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(pLeaf)).FmaskPage)&(libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TMemPage)(unsafe.Pointer(pLeaf)).FaCellIdx + uintptr(int32(2)*(libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(pLeaf)).FnCell)-int32(1))))))<<libc.Int32FromInt32(8)|libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TMemPage)(unsafe.Pointer(pLeaf)).FaCellIdx + uintptr(int32(2)*(libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(pLeaf)).FnCell)-int32(1))) + 1)))))
if pCell < (*TMemPage)(unsafe.Pointer(pLeaf)).FaData+4 {
return _sqlite3CorruptError(tls, int32(83347))
}
nCell = libc.Int32FromUint16((*(*func(*libc.TLS, uintptr, uintptr) Tu16)(unsafe.Pointer(&struct{ uintptr }{(*TMemPage)(unsafe.Pointer(pLeaf)).FxCellSize})))(tls, pLeaf, pCell))
pTmp = (*TBtShared)(unsafe.Pointer(pBt)).FpTmpSpace
**(**int32)(__ccgo_up(bp)) = _sqlite3PagerWrite(tls, (*TMemPage)(unsafe.Pointer(pLeaf)).FpDbPage)
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
**(**int32)(__ccgo_up(bp)) = _insertCell(tls, pPage, iCellIdx, pCell-uintptr(4), nCell+int32(4), pTmp, n)
}
_dropCell(tls, pLeaf, libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(pLeaf)).FnCell)-int32(1), nCell, bp)
if **(**int32)(__ccgo_up(bp)) != 0 {
return **(**int32)(__ccgo_up(bp))
}
}
/* Balance the tree. If the entry deleted was located on a leaf page,
** then the cursor still points to that page. In this case the first
** call to balance() repairs the tree, and the if(...) condition is
** never true.
**
** Otherwise, if the entry deleted was on an internal node page, then
** pCur is pointing to the leaf page from which a cell was removed to
** replace the cell deleted from the internal node. This is slightly
** tricky as the leaf node may be underfull, and the internal node may
** be either under or overfull. In this case run the balancing algorithm
** on the leaf node first. If the balance proceeds far enough up the
** tree that we can be sure that any problem in the internal node has
** been corrected, so be it. Otherwise, after balancing the leaf node,
** walk the cursor up the tree to the internal node and balance it as
** well. */
if (*TMemPage)(unsafe.Pointer((*TBtCursor)(unsafe.Pointer(pCur)).FpPage)).FnFree*int32(3) <= libc.Int32FromUint32((*TBtShared)(unsafe.Pointer((*TBtCursor)(unsafe.Pointer(pCur)).FpBt)).FusableSize)*int32(2) {
/* Optimization: If the free space is less than 2/3rds of the page,
** then balance() will always be a no-op. No need to invoke it. */
**(**int32)(__ccgo_up(bp)) = SQLITE_OK
} else {
**(**int32)(__ccgo_up(bp)) = _balance(tls, pCur)
}
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK && int32((*TBtCursor)(unsafe.Pointer(pCur)).FiPage) > iCellDepth {
_releasePageNotNull(tls, (*TBtCursor)(unsafe.Pointer(pCur)).FpPage)
(*TBtCursor)(unsafe.Pointer(pCur)).FiPage = (*TBtCursor)(unsafe.Pointer(pCur)).FiPage - 1
for int32((*TBtCursor)(unsafe.Pointer(pCur)).FiPage) > iCellDepth {
v2 = pCur + 84
v1 = *(*Ti8)(unsafe.Pointer(v2))
*(*Ti8)(unsafe.Pointer(v2)) = *(*Ti8)(unsafe.Pointer(v2)) - 1
_releasePage(tls, **(**uintptr)(__ccgo_up(pCur + 144 + uintptr(v1)*8)))
}
(*TBtCursor)(unsafe.Pointer(pCur)).FpPage = **(**uintptr)(__ccgo_up(pCur + 144 + uintptr((*TBtCursor)(unsafe.Pointer(pCur)).FiPage)*8))
**(**int32)(__ccgo_up(bp)) = _balance(tls, pCur)
}
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
if libc.Int32FromUint8(bPreserve) > int32(1) {
(*TBtCursor)(unsafe.Pointer(pCur)).FeState = uint8(CURSOR_SKIPNEXT)
if iCellIdx >= libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(pPage)).FnCell) {
(*TBtCursor)(unsafe.Pointer(pCur)).FskipNext = -int32(1)
(*TBtCursor)(unsafe.Pointer(pCur)).Fix = libc.Uint16FromInt32(libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(pPage)).FnCell) - int32(1))
} else {
(*TBtCursor)(unsafe.Pointer(pCur)).FskipNext = int32(1)
}
} else {
**(**int32)(__ccgo_up(bp)) = _moveToRoot(tls, pCur)
if bPreserve != 0 {
_btreeReleaseAllCursorPages(tls, pCur)
(*TBtCursor)(unsafe.Pointer(pCur)).FeState = uint8(CURSOR_REQUIRESEEK)
}
if **(**int32)(__ccgo_up(bp)) == int32(SQLITE_EMPTY) {
**(**int32)(__ccgo_up(bp)) = SQLITE_OK
}
}
}
return **(**int32)(__ccgo_up(bp))
}
// C documentation
//
// /*
// ** Return the declared type of a column. Or return zDflt if the column
// ** has no declared type.
// **
// ** The column type is an extra string stored after the zero-terminator on
// ** the column name if and only if the COLFLAG_HASTYPE flag is set.
// */
func _sqlite3ColumnType(tls *libc.TLS, pCol uintptr, zDflt uintptr) (r uintptr) {
if libc.Int32FromUint16((*TColumn)(unsafe.Pointer(pCol)).FcolFlags)&int32(COLFLAG_HASTYPE) != 0 {
return (*TColumn)(unsafe.Pointer(pCol)).FzCnName + uintptr(libc.Xstrlen(tls, (*TColumn)(unsafe.Pointer(pCol)).FzCnName)) + uintptr(1)
} else {
if int32(uint32(*(*uint8)(unsafe.Pointer(pCol + 8))&0xf0>>4)) != 0 {
return _sqlite3StdType[int32(uint32(*(*uint8)(unsafe.Pointer(pCol + 8))&0xf0>>4))-int32(1)]
} else {
return zDflt
}
}
return r
}
// C documentation
//
// /*
// ** This routine generates code to finish the INSERT or UPDATE operation
// ** that was started by a prior call to sqlite3GenerateConstraintChecks.
// ** A consecutive range of registers starting at regNewData contains the
// ** rowid and the content to be inserted.
// **
// ** The arguments to this routine should be the same as the first six
// ** arguments to sqlite3GenerateConstraintChecks.
// */
func _sqlite3CompleteInsertion(tls *libc.TLS, pParse uintptr, pTab uintptr, iDataCur int32, iIdxCur int32, regNewData int32, aRegIdx uintptr, update_flags int32, appendBias int32, useSeekResult int32) {
var i, v2 int32
var pIdx, v uintptr
var pik_flags Tu8
_, _, _, _, _ = i, pIdx, pik_flags, v, v2 /* Loop counter */
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
/* This table is not a VIEW */
i = 0
pIdx = (*TTable)(unsafe.Pointer(pTab)).FpIndex
for {
if !(pIdx != 0) {
break
}
/* All REPLACE indexes are at the end of the list */
if **(**int32)(__ccgo_up(aRegIdx + uintptr(i)*4)) == 0 {
goto _1
}
if (*TIndex)(unsafe.Pointer(pIdx)).FpPartIdxWhere != 0 {
_sqlite3VdbeAddOp2(tls, v, int32(OP_IsNull), **(**int32)(__ccgo_up(aRegIdx + uintptr(i)*4)), _sqlite3VdbeCurrentAddr(tls, v)+int32(2))
}
if useSeekResult != 0 {
v2 = int32(OPFLAG_USESEEKRESULT)
} else {
v2 = 0
}
pik_flags = libc.Uint8FromInt32(v2)
if int32(uint32(*(*uint16)(unsafe.Pointer(pIdx + 100))&0x3>>0)) == int32(SQLITE_IDXTYPE_PRIMARYKEY) && !((*TTable)(unsafe.Pointer(pTab)).FtabFlags&libc.Uint32FromInt32(TF_WithoutRowid) == libc.Uint32FromInt32(0)) {
pik_flags = libc.Uint8FromInt32(int32(pik_flags) | libc.Int32FromInt32(OPFLAG_NCHANGE))
pik_flags = libc.Uint8FromInt32(int32(pik_flags) | update_flags&libc.Int32FromInt32(OPFLAG_SAVEPOSITION))
if update_flags == 0 {
_codeWithoutRowidPreupdate(tls, pParse, pTab, iIdxCur+i, **(**int32)(__ccgo_up(aRegIdx + uintptr(i)*4)))
}
}
if int32(uint32(*(*uint16)(unsafe.Pointer(pIdx + 100))&0x8>>3)) != 0 {
v2 = libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnKeyCol)
} else {
v2 = libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnColumn)
}
_sqlite3VdbeAddOp4Int(tls, v, int32(OP_IdxInsert), iIdxCur+i, **(**int32)(__ccgo_up(aRegIdx + uintptr(i)*4)), **(**int32)(__ccgo_up(aRegIdx + uintptr(i)*4))+int32(1), v2)
_sqlite3VdbeChangeP5(tls, v, uint16(pik_flags))
goto _1
_1:
;
pIdx = (*TIndex)(unsafe.Pointer(pIdx)).FpNext
i = i + 1
}
if !((*TTable)(unsafe.Pointer(pTab)).FtabFlags&libc.Uint32FromInt32(TF_WithoutRowid) == libc.Uint32FromInt32(0)) {
return
}
if (*TParse)(unsafe.Pointer(pParse)).Fnested != 0 {
pik_flags = uint8(0)
} else {
pik_flags = uint8(OPFLAG_NCHANGE)
if update_flags != 0 {
v2 = update_flags
} else {
v2 = int32(OPFLAG_LASTROWID)
}
pik_flags = libc.Uint8FromInt32(int32(pik_flags) | v2)
}
if appendBias != 0 {
pik_flags = libc.Uint8FromInt32(int32(pik_flags) | libc.Int32FromInt32(OPFLAG_APPEND))
}
if useSeekResult != 0 {
pik_flags = libc.Uint8FromInt32(int32(pik_flags) | libc.Int32FromInt32(OPFLAG_USESEEKRESULT))
}
_sqlite3VdbeAddOp3(tls, v, int32(OP_Insert), iDataCur, **(**int32)(__ccgo_up(aRegIdx + uintptr(i)*4)), regNewData)
if !((*TParse)(unsafe.Pointer(pParse)).Fnested != 0) {
_sqlite3VdbeAppendP4(tls, v, pTab, -int32(5))
}
_sqlite3VdbeChangeP5(tls, v, uint16(pik_flags))
}
// C documentation
//
// /* The input list pList is the list of result set terms from a RETURNING
// ** clause. The table that we are returning from is pTab.
// **
// ** This routine makes a copy of the pList, and at the same time expands
// ** any "*" wildcards to be the complete set of columns from pTab.
// */
func _sqlite3ExpandReturning(tls *libc.TLS, pParse uintptr, pList uintptr, pTab uintptr) (r uintptr) {
var db, pItem, pItem1, pNew, pNewExpr, pNewExpr1, pOldExpr uintptr
var i, jj int32
_, _, _, _, _, _, _, _, _ = db, i, jj, pItem, pItem1, pNew, pNewExpr, pNewExpr1, pOldExpr
pNew = uintptr(0)
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
i = 0
for {
if !(i < (*TExprList)(unsafe.Pointer(pList)).FnExpr) {
break
}
pOldExpr = (*(*TExprList_item)(unsafe.Pointer(pList + 8 + uintptr(i)*32))).FpExpr
if pOldExpr == uintptr(0) {
goto _1
}
if _isAsteriskTerm(tls, pParse, pOldExpr) != 0 {
jj = 0
for {
if !(jj < int32((*TTable)(unsafe.Pointer(pTab)).FnCol)) {
break
}
if libc.Int32FromUint16((*TColumn)(unsafe.Pointer((*TTable)(unsafe.Pointer(pTab)).FaCol+uintptr(jj)*16)).FcolFlags)&int32(COLFLAG_HIDDEN) != 0 {
goto _2
}
pNewExpr = _sqlite3Expr(tls, db, int32(TK_ID), (**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(jj)*16))).FzCnName)
pNew = _sqlite3ExprListAppend(tls, pParse, pNew, pNewExpr)
if !((*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0) {
pItem = pNew + 8 + uintptr((*TExprList)(unsafe.Pointer(pNew)).FnExpr-int32(1))*32
(*TExprList_item)(unsafe.Pointer(pItem)).FzEName = _sqlite3DbStrDup(tls, db, (**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(jj)*16))).FzCnName)
libc.SetBitFieldPtr16Uint32(pItem+16+4, libc.Uint32FromInt32(ENAME_NAME), 0, 0x3)
}
goto _2
_2:
;
jj = jj + 1
}
} else {
pNewExpr1 = _sqlite3ExprDup(tls, db, pOldExpr, 0)
pNew = _sqlite3ExprListAppend(tls, pParse, pNew, pNewExpr1)
if !((*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0) && (*(*TExprList_item)(unsafe.Pointer(pList + 8 + uintptr(i)*32))).FzEName != uintptr(0) {
pItem1 = pNew + 8 + uintptr((*TExprList)(unsafe.Pointer(pNew)).FnExpr-int32(1))*32
(*TExprList_item)(unsafe.Pointer(pItem1)).FzEName = _sqlite3DbStrDup(tls, db, (*(*TExprList_item)(unsafe.Pointer(pList + 8 + uintptr(i)*32))).FzEName)
libc.SetBitFieldPtr16Uint32(pItem1+16+4, libc.Uint32FromInt32(int32(uint32(*(*uint16)(unsafe.Pointer(pList + 8 + uintptr(i)*32 + 16 + 4))&0x3>>0))), 0, 0x3)
}
}
goto _1
_1:
;
i = i + 1
}
return pNew
}
// C documentation
//
// /*
// ** Mark every prepared statement associated with a database connection
// ** as expired.
// **
// ** An expired statement means that recompilation of the statement is
// ** recommend. Statements expire when things happen that make their
// ** programs obsolete. Removing user-defined functions or collating
// ** sequences, or changing an authorization function are the types of
// ** things that make prepared statements obsolete.
// **
// ** If iCode is 1, then expiration is advisory. The statement should
// ** be reprepared before being restarted, but if it is already running
// ** it is allowed to run to completion.
// **
// ** Internally, this function just sets the Vdbe.expired flag on all
// ** prepared statements. The flag is set to 1 for an immediate expiration
// ** and set to 2 for an advisory expiration.
// */
func _sqlite3ExpirePreparedStatements(tls *libc.TLS, db uintptr, iCode int32) {
var p uintptr
_ = p
p = (*Tsqlite3)(unsafe.Pointer(db)).FpVdbe
for {
if !(p != 0) {
break
}
libc.SetBitFieldPtr16Uint32(p+200, libc.Uint32FromInt32(iCode+libc.Int32FromInt32(1)), 0, 0x3)
goto _1
_1:
;
p = (*TVdbe)(unsafe.Pointer(p)).FpVNext
}
}
// C documentation
//
// /*
// ** Return FALSE if there is no chance that the expression can be NULL.
// **
// ** If the expression might be NULL or if the expression is too complex
// ** to tell return TRUE.
// **
// ** This routine is used as an optimization, to skip OP_IsNull opcodes
// ** when we know that a value cannot be NULL. Hence, a false positive
// ** (returning TRUE when in fact the expression can never be NULL) might
// ** be a small performance hit but is otherwise harmless. On the other
// ** hand, a false negative (returning FALSE when the result could be NULL)
// ** will likely result in an incorrect answer. So when in doubt, return
// ** TRUE.
// */
func _sqlite3ExprCanBeNull(tls *libc.TLS, p uintptr) (r int32) {
var op Tu8
_ = op
for libc.Int32FromUint8((*TExpr)(unsafe.Pointer(p)).Fop) == int32(TK_UPLUS) || libc.Int32FromUint8((*TExpr)(unsafe.Pointer(p)).Fop) == int32(TK_UMINUS) {
p = (*TExpr)(unsafe.Pointer(p)).FpLeft
}
op = (*TExpr)(unsafe.Pointer(p)).Fop
if libc.Int32FromUint8(op) == int32(TK_REGISTER) {
op = (*TExpr)(unsafe.Pointer(p)).Fop2
}
switch libc.Int32FromUint8(op) {
case int32(TK_INTEGER):
fallthrough
case int32(TK_STRING):
fallthrough
case int32(TK_FLOAT):
fallthrough
case int32(TK_BLOB):
return 0
case int32(TK_COLUMN):
return libc.BoolInt32((*TExpr)(unsafe.Pointer(p)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_CanBeNull)) != uint32(0) || *(*uintptr)(unsafe.Pointer(p + 64)) == uintptr(0) || int32((*TExpr)(unsafe.Pointer(p)).FiColumn) >= 0 && (*TTable)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(p + 64)))).FaCol != uintptr(0) && int32((*TExpr)(unsafe.Pointer(p)).FiColumn) < int32((*TTable)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(p + 64)))).FnCol) && int32(uint32(*(*uint8)(unsafe.Pointer((*TTable)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(p + 64)))).FaCol + uintptr((*TExpr)(unsafe.Pointer(p)).FiColumn)*16 + 8))&0xf>>0)) == 0)
default:
return int32(1)
}
return r
}
// C documentation
//
// /*
// ** Generate code that pushes the value of every element of the given
// ** expression list into a sequence of registers beginning at target.
// **
// ** Return the number of elements evaluated. The number returned will
// ** usually be pList->nExpr but might be reduced if SQLITE_ECEL_OMITREF
// ** is defined.
// **
// ** The SQLITE_ECEL_DUP flag prevents the arguments from being
// ** filled using OP_SCopy. OP_Copy must be used instead.
// **
// ** The SQLITE_ECEL_FACTOR argument allows constant arguments to be
// ** factored out into initialization code.
// **
// ** The SQLITE_ECEL_REF flag means that expressions in the list with
// ** ExprList.a[].u.x.iOrderByCol>0 have already been evaluated and stored
// ** in registers at srcReg, and so the value can be copied from there.
// ** If SQLITE_ECEL_OMITREF is also set, then the values with u.x.iOrderByCol>0
// ** are simply omitted rather than being copied from srcReg.
// */
func _sqlite3ExprCodeExprList(tls *libc.TLS, pParse uintptr, pList uintptr, target int32, srcReg int32, flags Tu8) (r int32) {
var copyOp Tu8
var i, inReg, j, n, v1 int32
var pExpr, pItem, pOp, v, v5 uintptr
var v4 bool
_, _, _, _, _, _, _, _, _, _, _, _ = copyOp, i, inReg, j, n, pExpr, pItem, pOp, v, v1, v4, v5
if libc.Int32FromUint8(flags)&int32(SQLITE_ECEL_DUP) != 0 {
v1 = int32(OP_Copy)
} else {
v1 = int32(OP_SCopy)
}
copyOp = libc.Uint8FromInt32(v1)
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
/* Never gets this far otherwise */
n = (*TExprList)(unsafe.Pointer(pList)).FnExpr
if !(int32(Tbft(*(*uint16)(unsafe.Pointer(pParse + 40))&0x80>>7)) != 0) {
flags = libc.Uint8FromInt32(int32(flags) & ^libc.Int32FromInt32(SQLITE_ECEL_FACTOR))
}
pItem = pList + 8
i = libc.Int32FromInt32(0)
for {
if !(i < n) {
break
}
pExpr = (*TExprList_item)(unsafe.Pointer(pItem)).FpExpr
if v4 = libc.Int32FromUint8(flags)&int32(SQLITE_ECEL_REF) != 0; v4 {
v1 = libc.Int32FromUint16((*(*struct {
FiOrderByCol Tu16
FiAlias Tu16
})(unsafe.Pointer(pItem + 24))).FiOrderByCol)
j = v1
}
if v4 && v1 > 0 {
if libc.Int32FromUint8(flags)&int32(SQLITE_ECEL_OMITREF) != 0 {
i = i - 1
n = n - 1
} else {
_sqlite3VdbeAddOp2(tls, v, libc.Int32FromUint8(copyOp), j+srcReg-int32(1), target+i)
}
} else {
if libc.Int32FromUint8(flags)&int32(SQLITE_ECEL_FACTOR) != 0 && _sqlite3ExprIsConstantNotJoin(tls, pParse, pExpr) != 0 {
_sqlite3ExprCodeRunJustOnce(tls, pParse, pExpr, target+i)
} else {
inReg = _sqlite3ExprCodeTarget(tls, pParse, pExpr, target+i)
if inReg != target+i {
if v4 = libc.Int32FromUint8(copyOp) == int32(OP_Copy); v4 {
v5 = _sqlite3VdbeGetLastOp(tls, v)
pOp = v5
}
if v4 && libc.Int32FromUint8((*TVdbeOp)(unsafe.Pointer(v5)).Fopcode) == int32(OP_Copy) && (*TVdbeOp)(unsafe.Pointer(pOp)).Fp1+(*TVdbeOp)(unsafe.Pointer(pOp)).Fp3+int32(1) == inReg && (*TVdbeOp)(unsafe.Pointer(pOp)).Fp2+(*TVdbeOp)(unsafe.Pointer(pOp)).Fp3+int32(1) == target+i && libc.Int32FromUint16((*TVdbeOp)(unsafe.Pointer(pOp)).Fp5) == 0 {
(*TVdbeOp)(unsafe.Pointer(pOp)).Fp3 = (*TVdbeOp)(unsafe.Pointer(pOp)).Fp3 + 1
} else {
_sqlite3VdbeAddOp2(tls, v, libc.Int32FromUint8(copyOp), inReg, target+i)
}
}
}
}
goto _2
_2:
;
i = i + 1
pItem += 32
}
return n
}
// C documentation
//
// /*
// ** Generate code that will evaluate expression pExpr just one time
// ** per prepared statement execution.
// **
// ** If the expression uses functions (that might throw an exception) then
// ** guard them with an OP_Once opcode to ensure that the code is only executed
// ** once. If no functions are involved, then factor the code out and put it at
// ** the end of the prepared statement in the initialization section.
// **
// ** If regDest>0 then the result is always stored in that register and the
// ** result is not reusable. If regDest<0 then this routine is free to
// ** store the value wherever it wants. The register where the expression
// ** is stored is returned. When regDest<0, two identical expressions might
// ** code to the same register, if they do not contain function calls and hence
// ** are factored out into the initialization section at the end of the
// ** prepared statement.
// */
func _sqlite3ExprCodeRunJustOnce(tls *libc.TLS, pParse uintptr, pExpr uintptr, regDest int32) (r int32) {
var addr, i, v2 int32
var p, pItem, pItem1, v, v3 uintptr
_, _, _, _, _, _, _, _ = addr, i, p, pItem, pItem1, v, v2, v3
p = (*TParse)(unsafe.Pointer(pParse)).FpConstExpr
if regDest < 0 && p != 0 {
pItem = p + 8
i = (*TExprList)(unsafe.Pointer(p)).FnExpr
for {
if !(i > 0) {
break
}
if int32(uint32(*(*uint16)(unsafe.Pointer(pItem + 16 + 4))&0x8>>3)) != 0 && _sqlite3ExprCompare(tls, uintptr(0), (*TExprList_item)(unsafe.Pointer(pItem)).FpExpr, pExpr, -int32(1)) == 0 {
return *(*int32)(unsafe.Pointer(pItem + 24))
}
goto _1
_1:
;
pItem += 32
i = i - 1
}
}
pExpr = _sqlite3ExprDup(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pExpr, 0)
if pExpr != uintptr(0) && (*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_HasFunc)) != uint32(0) {
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
addr = _sqlite3VdbeAddOp0(tls, v, int32(OP_Once))
libc.SetBitFieldPtr16Uint32(pParse+40, libc.Uint32FromInt32(0), 7, 0x80)
if !((*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer(pParse)).Fdb)).FmallocFailed != 0) {
if regDest < 0 {
v3 = pParse + 60
*(*int32)(unsafe.Pointer(v3)) = *(*int32)(unsafe.Pointer(v3)) + 1
v2 = *(*int32)(unsafe.Pointer(v3))
regDest = v2
}
_sqlite3ExprCode(tls, pParse, pExpr, regDest)
}
libc.SetBitFieldPtr16Uint32(pParse+40, libc.Uint32FromInt32(1), 7, 0x80)
_sqlite3ExprDelete(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pExpr)
_sqlite3VdbeJumpHere(tls, v, addr)
} else {
p = _sqlite3ExprListAppend(tls, pParse, p, pExpr)
if p != 0 {
pItem1 = p + 8 + uintptr((*TExprList)(unsafe.Pointer(p)).FnExpr-int32(1))*32
libc.SetBitFieldPtr16Uint32(pItem1+16+4, libc.BoolUint32(regDest < libc.Int32FromInt32(0)), 3, 0x8)
if regDest < 0 {
v3 = pParse + 60
*(*int32)(unsafe.Pointer(v3)) = *(*int32)(unsafe.Pointer(v3)) + 1
v2 = *(*int32)(unsafe.Pointer(v3))
regDest = v2
}
*(*int32)(unsafe.Pointer(pItem1 + 24)) = regDest
}
(*TParse)(unsafe.Pointer(pParse)).FpConstExpr = p
}
return regDest
}
// C documentation
//
// /*
// ** Generate code to evaluate an expression and store the results
// ** into a register. Return the register number where the results
// ** are stored.
// **
// ** If the register is a temporary register that can be deallocated,
// ** then write its number into *pReg. If the result register is not
// ** a temporary, then set *pReg to zero.
// **
// ** If pExpr is a constant, then this routine might generate this
// ** code to fill the register in the initialization section of the
// ** VDBE program, in order to factor it out of the evaluation loop.
// */
func _sqlite3ExprCodeTemp(tls *libc.TLS, pParse uintptr, pExpr uintptr, pReg uintptr) (r int32) {
var r1, r2 int32
_, _ = r1, r2
pExpr = _sqlite3ExprSkipCollateAndLikely(tls, pExpr)
if int32(Tbft(*(*uint16)(unsafe.Pointer(pParse + 40))&0x80>>7)) != 0 && pExpr != uintptr(0) && libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) != int32(TK_REGISTER) && _sqlite3ExprIsConstantNotJoin(tls, pParse, pExpr) != 0 {
**(**int32)(__ccgo_up(pReg)) = 0
r2 = _sqlite3ExprCodeRunJustOnce(tls, pParse, pExpr, -int32(1))
} else {
r1 = _sqlite3GetTempReg(tls, pParse)
r2 = _sqlite3ExprCodeTarget(tls, pParse, pExpr, r1)
if r2 == r1 {
**(**int32)(__ccgo_up(pReg)) = r1
} else {
_sqlite3ReleaseTempReg(tls, pParse, r1)
**(**int32)(__ccgo_up(pReg)) = 0
}
}
return r2
}
// C documentation
//
// /*
// ** Set the sort order for the last element on the given ExprList.
// */
func _sqlite3ExprListSetSortOrder(tls *libc.TLS, p uintptr, iSortOrder int32, eNulls int32) {
var pItem, v1 uintptr
_, _ = pItem, v1
if p == uintptr(0) {
return
}
pItem = p + 8 + uintptr((*TExprList)(unsafe.Pointer(p)).FnExpr-int32(1))*32
if iSortOrder == -int32(1) {
iSortOrder = SQLITE_SO_ASC
}
(*TExprList_item)(unsafe.Pointer(pItem)).Ffg.FsortFlags = libc.Uint8FromInt32(iSortOrder)
if eNulls != -int32(1) {
libc.SetBitFieldPtr16Uint32(pItem+16+4, libc.Uint32FromInt32(1), 5, 0x20)
if iSortOrder != eNulls {
v1 = pItem + 16
*(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) | libc.Int32FromInt32(KEYINFO_ORDER_BIGNULL))
}
}
}
// C documentation
//
// /*
// ** This routine is called after a single SQL statement has been
// ** parsed and a VDBE program to execute that statement has been
// ** prepared. This routine puts the finishing touches on the
// ** VDBE program and resets the pParse structure for the next
// ** parse.
// **
// ** Note that if an error occurred, it might be the case that
// ** no VDBE code was generated.
// */
func _sqlite3FinishCoding(tls *libc.TLS, pParse uintptr) {
var addrRewind, i, iDb, reg, v2 int32
var db, pEL, pRet, pReturning, pSchema, v, vtab uintptr
_, _, _, _, _, _, _, _, _, _, _, _ = addrRewind, db, i, iDb, pEL, pRet, pReturning, pSchema, reg, v, vtab, v2
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
if (*TParse)(unsafe.Pointer(pParse)).Fnested != 0 {
return
}
if (*TParse)(unsafe.Pointer(pParse)).FnErr != 0 {
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
(*TParse)(unsafe.Pointer(pParse)).Frc = int32(SQLITE_NOMEM)
}
return
}
/* Begin by generating some termination code at the end of the
** vdbe program
*/
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
if v == uintptr(0) {
if (*Tsqlite3)(unsafe.Pointer(db)).Finit1.Fbusy != 0 {
(*TParse)(unsafe.Pointer(pParse)).Frc = int32(SQLITE_DONE)
return
}
v = _sqlite3GetVdbe(tls, pParse)
if v == uintptr(0) {
(*TParse)(unsafe.Pointer(pParse)).Frc = int32(SQLITE_ERROR)
}
}
if v != 0 {
if int32(Tbft(*(*uint16)(unsafe.Pointer(pParse + 40))&0x8>>3)) != 0 {
pReturning = (*(*struct {
FpReturning uintptr
})(unsafe.Pointer(&(*TParse)(unsafe.Pointer(pParse)).Fu1))).FpReturning
if (*TReturning)(unsafe.Pointer(pReturning)).FnRetCol != 0 {
_sqlite3VdbeAddOp0(tls, v, int32(OP_FkCheck))
addrRewind = _sqlite3VdbeAddOp1(tls, v, int32(OP_Rewind), (*TReturning)(unsafe.Pointer(pReturning)).FiRetCur)
reg = (*TReturning)(unsafe.Pointer(pReturning)).FiRetReg
i = 0
for {
if !(i < (*TReturning)(unsafe.Pointer(pReturning)).FnRetCol) {
break
}
_sqlite3VdbeAddOp3(tls, v, int32(OP_Column), (*TReturning)(unsafe.Pointer(pReturning)).FiRetCur, i, reg+i)
goto _1
_1:
;
i = i + 1
}
_sqlite3VdbeAddOp2(tls, v, int32(OP_ResultRow), reg, i)
_sqlite3VdbeAddOp2(tls, v, int32(OP_Next), (*TReturning)(unsafe.Pointer(pReturning)).FiRetCur, addrRewind+int32(1))
_sqlite3VdbeJumpHere(tls, v, addrRewind)
}
}
_sqlite3VdbeAddOp0(tls, v, int32(OP_Halt))
/* The cookie mask contains one bit for each database file open.
** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are
** set for each database that is used. Generate code to start a
** transaction on each used database and to verify the schema cookie
** on each used database.
*/
_sqlite3VdbeJumpHere(tls, v, 0)
iDb = 0
for {
if libc.BoolInt32((*TParse)(unsafe.Pointer(pParse)).FcookieMask&(libc.Uint32FromInt32(1)<<iDb) != uint32(0)) == 0 {
goto _3
}
_sqlite3VdbeUsesBtree(tls, v, iDb)
pSchema = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FpSchema
_sqlite3VdbeAddOp4Int(tls, v, int32(OP_Transaction), iDb, libc.BoolInt32((*TParse)(unsafe.Pointer(pParse)).FwriteMask&(libc.Uint32FromInt32(1)<<iDb) != uint32(0)), (*TSchema)(unsafe.Pointer(pSchema)).Fschema_cookie, (*TSchema)(unsafe.Pointer(pSchema)).FiGeneration)
if libc.Int32FromUint8((*Tsqlite3)(unsafe.Pointer(db)).Finit1.Fbusy) == 0 {
_sqlite3VdbeChangeP5(tls, v, uint16(1))
}
goto _3
_3:
;
iDb = iDb + 1
v2 = iDb
if !(v2 < (*Tsqlite3)(unsafe.Pointer(db)).FnDb) {
break
}
}
i = 0
for {
if !(i < (*TParse)(unsafe.Pointer(pParse)).FnVtabLock) {
break
}
vtab = _sqlite3GetVTable(tls, db, **(**uintptr)(__ccgo_up((*TParse)(unsafe.Pointer(pParse)).FapVtabLock + uintptr(i)*8)))
_sqlite3VdbeAddOp4(tls, v, int32(OP_VBegin), 0, 0, 0, vtab, -int32(12))
goto _4
_4:
;
i = i + 1
}
(*TParse)(unsafe.Pointer(pParse)).FnVtabLock = 0
/* Once all the cookies have been verified and transactions opened,
** obtain the required table-locks. This is a no-op unless the
** shared-cache feature is enabled.
*/
if (*TParse)(unsafe.Pointer(pParse)).FnTableLock != 0 {
_codeTableLocks(tls, pParse)
}
/* Initialize any AUTOINCREMENT data structures required.
*/
if (*TParse)(unsafe.Pointer(pParse)).FpAinc != 0 {
_sqlite3AutoincrementBegin(tls, pParse)
}
/* Code constant expressions that were factored out of inner loops.
*/
if (*TParse)(unsafe.Pointer(pParse)).FpConstExpr != 0 {
pEL = (*TParse)(unsafe.Pointer(pParse)).FpConstExpr
libc.SetBitFieldPtr16Uint32(pParse+40, libc.Uint32FromInt32(0), 7, 0x80)
i = 0
for {
if !(i < (*TExprList)(unsafe.Pointer(pEL)).FnExpr) {
break
}
_sqlite3ExprCode(tls, pParse, (*(*TExprList_item)(unsafe.Pointer(pEL + 8 + uintptr(i)*32))).FpExpr, *(*int32)(unsafe.Pointer(pEL + 8 + uintptr(i)*32 + 24)))
goto _5
_5:
;
i = i + 1
}
}
if int32(Tbft(*(*uint16)(unsafe.Pointer(pParse + 40))&0x8>>3)) != 0 {
pRet = (*(*struct {
FpReturning uintptr
})(unsafe.Pointer(&(*TParse)(unsafe.Pointer(pParse)).Fu1))).FpReturning
if (*TReturning)(unsafe.Pointer(pRet)).FnRetCol != 0 {
_sqlite3VdbeAddOp2(tls, v, int32(OP_OpenEphemeral), (*TReturning)(unsafe.Pointer(pRet)).FiRetCur, (*TReturning)(unsafe.Pointer(pRet)).FnRetCol)
}
}
/* Finally, jump back to the beginning of the executable code. */
_sqlite3VdbeGoto(tls, v, int32(1))
}
/* Get the VDBE program ready for execution
*/
if (*TParse)(unsafe.Pointer(pParse)).FnErr == 0 {
/* A minimum of one cursor is required if autoincrement is used
* See ticket [a696379c1f08866] */
_sqlite3VdbeMakeReady(tls, v, pParse)
(*TParse)(unsafe.Pointer(pParse)).Frc = int32(SQLITE_DONE)
} else {
(*TParse)(unsafe.Pointer(pParse)).Frc = int32(SQLITE_ERROR)
}
}
// C documentation
//
// /*
// ** This function is called when inserting, deleting or updating a row of
// ** table pTab to generate VDBE code to perform foreign key constraint
// ** processing for the operation.
// **
// ** For a DELETE operation, parameter regOld is passed the index of the
// ** first register in an array of (pTab->nCol+1) registers containing the
// ** rowid of the row being deleted, followed by each of the column values
// ** of the row being deleted, from left to right. Parameter regNew is passed
// ** zero in this case.
// **
// ** For an INSERT operation, regOld is passed zero and regNew is passed the
// ** first register of an array of (pTab->nCol+1) registers containing the new
// ** row data.
// **
// ** For an UPDATE operation, this function is called twice. Once before
// ** the original record is deleted from the table using the calling convention
// ** described for DELETE. Then again after the original record is deleted
// ** but before the new record is inserted using the INSERT convention.
// */
func _sqlite3FkCheck(tls *libc.TLS, pParse uintptr, pTab uintptr, regOld int32, regNew int32, aChange uintptr, bChngRowid int32) {
bp := tls.Alloc(48)
defer tls.Free(48)
var aiCol, db, pFKey, pItem, pSrc, pTo, v, zCol, zDb, v7 uintptr
var bIgnore, eAction, i, iDb, iFromCol, iJump, iReg, isIgnoreErrors, rcauth, v4 int32
var _ /* aiCol at bp+32 */ uintptr
var _ /* aiFree at bp+8 */ uintptr
var _ /* iCol at bp+16 */ int32
var _ /* pIdx at bp+0 */ uintptr
var _ /* pIdx at bp+24 */ uintptr
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = aiCol, bIgnore, db, eAction, i, iDb, iFromCol, iJump, iReg, isIgnoreErrors, pFKey, pItem, pSrc, pTo, rcauth, v, zCol, zDb, v4, v7
db = (*TParse)(unsafe.Pointer(pParse)).Fdb /* Name of database containing pTab */
isIgnoreErrors = int32(Tbft(*(*uint16)(unsafe.Pointer(pParse + 40)) & 0x1 >> 0))
/* Exactly one of regOld and regNew should be non-zero. */
/* If foreign-keys are disabled, this function is a no-op. */
if (*Tsqlite3)(unsafe.Pointer(db)).Fflags&uint64(SQLITE_ForeignKeys) == uint64(0) {
return
}
if !(libc.Int32FromUint8((*TTable)(unsafe.Pointer(pTab)).FeTabType) == libc.Int32FromInt32(TABTYP_NORM)) {
return
}
iDb = _sqlite3SchemaToIndex(tls, db, (*TTable)(unsafe.Pointer(pTab)).FpSchema)
zDb = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FzDbSName
/* Loop through all the foreign key constraints for which pTab is the
** child table (the table that the foreign key definition is part of). */
pFKey = (*(*struct {
FaddColOffset int32
FpFKey uintptr
FpDfltList uintptr
})(unsafe.Pointer(pTab + 64))).FpFKey
for {
if !(pFKey != 0) {
break
} /* Parent table of foreign key pFKey */
**(**uintptr)(__ccgo_up(bp)) = uintptr(0) /* Index on key columns in pTo */
**(**uintptr)(__ccgo_up(bp + 8)) = uintptr(0)
bIgnore = 0
if aChange != 0 && Xsqlite3_stricmp(tls, (*TTable)(unsafe.Pointer(pTab)).FzName, (*TFKey)(unsafe.Pointer(pFKey)).FzTo) != 0 && _fkChildIsModified(tls, pTab, pFKey, aChange, bChngRowid) == 0 {
goto _1
}
/* Find the parent table of this foreign key. Also find a unique index
** on the parent key columns in the parent table. If either of these
** schema items cannot be located, set an error in pParse and return
** early. */
if int32(Tbft(*(*uint16)(unsafe.Pointer(pParse + 40))&0x1>>0)) != 0 {
pTo = _sqlite3FindTable(tls, db, (*TFKey)(unsafe.Pointer(pFKey)).FzTo, zDb)
} else {
pTo = _sqlite3LocateTable(tls, pParse, uint32(0), (*TFKey)(unsafe.Pointer(pFKey)).FzTo, zDb)
}
if !(pTo != 0) || _sqlite3FkLocateIndex(tls, pParse, pTo, pFKey, bp, bp+8) != 0 {
if !(isIgnoreErrors != 0) || (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
return
}
if pTo == uintptr(0) {
/* If isIgnoreErrors is true, then a table is being dropped. In this
** case SQLite runs a "DELETE FROM xxx" on the table being dropped
** before actually dropping it in order to check FK constraints.
** If the parent table of an FK constraint on the current table is
** missing, behave as if it is empty. i.e. decrement the relevant
** FK counter for each row of the current table with non-NULL keys.
*/
v = _sqlite3GetVdbe(tls, pParse)
iJump = _sqlite3VdbeCurrentAddr(tls, v) + (*TFKey)(unsafe.Pointer(pFKey)).FnCol + int32(1)
i = 0
for {
if !(i < (*TFKey)(unsafe.Pointer(pFKey)).FnCol) {
break
}
iFromCol = (*(*TsColMap)(unsafe.Pointer(pFKey + 64 + uintptr(i)*16))).FiFrom
iReg = int32(_sqlite3TableColumnToStorage(tls, (*TFKey)(unsafe.Pointer(pFKey)).FpFrom, int16(iFromCol))) + regOld + int32(1)
_sqlite3VdbeAddOp2(tls, v, int32(OP_IsNull), iReg, iJump)
goto _2
_2:
;
i = i + 1
}
_sqlite3VdbeAddOp2(tls, v, int32(OP_FkCounter), libc.Int32FromUint8((*TFKey)(unsafe.Pointer(pFKey)).FisDeferred), -int32(1))
}
goto _1
}
if **(**uintptr)(__ccgo_up(bp + 8)) != 0 {
aiCol = **(**uintptr)(__ccgo_up(bp + 8))
} else {
**(**int32)(__ccgo_up(bp + 16)) = (*(*TsColMap)(unsafe.Pointer(pFKey + 64))).FiFrom
aiCol = bp + 16
}
i = 0
for {
if !(i < (*TFKey)(unsafe.Pointer(pFKey)).FnCol) {
break
}
if **(**int32)(__ccgo_up(aiCol + uintptr(i)*4)) == int32((*TTable)(unsafe.Pointer(pTab)).FiPKey) {
**(**int32)(__ccgo_up(aiCol + uintptr(i)*4)) = -int32(1)
}
/* Request permission to read the parent key columns. If the
** authorization callback returns SQLITE_IGNORE, behave as if any
** values read from the parent table are NULL. */
if (*Tsqlite3)(unsafe.Pointer(db)).FxAuth != 0 {
if **(**uintptr)(__ccgo_up(bp)) != 0 {
v4 = int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FaiColumn + uintptr(i)*2)))
} else {
v4 = int32((*TTable)(unsafe.Pointer(pTo)).FiPKey)
}
zCol = (**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTo)).FaCol + uintptr(v4)*16))).FzCnName
rcauth = _sqlite3AuthReadCol(tls, pParse, (*TTable)(unsafe.Pointer(pTo)).FzName, zCol, iDb)
bIgnore = libc.BoolInt32(rcauth == int32(SQLITE_IGNORE))
}
goto _3
_3:
;
i = i + 1
}
/* Take a shared-cache advisory read-lock on the parent table. Allocate
** a cursor to use to search the unique index on the parent key columns
** in the parent table. */
_sqlite3TableLock(tls, pParse, iDb, (*TTable)(unsafe.Pointer(pTo)).Ftnum, uint8(0), (*TTable)(unsafe.Pointer(pTo)).FzName)
(*TParse)(unsafe.Pointer(pParse)).FnTab = (*TParse)(unsafe.Pointer(pParse)).FnTab + 1
if regOld != 0 {
/* A row is being removed from the child table. Search for the parent.
** If the parent does not exist, removing the child row resolves an
** outstanding foreign key constraint violation. */
_fkLookupParent(tls, pParse, iDb, pTo, **(**uintptr)(__ccgo_up(bp)), pFKey, aiCol, regOld, -int32(1), bIgnore)
}
if regNew != 0 && !(_isSetNullAction(tls, pParse, pFKey) != 0) {
/* A row is being added to the child table. If a parent row cannot
** be found, adding the child row has violated the FK constraint.
**
** If this operation is being performed as part of a trigger program
** that is actually a "SET NULL" action belonging to this very
** foreign key, then omit this scan altogether. As all child key
** values are guaranteed to be NULL, it is not possible for adding
** this row to cause an FK violation. */
_fkLookupParent(tls, pParse, iDb, pTo, **(**uintptr)(__ccgo_up(bp)), pFKey, aiCol, regNew, +libc.Int32FromInt32(1), bIgnore)
}
_sqlite3DbFree(tls, db, **(**uintptr)(__ccgo_up(bp + 8)))
goto _1
_1:
;
pFKey = (*TFKey)(unsafe.Pointer(pFKey)).FpNextFrom
}
/* Loop through all the foreign key constraints that refer to this table.
** (the "child" constraints) */
pFKey = _sqlite3FkReferences(tls, pTab)
for {
if !(pFKey != 0) {
break
}
**(**uintptr)(__ccgo_up(bp + 24)) = uintptr(0)
**(**uintptr)(__ccgo_up(bp + 32)) = uintptr(0)
if aChange != 0 && _fkParentIsModified(tls, pTab, pFKey, aChange, bChngRowid) == 0 {
goto _5
}
if !((*TFKey)(unsafe.Pointer(pFKey)).FisDeferred != 0) && !((*Tsqlite3)(unsafe.Pointer(db)).Fflags&libc.Uint64FromInt32(SQLITE_DeferFKs) != 0) && !((*TParse)(unsafe.Pointer(pParse)).FpToplevel != 0) && !((*TParse)(unsafe.Pointer(pParse)).FisMultiWrite != 0) {
/* Inserting a single row into a parent table cannot cause (or fix)
** an immediate foreign key violation. So do nothing in this case. */
goto _5
}
if _sqlite3FkLocateIndex(tls, pParse, pTab, pFKey, bp+24, bp+32) != 0 {
if !(isIgnoreErrors != 0) || (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
return
}
goto _5
}
/* Create a SrcList structure containing the child table. We need the
** child table as a SrcList for sqlite3WhereBegin() */
pSrc = _sqlite3SrcListAppend(tls, pParse, uintptr(0), uintptr(0), uintptr(0))
if pSrc != 0 {
pItem = pSrc + 8
(*TSrcItem)(unsafe.Pointer(pItem)).FpSTab = (*TFKey)(unsafe.Pointer(pFKey)).FpFrom
(*TSrcItem)(unsafe.Pointer(pItem)).FzName = (*TTable)(unsafe.Pointer((*TFKey)(unsafe.Pointer(pFKey)).FpFrom)).FzName
(*TTable)(unsafe.Pointer((*TSrcItem)(unsafe.Pointer(pItem)).FpSTab)).FnTabRef = (*TTable)(unsafe.Pointer((*TSrcItem)(unsafe.Pointer(pItem)).FpSTab)).FnTabRef + 1
v7 = pParse + 56
v4 = *(*int32)(unsafe.Pointer(v7))
*(*int32)(unsafe.Pointer(v7)) = *(*int32)(unsafe.Pointer(v7)) + 1
(*TSrcItem)(unsafe.Pointer(pItem)).FiCursor = v4
if regNew != 0 {
_fkScanChildren(tls, pParse, pSrc, pTab, **(**uintptr)(__ccgo_up(bp + 24)), pFKey, **(**uintptr)(__ccgo_up(bp + 32)), regNew, -int32(1))
}
if regOld != 0 {
eAction = libc.Int32FromUint8(**(**Tu8)(__ccgo_up(pFKey + 45 + libc.BoolUintptr(aChange != uintptr(0)))))
if (*Tsqlite3)(unsafe.Pointer(db)).Fflags&(libc.Uint64FromInt32(libc.Int32FromInt32(0x00008))<<libc.Int32FromInt32(32)) != 0 {
eAction = OE_None
}
_fkScanChildren(tls, pParse, pSrc, pTab, **(**uintptr)(__ccgo_up(bp + 24)), pFKey, **(**uintptr)(__ccgo_up(bp + 32)), regOld, int32(1))
/* If this is a deferred FK constraint, or a CASCADE or SET NULL
** action applies, then any foreign key violations caused by
** removing the parent key will be rectified by the action trigger.
** So do not set the "may-abort" flag in this case.
**
** Note 1: If the FK is declared "ON UPDATE CASCADE", then the
** may-abort flag will eventually be set on this statement anyway
** (when this function is called as part of processing the UPDATE
** within the action trigger).
**
** Note 2: At first glance it may seem like SQLite could simply omit
** all OP_FkCounter related scans when either CASCADE or SET NULL
** applies. The trouble starts if the CASCADE or SET NULL action
** trigger causes other triggers or action rules attached to the
** child table to fire. In these cases the fk constraint counters
** might be set incorrectly if any OP_FkCounter related scans are
** omitted. */
if !((*TFKey)(unsafe.Pointer(pFKey)).FisDeferred != 0) && eAction != int32(OE_Cascade) && eAction != int32(OE_SetNull) {
_sqlite3MayAbort(tls, pParse)
}
}
(*TSrcItem)(unsafe.Pointer(pItem)).FzName = uintptr(0)
_sqlite3SrcListDelete(tls, db, pSrc)
}
_sqlite3DbFree(tls, db, **(**uintptr)(__ccgo_up(bp + 32)))
goto _5
_5:
;
pFKey = (*TFKey)(unsafe.Pointer(pFKey)).FpNextTo
}
}
// C documentation
//
// /*
// ** This function is called to generate code that runs when table pTab is
// ** being dropped from the database. The SrcList passed as the second argument
// ** to this function contains a single entry guaranteed to resolve to
// ** table pTab.
// **
// ** Normally, no code is required. However, if either
// **
// ** (a) The table is the parent table of a FK constraint, or
// ** (b) The table is the child table of a deferred FK constraint and it is
// ** determined at runtime that there are outstanding deferred FK
// ** constraint violations in the database,
// **
// ** then the equivalent of "DELETE FROM <tbl>" is executed before dropping
// ** the table from the database. Triggers are disabled while running this
// ** DELETE, but foreign key actions are not.
// */
func _sqlite3FkDropTable(tls *libc.TLS, pParse uintptr, pName uintptr, pTab uintptr) {
var db, p, v uintptr
var iSkip int32
_, _, _, _ = db, iSkip, p, v
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
if (*Tsqlite3)(unsafe.Pointer(db)).Fflags&uint64(SQLITE_ForeignKeys) != 0 && libc.Int32FromUint8((*TTable)(unsafe.Pointer(pTab)).FeTabType) == TABTYP_NORM {
iSkip = 0
v = _sqlite3GetVdbe(tls, pParse)
/* VDBE has already been allocated */
if _sqlite3FkReferences(tls, pTab) == uintptr(0) {
p = (*(*struct {
FaddColOffset int32
FpFKey uintptr
FpDfltList uintptr
})(unsafe.Pointer(pTab + 64))).FpFKey
for {
if !(p != 0) {
break
}
if (*TFKey)(unsafe.Pointer(p)).FisDeferred != 0 || (*Tsqlite3)(unsafe.Pointer(db)).Fflags&uint64(SQLITE_DeferFKs) != 0 {
break
}
goto _1
_1:
;
p = (*TFKey)(unsafe.Pointer(p)).FpNextFrom
}
if !(p != 0) {
return
}
iSkip = _sqlite3VdbeMakeLabel(tls, pParse)
_sqlite3VdbeAddOp2(tls, v, int32(OP_FkIfZero), int32(1), iSkip)
}
libc.SetBitFieldPtr16Uint32(pParse+40, libc.Uint32FromInt32(1), 0, 0x1)
_sqlite3DeleteFrom(tls, pParse, _sqlite3SrcListDup(tls, db, pName, 0), uintptr(0), uintptr(0), uintptr(0))
libc.SetBitFieldPtr16Uint32(pParse+40, libc.Uint32FromInt32(0), 0, 0x1)
/* If the DELETE has generated immediate foreign key constraint
** violations, halt the VDBE and return an error at this point, before
** any modifications to the schema are made. This is because statement
** transactions are not able to rollback schema changes.
**
** If the SQLITE_DeferFKs flag is set, then this is not required, as
** the statement transaction will not be rolled back even if FK
** constraints are violated.
*/
if (*Tsqlite3)(unsafe.Pointer(db)).Fflags&uint64(SQLITE_DeferFKs) == uint64(0) {
_sqlite3VdbeAddOp2(tls, v, int32(OP_FkIfZero), 0, _sqlite3VdbeCurrentAddr(tls, v)+int32(2))
_sqlite3HaltConstraint(tls, pParse, libc.Int32FromInt32(SQLITE_CONSTRAINT)|libc.Int32FromInt32(3)<<libc.Int32FromInt32(8), int32(OE_Abort), uintptr(0), int8(-libc.Int32FromInt32(1)), uint8(P5_ConstraintFK))
}
if iSkip != 0 {
_sqlite3VdbeResolveLabel(tls, v, iSkip)
}
}
}
// C documentation
//
// /*
// ** Generate code that will assemble an index key and stores it in register
// ** regOut. The key with be for index pIdx which is an index on pTab.
// ** iCur is the index of a cursor open on the pTab table and pointing to
// ** the entry that needs indexing. If pTab is a WITHOUT ROWID table, then
// ** iCur must be the cursor of the PRIMARY KEY index.
// **
// ** Return a register number which is the first in a block of
// ** registers that holds the elements of the index key. The
// ** block of registers has already been deallocated by the time
// ** this routine returns.
// **
// ** If *piPartIdxLabel is not NULL, fill it in with a label and jump
// ** to that label if pIdx is a partial index that should be skipped.
// ** The label should be resolved using sqlite3ResolvePartIdxLabel().
// ** A partial index should be skipped if its WHERE clause evaluates
// ** to false or null. If pIdx is not a partial index, *piPartIdxLabel
// ** will be set to zero which is an empty label that is ignored by
// ** sqlite3ResolvePartIdxLabel().
// **
// ** The pPrior and regPrior parameters are used to implement a cache to
// ** avoid unnecessary register loads. If pPrior is not NULL, then it is
// ** a pointer to a different index for which an index key has just been
// ** computed into register regPrior. If the current pIdx index is generating
// ** its key into the same sequence of registers and if pPrior and pIdx share
// ** a column in common, then the register corresponding to that column already
// ** holds the correct value and the loading of that register is skipped.
// ** This optimization is helpful when doing a DELETE or an INTEGRITY_CHECK
// ** on a table with multiple indices, and especially with the ROWID or
// ** PRIMARY KEY columns of the index.
// */
func _sqlite3GenerateIndexKey(tls *libc.TLS, pParse uintptr, pIdx uintptr, iDataCur int32, regOut int32, prefixOnly int32, piPartIdxLabel uintptr, pPrior uintptr, regPrior int32) (r int32) {
var j, nCol, regBase, v1 int32
var v uintptr
_, _, _, _, _ = j, nCol, regBase, v, v1
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
if piPartIdxLabel != 0 {
if (*TIndex)(unsafe.Pointer(pIdx)).FpPartIdxWhere != 0 {
**(**int32)(__ccgo_up(piPartIdxLabel)) = _sqlite3VdbeMakeLabel(tls, pParse)
(*TParse)(unsafe.Pointer(pParse)).FiSelfTab = iDataCur + int32(1)
_sqlite3ExprIfFalseDup(tls, pParse, (*TIndex)(unsafe.Pointer(pIdx)).FpPartIdxWhere, **(**int32)(__ccgo_up(piPartIdxLabel)), int32(SQLITE_JUMPIFNULL))
(*TParse)(unsafe.Pointer(pParse)).FiSelfTab = 0
pPrior = uintptr(0) /* Ticket a9efb42811fa41ee 2019-11-02;
** pPartIdxWhere may have corrupted regPrior registers */
} else {
**(**int32)(__ccgo_up(piPartIdxLabel)) = 0
}
}
if prefixOnly != 0 && int32(uint32(*(*uint16)(unsafe.Pointer(pIdx + 100))&0x8>>3)) != 0 {
v1 = libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnKeyCol)
} else {
v1 = libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnColumn)
}
nCol = v1
regBase = _sqlite3GetTempRange(tls, pParse, nCol)
if pPrior != 0 && (regBase != regPrior || (*TIndex)(unsafe.Pointer(pPrior)).FpPartIdxWhere != 0) {
pPrior = uintptr(0)
}
j = 0
for {
if !(j < nCol) {
break
}
if pPrior != 0 && int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pPrior)).FaiColumn + uintptr(j)*2))) == int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(j)*2))) && int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pPrior)).FaiColumn + uintptr(j)*2))) != -int32(2) {
/* This column was already computed by the previous index */
goto _2
}
_sqlite3ExprCodeLoadIndexColumn(tls, pParse, pIdx, iDataCur, j, regBase+j)
if int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(j)*2))) >= 0 {
/* If the column affinity is REAL but the number is an integer, then it
** might be stored in the table as an integer (using a compact
** representation) then converted to REAL by an OP_RealAffinity opcode.
** But we are getting ready to store this value back into an index, where
** it should be converted by to INTEGER again. So omit the
** OP_RealAffinity opcode if it is present */
_sqlite3VdbeDeletePriorOpcode(tls, v, uint8(OP_RealAffinity))
}
goto _2
_2:
;
j = j + 1
}
if regOut != 0 {
_sqlite3VdbeAddOp3(tls, v, int32(OP_MakeRecord), regBase, nCol, regOut)
}
_sqlite3ReleaseTempRange(tls, pParse, regBase, nCol)
return regBase
}
// C documentation
//
// /*
// ** This routine generates VDBE code that causes the deletion of all
// ** index entries associated with a single row of a single table, pTab
// **
// ** Preconditions:
// **
// ** 1. A read/write cursor "iDataCur" must be open on the canonical storage
// ** btree for the table pTab. (This will be either the table itself
// ** for rowid tables or to the primary key index for WITHOUT ROWID
// ** tables.)
// **
// ** 2. Read/write cursors for all indices of pTab must be open as
// ** cursor number iIdxCur+i for the i-th index. (The pTab->pIndex
// ** index is the 0-th index.)
// **
// ** 3. The "iDataCur" cursor must be already be positioned on the row
// ** that is to be deleted.
// */
func _sqlite3GenerateRowIndexDelete(tls *libc.TLS, pParse uintptr, pTab uintptr, iDataCur int32, iIdxCur int32, aRegIdx uintptr, iIdxNoSeek int32) {
bp := tls.Alloc(16)
defer tls.Free(16)
var i, r1, v3 int32
var pIdx, pPk, pPrior, v, v1 uintptr
var _ /* iPartIdxLabel at bp+0 */ int32
_, _, _, _, _, _, _, _ = i, pIdx, pPk, pPrior, r1, v, v1, v3 /* Index loop counter */
r1 = -int32(1) /* Current index */
pPrior = uintptr(0) /* PRIMARY KEY index, or NULL for rowid tables */
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
if (*TTable)(unsafe.Pointer(pTab)).FtabFlags&uint32(TF_WithoutRowid) == uint32(0) {
v1 = uintptr(0)
} else {
v1 = _sqlite3PrimaryKeyIndex(tls, pTab)
}
pPk = v1
i = 0
pIdx = (*TTable)(unsafe.Pointer(pTab)).FpIndex
for {
if !(pIdx != 0) {
break
}
if aRegIdx != uintptr(0) && **(**int32)(__ccgo_up(aRegIdx + uintptr(i)*4)) == 0 {
goto _2
}
if pIdx == pPk {
goto _2
}
if iIdxCur+i == iIdxNoSeek {
goto _2
}
r1 = _sqlite3GenerateIndexKey(tls, pParse, pIdx, iDataCur, 0, int32(1), bp, pPrior, r1)
if int32(uint32(*(*uint16)(unsafe.Pointer(pIdx + 100))&0x8>>3)) != 0 {
v3 = libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnKeyCol)
} else {
v3 = libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnColumn)
}
_sqlite3VdbeAddOp3(tls, v, int32(OP_IdxDelete), iIdxCur+i, r1, v3)
_sqlite3VdbeChangeP4(tls, v, -int32(1), pIdx, -int32(6))
_sqlite3ResolvePartIdxLabel(tls, pParse, **(**int32)(__ccgo_up(bp)))
pPrior = pIdx
goto _2
_2:
;
i = i + 1
pIdx = (*TIndex)(unsafe.Pointer(pIdx)).FpNext
}
}
// C documentation
//
// /*
// ** Get a VDBE for the given parser context. Create a new one if necessary.
// ** If an error occurs, return NULL and leave a message in pParse.
// */
func _sqlite3GetVdbe(tls *libc.TLS, pParse uintptr) (r uintptr) {
if (*TParse)(unsafe.Pointer(pParse)).FpVdbe != 0 {
return (*TParse)(unsafe.Pointer(pParse)).FpVdbe
}
if (*TParse)(unsafe.Pointer(pParse)).FpToplevel == uintptr(0) && (*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer(pParse)).Fdb)).FdbOptFlags&libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_FactorOutConst)) == uint32(0) {
libc.SetBitFieldPtr16Uint32(pParse+40, libc.Uint32FromInt32(1), 7, 0x80)
}
return _sqlite3VdbeCreate(tls, pParse)
}
// C documentation
//
// /*
// ** Return a KeyInfo structure that is appropriate for the given Index.
// **
// ** The caller should invoke sqlite3KeyInfoUnref() on the returned object
// ** when it has finished using it.
// */
func _sqlite3KeyInfoOfIndex(tls *libc.TLS, pParse uintptr, pIdx uintptr) (r uintptr) {
var i, nCol, nKey int32
var pKey, zColl, v2 uintptr
_, _, _, _, _, _ = i, nCol, nKey, pKey, zColl, v2
nCol = libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnColumn)
nKey = libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnKeyCol)
if (*TParse)(unsafe.Pointer(pParse)).FnErr != 0 {
return uintptr(0)
}
if int32(uint32(*(*uint16)(unsafe.Pointer(pIdx + 100))&0x8>>3)) != 0 {
pKey = _sqlite3KeyInfoAlloc(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, nKey, nCol-nKey)
} else {
pKey = _sqlite3KeyInfoAlloc(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, nCol, 0)
}
if pKey != 0 {
i = 0
for {
if !(i < nCol) {
break
}
zColl = **(**uintptr)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FazColl + uintptr(i)*8))
if zColl == uintptr(unsafe.Pointer(&_sqlite3StrBINARY)) {
v2 = uintptr(0)
} else {
v2 = _sqlite3LocateCollSeq(tls, pParse, zColl)
}
*(*uintptr)(unsafe.Pointer(pKey + 32 + uintptr(i)*8)) = v2
**(**Tu8)(__ccgo_up((*TKeyInfo)(unsafe.Pointer(pKey)).FaSortFlags + uintptr(i))) = **(**Tu8)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaSortOrder + uintptr(i)))
goto _1
_1:
;
i = i + 1
}
if (*TParse)(unsafe.Pointer(pParse)).FnErr != 0 {
if int32(uint32(*(*uint16)(unsafe.Pointer(pIdx + 100))&0x100>>8)) == 0 && _sqlite3HashFind(tls, (*TIndex)(unsafe.Pointer(pIdx)).FpSchema+32, (*TIndex)(unsafe.Pointer(pIdx)).FzName) != 0 {
/* Deactivate the index because it contains an unknown collating
** sequence. The only way to reactive the index is to reload the
** schema. Adding the missing collating sequence later does not
** reactive the index. The application had the chance to register
** the missing index using the collation-needed callback. For
** simplicity, SQLite will not give the application a second chance.
**
** Except, do not do this if the index is not in the schema hash
** table. In this case the index is currently being constructed
** by a CREATE INDEX statement, and retrying will not help. */
libc.SetBitFieldPtr16Uint32(pIdx+100, libc.Uint32FromInt32(1), 8, 0x100)
(*TParse)(unsafe.Pointer(pParse)).Frc = libc.Int32FromInt32(SQLITE_ERROR) | libc.Int32FromInt32(2)<<libc.Int32FromInt32(8)
}
_sqlite3KeyInfoUnref(tls, pKey)
pKey = uintptr(0)
}
}
return pKey
}
// C documentation
//
// /*
// ** This function is called by the parser for the second and subsequent
// ** rows of a multi-row VALUES clause. Argument pLeft is the part of
// ** the VALUES clause already parsed, argument pRow is the vector of values
// ** for the new row. The Select object returned represents the complete
// ** VALUES clause, including the new row.
// **
// ** There are two ways in which this may be achieved - by incremental
// ** coding of a co-routine (the "co-routine" method) or by returning a
// ** Select object equivalent to the following (the "UNION ALL" method):
// **
// ** "pLeft UNION ALL SELECT pRow"
// **
// ** If the VALUES clause contains a lot of rows, this compound Select
// ** object may consume a lot of memory.
// **
// ** When the co-routine method is used, each row that will be returned
// ** by the VALUES clause is coded into part of a co-routine as it is
// ** passed to this function. The returned Select object is equivalent to:
// **
// ** SELECT * FROM (
// ** Select object to read co-routine
// ** )
// **
// ** The co-routine method is used in most cases. Exceptions are:
// **
// ** a) If the current statement has a WITH clause. This is to avoid
// ** statements like:
// **
// ** WITH cte AS ( VALUES('x'), ('y') ... )
// ** SELECT * FROM cte AS a, cte AS b;
// **
// ** This will not work, as the co-routine uses a hard-coded register
// ** for its OP_Yield instructions, and so it is not possible for two
// ** cursors to iterate through it concurrently.
// **
// ** b) The schema is currently being parsed (i.e. the VALUES clause is part
// ** of a schema item like a VIEW or TRIGGER). In this case there is no VM
// ** being generated when parsing is taking place, and so generating
// ** a co-routine is not possible.
// **
// ** c) There are non-constant expressions in the VALUES clause (e.g.
// ** the VALUES clause is part of a correlated sub-query).
// **
// ** d) One or more of the values in the first row of the VALUES clause
// ** has an affinity (i.e. is a CAST expression). This causes problems
// ** because the complex rules SQLite uses (see function
// ** sqlite3SubqueryColumnTypes() in select.c) to determine the effective
// ** affinity of such a column for all rows require access to all values in
// ** the column simultaneously.
// */
func _sqlite3MultiValues(tls *libc.TLS, pParse uintptr, pLeft uintptr, pRow uintptr) (r uintptr) {
bp := tls.Alloc(48)
defer tls.Free(48)
var f, v1 int32
var p, pRet, pSelect, pSubq, pSubq1, v, v2 uintptr
var _ /* dest at bp+0 */ TSelectDest
_, _, _, _, _, _, _, _, _ = f, p, pRet, pSelect, pSubq, pSubq1, v, v1, v2
if int32(Tbft(*(*uint16)(unsafe.Pointer(pParse + 40))&0x40>>6)) != 0 || (*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer(pParse)).Fdb)).Finit1.Fbusy != 0 || _exprListIsConstant(tls, pParse, pRow) == 0 || (*TSrcList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pLeft)).FpSrc)).FnSrc == 0 && _exprListIsNoAffinity(tls, pParse, (*TSelect)(unsafe.Pointer(pLeft)).FpEList) == 0 || libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) != PARSE_MODE_NORMAL {
/* The co-routine method cannot be used. Fall back to UNION ALL. */
pSelect = uintptr(0)
f = libc.Int32FromInt32(SF_Values) | libc.Int32FromInt32(SF_MultiValue)
if (*TSrcList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pLeft)).FpSrc)).FnSrc != 0 {
_sqlite3MultiValuesEnd(tls, pParse, pLeft)
f = int32(SF_Values)
} else {
if (*TSelect)(unsafe.Pointer(pLeft)).FpPrior != 0 {
/* In this case set the SF_MultiValue flag only if it was set on pLeft */
f = libc.Int32FromUint32(libc.Uint32FromInt32(f) & (*TSelect)(unsafe.Pointer(pLeft)).FselFlags)
}
}
pSelect = _sqlite3SelectNew(tls, pParse, pRow, uintptr(0), uintptr(0), uintptr(0), uintptr(0), uintptr(0), libc.Uint32FromInt32(f), uintptr(0))
**(**Tu32)(__ccgo_up(pLeft + 4)) &= ^libc.Uint32FromInt32(SF_MultiValue)
if pSelect != 0 {
(*TSelect)(unsafe.Pointer(pSelect)).Fop = uint8(TK_ALL)
(*TSelect)(unsafe.Pointer(pSelect)).FpPrior = pLeft
pLeft = pSelect
}
} else {
p = uintptr(0) /* SrcItem that reads from co-routine */
if (*TSrcList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pLeft)).FpSrc)).FnSrc == 0 {
/* Co-routine has not yet been started and the special Select object
** that accesses the co-routine has not yet been created. This block
** does both those things. */
v = _sqlite3GetVdbe(tls, pParse)
pRet = _sqlite3SelectNew(tls, pParse, uintptr(0), uintptr(0), uintptr(0), uintptr(0), uintptr(0), uintptr(0), uint32(0), uintptr(0))
/* Ensure the database schema has been read. This is to ensure we have
** the correct text encoding. */
if (*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer(pParse)).Fdb)).FmDbFlags&uint32(DBFLAG_SchemaKnownOk) == uint32(0) {
_sqlite3ReadSchema(tls, pParse)
}
if pRet != 0 {
(*TSrcList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pRet)).FpSrc)).FnSrc = int32(1)
(*TSelect)(unsafe.Pointer(pRet)).FpPrior = (*TSelect)(unsafe.Pointer(pLeft)).FpPrior
(*TSelect)(unsafe.Pointer(pRet)).Fop = (*TSelect)(unsafe.Pointer(pLeft)).Fop
if (*TSelect)(unsafe.Pointer(pRet)).FpPrior != 0 {
**(**Tu32)(__ccgo_up(pRet + 4)) |= uint32(SF_Values)
}
(*TSelect)(unsafe.Pointer(pLeft)).FpPrior = uintptr(0)
(*TSelect)(unsafe.Pointer(pLeft)).Fop = uint8(TK_SELECT)
p = (*TSelect)(unsafe.Pointer(pRet)).FpSrc + 8
libc.SetBitFieldPtr32Uint32(p+24+4, libc.Uint32FromInt32(1), 6, 0x40)
(*TSrcItem)(unsafe.Pointer(p)).FiCursor = -int32(1)
*(*Tu32)(unsafe.Pointer(&(*TSrcItem)(unsafe.Pointer(p)).Fu1)) = uint32(2)
if _sqlite3SrcItemAttachSubquery(tls, pParse, p, pLeft, 0) != 0 {
pSubq = *(*uintptr)(unsafe.Pointer(p + 72))
(*TSubquery)(unsafe.Pointer(pSubq)).FaddrFillSub = _sqlite3VdbeCurrentAddr(tls, v) + int32(1)
v2 = pParse + 60
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
v1 = *(*int32)(unsafe.Pointer(v2))
(*TSubquery)(unsafe.Pointer(pSubq)).FregReturn = v1
_sqlite3VdbeAddOp3(tls, v, int32(OP_InitCoroutine), (*TSubquery)(unsafe.Pointer(pSubq)).FregReturn, 0, (*TSubquery)(unsafe.Pointer(pSubq)).FaddrFillSub)
_sqlite3SelectDestInit(tls, bp, int32(SRT_Coroutine), (*TSubquery)(unsafe.Pointer(pSubq)).FregReturn)
/* Allocate registers for the output of the co-routine. Do so so
** that there are two unused registers immediately before those
** used by the co-routine. This allows the code in sqlite3Insert()
** to use these registers directly, instead of copying the output
** of the co-routine to a separate array for processing. */
(**(**TSelectDest)(__ccgo_up(bp))).FiSdst = (*TParse)(unsafe.Pointer(pParse)).FnMem + int32(3)
(**(**TSelectDest)(__ccgo_up(bp))).FnSdst = (*TExprList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pLeft)).FpEList)).FnExpr
**(**int32)(__ccgo_up(pParse + 60)) += int32(2) + (**(**TSelectDest)(__ccgo_up(bp))).FnSdst
**(**Tu32)(__ccgo_up(pLeft + 4)) |= uint32(SF_MultiValue)
_sqlite3Select(tls, pParse, pLeft, bp)
(*TSubquery)(unsafe.Pointer(pSubq)).FregResult = (**(**TSelectDest)(__ccgo_up(bp))).FiSdst
}
pLeft = pRet
}
} else {
p = (*TSelect)(unsafe.Pointer(pLeft)).FpSrc + 8
*(*Tu32)(unsafe.Pointer(&(*TSrcItem)(unsafe.Pointer(p)).Fu1)) = *(*Tu32)(unsafe.Pointer(&(*TSrcItem)(unsafe.Pointer(p)).Fu1)) + 1
}
if (*TParse)(unsafe.Pointer(pParse)).FnErr == 0 {
pSubq1 = *(*uintptr)(unsafe.Pointer(p + 72))
if (*TExprList)(unsafe.Pointer((*TSelect)(unsafe.Pointer((*TSubquery)(unsafe.Pointer(pSubq1)).FpSelect)).FpEList)).FnExpr != (*TExprList)(unsafe.Pointer(pRow)).FnExpr {
_sqlite3SelectWrongNumTermsError(tls, pParse, (*TSubquery)(unsafe.Pointer(pSubq1)).FpSelect)
} else {
_sqlite3ExprCodeExprList(tls, pParse, pRow, (*TSubquery)(unsafe.Pointer(pSubq1)).FregResult, 0, uint8(0))
_sqlite3VdbeAddOp1(tls, (*TParse)(unsafe.Pointer(pParse)).FpVdbe, int32(OP_Yield), (*TSubquery)(unsafe.Pointer(pSubq1)).FregReturn)
}
}
_sqlite3ExprListDelete(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pRow)
}
return pLeft
}
// C documentation
//
// /*
// ** Allocate cursors for the pTab table and all its indices and generate
// ** code to open and initialized those cursors.
// **
// ** The cursor for the object that contains the complete data (normally
// ** the table itself, but the PRIMARY KEY index in the case of a WITHOUT
// ** ROWID table) is returned in *piDataCur. The first index cursor is
// ** returned in *piIdxCur. The number of indices is returned.
// **
// ** Use iBase as the first cursor (either the *piDataCur for rowid tables
// ** or the first index for WITHOUT ROWID tables) if it is non-negative.
// ** If iBase is negative, then allocate the next available cursor.
// **
// ** For a rowid table, *piDataCur will be exactly one less than *piIdxCur.
// ** For a WITHOUT ROWID table, *piDataCur will be somewhere in the range
// ** of *piIdxCurs, depending on where the PRIMARY KEY index appears on the
// ** pTab->pIndex list.
// **
// ** If pTab is a virtual table, then this routine is a no-op and the
// ** *piDataCur and *piIdxCur values are left uninitialized.
// */
func _sqlite3OpenTableAndIndices(tls *libc.TLS, pParse uintptr, pTab uintptr, op int32, p5 Tu8, iBase int32, aToOpen uintptr, piDataCur uintptr, piIdxCur uintptr) (r int32) {
var i, iDataCur, iDb, iIdxCur, v1 int32
var pIdx, v uintptr
_, _, _, _, _, _, _ = i, iDataCur, iDb, iIdxCur, pIdx, v, v1
if libc.Int32FromUint8((*TTable)(unsafe.Pointer(pTab)).FeTabType) == int32(TABTYP_VTAB) {
/* This routine is a no-op for virtual tables. Leave the output
** variables *piDataCur and *piIdxCur set to illegal cursor numbers
** for improved error detection. */
v1 = -libc.Int32FromInt32(999)
**(**int32)(__ccgo_up(piIdxCur)) = v1
**(**int32)(__ccgo_up(piDataCur)) = v1
return 0
}
iDb = _sqlite3SchemaToIndex(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, (*TTable)(unsafe.Pointer(pTab)).FpSchema)
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
if iBase < 0 {
iBase = (*TParse)(unsafe.Pointer(pParse)).FnTab
}
v1 = iBase
iBase = iBase + 1
iDataCur = v1
**(**int32)(__ccgo_up(piDataCur)) = iDataCur
if (*TTable)(unsafe.Pointer(pTab)).FtabFlags&uint32(TF_WithoutRowid) == uint32(0) && (aToOpen == uintptr(0) || **(**Tu8)(__ccgo_up(aToOpen)) != 0) {
_sqlite3OpenTable(tls, pParse, iDataCur, iDb, pTab, op)
} else {
if libc.Int32FromUint8((*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer(pParse)).Fdb)).FnoSharedCache) == 0 {
_sqlite3TableLock(tls, pParse, iDb, (*TTable)(unsafe.Pointer(pTab)).Ftnum, libc.BoolUint8(op == int32(OP_OpenWrite)), (*TTable)(unsafe.Pointer(pTab)).FzName)
}
}
**(**int32)(__ccgo_up(piIdxCur)) = iBase
i = 0
pIdx = (*TTable)(unsafe.Pointer(pTab)).FpIndex
for {
if !(pIdx != 0) {
break
}
v1 = iBase
iBase = iBase + 1
iIdxCur = v1
if int32(uint32(*(*uint16)(unsafe.Pointer(pIdx + 100))&0x3>>0)) == int32(SQLITE_IDXTYPE_PRIMARYKEY) && !((*TTable)(unsafe.Pointer(pTab)).FtabFlags&libc.Uint32FromInt32(TF_WithoutRowid) == libc.Uint32FromInt32(0)) {
**(**int32)(__ccgo_up(piDataCur)) = iIdxCur
p5 = uint8(0)
}
if aToOpen == uintptr(0) || **(**Tu8)(__ccgo_up(aToOpen + uintptr(i+int32(1)))) != 0 {
_sqlite3VdbeAddOp3(tls, v, op, iIdxCur, libc.Int32FromUint32((*TIndex)(unsafe.Pointer(pIdx)).Ftnum), iDb)
_sqlite3VdbeSetP4KeyInfo(tls, pParse, pIdx)
_sqlite3VdbeChangeP5(tls, v, uint16(p5))
}
goto _3
_3:
;
pIdx = (*TIndex)(unsafe.Pointer(pIdx)).FpNext
i = i + 1
}
if iBase > (*TParse)(unsafe.Pointer(pParse)).FnTab {
(*TParse)(unsafe.Pointer(pParse)).FnTab = iBase
}
return i
}
// C documentation
//
// /*
// ** Generate code that will erase and refill index *pIdx. This is
// ** used to initialize a newly created index or to recompute the
// ** content of an index in response to a REINDEX command.
// **
// ** if memRootPage is not negative, it means that the index is newly
// ** created. The register specified by memRootPage contains the
// ** root page number of the index. If memRootPage is negative, then
// ** the index already exists and must be cleared before being refilled and
// ** the root page number of the index is taken from pIndex->tnum.
// */
func _sqlite3RefillIndex(tls *libc.TLS, pParse uintptr, pIndex uintptr, memRootPage int32) {
bp := tls.Alloc(16)
defer tls.Free(16)
var addr1, addr2, iDb, iIdx, iSorter, iTab, j2, regRecord, v1, v3 int32
var db, pKey, pTab, v, v2, v4 uintptr
var tnum TPgno
var _ /* iPartIdxLabel at bp+0 */ int32
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = addr1, addr2, db, iDb, iIdx, iSorter, iTab, j2, pKey, pTab, regRecord, tnum, v, v1, v2, v3, v4
pTab = (*TIndex)(unsafe.Pointer(pIndex)).FpTable
v2 = pParse + 56
v1 = *(*int32)(unsafe.Pointer(v2))
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1 /* The table that is indexed */
iTab = v1
v4 = pParse + 56
v3 = *(*int32)(unsafe.Pointer(v4))
*(*int32)(unsafe.Pointer(v4)) = *(*int32)(unsafe.Pointer(v4)) + 1 /* Btree cursor used for pTab */
iIdx = v3 /* Register holding assembled index record */
db = (*TParse)(unsafe.Pointer(pParse)).Fdb /* The database connection */
iDb = _sqlite3SchemaToIndex(tls, db, (*TIndex)(unsafe.Pointer(pIndex)).FpSchema)
if _sqlite3AuthCheck(tls, pParse, int32(SQLITE_REINDEX), (*TIndex)(unsafe.Pointer(pIndex)).FzName, uintptr(0), (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FzDbSName) != 0 {
return
}
/* Require a write-lock on the table to perform this operation */
_sqlite3TableLock(tls, pParse, iDb, (*TTable)(unsafe.Pointer(pTab)).Ftnum, uint8(1), (*TTable)(unsafe.Pointer(pTab)).FzName)
v = _sqlite3GetVdbe(tls, pParse)
if v == uintptr(0) {
return
}
if memRootPage >= 0 {
tnum = libc.Uint32FromInt32(memRootPage)
} else {
tnum = (*TIndex)(unsafe.Pointer(pIndex)).Ftnum
}
pKey = _sqlite3KeyInfoOfIndex(tls, pParse, pIndex)
/* Open the sorter cursor if we are to use one. */
v2 = pParse + 56
v1 = *(*int32)(unsafe.Pointer(v2))
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
iSorter = v1
_sqlite3VdbeAddOp4(tls, v, int32(OP_SorterOpen), iSorter, 0, libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIndex)).FnKeyCol), _sqlite3KeyInfoRef(tls, pKey), -int32(9))
/* Open the table. Loop through all rows of the table, inserting index
** records into the sorter. */
_sqlite3OpenTable(tls, pParse, iTab, iDb, pTab, int32(OP_OpenRead))
addr1 = _sqlite3VdbeAddOp2(tls, v, int32(OP_Rewind), iTab, 0)
regRecord = _sqlite3GetTempReg(tls, pParse)
_sqlite3MultiWrite(tls, pParse)
_sqlite3GenerateIndexKey(tls, pParse, pIndex, iTab, regRecord, 0, bp, uintptr(0), 0)
_sqlite3VdbeAddOp2(tls, v, int32(OP_SorterInsert), iSorter, regRecord)
_sqlite3ResolvePartIdxLabel(tls, pParse, **(**int32)(__ccgo_up(bp)))
_sqlite3VdbeAddOp2(tls, v, int32(OP_Next), iTab, addr1+int32(1))
_sqlite3VdbeJumpHere(tls, v, addr1)
if memRootPage < 0 {
_sqlite3VdbeAddOp2(tls, v, int32(OP_Clear), libc.Int32FromUint32(tnum), iDb)
}
_sqlite3VdbeAddOp4(tls, v, int32(OP_OpenWrite), iIdx, libc.Int32FromUint32(tnum), iDb, pKey, -int32(9))
if memRootPage >= 0 {
v1 = int32(OPFLAG_P2ISREG)
} else {
v1 = 0
}
_sqlite3VdbeChangeP5(tls, v, libc.Uint16FromInt32(int32(OPFLAG_BULKCSR)|v1))
addr1 = _sqlite3VdbeAddOp2(tls, v, int32(OP_SorterSort), iSorter, 0)
if libc.Int32FromUint8((*TIndex)(unsafe.Pointer(pIndex)).FonError) != OE_None {
j2 = _sqlite3VdbeGoto(tls, v, int32(1))
addr2 = _sqlite3VdbeCurrentAddr(tls, v)
_sqlite3VdbeAddOp4Int(tls, v, int32(OP_SorterCompare), iSorter, j2, regRecord, libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIndex)).FnKeyCol))
_sqlite3UniqueConstraint(tls, pParse, int32(OE_Abort), pIndex)
_sqlite3VdbeJumpHere(tls, v, j2)
} else {
/* Most CREATE INDEX and REINDEX statements that are not UNIQUE can not
** abort. The exception is if one of the indexed expressions contains a
** user function that throws an exception when it is evaluated. But the
** overhead of adding a statement journal to a CREATE INDEX statement is
** very small (since most of the pages written do not contain content that
** needs to be restored if the statement aborts), so we call
** sqlite3MayAbort() for all CREATE INDEX statements. */
_sqlite3MayAbort(tls, pParse)
addr2 = _sqlite3VdbeCurrentAddr(tls, v)
}
_sqlite3VdbeAddOp3(tls, v, int32(OP_SorterData), iSorter, regRecord, iIdx)
if !(int32(uint32(*(*uint16)(unsafe.Pointer(pIndex + 100))&0x200>>9)) != 0) {
/* This OP_SeekEnd opcode makes index insert for a REINDEX go much
** faster by avoiding unnecessary seeks. But the optimization does
** not work for UNIQUE constraint indexes on WITHOUT ROWID tables
** with DESC primary keys, since those indexes have there keys in
** a different order from the main table.
** See ticket: https://sqlite.org/src/info/bba7b69f9849b5bf
*/
_sqlite3VdbeAddOp1(tls, v, int32(OP_SeekEnd), iIdx)
}
_sqlite3VdbeAddOp2(tls, v, int32(OP_IdxInsert), iIdx, regRecord)
_sqlite3VdbeChangeP5(tls, v, uint16(OPFLAG_USESEEKRESULT))
_sqlite3ReleaseTempReg(tls, pParse, regRecord)
_sqlite3VdbeAddOp2(tls, v, int32(OP_SorterNext), iSorter, addr2)
_sqlite3VdbeJumpHere(tls, v, addr1)
_sqlite3VdbeAddOp1(tls, v, int32(OP_Close), iTab)
_sqlite3VdbeAddOp1(tls, v, int32(OP_Close), iIdx)
_sqlite3VdbeAddOp1(tls, v, int32(OP_Close), iSorter)
}
// C documentation
//
// /*
// ** Execute the statement pStmt, either until a row of data is ready, the
// ** statement is completely executed or an error occurs.
// **
// ** This routine implements the bulk of the logic behind the sqlite_step()
// ** API. The only thing omitted is the automatic recompile if a
// ** schema change has occurred. That detail is handled by the
// ** outer sqlite3_step() wrapper procedure.
// */
func _sqlite3Step(tls *libc.TLS, p uintptr) (r int32) {
var db uintptr
var rc int32
_, _ = db, rc
db = (*TVdbe)(unsafe.Pointer(p)).Fdb
if libc.Int32FromUint8((*TVdbe)(unsafe.Pointer(p)).FeVdbeState) != int32(VDBE_RUN_STATE) {
goto restart_step
restart_step:
;
if libc.Int32FromUint8((*TVdbe)(unsafe.Pointer(p)).FeVdbeState) == int32(VDBE_READY_STATE) {
if int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0x3>>0)) != 0 {
(*TVdbe)(unsafe.Pointer(p)).Frc = int32(SQLITE_SCHEMA)
rc = int32(SQLITE_ERROR)
if libc.Int32FromUint8((*TVdbe)(unsafe.Pointer(p)).FprepFlags)&int32(SQLITE_PREPARE_SAVESQL) != 0 {
/* If this statement was prepared using saved SQL and an
** error has occurred, then return the error code in p->rc to the
** caller. Set the error code in the database handle to the same
** value.
*/
rc = _sqlite3VdbeTransferError(tls, p)
}
goto end_of_step
}
/* If there are no other statements currently running, then
** reset the interrupt flag. This prevents a call to sqlite3_interrupt
** from interrupting a statement that has not yet started.
*/
if (*Tsqlite3)(unsafe.Pointer(db)).FnVdbeActive == 0 {
libc.AtomicStoreNInt32(db+432, libc.Int32FromInt32(0), libc.Int32FromInt32(__ATOMIC_RELAXED))
}
if libc.Int32FromUint8((*Tsqlite3)(unsafe.Pointer(db)).FmTrace)&(libc.Int32FromInt32(SQLITE_TRACE_PROFILE)|libc.Int32FromInt32(SQLITE_TRACE_XPROFILE)) != 0 && !((*Tsqlite3)(unsafe.Pointer(db)).Finit1.Fbusy != 0) && (*TVdbe)(unsafe.Pointer(p)).FzSql != 0 {
_sqlite3OsCurrentTimeInt64(tls, (*Tsqlite3)(unsafe.Pointer(db)).FpVfs, p+184)
} else {
}
(*Tsqlite3)(unsafe.Pointer(db)).FnVdbeActive = (*Tsqlite3)(unsafe.Pointer(db)).FnVdbeActive + 1
if int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0x40>>6)) == 0 {
(*Tsqlite3)(unsafe.Pointer(db)).FnVdbeWrite = (*Tsqlite3)(unsafe.Pointer(db)).FnVdbeWrite + 1
}
if int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0x80>>7)) != 0 {
(*Tsqlite3)(unsafe.Pointer(db)).FnVdbeRead = (*Tsqlite3)(unsafe.Pointer(db)).FnVdbeRead + 1
}
(*TVdbe)(unsafe.Pointer(p)).Fpc = 0
(*TVdbe)(unsafe.Pointer(p)).FeVdbeState = uint8(VDBE_RUN_STATE)
} else {
if libc.Int32FromUint8((*TVdbe)(unsafe.Pointer(p)).FeVdbeState) == int32(VDBE_HALT_STATE) {
/* We used to require that sqlite3_reset() be called before retrying
** sqlite3_step() after any error or after SQLITE_DONE. But beginning
** with version 3.7.0, we changed this so that sqlite3_reset() would
** be called automatically instead of throwing the SQLITE_MISUSE error.
** This "automatic-reset" change is not technically an incompatibility,
** since any application that receives an SQLITE_MISUSE is broken by
** definition.
**
** Nevertheless, some published applications that were originally written
** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE
** returns, and those were broken by the automatic-reset change. As a
** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the
** legacy behavior of returning SQLITE_MISUSE for cases where the
** previous sqlite3_step() returned something other than a SQLITE_LOCKED
** or SQLITE_BUSY error.
*/
Xsqlite3_reset(tls, p)
goto restart_step
}
}
}
if int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0xc>>2)) != 0 {
rc = _sqlite3VdbeList(tls, p)
} else {
(*Tsqlite3)(unsafe.Pointer(db)).FnVdbeExec = (*Tsqlite3)(unsafe.Pointer(db)).FnVdbeExec + 1
rc = _sqlite3VdbeExec(tls, p)
(*Tsqlite3)(unsafe.Pointer(db)).FnVdbeExec = (*Tsqlite3)(unsafe.Pointer(db)).FnVdbeExec - 1
}
if rc == int32(SQLITE_ROW) {
(*Tsqlite3)(unsafe.Pointer(db)).FerrCode = int32(SQLITE_ROW)
return int32(SQLITE_ROW)
} else {
/* If the statement completed successfully, invoke the profile callback */
if (*TVdbe)(unsafe.Pointer(p)).FstartTime > 0 {
_invokeProfileCallback(tls, db, p)
}
(*TVdbe)(unsafe.Pointer(p)).FpResultRow = uintptr(0)
if rc == int32(SQLITE_DONE) && (*Tsqlite3)(unsafe.Pointer(db)).FautoCommit != 0 {
(*TVdbe)(unsafe.Pointer(p)).Frc = _doWalCallbacks(tls, db)
if (*TVdbe)(unsafe.Pointer(p)).Frc != SQLITE_OK {
rc = int32(SQLITE_ERROR)
}
} else {
if rc != int32(SQLITE_DONE) && libc.Int32FromUint8((*TVdbe)(unsafe.Pointer(p)).FprepFlags)&int32(SQLITE_PREPARE_SAVESQL) != 0 {
/* If this statement was prepared using saved SQL and an
** error has occurred, then return the error code in p->rc to the
** caller. Set the error code in the database handle to the same value.
*/
rc = _sqlite3VdbeTransferError(tls, p)
}
}
}
(*Tsqlite3)(unsafe.Pointer(db)).FerrCode = rc
if int32(SQLITE_NOMEM) == _sqlite3ApiExit(tls, (*TVdbe)(unsafe.Pointer(p)).Fdb, (*TVdbe)(unsafe.Pointer(p)).Frc) {
(*TVdbe)(unsafe.Pointer(p)).Frc = int32(SQLITE_NOMEM)
if libc.Int32FromUint8((*TVdbe)(unsafe.Pointer(p)).FprepFlags)&int32(SQLITE_PREPARE_SAVESQL) != 0 {
rc = (*TVdbe)(unsafe.Pointer(p)).Frc
}
}
goto end_of_step
end_of_step:
;
/* There are only a limited number of result codes allowed from the
** statements prepared using the legacy sqlite3_prepare() interface */
return rc & (*Tsqlite3)(unsafe.Pointer(db)).FerrMask
}
// C documentation
//
// /*
// ** zIn is a UTF-16 encoded unicode string at least nByte bytes long.
// ** Return the number of bytes in the first nChar unicode characters
// ** in pZ. nChar must be non-negative. Surrogate pairs count as a single
// ** character.
// */
func _sqlite3Utf16ByteLen(tls *libc.TLS, zIn uintptr, nByte int32, nChar int32) (r int32) {
var c, n int32
var z, zEnd uintptr
_, _, _, _ = c, n, z, zEnd
z = zIn
zEnd = z + uintptr(nByte-int32(1))
n = 0
if true {
z = z + 1
}
for n < nChar && z <= zEnd {
c = libc.Int32FromUint8(**(**uint8)(__ccgo_up(z)))
z = z + uintptr(2)
if c >= int32(0xd8) && c < int32(0xdc) && z <= zEnd && libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) >= int32(0xdc) && libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) < int32(0xe0) {
z = z + uintptr(2)
}
n = n + 1
}
return int32(int64(z)-int64(zIn)) - libc.BoolInt32(true)
}
func _sqlite3VdbeFreeCursorNN(tls *libc.TLS, p uintptr, pCx uintptr) {
var pModule, pVCur uintptr
_, _ = pModule, pVCur
if int32(TBool(*(*uint8)(unsafe.Pointer(pCx + 8))&0x10>>4)) != 0 {
_freeCursorWithCache(tls, p, pCx)
return
}
switch libc.Int32FromUint8((*TVdbeCursor)(unsafe.Pointer(pCx)).FeCurType) {
case int32(CURTYPE_SORTER):
_sqlite3VdbeSorterClose(tls, (*TVdbe)(unsafe.Pointer(p)).Fdb, pCx)
case CURTYPE_BTREE:
_sqlite3BtreeCloseCursor(tls, *(*uintptr)(unsafe.Pointer(pCx + 48)))
case int32(CURTYPE_VTAB):
pVCur = *(*uintptr)(unsafe.Pointer(pCx + 48))
pModule = (*Tsqlite3_vtab)(unsafe.Pointer((*Tsqlite3_vtab_cursor)(unsafe.Pointer(pVCur)).FpVtab)).FpModule
(*Tsqlite3_vtab)(unsafe.Pointer((*Tsqlite3_vtab_cursor)(unsafe.Pointer(pVCur)).FpVtab)).FnRef = (*Tsqlite3_vtab)(unsafe.Pointer((*Tsqlite3_vtab_cursor)(unsafe.Pointer(pVCur)).FpVtab)).FnRef - 1
(*(*func(*libc.TLS, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{(*Tsqlite3_module)(unsafe.Pointer(pModule)).FxClose})))(tls, pVCur)
break
}
}
// C documentation
//
// /*
// ** This routine is called the when a VDBE tries to halt. If the VDBE
// ** has made changes and is in autocommit mode, then commit those
// ** changes. If a rollback is needed, then do the rollback.
// **
// ** This routine is the only way to move the sqlite3eOpenState of a VM from
// ** SQLITE_STATE_RUN to SQLITE_STATE_HALT. It is harmless to
// ** call this on a VM that is in the SQLITE_STATE_HALT state.
// **
// ** Return an error code. If the commit could not complete because of
// ** lock contention, return SQLITE_BUSY. If SQLITE_BUSY is returned, it
// ** means the close did not happen and needs to be repeated.
// */
func _sqlite3VdbeHalt(tls *libc.TLS, p uintptr) (r int32) {
var db uintptr
var eStatementOp, isSpecialError, mrc, rc, v1 int32
_, _, _, _, _, _ = db, eStatementOp, isSpecialError, mrc, rc, v1 /* Used to store transient return codes */
db = (*TVdbe)(unsafe.Pointer(p)).Fdb
/* This function contains the logic that determines if a statement or
** transaction will be committed or rolled back as a result of the
** execution of this virtual machine.
**
** If any of the following errors occur:
**
** SQLITE_NOMEM
** SQLITE_IOERR
** SQLITE_FULL
** SQLITE_INTERRUPT
**
** Then the internal cache might have been left in an inconsistent
** state. We need to rollback the statement transaction, if there is
** one, or the complete transaction if there is no statement transaction.
*/
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
(*TVdbe)(unsafe.Pointer(p)).Frc = int32(SQLITE_NOMEM)
}
_closeAllCursors(tls, p)
/* No commit or rollback needed if the program never started or if the
** SQL statement does not read or write a database file. */
if int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0x80>>7)) != 0 { /* Primary error code from p->rc */
eStatementOp = 0 /* Set to true if a 'special' error */
/* Lock all btrees used by the statement */
_sqlite3VdbeEnter(tls, p)
/* Check for one of the special errors */
if (*TVdbe)(unsafe.Pointer(p)).Frc != 0 {
mrc = (*TVdbe)(unsafe.Pointer(p)).Frc & int32(0xff)
isSpecialError = libc.BoolInt32(mrc == int32(SQLITE_NOMEM) || mrc == int32(SQLITE_IOERR) || mrc == int32(SQLITE_INTERRUPT) || mrc == int32(SQLITE_FULL))
} else {
v1 = libc.Int32FromInt32(0)
isSpecialError = v1
mrc = v1
}
if isSpecialError != 0 {
/* If the query was read-only and the error code is SQLITE_INTERRUPT,
** no rollback is necessary. Otherwise, at least a savepoint
** transaction must be rolled back to restore the database to a
** consistent state.
**
** Even if the statement is read-only, it is important to perform
** a statement or transaction rollback operation. If the error
** occurred while writing to the journal, sub-journal or database
** file as part of an effort to free up cache space (see function
** pagerStress() in pager.c), the rollback is required to restore
** the pager to a consistent state.
*/
if !(int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0x40>>6)) != 0) || mrc != int32(SQLITE_INTERRUPT) {
if (mrc == int32(SQLITE_NOMEM) || mrc == int32(SQLITE_FULL)) && int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0x20>>5)) != 0 {
eStatementOp = int32(SAVEPOINT_ROLLBACK)
} else {
/* We are forced to roll back the active transaction. Before doing
** so, abort any other statements this handle currently has active.
*/
_sqlite3RollbackAll(tls, db, libc.Int32FromInt32(SQLITE_ABORT)|libc.Int32FromInt32(2)<<libc.Int32FromInt32(8))
_sqlite3CloseSavepoints(tls, db)
(*Tsqlite3)(unsafe.Pointer(db)).FautoCommit = uint8(1)
(*TVdbe)(unsafe.Pointer(p)).FnChange = 0
}
}
}
/* Check for immediate foreign key violations. */
if (*TVdbe)(unsafe.Pointer(p)).Frc == SQLITE_OK || libc.Int32FromUint8((*TVdbe)(unsafe.Pointer(p)).FerrorAction) == int32(OE_Fail) && !(isSpecialError != 0) {
_sqlite3VdbeCheckFkImmediate(tls, p)
}
/* If the auto-commit flag is set and this is the only active writer
** VM, then we do either a commit or rollback of the current transaction.
**
** Note: This block also runs if one of the special errors handled
** above has occurred.
*/
if !((*Tsqlite3)(unsafe.Pointer(db)).FnVTrans > 0 && (*Tsqlite3)(unsafe.Pointer(db)).FaVTrans == uintptr(0)) && (*Tsqlite3)(unsafe.Pointer(db)).FautoCommit != 0 && (*Tsqlite3)(unsafe.Pointer(db)).FnVdbeWrite == libc.BoolInt32(int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0x40>>6)) == 0) {
if (*TVdbe)(unsafe.Pointer(p)).Frc == SQLITE_OK || libc.Int32FromUint8((*TVdbe)(unsafe.Pointer(p)).FerrorAction) == int32(OE_Fail) && !(isSpecialError != 0) {
rc = _sqlite3VdbeCheckFkDeferred(tls, p)
if rc != SQLITE_OK {
if int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0x40>>6)) != 0 {
_sqlite3VdbeLeave(tls, p)
return int32(SQLITE_ERROR)
}
rc = libc.Int32FromInt32(SQLITE_CONSTRAINT) | libc.Int32FromInt32(3)<<libc.Int32FromInt32(8)
} else {
if (*Tsqlite3)(unsafe.Pointer(db)).Fflags&(libc.Uint64FromInt32(libc.Int32FromInt32(0x00002))<<libc.Int32FromInt32(32)) != 0 {
rc = int32(SQLITE_CORRUPT)
**(**Tu64)(__ccgo_up(db + 48)) &= ^(libc.Uint64FromInt32(libc.Int32FromInt32(0x00002)) << libc.Int32FromInt32(32))
} else {
/* The auto-commit flag is true, the vdbe program was successful
** or hit an 'OR FAIL' constraint and there are no deferred foreign
** key constraints to hold up the transaction. This means a commit
** is required. */
rc = _vdbeCommit(tls, db, p)
}
}
if rc == int32(SQLITE_BUSY) && int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0x40>>6)) != 0 {
_sqlite3VdbeLeave(tls, p)
return int32(SQLITE_BUSY)
} else {
if rc != SQLITE_OK {
_sqlite3SystemError(tls, db, rc)
(*TVdbe)(unsafe.Pointer(p)).Frc = rc
_sqlite3RollbackAll(tls, db, SQLITE_OK)
(*TVdbe)(unsafe.Pointer(p)).FnChange = 0
} else {
(*Tsqlite3)(unsafe.Pointer(db)).FnDeferredCons = 0
(*Tsqlite3)(unsafe.Pointer(db)).FnDeferredImmCons = 0
**(**Tu64)(__ccgo_up(db + 48)) &= ^libc.Uint64FromInt32(SQLITE_DeferFKs)
_sqlite3CommitInternalChanges(tls, db)
}
}
} else {
if (*TVdbe)(unsafe.Pointer(p)).Frc == int32(SQLITE_SCHEMA) && (*Tsqlite3)(unsafe.Pointer(db)).FnVdbeActive > int32(1) {
(*TVdbe)(unsafe.Pointer(p)).FnChange = 0
} else {
_sqlite3RollbackAll(tls, db, SQLITE_OK)
(*TVdbe)(unsafe.Pointer(p)).FnChange = 0
}
}
(*Tsqlite3)(unsafe.Pointer(db)).FnStatement = 0
} else {
if eStatementOp == 0 {
if (*TVdbe)(unsafe.Pointer(p)).Frc == SQLITE_OK || libc.Int32FromUint8((*TVdbe)(unsafe.Pointer(p)).FerrorAction) == int32(OE_Fail) {
eStatementOp = int32(SAVEPOINT_RELEASE)
} else {
if libc.Int32FromUint8((*TVdbe)(unsafe.Pointer(p)).FerrorAction) == int32(OE_Abort) {
eStatementOp = int32(SAVEPOINT_ROLLBACK)
} else {
_sqlite3RollbackAll(tls, db, libc.Int32FromInt32(SQLITE_ABORT)|libc.Int32FromInt32(2)<<libc.Int32FromInt32(8))
_sqlite3CloseSavepoints(tls, db)
(*Tsqlite3)(unsafe.Pointer(db)).FautoCommit = uint8(1)
(*TVdbe)(unsafe.Pointer(p)).FnChange = 0
}
}
}
}
/* If eStatementOp is non-zero, then a statement transaction needs to
** be committed or rolled back. Call sqlite3VdbeCloseStatement() to
** do so. If this operation returns an error, and the current statement
** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the
** current statement error code.
*/
if eStatementOp != 0 {
rc = _sqlite3VdbeCloseStatement(tls, p, eStatementOp)
if rc != 0 {
if (*TVdbe)(unsafe.Pointer(p)).Frc == SQLITE_OK || (*TVdbe)(unsafe.Pointer(p)).Frc&int32(0xff) == int32(SQLITE_CONSTRAINT) {
(*TVdbe)(unsafe.Pointer(p)).Frc = rc
_sqlite3DbFree(tls, db, (*TVdbe)(unsafe.Pointer(p)).FzErrMsg)
(*TVdbe)(unsafe.Pointer(p)).FzErrMsg = uintptr(0)
}
_sqlite3RollbackAll(tls, db, libc.Int32FromInt32(SQLITE_ABORT)|libc.Int32FromInt32(2)<<libc.Int32FromInt32(8))
_sqlite3CloseSavepoints(tls, db)
(*Tsqlite3)(unsafe.Pointer(db)).FautoCommit = uint8(1)
(*TVdbe)(unsafe.Pointer(p)).FnChange = 0
}
}
/* If this was an INSERT, UPDATE or DELETE and no statement transaction
** has been rolled back, update the database connection change-counter.
*/
if int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0x10>>4)) != 0 {
if eStatementOp != int32(SAVEPOINT_ROLLBACK) {
_sqlite3VdbeSetChanges(tls, db, (*TVdbe)(unsafe.Pointer(p)).FnChange)
} else {
_sqlite3VdbeSetChanges(tls, db, 0)
}
(*TVdbe)(unsafe.Pointer(p)).FnChange = 0
}
/* Release the locks */
_sqlite3VdbeLeave(tls, p)
}
/* We have successfully halted and closed the VM. Record this fact. */
(*Tsqlite3)(unsafe.Pointer(db)).FnVdbeActive = (*Tsqlite3)(unsafe.Pointer(db)).FnVdbeActive - 1
if !(int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0x40>>6)) != 0) {
(*Tsqlite3)(unsafe.Pointer(db)).FnVdbeWrite = (*Tsqlite3)(unsafe.Pointer(db)).FnVdbeWrite - 1
}
if int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0x80>>7)) != 0 {
(*Tsqlite3)(unsafe.Pointer(db)).FnVdbeRead = (*Tsqlite3)(unsafe.Pointer(db)).FnVdbeRead - 1
}
(*TVdbe)(unsafe.Pointer(p)).FeVdbeState = uint8(VDBE_HALT_STATE)
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
(*TVdbe)(unsafe.Pointer(p)).Frc = int32(SQLITE_NOMEM)
}
/* If the auto-commit flag is set to true, then any locks that were held
** by connection db have now been released. Call sqlite3ConnectionUnlocked()
** to invoke any required unlock-notify callbacks.
*/
if (*Tsqlite3)(unsafe.Pointer(db)).FautoCommit != 0 {
_sqlite3ConnectionUnlocked(tls, db)
}
if (*TVdbe)(unsafe.Pointer(p)).Frc == int32(SQLITE_BUSY) {
v1 = int32(SQLITE_BUSY)
} else {
v1 = SQLITE_OK
}
return v1
}
// C documentation
//
// /*
// ** Give a listing of the program in the virtual machine.
// **
// ** The interface is the same as sqlite3VdbeExec(). But instead of
// ** running the code, it invokes the callback once for each instruction.
// ** This feature is used to implement "EXPLAIN".
// **
// ** When p->explain==1, each instruction is listed. When
// ** p->explain==2, only OP_Explain instructions are listed and these
// ** are shown in a different format. p->explain==2 is used to implement
// ** EXPLAIN QUERY PLAN.
// ** 2018-04-24: In p->explain==2 mode, the OP_Init opcodes of triggers
// ** are also shown, so that the boundaries between the main program and
// ** each trigger are clear.
// **
// ** When p->explain==1, first the main program is listed, then each of
// ** the trigger subprograms are listed one by one.
// */
func _sqlite3VdbeList(tls *libc.TLS, p uintptr) (r int32) {
bp := tls.Alloc(16)
defer tls.Free(16)
var bListSubprogs, rc int32
var db, pMem, pOp, pSub, zP4 uintptr
var _ /* aOp at bp+8 */ uintptr
var _ /* i at bp+0 */ int32
_, _, _, _, _, _, _ = bListSubprogs, db, pMem, pOp, pSub, rc, zP4
pSub = uintptr(0) /* Memory cell hold array of subprogs */
db = (*TVdbe)(unsafe.Pointer(p)).Fdb /* Loop counter */
rc = SQLITE_OK /* Return code */
pMem = (*TVdbe)(unsafe.Pointer(p)).FaMem + 1*56 /* First Mem of result set */
bListSubprogs = libc.BoolInt32(int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0xc>>2)) == int32(1) || (*Tsqlite3)(unsafe.Pointer(db)).Fflags&uint64(SQLITE_TriggerEQP) != uint64(0)) /* Current opcode */
/* Even though this opcode does not use dynamic strings for
** the result, result columns may become dynamic if the user calls
** sqlite3_column_text16(), causing a translation to UTF-16 encoding.
*/
_releaseMemArray(tls, pMem, int32(8))
if (*TVdbe)(unsafe.Pointer(p)).Frc == int32(SQLITE_NOMEM) {
/* This happens if a malloc() inside a call to sqlite3_column_text() or
** sqlite3_column_text16() failed. */
_sqlite3OomFault(tls, db)
return int32(SQLITE_ERROR)
}
if bListSubprogs != 0 {
/* The first 8 memory cells are used for the result set. So we will
** commandeer the 9th cell to use as storage for an array of pointers
** to trigger subprograms. The VDBE is guaranteed to have at least 9
** cells. */
pSub = (*TVdbe)(unsafe.Pointer(p)).FaMem + 9*56
} else {
pSub = uintptr(0)
}
/* Figure out which opcode is next to display */
rc = _sqlite3VdbeNextOpcode(tls, p, pSub, libc.BoolInt32(int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0xc>>2)) == int32(2)), p+48, bp, bp+8)
if rc == SQLITE_OK {
pOp = **(**uintptr)(__ccgo_up(bp + 8)) + uintptr(**(**int32)(__ccgo_up(bp)))*24
if libc.AtomicLoadNInt32(db+432, libc.Int32FromInt32(__ATOMIC_RELAXED)) != 0 {
(*TVdbe)(unsafe.Pointer(p)).Frc = int32(SQLITE_INTERRUPT)
rc = int32(SQLITE_ERROR)
_sqlite3VdbeError(tls, p, _sqlite3ErrStr(tls, (*TVdbe)(unsafe.Pointer(p)).Frc), 0)
} else {
zP4 = _sqlite3VdbeDisplayP4(tls, db, pOp)
if int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200))&0xc>>2)) == int32(2) {
_sqlite3VdbeMemSetInt64(tls, pMem, int64((*TOp)(unsafe.Pointer(pOp)).Fp1))
_sqlite3VdbeMemSetInt64(tls, pMem+uintptr(1)*56, int64((*TOp)(unsafe.Pointer(pOp)).Fp2))
_sqlite3VdbeMemSetInt64(tls, pMem+uintptr(2)*56, int64((*TOp)(unsafe.Pointer(pOp)).Fp3))
_sqlite3VdbeMemSetStr(tls, pMem+uintptr(3)*56, zP4, int64(-int32(1)), uint8(SQLITE_UTF8), __ccgo_fp(Xsqlite3_free))
} else {
_sqlite3VdbeMemSetInt64(tls, pMem+uintptr(0)*56, int64(**(**int32)(__ccgo_up(bp))))
_sqlite3VdbeMemSetStr(tls, pMem+uintptr(1)*56, _sqlite3OpcodeName(tls, libc.Int32FromUint8((*TOp)(unsafe.Pointer(pOp)).Fopcode)), int64(-int32(1)), uint8(SQLITE_UTF8), libc.UintptrFromInt32(0))
_sqlite3VdbeMemSetInt64(tls, pMem+uintptr(2)*56, int64((*TOp)(unsafe.Pointer(pOp)).Fp1))
_sqlite3VdbeMemSetInt64(tls, pMem+uintptr(3)*56, int64((*TOp)(unsafe.Pointer(pOp)).Fp2))
_sqlite3VdbeMemSetInt64(tls, pMem+uintptr(4)*56, int64((*TOp)(unsafe.Pointer(pOp)).Fp3))
/* pMem+5 for p4 is done last */
_sqlite3VdbeMemSetInt64(tls, pMem+uintptr(6)*56, libc.Int64FromUint16((*TOp)(unsafe.Pointer(pOp)).Fp5))
_sqlite3VdbeMemSetNull(tls, pMem+uintptr(7)*56)
_sqlite3VdbeMemSetStr(tls, pMem+uintptr(5)*56, zP4, int64(-int32(1)), uint8(SQLITE_UTF8), __ccgo_fp(Xsqlite3_free))
}
(*TVdbe)(unsafe.Pointer(p)).FpResultRow = pMem
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
(*TVdbe)(unsafe.Pointer(p)).Frc = int32(SQLITE_NOMEM)
rc = int32(SQLITE_ERROR)
} else {
(*TVdbe)(unsafe.Pointer(p)).Frc = SQLITE_OK
rc = int32(SQLITE_ROW)
}
}
}
return rc
}
// C documentation
//
// /*
// ** While generating code for the min/max optimization, after handling
// ** the aggregate-step call to min() or max(), check to see if any
// ** additional looping is required. If the output order is such that
// ** we are certain that the correct answer has already been found, then
// ** code an OP_Goto to by pass subsequent processing.
// **
// ** Any extra OP_Goto that is coded here is an optimization. The
// ** correct answer should be obtained regardless. This OP_Goto just
// ** makes the answer appear faster.
// */
func _sqlite3WhereMinMaxOptEarlyOut(tls *libc.TLS, v uintptr, pWInfo uintptr) {
var i int32
var pInner uintptr
_, _ = i, pInner
if !(int32(uint32(*(*uint8)(unsafe.Pointer(pWInfo + 68))&0x4>>2)) != 0) {
return
}
if int32((*TWhereInfo)(unsafe.Pointer(pWInfo)).FnOBSat) == 0 {
return
}
i = libc.Int32FromUint8((*TWhereInfo)(unsafe.Pointer(pWInfo)).FnLevel) - int32(1)
for {
if !(i >= 0) {
break
}
pInner = pWInfo + 856 + uintptr(i)*112
if (*TWhereLoop)(unsafe.Pointer((*TWhereLevel)(unsafe.Pointer(pInner)).FpWLoop)).FwsFlags&uint32(WHERE_COLUMN_IN) != uint32(0) {
_sqlite3VdbeGoto(tls, v, (*TWhereLevel)(unsafe.Pointer(pInner)).FaddrNxt)
return
}
goto _1
_1:
;
i = i - 1
}
_sqlite3VdbeGoto(tls, v, (*TWhereInfo)(unsafe.Pointer(pWInfo)).FiBreak)
}
// C documentation
//
// /*
// ** In the ORDER BY LIMIT optimization, if the inner-most loop is known
// ** to emit rows in increasing order, and if the last row emitted by the
// ** inner-most loop did not fit within the sorter, then we can skip all
// ** subsequent rows for the current iteration of the inner loop (because they
// ** will not fit in the sorter either) and continue with the second inner
// ** loop - the loop immediately outside the inner-most.
// **
// ** When a row does not fit in the sorter (because the sorter already
// ** holds LIMIT+OFFSET rows that are smaller), then a jump is made to the
// ** label returned by this function.
// **
// ** If the ORDER BY LIMIT optimization applies, the jump destination should
// ** be the continuation for the second-inner-most loop. If the ORDER BY
// ** LIMIT optimization does not apply, then the jump destination should
// ** be the continuation for the inner-most loop.
// **
// ** It is always safe for this routine to return the continuation of the
// ** inner-most loop, in the sense that a correct answer will result.
// ** Returning the continuation the second inner loop is an optimization
// ** that might make the code run a little faster, but should not change
// ** the final answer.
// */
func _sqlite3WhereOrderByLimitOptLabel(tls *libc.TLS, pWInfo uintptr) (r int32) {
var pInner uintptr
var v1 int32
_, _ = pInner, v1
if !(int32(uint32(*(*uint8)(unsafe.Pointer(pWInfo + 68))&0x4>>2)) != 0) {
/* The ORDER BY LIMIT optimization does not apply. Jump to the
** continuation of the inner-most loop. */
return (*TWhereInfo)(unsafe.Pointer(pWInfo)).FiContinue
}
pInner = pWInfo + 856 + uintptr(libc.Int32FromUint8((*TWhereInfo)(unsafe.Pointer(pWInfo)).FnLevel)-int32(1))*112
if (*TWhereLevel)(unsafe.Pointer(pInner)).FpRJ != 0 {
v1 = (*TWhereInfo)(unsafe.Pointer(pWInfo)).FiContinue
} else {
v1 = (*TWhereLevel)(unsafe.Pointer(pInner)).FaddrNxt
}
return v1
}
// C documentation
//
// /*
// ** Check to see if the frame with header in aFrame[] and content
// ** in aData[] is valid. If it is a valid frame, fill *piPage and
// ** *pnTruncate and return true. Return if the frame is not valid.
// */
func _walDecodeFrame(tls *libc.TLS, pWal uintptr, piPage uintptr, pnTruncate uintptr, aData uintptr, aFrame uintptr) (r int32) {
var aCksum uintptr
var nativeCksum int32
var pgno Tu32
_, _, _ = aCksum, nativeCksum, pgno /* True for native byte-order checksums */
aCksum = pWal + 72 + 24 /* Page number of the frame */
/* A frame is only valid if the salt values in the frame-header
** match the salt values in the wal-header.
*/
if libc.Xmemcmp(tls, pWal+72+32, aFrame+8, uint64(8)) != 0 {
return 0
}
/* A frame is only valid if the page number is greater than zero.
*/
pgno = _sqlite3Get4byte(tls, aFrame)
if pgno == uint32(0) {
return 0
}
/* Need a valid page size
*/
if !((*TWal)(unsafe.Pointer(pWal)).FszPage != 0) {
return 0
}
/* A frame is only valid if a checksum of the WAL header,
** all prior frames, the first 16 bytes of this frame-header,
** and the frame-data matches the checksum in the last 8
** bytes of this frame-header.
*/
nativeCksum = libc.BoolInt32(libc.Int32FromUint8((*TWal)(unsafe.Pointer(pWal)).Fhdr.FbigEndCksum) == SQLITE_BIGENDIAN)
_walChecksumBytes(tls, nativeCksum, aFrame, int32(8), aCksum, aCksum)
_walChecksumBytes(tls, nativeCksum, aData, libc.Int32FromUint32((*TWal)(unsafe.Pointer(pWal)).FszPage), aCksum, aCksum)
if **(**Tu32)(__ccgo_up(aCksum)) != _sqlite3Get4byte(tls, aFrame+16) || **(**Tu32)(__ccgo_up(aCksum + 1*4)) != _sqlite3Get4byte(tls, aFrame+20) {
/* Checksum failed. */
return 0
}
/* If we reach this point, the frame is valid. Return the page number
** and the new database size.
*/
**(**Tu32)(__ccgo_up(piPage)) = pgno
**(**Tu32)(__ccgo_up(pnTruncate)) = _sqlite3Get4byte(tls, aFrame+4)
return int32(1)
}
// C documentation
//
// /*
// ** Information passed in is pWalk->u.pCovIdxCk. Call it pCk.
// **
// ** If the Expr node references the table with cursor pCk->iTabCur, then
// ** make sure that column is covered by the index pCk->pIdx. We know that
// ** all columns less than 63 (really BMS-1) are covered, so we don't need
// ** to check them. But we do need to check any column at 63 or greater.
// **
// ** If the index does not cover the column, then set pWalk->eCode to
// ** non-zero and return WRC_Abort to stop the search.
// **
// ** If this node does not disprove that the index can be a covering index,
// ** then just return WRC_Continue, to continue the search.
// **
// ** If pCk->pIdx contains indexed expressions and one of those expressions
// ** matches pExpr, then prune the search.
// */
func _whereIsCoveringIndexWalkCallback(tls *libc.TLS, pWalk uintptr, pExpr uintptr) (r int32) {
var aiColumn, pCk, pIdx uintptr
var i int32
var nColumn Tu16
_, _, _, _, _ = aiColumn, i, nColumn, pCk, pIdx /* Info about this search */
pCk = *(*uintptr)(unsafe.Pointer(pWalk + 40))
pIdx = (*TCoveringIndexCheck)(unsafe.Pointer(pCk)).FpIdx
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_COLUMN) || libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_AGG_COLUMN) {
/* if( pExpr->iColumn<(BMS-1) && pIdx->bHasExpr==0 ) return WRC_Continue;*/
if (*TExpr)(unsafe.Pointer(pExpr)).FiTable != (*TCoveringIndexCheck)(unsafe.Pointer(pCk)).FiTabCur {
return WRC_Continue
}
pIdx = (*TCoveringIndexCheck)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pWalk + 40)))).FpIdx
aiColumn = (*TIndex)(unsafe.Pointer(pIdx)).FaiColumn
nColumn = (*TIndex)(unsafe.Pointer(pIdx)).FnColumn
i = 0
for {
if !(i < libc.Int32FromUint16(nColumn)) {
break
}
if int32(**(**Ti16)(__ccgo_up(aiColumn + uintptr(i)*2))) == int32((*TExpr)(unsafe.Pointer(pExpr)).FiColumn) {
return WRC_Continue
}
goto _1
_1:
;
i = i + 1
}
(*TCoveringIndexCheck)(unsafe.Pointer(pCk)).FbUnidx = uint8(1)
return int32(WRC_Abort)
} else {
if int32(uint32(*(*uint16)(unsafe.Pointer(pIdx + 100))&0x800>>11)) != 0 && _exprIsCoveredByIndex(tls, pExpr, pIdx, (*TCoveringIndexCheck)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pWalk + 40)))).FiTabCur) != 0 {
(*TCoveringIndexCheck)(unsafe.Pointer(pCk)).FbExpr = uint8(1)
return int32(WRC_Prune)
}
}
return WRC_Continue
}
// C documentation
//
// /*
// ** Estimate the location of a particular key among all keys in an
// ** index. Store the results in aStat as follows:
// **
// ** aStat[0] Est. number of rows less than pRec
// ** aStat[1] Est. number of rows equal to pRec
// **
// ** Return the index of the sample that is the smallest sample that
// ** is greater than or equal to pRec. Note that this index is not an index
// ** into the aSample[] array - it is an index into a virtual set of samples
// ** based on the contents of aSample[] and the number of fields in record
// ** pRec.
// */
func _whereKeyStats(tls *libc.TLS, pParse uintptr, pIdx uintptr, pRec uintptr, roundUp int32, aStat uintptr) (r int32) {
var aSample uintptr
var i, iCol, iMin, iSamp, iSample, iTest, n, nField, res, v1 int32
var iGap, iLower, iUpper TtRowcnt
_, _, _, _, _, _, _, _, _, _, _, _, _, _ = aSample, i, iCol, iGap, iLower, iMin, iSamp, iSample, iTest, iUpper, n, nField, res, v1
aSample = (*TIndex)(unsafe.Pointer(pIdx)).FaSample /* Smallest sample larger than or equal to pRec */
iMin = 0 /* Number of fields in pRec */
iLower = uint64(0) /* anLt[] + anEq[] of largest sample pRec is > */
_ = pParse
/* Do a binary search to find the first sample greater than or equal
** to pRec. If pRec contains a single field, the set of samples to search
** is simply the aSample[] array. If the samples in aSample[] contain more
** than one fields, all fields following the first are ignored.
**
** If pRec contains N fields, where N is more than one, then as well as the
** samples in aSample[] (truncated to N fields), the search also has to
** consider prefixes of those samples. For example, if the set of samples
** in aSample is:
**
** aSample[0] = (a, 5)
** aSample[1] = (a, 10)
** aSample[2] = (b, 5)
** aSample[3] = (c, 100)
** aSample[4] = (c, 105)
**
** Then the search space should ideally be the samples above and the
** unique prefixes [a], [b] and [c]. But since that is hard to organize,
** the code actually searches this set:
**
** 0: (a)
** 1: (a, 5)
** 2: (a, 10)
** 3: (a, 10)
** 4: (b)
** 5: (b, 5)
** 6: (c)
** 7: (c, 100)
** 8: (c, 105)
** 9: (c, 105)
**
** For each sample in the aSample[] array, N samples are present in the
** effective sample array. In the above, samples 0 and 1 are based on
** sample aSample[0]. Samples 2 and 3 on aSample[1] etc.
**
** Often, sample i of each block of N effective samples has (i+1) fields.
** Except, each sample may be extended to ensure that it is greater than or
** equal to the previous sample in the array. For example, in the above,
** sample 2 is the first sample of a block of N samples, so at first it
** appears that it should be 1 field in size. However, that would make it
** smaller than sample 1, so the binary search would not work. As a result,
** it is extended to two fields. The duplicates that this creates do not
** cause any problems.
*/
if !((*TTable)(unsafe.Pointer((*TIndex)(unsafe.Pointer(pIdx)).FpTable)).FtabFlags&libc.Uint32FromInt32(TF_WithoutRowid) == libc.Uint32FromInt32(0)) && int32(uint32(*(*uint16)(unsafe.Pointer(pIdx + 100))&0x3>>0)) == int32(SQLITE_IDXTYPE_PRIMARYKEY) {
nField = libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnKeyCol)
} else {
nField = libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnColumn)
}
if libc.Int32FromUint16((*TUnpackedRecord)(unsafe.Pointer(pRec)).FnField) < nField {
v1 = libc.Int32FromUint16((*TUnpackedRecord)(unsafe.Pointer(pRec)).FnField)
} else {
v1 = nField
}
nField = v1
iCol = 0
iSample = (*TIndex)(unsafe.Pointer(pIdx)).FnSample * nField
for cond := true; cond; cond = res != 0 && iMin < iSample { /* Number of fields in test sample */
iTest = (iMin + iSample) / int32(2)
iSamp = iTest / nField
if iSamp > 0 {
/* The proposed effective sample is a prefix of sample aSample[iSamp].
** Specifically, the shortest prefix of at least (1 + iTest%nField)
** fields that is greater than the previous effective sample. */
n = iTest%nField + int32(1)
for {
if !(n < nField) {
break
}
if **(**TtRowcnt)(__ccgo_up((**(**TIndexSample)(__ccgo_up(aSample + uintptr(iSamp-int32(1))*40))).FanLt + uintptr(n-int32(1))*8)) != **(**TtRowcnt)(__ccgo_up((**(**TIndexSample)(__ccgo_up(aSample + uintptr(iSamp)*40))).FanLt + uintptr(n-int32(1))*8)) {
break
}
goto _2
_2:
;
n = n + 1
}
} else {
n = iTest + int32(1)
}
(*TUnpackedRecord)(unsafe.Pointer(pRec)).FnField = libc.Uint16FromInt32(n)
res = _sqlite3VdbeRecordCompare(tls, (**(**TIndexSample)(__ccgo_up(aSample + uintptr(iSamp)*40))).Fn, (**(**TIndexSample)(__ccgo_up(aSample + uintptr(iSamp)*40))).Fp, pRec)
if res < 0 {
iLower = **(**TtRowcnt)(__ccgo_up((**(**TIndexSample)(__ccgo_up(aSample + uintptr(iSamp)*40))).FanLt + uintptr(n-int32(1))*8)) + **(**TtRowcnt)(__ccgo_up((**(**TIndexSample)(__ccgo_up(aSample + uintptr(iSamp)*40))).FanEq + uintptr(n-int32(1))*8))
iMin = iTest + int32(1)
} else {
if res == 0 && n < nField {
iLower = **(**TtRowcnt)(__ccgo_up((**(**TIndexSample)(__ccgo_up(aSample + uintptr(iSamp)*40))).FanLt + uintptr(n-int32(1))*8))
iMin = iTest + int32(1)
res = -int32(1)
} else {
iSample = iTest
iCol = n - int32(1)
}
}
}
i = iSample / nField
if res == 0 {
/* Record pRec is equal to sample i */
**(**TtRowcnt)(__ccgo_up(aStat)) = **(**TtRowcnt)(__ccgo_up((**(**TIndexSample)(__ccgo_up(aSample + uintptr(i)*40))).FanLt + uintptr(iCol)*8))
**(**TtRowcnt)(__ccgo_up(aStat + 1*8)) = **(**TtRowcnt)(__ccgo_up((**(**TIndexSample)(__ccgo_up(aSample + uintptr(i)*40))).FanEq + uintptr(iCol)*8))
} else {
if i >= (*TIndex)(unsafe.Pointer(pIdx)).FnSample {
iUpper = (*TIndex)(unsafe.Pointer(pIdx)).FnRowEst0
} else {
iUpper = **(**TtRowcnt)(__ccgo_up((**(**TIndexSample)(__ccgo_up(aSample + uintptr(i)*40))).FanLt + uintptr(iCol)*8))
}
if iLower >= iUpper {
iGap = uint64(0)
} else {
iGap = iUpper - iLower
}
if roundUp != 0 {
iGap = iGap * uint64(2) / uint64(3)
} else {
iGap = iGap / uint64(3)
}
**(**TtRowcnt)(__ccgo_up(aStat)) = iLower + iGap
**(**TtRowcnt)(__ccgo_up(aStat + 1*8)) = **(**TtRowcnt)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaAvgEq + uintptr(nField-int32(1))*8))
}
/* Restore the pRec->nField value before returning. */
(*TUnpackedRecord)(unsafe.Pointer(pRec)).FnField = libc.Uint16FromInt32(nField)
return i
}
// C documentation
//
// /*
// ** We have so far matched pBuilder->pNew->u.btree.nEq terms of the
// ** index pIndex. Try to match one more.
// **
// ** When this function is called, pBuilder->pNew->nOut contains the
// ** number of rows expected to be visited by filtering using the nEq
// ** terms only. If it is modified, this value is restored before this
// ** function returns.
// **
// ** If pProbe->idxType==SQLITE_IDXTYPE_IPK, that means pIndex is
// ** a fake index used for the INTEGER PRIMARY KEY.
// */
func _whereLoopAddBtreeIndex(tls *libc.TLS, pBuilder uintptr, pSrc uintptr, pProbe uintptr, nInMul TLogEst) (r int32) {
bp := tls.Alloc(128)
defer tls.Free(128)
var M, logK, nIter, nOutUnadjusted, rCostIdx, rLogSize, rSize, saved_nOut, x TLogEst
var bRedundant, i, iCol, nEq, nIn, nRecValid, nVecLen, opMask, rc, v21 int32
var db, pBtm, pExpr, pExpr1, pNew, pParse, pTerm, pTop, pWInfo, v2 uintptr
var eOp, saved_nBtm, saved_nEq, saved_nLTerm, saved_nSkip, saved_nTop, v4 Tu16
var saved_prereq TBitmask
var saved_wsFlags Tu32
var v22 bool
var _ /* nOut at bp+112 */ TtRowcnt
var _ /* scan at bp+0 */ TWhereScan
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = M, bRedundant, db, eOp, i, iCol, logK, nEq, nIn, nIter, nOutUnadjusted, nRecValid, nVecLen, opMask, pBtm, pExpr, pExpr1, pNew, pParse, pTerm, pTop, pWInfo, rCostIdx, rLogSize, rSize, rc, saved_nBtm, saved_nEq, saved_nLTerm, saved_nOut, saved_nSkip, saved_nTop, saved_prereq, saved_wsFlags, x, v2, v21, v22, v4
pWInfo = (*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FpWInfo /* WHERE analyze context */
pParse = (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpParse /* Parsing context */
db = (*TParse)(unsafe.Pointer(pParse)).Fdb /* Original value of pNew->nOut */
rc = SQLITE_OK /* Logarithm of table size */
pTop = uintptr(0)
pBtm = uintptr(0) /* Top and bottom range constraints */
pNew = (*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FpNew
if (*TParse)(unsafe.Pointer(pParse)).FnErr != 0 {
return (*TParse)(unsafe.Pointer(pParse)).Frc
}
if (*TWhereLoop)(unsafe.Pointer(pNew)).FwsFlags&uint32(WHERE_BTM_LIMIT) != 0 {
opMask = libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_LT)-libc.Int32FromInt32(TK_EQ)) | libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_LE)-libc.Int32FromInt32(TK_EQ))
} else {
opMask = libc.Int32FromInt32(WO_EQ) | libc.Int32FromInt32(WO_IN) | libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_GT)-libc.Int32FromInt32(TK_EQ)) | libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_GE)-libc.Int32FromInt32(TK_EQ)) | libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_LT)-libc.Int32FromInt32(TK_EQ)) | libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_LE)-libc.Int32FromInt32(TK_EQ)) | libc.Int32FromInt32(WO_ISNULL) | libc.Int32FromInt32(WO_IS)
}
if int32(uint32(*(*uint16)(unsafe.Pointer(pProbe + 100))&0x4>>2)) != 0 {
opMask = opMask & ^(libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_GT)-libc.Int32FromInt32(TK_EQ)) | libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_GE)-libc.Int32FromInt32(TK_EQ)) | libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_LT)-libc.Int32FromInt32(TK_EQ)) | libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_LE)-libc.Int32FromInt32(TK_EQ)))
}
saved_nEq = (*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnEq
saved_nBtm = (*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnBtm
saved_nTop = (*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnTop
saved_nSkip = (*TWhereLoop)(unsafe.Pointer(pNew)).FnSkip
saved_nLTerm = (*TWhereLoop)(unsafe.Pointer(pNew)).FnLTerm
saved_wsFlags = (*TWhereLoop)(unsafe.Pointer(pNew)).FwsFlags
saved_prereq = (*TWhereLoop)(unsafe.Pointer(pNew)).Fprereq
saved_nOut = (*TWhereLoop)(unsafe.Pointer(pNew)).FnOut
pTerm = _whereScanInit(tls, bp, (*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FpWC, (*TSrcItem)(unsafe.Pointer(pSrc)).FiCursor, libc.Int32FromUint16(saved_nEq), libc.Uint32FromInt32(opMask), pProbe)
(*TWhereLoop)(unsafe.Pointer(pNew)).FrSetup = 0
rSize = **(**TLogEst)(__ccgo_up((*TIndex)(unsafe.Pointer(pProbe)).FaiRowLogEst))
rLogSize = _estLog(tls, rSize)
for {
if !(rc == SQLITE_OK && pTerm != uintptr(0)) {
break
}
eOp = (*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator /* nOut before IN() and WHERE adjustments */
nIn = 0
nRecValid = (*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FnRecValid
if (libc.Int32FromUint16(eOp) == int32(WO_ISNULL) || libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTerm)).FwtFlags)&int32(TERM_VNULL) != 0) && _indexColumnNotNull(tls, pProbe, libc.Int32FromUint16(saved_nEq)) != 0 {
goto _1 /* ignore IS [NOT] NULL constraints on NOT NULL columns */
}
if (*TWhereTerm)(unsafe.Pointer(pTerm)).FprereqRight&(*TWhereLoop)(unsafe.Pointer(pNew)).FmaskSelf != 0 {
goto _1
}
/* Do not allow the upper bound of a LIKE optimization range constraint
** to mix with a lower range bound from some other source */
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTerm)).FwtFlags)&int32(TERM_LIKEOPT) != 0 && libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator) == libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_LT)-libc.Int32FromInt32(TK_EQ)) {
goto _1
}
if libc.Int32FromUint8((*TSrcItem)(unsafe.Pointer(pSrc)).Ffg.Fjointype)&(libc.Int32FromInt32(JT_LEFT)|libc.Int32FromInt32(JT_LTORJ)|libc.Int32FromInt32(JT_RIGHT)) != 0 && !(_constraintCompatibleWithOuterJoin(tls, pTerm, pSrc) != 0) {
goto _1
}
if libc.Int32FromUint8((*TIndex)(unsafe.Pointer(pProbe)).FonError) != OE_None && libc.Int32FromUint16(saved_nEq) == libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pProbe)).FnKeyCol)-int32(1) {
v2 = pBuilder + 44
*(*uint8)(unsafe.Pointer(v2)) = uint8(int32(*(*uint8)(unsafe.Pointer(v2))) | libc.Int32FromInt32(SQLITE_BLDF1_UNIQUE))
} else {
v2 = pBuilder + 44
*(*uint8)(unsafe.Pointer(v2)) = uint8(int32(*(*uint8)(unsafe.Pointer(v2))) | libc.Int32FromInt32(SQLITE_BLDF1_INDEXED))
}
(*TWhereLoop)(unsafe.Pointer(pNew)).FwsFlags = saved_wsFlags
(*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnEq = saved_nEq
(*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnBtm = saved_nBtm
(*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnTop = saved_nTop
(*TWhereLoop)(unsafe.Pointer(pNew)).FnLTerm = saved_nLTerm
if libc.Int32FromUint16((*TWhereLoop)(unsafe.Pointer(pNew)).FnLTerm) >= libc.Int32FromUint16((*TWhereLoop)(unsafe.Pointer(pNew)).FnLSlot) && _whereLoopResize(tls, db, pNew, libc.Int32FromUint16((*TWhereLoop)(unsafe.Pointer(pNew)).FnLTerm)+int32(1)) != 0 {
break /* OOM while trying to enlarge the pNew->aLTerm array */
}
v2 = pNew + 52
v4 = *(*Tu16)(unsafe.Pointer(v2))
*(*Tu16)(unsafe.Pointer(v2)) = *(*Tu16)(unsafe.Pointer(v2)) + 1
**(**uintptr)(__ccgo_up((*TWhereLoop)(unsafe.Pointer(pNew)).FaLTerm + uintptr(v4)*8)) = pTerm
(*TWhereLoop)(unsafe.Pointer(pNew)).Fprereq = (saved_prereq | (*TWhereTerm)(unsafe.Pointer(pTerm)).FprereqRight) & ^(*TWhereLoop)(unsafe.Pointer(pNew)).FmaskSelf
if libc.Int32FromUint16(eOp)&int32(WO_IN) != 0 {
pExpr = (*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr
if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&uint32(EP_xIsSelect) != uint32(0) {
bRedundant = 0
nIn = int32(46)
/* The expression may actually be of the form (x, y) IN (SELECT...).
** In this case there is a separate term for each of (x) and (y).
** However, the nIn multiplier should only be applied once, not once
** for each such term. The following loop checks that pTerm is the
** first such term in use, and sets nIn back to 0 if it is not. */
i = 0
for {
if !(i < libc.Int32FromUint16((*TWhereLoop)(unsafe.Pointer(pNew)).FnLTerm)-int32(1)) {
break
}
if **(**uintptr)(__ccgo_up((*TWhereLoop)(unsafe.Pointer(pNew)).FaLTerm + uintptr(i)*8)) != 0 && (*TWhereTerm)(unsafe.Pointer(**(**uintptr)(__ccgo_up((*TWhereLoop)(unsafe.Pointer(pNew)).FaLTerm + uintptr(i)*8)))).FpExpr == pExpr {
nIn = 0
if (*(*struct {
FleftColumn int32
FiField int32
})(unsafe.Pointer(**(**uintptr)(__ccgo_up((*TWhereLoop)(unsafe.Pointer(pNew)).FaLTerm + uintptr(i)*8)) + 32))).FiField == (*(*struct {
FleftColumn int32
FiField int32
})(unsafe.Pointer(pTerm + 32))).FiField {
/* Detect when two or more columns of an index match the same
** column of a vector IN operater, and avoid adding the column
** to the WhereLoop more than once. See tag-20250707-01
** in test/rowvalue.test */
bRedundant = int32(1)
}
}
goto _6
_6:
;
i = i + 1
}
if bRedundant != 0 {
(*TWhereLoop)(unsafe.Pointer(pNew)).FnLTerm = (*TWhereLoop)(unsafe.Pointer(pNew)).FnLTerm - 1
goto _1
}
} else {
if *(*uintptr)(unsafe.Pointer(pExpr + 32)) != 0 && (*TExprList)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)))).FnExpr != 0 {
/* "x IN (value, value, ...)" */
nIn = int32(_sqlite3LogEst(tls, libc.Uint64FromInt32((*TExprList)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)))).FnExpr)))
}
}
if int32(uint32(*(*uint16)(unsafe.Pointer(pProbe + 100))&0x80>>7)) != 0 && int32(rLogSize) >= int32(10) {
/* Let:
** N = the total number of rows in the table
** K = the number of entries on the RHS of the IN operator
** M = the number of rows in the table that match terms to the
** to the left in the same index. If the IN operator is on
** the left-most index column, M==N.
**
** Given the definitions above, it is better to omit the IN operator
** from the index lookup and instead do a scan of the M elements,
** testing each scanned row against the IN operator separately, if:
**
** M*log(K) < K*log(N)
**
** Our estimates for M, K, and N might be inaccurate, so we build in
** a safety margin of 2 (LogEst: 10) that favors using the IN operator
** with the index, as using an index has better worst-case behavior.
** If we do not have real sqlite_stat1 data, always prefer to use
** the index. Do not bother with this optimization on very small
** tables (less than 2 rows) as it is pointless in that case.
*/
M = **(**TLogEst)(__ccgo_up((*TIndex)(unsafe.Pointer(pProbe)).FaiRowLogEst + uintptr(saved_nEq)*2))
logK = _estLog(tls, int16(nIn))
/* TUNING v----- 10 to bias toward indexed IN */
x = int16(int32(M) + int32(logK) + int32(10) - (nIn + int32(rLogSize)))
if int32(x) >= 0 {
} else {
if int32(nInMul) < int32(2) && (*Tsqlite3)(unsafe.Pointer(db)).FdbOptFlags&libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_SeekScan)) == uint32(0) {
**(**Tu32)(__ccgo_up(pNew + 48)) |= uint32(WHERE_IN_SEEKSCAN)
} else {
goto _1
}
}
}
**(**Tu32)(__ccgo_up(pNew + 48)) |= uint32(WHERE_COLUMN_IN)
} else {
if libc.Int32FromUint16(eOp)&(libc.Int32FromInt32(WO_EQ)|libc.Int32FromInt32(WO_IS)) != 0 {
iCol = int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pProbe)).FaiColumn + uintptr(saved_nEq)*2)))
**(**Tu32)(__ccgo_up(pNew + 48)) |= uint32(WHERE_COLUMN_EQ)
if iCol == -int32(1) || iCol >= 0 && int32(nInMul) == 0 && libc.Int32FromUint16(saved_nEq) == libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pProbe)).FnKeyCol)-int32(1) {
if iCol == -int32(1) || int32(uint32(*(*uint16)(unsafe.Pointer(pProbe + 100))&0x8>>3)) != 0 || libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pProbe)).FnKeyCol) == int32(1) && (*TIndex)(unsafe.Pointer(pProbe)).FonError != 0 && libc.Int32FromUint16(eOp)&int32(WO_EQ) != 0 {
**(**Tu32)(__ccgo_up(pNew + 48)) |= uint32(WHERE_ONEROW)
} else {
**(**Tu32)(__ccgo_up(pNew + 48)) |= uint32(WHERE_UNQ_WANTED)
}
}
if libc.Int32FromUint8((**(**TWhereScan)(__ccgo_up(bp))).FiEquiv) > int32(1) {
**(**Tu32)(__ccgo_up(pNew + 48)) |= uint32(WHERE_TRANSCONS)
}
} else {
if libc.Int32FromUint16(eOp)&int32(WO_ISNULL) != 0 {
**(**Tu32)(__ccgo_up(pNew + 48)) |= uint32(WHERE_COLUMN_NULL)
} else {
nVecLen = _whereRangeVectorLen(tls, pParse, (*TSrcItem)(unsafe.Pointer(pSrc)).FiCursor, pProbe, libc.Int32FromUint16(saved_nEq), pTerm)
if libc.Int32FromUint16(eOp)&(libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_GT)-libc.Int32FromInt32(TK_EQ))|libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_GE)-libc.Int32FromInt32(TK_EQ))) != 0 {
**(**Tu32)(__ccgo_up(pNew + 48)) |= libc.Uint32FromInt32(libc.Int32FromInt32(WHERE_COLUMN_RANGE) | libc.Int32FromInt32(WHERE_BTM_LIMIT))
(*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnBtm = libc.Uint16FromInt32(nVecLen)
pBtm = pTerm
pTop = uintptr(0)
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTerm)).FwtFlags)&int32(TERM_LIKEOPT) != 0 {
/* Range constraints that come from the LIKE optimization are
** always used in pairs. */
pTop = pTerm + 1*56
if _whereLoopResize(tls, db, pNew, libc.Int32FromUint16((*TWhereLoop)(unsafe.Pointer(pNew)).FnLTerm)+int32(1)) != 0 {
break
} /* OOM */
v2 = pNew + 52
v4 = *(*Tu16)(unsafe.Pointer(v2))
*(*Tu16)(unsafe.Pointer(v2)) = *(*Tu16)(unsafe.Pointer(v2)) + 1
**(**uintptr)(__ccgo_up((*TWhereLoop)(unsafe.Pointer(pNew)).FaLTerm + uintptr(v4)*8)) = pTop
**(**Tu32)(__ccgo_up(pNew + 48)) |= uint32(WHERE_TOP_LIMIT)
(*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnTop = uint16(1)
}
} else {
**(**Tu32)(__ccgo_up(pNew + 48)) |= libc.Uint32FromInt32(libc.Int32FromInt32(WHERE_COLUMN_RANGE) | libc.Int32FromInt32(WHERE_TOP_LIMIT))
(*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnTop = libc.Uint16FromInt32(nVecLen)
pTop = pTerm
if (*TWhereLoop)(unsafe.Pointer(pNew)).FwsFlags&uint32(WHERE_BTM_LIMIT) != uint32(0) {
v2 = **(**uintptr)(__ccgo_up((*TWhereLoop)(unsafe.Pointer(pNew)).FaLTerm + uintptr(libc.Int32FromUint16((*TWhereLoop)(unsafe.Pointer(pNew)).FnLTerm)-int32(2))*8))
} else {
v2 = uintptr(0)
}
pBtm = v2
}
}
}
}
/* At this point pNew->nOut is set to the number of rows expected to
** be visited by the index scan before considering term pTerm, or the
** values of nIn and nInMul. In other words, assuming that all
** "x IN(...)" terms are replaced with "x = ?". This block updates
** the value of pNew->nOut to account for pTerm (but not nIn/nInMul). */
if (*TWhereLoop)(unsafe.Pointer(pNew)).FwsFlags&uint32(WHERE_COLUMN_RANGE) != 0 {
/* Adjust nOut using stat4 data. Or, if there is no stat4
** data, using some other estimate. */
_whereRangeScanEst(tls, pParse, pBuilder, pBtm, pTop, pNew)
} else {
v2 = pNew + 24
*(*Tu16)(unsafe.Pointer(v2)) = *(*Tu16)(unsafe.Pointer(v2)) + 1
v4 = *(*Tu16)(unsafe.Pointer(v2))
nEq = libc.Int32FromUint16(v4)
if int32((*TWhereTerm)(unsafe.Pointer(pTerm)).FtruthProb) <= 0 && int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pProbe)).FaiColumn + uintptr(saved_nEq)*2))) >= 0 {
v2 = pNew + 22
*(*TLogEst)(unsafe.Pointer(v2)) = TLogEst(int32(*(*TLogEst)(unsafe.Pointer(v2))) + int32((*TWhereTerm)(unsafe.Pointer(pTerm)).FtruthProb))
v2 = pNew + 22
*(*TLogEst)(unsafe.Pointer(v2)) = TLogEst(int32(*(*TLogEst)(unsafe.Pointer(v2))) - nIn)
} else {
**(**TtRowcnt)(__ccgo_up(bp + 112)) = uint64(0)
if int32(nInMul) == 0 && (*TIndex)(unsafe.Pointer(pProbe)).FnSample != 0 && libc.Int32FromUint16((*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnEq) <= (*TIndex)(unsafe.Pointer(pProbe)).FnSampleCol && (libc.Int32FromUint16(eOp)&int32(WO_IN) == 0 || (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr)).Fflags&uint32(EP_xIsSelect) == uint32(0)) && (*Tsqlite3)(unsafe.Pointer(db)).FdbOptFlags&libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_Stat4)) == uint32(0) {
pExpr1 = (*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr
if libc.Int32FromUint16(eOp)&(libc.Int32FromInt32(WO_EQ)|libc.Int32FromInt32(WO_ISNULL)|libc.Int32FromInt32(WO_IS)) != 0 {
rc = _whereEqualScanEst(tls, pParse, pBuilder, (*TExpr)(unsafe.Pointer(pExpr1)).FpRight, bp+112)
} else {
rc = _whereInScanEst(tls, pParse, pBuilder, *(*uintptr)(unsafe.Pointer(pExpr1 + 32)), bp+112)
}
if rc == int32(SQLITE_NOTFOUND) {
rc = SQLITE_OK
}
if rc != SQLITE_OK {
break
} /* Jump out of the pTerm loop */
if **(**TtRowcnt)(__ccgo_up(bp + 112)) != 0 {
(*TWhereLoop)(unsafe.Pointer(pNew)).FnOut = _sqlite3LogEst(tls, **(**TtRowcnt)(__ccgo_up(bp + 112)))
if nEq == int32(1) && int32((*TWhereLoop)(unsafe.Pointer(pNew)).FnOut)+int32(10) > int32(**(**TLogEst)(__ccgo_up((*TIndex)(unsafe.Pointer(pProbe)).FaiRowLogEst))) {
v2 = pTerm + 18
*(*Tu16)(unsafe.Pointer(v2)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v2))) | libc.Int32FromInt32(TERM_HIGHTRUTH))
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTerm)).FwtFlags)&int32(TERM_HEURTRUTH) != 0 {
/* If the term has previously been used with an assumption of
** higher selectivity, then set the flag to rerun the
** loop computations. */
v2 = pBuilder + 45
*(*uint8)(unsafe.Pointer(v2)) = uint8(int32(*(*uint8)(unsafe.Pointer(v2))) | libc.Int32FromInt32(SQLITE_BLDF2_2NDPASS))
}
}
if int32((*TWhereLoop)(unsafe.Pointer(pNew)).FnOut) > int32(saved_nOut) {
(*TWhereLoop)(unsafe.Pointer(pNew)).FnOut = saved_nOut
}
v2 = pNew + 22
*(*TLogEst)(unsafe.Pointer(v2)) = TLogEst(int32(*(*TLogEst)(unsafe.Pointer(v2))) - nIn)
}
}
if **(**TtRowcnt)(__ccgo_up(bp + 112)) == uint64(0) {
v2 = pNew + 22
*(*TLogEst)(unsafe.Pointer(v2)) = TLogEst(int32(*(*TLogEst)(unsafe.Pointer(v2))) + (int32(**(**TLogEst)(__ccgo_up((*TIndex)(unsafe.Pointer(pProbe)).FaiRowLogEst + uintptr(nEq)*2))) - int32(**(**TLogEst)(__ccgo_up((*TIndex)(unsafe.Pointer(pProbe)).FaiRowLogEst + uintptr(nEq-int32(1))*2)))))
if libc.Int32FromUint16(eOp)&int32(WO_ISNULL) != 0 {
/* TUNING: If there is no likelihood() value, assume that a
** "col IS NULL" expression matches twice as many rows
** as (col=?). */
v2 = pNew + 22
*(*TLogEst)(unsafe.Pointer(v2)) = TLogEst(int32(*(*TLogEst)(unsafe.Pointer(v2))) + libc.Int32FromInt32(10))
}
}
}
}
/* Set rCostIdx to the estimated cost of visiting selected rows in the
** index. The estimate is the sum of two values:
** 1. The cost of doing one search-by-key to find the first matching
** entry
** 2. Stepping forward in the index pNew->nOut times to find all
** additional matching entries.
*/
if int32(uint32(*(*uint16)(unsafe.Pointer(pProbe + 100))&0x3>>0)) == int32(SQLITE_IDXTYPE_IPK) {
/* The pProbe->szIdxRow is low for an IPK table since the interior
** pages are small. Thus szIdxRow gives a good estimate of seek cost.
** But the leaf pages are full-size, so pProbe->szIdxRow would badly
** under-estimate the scanning cost. */
rCostIdx = int16(int32((*TWhereLoop)(unsafe.Pointer(pNew)).FnOut) + int32(16))
} else {
rCostIdx = int16(int32((*TWhereLoop)(unsafe.Pointer(pNew)).FnOut) + int32(1) + int32(15)*int32((*TIndex)(unsafe.Pointer(pProbe)).FszIdxRow)/int32((*TTable)(unsafe.Pointer((*TSrcItem)(unsafe.Pointer(pSrc)).FpSTab)).FszTabRow))
}
rCostIdx = _sqlite3LogEstAdd(tls, rLogSize, rCostIdx)
/* Estimate the cost of running the loop. If all data is coming
** from the index, then this is just the cost of doing the index
** lookup and scan. But if some data is coming out of the main table,
** we also have to add in the cost of doing pNew->nOut searches to
** locate the row in the main table that corresponds to the index entry.
*/
(*TWhereLoop)(unsafe.Pointer(pNew)).FrRun = rCostIdx
if (*TWhereLoop)(unsafe.Pointer(pNew)).FwsFlags&libc.Uint32FromInt32(libc.Int32FromInt32(WHERE_IDX_ONLY)|libc.Int32FromInt32(WHERE_IPK)|libc.Int32FromInt32(WHERE_EXPRIDX)) == uint32(0) {
(*TWhereLoop)(unsafe.Pointer(pNew)).FrRun = _sqlite3LogEstAdd(tls, (*TWhereLoop)(unsafe.Pointer(pNew)).FrRun, int16(int32((*TWhereLoop)(unsafe.Pointer(pNew)).FnOut)+int32(16)))
}
nOutUnadjusted = (*TWhereLoop)(unsafe.Pointer(pNew)).FnOut
v2 = pNew + 20
*(*TLogEst)(unsafe.Pointer(v2)) = TLogEst(int32(*(*TLogEst)(unsafe.Pointer(v2))) + (int32(nInMul) + nIn))
v2 = pNew + 22
*(*TLogEst)(unsafe.Pointer(v2)) = TLogEst(int32(*(*TLogEst)(unsafe.Pointer(v2))) + (int32(nInMul) + nIn))
_whereLoopOutputAdjust(tls, (*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FpWC, pNew, rSize)
if int32(*(*uint32)(unsafe.Pointer(pSrc + 24 + 4))&0x40000>>18) != 0 {
(*TWhereLoop)(unsafe.Pointer(pNew)).FnOut = 0
}
rc = _whereLoopInsert(tls, pBuilder, pNew)
if (*TWhereLoop)(unsafe.Pointer(pNew)).FwsFlags&uint32(WHERE_COLUMN_RANGE) != 0 {
(*TWhereLoop)(unsafe.Pointer(pNew)).FnOut = saved_nOut
} else {
(*TWhereLoop)(unsafe.Pointer(pNew)).FnOut = nOutUnadjusted
}
if (*TWhereLoop)(unsafe.Pointer(pNew)).FwsFlags&uint32(WHERE_TOP_LIMIT) == uint32(0) && libc.Int32FromUint16((*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnEq) < libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pProbe)).FnColumn) && (libc.Int32FromUint16((*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnEq) < libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pProbe)).FnKeyCol) || int32(uint32(*(*uint16)(unsafe.Pointer(pProbe + 100))&0x3>>0)) != int32(SQLITE_IDXTYPE_PRIMARYKEY)) {
if libc.Int32FromUint16((*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnEq) > int32(3) {
_sqlite3ProgressCheck(tls, pParse)
}
_whereLoopAddBtreeIndex(tls, pBuilder, pSrc, pProbe, int16(int32(nInMul)+nIn))
}
(*TWhereLoop)(unsafe.Pointer(pNew)).FnOut = saved_nOut
(*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FnRecValid = nRecValid
goto _1
_1:
;
pTerm = _whereScanNext(tls, bp)
}
(*TWhereLoop)(unsafe.Pointer(pNew)).Fprereq = saved_prereq
(*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnEq = saved_nEq
(*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnBtm = saved_nBtm
(*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnTop = saved_nTop
(*TWhereLoop)(unsafe.Pointer(pNew)).FnSkip = saved_nSkip
(*TWhereLoop)(unsafe.Pointer(pNew)).FwsFlags = saved_wsFlags
(*TWhereLoop)(unsafe.Pointer(pNew)).FnOut = saved_nOut
(*TWhereLoop)(unsafe.Pointer(pNew)).FnLTerm = saved_nLTerm
/* Consider using a skip-scan if there are no WHERE clause constraints
** available for the left-most terms of the index, and if the average
** number of repeats in the left-most terms is at least 18.
**
** The magic number 18 is selected on the basis that scanning 17 rows
** is almost always quicker than an index seek (even though if the index
** contains fewer than 2^17 rows we assume otherwise in other parts of
** the code). And, even if it is not, it should not be too much slower.
** On the other hand, the extra seeks could end up being significantly
** more expensive. */
if v22 = libc.Int32FromUint16(saved_nEq) == libc.Int32FromUint16(saved_nSkip) && libc.Int32FromUint16(saved_nEq)+int32(1) < libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pProbe)).FnKeyCol) && libc.Int32FromUint16(saved_nEq) == libc.Int32FromUint16((*TWhereLoop)(unsafe.Pointer(pNew)).FnLTerm) && int32(uint32(*(*uint16)(unsafe.Pointer(pProbe + 100))&0x40>>6)) == 0 && int32(uint32(*(*uint16)(unsafe.Pointer(pProbe + 100))&0x80>>7)) != 0 && (*Tsqlite3)(unsafe.Pointer(db)).FdbOptFlags&libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_SkipScan)) == uint32(0) && int32(**(**TLogEst)(__ccgo_up((*TIndex)(unsafe.Pointer(pProbe)).FaiRowLogEst + uintptr(libc.Int32FromUint16(saved_nEq)+int32(1))*2))) >= int32(42) && int32(*(*uint32)(unsafe.Pointer(pSrc + 24 + 4))&0x40000>>18) == 0; v22 {
v21 = _whereLoopResize(tls, db, pNew, libc.Int32FromUint16((*TWhereLoop)(unsafe.Pointer(pNew)).FnLTerm)+int32(1))
rc = v21
}
if v22 && v21 == SQLITE_OK {
(*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnEq = (*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnEq + 1
(*TWhereLoop)(unsafe.Pointer(pNew)).FnSkip = (*TWhereLoop)(unsafe.Pointer(pNew)).FnSkip + 1
v2 = pNew + 52
v4 = *(*Tu16)(unsafe.Pointer(v2))
*(*Tu16)(unsafe.Pointer(v2)) = *(*Tu16)(unsafe.Pointer(v2)) + 1
**(**uintptr)(__ccgo_up((*TWhereLoop)(unsafe.Pointer(pNew)).FaLTerm + uintptr(v4)*8)) = uintptr(0)
**(**Tu32)(__ccgo_up(pNew + 48)) |= uint32(WHERE_SKIPSCAN)
nIter = int16(int32(**(**TLogEst)(__ccgo_up((*TIndex)(unsafe.Pointer(pProbe)).FaiRowLogEst + uintptr(saved_nEq)*2))) - int32(**(**TLogEst)(__ccgo_up((*TIndex)(unsafe.Pointer(pProbe)).FaiRowLogEst + uintptr(libc.Int32FromUint16(saved_nEq)+int32(1))*2))))
v2 = pNew + 22
*(*TLogEst)(unsafe.Pointer(v2)) = TLogEst(int32(*(*TLogEst)(unsafe.Pointer(v2))) - int32(nIter))
/* TUNING: Because uncertainties in the estimates for skip-scan queries,
** add a 1.375 fudge factor to make skip-scan slightly less likely. */
nIter = int16(int32(nIter) + libc.Int32FromInt32(5))
_whereLoopAddBtreeIndex(tls, pBuilder, pSrc, pProbe, int16(int32(nIter)+int32(nInMul)))
(*TWhereLoop)(unsafe.Pointer(pNew)).FnOut = saved_nOut
(*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pNew + 24))).FnEq = saved_nEq
(*TWhereLoop)(unsafe.Pointer(pNew)).FnSkip = saved_nSkip
(*TWhereLoop)(unsafe.Pointer(pNew)).FwsFlags = saved_wsFlags
}
return rc
}
// C documentation
//
// /*
// ** Add all WhereLoop objects for a table of the join identified by
// ** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table.
// **
// ** If there are no LEFT or CROSS JOIN joins in the query, both mPrereq and
// ** mUnusable are set to 0. Otherwise, mPrereq is a mask of all FROM clause
// ** entries that occur before the virtual table in the FROM clause and are
// ** separated from it by at least one LEFT or CROSS JOIN. Similarly, the
// ** mUnusable mask contains all FROM clause entries that occur after the
// ** virtual table and are separated from it by at least one LEFT or
// ** CROSS JOIN.
// **
// ** For example, if the query were:
// **
// ** ... FROM t1, t2 LEFT JOIN t3, t4, vt CROSS JOIN t5, t6;
// **
// ** then mPrereq corresponds to (t1, t2) and mUnusable to (t5, t6).
// **
// ** All the tables in mPrereq must be scanned before the current virtual
// ** table. So any terms for which all prerequisites are satisfied by
// ** mPrereq may be specified as "usable" in all calls to xBestIndex.
// ** Conversely, all tables in mUnusable must be scanned after the current
// ** virtual table, so any terms for which the prerequisites overlap with
// ** mUnusable should always be configured as "not-usable" for xBestIndex.
// */
func _whereLoopAddVirtual(tls *libc.TLS, pBuilder uintptr, mPrereq TBitmask, mUnusable TBitmask) (r int32) {
bp := tls.Alloc(16)
defer tls.Free(16)
var i, iTerm, nConstraint, rc, seenZero, seenZeroNoIN int32
var mBest, mBestNoIn, mNext, mPrev, mThis, v1 TBitmask
var p, pNew, pParse, pSrc, pWC, pWInfo uintptr
var v2 bool
var _ /* bIn at bp+0 */ int32
var _ /* bRetry at bp+8 */ int32
var _ /* mNoOmit at bp+4 */ Tu16
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = i, iTerm, mBest, mBestNoIn, mNext, mPrev, mThis, nConstraint, p, pNew, pParse, pSrc, pWC, pWInfo, rc, seenZero, seenZeroNoIN, v1, v2
rc = SQLITE_OK
**(**int32)(__ccgo_up(bp + 8)) = 0 /* True to retry with LIMIT/OFFSET disabled */
pWInfo = (*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FpWInfo
pParse = (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpParse
pWC = (*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FpWC
pNew = (*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FpNew
pSrc = (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpTabList + 8 + uintptr((*TWhereLoop)(unsafe.Pointer(pNew)).FiTab)*80
p = _allocateIndexInfo(tls, pWInfo, pWC, mUnusable, pSrc, bp+4)
if p == uintptr(0) {
return int32(SQLITE_NOMEM)
}
(*TWhereLoop)(unsafe.Pointer(pNew)).FrSetup = 0
(*TWhereLoop)(unsafe.Pointer(pNew)).FwsFlags = uint32(WHERE_VIRTUALTABLE)
(*TWhereLoop)(unsafe.Pointer(pNew)).FnLTerm = uint16(0)
libc.SetBitFieldPtr8Uint32(pNew+24+4, libc.Uint32FromInt32(0), 0, 0x1)
nConstraint = (*Tsqlite3_index_info)(unsafe.Pointer(p)).FnConstraint
if _whereLoopResize(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pNew, nConstraint) != 0 {
_freeIndexInfo(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, p)
return int32(SQLITE_NOMEM)
}
/* First call xBestIndex() with all constraints usable. */
rc = _whereLoopAddVirtualOne(tls, pBuilder, mPrereq, libc.Uint64FromInt32(-libc.Int32FromInt32(1)), uint16(0), p, **(**Tu16)(__ccgo_up(bp + 4)), bp, bp+8)
if **(**int32)(__ccgo_up(bp + 8)) != 0 {
rc = _whereLoopAddVirtualOne(tls, pBuilder, mPrereq, libc.Uint64FromInt32(-libc.Int32FromInt32(1)), uint16(0), p, **(**Tu16)(__ccgo_up(bp + 4)), bp, uintptr(0))
}
/* If the call to xBestIndex() with all terms enabled produced a plan
** that does not require any source tables (IOW: a plan with mBest==0)
** and does not use an IN(...) operator, then there is no point in making
** any further calls to xBestIndex() since they will all return the same
** result (if the xBestIndex() implementation is sane). */
if v2 = rc == SQLITE_OK; v2 {
v1 = (*TWhereLoop)(unsafe.Pointer(pNew)).Fprereq & ^mPrereq
mBest = v1
}
if v2 && (v1 != uint64(0) || **(**int32)(__ccgo_up(bp)) != 0) {
seenZero = 0 /* True if a plan with no prereqs seen */
seenZeroNoIN = 0 /* Plan with no prereqs and no IN(...) seen */
mPrev = uint64(0)
mBestNoIn = uint64(0)
/* If the plan produced by the earlier call uses an IN(...) term, call
** xBestIndex again, this time with IN(...) terms disabled. */
if **(**int32)(__ccgo_up(bp)) != 0 {
rc = _whereLoopAddVirtualOne(tls, pBuilder, mPrereq, libc.Uint64FromInt32(-libc.Int32FromInt32(1)), uint16(WO_IN), p, **(**Tu16)(__ccgo_up(bp + 4)), bp, uintptr(0))
mBestNoIn = (*TWhereLoop)(unsafe.Pointer(pNew)).Fprereq & ^mPrereq
if mBestNoIn == uint64(0) {
seenZero = int32(1)
seenZeroNoIN = int32(1)
}
}
/* Call xBestIndex once for each distinct value of (prereqRight & ~mPrereq)
** in the set of terms that apply to the current virtual table. */
for rc == SQLITE_OK {
mNext = libc.Uint64FromInt32(-libc.Int32FromInt32(1))
i = 0
for {
if !(i < nConstraint) {
break
}
iTerm = (**(**Tsqlite3_index_constraint)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(p)).FaConstraint + uintptr(i)*12))).FiTermOffset
mThis = (*TWhereTerm)(unsafe.Pointer(_termFromWhereClause(tls, pWC, iTerm))).FprereqRight & ^mPrereq
if mThis > mPrev && mThis < mNext {
mNext = mThis
}
goto _3
_3:
;
i = i + 1
}
mPrev = mNext
if mNext == libc.Uint64FromInt32(-libc.Int32FromInt32(1)) {
break
}
if mNext == mBest || mNext == mBestNoIn {
continue
}
rc = _whereLoopAddVirtualOne(tls, pBuilder, mPrereq, mNext|mPrereq, uint16(0), p, **(**Tu16)(__ccgo_up(bp + 4)), bp, uintptr(0))
if (*TWhereLoop)(unsafe.Pointer(pNew)).Fprereq == mPrereq {
seenZero = int32(1)
if **(**int32)(__ccgo_up(bp)) == 0 {
seenZeroNoIN = int32(1)
}
}
}
/* If the calls to xBestIndex() in the above loop did not find a plan
** that requires no source tables at all (i.e. one guaranteed to be
** usable), make a call here with all source tables disabled */
if rc == SQLITE_OK && seenZero == 0 {
rc = _whereLoopAddVirtualOne(tls, pBuilder, mPrereq, mPrereq, uint16(0), p, **(**Tu16)(__ccgo_up(bp + 4)), bp, uintptr(0))
if **(**int32)(__ccgo_up(bp)) == 0 {
seenZeroNoIN = int32(1)
}
}
/* If the calls to xBestIndex() have so far failed to find a plan
** that requires no source tables at all and does not use an IN(...)
** operator, make a final call to obtain one here. */
if rc == SQLITE_OK && seenZeroNoIN == 0 {
rc = _whereLoopAddVirtualOne(tls, pBuilder, mPrereq, mPrereq, uint16(WO_IN), p, **(**Tu16)(__ccgo_up(bp + 4)), bp, uintptr(0))
}
}
_freeIndexInfo(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, p)
return rc
}
// C documentation
//
// /*
// ** Examine a WherePath (with the addition of the extra WhereLoop of the 6th
// ** parameters) to see if it outputs rows in the requested ORDER BY
// ** (or GROUP BY) without requiring a separate sort operation. Return N:
// **
// ** N>0: N terms of the ORDER BY clause are satisfied
// ** N==0: No terms of the ORDER BY clause are satisfied
// ** N<0: Unknown yet how many terms of ORDER BY might be satisfied.
// **
// ** Note that processing for WHERE_GROUPBY and WHERE_DISTINCTBY is not as
// ** strict. With GROUP BY and DISTINCT the only requirement is that
// ** equivalent rows appear immediately adjacent to one another. GROUP BY
// ** and DISTINCT do not require rows to appear in any particular order as long
// ** as equivalent rows are grouped together. Thus for GROUP BY and DISTINCT
// ** the pOrderBy terms can be matched in any order. With ORDER BY, the
// ** pOrderBy terms must be matched in strict left-to-right order.
// */
func _wherePathSatisfiesOrderBy(tls *libc.TLS, pWInfo uintptr, pOrderBy uintptr, pPath uintptr, wctrlFlags Tu16, nLoop Tu16, pLast uintptr, pRevMask uintptr) (r Ti8) {
bp := tls.Alloc(16)
defer tls.Free(16)
var bOnce, distinctColumns, isMatch, isOrderDistinct, rev, revIdx, revSet, v5 Tu8
var db, p, pColl, pColl1, pColl2, pIndex, pIxExpr, pLoop, pOBExpr, pParse, pTerm, pX, v4 uintptr
var eOp, eqOpMask, nColumn, nKeyCol, nOrderBy Tu16
var i, iColumn, iCur, iLoop, j int32
var m, mTerm, obDone, orderDistinctMask, ready TBitmask
var v11 uint64
var _ /* obSat at bp+0 */ TBitmask
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = bOnce, db, distinctColumns, eOp, eqOpMask, i, iColumn, iCur, iLoop, isMatch, isOrderDistinct, j, m, mTerm, nColumn, nKeyCol, nOrderBy, obDone, orderDistinctMask, p, pColl, pColl1, pColl2, pIndex, pIxExpr, pLoop, pOBExpr, pParse, pTerm, pX, ready, rev, revIdx, revSet, v11, v4, v5 /* A column number within table iCur */
pLoop = uintptr(0) /* The index associated with pLoop */
db = (*TParse)(unsafe.Pointer((*TWhereInfo)(unsafe.Pointer(pWInfo)).FpParse)).Fdb /* Database connection */
**(**TBitmask)(__ccgo_up(bp)) = uint64(0) /* Mask of inner loops */
/*
** We say the WhereLoop is "one-row" if it generates no more than one
** row of output. A WhereLoop is one-row if all of the following are true:
** (a) All index columns match with WHERE_COLUMN_EQ.
** (b) The index is unique
** Any WhereLoop with an WHERE_COLUMN_EQ constraint on the rowid is one-row.
** Every one-row WhereLoop will have the WHERE_ONEROW bit set in wsFlags.
**
** We say the WhereLoop is "order-distinct" if the set of columns from
** that WhereLoop that are in the ORDER BY clause are different for every
** row of the WhereLoop. Every one-row WhereLoop is automatically
** order-distinct. A WhereLoop that has no columns in the ORDER BY clause
** is not order-distinct. To be order-distinct is not quite the same as being
** UNIQUE since a UNIQUE column or index can have multiple rows that
** are NULL and NULL values are equivalent for the purpose of order-distinct.
** To be order-distinct, the columns must be UNIQUE and NOT NULL.
**
** The rowid for a table is always UNIQUE and NOT NULL so whenever the
** rowid appears in the ORDER BY clause, the corresponding WhereLoop is
** automatically order-distinct.
*/
if nLoop != 0 && (*Tsqlite3)(unsafe.Pointer(db)).FdbOptFlags&libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_OrderByIdxJoin)) != uint32(0) {
return 0
}
nOrderBy = libc.Uint16FromInt32((*TExprList)(unsafe.Pointer(pOrderBy)).FnExpr)
if libc.Int32FromUint16(nOrderBy) > libc.Int32FromUint64(libc.Uint64FromInt64(8)*libc.Uint64FromInt32(8))-libc.Int32FromInt32(1) {
return 0
} /* Cannot optimize overly large ORDER BYs */
isOrderDistinct = uint8(1)
obDone = libc.Uint64FromInt32(1)<<nOrderBy - uint64(1)
orderDistinctMask = uint64(0)
ready = uint64(0)
eqOpMask = libc.Uint16FromInt32(libc.Int32FromInt32(WO_EQ) | libc.Int32FromInt32(WO_IS) | libc.Int32FromInt32(WO_ISNULL))
if libc.Int32FromUint16(wctrlFlags)&(libc.Int32FromInt32(WHERE_ORDERBY_LIMIT)|libc.Int32FromInt32(WHERE_ORDERBY_MAX)|libc.Int32FromInt32(WHERE_ORDERBY_MIN)) != 0 {
eqOpMask = libc.Uint16FromInt32(int32(eqOpMask) | libc.Int32FromInt32(WO_IN))
}
iLoop = 0
for {
if !(isOrderDistinct != 0 && **(**TBitmask)(__ccgo_up(bp)) < obDone && iLoop <= libc.Int32FromUint16(nLoop)) {
break
}
if iLoop > 0 {
ready = ready | (*TWhereLoop)(unsafe.Pointer(pLoop)).FmaskSelf
}
if iLoop < libc.Int32FromUint16(nLoop) {
pLoop = **(**uintptr)(__ccgo_up((*TWherePath)(unsafe.Pointer(pPath)).FaLoop + uintptr(iLoop)*8))
if libc.Int32FromUint16(wctrlFlags)&int32(WHERE_ORDERBY_LIMIT) != 0 {
goto _1
}
} else {
pLoop = pLast
}
if (*TWhereLoop)(unsafe.Pointer(pLoop)).FwsFlags&uint32(WHERE_VIRTUALTABLE) != 0 {
if (*(*struct {
FidxNum int32
F__ccgo4 uint8
FisOrdered Ti8
FomitMask Tu16
FidxStr uintptr
FmHandleIn Tu32
})(unsafe.Pointer(pLoop + 24))).FisOrdered != 0 && (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpOrderBy == pOrderBy {
**(**TBitmask)(__ccgo_up(bp)) = obDone
} else {
/* No further ORDER BY terms may be matched. So this call should
** return >=0, not -1. Clear isOrderDistinct to ensure it does so. */
isOrderDistinct = uint8(0)
}
break
}
iCur = (*(*TSrcItem)(unsafe.Pointer((*TWhereInfo)(unsafe.Pointer(pWInfo)).FpTabList + 8 + uintptr((*TWhereLoop)(unsafe.Pointer(pLoop)).FiTab)*80))).FiCursor
/* Mark off any ORDER BY term X that is a column in the table of
** the current loop for which there is term in the WHERE
** clause of the form X IS NULL or X=? that reference only outer
** loops.
*/
i = 0
for {
if !(i < libc.Int32FromUint16(nOrderBy)) {
break
}
if libc.Uint64FromInt32(1)<<i&**(**TBitmask)(__ccgo_up(bp)) != 0 {
goto _2
}
pOBExpr = _sqlite3ExprSkipCollateAndLikely(tls, (*(*TExprList_item)(unsafe.Pointer(pOrderBy + 8 + uintptr(i)*32))).FpExpr)
if pOBExpr == uintptr(0) {
goto _2
}
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pOBExpr)).Fop) != int32(TK_COLUMN) && libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pOBExpr)).Fop) != int32(TK_AGG_COLUMN) {
goto _2
}
if (*TExpr)(unsafe.Pointer(pOBExpr)).FiTable != iCur {
goto _2
}
pTerm = _sqlite3WhereFindTerm(tls, pWInfo+104, iCur, int32((*TExpr)(unsafe.Pointer(pOBExpr)).FiColumn), ^ready, uint32(eqOpMask), uintptr(0))
if pTerm == uintptr(0) {
goto _2
}
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator) == int32(WO_IN) {
/* IN terms are only valid for sorting in the ORDER BY LIMIT
** optimization, and then only if they are actually used
** by the query plan */
j = 0
for {
if !(j < libc.Int32FromUint16((*TWhereLoop)(unsafe.Pointer(pLoop)).FnLTerm) && pTerm != **(**uintptr)(__ccgo_up((*TWhereLoop)(unsafe.Pointer(pLoop)).FaLTerm + uintptr(j)*8))) {
break
}
goto _3
_3:
;
j = j + 1
}
if j >= libc.Int32FromUint16((*TWhereLoop)(unsafe.Pointer(pLoop)).FnLTerm) {
goto _2
}
}
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator)&(libc.Int32FromInt32(WO_EQ)|libc.Int32FromInt32(WO_IS)) != 0 && int32((*TExpr)(unsafe.Pointer(pOBExpr)).FiColumn) >= 0 {
pParse = (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpParse
pColl1 = _sqlite3ExprNNCollSeq(tls, pParse, (*(*TExprList_item)(unsafe.Pointer(pOrderBy + 8 + uintptr(i)*32))).FpExpr)
pColl2 = _sqlite3ExprCompareCollSeq(tls, pParse, (*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr)
if pColl2 == uintptr(0) || _sqlite3StrICmp(tls, (*TCollSeq)(unsafe.Pointer(pColl1)).FzName, (*TCollSeq)(unsafe.Pointer(pColl2)).FzName) != 0 {
goto _2
}
}
**(**TBitmask)(__ccgo_up(bp)) = **(**TBitmask)(__ccgo_up(bp)) | libc.Uint64FromInt32(1)<<i
goto _2
_2:
;
i = i + 1
}
if (*TWhereLoop)(unsafe.Pointer(pLoop)).FwsFlags&uint32(WHERE_ONEROW) == uint32(0) {
if (*TWhereLoop)(unsafe.Pointer(pLoop)).FwsFlags&uint32(WHERE_IPK) != 0 {
if (*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pLoop + 24))).FpOrderBy != 0 && (*Tsqlite3)(unsafe.Pointer(db)).FdbOptFlags&libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_OrderBySubq)) == uint32(0) && _wherePathMatchSubqueryOB(tls, pWInfo, pLoop, iLoop, iCur, pOrderBy, pRevMask, bp) != 0 {
nColumn = uint16(0)
isOrderDistinct = uint8(0)
} else {
nColumn = uint16(1)
}
pIndex = uintptr(0)
nKeyCol = uint16(0)
} else {
v4 = (*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pLoop + 24))).FpIndex
pIndex = v4
if v4 == uintptr(0) || int32(uint32(*(*uint16)(unsafe.Pointer(pIndex + 100))&0x4>>2)) != 0 {
return 0
} else {
nKeyCol = (*TIndex)(unsafe.Pointer(pIndex)).FnKeyCol
nColumn = (*TIndex)(unsafe.Pointer(pIndex)).FnColumn
/* All relevant terms of the index must also be non-NULL in order
** for isOrderDistinct to be true. So the isOrderDistinct value
** computed here might be a false positive. Corrections will be
** made at tag-20210426-1 below */
isOrderDistinct = libc.BoolUint8(libc.Int32FromUint8((*TIndex)(unsafe.Pointer(pIndex)).FonError) != OE_None && (*TWhereLoop)(unsafe.Pointer(pLoop)).FwsFlags&uint32(WHERE_SKIPSCAN) == uint32(0))
}
}
/* Loop through all columns of the index and deal with the ones
** that are not constrained by == or IN.
*/
v5 = libc.Uint8FromInt32(0)
revSet = v5
rev = v5
distinctColumns = uint8(0)
j = 0
for {
if !(j < libc.Int32FromUint16(nColumn)) {
break
}
bOnce = uint8(1) /* True to run the ORDER BY search loop */
if j < libc.Int32FromUint16((*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pLoop + 24))).FnEq) && j >= libc.Int32FromUint16((*TWhereLoop)(unsafe.Pointer(pLoop)).FnSkip) {
eOp = (*TWhereTerm)(unsafe.Pointer(**(**uintptr)(__ccgo_up((*TWhereLoop)(unsafe.Pointer(pLoop)).FaLTerm + uintptr(j)*8)))).FeOperator
/* Skip over == and IS and ISNULL terms. (Also skip IN terms when
** doing WHERE_ORDERBY_LIMIT processing). Except, IS and ISNULL
** terms imply that the index is not UNIQUE NOT NULL in which case
** the loop need to be marked as not order-distinct because it can
** have repeated NULL rows.
**
** If the current term is a column of an ((?,?) IN (SELECT...))
** expression for which the SELECT returns more than one column,
** check that it is the only column used by this loop. Otherwise,
** if it is one of two or more, none of the columns can be
** considered to match an ORDER BY term.
*/
if libc.Int32FromUint16(eOp)&libc.Int32FromUint16(eqOpMask) != 0 {
if libc.Int32FromUint16(eOp)&(libc.Int32FromInt32(WO_ISNULL)|libc.Int32FromInt32(WO_IS)) != 0 {
isOrderDistinct = uint8(0)
}
goto _6
} else {
if libc.Int32FromUint16(eOp)&int32(WO_IN) != 0 {
/* ALWAYS() justification: eOp is an equality operator due to the
** j<pLoop->u.btree.nEq constraint above. Any equality other
** than WO_IN is captured by the previous "if". So this one
** always has to be WO_IN. */
pX = (*TWhereTerm)(unsafe.Pointer(**(**uintptr)(__ccgo_up((*TWhereLoop)(unsafe.Pointer(pLoop)).FaLTerm + uintptr(j)*8)))).FpExpr
i = j + int32(1)
for {
if !(i < libc.Int32FromUint16((*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pLoop + 24))).FnEq)) {
break
}
if (*TWhereTerm)(unsafe.Pointer(**(**uintptr)(__ccgo_up((*TWhereLoop)(unsafe.Pointer(pLoop)).FaLTerm + uintptr(i)*8)))).FpExpr == pX {
bOnce = uint8(0)
break
}
goto _7
_7:
;
i = i + 1
}
}
}
}
/* Get the column number in the table (iColumn) and sort order
** (revIdx) for the j-th column of the index.
*/
if pIndex != 0 {
iColumn = int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIndex)).FaiColumn + uintptr(j)*2)))
revIdx = libc.Uint8FromInt32(libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TIndex)(unsafe.Pointer(pIndex)).FaSortOrder + uintptr(j)))) & int32(KEYINFO_ORDER_DESC))
if iColumn == int32((*TTable)(unsafe.Pointer((*TIndex)(unsafe.Pointer(pIndex)).FpTable)).FiPKey) {
iColumn = -int32(1)
}
} else {
iColumn = -int32(1)
revIdx = uint8(0)
}
/* An unconstrained column that might be NULL means that this
** WhereLoop is not well-ordered. tag-20210426-1
*/
if isOrderDistinct != 0 {
if iColumn >= 0 && j >= libc.Int32FromUint16((*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pLoop + 24))).FnEq) && int32(uint32(*(*uint8)(unsafe.Pointer((*TTable)(unsafe.Pointer((*TIndex)(unsafe.Pointer(pIndex)).FpTable)).FaCol + uintptr(iColumn)*16 + 8))&0xf>>0)) == 0 {
isOrderDistinct = uint8(0)
}
if iColumn == -int32(2) {
isOrderDistinct = uint8(0)
}
}
/* Find the ORDER BY term that corresponds to the j-th column
** of the index and mark that ORDER BY term having been satisfied.
*/
isMatch = uint8(0)
i = 0
for {
if !(bOnce != 0 && i < libc.Int32FromUint16(nOrderBy)) {
break
}
if libc.Uint64FromInt32(1)<<i&**(**TBitmask)(__ccgo_up(bp)) != 0 {
goto _8
}
pOBExpr = _sqlite3ExprSkipCollateAndLikely(tls, (*(*TExprList_item)(unsafe.Pointer(pOrderBy + 8 + uintptr(i)*32))).FpExpr)
if pOBExpr == uintptr(0) {
goto _8
}
if libc.Int32FromUint16(wctrlFlags)&(libc.Int32FromInt32(WHERE_GROUPBY)|libc.Int32FromInt32(WHERE_DISTINCTBY)) == 0 {
bOnce = uint8(0)
}
if iColumn >= -int32(1) {
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pOBExpr)).Fop) != int32(TK_COLUMN) && libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pOBExpr)).Fop) != int32(TK_AGG_COLUMN) {
goto _8
}
if (*TExpr)(unsafe.Pointer(pOBExpr)).FiTable != iCur {
goto _8
}
if int32((*TExpr)(unsafe.Pointer(pOBExpr)).FiColumn) != iColumn {
goto _8
}
} else {
pIxExpr = (*(*TExprList_item)(unsafe.Pointer((*TIndex)(unsafe.Pointer(pIndex)).FaColExpr + 8 + uintptr(j)*32))).FpExpr
if _sqlite3ExprCompareSkip(tls, pOBExpr, pIxExpr, iCur) != 0 {
goto _8
}
}
if iColumn != -int32(1) {
pColl = _sqlite3ExprNNCollSeq(tls, (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpParse, (*(*TExprList_item)(unsafe.Pointer(pOrderBy + 8 + uintptr(i)*32))).FpExpr)
if _sqlite3StrICmp(tls, (*TCollSeq)(unsafe.Pointer(pColl)).FzName, **(**uintptr)(__ccgo_up((*TIndex)(unsafe.Pointer(pIndex)).FazColl + uintptr(j)*8))) != 0 {
goto _8
}
}
if libc.Int32FromUint16(wctrlFlags)&int32(WHERE_DISTINCTBY) != 0 {
(*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pLoop + 24))).FnDistinctCol = libc.Uint16FromInt32(j + int32(1))
}
isMatch = uint8(1)
break
goto _8
_8:
;
i = i + 1
}
if isMatch != 0 && libc.Int32FromUint16(wctrlFlags)&int32(WHERE_GROUPBY) == 0 {
/* Make sure the sort order is compatible in an ORDER BY clause.
** Sort order is irrelevant for a GROUP BY clause. */
if revSet != 0 {
if libc.Int32FromUint8(rev)^libc.Int32FromUint8(revIdx) != libc.Int32FromUint8((*(*TExprList_item)(unsafe.Pointer(pOrderBy + 8 + uintptr(i)*32))).Ffg.FsortFlags)&int32(KEYINFO_ORDER_DESC) {
isMatch = uint8(0)
}
} else {
rev = libc.Uint8FromInt32(libc.Int32FromUint8(revIdx) ^ libc.Int32FromUint8((*(*TExprList_item)(unsafe.Pointer(pOrderBy + 8 + uintptr(i)*32))).Ffg.FsortFlags)&int32(KEYINFO_ORDER_DESC))
if rev != 0 {
**(**TBitmask)(__ccgo_up(pRevMask)) |= libc.Uint64FromInt32(1) << iLoop
}
revSet = uint8(1)
}
}
if isMatch != 0 && libc.Int32FromUint8((*(*TExprList_item)(unsafe.Pointer(pOrderBy + 8 + uintptr(i)*32))).Ffg.FsortFlags)&int32(KEYINFO_ORDER_BIGNULL) != 0 {
if j == libc.Int32FromUint16((*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pLoop + 24))).FnEq) {
**(**Tu32)(__ccgo_up(pLoop + 48)) |= uint32(WHERE_BIGNULL_SORT)
} else {
isMatch = uint8(0)
}
}
if isMatch != 0 {
if iColumn == -int32(1) {
distinctColumns = uint8(1)
}
**(**TBitmask)(__ccgo_up(bp)) = **(**TBitmask)(__ccgo_up(bp)) | libc.Uint64FromInt32(1)<<i
} else {
/* No match found */
if j == 0 || j < libc.Int32FromUint16(nKeyCol) {
isOrderDistinct = uint8(0)
}
break
}
goto _6
_6:
;
j = j + 1
} /* end Loop over all index columns */
if distinctColumns != 0 {
isOrderDistinct = uint8(1)
}
} /* end-if not one-row */
/* Mark off any other ORDER BY terms that reference pLoop */
if isOrderDistinct != 0 {
orderDistinctMask = orderDistinctMask | (*TWhereLoop)(unsafe.Pointer(pLoop)).FmaskSelf
i = 0
for {
if !(i < libc.Int32FromUint16(nOrderBy)) {
break
}
if libc.Uint64FromInt32(1)<<i&**(**TBitmask)(__ccgo_up(bp)) != 0 {
goto _9
}
p = (*(*TExprList_item)(unsafe.Pointer(pOrderBy + 8 + uintptr(i)*32))).FpExpr
mTerm = _sqlite3WhereExprUsage(tls, pWInfo+592, p)
if mTerm == uint64(0) && !(_sqlite3ExprIsConstant(tls, uintptr(0), p) != 0) {
goto _9
}
if mTerm & ^orderDistinctMask == uint64(0) {
**(**TBitmask)(__ccgo_up(bp)) = **(**TBitmask)(__ccgo_up(bp)) | libc.Uint64FromInt32(1)<<i
}
goto _9
_9:
;
i = i + 1
}
}
goto _1
_1:
;
iLoop = iLoop + 1
} /* End the loop over all WhereLoops from outer-most down to inner-most */
if **(**TBitmask)(__ccgo_up(bp)) == obDone {
return libc.Int8FromUint16(nOrderBy)
}
if !(isOrderDistinct != 0) {
i = libc.Int32FromUint16(nOrderBy) - int32(1)
for {
if !(i > 0) {
break
}
if i < libc.Int32FromUint64(libc.Uint64FromInt64(8)*libc.Uint64FromInt32(8)) {
v11 = libc.Uint64FromInt32(1)<<i - uint64(1)
} else {
v11 = uint64(0)
}
m = v11
if **(**TBitmask)(__ccgo_up(bp))&m == m {
return int8(i)
}
goto _10
_10:
;
i = i - 1
}
return 0
}
return int8(-int32(1))
}
// C documentation
//
// /*
// ** Set the reverse-scan order mask to one for all tables in the query
// ** with the exception of MATERIALIZED common table expressions that have
// ** their own internal ORDER BY clauses.
// **
// ** This implements the PRAGMA reverse_unordered_selects=ON setting.
// ** (Also SQLITE_DBCONFIG_REVERSE_SCANORDER).
// */
func _whereReverseScanOrder(tls *libc.TLS, pWInfo uintptr) {
var ii int32
var pItem uintptr
_, _ = ii, pItem
ii = 0
for {
if !(ii < (*TSrcList)(unsafe.Pointer((*TWhereInfo)(unsafe.Pointer(pWInfo)).FpTabList)).FnSrc) {
break
}
pItem = (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpTabList + 8 + uintptr(ii)*80
if !(int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x200>>9) != 0) || libc.Int32FromUint8((*TCteUse)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pItem + 56)))).FeM10d) != M10d_Yes || int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x4>>2) == 0 || (*TSelect)(unsafe.Pointer((*TSubquery)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pItem + 72)))).FpSelect)).FpOrderBy == uintptr(0) {
**(**TBitmask)(__ccgo_up(pWInfo + 96)) |= libc.Uint64FromInt32(1) << ii
}
goto _1
_1:
;
ii = ii + 1
}
}
// C documentation
//
// /*
// ** Most queries use only a single table (they are not joins) and have
// ** simple == constraints against indexed fields. This routine attempts
// ** to plan those simple cases using much less ceremony than the
// ** general-purpose query planner, and thereby yield faster sqlite3_prepare()
// ** times for the common case.
// **
// ** Return non-zero on success, if this query can be handled by this
// ** no-frills query planner. Return zero if this query needs the
// ** general-purpose query planner.
// */
func _whereShortCut(tls *libc.TLS, pBuilder uintptr) (r int32) {
bp := tls.Alloc(112)
defer tls.Free(112)
var iCur, j, opMask, v2 int32
var pIdx, pItem, pLoop, pTab, pTerm, pWC, pWInfo uintptr
var _ /* scan at bp+0 */ TWhereScan
_, _, _, _, _, _, _, _, _, _, _ = iCur, j, opMask, pIdx, pItem, pLoop, pTab, pTerm, pWC, pWInfo, v2
pWInfo = (*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FpWInfo
if libc.Int32FromUint16((*TWhereInfo)(unsafe.Pointer(pWInfo)).FwctrlFlags)&int32(WHERE_OR_SUBCLAUSE) != 0 {
return 0
}
pItem = (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpTabList + 8
pTab = (*TSrcItem)(unsafe.Pointer(pItem)).FpSTab
if libc.Int32FromUint8((*TTable)(unsafe.Pointer(pTab)).FeTabType) == int32(TABTYP_VTAB) {
return 0
}
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x2>>1) != 0 || int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x1>>0) != 0 {
return 0
}
iCur = (*TSrcItem)(unsafe.Pointer(pItem)).FiCursor
pWC = pWInfo + 104
pLoop = (*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FpNew
(*TWhereLoop)(unsafe.Pointer(pLoop)).FwsFlags = uint32(0)
(*TWhereLoop)(unsafe.Pointer(pLoop)).FnSkip = uint16(0)
pTerm = _whereScanInit(tls, bp, pWC, iCur, -int32(1), libc.Uint32FromInt32(libc.Int32FromInt32(WO_EQ)|libc.Int32FromInt32(WO_IS)), uintptr(0))
for pTerm != 0 && (*TWhereTerm)(unsafe.Pointer(pTerm)).FprereqRight != 0 {
pTerm = _whereScanNext(tls, bp)
}
if pTerm != 0 {
(*TWhereLoop)(unsafe.Pointer(pLoop)).FwsFlags = libc.Uint32FromInt32(libc.Int32FromInt32(WHERE_COLUMN_EQ) | libc.Int32FromInt32(WHERE_IPK) | libc.Int32FromInt32(WHERE_ONEROW))
**(**uintptr)(__ccgo_up((*TWhereLoop)(unsafe.Pointer(pLoop)).FaLTerm)) = pTerm
(*TWhereLoop)(unsafe.Pointer(pLoop)).FnLTerm = uint16(1)
(*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pLoop + 24))).FnEq = uint16(1)
/* TUNING: Cost of a rowid lookup is 10 */
(*TWhereLoop)(unsafe.Pointer(pLoop)).FrRun = int16(33) /* 33==sqlite3LogEst(10) */
} else {
pIdx = (*TTable)(unsafe.Pointer(pTab)).FpIndex
for {
if !(pIdx != 0) {
break
}
if !(libc.Int32FromUint8((*TIndex)(unsafe.Pointer(pIdx)).FonError) != libc.Int32FromInt32(OE_None)) || (*TIndex)(unsafe.Pointer(pIdx)).FpPartIdxWhere != uintptr(0) || libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnKeyCol) > libc.Int32FromUint64(libc.Uint64FromInt64(24)/libc.Uint64FromInt64(8)) {
goto _1
}
if int32(uint32(*(*uint16)(unsafe.Pointer(pIdx + 100))&0x8>>3)) != 0 {
v2 = libc.Int32FromInt32(WO_EQ) | libc.Int32FromInt32(WO_IS)
} else {
v2 = int32(WO_EQ)
}
opMask = v2
j = 0
for {
if !(j < libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnKeyCol)) {
break
}
pTerm = _whereScanInit(tls, bp, pWC, iCur, j, libc.Uint32FromInt32(opMask), pIdx)
for pTerm != 0 && (*TWhereTerm)(unsafe.Pointer(pTerm)).FprereqRight != 0 {
pTerm = _whereScanNext(tls, bp)
}
if pTerm == uintptr(0) {
break
}
**(**uintptr)(__ccgo_up((*TWhereLoop)(unsafe.Pointer(pLoop)).FaLTerm + uintptr(j)*8)) = pTerm
goto _3
_3:
;
j = j + 1
}
if j != libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnKeyCol) {
goto _1
}
(*TWhereLoop)(unsafe.Pointer(pLoop)).FwsFlags = libc.Uint32FromInt32(libc.Int32FromInt32(WHERE_COLUMN_EQ) | libc.Int32FromInt32(WHERE_ONEROW) | libc.Int32FromInt32(WHERE_INDEXED))
if int32(uint32(*(*uint16)(unsafe.Pointer(pIdx + 100))&0x20>>5)) != 0 || (*TSrcItem)(unsafe.Pointer(pItem)).FcolUsed&(*TIndex)(unsafe.Pointer(pIdx)).FcolNotIdxed == uint64(0) {
**(**Tu32)(__ccgo_up(pLoop + 48)) |= uint32(WHERE_IDX_ONLY)
}
(*TWhereLoop)(unsafe.Pointer(pLoop)).FnLTerm = libc.Uint16FromInt32(j)
(*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pLoop + 24))).FnEq = libc.Uint16FromInt32(j)
(*(*struct {
FnEq Tu16
FnBtm Tu16
FnTop Tu16
FnDistinctCol Tu16
FpIndex uintptr
FpOrderBy uintptr
})(unsafe.Pointer(pLoop + 24))).FpIndex = pIdx
/* TUNING: Cost of a unique index lookup is 15 */
(*TWhereLoop)(unsafe.Pointer(pLoop)).FrRun = int16(39) /* 39==sqlite3LogEst(15) */
break
goto _1
_1:
;
pIdx = (*TIndex)(unsafe.Pointer(pIdx)).FpNext
}
}
if (*TWhereLoop)(unsafe.Pointer(pLoop)).FwsFlags != 0 {
(*TWhereLoop)(unsafe.Pointer(pLoop)).FnOut = libc.Int16FromInt32(1)
(*(*TWhereLevel)(unsafe.Pointer(pWInfo + 856))).FpWLoop = pLoop
(*TWhereLoop)(unsafe.Pointer(pLoop)).FmaskSelf = uint64(1) /* sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur); */
(*(*TWhereLevel)(unsafe.Pointer(pWInfo + 856))).FiTabCur = iCur
(*TWhereInfo)(unsafe.Pointer(pWInfo)).FnRowOut = int16(1)
if (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpOrderBy != 0 {
(*TWhereInfo)(unsafe.Pointer(pWInfo)).FnOBSat = int8((*TExprList)(unsafe.Pointer((*TWhereInfo)(unsafe.Pointer(pWInfo)).FpOrderBy)).FnExpr)
}
if libc.Int32FromUint16((*TWhereInfo)(unsafe.Pointer(pWInfo)).FwctrlFlags)&int32(WHERE_WANT_DISTINCT) != 0 {
(*TWhereInfo)(unsafe.Pointer(pWInfo)).FeDistinct = uint8(WHERE_DISTINCT_UNIQUE)
}
if libc.Int32FromUint8((**(**TWhereScan)(__ccgo_up(bp))).FiEquiv) > int32(1) {
**(**Tu32)(__ccgo_up(pLoop + 48)) |= uint32(WHERE_TRANSCONS)
}
return int32(1)
}
return 0
}