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.
11575 lines
472 KiB
Go
11575 lines
472 KiB
Go
// Code generated by modernc.org/undup from the per-target sqlite_*.go files; DO NOT EDIT.
|
|
|
|
//go:build (linux && arm64) || (linux && ppc64le) || (linux && riscv64) || (linux && s390x)
|
|
|
|
package sqlite3
|
|
|
|
import (
|
|
"unsafe"
|
|
|
|
"modernc.org/libc"
|
|
)
|
|
|
|
type Tfpos_t = struct {
|
|
F__lldata [0]int64
|
|
F__align [0]float64
|
|
F__opaque [16]uint8
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Given the name of a compile-time option, return true if that option
|
|
// ** was used and false if not.
|
|
// **
|
|
// ** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix
|
|
// ** is not required for a match.
|
|
// */
|
|
func Xsqlite3_compileoption_used(tls *libc.TLS, zOptName uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var azCompileOpt uintptr
|
|
var i, n int32
|
|
var _ /* nOpt at bp+0 */ int32
|
|
_, _, _ = azCompileOpt, i, n
|
|
azCompileOpt = _sqlite3CompileOptions(tls, bp)
|
|
if Xsqlite3_strnicmp(tls, zOptName, __ccgo_ts+26392, int32(7)) == 0 {
|
|
zOptName = zOptName + uintptr(7)
|
|
}
|
|
n = _sqlite3Strlen30(tls, zOptName)
|
|
/* Since nOpt is normally in single digits, a linear search is
|
|
** adequate. No need for a binary search. */
|
|
i = 0
|
|
for {
|
|
if !(i < **(**int32)(__ccgo_up(bp))) {
|
|
break
|
|
}
|
|
if Xsqlite3_strnicmp(tls, zOptName, **(**uintptr)(__ccgo_up(azCompileOpt + uintptr(i)*8)), n) == 0 && _sqlite3IsIdChar(tls, uint8(**(**uint8)(__ccgo_up(**(**uintptr)(__ccgo_up(azCompileOpt + uintptr(i)*8)) + uintptr(n))))) == 0 {
|
|
return int32(1)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Execute SQL code. Return one of the SQLITE_ success/failure
|
|
// ** codes. Also write an error message into memory obtained from
|
|
// ** malloc() and make *pzErrMsg point to that message.
|
|
// **
|
|
// ** If the SQL is a query, then for each row in the query result
|
|
// ** the xCallback() function is called. pArg becomes the first
|
|
// ** argument to xCallback(). If xCallback=NULL then no callback
|
|
// ** is invoked, even for queries.
|
|
// */
|
|
func Xsqlite3_exec(tls *libc.TLS, db uintptr, zSql uintptr, __ccgo_fp_xCallback Tsqlite3_callback, pArg uintptr, pzErrMsg uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var azCols, azVals uintptr
|
|
var callbackIsInit, i, nCol, rc int32
|
|
var _ /* pStmt at bp+8 */ uintptr
|
|
var _ /* zLeftover at bp+0 */ uintptr
|
|
_, _, _, _, _, _ = azCols, azVals, callbackIsInit, i, nCol, rc
|
|
rc = SQLITE_OK /* Tail of unprocessed SQL */
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = uintptr(0) /* The current SQL statement */
|
|
azCols = uintptr(0) /* True if callback data is initialized */
|
|
if !(_sqlite3SafetyCheckOk(tls, db) != 0) {
|
|
return _sqlite3MisuseError(tls, int32(142492))
|
|
}
|
|
if zSql == uintptr(0) {
|
|
zSql = __ccgo_ts + 1704
|
|
}
|
|
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
_sqlite3Error(tls, db, SQLITE_OK)
|
|
for rc == SQLITE_OK && **(**uint8)(__ccgo_up(zSql)) != 0 {
|
|
nCol = 0
|
|
azVals = uintptr(0)
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = uintptr(0)
|
|
rc = Xsqlite3_prepare_v2(tls, db, zSql, -int32(1), bp+8, bp)
|
|
if rc != SQLITE_OK {
|
|
continue
|
|
}
|
|
if !(**(**uintptr)(__ccgo_up(bp + 8)) != 0) {
|
|
/* this happens for a comment or white-space */
|
|
zSql = **(**uintptr)(__ccgo_up(bp))
|
|
continue
|
|
}
|
|
callbackIsInit = 0
|
|
for int32(1) != 0 {
|
|
rc = Xsqlite3_step(tls, **(**uintptr)(__ccgo_up(bp + 8)))
|
|
/* Invoke the callback function if required */
|
|
if __ccgo_fp_xCallback != 0 && (int32(SQLITE_ROW) == rc || int32(SQLITE_DONE) == rc && !(callbackIsInit != 0) && (*Tsqlite3)(unsafe.Pointer(db)).Fflags&uint64(SQLITE_NullCallback) != 0) {
|
|
if !(callbackIsInit != 0) {
|
|
nCol = Xsqlite3_column_count(tls, **(**uintptr)(__ccgo_up(bp + 8)))
|
|
azCols = _sqlite3DbMallocRaw(tls, db, uint64(libc.Uint64FromInt32(libc.Int32FromInt32(2)*nCol+libc.Int32FromInt32(1))*uint64(8)))
|
|
if azCols == uintptr(0) {
|
|
goto exec_out
|
|
}
|
|
i = 0
|
|
for {
|
|
if !(i < nCol) {
|
|
break
|
|
}
|
|
**(**uintptr)(__ccgo_up(azCols + uintptr(i)*8)) = Xsqlite3_column_name(tls, **(**uintptr)(__ccgo_up(bp + 8)), i)
|
|
/* sqlite3VdbeSetColName() installs column names as UTF8
|
|
** strings so there is no way for sqlite3_column_name() to fail. */
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
callbackIsInit = int32(1)
|
|
}
|
|
if rc == int32(SQLITE_ROW) {
|
|
azVals = azCols + uintptr(nCol)*8
|
|
i = 0
|
|
for {
|
|
if !(i < nCol) {
|
|
break
|
|
}
|
|
**(**uintptr)(__ccgo_up(azVals + uintptr(i)*8)) = Xsqlite3_column_text(tls, **(**uintptr)(__ccgo_up(bp + 8)), i)
|
|
if !(**(**uintptr)(__ccgo_up(azVals + uintptr(i)*8)) != 0) && Xsqlite3_column_type(tls, **(**uintptr)(__ccgo_up(bp + 8)), i) != int32(SQLITE_NULL) {
|
|
_sqlite3OomFault(tls, db)
|
|
goto exec_out
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
**(**uintptr)(__ccgo_up(azVals + uintptr(i)*8)) = uintptr(0)
|
|
}
|
|
if (*(*func(*libc.TLS, uintptr, int32, uintptr, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xCallback})))(tls, pArg, nCol, azVals, azCols) != 0 {
|
|
/* EVIDENCE-OF: R-38229-40159 If the callback function to
|
|
** sqlite3_exec() returns non-zero, then sqlite3_exec() will
|
|
** return SQLITE_ABORT. */
|
|
rc = int32(SQLITE_ABORT)
|
|
_sqlite3VdbeFinalize(tls, **(**uintptr)(__ccgo_up(bp + 8)))
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = uintptr(0)
|
|
_sqlite3Error(tls, db, int32(SQLITE_ABORT))
|
|
goto exec_out
|
|
}
|
|
}
|
|
if rc != int32(SQLITE_ROW) {
|
|
rc = _sqlite3VdbeFinalize(tls, **(**uintptr)(__ccgo_up(bp + 8)))
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = uintptr(0)
|
|
zSql = **(**uintptr)(__ccgo_up(bp))
|
|
for libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(zSql)))])&int32(0x01) != 0 {
|
|
zSql = zSql + 1
|
|
}
|
|
break
|
|
}
|
|
}
|
|
_sqlite3DbFree(tls, db, azCols)
|
|
azCols = uintptr(0)
|
|
}
|
|
goto exec_out
|
|
exec_out:
|
|
;
|
|
if **(**uintptr)(__ccgo_up(bp + 8)) != 0 {
|
|
_sqlite3VdbeFinalize(tls, **(**uintptr)(__ccgo_up(bp + 8)))
|
|
}
|
|
_sqlite3DbFree(tls, db, azCols)
|
|
rc = _sqlite3ApiExit(tls, db, rc)
|
|
if rc != SQLITE_OK && pzErrMsg != 0 {
|
|
**(**uintptr)(__ccgo_up(pzErrMsg)) = _sqlite3DbStrDup(tls, uintptr(0), Xsqlite3_errmsg(tls, db))
|
|
if **(**uintptr)(__ccgo_up(pzErrMsg)) == uintptr(0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
_sqlite3Error(tls, db, int32(SQLITE_NOMEM))
|
|
}
|
|
} else {
|
|
if pzErrMsg != 0 {
|
|
**(**uintptr)(__ccgo_up(pzErrMsg)) = uintptr(0)
|
|
}
|
|
}
|
|
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Checkpoint database zDb.
|
|
// */
|
|
func Xsqlite3_wal_checkpoint_v2(tls *libc.TLS, db uintptr, zDb uintptr, eMode int32, pnLog uintptr, pnCkpt uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var iDb, rc int32
|
|
_, _ = iDb, rc /* Schema to checkpoint */
|
|
/* Initialize the output variables to -1 in case an error occurs. */
|
|
if pnLog != 0 {
|
|
**(**int32)(__ccgo_up(pnLog)) = -int32(1)
|
|
}
|
|
if pnCkpt != 0 {
|
|
**(**int32)(__ccgo_up(pnCkpt)) = -int32(1)
|
|
}
|
|
if eMode < -int32(1) || eMode > int32(SQLITE_CHECKPOINT_TRUNCATE) {
|
|
/* EVIDENCE-OF: R-03996-12088 The M parameter must be a valid checkpoint
|
|
** mode: */
|
|
return _sqlite3MisuseError(tls, int32(190116))
|
|
}
|
|
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
if zDb != 0 && **(**uint8)(__ccgo_up(zDb)) != 0 {
|
|
iDb = _sqlite3FindDbName(tls, db, zDb)
|
|
} else {
|
|
iDb = libc.Int32FromInt32(SQLITE_MAX_ATTACHED) + libc.Int32FromInt32(2) /* This means process all schemas */
|
|
}
|
|
if iDb < 0 {
|
|
rc = int32(SQLITE_ERROR)
|
|
_sqlite3ErrorWithMsg(tls, db, int32(SQLITE_ERROR), __ccgo_ts+26053, libc.VaList(bp+8, zDb))
|
|
} else {
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FbusyHandler.FnBusy = 0
|
|
rc = _sqlite3Checkpoint(tls, db, iDb, eMode, pnLog, pnCkpt)
|
|
_sqlite3Error(tls, db, rc)
|
|
}
|
|
rc = _sqlite3ApiExit(tls, db, rc)
|
|
/* If there are no active statements, clear the interrupt flag at this
|
|
** point. */
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FnVdbeActive == 0 {
|
|
libc.AtomicStoreNInt32(db+432, libc.Int32FromInt32(0), libc.Int32FromInt32(__ATOMIC_RELAXED))
|
|
}
|
|
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Fill the InitData structure with an error message that indicates
|
|
// ** that the database is corrupt.
|
|
// */
|
|
func _corruptSchema(tls *libc.TLS, pData uintptr, azObj uintptr, zExtra uintptr) {
|
|
bp := tls.Alloc(48)
|
|
defer tls.Free(48)
|
|
var db, z, zObj, v1 uintptr
|
|
_, _, _, _ = db, z, zObj, v1
|
|
db = (*TInitData)(unsafe.Pointer(pData)).Fdb
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
|
|
(*TInitData)(unsafe.Pointer(pData)).Frc = int32(SQLITE_NOMEM)
|
|
} else {
|
|
if **(**uintptr)(__ccgo_up((*TInitData)(unsafe.Pointer(pData)).FpzErrMsg)) != uintptr(0) {
|
|
/* A error message has already been generated. Do not overwrite it */
|
|
} else {
|
|
if (*TInitData)(unsafe.Pointer(pData)).FmInitFlags&libc.Uint32FromInt32(libc.Int32FromInt32(INITFLAG_AlterMask)) != 0 {
|
|
**(**uintptr)(__ccgo_up((*TInitData)(unsafe.Pointer(pData)).FpzErrMsg)) = _sqlite3MPrintf(tls, db, __ccgo_ts+20051, libc.VaList(bp+8, **(**uintptr)(__ccgo_up(azObj)), **(**uintptr)(__ccgo_up(azObj + 1*8)), _azAlterType[(*TInitData)(unsafe.Pointer(pData)).FmInitFlags&uint32(INITFLAG_AlterMask)-uint32(1)], zExtra))
|
|
(*TInitData)(unsafe.Pointer(pData)).Frc = int32(SQLITE_ERROR)
|
|
} else {
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).Fflags&uint64(SQLITE_WriteSchema) != 0 {
|
|
(*TInitData)(unsafe.Pointer(pData)).Frc = _sqlite3CorruptError(tls, int32(148102))
|
|
} else {
|
|
if **(**uintptr)(__ccgo_up(azObj + 1*8)) != 0 {
|
|
v1 = **(**uintptr)(__ccgo_up(azObj + 1*8))
|
|
} else {
|
|
v1 = __ccgo_ts + 5287
|
|
}
|
|
zObj = v1
|
|
z = _sqlite3MPrintf(tls, db, __ccgo_ts+20079, libc.VaList(bp+8, zObj))
|
|
if zExtra != 0 && **(**uint8)(__ccgo_up(zExtra)) != 0 {
|
|
z = _sqlite3MPrintf(tls, db, __ccgo_ts+20110, libc.VaList(bp+8, z, zExtra))
|
|
}
|
|
**(**uintptr)(__ccgo_up((*TInitData)(unsafe.Pointer(pData)).FpzErrMsg)) = z
|
|
(*TInitData)(unsafe.Pointer(pData)).Frc = _sqlite3CorruptError(tls, int32(148109))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Generate a CREATE TABLE statement appropriate for the given
|
|
// ** table. Memory to hold the text of the statement is obtained
|
|
// ** from sqliteMalloc() and must be freed by the calling function.
|
|
// */
|
|
func _createTableStmt(tls *libc.TLS, db uintptr, p uintptr) (r uintptr) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var i, len1, v2 int32
|
|
var n Ti64
|
|
var pCol, zEnd, zSep, zSep2, zStmt, zType uintptr
|
|
var _ /* k at bp+0 */ int32
|
|
_, _, _, _, _, _, _, _, _, _ = i, len1, n, pCol, zEnd, zSep, zSep2, zStmt, zType, v2
|
|
n = 0
|
|
pCol = (*TTable)(unsafe.Pointer(p)).FaCol
|
|
i = libc.Int32FromInt32(0)
|
|
for {
|
|
if !(i < int32((*TTable)(unsafe.Pointer(p)).FnCol)) {
|
|
break
|
|
}
|
|
n = n + (_identLength(tls, (*TColumn)(unsafe.Pointer(pCol)).FzCnName) + int64(5))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
pCol += 16
|
|
}
|
|
n = n + _identLength(tls, (*TTable)(unsafe.Pointer(p)).FzName)
|
|
if n < int64(50) {
|
|
zSep = __ccgo_ts + 1704
|
|
zSep2 = __ccgo_ts + 14374
|
|
zEnd = __ccgo_ts + 5285
|
|
} else {
|
|
zSep = __ccgo_ts + 14376
|
|
zSep2 = __ccgo_ts + 14380
|
|
zEnd = __ccgo_ts + 14385
|
|
}
|
|
n = n + int64(int32(35)+int32(6)*int32((*TTable)(unsafe.Pointer(p)).FnCol))
|
|
zStmt = _sqlite3DbMallocRaw(tls, uintptr(0), libc.Uint64FromInt64(n))
|
|
if zStmt == uintptr(0) {
|
|
_sqlite3OomFault(tls, db)
|
|
return uintptr(0)
|
|
}
|
|
libc.Xmemcpy(tls, zStmt, __ccgo_ts+14388, uint64(13))
|
|
**(**int32)(__ccgo_up(bp)) = int32(13)
|
|
_identPut(tls, zStmt, bp, (*TTable)(unsafe.Pointer(p)).FzName)
|
|
v2 = **(**int32)(__ccgo_up(bp))
|
|
**(**int32)(__ccgo_up(bp)) = **(**int32)(__ccgo_up(bp)) + 1
|
|
**(**uint8)(__ccgo_up(zStmt + uintptr(v2))) = uint8('(')
|
|
pCol = (*TTable)(unsafe.Pointer(p)).FaCol
|
|
i = libc.Int32FromInt32(0)
|
|
for {
|
|
if !(i < int32((*TTable)(unsafe.Pointer(p)).FnCol)) {
|
|
break
|
|
}
|
|
len1 = _sqlite3Strlen30(tls, zSep)
|
|
libc.Xmemcpy(tls, zStmt+uintptr(**(**int32)(__ccgo_up(bp))), zSep, libc.Uint64FromInt32(len1))
|
|
**(**int32)(__ccgo_up(bp)) = **(**int32)(__ccgo_up(bp)) + len1
|
|
zSep = zSep2
|
|
_identPut(tls, zStmt, bp, (*TColumn)(unsafe.Pointer(pCol)).FzCnName)
|
|
zType = _azType1[libc.Int32FromUint8((*TColumn)(unsafe.Pointer(pCol)).Faffinity)-int32(SQLITE_AFF_BLOB)]
|
|
len1 = _sqlite3Strlen30(tls, zType)
|
|
libc.Xmemcpy(tls, zStmt+uintptr(**(**int32)(__ccgo_up(bp))), zType, libc.Uint64FromInt32(len1))
|
|
**(**int32)(__ccgo_up(bp)) = **(**int32)(__ccgo_up(bp)) + len1
|
|
goto _3
|
|
_3:
|
|
;
|
|
i = i + 1
|
|
pCol += 16
|
|
}
|
|
len1 = _sqlite3Strlen30(tls, zEnd)
|
|
libc.Xmemcpy(tls, zStmt+uintptr(**(**int32)(__ccgo_up(bp))), zEnd, libc.Uint64FromInt32(len1+int32(1)))
|
|
return zStmt
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** An SQL user-function registered to do the work of an DETACH statement. The
|
|
// ** three arguments to the function come directly from a detach statement:
|
|
// **
|
|
// ** DETACH DATABASE x
|
|
// **
|
|
// ** SELECT sqlite_detach(x)
|
|
// */
|
|
func _detachFunc(tls *libc.TLS, context uintptr, NotUsed int32, argv uintptr) {
|
|
bp := tls.Alloc(144)
|
|
defer tls.Free(144)
|
|
var db, pDb, pEntry, pTrig, zName uintptr
|
|
var i int32
|
|
var _ /* zErr at bp+0 */ [128]uint8
|
|
_, _, _, _, _, _ = db, i, pDb, pEntry, pTrig, zName
|
|
zName = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
db = Xsqlite3_context_db_handle(tls, context)
|
|
pDb = uintptr(0)
|
|
_ = NotUsed
|
|
if zName == uintptr(0) {
|
|
zName = __ccgo_ts + 1704
|
|
}
|
|
i = 0
|
|
for {
|
|
if !(i < (*Tsqlite3)(unsafe.Pointer(db)).FnDb) {
|
|
break
|
|
}
|
|
pDb = (*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(i)*32
|
|
if (*TDb)(unsafe.Pointer(pDb)).FpBt == uintptr(0) {
|
|
goto _1
|
|
}
|
|
if _sqlite3DbIsNamed(tls, db, i, zName) != 0 {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if i >= (*Tsqlite3)(unsafe.Pointer(db)).FnDb {
|
|
Xsqlite3_snprintf(tls, int32(128), bp, __ccgo_ts+13470, libc.VaList(bp+136, zName))
|
|
goto detach_error
|
|
}
|
|
if i < int32(2) {
|
|
Xsqlite3_snprintf(tls, int32(128), bp, __ccgo_ts+13491, libc.VaList(bp+136, zName))
|
|
goto detach_error
|
|
}
|
|
if _sqlite3BtreeTxnState(tls, (*TDb)(unsafe.Pointer(pDb)).FpBt) != SQLITE_TXN_NONE || _sqlite3BtreeIsInBackup(tls, (*TDb)(unsafe.Pointer(pDb)).FpBt) != 0 {
|
|
Xsqlite3_snprintf(tls, int32(128), bp, __ccgo_ts+13517, libc.VaList(bp+136, zName))
|
|
goto detach_error
|
|
}
|
|
/* If any TEMP triggers reference the schema being detached, move those
|
|
** triggers to reference the TEMP schema itself. */
|
|
pEntry = (*THash)(unsafe.Pointer((**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + 1*32))).FpSchema + 56)).Ffirst
|
|
for pEntry != 0 {
|
|
pTrig = (*THashElem)(unsafe.Pointer(pEntry)).Fdata
|
|
if (*TTrigger)(unsafe.Pointer(pTrig)).FpTabSchema == (*TDb)(unsafe.Pointer(pDb)).FpSchema {
|
|
(*TTrigger)(unsafe.Pointer(pTrig)).FpTabSchema = (*TTrigger)(unsafe.Pointer(pTrig)).FpSchema
|
|
}
|
|
pEntry = (*THashElem)(unsafe.Pointer(pEntry)).Fnext
|
|
}
|
|
_sqlite3BtreeClose(tls, (*TDb)(unsafe.Pointer(pDb)).FpBt)
|
|
(*TDb)(unsafe.Pointer(pDb)).FpBt = uintptr(0)
|
|
(*TDb)(unsafe.Pointer(pDb)).FpSchema = uintptr(0)
|
|
_sqlite3CollapseDatabaseArray(tls, db)
|
|
return
|
|
goto detach_error
|
|
detach_error:
|
|
;
|
|
Xsqlite3_result_error(tls, context, bp, -int32(1))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The input to this routine is an WhereTerm structure with only the
|
|
// ** "pExpr" field filled in. The job of this routine is to analyze the
|
|
// ** subexpression and populate all the other fields of the WhereTerm
|
|
// ** structure.
|
|
// **
|
|
// ** If the expression is of the form "<expr> <op> X" it gets commuted
|
|
// ** to the standard form of "X <op> <expr>".
|
|
// **
|
|
// ** If the expression is of the form "X <op> Y" where both X and Y are
|
|
// ** columns, then the original expression is unchanged and a new virtual
|
|
// ** term of the form "Y <op> X" is added to the WHERE clause and
|
|
// ** analyzed separately. The original term is marked with TERM_COPIED
|
|
// ** and the new term is marked with TERM_DYNAMIC (because it's pExpr
|
|
// ** needs to be freed with the WhereClause) and TERM_VIRTUAL (because it
|
|
// ** is a commuted copy of a prior term.) The original term has nChild=1
|
|
// ** and the copy has idxParent set to the index of the original term.
|
|
// */
|
|
func _exprAnalyze(tls *libc.TLS, pSrc uintptr, pWC uintptr, idxTerm int32) {
|
|
bp := tls.Alloc(48)
|
|
defer tls.Free(48)
|
|
var c, v12 uint8
|
|
var db, pC, pDup, pExpr, pLeft, pLeft1, pLeft2, pLeft3, pList, pMaskSet, pNew, pNew1, pNewExpr, pNewExpr1, pNewExpr11, pNewExpr2, pNewExpr21, pNewTerm, pNewTerm1, pParse, pRight, pRight1, pStr2, pTerm, pWInfo, t, zCollSeqName, v1 uintptr
|
|
var eExtraOp, opMask, wtFlags Tu16
|
|
var extraRight, prereqAll, prereqColumn, prereqExpr, prereqLeft, x TBitmask
|
|
var i, i1, i2, i3, idxNew, idxNew1, idxNew11, idxNew2, idxNew21, idxNew3, idxNew4, idxNew5, nLeft, op, res, v2 int32
|
|
var v15 bool
|
|
var _ /* aiCurCol at bp+24 */ [2]int32
|
|
var _ /* eOp2 at bp+16 */ uint8
|
|
var _ /* isComplete at bp+8 */ int32
|
|
var _ /* noCase at bp+12 */ int32
|
|
var _ /* pLeft at bp+40 */ uintptr
|
|
var _ /* pRight at bp+32 */ uintptr
|
|
var _ /* pStr1 at bp+0 */ uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = c, db, eExtraOp, extraRight, i, i1, i2, i3, idxNew, idxNew1, idxNew11, idxNew2, idxNew21, idxNew3, idxNew4, idxNew5, nLeft, op, opMask, pC, pDup, pExpr, pLeft, pLeft1, pLeft2, pLeft3, pList, pMaskSet, pNew, pNew1, pNewExpr, pNewExpr1, pNewExpr11, pNewExpr2, pNewExpr21, pNewTerm, pNewTerm1, pParse, pRight, pRight1, pStr2, pTerm, pWInfo, prereqAll, prereqColumn, prereqExpr, prereqLeft, res, t, wtFlags, x, zCollSeqName, v1, v12, v15, v2
|
|
pWInfo = (*TWhereClause)(unsafe.Pointer(pWC)).FpWInfo /* Prerequisites of pExpr */
|
|
extraRight = uint64(0) /* Extra dependencies on LEFT JOIN */
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0) /* RHS of LIKE/GLOB operator */
|
|
**(**int32)(__ccgo_up(bp + 8)) = 0 /* RHS of LIKE/GLOB ends with wildcard */
|
|
**(**int32)(__ccgo_up(bp + 12)) = 0 /* Top-level operator. pExpr->op */
|
|
pParse = (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpParse /* Parsing context */
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb /* Database connection */
|
|
**(**uint8)(__ccgo_up(bp + 16)) = uint8(0) /* Number of elements on left side vector */
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
|
|
return
|
|
}
|
|
pTerm = (*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(idxTerm)*56
|
|
pMaskSet = pWInfo + 592
|
|
pExpr = (*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr
|
|
/* Because malloc() has not failed */
|
|
(*TWhereMaskSet)(unsafe.Pointer(pMaskSet)).FbVarSelect = 0
|
|
prereqLeft = _sqlite3WhereExprUsage(tls, pMaskSet, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft)
|
|
op = libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop)
|
|
if op == int32(TK_IN) {
|
|
if _sqlite3ExprCheckIN(tls, pParse, pExpr) != 0 {
|
|
return
|
|
}
|
|
if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&uint32(EP_xIsSelect) != uint32(0) {
|
|
(*TWhereTerm)(unsafe.Pointer(pTerm)).FprereqRight = _exprSelectUsage(tls, pMaskSet, *(*uintptr)(unsafe.Pointer(pExpr + 32)))
|
|
} else {
|
|
(*TWhereTerm)(unsafe.Pointer(pTerm)).FprereqRight = _sqlite3WhereExprListUsage(tls, pMaskSet, *(*uintptr)(unsafe.Pointer(pExpr + 32)))
|
|
}
|
|
prereqAll = prereqLeft | (*TWhereTerm)(unsafe.Pointer(pTerm)).FprereqRight
|
|
} else {
|
|
(*TWhereTerm)(unsafe.Pointer(pTerm)).FprereqRight = _sqlite3WhereExprUsage(tls, pMaskSet, (*TExpr)(unsafe.Pointer(pExpr)).FpRight)
|
|
if (*TExpr)(unsafe.Pointer(pExpr)).FpLeft == uintptr(0) || (*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_xIsSelect)|libc.Int32FromInt32(EP_IfNullRow)) != uint32(0) || *(*uintptr)(unsafe.Pointer(pExpr + 32)) != uintptr(0) {
|
|
prereqAll = _sqlite3WhereExprUsageNN(tls, pMaskSet, pExpr)
|
|
} else {
|
|
prereqAll = prereqLeft | (*TWhereTerm)(unsafe.Pointer(pTerm)).FprereqRight
|
|
}
|
|
}
|
|
if (*TWhereMaskSet)(unsafe.Pointer(pMaskSet)).FbVarSelect != 0 {
|
|
v1 = pTerm + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(TERM_VARSELECT))
|
|
}
|
|
if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_OuterON)|libc.Int32FromInt32(EP_InnerON)) != uint32(0) {
|
|
x = _sqlite3WhereGetMask(tls, pMaskSet, *(*int32)(unsafe.Pointer(pExpr + 52)))
|
|
if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_OuterON)) != uint32(0) {
|
|
prereqAll = prereqAll | x
|
|
extraRight = x - uint64(1) /* ON clause terms may not be used with an index
|
|
** on left table of a LEFT JOIN. Ticket #3015 */
|
|
} else {
|
|
if prereqAll>>libc.Int32FromInt32(1) >= x {
|
|
**(**Tu32)(__ccgo_up(pExpr + 4)) &= ^libc.Uint32FromInt32(libc.Int32FromInt32(EP_InnerON))
|
|
}
|
|
}
|
|
}
|
|
(*TWhereTerm)(unsafe.Pointer(pTerm)).FprereqAll = prereqAll
|
|
(*TWhereTerm)(unsafe.Pointer(pTerm)).FleftCursor = -int32(1)
|
|
(*TWhereTerm)(unsafe.Pointer(pTerm)).FiParent = -int32(1)
|
|
(*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator = uint16(0)
|
|
if _allowedOp(tls, op) != 0 {
|
|
pLeft = _sqlite3ExprSkipCollate(tls, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft)
|
|
pRight = _sqlite3ExprSkipCollate(tls, (*TExpr)(unsafe.Pointer(pExpr)).FpRight)
|
|
if (*TWhereTerm)(unsafe.Pointer(pTerm)).FprereqRight&prereqLeft == uint64(0) {
|
|
v2 = int32(WO_ALL)
|
|
} else {
|
|
v2 = int32(WO_EQUIV)
|
|
}
|
|
opMask = libc.Uint16FromInt32(v2)
|
|
if (*(*struct {
|
|
FleftColumn int32
|
|
FiField int32
|
|
})(unsafe.Pointer(pTerm + 32))).FiField > 0 {
|
|
pLeft = (*(*TExprList_item)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pLeft + 32)) + 8 + uintptr((*(*struct {
|
|
FleftColumn int32
|
|
FiField int32
|
|
})(unsafe.Pointer(pTerm + 32))).FiField-int32(1))*32))).FpExpr
|
|
}
|
|
if _exprMightBeIndexed(tls, pSrc, bp+24, pLeft, op) != 0 {
|
|
(*TWhereTerm)(unsafe.Pointer(pTerm)).FleftCursor = (**(**[2]int32)(__ccgo_up(bp + 24)))[0]
|
|
(*(*struct {
|
|
FleftColumn int32
|
|
FiField int32
|
|
})(unsafe.Pointer(pTerm + 32))).FleftColumn = (**(**[2]int32)(__ccgo_up(bp + 24)))[int32(1)]
|
|
(*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator = libc.Uint16FromInt32(libc.Int32FromUint16(_operatorMask(tls, op)) & libc.Int32FromUint16(opMask))
|
|
}
|
|
if op == int32(TK_IS) {
|
|
v1 = pTerm + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(TERM_IS))
|
|
}
|
|
if pRight != 0 && _exprMightBeIndexed(tls, pSrc, bp+24, pRight, op) != 0 && !((*TExpr)(unsafe.Pointer(pRight)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_FixedCol)) != libc.Uint32FromInt32(0)) {
|
|
eExtraOp = uint16(0) /* Extra bits for pNew->eOperator */
|
|
if (*TWhereTerm)(unsafe.Pointer(pTerm)).FleftCursor >= 0 {
|
|
pDup = _sqlite3ExprDup(tls, db, pExpr, 0)
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
|
|
_sqlite3ExprDelete(tls, db, pDup)
|
|
return
|
|
}
|
|
idxNew = _whereClauseInsert(tls, pWC, pDup, libc.Uint16FromInt32(libc.Int32FromInt32(TERM_VIRTUAL)|libc.Int32FromInt32(TERM_DYNAMIC)))
|
|
if idxNew == 0 {
|
|
return
|
|
}
|
|
pNew = (*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(idxNew)*56
|
|
_markTermAsChild(tls, pWC, idxNew, idxTerm)
|
|
if op == int32(TK_IS) {
|
|
v1 = pNew + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(TERM_IS))
|
|
}
|
|
pTerm = (*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(idxTerm)*56
|
|
v1 = pTerm + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(TERM_COPIED))
|
|
if _termIsEquivalence(tls, pParse, pDup, (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpTabList) != 0 {
|
|
v1 = pTerm + 20
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(WO_EQUIV))
|
|
eExtraOp = uint16(WO_EQUIV)
|
|
}
|
|
} else {
|
|
pDup = pExpr
|
|
pNew = pTerm
|
|
}
|
|
v1 = pNew + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromUint16(_exprCommute(tls, pParse, pDup)))
|
|
(*TWhereTerm)(unsafe.Pointer(pNew)).FleftCursor = (**(**[2]int32)(__ccgo_up(bp + 24)))[0]
|
|
(*(*struct {
|
|
FleftColumn int32
|
|
FiField int32
|
|
})(unsafe.Pointer(pNew + 32))).FleftColumn = (**(**[2]int32)(__ccgo_up(bp + 24)))[int32(1)]
|
|
(*TWhereTerm)(unsafe.Pointer(pNew)).FprereqRight = prereqLeft | extraRight
|
|
(*TWhereTerm)(unsafe.Pointer(pNew)).FprereqAll = prereqAll
|
|
(*TWhereTerm)(unsafe.Pointer(pNew)).FeOperator = libc.Uint16FromInt32((libc.Int32FromUint16(_operatorMask(tls, libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pDup)).Fop))) + libc.Int32FromUint16(eExtraOp)) & libc.Int32FromUint16(opMask))
|
|
} else {
|
|
if op == int32(TK_ISNULL) && !((*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_OuterON)) != libc.Uint32FromInt32(0)) && 0 == _sqlite3ExprCanBeNull(tls, pLeft) {
|
|
(*TExpr)(unsafe.Pointer(pExpr)).Fop = uint8(TK_TRUEFALSE) /* See tag-20230504-1 */
|
|
*(*uintptr)(unsafe.Pointer(pExpr + 8)) = __ccgo_ts + 8211
|
|
**(**Tu32)(__ccgo_up(pExpr + 4)) |= libc.Uint32FromInt32(libc.Int32FromInt32(EP_IsFalse))
|
|
(*TWhereTerm)(unsafe.Pointer(pTerm)).FprereqAll = uint64(0)
|
|
(*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator = uint16(0)
|
|
}
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_BETWEEN) && libc.Int32FromUint8((*TWhereClause)(unsafe.Pointer(pWC)).Fop) == int32(TK_AND) {
|
|
pList = *(*uintptr)(unsafe.Pointer(pExpr + 32))
|
|
i = 0
|
|
for {
|
|
if !(i < int32(2)) {
|
|
break
|
|
}
|
|
pNewExpr = _sqlite3PExpr(tls, pParse, libc.Int32FromUint8(_ops[i]), _sqlite3ExprDup(tls, db, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, 0), _sqlite3ExprDup(tls, db, (*(*TExprList_item)(unsafe.Pointer(pList + 8 + uintptr(i)*32))).FpExpr, 0))
|
|
_transferJoinMarkings(tls, pNewExpr, pExpr)
|
|
idxNew1 = _whereClauseInsert(tls, pWC, pNewExpr, libc.Uint16FromInt32(libc.Int32FromInt32(TERM_VIRTUAL)|libc.Int32FromInt32(TERM_DYNAMIC)))
|
|
_exprAnalyze(tls, pSrc, pWC, idxNew1)
|
|
pTerm = (*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(idxTerm)*56
|
|
_markTermAsChild(tls, pWC, idxNew1, idxTerm)
|
|
goto _8
|
|
_8:
|
|
;
|
|
i = i + 1
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_OR) && !((*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Collate)) != libc.Uint32FromInt32(0)) {
|
|
_exprAnalyzeOrTerm(tls, pSrc, pWC, idxTerm)
|
|
pTerm = (*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(idxTerm)*56
|
|
} else {
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_NOTNULL) {
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer((*TExpr)(unsafe.Pointer(pExpr)).FpLeft)).Fop) == int32(TK_COLUMN) && int32((*TExpr)(unsafe.Pointer((*TExpr)(unsafe.Pointer(pExpr)).FpLeft)).FiColumn) >= 0 && !((*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_OuterON)) != libc.Uint32FromInt32(0)) {
|
|
pLeft1 = (*TExpr)(unsafe.Pointer(pExpr)).FpLeft
|
|
pNewExpr1 = _sqlite3PExpr(tls, pParse, int32(TK_GT), _sqlite3ExprDup(tls, db, pLeft1, 0), _sqlite3ExprAlloc(tls, db, int32(TK_NULL), uintptr(0), 0))
|
|
idxNew2 = _whereClauseInsert(tls, pWC, pNewExpr1, libc.Uint16FromInt32(libc.Int32FromInt32(TERM_VIRTUAL)|libc.Int32FromInt32(TERM_DYNAMIC)|libc.Int32FromInt32(TERM_VNULL)))
|
|
if idxNew2 != 0 {
|
|
pNewTerm = (*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(idxNew2)*56
|
|
(*TWhereTerm)(unsafe.Pointer(pNewTerm)).FprereqRight = uint64(0)
|
|
(*TWhereTerm)(unsafe.Pointer(pNewTerm)).FleftCursor = (*TExpr)(unsafe.Pointer(pLeft1)).FiTable
|
|
(*(*struct {
|
|
FleftColumn int32
|
|
FiField int32
|
|
})(unsafe.Pointer(pNewTerm + 32))).FleftColumn = int32((*TExpr)(unsafe.Pointer(pLeft1)).FiColumn)
|
|
(*TWhereTerm)(unsafe.Pointer(pNewTerm)).FeOperator = libc.Uint16FromInt32(libc.Int32FromInt32(WO_EQ) << (libc.Int32FromInt32(TK_GT) - libc.Int32FromInt32(TK_EQ)))
|
|
_markTermAsChild(tls, pWC, idxNew2, idxTerm)
|
|
pTerm = (*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(idxTerm)*56
|
|
v1 = pTerm + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(TERM_COPIED))
|
|
(*TWhereTerm)(unsafe.Pointer(pNewTerm)).FprereqAll = (*TWhereTerm)(unsafe.Pointer(pTerm)).FprereqAll
|
|
}
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_FUNCTION) && libc.Int32FromUint8((*TWhereClause)(unsafe.Pointer(pWC)).Fop) == int32(TK_AND) && _isLikeOrGlob(tls, pParse, pExpr, bp, bp+8, bp+12) != 0 { /* Name of collating sequence */
|
|
wtFlags = libc.Uint16FromInt32(libc.Int32FromInt32(TERM_LIKEOPT) | libc.Int32FromInt32(TERM_VIRTUAL) | libc.Int32FromInt32(TERM_DYNAMIC))
|
|
pLeft2 = (*(*TExprList_item)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)) + 8 + 1*32))).FpExpr
|
|
pStr2 = _sqlite3ExprDup(tls, db, **(**uintptr)(__ccgo_up(bp)), 0)
|
|
/* Convert the lower bound to upper-case and the upper bound to
|
|
** lower-case (upper-case is less than lower-case in ASCII) so that
|
|
** the range constraints also work for BLOBs
|
|
*/
|
|
if **(**int32)(__ccgo_up(bp + 12)) != 0 && !((*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer(pParse)).Fdb)).FmallocFailed != 0) {
|
|
v1 = pTerm + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(TERM_LIKE))
|
|
i1 = 0
|
|
for {
|
|
v12 = **(**uint8)(__ccgo_up(*(*uintptr)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)) + 8)) + uintptr(i1)))
|
|
c = v12
|
|
if !(libc.Int32FromUint8(v12) != 0) {
|
|
break
|
|
}
|
|
**(**uint8)(__ccgo_up(*(*uintptr)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)) + 8)) + uintptr(i1))) = libc.Uint8FromInt32(libc.Int32FromUint8(c) & ^(libc.Int32FromUint8(_sqlite3CtypeMap[c]) & libc.Int32FromInt32(0x20)))
|
|
**(**uint8)(__ccgo_up(*(*uintptr)(unsafe.Pointer(pStr2 + 8)) + uintptr(i1))) = _sqlite3UpperToLower[c]
|
|
goto _11
|
|
_11:
|
|
;
|
|
i1 = i1 + 1
|
|
}
|
|
}
|
|
if !((*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0) { /* Last character before the first wildcard */
|
|
pC = *(*uintptr)(unsafe.Pointer(pStr2 + 8)) + uintptr(_sqlite3Strlen30(tls, *(*uintptr)(unsafe.Pointer(pStr2 + 8)))-int32(1))
|
|
if **(**int32)(__ccgo_up(bp + 12)) != 0 {
|
|
/* The point is to increment the last character before the first
|
|
** wildcard. But if we increment '@', that will push it into the
|
|
** alphabetic range where case conversions will mess up the
|
|
** inequality. To avoid this, make sure to also run the full
|
|
** LIKE on all candidate expressions by clearing the isComplete flag
|
|
*/
|
|
if libc.Int32FromUint8(**(**Tu8)(__ccgo_up(pC))) == libc.Int32FromUint8('A')-libc.Int32FromInt32(1) {
|
|
**(**int32)(__ccgo_up(bp + 8)) = 0
|
|
}
|
|
**(**Tu8)(__ccgo_up(pC)) = _sqlite3UpperToLower[**(**Tu8)(__ccgo_up(pC))]
|
|
}
|
|
/* Increment the value of the last utf8 character in the prefix. */
|
|
for libc.Int32FromUint8(**(**Tu8)(__ccgo_up(pC))) == int32(0xBF) && pC > *(*uintptr)(unsafe.Pointer(pStr2 + 8)) {
|
|
**(**Tu8)(__ccgo_up(pC)) = uint8(0x80)
|
|
pC = pC - 1
|
|
}
|
|
/* isLikeOrGlob() guarantees this */
|
|
**(**Tu8)(__ccgo_up(pC)) = **(**Tu8)(__ccgo_up(pC)) + 1
|
|
}
|
|
if **(**int32)(__ccgo_up(bp + 12)) != 0 {
|
|
v1 = __ccgo_ts + 23969
|
|
} else {
|
|
v1 = uintptr(unsafe.Pointer(&_sqlite3StrBINARY))
|
|
}
|
|
zCollSeqName = v1
|
|
pNewExpr11 = _sqlite3ExprDup(tls, db, pLeft2, 0)
|
|
pNewExpr11 = _sqlite3PExpr(tls, pParse, int32(TK_GE), _sqlite3ExprAddCollateString(tls, pParse, pNewExpr11, zCollSeqName), **(**uintptr)(__ccgo_up(bp)))
|
|
_transferJoinMarkings(tls, pNewExpr11, pExpr)
|
|
idxNew11 = _whereClauseInsert(tls, pWC, pNewExpr11, wtFlags)
|
|
pNewExpr21 = _sqlite3ExprDup(tls, db, pLeft2, 0)
|
|
pNewExpr21 = _sqlite3PExpr(tls, pParse, int32(TK_LT), _sqlite3ExprAddCollateString(tls, pParse, pNewExpr21, zCollSeqName), pStr2)
|
|
_transferJoinMarkings(tls, pNewExpr21, pExpr)
|
|
idxNew21 = _whereClauseInsert(tls, pWC, pNewExpr21, wtFlags)
|
|
_exprAnalyze(tls, pSrc, pWC, idxNew11)
|
|
_exprAnalyze(tls, pSrc, pWC, idxNew21)
|
|
pTerm = (*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(idxTerm)*56
|
|
if **(**int32)(__ccgo_up(bp + 8)) != 0 {
|
|
_markTermAsChild(tls, pWC, idxNew11, idxTerm)
|
|
_markTermAsChild(tls, pWC, idxNew21, idxTerm)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* If there is a vector == or IS term - e.g. "(a, b) == (?, ?)" - create
|
|
** new terms for each component comparison - "a = ?" and "b = ?". The
|
|
** new terms completely replace the original vector comparison, which is
|
|
** no longer used.
|
|
**
|
|
** This is only required if at least one side of the comparison operation
|
|
** is not a sub-select.
|
|
**
|
|
** tag-20220128a
|
|
*/
|
|
if v15 = libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_EQ) || libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_IS); v15 {
|
|
v2 = _sqlite3ExprVectorSize(tls, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft)
|
|
nLeft = v2
|
|
}
|
|
if v15 && v2 > int32(1) && _sqlite3ExprVectorSize(tls, (*TExpr)(unsafe.Pointer(pExpr)).FpRight) == nLeft && ((*TExpr)(unsafe.Pointer((*TExpr)(unsafe.Pointer(pExpr)).FpLeft)).Fflags&uint32(EP_xIsSelect) == uint32(0) || (*TExpr)(unsafe.Pointer((*TExpr)(unsafe.Pointer(pExpr)).FpRight)).Fflags&uint32(EP_xIsSelect) == uint32(0)) && libc.Int32FromUint8((*TWhereClause)(unsafe.Pointer(pWC)).Fop) == int32(TK_AND) {
|
|
i2 = 0
|
|
for {
|
|
if !(i2 < nLeft) {
|
|
break
|
|
}
|
|
pLeft3 = _sqlite3ExprForVectorField(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, i2, nLeft)
|
|
pRight1 = _sqlite3ExprForVectorField(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpRight, i2, nLeft)
|
|
pNew1 = _sqlite3PExpr(tls, pParse, libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop), pLeft3, pRight1)
|
|
_transferJoinMarkings(tls, pNew1, pExpr)
|
|
idxNew3 = _whereClauseInsert(tls, pWC, pNew1, libc.Uint16FromInt32(libc.Int32FromInt32(TERM_DYNAMIC)|libc.Int32FromInt32(TERM_SLICE)))
|
|
_exprAnalyze(tls, pSrc, pWC, idxNew3)
|
|
goto _16
|
|
_16:
|
|
;
|
|
i2 = i2 + 1
|
|
}
|
|
pTerm = (*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(idxTerm)*56
|
|
v1 = pTerm + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | (libc.Int32FromInt32(TERM_CODED) | libc.Int32FromInt32(TERM_VIRTUAL))) /* Disable the original */
|
|
(*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator = uint16(WO_ROWVAL)
|
|
} else {
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_IN) && (*(*struct {
|
|
FleftColumn int32
|
|
FiField int32
|
|
})(unsafe.Pointer(pTerm + 32))).FiField == 0 && libc.Int32FromUint8((*TExpr)(unsafe.Pointer((*TExpr)(unsafe.Pointer(pExpr)).FpLeft)).Fop) == int32(TK_VECTOR) && (*TExpr)(unsafe.Pointer(pExpr)).Fflags&uint32(EP_xIsSelect) != uint32(0) && ((*TSelect)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)))).FpPrior == uintptr(0) || (*TSelect)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)))).FselFlags&uint32(SF_Values) != 0) && (*TSelect)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)))).FpWin == uintptr(0) && libc.Int32FromUint8((*TWhereClause)(unsafe.Pointer(pWC)).Fop) == int32(TK_AND) && int64((*TExprList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)))).FpEList)).FnExpr) <= libc.Int64FromInt32(1)<<(libc.Uint64FromInt64(1)*libc.Uint64FromInt32(8))-libc.Int64FromInt32(1) {
|
|
i3 = 0
|
|
for {
|
|
if !(i3 < _sqlite3ExprVectorSize(tls, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft)) {
|
|
break
|
|
}
|
|
idxNew4 = _whereClauseInsert(tls, pWC, pExpr, libc.Uint16FromInt32(libc.Int32FromInt32(TERM_VIRTUAL)|libc.Int32FromInt32(TERM_SLICE)))
|
|
*(*int32)(unsafe.Pointer((*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(idxNew4)*56 + 32 + 4)) = i3 + int32(1)
|
|
_exprAnalyze(tls, pSrc, pWC, idxNew4)
|
|
_markTermAsChild(tls, pWC, idxNew4, idxTerm)
|
|
goto _18
|
|
_18:
|
|
;
|
|
i3 = i3 + 1
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint8((*TWhereClause)(unsafe.Pointer(pWC)).Fop) == int32(TK_AND) {
|
|
**(**uintptr)(__ccgo_up(bp + 32)) = uintptr(0)
|
|
**(**uintptr)(__ccgo_up(bp + 40)) = uintptr(0)
|
|
res = _isAuxiliaryVtabOperator(tls, db, pExpr, bp+16, bp+40, bp+32)
|
|
for {
|
|
v2 = res
|
|
res = res - 1
|
|
if !(v2 > 0) {
|
|
break
|
|
}
|
|
prereqExpr = _sqlite3WhereExprUsage(tls, pMaskSet, **(**uintptr)(__ccgo_up(bp + 32)))
|
|
prereqColumn = _sqlite3WhereExprUsage(tls, pMaskSet, **(**uintptr)(__ccgo_up(bp + 40)))
|
|
if prereqExpr&prereqColumn == uint64(0) {
|
|
pNewExpr2 = _sqlite3PExpr(tls, pParse, int32(TK_MATCH), uintptr(0), _sqlite3ExprDup(tls, db, **(**uintptr)(__ccgo_up(bp + 32)), 0))
|
|
if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_OuterON)) != uint32(0) && pNewExpr2 != 0 {
|
|
**(**Tu32)(__ccgo_up(pNewExpr2 + 4)) |= libc.Uint32FromInt32(libc.Int32FromInt32(EP_OuterON))
|
|
*(*int32)(unsafe.Pointer(pNewExpr2 + 52)) = *(*int32)(unsafe.Pointer(pExpr + 52))
|
|
}
|
|
idxNew5 = _whereClauseInsert(tls, pWC, pNewExpr2, libc.Uint16FromInt32(libc.Int32FromInt32(TERM_VIRTUAL)|libc.Int32FromInt32(TERM_DYNAMIC)))
|
|
pNewTerm1 = (*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(idxNew5)*56
|
|
(*TWhereTerm)(unsafe.Pointer(pNewTerm1)).FprereqRight = prereqExpr | extraRight
|
|
(*TWhereTerm)(unsafe.Pointer(pNewTerm1)).FleftCursor = (*TExpr)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp + 40)))).FiTable
|
|
(*(*struct {
|
|
FleftColumn int32
|
|
FiField int32
|
|
})(unsafe.Pointer(pNewTerm1 + 32))).FleftColumn = int32((*TExpr)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp + 40)))).FiColumn)
|
|
(*TWhereTerm)(unsafe.Pointer(pNewTerm1)).FeOperator = uint16(WO_AUX)
|
|
(*TWhereTerm)(unsafe.Pointer(pNewTerm1)).FeMatchOp = **(**uint8)(__ccgo_up(bp + 16))
|
|
_markTermAsChild(tls, pWC, idxNew5, idxTerm)
|
|
pTerm = (*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(idxTerm)*56
|
|
v1 = pTerm + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(TERM_COPIED))
|
|
(*TWhereTerm)(unsafe.Pointer(pNewTerm1)).FprereqAll = (*TWhereTerm)(unsafe.Pointer(pTerm)).FprereqAll
|
|
}
|
|
t = **(**uintptr)(__ccgo_up(bp + 40))
|
|
**(**uintptr)(__ccgo_up(bp + 40)) = **(**uintptr)(__ccgo_up(bp + 32))
|
|
**(**uintptr)(__ccgo_up(bp + 32)) = t
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* Prevent ON clause terms of a LEFT JOIN from being used to drive
|
|
** an index for tables to the left of the join.
|
|
*/
|
|
pTerm = (*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(idxTerm)*56
|
|
**(**TBitmask)(__ccgo_up(pTerm + 40)) |= extraRight
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Generate code to implement special SQL functions that are implemented
|
|
// ** in-line rather than by using the usual callbacks.
|
|
// */
|
|
func _exprCodeInlineFunction(tls *libc.TLS, pParse uintptr, pFarg uintptr, iFuncId int32, target int32) (r int32) {
|
|
bp := tls.Alloc(80)
|
|
defer tls.Free(80)
|
|
var aff uint8
|
|
var azAff [6]uintptr
|
|
var endCoalesce, i, nFarg int32
|
|
var pA1, pArg, v, v2 uintptr
|
|
var _ /* caseExpr at bp+0 */ TExpr
|
|
_, _, _, _, _, _, _, _, _ = aff, azAff, endCoalesce, i, nFarg, pA1, pArg, v, v2
|
|
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
|
|
nFarg = (*TExprList)(unsafe.Pointer(pFarg)).FnExpr
|
|
/* All in-line functions have at least one argument */
|
|
switch iFuncId {
|
|
case INLINEFUNC_coalesce:
|
|
/* Attempt a direct implementation of the built-in COALESCE() and
|
|
** IFNULL() functions. This avoids unnecessary evaluation of
|
|
** arguments past the first non-NULL argument.
|
|
*/
|
|
endCoalesce = _sqlite3VdbeMakeLabel(tls, pParse)
|
|
_sqlite3ExprCode(tls, pParse, (*(*TExprList_item)(unsafe.Pointer(pFarg + 8))).FpExpr, target)
|
|
i = int32(1)
|
|
for {
|
|
if !(i < nFarg) {
|
|
break
|
|
}
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_NotNull), target, endCoalesce)
|
|
_sqlite3ExprCode(tls, pParse, (*(*TExprList_item)(unsafe.Pointer(pFarg + 8 + uintptr(i)*32))).FpExpr, target)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_setDoNotMergeFlagOnCopy(tls, v)
|
|
_sqlite3VdbeResolveLabel(tls, v, endCoalesce)
|
|
case int32(INLINEFUNC_iif):
|
|
libc.Xmemset(tls, bp, 0, uint64(72))
|
|
(**(**TExpr)(__ccgo_up(bp))).Fop = uint8(TK_CASE)
|
|
*(*uintptr)(unsafe.Pointer(bp + 32)) = pFarg
|
|
return _sqlite3ExprCodeTarget(tls, pParse, bp, target)
|
|
case int32(INLINEFUNC_sqlite_offset):
|
|
pArg = (*(*TExprList_item)(unsafe.Pointer(pFarg + 8))).FpExpr
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pArg)).Fop) == int32(TK_COLUMN) && (*TExpr)(unsafe.Pointer(pArg)).FiTable >= 0 {
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Offset), (*TExpr)(unsafe.Pointer(pArg)).FiTable, int32((*TExpr)(unsafe.Pointer(pArg)).FiColumn), target)
|
|
} else {
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Null), 0, target)
|
|
}
|
|
default:
|
|
/* The UNLIKELY() function is a no-op. The result is the value
|
|
** of the first argument.
|
|
*/
|
|
target = _sqlite3ExprCodeTarget(tls, pParse, (*(*TExprList_item)(unsafe.Pointer(pFarg + 8))).FpExpr, target)
|
|
break
|
|
/***********************************************************************
|
|
** Test-only SQL functions that are only usable if enabled
|
|
** via SQLITE_TESTCTRL_INTERNAL_FUNCTIONS
|
|
*/
|
|
fallthrough
|
|
case int32(INLINEFUNC_expr_compare):
|
|
/* Compare two expressions using sqlite3ExprCompare() */
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Integer), _sqlite3ExprCompare(tls, uintptr(0), (*(*TExprList_item)(unsafe.Pointer(pFarg + 8))).FpExpr, (*(*TExprList_item)(unsafe.Pointer(pFarg + 8 + 1*32))).FpExpr, -int32(1)), target)
|
|
case int32(INLINEFUNC_expr_implies_expr):
|
|
/* Compare two expressions using sqlite3ExprImpliesExpr() */
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Integer), _sqlite3ExprImpliesExpr(tls, pParse, (*(*TExprList_item)(unsafe.Pointer(pFarg + 8))).FpExpr, (*(*TExprList_item)(unsafe.Pointer(pFarg + 8 + 1*32))).FpExpr, -int32(1)), target)
|
|
case int32(INLINEFUNC_implies_nonnull_row):
|
|
pA1 = (*(*TExprList_item)(unsafe.Pointer(pFarg + 8 + 1*32))).FpExpr
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pA1)).Fop) == int32(TK_COLUMN) {
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Integer), _sqlite3ExprImpliesNonNullRow(tls, (*(*TExprList_item)(unsafe.Pointer(pFarg + 8))).FpExpr, (*TExpr)(unsafe.Pointer(pA1)).FiTable, int32(1)), target)
|
|
} else {
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Null), 0, target)
|
|
}
|
|
case int32(INLINEFUNC_affinity):
|
|
/* The AFFINITY() function evaluates to a string that describes
|
|
** the type affinity of the argument. This is used for testing of
|
|
** the SQLite type logic.
|
|
*/
|
|
azAff = [6]uintptr{
|
|
0: __ccgo_ts + 8510,
|
|
1: __ccgo_ts + 8515,
|
|
2: __ccgo_ts + 8520,
|
|
3: __ccgo_ts + 6520,
|
|
4: __ccgo_ts + 6515,
|
|
5: __ccgo_ts + 8528,
|
|
}
|
|
aff = _sqlite3ExprAffinity(tls, (*(*TExprList_item)(unsafe.Pointer(pFarg + 8))).FpExpr)
|
|
if libc.Int32FromUint8(aff) <= int32(SQLITE_AFF_NONE) {
|
|
v2 = __ccgo_ts + 8536
|
|
} else {
|
|
v2 = azAff[libc.Int32FromUint8(aff)-int32(SQLITE_AFF_BLOB)]
|
|
}
|
|
_sqlite3VdbeLoadString(tls, v, target, v2)
|
|
break
|
|
}
|
|
return target
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is called by unixOpen() to determine the unix permissions
|
|
// ** to create new files with. If no error occurs, then SQLITE_OK is returned
|
|
// ** and a value suitable for passing as the third argument to open(2) is
|
|
// ** written to *pMode. If an IO error occurs, an SQLite error code is
|
|
// ** returned and the value of *pMode is not modified.
|
|
// **
|
|
// ** In most cases, this routine sets *pMode to 0, which will become
|
|
// ** an indication to robust_open() to create the file using
|
|
// ** SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask.
|
|
// ** But if the file being opened is a WAL or regular journal file, then
|
|
// ** this function queries the file-system for the permissions on the
|
|
// ** corresponding database file and sets *pMode to this value. Whenever
|
|
// ** possible, WAL and journal files are created using the same permissions
|
|
// ** as the associated database file.
|
|
// **
|
|
// ** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
|
|
// ** original filename is unavailable. But 8_3_NAMES is only used for
|
|
// ** FAT filesystems and permissions do not matter there, so just use
|
|
// ** the default permissions. In 8_3_NAMES mode, leave *pMode set to zero.
|
|
// */
|
|
func _findCreateFileMode(tls *libc.TLS, zPath uintptr, flags int32, pMode uintptr, pUid uintptr, pGid uintptr) (r int32) {
|
|
bp := tls.Alloc(528)
|
|
defer tls.Free(528)
|
|
var nDb, rc int32
|
|
var z uintptr
|
|
var _ /* zDb at bp+0 */ [513]uint8
|
|
_, _, _ = nDb, rc, z
|
|
rc = SQLITE_OK /* Return Code */
|
|
**(**Tmode_t)(__ccgo_up(pMode)) = uint32(0)
|
|
**(**Tuid_t)(__ccgo_up(pUid)) = uint32(0)
|
|
**(**Tgid_t)(__ccgo_up(pGid)) = uint32(0)
|
|
if flags&(libc.Int32FromInt32(SQLITE_OPEN_WAL)|libc.Int32FromInt32(SQLITE_OPEN_MAIN_JOURNAL)) != 0 { /* Number of valid bytes in zDb */
|
|
/* zPath is a path to a WAL or journal file. The following block derives
|
|
** the path to the associated database file from zPath. This block handles
|
|
** the following naming conventions:
|
|
**
|
|
** "<path to db>-journal"
|
|
** "<path to db>-wal"
|
|
** "<path to db>-journalNN"
|
|
** "<path to db>-walNN"
|
|
**
|
|
** where NN is a decimal number. The NN naming schemes are
|
|
** used by the test_multiplex.c module.
|
|
**
|
|
** In normal operation, the journal file name will always contain
|
|
** a '-' character. However in 8+3 filename mode, or if a corrupt
|
|
** rollback journal specifies a super-journal with a goofy name, then
|
|
** the '-' might be missing or the '-' might be the first character in
|
|
** the filename. In that case, just return SQLITE_OK with *pMode==0.
|
|
*/
|
|
nDb = _sqlite3Strlen30(tls, zPath) - int32(1)
|
|
for nDb > 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath + uintptr(nDb)))) != int32('.') {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath + uintptr(nDb)))) == int32('-') {
|
|
libc.Xmemcpy(tls, bp, zPath, libc.Uint64FromInt32(nDb))
|
|
(**(**[513]uint8)(__ccgo_up(bp)))[nDb] = uint8('\000')
|
|
rc = _getFileMode(tls, bp, pMode, pUid, pGid)
|
|
break
|
|
}
|
|
nDb = nDb - 1
|
|
}
|
|
} else {
|
|
if flags&int32(SQLITE_OPEN_DELETEONCLOSE) != 0 {
|
|
**(**Tmode_t)(__ccgo_up(pMode)) = uint32(0600)
|
|
} else {
|
|
if flags&int32(SQLITE_OPEN_URI) != 0 {
|
|
/* If this is a main database file and the file was opened using a URI
|
|
** filename, check for the "modeof" parameter. If present, interpret
|
|
** its value as a filename and try to copy the mode, uid and gid from
|
|
** that file. */
|
|
z = Xsqlite3_uri_parameter(tls, zPath, __ccgo_ts+4086)
|
|
if z != 0 {
|
|
rc = _getFileMode(tls, z, pMode, pUid, pGid)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of the xBestIndex method for FTS5 tables. Within the
|
|
// ** WHERE constraint, it searches for the following:
|
|
// **
|
|
// ** 1. A MATCH constraint against the table column.
|
|
// ** 2. A MATCH constraint against the "rank" column.
|
|
// ** 3. A MATCH constraint against some other column.
|
|
// ** 4. An == constraint against the rowid column.
|
|
// ** 5. A < or <= constraint against the rowid column.
|
|
// ** 6. A > or >= constraint against the rowid column.
|
|
// **
|
|
// ** Within the ORDER BY, the following are supported:
|
|
// **
|
|
// ** 5. ORDER BY rank [ASC|DESC]
|
|
// ** 6. ORDER BY rowid [ASC|DESC]
|
|
// **
|
|
// ** Information for the xFilter call is passed via both the idxNum and
|
|
// ** idxStr variables. Specifically, idxNum is a bitmask of the following
|
|
// ** flags used to encode the ORDER BY clause:
|
|
// **
|
|
// ** FTS5_BI_ORDER_RANK
|
|
// ** FTS5_BI_ORDER_ROWID
|
|
// ** FTS5_BI_ORDER_DESC
|
|
// **
|
|
// ** idxStr is used to encode data from the WHERE clause. For each argument
|
|
// ** passed to the xFilter method, the following is appended to idxStr:
|
|
// **
|
|
// ** Match against table column: "m"
|
|
// ** Match against rank column: "r"
|
|
// ** Match against other column: "M<column-number>"
|
|
// ** LIKE against other column: "L<column-number>"
|
|
// ** GLOB against other column: "G<column-number>"
|
|
// ** Equality constraint against the rowid: "="
|
|
// ** A < or <= against the rowid: "<"
|
|
// ** A > or >= against the rowid: ">"
|
|
// **
|
|
// ** This function ensures that there is at most one "r" or "=". And that if
|
|
// ** there exists an "=" then there is no "<" or ">".
|
|
// **
|
|
// ** If an unusable MATCH operator is present in the WHERE clause, then
|
|
// ** SQLITE_CONSTRAINT is returned.
|
|
// **
|
|
// ** Costs are assigned as follows:
|
|
// **
|
|
// ** a) If a MATCH operator is present, the cost depends on the other
|
|
// ** constraints also present. As follows:
|
|
// **
|
|
// ** * No other constraints: cost=50000.0
|
|
// ** * One rowid range constraint: cost=37500.0
|
|
// ** * Both rowid range constraints: cost=30000.0
|
|
// ** * An == rowid constraint: cost=25000.0
|
|
// **
|
|
// ** b) Otherwise, if there is no MATCH:
|
|
// **
|
|
// ** * No other constraints: cost=3000000.0
|
|
// ** * One rowid range constraints: cost=2250000.0
|
|
// ** * Both rowid range constraint: cost=750000.0
|
|
// ** * An == rowid constraint: cost=25.0
|
|
// **
|
|
// ** Costs are not modified by the ORDER BY clause.
|
|
// **
|
|
// ** The ratios used in case (a) are based on informal results obtained from
|
|
// ** the tool/fts5cost.tcl script. The "MATCH and ==" combination has the
|
|
// ** cost set quite high because the query may be a prefix query. Unless
|
|
// ** there is a prefix index, prefix queries with rowid constraints are much
|
|
// ** more expensive than non-prefix queries with rowid constraints.
|
|
// **
|
|
// ** The estimated rows returned is set to the cost/40. For simple queries,
|
|
// ** experimental results show that cost/4 might be about right. But for
|
|
// ** more complex queries that use multiple terms the number of rows might
|
|
// ** be far fewer than this. So we compromise and use cost/40.
|
|
// */
|
|
func _fts5BestIndexMethod(tls *libc.TLS, pVTab uintptr, pInfo uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var bSeenEq, bSeenGt, bSeenLt, bSeenRank, i, iCol, iCons, iIdxStr, iSort, idxFlags, nCol, nSeenMatch, op, v2, v3 int32
|
|
var idxStr, p, p1, pConfig, pTab uintptr
|
|
var nEstRows Ti64
|
|
var v15 float64
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = bSeenEq, bSeenGt, bSeenLt, bSeenRank, i, iCol, iCons, iIdxStr, iSort, idxFlags, idxStr, nCol, nEstRows, nSeenMatch, op, p, p1, pConfig, pTab, v15, v2, v3
|
|
pTab = pVTab
|
|
pConfig = (*TFts5Table)(unsafe.Pointer(pTab)).FpConfig
|
|
nCol = (*TFts5Config)(unsafe.Pointer(pConfig)).FnCol
|
|
idxFlags = 0
|
|
iIdxStr = 0
|
|
iCons = 0
|
|
bSeenEq = 0
|
|
bSeenGt = 0
|
|
bSeenLt = 0
|
|
nSeenMatch = 0
|
|
bSeenRank = 0
|
|
if (*TFts5Config)(unsafe.Pointer(pConfig)).FbLock != 0 {
|
|
(*TFts5Table)(unsafe.Pointer(pTab)).Fbase.FzErrMsg = Xsqlite3_mprintf(tls, __ccgo_ts+39740, 0)
|
|
return int32(SQLITE_ERROR)
|
|
}
|
|
idxStr = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(int64((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FnConstraint)*int64(8)+int64(1)))
|
|
if idxStr == uintptr(0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FidxStr = idxStr
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FneedToFreeIdxStr = int32(1)
|
|
i = 0
|
|
for {
|
|
if !(i < (*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FnConstraint) {
|
|
break
|
|
}
|
|
p = (*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FaConstraint + uintptr(i)*12
|
|
iCol = (*Tsqlite3_index_constraint)(unsafe.Pointer(p)).FiColumn
|
|
if libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fop) == int32(SQLITE_INDEX_CONSTRAINT_MATCH) || libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fop) == int32(SQLITE_INDEX_CONSTRAINT_EQ) && iCol >= nCol {
|
|
/* A MATCH operator or equivalent */
|
|
if libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fusable) == 0 || iCol < 0 {
|
|
/* As there exists an unusable MATCH constraint this is an
|
|
** unusable plan. Return SQLITE_CONSTRAINT. */
|
|
**(**uint8)(__ccgo_up(idxStr + uintptr(iIdxStr))) = uint8(0)
|
|
return int32(SQLITE_CONSTRAINT)
|
|
} else {
|
|
if iCol == nCol+int32(1) {
|
|
if bSeenRank != 0 {
|
|
goto _1
|
|
}
|
|
v2 = iIdxStr
|
|
iIdxStr = iIdxStr + 1
|
|
**(**uint8)(__ccgo_up(idxStr + uintptr(v2))) = uint8('r')
|
|
bSeenRank = int32(1)
|
|
} else {
|
|
nSeenMatch = nSeenMatch + 1
|
|
v2 = iIdxStr
|
|
iIdxStr = iIdxStr + 1
|
|
**(**uint8)(__ccgo_up(idxStr + uintptr(v2))) = uint8('M')
|
|
Xsqlite3_snprintf(tls, int32(6), idxStr+uintptr(iIdxStr), __ccgo_ts+5317, libc.VaList(bp+8, iCol))
|
|
iIdxStr = iIdxStr + libc.Int32FromUint64(libc.Xstrlen(tls, idxStr+uintptr(iIdxStr)))
|
|
}
|
|
iCons = iCons + 1
|
|
v2 = iCons
|
|
(**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FaConstraintUsage + uintptr(i)*8))).FargvIndex = v2
|
|
(**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FaConstraintUsage + uintptr(i)*8))).Fomit = uint8(1)
|
|
}
|
|
} else {
|
|
if (*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fusable != 0 {
|
|
if iCol >= 0 && iCol < nCol && _fts5UsePatternMatch(tls, pConfig, p) != 0 {
|
|
v2 = iIdxStr
|
|
iIdxStr = iIdxStr + 1
|
|
if libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fop) == int32(FTS5_PATTERN_LIKE) {
|
|
v3 = int32('L')
|
|
} else {
|
|
v3 = int32('G')
|
|
}
|
|
**(**uint8)(__ccgo_up(idxStr + uintptr(v2))) = libc.Uint8FromInt32(v3)
|
|
Xsqlite3_snprintf(tls, int32(6), idxStr+uintptr(iIdxStr), __ccgo_ts+5317, libc.VaList(bp+8, iCol))
|
|
idxStr = idxStr + uintptr(libc.Xstrlen(tls, idxStr+uintptr(iIdxStr)))
|
|
iCons = iCons + 1
|
|
v2 = iCons
|
|
(**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FaConstraintUsage + uintptr(i)*8))).FargvIndex = v2
|
|
nSeenMatch = nSeenMatch + 1
|
|
} else {
|
|
if bSeenEq == 0 && libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fop) == int32(SQLITE_INDEX_CONSTRAINT_EQ) && iCol < 0 {
|
|
v2 = iIdxStr
|
|
iIdxStr = iIdxStr + 1
|
|
**(**uint8)(__ccgo_up(idxStr + uintptr(v2))) = uint8('=')
|
|
bSeenEq = int32(1)
|
|
iCons = iCons + 1
|
|
v2 = iCons
|
|
(**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FaConstraintUsage + uintptr(i)*8))).FargvIndex = v2
|
|
(**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FaConstraintUsage + uintptr(i)*8))).Fomit = uint8(1)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if bSeenEq == 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FnConstraint) {
|
|
break
|
|
}
|
|
p1 = (*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FaConstraint + uintptr(i)*12
|
|
if (*Tsqlite3_index_constraint)(unsafe.Pointer(p1)).FiColumn < 0 && (*Tsqlite3_index_constraint)(unsafe.Pointer(p1)).Fusable != 0 {
|
|
op = libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p1)).Fop)
|
|
if op == int32(SQLITE_INDEX_CONSTRAINT_LT) || op == int32(SQLITE_INDEX_CONSTRAINT_LE) {
|
|
if bSeenLt != 0 {
|
|
goto _10
|
|
}
|
|
v2 = iIdxStr
|
|
iIdxStr = iIdxStr + 1
|
|
**(**uint8)(__ccgo_up(idxStr + uintptr(v2))) = uint8('<')
|
|
iCons = iCons + 1
|
|
v2 = iCons
|
|
(**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FaConstraintUsage + uintptr(i)*8))).FargvIndex = v2
|
|
bSeenLt = int32(1)
|
|
} else {
|
|
if op == int32(SQLITE_INDEX_CONSTRAINT_GT) || op == int32(SQLITE_INDEX_CONSTRAINT_GE) {
|
|
if bSeenGt != 0 {
|
|
goto _10
|
|
}
|
|
v2 = iIdxStr
|
|
iIdxStr = iIdxStr + 1
|
|
**(**uint8)(__ccgo_up(idxStr + uintptr(v2))) = uint8('>')
|
|
iCons = iCons + 1
|
|
v2 = iCons
|
|
(**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FaConstraintUsage + uintptr(i)*8))).FargvIndex = v2
|
|
bSeenGt = int32(1)
|
|
}
|
|
}
|
|
}
|
|
goto _10
|
|
_10:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
**(**uint8)(__ccgo_up(idxStr + uintptr(iIdxStr))) = uint8('\000')
|
|
/* Set idxFlags flags for the ORDER BY clause
|
|
**
|
|
** Note that tokendata=1 tables cannot currently handle "ORDER BY rowid DESC".
|
|
*/
|
|
if (*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FnOrderBy == int32(1) {
|
|
iSort = (**(**Tsqlite3_index_orderby)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FaOrderBy))).FiColumn
|
|
if iSort == (*TFts5Config)(unsafe.Pointer(pConfig)).FnCol+int32(1) && nSeenMatch > 0 {
|
|
idxFlags = idxFlags | int32(FTS5_BI_ORDER_RANK)
|
|
} else {
|
|
if iSort == -int32(1) && (!((**(**Tsqlite3_index_orderby)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FaOrderBy))).Fdesc != 0) || !((*TFts5Config)(unsafe.Pointer(pConfig)).FbTokendata != 0)) {
|
|
idxFlags = idxFlags | int32(FTS5_BI_ORDER_ROWID)
|
|
}
|
|
}
|
|
if idxFlags&(libc.Int32FromInt32(FTS5_BI_ORDER_RANK)|libc.Int32FromInt32(FTS5_BI_ORDER_ROWID)) != 0 {
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).ForderByConsumed = int32(1)
|
|
if (**(**Tsqlite3_index_orderby)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FaOrderBy))).Fdesc != 0 {
|
|
idxFlags = idxFlags | int32(FTS5_BI_ORDER_DESC)
|
|
}
|
|
}
|
|
}
|
|
/* Calculate the estimated cost based on the flags set in idxFlags. */
|
|
if bSeenEq != 0 {
|
|
if nSeenMatch != 0 {
|
|
v15 = float64(25000)
|
|
} else {
|
|
v15 = float64(25)
|
|
}
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FestimatedCost = v15
|
|
_fts5SetEstimatedRows(tls, pInfo, int64(1))
|
|
_fts5SetUniqueFlag(tls, pInfo)
|
|
} else {
|
|
if nSeenMatch != 0 {
|
|
if bSeenLt != 0 && bSeenGt != 0 {
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FestimatedCost = float64(50000)
|
|
} else {
|
|
if bSeenLt != 0 || bSeenGt != 0 {
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FestimatedCost = float64(37500)
|
|
} else {
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FestimatedCost = float64(50000)
|
|
}
|
|
}
|
|
nEstRows = int64((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FestimatedCost / libc.Float64FromFloat64(40))
|
|
i = int32(1)
|
|
for {
|
|
if !(i < nSeenMatch) {
|
|
break
|
|
}
|
|
**(**float64)(__ccgo_up(pInfo + 64)) *= float64(2.5)
|
|
nEstRows = nEstRows / int64(2)
|
|
goto _16
|
|
_16:
|
|
;
|
|
i = i + 1
|
|
}
|
|
} else {
|
|
if bSeenLt != 0 && bSeenGt != 0 {
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FestimatedCost = float64(750000)
|
|
} else {
|
|
if bSeenLt != 0 || bSeenGt != 0 {
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FestimatedCost = float64(2.25e+06)
|
|
} else {
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FestimatedCost = float64(3e+06)
|
|
}
|
|
}
|
|
nEstRows = int64((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FestimatedCost / libc.Float64FromFloat64(4))
|
|
}
|
|
_fts5SetEstimatedRows(tls, pInfo, nEstRows)
|
|
}
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FidxNum = idxFlags
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Parse a "special" CREATE VIRTUAL TABLE directive and update
|
|
// ** configuration object pConfig as appropriate.
|
|
// **
|
|
// ** If successful, object pConfig is updated and SQLITE_OK returned. If
|
|
// ** an error occurs, an SQLite error code is returned and an error message
|
|
// ** may be left in *pzErr. It is the responsibility of the caller to
|
|
// ** eventually free any such error message using sqlite3_free().
|
|
// */
|
|
func _fts5ConfigParseSpecial(tls *libc.TLS, pConfig uintptr, zCmd uintptr, zArg uintptr, pzErr uintptr) (r int32) {
|
|
bp := tls.Alloc(96)
|
|
defer tls.Free(96)
|
|
var azArg, p, p1, p2, pSpace uintptr
|
|
var bFirst, nByte, nCmd, nPre, v2 int32
|
|
var nArg Tsqlite3_int64
|
|
var _ /* aDetail at bp+8 */ [4]TFts5Enum
|
|
var _ /* rc at bp+0 */ int32
|
|
_, _, _, _, _, _, _, _, _, _, _ = azArg, bFirst, nArg, nByte, nCmd, nPre, p, p1, p2, pSpace, v2
|
|
**(**int32)(__ccgo_up(bp)) = SQLITE_OK
|
|
nCmd = libc.Int32FromUint64(libc.Xstrlen(tls, zCmd))
|
|
if Xsqlite3_strnicmp(tls, __ccgo_ts+37431, zCmd, nCmd) == 0 {
|
|
nByte = libc.Int32FromUint64(libc.Uint64FromInt64(4) * libc.Uint64FromInt32(FTS5_MAX_PREFIX_INDEXES))
|
|
bFirst = int32(1)
|
|
if (*TFts5Config)(unsafe.Pointer(pConfig)).FaPrefix == uintptr(0) {
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).FaPrefix = _sqlite3Fts5MallocZero(tls, bp, int64(nByte))
|
|
if **(**int32)(__ccgo_up(bp)) != 0 {
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
}
|
|
p = zArg
|
|
for int32(1) != 0 {
|
|
nPre = 0
|
|
for libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) == int32(' ') {
|
|
p = p + 1
|
|
}
|
|
if bFirst == 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) == int32(',') {
|
|
p = p + 1
|
|
for libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) == int32(' ') {
|
|
p = p + 1
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) == int32('\000') {
|
|
break
|
|
}
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) < int32('0') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) > int32('9') {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+37438, 0)
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
break
|
|
}
|
|
if (*TFts5Config)(unsafe.Pointer(pConfig)).FnPrefix == int32(FTS5_MAX_PREFIX_INDEXES) {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+37469, libc.VaList(bp+80, int32(FTS5_MAX_PREFIX_INDEXES)))
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
break
|
|
}
|
|
for libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) >= int32('0') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) <= int32('9') && nPre < int32(1000) {
|
|
nPre = nPre*int32(10) + (libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) - int32('0'))
|
|
p = p + 1
|
|
}
|
|
if nPre <= 0 || nPre >= int32(1000) {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+37502, 0)
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
break
|
|
}
|
|
**(**int32)(__ccgo_up((*TFts5Config)(unsafe.Pointer(pConfig)).FaPrefix + uintptr((*TFts5Config)(unsafe.Pointer(pConfig)).FnPrefix)*4)) = nPre
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).FnPrefix = (*TFts5Config)(unsafe.Pointer(pConfig)).FnPrefix + 1
|
|
bFirst = 0
|
|
}
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
if Xsqlite3_strnicmp(tls, __ccgo_ts+37539, zCmd, nCmd) == 0 {
|
|
p1 = zArg
|
|
nArg = libc.Int64FromUint64(libc.Xstrlen(tls, zArg) + uint64(1))
|
|
azArg = _sqlite3Fts5MallocZero(tls, bp, libc.Int64FromUint64(uint64(libc.Uint64FromInt64(8)+libc.Uint64FromInt32(2))*libc.Uint64FromInt64(nArg)))
|
|
if azArg != 0 {
|
|
pSpace = azArg + uintptr(nArg)*8
|
|
if (*TFts5Config)(unsafe.Pointer(pConfig)).Ft.FazArg != 0 {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+37548, 0)
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
} else {
|
|
nArg = 0
|
|
for {
|
|
if !(p1 != 0 && **(**uint8)(__ccgo_up(p1)) != 0) {
|
|
break
|
|
}
|
|
p2 = _fts5ConfigSkipWhitespace(tls, p1)
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(p2))) == int32('\'') {
|
|
p1 = _fts5ConfigSkipLiteral(tls, p2)
|
|
} else {
|
|
p1 = _fts5ConfigSkipBareword(tls, p2)
|
|
}
|
|
if p1 != 0 {
|
|
libc.Xmemcpy(tls, pSpace, p2, libc.Uint64FromInt64(int64(p1)-int64(p2)))
|
|
**(**uintptr)(__ccgo_up(azArg + uintptr(nArg)*8)) = pSpace
|
|
_sqlite3Fts5Dequote(tls, pSpace)
|
|
pSpace = pSpace + uintptr(int64(p1)-int64(p2)+int64(1))
|
|
p1 = _fts5ConfigSkipWhitespace(tls, p1)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
nArg = nArg + 1
|
|
}
|
|
if p1 == uintptr(0) {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+37581, 0)
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
} else {
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).Ft.FazArg = azArg
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).Ft.FnArg = int32(nArg)
|
|
azArg = uintptr(0)
|
|
}
|
|
}
|
|
}
|
|
Xsqlite3_free(tls, azArg)
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
if Xsqlite3_strnicmp(tls, __ccgo_ts+37615, zCmd, nCmd) == 0 {
|
|
if (*TFts5Config)(unsafe.Pointer(pConfig)).FeContent != FTS5_CONTENT_NORMAL {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+37623, 0)
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
} else {
|
|
if **(**uint8)(__ccgo_up(zArg)) != 0 {
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).FeContent = int32(FTS5_CONTENT_EXTERNAL)
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).FzContent = _sqlite3Fts5Mprintf(tls, bp, __ccgo_ts+37655, libc.VaList(bp+80, (*TFts5Config)(unsafe.Pointer(pConfig)).FzDb, zArg))
|
|
} else {
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).FeContent = int32(FTS5_CONTENT_NONE)
|
|
}
|
|
}
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
if Xsqlite3_strnicmp(tls, __ccgo_ts+37661, zCmd, nCmd) == 0 {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('0') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('1') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg + 1))) != int32('\000') {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+37680, 0)
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
} else {
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).FbContentlessDelete = libc.BoolInt32(libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) == int32('1'))
|
|
}
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
if Xsqlite3_strnicmp(tls, __ccgo_ts+37723, zCmd, nCmd) == 0 {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('0') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('1') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg + 1))) != int32('\000') {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+37680, 0)
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
} else {
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).FbContentlessUnindexed = libc.BoolInt32(libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) == int32('1'))
|
|
}
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
if Xsqlite3_strnicmp(tls, __ccgo_ts+37745, zCmd, nCmd) == 0 {
|
|
if (*TFts5Config)(unsafe.Pointer(pConfig)).FzContentRowid != 0 {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+37759, 0)
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
} else {
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).FzContentRowid = _sqlite3Fts5Strndup(tls, bp, zArg, -int32(1))
|
|
}
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
if Xsqlite3_strnicmp(tls, __ccgo_ts+37797, zCmd, nCmd) == 0 {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('0') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('1') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg + 1))) != int32('\000') {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+37808, 0)
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
} else {
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).FbColumnsize = libc.BoolInt32(libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) == int32('1'))
|
|
}
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
if Xsqlite3_strnicmp(tls, __ccgo_ts+37843, zCmd, nCmd) == 0 {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('0') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('1') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg + 1))) != int32('\000') {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+37850, 0)
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
} else {
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).FbLocale = libc.BoolInt32(libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) == int32('1'))
|
|
}
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
if Xsqlite3_strnicmp(tls, __ccgo_ts+5694, zCmd, nCmd) == 0 {
|
|
**(**[4]TFts5Enum)(__ccgo_up(bp + 8)) = [4]TFts5Enum{
|
|
0: {
|
|
FzName: __ccgo_ts + 8536,
|
|
FeVal: int32(FTS5_DETAIL_NONE),
|
|
},
|
|
1: {
|
|
FzName: __ccgo_ts + 19044,
|
|
},
|
|
2: {
|
|
FzName: __ccgo_ts + 37881,
|
|
FeVal: int32(FTS5_DETAIL_COLUMNS),
|
|
},
|
|
3: {},
|
|
}
|
|
v2 = _fts5ConfigSetEnum(tls, bp+8, zArg, pConfig+116)
|
|
**(**int32)(__ccgo_up(bp)) = v2
|
|
if v2 != 0 {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+37889, 0)
|
|
}
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
if Xsqlite3_strnicmp(tls, __ccgo_ts+37920, zCmd, nCmd) == 0 {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('0') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('1') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg + 1))) != int32('\000') {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+37930, 0)
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
} else {
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).FbTokendata = libc.BoolInt32(libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) == int32('1'))
|
|
}
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+37964, libc.VaList(bp+80, nCmd, zCmd))
|
|
return int32(SQLITE_ERROR)
|
|
}
|
|
|
|
func _fts5ConfigSkipLiteral(tls *libc.TLS, pIn uintptr) (r uintptr) {
|
|
var p uintptr
|
|
_ = p
|
|
p = pIn
|
|
switch libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) {
|
|
case int32('n'):
|
|
fallthrough
|
|
case int32('N'):
|
|
if Xsqlite3_strnicmp(tls, __ccgo_ts+1690, p, int32(4)) == 0 {
|
|
p = p + 4
|
|
} else {
|
|
p = uintptr(0)
|
|
}
|
|
case int32('x'):
|
|
fallthrough
|
|
case int32('X'):
|
|
p = p + 1
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) == int32('\'') {
|
|
p = p + 1
|
|
for libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) >= int32('a') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) <= int32('f') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) >= int32('A') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) <= int32('F') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) >= int32('0') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) <= int32('9') {
|
|
p = p + 1
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) == int32('\'') && 0 == (int64(p)-int64(pIn))%int64(2) {
|
|
p = p + 1
|
|
} else {
|
|
p = uintptr(0)
|
|
}
|
|
} else {
|
|
p = uintptr(0)
|
|
}
|
|
case int32('\''):
|
|
p = p + 1
|
|
for p != 0 {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) == int32('\'') {
|
|
p = p + 1
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) != int32('\'') {
|
|
break
|
|
}
|
|
}
|
|
p = p + 1
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) == 0 {
|
|
p = uintptr(0)
|
|
}
|
|
}
|
|
default:
|
|
/* maybe a number */
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) == int32('+') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) == int32('-') {
|
|
p = p + 1
|
|
}
|
|
for _fts5_isdigit(tls, **(**uint8)(__ccgo_up(p))) != 0 {
|
|
p = p + 1
|
|
}
|
|
/* At this point, if the literal was an integer, the parse is
|
|
** finished. Or, if it is a floating point value, it may continue
|
|
** with either a decimal point or an 'E' character. */
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) == int32('.') && _fts5_isdigit(tls, **(**uint8)(__ccgo_up(p + 1))) != 0 {
|
|
p = p + uintptr(2)
|
|
for _fts5_isdigit(tls, **(**uint8)(__ccgo_up(p))) != 0 {
|
|
p = p + 1
|
|
}
|
|
}
|
|
if p == pIn {
|
|
p = uintptr(0)
|
|
}
|
|
break
|
|
}
|
|
return p
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Read the first token from the nul-terminated string at *pz.
|
|
// */
|
|
func _fts5ExprGetToken(tls *libc.TLS, pParse uintptr, pz uintptr, pToken uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var tok int32
|
|
var z, z2, z21 uintptr
|
|
_, _, _, _ = tok, z, z2, z21
|
|
z = **(**uintptr)(__ccgo_up(pz))
|
|
/* Skip past any whitespace */
|
|
for _fts5ExprIsspace(tls, **(**uint8)(__ccgo_up(z))) != 0 {
|
|
z = z + 1
|
|
}
|
|
(*TFts5Token)(unsafe.Pointer(pToken)).Fp = z
|
|
(*TFts5Token)(unsafe.Pointer(pToken)).Fn = int32(1)
|
|
switch libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) {
|
|
case int32('('):
|
|
tok = int32(FTS5_LP)
|
|
case int32(')'):
|
|
tok = int32(FTS5_RP)
|
|
case int32('{'):
|
|
tok = int32(FTS5_LCP)
|
|
case int32('}'):
|
|
tok = int32(FTS5_RCP)
|
|
case int32(':'):
|
|
tok = int32(FTS5_COLON)
|
|
case int32(','):
|
|
tok = int32(FTS5_COMMA)
|
|
case int32('+'):
|
|
tok = int32(FTS5_PLUS)
|
|
case int32('*'):
|
|
tok = int32(FTS5_STAR)
|
|
case int32('-'):
|
|
tok = int32(FTS5_MINUS)
|
|
case int32('^'):
|
|
tok = int32(FTS5_CARET)
|
|
case int32('\000'):
|
|
tok = FTS5_EOF
|
|
case int32('"'):
|
|
tok = int32(FTS5_STRING)
|
|
z2 = z + 1
|
|
for {
|
|
if !(int32(1) != 0) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z2))) == int32('"') {
|
|
z2 = z2 + 1
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z2))) != int32('"') {
|
|
break
|
|
}
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z2))) == int32('\000') {
|
|
_sqlite3Fts5ParseError(tls, pParse, __ccgo_ts+38571, 0)
|
|
return FTS5_EOF
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
z2 = z2 + 1
|
|
}
|
|
(*TFts5Token)(unsafe.Pointer(pToken)).Fn = int32(int64(z2) - int64(z))
|
|
default:
|
|
if _sqlite3Fts5IsBareword(tls, **(**uint8)(__ccgo_up(z))) == 0 {
|
|
_sqlite3Fts5ParseError(tls, pParse, __ccgo_ts+38591, libc.VaList(bp+8, z))
|
|
return FTS5_EOF
|
|
}
|
|
tok = int32(FTS5_STRING)
|
|
z21 = z + 1
|
|
for {
|
|
if !(_sqlite3Fts5IsBareword(tls, **(**uint8)(__ccgo_up(z21))) != 0) {
|
|
break
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
z21 = z21 + 1
|
|
}
|
|
(*TFts5Token)(unsafe.Pointer(pToken)).Fn = int32(int64(z21) - int64(z))
|
|
if (*TFts5Token)(unsafe.Pointer(pToken)).Fn == int32(2) && libc.Xmemcmp(tls, (*TFts5Token)(unsafe.Pointer(pToken)).Fp, __ccgo_ts+38622, uint64(2)) == 0 {
|
|
tok = int32(FTS5_OR)
|
|
}
|
|
if (*TFts5Token)(unsafe.Pointer(pToken)).Fn == int32(3) && libc.Xmemcmp(tls, (*TFts5Token)(unsafe.Pointer(pToken)).Fp, __ccgo_ts+38625, uint64(3)) == 0 {
|
|
tok = int32(FTS5_NOT)
|
|
}
|
|
if (*TFts5Token)(unsafe.Pointer(pToken)).Fn == int32(3) && libc.Xmemcmp(tls, (*TFts5Token)(unsafe.Pointer(pToken)).Fp, __ccgo_ts+32432, uint64(3)) == 0 {
|
|
tok = int32(FTS5_AND)
|
|
}
|
|
break
|
|
}
|
|
**(**uintptr)(__ccgo_up(pz)) = (*TFts5Token)(unsafe.Pointer(pToken)).Fp + uintptr((*TFts5Token)(unsafe.Pointer(pToken)).Fn)
|
|
return tok
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This is the xFilter interface for the virtual table. See
|
|
// ** the virtual table xFilter method documentation for additional
|
|
// ** information.
|
|
// **
|
|
// ** There are three possible query strategies:
|
|
// **
|
|
// ** 1. Full-text search using a MATCH operator.
|
|
// ** 2. A by-rowid lookup.
|
|
// ** 3. A full-table scan.
|
|
// */
|
|
func _fts5FilterMethod(tls *libc.TLS, pCursor uintptr, idxNum int32, idxStr uintptr, nVal int32, apVal uintptr) (r int32) {
|
|
bp := tls.Alloc(48)
|
|
defer tls.Free(48)
|
|
var bDesc, bGlob, bInternal, bOrderByRank, bPrefixInsttoken, i, iCol, iIdxStr, rc, v2, v3 int32
|
|
var pConfig, pCsr, pRank, pRowidEq, pRowidGe, pRowidLe, pTab, pzErr, pzErrmsg, zText1, v6 uintptr
|
|
var _ /* bFreeAndReset at bp+16 */ int32
|
|
var _ /* pExpr at bp+0 */ uintptr
|
|
var _ /* zText at bp+8 */ uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = bDesc, bGlob, bInternal, bOrderByRank, bPrefixInsttoken, i, iCol, iIdxStr, pConfig, pCsr, pRank, pRowidEq, pRowidGe, pRowidLe, pTab, pzErr, pzErrmsg, rc, zText1, v2, v3, v6
|
|
pTab = (*Tsqlite3_vtab_cursor)(unsafe.Pointer(pCursor)).FpVtab
|
|
pConfig = (*TFts5FullTable)(unsafe.Pointer(pTab)).Fp.FpConfig
|
|
pCsr = pCursor
|
|
rc = SQLITE_OK /* True if ORDER BY rank */
|
|
pRank = uintptr(0) /* rank MATCH ? expression (or NULL) */
|
|
pRowidEq = uintptr(0) /* rowid = ? expression (or NULL) */
|
|
pRowidLe = uintptr(0) /* rowid <= ? expression (or NULL) */
|
|
pRowidGe = uintptr(0) /* Column on LHS of MATCH operator */
|
|
pzErrmsg = (*TFts5Config)(unsafe.Pointer(pConfig)).FpzErrmsg
|
|
bPrefixInsttoken = (*TFts5Config)(unsafe.Pointer(pConfig)).FbPrefixInsttoken
|
|
iIdxStr = 0
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
if (*TFts5Cursor)(unsafe.Pointer(pCsr)).FePlan != 0 {
|
|
_fts5FreeCursorComponents(tls, pCsr)
|
|
libc.Xmemset(tls, pCsr+32, 0, uint64(184)-libc.Uint64FromInt64(int64(pCsr+32)-int64(pCsr)))
|
|
}
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).FpzErrmsg = pTab + 16
|
|
/* Decode the arguments passed through to this function. */
|
|
i = 0
|
|
for {
|
|
if !(i < nVal) {
|
|
break
|
|
}
|
|
v2 = iIdxStr
|
|
iIdxStr = iIdxStr + 1
|
|
switch libc.Int32FromUint8(**(**uint8)(__ccgo_up(idxStr + uintptr(v2)))) {
|
|
case int32('r'):
|
|
pRank = **(**uintptr)(__ccgo_up(apVal + uintptr(i)*8))
|
|
case int32('M'):
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = uintptr(0)
|
|
**(**int32)(__ccgo_up(bp + 16)) = 0
|
|
bInternal = 0
|
|
rc = _fts5ExtractExprText(tls, pConfig, **(**uintptr)(__ccgo_up(apVal + uintptr(i)*8)), bp+8, bp+16)
|
|
if rc != SQLITE_OK {
|
|
goto filter_out
|
|
}
|
|
if **(**uintptr)(__ccgo_up(bp + 8)) == uintptr(0) {
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = __ccgo_ts + 1704
|
|
}
|
|
if Xsqlite3_value_subtype(tls, **(**uintptr)(__ccgo_up(apVal + uintptr(i)*8))) == uint32(FTS5_INSTTOKEN_SUBTYPE) {
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).FbPrefixInsttoken = int32(1)
|
|
}
|
|
iCol = 0
|
|
for cond := true; cond; cond = libc.Int32FromUint8(**(**uint8)(__ccgo_up(idxStr + uintptr(iIdxStr)))) >= int32('0') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(idxStr + uintptr(iIdxStr)))) <= int32('9') {
|
|
iCol = iCol*int32(10) + (libc.Int32FromUint8(**(**uint8)(__ccgo_up(idxStr + uintptr(iIdxStr)))) - int32('0'))
|
|
iIdxStr = iIdxStr + 1
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp + 8))))) == int32('*') {
|
|
/* The user has issued a query of the form "MATCH '*...'". This
|
|
** indicates that the MATCH expression is not a full text query,
|
|
** but a request for an internal parameter. */
|
|
rc = _fts5SpecialMatch(tls, pTab, pCsr, **(**uintptr)(__ccgo_up(bp + 8))+1)
|
|
bInternal = int32(1)
|
|
} else {
|
|
pzErr = pTab + 16
|
|
rc = _sqlite3Fts5ExprNew(tls, pConfig, 0, iCol, **(**uintptr)(__ccgo_up(bp + 8)), bp, pzErr)
|
|
if rc == SQLITE_OK {
|
|
rc = _sqlite3Fts5ExprAnd(tls, pCsr+64, **(**uintptr)(__ccgo_up(bp)))
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
}
|
|
}
|
|
if **(**int32)(__ccgo_up(bp + 16)) != 0 {
|
|
Xsqlite3_free(tls, **(**uintptr)(__ccgo_up(bp + 8)))
|
|
_sqlite3Fts5ClearLocale(tls, pConfig)
|
|
}
|
|
if bInternal != 0 || rc != SQLITE_OK {
|
|
goto filter_out
|
|
}
|
|
case int32('L'):
|
|
fallthrough
|
|
case int32('G'):
|
|
bGlob = libc.BoolInt32(libc.Int32FromUint8(**(**uint8)(__ccgo_up(idxStr + uintptr(iIdxStr-int32(1))))) == int32('G'))
|
|
zText1 = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(apVal + uintptr(i)*8)))
|
|
iCol = 0
|
|
for cond := true; cond; cond = libc.Int32FromUint8(**(**uint8)(__ccgo_up(idxStr + uintptr(iIdxStr)))) >= int32('0') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(idxStr + uintptr(iIdxStr)))) <= int32('9') {
|
|
iCol = iCol*int32(10) + (libc.Int32FromUint8(**(**uint8)(__ccgo_up(idxStr + uintptr(iIdxStr)))) - int32('0'))
|
|
iIdxStr = iIdxStr + 1
|
|
}
|
|
if zText1 != 0 {
|
|
rc = _sqlite3Fts5ExprPattern(tls, pConfig, bGlob, iCol, zText1, bp)
|
|
}
|
|
if rc == SQLITE_OK {
|
|
rc = _sqlite3Fts5ExprAnd(tls, pCsr+64, **(**uintptr)(__ccgo_up(bp)))
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
}
|
|
if rc != SQLITE_OK {
|
|
goto filter_out
|
|
}
|
|
case int32('='):
|
|
pRowidEq = **(**uintptr)(__ccgo_up(apVal + uintptr(i)*8))
|
|
case int32('<'):
|
|
pRowidLe = **(**uintptr)(__ccgo_up(apVal + uintptr(i)*8))
|
|
default:
|
|
pRowidGe = **(**uintptr)(__ccgo_up(apVal + uintptr(i)*8))
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if idxNum&int32(FTS5_BI_ORDER_RANK) != 0 {
|
|
v2 = int32(1)
|
|
} else {
|
|
v2 = 0
|
|
}
|
|
bOrderByRank = v2
|
|
if idxNum&int32(FTS5_BI_ORDER_DESC) != 0 {
|
|
v3 = int32(1)
|
|
} else {
|
|
v3 = 0
|
|
}
|
|
v2 = v3
|
|
bDesc = v2
|
|
(*TFts5Cursor)(unsafe.Pointer(pCsr)).FbDesc = v2
|
|
/* Set the cursor upper and lower rowid limits. Only some strategies
|
|
** actually use them. This is ok, as the xBestIndex() method leaves the
|
|
** sqlite3_index_constraint.omit flag clear for range constraints
|
|
** on the rowid field. */
|
|
if pRowidEq != 0 {
|
|
v6 = pRowidEq
|
|
pRowidGe = v6
|
|
pRowidLe = v6
|
|
}
|
|
if bDesc != 0 {
|
|
(*TFts5Cursor)(unsafe.Pointer(pCsr)).FiFirstRowid = _fts5GetRowidLimit(tls, pRowidLe, libc.Int64FromUint32(0xffffffff)|libc.Int64FromInt32(0x7fffffff)<<libc.Int32FromInt32(32))
|
|
(*TFts5Cursor)(unsafe.Pointer(pCsr)).FiLastRowid = _fts5GetRowidLimit(tls, pRowidGe, int64(-libc.Int32FromInt32(1))-(libc.Int64FromUint32(0xffffffff)|libc.Int64FromInt32(0x7fffffff)<<libc.Int32FromInt32(32)))
|
|
} else {
|
|
(*TFts5Cursor)(unsafe.Pointer(pCsr)).FiLastRowid = _fts5GetRowidLimit(tls, pRowidLe, libc.Int64FromUint32(0xffffffff)|libc.Int64FromInt32(0x7fffffff)<<libc.Int32FromInt32(32))
|
|
(*TFts5Cursor)(unsafe.Pointer(pCsr)).FiFirstRowid = _fts5GetRowidLimit(tls, pRowidGe, int64(-libc.Int32FromInt32(1))-(libc.Int64FromUint32(0xffffffff)|libc.Int64FromInt32(0x7fffffff)<<libc.Int32FromInt32(32)))
|
|
}
|
|
rc = _sqlite3Fts5IndexLoadConfig(tls, (*TFts5FullTable)(unsafe.Pointer(pTab)).Fp.FpIndex)
|
|
if rc != SQLITE_OK {
|
|
goto filter_out
|
|
}
|
|
if (*TFts5FullTable)(unsafe.Pointer(pTab)).FpSortCsr != 0 {
|
|
/* If pSortCsr is non-NULL, then this call is being made as part of
|
|
** processing for a "... MATCH <expr> ORDER BY rank" query (ePlan is
|
|
** set to FTS5_PLAN_SORTED_MATCH). pSortCsr is the cursor that will
|
|
** return results to the user for this query. The current cursor
|
|
** (pCursor) is used to execute the query issued by function
|
|
** fts5CursorFirstSorted() above. */
|
|
if (*TFts5Cursor)(unsafe.Pointer((*TFts5FullTable)(unsafe.Pointer(pTab)).FpSortCsr)).FbDesc != 0 {
|
|
(*TFts5Cursor)(unsafe.Pointer(pCsr)).FiLastRowid = (*TFts5Cursor)(unsafe.Pointer((*TFts5FullTable)(unsafe.Pointer(pTab)).FpSortCsr)).FiFirstRowid
|
|
(*TFts5Cursor)(unsafe.Pointer(pCsr)).FiFirstRowid = (*TFts5Cursor)(unsafe.Pointer((*TFts5FullTable)(unsafe.Pointer(pTab)).FpSortCsr)).FiLastRowid
|
|
} else {
|
|
(*TFts5Cursor)(unsafe.Pointer(pCsr)).FiLastRowid = (*TFts5Cursor)(unsafe.Pointer((*TFts5FullTable)(unsafe.Pointer(pTab)).FpSortCsr)).FiLastRowid
|
|
(*TFts5Cursor)(unsafe.Pointer(pCsr)).FiFirstRowid = (*TFts5Cursor)(unsafe.Pointer((*TFts5FullTable)(unsafe.Pointer(pTab)).FpSortCsr)).FiFirstRowid
|
|
}
|
|
(*TFts5Cursor)(unsafe.Pointer(pCsr)).FePlan = int32(FTS5_PLAN_SOURCE)
|
|
(*TFts5Cursor)(unsafe.Pointer(pCsr)).FpExpr = (*TFts5Cursor)(unsafe.Pointer((*TFts5FullTable)(unsafe.Pointer(pTab)).FpSortCsr)).FpExpr
|
|
rc = _fts5CursorFirst(tls, pTab, pCsr, bDesc)
|
|
} else {
|
|
if (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpExpr != 0 {
|
|
rc = _fts5CursorParseRank(tls, pConfig, pCsr, pRank)
|
|
if rc == SQLITE_OK {
|
|
if bOrderByRank != 0 {
|
|
(*TFts5Cursor)(unsafe.Pointer(pCsr)).FePlan = int32(FTS5_PLAN_SORTED_MATCH)
|
|
rc = _fts5CursorFirstSorted(tls, pTab, pCsr, bDesc)
|
|
} else {
|
|
(*TFts5Cursor)(unsafe.Pointer(pCsr)).FePlan = int32(FTS5_PLAN_MATCH)
|
|
rc = _fts5CursorFirst(tls, pTab, pCsr, bDesc)
|
|
}
|
|
}
|
|
} else {
|
|
if (*TFts5Config)(unsafe.Pointer(pConfig)).FzContent == uintptr(0) {
|
|
_fts5SetVtabError(tls, pTab, __ccgo_ts+39941, libc.VaList(bp+32, (*TFts5Config)(unsafe.Pointer(pConfig)).FzName))
|
|
rc = int32(SQLITE_ERROR)
|
|
} else {
|
|
/* This is either a full-table scan (ePlan==FTS5_PLAN_SCAN) or a lookup
|
|
** by rowid (ePlan==FTS5_PLAN_ROWID). */
|
|
if pRowidEq != 0 {
|
|
v2 = int32(FTS5_PLAN_ROWID)
|
|
} else {
|
|
v2 = int32(FTS5_PLAN_SCAN)
|
|
}
|
|
(*TFts5Cursor)(unsafe.Pointer(pCsr)).FePlan = v2
|
|
rc = _sqlite3Fts5StorageStmt(tls, (*TFts5FullTable)(unsafe.Pointer(pTab)).FpStorage, _fts5StmtType(tls, pCsr), pCsr+56, pTab+16)
|
|
if rc == SQLITE_OK {
|
|
if pRowidEq != uintptr(0) {
|
|
Xsqlite3_bind_value(tls, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpStmt, int32(1), pRowidEq)
|
|
} else {
|
|
Xsqlite3_bind_int64(tls, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpStmt, int32(1), (*TFts5Cursor)(unsafe.Pointer(pCsr)).FiFirstRowid)
|
|
Xsqlite3_bind_int64(tls, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpStmt, int32(2), (*TFts5Cursor)(unsafe.Pointer(pCsr)).FiLastRowid)
|
|
}
|
|
rc = _fts5NextMethod(tls, pCursor)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
goto filter_out
|
|
filter_out:
|
|
;
|
|
_sqlite3Fts5ExprFree(tls, **(**uintptr)(__ccgo_up(bp)))
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).FpzErrmsg = pzErrmsg
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).FbPrefixInsttoken = bPrefixInsttoken
|
|
return rc
|
|
}
|
|
|
|
func _fts5PorterStep1B(tls *libc.TLS, aBuf uintptr, pnBuf uintptr) (r int32) {
|
|
var nBuf, ret int32
|
|
_, _ = nBuf, ret
|
|
ret = 0
|
|
nBuf = **(**int32)(__ccgo_up(pnBuf))
|
|
switch libc.Int32FromUint8(**(**uint8)(__ccgo_up(aBuf + uintptr(nBuf-int32(2))))) {
|
|
case int32('e'):
|
|
if nBuf > int32(3) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42200, aBuf+uintptr(nBuf-int32(3)), uint64(3)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(3)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(3)), __ccgo_ts+42204, uint64(2))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(3) + int32(2)
|
|
}
|
|
} else {
|
|
if nBuf > int32(2) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42207, aBuf+uintptr(nBuf-int32(2)), uint64(2)) {
|
|
if _fts5Porter_Vowel(tls, aBuf, nBuf-int32(2)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(2)
|
|
ret = int32(1)
|
|
}
|
|
}
|
|
}
|
|
case int32('n'):
|
|
if nBuf > int32(3) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42210, aBuf+uintptr(nBuf-int32(3)), uint64(3)) {
|
|
if _fts5Porter_Vowel(tls, aBuf, nBuf-int32(3)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(3)
|
|
ret = int32(1)
|
|
}
|
|
}
|
|
break
|
|
}
|
|
return ret
|
|
}
|
|
|
|
/*
|
|
** GENERATED CODE ENDS HERE (mkportersteps.tcl)
|
|
***************************************************************************
|
|
**************************************************************************/
|
|
|
|
func _fts5PorterStep1B2(tls *libc.TLS, aBuf uintptr, pnBuf uintptr) (r int32) {
|
|
var nBuf, ret int32
|
|
_, _ = nBuf, ret
|
|
ret = 0
|
|
nBuf = **(**int32)(__ccgo_up(pnBuf))
|
|
switch libc.Int32FromUint8(**(**uint8)(__ccgo_up(aBuf + uintptr(nBuf-int32(2))))) {
|
|
case int32('a'):
|
|
if nBuf > int32(2) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42014, aBuf+uintptr(nBuf-int32(2)), uint64(2)) {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(2)), __ccgo_ts+41994, uint64(3))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(2) + int32(3)
|
|
ret = int32(1)
|
|
}
|
|
case int32('b'):
|
|
if nBuf > int32(2) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42017, aBuf+uintptr(nBuf-int32(2)), uint64(2)) {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(2)), __ccgo_ts+42020, uint64(3))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(2) + int32(3)
|
|
ret = int32(1)
|
|
}
|
|
case int32('i'):
|
|
if nBuf > int32(2) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42024, aBuf+uintptr(nBuf-int32(2)), uint64(2)) {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(2)), __ccgo_ts+42010, uint64(3))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(2) + int32(3)
|
|
ret = int32(1)
|
|
}
|
|
break
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func _fts5PorterStep2(tls *libc.TLS, aBuf uintptr, pnBuf uintptr) (r int32) {
|
|
var nBuf, ret int32
|
|
_, _ = nBuf, ret
|
|
ret = 0
|
|
nBuf = **(**int32)(__ccgo_up(pnBuf))
|
|
switch libc.Int32FromUint8(**(**uint8)(__ccgo_up(aBuf + uintptr(nBuf-int32(2))))) {
|
|
case int32('a'):
|
|
if nBuf > int32(7) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42027, aBuf+uintptr(nBuf-int32(7)), uint64(7)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(7)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(7)), __ccgo_ts+41994, uint64(3))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(7) + int32(3)
|
|
}
|
|
} else {
|
|
if nBuf > int32(6) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42035, aBuf+uintptr(nBuf-int32(6)), uint64(6)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(6)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(6)), __ccgo_ts+42042, uint64(4))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(6) + int32(4)
|
|
}
|
|
}
|
|
}
|
|
case int32('c'):
|
|
if nBuf > int32(4) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42047, aBuf+uintptr(nBuf-int32(4)), uint64(4)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(4)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(4)), __ccgo_ts+41943, uint64(4))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(4) + int32(4)
|
|
}
|
|
} else {
|
|
if nBuf > int32(4) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42052, aBuf+uintptr(nBuf-int32(4)), uint64(4)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(4)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(4)), __ccgo_ts+41938, uint64(4))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(4) + int32(4)
|
|
}
|
|
}
|
|
}
|
|
case int32('e'):
|
|
if nBuf > int32(4) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42057, aBuf+uintptr(nBuf-int32(4)), uint64(4)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(4)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(4)), __ccgo_ts+42010, uint64(3))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(4) + int32(3)
|
|
}
|
|
}
|
|
case int32('g'):
|
|
if nBuf > int32(4) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42062, aBuf+uintptr(nBuf-int32(4)), uint64(4)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(4)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(4)), __ccgo_ts+17193, uint64(3))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(4) + int32(3)
|
|
}
|
|
}
|
|
case int32('l'):
|
|
if nBuf > int32(3) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42067, aBuf+uintptr(nBuf-int32(3)), uint64(3)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(3)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(3)), __ccgo_ts+42020, uint64(3))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(3) + int32(3)
|
|
}
|
|
} else {
|
|
if nBuf > int32(4) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42071, aBuf+uintptr(nBuf-int32(4)), uint64(4)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(4)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(4)), __ccgo_ts+41935, uint64(2))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(4) + int32(2)
|
|
}
|
|
} else {
|
|
if nBuf > int32(5) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42076, aBuf+uintptr(nBuf-int32(5)), uint64(5)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(5)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(5)), __ccgo_ts+41979, uint64(3))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(5) + int32(3)
|
|
}
|
|
} else {
|
|
if nBuf > int32(3) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42082, aBuf+uintptr(nBuf-int32(3)), uint64(3)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(3)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(3)), __ccgo_ts+42086, uint64(1))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(3) + int32(1)
|
|
}
|
|
} else {
|
|
if nBuf > int32(5) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42088, aBuf+uintptr(nBuf-int32(5)), uint64(5)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(5)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(5)), __ccgo_ts+42002, uint64(3))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(5) + int32(3)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
case int32('o'):
|
|
if nBuf > int32(7) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42094, aBuf+uintptr(nBuf-int32(7)), uint64(7)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(7)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(7)), __ccgo_ts+42010, uint64(3))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(7) + int32(3)
|
|
}
|
|
} else {
|
|
if nBuf > int32(5) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42102, aBuf+uintptr(nBuf-int32(5)), uint64(5)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(5)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(5)), __ccgo_ts+41994, uint64(3))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(5) + int32(3)
|
|
}
|
|
} else {
|
|
if nBuf > int32(4) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42108, aBuf+uintptr(nBuf-int32(4)), uint64(4)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(4)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(4)), __ccgo_ts+41994, uint64(3))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(4) + int32(3)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
case int32('s'):
|
|
if nBuf > int32(5) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42113, aBuf+uintptr(nBuf-int32(5)), uint64(5)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(5)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(5)), __ccgo_ts+41935, uint64(2))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(5) + int32(2)
|
|
}
|
|
} else {
|
|
if nBuf > int32(7) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42119, aBuf+uintptr(nBuf-int32(7)), uint64(7)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(7)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(7)), __ccgo_ts+42006, uint64(3))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(7) + int32(3)
|
|
}
|
|
} else {
|
|
if nBuf > int32(7) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42127, aBuf+uintptr(nBuf-int32(7)), uint64(7)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(7)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(7)), __ccgo_ts+42135, uint64(3))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(7) + int32(3)
|
|
}
|
|
} else {
|
|
if nBuf > int32(7) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42139, aBuf+uintptr(nBuf-int32(7)), uint64(7)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(7)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(7)), __ccgo_ts+42002, uint64(3))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(7) + int32(3)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
case int32('t'):
|
|
if nBuf > int32(5) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42147, aBuf+uintptr(nBuf-int32(5)), uint64(5)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(5)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(5)), __ccgo_ts+41935, uint64(2))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(5) + int32(2)
|
|
}
|
|
} else {
|
|
if nBuf > int32(5) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42153, aBuf+uintptr(nBuf-int32(5)), uint64(5)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(5)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(5)), __ccgo_ts+42006, uint64(3))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(5) + int32(3)
|
|
}
|
|
} else {
|
|
if nBuf > int32(6) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42159, aBuf+uintptr(nBuf-int32(6)), uint64(6)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(6)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(6)), __ccgo_ts+42020, uint64(3))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(6) + int32(3)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func _fts5PorterStep3(tls *libc.TLS, aBuf uintptr, pnBuf uintptr) (r int32) {
|
|
var nBuf, ret int32
|
|
_, _ = nBuf, ret
|
|
ret = 0
|
|
nBuf = **(**int32)(__ccgo_up(pnBuf))
|
|
switch libc.Int32FromUint8(**(**uint8)(__ccgo_up(aBuf + uintptr(nBuf-int32(2))))) {
|
|
case int32('a'):
|
|
if nBuf > int32(4) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42166, aBuf+uintptr(nBuf-int32(4)), uint64(4)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(4)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(4)), __ccgo_ts+41951, uint64(2))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(4) + int32(2)
|
|
}
|
|
}
|
|
case int32('s'):
|
|
if nBuf > int32(4) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42171, aBuf+uintptr(nBuf-int32(4)), uint64(4)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(4)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(4)
|
|
}
|
|
}
|
|
case int32('t'):
|
|
if nBuf > int32(5) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42176, aBuf+uintptr(nBuf-int32(5)), uint64(5)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(5)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(5)), __ccgo_ts+41951, uint64(2))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(5) + int32(2)
|
|
}
|
|
} else {
|
|
if nBuf > int32(5) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42182, aBuf+uintptr(nBuf-int32(5)), uint64(5)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(5)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(5)), __ccgo_ts+41951, uint64(2))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(5) + int32(2)
|
|
}
|
|
}
|
|
}
|
|
case int32('u'):
|
|
if nBuf > int32(3) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42135, aBuf+uintptr(nBuf-int32(3)), uint64(3)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(3)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(3)
|
|
}
|
|
}
|
|
case int32('v'):
|
|
if nBuf > int32(5) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42188, aBuf+uintptr(nBuf-int32(5)), uint64(5)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(5)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(5)
|
|
}
|
|
}
|
|
case int32('z'):
|
|
if nBuf > int32(5) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42194, aBuf+uintptr(nBuf-int32(5)), uint64(5)) {
|
|
if _fts5Porter_MGt0(tls, aBuf, nBuf-int32(5)) != 0 {
|
|
libc.Xmemcpy(tls, aBuf+uintptr(nBuf-int32(5)), __ccgo_ts+41935, uint64(2))
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(5) + int32(2)
|
|
}
|
|
}
|
|
break
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func _fts5PorterStep4(tls *libc.TLS, aBuf uintptr, pnBuf uintptr) (r int32) {
|
|
var nBuf, ret int32
|
|
_, _ = nBuf, ret
|
|
ret = 0
|
|
nBuf = **(**int32)(__ccgo_up(pnBuf))
|
|
switch libc.Int32FromUint8(**(**uint8)(__ccgo_up(aBuf + uintptr(nBuf-int32(2))))) {
|
|
case int32('a'):
|
|
if nBuf > int32(2) && 0 == libc.Xmemcmp(tls, __ccgo_ts+41935, aBuf+uintptr(nBuf-int32(2)), uint64(2)) {
|
|
if _fts5Porter_MGt1(tls, aBuf, nBuf-int32(2)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(2)
|
|
}
|
|
}
|
|
case int32('c'):
|
|
if nBuf > int32(4) && 0 == libc.Xmemcmp(tls, __ccgo_ts+41938, aBuf+uintptr(nBuf-int32(4)), uint64(4)) {
|
|
if _fts5Porter_MGt1(tls, aBuf, nBuf-int32(4)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(4)
|
|
}
|
|
} else {
|
|
if nBuf > int32(4) && 0 == libc.Xmemcmp(tls, __ccgo_ts+41943, aBuf+uintptr(nBuf-int32(4)), uint64(4)) {
|
|
if _fts5Porter_MGt1(tls, aBuf, nBuf-int32(4)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(4)
|
|
}
|
|
}
|
|
}
|
|
case int32('e'):
|
|
if nBuf > int32(2) && 0 == libc.Xmemcmp(tls, __ccgo_ts+41948, aBuf+uintptr(nBuf-int32(2)), uint64(2)) {
|
|
if _fts5Porter_MGt1(tls, aBuf, nBuf-int32(2)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(2)
|
|
}
|
|
}
|
|
case int32('i'):
|
|
if nBuf > int32(2) && 0 == libc.Xmemcmp(tls, __ccgo_ts+41951, aBuf+uintptr(nBuf-int32(2)), uint64(2)) {
|
|
if _fts5Porter_MGt1(tls, aBuf, nBuf-int32(2)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(2)
|
|
}
|
|
}
|
|
case int32('l'):
|
|
if nBuf > int32(4) && 0 == libc.Xmemcmp(tls, __ccgo_ts+41954, aBuf+uintptr(nBuf-int32(4)), uint64(4)) {
|
|
if _fts5Porter_MGt1(tls, aBuf, nBuf-int32(4)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(4)
|
|
}
|
|
} else {
|
|
if nBuf > int32(4) && 0 == libc.Xmemcmp(tls, __ccgo_ts+41959, aBuf+uintptr(nBuf-int32(4)), uint64(4)) {
|
|
if _fts5Porter_MGt1(tls, aBuf, nBuf-int32(4)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(4)
|
|
}
|
|
}
|
|
}
|
|
case int32('n'):
|
|
if nBuf > int32(3) && 0 == libc.Xmemcmp(tls, __ccgo_ts+41964, aBuf+uintptr(nBuf-int32(3)), uint64(3)) {
|
|
if _fts5Porter_MGt1(tls, aBuf, nBuf-int32(3)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(3)
|
|
}
|
|
} else {
|
|
if nBuf > int32(5) && 0 == libc.Xmemcmp(tls, __ccgo_ts+41968, aBuf+uintptr(nBuf-int32(5)), uint64(5)) {
|
|
if _fts5Porter_MGt1(tls, aBuf, nBuf-int32(5)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(5)
|
|
}
|
|
} else {
|
|
if nBuf > int32(4) && 0 == libc.Xmemcmp(tls, __ccgo_ts+41974, aBuf+uintptr(nBuf-int32(4)), uint64(4)) {
|
|
if _fts5Porter_MGt1(tls, aBuf, nBuf-int32(4)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(4)
|
|
}
|
|
} else {
|
|
if nBuf > int32(3) && 0 == libc.Xmemcmp(tls, __ccgo_ts+41979, aBuf+uintptr(nBuf-int32(3)), uint64(3)) {
|
|
if _fts5Porter_MGt1(tls, aBuf, nBuf-int32(3)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(3)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
case int32('o'):
|
|
if nBuf > int32(3) && 0 == libc.Xmemcmp(tls, __ccgo_ts+41983, aBuf+uintptr(nBuf-int32(3)), uint64(3)) {
|
|
if _fts5Porter_MGt1_and_S_or_T(tls, aBuf, nBuf-int32(3)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(3)
|
|
}
|
|
} else {
|
|
if nBuf > int32(2) && 0 == libc.Xmemcmp(tls, __ccgo_ts+41987, aBuf+uintptr(nBuf-int32(2)), uint64(2)) {
|
|
if _fts5Porter_MGt1(tls, aBuf, nBuf-int32(2)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(2)
|
|
}
|
|
}
|
|
}
|
|
case int32('s'):
|
|
if nBuf > int32(3) && 0 == libc.Xmemcmp(tls, __ccgo_ts+41990, aBuf+uintptr(nBuf-int32(3)), uint64(3)) {
|
|
if _fts5Porter_MGt1(tls, aBuf, nBuf-int32(3)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(3)
|
|
}
|
|
}
|
|
case int32('t'):
|
|
if nBuf > int32(3) && 0 == libc.Xmemcmp(tls, __ccgo_ts+41994, aBuf+uintptr(nBuf-int32(3)), uint64(3)) {
|
|
if _fts5Porter_MGt1(tls, aBuf, nBuf-int32(3)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(3)
|
|
}
|
|
} else {
|
|
if nBuf > int32(3) && 0 == libc.Xmemcmp(tls, __ccgo_ts+41998, aBuf+uintptr(nBuf-int32(3)), uint64(3)) {
|
|
if _fts5Porter_MGt1(tls, aBuf, nBuf-int32(3)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(3)
|
|
}
|
|
}
|
|
}
|
|
case int32('u'):
|
|
if nBuf > int32(3) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42002, aBuf+uintptr(nBuf-int32(3)), uint64(3)) {
|
|
if _fts5Porter_MGt1(tls, aBuf, nBuf-int32(3)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(3)
|
|
}
|
|
}
|
|
case int32('v'):
|
|
if nBuf > int32(3) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42006, aBuf+uintptr(nBuf-int32(3)), uint64(3)) {
|
|
if _fts5Porter_MGt1(tls, aBuf, nBuf-int32(3)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(3)
|
|
}
|
|
}
|
|
case int32('z'):
|
|
if nBuf > int32(3) && 0 == libc.Xmemcmp(tls, __ccgo_ts+42010, aBuf+uintptr(nBuf-int32(3)), uint64(3)) {
|
|
if _fts5Porter_MGt1(tls, aBuf, nBuf-int32(3)) != 0 {
|
|
**(**int32)(__ccgo_up(pnBuf)) = nBuf - int32(3)
|
|
}
|
|
}
|
|
break
|
|
}
|
|
return ret
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Allocate a trigram tokenizer.
|
|
// */
|
|
func _fts5TriCreate(tls *libc.TLS, pUnused uintptr, azArg uintptr, nArg int32, ppOut uintptr) (r int32) {
|
|
var i, rc, v2 int32
|
|
var pNew, zArg uintptr
|
|
_, _, _, _, _ = i, pNew, rc, zArg, v2
|
|
rc = SQLITE_OK
|
|
pNew = uintptr(0)
|
|
_ = pUnused
|
|
if nArg%int32(2) != 0 {
|
|
rc = int32(SQLITE_ERROR)
|
|
} else {
|
|
pNew = Xsqlite3_malloc64(tls, uint64(8))
|
|
if pNew == uintptr(0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
} else {
|
|
(*TTrigramTokenizer)(unsafe.Pointer(pNew)).FbFold = int32(1)
|
|
(*TTrigramTokenizer)(unsafe.Pointer(pNew)).FiFoldParam = 0
|
|
i = 0
|
|
for {
|
|
if !(rc == SQLITE_OK && i < nArg) {
|
|
break
|
|
}
|
|
zArg = **(**uintptr)(__ccgo_up(azArg + uintptr(i+int32(1))*8))
|
|
if 0 == Xsqlite3_stricmp(tls, **(**uintptr)(__ccgo_up(azArg + uintptr(i)*8)), __ccgo_ts+42214) {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('0') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('1') || **(**uint8)(__ccgo_up(zArg + 1)) != 0 {
|
|
rc = int32(SQLITE_ERROR)
|
|
} else {
|
|
(*TTrigramTokenizer)(unsafe.Pointer(pNew)).FbFold = libc.BoolInt32(libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) == int32('0'))
|
|
}
|
|
} else {
|
|
if 0 == Xsqlite3_stricmp(tls, **(**uintptr)(__ccgo_up(azArg + uintptr(i)*8)), __ccgo_ts+41900) {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('0') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('1') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('2') || **(**uint8)(__ccgo_up(zArg + 1)) != 0 {
|
|
rc = int32(SQLITE_ERROR)
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('0') {
|
|
v2 = int32(2)
|
|
} else {
|
|
v2 = 0
|
|
}
|
|
(*TTrigramTokenizer)(unsafe.Pointer(pNew)).FiFoldParam = v2
|
|
}
|
|
} else {
|
|
rc = int32(SQLITE_ERROR)
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + int32(2)
|
|
}
|
|
if (*TTrigramTokenizer)(unsafe.Pointer(pNew)).FiFoldParam != 0 && (*TTrigramTokenizer)(unsafe.Pointer(pNew)).FbFold == 0 {
|
|
rc = int32(SQLITE_ERROR)
|
|
}
|
|
if rc != SQLITE_OK {
|
|
_fts5TriDelete(tls, pNew)
|
|
pNew = uintptr(0)
|
|
}
|
|
}
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppOut)) = pNew
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Create a "unicode61" tokenizer.
|
|
// */
|
|
func _fts5UnicodeCreate(tls *libc.TLS, pUnused uintptr, azArg uintptr, nArg int32, ppOut uintptr) (r int32) {
|
|
var i, rc int32
|
|
var p, zArg, zCat uintptr
|
|
_, _, _, _, _ = i, p, rc, zArg, zCat
|
|
rc = SQLITE_OK /* Return code */
|
|
p = uintptr(0) /* New tokenizer object */
|
|
_ = pUnused
|
|
if nArg%int32(2) != 0 {
|
|
rc = int32(SQLITE_ERROR)
|
|
} else {
|
|
p = Xsqlite3_malloc64(tls, uint64(192))
|
|
if p != 0 {
|
|
zCat = __ccgo_ts + 41880
|
|
libc.Xmemset(tls, p, 0, uint64(192))
|
|
(*TUnicode61Tokenizer)(unsafe.Pointer(p)).FeRemoveDiacritic = int32(FTS5_REMOVE_DIACRITICS_SIMPLE)
|
|
(*TUnicode61Tokenizer)(unsafe.Pointer(p)).FnFold = int32(64)
|
|
(*TUnicode61Tokenizer)(unsafe.Pointer(p)).FaFold = Xsqlite3_malloc64(tls, uint64(libc.Uint64FromInt32((*TUnicode61Tokenizer)(unsafe.Pointer(p)).FnFold)*uint64(1)))
|
|
if (*TUnicode61Tokenizer)(unsafe.Pointer(p)).FaFold == uintptr(0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
}
|
|
/* Search for a "categories" argument */
|
|
i = 0
|
|
for {
|
|
if !(rc == SQLITE_OK && i < nArg) {
|
|
break
|
|
}
|
|
if 0 == Xsqlite3_stricmp(tls, **(**uintptr)(__ccgo_up(azArg + uintptr(i)*8)), __ccgo_ts+41889) {
|
|
zCat = **(**uintptr)(__ccgo_up(azArg + uintptr(i+int32(1))*8))
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + int32(2)
|
|
}
|
|
if rc == SQLITE_OK {
|
|
rc = _unicodeSetCategories(tls, p, zCat)
|
|
}
|
|
i = 0
|
|
for {
|
|
if !(rc == SQLITE_OK && i < nArg) {
|
|
break
|
|
}
|
|
zArg = **(**uintptr)(__ccgo_up(azArg + uintptr(i+int32(1))*8))
|
|
if 0 == Xsqlite3_stricmp(tls, **(**uintptr)(__ccgo_up(azArg + uintptr(i)*8)), __ccgo_ts+41900) {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('0') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('1') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) != int32('2') || **(**uint8)(__ccgo_up(zArg + 1)) != 0 {
|
|
rc = int32(SQLITE_ERROR)
|
|
} else {
|
|
(*TUnicode61Tokenizer)(unsafe.Pointer(p)).FeRemoveDiacritic = libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) - int32('0')
|
|
}
|
|
} else {
|
|
if 0 == Xsqlite3_stricmp(tls, **(**uintptr)(__ccgo_up(azArg + uintptr(i)*8)), __ccgo_ts+41858) {
|
|
rc = _fts5UnicodeAddExceptions(tls, p, zArg, int32(1))
|
|
} else {
|
|
if 0 == Xsqlite3_stricmp(tls, **(**uintptr)(__ccgo_up(azArg + uintptr(i)*8)), __ccgo_ts+41869) {
|
|
rc = _fts5UnicodeAddExceptions(tls, p, zArg, 0)
|
|
} else {
|
|
if 0 == Xsqlite3_stricmp(tls, **(**uintptr)(__ccgo_up(azArg + uintptr(i)*8)), __ccgo_ts+41889) {
|
|
/* no-op */
|
|
} else {
|
|
rc = int32(SQLITE_ERROR)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + int32(2)
|
|
}
|
|
} else {
|
|
rc = int32(SQLITE_NOMEM)
|
|
}
|
|
if rc != SQLITE_OK {
|
|
_fts5UnicodeDelete(tls, p)
|
|
p = uintptr(0)
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppOut)) = p
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** SQL function: geopoly_svg(X, ....)
|
|
// **
|
|
// ** Interpret X as a polygon and render it as a SVG <polyline>.
|
|
// ** Additional arguments are added as attributes to the <polyline>.
|
|
// */
|
|
func _geopolySvgFunc(tls *libc.TLS, context uintptr, argc int32, argv uintptr) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var cSep uint8
|
|
var db, p, x, z uintptr
|
|
var i int32
|
|
_, _, _, _, _, _ = cSep, db, i, p, x, z
|
|
if argc < int32(1) {
|
|
return
|
|
}
|
|
p = _geopolyFuncParam(tls, context, **(**uintptr)(__ccgo_up(argv)), uintptr(0))
|
|
if p != 0 {
|
|
db = Xsqlite3_context_db_handle(tls, context)
|
|
x = Xsqlite3_str_new(tls, db)
|
|
cSep = uint8('\'')
|
|
Xsqlite3_str_appendf(tls, x, __ccgo_ts+29883, 0)
|
|
i = 0
|
|
for {
|
|
if !(i < (*TGeoPoly)(unsafe.Pointer(p)).FnVertex) {
|
|
break
|
|
}
|
|
Xsqlite3_str_appendf(tls, x, __ccgo_ts+29901, libc.VaList(bp+8, libc.Int32FromUint8(cSep), float64(**(**TGeoCoord)(__ccgo_up(p + 8 + uintptr(i*int32(2))*4))), float64(**(**TGeoCoord)(__ccgo_up(p + 8 + uintptr(i*int32(2)+int32(1))*4)))))
|
|
cSep = uint8(' ')
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
Xsqlite3_str_appendf(tls, x, __ccgo_ts+29909, libc.VaList(bp+8, float64(**(**TGeoCoord)(__ccgo_up(p + 8 + uintptr(libc.Int32FromInt32(0)*libc.Int32FromInt32(2))*4))), float64(**(**TGeoCoord)(__ccgo_up(p + 8 + uintptr(libc.Int32FromInt32(0)*libc.Int32FromInt32(2)+libc.Int32FromInt32(1))*4)))))
|
|
i = int32(1)
|
|
for {
|
|
if !(i < argc) {
|
|
break
|
|
}
|
|
z = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8)))
|
|
if z != 0 && **(**uint8)(__ccgo_up(z)) != 0 {
|
|
Xsqlite3_str_appendf(tls, x, __ccgo_ts+29917, libc.VaList(bp+8, z))
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
Xsqlite3_str_appendf(tls, x, __ccgo_ts+29921, 0)
|
|
Xsqlite3_result_text(tls, context, Xsqlite3_str_finish(tls, x), -int32(1), __ccgo_fp(Xsqlite3_free))
|
|
Xsqlite3_free(tls, p)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* c is a control character. Append the canonical JSON representation
|
|
// ** of that control character to p.
|
|
// **
|
|
// ** This routine assumes that the output buffer has already been enlarged
|
|
// ** sufficiently to hold the worst-case encoding plus a nul terminator.
|
|
// */
|
|
func _jsonAppendControlChar(tls *libc.TLS, p uintptr, c Tu8) {
|
|
if _aSpecial[c] != 0 {
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr((*TJsonString)(unsafe.Pointer(p)).FnUsed))) = uint8('\\')
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr((*TJsonString)(unsafe.Pointer(p)).FnUsed+uint64(1)))) = _aSpecial[c]
|
|
**(**Tu64)(__ccgo_up(p + 24)) += uint64(2)
|
|
} else {
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr((*TJsonString)(unsafe.Pointer(p)).FnUsed))) = uint8('\\')
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr((*TJsonString)(unsafe.Pointer(p)).FnUsed+uint64(1)))) = uint8('u')
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr((*TJsonString)(unsafe.Pointer(p)).FnUsed+uint64(2)))) = uint8('0')
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr((*TJsonString)(unsafe.Pointer(p)).FnUsed+uint64(3)))) = uint8('0')
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr((*TJsonString)(unsafe.Pointer(p)).FnUsed+uint64(4)))) = **(**uint8)(__ccgo_up(__ccgo_ts + 1726 + uintptr(libc.Int32FromUint8(c)>>int32(4))))
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr((*TJsonString)(unsafe.Pointer(p)).FnUsed+uint64(5)))) = **(**uint8)(__ccgo_up(__ccgo_ts + 1726 + uintptr(libc.Int32FromUint8(c)&int32(0xf))))
|
|
**(**Tu64)(__ccgo_up(p + 24)) += uint64(6)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Append the path name for the current element.
|
|
// */
|
|
func _jsonAppendPathName(tls *libc.TLS, p uintptr) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var i, k, n Tu32
|
|
var needQuote int32
|
|
var z uintptr
|
|
var _ /* sz at bp+0 */ Tu32
|
|
_, _, _, _, _ = i, k, n, needQuote, z
|
|
if libc.Int32FromUint8((*TJsonEachCursor)(unsafe.Pointer(p)).FeType) == int32(JSONB_ARRAY) {
|
|
_jsonPrintf(tls, int32(30), p+56, __ccgo_ts+26969, libc.VaList(bp+16, (**(**TJsonParent)(__ccgo_up((*TJsonEachCursor)(unsafe.Pointer(p)).FaParent + uintptr((*TJsonEachCursor)(unsafe.Pointer(p)).FnParent-uint32(1))*24))).FiKey))
|
|
} else {
|
|
**(**Tu32)(__ccgo_up(bp)) = uint32(0)
|
|
needQuote = 0
|
|
n = _jsonbPayloadSize(tls, p+192, (*TJsonEachCursor)(unsafe.Pointer(p)).Fi, bp)
|
|
k = (*TJsonEachCursor)(unsafe.Pointer(p)).Fi + n
|
|
z = (*TJsonEachCursor)(unsafe.Pointer(p)).FsParse.FaBlob + uintptr(k)
|
|
if **(**Tu32)(__ccgo_up(bp)) == uint32(0) || !(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z)))])&libc.Int32FromInt32(0x02) != 0) {
|
|
needQuote = int32(1)
|
|
} else {
|
|
i = uint32(0)
|
|
for {
|
|
if !(i < **(**Tu32)(__ccgo_up(bp))) {
|
|
break
|
|
}
|
|
if !(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(i))))])&libc.Int32FromInt32(0x06) != 0) {
|
|
needQuote = int32(1)
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
if needQuote != 0 {
|
|
_jsonPrintf(tls, libc.Int32FromUint32(**(**Tu32)(__ccgo_up(bp))+uint32(4)), p+56, __ccgo_ts+26976, libc.VaList(bp+16, **(**Tu32)(__ccgo_up(bp)), z))
|
|
} else {
|
|
_jsonPrintf(tls, libc.Int32FromUint32(**(**Tu32)(__ccgo_up(bp))+uint32(2)), p+56, __ccgo_ts+26984, libc.VaList(bp+16, **(**Tu32)(__ccgo_up(bp)), z))
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** json_array_length(JSON)
|
|
// ** json_array_length(JSON, PATH)
|
|
// **
|
|
// ** Return the number of elements in the top-level JSON array.
|
|
// ** Return 0 if the input is not a well-formed JSON array.
|
|
// */
|
|
func _jsonArrayLengthFunc(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
|
|
var cnt Tsqlite3_int64
|
|
var eErr Tu8
|
|
var i Tu32
|
|
var p, zPath, v1 uintptr
|
|
_, _, _, _, _, _ = cnt, eErr, i, p, zPath, v1 /* The parse */
|
|
cnt = 0
|
|
eErr = uint8(0)
|
|
p = _jsonParseFuncArg(tls, ctx, **(**uintptr)(__ccgo_up(argv)), uint32(0))
|
|
if p == uintptr(0) {
|
|
return
|
|
}
|
|
if argc == int32(2) {
|
|
zPath = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv + 1*8)))
|
|
if zPath == uintptr(0) {
|
|
_jsonParseFree(tls, p)
|
|
return
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath))) == int32('$') {
|
|
v1 = zPath + uintptr(1)
|
|
} else {
|
|
v1 = __ccgo_ts + 26696
|
|
}
|
|
i = _jsonLookupStep(tls, p, uint32(0), v1, uint32(0))
|
|
if i >= uint32(JSON_LOOKUP_PATHERROR) {
|
|
if i == uint32(JSON_LOOKUP_NOTFOUND) {
|
|
/* no-op */
|
|
} else {
|
|
_jsonBadPathError(tls, ctx, zPath, libc.Int32FromUint32(i))
|
|
}
|
|
eErr = uint8(1)
|
|
i = uint32(0)
|
|
}
|
|
} else {
|
|
i = uint32(0)
|
|
}
|
|
if libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(p)).FaBlob + uintptr(i))))&int32(0x0f) == int32(JSONB_ARRAY) {
|
|
cnt = libc.Int64FromUint32(_jsonbArrayCount(tls, p, i))
|
|
}
|
|
if !(eErr != 0) {
|
|
Xsqlite3_result_int64(tls, ctx, cnt)
|
|
}
|
|
_jsonParseFree(tls, p)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Constructor for the json_each virtual table */
|
|
func _jsonEachConnect(tls *libc.TLS, db uintptr, pAux uintptr, argc int32, argv uintptr, ppVtab uintptr, pzErr uintptr) (r int32) {
|
|
var pNew uintptr
|
|
var rc, v1 int32
|
|
_, _, _ = pNew, rc, v1
|
|
/* Column numbers */
|
|
/* The xBestIndex method assumes that the JSON and ROOT columns are
|
|
** the last two columns in the table. Should this ever changes, be
|
|
** sure to update the xBestIndex method. */
|
|
_ = pzErr
|
|
_ = argv
|
|
_ = argc
|
|
_ = pAux
|
|
rc = Xsqlite3_declare_vtab(tls, db, __ccgo_ts+26886)
|
|
if rc == SQLITE_OK {
|
|
pNew = _sqlite3DbMallocZero(tls, db, uint64(40))
|
|
**(**uintptr)(__ccgo_up(ppVtab)) = pNew
|
|
if pNew == uintptr(0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
Xsqlite3_vtab_config(tls, db, int32(SQLITE_VTAB_INNOCUOUS), 0)
|
|
(*TJsonEachConnection)(unsafe.Pointer(pNew)).Fdb = db
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(**(**uintptr)(__ccgo_up(argv)) + 4))) == int32('b') {
|
|
v1 = int32(2)
|
|
} else {
|
|
v1 = int32(1)
|
|
}
|
|
(*TJsonEachConnection)(unsafe.Pointer(pNew)).FeMode = libc.Uint8FromInt32(v1)
|
|
(*TJsonEachConnection)(unsafe.Pointer(pNew)).FbRecursive = libc.BoolUint8(libc.Int32FromUint8(**(**uint8)(__ccgo_up(**(**uintptr)(__ccgo_up(argv)) + uintptr(int32(4)+libc.Int32FromUint8((*TJsonEachConnection)(unsafe.Pointer(pNew)).FeMode))))) == int32('t'))
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Start a search on a new JSON string */
|
|
func _jsonEachFilter(tls *libc.TLS, cur uintptr, idxNum int32, idxStr uintptr, argc int32, argv uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var i, n, v1 Tu32
|
|
var p, zRoot uintptr
|
|
var v2 int32
|
|
var _ /* sz at bp+0 */ Tu32
|
|
_, _, _, _, _, _ = i, n, p, zRoot, v1, v2
|
|
p = cur
|
|
zRoot = uintptr(0)
|
|
_ = idxStr
|
|
_ = argc
|
|
_jsonEachCursorReset(tls, p)
|
|
if idxNum == 0 {
|
|
return SQLITE_OK
|
|
}
|
|
libc.Xmemset(tls, p+192, 0, uint64(72))
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FsParse.FnJPRef = uint32(1)
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FsParse.Fdb = (*TJsonEachCursor)(unsafe.Pointer(p)).Fdb
|
|
if _jsonArgIsJsonb(tls, **(**uintptr)(__ccgo_up(argv)), p+192) != 0 {
|
|
/* We have JSONB */
|
|
} else {
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FsParse.FzJson = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FsParse.FnJson = Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
if (*TJsonEachCursor)(unsafe.Pointer(p)).FsParse.FzJson == uintptr(0) {
|
|
v1 = libc.Uint32FromInt32(0)
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FiEnd = v1
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).Fi = v1
|
|
return SQLITE_OK
|
|
}
|
|
if _jsonConvertTextToBlob(tls, p+192, uintptr(0)) != 0 {
|
|
if (*TJsonEachCursor)(unsafe.Pointer(p)).FsParse.Foom != 0 {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
goto json_each_malformed_input
|
|
}
|
|
}
|
|
if idxNum == int32(3) {
|
|
zRoot = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv + 1*8)))
|
|
if zRoot == uintptr(0) {
|
|
return SQLITE_OK
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zRoot))) != int32('$') {
|
|
Xsqlite3_free(tls, (*Tsqlite3_vtab)(unsafe.Pointer((*Tsqlite3_vtab_cursor)(unsafe.Pointer(cur)).FpVtab)).FzErrMsg)
|
|
(*Tsqlite3_vtab)(unsafe.Pointer((*Tsqlite3_vtab_cursor)(unsafe.Pointer(cur)).FpVtab)).FzErrMsg = _jsonBadPathError(tls, uintptr(0), zRoot, 0)
|
|
_jsonEachCursorReset(tls, p)
|
|
if (*Tsqlite3_vtab)(unsafe.Pointer((*Tsqlite3_vtab_cursor)(unsafe.Pointer(cur)).FpVtab)).FzErrMsg != 0 {
|
|
v2 = int32(SQLITE_ERROR)
|
|
} else {
|
|
v2 = int32(SQLITE_NOMEM)
|
|
}
|
|
return v2
|
|
}
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FnRoot = libc.Uint32FromInt32(_sqlite3Strlen30(tls, zRoot))
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zRoot + 1))) == 0 {
|
|
v1 = libc.Uint32FromInt32(0)
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).Fi = v1
|
|
i = v1
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FeType = uint8(0)
|
|
} else {
|
|
i = _jsonLookupStep(tls, p+192, uint32(0), zRoot+uintptr(1), uint32(0))
|
|
if i >= uint32(JSON_LOOKUP_PATHERROR) {
|
|
if i == uint32(JSON_LOOKUP_NOTFOUND) {
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).Fi = uint32(0)
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FeType = uint8(0)
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FiEnd = uint32(0)
|
|
return SQLITE_OK
|
|
}
|
|
Xsqlite3_free(tls, (*Tsqlite3_vtab)(unsafe.Pointer((*Tsqlite3_vtab_cursor)(unsafe.Pointer(cur)).FpVtab)).FzErrMsg)
|
|
(*Tsqlite3_vtab)(unsafe.Pointer((*Tsqlite3_vtab_cursor)(unsafe.Pointer(cur)).FpVtab)).FzErrMsg = _jsonBadPathError(tls, uintptr(0), zRoot, 0)
|
|
_jsonEachCursorReset(tls, p)
|
|
if (*Tsqlite3_vtab)(unsafe.Pointer((*Tsqlite3_vtab_cursor)(unsafe.Pointer(cur)).FpVtab)).FzErrMsg != 0 {
|
|
v2 = int32(SQLITE_ERROR)
|
|
} else {
|
|
v2 = int32(SQLITE_NOMEM)
|
|
}
|
|
return v2
|
|
}
|
|
if (*TJsonEachCursor)(unsafe.Pointer(p)).FsParse.FiLabel != 0 {
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).Fi = (*TJsonEachCursor)(unsafe.Pointer(p)).FsParse.FiLabel
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FeType = uint8(JSONB_OBJECT)
|
|
} else {
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).Fi = i
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FeType = uint8(JSONB_ARRAY)
|
|
}
|
|
}
|
|
_jsonAppendRaw(tls, p+56, zRoot, (*TJsonEachCursor)(unsafe.Pointer(p)).FnRoot)
|
|
} else {
|
|
v1 = libc.Uint32FromInt32(0)
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).Fi = v1
|
|
i = v1
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FeType = uint8(0)
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FnRoot = uint32(1)
|
|
_jsonAppendRaw(tls, p+56, __ccgo_ts+26990, uint32(1))
|
|
}
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FnParent = uint32(0)
|
|
n = _jsonbPayloadSize(tls, p+192, i, bp)
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FiEnd = i + n + **(**Tu32)(__ccgo_up(bp))
|
|
if libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonEachCursor)(unsafe.Pointer(p)).FsParse.FaBlob + uintptr(i))))&int32(0x0f) >= int32(JSONB_ARRAY) && !((*TJsonEachCursor)(unsafe.Pointer(p)).FbRecursive != 0) {
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).Fi = i + n
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FeType = libc.Uint8FromInt32(libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonEachCursor)(unsafe.Pointer(p)).FsParse.FaBlob + uintptr(i)))) & int32(0x0f))
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FaParent = _sqlite3DbMallocZero(tls, (*TJsonEachCursor)(unsafe.Pointer(p)).Fdb, uint64(24))
|
|
if (*TJsonEachCursor)(unsafe.Pointer(p)).FaParent == uintptr(0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FnParent = uint32(1)
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FnParentAlloc = uint32(1)
|
|
(**(**TJsonParent)(__ccgo_up((*TJsonEachCursor)(unsafe.Pointer(p)).FaParent))).FiKey = 0
|
|
(**(**TJsonParent)(__ccgo_up((*TJsonEachCursor)(unsafe.Pointer(p)).FaParent))).FiEnd = (*TJsonEachCursor)(unsafe.Pointer(p)).FiEnd
|
|
(**(**TJsonParent)(__ccgo_up((*TJsonEachCursor)(unsafe.Pointer(p)).FaParent))).FiHead = (*TJsonEachCursor)(unsafe.Pointer(p)).Fi
|
|
(**(**TJsonParent)(__ccgo_up((*TJsonEachCursor)(unsafe.Pointer(p)).FaParent))).FiValue = i
|
|
}
|
|
return SQLITE_OK
|
|
goto json_each_malformed_input
|
|
json_each_malformed_input:
|
|
;
|
|
Xsqlite3_free(tls, (*Tsqlite3_vtab)(unsafe.Pointer((*Tsqlite3_vtab_cursor)(unsafe.Pointer(cur)).FpVtab)).FzErrMsg)
|
|
(*Tsqlite3_vtab)(unsafe.Pointer((*Tsqlite3_vtab_cursor)(unsafe.Pointer(cur)).FpVtab)).FzErrMsg = Xsqlite3_mprintf(tls, __ccgo_ts+26486, 0)
|
|
_jsonEachCursorReset(tls, p)
|
|
if (*Tsqlite3_vtab)(unsafe.Pointer((*Tsqlite3_vtab_cursor)(unsafe.Pointer(cur)).FpVtab)).FzErrMsg != 0 {
|
|
v2 = int32(SQLITE_ERROR)
|
|
} else {
|
|
v2 = int32(SQLITE_NOMEM)
|
|
}
|
|
return v2
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** json_extract(JSON, PATH, ...)
|
|
// ** "->"(JSON,PATH)
|
|
// ** "->>"(JSON,PATH)
|
|
// **
|
|
// ** Return the element described by PATH. Return NULL if that PATH element
|
|
// ** is not found.
|
|
// **
|
|
// ** If JSON_JSON is set or if more that one PATH argument is supplied then
|
|
// ** always return a JSON representation of the result. If JSON_SQL is set,
|
|
// ** then always return an SQL representation of the result. If neither flag
|
|
// ** is present and argc==2, then return JSON for objects and arrays and SQL
|
|
// ** for all other values.
|
|
// **
|
|
// ** When multiple PATH arguments are supplied, the result is a JSON array
|
|
// ** containing the result of each PATH.
|
|
// **
|
|
// ** Abbreviated JSON path expressions are allows if JSON_ABPATH, for
|
|
// ** compatibility with PG.
|
|
// */
|
|
func _jsonExtractFunc(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
|
|
bp := tls.Alloc(144)
|
|
defer tls.Free(144)
|
|
var flags, i, nPath int32
|
|
var j Tu32
|
|
var p, zPath uintptr
|
|
var _ /* jx at bp+0 */ TJsonString
|
|
_, _, _, _, _, _ = flags, i, j, nPath, p, zPath
|
|
p = uintptr(0) /* String for array result */
|
|
if argc < int32(2) {
|
|
return
|
|
}
|
|
p = _jsonParseFuncArg(tls, ctx, **(**uintptr)(__ccgo_up(argv)), uint32(0))
|
|
if p == uintptr(0) {
|
|
return
|
|
}
|
|
flags = int32(int64(Xsqlite3_user_data(tls, ctx)))
|
|
_jsonStringInit(tls, bp, ctx)
|
|
if argc > int32(2) {
|
|
_jsonAppendChar(tls, bp, uint8('['))
|
|
}
|
|
i = int32(1)
|
|
for {
|
|
if !(i < argc) {
|
|
break
|
|
}
|
|
/* With a single PATH argument */
|
|
zPath = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8)))
|
|
if zPath == uintptr(0) {
|
|
goto json_extract_error
|
|
}
|
|
nPath = _sqlite3Strlen30(tls, zPath)
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath))) == int32('$') {
|
|
j = _jsonLookupStep(tls, p, uint32(0), zPath+uintptr(1), uint32(0))
|
|
} else {
|
|
if flags&int32(JSON_ABPATH) != 0 {
|
|
/* The -> and ->> operators accept abbreviated PATH arguments. This
|
|
** is mostly for compatibility with PostgreSQL, but also for
|
|
** convenience.
|
|
**
|
|
** NUMBER ==> $[NUMBER] // PG compatible
|
|
** LABEL ==> $.LABEL // PG compatible
|
|
** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience
|
|
**
|
|
** Updated 2024-05-27: If the NUMBER is negative, then PG counts from
|
|
** the right of the array. Hence for negative NUMBER:
|
|
**
|
|
** NUMBER ==> $[#NUMBER] // PG compatible
|
|
*/
|
|
_jsonStringInit(tls, bp, ctx)
|
|
if Xsqlite3_value_type(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8))) == int32(SQLITE_INTEGER) {
|
|
_jsonAppendRawNZ(tls, bp, __ccgo_ts+26698, uint32(1))
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath))) == int32('-') {
|
|
_jsonAppendRawNZ(tls, bp, __ccgo_ts+26700, uint32(1))
|
|
}
|
|
_jsonAppendRaw(tls, bp, zPath, libc.Uint32FromInt32(nPath))
|
|
_jsonAppendRawNZ(tls, bp, __ccgo_ts+5340, uint32(2))
|
|
} else {
|
|
if _jsonAllAlphanum(tls, zPath, nPath) != 0 {
|
|
_jsonAppendRawNZ(tls, bp, __ccgo_ts+1743, uint32(1))
|
|
_jsonAppendRaw(tls, bp, zPath, libc.Uint32FromInt32(nPath))
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath))) == int32('[') && nPath >= int32(3) && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath + uintptr(nPath-int32(1))))) == int32(']') {
|
|
_jsonAppendRaw(tls, bp, zPath, libc.Uint32FromInt32(nPath))
|
|
} else {
|
|
_jsonAppendRawNZ(tls, bp, __ccgo_ts+26702, uint32(2))
|
|
_jsonAppendRaw(tls, bp, zPath, libc.Uint32FromInt32(nPath))
|
|
_jsonAppendRawNZ(tls, bp, __ccgo_ts+26705, uint32(1))
|
|
}
|
|
}
|
|
}
|
|
_jsonStringTerminate(tls, bp)
|
|
j = _jsonLookupStep(tls, p, uint32(0), (**(**TJsonString)(__ccgo_up(bp))).FzBuf, uint32(0))
|
|
_jsonStringReset(tls, bp)
|
|
} else {
|
|
_jsonBadPathError(tls, ctx, zPath, 0)
|
|
goto json_extract_error
|
|
}
|
|
}
|
|
if j < (*TJsonParse)(unsafe.Pointer(p)).FnBlob {
|
|
if argc == int32(2) {
|
|
if flags&int32(JSON_JSON) != 0 {
|
|
_jsonStringInit(tls, bp, ctx)
|
|
_jsonTranslateBlobToText(tls, p, j, bp)
|
|
_jsonReturnString(tls, bp, uintptr(0), uintptr(0))
|
|
_jsonStringReset(tls, bp)
|
|
Xsqlite3_result_subtype(tls, ctx, uint32(JSON_SUBTYPE))
|
|
} else {
|
|
_jsonReturnFromBlob(tls, p, j, ctx, 0)
|
|
if flags&(libc.Int32FromInt32(JSON_SQL)|libc.Int32FromInt32(JSON_BLOB)) == 0 && libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(p)).FaBlob + uintptr(j))))&int32(0x0f) >= int32(JSONB_ARRAY) {
|
|
Xsqlite3_result_subtype(tls, ctx, uint32(JSON_SUBTYPE))
|
|
}
|
|
}
|
|
} else {
|
|
_jsonAppendSeparator(tls, bp)
|
|
_jsonTranslateBlobToText(tls, p, j, bp)
|
|
}
|
|
} else {
|
|
if j == uint32(JSON_LOOKUP_NOTFOUND) {
|
|
if argc == int32(2) {
|
|
goto json_extract_error /* Return NULL if not found */
|
|
} else {
|
|
_jsonAppendSeparator(tls, bp)
|
|
_jsonAppendRawNZ(tls, bp, __ccgo_ts+1690, uint32(4))
|
|
}
|
|
} else {
|
|
_jsonBadPathError(tls, ctx, zPath, libc.Int32FromUint32(j))
|
|
goto json_extract_error
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if argc > int32(2) {
|
|
_jsonAppendChar(tls, bp, uint8(']'))
|
|
_jsonReturnString(tls, bp, uintptr(0), uintptr(0))
|
|
if flags&int32(JSON_BLOB) == 0 {
|
|
Xsqlite3_result_subtype(tls, ctx, uint32(JSON_SUBTYPE))
|
|
}
|
|
}
|
|
goto json_extract_error
|
|
json_extract_error:
|
|
;
|
|
_jsonStringReset(tls, bp)
|
|
_jsonParseFree(tls, p)
|
|
return
|
|
}
|
|
|
|
/*
|
|
** Return codes for jsonMergePatch()
|
|
*/
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** pArg is a function argument that might be an SQL value or a JSON
|
|
// ** value. Figure out what it is and encode it as a JSONB blob.
|
|
// ** Return the results in pParse.
|
|
// **
|
|
// ** pParse is uninitialized upon entry. This routine will handle the
|
|
// ** initialization of pParse. The result will be contained in
|
|
// ** pParse->aBlob and pParse->nBlob. pParse->aBlob might be dynamically
|
|
// ** allocated (if pParse->nBlobAlloc is greater than zero) in which case
|
|
// ** the caller is responsible for freeing the space allocated to pParse->aBlob
|
|
// ** when it has finished with it. Or pParse->aBlob might be a static string
|
|
// ** or a value obtained from sqlite3_value_blob(pArg).
|
|
// **
|
|
// ** If the argument is a BLOB that is clearly not a JSONB, then this
|
|
// ** function might set an error message in ctx and return non-zero.
|
|
// ** It might also set an error message and return non-zero on an OOM error.
|
|
// */
|
|
func _jsonFunctionArgToBlob(tls *libc.TLS, ctx uintptr, pArg uintptr, pParse uintptr) (r1 int32) {
|
|
var eType, n, n1, nJson int32
|
|
var r float64
|
|
var z, z1, zJson uintptr
|
|
_, _, _, _, _, _, _, _ = eType, n, n1, nJson, r, z, z1, zJson
|
|
eType = Xsqlite3_value_type(tls, pArg)
|
|
libc.Xmemset(tls, pParse, 0, uint64(72))
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).Fdb = Xsqlite3_context_db_handle(tls, ctx)
|
|
switch eType {
|
|
default:
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FaBlob = uintptr(unsafe.Pointer(&_aNull))
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FnBlob = uint32(1)
|
|
return 0
|
|
case int32(SQLITE_BLOB):
|
|
if !(_jsonArgIsJsonb(tls, pArg, pParse) != 0) {
|
|
Xsqlite3_result_error(tls, ctx, __ccgo_ts+26457, -int32(1))
|
|
return int32(1)
|
|
}
|
|
case int32(SQLITE_TEXT):
|
|
zJson = Xsqlite3_value_text(tls, pArg)
|
|
nJson = Xsqlite3_value_bytes(tls, pArg)
|
|
if zJson == uintptr(0) {
|
|
return int32(1)
|
|
}
|
|
if Xsqlite3_value_subtype(tls, pArg) == uint32(JSON_SUBTYPE) {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FzJson = zJson
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FnJson = nJson
|
|
if _jsonConvertTextToBlob(tls, pParse, ctx) != 0 {
|
|
Xsqlite3_result_error(tls, ctx, __ccgo_ts+26486, -int32(1))
|
|
_sqlite3DbFree(tls, (*TJsonParse)(unsafe.Pointer(pParse)).Fdb, (*TJsonParse)(unsafe.Pointer(pParse)).FaBlob)
|
|
libc.Xmemset(tls, pParse, 0, uint64(72))
|
|
return int32(1)
|
|
}
|
|
} else {
|
|
_jsonBlobAppendNode(tls, pParse, uint8(JSONB_TEXTRAW), libc.Uint64FromInt32(nJson), zJson)
|
|
}
|
|
case int32(SQLITE_FLOAT):
|
|
r = Xsqlite3_value_double(tls, pArg)
|
|
if _sqlite3IsNaN(tls, r) != 0 {
|
|
_jsonBlobAppendNode(tls, pParse, uint8(JSONB_NULL), uint64(0), uintptr(0))
|
|
} else {
|
|
n = Xsqlite3_value_bytes(tls, pArg)
|
|
z = Xsqlite3_value_text(tls, pArg)
|
|
if z == uintptr(0) {
|
|
return int32(1)
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) == int32('I') {
|
|
_jsonBlobAppendNode(tls, pParse, uint8(JSONB_FLOAT), uint64(5), __ccgo_ts+26591)
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) == int32('-') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 1))) == int32('I') {
|
|
_jsonBlobAppendNode(tls, pParse, uint8(JSONB_FLOAT), uint64(6), __ccgo_ts+26584)
|
|
} else {
|
|
_jsonBlobAppendNode(tls, pParse, uint8(JSONB_FLOAT), libc.Uint64FromInt32(n), z)
|
|
}
|
|
}
|
|
}
|
|
case int32(SQLITE_INTEGER):
|
|
n1 = Xsqlite3_value_bytes(tls, pArg)
|
|
z1 = Xsqlite3_value_text(tls, pArg)
|
|
if z1 == uintptr(0) {
|
|
return int32(1)
|
|
}
|
|
_jsonBlobAppendNode(tls, pParse, uint8(JSONB_INT), libc.Uint64FromInt32(n1), z1)
|
|
break
|
|
}
|
|
if (*TJsonParse)(unsafe.Pointer(pParse)).Foom != 0 {
|
|
Xsqlite3_result_error_nomem(tls, ctx)
|
|
return int32(1)
|
|
} else {
|
|
return 0
|
|
}
|
|
return r1
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Search along zPath to find the Json element specified. Return an
|
|
// ** index into pParse->aBlob[] for the start of that element's value.
|
|
// **
|
|
// ** If the value found by this routine is the value half of label/value pair
|
|
// ** within an object, then set pPath->iLabel to the start of the corresponding
|
|
// ** label, before returning.
|
|
// **
|
|
// ** Return one of the JSON_LOOKUP error codes if problems are seen.
|
|
// **
|
|
// ** This routine will also modify the blob. If pParse->eEdit is one of
|
|
// ** JEDIT_DEL, JEDIT_REPL, JEDIT_INS, JEDIT_SET, or JEDIT_AINS, then changes
|
|
// ** might be made to the selected value. If an edit is performed, then the
|
|
// ** return value does not necessarily point to the select element. If an edit
|
|
// ** is performed, the return value is only useful for detecting error
|
|
// ** conditions.
|
|
// */
|
|
func _jsonLookupStep(tls *libc.TLS, pParse uintptr, iRoot Tu32, zPath uintptr, iLabel Tu32) (r Tu32) {
|
|
bp := tls.Alloc(224)
|
|
defer tls.Free(224)
|
|
var i, iEnd, j, k, n, nIns, nKey, rc, v Tu32
|
|
var kk, nn Tu64
|
|
var rawKey, rawLabel, v5 int32
|
|
var x Tu8
|
|
var zKey, zLabel, v4 uintptr
|
|
var v3 Tu16
|
|
var _ /* ix at bp+80 */ TJsonParse
|
|
var _ /* sz at bp+0 */ Tu32
|
|
var _ /* v at bp+152 */ TJsonParse
|
|
var _ /* v at bp+8 */ TJsonParse
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = i, iEnd, j, k, kk, n, nIns, nKey, nn, rawKey, rawLabel, rc, v, x, zKey, zLabel, v3, v4, v5
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath))) == 0 {
|
|
if (*TJsonParse)(unsafe.Pointer(pParse)).FeEdit != 0 && _jsonBlobMakeEditable(tls, pParse, (*TJsonParse)(unsafe.Pointer(pParse)).FnIns) != 0 {
|
|
n = _jsonbPayloadSize(tls, pParse, iRoot, bp)
|
|
**(**Tu32)(__ccgo_up(bp)) = **(**Tu32)(__ccgo_up(bp)) + n
|
|
if libc.Int32FromUint8((*TJsonParse)(unsafe.Pointer(pParse)).FeEdit) == int32(JEDIT_DEL) {
|
|
if iLabel > uint32(0) {
|
|
**(**Tu32)(__ccgo_up(bp)) = **(**Tu32)(__ccgo_up(bp)) + (iRoot - iLabel)
|
|
iRoot = iLabel
|
|
}
|
|
_jsonBlobEdit(tls, pParse, iRoot, **(**Tu32)(__ccgo_up(bp)), uintptr(0), uint32(0))
|
|
} else {
|
|
if libc.Int32FromUint8((*TJsonParse)(unsafe.Pointer(pParse)).FeEdit) == int32(JEDIT_INS) {
|
|
/* Already exists, so json_insert() is a no-op */
|
|
} else {
|
|
if libc.Int32FromUint8((*TJsonParse)(unsafe.Pointer(pParse)).FeEdit) == int32(JEDIT_AINS) {
|
|
/* json_array_insert() */
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath + uintptr(-libc.Int32FromInt32(1))))) != int32(']') {
|
|
return uint32(JSON_LOOKUP_NOTARRAY)
|
|
} else {
|
|
_jsonBlobEdit(tls, pParse, iRoot, uint32(0), (*TJsonParse)(unsafe.Pointer(pParse)).FaIns, (*TJsonParse)(unsafe.Pointer(pParse)).FnIns)
|
|
}
|
|
} else {
|
|
/* json_set() or json_replace() */
|
|
_jsonBlobEdit(tls, pParse, iRoot, **(**Tu32)(__ccgo_up(bp)), (*TJsonParse)(unsafe.Pointer(pParse)).FaIns, (*TJsonParse)(unsafe.Pointer(pParse)).FnIns)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiLabel = iLabel
|
|
return iRoot
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath))) == int32('.') {
|
|
rawKey = int32(1)
|
|
x = **(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(iRoot)))
|
|
zPath = zPath + 1
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath))) == int32('"') {
|
|
zKey = zPath + uintptr(1)
|
|
i = uint32(1)
|
|
for {
|
|
if !(**(**uint8)(__ccgo_up(zPath + uintptr(i))) != 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath + uintptr(i)))) != int32('"')) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath + uintptr(i)))) == int32('\\') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath + uintptr(i+uint32(1))))) != 0 {
|
|
i = i + 1
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
nKey = i - uint32(1)
|
|
if **(**uint8)(__ccgo_up(zPath + uintptr(i))) != 0 {
|
|
i = i + 1
|
|
} else {
|
|
return uint32(JSON_LOOKUP_PATHERROR)
|
|
}
|
|
rawKey = libc.BoolInt32(libc.Xmemchr(tls, zKey, int32('\\'), uint64(nKey)) == uintptr(0))
|
|
} else {
|
|
zKey = zPath
|
|
i = uint32(0)
|
|
for {
|
|
if !(**(**uint8)(__ccgo_up(zPath + uintptr(i))) != 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath + uintptr(i)))) != int32('.') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath + uintptr(i)))) != int32('[')) {
|
|
break
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
nKey = i
|
|
if nKey == uint32(0) {
|
|
return uint32(JSON_LOOKUP_PATHERROR)
|
|
}
|
|
}
|
|
if libc.Int32FromUint8(x)&int32(0x0f) != int32(JSONB_OBJECT) {
|
|
return uint32(JSON_LOOKUP_NOTFOUND)
|
|
}
|
|
n = _jsonbPayloadSize(tls, pParse, iRoot, bp)
|
|
j = iRoot + n /* j is the index of a label */
|
|
iEnd = j + **(**Tu32)(__ccgo_up(bp))
|
|
for j < iEnd {
|
|
x = libc.Uint8FromInt32(libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(j)))) & int32(0x0f))
|
|
if libc.Int32FromUint8(x) < int32(JSONB_TEXT) || libc.Int32FromUint8(x) > int32(JSONB_TEXTRAW) {
|
|
return uint32(JSON_LOOKUP_ERROR)
|
|
}
|
|
n = _jsonbPayloadSize(tls, pParse, j, bp)
|
|
if n == uint32(0) {
|
|
return uint32(JSON_LOOKUP_ERROR)
|
|
}
|
|
k = j + n /* k is the index of the label text */
|
|
if k+**(**Tu32)(__ccgo_up(bp)) >= iEnd {
|
|
return uint32(JSON_LOOKUP_ERROR)
|
|
}
|
|
zLabel = (*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(k)
|
|
rawLabel = libc.BoolInt32(libc.Int32FromUint8(x) == int32(JSONB_TEXT) || libc.Int32FromUint8(x) == int32(JSONB_TEXTRAW))
|
|
if _jsonLabelCompare(tls, zKey, nKey, rawKey, zLabel, **(**Tu32)(__ccgo_up(bp)), rawLabel) != 0 {
|
|
v = k + **(**Tu32)(__ccgo_up(bp)) /* v is the index of the value */
|
|
if libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(v))))&int32(0x0f) > int32(JSONB_OBJECT) {
|
|
return uint32(JSON_LOOKUP_ERROR)
|
|
}
|
|
n = _jsonbPayloadSize(tls, pParse, v, bp)
|
|
if n == uint32(0) || v+n+**(**Tu32)(__ccgo_up(bp)) > iEnd {
|
|
return uint32(JSON_LOOKUP_ERROR)
|
|
}
|
|
v4 = pParse + 44
|
|
*(*Tu16)(unsafe.Pointer(v4)) = *(*Tu16)(unsafe.Pointer(v4)) + 1
|
|
v3 = *(*Tu16)(unsafe.Pointer(v4))
|
|
if libc.Int32FromUint16(v3) >= int32(JSON_MAX_DEPTH) {
|
|
return uint32(JSON_LOOKUP_TOODEEP)
|
|
}
|
|
rc = _jsonLookupStep(tls, pParse, v, zPath+uintptr(i), j)
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiDepth = (*TJsonParse)(unsafe.Pointer(pParse)).FiDepth - 1
|
|
if (*TJsonParse)(unsafe.Pointer(pParse)).Fdelta != 0 {
|
|
_jsonAfterEditSizeAdjust(tls, pParse, iRoot)
|
|
}
|
|
return rc
|
|
}
|
|
j = k + **(**Tu32)(__ccgo_up(bp))
|
|
if libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(j))))&int32(0x0f) > int32(JSONB_OBJECT) {
|
|
return uint32(JSON_LOOKUP_ERROR)
|
|
}
|
|
n = _jsonbPayloadSize(tls, pParse, j, bp)
|
|
if n == uint32(0) {
|
|
return uint32(JSON_LOOKUP_ERROR)
|
|
}
|
|
j = j + (n + **(**Tu32)(__ccgo_up(bp)))
|
|
}
|
|
if j > iEnd {
|
|
return uint32(JSON_LOOKUP_ERROR)
|
|
}
|
|
if libc.Int32FromUint8((*TJsonParse)(unsafe.Pointer(pParse)).FeEdit) >= int32(JEDIT_INS) { /* Header of the label to be inserted */
|
|
if libc.Int32FromUint8((*TJsonParse)(unsafe.Pointer(pParse)).FeEdit) == int32(JEDIT_AINS) && Xsqlite3_strglob(tls, __ccgo_ts+26631, zPath+uintptr(i)) != 0 {
|
|
return uint32(JSON_LOOKUP_NOTARRAY)
|
|
}
|
|
libc.Xmemset(tls, bp+80, 0, uint64(72))
|
|
(**(**TJsonParse)(__ccgo_up(bp + 80))).Fdb = (*TJsonParse)(unsafe.Pointer(pParse)).Fdb
|
|
if rawKey != 0 {
|
|
v5 = int32(JSONB_TEXTRAW)
|
|
} else {
|
|
v5 = int32(JSONB_TEXT5)
|
|
}
|
|
_jsonBlobAppendNode(tls, bp+80, libc.Uint8FromInt32(v5), uint64(nKey), uintptr(0))
|
|
v4 = pParse + 47
|
|
*(*Tu8)(unsafe.Pointer(v4)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v4))) | libc.Int32FromUint8((**(**TJsonParse)(__ccgo_up(bp + 80))).Foom))
|
|
rc = _jsonCreateEditSubstructure(tls, pParse, bp+8, zPath+uintptr(i))
|
|
if !(rc >= libc.Uint32FromUint32(JSON_LOOKUP_PATHERROR)) && _jsonBlobMakeEditable(tls, pParse, (**(**TJsonParse)(__ccgo_up(bp + 80))).FnBlob+nKey+(**(**TJsonParse)(__ccgo_up(bp + 8))).FnBlob) != 0 {
|
|
nIns = (**(**TJsonParse)(__ccgo_up(bp + 80))).FnBlob + nKey + (**(**TJsonParse)(__ccgo_up(bp + 8))).FnBlob
|
|
_jsonBlobEdit(tls, pParse, j, uint32(0), uintptr(0), nIns)
|
|
if !((*TJsonParse)(unsafe.Pointer(pParse)).Foom != 0) {
|
|
/* Because pParse->oom!=0 */
|
|
/* Because pPasre->oom!=0 */
|
|
libc.Xmemcpy(tls, (*TJsonParse)(unsafe.Pointer(pParse)).FaBlob+uintptr(j), (**(**TJsonParse)(__ccgo_up(bp + 80))).FaBlob, uint64((**(**TJsonParse)(__ccgo_up(bp + 80))).FnBlob))
|
|
k = j + (**(**TJsonParse)(__ccgo_up(bp + 80))).FnBlob
|
|
libc.Xmemcpy(tls, (*TJsonParse)(unsafe.Pointer(pParse)).FaBlob+uintptr(k), zKey, uint64(nKey))
|
|
k = k + nKey
|
|
libc.Xmemcpy(tls, (*TJsonParse)(unsafe.Pointer(pParse)).FaBlob+uintptr(k), (**(**TJsonParse)(__ccgo_up(bp + 8))).FaBlob, uint64((**(**TJsonParse)(__ccgo_up(bp + 8))).FnBlob))
|
|
if (*TJsonParse)(unsafe.Pointer(pParse)).Fdelta != 0 {
|
|
_jsonAfterEditSizeAdjust(tls, pParse, iRoot)
|
|
}
|
|
}
|
|
}
|
|
_jsonParseReset(tls, bp+8)
|
|
_jsonParseReset(tls, bp+80)
|
|
return rc
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath))) == int32('[') {
|
|
kk = uint64(0)
|
|
x = libc.Uint8FromInt32(libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(iRoot)))) & int32(0x0f))
|
|
if libc.Int32FromUint8(x) != int32(JSONB_ARRAY) {
|
|
return uint32(JSON_LOOKUP_NOTFOUND)
|
|
}
|
|
n = _jsonbPayloadSize(tls, pParse, iRoot, bp)
|
|
i = uint32(1)
|
|
for libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(zPath + uintptr(i))))])&int32(0x04) != 0 {
|
|
if kk < uint64(0xffffffff) {
|
|
kk = kk*uint64(10) + uint64(**(**uint8)(__ccgo_up(zPath + uintptr(i)))) - uint64('0')
|
|
}
|
|
/* ^^^^^^^^^^--- Allow kk to be bigger than any JSON array so that
|
|
** we get NOTFOUND instead of PATHERROR, without overflowing kk. */
|
|
i = i + 1
|
|
}
|
|
if i < uint32(2) || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath + uintptr(i)))) != int32(']') {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath + 1))) == int32('#') {
|
|
kk = uint64(_jsonbArrayCount(tls, pParse, iRoot))
|
|
i = uint32(2)
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath + 2))) == int32('-') && libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(zPath + 3)))])&int32(0x04) != 0 {
|
|
nn = uint64(0)
|
|
i = uint32(3)
|
|
for cond := true; cond; cond = libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(zPath + uintptr(i))))])&int32(0x04) != 0 {
|
|
if nn < uint64(0xffffffff) {
|
|
nn = nn*uint64(10) + uint64(**(**uint8)(__ccgo_up(zPath + uintptr(i)))) - uint64('0')
|
|
}
|
|
/* ^^^^^^^^^^--- Allow nn to be bigger than any JSON array to
|
|
** get NOTFOUND instead of PATHERROR, without overflowing nn. */
|
|
i = i + 1
|
|
}
|
|
if nn > kk {
|
|
return uint32(JSON_LOOKUP_NOTFOUND)
|
|
}
|
|
kk = kk - nn
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath + uintptr(i)))) != int32(']') {
|
|
return uint32(JSON_LOOKUP_PATHERROR)
|
|
}
|
|
} else {
|
|
return uint32(JSON_LOOKUP_PATHERROR)
|
|
}
|
|
}
|
|
j = iRoot + n
|
|
iEnd = j + **(**Tu32)(__ccgo_up(bp))
|
|
for j < iEnd {
|
|
if kk == uint64(0) {
|
|
v4 = pParse + 44
|
|
*(*Tu16)(unsafe.Pointer(v4)) = *(*Tu16)(unsafe.Pointer(v4)) + 1
|
|
v3 = *(*Tu16)(unsafe.Pointer(v4))
|
|
if libc.Int32FromUint16(v3) >= int32(JSON_MAX_DEPTH) {
|
|
return uint32(JSON_LOOKUP_TOODEEP)
|
|
}
|
|
rc = _jsonLookupStep(tls, pParse, j, zPath+uintptr(i+uint32(1)), uint32(0))
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiDepth = (*TJsonParse)(unsafe.Pointer(pParse)).FiDepth - 1
|
|
if (*TJsonParse)(unsafe.Pointer(pParse)).Fdelta != 0 {
|
|
_jsonAfterEditSizeAdjust(tls, pParse, iRoot)
|
|
}
|
|
return rc
|
|
}
|
|
kk = kk - 1
|
|
n = _jsonbPayloadSize(tls, pParse, j, bp)
|
|
if n == uint32(0) {
|
|
return uint32(JSON_LOOKUP_ERROR)
|
|
}
|
|
j = j + (n + **(**Tu32)(__ccgo_up(bp)))
|
|
}
|
|
if j > iEnd {
|
|
return uint32(JSON_LOOKUP_ERROR)
|
|
}
|
|
if kk > uint64(0) {
|
|
return uint32(JSON_LOOKUP_NOTFOUND)
|
|
}
|
|
if libc.Int32FromUint8((*TJsonParse)(unsafe.Pointer(pParse)).FeEdit) >= int32(JEDIT_INS) {
|
|
rc = _jsonCreateEditSubstructure(tls, pParse, bp+152, zPath+uintptr(i+uint32(1)))
|
|
if !(rc >= libc.Uint32FromUint32(JSON_LOOKUP_PATHERROR)) && _jsonBlobMakeEditable(tls, pParse, (**(**TJsonParse)(__ccgo_up(bp + 152))).FnBlob) != 0 {
|
|
_jsonBlobEdit(tls, pParse, j, uint32(0), (**(**TJsonParse)(__ccgo_up(bp + 152))).FaBlob, (**(**TJsonParse)(__ccgo_up(bp + 152))).FnBlob)
|
|
}
|
|
_jsonParseReset(tls, bp+152)
|
|
if (*TJsonParse)(unsafe.Pointer(pParse)).Fdelta != 0 {
|
|
_jsonAfterEditSizeAdjust(tls, pParse, iRoot)
|
|
}
|
|
return rc
|
|
}
|
|
} else {
|
|
return uint32(JSON_LOOKUP_PATHERROR)
|
|
}
|
|
}
|
|
return uint32(JSON_LOOKUP_NOTFOUND)
|
|
}
|
|
|
|
func _jsonObjectCompute(tls *libc.TLS, ctx uintptr, isFinal int32) {
|
|
bp := tls.Alloc(144)
|
|
defer tls.Free(144)
|
|
var c uint8
|
|
var flags, inStr int32
|
|
var i, j, v2, v3 Tu64
|
|
var pOgStr, pStr uintptr
|
|
var v8 Tsqlite3_destructor_type
|
|
var _ /* tmpStr at bp+0 */ TJsonString
|
|
_, _, _, _, _, _, _, _, _, _ = c, flags, i, inStr, j, pOgStr, pStr, v2, v3, v8
|
|
flags = int32(int64(Xsqlite3_user_data(tls, ctx)))
|
|
pStr = Xsqlite3_aggregate_context(tls, ctx, 0)
|
|
if pStr != 0 {
|
|
pOgStr = pStr
|
|
_jsonAppendRawNZ(tls, pOgStr, __ccgo_ts+26881, uint32(2)) /* Ensure it is zero-terminated */
|
|
_jsonStringTrimOneChar(tls, pOgStr) /* Remove the zero terminator */
|
|
(*TJsonString)(unsafe.Pointer(pStr)).FpCtx = ctx
|
|
if (*TJsonString)(unsafe.Pointer(pStr)).FeErr != 0 {
|
|
_jsonReturnString(tls, pStr, uintptr(0), uintptr(0))
|
|
return
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(pStr)).FzBuf))) != int32('{') {
|
|
inStr = 0
|
|
if !(isFinal != 0) {
|
|
/* Work with a temporary copy of the string if this is not the
|
|
** final result */
|
|
_jsonStringInit(tls, bp, ctx)
|
|
_jsonAppendRawNZ(tls, bp, (*TJsonString)(unsafe.Pointer(pStr)).FzBuf, uint32((*TJsonString)(unsafe.Pointer(pStr)).FnUsed+uint64(1)))
|
|
pStr = bp
|
|
if (*TJsonString)(unsafe.Pointer(pStr)).FeErr != 0 {
|
|
_jsonReturnString(tls, pStr, uintptr(0), uintptr(0))
|
|
return
|
|
}
|
|
_jsonStringTrimOneChar(tls, pStr) /* Remove zero terminator */
|
|
}
|
|
/* Fix up the string by changing the initial "@" flag back to
|
|
** to "{" and removing all subsequence "@" entries, with their
|
|
** associated comma delimeters. */
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(pStr)).FzBuf)) = uint8('{')
|
|
v2 = libc.Uint64FromInt32(1)
|
|
j = v2
|
|
i = v2
|
|
for {
|
|
if !(i < (*TJsonString)(unsafe.Pointer(pStr)).FnUsed) {
|
|
break
|
|
}
|
|
c = **(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(pStr)).FzBuf + uintptr(i)))
|
|
if libc.Int32FromUint8(c) == int32('"') {
|
|
inStr = libc.BoolInt32(!(inStr != 0))
|
|
v2 = j
|
|
j = j + 1
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(pStr)).FzBuf + uintptr(v2))) = uint8('"')
|
|
} else {
|
|
if libc.Int32FromUint8(c) == int32('\\') {
|
|
v2 = j
|
|
j = j + 1
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(pStr)).FzBuf + uintptr(v2))) = uint8('\\')
|
|
v2 = j
|
|
j = j + 1
|
|
i = i + 1
|
|
v3 = i
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(pStr)).FzBuf + uintptr(v2))) = **(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(pStr)).FzBuf + uintptr(v3)))
|
|
} else {
|
|
if libc.Int32FromUint8(c) == int32('@') && !(inStr != 0) {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(pStr)).FzBuf + uintptr(i+uint64(1))))) == int32(',') {
|
|
i = i + 1
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(pStr)).FzBuf + uintptr(j-uint64(1))))) == int32(',') {
|
|
j = j - 1
|
|
}
|
|
}
|
|
} else {
|
|
v2 = j
|
|
j = j + 1
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(pStr)).FzBuf + uintptr(v2))) = c
|
|
}
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(pStr)).FzBuf + uintptr(j))) = uint8(0) /* Restore zero terminator */
|
|
(*TJsonString)(unsafe.Pointer(pStr)).FnUsed = j /* Truncate the string */
|
|
}
|
|
if flags&int32(JSON_BLOB) != 0 {
|
|
_jsonReturnStringAsBlob(tls, pStr)
|
|
if isFinal != 0 {
|
|
if !((*TJsonString)(unsafe.Pointer(pStr)).FbStatic != 0) {
|
|
_sqlite3RCStrUnref(tls, (*TJsonString)(unsafe.Pointer(pStr)).FzBuf)
|
|
}
|
|
} else {
|
|
_jsonStringTrimOneChar(tls, pOgStr)
|
|
}
|
|
} else {
|
|
if isFinal != 0 {
|
|
if (*TJsonString)(unsafe.Pointer(pStr)).FbStatic != 0 {
|
|
v8 = uintptr(-libc.Int32FromInt32(1))
|
|
} else {
|
|
v8 = __ccgo_fp(_sqlite3RCStrUnref)
|
|
}
|
|
Xsqlite3_result_text(tls, ctx, (*TJsonString)(unsafe.Pointer(pStr)).FzBuf, libc.Int32FromUint64((*TJsonString)(unsafe.Pointer(pStr)).FnUsed), v8)
|
|
(*TJsonString)(unsafe.Pointer(pStr)).FbStatic = uint8(1)
|
|
} else {
|
|
Xsqlite3_result_text(tls, ctx, (*TJsonString)(unsafe.Pointer(pStr)).FzBuf, libc.Int32FromUint64((*TJsonString)(unsafe.Pointer(pStr)).FnUsed), uintptr(-libc.Int32FromInt32(1)))
|
|
_jsonStringTrimOneChar(tls, pOgStr)
|
|
}
|
|
}
|
|
if pStr != pOgStr {
|
|
_jsonStringReset(tls, pStr)
|
|
}
|
|
} else {
|
|
if flags&int32(JSON_BLOB) != 0 {
|
|
Xsqlite3_result_blob(tls, ctx, uintptr(unsafe.Pointer(&_emptyObject1)), int32(1), libc.UintptrFromInt32(0))
|
|
} else {
|
|
Xsqlite3_result_text(tls, ctx, __ccgo_ts+26883, int32(2), libc.UintptrFromInt32(0))
|
|
}
|
|
}
|
|
Xsqlite3_result_subtype(tls, ctx, uint32(JSON_SUBTYPE))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of the json_object(NAME,VALUE,...) function. Return a JSON
|
|
// ** object that contains all name/value given in arguments. Or if any name
|
|
// ** is not a string or if any value is a BLOB, throw an error.
|
|
// */
|
|
func _jsonObjectFunc(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
|
|
bp := tls.Alloc(144)
|
|
defer tls.Free(144)
|
|
var i int32
|
|
var n Tu32
|
|
var z uintptr
|
|
var _ /* jx at bp+0 */ TJsonString
|
|
_, _, _ = i, n, z
|
|
if argc&int32(1) != 0 {
|
|
Xsqlite3_result_error(tls, ctx, __ccgo_ts+26707, -int32(1))
|
|
return
|
|
}
|
|
_jsonStringInit(tls, bp, ctx)
|
|
_jsonAppendChar(tls, bp, uint8('{'))
|
|
i = 0
|
|
for {
|
|
if !(i < argc) {
|
|
break
|
|
}
|
|
if Xsqlite3_value_type(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8))) != int32(SQLITE_TEXT) {
|
|
Xsqlite3_result_error(tls, ctx, __ccgo_ts+26758, -int32(1))
|
|
_jsonStringReset(tls, bp)
|
|
return
|
|
}
|
|
_jsonAppendSeparator(tls, bp)
|
|
z = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8)))
|
|
n = libc.Uint32FromInt32(Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8))))
|
|
_jsonAppendString(tls, bp, z, n)
|
|
_jsonAppendChar(tls, bp, uint8(':'))
|
|
_jsonAppendSqlValue(tls, bp, **(**uintptr)(__ccgo_up(argv + uintptr(i+int32(1))*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + int32(2)
|
|
}
|
|
_jsonAppendChar(tls, bp, uint8('}'))
|
|
_jsonReturnString(tls, bp, uintptr(0), uintptr(0))
|
|
Xsqlite3_result_subtype(tls, ctx, uint32(JSON_SUBTYPE))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** json_group_obj(NAME,VALUE)
|
|
// **
|
|
// ** Return a JSON object composed of all names and values in the aggregate.
|
|
// **
|
|
// ** Rows for which NAME is NULL do not result in a new entry. However, we
|
|
// ** do initially insert a "@" entry into the growing string for each null entry
|
|
// ** and change the first character of the string to "@" to signal that the
|
|
// ** string contains null entries. The "@" markers are needed in order to
|
|
// ** correctly process xInverse() requests. The initial "@" is converted
|
|
// ** back into "{" and the "@" null values are removed by jsonObjectCompute().
|
|
// */
|
|
func _jsonObjectStep(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
|
|
var n Tu32
|
|
var pStr, z uintptr
|
|
_, _, _ = n, pStr, z
|
|
_ = argc
|
|
pStr = Xsqlite3_aggregate_context(tls, ctx, int32(136))
|
|
if pStr != 0 {
|
|
z = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
n = libc.Uint32FromInt32(_sqlite3Strlen30(tls, z))
|
|
if (*TJsonString)(unsafe.Pointer(pStr)).FzBuf == uintptr(0) {
|
|
_jsonStringInit(tls, pStr, ctx)
|
|
_jsonAppendChar(tls, pStr, uint8('{'))
|
|
} else {
|
|
if (*TJsonString)(unsafe.Pointer(pStr)).FnUsed > uint64(1) {
|
|
_jsonAppendChar(tls, pStr, uint8(','))
|
|
}
|
|
}
|
|
(*TJsonString)(unsafe.Pointer(pStr)).FpCtx = ctx
|
|
if z != uintptr(0) {
|
|
_jsonAppendString(tls, pStr, z, n)
|
|
_jsonAppendChar(tls, pStr, uint8(':'))
|
|
_jsonAppendSqlValue(tls, pStr, **(**uintptr)(__ccgo_up(argv + 1*8)))
|
|
} else {
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(pStr)).FzBuf)) = uint8('@')
|
|
_jsonAppendRawNZ(tls, pStr, __ccgo_ts+26696, uint32(1))
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Generate a JsonParse object, containing valid JSONB in aBlob and nBlob,
|
|
// ** from the SQL function argument pArg. Return a pointer to the new
|
|
// ** JsonParse object.
|
|
// **
|
|
// ** Ownership of the new JsonParse object is passed to the caller. The
|
|
// ** caller should invoke jsonParseFree() on the return value when it
|
|
// ** has finished using it.
|
|
// **
|
|
// ** If any errors are detected, an appropriate error messages is set
|
|
// ** using sqlite3_result_error() or the equivalent and this routine
|
|
// ** returns NULL. This routine also returns NULL if the pArg argument
|
|
// ** is an SQL NULL value, but no error message is set in that case. This
|
|
// ** is so that SQL functions that are given NULL arguments will return
|
|
// ** a NULL value.
|
|
// */
|
|
func _jsonParseFuncArg(tls *libc.TLS, ctx uintptr, pArg uintptr, flgs Tu32) (r uintptr) {
|
|
var db, p, pFromCache, zNew, v2 uintptr
|
|
var eType, isRCStr, rc int32
|
|
var nBlob, v1 Tu32
|
|
_, _, _, _, _, _, _, _, _, _ = db, eType, isRCStr, nBlob, p, pFromCache, rc, zNew, v1, v2 /* Datatype of pArg */
|
|
p = uintptr(0) /* Value to be returned */
|
|
pFromCache = uintptr(0) /* The database connection */
|
|
eType = Xsqlite3_value_type(tls, pArg)
|
|
if eType == int32(SQLITE_NULL) {
|
|
return uintptr(0)
|
|
}
|
|
pFromCache = _jsonCacheSearch(tls, ctx, pArg)
|
|
if pFromCache != 0 {
|
|
(*TJsonParse)(unsafe.Pointer(pFromCache)).FnJPRef = (*TJsonParse)(unsafe.Pointer(pFromCache)).FnJPRef + 1
|
|
if flgs&uint32(JSON_EDITABLE) == uint32(0) {
|
|
return pFromCache
|
|
}
|
|
}
|
|
db = Xsqlite3_context_db_handle(tls, ctx)
|
|
goto rebuild_from_cache
|
|
rebuild_from_cache:
|
|
;
|
|
p = _sqlite3DbMallocZero(tls, db, uint64(72))
|
|
if p == uintptr(0) {
|
|
goto json_pfa_oom
|
|
}
|
|
libc.Xmemset(tls, p, 0, uint64(72))
|
|
(*TJsonParse)(unsafe.Pointer(p)).Fdb = db
|
|
(*TJsonParse)(unsafe.Pointer(p)).FnJPRef = uint32(1)
|
|
if pFromCache != uintptr(0) {
|
|
nBlob = (*TJsonParse)(unsafe.Pointer(pFromCache)).FnBlob
|
|
(*TJsonParse)(unsafe.Pointer(p)).FaBlob = _sqlite3DbMallocRaw(tls, db, uint64(nBlob))
|
|
if (*TJsonParse)(unsafe.Pointer(p)).FaBlob == uintptr(0) {
|
|
goto json_pfa_oom
|
|
}
|
|
libc.Xmemcpy(tls, (*TJsonParse)(unsafe.Pointer(p)).FaBlob, (*TJsonParse)(unsafe.Pointer(pFromCache)).FaBlob, uint64(nBlob))
|
|
v1 = nBlob
|
|
(*TJsonParse)(unsafe.Pointer(p)).FnBlob = v1
|
|
(*TJsonParse)(unsafe.Pointer(p)).FnBlobAlloc = v1
|
|
(*TJsonParse)(unsafe.Pointer(p)).FhasNonstd = (*TJsonParse)(unsafe.Pointer(pFromCache)).FhasNonstd
|
|
_jsonParseFree(tls, pFromCache)
|
|
return p
|
|
}
|
|
if eType == int32(SQLITE_BLOB) {
|
|
if _jsonArgIsJsonb(tls, pArg, p) != 0 {
|
|
if flgs&uint32(JSON_EDITABLE) != uint32(0) && _jsonBlobMakeEditable(tls, p, uint32(0)) == 0 {
|
|
goto json_pfa_oom
|
|
}
|
|
return p
|
|
}
|
|
/* If the blob is not valid JSONB, fall through into trying to cast
|
|
** the blob into text which is then interpreted as JSON. (tag-20240123-a)
|
|
**
|
|
** This goes against all historical documentation about how the SQLite
|
|
** JSON functions were suppose to work. From the beginning, blob was
|
|
** reserved for expansion and a blob value should have raised an error.
|
|
** But it did not, due to a bug. And many applications came to depend
|
|
** upon this buggy behavior, especially when using the CLI and reading
|
|
** JSON text using readfile(), which returns a blob. For this reason
|
|
** we will continue to support the bug moving forward.
|
|
** See for example https://sqlite.org/forum/forumpost/012136abd5292b8d
|
|
*/
|
|
}
|
|
(*TJsonParse)(unsafe.Pointer(p)).FzJson = Xsqlite3_value_text(tls, pArg)
|
|
(*TJsonParse)(unsafe.Pointer(p)).FnJson = Xsqlite3_value_bytes(tls, pArg)
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
|
|
goto json_pfa_oom
|
|
}
|
|
if (*TJsonParse)(unsafe.Pointer(p)).FnJson == 0 {
|
|
goto json_pfa_malformed
|
|
}
|
|
if flgs&uint32(JSON_KEEPERROR) != 0 {
|
|
v2 = uintptr(0)
|
|
} else {
|
|
v2 = ctx
|
|
}
|
|
if _jsonConvertTextToBlob(tls, p, v2) != 0 {
|
|
if flgs&uint32(JSON_KEEPERROR) != 0 {
|
|
(*TJsonParse)(unsafe.Pointer(p)).FnErr = uint8(1)
|
|
return p
|
|
} else {
|
|
_jsonParseFree(tls, p)
|
|
return uintptr(0)
|
|
}
|
|
} else {
|
|
isRCStr = _sqlite3ValueIsOfClass(tls, pArg, __ccgo_fp(_sqlite3RCStrUnref))
|
|
if !(isRCStr != 0) {
|
|
zNew = _sqlite3RCStrNew(tls, libc.Uint64FromInt32((*TJsonParse)(unsafe.Pointer(p)).FnJson))
|
|
if zNew == uintptr(0) {
|
|
goto json_pfa_oom
|
|
}
|
|
libc.Xmemcpy(tls, zNew, (*TJsonParse)(unsafe.Pointer(p)).FzJson, libc.Uint64FromInt32((*TJsonParse)(unsafe.Pointer(p)).FnJson))
|
|
(*TJsonParse)(unsafe.Pointer(p)).FzJson = zNew
|
|
**(**uint8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(p)).FzJson + uintptr((*TJsonParse)(unsafe.Pointer(p)).FnJson))) = uint8(0)
|
|
} else {
|
|
_sqlite3RCStrRef(tls, (*TJsonParse)(unsafe.Pointer(p)).FzJson)
|
|
}
|
|
(*TJsonParse)(unsafe.Pointer(p)).FbJsonIsRCStr = uint8(1)
|
|
rc = _jsonCacheInsert(tls, ctx, p)
|
|
if rc == int32(SQLITE_NOMEM) {
|
|
goto json_pfa_oom
|
|
}
|
|
if flgs&uint32(JSON_EDITABLE) != 0 {
|
|
pFromCache = p
|
|
p = uintptr(0)
|
|
goto rebuild_from_cache
|
|
}
|
|
}
|
|
return p
|
|
goto json_pfa_malformed
|
|
json_pfa_malformed:
|
|
;
|
|
if flgs&uint32(JSON_KEEPERROR) != 0 {
|
|
(*TJsonParse)(unsafe.Pointer(p)).FnErr = uint8(1)
|
|
return p
|
|
} else {
|
|
_jsonParseFree(tls, p)
|
|
Xsqlite3_result_error(tls, ctx, __ccgo_ts+26486, -int32(1))
|
|
return uintptr(0)
|
|
}
|
|
goto json_pfa_oom
|
|
json_pfa_oom:
|
|
;
|
|
_jsonParseFree(tls, pFromCache)
|
|
_jsonParseFree(tls, p)
|
|
Xsqlite3_result_error_nomem(tls, ctx)
|
|
return uintptr(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the value of the BLOB node at index i.
|
|
// **
|
|
// ** If the value is a primitive, return it as an SQL value.
|
|
// ** If the value is an array or object, return it as either
|
|
// ** JSON text or the BLOB encoding, depending on the eMode flag
|
|
// ** as follows:
|
|
// **
|
|
// ** eMode==0 JSONB if the JSON_B flag is set in userdata or
|
|
// ** text if the JSON_B flag is omitted from userdata.
|
|
// **
|
|
// ** eMode==1 Text
|
|
// **
|
|
// ** eMode==2 JSONB
|
|
// */
|
|
func _jsonReturnFromBlob(tls *libc.TLS, pParse uintptr, i Tu32, pCtx uintptr, eMode int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var bNeg, rc int32
|
|
var c, x uint8
|
|
var db, z, z1, z2, zOut uintptr
|
|
var iIn, iOut, n, nOut, szEscape, v19, v20 Tu32
|
|
var r, v16 float64
|
|
var v17 int64
|
|
var _ /* iRes at bp+8 */ Tsqlite3_int64
|
|
var _ /* r at bp+16 */ float64
|
|
var _ /* sz at bp+0 */ Tu32
|
|
var _ /* v at bp+24 */ Tu32
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = bNeg, c, db, iIn, iOut, n, nOut, r, rc, szEscape, x, z, z1, z2, zOut, v16, v17, v19, v20
|
|
db = Xsqlite3_context_db_handle(tls, pCtx)
|
|
n = _jsonbPayloadSize(tls, pParse, i, bp)
|
|
if n == uint32(0) {
|
|
Xsqlite3_result_error(tls, pCtx, __ccgo_ts+26486, -int32(1))
|
|
return
|
|
}
|
|
switch libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(i)))) & libc.Int32FromInt32(0x0f) {
|
|
case JSONB_NULL:
|
|
goto _1
|
|
case int32(JSONB_TRUE):
|
|
goto _2
|
|
case int32(JSONB_FALSE):
|
|
goto _3
|
|
case int32(JSONB_INT):
|
|
goto _4
|
|
case int32(JSONB_INT5):
|
|
goto _5
|
|
case int32(JSONB_FLOAT):
|
|
goto _6
|
|
case int32(JSONB_FLOAT5):
|
|
goto _7
|
|
case int32(JSONB_TEXT):
|
|
goto _8
|
|
case int32(JSONB_TEXTRAW):
|
|
goto _9
|
|
case int32(JSONB_TEXTJ):
|
|
goto _10
|
|
case int32(JSONB_TEXT5):
|
|
goto _11
|
|
case int32(JSONB_OBJECT):
|
|
goto _12
|
|
case int32(JSONB_ARRAY):
|
|
goto _13
|
|
default:
|
|
goto _14
|
|
}
|
|
goto _15
|
|
_1:
|
|
;
|
|
if **(**Tu32)(__ccgo_up(bp)) != 0 {
|
|
goto returnfromblob_malformed
|
|
}
|
|
Xsqlite3_result_null(tls, pCtx)
|
|
goto _15
|
|
_2:
|
|
;
|
|
if **(**Tu32)(__ccgo_up(bp)) != 0 {
|
|
goto returnfromblob_malformed
|
|
}
|
|
Xsqlite3_result_int(tls, pCtx, int32(1))
|
|
goto _15
|
|
_3:
|
|
;
|
|
if **(**Tu32)(__ccgo_up(bp)) != 0 {
|
|
goto returnfromblob_malformed
|
|
}
|
|
Xsqlite3_result_int(tls, pCtx, 0)
|
|
goto _15
|
|
_5:
|
|
;
|
|
_4:
|
|
;
|
|
**(**Tsqlite3_int64)(__ccgo_up(bp + 8)) = 0
|
|
bNeg = 0
|
|
if **(**Tu32)(__ccgo_up(bp)) == uint32(0) {
|
|
goto returnfromblob_malformed
|
|
}
|
|
x = uint8(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(i+n))))
|
|
if libc.Int32FromUint8(x) == int32('-') {
|
|
if **(**Tu32)(__ccgo_up(bp)) < uint32(2) {
|
|
goto returnfromblob_malformed
|
|
}
|
|
n = n + 1
|
|
**(**Tu32)(__ccgo_up(bp)) = **(**Tu32)(__ccgo_up(bp)) - 1
|
|
bNeg = int32(1)
|
|
}
|
|
z = _sqlite3DbStrNDup(tls, db, (*TJsonParse)(unsafe.Pointer(pParse)).FaBlob+uintptr(i+n), libc.Uint64FromInt32(libc.Int32FromUint32(**(**Tu32)(__ccgo_up(bp)))))
|
|
if z == uintptr(0) {
|
|
goto returnfromblob_oom
|
|
}
|
|
rc = _sqlite3DecOrHexToI64(tls, z, bp+8)
|
|
_sqlite3DbFree(tls, db, z)
|
|
if rc == 0 {
|
|
if **(**Tsqlite3_int64)(__ccgo_up(bp + 8)) < 0 {
|
|
r = float64(**(**Tsqlite3_uint64)(__ccgo_up(bp + 8)))
|
|
if bNeg != 0 {
|
|
v16 = -r
|
|
} else {
|
|
v16 = r
|
|
}
|
|
Xsqlite3_result_double(tls, pCtx, v16)
|
|
} else {
|
|
if bNeg != 0 {
|
|
v17 = -**(**Tsqlite3_int64)(__ccgo_up(bp + 8))
|
|
} else {
|
|
v17 = **(**Tsqlite3_int64)(__ccgo_up(bp + 8))
|
|
}
|
|
Xsqlite3_result_int64(tls, pCtx, v17)
|
|
}
|
|
} else {
|
|
if rc == int32(3) && bNeg != 0 {
|
|
Xsqlite3_result_int64(tls, pCtx, int64(-libc.Int32FromInt32(1))-(libc.Int64FromUint32(0xffffffff)|libc.Int64FromInt32(0x7fffffff)<<libc.Int32FromInt32(32)))
|
|
} else {
|
|
if rc == int32(1) {
|
|
goto returnfromblob_malformed
|
|
} else {
|
|
if bNeg != 0 {
|
|
n = n - 1
|
|
**(**Tu32)(__ccgo_up(bp)) = **(**Tu32)(__ccgo_up(bp)) + 1
|
|
}
|
|
goto to_double
|
|
}
|
|
}
|
|
}
|
|
goto _15
|
|
_7:
|
|
;
|
|
_6:
|
|
;
|
|
if **(**Tu32)(__ccgo_up(bp)) == uint32(0) {
|
|
goto returnfromblob_malformed
|
|
}
|
|
goto to_double
|
|
to_double:
|
|
;
|
|
z1 = _sqlite3DbStrNDup(tls, db, (*TJsonParse)(unsafe.Pointer(pParse)).FaBlob+uintptr(i+n), libc.Uint64FromInt32(libc.Int32FromUint32(**(**Tu32)(__ccgo_up(bp)))))
|
|
if z1 == uintptr(0) {
|
|
goto returnfromblob_oom
|
|
}
|
|
rc = _sqlite3AtoF(tls, z1, bp+16)
|
|
_sqlite3DbFree(tls, db, z1)
|
|
if rc <= 0 {
|
|
goto returnfromblob_malformed
|
|
}
|
|
Xsqlite3_result_double(tls, pCtx, **(**float64)(__ccgo_up(bp + 16)))
|
|
goto _15
|
|
_9:
|
|
;
|
|
_8:
|
|
;
|
|
Xsqlite3_result_text(tls, pCtx, (*TJsonParse)(unsafe.Pointer(pParse)).FaBlob+uintptr(i+n), libc.Int32FromUint32(**(**Tu32)(__ccgo_up(bp))), uintptr(-libc.Int32FromInt32(1)))
|
|
goto _15
|
|
_11:
|
|
;
|
|
_10:
|
|
;
|
|
nOut = **(**Tu32)(__ccgo_up(bp))
|
|
z2 = (*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(i+n)
|
|
zOut = _sqlite3DbMallocRaw(tls, db, uint64(nOut)+uint64(1))
|
|
if zOut == uintptr(0) {
|
|
goto returnfromblob_oom
|
|
}
|
|
v19 = libc.Uint32FromInt32(0)
|
|
iOut = v19
|
|
iIn = v19
|
|
for {
|
|
if !(iIn < **(**Tu32)(__ccgo_up(bp))) {
|
|
break
|
|
}
|
|
c = **(**uint8)(__ccgo_up(z2 + uintptr(iIn)))
|
|
if libc.Int32FromUint8(c) == int32('\\') {
|
|
szEscape = _jsonUnescapeOneChar(tls, z2+uintptr(iIn), **(**Tu32)(__ccgo_up(bp))-iIn, bp+24)
|
|
if **(**Tu32)(__ccgo_up(bp + 24)) <= uint32(0x7f) {
|
|
v20 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zOut + uintptr(v20))) = uint8(**(**Tu32)(__ccgo_up(bp + 24)))
|
|
} else {
|
|
if **(**Tu32)(__ccgo_up(bp + 24)) <= uint32(0x7ff) {
|
|
v19 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zOut + uintptr(v19))) = uint8(libc.Uint32FromInt32(0xc0) | **(**Tu32)(__ccgo_up(bp + 24))>>libc.Int32FromInt32(6))
|
|
v19 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zOut + uintptr(v19))) = uint8(uint32(0x80) | **(**Tu32)(__ccgo_up(bp + 24))&uint32(0x3f))
|
|
} else {
|
|
if **(**Tu32)(__ccgo_up(bp + 24)) < uint32(0x10000) {
|
|
v19 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zOut + uintptr(v19))) = uint8(uint32(0xe0) | **(**Tu32)(__ccgo_up(bp + 24))>>libc.Int32FromInt32(12))
|
|
v19 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zOut + uintptr(v19))) = uint8(uint32(0x80) | **(**Tu32)(__ccgo_up(bp + 24))>>libc.Int32FromInt32(6)&uint32(0x3f))
|
|
v19 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zOut + uintptr(v19))) = uint8(uint32(0x80) | **(**Tu32)(__ccgo_up(bp + 24))&uint32(0x3f))
|
|
} else {
|
|
if **(**Tu32)(__ccgo_up(bp + 24)) == uint32(JSON_INVALID_CHAR) {
|
|
/* Silently ignore illegal unicode */
|
|
} else {
|
|
v19 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zOut + uintptr(v19))) = uint8(uint32(0xf0) | **(**Tu32)(__ccgo_up(bp + 24))>>libc.Int32FromInt32(18))
|
|
v19 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zOut + uintptr(v19))) = uint8(uint32(0x80) | **(**Tu32)(__ccgo_up(bp + 24))>>libc.Int32FromInt32(12)&uint32(0x3f))
|
|
v19 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zOut + uintptr(v19))) = uint8(uint32(0x80) | **(**Tu32)(__ccgo_up(bp + 24))>>libc.Int32FromInt32(6)&uint32(0x3f))
|
|
v19 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zOut + uintptr(v19))) = uint8(uint32(0x80) | **(**Tu32)(__ccgo_up(bp + 24))&uint32(0x3f))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
iIn = iIn + (szEscape - uint32(1))
|
|
} else {
|
|
v19 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zOut + uintptr(v19))) = c
|
|
}
|
|
goto _18
|
|
_18:
|
|
;
|
|
iIn = iIn + 1
|
|
} /* end for() */
|
|
**(**uint8)(__ccgo_up(zOut + uintptr(iOut))) = uint8(0)
|
|
Xsqlite3_result_text(tls, pCtx, zOut, libc.Int32FromUint32(iOut), __ccgo_fp(_sqlite3RowSetClear))
|
|
goto _15
|
|
_13:
|
|
;
|
|
_12:
|
|
;
|
|
if eMode == 0 {
|
|
if int32(int64(Xsqlite3_user_data(tls, pCtx)))&int32(JSON_BLOB) != 0 {
|
|
eMode = int32(2)
|
|
} else {
|
|
eMode = int32(1)
|
|
}
|
|
}
|
|
if eMode == int32(2) {
|
|
Xsqlite3_result_blob(tls, pCtx, (*TJsonParse)(unsafe.Pointer(pParse)).FaBlob+uintptr(i), libc.Int32FromUint32(**(**Tu32)(__ccgo_up(bp))+n), uintptr(-libc.Int32FromInt32(1)))
|
|
} else {
|
|
_jsonReturnTextJsonFromBlob(tls, pCtx, (*TJsonParse)(unsafe.Pointer(pParse)).FaBlob+uintptr(i), **(**Tu32)(__ccgo_up(bp))+n)
|
|
}
|
|
goto _15
|
|
_14:
|
|
;
|
|
goto returnfromblob_malformed
|
|
_15:
|
|
;
|
|
return
|
|
goto returnfromblob_oom
|
|
returnfromblob_oom:
|
|
;
|
|
Xsqlite3_result_error_nomem(tls, pCtx)
|
|
return
|
|
goto returnfromblob_malformed
|
|
returnfromblob_malformed:
|
|
;
|
|
Xsqlite3_result_error(tls, pCtx, __ccgo_ts+26486, -int32(1))
|
|
return
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Translate the binary JSONB representation of JSON beginning at
|
|
// ** pParse->aBlob[i] into a JSON text string. Append the JSON
|
|
// ** text onto the end of pOut. Return the index in pParse->aBlob[]
|
|
// ** of the first byte past the end of the element that is translated.
|
|
// **
|
|
// ** This is a variant of jsonTranslateBlobToText() that "pretty-prints"
|
|
// ** the output. Extra whitespace is inserted to make the JSON easier
|
|
// ** for humans to read.
|
|
// **
|
|
// ** If an error is detected in the BLOB input, the pOut->eErr flag
|
|
// ** might get set to JSTRING_MALFORMED. But not all BLOB input errors
|
|
// ** are detected. So a malformed JSONB input might either result
|
|
// ** in an error, or in incorrect JSON.
|
|
// **
|
|
// ** The pOut->eErr JSTRING_OOM flag is set on a OOM.
|
|
// */
|
|
func _jsonTranslateBlobToPrettyText(tls *libc.TLS, pPretty uintptr, i Tu32) (r Tu32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var iEnd, j, n Tu32
|
|
var pOut, pParse, v1 uintptr
|
|
var _ /* sz at bp+0 */ Tu32
|
|
_, _, _, _, _, _ = iEnd, j, n, pOut, pParse, v1
|
|
pParse = (*TJsonPretty)(unsafe.Pointer(pPretty)).FpParse
|
|
pOut = (*TJsonPretty)(unsafe.Pointer(pPretty)).FpOut
|
|
n = _jsonbPayloadSize(tls, pParse, i, bp)
|
|
if n == uint32(0) {
|
|
v1 = pOut + 33
|
|
*(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) | libc.Int32FromInt32(JSTRING_MALFORMED))
|
|
return (*TJsonParse)(unsafe.Pointer(pParse)).FnBlob + uint32(1)
|
|
}
|
|
switch libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(i)))) & libc.Int32FromInt32(0x0f) {
|
|
case int32(JSONB_ARRAY):
|
|
j = i + n
|
|
iEnd = j + **(**Tu32)(__ccgo_up(bp))
|
|
_jsonAppendChar(tls, pOut, uint8('['))
|
|
if j < iEnd {
|
|
_jsonAppendChar(tls, pOut, uint8('\n'))
|
|
(*TJsonPretty)(unsafe.Pointer(pPretty)).FnIndent = (*TJsonPretty)(unsafe.Pointer(pPretty)).FnIndent + 1
|
|
if (*TJsonPretty)(unsafe.Pointer(pPretty)).FnIndent >= uint32(JSON_MAX_DEPTH) {
|
|
_jsonStringTooDeep(tls, pOut)
|
|
}
|
|
for libc.Int32FromUint8((*TJsonString)(unsafe.Pointer(pOut)).FeErr) == 0 {
|
|
_jsonPrettyIndent(tls, pPretty)
|
|
j = _jsonTranslateBlobToPrettyText(tls, pPretty, j)
|
|
if j >= iEnd {
|
|
break
|
|
}
|
|
_jsonAppendRawNZ(tls, pOut, __ccgo_ts+26625, uint32(2))
|
|
}
|
|
_jsonAppendChar(tls, pOut, uint8('\n'))
|
|
(*TJsonPretty)(unsafe.Pointer(pPretty)).FnIndent = (*TJsonPretty)(unsafe.Pointer(pPretty)).FnIndent - 1
|
|
_jsonPrettyIndent(tls, pPretty)
|
|
}
|
|
_jsonAppendChar(tls, pOut, uint8(']'))
|
|
i = iEnd
|
|
case int32(JSONB_OBJECT):
|
|
j = i + n
|
|
iEnd = j + **(**Tu32)(__ccgo_up(bp))
|
|
_jsonAppendChar(tls, pOut, uint8('{'))
|
|
if j < iEnd {
|
|
_jsonAppendChar(tls, pOut, uint8('\n'))
|
|
(*TJsonPretty)(unsafe.Pointer(pPretty)).FnIndent = (*TJsonPretty)(unsafe.Pointer(pPretty)).FnIndent + 1
|
|
if (*TJsonPretty)(unsafe.Pointer(pPretty)).FnIndent >= uint32(JSON_MAX_DEPTH) {
|
|
_jsonStringTooDeep(tls, pOut)
|
|
}
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiDepth = uint16((*TJsonPretty)(unsafe.Pointer(pPretty)).FnIndent)
|
|
for libc.Int32FromUint8((*TJsonString)(unsafe.Pointer(pOut)).FeErr) == 0 {
|
|
_jsonPrettyIndent(tls, pPretty)
|
|
j = _jsonTranslateBlobToText(tls, pParse, j, pOut)
|
|
if j > iEnd {
|
|
v1 = pOut + 33
|
|
*(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) | libc.Int32FromInt32(JSTRING_MALFORMED))
|
|
break
|
|
}
|
|
_jsonAppendRawNZ(tls, pOut, __ccgo_ts+26628, uint32(2))
|
|
j = _jsonTranslateBlobToPrettyText(tls, pPretty, j)
|
|
if j >= iEnd {
|
|
break
|
|
}
|
|
_jsonAppendRawNZ(tls, pOut, __ccgo_ts+26625, uint32(2))
|
|
}
|
|
_jsonAppendChar(tls, pOut, uint8('\n'))
|
|
(*TJsonPretty)(unsafe.Pointer(pPretty)).FnIndent = (*TJsonPretty)(unsafe.Pointer(pPretty)).FnIndent - 1
|
|
_jsonPrettyIndent(tls, pPretty)
|
|
}
|
|
_jsonAppendChar(tls, pOut, uint8('}'))
|
|
i = iEnd
|
|
default:
|
|
i = _jsonTranslateBlobToText(tls, pParse, i, pOut)
|
|
break
|
|
}
|
|
return i
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Translate the binary JSONB representation of JSON beginning at
|
|
// ** pParse->aBlob[i] into a JSON text string. Append the JSON
|
|
// ** text onto the end of pOut. Return the index in pParse->aBlob[]
|
|
// ** of the first byte past the end of the element that is translated.
|
|
// **
|
|
// ** If an error is detected in the BLOB input, the pOut->eErr flag
|
|
// ** might get set to JSTRING_MALFORMED. But not all BLOB input errors
|
|
// ** are detected. So a malformed JSONB input might either result
|
|
// ** in an error, or in incorrect JSON.
|
|
// **
|
|
// ** The pOut->eErr JSTRING_OOM flag is set on a OOM.
|
|
// */
|
|
func _jsonTranslateBlobToText(tls *libc.TLS, pParse uintptr, i Tu32, pOut uintptr) (r Tu32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var bOverflow, x, v30, v31 int32
|
|
var iEnd, j, k, k1, k2, n, sz2 Tu32
|
|
var u Tsqlite3_uint64
|
|
var zIn, zIn1, zIn2, v1 uintptr
|
|
var v25 Tu16
|
|
var _ /* sz at bp+0 */ Tu32
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = bOverflow, iEnd, j, k, k1, k2, n, sz2, u, x, zIn, zIn1, zIn2, v1, v25, v30, v31
|
|
n = _jsonbPayloadSize(tls, pParse, i, bp)
|
|
if n == uint32(0) {
|
|
v1 = pOut + 33
|
|
*(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) | libc.Int32FromInt32(JSTRING_MALFORMED))
|
|
return (*TJsonParse)(unsafe.Pointer(pParse)).FnBlob + uint32(1)
|
|
}
|
|
switch libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(i)))) & libc.Int32FromInt32(0x0f) {
|
|
case JSONB_NULL:
|
|
goto _2
|
|
case int32(JSONB_TRUE):
|
|
goto _3
|
|
case int32(JSONB_FALSE):
|
|
goto _4
|
|
case int32(JSONB_FLOAT):
|
|
goto _5
|
|
case int32(JSONB_INT):
|
|
goto _6
|
|
case int32(JSONB_INT5):
|
|
goto _7
|
|
case int32(JSONB_FLOAT5):
|
|
goto _8
|
|
case int32(JSONB_TEXTJ):
|
|
goto _9
|
|
case int32(JSONB_TEXT):
|
|
goto _10
|
|
case int32(JSONB_TEXT5):
|
|
goto _11
|
|
case int32(JSONB_TEXTRAW):
|
|
goto _12
|
|
case int32(JSONB_ARRAY):
|
|
goto _13
|
|
case int32(JSONB_OBJECT):
|
|
goto _14
|
|
default:
|
|
goto _15
|
|
}
|
|
goto _16
|
|
_2:
|
|
;
|
|
_jsonAppendRawNZ(tls, pOut, __ccgo_ts+1690, uint32(4))
|
|
return i + uint32(1)
|
|
_3:
|
|
;
|
|
_jsonAppendRawNZ(tls, pOut, __ccgo_ts+8206, uint32(4))
|
|
return i + uint32(1)
|
|
_4:
|
|
;
|
|
_jsonAppendRawNZ(tls, pOut, __ccgo_ts+8211, uint32(5))
|
|
return i + uint32(1)
|
|
_6:
|
|
;
|
|
_5:
|
|
;
|
|
if **(**Tu32)(__ccgo_up(bp)) == uint32(0) {
|
|
goto malformed_jsonb
|
|
}
|
|
_jsonAppendRaw(tls, pOut, (*TJsonParse)(unsafe.Pointer(pParse)).FaBlob+uintptr(i+n), **(**Tu32)(__ccgo_up(bp)))
|
|
goto _16
|
|
_7:
|
|
; /* Integer literal in hexadecimal notation */
|
|
k = uint32(2)
|
|
u = uint64(0)
|
|
zIn = (*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(i+n)
|
|
bOverflow = 0
|
|
if **(**Tu32)(__ccgo_up(bp)) == uint32(0) {
|
|
goto malformed_jsonb
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn))) == int32('-') {
|
|
_jsonAppendChar(tls, pOut, uint8('-'))
|
|
k = k + 1
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn))) == int32('+') {
|
|
k = k + 1
|
|
}
|
|
}
|
|
for {
|
|
if !(k < **(**Tu32)(__ccgo_up(bp))) {
|
|
break
|
|
}
|
|
if !(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(zIn + uintptr(k))))])&libc.Int32FromInt32(0x08) != 0) {
|
|
v1 = pOut + 33
|
|
*(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) | libc.Int32FromInt32(JSTRING_MALFORMED))
|
|
break
|
|
} else {
|
|
if u>>libc.Int32FromInt32(60) != uint64(0) {
|
|
bOverflow = int32(1)
|
|
} else {
|
|
u = u*uint64(16) + uint64(_sqlite3HexToInt(tls, libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn + uintptr(k))))))
|
|
}
|
|
}
|
|
goto _17
|
|
_17:
|
|
;
|
|
k = k + 1
|
|
}
|
|
if bOverflow != 0 {
|
|
v1 = __ccgo_ts + 26505
|
|
} else {
|
|
v1 = __ccgo_ts + 13032
|
|
}
|
|
_jsonPrintf(tls, int32(100), pOut, v1, libc.VaList(bp+16, u))
|
|
goto _16
|
|
_8:
|
|
; /* Float literal missing digits beside "." */
|
|
k1 = uint32(0)
|
|
zIn1 = (*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(i+n)
|
|
if **(**Tu32)(__ccgo_up(bp)) == uint32(0) {
|
|
goto malformed_jsonb
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn1))) == int32('-') {
|
|
_jsonAppendChar(tls, pOut, uint8('-'))
|
|
if **(**Tu32)(__ccgo_up(bp)) <= uint32(1) {
|
|
goto malformed_jsonb
|
|
}
|
|
k1 = uint32(1)
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn1 + uintptr(k1)))) == int32('.') {
|
|
_jsonAppendChar(tls, pOut, uint8('0'))
|
|
}
|
|
for {
|
|
if !(k1 < **(**Tu32)(__ccgo_up(bp))) {
|
|
break
|
|
}
|
|
_jsonAppendChar(tls, pOut, **(**uint8)(__ccgo_up(zIn1 + uintptr(k1))))
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn1 + uintptr(k1)))) == int32('.') && (k1+uint32(1) == **(**Tu32)(__ccgo_up(bp)) || !(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(zIn1 + uintptr(k1+uint32(1)))))])&libc.Int32FromInt32(0x04) != 0)) {
|
|
_jsonAppendChar(tls, pOut, uint8('0'))
|
|
}
|
|
goto _20
|
|
_20:
|
|
;
|
|
k1 = k1 + 1
|
|
}
|
|
goto _16
|
|
_10:
|
|
;
|
|
_9:
|
|
;
|
|
if (*TJsonString)(unsafe.Pointer(pOut)).FnUsed+uint64(**(**Tu32)(__ccgo_up(bp)))+uint64(2) <= (*TJsonString)(unsafe.Pointer(pOut)).FnAlloc || _jsonStringGrow(tls, pOut, **(**Tu32)(__ccgo_up(bp))+uint32(2)) == 0 {
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(pOut)).FzBuf + uintptr((*TJsonString)(unsafe.Pointer(pOut)).FnUsed))) = uint8('"')
|
|
libc.Xmemcpy(tls, (*TJsonString)(unsafe.Pointer(pOut)).FzBuf+uintptr((*TJsonString)(unsafe.Pointer(pOut)).FnUsed)+uintptr(1), (*TJsonParse)(unsafe.Pointer(pParse)).FaBlob+uintptr(i+n), uint64(**(**Tu32)(__ccgo_up(bp))))
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(pOut)).FzBuf + uintptr((*TJsonString)(unsafe.Pointer(pOut)).FnUsed+uint64(**(**Tu32)(__ccgo_up(bp)))+uint64(1)))) = uint8('"')
|
|
**(**Tu64)(__ccgo_up(pOut + 24)) += uint64(**(**Tu32)(__ccgo_up(bp)) + uint32(2))
|
|
}
|
|
goto _16
|
|
_11:
|
|
;
|
|
sz2 = **(**Tu32)(__ccgo_up(bp))
|
|
zIn2 = (*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(i+n)
|
|
_jsonAppendChar(tls, pOut, uint8('"'))
|
|
for sz2 > uint32(0) {
|
|
k2 = uint32(0)
|
|
for {
|
|
if !(k2 < sz2 && (_jsonIsOk[uint8(**(**uint8)(__ccgo_up(zIn2 + uintptr(k2))))] != 0 || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn2 + uintptr(k2)))) == int32('\''))) {
|
|
break
|
|
}
|
|
goto _21
|
|
_21:
|
|
;
|
|
k2 = k2 + 1
|
|
}
|
|
if k2 > uint32(0) {
|
|
_jsonAppendRawNZ(tls, pOut, zIn2, k2)
|
|
if k2 >= sz2 {
|
|
break
|
|
}
|
|
zIn2 = zIn2 + uintptr(k2)
|
|
sz2 = sz2 - k2
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn2))) == int32('"') {
|
|
_jsonAppendRawNZ(tls, pOut, __ccgo_ts+26603, uint32(2))
|
|
zIn2 = zIn2 + 1
|
|
sz2 = sz2 - 1
|
|
continue
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn2))) <= int32(0x1f) {
|
|
if (*TJsonString)(unsafe.Pointer(pOut)).FnUsed+uint64(7) > (*TJsonString)(unsafe.Pointer(pOut)).FnAlloc && _jsonStringGrow(tls, pOut, uint32(7)) != 0 {
|
|
break
|
|
}
|
|
_jsonAppendControlChar(tls, pOut, uint8(**(**uint8)(__ccgo_up(zIn2))))
|
|
zIn2 = zIn2 + 1
|
|
sz2 = sz2 - 1
|
|
continue
|
|
}
|
|
if sz2 < uint32(2) {
|
|
v1 = pOut + 33
|
|
*(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) | libc.Int32FromInt32(JSTRING_MALFORMED))
|
|
break
|
|
}
|
|
switch libc.Int32FromUint8(uint8(**(**uint8)(__ccgo_up(zIn2 + 1)))) {
|
|
case int32('\''):
|
|
_jsonAppendChar(tls, pOut, uint8('\''))
|
|
case int32('v'):
|
|
_jsonAppendRawNZ(tls, pOut, __ccgo_ts+26606, uint32(6))
|
|
case int32('x'):
|
|
if sz2 < uint32(4) {
|
|
v1 = pOut + 33
|
|
*(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) | libc.Int32FromInt32(JSTRING_MALFORMED))
|
|
sz2 = uint32(2)
|
|
break
|
|
}
|
|
_jsonAppendRawNZ(tls, pOut, __ccgo_ts+26613, uint32(4))
|
|
_jsonAppendRawNZ(tls, pOut, zIn2+2, uint32(2))
|
|
zIn2 = zIn2 + uintptr(2)
|
|
sz2 = sz2 - uint32(2)
|
|
case int32('0'):
|
|
_jsonAppendRawNZ(tls, pOut, __ccgo_ts+26618, uint32(6))
|
|
case int32('\r'):
|
|
if sz2 > uint32(2) && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn2 + 2))) == int32('\n') {
|
|
zIn2 = zIn2 + 1
|
|
sz2 = sz2 - 1
|
|
}
|
|
case int32('\n'):
|
|
case int32(0xe2):
|
|
/* '\' followed by either U+2028 or U+2029 is ignored as
|
|
** whitespace. Not that in UTF8, U+2028 is 0xe2 0x80 0x29.
|
|
** U+2029 is the same except for the last byte */
|
|
if sz2 < uint32(4) || int32(0x80) != libc.Int32FromUint8(uint8(**(**uint8)(__ccgo_up(zIn2 + 2)))) || int32(0xa8) != libc.Int32FromUint8(uint8(**(**uint8)(__ccgo_up(zIn2 + 3)))) && int32(0xa9) != libc.Int32FromUint8(uint8(**(**uint8)(__ccgo_up(zIn2 + 3)))) {
|
|
v1 = pOut + 33
|
|
*(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) | libc.Int32FromInt32(JSTRING_MALFORMED))
|
|
sz2 = uint32(2)
|
|
break
|
|
}
|
|
zIn2 = zIn2 + uintptr(2)
|
|
sz2 = sz2 - uint32(2)
|
|
default:
|
|
_jsonAppendRawNZ(tls, pOut, zIn2, uint32(2))
|
|
break
|
|
}
|
|
zIn2 = zIn2 + uintptr(2)
|
|
sz2 = sz2 - uint32(2)
|
|
}
|
|
_jsonAppendChar(tls, pOut, uint8('"'))
|
|
goto _16
|
|
_12:
|
|
;
|
|
_jsonAppendString(tls, pOut, (*TJsonParse)(unsafe.Pointer(pParse)).FaBlob+uintptr(i+n), **(**Tu32)(__ccgo_up(bp)))
|
|
goto _16
|
|
_13:
|
|
;
|
|
_jsonAppendChar(tls, pOut, uint8('['))
|
|
j = i + n
|
|
iEnd = j + **(**Tu32)(__ccgo_up(bp))
|
|
v1 = pParse + 44
|
|
*(*Tu16)(unsafe.Pointer(v1)) = *(*Tu16)(unsafe.Pointer(v1)) + 1
|
|
v25 = *(*Tu16)(unsafe.Pointer(v1))
|
|
if libc.Int32FromUint16(v25) > int32(JSON_MAX_DEPTH) {
|
|
_jsonStringTooDeep(tls, pOut)
|
|
}
|
|
for j < iEnd && libc.Int32FromUint8((*TJsonString)(unsafe.Pointer(pOut)).FeErr) == 0 {
|
|
j = _jsonTranslateBlobToText(tls, pParse, j, pOut)
|
|
_jsonAppendChar(tls, pOut, uint8(','))
|
|
}
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiDepth = (*TJsonParse)(unsafe.Pointer(pParse)).FiDepth - 1
|
|
if j > iEnd {
|
|
v1 = pOut + 33
|
|
*(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) | libc.Int32FromInt32(JSTRING_MALFORMED))
|
|
}
|
|
if **(**Tu32)(__ccgo_up(bp)) > uint32(0) {
|
|
_jsonStringTrimOneChar(tls, pOut)
|
|
}
|
|
_jsonAppendChar(tls, pOut, uint8(']'))
|
|
goto _16
|
|
_14:
|
|
;
|
|
x = 0
|
|
_jsonAppendChar(tls, pOut, uint8('{'))
|
|
j = i + n
|
|
iEnd = j + **(**Tu32)(__ccgo_up(bp))
|
|
v1 = pParse + 44
|
|
*(*Tu16)(unsafe.Pointer(v1)) = *(*Tu16)(unsafe.Pointer(v1)) + 1
|
|
v25 = *(*Tu16)(unsafe.Pointer(v1))
|
|
if libc.Int32FromUint16(v25) > int32(JSON_MAX_DEPTH) {
|
|
_jsonStringTooDeep(tls, pOut)
|
|
}
|
|
for j < iEnd && libc.Int32FromUint8((*TJsonString)(unsafe.Pointer(pOut)).FeErr) == 0 {
|
|
j = _jsonTranslateBlobToText(tls, pParse, j, pOut)
|
|
v31 = x
|
|
x = x + 1
|
|
if v31&int32(1) != 0 {
|
|
v30 = int32(',')
|
|
} else {
|
|
v30 = int32(':')
|
|
}
|
|
_jsonAppendChar(tls, pOut, libc.Uint8FromInt32(v30))
|
|
}
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiDepth = (*TJsonParse)(unsafe.Pointer(pParse)).FiDepth - 1
|
|
if x&int32(1) != 0 || j > iEnd {
|
|
v1 = pOut + 33
|
|
*(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) | libc.Int32FromInt32(JSTRING_MALFORMED))
|
|
}
|
|
if **(**Tu32)(__ccgo_up(bp)) > uint32(0) {
|
|
_jsonStringTrimOneChar(tls, pOut)
|
|
}
|
|
_jsonAppendChar(tls, pOut, uint8('}'))
|
|
goto _16
|
|
_15:
|
|
;
|
|
goto malformed_jsonb
|
|
malformed_jsonb:
|
|
;
|
|
v1 = pOut + 33
|
|
*(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) | libc.Int32FromInt32(JSTRING_MALFORMED))
|
|
goto _16
|
|
_16:
|
|
;
|
|
return i + n + **(**Tu32)(__ccgo_up(bp))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Translate a single element of JSON text at pParse->zJson[i] into
|
|
// ** its equivalent binary JSONB representation. Append the translation into
|
|
// ** pParse->aBlob[] beginning at pParse->nBlob. The size of
|
|
// ** pParse->aBlob[] is increased as necessary.
|
|
// **
|
|
// ** Return the index of the first character past the end of the element parsed,
|
|
// ** or one of the following special result codes:
|
|
// **
|
|
// ** 0 End of input
|
|
// ** -1 Syntax error or OOM
|
|
// ** -2 '}' seen ** -3 ']' seen \___ For these returns, pParse->iErr is set to
|
|
// ** -4 ',' seen / the index in zJson[] of the seen character
|
|
// ** -5 ':' seen /
|
|
// */
|
|
func _jsonTranslateTextToBlob(tls *libc.TLS, pParse uintptr, i Tu32) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var c, cDelim uint8
|
|
var iBlob, iStart, iThis, j, k1, v46 Tu32
|
|
var k, nn, x, v48 int32
|
|
var opcode, seenE, t Tu8
|
|
var z, v41 uintptr
|
|
var v40 Tu16
|
|
var _ /* op at bp+0 */ int32
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = c, cDelim, iBlob, iStart, iThis, j, k, k1, nn, opcode, seenE, t, x, z, v40, v41, v46, v48
|
|
z = (*TJsonParse)(unsafe.Pointer(pParse)).FzJson
|
|
goto json_parse_restart
|
|
json_parse_restart:
|
|
;
|
|
switch libc.Int32FromUint8(uint8(**(**uint8)(__ccgo_up(z + uintptr(i))))) {
|
|
case int32('{'):
|
|
goto _1
|
|
case int32('['):
|
|
goto _2
|
|
case int32('"'):
|
|
goto _3
|
|
case int32('\''):
|
|
goto _4
|
|
case int32('t'):
|
|
goto _5
|
|
case int32('f'):
|
|
goto _6
|
|
case int32('.'):
|
|
goto _7
|
|
case int32('9'):
|
|
goto _8
|
|
case int32('8'):
|
|
goto _9
|
|
case int32('7'):
|
|
goto _10
|
|
case int32('6'):
|
|
goto _11
|
|
case int32('5'):
|
|
goto _12
|
|
case int32('4'):
|
|
goto _13
|
|
case int32('3'):
|
|
goto _14
|
|
case int32('2'):
|
|
goto _15
|
|
case int32('1'):
|
|
goto _16
|
|
case int32('0'):
|
|
goto _17
|
|
case int32('-'):
|
|
goto _18
|
|
case int32('+'):
|
|
goto _19
|
|
case int32('}'):
|
|
goto _20
|
|
case int32(']'):
|
|
goto _21
|
|
case int32(','):
|
|
goto _22
|
|
case int32(':'):
|
|
goto _23
|
|
case 0:
|
|
goto _24
|
|
case int32(0x20):
|
|
goto _25
|
|
case int32(0x0d):
|
|
goto _26
|
|
case int32(0x0a):
|
|
goto _27
|
|
case int32(0x09):
|
|
goto _28
|
|
case int32(0xef):
|
|
goto _29
|
|
case int32(0xe3):
|
|
goto _30
|
|
case int32(0xe2):
|
|
goto _31
|
|
case int32(0xe1):
|
|
goto _32
|
|
case int32(0xc2):
|
|
goto _33
|
|
case int32('/'):
|
|
goto _34
|
|
case int32(0x0c):
|
|
goto _35
|
|
case int32(0x0b):
|
|
goto _36
|
|
case int32('n'):
|
|
goto _37
|
|
default:
|
|
goto _38
|
|
}
|
|
goto _39
|
|
_1:
|
|
;
|
|
/* Parse object */
|
|
iThis = (*TJsonParse)(unsafe.Pointer(pParse)).FnBlob
|
|
_jsonBlobAppendNode(tls, pParse, uint8(JSONB_OBJECT), uint64(libc.Uint32FromInt32((*TJsonParse)(unsafe.Pointer(pParse)).FnJson)-i), uintptr(0))
|
|
v41 = pParse + 44
|
|
*(*Tu16)(unsafe.Pointer(v41)) = *(*Tu16)(unsafe.Pointer(v41)) + 1
|
|
v40 = *(*Tu16)(unsafe.Pointer(v41))
|
|
if libc.Int32FromUint16(v40) > int32(JSON_MAX_DEPTH) {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = i
|
|
return -int32(1)
|
|
}
|
|
iStart = (*TJsonParse)(unsafe.Pointer(pParse)).FnBlob
|
|
j = i + uint32(1)
|
|
for {
|
|
iBlob = (*TJsonParse)(unsafe.Pointer(pParse)).FnBlob
|
|
x = _jsonTranslateTextToBlob(tls, pParse, j)
|
|
if x <= 0 {
|
|
if x == -int32(2) {
|
|
j = (*TJsonParse)(unsafe.Pointer(pParse)).FiErr
|
|
if (*TJsonParse)(unsafe.Pointer(pParse)).FnBlob != iStart {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FhasNonstd = uint8(1)
|
|
}
|
|
break
|
|
}
|
|
j = j + libc.Uint32FromInt32(_json5Whitespace(tls, z+uintptr(j)))
|
|
**(**int32)(__ccgo_up(bp)) = int32(JSONB_TEXT)
|
|
if libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(j))))])&int32(0x42) != 0 || libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(j)))) == int32('\\') && _jsonIs4HexB(tls, z+uintptr(j+uint32(1)), bp) != 0 {
|
|
k = libc.Int32FromUint32(j + uint32(1))
|
|
for libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(k))))])&int32(0x46) != 0 && _json5Whitespace(tls, z+uintptr(k)) == 0 || libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(k)))) == int32('\\') && _jsonIs4HexB(tls, z+uintptr(k+int32(1)), bp) != 0 {
|
|
k = k + 1
|
|
}
|
|
_jsonBlobAppendNode(tls, pParse, libc.Uint8FromInt32(**(**int32)(__ccgo_up(bp))), uint64(libc.Uint32FromInt32(k)-j), z+uintptr(j))
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FhasNonstd = uint8(1)
|
|
x = k
|
|
} else {
|
|
if x != -int32(1) {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = j
|
|
}
|
|
return -int32(1)
|
|
}
|
|
}
|
|
if (*TJsonParse)(unsafe.Pointer(pParse)).Foom != 0 {
|
|
return -int32(1)
|
|
}
|
|
t = libc.Uint8FromInt32(libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(iBlob)))) & int32(0x0f))
|
|
if libc.Int32FromUint8(t) < int32(JSONB_TEXT) || libc.Int32FromUint8(t) > int32(JSONB_TEXTRAW) {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = j
|
|
return -int32(1)
|
|
}
|
|
j = libc.Uint32FromInt32(x)
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(j)))) == int32(':') {
|
|
j = j + 1
|
|
} else {
|
|
if _jsonIsSpace[uint8(**(**uint8)(__ccgo_up(z + uintptr(j))))] != 0 {
|
|
/* strspn() is not helpful here */
|
|
for cond := true; cond; cond = _jsonIsSpace[uint8(**(**uint8)(__ccgo_up(z + uintptr(j))))] != 0 {
|
|
j = j + 1
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(j)))) == int32(':') {
|
|
j = j + 1
|
|
goto parse_object_value
|
|
}
|
|
}
|
|
x = _jsonTranslateTextToBlob(tls, pParse, j)
|
|
if x != -int32(5) {
|
|
if x != -int32(1) {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = j
|
|
}
|
|
return -int32(1)
|
|
}
|
|
j = (*TJsonParse)(unsafe.Pointer(pParse)).FiErr + uint32(1)
|
|
}
|
|
goto parse_object_value
|
|
parse_object_value:
|
|
;
|
|
x = _jsonTranslateTextToBlob(tls, pParse, j)
|
|
if x <= 0 {
|
|
if x != -int32(1) {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = j
|
|
}
|
|
return -int32(1)
|
|
}
|
|
j = libc.Uint32FromInt32(x)
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(j)))) == int32(',') {
|
|
goto _42
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(j)))) == int32('}') {
|
|
break
|
|
} else {
|
|
if _jsonIsSpace[uint8(**(**uint8)(__ccgo_up(z + uintptr(j))))] != 0 {
|
|
j = j + (uint32(1) + uint32(libc.Xstrspn(tls, z+uintptr(j+uint32(1)), uintptr(unsafe.Pointer(&_jsonSpaces)))))
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(j)))) == int32(',') {
|
|
goto _42
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(j)))) == int32('}') {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
x = _jsonTranslateTextToBlob(tls, pParse, j)
|
|
if x == -int32(4) {
|
|
j = (*TJsonParse)(unsafe.Pointer(pParse)).FiErr
|
|
goto _42
|
|
}
|
|
if x == -int32(2) {
|
|
j = (*TJsonParse)(unsafe.Pointer(pParse)).FiErr
|
|
break
|
|
}
|
|
}
|
|
}
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = j
|
|
return -int32(1)
|
|
goto _42
|
|
_42:
|
|
;
|
|
j = j + 1
|
|
}
|
|
_jsonBlobChangePayloadSize(tls, pParse, iThis, (*TJsonParse)(unsafe.Pointer(pParse)).FnBlob-iStart)
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiDepth = (*TJsonParse)(unsafe.Pointer(pParse)).FiDepth - 1
|
|
return libc.Int32FromUint32(j + uint32(1))
|
|
_2:
|
|
;
|
|
/* Parse array */
|
|
iThis = (*TJsonParse)(unsafe.Pointer(pParse)).FnBlob
|
|
_jsonBlobAppendNode(tls, pParse, uint8(JSONB_ARRAY), uint64(libc.Uint32FromInt32((*TJsonParse)(unsafe.Pointer(pParse)).FnJson)-i), uintptr(0))
|
|
iStart = (*TJsonParse)(unsafe.Pointer(pParse)).FnBlob
|
|
if (*TJsonParse)(unsafe.Pointer(pParse)).Foom != 0 {
|
|
return -int32(1)
|
|
}
|
|
v41 = pParse + 44
|
|
*(*Tu16)(unsafe.Pointer(v41)) = *(*Tu16)(unsafe.Pointer(v41)) + 1
|
|
v40 = *(*Tu16)(unsafe.Pointer(v41))
|
|
if libc.Int32FromUint16(v40) > int32(JSON_MAX_DEPTH) {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = i
|
|
return -int32(1)
|
|
}
|
|
j = i + uint32(1)
|
|
for {
|
|
x = _jsonTranslateTextToBlob(tls, pParse, j)
|
|
if x <= 0 {
|
|
if x == -int32(3) {
|
|
j = (*TJsonParse)(unsafe.Pointer(pParse)).FiErr
|
|
if (*TJsonParse)(unsafe.Pointer(pParse)).FnBlob != iStart {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FhasNonstd = uint8(1)
|
|
}
|
|
break
|
|
}
|
|
if x != -int32(1) {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = j
|
|
}
|
|
return -int32(1)
|
|
}
|
|
j = libc.Uint32FromInt32(x)
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(j)))) == int32(',') {
|
|
goto _45
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(j)))) == int32(']') {
|
|
break
|
|
} else {
|
|
if _jsonIsSpace[uint8(**(**uint8)(__ccgo_up(z + uintptr(j))))] != 0 {
|
|
j = j + (uint32(1) + uint32(libc.Xstrspn(tls, z+uintptr(j+uint32(1)), uintptr(unsafe.Pointer(&_jsonSpaces)))))
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(j)))) == int32(',') {
|
|
goto _45
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(j)))) == int32(']') {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
x = _jsonTranslateTextToBlob(tls, pParse, j)
|
|
if x == -int32(4) {
|
|
j = (*TJsonParse)(unsafe.Pointer(pParse)).FiErr
|
|
goto _45
|
|
}
|
|
if x == -int32(3) {
|
|
j = (*TJsonParse)(unsafe.Pointer(pParse)).FiErr
|
|
break
|
|
}
|
|
}
|
|
}
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = j
|
|
return -int32(1)
|
|
goto _45
|
|
_45:
|
|
;
|
|
j = j + 1
|
|
}
|
|
_jsonBlobChangePayloadSize(tls, pParse, iThis, (*TJsonParse)(unsafe.Pointer(pParse)).FnBlob-iStart)
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiDepth = (*TJsonParse)(unsafe.Pointer(pParse)).FiDepth - 1
|
|
return libc.Int32FromUint32(j + uint32(1))
|
|
_4:
|
|
;
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FhasNonstd = uint8(1)
|
|
opcode = uint8(JSONB_TEXT)
|
|
goto parse_string
|
|
_3:
|
|
;
|
|
/* Parse string */
|
|
opcode = uint8(JSONB_TEXT)
|
|
goto parse_string
|
|
parse_string:
|
|
;
|
|
cDelim = **(**uint8)(__ccgo_up(z + uintptr(i)))
|
|
j = i + uint32(1)
|
|
for int32(1) != 0 {
|
|
if _jsonIsOk[uint8(**(**uint8)(__ccgo_up(z + uintptr(j))))] != 0 {
|
|
if !(_jsonIsOk[uint8(**(**uint8)(__ccgo_up(z + uintptr(j+uint32(1)))))] != 0) {
|
|
j = j + uint32(1)
|
|
} else {
|
|
if !(_jsonIsOk[uint8(**(**uint8)(__ccgo_up(z + uintptr(j+uint32(2)))))] != 0) {
|
|
j = j + uint32(2)
|
|
} else {
|
|
j = j + uint32(3)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
c = **(**uint8)(__ccgo_up(z + uintptr(j)))
|
|
if libc.Int32FromUint8(c) == libc.Int32FromUint8(cDelim) {
|
|
break
|
|
} else {
|
|
if libc.Int32FromUint8(c) == int32('\\') {
|
|
j = j + 1
|
|
v46 = j
|
|
c = **(**uint8)(__ccgo_up(z + uintptr(v46)))
|
|
if libc.Int32FromUint8(c) == int32('"') || libc.Int32FromUint8(c) == int32('\\') || libc.Int32FromUint8(c) == int32('/') || libc.Int32FromUint8(c) == int32('b') || libc.Int32FromUint8(c) == int32('f') || libc.Int32FromUint8(c) == int32('n') || libc.Int32FromUint8(c) == int32('r') || libc.Int32FromUint8(c) == int32('t') || libc.Int32FromUint8(c) == int32('u') && _jsonIs4Hex(tls, z+uintptr(j+uint32(1))) != 0 {
|
|
if libc.Int32FromUint8(opcode) == int32(JSONB_TEXT) {
|
|
opcode = uint8(JSONB_TEXTJ)
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint8(c) == int32('\'') || libc.Int32FromUint8(c) == int32('v') || libc.Int32FromUint8(c) == int32('\n') || libc.Int32FromUint8(c) == int32('0') && !(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(j+uint32(1)))))])&libc.Int32FromInt32(0x04) != 0) || int32(0xe2) == libc.Int32FromUint8(c) && int32(0x80) == libc.Int32FromUint8(uint8(**(**uint8)(__ccgo_up(z + uintptr(j+uint32(1)))))) && (int32(0xa8) == libc.Int32FromUint8(uint8(**(**uint8)(__ccgo_up(z + uintptr(j+uint32(2)))))) || int32(0xa9) == libc.Int32FromUint8(uint8(**(**uint8)(__ccgo_up(z + uintptr(j+uint32(2))))))) || libc.Int32FromUint8(c) == int32('x') && _jsonIs2Hex(tls, z+uintptr(j+uint32(1))) != 0 {
|
|
opcode = uint8(JSONB_TEXT5)
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FhasNonstd = uint8(1)
|
|
} else {
|
|
if libc.Int32FromUint8(c) == int32('\r') {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(j+uint32(1))))) == int32('\n') {
|
|
j = j + 1
|
|
}
|
|
opcode = uint8(JSONB_TEXT5)
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FhasNonstd = uint8(1)
|
|
} else {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = j
|
|
return -int32(1)
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint8(c) <= int32(0x1f) {
|
|
if libc.Int32FromUint8(c) == 0 {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = j
|
|
return -int32(1)
|
|
}
|
|
/* Control characters are not allowed in canonical JSON string
|
|
** literals, but are allowed in JSON5 string literals. */
|
|
opcode = uint8(JSONB_TEXT5)
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FhasNonstd = uint8(1)
|
|
} else {
|
|
if libc.Int32FromUint8(c) == int32('"') {
|
|
opcode = uint8(JSONB_TEXT5)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
j = j + 1
|
|
}
|
|
_jsonBlobAppendNode(tls, pParse, opcode, uint64(j-uint32(1)-i), z+uintptr(i+uint32(1)))
|
|
return libc.Int32FromUint32(j + uint32(1))
|
|
_5:
|
|
;
|
|
if libc.Xstrncmp(tls, z+uintptr(i), __ccgo_ts+8206, uint64(4)) == 0 && !(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(i+uint32(4)))))])&libc.Int32FromInt32(0x06) != 0) {
|
|
_jsonBlobAppendOneByte(tls, pParse, uint8(JSONB_TRUE))
|
|
return libc.Int32FromUint32(i + uint32(4))
|
|
}
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = i
|
|
return -int32(1)
|
|
_6:
|
|
;
|
|
if libc.Xstrncmp(tls, z+uintptr(i), __ccgo_ts+8211, uint64(5)) == 0 && !(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(i+uint32(5)))))])&libc.Int32FromInt32(0x06) != 0) {
|
|
_jsonBlobAppendOneByte(tls, pParse, uint8(JSONB_FALSE))
|
|
return libc.Int32FromUint32(i + uint32(5))
|
|
}
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = i
|
|
return -int32(1)
|
|
_19:
|
|
;
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FhasNonstd = uint8(1)
|
|
t = uint8(0x00) /* Bit 0x01: JSON5. Bit 0x02: FLOAT */
|
|
goto parse_number
|
|
_7:
|
|
;
|
|
if libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(i+uint32(1)))))])&int32(0x04) != 0 {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FhasNonstd = uint8(1)
|
|
t = uint8(0x03) /* Bit 0x01: JSON5. Bit 0x02: FLOAT */
|
|
seenE = uint8(0)
|
|
goto parse_number_2
|
|
}
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = i
|
|
return -int32(1)
|
|
_18:
|
|
;
|
|
_17:
|
|
;
|
|
_16:
|
|
;
|
|
_15:
|
|
;
|
|
_14:
|
|
;
|
|
_13:
|
|
;
|
|
_12:
|
|
;
|
|
_11:
|
|
;
|
|
_10:
|
|
;
|
|
_9:
|
|
;
|
|
_8:
|
|
;
|
|
/* Parse number */
|
|
t = uint8(0x00) /* Bit 0x01: JSON5. Bit 0x02: FLOAT */
|
|
goto parse_number
|
|
parse_number:
|
|
;
|
|
seenE = uint8(0)
|
|
c = **(**uint8)(__ccgo_up(z + uintptr(i)))
|
|
if libc.Int32FromUint8(c) <= int32('0') {
|
|
if libc.Int32FromUint8(c) == int32('0') {
|
|
if (libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i+uint32(1))))) == int32('x') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i+uint32(1))))) == int32('X')) && libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(i+uint32(2)))))])&int32(0x08) != 0 {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FhasNonstd = uint8(1)
|
|
t = uint8(0x01)
|
|
j = i + uint32(3)
|
|
for {
|
|
if !(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(j))))])&int32(0x08) != 0) {
|
|
break
|
|
}
|
|
goto _47
|
|
_47:
|
|
;
|
|
j = j + 1
|
|
}
|
|
goto parse_number_finish
|
|
} else {
|
|
if libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(i+uint32(1)))))])&int32(0x04) != 0 {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = i + uint32(1)
|
|
return -int32(1)
|
|
}
|
|
}
|
|
} else {
|
|
if !(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(i+uint32(1)))))])&libc.Int32FromInt32(0x04) != 0) {
|
|
/* JSON5 allows for "+Infinity" and "-Infinity" using exactly
|
|
** that case. SQLite also allows these in any case and it allows
|
|
** "+inf" and "-inf". */
|
|
if (libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i+uint32(1))))) == int32('I') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i+uint32(1))))) == int32('i')) && Xsqlite3_strnicmp(tls, z+uintptr(i+uint32(1)), __ccgo_ts+26501, int32(3)) == 0 {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FhasNonstd = uint8(1)
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) == int32('-') {
|
|
_jsonBlobAppendNode(tls, pParse, uint8(JSONB_FLOAT), uint64(6), __ccgo_ts+26584)
|
|
} else {
|
|
_jsonBlobAppendNode(tls, pParse, uint8(JSONB_FLOAT), uint64(5), __ccgo_ts+26591)
|
|
}
|
|
if Xsqlite3_strnicmp(tls, z+uintptr(i+uint32(4)), __ccgo_ts+26597, int32(5)) == 0 {
|
|
v48 = int32(9)
|
|
} else {
|
|
v48 = int32(4)
|
|
}
|
|
return libc.Int32FromUint32(i + libc.Uint32FromInt32(v48))
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i+uint32(1))))) == int32('.') {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FhasNonstd = uint8(1)
|
|
t = libc.Uint8FromInt32(int32(t) | libc.Int32FromInt32(0x01))
|
|
goto parse_number_2
|
|
}
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = i
|
|
return -int32(1)
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i+uint32(1))))) == int32('0') {
|
|
if libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(i+uint32(2)))))])&int32(0x04) != 0 {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = i + uint32(1)
|
|
return -int32(1)
|
|
} else {
|
|
if (libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i+uint32(2))))) == int32('x') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i+uint32(2))))) == int32('X')) && libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(i+uint32(3)))))])&int32(0x08) != 0 {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FhasNonstd = uint8(1)
|
|
t = libc.Uint8FromInt32(int32(t) | libc.Int32FromInt32(0x01))
|
|
j = i + uint32(4)
|
|
for {
|
|
if !(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(j))))])&int32(0x08) != 0) {
|
|
break
|
|
}
|
|
goto _49
|
|
_49:
|
|
;
|
|
j = j + 1
|
|
}
|
|
goto parse_number_finish
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
goto parse_number_2
|
|
parse_number_2:
|
|
;
|
|
j = i + uint32(1)
|
|
for {
|
|
c = **(**uint8)(__ccgo_up(z + uintptr(j)))
|
|
if libc.Int32FromUint8(_sqlite3CtypeMap[c])&int32(0x04) != 0 {
|
|
goto _50
|
|
}
|
|
if libc.Int32FromUint8(c) == int32('.') {
|
|
if libc.Int32FromUint8(t)&int32(0x02) != 0 {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = j
|
|
return -int32(1)
|
|
}
|
|
t = libc.Uint8FromInt32(int32(t) | libc.Int32FromInt32(0x02))
|
|
goto _50
|
|
}
|
|
if libc.Int32FromUint8(c) == int32('e') || libc.Int32FromUint8(c) == int32('E') {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(j-uint32(1))))) < int32('0') {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(j-uint32(1))))) == int32('.') && j-uint32(2) >= i && libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(j-uint32(2)))))])&int32(0x04) != 0 {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FhasNonstd = uint8(1)
|
|
t = libc.Uint8FromInt32(int32(t) | libc.Int32FromInt32(0x01))
|
|
} else {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = j
|
|
return -int32(1)
|
|
}
|
|
}
|
|
if seenE != 0 {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = j
|
|
return -int32(1)
|
|
}
|
|
t = libc.Uint8FromInt32(int32(t) | libc.Int32FromInt32(0x02))
|
|
seenE = uint8(1)
|
|
c = **(**uint8)(__ccgo_up(z + uintptr(j+uint32(1))))
|
|
if libc.Int32FromUint8(c) == int32('+') || libc.Int32FromUint8(c) == int32('-') {
|
|
j = j + 1
|
|
c = **(**uint8)(__ccgo_up(z + uintptr(j+uint32(1))))
|
|
}
|
|
if libc.Int32FromUint8(c) < int32('0') || libc.Int32FromUint8(c) > int32('9') {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = j
|
|
return -int32(1)
|
|
}
|
|
goto _50
|
|
}
|
|
break
|
|
goto _50
|
|
_50:
|
|
;
|
|
j = j + 1
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(j-uint32(1))))) < int32('0') {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(j-uint32(1))))) == int32('.') && j-uint32(2) >= i && libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(j-uint32(2)))))])&int32(0x04) != 0 {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FhasNonstd = uint8(1)
|
|
t = libc.Uint8FromInt32(int32(t) | libc.Int32FromInt32(0x01))
|
|
} else {
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = j
|
|
return -int32(1)
|
|
}
|
|
}
|
|
goto parse_number_finish
|
|
parse_number_finish:
|
|
;
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) == int32('+') {
|
|
i = i + 1
|
|
}
|
|
_jsonBlobAppendNode(tls, pParse, libc.Uint8FromInt32(int32(JSONB_INT)+libc.Int32FromUint8(t)), uint64(j-i), z+uintptr(i))
|
|
return libc.Int32FromUint32(j)
|
|
_20:
|
|
;
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = i
|
|
return -int32(2) /* End of {...} */
|
|
_21:
|
|
;
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = i
|
|
return -int32(3) /* End of [...] */
|
|
_22:
|
|
;
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = i
|
|
return -int32(4) /* List separator */
|
|
_23:
|
|
;
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = i
|
|
return -int32(5) /* Object label/value separator */
|
|
_24:
|
|
;
|
|
return 0 /* End of file */
|
|
_28:
|
|
;
|
|
_27:
|
|
;
|
|
_26:
|
|
;
|
|
_25:
|
|
;
|
|
i = i + (uint32(1) + uint32(libc.Xstrspn(tls, z+uintptr(i+uint32(1)), uintptr(unsafe.Pointer(&_jsonSpaces)))))
|
|
goto json_parse_restart
|
|
_36:
|
|
;
|
|
_35:
|
|
;
|
|
_34:
|
|
;
|
|
_33:
|
|
;
|
|
_32:
|
|
;
|
|
_31:
|
|
;
|
|
_30:
|
|
;
|
|
_29:
|
|
;
|
|
j = libc.Uint32FromInt32(_json5Whitespace(tls, z+uintptr(i)))
|
|
if j > uint32(0) {
|
|
i = i + j
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FhasNonstd = uint8(1)
|
|
goto json_parse_restart
|
|
}
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = i
|
|
return -int32(1)
|
|
_37:
|
|
;
|
|
if libc.Xstrncmp(tls, z+uintptr(i), __ccgo_ts+1690, uint64(4)) == 0 && !(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(i+uint32(4)))))])&libc.Int32FromInt32(0x06) != 0) {
|
|
_jsonBlobAppendOneByte(tls, pParse, uint8(JSONB_NULL))
|
|
return libc.Int32FromUint32(i + uint32(4))
|
|
}
|
|
/* fall-through into the default case that checks for NaN */
|
|
_38:
|
|
;
|
|
c = **(**uint8)(__ccgo_up(z + uintptr(i)))
|
|
k1 = uint32(0)
|
|
for {
|
|
if !(uint64(k1) < libc.Uint64FromInt64(120)/libc.Uint64FromInt64(24)) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint8(c) != libc.Int32FromUint8(_aNanInfName[k1].Fc1) && libc.Int32FromUint8(c) != libc.Int32FromUint8(_aNanInfName[k1].Fc2) {
|
|
goto _51
|
|
}
|
|
nn = libc.Int32FromUint8(_aNanInfName[k1].Fn)
|
|
if Xsqlite3_strnicmp(tls, z+uintptr(i), _aNanInfName[k1].FzMatch, nn) != 0 {
|
|
goto _51
|
|
}
|
|
if libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(i+libc.Uint32FromInt32(nn)))))])&int32(0x06) != 0 {
|
|
goto _51
|
|
}
|
|
if libc.Int32FromUint8(_aNanInfName[k1].FeType) == int32(JSONB_FLOAT) {
|
|
_jsonBlobAppendNode(tls, pParse, uint8(JSONB_FLOAT), uint64(5), __ccgo_ts+26591)
|
|
} else {
|
|
_jsonBlobAppendOneByte(tls, pParse, uint8(JSONB_NULL))
|
|
}
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FhasNonstd = uint8(1)
|
|
return libc.Int32FromUint32(i + libc.Uint32FromInt32(nn))
|
|
goto _51
|
|
_51:
|
|
;
|
|
k1 = k1 + 1
|
|
}
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiErr = i
|
|
return -int32(1) /* Syntax error */
|
|
_39:
|
|
; /* End switch(z[i]) */
|
|
return r
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Open a file descriptor to the directory containing file zFilename.
|
|
// ** If successful, *pFd is set to the opened file descriptor and
|
|
// ** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
|
|
// ** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
|
|
// ** value.
|
|
// **
|
|
// ** The directory file descriptor is used for only one thing - to
|
|
// ** fsync() a directory to make sure file creation and deletion events
|
|
// ** are flushed to disk. Such fsyncs are not needed on newer
|
|
// ** journaling filesystems, but are required on older filesystems.
|
|
// **
|
|
// ** This routine can be overridden using the xSetSysCall interface.
|
|
// ** The ability to override this routine was added in support of the
|
|
// ** chromium sandbox. Opening a directory is a security risk (we are
|
|
// ** told) so making it overrideable allows the chromium sandbox to
|
|
// ** replace this routine with a harmless no-op. To make this routine
|
|
// ** a no-op, replace it with a stub that returns SQLITE_OK but leaves
|
|
// ** *pFd set to a negative number.
|
|
// **
|
|
// ** If SQLITE_OK is returned, the caller is responsible for closing
|
|
// ** the file descriptor *pFd using close().
|
|
// */
|
|
func _openDirectory(tls *libc.TLS, zFilename uintptr, pFd uintptr) (r int32) {
|
|
bp := tls.Alloc(544)
|
|
defer tls.Free(544)
|
|
var fd, ii int32
|
|
var _ /* zDirname at bp+0 */ [513]uint8
|
|
_, _ = fd, ii
|
|
fd = -int32(1)
|
|
Xsqlite3_snprintf(tls, int32(MAX_PATHNAME), bp, __ccgo_ts+3968, libc.VaList(bp+528, zFilename))
|
|
ii = libc.Int32FromUint64(libc.Xstrlen(tls, bp))
|
|
for {
|
|
if !(ii > 0 && libc.Int32FromUint8((**(**[513]uint8)(__ccgo_up(bp)))[ii]) != int32('/')) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii - 1
|
|
}
|
|
if ii > 0 {
|
|
(**(**[513]uint8)(__ccgo_up(bp)))[ii] = uint8('\000')
|
|
} else {
|
|
if libc.Int32FromUint8((**(**[513]uint8)(__ccgo_up(bp)))[0]) != int32('/') {
|
|
(**(**[513]uint8)(__ccgo_up(bp)))[0] = uint8('.')
|
|
}
|
|
(**(**[513]uint8)(__ccgo_up(bp)))[int32(1)] = uint8(0)
|
|
}
|
|
fd = _robust_open(tls, bp, libc.Int32FromInt32(O_RDONLY)|libc.Int32FromInt32(O_BINARY), uint32(0))
|
|
if fd >= 0 {
|
|
}
|
|
**(**int32)(__ccgo_up(pFd)) = fd
|
|
if fd >= 0 {
|
|
return SQLITE_OK
|
|
}
|
|
return _unixLogErrorAtLine(tls, _sqlite3CantopenError(tls, int32(44235)), __ccgo_ts+3659, bp, int32(44235))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Check if zSuper is a valid super-journal name. There are two valid
|
|
// ** formats:
|
|
// **
|
|
// ** + The 3rd and 4th last bytes of the filename are ".9", and the
|
|
// ** following 2 bytes are hex digits. This is a file created in 8.3
|
|
// ** filenames mode.
|
|
// **
|
|
// ** + The 3rd last byte of the filename is "9" and the filename
|
|
// ** contains the string "-mj" starting at the 12th last byte.
|
|
// ** All bytes following the "-mj" are hex digits.
|
|
// **
|
|
// ** If the filename matches either of these patterns, return non-zero.
|
|
// ** Otherwise, return zero.
|
|
// */
|
|
func _pagerIsSuperJrnlName(tls *libc.TLS, zSuper uintptr) (r int32) {
|
|
var ii, nSuper int32
|
|
_, _ = ii, nSuper
|
|
nSuper = _sqlite3Strlen30(tls, zSuper)
|
|
if nSuper < int32(4) {
|
|
return 0
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zSuper + uintptr(nSuper-int32(3))))) != int32('9') {
|
|
return 0
|
|
}
|
|
if nSuper < int32(12) {
|
|
return 0
|
|
}
|
|
if libc.Xmemcmp(tls, zSuper+uintptr(nSuper-int32(12)), __ccgo_ts+4224, uint64(3)) != 0 {
|
|
return 0
|
|
}
|
|
ii = nSuper - int32(9)
|
|
for {
|
|
if !(ii < nSuper) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(zSuper + uintptr(ii))))])&int32(0x08) == 0 {
|
|
return 0
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
return int32(1)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Pragma virtual table module xConnect method.
|
|
// */
|
|
func _pragmaVtabConnect(tls *libc.TLS, db uintptr, pAux uintptr, argc int32, argv uintptr, ppVtab uintptr, pzErr uintptr) (r int32) {
|
|
bp := tls.Alloc(256)
|
|
defer tls.Free(256)
|
|
var cSep uint8
|
|
var i, j, rc int32
|
|
var pPragma, pTab uintptr
|
|
var _ /* acc at bp+0 */ TStrAccum
|
|
var _ /* zBuf at bp+32 */ [200]uint8
|
|
_, _, _, _, _, _ = cSep, i, j, pPragma, pTab, rc
|
|
pPragma = pAux
|
|
pTab = uintptr(0)
|
|
cSep = uint8('(')
|
|
_ = argc
|
|
_ = argv
|
|
_sqlite3StrAccumInit(tls, bp, uintptr(0), bp+32, int32(200), 0)
|
|
Xsqlite3_str_appendall(tls, bp, __ccgo_ts+19934)
|
|
i = 0
|
|
j = libc.Int32FromUint8((*TPragmaName)(unsafe.Pointer(pPragma)).FiPragCName)
|
|
for {
|
|
if !(i < libc.Int32FromUint8((*TPragmaName)(unsafe.Pointer(pPragma)).FnPragCName)) {
|
|
break
|
|
}
|
|
Xsqlite3_str_appendf(tls, bp, __ccgo_ts+19949, libc.VaList(bp+240, libc.Int32FromUint8(cSep), _pragCName[j]))
|
|
cSep = uint8(',')
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
j = j + 1
|
|
}
|
|
if i == 0 {
|
|
Xsqlite3_str_appendf(tls, bp, __ccgo_ts+19956, libc.VaList(bp+240, (*TPragmaName)(unsafe.Pointer(pPragma)).FzName))
|
|
i = i + 1
|
|
}
|
|
j = 0
|
|
if libc.Int32FromUint8((*TPragmaName)(unsafe.Pointer(pPragma)).FmPragFlg)&int32(PragFlg_Result1) != 0 {
|
|
Xsqlite3_str_appendall(tls, bp, __ccgo_ts+19962)
|
|
j = j + 1
|
|
}
|
|
if libc.Int32FromUint8((*TPragmaName)(unsafe.Pointer(pPragma)).FmPragFlg)&(libc.Int32FromInt32(PragFlg_SchemaOpt)|libc.Int32FromInt32(PragFlg_SchemaReq)) != 0 {
|
|
Xsqlite3_str_appendall(tls, bp, __ccgo_ts+19974)
|
|
j = j + 1
|
|
}
|
|
Xsqlite3_str_append(tls, bp, __ccgo_ts+5285, int32(1))
|
|
_sqlite3StrAccumFinish(tls, bp)
|
|
rc = Xsqlite3_declare_vtab(tls, db, bp+32)
|
|
if rc == SQLITE_OK {
|
|
pTab = Xsqlite3_malloc(tls, int32(48))
|
|
if pTab == uintptr(0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
} else {
|
|
libc.Xmemset(tls, pTab, 0, uint64(48))
|
|
(*TPragmaVtab)(unsafe.Pointer(pTab)).FpName = pPragma
|
|
(*TPragmaVtab)(unsafe.Pointer(pTab)).Fdb = db
|
|
(*TPragmaVtab)(unsafe.Pointer(pTab)).FiHidden = libc.Uint8FromInt32(i)
|
|
(*TPragmaVtab)(unsafe.Pointer(pTab)).FnHidden = libc.Uint8FromInt32(j)
|
|
}
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+3968, libc.VaList(bp+240, Xsqlite3_errmsg(tls, db)))
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppVtab)) = pTab
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If the error code currently stored in the RBU handle is SQLITE_CONSTRAINT,
|
|
// ** then edit any error message string so as to remove all occurrences of
|
|
// ** the pattern "rbu_imp_[0-9]*".
|
|
// */
|
|
func _rbuEditErrmsg(tls *libc.TLS, p uintptr) {
|
|
var i uint32
|
|
var nDel int32
|
|
var nErrmsg Tsize_t
|
|
_, _, _ = i, nDel, nErrmsg
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == int32(SQLITE_CONSTRAINT) && (*Tsqlite3rbu)(unsafe.Pointer(p)).FzErrmsg != 0 {
|
|
nErrmsg = libc.Xstrlen(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).FzErrmsg)
|
|
i = uint32(0)
|
|
for {
|
|
if !(uint64(i) < nErrmsg-uint64(8)) {
|
|
break
|
|
}
|
|
if libc.Xmemcmp(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).FzErrmsg+uintptr(i), __ccgo_ts+32723, uint64(8)) == 0 {
|
|
nDel = int32(8)
|
|
for libc.Int32FromUint8(**(**uint8)(__ccgo_up((*Tsqlite3rbu)(unsafe.Pointer(p)).FzErrmsg + uintptr(i+libc.Uint32FromInt32(nDel))))) >= int32('0') && libc.Int32FromUint8(**(**uint8)(__ccgo_up((*Tsqlite3rbu)(unsafe.Pointer(p)).FzErrmsg + uintptr(i+libc.Uint32FromInt32(nDel))))) <= int32('9') {
|
|
nDel = nDel + 1
|
|
}
|
|
libc.Xmemmove(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).FzErrmsg+uintptr(i), (*Tsqlite3rbu)(unsafe.Pointer(p)).FzErrmsg+uintptr(i+libc.Uint32FromInt32(nDel)), nErrmsg+uint64(1)-uint64(i)-libc.Uint64FromInt32(nDel))
|
|
nErrmsg = nErrmsg - libc.Uint64FromInt32(nDel)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
}
|
|
|
|
func _rbuObjIterGetIndexWhere(tls *libc.TLS, p uintptr, pIter uintptr) (r uintptr) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var aIdxCol, zRet, zSql, v1 uintptr
|
|
var c uint8
|
|
var i, iIdxCol, nIdxAlloc, nParen, nSpan, nSpan1, rc2, v3 int32
|
|
var _ /* pStmt at bp+0 */ uintptr
|
|
var _ /* rc at bp+8 */ int32
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _ = aIdxCol, c, i, iIdxCol, nIdxAlloc, nParen, nSpan, nSpan1, rc2, zRet, zSql, v1, v3
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
**(**int32)(__ccgo_up(bp + 8)) = (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc
|
|
zRet = uintptr(0)
|
|
if **(**int32)(__ccgo_up(bp + 8)) == SQLITE_OK {
|
|
**(**int32)(__ccgo_up(bp + 8)) = _prepareAndCollectError(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).FdbMain, bp, p+64, __ccgo_ts+32211)
|
|
}
|
|
if **(**int32)(__ccgo_up(bp + 8)) == SQLITE_OK {
|
|
**(**int32)(__ccgo_up(bp + 8)) = Xsqlite3_bind_text(tls, **(**uintptr)(__ccgo_up(bp)), int32(1), (*TRbuObjIter)(unsafe.Pointer(pIter)).FzIdx, -int32(1), libc.UintptrFromInt32(0))
|
|
if **(**int32)(__ccgo_up(bp + 8)) == SQLITE_OK && int32(SQLITE_ROW) == Xsqlite3_step(tls, **(**uintptr)(__ccgo_up(bp))) {
|
|
zSql = Xsqlite3_column_text(tls, **(**uintptr)(__ccgo_up(bp)), 0)
|
|
if zSql != 0 {
|
|
v1 = _rbuStrndup(tls, zSql, bp+8)
|
|
zSql = v1
|
|
(*TRbuObjIter)(unsafe.Pointer(pIter)).FzIdxSql = v1
|
|
}
|
|
if zSql != 0 {
|
|
nParen = 0
|
|
iIdxCol = 0
|
|
nIdxAlloc = 0
|
|
i = 0
|
|
for {
|
|
if !(**(**uint8)(__ccgo_up(zSql + uintptr(i))) != 0) {
|
|
break
|
|
}
|
|
c = **(**uint8)(__ccgo_up(zSql + uintptr(i)))
|
|
/* If necessary, grow the pIter->aIdxCol[] array */
|
|
if iIdxCol == nIdxAlloc {
|
|
aIdxCol = Xsqlite3_realloc64(tls, (*TRbuObjIter)(unsafe.Pointer(pIter)).FaIdxCol, uint64(libc.Uint64FromInt32(nIdxAlloc)*uint64(16)+libc.Uint64FromInt32(16)*libc.Uint64FromInt64(16)))
|
|
if aIdxCol == uintptr(0) {
|
|
**(**int32)(__ccgo_up(bp + 8)) = int32(SQLITE_NOMEM)
|
|
break
|
|
}
|
|
(*TRbuObjIter)(unsafe.Pointer(pIter)).FaIdxCol = aIdxCol
|
|
nIdxAlloc = nIdxAlloc + int32(16)
|
|
}
|
|
if libc.Int32FromUint8(c) == int32('(') {
|
|
if nParen == 0 {
|
|
(**(**TRbuSpan)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FaIdxCol))).FzSpan = zSql + uintptr(i+int32(1))
|
|
}
|
|
nParen = nParen + 1
|
|
} else {
|
|
if libc.Int32FromUint8(c) == int32(')') {
|
|
nParen = nParen - 1
|
|
if nParen == 0 {
|
|
nSpan = int32(t__predefined_ptrdiff_t(zSql+uintptr(i)) - int64((**(**TRbuSpan)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FaIdxCol + uintptr(iIdxCol)*16))).FzSpan))
|
|
v3 = iIdxCol
|
|
iIdxCol = iIdxCol + 1
|
|
(**(**TRbuSpan)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FaIdxCol + uintptr(v3)*16))).FnSpan = nSpan
|
|
i = i + 1
|
|
break
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint8(c) == int32(',') && nParen == int32(1) {
|
|
nSpan1 = int32(t__predefined_ptrdiff_t(zSql+uintptr(i)) - int64((**(**TRbuSpan)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FaIdxCol + uintptr(iIdxCol)*16))).FzSpan))
|
|
v3 = iIdxCol
|
|
iIdxCol = iIdxCol + 1
|
|
(**(**TRbuSpan)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FaIdxCol + uintptr(v3)*16))).FnSpan = nSpan1
|
|
(**(**TRbuSpan)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FaIdxCol + uintptr(iIdxCol)*16))).FzSpan = zSql + uintptr(i+int32(1))
|
|
} else {
|
|
if libc.Int32FromUint8(c) == int32('"') || libc.Int32FromUint8(c) == int32('\'') || libc.Int32FromUint8(c) == int32('`') {
|
|
i = i + 1
|
|
for {
|
|
if !(int32(1) != 0) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zSql + uintptr(i)))) == libc.Int32FromUint8(c) {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zSql + uintptr(i+int32(1))))) != libc.Int32FromUint8(c) {
|
|
break
|
|
}
|
|
i = i + 1
|
|
}
|
|
goto _5
|
|
_5:
|
|
;
|
|
i = i + 1
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint8(c) == int32('[') {
|
|
i = i + 1
|
|
for {
|
|
if !(int32(1) != 0) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zSql + uintptr(i)))) == int32(']') {
|
|
break
|
|
}
|
|
goto _6
|
|
_6:
|
|
;
|
|
i = i + 1
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint8(c) == int32('-') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zSql + uintptr(i+int32(1))))) == int32('-') {
|
|
i = i + int32(2)
|
|
for {
|
|
if !(**(**uint8)(__ccgo_up(zSql + uintptr(i))) != 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zSql + uintptr(i)))) != int32('\n')) {
|
|
break
|
|
}
|
|
goto _7
|
|
_7:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zSql + uintptr(i)))) == int32('\000') {
|
|
break
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint8(c) == int32('/') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zSql + uintptr(i+int32(1))))) == int32('*') {
|
|
i = i + int32(2)
|
|
for {
|
|
if !(**(**uint8)(__ccgo_up(zSql + uintptr(i))) != 0 && (libc.Int32FromUint8(**(**uint8)(__ccgo_up(zSql + uintptr(i)))) != int32('*') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zSql + uintptr(i+int32(1))))) != int32('/'))) {
|
|
break
|
|
}
|
|
goto _8
|
|
_8:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zSql + uintptr(i)))) == int32('\000') {
|
|
break
|
|
}
|
|
i = i + 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if **(**uint8)(__ccgo_up(zSql + uintptr(i))) != 0 {
|
|
zRet = _rbuStrndup(tls, zSql+uintptr(i), bp+8)
|
|
}
|
|
(*TRbuObjIter)(unsafe.Pointer(pIter)).FnIdxCol = iIdxCol
|
|
}
|
|
}
|
|
rc2 = Xsqlite3_finalize(tls, **(**uintptr)(__ccgo_up(bp)))
|
|
if **(**int32)(__ccgo_up(bp + 8)) == SQLITE_OK {
|
|
**(**int32)(__ccgo_up(bp + 8)) = rc2
|
|
}
|
|
}
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = **(**int32)(__ccgo_up(bp + 8))
|
|
return zRet
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return a nul-terminated string containing the comma separated list of
|
|
// ** assignments that should be included following the "SET" keyword of
|
|
// ** an UPDATE statement used to update the table object that the iterator
|
|
// ** passed as the second argument currently points to if the rbu_control
|
|
// ** column of the data_xxx table entry is set to zMask.
|
|
// **
|
|
// ** The memory for the returned string is obtained from sqlite3_malloc().
|
|
// ** It is the responsibility of the caller to eventually free it using
|
|
// ** sqlite3_free().
|
|
// **
|
|
// ** If an OOM error is encountered when allocating space for the new
|
|
// ** string, an error code is left in the rbu handle passed as the first
|
|
// ** argument and NULL is returned. Or, if an error has already occurred
|
|
// ** when this function is called, NULL is returned immediately, without
|
|
// ** attempting the allocation or modifying the stored error code.
|
|
// */
|
|
func _rbuObjIterGetSetlist(tls *libc.TLS, p uintptr, pIter uintptr, zMask uintptr) (r uintptr) {
|
|
bp := tls.Alloc(48)
|
|
defer tls.Free(48)
|
|
var c uint8
|
|
var i int32
|
|
var zList, zSep uintptr
|
|
_, _, _, _ = c, i, zList, zSep
|
|
zList = uintptr(0)
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK {
|
|
if libc.Int32FromUint64(libc.Xstrlen(tls, zMask)) != (*TRbuObjIter)(unsafe.Pointer(pIter)).FnTblCol {
|
|
_rbuBadControlError(tls, p)
|
|
} else {
|
|
zSep = __ccgo_ts + 1704
|
|
i = 0
|
|
for {
|
|
if !(i < (*TRbuObjIter)(unsafe.Pointer(pIter)).FnTblCol) {
|
|
break
|
|
}
|
|
c = **(**uint8)(__ccgo_up(zMask + uintptr(**(**int32)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FaiSrcOrder + uintptr(i)*4)))))
|
|
if libc.Int32FromUint8(c) == int32('x') {
|
|
zList = _rbuMPrintf(tls, p, __ccgo_ts+31757, libc.VaList(bp+8, zList, zSep, **(**uintptr)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FazTblCol + uintptr(i)*8)), i+int32(1)))
|
|
zSep = __ccgo_ts + 16242
|
|
} else {
|
|
if libc.Int32FromUint8(c) == int32('d') {
|
|
zList = _rbuMPrintf(tls, p, __ccgo_ts+31796, libc.VaList(bp+8, zList, zSep, **(**uintptr)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FazTblCol + uintptr(i)*8)), **(**uintptr)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FazTblCol + uintptr(i)*8)), i+int32(1)))
|
|
zSep = __ccgo_ts + 16242
|
|
} else {
|
|
if libc.Int32FromUint8(c) == int32('f') {
|
|
zList = _rbuMPrintf(tls, p, __ccgo_ts+31826, libc.VaList(bp+8, zList, zSep, **(**uintptr)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FazTblCol + uintptr(i)*8)), **(**uintptr)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FazTblCol + uintptr(i)*8)), i+int32(1)))
|
|
zSep = __ccgo_ts + 16242
|
|
}
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
}
|
|
return zList
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Open the database handle and attach the RBU database as "rbu". If an
|
|
// ** error occurs, leave an error code and message in the RBU handle.
|
|
// **
|
|
// ** If argument dbMain is not NULL, then it is a database handle already
|
|
// ** open on the target database. Use this handle instead of opening a new
|
|
// ** one.
|
|
// */
|
|
func _rbuOpenDatabase(tls *libc.TLS, p uintptr, dbMain uintptr, pbRetry uintptr) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var bOpen, rc int32
|
|
var pState, zExtra, zFile, zTarget, v1, v2 uintptr
|
|
_, _, _, _, _, _, _, _ = bOpen, pState, rc, zExtra, zFile, zTarget, v1, v2
|
|
/* Open the RBU database */
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).FdbRbu = _rbuOpenDbhandle(tls, p, (*Tsqlite3rbu)(unsafe.Pointer(p)).FzRbu, int32(1))
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).FdbMain = dbMain
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK && (*Tsqlite3rbu)(unsafe.Pointer(p)).FzTarget == uintptr(0) {
|
|
Xsqlite3_file_control(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).FdbRbu, __ccgo_ts+6844, int32(SQLITE_FCNTL_RBUCNT), p)
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).FzState == uintptr(0) {
|
|
zFile = Xsqlite3_db_filename(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).FdbRbu, __ccgo_ts+6844)
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).FzState = _rbuMPrintf(tls, p, __ccgo_ts+33444, libc.VaList(bp+8, zFile, zFile))
|
|
}
|
|
}
|
|
/* If using separate RBU and state databases, attach the state database to
|
|
** the RBU db handle now. */
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).FzState != 0 {
|
|
_rbuMPrintfExec(tls, p, (*Tsqlite3rbu)(unsafe.Pointer(p)).FdbRbu, __ccgo_ts+33472, libc.VaList(bp+8, (*Tsqlite3rbu)(unsafe.Pointer(p)).FzState))
|
|
libc.Xmemcpy(tls, p+48, __ccgo_ts+3567, uint64(4))
|
|
} else {
|
|
libc.Xmemcpy(tls, p+48, __ccgo_ts+6844, uint64(4))
|
|
}
|
|
/* If it has not already been created, create the rbu_state table */
|
|
_rbuMPrintfExec(tls, p, (*Tsqlite3rbu)(unsafe.Pointer(p)).FdbRbu, __ccgo_ts+33490, libc.VaList(bp+8, p+48))
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK && (*Tsqlite3rbu)(unsafe.Pointer(p)).FzTarget == uintptr(0) {
|
|
bOpen = 0
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).FnRbu = 0
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).FpRbuFd = uintptr(0)
|
|
rc = Xsqlite3_file_control(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).FdbRbu, __ccgo_ts+6844, int32(SQLITE_FCNTL_RBUCNT), p)
|
|
if rc != int32(SQLITE_NOTFOUND) {
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = rc
|
|
}
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).FeStage >= int32(RBU_STAGE_MOVE) {
|
|
bOpen = int32(1)
|
|
} else {
|
|
pState = _rbuLoadState(tls, p)
|
|
if pState != 0 {
|
|
bOpen = libc.BoolInt32((*TRbuState)(unsafe.Pointer(pState)).FeStage >= int32(RBU_STAGE_MOVE))
|
|
_rbuFreeState(tls, pState)
|
|
}
|
|
}
|
|
if bOpen != 0 {
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).FdbMain = _rbuOpenDbhandle(tls, p, (*Tsqlite3rbu)(unsafe.Pointer(p)).FzRbu, libc.BoolInt32((*Tsqlite3rbu)(unsafe.Pointer(p)).FnRbu <= int32(1)))
|
|
}
|
|
}
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).FeStage = 0
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK && (*Tsqlite3rbu)(unsafe.Pointer(p)).FdbMain == uintptr(0) {
|
|
if !((*Tsqlite3rbu)(unsafe.Pointer(p)).FzTarget == libc.UintptrFromInt32(0)) {
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).FdbMain = _rbuOpenDbhandle(tls, p, (*Tsqlite3rbu)(unsafe.Pointer(p)).FzTarget, int32(1))
|
|
} else {
|
|
if (*Trbu_file)(unsafe.Pointer((*Tsqlite3rbu)(unsafe.Pointer(p)).FpRbuFd)).FpWalFd != 0 {
|
|
if pbRetry != 0 {
|
|
(*Trbu_file)(unsafe.Pointer((*Tsqlite3rbu)(unsafe.Pointer(p)).FpRbuFd)).FbNolock = uint8(0)
|
|
Xsqlite3_close(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).FdbRbu)
|
|
Xsqlite3_close(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).FdbMain)
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).FdbMain = uintptr(0)
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).FdbRbu = uintptr(0)
|
|
**(**int32)(__ccgo_up(pbRetry)) = int32(1)
|
|
return
|
|
}
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = int32(SQLITE_ERROR)
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).FzErrmsg = Xsqlite3_mprintf(tls, __ccgo_ts+33556, 0)
|
|
} else {
|
|
zExtra = uintptr(0)
|
|
if libc.Xstrlen(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).FzRbu) >= uint64(5) && 0 == libc.Xmemcmp(tls, __ccgo_ts+26142, (*Tsqlite3rbu)(unsafe.Pointer(p)).FzRbu, uint64(5)) {
|
|
zExtra = (*Tsqlite3rbu)(unsafe.Pointer(p)).FzRbu + 5
|
|
for **(**uint8)(__ccgo_up(zExtra)) != 0 {
|
|
v1 = zExtra
|
|
zExtra = zExtra + 1
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(v1))) == int32('?') {
|
|
break
|
|
}
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zExtra))) == int32('\000') {
|
|
zExtra = uintptr(0)
|
|
}
|
|
}
|
|
if zExtra == uintptr(0) {
|
|
v1 = __ccgo_ts + 1704
|
|
} else {
|
|
v1 = __ccgo_ts + 33588
|
|
}
|
|
if zExtra == uintptr(0) {
|
|
v2 = __ccgo_ts + 1704
|
|
} else {
|
|
v2 = zExtra
|
|
}
|
|
zTarget = Xsqlite3_mprintf(tls, __ccgo_ts+33590, libc.VaList(bp+8, Xsqlite3_db_filename(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).FdbRbu, __ccgo_ts+6844), v1, v2))
|
|
if zTarget == uintptr(0) {
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = int32(SQLITE_NOMEM)
|
|
return
|
|
}
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).FdbMain = _rbuOpenDbhandle(tls, p, zTarget, libc.BoolInt32((*Tsqlite3rbu)(unsafe.Pointer(p)).FnRbu <= int32(1)))
|
|
Xsqlite3_free(tls, zTarget)
|
|
}
|
|
}
|
|
}
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK {
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = Xsqlite3_create_function(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).FdbMain, __ccgo_ts+33622, -int32(1), int32(SQLITE_UTF8), p, __ccgo_fp(_rbuTmpInsertFunc), uintptr(0), uintptr(0))
|
|
}
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK {
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = Xsqlite3_create_function(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).FdbMain, __ccgo_ts+33637, int32(2), int32(SQLITE_UTF8), uintptr(0), __ccgo_fp(_rbuFossilDeltaFunc), uintptr(0), uintptr(0))
|
|
}
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK {
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = Xsqlite3_create_function(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).FdbRbu, __ccgo_ts+33654, -int32(1), int32(SQLITE_UTF8), p, __ccgo_fp(_rbuTargetNameFunc), uintptr(0), uintptr(0))
|
|
}
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK {
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = Xsqlite3_file_control(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).FdbMain, __ccgo_ts+6844, int32(SQLITE_FCNTL_RBU), p)
|
|
}
|
|
_rbuMPrintfExec(tls, p, (*Tsqlite3rbu)(unsafe.Pointer(p)).FdbMain, __ccgo_ts+33670, 0)
|
|
/* Mark the database file just opened as an RBU target database. If
|
|
** this call returns SQLITE_NOTFOUND, then the RBU vfs is not in use.
|
|
** This is an error. */
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK {
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = Xsqlite3_file_control(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).FdbMain, __ccgo_ts+6844, int32(SQLITE_FCNTL_RBU), p)
|
|
}
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == int32(SQLITE_NOTFOUND) {
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = int32(SQLITE_ERROR)
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).FzErrmsg = Xsqlite3_mprintf(tls, __ccgo_ts+33698, 0)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The implementation of the rbu_target_name() SQL function. This function
|
|
// ** accepts one or two arguments. The first argument is the name of a table -
|
|
// ** the name of a table in the RBU database. The second, if it is present, is 1
|
|
// ** for a view or 0 for a table.
|
|
// **
|
|
// ** For a non-vacuum RBU handle, if the table name matches the pattern:
|
|
// **
|
|
// ** data[0-9]_<name>
|
|
// **
|
|
// ** where <name> is any sequence of 1 or more characters, <name> is returned.
|
|
// ** Otherwise, if the only argument does not match the above pattern, an SQL
|
|
// ** NULL is returned.
|
|
// **
|
|
// ** "data_t1" -> "t1"
|
|
// ** "data0123_t2" -> "t2"
|
|
// ** "dataAB_t3" -> NULL
|
|
// **
|
|
// ** For an rbu vacuum handle, a copy of the first argument is returned if
|
|
// ** the second argument is either missing or 0 (not a view).
|
|
// */
|
|
func _rbuTargetNameFunc(tls *libc.TLS, pCtx uintptr, argc int32, argv uintptr) {
|
|
var i int32
|
|
var p, zIn uintptr
|
|
_, _, _ = i, p, zIn
|
|
p = Xsqlite3_user_data(tls, pCtx)
|
|
zIn = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
if zIn != 0 {
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).FzTarget == uintptr(0) {
|
|
if argc == int32(1) || 0 == Xsqlite3_value_int(tls, **(**uintptr)(__ccgo_up(argv + 1*8))) {
|
|
Xsqlite3_result_text(tls, pCtx, zIn, -int32(1), libc.UintptrFromInt32(0))
|
|
}
|
|
} else {
|
|
if libc.Xstrlen(tls, zIn) > uint64(4) && libc.Xmemcmp(tls, __ccgo_ts+27432, zIn, uint64(4)) == 0 {
|
|
i = int32(4)
|
|
for {
|
|
if !(libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn + uintptr(i)))) >= int32('0') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn + uintptr(i)))) <= int32('9')) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn + uintptr(i)))) == int32('_') && **(**uint8)(__ccgo_up(zIn + uintptr(i+int32(1)))) != 0 {
|
|
Xsqlite3_result_text(tls, pCtx, zIn+uintptr(i+int32(1)), -int32(1), libc.UintptrFromInt32(0))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is called as part of restating an RBU vacuum when the
|
|
// ** current operation is writing content to an index. If possible, it
|
|
// ** queries the target index b-tree for the largest key already written to
|
|
// ** it, then composes and returns an expression that can be used in a WHERE
|
|
// ** clause to select the remaining required rows from the source table.
|
|
// ** It is only possible to return such an expression if:
|
|
// **
|
|
// ** * The index contains no DESC columns, and
|
|
// ** * The last key written to the index before the operation was
|
|
// ** suspended does not contain any NULL values.
|
|
// **
|
|
// ** The expression is of the form:
|
|
// **
|
|
// ** (index-field1, index-field2, ...) > (?, ?, ...)
|
|
// **
|
|
// ** except that the "?" placeholders are replaced with literal values.
|
|
// **
|
|
// ** If the expression cannot be created, NULL is returned. In this case,
|
|
// ** the caller has to use an OFFSET clause to extract only the required
|
|
// ** rows from the sourct table, just as it does for an RBU update operation.
|
|
// */
|
|
func _rbuVacuumIndexStart(tls *libc.TLS, p uintptr, pIter uintptr) (r uintptr) {
|
|
bp := tls.Alloc(64)
|
|
defer tls.Free(64)
|
|
var bFailed, i, iCid, iCol int32
|
|
var zCol, zCollate, zLhs, zOrder, zQuoted, zRet, zSelect, zSep, zVector uintptr
|
|
var _ /* pSel at bp+8 */ uintptr
|
|
var _ /* pXInfo at bp+0 */ uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _ = bFailed, i, iCid, iCol, zCol, zCollate, zLhs, zOrder, zQuoted, zRet, zSelect, zSep, zVector
|
|
zOrder = uintptr(0)
|
|
zLhs = uintptr(0)
|
|
zSelect = uintptr(0)
|
|
zVector = uintptr(0)
|
|
zRet = uintptr(0)
|
|
bFailed = 0
|
|
zSep = __ccgo_ts + 1704
|
|
iCol = 0
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = _prepareFreeAndCollectError(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).FdbMain, bp, p+64, Xsqlite3_mprintf(tls, __ccgo_ts+31043, libc.VaList(bp+24, (*TRbuObjIter)(unsafe.Pointer(pIter)).FzIdx)))
|
|
for (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK && int32(SQLITE_ROW) == Xsqlite3_step(tls, **(**uintptr)(__ccgo_up(bp))) {
|
|
iCid = Xsqlite3_column_int(tls, **(**uintptr)(__ccgo_up(bp)), int32(1))
|
|
zCollate = Xsqlite3_column_text(tls, **(**uintptr)(__ccgo_up(bp)), int32(4))
|
|
if Xsqlite3_column_int(tls, **(**uintptr)(__ccgo_up(bp)), int32(3)) != 0 {
|
|
bFailed = int32(1)
|
|
break
|
|
}
|
|
if iCid < 0 {
|
|
if (*TRbuObjIter)(unsafe.Pointer(pIter)).FeType == int32(RBU_PK_IPK) {
|
|
i = 0
|
|
for {
|
|
if !(libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FabTblPk + uintptr(i)))) == 0) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
zCol = **(**uintptr)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FazTblCol + uintptr(i)*8))
|
|
} else {
|
|
zCol = __ccgo_ts + 31366
|
|
}
|
|
} else {
|
|
zCol = **(**uintptr)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FazTblCol + uintptr(iCid)*8))
|
|
}
|
|
zLhs = _rbuMPrintf(tls, p, __ccgo_ts+31374, libc.VaList(bp+24, zLhs, zSep, zCol, zCollate))
|
|
zOrder = _rbuMPrintf(tls, p, __ccgo_ts+31395, libc.VaList(bp+24, zOrder, zSep, iCol, zCol, zCollate))
|
|
zSelect = _rbuMPrintf(tls, p, __ccgo_ts+31431, libc.VaList(bp+24, zSelect, zSep, iCol, zCol))
|
|
zSep = __ccgo_ts + 16242
|
|
iCol = iCol + 1
|
|
}
|
|
_rbuFinalize(tls, p, **(**uintptr)(__ccgo_up(bp)))
|
|
if bFailed != 0 {
|
|
goto index_start_out
|
|
}
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK {
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = uintptr(0)
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = _prepareFreeAndCollectError(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).FdbMain, bp+8, p+64, Xsqlite3_mprintf(tls, __ccgo_ts+31458, libc.VaList(bp+24, zSelect, (*TRbuObjIter)(unsafe.Pointer(pIter)).FzTbl, zOrder)))
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK && int32(SQLITE_ROW) == Xsqlite3_step(tls, **(**uintptr)(__ccgo_up(bp + 8))) {
|
|
zSep = __ccgo_ts + 1704
|
|
iCol = 0
|
|
for {
|
|
if !(iCol < (*TRbuObjIter)(unsafe.Pointer(pIter)).FnCol) {
|
|
break
|
|
}
|
|
zQuoted = Xsqlite3_column_text(tls, **(**uintptr)(__ccgo_up(bp + 8)), iCol)
|
|
if zQuoted == uintptr(0) {
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = int32(SQLITE_NOMEM)
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zQuoted))) == int32('N') {
|
|
bFailed = int32(1)
|
|
break
|
|
}
|
|
}
|
|
zVector = _rbuMPrintf(tls, p, __ccgo_ts+31506, libc.VaList(bp+24, zVector, zSep, zQuoted))
|
|
zSep = __ccgo_ts + 16242
|
|
goto _2
|
|
_2:
|
|
;
|
|
iCol = iCol + 1
|
|
}
|
|
if !(bFailed != 0) {
|
|
zRet = _rbuMPrintf(tls, p, __ccgo_ts+31513, libc.VaList(bp+24, zLhs, zVector))
|
|
}
|
|
}
|
|
_rbuFinalize(tls, p, **(**uintptr)(__ccgo_up(bp + 8)))
|
|
}
|
|
goto index_start_out
|
|
index_start_out:
|
|
;
|
|
Xsqlite3_free(tls, zOrder)
|
|
Xsqlite3_free(tls, zSelect)
|
|
Xsqlite3_free(tls, zVector)
|
|
Xsqlite3_free(tls, zLhs)
|
|
return zRet
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Open an rbu file handle.
|
|
// */
|
|
func _rbuVfsOpen(tls *libc.TLS, pVfs uintptr, zName uintptr, pFile uintptr, flags int32, pOutFlags uintptr) (r int32) {
|
|
var nOpen Tsize_t
|
|
var oflags, rc int32
|
|
var pDb, pFd, pMeth, pRbuVfs, pRealVfs, zOpen uintptr
|
|
_, _, _, _, _, _, _, _, _ = nOpen, oflags, pDb, pFd, pMeth, pRbuVfs, pRealVfs, rc, zOpen
|
|
pRbuVfs = pVfs
|
|
pRealVfs = (*Trbu_vfs)(unsafe.Pointer(pRbuVfs)).FpRealVfs
|
|
pFd = pFile
|
|
rc = SQLITE_OK
|
|
zOpen = zName
|
|
oflags = flags
|
|
libc.Xmemset(tls, pFd, 0, uint64(104))
|
|
(*Trbu_file)(unsafe.Pointer(pFd)).FpReal = pFd + 1*104
|
|
(*Trbu_file)(unsafe.Pointer(pFd)).FpRbuVfs = pRbuVfs
|
|
(*Trbu_file)(unsafe.Pointer(pFd)).FopenFlags = flags
|
|
if zName != 0 {
|
|
if flags&int32(SQLITE_OPEN_MAIN_DB) != 0 {
|
|
/* A main database has just been opened. The following block sets
|
|
** (pFd->zWal) to point to a buffer owned by SQLite that contains
|
|
** the name of the *-wal file this db connection will use. SQLite
|
|
** happens to pass a pointer to this buffer when using xAccess()
|
|
** or xOpen() to operate on the *-wal file. */
|
|
(*Trbu_file)(unsafe.Pointer(pFd)).FzWal = Xsqlite3_filename_wal(tls, zName)
|
|
} else {
|
|
if flags&int32(SQLITE_OPEN_WAL) != 0 {
|
|
pDb = _rbuFindMaindb(tls, pRbuVfs, zName, 0)
|
|
if pDb != 0 {
|
|
if (*Trbu_file)(unsafe.Pointer(pDb)).FpRbu != 0 && (*Tsqlite3rbu)(unsafe.Pointer((*Trbu_file)(unsafe.Pointer(pDb)).FpRbu)).FeStage == int32(RBU_STAGE_OAL) {
|
|
if (*Tsqlite3rbu)(unsafe.Pointer((*Trbu_file)(unsafe.Pointer(pDb)).FpRbu)).FzTarget == uintptr(0) {
|
|
zOpen = Xsqlite3_db_filename(tls, (*Tsqlite3rbu)(unsafe.Pointer((*Trbu_file)(unsafe.Pointer(pDb)).FpRbu)).FdbRbu, __ccgo_ts+6844)
|
|
zOpen = Xsqlite3_filename_wal(tls, zOpen)
|
|
}
|
|
nOpen = libc.Xstrlen(tls, zOpen)
|
|
**(**uint8)(__ccgo_up(zOpen + uintptr(nOpen-uint64(3)))) = uint8('o')
|
|
(*Trbu_file)(unsafe.Pointer(pFd)).FpRbu = (*Trbu_file)(unsafe.Pointer(pDb)).FpRbu
|
|
}
|
|
(*Trbu_file)(unsafe.Pointer(pDb)).FpWalFd = pFd
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
(*Trbu_file)(unsafe.Pointer(pFd)).FpRbu = (*Trbu_vfs)(unsafe.Pointer(pRbuVfs)).FpRbu
|
|
}
|
|
if oflags&int32(SQLITE_OPEN_MAIN_DB) != 0 && Xsqlite3_uri_boolean(tls, zName, __ccgo_ts+34769, 0) != 0 {
|
|
oflags = libc.Int32FromInt32(SQLITE_OPEN_TEMP_DB) | libc.Int32FromInt32(SQLITE_OPEN_READWRITE) | libc.Int32FromInt32(SQLITE_OPEN_CREATE) | libc.Int32FromInt32(SQLITE_OPEN_EXCLUSIVE) | libc.Int32FromInt32(SQLITE_OPEN_DELETEONCLOSE)
|
|
zOpen = uintptr(0)
|
|
}
|
|
if rc == SQLITE_OK {
|
|
rc = (*(*func(*libc.TLS, uintptr, Tsqlite3_filename, uintptr, int32, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{(*Tsqlite3_vfs)(unsafe.Pointer(pRealVfs)).FxOpen})))(tls, pRealVfs, zOpen, (*Trbu_file)(unsafe.Pointer(pFd)).FpReal, oflags, pOutFlags)
|
|
}
|
|
if (*Tsqlite3_file)(unsafe.Pointer((*Trbu_file)(unsafe.Pointer(pFd)).FpReal)).FpMethods != 0 {
|
|
pMeth = (*Tsqlite3_file)(unsafe.Pointer((*Trbu_file)(unsafe.Pointer(pFd)).FpReal)).FpMethods
|
|
/* The xOpen() operation has succeeded. Set the sqlite3_file.pMethods
|
|
** pointer and, if the file is a main database file, link it into the
|
|
** mutex protected linked list of all such files. */
|
|
if (*Tsqlite3_io_methods)(unsafe.Pointer(pMeth)).FiVersion < int32(2) || (*Tsqlite3_io_methods)(unsafe.Pointer(pMeth)).FxShmLock == uintptr(0) {
|
|
(*Tsqlite3_file)(unsafe.Pointer(pFile)).FpMethods = uintptr(unsafe.Pointer(&_rbuvfs_io_methods1))
|
|
} else {
|
|
(*Tsqlite3_file)(unsafe.Pointer(pFile)).FpMethods = uintptr(unsafe.Pointer(&_rbuvfs_io_methods))
|
|
}
|
|
if flags&int32(SQLITE_OPEN_MAIN_DB) != 0 {
|
|
_rbuMainlistAdd(tls, pFd)
|
|
}
|
|
} else {
|
|
Xsqlite3_free(tls, (*Trbu_file)(unsafe.Pointer(pFd)).FzDel)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function edits SQL statement zSql, replacing each token identified
|
|
// ** by the linked list pRename with the text of zNew. If argument bQuote is
|
|
// ** true, then zNew is always quoted first. If no error occurs, the result
|
|
// ** is loaded into context object pCtx as the result.
|
|
// **
|
|
// ** Or, if an error occurs (i.e. an OOM condition), an error is left in
|
|
// ** pCtx and an SQLite error code returned.
|
|
// */
|
|
func _renameEditSql(tls *libc.TLS, pCtx uintptr, pRename uintptr, zSql uintptr, zNew uintptr, bQuote int32) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var db, pBest, zBuf1, zBuf2, zOut, zQuot, zReplace, v1 uintptr
|
|
var iOff, rc int32
|
|
var nNew, nOut, nQuot, nReplace, nSql Ti64
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = db, iOff, nNew, nOut, nQuot, nReplace, nSql, pBest, rc, zBuf1, zBuf2, zOut, zQuot, zReplace, v1
|
|
nNew = int64(_sqlite3Strlen30(tls, zNew))
|
|
nSql = int64(_sqlite3Strlen30(tls, zSql))
|
|
db = Xsqlite3_context_db_handle(tls, pCtx)
|
|
rc = SQLITE_OK
|
|
zQuot = uintptr(0)
|
|
nQuot = 0
|
|
zBuf1 = uintptr(0)
|
|
zBuf2 = uintptr(0)
|
|
if zNew != 0 {
|
|
/* Set zQuot to point to a buffer containing a quoted copy of the
|
|
** identifier zNew. If the corresponding identifier in the original
|
|
** ALTER TABLE statement was quoted (bQuote==1), then set zNew to
|
|
** point to zQuot so that all substitutions are made using the
|
|
** quoted version of the new column name. */
|
|
zQuot = _sqlite3MPrintf(tls, db, __ccgo_ts+11602, libc.VaList(bp+8, zNew))
|
|
if zQuot == uintptr(0) {
|
|
return int32(SQLITE_NOMEM)
|
|
} else {
|
|
nQuot = int64(_sqlite3Strlen30(tls, zQuot) - int32(1))
|
|
}
|
|
zOut = _sqlite3DbMallocZero(tls, db, libc.Uint64FromInt64(nSql)+libc.Uint64FromInt32((*TRenameCtx)(unsafe.Pointer(pRename)).FnList)*libc.Uint64FromInt64(nQuot)+uint64(1))
|
|
} else {
|
|
zOut = _sqlite3DbMallocZero(tls, db, (uint64(2)*libc.Uint64FromInt64(nSql)+uint64(1))*uint64(3))
|
|
if zOut != 0 {
|
|
zBuf1 = zOut + uintptr(nSql*int64(2)+int64(1))
|
|
zBuf2 = zOut + uintptr(nSql*int64(4)+int64(2))
|
|
}
|
|
}
|
|
/* At this point pRename->pList contains a list of RenameToken objects
|
|
** corresponding to all tokens in the input SQL that must be replaced
|
|
** with the new column name, or with single-quoted versions of themselves.
|
|
** All that remains is to construct and return the edited SQL string. */
|
|
if zOut != 0 {
|
|
nOut = nSql
|
|
libc.Xmemcpy(tls, zOut, zSql, libc.Uint64FromInt64(nSql))
|
|
for (*TRenameCtx)(unsafe.Pointer(pRename)).FpList != 0 {
|
|
pBest = _renameColumnTokenNext(tls, pRename)
|
|
if zNew != 0 {
|
|
if bQuote == 0 && _sqlite3IsIdChar(tls, **(**Tu8)(__ccgo_up((*TRenameToken)(unsafe.Pointer(pBest)).Ft.Fz))) != 0 {
|
|
nReplace = nNew
|
|
zReplace = zNew
|
|
} else {
|
|
nReplace = nQuot
|
|
zReplace = zQuot
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up((*TRenameToken)(unsafe.Pointer(pBest)).Ft.Fz + uintptr((*TRenameToken)(unsafe.Pointer(pBest)).Ft.Fn)))) == int32('"') {
|
|
nReplace = nReplace + 1
|
|
}
|
|
}
|
|
} else {
|
|
/* Dequote the double-quoted token. Then requote it again, this time
|
|
** using single quotes. If the character immediately following the
|
|
** original token within the input SQL was a single quote ('), then
|
|
** add another space after the new, single-quoted version of the
|
|
** token. This is so that (SELECT "string"'alias') maps to
|
|
** (SELECT 'string' 'alias'), and not (SELECT 'string''alias'). */
|
|
libc.Xmemcpy(tls, zBuf1, (*TRenameToken)(unsafe.Pointer(pBest)).Ft.Fz, uint64((*TRenameToken)(unsafe.Pointer(pBest)).Ft.Fn))
|
|
**(**uint8)(__ccgo_up(zBuf1 + uintptr((*TRenameToken)(unsafe.Pointer(pBest)).Ft.Fn))) = uint8(0)
|
|
_sqlite3Dequote(tls, zBuf1)
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up((*TRenameToken)(unsafe.Pointer(pBest)).Ft.Fz + uintptr((*TRenameToken)(unsafe.Pointer(pBest)).Ft.Fn)))) == int32('\'') {
|
|
v1 = __ccgo_ts + 11569
|
|
} else {
|
|
v1 = __ccgo_ts + 1704
|
|
}
|
|
Xsqlite3_snprintf(tls, int32(nSql*libc.Int64FromInt32(2)), zBuf2, __ccgo_ts+11608, libc.VaList(bp+8, zBuf1, v1))
|
|
zReplace = zBuf2
|
|
nReplace = int64(_sqlite3Strlen30(tls, zReplace))
|
|
}
|
|
iOff = int32(int64((*TRenameToken)(unsafe.Pointer(pBest)).Ft.Fz) - int64(zSql))
|
|
if libc.Int64FromUint32((*TRenameToken)(unsafe.Pointer(pBest)).Ft.Fn) != nReplace {
|
|
libc.Xmemmove(tls, zOut+uintptr(int64(iOff)+nReplace), zOut+uintptr(libc.Uint32FromInt32(iOff)+(*TRenameToken)(unsafe.Pointer(pBest)).Ft.Fn), libc.Uint64FromInt64(nOut-libc.Int64FromUint32(libc.Uint32FromInt32(iOff)+(*TRenameToken)(unsafe.Pointer(pBest)).Ft.Fn)))
|
|
nOut = nOut + (nReplace - libc.Int64FromUint32((*TRenameToken)(unsafe.Pointer(pBest)).Ft.Fn))
|
|
**(**uint8)(__ccgo_up(zOut + uintptr(nOut))) = uint8('\000')
|
|
}
|
|
libc.Xmemcpy(tls, zOut+uintptr(iOff), zReplace, libc.Uint64FromInt64(nReplace))
|
|
_sqlite3DbFree(tls, db, pBest)
|
|
}
|
|
Xsqlite3_result_text(tls, pCtx, zOut, -int32(1), uintptr(-libc.Int32FromInt32(1)))
|
|
_sqlite3DbFree(tls, db, zOut)
|
|
} else {
|
|
rc = int32(SQLITE_NOMEM)
|
|
}
|
|
Xsqlite3_free(tls, zQuot)
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is the implementation of both the xConnect and xCreate
|
|
// ** methods of the r-tree virtual table.
|
|
// **
|
|
// ** argv[0] -> module name
|
|
// ** argv[1] -> database name
|
|
// ** argv[2] -> table name
|
|
// ** argv[...] -> column names...
|
|
// */
|
|
func _rtreeInit(tls *libc.TLS, db uintptr, pAux uintptr, argc int32, argv uintptr, ppVtab uintptr, pzErr uintptr, isCreate int32) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var aErrMsg [5]uintptr
|
|
var eCoordType, iErr, ii, nDb, nName, rc, v1 int32
|
|
var pRtree, pSql, zArg, zSql uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _, _ = aErrMsg, eCoordType, iErr, ii, nDb, nName, pRtree, pSql, rc, zArg, zSql, v1
|
|
rc = SQLITE_OK
|
|
if pAux != 0 {
|
|
v1 = int32(RTREE_COORD_INT32)
|
|
} else {
|
|
v1 = RTREE_COORD_REAL32
|
|
} /* Length of string argv[2] */
|
|
eCoordType = v1
|
|
ii = int32(4)
|
|
aErrMsg = [5]uintptr{
|
|
1: __ccgo_ts + 28825,
|
|
2: __ccgo_ts + 28868,
|
|
3: __ccgo_ts + 28903,
|
|
4: __ccgo_ts + 28939,
|
|
}
|
|
if argc < int32(6) || argc > libc.Int32FromInt32(RTREE_MAX_AUX_COLUMN)+libc.Int32FromInt32(3) {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+3968, libc.VaList(bp+8, aErrMsg[int32(2)+libc.BoolInt32(argc >= int32(6))]))
|
|
return int32(SQLITE_ERROR)
|
|
}
|
|
Xsqlite3_vtab_config(tls, db, int32(SQLITE_VTAB_CONSTRAINT_SUPPORT), libc.VaList(bp+8, int32(1)))
|
|
Xsqlite3_vtab_config(tls, db, int32(SQLITE_VTAB_INNOCUOUS), 0)
|
|
/* Allocate the sqlite3_vtab structure */
|
|
nDb = libc.Int32FromUint64(libc.Xstrlen(tls, **(**uintptr)(__ccgo_up(argv + 1*8))))
|
|
nName = libc.Int32FromUint64(libc.Xstrlen(tls, **(**uintptr)(__ccgo_up(argv + 2*8))))
|
|
pRtree = Xsqlite3_malloc64(tls, uint64(uint64(976)+libc.Uint64FromInt32(nDb)+libc.Uint64FromInt32(nName*int32(2))+uint64(8)))
|
|
if !(pRtree != 0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
libc.Xmemset(tls, pRtree, 0, uint64(976)+libc.Uint64FromInt32(nDb)+libc.Uint64FromInt32(nName*int32(2))+uint64(8))
|
|
(*TRtree)(unsafe.Pointer(pRtree)).FnBusy = uint32(1)
|
|
(*TRtree)(unsafe.Pointer(pRtree)).Fbase.FpModule = uintptr(unsafe.Pointer(&_rtreeModule))
|
|
(*TRtree)(unsafe.Pointer(pRtree)).FzDb = pRtree + 1*976
|
|
(*TRtree)(unsafe.Pointer(pRtree)).FzName = (*TRtree)(unsafe.Pointer(pRtree)).FzDb + uintptr(nDb+int32(1))
|
|
(*TRtree)(unsafe.Pointer(pRtree)).FzNodeName = (*TRtree)(unsafe.Pointer(pRtree)).FzName + uintptr(nName+int32(1))
|
|
(*TRtree)(unsafe.Pointer(pRtree)).FeCoordType = libc.Uint8FromInt32(eCoordType)
|
|
libc.Xmemcpy(tls, (*TRtree)(unsafe.Pointer(pRtree)).FzDb, **(**uintptr)(__ccgo_up(argv + 1*8)), libc.Uint64FromInt32(nDb))
|
|
libc.Xmemcpy(tls, (*TRtree)(unsafe.Pointer(pRtree)).FzName, **(**uintptr)(__ccgo_up(argv + 2*8)), libc.Uint64FromInt32(nName))
|
|
libc.Xmemcpy(tls, (*TRtree)(unsafe.Pointer(pRtree)).FzNodeName, **(**uintptr)(__ccgo_up(argv + 2*8)), libc.Uint64FromInt32(nName))
|
|
libc.Xmemcpy(tls, (*TRtree)(unsafe.Pointer(pRtree)).FzNodeName+uintptr(nName), __ccgo_ts+28976, uint64(6))
|
|
/* Create/Connect to the underlying relational database schema. If
|
|
** that is successful, call sqlite3_declare_vtab() to configure
|
|
** the r-tree table schema.
|
|
*/
|
|
pSql = Xsqlite3_str_new(tls, db)
|
|
Xsqlite3_str_appendf(tls, pSql, __ccgo_ts+28982, libc.VaList(bp+8, _rtreeTokenLength(tls, **(**uintptr)(__ccgo_up(argv + 3*8))), **(**uintptr)(__ccgo_up(argv + 3*8))))
|
|
ii = int32(4)
|
|
for {
|
|
if !(ii < argc) {
|
|
break
|
|
}
|
|
zArg = **(**uintptr)(__ccgo_up(argv + uintptr(ii)*8))
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zArg))) == int32('+') {
|
|
(*TRtree)(unsafe.Pointer(pRtree)).FnAux = (*TRtree)(unsafe.Pointer(pRtree)).FnAux + 1
|
|
Xsqlite3_str_appendf(tls, pSql, __ccgo_ts+29006, libc.VaList(bp+8, _rtreeTokenLength(tls, zArg+uintptr(1)), zArg+uintptr(1)))
|
|
} else {
|
|
if libc.Int32FromUint16((*TRtree)(unsafe.Pointer(pRtree)).FnAux) > 0 {
|
|
break
|
|
} else {
|
|
(*TRtree)(unsafe.Pointer(pRtree)).FnDim2 = (*TRtree)(unsafe.Pointer(pRtree)).FnDim2 + 1
|
|
Xsqlite3_str_appendf(tls, pSql, _azFormat[eCoordType], libc.VaList(bp+8, _rtreeTokenLength(tls, zArg), zArg))
|
|
}
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
Xsqlite3_str_appendf(tls, pSql, __ccgo_ts+29033, 0)
|
|
zSql = Xsqlite3_str_finish(tls, pSql)
|
|
if !(zSql != 0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
} else {
|
|
if ii < argc {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+3968, libc.VaList(bp+8, aErrMsg[int32(4)]))
|
|
rc = int32(SQLITE_ERROR)
|
|
} else {
|
|
v1 = Xsqlite3_declare_vtab(tls, db, zSql)
|
|
rc = v1
|
|
if SQLITE_OK != v1 {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+3968, libc.VaList(bp+8, Xsqlite3_errmsg(tls, db)))
|
|
}
|
|
}
|
|
}
|
|
Xsqlite3_free(tls, zSql)
|
|
if rc != 0 {
|
|
goto rtreeInit_fail
|
|
}
|
|
(*TRtree)(unsafe.Pointer(pRtree)).FnDim = libc.Uint8FromInt32(libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FnDim2) / int32(2))
|
|
if libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FnDim) < int32(1) {
|
|
iErr = int32(2)
|
|
} else {
|
|
if libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FnDim2) > libc.Int32FromInt32(RTREE_MAX_DIMENSIONS)*libc.Int32FromInt32(2) {
|
|
iErr = int32(3)
|
|
} else {
|
|
if libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FnDim2)%int32(2) != 0 {
|
|
iErr = int32(1)
|
|
} else {
|
|
iErr = 0
|
|
}
|
|
}
|
|
}
|
|
if iErr != 0 {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+3968, libc.VaList(bp+8, aErrMsg[iErr]))
|
|
goto rtreeInit_fail
|
|
}
|
|
(*TRtree)(unsafe.Pointer(pRtree)).FnBytesPerCell = libc.Uint8FromInt32(int32(8) + libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FnDim2)*int32(4))
|
|
/* Figure out the node size to use. */
|
|
rc = _getNodeSize(tls, db, pRtree, isCreate, pzErr)
|
|
if rc != 0 {
|
|
goto rtreeInit_fail
|
|
}
|
|
rc = _rtreeSqlInit(tls, pRtree, db, **(**uintptr)(__ccgo_up(argv + 1*8)), **(**uintptr)(__ccgo_up(argv + 2*8)), isCreate)
|
|
if rc != 0 {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+3968, libc.VaList(bp+8, Xsqlite3_errmsg(tls, db)))
|
|
goto rtreeInit_fail
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppVtab)) = pRtree
|
|
return SQLITE_OK
|
|
goto rtreeInit_fail
|
|
rtreeInit_fail:
|
|
;
|
|
if rc == SQLITE_OK {
|
|
rc = int32(SQLITE_ERROR)
|
|
}
|
|
_rtreeRelease(tls, pRtree)
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is a no-op if *pRc is other than SQLITE_OK when it is
|
|
// ** called. Otherwise, append the string representation of integer iVal
|
|
// ** to the buffer. No nul-terminator is written.
|
|
// **
|
|
// ** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before
|
|
// ** returning.
|
|
// */
|
|
func _sessionAppendInteger(tls *libc.TLS, p uintptr, iVal int32, pRc uintptr) {
|
|
bp := tls.Alloc(48)
|
|
defer tls.Free(48)
|
|
var _ /* aBuf at bp+0 */ [24]uint8
|
|
Xsqlite3_snprintf(tls, libc.Int32FromUint64(libc.Uint64FromInt64(24)-libc.Uint64FromInt32(1)), bp, __ccgo_ts+5317, libc.VaList(bp+32, iVal))
|
|
_sessionAppendStr(tls, p, bp, pRc)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is called by the parser upon parsing an
|
|
// **
|
|
// ** ALTER TABLE pSrc DROP COLUMN pName
|
|
// **
|
|
// ** statement. Argument pSrc contains the possibly qualified name of the
|
|
// ** table being edited, and token pName the name of the column to drop.
|
|
// */
|
|
func _sqlite3AlterDropColumn(tls *libc.TLS, pParse uintptr, pSrc uintptr, pName uintptr) {
|
|
bp := tls.Alloc(48)
|
|
defer tls.Free(48)
|
|
var addr, i, iCol, iColPos, iCur, iDb, iPos, nField, reg, regOut, regRec, v2 int32
|
|
var aff uint8
|
|
var db, pPk, pTab, v, zCol, zDb, v1 uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = addr, aff, db, i, iCol, iColPos, iCur, iDb, iPos, nField, pPk, pTab, reg, regOut, regRec, v, zCol, zDb, v1, v2
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb /* Database containing pTab ("main" etc.) */
|
|
zCol = uintptr(0) /* Index of column zCol in pTab->aCol[] */
|
|
/* Look up the table being altered. */
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
|
|
goto exit_drop_column
|
|
}
|
|
pTab = _sqlite3LocateTableItem(tls, pParse, uint32(0), pSrc+8)
|
|
if !(pTab != 0) {
|
|
goto exit_drop_column
|
|
}
|
|
/* Make sure this is not an attempt to ALTER a view, virtual table or
|
|
** system table. */
|
|
if SQLITE_OK != _isAlterableTable(tls, pParse, pTab) {
|
|
goto exit_drop_column
|
|
}
|
|
if SQLITE_OK != _isRealTable(tls, pParse, pTab, int32(1)) {
|
|
goto exit_drop_column
|
|
}
|
|
/* Find the index of the column being dropped. */
|
|
zCol = _sqlite3NameFromToken(tls, db, pName)
|
|
if zCol == uintptr(0) {
|
|
goto exit_drop_column
|
|
}
|
|
iCol = _sqlite3ColumnIndex(tls, pTab, zCol)
|
|
if iCol < 0 {
|
|
_sqlite3ErrorMsg(tls, pParse, __ccgo_ts+11235, libc.VaList(bp+8, pName))
|
|
goto exit_drop_column
|
|
}
|
|
/* Do not allow the user to drop a PRIMARY KEY column or a column
|
|
** constrained by a UNIQUE constraint. */
|
|
if libc.Int32FromUint16((**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(iCol)*16))).FcolFlags)&(libc.Int32FromInt32(COLFLAG_PRIMKEY)|libc.Int32FromInt32(COLFLAG_UNIQUE)) != 0 {
|
|
if libc.Int32FromUint16((**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(iCol)*16))).FcolFlags)&int32(COLFLAG_PRIMKEY) != 0 {
|
|
v1 = __ccgo_ts + 11620
|
|
} else {
|
|
v1 = __ccgo_ts + 5859
|
|
}
|
|
_sqlite3ErrorMsg(tls, pParse, __ccgo_ts+11632, libc.VaList(bp+8, v1, zCol))
|
|
goto exit_drop_column
|
|
}
|
|
/* Do not allow the number of columns to go to zero */
|
|
if int32((*TTable)(unsafe.Pointer(pTab)).FnCol) <= int32(1) {
|
|
_sqlite3ErrorMsg(tls, pParse, __ccgo_ts+11660, libc.VaList(bp+8, zCol))
|
|
goto exit_drop_column
|
|
}
|
|
/* Edit the sqlite_schema table */
|
|
iDb = _sqlite3SchemaToIndex(tls, db, (*TTable)(unsafe.Pointer(pTab)).FpSchema)
|
|
zDb = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FzDbSName
|
|
/* Invoke the authorization callback. */
|
|
if _sqlite3AuthCheck(tls, pParse, int32(SQLITE_ALTER_TABLE), zDb, (*TTable)(unsafe.Pointer(pTab)).FzName, zCol) != 0 {
|
|
goto exit_drop_column
|
|
}
|
|
_renameTestSchema(tls, pParse, zDb, libc.BoolInt32(iDb == int32(1)), __ccgo_ts+1704, 0)
|
|
_renameFixQuotes(tls, pParse, zDb, libc.BoolInt32(iDb == int32(1)))
|
|
_sqlite3NestedParse(tls, pParse, __ccgo_ts+11708, libc.VaList(bp+8, zDb, iDb, iCol, (*TTable)(unsafe.Pointer(pTab)).FzName))
|
|
/* Drop and reload the database schema. */
|
|
_renameReloadSchema(tls, pParse, iDb, uint16(INITFLAG_AlterDrop))
|
|
_renameTestSchema(tls, pParse, zDb, libc.BoolInt32(iDb == int32(1)), __ccgo_ts+11829, int32(1))
|
|
/* Edit rows of table on disk */
|
|
if (*TParse)(unsafe.Pointer(pParse)).FnErr == 0 && libc.Int32FromUint16((**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(iCol)*16))).FcolFlags)&int32(COLFLAG_VIRTUAL) == 0 {
|
|
pPk = uintptr(0)
|
|
nField = 0
|
|
v = _sqlite3GetVdbe(tls, pParse)
|
|
v1 = pParse + 56
|
|
v2 = *(*int32)(unsafe.Pointer(v1))
|
|
*(*int32)(unsafe.Pointer(v1)) = *(*int32)(unsafe.Pointer(v1)) + 1
|
|
iCur = v2
|
|
_sqlite3OpenTable(tls, pParse, iCur, iDb, pTab, int32(OP_OpenWrite))
|
|
addr = _sqlite3VdbeAddOp1(tls, v, int32(OP_Rewind), iCur)
|
|
v1 = pParse + 60
|
|
*(*int32)(unsafe.Pointer(v1)) = *(*int32)(unsafe.Pointer(v1)) + 1
|
|
v2 = *(*int32)(unsafe.Pointer(v1))
|
|
reg = v2
|
|
if (*TTable)(unsafe.Pointer(pTab)).FtabFlags&uint32(TF_WithoutRowid) == uint32(0) {
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Rowid), iCur, reg)
|
|
**(**int32)(__ccgo_up(pParse + 60)) += int32((*TTable)(unsafe.Pointer(pTab)).FnCol)
|
|
} else {
|
|
pPk = _sqlite3PrimaryKeyIndex(tls, pTab)
|
|
**(**int32)(__ccgo_up(pParse + 60)) += libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pPk)).FnColumn)
|
|
i = 0
|
|
for {
|
|
if !(i < libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pPk)).FnKeyCol)) {
|
|
break
|
|
}
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Column), iCur, i, reg+i+int32(1))
|
|
goto _6
|
|
_6:
|
|
;
|
|
i = i + 1
|
|
}
|
|
nField = libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pPk)).FnKeyCol)
|
|
}
|
|
v1 = pParse + 60
|
|
*(*int32)(unsafe.Pointer(v1)) = *(*int32)(unsafe.Pointer(v1)) + 1
|
|
v2 = *(*int32)(unsafe.Pointer(v1))
|
|
regRec = v2
|
|
i = 0
|
|
for {
|
|
if !(i < int32((*TTable)(unsafe.Pointer(pTab)).FnCol)) {
|
|
break
|
|
}
|
|
if i != iCol && libc.Int32FromUint16((**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(i)*16))).FcolFlags)&int32(COLFLAG_VIRTUAL) == 0 {
|
|
if pPk != 0 {
|
|
iPos = _sqlite3TableColumnToIndex(tls, pPk, i)
|
|
iColPos = _sqlite3TableColumnToIndex(tls, pPk, iCol)
|
|
if iPos < libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pPk)).FnKeyCol) {
|
|
goto _9
|
|
}
|
|
regOut = reg + int32(1) + iPos - libc.BoolInt32(iPos > iColPos)
|
|
} else {
|
|
regOut = reg + int32(1) + nField
|
|
}
|
|
if i == int32((*TTable)(unsafe.Pointer(pTab)).FiPKey) {
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Null), 0, regOut)
|
|
} else {
|
|
aff = (**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(i)*16))).Faffinity
|
|
if libc.Int32FromUint8(aff) == int32(SQLITE_AFF_REAL) {
|
|
(**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(i)*16))).Faffinity = uint8(SQLITE_AFF_NUMERIC)
|
|
}
|
|
_sqlite3ExprCodeGetColumnOfTable(tls, v, pTab, iCur, i, regOut)
|
|
(**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(i)*16))).Faffinity = aff
|
|
}
|
|
nField = nField + 1
|
|
}
|
|
goto _9
|
|
_9:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if nField == 0 {
|
|
/* dbsqlfuzz 5f09e7bcc78b4954d06bf9f2400d7715f48d1fef */
|
|
(*TParse)(unsafe.Pointer(pParse)).FnMem = (*TParse)(unsafe.Pointer(pParse)).FnMem + 1
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Null), 0, reg+int32(1))
|
|
nField = int32(1)
|
|
}
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_MakeRecord), reg+int32(1), nField, regRec)
|
|
if pPk != 0 {
|
|
_sqlite3VdbeAddOp4Int(tls, v, int32(OP_IdxInsert), iCur, regRec, reg+int32(1), libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pPk)).FnKeyCol))
|
|
} else {
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Insert), iCur, regRec, reg)
|
|
}
|
|
_sqlite3VdbeChangeP5(tls, v, uint16(OPFLAG_SAVEPOSITION))
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Next), iCur, addr+int32(1))
|
|
_sqlite3VdbeJumpHere(tls, v, addr)
|
|
}
|
|
goto exit_drop_column
|
|
exit_drop_column:
|
|
;
|
|
_sqlite3DbFree(tls, db, zCol)
|
|
_sqlite3SrcListDelete(tls, db, pSrc)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Handles the following parser reduction:
|
|
// **
|
|
// ** cmd ::= ALTER TABLE pSrc RENAME COLUMN pOld TO pNew
|
|
// */
|
|
func _sqlite3AlterRenameColumn(tls *libc.TLS, pParse uintptr, pSrc uintptr, pOld uintptr, pNew uintptr) {
|
|
bp := tls.Alloc(80)
|
|
defer tls.Free(80)
|
|
var bQuote, iCol, iSchema int32
|
|
var db, pTab, zDb, zNew, zOld uintptr
|
|
_, _, _, _, _, _, _, _ = bQuote, db, iCol, iSchema, pTab, zDb, zNew, zOld
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb /* Index of column being renamed */
|
|
zOld = uintptr(0) /* Old column name */
|
|
zNew = uintptr(0) /* True to quote the new name */
|
|
/* Locate the table to be altered */
|
|
pTab = _sqlite3LocateTableItem(tls, pParse, uint32(0), pSrc+8)
|
|
if !(pTab != 0) {
|
|
goto exit_rename_column
|
|
}
|
|
/* Cannot alter a system table */
|
|
if SQLITE_OK != _isAlterableTable(tls, pParse, pTab) {
|
|
goto exit_rename_column
|
|
}
|
|
if SQLITE_OK != _isRealTable(tls, pParse, pTab, 0) {
|
|
goto exit_rename_column
|
|
}
|
|
/* Which schema holds the table to be altered */
|
|
iSchema = _sqlite3SchemaToIndex(tls, db, (*TTable)(unsafe.Pointer(pTab)).FpSchema)
|
|
zDb = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iSchema)*32))).FzDbSName
|
|
/* Invoke the authorization callback. */
|
|
if _sqlite3AuthCheck(tls, pParse, int32(SQLITE_ALTER_TABLE), zDb, (*TTable)(unsafe.Pointer(pTab)).FzName, uintptr(0)) != 0 {
|
|
goto exit_rename_column
|
|
}
|
|
/* Make sure the old name really is a column name in the table to be
|
|
** altered. Set iCol to be the index of the column being renamed */
|
|
zOld = _sqlite3NameFromToken(tls, db, pOld)
|
|
if !(zOld != 0) {
|
|
goto exit_rename_column
|
|
}
|
|
iCol = _sqlite3ColumnIndex(tls, pTab, zOld)
|
|
if iCol < 0 {
|
|
_sqlite3ErrorMsg(tls, pParse, __ccgo_ts+11235, libc.VaList(bp+8, pOld))
|
|
goto exit_rename_column
|
|
}
|
|
/* Ensure the schema contains no double-quoted strings */
|
|
_renameTestSchema(tls, pParse, zDb, libc.BoolInt32(iSchema == int32(1)), __ccgo_ts+1704, 0)
|
|
_renameFixQuotes(tls, pParse, zDb, libc.BoolInt32(iSchema == int32(1)))
|
|
/* Do the rename operation using a recursive UPDATE statement that
|
|
** uses the sqlite_rename_column() SQL function to compute the new
|
|
** CREATE statement text for the sqlite_schema table.
|
|
*/
|
|
_sqlite3MayAbort(tls, pParse)
|
|
zNew = _sqlite3NameFromToken(tls, db, pNew)
|
|
if !(zNew != 0) {
|
|
goto exit_rename_column
|
|
}
|
|
bQuote = libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up((*TToken)(unsafe.Pointer(pNew)).Fz)))]) & int32(0x80)
|
|
_sqlite3NestedParse(tls, pParse, __ccgo_ts+11256, libc.VaList(bp+8, zDb, zDb, (*TTable)(unsafe.Pointer(pTab)).FzName, iCol, zNew, bQuote, libc.BoolInt32(iSchema == int32(1)), (*TTable)(unsafe.Pointer(pTab)).FzName))
|
|
_sqlite3NestedParse(tls, pParse, __ccgo_ts+11438, libc.VaList(bp+8, zDb, (*TTable)(unsafe.Pointer(pTab)).FzName, iCol, zNew, bQuote))
|
|
/* Drop and reload the database schema. */
|
|
_renameReloadSchema(tls, pParse, iSchema, uint16(INITFLAG_AlterRename))
|
|
_renameTestSchema(tls, pParse, zDb, libc.BoolInt32(iSchema == int32(1)), __ccgo_ts+10266, int32(1))
|
|
goto exit_rename_column
|
|
exit_rename_column:
|
|
;
|
|
_sqlite3SrcListDelete(tls, db, pSrc)
|
|
_sqlite3DbFree(tls, db, zOld)
|
|
_sqlite3DbFree(tls, db, zNew)
|
|
return
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This routine does a complete check of the given BTree file. aRoot[] is
|
|
// ** an array of pages numbers were each page number is the root page of
|
|
// ** a table. nRoot is the number of entries in aRoot.
|
|
// **
|
|
// ** A read-only or read-write transaction must be opened before calling
|
|
// ** this function.
|
|
// **
|
|
// ** Write the number of error seen in *pnErr. Except for some memory
|
|
// ** allocation errors, an error message held in memory obtained from
|
|
// ** malloc is returned if *pnErr is non-zero. If *pnErr==0 then NULL is
|
|
// ** returned. If a memory allocation error occurs, NULL is returned.
|
|
// **
|
|
// ** If the first entry in aRoot[] is 0, that indicates that the list of
|
|
// ** root pages is incomplete. This is a "partial integrity-check". This
|
|
// ** happens when performing an integrity check on a single table. The
|
|
// ** zero is skipped, of course. But in addition, the freelist checks
|
|
// ** and the checks to make sure every page is referenced are also skipped,
|
|
// ** since obviously it is not possible to know which pages are covered by
|
|
// ** the unverified btrees. Except, if aRoot[1] is 1, then the freelist
|
|
// ** checks are still performed.
|
|
// */
|
|
func _sqlite3BtreeIntegrityCheck(tls *libc.TLS, db uintptr, p uintptr, aRoot uintptr, aCnt uintptr, nRoot int32, mxErr int32, pnErr uintptr, pzOut uintptr) (r int32) {
|
|
bp := tls.Alloc(272)
|
|
defer tls.Free(272)
|
|
var bCkFreelist, bPartial int32
|
|
var i, mx, mxInHdr TPgno
|
|
var pBt uintptr
|
|
var savedDbFlags Tu64
|
|
var _ /* notUsed at bp+232 */ Ti64
|
|
var _ /* sCheck at bp+0 */ TIntegrityCk
|
|
var _ /* zErr at bp+128 */ [100]uint8
|
|
_, _, _, _, _, _, _ = bCkFreelist, bPartial, i, mx, mxInHdr, pBt, savedDbFlags
|
|
pBt = (*TBtree)(unsafe.Pointer(p)).FpBt
|
|
savedDbFlags = (*Tsqlite3)(unsafe.Pointer((*TBtShared)(unsafe.Pointer(pBt)).Fdb)).Fflags
|
|
bPartial = 0 /* True if not checking all btrees */
|
|
bCkFreelist = int32(1) /* True to scan the freelist */
|
|
/* aRoot[0]==0 means this is a partial check */
|
|
if **(**TPgno)(__ccgo_up(aRoot)) == uint32(0) {
|
|
bPartial = int32(1)
|
|
if **(**TPgno)(__ccgo_up(aRoot + 1*4)) != uint32(1) {
|
|
bCkFreelist = 0
|
|
}
|
|
}
|
|
_sqlite3BtreeEnter(tls, p)
|
|
libc.Xmemset(tls, bp, 0, uint64(128))
|
|
(**(**TIntegrityCk)(__ccgo_up(bp))).Fdb = db
|
|
(**(**TIntegrityCk)(__ccgo_up(bp))).FpBt = pBt
|
|
(**(**TIntegrityCk)(__ccgo_up(bp))).FpPager = (*TBtShared)(unsafe.Pointer(pBt)).FpPager
|
|
(**(**TIntegrityCk)(__ccgo_up(bp))).FnCkPage = _btreePagecount(tls, (**(**TIntegrityCk)(__ccgo_up(bp))).FpBt)
|
|
(**(**TIntegrityCk)(__ccgo_up(bp))).FmxErr = mxErr
|
|
_sqlite3StrAccumInit(tls, bp+72, uintptr(0), bp+128, int32(100), int32(SQLITE_MAX_LENGTH))
|
|
(**(**TIntegrityCk)(__ccgo_up(bp))).FerrMsg.FprintfFlags = uint8(SQLITE_PRINTF_INTERNAL)
|
|
if (**(**TIntegrityCk)(__ccgo_up(bp))).FnCkPage == uint32(0) {
|
|
goto integrity_ck_cleanup
|
|
}
|
|
(**(**TIntegrityCk)(__ccgo_up(bp))).FaPgRef = _sqlite3MallocZero(tls, uint64((**(**TIntegrityCk)(__ccgo_up(bp))).FnCkPage/uint32(8)+uint32(1)))
|
|
if !((**(**TIntegrityCk)(__ccgo_up(bp))).FaPgRef != 0) {
|
|
_checkOom(tls, bp)
|
|
goto integrity_ck_cleanup
|
|
}
|
|
(**(**TIntegrityCk)(__ccgo_up(bp))).Fheap = _sqlite3PageMalloc(tls, libc.Int32FromUint32((*TBtShared)(unsafe.Pointer(pBt)).FpageSize))
|
|
if (**(**TIntegrityCk)(__ccgo_up(bp))).Fheap == uintptr(0) {
|
|
_checkOom(tls, bp)
|
|
goto integrity_ck_cleanup
|
|
}
|
|
i = libc.Uint32FromInt32(_sqlite3PendingByte)/(*TBtShared)(unsafe.Pointer(pBt)).FpageSize + libc.Uint32FromInt32(1)
|
|
if i <= (**(**TIntegrityCk)(__ccgo_up(bp))).FnCkPage {
|
|
_setPageReferenced(tls, bp, i)
|
|
}
|
|
/* Check the integrity of the freelist
|
|
*/
|
|
if bCkFreelist != 0 {
|
|
(**(**TIntegrityCk)(__ccgo_up(bp))).FzPfx = __ccgo_ts + 4990
|
|
_checkList(tls, bp, int32(1), _sqlite3Get4byte(tls, (*TMemPage)(unsafe.Pointer((*TBtShared)(unsafe.Pointer(pBt)).FpPage1)).FaData+32), _sqlite3Get4byte(tls, (*TMemPage)(unsafe.Pointer((*TBtShared)(unsafe.Pointer(pBt)).FpPage1)).FaData+36))
|
|
(**(**TIntegrityCk)(__ccgo_up(bp))).FzPfx = uintptr(0)
|
|
}
|
|
/* Check all the tables.
|
|
*/
|
|
if !(bPartial != 0) {
|
|
if (*TBtShared)(unsafe.Pointer(pBt)).FautoVacuum != 0 {
|
|
mx = uint32(0)
|
|
i = uint32(0)
|
|
for {
|
|
if !(libc.Int32FromUint32(i) < nRoot) {
|
|
break
|
|
}
|
|
if mx < **(**TPgno)(__ccgo_up(aRoot + uintptr(i)*4)) {
|
|
mx = **(**TPgno)(__ccgo_up(aRoot + uintptr(i)*4))
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
mxInHdr = _sqlite3Get4byte(tls, (*TMemPage)(unsafe.Pointer((*TBtShared)(unsafe.Pointer(pBt)).FpPage1)).FaData+52)
|
|
if mx != mxInHdr {
|
|
_checkAppendMsg(tls, bp, __ccgo_ts+5001, libc.VaList(bp+248, mx, mxInHdr))
|
|
}
|
|
} else {
|
|
if _sqlite3Get4byte(tls, (*TMemPage)(unsafe.Pointer((*TBtShared)(unsafe.Pointer(pBt)).FpPage1)).FaData+64) != uint32(0) {
|
|
_checkAppendMsg(tls, bp, __ccgo_ts+5046, 0)
|
|
}
|
|
}
|
|
}
|
|
**(**Tu64)(__ccgo_up((*TBtShared)(unsafe.Pointer(pBt)).Fdb + 48)) &= ^libc.Uint64FromInt32(SQLITE_CellSizeCk)
|
|
i = uint32(0)
|
|
for {
|
|
if !(libc.Int32FromUint32(i) < nRoot && (**(**TIntegrityCk)(__ccgo_up(bp))).FmxErr != 0) {
|
|
break
|
|
}
|
|
(**(**TIntegrityCk)(__ccgo_up(bp))).FnRow = 0
|
|
if **(**TPgno)(__ccgo_up(aRoot + uintptr(i)*4)) != 0 {
|
|
if (*TBtShared)(unsafe.Pointer(pBt)).FautoVacuum != 0 && **(**TPgno)(__ccgo_up(aRoot + uintptr(i)*4)) > uint32(1) && !(bPartial != 0) {
|
|
_checkPtrmap(tls, bp, **(**TPgno)(__ccgo_up(aRoot + uintptr(i)*4)), uint8(PTRMAP_ROOTPAGE), uint32(0))
|
|
}
|
|
(**(**TIntegrityCk)(__ccgo_up(bp))).Fv0 = **(**TPgno)(__ccgo_up(aRoot + uintptr(i)*4))
|
|
_checkTreePage(tls, bp, **(**TPgno)(__ccgo_up(aRoot + uintptr(i)*4)), bp+232, libc.Int64FromUint32(0xffffffff)|libc.Int64FromInt32(0x7fffffff)<<libc.Int32FromInt32(32))
|
|
}
|
|
_sqlite3MemSetArrayInt64(tls, aCnt, libc.Int32FromUint32(i), (**(**TIntegrityCk)(__ccgo_up(bp))).FnRow)
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
(*Tsqlite3)(unsafe.Pointer((*TBtShared)(unsafe.Pointer(pBt)).Fdb)).Fflags = savedDbFlags
|
|
/* Make sure every page in the file is referenced
|
|
*/
|
|
if !(bPartial != 0) {
|
|
i = uint32(1)
|
|
for {
|
|
if !(i <= (**(**TIntegrityCk)(__ccgo_up(bp))).FnCkPage && (**(**TIntegrityCk)(__ccgo_up(bp))).FmxErr != 0) {
|
|
break
|
|
}
|
|
/* If the database supports auto-vacuum, make sure no tables contain
|
|
** references to pointer-map pages.
|
|
*/
|
|
if _getPageReferenced(tls, bp, i) == 0 && (_ptrmapPageno(tls, pBt, i) != i || !((*TBtShared)(unsafe.Pointer(pBt)).FautoVacuum != 0)) {
|
|
_checkAppendMsg(tls, bp, __ccgo_ts+5101, libc.VaList(bp+248, i))
|
|
}
|
|
if _getPageReferenced(tls, bp, i) != 0 && (_ptrmapPageno(tls, pBt, i) == i && (*TBtShared)(unsafe.Pointer(pBt)).FautoVacuum != 0) {
|
|
_checkAppendMsg(tls, bp, __ccgo_ts+5121, libc.VaList(bp+248, i))
|
|
}
|
|
goto _3
|
|
_3:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
/* Clean up and report errors.
|
|
*/
|
|
goto integrity_ck_cleanup
|
|
integrity_ck_cleanup:
|
|
;
|
|
_sqlite3PageFree(tls, (**(**TIntegrityCk)(__ccgo_up(bp))).Fheap)
|
|
Xsqlite3_free(tls, (**(**TIntegrityCk)(__ccgo_up(bp))).FaPgRef)
|
|
**(**int32)(__ccgo_up(pnErr)) = (**(**TIntegrityCk)(__ccgo_up(bp))).FnErr
|
|
if (**(**TIntegrityCk)(__ccgo_up(bp))).FnErr == 0 {
|
|
Xsqlite3_str_reset(tls, bp+72)
|
|
**(**uintptr)(__ccgo_up(pzOut)) = uintptr(0)
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(pzOut)) = _sqlite3StrAccumFinish(tls, bp+72)
|
|
}
|
|
/* Make sure this analysis did not leave any unref() pages. */
|
|
_sqlite3BtreeLeave(tls, p)
|
|
return (**(**TIntegrityCk)(__ccgo_up(bp))).Frc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Open a database file.
|
|
// **
|
|
// ** zFilename is the name of the database file. If zFilename is NULL
|
|
// ** then an ephemeral database is created. The ephemeral database might
|
|
// ** be exclusively in memory, or it might use a disk-based memory cache.
|
|
// ** Either way, the ephemeral database will be automatically deleted
|
|
// ** when sqlite3BtreeClose() is called.
|
|
// **
|
|
// ** If zFilename is ":memory:" then an in-memory database is created
|
|
// ** that is automatically destroyed when it is closed.
|
|
// **
|
|
// ** The "flags" parameter is a bitmask that might contain bits like
|
|
// ** BTREE_OMIT_JOURNAL and/or BTREE_MEMORY.
|
|
// **
|
|
// ** If the database is already opened in the same database connection
|
|
// ** and we are in shared cache mode, then the open will fail with an
|
|
// ** SQLITE_CONSTRAINT error. We cannot allow two or more BtShared
|
|
// ** objects in the same database connection since doing so will lead
|
|
// ** to problems with locking.
|
|
// */
|
|
func _sqlite3BtreeOpen(tls *libc.TLS, pVfs uintptr, zFilename uintptr, db uintptr, ppBtree uintptr, flags int32, vfsFlags int32) (r int32) {
|
|
bp := tls.Alloc(112)
|
|
defer tls.Free(112)
|
|
var i, iDb, isMemdb, isTempDb, nFilename, nFullPathname, rc, v1 int32
|
|
var mutexOpen, mutexShared, mutexShared1, p, pBt, pExisting, pFile, pSib, zFullPathname, v4 uintptr
|
|
var nReserve Tu8
|
|
var _ /* zDbHeader at bp+0 */ [100]uint8
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = i, iDb, isMemdb, isTempDb, mutexOpen, mutexShared, mutexShared1, nFilename, nFullPathname, nReserve, p, pBt, pExisting, pFile, pSib, rc, zFullPathname, v1, v4
|
|
pBt = uintptr(0) /* Handle to return */
|
|
mutexOpen = uintptr(0) /* Prevents a race condition. Ticket #3537 */
|
|
rc = SQLITE_OK /* Database header content */
|
|
/* True if opening an ephemeral, temporary database */
|
|
isTempDb = libc.BoolInt32(zFilename == uintptr(0) || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zFilename))) == 0)
|
|
/* Set the variable isMemdb to true for an in-memory database, or
|
|
** false for a file-based database.
|
|
*/
|
|
isMemdb = libc.BoolInt32(zFilename != 0 && libc.Xstrcmp(tls, zFilename, __ccgo_ts+4367) == 0 || isTempDb != 0 && _sqlite3TempInMemory(tls, db) != 0 || vfsFlags&int32(SQLITE_OPEN_MEMORY) != 0)
|
|
/* flags fit in 8 bits */
|
|
/* Only a BTREE_SINGLE database can be BTREE_UNORDERED */
|
|
/* A BTREE_SINGLE database is always a temporary and/or ephemeral */
|
|
if isMemdb != 0 {
|
|
flags = flags | int32(BTREE_MEMORY)
|
|
}
|
|
if vfsFlags&int32(SQLITE_OPEN_MAIN_DB) != 0 && (isMemdb != 0 || isTempDb != 0) {
|
|
vfsFlags = vfsFlags & ^libc.Int32FromInt32(SQLITE_OPEN_MAIN_DB) | int32(SQLITE_OPEN_TEMP_DB)
|
|
}
|
|
p = _sqlite3MallocZero(tls, uint64(72))
|
|
if !(p != 0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
(*TBtree)(unsafe.Pointer(p)).FinTrans = uint8(TRANS_NONE)
|
|
(*TBtree)(unsafe.Pointer(p)).Fdb = db
|
|
(*TBtree)(unsafe.Pointer(p)).Flock.FpBtree = p
|
|
(*TBtree)(unsafe.Pointer(p)).Flock.FiTable = uint32(1)
|
|
/*
|
|
** If this Btree is a candidate for shared cache, try to find an
|
|
** existing BtShared object that we can share with
|
|
*/
|
|
if isTempDb == 0 && (isMemdb == 0 || vfsFlags&int32(SQLITE_OPEN_URI) != 0) {
|
|
if vfsFlags&int32(SQLITE_OPEN_SHAREDCACHE) != 0 {
|
|
nFilename = _sqlite3Strlen30(tls, zFilename) + int32(1)
|
|
nFullPathname = (*Tsqlite3_vfs)(unsafe.Pointer(pVfs)).FmxPathname + int32(1)
|
|
if nFullPathname > nFilename {
|
|
v1 = nFullPathname
|
|
} else {
|
|
v1 = nFilename
|
|
}
|
|
zFullPathname = _sqlite3Malloc(tls, libc.Uint64FromInt32(v1))
|
|
(*TBtree)(unsafe.Pointer(p)).Fsharable = uint8(1)
|
|
if !(zFullPathname != 0) {
|
|
Xsqlite3_free(tls, p)
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
if isMemdb != 0 {
|
|
libc.Xmemcpy(tls, zFullPathname, zFilename, libc.Uint64FromInt32(nFilename))
|
|
} else {
|
|
rc = _sqlite3OsFullPathname(tls, pVfs, zFilename, nFullPathname, zFullPathname)
|
|
if rc != 0 {
|
|
if rc == libc.Int32FromInt32(SQLITE_OK)|libc.Int32FromInt32(2)<<libc.Int32FromInt32(8) {
|
|
rc = SQLITE_OK
|
|
} else {
|
|
Xsqlite3_free(tls, zFullPathname)
|
|
Xsqlite3_free(tls, p)
|
|
return rc
|
|
}
|
|
}
|
|
}
|
|
mutexOpen = _sqlite3MutexAlloc(tls, int32(SQLITE_MUTEX_STATIC_OPEN))
|
|
Xsqlite3_mutex_enter(tls, mutexOpen)
|
|
mutexShared = _sqlite3MutexAlloc(tls, int32(SQLITE_MUTEX_STATIC_MAIN))
|
|
Xsqlite3_mutex_enter(tls, mutexShared)
|
|
pBt = _sqlite3SharedCacheList
|
|
for {
|
|
if !(pBt != 0) {
|
|
break
|
|
}
|
|
if 0 == libc.Xstrcmp(tls, zFullPathname, _sqlite3PagerFilename(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager, 0)) && _sqlite3PagerVfs(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager) == pVfs {
|
|
iDb = (*Tsqlite3)(unsafe.Pointer(db)).FnDb - int32(1)
|
|
for {
|
|
if !(iDb >= 0) {
|
|
break
|
|
}
|
|
pExisting = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FpBt
|
|
if pExisting != 0 && (*TBtree)(unsafe.Pointer(pExisting)).FpBt == pBt {
|
|
Xsqlite3_mutex_leave(tls, mutexShared)
|
|
Xsqlite3_mutex_leave(tls, mutexOpen)
|
|
Xsqlite3_free(tls, zFullPathname)
|
|
Xsqlite3_free(tls, p)
|
|
return int32(SQLITE_CONSTRAINT)
|
|
}
|
|
goto _3
|
|
_3:
|
|
;
|
|
iDb = iDb - 1
|
|
}
|
|
(*TBtree)(unsafe.Pointer(p)).FpBt = pBt
|
|
(*TBtShared)(unsafe.Pointer(pBt)).FnRef = (*TBtShared)(unsafe.Pointer(pBt)).FnRef + 1
|
|
break
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
pBt = (*TBtShared)(unsafe.Pointer(pBt)).FpNext
|
|
}
|
|
Xsqlite3_mutex_leave(tls, mutexShared)
|
|
Xsqlite3_free(tls, zFullPathname)
|
|
}
|
|
}
|
|
if pBt == uintptr(0) {
|
|
/*
|
|
** The following asserts make sure that structures used by the btree are
|
|
** the right size. This is to guard against size changes that result
|
|
** when compiling on a different architecture.
|
|
*/
|
|
/* Suppress false-positive compiler warning from PVS-Studio */
|
|
libc.Xmemset(tls, bp+16, 0, uint64(8))
|
|
pBt = _sqlite3MallocZero(tls, uint64(152))
|
|
if pBt == uintptr(0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
goto btree_open_out
|
|
}
|
|
rc = _sqlite3PagerOpen(tls, pVfs, pBt, zFilename, int32(136), flags, vfsFlags, __ccgo_fp(_pageReinit))
|
|
if rc == SQLITE_OK {
|
|
_sqlite3PagerSetMmapLimit(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager, (*Tsqlite3)(unsafe.Pointer(db)).FszMmap)
|
|
rc = _sqlite3PagerReadFileheader(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager, int32(100), bp)
|
|
}
|
|
if rc != SQLITE_OK {
|
|
goto btree_open_out
|
|
}
|
|
(*TBtShared)(unsafe.Pointer(pBt)).FopenFlags = libc.Uint8FromInt32(flags)
|
|
(*TBtShared)(unsafe.Pointer(pBt)).Fdb = db
|
|
_sqlite3PagerSetBusyHandler(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager, __ccgo_fp(_btreeInvokeBusyHandler), pBt)
|
|
(*TBtree)(unsafe.Pointer(p)).FpBt = pBt
|
|
(*TBtShared)(unsafe.Pointer(pBt)).FpCursor = uintptr(0)
|
|
(*TBtShared)(unsafe.Pointer(pBt)).FpPage1 = uintptr(0)
|
|
if _sqlite3PagerIsreadonly(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager) != 0 {
|
|
v4 = pBt + 40
|
|
*(*Tu16)(unsafe.Pointer(v4)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v4))) | libc.Int32FromInt32(BTS_READ_ONLY))
|
|
}
|
|
/* EVIDENCE-OF: R-51873-39618 The page size for a database file is
|
|
** determined by the 2-byte integer located at an offset of 16 bytes from
|
|
** the beginning of the database file. */
|
|
(*TBtShared)(unsafe.Pointer(pBt)).FpageSize = libc.Uint32FromInt32(libc.Int32FromUint8((**(**[100]uint8)(__ccgo_up(bp)))[int32(16)])<<int32(8) | libc.Int32FromUint8((**(**[100]uint8)(__ccgo_up(bp)))[int32(17)])<<int32(16))
|
|
if (*TBtShared)(unsafe.Pointer(pBt)).FpageSize < uint32(512) || (*TBtShared)(unsafe.Pointer(pBt)).FpageSize > uint32(SQLITE_MAX_PAGE_SIZE) || ((*TBtShared)(unsafe.Pointer(pBt)).FpageSize-uint32(1))&(*TBtShared)(unsafe.Pointer(pBt)).FpageSize != uint32(0) {
|
|
(*TBtShared)(unsafe.Pointer(pBt)).FpageSize = uint32(0)
|
|
/* If the magic name ":memory:" will create an in-memory database, then
|
|
** leave the autoVacuum mode at 0 (do not auto-vacuum), even if
|
|
** SQLITE_DEFAULT_AUTOVACUUM is true. On the other hand, if
|
|
** SQLITE_OMIT_MEMORYDB has been defined, then ":memory:" is just a
|
|
** regular file-name. In this case the auto-vacuum applies as per normal.
|
|
*/
|
|
if zFilename != 0 && !(isMemdb != 0) {
|
|
(*TBtShared)(unsafe.Pointer(pBt)).FautoVacuum = libc.Uint8FromInt32(libc.Int32FromInt32(0))
|
|
(*TBtShared)(unsafe.Pointer(pBt)).FincrVacuum = libc.Uint8FromInt32(libc.Int32FromInt32(0))
|
|
}
|
|
nReserve = uint8(0)
|
|
} else {
|
|
/* EVIDENCE-OF: R-37497-42412 The size of the reserved region is
|
|
** determined by the one-byte unsigned integer found at an offset of 20
|
|
** into the database file header. */
|
|
nReserve = (**(**[100]uint8)(__ccgo_up(bp)))[int32(20)]
|
|
v4 = pBt + 40
|
|
*(*Tu16)(unsafe.Pointer(v4)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v4))) | libc.Int32FromInt32(BTS_PAGESIZE_FIXED))
|
|
if _sqlite3Get4byte(tls, bp+uintptr(libc.Int32FromInt32(36)+libc.Int32FromInt32(4)*libc.Int32FromInt32(4))) != 0 {
|
|
v1 = int32(1)
|
|
} else {
|
|
v1 = 0
|
|
}
|
|
(*TBtShared)(unsafe.Pointer(pBt)).FautoVacuum = libc.Uint8FromInt32(v1)
|
|
if _sqlite3Get4byte(tls, bp+uintptr(libc.Int32FromInt32(36)+libc.Int32FromInt32(7)*libc.Int32FromInt32(4))) != 0 {
|
|
v1 = int32(1)
|
|
} else {
|
|
v1 = 0
|
|
}
|
|
(*TBtShared)(unsafe.Pointer(pBt)).FincrVacuum = libc.Uint8FromInt32(v1)
|
|
}
|
|
rc = _sqlite3PagerSetPagesize(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager, pBt+52, libc.Int32FromUint8(nReserve))
|
|
if rc != 0 {
|
|
goto btree_open_out
|
|
}
|
|
(*TBtShared)(unsafe.Pointer(pBt)).FusableSize = (*TBtShared)(unsafe.Pointer(pBt)).FpageSize - uint32(nReserve)
|
|
/* 8-byte alignment of pageSize */
|
|
/* Add the new BtShared object to the linked list sharable BtShareds.
|
|
*/
|
|
(*TBtShared)(unsafe.Pointer(pBt)).FnRef = int32(1)
|
|
if (*TBtree)(unsafe.Pointer(p)).Fsharable != 0 {
|
|
mutexShared1 = _sqlite3MutexAlloc(tls, int32(SQLITE_MUTEX_STATIC_MAIN))
|
|
if libc.Bool(int32(SQLITE_THREADSAFE) != 0) && _sqlite3Config.FbCoreMutex != 0 {
|
|
(*TBtShared)(unsafe.Pointer(pBt)).Fmutex = _sqlite3MutexAlloc(tls, SQLITE_MUTEX_FAST)
|
|
if (*TBtShared)(unsafe.Pointer(pBt)).Fmutex == uintptr(0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
goto btree_open_out
|
|
}
|
|
}
|
|
Xsqlite3_mutex_enter(tls, mutexShared1)
|
|
(*TBtShared)(unsafe.Pointer(pBt)).FpNext = _sqlite3SharedCacheList
|
|
_sqlite3SharedCacheList = pBt
|
|
Xsqlite3_mutex_leave(tls, mutexShared1)
|
|
}
|
|
}
|
|
/* If the new Btree uses a sharable pBtShared, then link the new
|
|
** Btree into the list of all sharable Btrees for the same connection.
|
|
** The list is kept in ascending order by pBt address.
|
|
*/
|
|
if (*TBtree)(unsafe.Pointer(p)).Fsharable != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*Tsqlite3)(unsafe.Pointer(db)).FnDb) {
|
|
break
|
|
}
|
|
v4 = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(i)*32))).FpBt
|
|
pSib = v4
|
|
if v4 != uintptr(0) && (*TBtree)(unsafe.Pointer(pSib)).Fsharable != 0 {
|
|
for (*TBtree)(unsafe.Pointer(pSib)).FpPrev != 0 {
|
|
pSib = (*TBtree)(unsafe.Pointer(pSib)).FpPrev
|
|
}
|
|
if uint64((*TBtree)(unsafe.Pointer(p)).FpBt) < uint64((*TBtree)(unsafe.Pointer(pSib)).FpBt) {
|
|
(*TBtree)(unsafe.Pointer(p)).FpNext = pSib
|
|
(*TBtree)(unsafe.Pointer(p)).FpPrev = uintptr(0)
|
|
(*TBtree)(unsafe.Pointer(pSib)).FpPrev = p
|
|
} else {
|
|
for (*TBtree)(unsafe.Pointer(pSib)).FpNext != 0 && uint64((*TBtree)(unsafe.Pointer((*TBtree)(unsafe.Pointer(pSib)).FpNext)).FpBt) < uint64((*TBtree)(unsafe.Pointer(p)).FpBt) {
|
|
pSib = (*TBtree)(unsafe.Pointer(pSib)).FpNext
|
|
}
|
|
(*TBtree)(unsafe.Pointer(p)).FpNext = (*TBtree)(unsafe.Pointer(pSib)).FpNext
|
|
(*TBtree)(unsafe.Pointer(p)).FpPrev = pSib
|
|
if (*TBtree)(unsafe.Pointer(p)).FpNext != 0 {
|
|
(*TBtree)(unsafe.Pointer((*TBtree)(unsafe.Pointer(p)).FpNext)).FpPrev = p
|
|
}
|
|
(*TBtree)(unsafe.Pointer(pSib)).FpNext = p
|
|
}
|
|
break
|
|
}
|
|
goto _8
|
|
_8:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppBtree)) = p
|
|
goto btree_open_out
|
|
btree_open_out:
|
|
;
|
|
if rc != SQLITE_OK {
|
|
if pBt != 0 && (*TBtShared)(unsafe.Pointer(pBt)).FpPager != 0 {
|
|
_sqlite3PagerClose(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager, uintptr(0))
|
|
}
|
|
Xsqlite3_free(tls, pBt)
|
|
Xsqlite3_free(tls, p)
|
|
**(**uintptr)(__ccgo_up(ppBtree)) = uintptr(0)
|
|
} else {
|
|
/* If the B-Tree was successfully opened, set the pager-cache size to the
|
|
** default value. Except, when opening on an existing shared pager-cache,
|
|
** do not change the pager-cache size.
|
|
*/
|
|
if _sqlite3BtreeSchema(tls, p, 0, uintptr(0)) == uintptr(0) {
|
|
_sqlite3BtreeSetCacheSize(tls, p, -int32(2000))
|
|
}
|
|
pFile = _sqlite3PagerFile(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager)
|
|
if (*Tsqlite3_file)(unsafe.Pointer(pFile)).FpMethods != 0 {
|
|
_sqlite3OsFileControlHint(tls, pFile, int32(SQLITE_FCNTL_PDB), pBt+8)
|
|
}
|
|
}
|
|
if mutexOpen != 0 {
|
|
Xsqlite3_mutex_leave(tls, mutexOpen)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Remove entries from the sqlite_statN tables (for N in (1,2,3))
|
|
// ** after a DROP INDEX or DROP TABLE command.
|
|
// */
|
|
func _sqlite3ClearStatTables(tls *libc.TLS, pParse uintptr, iDb int32, zType uintptr, zName uintptr) {
|
|
bp := tls.Alloc(64)
|
|
defer tls.Free(64)
|
|
var i int32
|
|
var zDbName uintptr
|
|
var _ /* zTab at bp+0 */ [24]uint8
|
|
_, _ = i, zDbName
|
|
zDbName = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer(pParse)).Fdb)).FaDb + uintptr(iDb)*32))).FzDbSName
|
|
i = int32(1)
|
|
for {
|
|
if !(i <= int32(4)) {
|
|
break
|
|
}
|
|
Xsqlite3_snprintf(tls, int32(24), bp, __ccgo_ts+14979, libc.VaList(bp+32, i))
|
|
if _sqlite3FindTable(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, bp, zDbName) != 0 {
|
|
_sqlite3NestedParse(tls, pParse, __ccgo_ts+12964, libc.VaList(bp+32, zDbName, bp, zType, zName))
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Generate code that will construct an ephemeral table containing all terms
|
|
// ** in the RHS of an IN operator. The IN operator can be in either of two
|
|
// ** forms:
|
|
// **
|
|
// ** x IN (4,5,11) -- IN operator with list on right-hand side
|
|
// ** x IN (SELECT a FROM b) -- IN operator with subquery on the right
|
|
// **
|
|
// ** The pExpr parameter is the IN operator. The cursor number for the
|
|
// ** constructed ephemeral table is returned. The first time the ephemeral
|
|
// ** table is computed, the cursor number is also stored in pExpr->iTable,
|
|
// ** however the cursor number returned might not be the same, as it might
|
|
// ** have been duplicated using OP_OpenDup.
|
|
// **
|
|
// ** If the LHS expression ("x" in the examples) is a column value, or
|
|
// ** the SELECT statement returns a column value, then the affinity of that
|
|
// ** column is used to build the index keys. If both 'x' and the
|
|
// ** SELECT... statement are columns, then numeric affinity is used
|
|
// ** if either column has NUMERIC or INTEGER affinity. If neither
|
|
// ** 'x' nor the SELECT... statement are columns, then numeric affinity
|
|
// ** is used.
|
|
// */
|
|
func _sqlite3CodeRhsOfIN(tls *libc.TLS, pParse uintptr, pExpr uintptr, iTab int32, allowBloom int32) {
|
|
bp := tls.Alloc(80)
|
|
defer tls.Free(80)
|
|
var addr, addrBloom, addrOnce, i, i1, nVal, r1, r2, rc, regBloom, v1 int32
|
|
var p, pCopy, pE2, pEList, pItem, pKeyInfo, pLeft, pList, pSelect, pSig, v, v2 uintptr
|
|
var _ /* affinity at bp+40 */ uint8
|
|
var _ /* dest at bp+0 */ TSelectDest
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = addr, addrBloom, addrOnce, i, i1, nVal, p, pCopy, pE2, pEList, pItem, pKeyInfo, pLeft, pList, pSelect, pSig, r1, r2, rc, regBloom, v, v1, v2
|
|
addrOnce = 0 /* the LHS of the IN operator */
|
|
pKeyInfo = uintptr(0) /* The prepared statement under construction */
|
|
pSig = uintptr(0) /* Signature for this subroutine */
|
|
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
|
|
/* The evaluation of the IN must be repeated every time it
|
|
** is encountered if any of the following is true:
|
|
**
|
|
** * The right-hand side is a correlated subquery
|
|
** * The right-hand side is an expression list containing variables
|
|
** * We are inside a trigger
|
|
**
|
|
** If all of the above are false, then we can compute the RHS just once
|
|
** and reuse it many names.
|
|
*/
|
|
if !((*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_VarSelect)) != libc.Uint32FromInt32(0)) && (*TParse)(unsafe.Pointer(pParse)).FiSelfTab == 0 {
|
|
/* Reuse of the RHS is allowed
|
|
**
|
|
** Compute a signature for the RHS of the IN operator to facility
|
|
** finding and reusing prior instances of the same IN operator.
|
|
*/
|
|
if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&uint32(EP_xIsSelect) != uint32(0) && (*TSelect)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)))).FselFlags&uint32(SF_All) == uint32(0) {
|
|
pSig = _sqlite3DbMallocRawNN(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, uint64(32))
|
|
if pSig != 0 {
|
|
(*TSubrtnSig)(unsafe.Pointer(pSig)).FselId = libc.Int32FromUint32((*TSelect)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)))).FselId)
|
|
(*TSubrtnSig)(unsafe.Pointer(pSig)).FzAff = _exprINAffinity(tls, pParse, pExpr)
|
|
}
|
|
}
|
|
/* Check to see if there is a prior materialization of the RHS of
|
|
** this IN operator. If there is, then make use of that prior
|
|
** materialization rather than recomputing it.
|
|
*/
|
|
if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Subrtn)) != uint32(0) || _findCompatibleInRhsSubrtn(tls, pParse, pExpr, pSig) != 0 {
|
|
addrOnce = _sqlite3VdbeAddOp0(tls, v, int32(OP_Once))
|
|
if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&uint32(EP_xIsSelect) != uint32(0) {
|
|
_sqlite3VdbeExplain(tls, pParse, uint8(0), __ccgo_ts+8357, libc.VaList(bp+56, (*TSelect)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)))).FselId))
|
|
}
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Gosub), (*(*struct {
|
|
FiAddr int32
|
|
FregReturn int32
|
|
})(unsafe.Pointer(pExpr + 64))).FregReturn, (*(*struct {
|
|
FiAddr int32
|
|
FregReturn int32
|
|
})(unsafe.Pointer(pExpr + 64))).FiAddr)
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_OpenDup), iTab, (*TExpr)(unsafe.Pointer(pExpr)).FiTable)
|
|
_sqlite3VdbeJumpHere(tls, v, addrOnce)
|
|
if pSig != 0 {
|
|
_sqlite3DbFree(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, (*TSubrtnSig)(unsafe.Pointer(pSig)).FzAff)
|
|
_sqlite3DbFree(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pSig)
|
|
}
|
|
return
|
|
}
|
|
/* Begin coding the subroutine */
|
|
**(**Tu32)(__ccgo_up(pExpr + 4)) |= libc.Uint32FromInt32(libc.Int32FromInt32(EP_Subrtn))
|
|
v2 = pParse + 60
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
(*(*struct {
|
|
FiAddr int32
|
|
FregReturn int32
|
|
})(unsafe.Pointer(pExpr + 64))).FregReturn = v1
|
|
(*(*struct {
|
|
FiAddr int32
|
|
FregReturn int32
|
|
})(unsafe.Pointer(pExpr + 64))).FiAddr = _sqlite3VdbeAddOp2(tls, v, int32(OP_BeginSubrtn), 0, (*(*struct {
|
|
FiAddr int32
|
|
FregReturn int32
|
|
})(unsafe.Pointer(pExpr + 64))).FregReturn) + int32(1)
|
|
if pSig != 0 {
|
|
(*TSubrtnSig)(unsafe.Pointer(pSig)).FbComplete = uint8(0)
|
|
(*TSubrtnSig)(unsafe.Pointer(pSig)).FiAddr = (*(*struct {
|
|
FiAddr int32
|
|
FregReturn int32
|
|
})(unsafe.Pointer(pExpr + 64))).FiAddr
|
|
(*TSubrtnSig)(unsafe.Pointer(pSig)).FregReturn = (*(*struct {
|
|
FiAddr int32
|
|
FregReturn int32
|
|
})(unsafe.Pointer(pExpr + 64))).FregReturn
|
|
(*TSubrtnSig)(unsafe.Pointer(pSig)).FiTable = iTab
|
|
(*TParse)(unsafe.Pointer(pParse)).FmSubrtnSig = libc.Uint8FromInt32(int32(1) << ((*TSubrtnSig)(unsafe.Pointer(pSig)).FselId & int32(7)))
|
|
_sqlite3VdbeChangeP4(tls, v, -int32(1), pSig, -int32(18))
|
|
}
|
|
addrOnce = _sqlite3VdbeAddOp0(tls, v, int32(OP_Once))
|
|
}
|
|
/* Check to see if this is a vector IN operator */
|
|
pLeft = (*TExpr)(unsafe.Pointer(pExpr)).FpLeft
|
|
nVal = _sqlite3ExprVectorSize(tls, pLeft)
|
|
/* Construct the ephemeral table that will contain the content of
|
|
** RHS of the IN operator.
|
|
*/
|
|
(*TExpr)(unsafe.Pointer(pExpr)).FiTable = iTab
|
|
addr = _sqlite3VdbeAddOp2(tls, v, int32(OP_OpenEphemeral), (*TExpr)(unsafe.Pointer(pExpr)).FiTable, nVal)
|
|
pKeyInfo = _sqlite3KeyInfoAlloc(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, nVal, int32(1))
|
|
if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&uint32(EP_xIsSelect) != uint32(0) {
|
|
/* Case 1: expr IN (SELECT ...)
|
|
**
|
|
** Generate code to write the results of the select into the temporary
|
|
** table allocated and opened above.
|
|
*/
|
|
pSelect = *(*uintptr)(unsafe.Pointer(pExpr + 32))
|
|
pEList = (*TSelect)(unsafe.Pointer(pSelect)).FpEList
|
|
if addrOnce != 0 {
|
|
v2 = __ccgo_ts + 1704
|
|
} else {
|
|
v2 = __ccgo_ts + 8380
|
|
}
|
|
_sqlite3VdbeExplain(tls, pParse, uint8(1), __ccgo_ts+8392, libc.VaList(bp+56, v2, (*TSelect)(unsafe.Pointer(pSelect)).FselId))
|
|
/* If the LHS and RHS of the IN operator do not match, that
|
|
** error will have been caught long before we reach this point. */
|
|
if (*TExprList)(unsafe.Pointer(pEList)).FnExpr == nVal {
|
|
addrBloom = 0
|
|
_sqlite3SelectDestInit(tls, bp, int32(SRT_Set), iTab)
|
|
(**(**TSelectDest)(__ccgo_up(bp))).FzAffSdst = _exprINAffinity(tls, pParse, pExpr)
|
|
(*TSelect)(unsafe.Pointer(pSelect)).FiLimit = 0
|
|
if addrOnce != 0 && allowBloom != 0 && (*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer(pParse)).Fdb)).FdbOptFlags&libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_BloomFilter)) == uint32(0) {
|
|
v2 = pParse + 60
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
regBloom = v1
|
|
addrBloom = _sqlite3VdbeAddOp2(tls, v, int32(OP_Blob), int32(10000), regBloom)
|
|
(**(**TSelectDest)(__ccgo_up(bp))).FiSDParm2 = regBloom
|
|
}
|
|
/* Caused by OOM in sqlite3KeyInfoAlloc() */
|
|
pCopy = _sqlite3SelectDup(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pSelect, 0)
|
|
if (*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer(pParse)).Fdb)).FmallocFailed != 0 {
|
|
v1 = int32(1)
|
|
} else {
|
|
v1 = _sqlite3Select(tls, pParse, pCopy, bp)
|
|
}
|
|
rc = v1
|
|
_sqlite3SelectDelete(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pCopy)
|
|
_sqlite3DbFree(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, (**(**TSelectDest)(__ccgo_up(bp))).FzAffSdst)
|
|
if addrBloom != 0 {
|
|
/* Remember that location of the Bloom filter in the P3 operand
|
|
** of the OP_Once that began this subroutine. tag-202407032019 */
|
|
(*TVdbeOp)(unsafe.Pointer(_sqlite3VdbeGetOp(tls, v, addrOnce))).Fp3 = (**(**TSelectDest)(__ccgo_up(bp))).FiSDParm2
|
|
if (**(**TSelectDest)(__ccgo_up(bp))).FiSDParm2 == 0 {
|
|
/* If the Bloom filter won't actually be used, keep it small */
|
|
(*TVdbeOp)(unsafe.Pointer(_sqlite3VdbeGetOp(tls, v, addrBloom))).Fp1 = int32(10)
|
|
}
|
|
}
|
|
if rc != 0 {
|
|
_sqlite3KeyInfoUnref(tls, pKeyInfo)
|
|
return
|
|
}
|
|
/* OOM will cause exit after sqlite3Select() */
|
|
i = 0
|
|
for {
|
|
if !(i < nVal) {
|
|
break
|
|
}
|
|
p = _sqlite3VectorFieldSubexpr(tls, pLeft, i)
|
|
*(*uintptr)(unsafe.Pointer(pKeyInfo + 32 + uintptr(i)*8)) = _sqlite3BinaryCompareCollSeq(tls, pParse, p, (*(*TExprList_item)(unsafe.Pointer(pEList + 8 + uintptr(i)*32))).FpExpr)
|
|
goto _7
|
|
_7:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
} else {
|
|
if *(*uintptr)(unsafe.Pointer(pExpr + 32)) != uintptr(0) {
|
|
pList = *(*uintptr)(unsafe.Pointer(pExpr + 32))
|
|
**(**uint8)(__ccgo_up(bp + 40)) = _sqlite3ExprAffinity(tls, pLeft)
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(bp + 40))) <= int32(SQLITE_AFF_NONE) {
|
|
**(**uint8)(__ccgo_up(bp + 40)) = uint8(SQLITE_AFF_BLOB)
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(bp + 40))) == int32(SQLITE_AFF_REAL) {
|
|
**(**uint8)(__ccgo_up(bp + 40)) = uint8(SQLITE_AFF_NUMERIC)
|
|
}
|
|
}
|
|
if pKeyInfo != 0 {
|
|
*(*uintptr)(unsafe.Pointer(pKeyInfo + 32)) = _sqlite3ExprCollSeq(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft)
|
|
}
|
|
/* Loop through each expression in <exprlist>. */
|
|
r1 = _sqlite3GetTempReg(tls, pParse)
|
|
r2 = _sqlite3GetTempReg(tls, pParse)
|
|
i1 = (*TExprList)(unsafe.Pointer(pList)).FnExpr
|
|
pItem = pList + 8
|
|
for {
|
|
if !(i1 > 0) {
|
|
break
|
|
}
|
|
pE2 = (*TExprList_item)(unsafe.Pointer(pItem)).FpExpr
|
|
/* If the expression is not constant then we will need to
|
|
** disable the test that was generated above that makes sure
|
|
** this code only executes once. Because for a non-constant
|
|
** expression we need to rerun this code each time.
|
|
*/
|
|
if addrOnce != 0 && !(_sqlite3ExprIsConstant(tls, pParse, pE2) != 0) {
|
|
_sqlite3VdbeChangeToNoop(tls, v, addrOnce-int32(1))
|
|
_sqlite3VdbeChangeToNoop(tls, v, addrOnce)
|
|
**(**Tu32)(__ccgo_up(pExpr + 4)) &= ^libc.Uint32FromInt32(libc.Int32FromInt32(EP_Subrtn))
|
|
addrOnce = 0
|
|
}
|
|
/* Evaluate the expression and insert it into the temp table */
|
|
_sqlite3ExprCode(tls, pParse, pE2, r1)
|
|
_sqlite3VdbeAddOp4(tls, v, int32(OP_MakeRecord), r1, int32(1), r2, bp+40, int32(1))
|
|
_sqlite3VdbeAddOp4Int(tls, v, int32(OP_IdxInsert), iTab, r2, r1, int32(1))
|
|
goto _8
|
|
_8:
|
|
;
|
|
i1 = i1 - 1
|
|
pItem += 32
|
|
}
|
|
_sqlite3ReleaseTempReg(tls, pParse, r1)
|
|
_sqlite3ReleaseTempReg(tls, pParse, r2)
|
|
}
|
|
}
|
|
if pSig != 0 {
|
|
(*TSubrtnSig)(unsafe.Pointer(pSig)).FbComplete = uint8(1)
|
|
}
|
|
if pKeyInfo != 0 {
|
|
_sqlite3VdbeChangeP4(tls, v, addr, pKeyInfo, -int32(9))
|
|
}
|
|
if addrOnce != 0 {
|
|
_sqlite3VdbeAddOp1(tls, v, int32(OP_NullRow), iTab)
|
|
_sqlite3VdbeJumpHere(tls, v, addrOnce)
|
|
/* Subroutine return */
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Return), (*(*struct {
|
|
FiAddr int32
|
|
FregReturn int32
|
|
})(unsafe.Pointer(pExpr + 64))).FregReturn, (*(*struct {
|
|
FiAddr int32
|
|
FregReturn int32
|
|
})(unsafe.Pointer(pExpr + 64))).FiAddr, int32(1))
|
|
_sqlite3ClearTempRegCache(tls, pParse)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Generate code for scalar subqueries used as a subquery expression
|
|
// ** or EXISTS operator:
|
|
// **
|
|
// ** (SELECT a FROM b) -- subquery
|
|
// ** EXISTS (SELECT a FROM b) -- EXISTS subquery
|
|
// **
|
|
// ** The pExpr parameter is the SELECT or EXISTS operator to be coded.
|
|
// **
|
|
// ** Return the register that holds the result. For a multi-column SELECT,
|
|
// ** the result is stored in a contiguous array of registers and the
|
|
// ** return value is the register of the left-most result column.
|
|
// ** Return 0 if an error occurs.
|
|
// */
|
|
func _sqlite3CodeSubselect(tls *libc.TLS, pParse uintptr, pExpr uintptr) (r int32) {
|
|
bp := tls.Alloc(64)
|
|
defer tls.Free(64)
|
|
var addrOnce, nReg, rReg, v1 int32
|
|
var db, pLeft, pLimit, pSel, v, v2 uintptr
|
|
var _ /* dest at bp+0 */ TSelectDest
|
|
_, _, _, _, _, _, _, _, _, _ = addrOnce, db, nReg, pLeft, pLimit, pSel, rReg, v, v1, v2
|
|
addrOnce = 0 /* Address of OP_Once at top of subroutine */
|
|
rReg = 0 /* New limit expression */
|
|
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
|
|
if (*TParse)(unsafe.Pointer(pParse)).FnErr != 0 {
|
|
return 0
|
|
}
|
|
pSel = *(*uintptr)(unsafe.Pointer(pExpr + 32))
|
|
/* If this routine has already been coded, then invoke it as a
|
|
** subroutine. */
|
|
if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Subrtn)) != uint32(0) {
|
|
_sqlite3VdbeExplain(tls, pParse, uint8(0), __ccgo_ts+8411, libc.VaList(bp+48, (*TSelect)(unsafe.Pointer(pSel)).FselId))
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Gosub), (*(*struct {
|
|
FiAddr int32
|
|
FregReturn int32
|
|
})(unsafe.Pointer(pExpr + 64))).FregReturn, (*(*struct {
|
|
FiAddr int32
|
|
FregReturn int32
|
|
})(unsafe.Pointer(pExpr + 64))).FiAddr)
|
|
return (*TExpr)(unsafe.Pointer(pExpr)).FiTable
|
|
}
|
|
/* Begin coding the subroutine */
|
|
**(**Tu32)(__ccgo_up(pExpr + 4)) |= libc.Uint32FromInt32(libc.Int32FromInt32(EP_Subrtn))
|
|
v2 = pParse + 60
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
(*(*struct {
|
|
FiAddr int32
|
|
FregReturn int32
|
|
})(unsafe.Pointer(pExpr + 64))).FregReturn = v1
|
|
(*(*struct {
|
|
FiAddr int32
|
|
FregReturn int32
|
|
})(unsafe.Pointer(pExpr + 64))).FiAddr = _sqlite3VdbeAddOp2(tls, v, int32(OP_BeginSubrtn), 0, (*(*struct {
|
|
FiAddr int32
|
|
FregReturn int32
|
|
})(unsafe.Pointer(pExpr + 64))).FregReturn) + int32(1)
|
|
/* The evaluation of the EXISTS/SELECT must be repeated every time it
|
|
** is encountered if any of the following is true:
|
|
**
|
|
** * The right-hand side is a correlated subquery
|
|
** * The right-hand side is an expression list containing variables
|
|
** * We are inside a trigger
|
|
**
|
|
** If all of the above are false, then we can run this code just once
|
|
** save the results, and reuse the same result on subsequent invocations.
|
|
*/
|
|
if !((*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_VarSelect)) != libc.Uint32FromInt32(0)) {
|
|
addrOnce = _sqlite3VdbeAddOp0(tls, v, int32(OP_Once))
|
|
}
|
|
/* For a SELECT, generate code to put the values for all columns of
|
|
** the first row into an array of registers and return the index of
|
|
** the first register.
|
|
**
|
|
** If this is an EXISTS, write an integer 0 (not exists) or 1 (exists)
|
|
** into a register and return that register number.
|
|
**
|
|
** In both cases, the query is augmented with "LIMIT 1". Any
|
|
** preexisting limit is discarded in place of the new LIMIT 1.
|
|
*/
|
|
if addrOnce != 0 {
|
|
v2 = __ccgo_ts + 1704
|
|
} else {
|
|
v2 = __ccgo_ts + 8380
|
|
}
|
|
_sqlite3VdbeExplain(tls, pParse, uint8(1), __ccgo_ts+8429, libc.VaList(bp+48, v2, (*TSelect)(unsafe.Pointer(pSel)).FselId))
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_SELECT) {
|
|
v1 = (*TExprList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pSel)).FpEList)).FnExpr
|
|
} else {
|
|
v1 = int32(1)
|
|
}
|
|
nReg = v1
|
|
_sqlite3SelectDestInit(tls, bp, 0, (*TParse)(unsafe.Pointer(pParse)).FnMem+int32(1))
|
|
**(**int32)(__ccgo_up(pParse + 60)) += nReg
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_SELECT) {
|
|
(**(**TSelectDest)(__ccgo_up(bp))).FeDest = uint8(SRT_Mem)
|
|
if (*TSelect)(unsafe.Pointer(pSel)).FselFlags&uint32(SF_Distinct) != 0 && (*TSelect)(unsafe.Pointer(pSel)).FpLimit != 0 && (*TExpr)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pSel)).FpLimit)).FpRight != 0 {
|
|
/* If there is both a DISTINCT and an OFFSET clause, then allocate
|
|
** a separate dest.iSdst array for sqlite3Select() and other
|
|
** routines to populate. In this case results will be copied over
|
|
** into the dest.iSDParm array only after OFFSET processing. This
|
|
** ensures that in the case where OFFSET excludes all rows, the
|
|
** dest.iSDParm array is not left populated with the contents of the
|
|
** last row visited - it should be all NULLs if all rows were
|
|
** excluded by OFFSET. */
|
|
(**(**TSelectDest)(__ccgo_up(bp))).FiSdst = (*TParse)(unsafe.Pointer(pParse)).FnMem + int32(1)
|
|
**(**int32)(__ccgo_up(pParse + 60)) += nReg
|
|
} else {
|
|
(**(**TSelectDest)(__ccgo_up(bp))).FiSdst = (**(**TSelectDest)(__ccgo_up(bp))).FiSDParm
|
|
}
|
|
(**(**TSelectDest)(__ccgo_up(bp))).FnSdst = nReg
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Null), 0, (**(**TSelectDest)(__ccgo_up(bp))).FiSDParm, (*TParse)(unsafe.Pointer(pParse)).FnMem)
|
|
} else {
|
|
(**(**TSelectDest)(__ccgo_up(bp))).FeDest = uint8(SRT_Exists)
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Integer), 0, (**(**TSelectDest)(__ccgo_up(bp))).FiSDParm)
|
|
}
|
|
if (*TSelect)(unsafe.Pointer(pSel)).FpLimit != 0 {
|
|
/* The subquery already has a limit. If the pre-existing limit X is
|
|
** not already integer value 1 or 0, then make the new limit X<>0 so that
|
|
** the new limit is either 1 or 0 */
|
|
pLeft = (*TExpr)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pSel)).FpLimit)).FpLeft
|
|
if libc.BoolInt32((*TExpr)(unsafe.Pointer(pLeft)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_IntValue)) != uint32(0)) == 0 || *(*int32)(unsafe.Pointer(&(*TExpr)(unsafe.Pointer(pLeft)).Fu)) != int32(1) && *(*int32)(unsafe.Pointer(&(*TExpr)(unsafe.Pointer(pLeft)).Fu)) != 0 {
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
pLimit = _sqlite3ExprInt32(tls, db, 0)
|
|
if pLimit != 0 {
|
|
(*TExpr)(unsafe.Pointer(pLimit)).FaffExpr = uint8(SQLITE_AFF_NUMERIC)
|
|
pLimit = _sqlite3PExpr(tls, pParse, int32(TK_NE), _sqlite3ExprDup(tls, db, pLeft, 0), pLimit)
|
|
}
|
|
_sqlite3ExprDeferredDelete(tls, pParse, pLeft)
|
|
(*TExpr)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pSel)).FpLimit)).FpLeft = pLimit
|
|
}
|
|
} else {
|
|
/* If there is no pre-existing limit add a limit of 1 */
|
|
pLimit = _sqlite3ExprInt32(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, int32(1))
|
|
(*TSelect)(unsafe.Pointer(pSel)).FpLimit = _sqlite3PExpr(tls, pParse, int32(TK_LIMIT), pLimit, uintptr(0))
|
|
}
|
|
(*TSelect)(unsafe.Pointer(pSel)).FiLimit = 0
|
|
if _sqlite3Select(tls, pParse, pSel, bp) != 0 {
|
|
(*TExpr)(unsafe.Pointer(pExpr)).Fop2 = (*TExpr)(unsafe.Pointer(pExpr)).Fop
|
|
(*TExpr)(unsafe.Pointer(pExpr)).Fop = uint8(TK_ERROR)
|
|
return 0
|
|
}
|
|
v1 = (**(**TSelectDest)(__ccgo_up(bp))).FiSDParm
|
|
rReg = v1
|
|
(*TExpr)(unsafe.Pointer(pExpr)).FiTable = v1
|
|
if addrOnce != 0 {
|
|
_sqlite3VdbeJumpHere(tls, v, addrOnce)
|
|
}
|
|
/* Subroutine return */
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Return), (*(*struct {
|
|
FiAddr int32
|
|
FregReturn int32
|
|
})(unsafe.Pointer(pExpr + 64))).FregReturn, (*(*struct {
|
|
FiAddr int32
|
|
FregReturn int32
|
|
})(unsafe.Pointer(pExpr + 64))).FiAddr, int32(1))
|
|
_sqlite3ClearTempRegCache(tls, pParse)
|
|
return rReg
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** All regular columns for table pTab have been puts into registers
|
|
// ** starting with iRegStore. The registers that correspond to STORED
|
|
// ** or VIRTUAL columns have not yet been initialized. This routine goes
|
|
// ** back and computes the values for those columns based on the previously
|
|
// ** computed normal columns.
|
|
// */
|
|
func _sqlite3ComputeGeneratedColumns(tls *libc.TLS, pParse uintptr, iRegStore int32, pTab uintptr) {
|
|
bp := tls.Alloc(64)
|
|
defer tls.Free(64)
|
|
var eProgress, i, ii, jj, x, v2 int32
|
|
var pCol, pOp, pRedo, zP4, v4 uintptr
|
|
var _ /* w at bp+0 */ TWalker
|
|
_, _, _, _, _, _, _, _, _, _, _ = eProgress, i, ii, jj, pCol, pOp, pRedo, x, zP4, v2, v4
|
|
/* Before computing generated columns, first go through and make sure
|
|
** that appropriate affinity has been applied to the regular columns
|
|
*/
|
|
_sqlite3TableAffinity(tls, (*TParse)(unsafe.Pointer(pParse)).FpVdbe, pTab, iRegStore)
|
|
if (*TTable)(unsafe.Pointer(pTab)).FtabFlags&uint32(TF_HasStored) != uint32(0) {
|
|
pOp = _sqlite3VdbeGetLastOp(tls, (*TParse)(unsafe.Pointer(pParse)).FpVdbe)
|
|
if libc.Int32FromUint8((*TVdbeOp)(unsafe.Pointer(pOp)).Fopcode) == int32(OP_Affinity) {
|
|
zP4 = *(*uintptr)(unsafe.Pointer(pOp + 16))
|
|
v2 = libc.Int32FromInt32(0)
|
|
jj = v2
|
|
ii = v2
|
|
for {
|
|
if !(**(**uint8)(__ccgo_up(zP4 + uintptr(jj))) != 0) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint16((**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(ii)*16))).FcolFlags)&int32(COLFLAG_VIRTUAL) != 0 {
|
|
goto _1
|
|
}
|
|
if libc.Int32FromUint16((**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(ii)*16))).FcolFlags)&int32(COLFLAG_STORED) != 0 {
|
|
**(**uint8)(__ccgo_up(zP4 + uintptr(jj))) = uint8(SQLITE_AFF_NONE)
|
|
}
|
|
jj = jj + 1
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint8((*TVdbeOp)(unsafe.Pointer(pOp)).Fopcode) == int32(OP_TypeCheck) {
|
|
/* If an OP_TypeCheck was generated because the table is STRICT,
|
|
** then set the P3 operand to indicate that generated columns should
|
|
** not be checked */
|
|
(*TVdbeOp)(unsafe.Pointer(pOp)).Fp3 = int32(1)
|
|
}
|
|
}
|
|
}
|
|
/* Because there can be multiple generated columns that refer to one another,
|
|
** this is a two-pass algorithm. On the first pass, mark all generated
|
|
** columns as "not available".
|
|
*/
|
|
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_GENERATED) != 0 {
|
|
v4 = (*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(i)*16 + 14
|
|
*(*Tu16)(unsafe.Pointer(v4)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v4))) | libc.Int32FromInt32(COLFLAG_NOTAVAIL))
|
|
}
|
|
goto _3
|
|
_3:
|
|
;
|
|
i = i + 1
|
|
}
|
|
*(*uintptr)(unsafe.Pointer(bp + 40)) = pTab
|
|
(**(**TWalker)(__ccgo_up(bp))).FxExprCallback = __ccgo_fp(_exprColumnFlagUnion)
|
|
(**(**TWalker)(__ccgo_up(bp))).FxSelectCallback = uintptr(0)
|
|
(**(**TWalker)(__ccgo_up(bp))).FxSelectCallback2 = uintptr(0)
|
|
/* On the second pass, compute the value of each NOT-AVAILABLE column.
|
|
** Companion code in the TK_COLUMN case of sqlite3ExprCodeTarget() will
|
|
** compute dependencies and mark remove the COLSPAN_NOTAVAIL mark, as
|
|
** they are needed.
|
|
*/
|
|
(*TParse)(unsafe.Pointer(pParse)).FiSelfTab = -iRegStore
|
|
for cond := true; cond; cond = pRedo != 0 && eProgress != 0 {
|
|
eProgress = 0
|
|
pRedo = uintptr(0)
|
|
i = 0
|
|
for {
|
|
if !(i < int32((*TTable)(unsafe.Pointer(pTab)).FnCol)) {
|
|
break
|
|
}
|
|
pCol = (*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(i)*16
|
|
if libc.Int32FromUint16((*TColumn)(unsafe.Pointer(pCol)).FcolFlags)&int32(COLFLAG_NOTAVAIL) != 0 {
|
|
v4 = pCol + 14
|
|
*(*Tu16)(unsafe.Pointer(v4)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v4))) | libc.Int32FromInt32(COLFLAG_BUSY))
|
|
(**(**TWalker)(__ccgo_up(bp))).FeCode = uint16(0)
|
|
_sqlite3WalkExpr(tls, bp, _sqlite3ColumnExpr(tls, pTab, pCol))
|
|
v4 = pCol + 14
|
|
*(*Tu16)(unsafe.Pointer(v4)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v4))) & ^libc.Int32FromInt32(COLFLAG_BUSY))
|
|
if libc.Int32FromUint16((**(**TWalker)(__ccgo_up(bp))).FeCode)&int32(COLFLAG_NOTAVAIL) != 0 {
|
|
pRedo = pCol
|
|
goto _5
|
|
}
|
|
eProgress = int32(1)
|
|
x = int32(_sqlite3TableColumnToStorage(tls, pTab, int16(i))) + iRegStore
|
|
_sqlite3ExprCodeGeneratedColumn(tls, pParse, pTab, pCol, x)
|
|
v4 = pCol + 14
|
|
*(*Tu16)(unsafe.Pointer(v4)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v4))) & ^libc.Int32FromInt32(COLFLAG_NOTAVAIL))
|
|
}
|
|
goto _5
|
|
_5:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
if pRedo != 0 {
|
|
_sqlite3ErrorMsg(tls, pParse, __ccgo_ts+8480, libc.VaList(bp+56, (*TColumn)(unsafe.Pointer(pRedo)).FzCnName))
|
|
}
|
|
(*TParse)(unsafe.Pointer(pParse)).FiSelfTab = 0
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This routine is called to create a new foreign key on the table
|
|
// ** currently under construction. pFromCol determines which columns
|
|
// ** in the current table point to the foreign key. If pFromCol==0 then
|
|
// ** connect the key to the last column inserted. pTo is the name of
|
|
// ** the table referred to (a.k.a the "parent" table). pToCol is a list
|
|
// ** of tables in the parent pTo table. flags contains all
|
|
// ** information about the conflict resolution algorithms specified
|
|
// ** in the ON DELETE, ON UPDATE and ON INSERT clauses.
|
|
// **
|
|
// ** An FKey structure is created and added to the table currently
|
|
// ** under construction in the pParse->pNewTable field.
|
|
// **
|
|
// ** The foreign key is set for IMMEDIATE processing. A subsequent call
|
|
// ** to sqlite3DeferForeignKey() might change this to DEFERRED.
|
|
// */
|
|
func _sqlite3CreateForeignKey(tls *libc.TLS, pParse uintptr, pFromCol uintptr, pTo uintptr, pToCol uintptr, flags int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var db, p, pFKey, pNextTo, z uintptr
|
|
var i, iCol, j, n, nCol int32
|
|
var nByte Ti64
|
|
_, _, _, _, _, _, _, _, _, _, _ = db, i, iCol, j, n, nByte, nCol, p, pFKey, pNextTo, z
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
pFKey = uintptr(0)
|
|
p = (*TParse)(unsafe.Pointer(pParse)).FpNewTable
|
|
if p == uintptr(0) || libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) == int32(PARSE_MODE_DECLARE_VTAB) {
|
|
goto fk_end
|
|
}
|
|
if pFromCol == uintptr(0) {
|
|
iCol = int32((*TTable)(unsafe.Pointer(p)).FnCol) - int32(1)
|
|
if iCol < 0 {
|
|
goto fk_end
|
|
}
|
|
if pToCol != 0 && (*TExprList)(unsafe.Pointer(pToCol)).FnExpr != int32(1) {
|
|
_sqlite3ErrorMsg(tls, pParse, __ccgo_ts+15199, libc.VaList(bp+8, (**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(p)).FaCol + uintptr(iCol)*16))).FzCnName, pTo))
|
|
goto fk_end
|
|
}
|
|
nCol = int32(1)
|
|
} else {
|
|
if pToCol != 0 && (*TExprList)(unsafe.Pointer(pToCol)).FnExpr != (*TExprList)(unsafe.Pointer(pFromCol)).FnExpr {
|
|
_sqlite3ErrorMsg(tls, pParse, __ccgo_ts+15262, 0)
|
|
goto fk_end
|
|
} else {
|
|
nCol = (*TExprList)(unsafe.Pointer(pFromCol)).FnExpr
|
|
}
|
|
}
|
|
nByte = libc.Int64FromUint64(uint64(libc.UintptrFromInt32(0)+64) + libc.Uint64FromInt32(nCol)*uint64(16) + uint64((*TToken)(unsafe.Pointer(pTo)).Fn) + uint64(1))
|
|
if pToCol != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TExprList)(unsafe.Pointer(pToCol)).FnExpr) {
|
|
break
|
|
}
|
|
nByte = nByte + int64(_sqlite3Strlen30(tls, (*(*TExprList_item)(unsafe.Pointer(pToCol + 8 + uintptr(i)*32))).FzEName)+int32(1))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
pFKey = _sqlite3DbMallocZero(tls, db, libc.Uint64FromInt64(nByte))
|
|
if pFKey == uintptr(0) {
|
|
goto fk_end
|
|
}
|
|
(*TFKey)(unsafe.Pointer(pFKey)).FpFrom = p
|
|
(*TFKey)(unsafe.Pointer(pFKey)).FpNextFrom = (*(*struct {
|
|
FaddColOffset int32
|
|
FpFKey uintptr
|
|
FpDfltList uintptr
|
|
})(unsafe.Pointer(p + 64))).FpFKey
|
|
z = pFKey + 64 + uintptr(nCol)*16
|
|
(*TFKey)(unsafe.Pointer(pFKey)).FzTo = z
|
|
if libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= int32(PARSE_MODE_RENAME) {
|
|
_sqlite3RenameTokenMap(tls, pParse, z, pTo)
|
|
}
|
|
libc.Xmemcpy(tls, z, (*TToken)(unsafe.Pointer(pTo)).Fz, uint64((*TToken)(unsafe.Pointer(pTo)).Fn))
|
|
**(**uint8)(__ccgo_up(z + uintptr((*TToken)(unsafe.Pointer(pTo)).Fn))) = uint8(0)
|
|
_sqlite3Dequote(tls, z)
|
|
z = z + uintptr((*TToken)(unsafe.Pointer(pTo)).Fn+uint32(1))
|
|
(*TFKey)(unsafe.Pointer(pFKey)).FnCol = nCol
|
|
if pFromCol == uintptr(0) {
|
|
(*(*TsColMap)(unsafe.Pointer(pFKey + 64))).FiFrom = int32((*TTable)(unsafe.Pointer(p)).FnCol) - int32(1)
|
|
} else {
|
|
i = 0
|
|
for {
|
|
if !(i < nCol) {
|
|
break
|
|
}
|
|
j = 0
|
|
for {
|
|
if !(j < int32((*TTable)(unsafe.Pointer(p)).FnCol)) {
|
|
break
|
|
}
|
|
if _sqlite3StrICmp(tls, (**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(p)).FaCol + uintptr(j)*16))).FzCnName, (*(*TExprList_item)(unsafe.Pointer(pFromCol + 8 + uintptr(i)*32))).FzEName) == 0 {
|
|
(*(*TsColMap)(unsafe.Pointer(pFKey + 64 + uintptr(i)*16))).FiFrom = j
|
|
break
|
|
}
|
|
goto _3
|
|
_3:
|
|
;
|
|
j = j + 1
|
|
}
|
|
if j >= int32((*TTable)(unsafe.Pointer(p)).FnCol) {
|
|
_sqlite3ErrorMsg(tls, pParse, __ccgo_ts+15356, libc.VaList(bp+8, (*(*TExprList_item)(unsafe.Pointer(pFromCol + 8 + uintptr(i)*32))).FzEName))
|
|
goto fk_end
|
|
}
|
|
if libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= int32(PARSE_MODE_RENAME) {
|
|
_sqlite3RenameTokenRemap(tls, pParse, pFKey+64+uintptr(i)*16, (*(*TExprList_item)(unsafe.Pointer(pFromCol + 8 + uintptr(i)*32))).FzEName)
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
if pToCol != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < nCol) {
|
|
break
|
|
}
|
|
n = _sqlite3Strlen30(tls, (*(*TExprList_item)(unsafe.Pointer(pToCol + 8 + uintptr(i)*32))).FzEName)
|
|
(*(*TsColMap)(unsafe.Pointer(pFKey + 64 + uintptr(i)*16))).FzCol = z
|
|
if libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= int32(PARSE_MODE_RENAME) {
|
|
_sqlite3RenameTokenRemap(tls, pParse, z, (*(*TExprList_item)(unsafe.Pointer(pToCol + 8 + uintptr(i)*32))).FzEName)
|
|
}
|
|
libc.Xmemcpy(tls, z, (*(*TExprList_item)(unsafe.Pointer(pToCol + 8 + uintptr(i)*32))).FzEName, libc.Uint64FromInt32(n))
|
|
**(**uint8)(__ccgo_up(z + uintptr(n))) = uint8(0)
|
|
z = z + uintptr(n+int32(1))
|
|
goto _4
|
|
_4:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
(*TFKey)(unsafe.Pointer(pFKey)).FisDeferred = uint8(0)
|
|
**(**Tu8)(__ccgo_up(pFKey + 45)) = libc.Uint8FromInt32(flags & libc.Int32FromInt32(0xff)) /* ON DELETE action */
|
|
**(**Tu8)(__ccgo_up(pFKey + 45 + 1)) = libc.Uint8FromInt32(flags >> libc.Int32FromInt32(8) & libc.Int32FromInt32(0xff)) /* ON UPDATE action */
|
|
pNextTo = _sqlite3HashInsert(tls, (*TTable)(unsafe.Pointer(p)).FpSchema+80, (*TFKey)(unsafe.Pointer(pFKey)).FzTo, pFKey)
|
|
if pNextTo == pFKey {
|
|
_sqlite3OomFault(tls, db)
|
|
goto fk_end
|
|
}
|
|
if pNextTo != 0 {
|
|
(*TFKey)(unsafe.Pointer(pFKey)).FpNextTo = pNextTo
|
|
(*TFKey)(unsafe.Pointer(pNextTo)).FpPrevTo = pFKey
|
|
}
|
|
/* Link the foreign key to the table as the last step.
|
|
*/
|
|
(*(*struct {
|
|
FaddColOffset int32
|
|
FpFKey uintptr
|
|
FpDfltList uintptr
|
|
})(unsafe.Pointer(p + 64))).FpFKey = pFKey
|
|
pFKey = uintptr(0)
|
|
goto fk_end
|
|
fk_end:
|
|
;
|
|
_sqlite3DbFree(tls, db, pFKey)
|
|
_sqlite3ExprListDelete(tls, db, pFromCol)
|
|
_sqlite3ExprListDelete(tls, db, pToCol)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The parser calls this routine in order to create a new VIEW
|
|
// */
|
|
func _sqlite3CreateView(tls *libc.TLS, pParse uintptr, pBegin uintptr, pName1 uintptr, pName2 uintptr, pCNames uintptr, pSelect uintptr, isTemp int32, noErr int32) {
|
|
bp := tls.Alloc(128)
|
|
defer tls.Free(128)
|
|
var db, p, z uintptr
|
|
var iDb, n int32
|
|
var _ /* pName at bp+112 */ uintptr
|
|
var _ /* sEnd at bp+0 */ TToken
|
|
var _ /* sFix at bp+16 */ TDbFixer
|
|
_, _, _, _, _ = db, iDb, n, p, z
|
|
**(**uintptr)(__ccgo_up(bp + 112)) = uintptr(0)
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
if int32((*TParse)(unsafe.Pointer(pParse)).FnVar) > 0 {
|
|
_sqlite3ErrorMsg(tls, pParse, __ccgo_ts+14831, 0)
|
|
goto create_view_fail
|
|
}
|
|
_sqlite3StartTable(tls, pParse, pName1, pName2, isTemp, int32(1), 0, noErr)
|
|
p = (*TParse)(unsafe.Pointer(pParse)).FpNewTable
|
|
if p == uintptr(0) || (*TParse)(unsafe.Pointer(pParse)).FnErr != 0 {
|
|
goto create_view_fail
|
|
}
|
|
/* Legacy versions of SQLite allowed the use of the magic "rowid" column
|
|
** on a view, even though views do not have rowids. The following flag
|
|
** setting fixes this problem. But the fix can be disabled by compiling
|
|
** with -DSQLITE_ALLOW_ROWID_IN_VIEW in case there are legacy apps that
|
|
** depend upon the old buggy behavior. The ability can also be toggled
|
|
** using sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW,...) */
|
|
**(**Tu32)(__ccgo_up(p + 48)) |= uint32(TF_NoVisibleRowid) /* Never allow rowid in view */
|
|
_sqlite3TwoPartName(tls, pParse, pName1, pName2, bp+112)
|
|
iDb = _sqlite3SchemaToIndex(tls, db, (*TTable)(unsafe.Pointer(p)).FpSchema)
|
|
_sqlite3FixInit(tls, bp+16, pParse, iDb, __ccgo_ts+11143, **(**uintptr)(__ccgo_up(bp + 112)))
|
|
if _sqlite3FixSelect(tls, bp+16, pSelect) != 0 {
|
|
goto create_view_fail
|
|
}
|
|
/* Make a copy of the entire SELECT statement that defines the view.
|
|
** This will force all the Expr.token.z values to be dynamically
|
|
** allocated rather than point to the input string - which means that
|
|
** they will persist after the current sqlite3_exec() call returns.
|
|
*/
|
|
**(**Tu32)(__ccgo_up(pSelect + 4)) |= uint32(SF_View)
|
|
if libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= int32(PARSE_MODE_RENAME) {
|
|
(*(*struct {
|
|
FpSelect uintptr
|
|
})(unsafe.Pointer(&(*TTable)(unsafe.Pointer(p)).Fu))).FpSelect = pSelect
|
|
pSelect = uintptr(0)
|
|
} else {
|
|
(*(*struct {
|
|
FpSelect uintptr
|
|
})(unsafe.Pointer(&(*TTable)(unsafe.Pointer(p)).Fu))).FpSelect = _sqlite3SelectDup(tls, db, pSelect, int32(EXPRDUP_REDUCE))
|
|
}
|
|
(*TTable)(unsafe.Pointer(p)).FpCheck = _sqlite3ExprListDup(tls, db, pCNames, int32(EXPRDUP_REDUCE))
|
|
(*TTable)(unsafe.Pointer(p)).FeTabType = uint8(TABTYP_VIEW)
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
|
|
goto create_view_fail
|
|
}
|
|
/* Locate the end of the CREATE VIEW statement. Make sEnd point to
|
|
** the end.
|
|
*/
|
|
**(**TToken)(__ccgo_up(bp)) = (*TParse)(unsafe.Pointer(pParse)).FsLastToken
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up((**(**TToken)(__ccgo_up(bp))).Fz))) != int32(';') {
|
|
(**(**TToken)(__ccgo_up(bp))).Fz += uintptr((**(**TToken)(__ccgo_up(bp))).Fn)
|
|
}
|
|
(**(**TToken)(__ccgo_up(bp))).Fn = uint32(0)
|
|
n = int32(int64((**(**TToken)(__ccgo_up(bp))).Fz) - int64((*TToken)(unsafe.Pointer(pBegin)).Fz))
|
|
z = (*TToken)(unsafe.Pointer(pBegin)).Fz
|
|
for libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(n-int32(1)))))])&int32(0x01) != 0 {
|
|
n = n - 1
|
|
}
|
|
(**(**TToken)(__ccgo_up(bp))).Fz = z + uintptr(n-int32(1))
|
|
(**(**TToken)(__ccgo_up(bp))).Fn = uint32(1)
|
|
/* Use sqlite3EndTable() to add the view to the schema table */
|
|
_sqlite3EndTable(tls, pParse, uintptr(0), bp, uint32(0), uintptr(0))
|
|
goto create_view_fail
|
|
create_view_fail:
|
|
;
|
|
_sqlite3SelectDelete(tls, db, pSelect)
|
|
if libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= int32(PARSE_MODE_RENAME) {
|
|
_sqlite3RenameExprlistUnmap(tls, pParse, pCNames)
|
|
}
|
|
_sqlite3ExprListDelete(tls, db, pCNames)
|
|
return
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Transform a UTF-8 integer literal, in either decimal or hexadecimal,
|
|
// ** into a 64-bit signed integer. This routine accepts hexadecimal literals,
|
|
// ** whereas sqlite3Atoi64() does not.
|
|
// **
|
|
// ** Returns:
|
|
// **
|
|
// ** 0 Successful transformation. Fits in a 64-bit signed integer.
|
|
// ** 1 Excess text after the integer value
|
|
// ** 2 Integer too large for a 64-bit signed integer or is malformed
|
|
// ** 3 Special case of 9223372036854775808
|
|
// */
|
|
func _sqlite3DecOrHexToI64(tls *libc.TLS, z uintptr, pOut uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var i, k, n int32
|
|
var _ /* u at bp+0 */ Tu64
|
|
_, _, _ = i, k, n
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) == int32('0') && (libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 1))) == int32('x') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 1))) == int32('X')) {
|
|
**(**Tu64)(__ccgo_up(bp)) = uint64(0)
|
|
i = int32(2)
|
|
for {
|
|
if !(libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) == int32('0')) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
k = i
|
|
for {
|
|
if !(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z + uintptr(k))))])&int32(0x08) != 0) {
|
|
break
|
|
}
|
|
**(**Tu64)(__ccgo_up(bp)) = **(**Tu64)(__ccgo_up(bp))*uint64(16) + uint64(_sqlite3HexToInt(tls, libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(k))))))
|
|
goto _2
|
|
_2:
|
|
;
|
|
k = k + 1
|
|
}
|
|
libc.Xmemcpy(tls, pOut, bp, uint64(8))
|
|
if k-i > int32(16) {
|
|
return int32(2)
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(k)))) != 0 {
|
|
return int32(1)
|
|
}
|
|
return 0
|
|
} else {
|
|
n = libc.Int32FromUint64(libc.Uint64FromInt32(0x3fffffff) & libc.Xstrspn(tls, z, __ccgo_ts+1834))
|
|
if **(**uint8)(__ccgo_up(z + uintptr(n))) != 0 {
|
|
n = n + 1
|
|
}
|
|
return _sqlite3Atoi64(tls, z, pOut, n, uint8(SQLITE_UTF8))
|
|
}
|
|
return r
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Expression p is a QNUMBER (quoted number). Dequote the value in p->u.zToken
|
|
// ** and set the type to INTEGER or FLOAT. "Quoted" integers or floats are those
|
|
// ** that contain '_' characters that must be removed before further processing.
|
|
// */
|
|
func _sqlite3DequoteNumber(tls *libc.TLS, pParse uintptr, p uintptr) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var bHex int32
|
|
var pIn, pOut, v1, v3 uintptr
|
|
var _ /* iValue at bp+0 */ int32
|
|
_, _, _, _, _ = bHex, pIn, pOut, v1, v3
|
|
if p != 0 {
|
|
pIn = *(*uintptr)(unsafe.Pointer(p + 8))
|
|
pOut = *(*uintptr)(unsafe.Pointer(p + 8))
|
|
bHex = libc.BoolInt32(libc.Int32FromUint8(**(**uint8)(__ccgo_up(pIn))) == int32('0') && (libc.Int32FromUint8(**(**uint8)(__ccgo_up(pIn + 1))) == int32('x') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(pIn + 1))) == int32('X')))
|
|
(*TExpr)(unsafe.Pointer(p)).Fop = uint8(TK_INTEGER)
|
|
for {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(pIn))) != int32('_') {
|
|
v3 = pOut
|
|
pOut = pOut + 1
|
|
**(**uint8)(__ccgo_up(v3)) = **(**uint8)(__ccgo_up(pIn))
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(pIn))) == int32('e') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(pIn))) == int32('E') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(pIn))) == int32('.') {
|
|
(*TExpr)(unsafe.Pointer(p)).Fop = uint8(TK_FLOAT)
|
|
}
|
|
} else {
|
|
if bHex == 0 && (!(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(pIn + uintptr(-libc.Int32FromInt32(1)))))])&libc.Int32FromInt32(0x04) != 0) || !(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(pIn + 1)))])&libc.Int32FromInt32(0x04) != 0)) || bHex == int32(1) && (!(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(pIn + uintptr(-libc.Int32FromInt32(1)))))])&libc.Int32FromInt32(0x08) != 0) || !(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(pIn + 1)))])&libc.Int32FromInt32(0x08) != 0)) {
|
|
_sqlite3ErrorMsg(tls, pParse, __ccgo_ts+1790, libc.VaList(bp+16, *(*uintptr)(unsafe.Pointer(p + 8))))
|
|
}
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
v1 = pIn
|
|
pIn = pIn + 1
|
|
if !(**(**uint8)(__ccgo_up(v1)) != 0) {
|
|
break
|
|
}
|
|
}
|
|
if bHex != 0 {
|
|
(*TExpr)(unsafe.Pointer(p)).Fop = uint8(TK_INTEGER)
|
|
}
|
|
/* tag-20240227-a: If after dequoting, the number is an integer that
|
|
** fits in 32 bits, then it must be converted into EP_IntValue. Other
|
|
** parts of the code expect this. See also tag-20240227-b. */
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(p)).Fop) == int32(TK_INTEGER) && _sqlite3GetInt32(tls, *(*uintptr)(unsafe.Pointer(p + 8)), bp) != 0 {
|
|
*(*int32)(unsafe.Pointer(&(*TExpr)(unsafe.Pointer(p)).Fu)) = **(**int32)(__ccgo_up(bp))
|
|
**(**Tu32)(__ccgo_up(p + 4)) |= uint32(EP_IntValue)
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Assign a variable number to an expression that encodes a wildcard
|
|
// ** in the original SQL statement.
|
|
// **
|
|
// ** Wildcards consisting of a single "?" are assigned the next sequential
|
|
// ** variable number.
|
|
// **
|
|
// ** Wildcards of the form "?nnn" are assigned the number "nnn". We make
|
|
// ** sure "nnn" is not too big to avoid a denial of service attack when
|
|
// ** the SQL statement comes from an external source.
|
|
// **
|
|
// ** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number
|
|
// ** as the previous instance of the same wildcard. Or if this is the first
|
|
// ** instance of the wildcard, the next sequential variable number is
|
|
// ** assigned.
|
|
// */
|
|
func _sqlite3ExprAssignVarNumber(tls *libc.TLS, pParse uintptr, pExpr uintptr, n Tu32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var bOk, doAdd int32
|
|
var db, z, v2 uintptr
|
|
var x, v1 TynVar
|
|
var _ /* i at bp+0 */ Ti64
|
|
_, _, _, _, _, _, _ = bOk, db, doAdd, x, z, v1, v2
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
if pExpr == uintptr(0) {
|
|
return
|
|
}
|
|
z = *(*uintptr)(unsafe.Pointer(pExpr + 8))
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 1))) == 0 {
|
|
/* Wildcard of the form "?". Assign the next variable number */
|
|
v2 = pParse + 304
|
|
*(*TynVar)(unsafe.Pointer(v2)) = *(*TynVar)(unsafe.Pointer(v2)) + 1
|
|
v1 = *(*TynVar)(unsafe.Pointer(v2))
|
|
x = v1
|
|
} else {
|
|
doAdd = 0
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) == int32('?') {
|
|
if n == uint32(2) { /*OPTIMIZATION-IF-TRUE*/
|
|
**(**Ti64)(__ccgo_up(bp)) = int64(libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 1))) - int32('0')) /* The common case of ?N for a single digit N */
|
|
bOk = int32(1)
|
|
} else {
|
|
bOk = libc.BoolInt32(0 == _sqlite3Atoi64(tls, z+1, bp, libc.Int32FromUint32(n-uint32(1)), uint8(SQLITE_UTF8)))
|
|
}
|
|
if bOk == 0 || **(**Ti64)(__ccgo_up(bp)) < int64(1) || **(**Ti64)(__ccgo_up(bp)) > int64(**(**int32)(__ccgo_up(db + 136 + 9*4))) {
|
|
_sqlite3ErrorMsg(tls, pParse, __ccgo_ts+8087, libc.VaList(bp+16, **(**int32)(__ccgo_up(db + 136 + 9*4))))
|
|
_sqlite3RecordErrorOffsetOfExpr(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pExpr)
|
|
return
|
|
}
|
|
x = int16(**(**Ti64)(__ccgo_up(bp)))
|
|
if int32(x) > int32((*TParse)(unsafe.Pointer(pParse)).FnVar) {
|
|
(*TParse)(unsafe.Pointer(pParse)).FnVar = int16(int32(x))
|
|
doAdd = int32(1)
|
|
} else {
|
|
if _sqlite3VListNumToName(tls, (*TParse)(unsafe.Pointer(pParse)).FpVList, int32(x)) == uintptr(0) {
|
|
doAdd = int32(1)
|
|
}
|
|
}
|
|
} else {
|
|
/* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable
|
|
** number as the prior appearance of the same name, or if the name
|
|
** has never appeared before, reuse the same variable number
|
|
*/
|
|
x = int16(_sqlite3VListNameToNum(tls, (*TParse)(unsafe.Pointer(pParse)).FpVList, z, libc.Int32FromUint32(n)))
|
|
if int32(x) == 0 {
|
|
v2 = pParse + 304
|
|
*(*TynVar)(unsafe.Pointer(v2)) = *(*TynVar)(unsafe.Pointer(v2)) + 1
|
|
v1 = *(*TynVar)(unsafe.Pointer(v2))
|
|
x = v1
|
|
doAdd = int32(1)
|
|
}
|
|
}
|
|
if doAdd != 0 {
|
|
(*TParse)(unsafe.Pointer(pParse)).FpVList = _sqlite3VListAdd(tls, db, (*TParse)(unsafe.Pointer(pParse)).FpVList, z, libc.Int32FromUint32(n), int32(x))
|
|
}
|
|
}
|
|
(*TExpr)(unsafe.Pointer(pExpr)).FiColumn = x
|
|
if int32(x) > **(**int32)(__ccgo_up(db + 136 + 9*4)) {
|
|
_sqlite3ErrorMsg(tls, pParse, __ccgo_ts+8130, 0)
|
|
_sqlite3RecordErrorOffsetOfExpr(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pExpr)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is used by the implementation of the IN (...) operator.
|
|
// ** The pX parameter is the expression on the RHS of the IN operator, which
|
|
// ** might be either a list of expressions or a subquery.
|
|
// **
|
|
// ** The job of this routine is to find or create a b-tree object that can
|
|
// ** be used either to test for membership in the RHS set or to iterate through
|
|
// ** all members of the RHS set, skipping duplicates.
|
|
// **
|
|
// ** A cursor is opened on the b-tree object that is the RHS of the IN operator
|
|
// ** and the *piTab parameter is set to the index of that cursor.
|
|
// **
|
|
// ** The returned value of this function indicates the b-tree type, as follows:
|
|
// **
|
|
// ** IN_INDEX_ROWID - The cursor was opened on a database table.
|
|
// ** IN_INDEX_INDEX_ASC - The cursor was opened on an ascending index.
|
|
// ** IN_INDEX_INDEX_DESC - The cursor was opened on a descending index.
|
|
// ** IN_INDEX_EPH - The cursor was opened on a specially created and
|
|
// ** populated ephemeral table.
|
|
// ** IN_INDEX_NOOP - No cursor was allocated. The IN operator must be
|
|
// ** implemented as a sequence of comparisons.
|
|
// **
|
|
// ** An existing b-tree might be used if the RHS expression pX is a simple
|
|
// ** subquery such as:
|
|
// **
|
|
// ** SELECT <column1>, <column2>... FROM <table>
|
|
// **
|
|
// ** If the RHS of the IN operator is a list or a more complex subquery, then
|
|
// ** an ephemeral table might need to be generated from the RHS and then
|
|
// ** pX->iTable made to point to the ephemeral table instead of an
|
|
// ** existing table. In this case, the creation and initialization of the
|
|
// ** ephemeral table might be put inside of a subroutine, the EP_Subrtn flag
|
|
// ** will be set on pX and the pX->y.sub fields will be set to show where
|
|
// ** the subroutine is coded.
|
|
// **
|
|
// ** The inFlags parameter must contain, at a minimum, one of the bits
|
|
// ** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP but not both. If inFlags contains
|
|
// ** IN_INDEX_MEMBERSHIP, then the generated table will be used for a fast
|
|
// ** membership test. When the IN_INDEX_LOOP bit is set, the IN index will
|
|
// ** be used to loop over all values of the RHS of the IN operator.
|
|
// **
|
|
// ** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate
|
|
// ** through the set members) then the b-tree must not contain duplicates.
|
|
// ** An ephemeral table will be created unless the selected columns are guaranteed
|
|
// ** to be unique - either because it is an INTEGER PRIMARY KEY or due to
|
|
// ** a UNIQUE constraint or index.
|
|
// **
|
|
// ** When IN_INDEX_MEMBERSHIP is used (and the b-tree will be used
|
|
// ** for fast set membership tests) then an ephemeral table must
|
|
// ** be used unless <columns> is a single INTEGER PRIMARY KEY column or an
|
|
// ** index can be found with the specified <columns> as its left-most.
|
|
// **
|
|
// ** If the IN_INDEX_NOOP_OK and IN_INDEX_MEMBERSHIP are both set and
|
|
// ** if the RHS of the IN operator is a list (not a subquery) then this
|
|
// ** routine might decide that creating an ephemeral b-tree for membership
|
|
// ** testing is too expensive and return IN_INDEX_NOOP. In that case, the
|
|
// ** calling routine should implement the IN operator using a sequence
|
|
// ** of Eq or Ne comparison operations.
|
|
// **
|
|
// ** When the b-tree is being used for membership tests, the calling function
|
|
// ** might need to know whether or not the RHS side of the IN operator
|
|
// ** contains a NULL. If prRhsHasNull is not a NULL pointer and
|
|
// ** if there is any chance that the (...) might contain a NULL value at
|
|
// ** runtime, then a register is allocated and the register number written
|
|
// ** to *prRhsHasNull. If there is no chance that the (...) contains a
|
|
// ** NULL value, then *prRhsHasNull is left unchanged.
|
|
// **
|
|
// ** If a register is allocated and its location stored in *prRhsHasNull, then
|
|
// ** the value in that register will be NULL if the b-tree contains one or more
|
|
// ** NULL values, and it will be some non-NULL value if the b-tree contains no
|
|
// ** NULL values.
|
|
// **
|
|
// ** If the aiMap parameter is not NULL, it must point to an array containing
|
|
// ** one element for each column returned by the SELECT statement on the RHS
|
|
// ** of the IN(...) operator. The i'th entry of the array is populated with the
|
|
// ** offset of the index column that matches the i'th column returned by the
|
|
// ** SELECT. For example, if the expression and selected index are:
|
|
// **
|
|
// ** (?,?,?) IN (SELECT a, b, c FROM t1)
|
|
// ** CREATE INDEX i1 ON t1(b, c, a);
|
|
// **
|
|
// ** then aiMap[] is populated with {2, 0, 1}.
|
|
// */
|
|
func _sqlite3FindInIndex(tls *libc.TLS, pParse uintptr, pX uintptr, inFlags Tu32, prRhsHasNull uintptr, aiMap uintptr, piTab uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var affinity_ok, bloomOk, eType, i, i1, i2, iAddr, iAddr1, iCol, iDb, iTab, j, mustBeUnique, n, nExpr, rMayHaveNull, v1, v10 int32
|
|
var cmpaff, idxaff uint8
|
|
var colUsed, mCol TBitmask
|
|
var db, p, pEList, pEList1, pIdx, pLhs, pLhs1, pReq, pRhs, pTab, v, v2 uintptr
|
|
var savedNQueryLoop Tu32
|
|
var v5 bool
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = affinity_ok, bloomOk, cmpaff, colUsed, db, eType, i, i1, i2, iAddr, iAddr1, iCol, iDb, iTab, idxaff, j, mCol, mustBeUnique, n, nExpr, p, pEList, pEList1, pIdx, pLhs, pLhs1, pReq, pRhs, pTab, rMayHaveNull, savedNQueryLoop, v, v1, v10, v2, v5 /* SELECT to the right of IN operator */
|
|
eType = 0 /* True if RHS must be unique */
|
|
v = _sqlite3GetVdbe(tls, pParse) /* Virtual machine being coded */
|
|
mustBeUnique = libc.BoolInt32(inFlags&uint32(IN_INDEX_LOOP) != uint32(0))
|
|
v2 = pParse + 56
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
iTab = v1
|
|
/* If the RHS of this IN(...) operator is a SELECT, and if it matters
|
|
** whether or not the SELECT result contains NULL values, check whether
|
|
** or not NULL is actually possible (it may not be, for example, due
|
|
** to NOT NULL constraints in the schema). If no NULL values are possible,
|
|
** set prRhsHasNull to 0 before continuing. */
|
|
if prRhsHasNull != 0 && (*TExpr)(unsafe.Pointer(pX)).Fflags&uint32(EP_xIsSelect) != uint32(0) {
|
|
pEList = (*TSelect)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pX + 32)))).FpEList
|
|
i = 0
|
|
for {
|
|
if !(i < (*TExprList)(unsafe.Pointer(pEList)).FnExpr) {
|
|
break
|
|
}
|
|
if _sqlite3ExprCanBeNull(tls, (*(*TExprList_item)(unsafe.Pointer(pEList + 8 + uintptr(i)*32))).FpExpr) != 0 {
|
|
break
|
|
}
|
|
goto _3
|
|
_3:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if i == (*TExprList)(unsafe.Pointer(pEList)).FnExpr {
|
|
prRhsHasNull = uintptr(0)
|
|
}
|
|
}
|
|
/* Check to see if an existing table or index can be used to
|
|
** satisfy the query. This is preferable to generating a new
|
|
** ephemeral table. */
|
|
if v5 = (*TParse)(unsafe.Pointer(pParse)).FnErr == 0; v5 {
|
|
v2 = _isCandidateForInOpt(tls, pX)
|
|
p = v2
|
|
}
|
|
if v5 && v2 != uintptr(0) {
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb /* Database idx for pTab */
|
|
pEList1 = (*TSelect)(unsafe.Pointer(p)).FpEList
|
|
nExpr = (*TExprList)(unsafe.Pointer(pEList1)).FnExpr
|
|
/* Because of isCandidateForInOpt(p) */
|
|
/* Because of isCandidateForInOpt(p) */
|
|
/* Because of isCandidateForInOpt(p) */
|
|
pTab = (*(*TSrcItem)(unsafe.Pointer((*TSelect)(unsafe.Pointer(p)).FpSrc + 8))).FpSTab
|
|
/* Code an OP_Transaction and OP_TableLock for <table>. */
|
|
iDb = _sqlite3SchemaToIndex(tls, db, (*TTable)(unsafe.Pointer(pTab)).FpSchema)
|
|
_sqlite3CodeVerifySchema(tls, pParse, iDb)
|
|
_sqlite3TableLock(tls, pParse, iDb, (*TTable)(unsafe.Pointer(pTab)).Ftnum, uint8(0), (*TTable)(unsafe.Pointer(pTab)).FzName)
|
|
/* sqlite3GetVdbe() has always been previously called */
|
|
if nExpr == int32(1) && int32((*TExpr)(unsafe.Pointer((*(*TExprList_item)(unsafe.Pointer(pEList1 + 8))).FpExpr)).FiColumn) < 0 {
|
|
/* The "x IN (SELECT rowid FROM table)" case */
|
|
iAddr = _sqlite3VdbeAddOp0(tls, v, int32(OP_Once))
|
|
_sqlite3OpenTable(tls, pParse, iTab, iDb, pTab, int32(OP_OpenRead))
|
|
eType = int32(IN_INDEX_ROWID)
|
|
_sqlite3VdbeExplain(tls, pParse, uint8(0), __ccgo_ts+8235, libc.VaList(bp+8, (*TTable)(unsafe.Pointer(pTab)).FzName))
|
|
_sqlite3VdbeJumpHere(tls, v, iAddr)
|
|
} else { /* Iterator variable */
|
|
affinity_ok = int32(1)
|
|
/* Check that the affinity that will be used to perform each
|
|
** comparison is the same as the affinity of each column in table
|
|
** on the RHS of the IN operator. If it not, it is not possible to
|
|
** use any index of the RHS table. */
|
|
i1 = 0
|
|
for {
|
|
if !(i1 < nExpr && affinity_ok != 0) {
|
|
break
|
|
}
|
|
pLhs = _sqlite3VectorFieldSubexpr(tls, (*TExpr)(unsafe.Pointer(pX)).FpLeft, i1)
|
|
iCol = int32((*TExpr)(unsafe.Pointer((*(*TExprList_item)(unsafe.Pointer(pEList1 + 8 + uintptr(i1)*32))).FpExpr)).FiColumn)
|
|
idxaff = _sqlite3TableColumnAffinity(tls, pTab, iCol) /* RHS table */
|
|
cmpaff = _sqlite3CompareAffinity(tls, pLhs, idxaff)
|
|
switch libc.Int32FromUint8(cmpaff) {
|
|
case int32(SQLITE_AFF_BLOB):
|
|
case int32(SQLITE_AFF_TEXT):
|
|
/* sqlite3CompareAffinity() only returns TEXT if one side or the
|
|
** other has no affinity and the other side is TEXT. Hence,
|
|
** the only way for cmpaff to be TEXT is for idxaff to be TEXT
|
|
** and for the term on the LHS of the IN to have no affinity. */
|
|
default:
|
|
affinity_ok = libc.BoolInt32(libc.Int32FromUint8(idxaff) >= int32(SQLITE_AFF_NUMERIC))
|
|
}
|
|
goto _6
|
|
_6:
|
|
;
|
|
i1 = i1 + 1
|
|
}
|
|
if affinity_ok != 0 {
|
|
/* Search for an existing index that will work for this IN operator */
|
|
pIdx = (*TTable)(unsafe.Pointer(pTab)).FpIndex
|
|
for {
|
|
if !(pIdx != 0 && eType == 0) {
|
|
break
|
|
} /* Mask for the current column */
|
|
if libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnColumn) < nExpr {
|
|
goto _7
|
|
}
|
|
if (*TIndex)(unsafe.Pointer(pIdx)).FpPartIdxWhere != uintptr(0) {
|
|
goto _7
|
|
}
|
|
/* Maximum nColumn is BMS-2, not BMS-1, so that we can compute
|
|
** BITMASK(nExpr) without overflowing */
|
|
if libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnColumn) >= libc.Int32FromUint64(libc.Uint64FromInt64(8)*libc.Uint64FromInt32(8))-libc.Int32FromInt32(1) {
|
|
goto _7
|
|
}
|
|
if mustBeUnique != 0 {
|
|
if libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnKeyCol) > nExpr || libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnColumn) > nExpr && !(libc.Int32FromUint8((*TIndex)(unsafe.Pointer(pIdx)).FonError) != libc.Int32FromInt32(OE_None)) {
|
|
goto _7 /* This index is not unique over the IN RHS columns */
|
|
}
|
|
}
|
|
colUsed = uint64(0) /* Columns of index used so far */
|
|
i1 = 0
|
|
for {
|
|
if !(i1 < nExpr) {
|
|
break
|
|
}
|
|
pLhs1 = _sqlite3VectorFieldSubexpr(tls, (*TExpr)(unsafe.Pointer(pX)).FpLeft, i1)
|
|
pRhs = (*(*TExprList_item)(unsafe.Pointer(pEList1 + 8 + uintptr(i1)*32))).FpExpr
|
|
pReq = _sqlite3BinaryCompareCollSeq(tls, pParse, pLhs1, pRhs)
|
|
j = 0
|
|
for {
|
|
if !(j < nExpr) {
|
|
break
|
|
}
|
|
if int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(j)*2))) != int32((*TExpr)(unsafe.Pointer(pRhs)).FiColumn) {
|
|
goto _9
|
|
}
|
|
if pReq != uintptr(0) && _sqlite3StrICmp(tls, (*TCollSeq)(unsafe.Pointer(pReq)).FzName, **(**uintptr)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FazColl + uintptr(j)*8))) != 0 {
|
|
goto _9
|
|
}
|
|
break
|
|
goto _9
|
|
_9:
|
|
;
|
|
j = j + 1
|
|
}
|
|
if j == nExpr {
|
|
break
|
|
}
|
|
mCol = libc.Uint64FromInt32(1) << j
|
|
if mCol&colUsed != 0 {
|
|
break
|
|
} /* Each column used only once */
|
|
colUsed = colUsed | mCol
|
|
if aiMap != 0 {
|
|
**(**int32)(__ccgo_up(aiMap + uintptr(i1)*4)) = j
|
|
}
|
|
goto _8
|
|
_8:
|
|
;
|
|
i1 = i1 + 1
|
|
}
|
|
if colUsed == libc.Uint64FromInt32(1)<<nExpr-uint64(1) {
|
|
/* If we reach this point, that means the index pIdx is usable */
|
|
iAddr1 = _sqlite3VdbeAddOp0(tls, v, int32(OP_Once))
|
|
_sqlite3VdbeExplain(tls, pParse, uint8(0), __ccgo_ts+8282, libc.VaList(bp+8, (*TIndex)(unsafe.Pointer(pIdx)).FzName))
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_OpenRead), iTab, libc.Int32FromUint32((*TIndex)(unsafe.Pointer(pIdx)).Ftnum), iDb)
|
|
_sqlite3VdbeSetP4KeyInfo(tls, pParse, pIdx)
|
|
eType = int32(IN_INDEX_INDEX_ASC) + libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaSortOrder)))
|
|
if prRhsHasNull != 0 {
|
|
v2 = pParse + 60
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
**(**int32)(__ccgo_up(prRhsHasNull)) = v1
|
|
if nExpr == int32(1) {
|
|
_sqlite3SetHasNullFlag(tls, v, iTab, **(**int32)(__ccgo_up(prRhsHasNull)))
|
|
}
|
|
}
|
|
_sqlite3VdbeJumpHere(tls, v, iAddr1)
|
|
}
|
|
goto _7
|
|
_7:
|
|
;
|
|
pIdx = (*TIndex)(unsafe.Pointer(pIdx)).FpNext
|
|
} /* End loop over indexes */
|
|
} /* End if( affinity_ok ) */
|
|
} /* End if not an rowid index */
|
|
} /* End attempt to optimize using an index */
|
|
/* If no preexisting index is available for the IN clause
|
|
** and IN_INDEX_NOOP is an allowed reply
|
|
** and the RHS of the IN operator is a list, not a subquery
|
|
** and the RHS is not constant or has two or fewer terms,
|
|
** then it is not worth creating an ephemeral table to evaluate
|
|
** the IN operator so return IN_INDEX_NOOP.
|
|
*/
|
|
if eType == 0 && inFlags&uint32(IN_INDEX_NOOP_OK) != 0 && (*TExpr)(unsafe.Pointer(pX)).Fflags&uint32(EP_xIsSelect) == uint32(0) && (!(_sqlite3InRhsIsConstant(tls, pParse, pX) != 0) || (*TExprList)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pX + 32)))).FnExpr <= int32(2)) {
|
|
(*TParse)(unsafe.Pointer(pParse)).FnTab = (*TParse)(unsafe.Pointer(pParse)).FnTab - 1 /* Back out the allocation of the unused cursor */
|
|
iTab = -int32(1) /* Cursor is not allocated */
|
|
eType = int32(IN_INDEX_NOOP)
|
|
}
|
|
if eType == 0 {
|
|
/* Could not find an existing table or index to use as the RHS b-tree.
|
|
** We will have to generate an ephemeral table to do the job.
|
|
*/
|
|
savedNQueryLoop = libc.Uint32FromInt16((*TParse)(unsafe.Pointer(pParse)).FnQueryLoop)
|
|
rMayHaveNull = 0
|
|
bloomOk = libc.BoolInt32(inFlags&uint32(IN_INDEX_MEMBERSHIP) != uint32(0))
|
|
eType = int32(IN_INDEX_EPH)
|
|
if inFlags&uint32(IN_INDEX_LOOP) != 0 {
|
|
(*TParse)(unsafe.Pointer(pParse)).FnQueryLoop = 0
|
|
} else {
|
|
if prRhsHasNull != 0 {
|
|
v2 = pParse + 60
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
v10 = *(*int32)(unsafe.Pointer(v2))
|
|
v1 = v10
|
|
rMayHaveNull = v1
|
|
**(**int32)(__ccgo_up(prRhsHasNull)) = v1
|
|
}
|
|
}
|
|
if !(bloomOk != 0) && (*TExpr)(unsafe.Pointer(pX)).Fflags&uint32(EP_xIsSelect) != uint32(0) && (*TSelect)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pX + 32)))).FselFlags&uint32(SF_ClonedRhsIn) != uint32(0) {
|
|
bloomOk = int32(1)
|
|
}
|
|
_sqlite3CodeRhsOfIN(tls, pParse, pX, iTab, bloomOk)
|
|
if rMayHaveNull != 0 {
|
|
_sqlite3SetHasNullFlag(tls, v, iTab, rMayHaveNull)
|
|
}
|
|
(*TParse)(unsafe.Pointer(pParse)).FnQueryLoop = libc.Int16FromUint32(savedNQueryLoop)
|
|
}
|
|
if aiMap != 0 && eType != int32(IN_INDEX_INDEX_ASC) && eType != int32(IN_INDEX_INDEX_DESC) {
|
|
n = _sqlite3ExprVectorSize(tls, (*TExpr)(unsafe.Pointer(pX)).FpLeft)
|
|
i2 = 0
|
|
for {
|
|
if !(i2 < n) {
|
|
break
|
|
}
|
|
**(**int32)(__ccgo_up(aiMap + uintptr(i2)*4)) = i2
|
|
goto _15
|
|
_15:
|
|
;
|
|
i2 = i2 + 1
|
|
}
|
|
}
|
|
**(**int32)(__ccgo_up(piTab)) = iTab
|
|
return eType
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Decode a floating-point value into an approximate decimal
|
|
// ** representation.
|
|
// **
|
|
// ** If iRound<=0 then round to -iRound significant digits to the
|
|
// ** the right of the decimal point, or to a maximum of mxRound total
|
|
// ** significant digits.
|
|
// **
|
|
// ** If iRound>0 round to min(iRound,mxRound) significant digits total.
|
|
// **
|
|
// ** mxRound must be positive.
|
|
// **
|
|
// ** The significant digits of the decimal representation are
|
|
// ** stored in p->z[] which is a often (but not always) a pointer
|
|
// ** into the middle of p->zBuf[]. There are p->n significant digits.
|
|
// ** The p->z[] array is *not* zero-terminated.
|
|
// */
|
|
func _sqlite3FpDecode(tls *libc.TLS, p uintptr, _r float64, iRound int32, mxRound int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
*(*float64)(unsafe.Pointer(bp)) = _r
|
|
var e, i, j, jj, jj1, kk, kk1, kk2, n, nn, v1 int32
|
|
var v2, v21 Tu64
|
|
var z, zBuf uintptr
|
|
var _ /* exp at bp+16 */ int32
|
|
var _ /* v at bp+8 */ Tu64
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = e, i, j, jj, jj1, kk, kk1, kk2, n, nn, v2, v21, z, zBuf, v1
|
|
**(**int32)(__ccgo_up(bp + 16)) = 0 /* Local alias for p->z */
|
|
(*TFpDecode)(unsafe.Pointer(p)).FisSpecial = uint8(0)
|
|
/* Convert negative numbers to positive. Deal with Infinity, 0.0, and
|
|
** NaN. */
|
|
if **(**float64)(__ccgo_up(bp)) < float64(0) {
|
|
(*TFpDecode)(unsafe.Pointer(p)).Fsign = uint8('-')
|
|
**(**float64)(__ccgo_up(bp)) = -**(**float64)(__ccgo_up(bp))
|
|
} else {
|
|
if **(**float64)(__ccgo_up(bp)) == float64(0) {
|
|
(*TFpDecode)(unsafe.Pointer(p)).Fsign = uint8('+')
|
|
(*TFpDecode)(unsafe.Pointer(p)).Fn = int32(1)
|
|
(*TFpDecode)(unsafe.Pointer(p)).FiDP = int32(1)
|
|
(*TFpDecode)(unsafe.Pointer(p)).Fz = __ccgo_ts + 1850
|
|
return
|
|
} else {
|
|
(*TFpDecode)(unsafe.Pointer(p)).Fsign = uint8('+')
|
|
}
|
|
}
|
|
libc.Xmemcpy(tls, bp+8, bp, uint64(8))
|
|
e = libc.Int32FromUint64(**(**Tu64)(__ccgo_up(bp + 8)) >> libc.Int32FromInt32(52) & uint64(0x7ff))
|
|
if e == int32(0x7ff) {
|
|
(*TFpDecode)(unsafe.Pointer(p)).FisSpecial = libc.Uint8FromInt32(int32(1) + libc.BoolInt32(**(**Tu64)(__ccgo_up(bp + 8)) != uint64(0x7ff0000000000000)))
|
|
(*TFpDecode)(unsafe.Pointer(p)).Fn = 0
|
|
(*TFpDecode)(unsafe.Pointer(p)).FiDP = 0
|
|
(*TFpDecode)(unsafe.Pointer(p)).Fz = p + 16
|
|
return
|
|
}
|
|
**(**Tu64)(__ccgo_up(bp + 8)) = **(**Tu64)(__ccgo_up(bp + 8)) & uint64(0x000fffffffffffff)
|
|
if e == 0 {
|
|
nn = _countLeadingZeros(tls, **(**Tu64)(__ccgo_up(bp + 8)))
|
|
**(**Tu64)(__ccgo_up(bp + 8)) = **(**Tu64)(__ccgo_up(bp + 8)) << libc.Uint64FromInt32(nn)
|
|
e = -int32(1074) - nn
|
|
} else {
|
|
**(**Tu64)(__ccgo_up(bp + 8)) = **(**Tu64)(__ccgo_up(bp + 8))<<libc.Int32FromInt32(11) | libc.Uint64FromInt32(1)<<libc.Int32FromInt32(63)
|
|
e = e - int32(1086)
|
|
}
|
|
if iRound <= 0 || iRound >= int32(18) {
|
|
v1 = int32(18)
|
|
} else {
|
|
v1 = iRound + int32(1)
|
|
}
|
|
_sqlite3Fp2Convert10(tls, **(**Tu64)(__ccgo_up(bp + 8)), e, v1, bp+8, bp+16)
|
|
/* Extract significant digits, start at the right-most slot in p->zBuf
|
|
** and working back to the right. "i" keeps track of the next slot in
|
|
** which to store a digit. */
|
|
zBuf = p + 16
|
|
i = int32(SQLITE_U64_DIGITS)
|
|
for **(**Tu64)(__ccgo_up(bp + 8)) >= uint64(10) {
|
|
kk = libc.Int32FromUint64(**(**Tu64)(__ccgo_up(bp + 8)) % uint64(100) * uint64(2))
|
|
**(**Tu16)(__ccgo_up(zBuf + uintptr(i-int32(2)))) = **(**Tu16)(__ccgo_up(uintptr(unsafe.Pointer(&_sqlite3DigitPairs)) + uintptr(kk)))
|
|
i = i - int32(2)
|
|
**(**Tu64)(__ccgo_up(bp + 8)) = **(**Tu64)(__ccgo_up(bp + 8)) / uint64(100)
|
|
}
|
|
if **(**Tu64)(__ccgo_up(bp + 8)) != 0 {
|
|
i = i - 1
|
|
v1 = i
|
|
**(**uint8)(__ccgo_up(zBuf + uintptr(v1))) = uint8(**(**Tu64)(__ccgo_up(bp + 8)) + uint64('0'))
|
|
}
|
|
n = int32(SQLITE_U64_DIGITS) - i /* Total number of digits extracted */
|
|
(*TFpDecode)(unsafe.Pointer(p)).FiDP = n + **(**int32)(__ccgo_up(bp + 16))
|
|
if iRound <= 0 {
|
|
iRound = (*TFpDecode)(unsafe.Pointer(p)).FiDP - iRound
|
|
if iRound == 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zBuf + uintptr(i)))) >= int32('5') {
|
|
iRound = int32(1)
|
|
i = i - 1
|
|
v1 = i
|
|
**(**uint8)(__ccgo_up(zBuf + uintptr(v1))) = uint8('0')
|
|
n = n + 1
|
|
(*TFpDecode)(unsafe.Pointer(p)).FiDP = (*TFpDecode)(unsafe.Pointer(p)).FiDP + 1
|
|
}
|
|
}
|
|
z = zBuf + uintptr(i) /* z points to the first digit */
|
|
if iRound > 0 && (iRound < n || n > mxRound) {
|
|
if iRound > mxRound {
|
|
iRound = mxRound
|
|
}
|
|
if iRound == int32(17) {
|
|
/* If the precision is exactly 17, which only happens with the "!"
|
|
** flag (ex: "%!.17g") then try to reduce the precision if that
|
|
** yields text that will round-trip to the original floating-point.
|
|
** value. Thus, for exaple, 49.47 will render as 49.47, rather than
|
|
** as 49.469999999999999. */
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 15))) == int32('9') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 14))) == int32('9') {
|
|
jj = int32(14)
|
|
for {
|
|
if !(jj > 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(jj-int32(1))))) == int32('9')) {
|
|
break
|
|
}
|
|
goto _4
|
|
_4:
|
|
;
|
|
jj = jj - 1
|
|
}
|
|
if jj == 0 {
|
|
v2 = uint64(1)
|
|
} else {
|
|
v2 = libc.Uint64FromInt32(libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) - int32('0'))
|
|
kk1 = int32(1)
|
|
for {
|
|
if !(kk1 < jj) {
|
|
break
|
|
}
|
|
v2 = v2*uint64(10) + uint64(**(**uint8)(__ccgo_up(z + uintptr(kk1)))) - uint64('0')
|
|
goto _5
|
|
_5:
|
|
;
|
|
kk1 = kk1 + 1
|
|
}
|
|
v2 = v2 + 1
|
|
}
|
|
if **(**float64)(__ccgo_up(bp)) == _sqlite3Fp10Convert2(tls, v2, **(**int32)(__ccgo_up(bp + 16))+n-jj) {
|
|
iRound = jj + int32(1)
|
|
}
|
|
} else {
|
|
if (*TFpDecode)(unsafe.Pointer(p)).FiDP >= n || libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 15))) == int32('0') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 14))) == int32('0') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 13))) == int32('0') {
|
|
jj1 = int32(13)
|
|
for {
|
|
if !(libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(jj1-int32(1))))) == int32('0')) {
|
|
break
|
|
}
|
|
goto _6
|
|
_6:
|
|
;
|
|
jj1 = jj1 - 1
|
|
}
|
|
v21 = libc.Uint64FromInt32(libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) - int32('0'))
|
|
kk2 = int32(1)
|
|
for {
|
|
if !(kk2 < jj1) {
|
|
break
|
|
}
|
|
v21 = v21*uint64(10) + uint64(**(**uint8)(__ccgo_up(z + uintptr(kk2)))) - uint64('0')
|
|
goto _7
|
|
_7:
|
|
;
|
|
kk2 = kk2 + 1
|
|
}
|
|
if **(**float64)(__ccgo_up(bp)) == _sqlite3Fp10Convert2(tls, v21, **(**int32)(__ccgo_up(bp + 16))+n-jj1) {
|
|
iRound = jj1 + int32(1)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
n = iRound
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(iRound)))) >= int32('5') {
|
|
j = iRound - int32(1)
|
|
for int32(1) != 0 {
|
|
**(**uint8)(__ccgo_up(z + uintptr(j))) = **(**uint8)(__ccgo_up(z + uintptr(j))) + 1
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(j)))) <= int32('9') {
|
|
break
|
|
}
|
|
**(**uint8)(__ccgo_up(z + uintptr(j))) = uint8('0')
|
|
if j == 0 {
|
|
z = z - 1
|
|
**(**uint8)(__ccgo_up(z)) = uint8('1')
|
|
n = n + 1
|
|
(*TFpDecode)(unsafe.Pointer(p)).FiDP = (*TFpDecode)(unsafe.Pointer(p)).FiDP + 1
|
|
break
|
|
} else {
|
|
j = j - 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(n-int32(1))))) == int32('0') {
|
|
n = n - 1
|
|
}
|
|
(*TFpDecode)(unsafe.Pointer(p)).Fn = n
|
|
(*TFpDecode)(unsafe.Pointer(p)).Fz = z
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Arguments nArg/azArg contain the string arguments passed to the xCreate
|
|
// ** or xConnect method of the virtual table. This function attempts to
|
|
// ** allocate an instance of Fts5Config containing the results of parsing
|
|
// ** those arguments.
|
|
// **
|
|
// ** If successful, SQLITE_OK is returned and *ppOut is set to point to the
|
|
// ** new Fts5Config object. If an error occurs, an SQLite error code is
|
|
// ** returned, *ppOut is set to NULL and an error message may be left in
|
|
// ** *pzErr. It is the responsibility of the caller to eventually free any
|
|
// ** such error message using sqlite3_free().
|
|
// */
|
|
func _sqlite3Fts5ConfigParse(tls *libc.TLS, pGlobal uintptr, db uintptr, nArg int32, azArg uintptr, ppOut uintptr, pzErr uintptr) (r int32) {
|
|
bp := tls.Alloc(64)
|
|
defer tls.Free(64)
|
|
var bOption, i int32
|
|
var nByte Tsqlite3_int64
|
|
var pRet, z, zOrig, zTail, v1, v2 uintptr
|
|
var _ /* bDummy at bp+28 */ int32
|
|
var _ /* bMustBeCol at bp+24 */ int32
|
|
var _ /* bUnindexed at bp+4 */ int32
|
|
var _ /* rc at bp+0 */ int32
|
|
var _ /* zOne at bp+8 */ uintptr
|
|
var _ /* zTwo at bp+16 */ uintptr
|
|
_, _, _, _, _, _, _, _, _ = bOption, i, nByte, pRet, z, zOrig, zTail, v1, v2
|
|
**(**int32)(__ccgo_up(bp)) = SQLITE_OK
|
|
**(**int32)(__ccgo_up(bp + 4)) = 0 /* True if there are one or more UNINDEXED */
|
|
v1 = Xsqlite3_malloc64(tls, uint64(256))
|
|
pRet = v1
|
|
**(**uintptr)(__ccgo_up(ppOut)) = v1
|
|
if pRet == uintptr(0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
libc.Xmemset(tls, pRet, 0, uint64(256))
|
|
(*TFts5Config)(unsafe.Pointer(pRet)).FpGlobal = pGlobal
|
|
(*TFts5Config)(unsafe.Pointer(pRet)).Fdb = db
|
|
(*TFts5Config)(unsafe.Pointer(pRet)).FiCookie = -int32(1)
|
|
nByte = libc.Int64FromUint64(libc.Uint64FromInt32(nArg) * (libc.Uint64FromInt64(8) + libc.Uint64FromInt64(1)))
|
|
(*TFts5Config)(unsafe.Pointer(pRet)).FazCol = _sqlite3Fts5MallocZero(tls, bp, nByte)
|
|
if (*TFts5Config)(unsafe.Pointer(pRet)).FazCol != 0 {
|
|
v1 = (*TFts5Config)(unsafe.Pointer(pRet)).FazCol + uintptr(nArg)*8
|
|
} else {
|
|
v1 = uintptr(0)
|
|
}
|
|
(*TFts5Config)(unsafe.Pointer(pRet)).FabUnindexed = v1
|
|
(*TFts5Config)(unsafe.Pointer(pRet)).FzDb = _sqlite3Fts5Strndup(tls, bp, **(**uintptr)(__ccgo_up(azArg + 1*8)), -int32(1))
|
|
(*TFts5Config)(unsafe.Pointer(pRet)).FzName = _sqlite3Fts5Strndup(tls, bp, **(**uintptr)(__ccgo_up(azArg + 2*8)), -int32(1))
|
|
(*TFts5Config)(unsafe.Pointer(pRet)).FbColumnsize = int32(1)
|
|
(*TFts5Config)(unsafe.Pointer(pRet)).FeDetail = FTS5_DETAIL_FULL
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK && Xsqlite3_stricmp(tls, (*TFts5Config)(unsafe.Pointer(pRet)).FzName, __ccgo_ts+37992) == 0 {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+38103, libc.VaList(bp+40, (*TFts5Config)(unsafe.Pointer(pRet)).FzName))
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
}
|
|
i = int32(3)
|
|
for {
|
|
if !(**(**int32)(__ccgo_up(bp)) == SQLITE_OK && i < nArg) {
|
|
break
|
|
}
|
|
zOrig = **(**uintptr)(__ccgo_up(azArg + uintptr(i)*8))
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = uintptr(0)
|
|
**(**uintptr)(__ccgo_up(bp + 16)) = uintptr(0)
|
|
bOption = 0
|
|
**(**int32)(__ccgo_up(bp + 24)) = 0
|
|
z = _fts5ConfigGobbleWord(tls, bp, zOrig, bp+8, bp+24)
|
|
z = _fts5ConfigSkipWhitespace(tls, z)
|
|
if z != 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) == int32('=') {
|
|
bOption = int32(1)
|
|
z = z + 1
|
|
if **(**int32)(__ccgo_up(bp + 24)) != 0 {
|
|
z = uintptr(0)
|
|
}
|
|
}
|
|
z = _fts5ConfigSkipWhitespace(tls, z)
|
|
if z != 0 && **(**uint8)(__ccgo_up(z)) != 0 {
|
|
z = _fts5ConfigGobbleWord(tls, bp, z, bp+16, bp+28)
|
|
if z != 0 && **(**uint8)(__ccgo_up(z)) != 0 {
|
|
z = uintptr(0)
|
|
}
|
|
}
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
if z == uintptr(0) {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+38132, libc.VaList(bp+40, zOrig))
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
} else {
|
|
if bOption != 0 {
|
|
if **(**uintptr)(__ccgo_up(bp + 8)) != 0 {
|
|
v1 = **(**uintptr)(__ccgo_up(bp + 8))
|
|
} else {
|
|
v1 = __ccgo_ts + 1704
|
|
}
|
|
if **(**uintptr)(__ccgo_up(bp + 16)) != 0 {
|
|
v2 = **(**uintptr)(__ccgo_up(bp + 16))
|
|
} else {
|
|
v2 = __ccgo_ts + 1704
|
|
}
|
|
**(**int32)(__ccgo_up(bp)) = _fts5ConfigParseSpecial(tls, pRet, v1, v2, pzErr)
|
|
} else {
|
|
**(**int32)(__ccgo_up(bp)) = _fts5ConfigParseColumn(tls, pRet, **(**uintptr)(__ccgo_up(bp + 8)), **(**uintptr)(__ccgo_up(bp + 16)), pzErr, bp+4)
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = uintptr(0)
|
|
}
|
|
}
|
|
}
|
|
Xsqlite3_free(tls, **(**uintptr)(__ccgo_up(bp + 8)))
|
|
Xsqlite3_free(tls, **(**uintptr)(__ccgo_up(bp + 16)))
|
|
goto _3
|
|
_3:
|
|
;
|
|
i = i + 1
|
|
}
|
|
/* We only allow contentless_delete=1 if the table is indeed contentless. */
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK && (*TFts5Config)(unsafe.Pointer(pRet)).FbContentlessDelete != 0 && (*TFts5Config)(unsafe.Pointer(pRet)).FeContent != int32(FTS5_CONTENT_NONE) {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+38152, 0)
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
}
|
|
/* We only allow contentless_delete=1 if columnsize=0 is not present.
|
|
**
|
|
** This restriction may be removed at some point.
|
|
*/
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK && (*TFts5Config)(unsafe.Pointer(pRet)).FbContentlessDelete != 0 && (*TFts5Config)(unsafe.Pointer(pRet)).FbColumnsize == 0 {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+38202, 0)
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
}
|
|
/* We only allow contentless_unindexed=1 if the table is actually a
|
|
** contentless one.
|
|
*/
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK && (*TFts5Config)(unsafe.Pointer(pRet)).FbContentlessUnindexed != 0 && (*TFts5Config)(unsafe.Pointer(pRet)).FeContent != int32(FTS5_CONTENT_NONE) {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = Xsqlite3_mprintf(tls, __ccgo_ts+38257, 0)
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
}
|
|
/* If no zContent option was specified, fill in the default values. */
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK && (*TFts5Config)(unsafe.Pointer(pRet)).FzContent == uintptr(0) {
|
|
zTail = uintptr(0)
|
|
if (*TFts5Config)(unsafe.Pointer(pRet)).FeContent == FTS5_CONTENT_NORMAL {
|
|
zTail = __ccgo_ts + 37615
|
|
} else {
|
|
if **(**int32)(__ccgo_up(bp + 4)) != 0 && (*TFts5Config)(unsafe.Pointer(pRet)).FbContentlessUnindexed != 0 {
|
|
(*TFts5Config)(unsafe.Pointer(pRet)).FeContent = int32(FTS5_CONTENT_UNINDEXED)
|
|
zTail = __ccgo_ts + 37615
|
|
} else {
|
|
if (*TFts5Config)(unsafe.Pointer(pRet)).FbColumnsize != 0 {
|
|
zTail = __ccgo_ts + 38310
|
|
}
|
|
}
|
|
}
|
|
if zTail != 0 {
|
|
(*TFts5Config)(unsafe.Pointer(pRet)).FzContent = _sqlite3Fts5Mprintf(tls, bp, __ccgo_ts+38318, libc.VaList(bp+40, (*TFts5Config)(unsafe.Pointer(pRet)).FzDb, (*TFts5Config)(unsafe.Pointer(pRet)).FzName, zTail))
|
|
}
|
|
}
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK && (*TFts5Config)(unsafe.Pointer(pRet)).FzContentRowid == uintptr(0) {
|
|
(*TFts5Config)(unsafe.Pointer(pRet)).FzContentRowid = _sqlite3Fts5Strndup(tls, bp, __ccgo_ts+17991, -int32(1))
|
|
}
|
|
/* Formulate the zContentExprlist text */
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
**(**int32)(__ccgo_up(bp)) = _fts5ConfigMakeExprlist(tls, pRet)
|
|
}
|
|
if **(**int32)(__ccgo_up(bp)) != SQLITE_OK {
|
|
_sqlite3Fts5ConfigFree(tls, pRet)
|
|
**(**uintptr)(__ccgo_up(ppOut)) = uintptr(0)
|
|
}
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Attempt to load an SQLite extension library contained in the file
|
|
// ** zFile. The entry point is zProc. zProc may be 0 in which case a
|
|
// ** default entry point name (sqlite3_extension_init) is used. Use
|
|
// ** of the default name is recommended.
|
|
// **
|
|
// ** Return SQLITE_OK on success and SQLITE_ERROR if something goes wrong.
|
|
// **
|
|
// ** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with
|
|
// ** error message text. The calling function should free this memory
|
|
// ** by calling sqlite3DbFree(db, ).
|
|
// */
|
|
func _sqlite3LoadExtension(tls *libc.TLS, db uintptr, zFile uintptr, zProc uintptr, pzErrMsg uintptr) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var aHandle, handle, pVfs, zAltEntry, zAltFile, zEntry, v1 uintptr
|
|
var c, cnt, iEntry, iFile, ii, ncFile, rc, v3, v8 int32
|
|
var nMsg Tu64
|
|
var xInit Tsqlite3_loadext_entry
|
|
var v4 bool
|
|
var _ /* zErrmsg at bp+0 */ uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = aHandle, c, cnt, handle, iEntry, iFile, ii, nMsg, ncFile, pVfs, rc, xInit, zAltEntry, zAltFile, zEntry, v1, v3, v4, v8
|
|
pVfs = (*Tsqlite3)(unsafe.Pointer(db)).FpVfs
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
zAltEntry = uintptr(0)
|
|
nMsg = uint64(libc.Xstrlen(tls, zFile))
|
|
if pzErrMsg != 0 {
|
|
**(**uintptr)(__ccgo_up(pzErrMsg)) = uintptr(0)
|
|
}
|
|
/* Ticket #1863. To avoid a creating security problems for older
|
|
** applications that relink against newer versions of SQLite, the
|
|
** ability to run load_extension is turned off by default. One
|
|
** must call either sqlite3_enable_load_extension(db) or
|
|
** sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, 0)
|
|
** to turn on extension loading.
|
|
*/
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).Fflags&uint64(SQLITE_LoadExtension) == uint64(0) {
|
|
if pzErrMsg != 0 {
|
|
**(**uintptr)(__ccgo_up(pzErrMsg)) = Xsqlite3_mprintf(tls, __ccgo_ts+13699, 0)
|
|
}
|
|
return int32(SQLITE_ERROR)
|
|
}
|
|
if zProc != 0 {
|
|
v1 = zProc
|
|
} else {
|
|
v1 = __ccgo_ts + 17615
|
|
}
|
|
zEntry = v1
|
|
/* tag-20210611-1. Some dlopen() implementations will segfault if given
|
|
** an oversize filename. Most filesystems have a pathname limit of 4K,
|
|
** so limit the extension filename length to about twice that.
|
|
** https://sqlite.org/forum/forumpost/08a0d6d9bf
|
|
**
|
|
** Later (2023-03-25): Save an extra 6 bytes for the filename suffix.
|
|
** See https://sqlite.org/forum/forumpost/24083b579d.
|
|
*/
|
|
if nMsg > uint64(FILENAME_MAX) {
|
|
goto extension_not_found
|
|
}
|
|
/* Do not allow sqlite3_load_extension() to link to a copy of the
|
|
** running application, by passing in an empty filename. */
|
|
if nMsg == uint64(0) {
|
|
goto extension_not_found
|
|
}
|
|
handle = _sqlite3OsDlOpen(tls, pVfs, zFile)
|
|
ii = 0
|
|
for {
|
|
if !(ii < libc.Int32FromUint64(libc.Uint64FromInt64(8)/libc.Uint64FromInt64(8)) && handle == uintptr(0)) {
|
|
break
|
|
}
|
|
zAltFile = Xsqlite3_mprintf(tls, __ccgo_ts+13660, libc.VaList(bp+16, zFile, _azEndings[ii]))
|
|
if zAltFile == uintptr(0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
if nMsg+uint64(libc.Xstrlen(tls, _azEndings[ii]))+uint64(1) <= uint64(FILENAME_MAX) {
|
|
handle = _sqlite3OsDlOpen(tls, pVfs, zAltFile)
|
|
}
|
|
Xsqlite3_free(tls, zAltFile)
|
|
goto _2
|
|
_2:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
if handle == uintptr(0) {
|
|
goto extension_not_found
|
|
}
|
|
xInit = _sqlite3OsDlSym(tls, pVfs, handle, zEntry)
|
|
/* If no entry point was specified and the default legacy
|
|
** entry point name "sqlite3_extension_init" was not found, then
|
|
** construct an entry point name "sqlite3_X_init" where the X is
|
|
** replaced by the lowercase value of every ASCII alphabetic
|
|
** character in the filename after the last "/" up to the first ".",
|
|
** and skipping the first three characters if they are "lib".
|
|
** Examples:
|
|
**
|
|
** /usr/local/lib/libExample5.4.3.so ==> sqlite3_example_init
|
|
** C:/lib/mathfuncs.dll ==> sqlite3_mathfuncs_init
|
|
**
|
|
** If that still finds no entry point, repeat a second time but this
|
|
** time include both alphabetic and numeric characters up to the first
|
|
** ".". Example:
|
|
**
|
|
** /usr/local/lib/libExample5.4.3.so ==> sqlite3_example5_init
|
|
*/
|
|
if xInit == uintptr(0) && zProc == uintptr(0) {
|
|
ncFile = _sqlite3Strlen30(tls, zFile)
|
|
cnt = 0
|
|
zAltEntry = Xsqlite3_malloc64(tls, libc.Uint64FromInt32(ncFile+int32(30)))
|
|
if zAltEntry == uintptr(0) {
|
|
_sqlite3OsDlClose(tls, pVfs, handle)
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
for {
|
|
libc.Xmemcpy(tls, zAltEntry, __ccgo_ts+17638, uint64(8))
|
|
iFile = ncFile - int32(1)
|
|
for {
|
|
if !(iFile >= 0 && !(libc.Int32FromUint8(**(**uint8)(__ccgo_up(zFile + uintptr(iFile)))) == libc.Int32FromUint8('/'))) {
|
|
break
|
|
}
|
|
goto _6
|
|
_6:
|
|
;
|
|
iFile = iFile - 1
|
|
}
|
|
iFile = iFile + 1
|
|
if Xsqlite3_strnicmp(tls, zFile+uintptr(iFile), __ccgo_ts+17647, int32(3)) == 0 {
|
|
iFile = iFile + int32(3)
|
|
}
|
|
iEntry = int32(8)
|
|
for {
|
|
v3 = libc.Int32FromUint8(**(**uint8)(__ccgo_up(zFile + uintptr(iFile))))
|
|
c = v3
|
|
if !(v3 != 0 && c != int32('.')) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint8(_sqlite3CtypeMap[libc.Uint8FromInt32(c)])&int32(0x02) != 0 || cnt != 0 && libc.Int32FromUint8(_sqlite3CtypeMap[libc.Uint8FromInt32(c)])&int32(0x04) != 0 {
|
|
v8 = iEntry
|
|
iEntry = iEntry + 1
|
|
**(**uint8)(__ccgo_up(zAltEntry + uintptr(v8))) = _sqlite3UpperToLower[libc.Uint32FromInt32(c)]
|
|
}
|
|
goto _7
|
|
_7:
|
|
;
|
|
iFile = iFile + 1
|
|
}
|
|
libc.Xmemcpy(tls, zAltEntry+uintptr(iEntry), __ccgo_ts+17651, uint64(6))
|
|
zEntry = zAltEntry
|
|
xInit = _sqlite3OsDlSym(tls, pVfs, handle, zEntry)
|
|
goto _5
|
|
_5:
|
|
;
|
|
if v4 = xInit == uintptr(0); v4 {
|
|
cnt = cnt + 1
|
|
v3 = cnt
|
|
}
|
|
if !(v4 && v3 < int32(2)) {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if xInit == uintptr(0) {
|
|
if pzErrMsg != 0 {
|
|
nMsg = nMsg + uint64(libc.Xstrlen(tls, zEntry)+uint64(300))
|
|
v1 = Xsqlite3_malloc64(tls, nMsg)
|
|
**(**uintptr)(__ccgo_up(bp)) = v1
|
|
**(**uintptr)(__ccgo_up(pzErrMsg)) = v1
|
|
if **(**uintptr)(__ccgo_up(bp)) != 0 {
|
|
/* zErrmsg would be NULL if not so */
|
|
Xsqlite3_snprintf(tls, libc.Int32FromUint64(nMsg), **(**uintptr)(__ccgo_up(bp)), __ccgo_ts+17657, libc.VaList(bp+16, zEntry, zFile))
|
|
_sqlite3OsDlError(tls, pVfs, libc.Int32FromUint64(nMsg-uint64(1)), **(**uintptr)(__ccgo_up(bp)))
|
|
}
|
|
}
|
|
_sqlite3OsDlClose(tls, pVfs, handle)
|
|
Xsqlite3_free(tls, zAltEntry)
|
|
return int32(SQLITE_ERROR)
|
|
}
|
|
Xsqlite3_free(tls, zAltEntry)
|
|
rc = (*(*func(*libc.TLS, uintptr, uintptr, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{xInit})))(tls, db, bp, uintptr(unsafe.Pointer(&_sqlite3Apis)))
|
|
if rc != 0 {
|
|
if rc == libc.Int32FromInt32(SQLITE_OK)|libc.Int32FromInt32(1)<<libc.Int32FromInt32(8) {
|
|
return SQLITE_OK
|
|
}
|
|
if pzErrMsg != 0 {
|
|
**(**uintptr)(__ccgo_up(pzErrMsg)) = Xsqlite3_mprintf(tls, __ccgo_ts+17700, libc.VaList(bp+16, **(**uintptr)(__ccgo_up(bp))))
|
|
}
|
|
Xsqlite3_free(tls, **(**uintptr)(__ccgo_up(bp)))
|
|
_sqlite3OsDlClose(tls, pVfs, handle)
|
|
return int32(SQLITE_ERROR)
|
|
}
|
|
/* Append the new shared library handle to the db->aExtension array. */
|
|
aHandle = _sqlite3DbMallocZero(tls, db, uint64(uint64(8)*libc.Uint64FromInt32((*Tsqlite3)(unsafe.Pointer(db)).FnExtension+libc.Int32FromInt32(1))))
|
|
if aHandle == uintptr(0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FnExtension > 0 {
|
|
libc.Xmemcpy(tls, aHandle, (*Tsqlite3)(unsafe.Pointer(db)).FaExtension, uint64(8)*libc.Uint64FromInt32((*Tsqlite3)(unsafe.Pointer(db)).FnExtension))
|
|
}
|
|
_sqlite3DbFree(tls, db, (*Tsqlite3)(unsafe.Pointer(db)).FaExtension)
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FaExtension = aHandle
|
|
v1 = db + 236
|
|
v3 = *(*int32)(unsafe.Pointer(v1))
|
|
*(*int32)(unsafe.Pointer(v1)) = *(*int32)(unsafe.Pointer(v1)) + 1
|
|
**(**uintptr)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaExtension + uintptr(v3)*8)) = handle
|
|
return SQLITE_OK
|
|
goto extension_not_found
|
|
extension_not_found:
|
|
;
|
|
if pzErrMsg != 0 {
|
|
nMsg = nMsg + uint64(300)
|
|
v1 = Xsqlite3_malloc64(tls, nMsg)
|
|
**(**uintptr)(__ccgo_up(bp)) = v1
|
|
**(**uintptr)(__ccgo_up(pzErrMsg)) = v1
|
|
if **(**uintptr)(__ccgo_up(bp)) != 0 {
|
|
/* zErrmsg would be NULL if not so */
|
|
Xsqlite3_snprintf(tls, libc.Int32FromUint64(nMsg), **(**uintptr)(__ccgo_up(bp)), __ccgo_ts+17732, libc.VaList(bp+16, int32(FILENAME_MAX), zFile))
|
|
_sqlite3OsDlError(tls, pVfs, libc.Int32FromUint64(nMsg-uint64(1)), **(**uintptr)(__ccgo_up(bp)))
|
|
}
|
|
}
|
|
return int32(SQLITE_ERROR)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Allocate and initialize a new Pager object and put a pointer to it
|
|
// ** in *ppPager. The pager should eventually be freed by passing it
|
|
// ** to sqlite3PagerClose().
|
|
// **
|
|
// ** The zFilename argument is the path to the database file to open.
|
|
// ** If zFilename is NULL then a randomly-named temporary file is created
|
|
// ** and used as the file to be cached. Temporary files are be deleted
|
|
// ** automatically when they are closed. If zFilename is ":memory:" then
|
|
// ** all information is held in cache. It is never written to disk.
|
|
// ** This can be used to implement an in-memory database.
|
|
// **
|
|
// ** The nExtra parameter specifies the number of bytes of space allocated
|
|
// ** along with each page reference. This space is available to the user
|
|
// ** via the sqlite3PagerGetExtra() API. When a new page is allocated, the
|
|
// ** first 8 bytes of this space are zeroed but the remainder is uninitialized.
|
|
// ** (The extra space is used by btree as the MemPage object.)
|
|
// **
|
|
// ** The flags argument is used to specify properties that affect the
|
|
// ** operation of the pager. It should be passed some bitwise combination
|
|
// ** of the PAGER_* flags.
|
|
// **
|
|
// ** The vfsFlags parameter is a bitmask to pass to the flags parameter
|
|
// ** of the xOpen() method of the supplied VFS when opening files.
|
|
// **
|
|
// ** If the pager object is allocated and the specified file opened
|
|
// ** successfully, SQLITE_OK is returned and *ppPager set to point to
|
|
// ** the new pager object. If an error occurs, *ppPager is set to NULL
|
|
// ** and error code returned. This function may return SQLITE_NOMEM
|
|
// ** (sqlite3Malloc() is used to allocate memory), SQLITE_CANTOPEN or
|
|
// ** various SQLITE_IO_XXX errors.
|
|
// */
|
|
func _sqlite3PagerOpen(tls *libc.TLS, pVfs uintptr, ppPager uintptr, zFilename uintptr, nExtra int32, flags int32, vfsFlags int32, __ccgo_fp_xReinit uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var iDc, journalFileSize, memDb, memJM, nPathname, nUriByte, pcacheSize, rc, readOnly, tempFile, useJournal, v4 int32
|
|
var pPtr, z, zPathname, zUri, v1 uintptr
|
|
var _ /* fout at bp+12 */ int32
|
|
var _ /* pPager at bp+0 */ uintptr
|
|
var _ /* szPageDflt at bp+8 */ Tu32
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = iDc, journalFileSize, memDb, memJM, nPathname, nUriByte, pPtr, pcacheSize, rc, readOnly, tempFile, useJournal, z, zPathname, zUri, v1, v4
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0) /* Pager object to allocate and return */
|
|
rc = SQLITE_OK /* Return code */
|
|
tempFile = 0 /* True for temp files (incl. in-memory files) */
|
|
memDb = 0 /* True if this is an in-memory file */
|
|
memJM = 0 /* Memory journal mode */
|
|
readOnly = 0 /* Bytes to allocate for each journal fd */
|
|
zPathname = uintptr(0) /* Full path to database file */
|
|
nPathname = 0 /* Number of bytes in zPathname */
|
|
useJournal = libc.BoolInt32(flags&int32(PAGER_OMIT_JOURNAL) == 0) /* False to omit journal */
|
|
pcacheSize = _sqlite3PcacheSize(tls) /* Bytes to allocate for PCache */
|
|
**(**Tu32)(__ccgo_up(bp + 8)) = uint32(SQLITE_DEFAULT_PAGE_SIZE) /* Default page size */
|
|
zUri = uintptr(0) /* URI args to copy */
|
|
nUriByte = int32(1) /* Number of bytes of URI args at *zUri */
|
|
/* Figure out how much space is required for each journal file-handle
|
|
** (there are two of them, the main journal and the sub-journal). */
|
|
journalFileSize = (_sqlite3JournalSize(tls, pVfs) + int32(7)) & ^libc.Int32FromInt32(7)
|
|
/* Set the output variable to NULL in case an error occurs. */
|
|
**(**uintptr)(__ccgo_up(ppPager)) = uintptr(0)
|
|
if flags&int32(PAGER_MEMORY) != 0 {
|
|
memDb = int32(1)
|
|
if zFilename != 0 && **(**uint8)(__ccgo_up(zFilename)) != 0 {
|
|
zPathname = _sqlite3DbStrDup(tls, uintptr(0), zFilename)
|
|
if zPathname == uintptr(0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
nPathname = _sqlite3Strlen30(tls, zPathname)
|
|
zFilename = uintptr(0)
|
|
}
|
|
}
|
|
/* Compute and store the full pathname in an allocated buffer pointed
|
|
** to by zPathname, length nPathname. Or, if this is a temporary file,
|
|
** leave both nPathname and zPathname set to 0.
|
|
*/
|
|
if zFilename != 0 && **(**uint8)(__ccgo_up(zFilename)) != 0 {
|
|
nPathname = (*Tsqlite3_vfs)(unsafe.Pointer(pVfs)).FmxPathname + int32(1)
|
|
zPathname = _sqlite3DbMallocRaw(tls, uintptr(0), libc.Uint64FromInt64(int64(2)*int64(nPathname)))
|
|
if zPathname == uintptr(0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
**(**uint8)(__ccgo_up(zPathname)) = uint8(0) /* Make sure initialized even if FullPathname() fails */
|
|
rc = _sqlite3OsFullPathname(tls, pVfs, zFilename, nPathname, zPathname)
|
|
if rc != SQLITE_OK {
|
|
if rc == libc.Int32FromInt32(SQLITE_OK)|libc.Int32FromInt32(2)<<libc.Int32FromInt32(8) {
|
|
if vfsFlags&int32(SQLITE_OPEN_NOFOLLOW) != 0 {
|
|
rc = libc.Int32FromInt32(SQLITE_CANTOPEN) | libc.Int32FromInt32(6)<<libc.Int32FromInt32(8)
|
|
} else {
|
|
rc = SQLITE_OK
|
|
}
|
|
}
|
|
}
|
|
nPathname = _sqlite3Strlen30(tls, zPathname)
|
|
v1 = zFilename + uintptr(_sqlite3Strlen30(tls, zFilename)+int32(1))
|
|
zUri = v1
|
|
z = v1
|
|
for **(**uint8)(__ccgo_up(z)) != 0 {
|
|
z = z + uintptr(libc.Xstrlen(tls, z)+uint64(1))
|
|
z = z + uintptr(libc.Xstrlen(tls, z)+uint64(1))
|
|
}
|
|
nUriByte = int32(t__predefined_ptrdiff_t(z+1) - int64(zUri))
|
|
if rc == SQLITE_OK && nPathname+int32(8) > (*Tsqlite3_vfs)(unsafe.Pointer(pVfs)).FmxPathname {
|
|
/* This branch is taken when the journal path required by
|
|
** the database being opened will be more than pVfs->mxPathname
|
|
** bytes in length. This means the database cannot be opened,
|
|
** as it will not be possible to open the journal file or even
|
|
** check for a hot-journal before reading.
|
|
*/
|
|
rc = _sqlite3CantopenError(tls, int32(64648))
|
|
}
|
|
if rc != SQLITE_OK {
|
|
_sqlite3DbFree(tls, uintptr(0), zPathname)
|
|
return rc
|
|
}
|
|
}
|
|
/* Allocate memory for the Pager structure, PCache object, the
|
|
** three file descriptors, the database file name and the journal
|
|
** file name. The layout in memory is as follows:
|
|
**
|
|
** Pager object (sizeof(Pager) bytes)
|
|
** PCache object (sqlite3PcacheSize() bytes)
|
|
** Database file handle (pVfs->szOsFile bytes)
|
|
** Sub-journal file handle (journalFileSize bytes)
|
|
** Main journal file handle (journalFileSize bytes)
|
|
** Ptr back to the Pager (sizeof(Pager*) bytes)
|
|
** \0\0\0\0 database prefix (4 bytes)
|
|
** Database file name (nPathname+1 bytes)
|
|
** URI query parameters (nUriByte bytes)
|
|
** Journal filename (nPathname+8+1 bytes)
|
|
** WAL filename (nPathname+4+1 bytes)
|
|
** \0\0\0 terminator (3 bytes)
|
|
**
|
|
** Some 3rd-party software, over which we have no control, depends on
|
|
** the specific order of the filenames and the \0 separators between them
|
|
** so that it can (for example) find the database filename given the WAL
|
|
** filename without using the sqlite3_filename_database() API. This is a
|
|
** misuse of SQLite and a bug in the 3rd-party software, but the 3rd-party
|
|
** software is in widespread use, so we try to avoid changing the filename
|
|
** order and formatting if possible. In particular, the details of the
|
|
** filename format expected by 3rd-party software should be as follows:
|
|
**
|
|
** - Main Database Path
|
|
** - \0
|
|
** - Multiple URI components consisting of:
|
|
** - Key
|
|
** - \0
|
|
** - Value
|
|
** - \0
|
|
** - \0
|
|
** - Journal Path
|
|
** - \0
|
|
** - WAL Path (zWALName)
|
|
** - \0
|
|
**
|
|
** The sqlite3_create_filename() interface and the databaseFilename() utility
|
|
** that is used by sqlite3_filename_database() and kin also depend on the
|
|
** specific formatting and order of the various filenames, so if the format
|
|
** changes here, be sure to change it there as well.
|
|
*/
|
|
pPtr = _sqlite3MallocZero(tls, uint64((libc.Uint64FromInt64(312)+libc.Uint64FromInt32(7))&libc.Uint64FromInt32(^libc.Int32FromInt32(7))+libc.Uint64FromInt32((pcacheSize+libc.Int32FromInt32(7)) & ^libc.Int32FromInt32(7))+libc.Uint64FromInt32(((*Tsqlite3_vfs)(unsafe.Pointer(pVfs)).FszOsFile+libc.Int32FromInt32(7)) & ^libc.Int32FromInt32(7)))+libc.Uint64FromInt32(journalFileSize)*uint64(2)+uint64(__SIZEOF_POINTER__)+uint64(4)+libc.Uint64FromInt32(nPathname)+uint64(1)+libc.Uint64FromInt32(nUriByte)+libc.Uint64FromInt32(nPathname)+uint64(8)+uint64(1)+libc.Uint64FromInt32(nPathname)+uint64(4)+uint64(1)+uint64(3))
|
|
if !(pPtr != 0) {
|
|
_sqlite3DbFree(tls, uintptr(0), zPathname)
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
**(**uintptr)(__ccgo_up(bp)) = pPtr
|
|
pPtr = pPtr + uintptr((libc.Uint64FromInt64(312)+libc.Uint64FromInt32(7))&libc.Uint64FromInt32(^libc.Int32FromInt32(7)))
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FpPCache = pPtr
|
|
pPtr = pPtr + uintptr((pcacheSize+libc.Int32FromInt32(7)) & ^libc.Int32FromInt32(7))
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).Ffd = pPtr
|
|
pPtr = pPtr + uintptr(((*Tsqlite3_vfs)(unsafe.Pointer(pVfs)).FszOsFile+libc.Int32FromInt32(7)) & ^libc.Int32FromInt32(7))
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).Fsjfd = pPtr
|
|
pPtr = pPtr + uintptr(journalFileSize)
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).Fjfd = pPtr
|
|
pPtr = pPtr + uintptr(journalFileSize)
|
|
libc.Xmemcpy(tls, pPtr, bp, uint64(__SIZEOF_POINTER__))
|
|
pPtr = pPtr + uintptr(__SIZEOF_POINTER__)
|
|
/* Fill in the Pager.zFilename and pPager.zQueryParam fields */
|
|
pPtr = pPtr + uintptr(4) /* Skip zero prefix */
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FzFilename = pPtr
|
|
if nPathname > 0 {
|
|
libc.Xmemcpy(tls, pPtr, zPathname, libc.Uint64FromInt32(nPathname))
|
|
pPtr = pPtr + uintptr(nPathname+int32(1))
|
|
if zUri != 0 {
|
|
libc.Xmemcpy(tls, pPtr, zUri, libc.Uint64FromInt32(nUriByte))
|
|
pPtr = pPtr + uintptr(nUriByte)
|
|
} else {
|
|
pPtr = pPtr + 1
|
|
}
|
|
}
|
|
/* Fill in Pager.zJournal */
|
|
if nPathname > 0 {
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FzJournal = pPtr
|
|
libc.Xmemcpy(tls, pPtr, zPathname, libc.Uint64FromInt32(nPathname))
|
|
pPtr = pPtr + uintptr(nPathname)
|
|
libc.Xmemcpy(tls, pPtr, __ccgo_ts+4255, uint64(8))
|
|
pPtr = pPtr + uintptr(libc.Int32FromInt32(8)+libc.Int32FromInt32(1))
|
|
} else {
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FzJournal = uintptr(0)
|
|
}
|
|
/* Fill in Pager.zWal */
|
|
if nPathname > 0 {
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FzWal = pPtr
|
|
libc.Xmemcpy(tls, pPtr, zPathname, libc.Uint64FromInt32(nPathname))
|
|
pPtr = pPtr + uintptr(nPathname)
|
|
libc.Xmemcpy(tls, pPtr, __ccgo_ts+4264, uint64(4))
|
|
pPtr = pPtr + uintptr(libc.Int32FromInt32(4)+libc.Int32FromInt32(1))
|
|
} else {
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FzWal = uintptr(0)
|
|
}
|
|
_ = pPtr /* Suppress warning about unused pPtr value */
|
|
if nPathname != 0 {
|
|
_sqlite3DbFree(tls, uintptr(0), zPathname)
|
|
}
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FpVfs = pVfs
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FvfsFlags = libc.Uint32FromInt32(vfsFlags)
|
|
/* Open the pager file.
|
|
*/
|
|
if !(zFilename != 0 && **(**uint8)(__ccgo_up(zFilename)) != 0) {
|
|
goto _2
|
|
}
|
|
**(**int32)(__ccgo_up(bp + 12)) = 0 /* VFS flags returned by xOpen() */
|
|
rc = _sqlite3OsOpen(tls, pVfs, (*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FzFilename, (*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).Ffd, vfsFlags, bp+12)
|
|
v4 = libc.BoolInt32(**(**int32)(__ccgo_up(bp + 12))&libc.Int32FromInt32(SQLITE_OPEN_MEMORY) != libc.Int32FromInt32(0))
|
|
memJM = v4
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FmemVfs = libc.Uint8FromInt32(v4)
|
|
readOnly = libc.BoolInt32(**(**int32)(__ccgo_up(bp + 12))&int32(SQLITE_OPEN_READONLY) != 0)
|
|
/* If the file was successfully opened for read/write access,
|
|
** choose a default page size in case we have to create the
|
|
** database file. The default page size is the maximum of:
|
|
**
|
|
** + SQLITE_DEFAULT_PAGE_SIZE,
|
|
** + The value returned by sqlite3OsSectorSize()
|
|
** + The largest page size that can be written atomically.
|
|
*/
|
|
if rc == SQLITE_OK {
|
|
iDc = _sqlite3OsDeviceCharacteristics(tls, (*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).Ffd)
|
|
if !(readOnly != 0) {
|
|
_setSectorSize(tls, **(**uintptr)(__ccgo_up(bp)))
|
|
if **(**Tu32)(__ccgo_up(bp + 8)) < (*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FsectorSize {
|
|
if (*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FsectorSize > uint32(SQLITE_MAX_DEFAULT_PAGE_SIZE) {
|
|
**(**Tu32)(__ccgo_up(bp + 8)) = uint32(SQLITE_MAX_DEFAULT_PAGE_SIZE)
|
|
} else {
|
|
**(**Tu32)(__ccgo_up(bp + 8)) = (*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FsectorSize
|
|
}
|
|
}
|
|
}
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FnoLock = libc.Uint8FromInt32(Xsqlite3_uri_boolean(tls, (*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FzFilename, __ccgo_ts+4269, 0))
|
|
if iDc&int32(SQLITE_IOCAP_IMMUTABLE) != 0 || Xsqlite3_uri_boolean(tls, (*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FzFilename, __ccgo_ts+4276, 0) != 0 {
|
|
vfsFlags = vfsFlags | int32(SQLITE_OPEN_READONLY)
|
|
goto act_like_temp_file
|
|
}
|
|
}
|
|
goto _3
|
|
_2:
|
|
;
|
|
/* If a temporary file is requested, it is not opened immediately.
|
|
** In this case we accept the default page size and delay actually
|
|
** opening the file until the first call to OsWrite().
|
|
**
|
|
** This branch is also run for an in-memory database. An in-memory
|
|
** database is the same as a temp-file that is never written out to
|
|
** disk and uses an in-memory rollback journal.
|
|
**
|
|
** This branch also runs for files marked as immutable.
|
|
*/
|
|
goto act_like_temp_file
|
|
act_like_temp_file:
|
|
;
|
|
tempFile = int32(1)
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FeState = uint8(PAGER_READER) /* Pretend we already have a lock */
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FeLock = uint8(EXCLUSIVE_LOCK) /* Pretend we are in EXCLUSIVE mode */
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FnoLock = uint8(1) /* Do no locking */
|
|
readOnly = vfsFlags & int32(SQLITE_OPEN_READONLY)
|
|
_3:
|
|
;
|
|
/* The following call to PagerSetPagesize() serves to set the value of
|
|
** Pager.pageSize and to allocate the Pager.pTmpSpace buffer.
|
|
*/
|
|
if rc == SQLITE_OK {
|
|
rc = _sqlite3PagerSetPagesize(tls, **(**uintptr)(__ccgo_up(bp)), bp+8, -int32(1))
|
|
}
|
|
/* Initialize the PCache object. */
|
|
if rc == SQLITE_OK {
|
|
nExtra = (nExtra + int32(7)) & ^libc.Int32FromInt32(7)
|
|
if !(memDb != 0) {
|
|
v1 = __ccgo_fp(_pagerStress)
|
|
} else {
|
|
v1 = uintptr(0)
|
|
}
|
|
rc = _sqlite3PcacheOpen(tls, libc.Int32FromUint32(**(**Tu32)(__ccgo_up(bp + 8))), nExtra, libc.BoolInt32(!(memDb != 0)), v1, **(**uintptr)(__ccgo_up(bp)), (*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FpPCache)
|
|
}
|
|
/* If an error occurred above, free the Pager structure and close the file.
|
|
*/
|
|
if rc != SQLITE_OK {
|
|
_sqlite3OsClose(tls, (*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).Ffd)
|
|
_sqlite3PageFree(tls, (*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FpTmpSpace)
|
|
Xsqlite3_free(tls, **(**uintptr)(__ccgo_up(bp)))
|
|
return rc
|
|
}
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FuseJournal = libc.Uint8FromInt32(useJournal)
|
|
/* pPager->stmtOpen = 0; */
|
|
/* pPager->stmtInUse = 0; */
|
|
/* pPager->nRef = 0; */
|
|
/* pPager->stmtSize = 0; */
|
|
/* pPager->stmtJSize = 0; */
|
|
/* pPager->nPage = 0; */
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FmxPgno = uint32(SQLITE_MAX_PAGE_COUNT)
|
|
/* pPager->state = PAGER_UNLOCK; */
|
|
/* pPager->errMask = 0; */
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FtempFile = libc.Uint8FromInt32(tempFile)
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FexclusiveMode = libc.Uint8FromInt32(tempFile)
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FchangeCountDone = (*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FtempFile
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FmemDb = libc.Uint8FromInt32(memDb)
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FreadOnly = libc.Uint8FromInt32(readOnly)
|
|
_sqlite3PagerSetFlags(tls, **(**uintptr)(__ccgo_up(bp)), libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_DEFAULT_SYNCHRONOUS)+libc.Int32FromInt32(1)|libc.Int32FromInt32(PAGER_CACHESPILL)))
|
|
/* pPager->pFirst = 0; */
|
|
/* pPager->pFirstSynced = 0; */
|
|
/* pPager->pLast = 0; */
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FnExtra = libc.Uint16FromInt32(nExtra)
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FjournalSizeLimit = int64(-int32(1))
|
|
_setSectorSize(tls, **(**uintptr)(__ccgo_up(bp)))
|
|
if !(useJournal != 0) {
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FjournalMode = uint8(PAGER_JOURNALMODE_OFF)
|
|
} else {
|
|
if memDb != 0 || memJM != 0 {
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FjournalMode = uint8(PAGER_JOURNALMODE_MEMORY)
|
|
}
|
|
}
|
|
/* pPager->xBusyHandler = 0; */
|
|
/* pPager->pBusyHandlerArg = 0; */
|
|
(*TPager)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FxReiniter = __ccgo_fp_xReinit
|
|
_setGetterMethod(tls, **(**uintptr)(__ccgo_up(bp)))
|
|
/* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
|
|
/* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */
|
|
**(**uintptr)(__ccgo_up(ppPager)) = **(**uintptr)(__ccgo_up(bp))
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is used to parse both URIs and non-URI filenames passed by the
|
|
// ** user to API functions sqlite3_open() or sqlite3_open_v2(), and for database
|
|
// ** URIs specified as part of ATTACH statements.
|
|
// **
|
|
// ** The first argument to this function is the name of the VFS to use (or
|
|
// ** a NULL to signify the default VFS) if the URI does not contain a "vfs=xxx"
|
|
// ** query parameter. The second argument contains the URI (or non-URI filename)
|
|
// ** itself. When this function is called the *pFlags variable should contain
|
|
// ** the default flags to open the database handle with. The value stored in
|
|
// ** *pFlags may be updated before returning if the URI filename contains
|
|
// ** "cache=xxx" or "mode=xxx" query parameters.
|
|
// **
|
|
// ** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to
|
|
// ** the VFS that should be used to open the database file. *pzFile is set to
|
|
// ** point to a buffer containing the name of the file to open. The value
|
|
// ** stored in *pzFile is a database name acceptable to sqlite3_uri_parameter()
|
|
// ** and is in the same format as names created using sqlite3_create_filename().
|
|
// ** The caller must invoke sqlite3_free_filename() (not sqlite3_free()!) on
|
|
// ** the value returned in *pzFile to avoid a memory leak.
|
|
// **
|
|
// ** If an error occurs, then an SQLite error code is returned and *pzErrMsg
|
|
// ** may be set to point to a buffer containing an English language error
|
|
// ** message. It is the responsibility of the caller to eventually release
|
|
// ** this buffer by calling sqlite3_free().
|
|
// */
|
|
func _sqlite3ParseUri(tls *libc.TLS, zDefaultVfs uintptr, zUri uintptr, pFlags uintptr, ppVfs uintptr, pzFile uintptr, pzErrMsg uintptr) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var aMode, z, zFile, zModeType, zOpt, zVal, zVfs uintptr
|
|
var c, v2 uint8
|
|
var eState, i, limit, mask, mode, octet, rc int32
|
|
var flags uint32
|
|
var iIn, iOut, nOpt, nUri, nVal, v3, v4 Ti64
|
|
var nByte Tu64
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = aMode, c, eState, flags, i, iIn, iOut, limit, mask, mode, nByte, nOpt, nUri, nVal, octet, rc, z, zFile, zModeType, zOpt, zVal, zVfs, v2, v3, v4
|
|
rc = SQLITE_OK
|
|
flags = **(**uint32)(__ccgo_up(pFlags))
|
|
zVfs = zDefaultVfs
|
|
nUri = libc.Int64FromUint64(libc.Xstrlen(tls, zUri))
|
|
if (flags&uint32(SQLITE_OPEN_URI) != 0 || libc.AtomicLoadNUint8(uintptr(unsafe.Pointer(&_sqlite3Config))+6, libc.Int32FromInt32(__ATOMIC_RELAXED)) != 0) && nUri >= int64(5) && libc.Xmemcmp(tls, zUri, __ccgo_ts+26142, uint64(5)) == 0 { /* Input character index */
|
|
iOut = 0 /* Output character index */
|
|
nByte = libc.Uint64FromInt64(nUri + int64(8)) /* Bytes of space to allocate */
|
|
/* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen
|
|
** method that there may be extra parameters following the file-name. */
|
|
flags = flags | uint32(SQLITE_OPEN_URI)
|
|
iIn = 0
|
|
for {
|
|
if !(iIn < nUri) {
|
|
break
|
|
}
|
|
nByte = nByte + libc.BoolUint64(libc.Int32FromUint8(**(**uint8)(__ccgo_up(zUri + uintptr(iIn)))) == libc.Int32FromUint8('&'))
|
|
goto _1
|
|
_1:
|
|
;
|
|
iIn = iIn + 1
|
|
}
|
|
zFile = Xsqlite3_malloc64(tls, nByte)
|
|
if !(zFile != 0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
libc.Xmemset(tls, zFile, 0, uint64(4)) /* 4-byte of 0x00 is the start of DB name marker */
|
|
zFile = zFile + uintptr(4)
|
|
iIn = int64(5)
|
|
/* Discard the scheme and authority segments of the URI. */
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zUri + 5))) == int32('/') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zUri + 6))) == int32('/') {
|
|
iIn = int64(7)
|
|
for **(**uint8)(__ccgo_up(zUri + uintptr(iIn))) != 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zUri + uintptr(iIn)))) != int32('/') {
|
|
iIn = iIn + 1
|
|
}
|
|
if iIn != int64(7) && (iIn != int64(16) || libc.Xmemcmp(tls, __ccgo_ts+26148, zUri+7, uint64(9)) != 0) {
|
|
**(**uintptr)(__ccgo_up(pzErrMsg)) = Xsqlite3_mprintf(tls, __ccgo_ts+26158, libc.VaList(bp+8, int32(iIn-libc.Int64FromInt32(7)), zUri+7))
|
|
rc = int32(SQLITE_ERROR)
|
|
goto parse_uri_out
|
|
}
|
|
}
|
|
/* Copy the filename and any query parameters into the zFile buffer.
|
|
** Decode %HH escape codes along the way.
|
|
**
|
|
** Within this loop, variable eState may be set to 0, 1 or 2, depending
|
|
** on the parsing context. As follows:
|
|
**
|
|
** 0: Parsing file-name.
|
|
** 1: Parsing name section of a name=value query parameter.
|
|
** 2: Parsing value section of a name=value query parameter.
|
|
*/
|
|
eState = 0
|
|
for {
|
|
v2 = **(**uint8)(__ccgo_up(zUri + uintptr(iIn)))
|
|
c = v2
|
|
if !(libc.Int32FromUint8(v2) != 0 && libc.Int32FromUint8(c) != int32('#')) {
|
|
break
|
|
}
|
|
iIn = iIn + 1
|
|
if libc.Int32FromUint8(c) == int32('%') && libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(zUri + uintptr(iIn))))])&int32(0x08) != 0 && libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(zUri + uintptr(iIn+int64(1)))))])&int32(0x08) != 0 {
|
|
v3 = iIn
|
|
iIn = iIn + 1
|
|
octet = libc.Int32FromUint8(_sqlite3HexToInt(tls, libc.Int32FromUint8(**(**uint8)(__ccgo_up(zUri + uintptr(v3)))))) << int32(4)
|
|
v4 = iIn
|
|
iIn = iIn + 1
|
|
octet = octet + libc.Int32FromUint8(_sqlite3HexToInt(tls, libc.Int32FromUint8(**(**uint8)(__ccgo_up(zUri + uintptr(v4))))))
|
|
if octet == 0 {
|
|
/* This branch is taken when "%00" appears within the URI. In this
|
|
** case we ignore all text in the remainder of the path, name or
|
|
** value currently being parsed. So ignore the current character
|
|
** and skip to the next "?", "=" or "&", as appropriate. */
|
|
for {
|
|
v2 = **(**uint8)(__ccgo_up(zUri + uintptr(iIn)))
|
|
c = v2
|
|
if !(libc.Int32FromUint8(v2) != 0 && libc.Int32FromUint8(c) != int32('#') && (eState != 0 || libc.Int32FromUint8(c) != int32('?')) && (eState != int32(1) || libc.Int32FromUint8(c) != int32('=') && libc.Int32FromUint8(c) != int32('&')) && (eState != int32(2) || libc.Int32FromUint8(c) != int32('&'))) {
|
|
break
|
|
}
|
|
iIn = iIn + 1
|
|
}
|
|
continue
|
|
}
|
|
c = libc.Uint8FromInt32(octet)
|
|
} else {
|
|
if eState == int32(1) && (libc.Int32FromUint8(c) == int32('&') || libc.Int32FromUint8(c) == int32('=')) {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zFile + uintptr(iOut-int64(1))))) == 0 {
|
|
/* An empty option name. Ignore this option altogether. */
|
|
for **(**uint8)(__ccgo_up(zUri + uintptr(iIn))) != 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zUri + uintptr(iIn)))) != int32('#') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zUri + uintptr(iIn-int64(1))))) != int32('&') {
|
|
iIn = iIn + 1
|
|
}
|
|
continue
|
|
}
|
|
if libc.Int32FromUint8(c) == int32('&') {
|
|
v3 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zFile + uintptr(v3))) = uint8('\000')
|
|
} else {
|
|
eState = int32(2)
|
|
}
|
|
c = uint8(0)
|
|
} else {
|
|
if eState == 0 && libc.Int32FromUint8(c) == int32('?') || eState == int32(2) && libc.Int32FromUint8(c) == int32('&') {
|
|
c = uint8(0)
|
|
eState = int32(1)
|
|
}
|
|
}
|
|
}
|
|
v3 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zFile + uintptr(v3))) = c
|
|
}
|
|
if eState == int32(1) {
|
|
v3 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zFile + uintptr(v3))) = uint8('\000')
|
|
}
|
|
libc.Xmemset(tls, zFile+uintptr(iOut), 0, uint64(4)) /* end-of-options + empty journal filenames */
|
|
/* Check if there were any options specified that should be interpreted
|
|
** here. Options that are interpreted here include "vfs" and those that
|
|
** correspond to flags that may be passed to the sqlite3_open_v2()
|
|
** method. */
|
|
zOpt = zFile + uintptr(libc.Xstrlen(tls, zFile)+uint64(1))
|
|
for **(**uint8)(__ccgo_up(zOpt)) != 0 {
|
|
nOpt = libc.Int64FromUint64(libc.Xstrlen(tls, zOpt))
|
|
zVal = zOpt + uintptr(nOpt+int64(1))
|
|
nVal = libc.Int64FromUint64(libc.Xstrlen(tls, zVal))
|
|
if nOpt == int64(3) && libc.Xmemcmp(tls, __ccgo_ts+26186, zOpt, uint64(3)) == 0 {
|
|
zVfs = zVal
|
|
} else {
|
|
aMode = uintptr(0)
|
|
zModeType = uintptr(0)
|
|
mask = 0
|
|
limit = 0
|
|
if nOpt == int64(5) && libc.Xmemcmp(tls, __ccgo_ts+26190, zOpt, uint64(5)) == 0 {
|
|
mask = libc.Int32FromInt32(SQLITE_OPEN_SHAREDCACHE) | libc.Int32FromInt32(SQLITE_OPEN_PRIVATECACHE)
|
|
aMode = uintptr(unsafe.Pointer(&_aCacheMode))
|
|
limit = mask
|
|
zModeType = __ccgo_ts + 26190
|
|
}
|
|
if nOpt == int64(4) && libc.Xmemcmp(tls, __ccgo_ts+26211, zOpt, uint64(4)) == 0 {
|
|
mask = libc.Int32FromInt32(SQLITE_OPEN_READONLY) | libc.Int32FromInt32(SQLITE_OPEN_READWRITE) | libc.Int32FromInt32(SQLITE_OPEN_CREATE) | libc.Int32FromInt32(SQLITE_OPEN_MEMORY)
|
|
aMode = uintptr(unsafe.Pointer(&_aOpenMode))
|
|
limit = libc.Int32FromUint32(libc.Uint32FromInt32(mask) & flags)
|
|
zModeType = __ccgo_ts + 3553
|
|
}
|
|
if aMode != 0 {
|
|
mode = 0
|
|
i = 0
|
|
for {
|
|
if !((**(**struct {
|
|
Fz uintptr
|
|
Fmode int32
|
|
})(__ccgo_up(aMode + uintptr(i)*16))).Fz != 0) {
|
|
break
|
|
}
|
|
z = (**(**struct {
|
|
Fz uintptr
|
|
Fmode int32
|
|
})(__ccgo_up(aMode + uintptr(i)*16))).Fz
|
|
if nVal == libc.Int64FromUint64(libc.Xstrlen(tls, z)) && 0 == libc.Xmemcmp(tls, zVal, z, libc.Uint64FromInt64(nVal)) {
|
|
mode = (**(**struct {
|
|
Fz uintptr
|
|
Fmode int32
|
|
})(__ccgo_up(aMode + uintptr(i)*16))).Fmode
|
|
break
|
|
}
|
|
goto _9
|
|
_9:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if mode == 0 {
|
|
**(**uintptr)(__ccgo_up(pzErrMsg)) = Xsqlite3_mprintf(tls, __ccgo_ts+26226, libc.VaList(bp+8, zModeType, zVal))
|
|
rc = int32(SQLITE_ERROR)
|
|
goto parse_uri_out
|
|
}
|
|
if mode & ^libc.Int32FromInt32(SQLITE_OPEN_MEMORY) > limit {
|
|
**(**uintptr)(__ccgo_up(pzErrMsg)) = Xsqlite3_mprintf(tls, __ccgo_ts+26246, libc.VaList(bp+8, zModeType, zVal))
|
|
rc = int32(SQLITE_PERM)
|
|
goto parse_uri_out
|
|
}
|
|
flags = flags&libc.Uint32FromInt32(^mask) | libc.Uint32FromInt32(mode)
|
|
}
|
|
}
|
|
zOpt = zVal + uintptr(nVal+int64(1))
|
|
}
|
|
} else {
|
|
zFile = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(nUri+int64(8)))
|
|
if !(zFile != 0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
libc.Xmemset(tls, zFile, 0, uint64(4))
|
|
zFile = zFile + uintptr(4)
|
|
if nUri != 0 {
|
|
libc.Xmemcpy(tls, zFile, zUri, libc.Uint64FromInt64(nUri))
|
|
}
|
|
libc.Xmemset(tls, zFile+uintptr(nUri), 0, uint64(4))
|
|
flags = flags & libc.Uint32FromInt32(^libc.Int32FromInt32(SQLITE_OPEN_URI))
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppVfs)) = Xsqlite3_vfs_find(tls, zVfs)
|
|
if **(**uintptr)(__ccgo_up(ppVfs)) == uintptr(0) {
|
|
**(**uintptr)(__ccgo_up(pzErrMsg)) = Xsqlite3_mprintf(tls, __ccgo_ts+26270, libc.VaList(bp+8, zVfs))
|
|
rc = int32(SQLITE_ERROR)
|
|
}
|
|
goto parse_uri_out
|
|
parse_uri_out:
|
|
;
|
|
if rc != SQLITE_OK {
|
|
Xsqlite3_free_filename(tls, zFile)
|
|
zFile = uintptr(0)
|
|
}
|
|
**(**uint32)(__ccgo_up(pFlags)) = flags
|
|
**(**uintptr)(__ccgo_up(pzFile)) = zFile
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Given a SELECT statement, generate a Table structure that describes
|
|
// ** the result set of that SELECT.
|
|
// */
|
|
func _sqlite3ResultSetOfSelect(tls *libc.TLS, pParse uintptr, pSelect uintptr, aff uint8) (r uintptr) {
|
|
var db, pTab uintptr
|
|
var savedFlags Tu64
|
|
_, _, _ = db, pTab, savedFlags
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
(*TParse)(unsafe.Pointer(pParse)).FnNestSel = (*TParse)(unsafe.Pointer(pParse)).FnNestSel + 1
|
|
if (*TParse)(unsafe.Pointer(pParse)).FnNestSel >= **(**int32)(__ccgo_up(db + 136 + 3*4)) {
|
|
_sqlite3ErrorMsg(tls, pParse, __ccgo_ts+20681, 0)
|
|
return uintptr(0)
|
|
}
|
|
savedFlags = (*Tsqlite3)(unsafe.Pointer(db)).Fflags
|
|
**(**Tu64)(__ccgo_up(db + 48)) &= ^libc.Uint64FromInt32(SQLITE_FullColNames)
|
|
**(**Tu64)(__ccgo_up(db + 48)) |= uint64(SQLITE_ShortColNames)
|
|
_sqlite3SelectPrep(tls, pParse, pSelect, uintptr(0))
|
|
(*Tsqlite3)(unsafe.Pointer(db)).Fflags = savedFlags
|
|
if (*TParse)(unsafe.Pointer(pParse)).FnErr != 0 {
|
|
return uintptr(0)
|
|
}
|
|
for (*TSelect)(unsafe.Pointer(pSelect)).FpPrior != 0 {
|
|
pSelect = (*TSelect)(unsafe.Pointer(pSelect)).FpPrior
|
|
}
|
|
pTab = _sqlite3DbMallocZero(tls, db, uint64(120))
|
|
if pTab == uintptr(0) {
|
|
return uintptr(0)
|
|
}
|
|
(*TTable)(unsafe.Pointer(pTab)).FnTabRef = uint32(1)
|
|
(*TTable)(unsafe.Pointer(pTab)).FzName = uintptr(0)
|
|
(*TTable)(unsafe.Pointer(pTab)).FnRowLogEst = int16(200)
|
|
_sqlite3ColumnsFromExprList(tls, pParse, (*TSelect)(unsafe.Pointer(pSelect)).FpEList, pTab+54, pTab+8)
|
|
_sqlite3SubqueryColumnTypes(tls, pParse, pTab, pSelect, aff)
|
|
(*TTable)(unsafe.Pointer(pTab)).FiPKey = int16(-int32(1))
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
|
|
_sqlite3DeleteTable(tls, db, pTab)
|
|
return uintptr(0)
|
|
}
|
|
(*TParse)(unsafe.Pointer(pParse)).FnNestSel = (*TParse)(unsafe.Pointer(pParse)).FnNestSel - 1
|
|
return pTab
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Run the parser on the given SQL string.
|
|
// */
|
|
func _sqlite3RunParser(tls *libc.TLS, pParse uintptr, zSql uintptr) (r int32) {
|
|
bp := tls.Alloc(1280)
|
|
defer tls.Free(1280)
|
|
var db, pEngine, pParentParse uintptr
|
|
var lastTokenParsed, nErr int32
|
|
var mxSqlLen, n Ti64
|
|
var _ /* sEngine at bp+8 */ TyyParser
|
|
var _ /* tokenType at bp+0 */ int32
|
|
var _ /* x at bp+1240 */ TToken
|
|
_, _, _, _, _, _, _ = db, lastTokenParsed, mxSqlLen, n, nErr, pEngine, pParentParse
|
|
nErr = 0 /* The LEMON-generated LALR(1) parser */
|
|
n = 0 /* type of the next token */
|
|
lastTokenParsed = -int32(1) /* type of the previous token */
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb /* Max length of an SQL string */
|
|
pParentParse = uintptr(0) /* Space to hold the Lemon-generated Parser object */
|
|
mxSqlLen = int64(**(**int32)(__ccgo_up(db + 136 + 1*4)))
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FnVdbeActive == 0 {
|
|
libc.AtomicStoreNInt32(db+432, libc.Int32FromInt32(0), libc.Int32FromInt32(__ATOMIC_RELAXED))
|
|
}
|
|
(*TParse)(unsafe.Pointer(pParse)).Frc = SQLITE_OK
|
|
(*TParse)(unsafe.Pointer(pParse)).FzTail = zSql
|
|
pEngine = bp + 8
|
|
_sqlite3ParserInit(tls, pEngine, pParse)
|
|
pParentParse = (*Tsqlite3)(unsafe.Pointer(db)).FpParse
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FpParse = pParse
|
|
for int32(1) != 0 {
|
|
n = _sqlite3GetToken(tls, zSql, bp)
|
|
mxSqlLen = mxSqlLen - n
|
|
if mxSqlLen < 0 {
|
|
(*TParse)(unsafe.Pointer(pParse)).Frc = int32(SQLITE_TOOBIG)
|
|
(*TParse)(unsafe.Pointer(pParse)).FnErr = (*TParse)(unsafe.Pointer(pParse)).FnErr + 1
|
|
break
|
|
}
|
|
if **(**int32)(__ccgo_up(bp)) >= int32(TK_WINDOW) {
|
|
if libc.AtomicLoadNInt32(db+432, libc.Int32FromInt32(__ATOMIC_RELAXED)) != 0 {
|
|
(*TParse)(unsafe.Pointer(pParse)).Frc = int32(SQLITE_INTERRUPT)
|
|
(*TParse)(unsafe.Pointer(pParse)).FnErr = (*TParse)(unsafe.Pointer(pParse)).FnErr + 1
|
|
break
|
|
}
|
|
if **(**int32)(__ccgo_up(bp)) == int32(TK_SPACE) {
|
|
zSql = zSql + uintptr(n)
|
|
continue
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zSql))) == 0 {
|
|
/* Upon reaching the end of input, call the parser two more times
|
|
** with tokens TK_SEMI and 0, in that order. */
|
|
if lastTokenParsed == int32(TK_SEMI) {
|
|
**(**int32)(__ccgo_up(bp)) = 0
|
|
} else {
|
|
if lastTokenParsed == 0 {
|
|
break
|
|
} else {
|
|
**(**int32)(__ccgo_up(bp)) = int32(TK_SEMI)
|
|
}
|
|
}
|
|
n = 0
|
|
} else {
|
|
if **(**int32)(__ccgo_up(bp)) == int32(TK_WINDOW) {
|
|
**(**int32)(__ccgo_up(bp)) = _analyzeWindowKeyword(tls, zSql+6)
|
|
} else {
|
|
if **(**int32)(__ccgo_up(bp)) == int32(TK_OVER) {
|
|
**(**int32)(__ccgo_up(bp)) = _analyzeOverKeyword(tls, zSql+4, lastTokenParsed)
|
|
} else {
|
|
if **(**int32)(__ccgo_up(bp)) == int32(TK_FILTER) {
|
|
**(**int32)(__ccgo_up(bp)) = _analyzeFilterKeyword(tls, zSql+6, lastTokenParsed)
|
|
} else {
|
|
if **(**int32)(__ccgo_up(bp)) == int32(TK_COMMENT) && ((*Tsqlite3)(unsafe.Pointer(db)).Finit1.Fbusy != 0 || (*Tsqlite3)(unsafe.Pointer(db)).Fflags&(libc.Uint64FromInt32(libc.Int32FromInt32(0x00040))<<libc.Int32FromInt32(32)) != uint64(0)) {
|
|
/* Ignore SQL comments if either (1) we are reparsing the schema or
|
|
** (2) SQLITE_DBCONFIG_ENABLE_COMMENTS is turned on (the default). */
|
|
zSql = zSql + uintptr(n)
|
|
continue
|
|
} else {
|
|
if **(**int32)(__ccgo_up(bp)) != int32(TK_QNUMBER) {
|
|
(**(**TToken)(__ccgo_up(bp + 1240))).Fz = zSql
|
|
(**(**TToken)(__ccgo_up(bp + 1240))).Fn = libc.Uint32FromInt64(n)
|
|
_sqlite3ErrorMsg(tls, pParse, __ccgo_ts+25245, libc.VaList(bp+1264, bp+1240))
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
(*TParse)(unsafe.Pointer(pParse)).FsLastToken.Fz = zSql
|
|
(*TParse)(unsafe.Pointer(pParse)).FsLastToken.Fn = libc.Uint32FromInt64(n)
|
|
_sqlite3Parser(tls, pEngine, **(**int32)(__ccgo_up(bp)), (*TParse)(unsafe.Pointer(pParse)).FsLastToken)
|
|
lastTokenParsed = **(**int32)(__ccgo_up(bp))
|
|
zSql = zSql + uintptr(n)
|
|
if (*TParse)(unsafe.Pointer(pParse)).Frc != SQLITE_OK {
|
|
break
|
|
}
|
|
}
|
|
_sqlite3ParserFinalize(tls, pEngine)
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
|
|
(*TParse)(unsafe.Pointer(pParse)).Frc = int32(SQLITE_NOMEM)
|
|
}
|
|
if (*TParse)(unsafe.Pointer(pParse)).FzErrMsg != 0 || (*TParse)(unsafe.Pointer(pParse)).Frc != SQLITE_OK && (*TParse)(unsafe.Pointer(pParse)).Frc != int32(SQLITE_DONE) {
|
|
if (*TParse)(unsafe.Pointer(pParse)).FzErrMsg == uintptr(0) {
|
|
(*TParse)(unsafe.Pointer(pParse)).FzErrMsg = _sqlite3DbStrDup(tls, db, _sqlite3ErrStr(tls, (*TParse)(unsafe.Pointer(pParse)).Frc))
|
|
}
|
|
if libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FprepFlags)&int32(SQLITE_PREPARE_DONT_LOG) == 0 {
|
|
Xsqlite3_log(tls, (*TParse)(unsafe.Pointer(pParse)).Frc, __ccgo_ts+25270, libc.VaList(bp+1264, (*TParse)(unsafe.Pointer(pParse)).FzErrMsg, (*TParse)(unsafe.Pointer(pParse)).FzTail))
|
|
}
|
|
nErr = nErr + 1
|
|
}
|
|
(*TParse)(unsafe.Pointer(pParse)).FzTail = zSql
|
|
Xsqlite3_free(tls, (*TParse)(unsafe.Pointer(pParse)).FapVtabLock)
|
|
if (*TParse)(unsafe.Pointer(pParse)).FpNewTable != 0 && !(libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) != libc.Int32FromInt32(PARSE_MODE_NORMAL)) {
|
|
/* If the pParse->declareVtab flag is set, do not delete any table
|
|
** structure built up in pParse->pNewTable. The calling code (see vtab.c)
|
|
** will take responsibility for freeing the Table structure.
|
|
*/
|
|
_sqlite3DeleteTable(tls, db, (*TParse)(unsafe.Pointer(pParse)).FpNewTable)
|
|
}
|
|
if (*TParse)(unsafe.Pointer(pParse)).FpNewTrigger != 0 && !(libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= libc.Int32FromInt32(PARSE_MODE_RENAME)) {
|
|
_sqlite3DeleteTrigger(tls, db, (*TParse)(unsafe.Pointer(pParse)).FpNewTrigger)
|
|
}
|
|
if (*TParse)(unsafe.Pointer(pParse)).FpVList != 0 {
|
|
_sqlite3DbNNFreeNN(tls, db, (*TParse)(unsafe.Pointer(pParse)).FpVList)
|
|
}
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FpParse = pParentParse
|
|
return nErr
|
|
}
|
|
|
|
/************** End of tokenize.c ********************************************/
|
|
/************** Begin file complete.c ****************************************/
|
|
/*
|
|
** 2001 September 15
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** An tokenizer for SQL
|
|
**
|
|
** This file contains C code that implements the sqlite3_complete() API.
|
|
** This code used to be part of the tokenizer.c source file. But by
|
|
** separating it out, the code will be automatically omitted from
|
|
** static links that do not use it.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/*
|
|
** This is defined in tokenize.c. We just have to import the definition.
|
|
*/
|
|
|
|
/*
|
|
** Token types used by the sqlite3_complete() routine. See the header
|
|
** comments on that procedure for additional information.
|
|
*/
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This routine implements the OP_Vacuum opcode of the VDBE.
|
|
// */
|
|
func _sqlite3RunVacuum(tls *libc.TLS, pzErrMsg uintptr, db uintptr, iDb int32, pOut uintptr) (r int32) {
|
|
bp := tls.Alloc(112)
|
|
defer tls.Free(112)
|
|
var i, isMemDb, nDb, nNew, nRes, rc, v1 int32
|
|
var id, pDb, pMain, pTemp, zDbMain, zFilename, zOut uintptr
|
|
var pgflags, saved_mDbFlags, saved_openFlags Tu32
|
|
var saved_flags Tu64
|
|
var saved_mTrace Tu8
|
|
var saved_nChange, saved_nTotalChange Ti64
|
|
var _ /* iRandom at bp+0 */ Tu64
|
|
var _ /* meta at bp+64 */ Tu32
|
|
var _ /* sz at bp+56 */ Ti64
|
|
var _ /* zDbVacuum at bp+8 */ [42]uint8
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = i, id, isMemDb, nDb, nNew, nRes, pDb, pMain, pTemp, pgflags, rc, saved_flags, saved_mDbFlags, saved_mTrace, saved_nChange, saved_nTotalChange, saved_openFlags, zDbMain, zFilename, zOut, v1
|
|
rc = SQLITE_OK /* Saved trace settings */
|
|
pDb = uintptr(0) /* Name of output file */
|
|
pgflags = uint32(PAGER_SYNCHRONOUS_OFF) /* Name of the ATTACH-ed database used for vacuum */
|
|
if !((*Tsqlite3)(unsafe.Pointer(db)).FautoCommit != 0) {
|
|
_sqlite3SetString(tls, pzErrMsg, db, __ccgo_ts+22765)
|
|
return int32(SQLITE_ERROR) /* IMP: R-12218-18073 */
|
|
}
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FnVdbeActive > int32(1) {
|
|
_sqlite3SetString(tls, pzErrMsg, db, __ccgo_ts+22805)
|
|
return int32(SQLITE_ERROR) /* IMP: R-15610-35227 */
|
|
}
|
|
saved_openFlags = (*Tsqlite3)(unsafe.Pointer(db)).FopenFlags
|
|
if pOut != 0 {
|
|
if Xsqlite3_value_type(tls, pOut) != int32(SQLITE_TEXT) {
|
|
_sqlite3SetString(tls, pzErrMsg, db, __ccgo_ts+22848)
|
|
return int32(SQLITE_ERROR)
|
|
}
|
|
zOut = Xsqlite3_value_text(tls, pOut)
|
|
**(**uint32)(__ccgo_up(db + 76)) &= libc.Uint32FromInt32(^libc.Int32FromInt32(SQLITE_OPEN_READONLY))
|
|
**(**uint32)(__ccgo_up(db + 76)) |= libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_OPEN_CREATE) | libc.Int32FromInt32(SQLITE_OPEN_READWRITE))
|
|
} else {
|
|
zOut = __ccgo_ts + 1704
|
|
}
|
|
/* Save the current value of the database flags so that it can be
|
|
** restored before returning. Then set the writable-schema flag, and
|
|
** disable CHECK and foreign key constraints. */
|
|
saved_flags = (*Tsqlite3)(unsafe.Pointer(db)).Fflags
|
|
saved_mDbFlags = (*Tsqlite3)(unsafe.Pointer(db)).FmDbFlags
|
|
saved_nChange = (*Tsqlite3)(unsafe.Pointer(db)).FnChange
|
|
saved_nTotalChange = (*Tsqlite3)(unsafe.Pointer(db)).FnTotalChange
|
|
saved_mTrace = (*Tsqlite3)(unsafe.Pointer(db)).FmTrace
|
|
**(**Tu64)(__ccgo_up(db + 48)) |= libc.Uint64FromInt32(libc.Int32FromInt32(SQLITE_WriteSchema)|libc.Int32FromInt32(SQLITE_IgnoreChecks)) | libc.Uint64FromInt32(libc.Int32FromInt32(0x00040))<<libc.Int32FromInt32(32) | libc.Uint64FromInt32(libc.Int32FromInt32(0x00010))<<libc.Int32FromInt32(32) | libc.Uint64FromInt32(libc.Int32FromInt32(0x00020))<<libc.Int32FromInt32(32)
|
|
**(**Tu32)(__ccgo_up(db + 44)) |= libc.Uint32FromInt32(libc.Int32FromInt32(DBFLAG_PreferBuiltin) | libc.Int32FromInt32(DBFLAG_Vacuum))
|
|
**(**Tu64)(__ccgo_up(db + 48)) &= ^(libc.Uint64FromInt32(libc.Int32FromInt32(SQLITE_ForeignKeys)|libc.Int32FromInt32(SQLITE_ReverseOrder)|libc.Int32FromInt32(SQLITE_Defensive)) | libc.Uint64FromInt32(libc.Int32FromInt32(0x00001))<<libc.Int32FromInt32(32))
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FmTrace = uint8(0)
|
|
zDbMain = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FzDbSName
|
|
pMain = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FpBt
|
|
isMemDb = _sqlite3PagerIsMemdb(tls, _sqlite3BtreePager(tls, pMain))
|
|
/* Attach the temporary database as 'vacuum_XXXXXX'. The synchronous pragma
|
|
** can be set to 'off' for this file, as it is not recovered if a crash
|
|
** occurs anyway. The integrity of the database is maintained by a
|
|
** (possibly synchronous) transaction opened on the main database before
|
|
** sqlite3BtreeCopyFile() is called.
|
|
**
|
|
** An optimization would be to use a non-journaled pager.
|
|
** (Later:) I tried setting "PRAGMA vacuum_XXXXXX.journal_mode=OFF" but
|
|
** that actually made the VACUUM run slower. Very little journalling
|
|
** actually occurs when doing a vacuum since the vacuum_db is initially
|
|
** empty. Only the journal header is written. Apparently it takes more
|
|
** time to parse and run the PRAGMA to turn journalling off than it does
|
|
** to write the journal header file.
|
|
*/
|
|
Xsqlite3_randomness(tls, int32(8), bp)
|
|
Xsqlite3_snprintf(tls, int32(42), bp+8, __ccgo_ts+22866, libc.VaList(bp+80, **(**Tu64)(__ccgo_up(bp))))
|
|
nDb = (*Tsqlite3)(unsafe.Pointer(db)).FnDb
|
|
rc = _execSqlF(tls, db, pzErrMsg, __ccgo_ts+22881, libc.VaList(bp+80, zOut, bp+8))
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FopenFlags = saved_openFlags
|
|
if rc != SQLITE_OK {
|
|
goto end_of_vacuum
|
|
}
|
|
pDb = (*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(nDb)*32
|
|
pTemp = (*TDb)(unsafe.Pointer(pDb)).FpBt
|
|
nRes = _sqlite3BtreeGetRequestedReserve(tls, pMain)
|
|
if pOut != 0 {
|
|
id = _sqlite3PagerFile(tls, _sqlite3BtreePager(tls, pTemp))
|
|
**(**Ti64)(__ccgo_up(bp + 56)) = 0
|
|
if (*Tsqlite3_file)(unsafe.Pointer(id)).FpMethods != uintptr(0) && (_sqlite3OsFileSize(tls, id, bp+56) != SQLITE_OK || **(**Ti64)(__ccgo_up(bp + 56)) > 0) {
|
|
rc = int32(SQLITE_ERROR)
|
|
_sqlite3SetString(tls, pzErrMsg, db, __ccgo_ts+22897)
|
|
goto end_of_vacuum
|
|
}
|
|
**(**Tu32)(__ccgo_up(db + 44)) |= uint32(DBFLAG_VacuumInto)
|
|
/* For a VACUUM INTO, the pager-flags are set to the same values as
|
|
** they are for the database being vacuumed, except that PAGER_CACHESPILL
|
|
** is always set. */
|
|
pgflags = uint32(uint64((**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).Fsafety_level) | (*Tsqlite3)(unsafe.Pointer(db)).Fflags&uint64(PAGER_FLAGS_MASK))
|
|
/* If the VACUUM INTO target file is a URI filename and if the
|
|
** "reserve=N" query parameter is present, reset the reserve to the
|
|
** amount specified, if the amount is within range */
|
|
zFilename = _sqlite3BtreeGetFilename(tls, pTemp)
|
|
if zFilename != 0 {
|
|
nNew = int32(Xsqlite3_uri_int64(tls, zFilename, __ccgo_ts+22924, int64(nRes)))
|
|
if nNew >= 0 && nNew <= int32(255) {
|
|
nRes = nNew
|
|
}
|
|
}
|
|
}
|
|
_sqlite3BtreeSetCacheSize(tls, pTemp, (*TSchema)(unsafe.Pointer((**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FpSchema)).Fcache_size)
|
|
_sqlite3BtreeSetSpillSize(tls, pTemp, _sqlite3BtreeSetSpillSize(tls, pMain, 0))
|
|
_sqlite3BtreeSetPagerFlags(tls, pTemp, pgflags|uint32(PAGER_CACHESPILL))
|
|
/* Begin a transaction and take an exclusive lock on the main database
|
|
** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below,
|
|
** to ensure that we do not try to change the page-size on a WAL database.
|
|
*/
|
|
rc = _execSql(tls, db, pzErrMsg, __ccgo_ts+16131)
|
|
if rc != SQLITE_OK {
|
|
goto end_of_vacuum
|
|
}
|
|
if pOut == uintptr(0) {
|
|
v1 = int32(2)
|
|
} else {
|
|
v1 = 0
|
|
}
|
|
rc = _sqlite3BtreeBeginTrans(tls, pMain, v1, uintptr(0))
|
|
if rc != SQLITE_OK {
|
|
goto end_of_vacuum
|
|
}
|
|
/* Do not attempt to change the page size for a WAL database */
|
|
if _sqlite3PagerGetJournalMode(tls, _sqlite3BtreePager(tls, pMain)) == int32(PAGER_JOURNALMODE_WAL) && pOut == uintptr(0) {
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FnextPagesize = 0
|
|
}
|
|
if _sqlite3BtreeSetPageSize(tls, pTemp, _sqlite3BtreeGetPageSize(tls, pMain), nRes, 0) != 0 || !(isMemDb != 0) && _sqlite3BtreeSetPageSize(tls, pTemp, (*Tsqlite3)(unsafe.Pointer(db)).FnextPagesize, nRes, 0) != 0 || (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
|
|
rc = int32(SQLITE_NOMEM)
|
|
goto end_of_vacuum
|
|
}
|
|
if int32((*Tsqlite3)(unsafe.Pointer(db)).FnextAutovac) >= 0 {
|
|
v1 = int32((*Tsqlite3)(unsafe.Pointer(db)).FnextAutovac)
|
|
} else {
|
|
v1 = _sqlite3BtreeGetAutoVacuum(tls, pMain)
|
|
}
|
|
_sqlite3BtreeSetAutoVacuum(tls, pTemp, v1)
|
|
/* Query the schema of the main database. Create a mirror schema
|
|
** in the temporary database.
|
|
*/
|
|
(*Tsqlite3)(unsafe.Pointer(db)).Finit1.FiDb = libc.Uint8FromInt32(nDb) /* force new CREATE statements into vacuum_db */
|
|
rc = _execSqlF(tls, db, pzErrMsg, __ccgo_ts+22932, libc.VaList(bp+80, zDbMain))
|
|
if rc != SQLITE_OK {
|
|
goto end_of_vacuum
|
|
}
|
|
rc = _execSqlF(tls, db, pzErrMsg, __ccgo_ts+23040, libc.VaList(bp+80, zDbMain))
|
|
if rc != SQLITE_OK {
|
|
goto end_of_vacuum
|
|
}
|
|
(*Tsqlite3)(unsafe.Pointer(db)).Finit1.FiDb = uint8(0)
|
|
/* Loop through the tables in the main database. For each, do
|
|
** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy
|
|
** the contents to the temporary database.
|
|
*/
|
|
rc = _execSqlF(tls, db, pzErrMsg, __ccgo_ts+23094, libc.VaList(bp+80, bp+8, zDbMain, bp+8))
|
|
**(**Tu32)(__ccgo_up(db + 44)) &= libc.Uint32FromInt32(^libc.Int32FromInt32(DBFLAG_Vacuum))
|
|
if rc != SQLITE_OK {
|
|
goto end_of_vacuum
|
|
}
|
|
/* Copy the triggers, views, and virtual tables from the main database
|
|
** over to the temporary database. None of these objects has any
|
|
** associated storage, so all we have to do is copy their entries
|
|
** from the schema table.
|
|
*/
|
|
rc = _execSqlF(tls, db, pzErrMsg, __ccgo_ts+23231, libc.VaList(bp+80, bp+8, zDbMain))
|
|
if rc != 0 {
|
|
goto end_of_vacuum
|
|
}
|
|
/* Copy Btree meta values */
|
|
i = 0
|
|
for {
|
|
if !(i < libc.Int32FromUint64(libc.Uint64FromInt64(10)/libc.Uint64FromInt64(1))) {
|
|
break
|
|
}
|
|
/* GetMeta() and UpdateMeta() cannot fail in this context because
|
|
** we already have page 1 loaded into cache and marked dirty. */
|
|
_sqlite3BtreeGetMeta(tls, pMain, libc.Int32FromUint8(_aCopy[i]), bp+64)
|
|
rc = _sqlite3BtreeUpdateMeta(tls, pTemp, libc.Int32FromUint8(_aCopy[i]), **(**Tu32)(__ccgo_up(bp + 64))+uint32(_aCopy[i+int32(1)]))
|
|
if rc != SQLITE_OK {
|
|
goto end_of_vacuum
|
|
}
|
|
goto _3
|
|
_3:
|
|
;
|
|
i = i + int32(2)
|
|
}
|
|
if pOut == uintptr(0) {
|
|
rc = _sqlite3BtreeCopyFile(tls, pMain, pTemp)
|
|
}
|
|
if rc != SQLITE_OK {
|
|
goto end_of_vacuum
|
|
}
|
|
rc = _sqlite3BtreeCommit(tls, pTemp)
|
|
if rc != SQLITE_OK {
|
|
goto end_of_vacuum
|
|
}
|
|
if pOut == uintptr(0) {
|
|
_sqlite3BtreeSetAutoVacuum(tls, pMain, _sqlite3BtreeGetAutoVacuum(tls, pTemp))
|
|
}
|
|
if pOut == uintptr(0) {
|
|
nRes = _sqlite3BtreeGetRequestedReserve(tls, pTemp)
|
|
rc = _sqlite3BtreeSetPageSize(tls, pMain, _sqlite3BtreeGetPageSize(tls, pTemp), nRes, int32(1))
|
|
}
|
|
goto end_of_vacuum
|
|
end_of_vacuum:
|
|
;
|
|
/* Restore the original value of db->flags */
|
|
(*Tsqlite3)(unsafe.Pointer(db)).Finit1.FiDb = uint8(0)
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FmDbFlags = saved_mDbFlags
|
|
(*Tsqlite3)(unsafe.Pointer(db)).Fflags = saved_flags
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FnChange = saved_nChange
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FnTotalChange = saved_nTotalChange
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FmTrace = saved_mTrace
|
|
_sqlite3BtreeSetPageSize(tls, pMain, -int32(1), 0, int32(1))
|
|
/* Currently there is an SQL level transaction open on the vacuum
|
|
** database. No locks are held on any other files (since the main file
|
|
** was committed at the btree level). So it safe to end the transaction
|
|
** by manually setting the autoCommit flag to true and detaching the
|
|
** vacuum database. The vacuum_db journal file is deleted when the pager
|
|
** is closed by the DETACH.
|
|
*/
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FautoCommit = uint8(1)
|
|
if pDb != 0 {
|
|
_sqlite3BtreeClose(tls, (*TDb)(unsafe.Pointer(pDb)).FpBt)
|
|
(*TDb)(unsafe.Pointer(pDb)).FpBt = uintptr(0)
|
|
(*TDb)(unsafe.Pointer(pDb)).FpSchema = uintptr(0)
|
|
}
|
|
/* This both clears the schemas and reduces the size of the db->aDb[]
|
|
** array. */
|
|
_sqlite3ResetAllSchemasOfConnection(tls, db)
|
|
return rc
|
|
}
|
|
|
|
/* At this point, there is a write transaction open on both the
|
|
** vacuum database and the main database. Assuming no error occurs,
|
|
** both transactions are closed by this block - the main database
|
|
** transaction by sqlite3BtreeCopyFile() and the other by an explicit
|
|
** call to sqlite3BtreeCommit().
|
|
*/
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** pTab is a transient Table object that represents a subquery of some
|
|
// ** kind (maybe a parenthesized subquery in the FROM clause of a larger
|
|
// ** query, or a VIEW, or a CTE). This routine computes type information
|
|
// ** for that Table object based on the Select object that implements the
|
|
// ** subquery. For the purposes of this routine, "type information" means:
|
|
// **
|
|
// ** * The datatype name, as it might appear in a CREATE TABLE statement
|
|
// ** * Which collating sequence to use for the column
|
|
// ** * The affinity of the column
|
|
// */
|
|
func _sqlite3SubqueryColumnTypes(tls *libc.TLS, pParse uintptr, pTab uintptr, pSelect uintptr, aff uint8) {
|
|
bp := tls.Alloc(64)
|
|
defer tls.Free(64)
|
|
var a, db, p, pCol, pColl, pS2, zType, v4 uintptr
|
|
var i, j, m int32
|
|
var k, n Ti64
|
|
var _ /* sNC at bp+0 */ TNameContext
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _ = a, db, i, j, k, m, n, p, pCol, pColl, pS2, zType, v4
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 || libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= int32(PARSE_MODE_RENAME) {
|
|
return
|
|
}
|
|
for (*TSelect)(unsafe.Pointer(pSelect)).FpPrior != 0 {
|
|
pSelect = (*TSelect)(unsafe.Pointer(pSelect)).FpPrior
|
|
}
|
|
a = (*TSelect)(unsafe.Pointer(pSelect)).FpEList + 8
|
|
libc.Xmemset(tls, bp, 0, uint64(56))
|
|
(**(**TNameContext)(__ccgo_up(bp))).FpSrcList = (*TSelect)(unsafe.Pointer(pSelect)).FpSrc
|
|
i = 0
|
|
pCol = (*TTable)(unsafe.Pointer(pTab)).FaCol
|
|
for {
|
|
if !(i < int32((*TTable)(unsafe.Pointer(pTab)).FnCol)) {
|
|
break
|
|
}
|
|
m = 0
|
|
pS2 = pSelect
|
|
**(**Tu32)(__ccgo_up(pTab + 48)) |= libc.Uint32FromInt32(libc.Int32FromUint16((*TColumn)(unsafe.Pointer(pCol)).FcolFlags) & libc.Int32FromInt32(COLFLAG_NOINSERT))
|
|
p = (**(**TExprList_item)(__ccgo_up(a + uintptr(i)*32))).FpExpr
|
|
/* pCol->szEst = ... // Column size est for SELECT tables never used */
|
|
(*TColumn)(unsafe.Pointer(pCol)).Faffinity = _sqlite3ExprAffinity(tls, p)
|
|
for libc.Int32FromUint8((*TColumn)(unsafe.Pointer(pCol)).Faffinity) <= int32(SQLITE_AFF_NONE) && (*TSelect)(unsafe.Pointer(pS2)).FpNext != uintptr(0) {
|
|
m = m | _sqlite3ExprDataType(tls, (*(*TExprList_item)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pS2)).FpEList + 8 + uintptr(i)*32))).FpExpr)
|
|
pS2 = (*TSelect)(unsafe.Pointer(pS2)).FpNext
|
|
(*TColumn)(unsafe.Pointer(pCol)).Faffinity = _sqlite3ExprAffinity(tls, (*(*TExprList_item)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pS2)).FpEList + 8 + uintptr(i)*32))).FpExpr)
|
|
}
|
|
if libc.Int32FromUint8((*TColumn)(unsafe.Pointer(pCol)).Faffinity) <= int32(SQLITE_AFF_NONE) {
|
|
(*TColumn)(unsafe.Pointer(pCol)).Faffinity = aff
|
|
}
|
|
if libc.Int32FromUint8((*TColumn)(unsafe.Pointer(pCol)).Faffinity) >= int32(SQLITE_AFF_TEXT) && ((*TSelect)(unsafe.Pointer(pS2)).FpNext != 0 || pS2 != pSelect) {
|
|
pS2 = (*TSelect)(unsafe.Pointer(pS2)).FpNext
|
|
for {
|
|
if !(pS2 != 0) {
|
|
break
|
|
}
|
|
m = m | _sqlite3ExprDataType(tls, (*(*TExprList_item)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pS2)).FpEList + 8 + uintptr(i)*32))).FpExpr)
|
|
goto _2
|
|
_2:
|
|
;
|
|
pS2 = (*TSelect)(unsafe.Pointer(pS2)).FpNext
|
|
}
|
|
if libc.Int32FromUint8((*TColumn)(unsafe.Pointer(pCol)).Faffinity) == int32(SQLITE_AFF_TEXT) && m&int32(0x01) != 0 {
|
|
(*TColumn)(unsafe.Pointer(pCol)).Faffinity = uint8(SQLITE_AFF_BLOB)
|
|
} else {
|
|
if libc.Int32FromUint8((*TColumn)(unsafe.Pointer(pCol)).Faffinity) >= int32(SQLITE_AFF_NUMERIC) && m&int32(0x02) != 0 {
|
|
(*TColumn)(unsafe.Pointer(pCol)).Faffinity = uint8(SQLITE_AFF_BLOB)
|
|
}
|
|
}
|
|
if libc.Int32FromUint8((*TColumn)(unsafe.Pointer(pCol)).Faffinity) >= int32(SQLITE_AFF_NUMERIC) && libc.Int32FromUint8((*TExpr)(unsafe.Pointer(p)).Fop) == int32(TK_CAST) {
|
|
(*TColumn)(unsafe.Pointer(pCol)).Faffinity = uint8(SQLITE_AFF_FLEXNUM)
|
|
}
|
|
}
|
|
zType = _columnTypeImpl(tls, bp, p, uintptr(0), uintptr(0), uintptr(0))
|
|
if zType == uintptr(0) || libc.Int32FromUint8((*TColumn)(unsafe.Pointer(pCol)).Faffinity) != libc.Int32FromUint8(_sqlite3AffinityType(tls, zType, uintptr(0))) {
|
|
if libc.Int32FromUint8((*TColumn)(unsafe.Pointer(pCol)).Faffinity) == int32(SQLITE_AFF_NUMERIC) || libc.Int32FromUint8((*TColumn)(unsafe.Pointer(pCol)).Faffinity) == int32(SQLITE_AFF_FLEXNUM) {
|
|
zType = __ccgo_ts + 20677
|
|
} else {
|
|
zType = uintptr(0)
|
|
j = int32(1)
|
|
for {
|
|
if !(j < int32(SQLITE_N_STDTYPE)) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint8(_sqlite3StdTypeAffinity[j]) == libc.Int32FromUint8((*TColumn)(unsafe.Pointer(pCol)).Faffinity) {
|
|
zType = _sqlite3StdType[j]
|
|
break
|
|
}
|
|
goto _3
|
|
_3:
|
|
;
|
|
j = j + 1
|
|
}
|
|
}
|
|
}
|
|
if zType != 0 {
|
|
k = libc.Int64FromUint64(libc.Xstrlen(tls, zType))
|
|
n = libc.Int64FromUint64(libc.Xstrlen(tls, (*TColumn)(unsafe.Pointer(pCol)).FzCnName))
|
|
(*TColumn)(unsafe.Pointer(pCol)).FzCnName = _sqlite3DbReallocOrFree(tls, db, (*TColumn)(unsafe.Pointer(pCol)).FzCnName, libc.Uint64FromInt64(n+k+int64(2)))
|
|
v4 = pCol + 14
|
|
*(*Tu16)(unsafe.Pointer(v4)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v4))) & ^(libc.Int32FromInt32(COLFLAG_HASTYPE) | libc.Int32FromInt32(COLFLAG_HASCOLL)))
|
|
if (*TColumn)(unsafe.Pointer(pCol)).FzCnName != 0 {
|
|
libc.Xmemcpy(tls, (*TColumn)(unsafe.Pointer(pCol)).FzCnName+uintptr(n+int64(1)), zType, libc.Uint64FromInt64(k+int64(1)))
|
|
v4 = pCol + 14
|
|
*(*Tu16)(unsafe.Pointer(v4)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v4))) | libc.Int32FromInt32(COLFLAG_HASTYPE))
|
|
}
|
|
}
|
|
pColl = _sqlite3ExprCollSeq(tls, pParse, p)
|
|
if pColl != 0 {
|
|
_sqlite3ColumnSetColl(tls, db, pCol, (*TCollSeq)(unsafe.Pointer(pColl)).FzName)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
pCol += 16
|
|
}
|
|
(*TTable)(unsafe.Pointer(pTab)).FszTabRow = int16(1) /* Any non-zero value works */
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Analyze the ON CONFLICT clause described by pUpsert. Resolve all
|
|
// ** symbols in the conflict-target.
|
|
// **
|
|
// ** Return SQLITE_OK if everything works, or an error code is something
|
|
// ** is wrong.
|
|
// */
|
|
func _sqlite3UpsertAnalyzeTarget(tls *libc.TLS, pParse uintptr, pTabList uintptr, pUpsert uintptr, pAll uintptr) (r int32) {
|
|
bp := tls.Alloc(240)
|
|
defer tls.Free(240)
|
|
var iCursor, ii, jj, nClause, nn, rc int32
|
|
var pExpr, pIdx, pTab, pTarget, pTerm, v2 uintptr
|
|
var v3 bool
|
|
var _ /* sCol at bp+56 */ [2]TExpr
|
|
var _ /* sNC at bp+0 */ TNameContext
|
|
var _ /* zWhich at bp+200 */ [16]uint8
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _ = iCursor, ii, jj, nClause, nn, pExpr, pIdx, pTab, pTarget, pTerm, rc, v2, v3 /* Index column converted into an Expr */
|
|
nClause = 0 /* Counter of ON CONFLICT clauses */
|
|
/* Resolve all symbolic names in the conflict-target clause, which
|
|
** includes both the list of columns and the optional partial-index
|
|
** WHERE clause.
|
|
*/
|
|
libc.Xmemset(tls, bp, 0, uint64(56))
|
|
(**(**TNameContext)(__ccgo_up(bp))).FpParse = pParse
|
|
(**(**TNameContext)(__ccgo_up(bp))).FpSrcList = pTabList
|
|
for {
|
|
if !(pUpsert != 0 && (*TUpsert)(unsafe.Pointer(pUpsert)).FpUpsertTarget != 0) {
|
|
break
|
|
}
|
|
rc = _sqlite3ResolveExprListNames(tls, bp, (*TUpsert)(unsafe.Pointer(pUpsert)).FpUpsertTarget)
|
|
if rc != 0 {
|
|
return rc
|
|
}
|
|
rc = _sqlite3ResolveExprNames(tls, bp, (*TUpsert)(unsafe.Pointer(pUpsert)).FpUpsertTargetWhere)
|
|
if rc != 0 {
|
|
return rc
|
|
}
|
|
/* Check to see if the conflict target matches the rowid. */
|
|
pTab = (*(*TSrcItem)(unsafe.Pointer(pTabList + 8))).FpSTab
|
|
pTarget = (*TUpsert)(unsafe.Pointer(pUpsert)).FpUpsertTarget
|
|
iCursor = (*(*TSrcItem)(unsafe.Pointer(pTabList + 8))).FiCursor
|
|
if v3 = (*TTable)(unsafe.Pointer(pTab)).FtabFlags&uint32(TF_WithoutRowid) == uint32(0) && (*TExprList)(unsafe.Pointer(pTarget)).FnExpr == int32(1); v3 {
|
|
v2 = (*(*TExprList_item)(unsafe.Pointer(pTarget + 8))).FpExpr
|
|
pTerm = v2
|
|
}
|
|
if v3 && libc.Int32FromUint8((*TExpr)(unsafe.Pointer(v2)).Fop) == int32(TK_COLUMN) && int32((*TExpr)(unsafe.Pointer(pTerm)).FiColumn) == -int32(1) {
|
|
/* The conflict-target is the rowid of the primary table */
|
|
goto _1
|
|
}
|
|
/* Initialize sCol[0..1] to be an expression parse tree for a
|
|
** single column of an index. The sCol[0] node will be the TK_COLLATE
|
|
** operator and sCol[1] will be the TK_COLUMN operator. Code below
|
|
** will populate the specific collation and column number values
|
|
** prior to comparing against the conflict-target expression.
|
|
*/
|
|
libc.Xmemset(tls, bp+56, 0, uint64(144))
|
|
(**(**[2]TExpr)(__ccgo_up(bp + 56)))[0].Fop = uint8(TK_COLLATE)
|
|
(**(**[2]TExpr)(__ccgo_up(bp + 56)))[0].FpLeft = bp + 56 + 1*72
|
|
(**(**[2]TExpr)(__ccgo_up(bp + 56)))[int32(1)].Fop = uint8(TK_COLUMN)
|
|
(**(**[2]TExpr)(__ccgo_up(bp + 56)))[int32(1)].FiTable = (*(*TSrcItem)(unsafe.Pointer(pTabList + 8))).FiCursor
|
|
/* Check for matches against other indexes */
|
|
pIdx = (*TTable)(unsafe.Pointer(pTab)).FpIndex
|
|
for {
|
|
if !(pIdx != 0) {
|
|
break
|
|
}
|
|
if !(libc.Int32FromUint8((*TIndex)(unsafe.Pointer(pIdx)).FonError) != libc.Int32FromInt32(OE_None)) {
|
|
goto _4
|
|
}
|
|
if (*TExprList)(unsafe.Pointer(pTarget)).FnExpr != libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnKeyCol) {
|
|
goto _4
|
|
}
|
|
if (*TIndex)(unsafe.Pointer(pIdx)).FpPartIdxWhere != 0 {
|
|
if (*TUpsert)(unsafe.Pointer(pUpsert)).FpUpsertTargetWhere == uintptr(0) {
|
|
goto _4
|
|
}
|
|
if _sqlite3ExprCompare(tls, pParse, (*TUpsert)(unsafe.Pointer(pUpsert)).FpUpsertTargetWhere, (*TIndex)(unsafe.Pointer(pIdx)).FpPartIdxWhere, iCursor) != 0 {
|
|
goto _4
|
|
}
|
|
}
|
|
nn = libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnKeyCol)
|
|
ii = 0
|
|
for {
|
|
if !(ii < nn) {
|
|
break
|
|
}
|
|
*(*uintptr)(unsafe.Pointer(bp + 56 + 8)) = **(**uintptr)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FazColl + uintptr(ii)*8))
|
|
if int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(ii)*2))) == -int32(2) {
|
|
pExpr = (*(*TExprList_item)(unsafe.Pointer((*TIndex)(unsafe.Pointer(pIdx)).FaColExpr + 8 + uintptr(ii)*32))).FpExpr
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) != int32(TK_COLLATE) {
|
|
(**(**[2]TExpr)(__ccgo_up(bp + 56)))[0].FpLeft = pExpr
|
|
pExpr = bp + 56
|
|
}
|
|
} else {
|
|
(**(**[2]TExpr)(__ccgo_up(bp + 56)))[0].FpLeft = bp + 56 + 1*72
|
|
(**(**[2]TExpr)(__ccgo_up(bp + 56)))[int32(1)].FiColumn = **(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(ii)*2))
|
|
pExpr = bp + 56
|
|
}
|
|
jj = 0
|
|
for {
|
|
if !(jj < nn) {
|
|
break
|
|
}
|
|
if _sqlite3ExprCompare(tls, uintptr(0), (*(*TExprList_item)(unsafe.Pointer(pTarget + 8 + uintptr(jj)*32))).FpExpr, pExpr, iCursor) < int32(2) {
|
|
break /* Column ii of the index matches column jj of target */
|
|
}
|
|
goto _6
|
|
_6:
|
|
;
|
|
jj = jj + 1
|
|
}
|
|
if jj >= nn {
|
|
/* The target contains no match for column jj of the index */
|
|
break
|
|
}
|
|
goto _5
|
|
_5:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
if ii < nn {
|
|
/* Column ii of the index did not match any term of the conflict target.
|
|
** Continue the search with the next index. */
|
|
goto _4
|
|
}
|
|
(*TUpsert)(unsafe.Pointer(pUpsert)).FpUpsertIdx = pIdx
|
|
if _sqlite3UpsertOfIndex(tls, pAll, pIdx) != pUpsert {
|
|
/* Really this should be an error. The isDup ON CONFLICT clause will
|
|
** never fire. But this problem was not discovered until three years
|
|
** after multi-CONFLICT upsert was added, and so we silently ignore
|
|
** the problem to prevent breaking applications that might actually
|
|
** have redundant ON CONFLICT clauses. */
|
|
(*TUpsert)(unsafe.Pointer(pUpsert)).FisDup = uint8(1)
|
|
}
|
|
break
|
|
goto _4
|
|
_4:
|
|
;
|
|
pIdx = (*TIndex)(unsafe.Pointer(pIdx)).FpNext
|
|
}
|
|
if (*TUpsert)(unsafe.Pointer(pUpsert)).FpUpsertIdx == uintptr(0) {
|
|
if nClause == 0 && (*TUpsert)(unsafe.Pointer(pUpsert)).FpNextUpsert == uintptr(0) {
|
|
(**(**[16]uint8)(__ccgo_up(bp + 200)))[0] = uint8(0)
|
|
} else {
|
|
Xsqlite3_snprintf(tls, int32(16), bp+200, __ccgo_ts+22680, libc.VaList(bp+224, nClause+int32(1)))
|
|
}
|
|
_sqlite3ErrorMsg(tls, pParse, __ccgo_ts+22684, libc.VaList(bp+224, bp+200))
|
|
return int32(SQLITE_ERROR)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pUpsert = (*TUpsert)(unsafe.Pointer(pUpsert)).FpNextUpsert
|
|
nClause = nClause + 1
|
|
}
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Generate bytecode that does an UPDATE as part of an upsert.
|
|
// **
|
|
// ** If pIdx is NULL, then the UNIQUE constraint that failed was the IPK.
|
|
// ** In this case parameter iCur is a cursor open on the table b-tree that
|
|
// ** currently points to the conflicting table row. Otherwise, if pIdx
|
|
// ** is not NULL, then pIdx is the constraint that failed and iCur is a
|
|
// ** cursor points to the conflicting row.
|
|
// */
|
|
func _sqlite3UpsertDoUpdate(tls *libc.TLS, pParse uintptr, pUpsert uintptr, pTab uintptr, pIdx uintptr, iCur int32) {
|
|
var db, pPk, pSrc, pTop, v uintptr
|
|
var i, iDataCur, iPk, iStorage, k, nPk, regRowid int32
|
|
_, _, _, _, _, _, _, _, _, _, _, _ = db, i, iDataCur, iPk, iStorage, k, nPk, pPk, pSrc, pTop, regRowid, v
|
|
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
pTop = pUpsert
|
|
iDataCur = (*TUpsert)(unsafe.Pointer(pUpsert)).FiDataCur
|
|
pUpsert = _sqlite3UpsertOfIndex(tls, pTop, pIdx)
|
|
if pIdx != 0 && iCur != iDataCur {
|
|
if (*TTable)(unsafe.Pointer(pTab)).FtabFlags&uint32(TF_WithoutRowid) == uint32(0) {
|
|
regRowid = _sqlite3GetTempReg(tls, pParse)
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_IdxRowid), iCur, regRowid)
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_SeekRowid), iDataCur, 0, regRowid)
|
|
_sqlite3ReleaseTempReg(tls, pParse, regRowid)
|
|
} else {
|
|
pPk = _sqlite3PrimaryKeyIndex(tls, pTab)
|
|
nPk = libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pPk)).FnKeyCol)
|
|
iPk = (*TParse)(unsafe.Pointer(pParse)).FnMem + int32(1)
|
|
**(**int32)(__ccgo_up(pParse + 60)) += nPk
|
|
i = 0
|
|
for {
|
|
if !(i < nPk) {
|
|
break
|
|
}
|
|
k = _sqlite3TableColumnToIndex(tls, pIdx, int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pPk)).FaiColumn + uintptr(i)*2))))
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Column), iCur, k, iPk+i)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
i = _sqlite3VdbeAddOp4Int(tls, v, int32(OP_Found), iDataCur, 0, iPk, nPk)
|
|
_sqlite3VdbeAddOp4(tls, v, int32(OP_Halt), int32(SQLITE_CORRUPT), int32(OE_Abort), 0, __ccgo_ts+13754, -int32(1))
|
|
_sqlite3MayAbort(tls, pParse)
|
|
_sqlite3VdbeJumpHere(tls, v, i)
|
|
}
|
|
}
|
|
/* pUpsert does not own pTop->pUpsertSrc - the outer INSERT statement does.
|
|
** So we have to make a copy before passing it down into sqlite3Update() */
|
|
pSrc = _sqlite3SrcListDup(tls, db, (*TUpsert)(unsafe.Pointer(pTop)).FpUpsertSrc, 0)
|
|
/* excluded.* columns of type REAL need to be converted to a hard real */
|
|
i = 0
|
|
for {
|
|
if !(i < int32((*TTable)(unsafe.Pointer(pTab)).FnCol)) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint8((**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(i)*16))).Faffinity) == int32(SQLITE_AFF_REAL) {
|
|
iStorage = (*TUpsert)(unsafe.Pointer(pTop)).FregData + int32(_sqlite3TableColumnToStorage(tls, pTab, int16(i)))
|
|
_sqlite3VdbeAddOp1(tls, v, int32(OP_RealAffinity), iStorage)
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_sqlite3Update(tls, pParse, pSrc, _sqlite3ExprListDup(tls, db, (*TUpsert)(unsafe.Pointer(pUpsert)).FpUpsertSet, 0), _sqlite3ExprDup(tls, db, (*TUpsert)(unsafe.Pointer(pUpsert)).FpUpsertWhere, 0), int32(OE_Abort), uintptr(0), uintptr(0), pUpsert)
|
|
}
|
|
|
|
/************** End of upsert.c **********************************************/
|
|
/************** Begin file vacuum.c ******************************************/
|
|
/*
|
|
** 2003 April 6
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** This file contains code used to implement the VACUUM command.
|
|
**
|
|
** Most of the code in this file may be omitted by defining the
|
|
** SQLITE_OMIT_VACUUM macro.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
/* #include "vdbeInt.h" */
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function returns a pointer to a nul-terminated string in memory
|
|
// ** obtained from sqlite3DbMalloc(). If sqlite3.nVdbeExec is 1, then the
|
|
// ** string contains a copy of zRawSql but with host parameters expanded to
|
|
// ** their current bindings. Or, if sqlite3.nVdbeExec is greater than 1,
|
|
// ** then the returned string holds a copy of zRawSql with "-- " prepended
|
|
// ** to each line of text.
|
|
// **
|
|
// ** If the SQLITE_TRACE_SIZE_LIMIT macro is defined to an integer, then
|
|
// ** then long strings and blobs are truncated to that many bytes. This
|
|
// ** can be used to prevent unreasonably large trace strings when dealing
|
|
// ** with large (multi-megabyte) strings and blobs.
|
|
// **
|
|
// ** The calling function is responsible for making sure the memory returned
|
|
// ** is eventually freed.
|
|
// **
|
|
// ** ALGORITHM: Scan the input string looking for host parameters in any of
|
|
// ** these forms: ?, ?N, $A, @A, :A. Take care to avoid text within
|
|
// ** string literals, quoted identifier names, and comments. For text forms,
|
|
// ** the host parameter index is found by scanning the prepared
|
|
// ** statement for the corresponding OP_Variable opcode. Once the host
|
|
// ** parameter index is known, locate the value in p->aVar[]. Then render
|
|
// ** the value as a literal in place of the host parameter name.
|
|
// */
|
|
func _sqlite3VdbeExpandSql(tls *libc.TLS, p uintptr, zRawSql uintptr) (r uintptr) {
|
|
bp := tls.Alloc(128)
|
|
defer tls.Free(128)
|
|
var db, pVar, zStart, v1 uintptr
|
|
var enc Tu8
|
|
var i, nOut, nOut1, nextIndex, v2 int32
|
|
var n Ti64
|
|
var _ /* idx at bp+0 */ int32
|
|
var _ /* nToken at bp+8 */ Ti64
|
|
var _ /* out at bp+16 */ TStrAccum
|
|
var _ /* utf8 at bp+48 */ TMem
|
|
_, _, _, _, _, _, _, _, _, _, _ = db, enc, i, n, nOut, nOut1, nextIndex, pVar, zStart, v1, v2 /* The database connection */
|
|
**(**int32)(__ccgo_up(bp)) = 0 /* Index of a host parameter */
|
|
nextIndex = int32(1) /* Used to convert UTF16 into UTF8 for display */
|
|
db = (*TVdbe)(unsafe.Pointer(p)).Fdb
|
|
_sqlite3StrAccumInit(tls, bp+16, uintptr(0), uintptr(0), 0, **(**int32)(__ccgo_up(db + 136)))
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FnVdbeExec > int32(1) {
|
|
for **(**uint8)(__ccgo_up(zRawSql)) != 0 {
|
|
zStart = zRawSql
|
|
for {
|
|
v1 = zRawSql
|
|
zRawSql = zRawSql + 1
|
|
if !(libc.Int32FromUint8(**(**uint8)(__ccgo_up(v1))) != int32('\n') && **(**uint8)(__ccgo_up(zRawSql)) != 0) {
|
|
break
|
|
}
|
|
}
|
|
Xsqlite3_str_append(tls, bp+16, __ccgo_ts+5741, int32(3))
|
|
Xsqlite3_str_append(tls, bp+16, zStart, int32(int64(zRawSql)-int64(zStart)))
|
|
}
|
|
} else {
|
|
if int32((*TVdbe)(unsafe.Pointer(p)).FnVar) == 0 {
|
|
Xsqlite3_str_append(tls, bp+16, zRawSql, _sqlite3Strlen30(tls, zRawSql))
|
|
} else {
|
|
for **(**uint8)(__ccgo_up(zRawSql)) != 0 {
|
|
n = _findNextHostParameter(tls, zRawSql, bp+8)
|
|
Xsqlite3_str_append(tls, bp+16, zRawSql, int32(n))
|
|
zRawSql = zRawSql + uintptr(n)
|
|
if **(**Ti64)(__ccgo_up(bp + 8)) == 0 {
|
|
break
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zRawSql))) == int32('?') {
|
|
if **(**Ti64)(__ccgo_up(bp + 8)) > int64(1) {
|
|
_sqlite3GetInt32(tls, zRawSql+1, bp)
|
|
} else {
|
|
**(**int32)(__ccgo_up(bp)) = nextIndex
|
|
}
|
|
} else {
|
|
**(**int32)(__ccgo_up(bp)) = _sqlite3VdbeParameterIndex(tls, p, zRawSql, int32(**(**Ti64)(__ccgo_up(bp + 8))))
|
|
}
|
|
zRawSql = zRawSql + uintptr(**(**Ti64)(__ccgo_up(bp + 8)))
|
|
if **(**int32)(__ccgo_up(bp))+int32(1) > nextIndex {
|
|
v2 = **(**int32)(__ccgo_up(bp)) + int32(1)
|
|
} else {
|
|
v2 = nextIndex
|
|
}
|
|
nextIndex = v2
|
|
pVar = (*TVdbe)(unsafe.Pointer(p)).FaVar + uintptr(**(**int32)(__ccgo_up(bp))-int32(1))*56
|
|
if libc.Int32FromUint16((*TMem)(unsafe.Pointer(pVar)).Fflags)&int32(MEM_Null) != 0 {
|
|
Xsqlite3_str_append(tls, bp+16, __ccgo_ts+1705, int32(4))
|
|
} else {
|
|
if libc.Int32FromUint16((*TMem)(unsafe.Pointer(pVar)).Fflags)&(libc.Int32FromInt32(MEM_Int)|libc.Int32FromInt32(MEM_IntReal)) != 0 {
|
|
Xsqlite3_str_appendf(tls, bp+16, __ccgo_ts+1465, libc.VaList(bp+112, *(*Ti64)(unsafe.Pointer(pVar))))
|
|
} else {
|
|
if libc.Int32FromUint16((*TMem)(unsafe.Pointer(pVar)).Fflags)&int32(MEM_Real) != 0 {
|
|
Xsqlite3_str_appendf(tls, bp+16, __ccgo_ts+5745, libc.VaList(bp+112, *(*float64)(unsafe.Pointer(pVar))))
|
|
} else {
|
|
if libc.Int32FromUint16((*TMem)(unsafe.Pointer(pVar)).Fflags)&int32(MEM_Str) != 0 { /* Number of bytes of the string text to include in output */
|
|
enc = (*Tsqlite3)(unsafe.Pointer(db)).Fenc
|
|
if libc.Int32FromUint8(enc) != int32(SQLITE_UTF8) {
|
|
libc.Xmemset(tls, bp+48, 0, uint64(56))
|
|
(**(**TMem)(__ccgo_up(bp + 48))).Fdb = db
|
|
_sqlite3VdbeMemSetStr(tls, bp+48, (*TMem)(unsafe.Pointer(pVar)).Fz, int64((*TMem)(unsafe.Pointer(pVar)).Fn), enc, libc.UintptrFromInt32(0))
|
|
if int32(SQLITE_NOMEM) == _sqlite3VdbeChangeEncoding(tls, bp+48, int32(SQLITE_UTF8)) {
|
|
(**(**TStrAccum)(__ccgo_up(bp + 16))).FaccError = uint8(SQLITE_NOMEM)
|
|
(**(**TStrAccum)(__ccgo_up(bp + 16))).FnAlloc = uint32(0)
|
|
}
|
|
pVar = bp + 48
|
|
}
|
|
nOut = (*TMem)(unsafe.Pointer(pVar)).Fn
|
|
Xsqlite3_str_appendf(tls, bp+16, __ccgo_ts+5752, libc.VaList(bp+112, nOut, (*TMem)(unsafe.Pointer(pVar)).Fz))
|
|
if libc.Int32FromUint8(enc) != int32(SQLITE_UTF8) {
|
|
_sqlite3VdbeMemRelease(tls, bp+48)
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint16((*TMem)(unsafe.Pointer(pVar)).Fflags)&int32(MEM_Zero) != 0 {
|
|
Xsqlite3_str_appendf(tls, bp+16, __ccgo_ts+5759, libc.VaList(bp+112, *(*int32)(unsafe.Pointer(&(*TMem)(unsafe.Pointer(pVar)).Fu))))
|
|
} else { /* Number of bytes of the blob to include in output */
|
|
Xsqlite3_str_append(tls, bp+16, __ccgo_ts+5772, int32(2))
|
|
nOut1 = (*TMem)(unsafe.Pointer(pVar)).Fn
|
|
i = 0
|
|
for {
|
|
if !(i < nOut1) {
|
|
break
|
|
}
|
|
Xsqlite3_str_appendf(tls, bp+16, __ccgo_ts+5775, libc.VaList(bp+112, libc.Int32FromUint8(**(**uint8)(__ccgo_up((*TMem)(unsafe.Pointer(pVar)).Fz + uintptr(i))))&int32(0xff)))
|
|
goto _3
|
|
_3:
|
|
;
|
|
i = i + 1
|
|
}
|
|
Xsqlite3_str_append(tls, bp+16, __ccgo_ts+5780, int32(1))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (**(**TStrAccum)(__ccgo_up(bp + 16))).FaccError != 0 {
|
|
Xsqlite3_str_reset(tls, bp+16)
|
|
}
|
|
return _sqlite3StrAccumFinish(tls, bp+16)
|
|
}
|
|
|
|
/************** End of vdbetrace.c *******************************************/
|
|
/************** Begin file vdbe.c ********************************************/
|
|
/*
|
|
** 2001 September 15
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** The code in this file implements the function that runs the
|
|
** bytecode of a prepared statement.
|
|
**
|
|
** Various scripts scan this source file in order to generate HTML
|
|
** documentation, headers files, or other derived files. The formatting
|
|
** of the code in this file is, therefore, important. See other comments
|
|
** in this file for details. If in doubt, do not deviate from existing
|
|
** commenting and indentation practices when changing or adding code.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
/* #include "vdbeInt.h" */
|
|
|
|
/*
|
|
** High-resolution hardware timer used for debugging and testing only.
|
|
*/
|
|
|
|
/*
|
|
** Invoke this macro on memory cells just prior to changing the
|
|
** value of the cell. This macro verifies that shallow copies are
|
|
** not misused. A shallow copy of a string or blob just copies a
|
|
** pointer to the string or blob, not the content. If the original
|
|
** is changed while the copy is still in use, the string or blob might
|
|
** be changed out from under the copy. This macro verifies that nothing
|
|
** like that ever happens.
|
|
*/
|
|
|
|
/*
|
|
** The following global variable is incremented every time a cursor
|
|
** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes. The test
|
|
** procedures use this information to make sure that indices are
|
|
** working correctly. This variable has no function other than to
|
|
** help verify the correct operation of the library.
|
|
*/
|
|
|
|
/*
|
|
** When this global variable is positive, it gets decremented once before
|
|
** each instruction in the VDBE. When it reaches zero, the u1.isInterrupted
|
|
** field of the sqlite3 structure is set in order to simulate an interrupt.
|
|
**
|
|
** This facility is used for testing purposes only. It does not function
|
|
** in an ordinary build.
|
|
*/
|
|
|
|
/*
|
|
** The next global variable is incremented each type the OP_Sort opcode
|
|
** is executed. The test procedures use this information to make sure that
|
|
** sorting is occurring or not occurring at appropriate times. This variable
|
|
** has no function other than to help verify the correct operation of the
|
|
** library.
|
|
*/
|
|
|
|
/*
|
|
** The next global variable records the size of the largest MEM_Blob
|
|
** or MEM_Str that has been used by a VDBE opcode. The test procedures
|
|
** use this information to make sure that the zero-blob functionality
|
|
** is working correctly. This variable has no function other than to
|
|
** help verify the correct operation of the library.
|
|
*/
|
|
|
|
/*
|
|
** This macro evaluates to true if either the update hook or the preupdate
|
|
** hook are enabled for database connect DB.
|
|
*/
|
|
|
|
/*
|
|
** The next global variable is incremented each time the OP_Found opcode
|
|
** is executed. This is used to test whether or not the foreign key
|
|
** operation implemented using OP_FkIsZero is working. This variable
|
|
** has no function other than to help verify the correct operation of the
|
|
** library.
|
|
*/
|
|
|
|
/*
|
|
** Test a register to see if it exceeds the current maximum blob size.
|
|
** If it does, record the new maximum blob size.
|
|
*/
|
|
|
|
/*
|
|
** Invoke the VDBE coverage callback, if that callback is defined. This
|
|
** feature is used for test suite validation only and does not appear an
|
|
** production builds.
|
|
**
|
|
** M is the type of branch. I is the direction taken for this instance of
|
|
** the branch.
|
|
**
|
|
** M: 2 - two-way branch (I=0: fall-thru 1: jump )
|
|
** 3 - two-way + NULL (I=0: fall-thru 1: jump 2: NULL )
|
|
** 4 - OP_Jump (I=0: jump p1 1: jump p2 2: jump p3)
|
|
**
|
|
** In other words, if M is 2, then I is either 0 (for fall-through) or
|
|
** 1 (for when the branch is taken). If M is 3, the I is 0 for an
|
|
** ordinary fall-through, I is 1 if the branch was taken, and I is 2
|
|
** if the result of comparison is NULL. For M=3, I=2 the jump may or
|
|
** may not be taken, depending on the SQLITE_JUMPIFNULL flags in p5.
|
|
** When M is 4, that means that an OP_Jump is being run. I is 0, 1, or 2
|
|
** depending on if the operands are less than, equal, or greater than.
|
|
**
|
|
** iSrcLine is the source code line (from the __LINE__ macro) that
|
|
** generated the VDBE instruction combined with flag bits. The source
|
|
** code line number is in the lower 24 bits of iSrcLine and the upper
|
|
** 8 bytes are flags. The lower three bits of the flags indicate
|
|
** values for I that should never occur. For example, if the branch is
|
|
** always taken, the flags should be 0x05 since the fall-through and
|
|
** alternate branch are never taken. If a branch is never taken then
|
|
** flags should be 0x06 since only the fall-through approach is allowed.
|
|
**
|
|
** Bit 0x08 of the flags indicates an OP_Jump opcode that is only
|
|
** interested in equal or not-equal. In other words, I==0 and I==2
|
|
** should be treated as equivalent
|
|
**
|
|
** Since only a line number is retained, not the filename, this macro
|
|
** only works for amalgamation builds. But that is ok, since these macros
|
|
** should be no-ops except for special builds used to measure test coverage.
|
|
*/
|
|
|
|
/*
|
|
** An ephemeral string value (signified by the MEM_Ephem flag) contains
|
|
** a pointer to a dynamically allocated string where some other entity
|
|
** is responsible for deallocating that string. Because the register
|
|
** does not control the string, it might be deleted without the register
|
|
** knowing it.
|
|
**
|
|
** This routine converts an ephemeral string into a dynamically allocated
|
|
** string that the register itself controls. In other words, it
|
|
** converts an MEM_Ephem string into a string with P.z==P.zMalloc.
|
|
*/
|
|
|
|
/* Return true if the cursor was opened using the OP_OpenSorter opcode. */
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Send a "statement aborts" message to the error log.
|
|
// */
|
|
func _sqlite3VdbeLogAbort(tls *libc.TLS, p uintptr, rc int32, pOp uintptr, aOp uintptr) {
|
|
bp := tls.Alloc(144)
|
|
defer tls.Free(144)
|
|
var pc int32
|
|
var zPrefix, zSql uintptr
|
|
var _ /* zXtra at bp+0 */ [100]uint8
|
|
_, _, _ = pc, zPrefix, zSql
|
|
zSql = (*TVdbe)(unsafe.Pointer(p)).FzSql /* Original SQL text */
|
|
zPrefix = __ccgo_ts + 1704 /* Buffer space to store zPrefix */
|
|
if (*TVdbe)(unsafe.Pointer(p)).FpFrame != 0 {
|
|
if *(*uintptr)(unsafe.Pointer(aOp + 16)) != uintptr(0) {
|
|
Xsqlite3_snprintf(tls, int32(100), bp, __ccgo_ts+5782, libc.VaList(bp+112, *(*uintptr)(unsafe.Pointer(aOp + 16))+uintptr(3)))
|
|
zPrefix = bp
|
|
} else {
|
|
zPrefix = __ccgo_ts + 5792
|
|
}
|
|
}
|
|
pc = int32((int64(pOp) - int64(aOp)) / 24)
|
|
Xsqlite3_log(tls, rc, __ccgo_ts+5815, libc.VaList(bp+112, pc, (*TVdbe)(unsafe.Pointer(p)).FzErrMsg, zPrefix, zSql))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Add a single OP_Explain opcode that describes a Bloom filter.
|
|
// **
|
|
// ** Or if not processing EXPLAIN QUERY PLAN and not in a SQLITE_DEBUG and/or
|
|
// ** SQLITE_ENABLE_STMT_SCANSTATUS build, then OP_Explain opcodes are not
|
|
// ** required and this routine is a no-op.
|
|
// **
|
|
// ** If an OP_Explain opcode is added to the VM, its address is returned.
|
|
// ** Otherwise, if no OP_Explain is coded, zero is returned.
|
|
// */
|
|
func _sqlite3WhereExplainBloomFilter(tls *libc.TLS, pParse uintptr, pWInfo uintptr, pLevel uintptr) (r int32) {
|
|
bp := tls.Alloc(160)
|
|
defer tls.Free(160)
|
|
var db, pItem, pLoop, pTab, v, z, zMsg uintptr
|
|
var i, ret int32
|
|
var _ /* str at bp+0 */ TStrAccum
|
|
var _ /* zBuf at bp+32 */ [100]uint8
|
|
_, _, _, _, _, _, _, _, _ = db, i, pItem, pLoop, pTab, ret, v, z, zMsg
|
|
ret = 0
|
|
pItem = (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpTabList + 8 + uintptr((*TWhereLevel)(unsafe.Pointer(pLevel)).FiFrom)*80
|
|
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe /* VM being constructed */
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb /* Initial space for EQP output string */
|
|
_sqlite3StrAccumInit(tls, bp, db, bp+32, int32(100), int32(SQLITE_MAX_LENGTH))
|
|
(**(**TStrAccum)(__ccgo_up(bp))).FprintfFlags = uint8(SQLITE_PRINTF_INTERNAL)
|
|
Xsqlite3_str_appendf(tls, bp, __ccgo_ts+23895, libc.VaList(bp+144, pItem))
|
|
pLoop = (*TWhereLevel)(unsafe.Pointer(pLevel)).FpWLoop
|
|
if (*TWhereLoop)(unsafe.Pointer(pLoop)).FwsFlags&uint32(WHERE_IPK) != 0 {
|
|
pTab = (*TSrcItem)(unsafe.Pointer(pItem)).FpSTab
|
|
if int32((*TTable)(unsafe.Pointer(pTab)).FiPKey) >= 0 {
|
|
Xsqlite3_str_appendf(tls, bp, __ccgo_ts+23664, libc.VaList(bp+144, (**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr((*TTable)(unsafe.Pointer(pTab)).FiPKey)*16))).FzCnName))
|
|
} else {
|
|
Xsqlite3_str_appendf(tls, bp, __ccgo_ts+23916, 0)
|
|
}
|
|
} else {
|
|
i = libc.Int32FromUint16((*TWhereLoop)(unsafe.Pointer(pLoop)).FnSkip)
|
|
for {
|
|
if !(i < libc.Int32FromUint16((*(*struct {
|
|
FnEq Tu16
|
|
FnBtm Tu16
|
|
FnTop Tu16
|
|
FnDistinctCol Tu16
|
|
FpIndex uintptr
|
|
FpOrderBy uintptr
|
|
})(unsafe.Pointer(pLoop + 24))).FnEq)) {
|
|
break
|
|
}
|
|
z = _explainIndexColumnName(tls, (*(*struct {
|
|
FnEq Tu16
|
|
FnBtm Tu16
|
|
FnTop Tu16
|
|
FnDistinctCol Tu16
|
|
FpIndex uintptr
|
|
FpOrderBy uintptr
|
|
})(unsafe.Pointer(pLoop + 24))).FpIndex, i)
|
|
if i > libc.Int32FromUint16((*TWhereLoop)(unsafe.Pointer(pLoop)).FnSkip) {
|
|
Xsqlite3_str_append(tls, bp, __ccgo_ts+23653, int32(5))
|
|
}
|
|
Xsqlite3_str_appendf(tls, bp, __ccgo_ts+23664, libc.VaList(bp+144, z))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
Xsqlite3_str_append(tls, bp, __ccgo_ts+5285, int32(1))
|
|
zMsg = _sqlite3StrAccumFinish(tls, bp)
|
|
ret = _sqlite3VdbeAddOp4(tls, v, int32(OP_Explain), _sqlite3VdbeCurrentAddr(tls, v), (*TParse)(unsafe.Pointer(pParse)).FaddrExplain, 0, zMsg, -int32(7))
|
|
return ret
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** timediff(DATE1, DATE2)
|
|
// **
|
|
// ** Return the amount of time that must be added to DATE2 in order to
|
|
// ** convert it into DATE2. The time difference format is:
|
|
// **
|
|
// ** +YYYY-MM-DD HH:MM:SS.SSS
|
|
// **
|
|
// ** The initial "+" becomes "-" if DATE1 occurs before DATE2. For
|
|
// ** date/time values A and B, the following invariant should hold:
|
|
// **
|
|
// ** datetime(A) == (datetime(B, timediff(A,B))
|
|
// **
|
|
// ** Both DATE arguments must be either a julian day number, or an
|
|
// ** ISO-8601 string. The unix timestamps are not supported by this
|
|
// ** routine.
|
|
// */
|
|
func _timediffFunc(tls *libc.TLS, context uintptr, NotUsed1 int32, argv uintptr) {
|
|
bp := tls.Alloc(192)
|
|
defer tls.Free(192)
|
|
var M, Y int32
|
|
var sign uint8
|
|
var v1 uintptr
|
|
var _ /* d1 at bp+0 */ TDateTime
|
|
var _ /* d2 at bp+48 */ TDateTime
|
|
var _ /* sRes at bp+96 */ Tsqlite3_str
|
|
_, _, _, _ = M, Y, sign, v1
|
|
_ = NotUsed1
|
|
if _isDate(tls, context, int32(1), argv, bp) != 0 {
|
|
return
|
|
}
|
|
if _isDate(tls, context, int32(1), argv+1*8, bp+48) != 0 {
|
|
return
|
|
}
|
|
_computeYMD_HMS(tls, bp)
|
|
_computeYMD_HMS(tls, bp+48)
|
|
if (**(**TDateTime)(__ccgo_up(bp))).FiJD >= (**(**TDateTime)(__ccgo_up(bp + 48))).FiJD {
|
|
sign = uint8('+')
|
|
Y = (**(**TDateTime)(__ccgo_up(bp))).FY - (**(**TDateTime)(__ccgo_up(bp + 48))).FY
|
|
if Y != 0 {
|
|
(**(**TDateTime)(__ccgo_up(bp + 48))).FY = (**(**TDateTime)(__ccgo_up(bp))).FY
|
|
(**(**TDateTime)(__ccgo_up(bp + 48))).FvalidJD = uint8(0)
|
|
_computeJD(tls, bp+48)
|
|
}
|
|
M = (**(**TDateTime)(__ccgo_up(bp))).FM - (**(**TDateTime)(__ccgo_up(bp + 48))).FM
|
|
if M < 0 {
|
|
Y = Y - 1
|
|
M = M + int32(12)
|
|
}
|
|
if M != 0 {
|
|
(**(**TDateTime)(__ccgo_up(bp + 48))).FM = (**(**TDateTime)(__ccgo_up(bp))).FM
|
|
(**(**TDateTime)(__ccgo_up(bp + 48))).FvalidJD = uint8(0)
|
|
_computeJD(tls, bp+48)
|
|
}
|
|
for (**(**TDateTime)(__ccgo_up(bp))).FiJD < (**(**TDateTime)(__ccgo_up(bp + 48))).FiJD {
|
|
M = M - 1
|
|
if M < 0 {
|
|
M = int32(11)
|
|
Y = Y - 1
|
|
}
|
|
(**(**TDateTime)(__ccgo_up(bp + 48))).FM = (**(**TDateTime)(__ccgo_up(bp + 48))).FM - 1
|
|
if (**(**TDateTime)(__ccgo_up(bp + 48))).FM < int32(1) {
|
|
(**(**TDateTime)(__ccgo_up(bp + 48))).FM = int32(12)
|
|
(**(**TDateTime)(__ccgo_up(bp + 48))).FY = (**(**TDateTime)(__ccgo_up(bp + 48))).FY - 1
|
|
}
|
|
(**(**TDateTime)(__ccgo_up(bp + 48))).FvalidJD = uint8(0)
|
|
_computeJD(tls, bp+48)
|
|
}
|
|
(**(**TDateTime)(__ccgo_up(bp))).FiJD -= (**(**TDateTime)(__ccgo_up(bp + 48))).FiJD
|
|
v1 = bp
|
|
*(*Tsqlite3_int64)(unsafe.Pointer(v1)) = Tsqlite3_int64(uint64(*(*Tsqlite3_int64)(unsafe.Pointer(v1))) + libc.Uint64FromInt32(1486995408)*libc.Uint64FromInt32(100000))
|
|
} else { /* d1<d2 */
|
|
sign = uint8('-')
|
|
Y = (**(**TDateTime)(__ccgo_up(bp + 48))).FY - (**(**TDateTime)(__ccgo_up(bp))).FY
|
|
if Y != 0 {
|
|
(**(**TDateTime)(__ccgo_up(bp + 48))).FY = (**(**TDateTime)(__ccgo_up(bp))).FY
|
|
(**(**TDateTime)(__ccgo_up(bp + 48))).FvalidJD = uint8(0)
|
|
_computeJD(tls, bp+48)
|
|
}
|
|
M = (**(**TDateTime)(__ccgo_up(bp + 48))).FM - (**(**TDateTime)(__ccgo_up(bp))).FM
|
|
if M < 0 {
|
|
Y = Y - 1
|
|
M = M + int32(12)
|
|
}
|
|
if M != 0 {
|
|
(**(**TDateTime)(__ccgo_up(bp + 48))).FM = (**(**TDateTime)(__ccgo_up(bp))).FM
|
|
(**(**TDateTime)(__ccgo_up(bp + 48))).FvalidJD = uint8(0)
|
|
_computeJD(tls, bp+48)
|
|
}
|
|
for (**(**TDateTime)(__ccgo_up(bp))).FiJD > (**(**TDateTime)(__ccgo_up(bp + 48))).FiJD {
|
|
M = M - 1
|
|
if M < 0 {
|
|
M = int32(11)
|
|
Y = Y - 1
|
|
}
|
|
(**(**TDateTime)(__ccgo_up(bp + 48))).FM = (**(**TDateTime)(__ccgo_up(bp + 48))).FM + 1
|
|
if (**(**TDateTime)(__ccgo_up(bp + 48))).FM > int32(12) {
|
|
(**(**TDateTime)(__ccgo_up(bp + 48))).FM = int32(1)
|
|
(**(**TDateTime)(__ccgo_up(bp + 48))).FY = (**(**TDateTime)(__ccgo_up(bp + 48))).FY + 1
|
|
}
|
|
(**(**TDateTime)(__ccgo_up(bp + 48))).FvalidJD = uint8(0)
|
|
_computeJD(tls, bp+48)
|
|
}
|
|
(**(**TDateTime)(__ccgo_up(bp))).FiJD = (**(**TDateTime)(__ccgo_up(bp + 48))).FiJD - (**(**TDateTime)(__ccgo_up(bp))).FiJD
|
|
v1 = bp
|
|
*(*Tsqlite3_int64)(unsafe.Pointer(v1)) = Tsqlite3_int64(uint64(*(*Tsqlite3_int64)(unsafe.Pointer(v1))) + libc.Uint64FromInt32(1486995408)*libc.Uint64FromInt32(100000))
|
|
}
|
|
_clearYMD_HMS_TZ(tls, bp)
|
|
_computeYMD_HMS(tls, bp)
|
|
_sqlite3StrAccumInit(tls, bp+96, uintptr(0), uintptr(0), 0, int32(100))
|
|
Xsqlite3_str_appendf(tls, bp+96, __ccgo_ts+1485, libc.VaList(bp+136, libc.Int32FromUint8(sign), Y, M, (**(**TDateTime)(__ccgo_up(bp))).FD-int32(1), (**(**TDateTime)(__ccgo_up(bp))).Fh, (**(**TDateTime)(__ccgo_up(bp))).Fm, (**(**TDateTime)(__ccgo_up(bp))).Fs))
|
|
_sqlite3ResultStrAccum(tls, context, bp+96)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of the UNISTR() function.
|
|
// **
|
|
// ** This is intended to be a work-alike of the UNISTR() function in
|
|
// ** PostgreSQL. Quoting from the PG documentation (PostgreSQL 17 -
|
|
// ** scraped on 2025-02-22):
|
|
// **
|
|
// ** Evaluate escaped Unicode characters in the argument. Unicode
|
|
// ** characters can be specified as \XXXX (4 hexadecimal digits),
|
|
// ** \+XXXXXX (6 hexadecimal digits), \uXXXX (4 hexadecimal digits),
|
|
// ** or \UXXXXXXXX (8 hexadecimal digits). To specify a backslash,
|
|
// ** write two backslashes. All other characters are taken literally.
|
|
// */
|
|
func _unistrFunc(tls *libc.TLS, context uintptr, argc int32, argv uintptr) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var i, j, n, nIn, v1 int32
|
|
var z, zIn, zOut uintptr
|
|
var _ /* v at bp+0 */ Tu32
|
|
_, _, _, _, _, _, _, _ = i, j, n, nIn, z, zIn, zOut, v1
|
|
_ = argc
|
|
zIn = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
if zIn == uintptr(0) {
|
|
return
|
|
}
|
|
nIn = Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
zOut = Xsqlite3_malloc64(tls, libc.Uint64FromInt32(nIn+int32(1)))
|
|
if zOut == uintptr(0) {
|
|
Xsqlite3_result_error_nomem(tls, context)
|
|
return
|
|
}
|
|
v1 = libc.Int32FromInt32(0)
|
|
j = v1
|
|
i = v1
|
|
for i < nIn {
|
|
z = libc.Xstrchr(tls, zIn+uintptr(i), int32('\\'))
|
|
if z == uintptr(0) {
|
|
n = nIn - i
|
|
libc.Xmemmove(tls, zOut+uintptr(j), zIn+uintptr(i), libc.Uint64FromInt32(n))
|
|
j = j + n
|
|
break
|
|
}
|
|
n = int32(int64(z) - t__predefined_ptrdiff_t(zIn+uintptr(i)))
|
|
if n > 0 {
|
|
libc.Xmemmove(tls, zOut+uintptr(j), zIn+uintptr(i), libc.Uint64FromInt32(n))
|
|
j = j + n
|
|
i = i + n
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn + uintptr(i+int32(1))))) == int32('\\') {
|
|
i = i + int32(2)
|
|
v1 = j
|
|
j = j + 1
|
|
**(**uint8)(__ccgo_up(zOut + uintptr(v1))) = uint8('\\')
|
|
} else {
|
|
if libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(zIn + uintptr(i+int32(1)))))])&int32(0x08) != 0 {
|
|
if !(_isNHex(tls, zIn+uintptr(i+int32(1)), int32(4), bp) != 0) {
|
|
goto unistr_error
|
|
}
|
|
i = i + int32(5)
|
|
j = j + _sqlite3AppendOneUtf8Character(tls, zOut+uintptr(j), **(**Tu32)(__ccgo_up(bp)))
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn + uintptr(i+int32(1))))) == int32('+') {
|
|
if !(_isNHex(tls, zIn+uintptr(i+int32(2)), int32(6), bp) != 0) {
|
|
goto unistr_error
|
|
}
|
|
i = i + int32(8)
|
|
j = j + _sqlite3AppendOneUtf8Character(tls, zOut+uintptr(j), **(**Tu32)(__ccgo_up(bp)))
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn + uintptr(i+int32(1))))) == int32('u') {
|
|
if !(_isNHex(tls, zIn+uintptr(i+int32(2)), int32(4), bp) != 0) {
|
|
goto unistr_error
|
|
}
|
|
i = i + int32(6)
|
|
j = j + _sqlite3AppendOneUtf8Character(tls, zOut+uintptr(j), **(**Tu32)(__ccgo_up(bp)))
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn + uintptr(i+int32(1))))) == int32('U') {
|
|
if !(_isNHex(tls, zIn+uintptr(i+int32(2)), int32(8), bp) != 0) {
|
|
goto unistr_error
|
|
}
|
|
i = i + int32(10)
|
|
j = j + _sqlite3AppendOneUtf8Character(tls, zOut+uintptr(j), **(**Tu32)(__ccgo_up(bp)))
|
|
} else {
|
|
goto unistr_error
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
**(**uint8)(__ccgo_up(zOut + uintptr(j))) = uint8(0)
|
|
Xsqlite3_result_text64(tls, context, zOut, libc.Uint64FromInt32(j), __ccgo_fp(Xsqlite3_free), uint8(SQLITE_UTF8_ZT))
|
|
return
|
|
goto unistr_error
|
|
unistr_error:
|
|
;
|
|
Xsqlite3_free(tls, zOut)
|
|
Xsqlite3_result_error(tls, context, __ccgo_ts+16599, -int32(1))
|
|
return
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Turn a relative pathname into a full pathname. The relative path
|
|
// ** is stored as a nul-terminated string in the buffer pointed to by
|
|
// ** zPath.
|
|
// **
|
|
// ** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes
|
|
// ** (in this case, MAX_PATHNAME bytes). The full-path is written to
|
|
// ** this buffer before returning.
|
|
// */
|
|
func _unixFullPathname(tls *libc.TLS, pVfs uintptr, zPath uintptr, nOut int32, zOut uintptr) (r int32) {
|
|
bp := tls.Alloc(4128)
|
|
defer tls.Free(4128)
|
|
var _ /* path at bp+0 */ TDbPath
|
|
var _ /* zPwd at bp+24 */ [4098]uint8
|
|
_ = pVfs
|
|
(**(**TDbPath)(__ccgo_up(bp))).Frc = 0
|
|
(**(**TDbPath)(__ccgo_up(bp))).FnUsed = 0
|
|
(**(**TDbPath)(__ccgo_up(bp))).FnSymlink = 0
|
|
(**(**TDbPath)(__ccgo_up(bp))).FnOut = nOut
|
|
(**(**TDbPath)(__ccgo_up(bp))).FzOut = zOut
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath))) != int32('/') {
|
|
if (*(*func(*libc.TLS, uintptr, Tsize_t) uintptr)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(3)].FpCurrent})))(tls, bp+24, libc.Uint64FromInt64(4098)-libc.Uint64FromInt32(2)) == uintptr(0) {
|
|
return _unixLogErrorAtLine(tls, _sqlite3CantopenError(tls, int32(47366)), __ccgo_ts+3560, zPath, int32(47366))
|
|
}
|
|
_appendAllPathElements(tls, bp, bp+24)
|
|
}
|
|
_appendAllPathElements(tls, bp, zPath)
|
|
**(**uint8)(__ccgo_up(zOut + uintptr((**(**TDbPath)(__ccgo_up(bp))).FnUsed))) = uint8(0)
|
|
if (**(**TDbPath)(__ccgo_up(bp))).Frc != 0 || (**(**TDbPath)(__ccgo_up(bp))).FnUsed < int32(2) {
|
|
return _sqlite3CantopenError(tls, int32(47372))
|
|
}
|
|
if (**(**TDbPath)(__ccgo_up(bp))).FnSymlink != 0 {
|
|
return libc.Int32FromInt32(SQLITE_OK) | libc.Int32FromInt32(2)<<libc.Int32FromInt32(8)
|
|
}
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Open the file zPath.
|
|
// **
|
|
// ** Previously, the SQLite OS layer used three functions in place of this
|
|
// ** one:
|
|
// **
|
|
// ** sqlite3OsOpenReadWrite();
|
|
// ** sqlite3OsOpenReadOnly();
|
|
// ** sqlite3OsOpenExclusive();
|
|
// **
|
|
// ** These calls correspond to the following combinations of flags:
|
|
// **
|
|
// ** ReadWrite() -> (READWRITE | CREATE)
|
|
// ** ReadOnly() -> (READONLY)
|
|
// ** OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE)
|
|
// **
|
|
// ** The old OpenExclusive() accepted a boolean argument - "delFlag". If
|
|
// ** true, the file was configured to be automatically deleted when the
|
|
// ** file handle closed. To achieve the same effect using this new
|
|
// ** interface, add the DELETEONCLOSE flag to those specified above for
|
|
// ** OpenExclusive().
|
|
// */
|
|
func _unixOpen(tls *libc.TLS, pVfs uintptr, zPath uintptr, pFile uintptr, flags int32, pOutFlags uintptr) (r int32) {
|
|
bp := tls.Alloc(528)
|
|
defer tls.Free(528)
|
|
var ctrlFlags, eType, fd, isCreate, isDelete, isExclusive, isNewJrnl, isReadWrite, isReadonly, noLock, openFlags, rc, rc2 int32
|
|
var p, pReadonly, pUnused, zName uintptr
|
|
var _ /* gid at bp+524 */ Tgid_t
|
|
var _ /* openMode at bp+516 */ Tmode_t
|
|
var _ /* uid at bp+520 */ Tuid_t
|
|
var _ /* zTmpname at bp+0 */ [514]uint8
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = ctrlFlags, eType, fd, isCreate, isDelete, isExclusive, isNewJrnl, isReadWrite, isReadonly, noLock, openFlags, p, pReadonly, pUnused, rc, rc2, zName
|
|
p = pFile
|
|
fd = -int32(1) /* File descriptor returned by open() */
|
|
openFlags = 0 /* Flags to pass to open() */
|
|
eType = flags & int32(0x0FFF00) /* True to omit locking primitives */
|
|
rc = SQLITE_OK /* Function Return Code */
|
|
ctrlFlags = 0 /* UNIXFILE_* flags */
|
|
isExclusive = flags & int32(SQLITE_OPEN_EXCLUSIVE)
|
|
isDelete = flags & int32(SQLITE_OPEN_DELETEONCLOSE)
|
|
isCreate = flags & int32(SQLITE_OPEN_CREATE)
|
|
isReadonly = flags & int32(SQLITE_OPEN_READONLY)
|
|
isReadWrite = flags & int32(SQLITE_OPEN_READWRITE)
|
|
/* If creating a super- or main-file journal, this function will open
|
|
** a file-descriptor on the directory too. The first time unixSync()
|
|
** is called the directory file descriptor will be fsync()ed and close()d.
|
|
*/
|
|
isNewJrnl = libc.BoolInt32(isCreate != 0 && (eType == int32(SQLITE_OPEN_SUPER_JOURNAL) || eType == int32(SQLITE_OPEN_MAIN_JOURNAL) || eType == int32(SQLITE_OPEN_WAL)))
|
|
zName = zPath
|
|
/* Check the following statements are true:
|
|
**
|
|
** (a) Exactly one of the READWRITE and READONLY flags must be set, and
|
|
** (b) if CREATE is set, then READWRITE must also be set, and
|
|
** (c) if EXCLUSIVE is set, then CREATE must also be set.
|
|
** (d) if DELETEONCLOSE is set, then CREATE must also be set.
|
|
*/
|
|
/* The main DB, main journal, WAL file and super-journal are never
|
|
** automatically deleted. Nor are they ever temporary files. */
|
|
/* Assert that the upper layer has set one of the "file-type" flags. */
|
|
/* Detect a pid change and reset the PRNG. There is a race condition
|
|
** here such that two or more threads all trying to open databases at
|
|
** the same instant might all reset the PRNG. But multiple resets
|
|
** are harmless.
|
|
*/
|
|
if libc.AtomicLoadPInt32(uintptr(unsafe.Pointer(&_randomnessPid))) != libc.Xgetpid(tls) {
|
|
libc.AtomicStorePInt32(uintptr(unsafe.Pointer(&_randomnessPid)), libc.Xgetpid(tls))
|
|
Xsqlite3_randomness(tls, 0, uintptr(0))
|
|
}
|
|
libc.Xmemset(tls, p, 0, uint64(120))
|
|
if eType == int32(SQLITE_OPEN_MAIN_DB) {
|
|
pUnused = _findReusableFd(tls, zName, flags)
|
|
if pUnused != 0 {
|
|
fd = (*TUnixUnusedFd)(unsafe.Pointer(pUnused)).Ffd
|
|
} else {
|
|
pUnused = Xsqlite3_malloc64(tls, uint64(16))
|
|
if !(pUnused != 0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
}
|
|
(*TunixFile)(unsafe.Pointer(p)).FpPreallocatedUnused = pUnused
|
|
/* Database filenames are double-zero terminated if they are not
|
|
** URIs with parameters. Hence, they can always be passed into
|
|
** sqlite3_uri_parameter(). */
|
|
} else {
|
|
if !(zName != 0) {
|
|
/* If zName is NULL, the upper layer is requesting a temp file. */
|
|
rc = _unixGetTempname(tls, (*Tsqlite3_vfs)(unsafe.Pointer(pVfs)).FmxPathname, bp)
|
|
if rc != SQLITE_OK {
|
|
return rc
|
|
}
|
|
zName = bp
|
|
/* Generated temporary filenames are always double-zero terminated
|
|
** for use by sqlite3_uri_parameter(). */
|
|
}
|
|
}
|
|
/* Determine the value of the flags parameter passed to POSIX function
|
|
** open(). These must be calculated even if open() is not called, as
|
|
** they may be stored as part of the file handle and used by the
|
|
** 'conch file' locking functions later on. */
|
|
if isReadonly != 0 {
|
|
openFlags = openFlags | O_RDONLY
|
|
}
|
|
if isReadWrite != 0 {
|
|
openFlags = openFlags | int32(O_RDWR)
|
|
}
|
|
if isCreate != 0 {
|
|
openFlags = openFlags | int32(O_CREAT)
|
|
}
|
|
if isExclusive != 0 {
|
|
openFlags = openFlags | (libc.Int32FromInt32(O_EXCL) | libc.Int32FromInt32(O_NOFOLLOW))
|
|
}
|
|
openFlags = openFlags | (libc.Int32FromInt32(O_LARGEFILE) | libc.Int32FromInt32(O_BINARY) | libc.Int32FromInt32(O_NOFOLLOW))
|
|
if fd < 0 { /* Groupid for the file */
|
|
rc = _findCreateFileMode(tls, zName, flags, bp+516, bp+520, bp+524)
|
|
if rc != SQLITE_OK {
|
|
return rc
|
|
}
|
|
fd = _robust_open(tls, zName, openFlags, **(**Tmode_t)(__ccgo_up(bp + 516)))
|
|
if fd < 0 {
|
|
if isNewJrnl != 0 && **(**int32)(__ccgo_up(libc.X__errno_location(tls))) == int32(EACCES) && (*(*func(*libc.TLS, uintptr, int32) int32)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(2)].FpCurrent})))(tls, zName, F_OK) != 0 {
|
|
/* If unable to create a journal because the directory is not
|
|
** writable, change the error code to indicate that. */
|
|
rc = libc.Int32FromInt32(SQLITE_READONLY) | libc.Int32FromInt32(6)<<libc.Int32FromInt32(8)
|
|
} else {
|
|
if **(**int32)(__ccgo_up(libc.X__errno_location(tls))) != int32(EISDIR) && isReadWrite != 0 {
|
|
/* Failed to open the file for read/write access. Try read-only. */
|
|
pReadonly = uintptr(0)
|
|
flags = flags & ^(libc.Int32FromInt32(SQLITE_OPEN_READWRITE) | libc.Int32FromInt32(SQLITE_OPEN_CREATE))
|
|
openFlags = openFlags & ^(libc.Int32FromInt32(O_RDWR) | libc.Int32FromInt32(O_CREAT))
|
|
flags = flags | int32(SQLITE_OPEN_READONLY)
|
|
openFlags = openFlags | O_RDONLY
|
|
isReadonly = int32(1)
|
|
pReadonly = _findReusableFd(tls, zName, flags)
|
|
if pReadonly != 0 {
|
|
fd = (*TUnixUnusedFd)(unsafe.Pointer(pReadonly)).Ffd
|
|
Xsqlite3_free(tls, pReadonly)
|
|
} else {
|
|
fd = _robust_open(tls, zName, openFlags, **(**Tmode_t)(__ccgo_up(bp + 516)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if fd < 0 {
|
|
rc2 = _unixLogErrorAtLine(tls, _sqlite3CantopenError(tls, int32(47049)), __ccgo_ts+3542, zName, int32(47049))
|
|
if rc == SQLITE_OK {
|
|
rc = rc2
|
|
}
|
|
goto open_finished
|
|
}
|
|
/* The owner of the rollback journal or WAL file should always be the
|
|
** same as the owner of the database file. Try to ensure that this is
|
|
** the case. The chown() system call will be a no-op if the current
|
|
** process lacks root privileges, be we should at least try. Without
|
|
** this step, if a root process opens a database file, it can leave
|
|
** behinds a journal/WAL that is owned by root and hence make the
|
|
** database inaccessible to unprivileged processes.
|
|
**
|
|
** If openMode==0, then that means uid and gid are not set correctly
|
|
** (probably because SQLite is configured to use 8+3 filename mode) and
|
|
** in that case we do not want to attempt the chown().
|
|
*/
|
|
if **(**Tmode_t)(__ccgo_up(bp + 516)) != 0 && flags&(libc.Int32FromInt32(SQLITE_OPEN_WAL)|libc.Int32FromInt32(SQLITE_OPEN_MAIN_JOURNAL)) != 0 {
|
|
_robustFchown(tls, fd, **(**Tuid_t)(__ccgo_up(bp + 520)), **(**Tgid_t)(__ccgo_up(bp + 524)))
|
|
}
|
|
}
|
|
if pOutFlags != 0 {
|
|
**(**int32)(__ccgo_up(pOutFlags)) = flags
|
|
}
|
|
if (*TunixFile)(unsafe.Pointer(p)).FpPreallocatedUnused != 0 {
|
|
(*TUnixUnusedFd)(unsafe.Pointer((*TunixFile)(unsafe.Pointer(p)).FpPreallocatedUnused)).Ffd = fd
|
|
(*TUnixUnusedFd)(unsafe.Pointer((*TunixFile)(unsafe.Pointer(p)).FpPreallocatedUnused)).Fflags = flags & (libc.Int32FromInt32(SQLITE_OPEN_READONLY) | libc.Int32FromInt32(SQLITE_OPEN_READWRITE))
|
|
}
|
|
if isDelete != 0 {
|
|
(*(*func(*libc.TLS, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(16)].FpCurrent})))(tls, zName)
|
|
}
|
|
/* Set up appropriate ctrlFlags */
|
|
if isDelete != 0 {
|
|
ctrlFlags = ctrlFlags | int32(UNIXFILE_DELETE)
|
|
}
|
|
if isReadonly != 0 {
|
|
ctrlFlags = ctrlFlags | int32(UNIXFILE_RDONLY)
|
|
}
|
|
noLock = libc.BoolInt32(eType != int32(SQLITE_OPEN_MAIN_DB))
|
|
if noLock != 0 {
|
|
ctrlFlags = ctrlFlags | int32(UNIXFILE_NOLOCK)
|
|
}
|
|
if isNewJrnl != 0 {
|
|
ctrlFlags = ctrlFlags | int32(UNIXFILE_DIRSYNC)
|
|
}
|
|
if flags&int32(SQLITE_OPEN_URI) != 0 {
|
|
ctrlFlags = ctrlFlags | int32(UNIXFILE_URI)
|
|
}
|
|
rc = _fillInUnixFile(tls, pVfs, fd, pFile, zPath, ctrlFlags)
|
|
goto open_finished
|
|
open_finished:
|
|
;
|
|
if rc != SQLITE_OK {
|
|
Xsqlite3_free(tls, (*TunixFile)(unsafe.Pointer(p)).FpPreallocatedUnused)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Extract a value from the supplied expression in the manner described
|
|
// ** above sqlite3ValueFromExpr(). Allocate the sqlite3_value object
|
|
// ** using valueNew().
|
|
// **
|
|
// ** If pCtx is NULL and an error occurs after the sqlite3_value object
|
|
// ** has been allocated, it is freed before returning. Or, if pCtx is not
|
|
// ** NULL, it is assumed that the caller will free any allocated object
|
|
// ** in all cases.
|
|
// */
|
|
func _valueFromExpr(tls *libc.TLS, db uintptr, pExpr uintptr, enc Tu8, affinity Tu8, ppVal uintptr, pCtx uintptr) (r int32) {
|
|
bp := tls.Alloc(48)
|
|
defer tls.Free(48)
|
|
var aff Tu8
|
|
var nVal, negInt, op, rc, v1 int32
|
|
var pLeft, zNeg, zVal, v3 uintptr
|
|
var _ /* iVal at bp+8 */ Ti64
|
|
var _ /* pVal at bp+0 */ uintptr
|
|
_, _, _, _, _, _, _, _, _, _ = aff, nVal, negInt, op, pLeft, rc, zNeg, zVal, v1, v3
|
|
zVal = uintptr(0)
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
negInt = int32(1)
|
|
zNeg = __ccgo_ts + 1704
|
|
rc = SQLITE_OK
|
|
for {
|
|
v1 = libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop)
|
|
op = v1
|
|
if !(v1 == int32(TK_UPLUS) || op == int32(TK_SPAN)) {
|
|
break
|
|
}
|
|
pExpr = (*TExpr)(unsafe.Pointer(pExpr)).FpLeft
|
|
}
|
|
if op == int32(TK_REGISTER) {
|
|
op = libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop2)
|
|
}
|
|
/* Compressed expressions only appear when parsing the DEFAULT clause
|
|
** on a table column definition, and hence only when pCtx==0. This
|
|
** check ensures that an EP_TokenOnly expression is never passed down
|
|
** into valueFromFunction(). */
|
|
if op == int32(TK_CAST) {
|
|
aff = _sqlite3AffinityType(tls, *(*uintptr)(unsafe.Pointer(pExpr + 8)), uintptr(0))
|
|
rc = _valueFromExpr(tls, db, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, enc, aff, ppVal, pCtx)
|
|
if **(**uintptr)(__ccgo_up(ppVal)) != 0 {
|
|
if libc.Int32FromUint16((*Tsqlite3_value)(unsafe.Pointer(**(**uintptr)(__ccgo_up(ppVal)))).Fflags)&int32(MEM_Zero) != 0 {
|
|
v1 = _sqlite3VdbeMemExpandBlob(tls, **(**uintptr)(__ccgo_up(ppVal)))
|
|
} else {
|
|
v1 = 0
|
|
}
|
|
rc = v1
|
|
_sqlite3VdbeMemCast(tls, **(**uintptr)(__ccgo_up(ppVal)), aff, enc)
|
|
_sqlite3ValueApplyAffinity(tls, **(**uintptr)(__ccgo_up(ppVal)), affinity, enc)
|
|
}
|
|
return rc
|
|
}
|
|
/* Handle negative integers in a single step. This is needed in the
|
|
** case when the value is -9223372036854775808. Except - do not do this
|
|
** for hexadecimal literals. */
|
|
if op == int32(TK_UMINUS) {
|
|
pLeft = (*TExpr)(unsafe.Pointer(pExpr)).FpLeft
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pLeft)).Fop) == int32(TK_INTEGER) || libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pLeft)).Fop) == int32(TK_FLOAT) {
|
|
if (*TExpr)(unsafe.Pointer(pLeft)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_IntValue)) != uint32(0) || libc.Int32FromUint8(**(**uint8)(__ccgo_up(*(*uintptr)(unsafe.Pointer(pLeft + 8))))) != int32('0') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(*(*uintptr)(unsafe.Pointer(pLeft + 8)) + 1))) & ^libc.Int32FromInt32(0x20) != int32('X') {
|
|
pExpr = pLeft
|
|
op = libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop)
|
|
negInt = -int32(1)
|
|
zNeg = __ccgo_ts + 5253
|
|
}
|
|
}
|
|
}
|
|
if op == int32(TK_STRING) || op == int32(TK_FLOAT) || op == int32(TK_INTEGER) {
|
|
**(**uintptr)(__ccgo_up(bp)) = _valueNew(tls, db, pCtx)
|
|
if **(**uintptr)(__ccgo_up(bp)) == uintptr(0) {
|
|
goto no_mem
|
|
}
|
|
if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_IntValue)) != uint32(0) {
|
|
_sqlite3VdbeMemSetInt64(tls, **(**uintptr)(__ccgo_up(bp)), int64(*(*int32)(unsafe.Pointer(&(*TExpr)(unsafe.Pointer(pExpr)).Fu)))*int64(negInt))
|
|
} else {
|
|
if op == int32(TK_INTEGER) && 0 == _sqlite3DecOrHexToI64(tls, *(*uintptr)(unsafe.Pointer(pExpr + 8)), bp+8) {
|
|
_sqlite3VdbeMemSetInt64(tls, **(**uintptr)(__ccgo_up(bp)), **(**Ti64)(__ccgo_up(bp + 8))*int64(negInt))
|
|
} else {
|
|
zVal = _sqlite3MPrintf(tls, db, __ccgo_ts+5255, libc.VaList(bp+24, zNeg, *(*uintptr)(unsafe.Pointer(pExpr + 8))))
|
|
if zVal == uintptr(0) {
|
|
goto no_mem
|
|
}
|
|
_sqlite3ValueSetStr(tls, **(**uintptr)(__ccgo_up(bp)), -int32(1), zVal, uint8(SQLITE_UTF8), __ccgo_fp(_sqlite3RowSetClear))
|
|
}
|
|
}
|
|
if libc.Int32FromUint8(affinity) == int32(SQLITE_AFF_BLOB) {
|
|
if op == int32(TK_FLOAT) {
|
|
_sqlite3AtoF(tls, (*Tsqlite3_value)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).Fz, **(**uintptr)(__ccgo_up(bp)))
|
|
(*Tsqlite3_value)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).Fflags = uint16(MEM_Real)
|
|
} else {
|
|
if op == int32(TK_INTEGER) {
|
|
/* This case is required by -9223372036854775808 and other strings
|
|
** that look like integers but cannot be handled by the
|
|
** sqlite3DecOrHexToI64() call above. */
|
|
_sqlite3ValueApplyAffinity(tls, **(**uintptr)(__ccgo_up(bp)), uint8(SQLITE_AFF_NUMERIC), uint8(SQLITE_UTF8))
|
|
}
|
|
}
|
|
} else {
|
|
_sqlite3ValueApplyAffinity(tls, **(**uintptr)(__ccgo_up(bp)), affinity, uint8(SQLITE_UTF8))
|
|
}
|
|
if libc.Int32FromUint16((*Tsqlite3_value)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).Fflags)&(libc.Int32FromInt32(MEM_Int)|libc.Int32FromInt32(MEM_IntReal)|libc.Int32FromInt32(MEM_Real)) != 0 {
|
|
v3 = **(**uintptr)(__ccgo_up(bp)) + 20
|
|
*(*Tu16)(unsafe.Pointer(v3)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v3))) & ^libc.Int32FromInt32(MEM_Str))
|
|
}
|
|
if libc.Int32FromUint8(enc) != int32(SQLITE_UTF8) {
|
|
rc = _sqlite3VdbeChangeEncoding(tls, **(**uintptr)(__ccgo_up(bp)), libc.Int32FromUint8(enc))
|
|
}
|
|
} else {
|
|
if op == int32(TK_UMINUS) {
|
|
/* This branch happens for multiple negative signs. Ex: -(-5) */
|
|
if SQLITE_OK == _valueFromExpr(tls, db, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, enc, affinity, bp, pCtx) && **(**uintptr)(__ccgo_up(bp)) != uintptr(0) {
|
|
_sqlite3VdbeMemNumerify(tls, **(**uintptr)(__ccgo_up(bp)))
|
|
if libc.Int32FromUint16((*Tsqlite3_value)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).Fflags)&int32(MEM_Real) != 0 {
|
|
*(*float64)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))) = -*(*float64)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp))))
|
|
} else {
|
|
if *(*Ti64)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))) == int64(-libc.Int32FromInt32(1))-(libc.Int64FromUint32(0xffffffff)|libc.Int64FromInt32(0x7fffffff)<<libc.Int32FromInt32(32)) {
|
|
*(*float64)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))) = -float64(int64(-libc.Int32FromInt32(1)) - (libc.Int64FromUint32(0xffffffff) | libc.Int64FromInt32(0x7fffffff)<<libc.Int32FromInt32(32)))
|
|
(*Tsqlite3_value)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).Fflags = libc.Uint16FromInt32(libc.Int32FromUint16((*Tsqlite3_value)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).Fflags) & ^(libc.Int32FromInt32(MEM_TypeMask)|libc.Int32FromInt32(MEM_Zero)) | int32(MEM_Real))
|
|
} else {
|
|
*(*Ti64)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))) = -*(*Ti64)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp))))
|
|
}
|
|
}
|
|
_sqlite3ValueApplyAffinity(tls, **(**uintptr)(__ccgo_up(bp)), affinity, enc)
|
|
}
|
|
} else {
|
|
if op == int32(TK_NULL) {
|
|
**(**uintptr)(__ccgo_up(bp)) = _valueNew(tls, db, pCtx)
|
|
if **(**uintptr)(__ccgo_up(bp)) == uintptr(0) {
|
|
goto no_mem
|
|
}
|
|
_sqlite3VdbeMemSetNull(tls, **(**uintptr)(__ccgo_up(bp)))
|
|
} else {
|
|
if op == int32(TK_BLOB) {
|
|
**(**uintptr)(__ccgo_up(bp)) = _valueNew(tls, db, pCtx)
|
|
if !(**(**uintptr)(__ccgo_up(bp)) != 0) {
|
|
goto no_mem
|
|
}
|
|
zVal = *(*uintptr)(unsafe.Pointer(pExpr + 8)) + 2
|
|
nVal = _sqlite3Strlen30(tls, zVal) - int32(1)
|
|
_sqlite3VdbeMemSetStr(tls, **(**uintptr)(__ccgo_up(bp)), _sqlite3HexToBlob(tls, db, zVal, nVal), int64(nVal/int32(2)), uint8(0), __ccgo_fp(_sqlite3RowSetClear))
|
|
} else {
|
|
if op == int32(TK_FUNCTION) && pCtx != uintptr(0) {
|
|
rc = _valueFromFunction(tls, db, pExpr, enc, affinity, bp, pCtx)
|
|
} else {
|
|
if op == int32(TK_TRUEFALSE) {
|
|
**(**uintptr)(__ccgo_up(bp)) = _valueNew(tls, db, pCtx)
|
|
if **(**uintptr)(__ccgo_up(bp)) != 0 {
|
|
(*Tsqlite3_value)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).Fflags = uint16(MEM_Int)
|
|
*(*Ti64)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))) = libc.BoolInt64(libc.Int32FromUint8(**(**uint8)(__ccgo_up(*(*uintptr)(unsafe.Pointer(pExpr + 8)) + 4))) == 0)
|
|
_sqlite3ValueApplyAffinity(tls, **(**uintptr)(__ccgo_up(bp)), affinity, enc)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppVal)) = **(**uintptr)(__ccgo_up(bp))
|
|
return rc
|
|
goto no_mem
|
|
no_mem:
|
|
;
|
|
if pCtx == uintptr(0) || (*TParse)(unsafe.Pointer((*TValueNewStat4Ctx)(unsafe.Pointer(pCtx)).FpParse)).FnErr == 0 {
|
|
_sqlite3OomFault(tls, db)
|
|
}
|
|
_sqlite3DbFree(tls, db, zVal)
|
|
if pCtx == uintptr(0) {
|
|
_sqlite3ValueFree(tls, **(**uintptr)(__ccgo_up(bp)))
|
|
}
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Render a Mem object which is one of MEM_Int, MEM_Real, or MEM_IntReal
|
|
// ** into a buffer.
|
|
// */
|
|
func _vdbeMemRenderNum(tls *libc.TLS, sz int32, zBuf uintptr, p uintptr) {
|
|
bp := tls.Alloc(64)
|
|
defer tls.Free(64)
|
|
var v1 int32
|
|
var _ /* acc at bp+0 */ TStrAccum
|
|
_ = v1
|
|
if libc.Int32FromUint16((*TMem)(unsafe.Pointer(p)).Fflags)&(libc.Int32FromInt32(MEM_Int)|libc.Int32FromInt32(MEM_IntReal)) != 0 {
|
|
(*TMem)(unsafe.Pointer(p)).Fn = _sqlite3Int64ToText(tls, *(*Ti64)(unsafe.Pointer(p)), zBuf)
|
|
if libc.Int32FromUint16((*TMem)(unsafe.Pointer(p)).Fflags)&int32(MEM_IntReal) != 0 {
|
|
libc.Xmemcpy(tls, zBuf+uintptr((*TMem)(unsafe.Pointer(p)).Fn), __ccgo_ts+5244, uint64(3))
|
|
**(**int32)(__ccgo_up(p + 16)) += int32(2)
|
|
}
|
|
} else {
|
|
_sqlite3StrAccumInit(tls, bp, uintptr(0), zBuf, sz, 0)
|
|
if (*TMem)(unsafe.Pointer(p)).Fdb != 0 {
|
|
v1 = libc.Int32FromUint8((*Tsqlite3)(unsafe.Pointer((*TMem)(unsafe.Pointer(p)).Fdb)).FnFpDigit)
|
|
} else {
|
|
v1 = int32(17)
|
|
}
|
|
Xsqlite3_str_appendf(tls, bp, __ccgo_ts+5247, libc.VaList(bp+40, v1, *(*float64)(unsafe.Pointer(p))))
|
|
**(**uint8)(__ccgo_up(zBuf + uintptr((**(**TStrAccum)(__ccgo_up(bp))).FnChar))) = uint8(0) /* Fast version of sqlite3StrAccumFinish(&acc) */
|
|
(*TMem)(unsafe.Pointer(p)).Fn = libc.Int32FromUint32((**(**TStrAccum)(__ccgo_up(bp))).FnChar)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The Table structure pTable is really a VIEW. Fill in the names of
|
|
// ** the columns of the view in the pTable structure. Return non-zero if
|
|
// ** there are errors. If an error is seen an error message is left
|
|
// ** in pParse->zErrMsg.
|
|
// */
|
|
func _viewGetColumnNames(tls *libc.TLS, pParse uintptr, pTable uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var db, pSel, pSelTab, v2 uintptr
|
|
var eParseMode Tu8
|
|
var nErr, nSelect, nTab, rc, v1 int32
|
|
var xAuth Tsqlite3_xauth
|
|
_, _, _, _, _, _, _, _, _, _, _ = db, eParseMode, nErr, nSelect, nTab, pSel, pSelTab, rc, xAuth, v1, v2 /* Copy of the SELECT that implements the view */
|
|
nErr = 0 /* Number of errors encountered */
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb /* Saved xAuth pointer */
|
|
if libc.Int32FromUint8((*TTable)(unsafe.Pointer(pTable)).FeTabType) == int32(TABTYP_VTAB) {
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FnSchemaLock = (*Tsqlite3)(unsafe.Pointer(db)).FnSchemaLock + 1
|
|
rc = _sqlite3VtabCallConnect(tls, pParse, pTable)
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FnSchemaLock = (*Tsqlite3)(unsafe.Pointer(db)).FnSchemaLock - 1
|
|
return rc
|
|
}
|
|
/* A positive nCol means the columns names for this view are
|
|
** already known. This routine is not called unless either the
|
|
** table is virtual or nCol is zero.
|
|
*/
|
|
/* A negative nCol is a special marker meaning that we are currently
|
|
** trying to compute the column names. If we enter this routine with
|
|
** a negative nCol, it means two or more views form a loop, like this:
|
|
**
|
|
** CREATE VIEW one AS SELECT * FROM two;
|
|
** CREATE VIEW two AS SELECT * FROM one;
|
|
**
|
|
** Actually, the error above is now caught prior to reaching this point.
|
|
** But the following test is still important as it does come up
|
|
** in the following:
|
|
**
|
|
** CREATE TABLE main.ex1(a);
|
|
** CREATE TEMP VIEW ex1 AS SELECT a FROM ex1;
|
|
** SELECT * FROM temp.ex1;
|
|
*/
|
|
if int32((*TTable)(unsafe.Pointer(pTable)).FnCol) < 0 {
|
|
_sqlite3ErrorMsg(tls, pParse, __ccgo_ts+14867, libc.VaList(bp+8, (*TTable)(unsafe.Pointer(pTable)).FzName))
|
|
return int32(1)
|
|
}
|
|
/* If we get this far, it means we need to compute the table names.
|
|
** Note that the call to sqlite3ResultSetOfSelect() will expand any
|
|
** "*" elements in the results set of the view and will assign cursors
|
|
** to the elements of the FROM clause. But we do not want these changes
|
|
** to be permanent. So the computation is done on a copy of the SELECT
|
|
** statement that defines the view.
|
|
*/
|
|
pSel = _sqlite3SelectDup(tls, db, (*(*struct {
|
|
FpSelect uintptr
|
|
})(unsafe.Pointer(&(*TTable)(unsafe.Pointer(pTable)).Fu))).FpSelect, 0)
|
|
if pSel != 0 {
|
|
eParseMode = (*TParse)(unsafe.Pointer(pParse)).FeParseMode
|
|
nTab = (*TParse)(unsafe.Pointer(pParse)).FnTab
|
|
nSelect = (*TParse)(unsafe.Pointer(pParse)).FnSelect
|
|
(*TParse)(unsafe.Pointer(pParse)).FeParseMode = uint8(PARSE_MODE_NORMAL)
|
|
_sqlite3SrcListAssignCursors(tls, pParse, (*TSelect)(unsafe.Pointer(pSel)).FpSrc)
|
|
(*TTable)(unsafe.Pointer(pTable)).FnCol = int16(-int32(1))
|
|
(*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FbDisable = (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FbDisable + 1
|
|
(*Tsqlite3)(unsafe.Pointer(db)).Flookaside.Fsz = uint16(0)
|
|
xAuth = (*Tsqlite3)(unsafe.Pointer(db)).FxAuth
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FxAuth = uintptr(0)
|
|
pSelTab = _sqlite3ResultSetOfSelect(tls, pParse, pSel, uint8(SQLITE_AFF_NONE))
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FxAuth = xAuth
|
|
(*TParse)(unsafe.Pointer(pParse)).FnTab = nTab
|
|
(*TParse)(unsafe.Pointer(pParse)).FnSelect = nSelect
|
|
if pSelTab == uintptr(0) {
|
|
(*TTable)(unsafe.Pointer(pTable)).FnCol = 0
|
|
nErr = nErr + 1
|
|
} else {
|
|
if (*TTable)(unsafe.Pointer(pTable)).FpCheck != 0 {
|
|
/* CREATE VIEW name(arglist) AS ...
|
|
** The names of the columns in the table are taken from
|
|
** arglist which is stored in pTable->pCheck. The pCheck field
|
|
** normally holds CHECK constraints on an ordinary table, but for
|
|
** a VIEW it holds the list of column names.
|
|
*/
|
|
_sqlite3ColumnsFromExprList(tls, pParse, (*TTable)(unsafe.Pointer(pTable)).FpCheck, pTable+54, pTable+8)
|
|
if (*TParse)(unsafe.Pointer(pParse)).FnErr == 0 && int32((*TTable)(unsafe.Pointer(pTable)).FnCol) == (*TExprList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pSel)).FpEList)).FnExpr {
|
|
_sqlite3SubqueryColumnTypes(tls, pParse, pTable, pSel, uint8(SQLITE_AFF_NONE))
|
|
}
|
|
} else {
|
|
/* CREATE VIEW name AS... without an argument list. Construct
|
|
** the column names from the SELECT statement that defines the view.
|
|
*/
|
|
(*TTable)(unsafe.Pointer(pTable)).FnCol = (*TTable)(unsafe.Pointer(pSelTab)).FnCol
|
|
(*TTable)(unsafe.Pointer(pTable)).FaCol = (*TTable)(unsafe.Pointer(pSelTab)).FaCol
|
|
**(**Tu32)(__ccgo_up(pTable + 48)) |= (*TTable)(unsafe.Pointer(pSelTab)).FtabFlags & uint32(COLFLAG_NOINSERT)
|
|
(*TTable)(unsafe.Pointer(pSelTab)).FnCol = 0
|
|
(*TTable)(unsafe.Pointer(pSelTab)).FaCol = uintptr(0)
|
|
}
|
|
}
|
|
(*TTable)(unsafe.Pointer(pTable)).FnNVCol = (*TTable)(unsafe.Pointer(pTable)).FnCol
|
|
_sqlite3DeleteTable(tls, db, pSelTab)
|
|
_sqlite3SelectDelete(tls, db, pSel)
|
|
(*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FbDisable = (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FbDisable - 1
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FbDisable != 0 {
|
|
v1 = 0
|
|
} else {
|
|
v1 = libc.Int32FromUint16((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FszTrue)
|
|
}
|
|
(*Tsqlite3)(unsafe.Pointer(db)).Flookaside.Fsz = libc.Uint16FromInt32(v1)
|
|
(*TParse)(unsafe.Pointer(pParse)).FeParseMode = eParseMode
|
|
} else {
|
|
nErr = nErr + 1
|
|
}
|
|
v2 = (*TTable)(unsafe.Pointer(pTable)).FpSchema + 114
|
|
*(*Tu16)(unsafe.Pointer(v2)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v2))) | libc.Int32FromInt32(DB_UnresetViews))
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
|
|
_sqlite3DeleteColumnNames(tls, db, pTable)
|
|
}
|
|
return nErr + (*TParse)(unsafe.Pointer(pParse)).FnErr
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Invoke a virtual table constructor (either xCreate or xConnect). The
|
|
// ** pointer to the function to invoke is passed as the fourth parameter
|
|
// ** to this procedure.
|
|
// */
|
|
func _vtabCallConstructor(tls *libc.TLS, db uintptr, pTab uintptr, pMod uintptr, __ccgo_fp_xConstruct uintptr, pzErr uintptr) (r int32) {
|
|
bp := tls.Alloc(64)
|
|
defer tls.Free(64)
|
|
var azArg, pCtx, pVTable, zFormat, zModuleName, zType, v6 uintptr
|
|
var i, iCol, iDb, j, nArg, nDel, nType, rc, v4 int32
|
|
var oooHidden Tu16
|
|
var _ /* sCtx at bp+0 */ TVtabCtx
|
|
var _ /* zErr at bp+32 */ uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = azArg, i, iCol, iDb, j, nArg, nDel, nType, oooHidden, pCtx, pVTable, rc, zFormat, zModuleName, zType, v4, v6
|
|
nArg = (*(*struct {
|
|
FnArg int32
|
|
FazArg uintptr
|
|
Fp uintptr
|
|
})(unsafe.Pointer(pTab + 64))).FnArg
|
|
**(**uintptr)(__ccgo_up(bp + 32)) = uintptr(0)
|
|
azArg = (*(*struct {
|
|
FnArg int32
|
|
FazArg uintptr
|
|
Fp uintptr
|
|
})(unsafe.Pointer(pTab + 64))).FazArg
|
|
/* Check that the virtual-table is not already being initialized */
|
|
pCtx = (*Tsqlite3)(unsafe.Pointer(db)).FpVtabCtx
|
|
for {
|
|
if !(pCtx != 0) {
|
|
break
|
|
}
|
|
if (*TVtabCtx)(unsafe.Pointer(pCtx)).FpTab == pTab {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = _sqlite3MPrintf(tls, db, __ccgo_ts+23496, libc.VaList(bp+48, (*TTable)(unsafe.Pointer(pTab)).FzName))
|
|
return int32(SQLITE_LOCKED)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pCtx = (*TVtabCtx)(unsafe.Pointer(pCtx)).FpPrior
|
|
}
|
|
zModuleName = _sqlite3DbStrDup(tls, db, (*TTable)(unsafe.Pointer(pTab)).FzName)
|
|
if !(zModuleName != 0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
pVTable = _sqlite3MallocZero(tls, uint64(48))
|
|
if !(pVTable != 0) {
|
|
_sqlite3OomFault(tls, db)
|
|
_sqlite3DbFree(tls, db, zModuleName)
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
(*TVTable)(unsafe.Pointer(pVTable)).Fdb = db
|
|
(*TVTable)(unsafe.Pointer(pVTable)).FpMod = pMod
|
|
(*TVTable)(unsafe.Pointer(pVTable)).FeVtabRisk = uint8(SQLITE_VTABRISK_Normal)
|
|
iDb = _sqlite3SchemaToIndex(tls, db, (*TTable)(unsafe.Pointer(pTab)).FpSchema)
|
|
**(**uintptr)(__ccgo_up((*(*struct {
|
|
FnArg int32
|
|
FazArg uintptr
|
|
Fp uintptr
|
|
})(unsafe.Pointer(pTab + 64))).FazArg + 1*8)) = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FzDbSName
|
|
/* Invoke the virtual table constructor */
|
|
(**(**TVtabCtx)(__ccgo_up(bp))).FpTab = pTab
|
|
(**(**TVtabCtx)(__ccgo_up(bp))).FpVTable = pVTable
|
|
(**(**TVtabCtx)(__ccgo_up(bp))).FpPrior = (*Tsqlite3)(unsafe.Pointer(db)).FpVtabCtx
|
|
(**(**TVtabCtx)(__ccgo_up(bp))).FbDeclared = 0
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FpVtabCtx = bp
|
|
(*TTable)(unsafe.Pointer(pTab)).FnTabRef = (*TTable)(unsafe.Pointer(pTab)).FnTabRef + 1
|
|
rc = (*(*func(*libc.TLS, uintptr, uintptr, int32, uintptr, uintptr, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xConstruct})))(tls, db, (*TModule)(unsafe.Pointer(pMod)).FpAux, nArg, azArg, pVTable+16, bp+32)
|
|
_sqlite3DeleteTable(tls, db, pTab)
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FpVtabCtx = (**(**TVtabCtx)(__ccgo_up(bp))).FpPrior
|
|
if rc == int32(SQLITE_NOMEM) {
|
|
_sqlite3OomFault(tls, db)
|
|
}
|
|
if SQLITE_OK != rc {
|
|
if **(**uintptr)(__ccgo_up(bp + 32)) == uintptr(0) {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = _sqlite3MPrintf(tls, db, __ccgo_ts+23538, libc.VaList(bp+48, zModuleName))
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(pzErr)) = _sqlite3MPrintf(tls, db, __ccgo_ts+3968, libc.VaList(bp+48, **(**uintptr)(__ccgo_up(bp + 32))))
|
|
Xsqlite3_free(tls, **(**uintptr)(__ccgo_up(bp + 32)))
|
|
}
|
|
_sqlite3DbFree(tls, db, pVTable)
|
|
} else {
|
|
if (*TVTable)(unsafe.Pointer(pVTable)).FpVtab != 0 {
|
|
/* Justification of ALWAYS(): A correct vtab constructor must allocate
|
|
** the sqlite3_vtab object if successful. */
|
|
libc.Xmemset(tls, (*TVTable)(unsafe.Pointer(pVTable)).FpVtab, 0, uint64(24))
|
|
(*Tsqlite3_vtab)(unsafe.Pointer((*TVTable)(unsafe.Pointer(pVTable)).FpVtab)).FpModule = (*TModule)(unsafe.Pointer(pMod)).FpModule
|
|
(*TModule)(unsafe.Pointer(pMod)).FnRefModule = (*TModule)(unsafe.Pointer(pMod)).FnRefModule + 1
|
|
(*TVTable)(unsafe.Pointer(pVTable)).FnRef = int32(1)
|
|
if (**(**TVtabCtx)(__ccgo_up(bp))).FbDeclared == 0 {
|
|
zFormat = __ccgo_ts + 23568
|
|
**(**uintptr)(__ccgo_up(pzErr)) = _sqlite3MPrintf(tls, db, zFormat, libc.VaList(bp+48, zModuleName))
|
|
_sqlite3VtabUnlock(tls, pVTable)
|
|
rc = int32(SQLITE_ERROR)
|
|
} else {
|
|
oooHidden = uint16(0)
|
|
/* If everything went according to plan, link the new VTable structure
|
|
** into the linked list headed by pTab->u.vtab.p. Then loop through the
|
|
** columns of the table to see if any of them contain the token "hidden".
|
|
** If so, set the Column COLFLAG_HIDDEN flag and remove the token from
|
|
** the type string. */
|
|
(*TVTable)(unsafe.Pointer(pVTable)).FpNext = (*(*struct {
|
|
FnArg int32
|
|
FazArg uintptr
|
|
Fp uintptr
|
|
})(unsafe.Pointer(pTab + 64))).Fp
|
|
(*(*struct {
|
|
FnArg int32
|
|
FazArg uintptr
|
|
Fp uintptr
|
|
})(unsafe.Pointer(pTab + 64))).Fp = pVTable
|
|
iCol = 0
|
|
for {
|
|
if !(iCol < int32((*TTable)(unsafe.Pointer(pTab)).FnCol)) {
|
|
break
|
|
}
|
|
zType = _sqlite3ColumnType(tls, (*TTable)(unsafe.Pointer(pTab)).FaCol+uintptr(iCol)*16, __ccgo_ts+1704)
|
|
i = 0
|
|
nType = _sqlite3Strlen30(tls, zType)
|
|
i = 0
|
|
for {
|
|
if !(i < nType) {
|
|
break
|
|
}
|
|
if 0 == Xsqlite3_strnicmp(tls, __ccgo_ts+17882, zType+uintptr(i), int32(6)) && (i == 0 || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zType + uintptr(i-int32(1))))) == int32(' ')) && (libc.Int32FromUint8(**(**uint8)(__ccgo_up(zType + uintptr(i+int32(6))))) == int32('\000') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zType + uintptr(i+int32(6))))) == int32(' ')) {
|
|
break
|
|
}
|
|
goto _3
|
|
_3:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if i < nType {
|
|
if **(**uint8)(__ccgo_up(zType + uintptr(i+int32(6)))) != 0 {
|
|
v4 = int32(1)
|
|
} else {
|
|
v4 = 0
|
|
}
|
|
nDel = int32(6) + v4
|
|
j = i
|
|
for {
|
|
if !(j+nDel <= nType) {
|
|
break
|
|
}
|
|
**(**uint8)(__ccgo_up(zType + uintptr(j))) = **(**uint8)(__ccgo_up(zType + uintptr(j+nDel)))
|
|
goto _5
|
|
_5:
|
|
;
|
|
j = j + 1
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zType + uintptr(i)))) == int32('\000') && i > 0 {
|
|
**(**uint8)(__ccgo_up(zType + uintptr(i-int32(1)))) = uint8('\000')
|
|
}
|
|
v6 = (*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(iCol)*16 + 14
|
|
*(*Tu16)(unsafe.Pointer(v6)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v6))) | libc.Int32FromInt32(COLFLAG_HIDDEN))
|
|
**(**Tu32)(__ccgo_up(pTab + 48)) |= uint32(TF_HasHidden)
|
|
oooHidden = uint16(TF_OOOHidden)
|
|
} else {
|
|
**(**Tu32)(__ccgo_up(pTab + 48)) |= uint32(oooHidden)
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
iCol = iCol + 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_sqlite3DbFree(tls, db, zModuleName)
|
|
return rc
|
|
}
|