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.
7193 lines
280 KiB
Go
7193 lines
280 KiB
Go
// Code generated by modernc.org/undup from the per-target sqlite_*.go files; DO NOT EDIT.
|
|
|
|
//go:build (freebsd && arm64) || (linux && arm64) || (linux && ppc64le) || (linux && riscv64) || (linux && s390x) || (openbsd && arm64)
|
|
|
|
package sqlite3
|
|
|
|
import (
|
|
"unsafe"
|
|
|
|
"modernc.org/libc"
|
|
)
|
|
|
|
type TColumn = struct {
|
|
FzCnName uintptr
|
|
F__ccgo8 uint8
|
|
Faffinity uint8
|
|
FszEst Tu8
|
|
FhName Tu8
|
|
FiDflt Tu16
|
|
FcolFlags Tu16
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** A structure for holding a single date and time.
|
|
// */
|
|
type TDateTime = struct {
|
|
FiJD Tsqlite3_int64
|
|
FY int32
|
|
FM int32
|
|
FD int32
|
|
Fh int32
|
|
Fm int32
|
|
Ftz int32
|
|
Fs float64
|
|
FvalidJD uint8
|
|
FvalidYMD uint8
|
|
FvalidHMS uint8
|
|
FnFloor uint8
|
|
F__ccgo44 uint8
|
|
}
|
|
|
|
type TExpr = struct {
|
|
Fop Tu8
|
|
FaffExpr uint8
|
|
Fop2 Tu8
|
|
Fflags Tu32
|
|
Fu struct {
|
|
FiValue [0]int32
|
|
FzToken uintptr
|
|
}
|
|
FpLeft uintptr
|
|
FpRight uintptr
|
|
Fx struct {
|
|
FpSelect [0]uintptr
|
|
FpList uintptr
|
|
}
|
|
FnHeight int32
|
|
FiTable int32
|
|
FiColumn TynVar
|
|
FiAgg Ti16
|
|
Fw struct {
|
|
FiOfst [0]int32
|
|
FiJoin int32
|
|
}
|
|
FpAggInfo uintptr
|
|
Fy struct {
|
|
FpWin [0]uintptr
|
|
FnReg [0]int32
|
|
Fsub [0]struct {
|
|
FiAddr int32
|
|
FregReturn int32
|
|
}
|
|
FpTab uintptr
|
|
}
|
|
}
|
|
|
|
type TJsonString = struct {
|
|
FpCtx uintptr
|
|
FzBuf uintptr
|
|
FnAlloc Tu64
|
|
FnUsed Tu64
|
|
FbStatic Tu8
|
|
FeErr Tu8
|
|
FzSpace [100]uint8
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Each open file is managed by a separate instance of the "Pager" structure.
|
|
// */
|
|
type TPager = struct {
|
|
FpVfs uintptr
|
|
FexclusiveMode Tu8
|
|
FjournalMode Tu8
|
|
FuseJournal Tu8
|
|
FnoSync Tu8
|
|
FfullSync Tu8
|
|
FextraSync Tu8
|
|
FsyncFlags Tu8
|
|
FwalSyncFlags Tu8
|
|
FtempFile Tu8
|
|
FnoLock Tu8
|
|
FreadOnly Tu8
|
|
FmemDb Tu8
|
|
FmemVfs Tu8
|
|
FeState Tu8
|
|
FeLock Tu8
|
|
FchangeCountDone Tu8
|
|
FsetSuper Tu8
|
|
FdoNotSpill Tu8
|
|
FsubjInMemory Tu8
|
|
FbUseFetch Tu8
|
|
FhasHeldSharedLock Tu8
|
|
FdbSize TPgno
|
|
FdbOrigSize TPgno
|
|
FdbFileSize TPgno
|
|
FdbHintSize TPgno
|
|
FerrCode int32
|
|
FnRec int32
|
|
FcksumInit Tu32
|
|
FnSubRec Tu32
|
|
FpInJournal uintptr
|
|
Ffd uintptr
|
|
Fjfd uintptr
|
|
Fsjfd uintptr
|
|
FjournalOff Ti64
|
|
FjournalHdr Ti64
|
|
FpBackup uintptr
|
|
FaSavepoint uintptr
|
|
FnSavepoint int32
|
|
FiDataVersion Tu32
|
|
FdbFileVers [16]uint8
|
|
FnMmapOut int32
|
|
FszMmap Tsqlite3_int64
|
|
FpMmapFreelist uintptr
|
|
FnExtra Tu16
|
|
FnReserve Ti16
|
|
FvfsFlags Tu32
|
|
FsectorSize Tu32
|
|
FmxPgno TPgno
|
|
FlckPgno TPgno
|
|
FpageSize Ti64
|
|
FjournalSizeLimit Ti64
|
|
FzFilename uintptr
|
|
FzJournal uintptr
|
|
FxBusyHandler uintptr
|
|
FpBusyHandlerArg uintptr
|
|
FaStat [4]Tu32
|
|
FxReiniter uintptr
|
|
FxGet uintptr
|
|
FpTmpSpace uintptr
|
|
FpPCache uintptr
|
|
FpWal uintptr
|
|
FzWal uintptr
|
|
}
|
|
|
|
type Tsqlite3rbu = struct {
|
|
FeStage int32
|
|
FdbMain uintptr
|
|
FdbRbu uintptr
|
|
FzTarget uintptr
|
|
FzRbu uintptr
|
|
FzState uintptr
|
|
FzStateDb [5]uint8
|
|
Frc int32
|
|
FzErrmsg uintptr
|
|
FnStep int32
|
|
FnProgress Tsqlite3_int64
|
|
Fobjiter TRbuObjIter
|
|
FzVfsName uintptr
|
|
FpTargetFd uintptr
|
|
FnPagePerSector int32
|
|
FiOalSz Ti64
|
|
FnPhaseOneStep Ti64
|
|
FpRenameArg uintptr
|
|
FxRename uintptr
|
|
FiMaxFrame Tu32
|
|
FmLock Tu32
|
|
FnFrame int32
|
|
FnFrameAlloc int32
|
|
FaFrame uintptr
|
|
Fpgsz int32
|
|
FaBuf uintptr
|
|
FiWalCksum Ti64
|
|
FszTemp Ti64
|
|
FszTempLimit Ti64
|
|
FnRbu int32
|
|
FpRbuFd uintptr
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Allocate memory to hold names for a database, journal file, WAL file,
|
|
// ** and query parameters. The pointer returned is valid for use by
|
|
// ** sqlite3_filename_database() and sqlite3_uri_parameter() and related
|
|
// ** functions.
|
|
// **
|
|
// ** Memory layout must be compatible with that generated by the pager
|
|
// ** and expected by sqlite3_uri_parameter() and databaseName().
|
|
// */
|
|
func Xsqlite3_create_filename(tls *libc.TLS, zDatabase uintptr, zJournal uintptr, zWal uintptr, nParam int32, azParam uintptr) (r uintptr) {
|
|
var i int32
|
|
var nByte Tsqlite3_int64
|
|
var p, pResult, v2 uintptr
|
|
_, _, _, _, _ = i, nByte, p, pResult, v2
|
|
nByte = libc.Int64FromUint64(libc.Xstrlen(tls, zDatabase) + libc.Xstrlen(tls, zJournal) + libc.Xstrlen(tls, zWal) + uint64(10))
|
|
i = 0
|
|
for {
|
|
if !(i < nParam*int32(2)) {
|
|
break
|
|
}
|
|
nByte = libc.Int64FromUint64(uint64(nByte) + uint64(libc.Xstrlen(tls, **(**uintptr)(__ccgo_up(azParam + uintptr(i)*8)))+libc.Uint64FromInt32(1)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
v2 = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(nByte))
|
|
p = v2
|
|
pResult = v2
|
|
if p == uintptr(0) {
|
|
return uintptr(0)
|
|
}
|
|
libc.Xmemset(tls, p, 0, uint64(4))
|
|
p = p + uintptr(4)
|
|
p = _appendText(tls, p, zDatabase)
|
|
i = 0
|
|
for {
|
|
if !(i < nParam*int32(2)) {
|
|
break
|
|
}
|
|
p = _appendText(tls, p, **(**uintptr)(__ccgo_up(azParam + uintptr(i)*8)))
|
|
goto _3
|
|
_3:
|
|
;
|
|
i = i + 1
|
|
}
|
|
v2 = p
|
|
p = p + 1
|
|
**(**uint8)(__ccgo_up(v2)) = uint8(0)
|
|
p = _appendText(tls, p, zJournal)
|
|
p = _appendText(tls, p, zWal)
|
|
v2 = p
|
|
p = p + 1
|
|
**(**uint8)(__ccgo_up(v2)) = uint8(0)
|
|
v2 = p
|
|
p = p + 1
|
|
**(**uint8)(__ccgo_up(v2)) = uint8(0)
|
|
return pResult + uintptr(4)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the sqlite3_file for the main database given the name
|
|
// ** of the corresponding WAL or Journal name as passed into
|
|
// ** xOpen.
|
|
// */
|
|
func Xsqlite3_database_file_object(tls *libc.TLS, zName uintptr) (r uintptr) {
|
|
var p, pPager uintptr
|
|
_, _ = p, pPager
|
|
for libc.Int32FromUint8(**(**uint8)(__ccgo_up(zName + uintptr(-libc.Int32FromInt32(1))))) != 0 || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zName + uintptr(-libc.Int32FromInt32(2))))) != 0 || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zName + uintptr(-libc.Int32FromInt32(3))))) != 0 || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zName + uintptr(-libc.Int32FromInt32(4))))) != 0 {
|
|
zName = zName - 1
|
|
}
|
|
p = zName - uintptr(4) - uintptr(8)
|
|
pPager = **(**uintptr)(__ccgo_up(p))
|
|
return (*TPager)(unsafe.Pointer(pPager)).Ffd
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is called from within a pre-update callback to retrieve
|
|
// ** a field of the row currently being updated or deleted.
|
|
// */
|
|
func Xsqlite3_preupdate_old(tls *libc.TLS, db uintptr, iIdx int32, ppValue uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var aRec, p, pCol, pDflt, pMem, v1 uintptr
|
|
var iStore, nByte, rc int32
|
|
var nRec Tu32
|
|
var _ /* pVal at bp+0 */ uintptr
|
|
_, _, _, _, _, _, _, _, _, _ = aRec, iStore, nByte, nRec, p, pCol, pDflt, pMem, rc, v1
|
|
rc = SQLITE_OK
|
|
iStore = 0
|
|
p = (*Tsqlite3)(unsafe.Pointer(db)).FpPreUpdate
|
|
/* Test that this call is being made from within an SQLITE_DELETE or
|
|
** SQLITE_UPDATE pre-update callback, and that iIdx is within range. */
|
|
if !(p != 0) || (*TPreUpdate)(unsafe.Pointer(p)).Fop == int32(SQLITE_INSERT) {
|
|
rc = _sqlite3MisuseError(tls, int32(96062))
|
|
goto preupdate_old_out
|
|
}
|
|
if (*TPreUpdate)(unsafe.Pointer(p)).FpPk != 0 {
|
|
iStore = _sqlite3TableColumnToIndex(tls, (*TPreUpdate)(unsafe.Pointer(p)).FpPk, iIdx)
|
|
} else {
|
|
if iIdx >= int32((*TTable)(unsafe.Pointer((*TPreUpdate)(unsafe.Pointer(p)).FpTab)).FnCol) {
|
|
rc = _sqlite3MisuseError(tls, int32(96068))
|
|
goto preupdate_old_out
|
|
} else {
|
|
iStore = int32(_sqlite3TableColumnToStorage(tls, (*TPreUpdate)(unsafe.Pointer(p)).FpTab, int16(iIdx)))
|
|
}
|
|
}
|
|
if iStore >= int32((*TVdbeCursor)(unsafe.Pointer((*TPreUpdate)(unsafe.Pointer(p)).FpCsr)).FnField) || iStore < 0 {
|
|
rc = int32(SQLITE_RANGE)
|
|
goto preupdate_old_out
|
|
}
|
|
if iIdx == int32((*TTable)(unsafe.Pointer((*TPreUpdate)(unsafe.Pointer(p)).FpTab)).FiPKey) {
|
|
v1 = p + 80
|
|
pMem = v1
|
|
**(**uintptr)(__ccgo_up(ppValue)) = v1
|
|
_sqlite3VdbeMemSetInt64(tls, pMem, (*TPreUpdate)(unsafe.Pointer(p)).FiKey1)
|
|
} else {
|
|
/* If the old.* record has not yet been loaded into memory, do so now. */
|
|
if (*TPreUpdate)(unsafe.Pointer(p)).FpUnpacked == uintptr(0) {
|
|
nRec = _sqlite3BtreePayloadSize(tls, *(*uintptr)(unsafe.Pointer((*TPreUpdate)(unsafe.Pointer(p)).FpCsr + 48)))
|
|
aRec = _sqlite3DbMallocRaw(tls, db, uint64(nRec))
|
|
if !(aRec != 0) {
|
|
goto preupdate_old_out
|
|
}
|
|
rc = _sqlite3BtreePayload(tls, *(*uintptr)(unsafe.Pointer((*TPreUpdate)(unsafe.Pointer(p)).FpCsr + 48)), uint32(0), nRec, aRec)
|
|
if rc == SQLITE_OK {
|
|
(*TPreUpdate)(unsafe.Pointer(p)).FpUnpacked = _vdbeUnpackRecord(tls, (*TPreUpdate)(unsafe.Pointer(p)).FpKeyinfo, libc.Int32FromUint32(nRec), aRec)
|
|
if !((*TPreUpdate)(unsafe.Pointer(p)).FpUnpacked != 0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
}
|
|
}
|
|
if rc != SQLITE_OK {
|
|
_sqlite3DbFree(tls, db, aRec)
|
|
goto preupdate_old_out
|
|
}
|
|
(*TPreUpdate)(unsafe.Pointer(p)).FaRecord = aRec
|
|
}
|
|
v1 = (*TUnpackedRecord)(unsafe.Pointer((*TPreUpdate)(unsafe.Pointer(p)).FpUnpacked)).FaMem + uintptr(iStore)*56
|
|
**(**uintptr)(__ccgo_up(ppValue)) = v1
|
|
pMem = v1
|
|
if iStore >= libc.Int32FromUint16((*TUnpackedRecord)(unsafe.Pointer((*TPreUpdate)(unsafe.Pointer(p)).FpUnpacked)).FnField) {
|
|
/* This occurs when the table has been extended using ALTER TABLE
|
|
** ADD COLUMN. The value to return is the default value of the column. */
|
|
pCol = (*TTable)(unsafe.Pointer((*TPreUpdate)(unsafe.Pointer(p)).FpTab)).FaCol + uintptr(iIdx)*16
|
|
if libc.Int32FromUint16((*TColumn)(unsafe.Pointer(pCol)).FiDflt) > 0 {
|
|
if (*TPreUpdate)(unsafe.Pointer(p)).FapDflt == uintptr(0) {
|
|
nByte = libc.Int32FromUint64(uint64(8) * libc.Uint64FromInt16((*TTable)(unsafe.Pointer((*TPreUpdate)(unsafe.Pointer(p)).FpTab)).FnCol))
|
|
(*TPreUpdate)(unsafe.Pointer(p)).FapDflt = _sqlite3DbMallocZero(tls, db, libc.Uint64FromInt32(nByte))
|
|
if (*TPreUpdate)(unsafe.Pointer(p)).FapDflt == uintptr(0) {
|
|
goto preupdate_old_out
|
|
}
|
|
}
|
|
if **(**uintptr)(__ccgo_up((*TPreUpdate)(unsafe.Pointer(p)).FapDflt + uintptr(iIdx)*8)) == uintptr(0) {
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
pDflt = (*(*TExprList_item)(unsafe.Pointer((*(*struct {
|
|
FaddColOffset int32
|
|
FpFKey uintptr
|
|
FpDfltList uintptr
|
|
})(unsafe.Pointer((*TPreUpdate)(unsafe.Pointer(p)).FpTab + 64))).FpDfltList + 8 + uintptr(libc.Int32FromUint16((*TColumn)(unsafe.Pointer(pCol)).FiDflt)-int32(1))*32))).FpExpr
|
|
rc = _sqlite3ValueFromExpr(tls, db, pDflt, (*Tsqlite3)(unsafe.Pointer(db)).Fenc, (*TColumn)(unsafe.Pointer(pCol)).Faffinity, bp)
|
|
if rc == SQLITE_OK && **(**uintptr)(__ccgo_up(bp)) == uintptr(0) {
|
|
rc = _sqlite3CorruptError(tls, int32(96124))
|
|
}
|
|
**(**uintptr)(__ccgo_up((*TPreUpdate)(unsafe.Pointer(p)).FapDflt + uintptr(iIdx)*8)) = **(**uintptr)(__ccgo_up(bp))
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppValue)) = **(**uintptr)(__ccgo_up((*TPreUpdate)(unsafe.Pointer(p)).FapDflt + uintptr(iIdx)*8))
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(ppValue)) = _columnNullValue(tls)
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint8((**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer((*TPreUpdate)(unsafe.Pointer(p)).FpTab)).FaCol + uintptr(iIdx)*16))).Faffinity) == int32(SQLITE_AFF_REAL) {
|
|
if libc.Int32FromUint16((*TMem)(unsafe.Pointer(pMem)).Fflags)&(libc.Int32FromInt32(MEM_Int)|libc.Int32FromInt32(MEM_IntReal)) != 0 {
|
|
_sqlite3VdbeMemRealify(tls, pMem)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
goto preupdate_old_out
|
|
preupdate_old_out:
|
|
;
|
|
_sqlite3Error(tls, db, rc)
|
|
return _sqlite3ApiExit(tls, db, rc)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Append N copies of character c to the given string buffer.
|
|
// */
|
|
func Xsqlite3_str_appendchar(tls *libc.TLS, p uintptr, N int32, c uint8) {
|
|
var v1 int32
|
|
var v2 bool
|
|
var v4 Tu32
|
|
var v5 uintptr
|
|
_, _, _, _ = v1, v2, v4, v5
|
|
if v2 = libc.Int64FromUint32((*Tsqlite3_str)(unsafe.Pointer(p)).FnChar)+int64(N) >= libc.Int64FromUint32((*Tsqlite3_str)(unsafe.Pointer(p)).FnAlloc); v2 {
|
|
v1 = _sqlite3StrAccumEnlarge(tls, p, int64(N))
|
|
N = v1
|
|
}
|
|
if v2 && v1 <= 0 {
|
|
return
|
|
}
|
|
for {
|
|
v1 = N
|
|
N = N - 1
|
|
if !(v1 > 0) {
|
|
break
|
|
}
|
|
v5 = p + 24
|
|
v4 = *(*Tu32)(unsafe.Pointer(v5))
|
|
*(*Tu32)(unsafe.Pointer(v5)) = *(*Tu32)(unsafe.Pointer(v5)) + 1
|
|
**(**uint8)(__ccgo_up((*Tsqlite3_str)(unsafe.Pointer(p)).FzText + uintptr(v4))) = c
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Print into memory obtained from sqlite3_malloc(). Omit the internal
|
|
// ** %-conversion extensions.
|
|
// */
|
|
func Xsqlite3_vmprintf(tls *libc.TLS, zFormat uintptr, ap Tva_list) (r uintptr) {
|
|
bp := tls.Alloc(112)
|
|
defer tls.Free(112)
|
|
var z uintptr
|
|
var _ /* acc at bp+72 */ TStrAccum
|
|
var _ /* zBase at bp+0 */ [70]uint8
|
|
_ = z
|
|
if Xsqlite3_initialize(tls) != 0 {
|
|
return uintptr(0)
|
|
}
|
|
_sqlite3StrAccumInit(tls, bp+72, uintptr(0), bp, int32(70), int32(SQLITE_MAX_LENGTH))
|
|
Xsqlite3_str_vappendf(tls, bp+72, zFormat, ap)
|
|
z = _sqlite3StrAccumFinish(tls, bp+72)
|
|
return z
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Processing is determine by the affinity parameter:
|
|
// **
|
|
// ** SQLITE_AFF_INTEGER:
|
|
// ** SQLITE_AFF_REAL:
|
|
// ** SQLITE_AFF_NUMERIC:
|
|
// ** Try to convert pRec to an integer representation or a
|
|
// ** floating-point representation if an integer representation
|
|
// ** is not possible. Note that the integer representation is
|
|
// ** always preferred, even if the affinity is REAL, because
|
|
// ** an integer representation is more space efficient on disk.
|
|
// **
|
|
// ** SQLITE_AFF_FLEXNUM:
|
|
// ** If the value is text, then try to convert it into a number of
|
|
// ** some kind (integer or real) but do not make any other changes.
|
|
// **
|
|
// ** SQLITE_AFF_TEXT:
|
|
// ** Convert pRec to a text representation.
|
|
// **
|
|
// ** SQLITE_AFF_BLOB:
|
|
// ** SQLITE_AFF_NONE:
|
|
// ** No-op. pRec is unchanged.
|
|
// */
|
|
func _applyAffinity(tls *libc.TLS, pRec uintptr, affinity uint8, enc Tu8) {
|
|
var v1 uintptr
|
|
_ = v1
|
|
if libc.Int32FromUint8(affinity) >= int32(SQLITE_AFF_NUMERIC) {
|
|
if libc.Int32FromUint16((*TMem)(unsafe.Pointer(pRec)).Fflags)&int32(MEM_Int) == 0 { /*OPTIMIZATION-IF-FALSE*/
|
|
if libc.Int32FromUint16((*TMem)(unsafe.Pointer(pRec)).Fflags)&(libc.Int32FromInt32(MEM_Real)|libc.Int32FromInt32(MEM_IntReal)) == 0 {
|
|
if libc.Int32FromUint16((*TMem)(unsafe.Pointer(pRec)).Fflags)&int32(MEM_Str) != 0 {
|
|
_applyNumericAffinity(tls, pRec, int32(1))
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint8(affinity) <= int32(SQLITE_AFF_REAL) {
|
|
_sqlite3VdbeIntegerAffinity(tls, pRec)
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint8(affinity) == int32(SQLITE_AFF_TEXT) {
|
|
/* Only attempt the conversion to TEXT if there is an integer or real
|
|
** representation (blob and NULL do not get converted) but no string
|
|
** representation. It would be harmless to repeat the conversion if
|
|
** there is already a string rep, but it is pointless to waste those
|
|
** CPU cycles. */
|
|
if 0 == libc.Int32FromUint16((*TMem)(unsafe.Pointer(pRec)).Fflags)&int32(MEM_Str) { /*OPTIMIZATION-IF-FALSE*/
|
|
if libc.Int32FromUint16((*TMem)(unsafe.Pointer(pRec)).Fflags)&(libc.Int32FromInt32(MEM_Real)|libc.Int32FromInt32(MEM_Int)|libc.Int32FromInt32(MEM_IntReal)) != 0 {
|
|
_sqlite3VdbeMemStringify(tls, pRec, enc, uint8(1))
|
|
}
|
|
}
|
|
v1 = pRec + 20
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) & ^(libc.Int32FromInt32(MEM_Real) | libc.Int32FromInt32(MEM_Int) | libc.Int32FromInt32(MEM_IntReal)))
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Generate code that will evaluate all == and IN constraints for an
|
|
// ** index scan.
|
|
// **
|
|
// ** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c).
|
|
// ** Suppose the WHERE clause is this: a==5 AND b IN (1,2,3) AND c>5 AND c<10
|
|
// ** The index has as many as three equality constraints, but in this
|
|
// ** example, the third "c" value is an inequality. So only two
|
|
// ** constraints are coded. This routine will generate code to evaluate
|
|
// ** a==5 and b IN (1,2,3). The current values for a and b will be stored
|
|
// ** in consecutive registers and the index of the first register is returned.
|
|
// **
|
|
// ** In the example above nEq==2. But this subroutine works for any value
|
|
// ** of nEq including 0. If nEq==0, this routine is nearly a no-op.
|
|
// ** The only thing it does is allocate the pLevel->iMem memory cell and
|
|
// ** compute the affinity string.
|
|
// **
|
|
// ** The nExtraReg parameter is 0 or 1. It is 0 if all WHERE clause constraints
|
|
// ** are == or IN and are covered by the nEq. nExtraReg is 1 if there is
|
|
// ** an inequality constraint (such as the "c>=5 AND c<10" in the example) that
|
|
// ** occurs after the nEq quality constraints.
|
|
// **
|
|
// ** This routine allocates a range of nEq+nExtraReg memory cells and returns
|
|
// ** the index of the first memory cell in that range. The code that
|
|
// ** calls this routine will use that memory range to store keys for
|
|
// ** start and termination conditions of the loop.
|
|
// ** key value of the loop. If one or more IN operators appear, then
|
|
// ** this routine allocates an additional nEq memory cells for internal
|
|
// ** use.
|
|
// **
|
|
// ** Before returning, *pzAff is set to point to a buffer containing a
|
|
// ** copy of the column affinity string of the index allocated using
|
|
// ** sqlite3DbMalloc(). Except, entries in the copy of the string associated
|
|
// ** with equality constraints that use BLOB or NONE affinity are set to
|
|
// ** SQLITE_AFF_BLOB. This is to deal with SQL such as the following:
|
|
// **
|
|
// ** CREATE TABLE t1(a TEXT PRIMARY KEY, b);
|
|
// ** SELECT ... FROM t1 AS t2, t1 WHERE t1.a = t2.b;
|
|
// **
|
|
// ** In the example above, the index on t1(a) has TEXT affinity. But since
|
|
// ** the right hand side of the equality constraint (t2.b) has BLOB/NONE affinity,
|
|
// ** no conversion should be attempted before using a t2.b value as part of
|
|
// ** a key to search the index. Hence the first byte in the returned affinity
|
|
// ** string in this example would be set to SQLITE_AFF_BLOB.
|
|
// */
|
|
func _codeAllEqualityTerms(tls *libc.TLS, pParse uintptr, pLevel uintptr, bRev int32, nExtraReg int32, pzAff uintptr) (r int32) {
|
|
var iIdxCur, j, nReg, r1, regBase, v1 int32
|
|
var nEq, nSkip Tu16
|
|
var pIdx, pLoop, pRight, pTerm, v, zAff uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _ = iIdxCur, j, nEq, nReg, nSkip, pIdx, pLoop, pRight, pTerm, r1, regBase, v, zAff, v1 /* Number of left-most columns to skip */
|
|
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe /* Affinity string to return */
|
|
/* This module is only called on query plans that use an index. */
|
|
pLoop = (*TWhereLevel)(unsafe.Pointer(pLevel)).FpWLoop
|
|
nEq = (*(*struct {
|
|
FnEq Tu16
|
|
FnBtm Tu16
|
|
FnTop Tu16
|
|
FnDistinctCol Tu16
|
|
FpIndex uintptr
|
|
FpOrderBy uintptr
|
|
})(unsafe.Pointer(pLoop + 24))).FnEq
|
|
nSkip = (*TWhereLoop)(unsafe.Pointer(pLoop)).FnSkip
|
|
pIdx = (*(*struct {
|
|
FnEq Tu16
|
|
FnBtm Tu16
|
|
FnTop Tu16
|
|
FnDistinctCol Tu16
|
|
FpIndex uintptr
|
|
FpOrderBy uintptr
|
|
})(unsafe.Pointer(pLoop + 24))).FpIndex
|
|
/* Figure out how many memory cells we will need then allocate them.
|
|
*/
|
|
regBase = (*TParse)(unsafe.Pointer(pParse)).FnMem + int32(1)
|
|
nReg = libc.Int32FromUint16(nEq) + nExtraReg
|
|
**(**int32)(__ccgo_up(pParse + 60)) += nReg
|
|
zAff = _sqlite3DbStrDup(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, _sqlite3IndexAffinityStr(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pIdx))
|
|
if nSkip != 0 {
|
|
iIdxCur = (*TWhereLevel)(unsafe.Pointer(pLevel)).FiIdxCur
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Null), 0, regBase, regBase+libc.Int32FromUint16(nSkip)-int32(1))
|
|
if bRev != 0 {
|
|
v1 = int32(OP_Last)
|
|
} else {
|
|
v1 = int32(OP_Rewind)
|
|
}
|
|
_sqlite3VdbeAddOp1(tls, v, v1, iIdxCur)
|
|
j = _sqlite3VdbeAddOp0(tls, v, int32(OP_Goto))
|
|
if bRev != 0 {
|
|
v1 = int32(OP_SeekLT)
|
|
} else {
|
|
v1 = int32(OP_SeekGT)
|
|
}
|
|
(*TWhereLevel)(unsafe.Pointer(pLevel)).FaddrSkip = _sqlite3VdbeAddOp4Int(tls, v, v1, iIdxCur, 0, regBase, libc.Int32FromUint16(nSkip))
|
|
_sqlite3VdbeJumpHere(tls, v, j)
|
|
j = 0
|
|
for {
|
|
if !(j < libc.Int32FromUint16(nSkip)) {
|
|
break
|
|
}
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Column), iIdxCur, j, regBase+j)
|
|
goto _3
|
|
_3:
|
|
;
|
|
j = j + 1
|
|
}
|
|
}
|
|
/* Evaluate the equality constraints
|
|
*/
|
|
j = libc.Int32FromUint16(nSkip)
|
|
for {
|
|
if !(j < libc.Int32FromUint16(nEq)) {
|
|
break
|
|
}
|
|
pTerm = **(**uintptr)(__ccgo_up((*TWhereLoop)(unsafe.Pointer(pLoop)).FaLTerm + uintptr(j)*8))
|
|
/* The following testcase is true for indices with redundant columns.
|
|
** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
|
|
r1 = _codeEqualityTerm(tls, pParse, pTerm, pLevel, j, bRev, regBase+j)
|
|
if r1 != regBase+j {
|
|
if nReg == int32(1) {
|
|
_sqlite3ReleaseTempReg(tls, pParse, regBase)
|
|
regBase = r1
|
|
} else {
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Copy), r1, regBase+j)
|
|
}
|
|
}
|
|
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator)&int32(WO_IN) != 0 {
|
|
if (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr)).Fflags&uint32(EP_xIsSelect) != 0 {
|
|
/* No affinity ever needs to be (or should be) applied to a value
|
|
** from the RHS of an "? IN (SELECT ...)" expression. The
|
|
** sqlite3FindInIndex() routine has already ensured that the
|
|
** affinity of the comparison has been applied to the value. */
|
|
if zAff != 0 {
|
|
**(**uint8)(__ccgo_up(zAff + uintptr(j))) = uint8(SQLITE_AFF_BLOB)
|
|
}
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator)&int32(WO_ISNULL) == 0 {
|
|
pRight = (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr)).FpRight
|
|
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTerm)).FwtFlags)&int32(TERM_IS) == 0 && _sqlite3ExprCanBeNull(tls, pRight) != 0 {
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_IsNull), regBase+j, (*TWhereLevel)(unsafe.Pointer(pLevel)).FaddrBrk)
|
|
}
|
|
if (*TParse)(unsafe.Pointer(pParse)).FnErr == 0 {
|
|
if libc.Int32FromUint8(_sqlite3CompareAffinity(tls, pRight, **(**uint8)(__ccgo_up(zAff + uintptr(j))))) == int32(SQLITE_AFF_BLOB) {
|
|
**(**uint8)(__ccgo_up(zAff + uintptr(j))) = uint8(SQLITE_AFF_BLOB)
|
|
}
|
|
if _sqlite3ExprNeedsNoAffinityChange(tls, pRight, **(**uint8)(__ccgo_up(zAff + uintptr(j)))) != 0 {
|
|
**(**uint8)(__ccgo_up(zAff + uintptr(j))) = uint8(SQLITE_AFF_BLOB)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
goto _4
|
|
_4:
|
|
;
|
|
j = j + 1
|
|
}
|
|
**(**uintptr)(__ccgo_up(pzAff)) = zAff
|
|
return regBase
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** pExpr is a comparison operator. Return the type affinity that should
|
|
// ** be applied to both operands prior to doing the comparison.
|
|
// */
|
|
func _comparisonAffinity(tls *libc.TLS, pExpr uintptr) (r uint8) {
|
|
var aff uint8
|
|
_ = aff
|
|
aff = _sqlite3ExprAffinity(tls, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft)
|
|
if (*TExpr)(unsafe.Pointer(pExpr)).FpRight != 0 {
|
|
aff = _sqlite3CompareAffinity(tls, (*TExpr)(unsafe.Pointer(pExpr)).FpRight, aff)
|
|
} else {
|
|
if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&uint32(EP_xIsSelect) != uint32(0) {
|
|
aff = _sqlite3CompareAffinity(tls, (*(*TExprList_item)(unsafe.Pointer((*TSelect)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)))).FpEList + 8))).FpExpr, aff)
|
|
} else {
|
|
if libc.Int32FromUint8(aff) == 0 {
|
|
aff = uint8(SQLITE_AFF_BLOB)
|
|
}
|
|
}
|
|
}
|
|
return aff
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return true if any of the result-set columns in the compound query
|
|
// ** have incompatible affinities on one or more arms of the compound.
|
|
// */
|
|
func _compoundHasDifferentAffinities(tls *libc.TLS, p uintptr) (r int32) {
|
|
var aff uint8
|
|
var ii int32
|
|
var pList, pSub1 uintptr
|
|
_, _, _, _ = aff, ii, pList, pSub1
|
|
pList = (*TSelect)(unsafe.Pointer(p)).FpEList
|
|
ii = 0
|
|
for {
|
|
if !(ii < (*TExprList)(unsafe.Pointer(pList)).FnExpr) {
|
|
break
|
|
}
|
|
aff = _sqlite3ExprAffinity(tls, (*(*TExprList_item)(unsafe.Pointer(pList + 8 + uintptr(ii)*32))).FpExpr)
|
|
pSub1 = (*TSelect)(unsafe.Pointer(p)).FpPrior
|
|
for {
|
|
if !(pSub1 != 0) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint8(_sqlite3ExprAffinity(tls, (*(*TExprList_item)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pSub1)).FpEList + 8 + uintptr(ii)*32))).FpExpr)) != libc.Int32FromUint8(aff) {
|
|
return int32(1)
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
pSub1 = (*TSelect)(unsafe.Pointer(pSub1)).FpPrior
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return a pointer to the column affinity string associated with index
|
|
// ** pIdx. A column affinity string has one character for each column in
|
|
// ** the table, according to the affinity of the column:
|
|
// **
|
|
// ** Character Column affinity
|
|
// ** ------------------------------
|
|
// ** 'A' BLOB
|
|
// ** 'B' TEXT
|
|
// ** 'C' NUMERIC
|
|
// ** 'D' INTEGER
|
|
// ** 'F' REAL
|
|
// **
|
|
// ** An extra 'D' is appended to the end of the string to cover the
|
|
// ** rowid that appears as the last column in every index.
|
|
// **
|
|
// ** Memory for the buffer containing the column index affinity string
|
|
// ** is managed along with the rest of the Index structure. It will be
|
|
// ** released when sqlite3DeleteIndex() is called.
|
|
// */
|
|
func _computeIndexAffStr(tls *libc.TLS, db uintptr, pIdx uintptr) (r uintptr) {
|
|
var aff uint8
|
|
var n int32
|
|
var pTab uintptr
|
|
var x Ti16
|
|
_, _, _, _ = aff, n, pTab, x
|
|
pTab = (*TIndex)(unsafe.Pointer(pIdx)).FpTable
|
|
(*TIndex)(unsafe.Pointer(pIdx)).FzColAff = _sqlite3DbMallocRaw(tls, uintptr(0), libc.Uint64FromInt32(libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnColumn)+int32(1)))
|
|
if !((*TIndex)(unsafe.Pointer(pIdx)).FzColAff != 0) {
|
|
_sqlite3OomFault(tls, db)
|
|
return uintptr(0)
|
|
}
|
|
n = 0
|
|
for {
|
|
if !(n < libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnColumn)) {
|
|
break
|
|
}
|
|
x = **(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(n)*2))
|
|
if int32(x) >= 0 {
|
|
aff = (**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(x)*16))).Faffinity
|
|
} else {
|
|
if int32(x) == -int32(1) {
|
|
aff = uint8(SQLITE_AFF_INTEGER)
|
|
} else {
|
|
aff = _sqlite3ExprAffinity(tls, (*(*TExprList_item)(unsafe.Pointer((*TIndex)(unsafe.Pointer(pIdx)).FaColExpr + 8 + uintptr(n)*32))).FpExpr)
|
|
}
|
|
}
|
|
if libc.Int32FromUint8(aff) < int32(SQLITE_AFF_BLOB) {
|
|
aff = uint8(SQLITE_AFF_BLOB)
|
|
}
|
|
if libc.Int32FromUint8(aff) > int32(SQLITE_AFF_NUMERIC) {
|
|
aff = uint8(SQLITE_AFF_NUMERIC)
|
|
}
|
|
**(**uint8)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FzColAff + uintptr(n))) = aff
|
|
goto _1
|
|
_1:
|
|
;
|
|
n = n + 1
|
|
}
|
|
**(**uint8)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FzColAff + uintptr(n))) = uint8(0)
|
|
return (*TIndex)(unsafe.Pointer(pIdx)).FzColAff
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* The core implementation of the CONCAT(...) and CONCAT_WS(SEP,...)
|
|
// ** functions.
|
|
// **
|
|
// ** Return a string value that is the concatenation of all non-null
|
|
// ** entries in argv[]. Use zSep as the separator.
|
|
// */
|
|
func _concatFuncCore(tls *libc.TLS, context uintptr, argc int32, argv uintptr, nSep int32, zSep uintptr) {
|
|
var bNotNull, i, k int32
|
|
var j, n Ti64
|
|
var v, z uintptr
|
|
_, _, _, _, _, _, _ = bNotNull, i, j, k, n, v, z
|
|
n = 0
|
|
bNotNull = 0
|
|
i = 0
|
|
for {
|
|
if !(i < argc) {
|
|
break
|
|
}
|
|
n = n + int64(Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8))))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
n = n + int64(argc-libc.Int32FromInt32(1))*int64(nSep)
|
|
z = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(n+int64(1)))
|
|
if z == uintptr(0) {
|
|
Xsqlite3_result_error_nomem(tls, context)
|
|
return
|
|
}
|
|
j = 0
|
|
i = 0
|
|
for {
|
|
if !(i < argc) {
|
|
break
|
|
}
|
|
if Xsqlite3_value_type(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8))) != int32(SQLITE_NULL) {
|
|
k = Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8)))
|
|
v = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8)))
|
|
if v != uintptr(0) {
|
|
if bNotNull != 0 && nSep > 0 {
|
|
libc.Xmemcpy(tls, z+uintptr(j), zSep, libc.Uint64FromInt32(nSep))
|
|
j = j + int64(nSep)
|
|
}
|
|
libc.Xmemcpy(tls, z+uintptr(j), v, libc.Uint64FromInt32(k))
|
|
j = j + int64(k)
|
|
bNotNull = int32(1)
|
|
}
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
**(**uint8)(__ccgo_up(z + uintptr(j))) = uint8(0)
|
|
Xsqlite3_result_text64(tls, context, z, libc.Uint64FromInt64(j), __ccgo_fp(Xsqlite3_free), uint8(SQLITE_UTF8_ZT))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Add a new entry to the pConst object. Except, do not add duplicate
|
|
// ** pColumn entries. Also, do not add if doing so would not be appropriate.
|
|
// **
|
|
// ** The caller guarantees the pColumn is a column and pValue is a constant.
|
|
// ** This routine has to do some additional checks before completing the
|
|
// ** insert.
|
|
// */
|
|
func _constInsert(tls *libc.TLS, pConst uintptr, pColumn uintptr, pValue uintptr, pExpr uintptr) {
|
|
var i int32
|
|
var pE2 uintptr
|
|
_, _ = i, pE2
|
|
if (*TExpr)(unsafe.Pointer(pColumn)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_FixedCol)) != uint32(0) {
|
|
return
|
|
}
|
|
if libc.Int32FromUint8(_sqlite3ExprAffinity(tls, pValue)) != 0 {
|
|
return
|
|
}
|
|
if !(_sqlite3IsBinary(tls, _sqlite3ExprCompareCollSeq(tls, (*TWhereConst)(unsafe.Pointer(pConst)).FpParse, pExpr)) != 0) {
|
|
return
|
|
}
|
|
/* 2018-10-25 ticket [cf5ed20f]
|
|
** Make sure the same pColumn is not inserted more than once */
|
|
i = 0
|
|
for {
|
|
if !(i < (*TWhereConst)(unsafe.Pointer(pConst)).FnConst) {
|
|
break
|
|
}
|
|
pE2 = **(**uintptr)(__ccgo_up((*TWhereConst)(unsafe.Pointer(pConst)).FapExpr + uintptr(i*int32(2))*8))
|
|
if (*TExpr)(unsafe.Pointer(pE2)).FiTable == (*TExpr)(unsafe.Pointer(pColumn)).FiTable && int32((*TExpr)(unsafe.Pointer(pE2)).FiColumn) == int32((*TExpr)(unsafe.Pointer(pColumn)).FiColumn) {
|
|
return /* Already present. Return without doing anything. */
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if libc.Int32FromUint8(_sqlite3ExprAffinity(tls, pColumn)) <= int32(SQLITE_AFF_BLOB) {
|
|
(*TWhereConst)(unsafe.Pointer(pConst)).FbHasAffBlob = int32(1)
|
|
}
|
|
(*TWhereConst)(unsafe.Pointer(pConst)).FnConst = (*TWhereConst)(unsafe.Pointer(pConst)).FnConst + 1
|
|
(*TWhereConst)(unsafe.Pointer(pConst)).FapExpr = _sqlite3DbReallocOrFree(tls, (*TParse)(unsafe.Pointer((*TWhereConst)(unsafe.Pointer(pConst)).FpParse)).Fdb, (*TWhereConst)(unsafe.Pointer(pConst)).FapExpr, uint64(libc.Uint64FromInt32((*TWhereConst)(unsafe.Pointer(pConst)).FnConst*int32(2))*uint64(8)))
|
|
if (*TWhereConst)(unsafe.Pointer(pConst)).FapExpr == uintptr(0) {
|
|
(*TWhereConst)(unsafe.Pointer(pConst)).FnConst = 0
|
|
} else {
|
|
**(**uintptr)(__ccgo_up((*TWhereConst)(unsafe.Pointer(pConst)).FapExpr + uintptr((*TWhereConst)(unsafe.Pointer(pConst)).FnConst*int32(2)-int32(2))*8)) = pColumn
|
|
**(**uintptr)(__ccgo_up((*TWhereConst)(unsafe.Pointer(pConst)).FapExpr + uintptr((*TWhereConst)(unsafe.Pointer(pConst)).FnConst*int32(2)-int32(1))*8)) = pValue
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Analyze a term that consists of two or more OR-connected
|
|
// ** subterms. So in:
|
|
// **
|
|
// ** ... WHERE (a=5) AND (b=7 OR c=9 OR d=13) AND (d=13)
|
|
// ** ^^^^^^^^^^^^^^^^^^^^
|
|
// **
|
|
// ** This routine analyzes terms such as the middle term in the above example.
|
|
// ** A WhereOrTerm object is computed and attached to the term under
|
|
// ** analysis, regardless of the outcome of the analysis. Hence:
|
|
// **
|
|
// ** WhereTerm.wtFlags |= TERM_ORINFO
|
|
// ** WhereTerm.u.pOrInfo = a dynamically allocated WhereOrTerm object
|
|
// **
|
|
// ** The term being analyzed must have two or more of OR-connected subterms.
|
|
// ** A single subterm might be a set of AND-connected sub-subterms.
|
|
// ** Examples of terms under analysis:
|
|
// **
|
|
// ** (A) t1.x=t2.y OR t1.x=t2.z OR t1.y=15 OR t1.z=t3.a+5
|
|
// ** (B) x=expr1 OR expr2=x OR x=expr3
|
|
// ** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15)
|
|
// ** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*')
|
|
// ** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6)
|
|
// ** (F) x>A OR (x=A AND y>=B)
|
|
// **
|
|
// ** CASE 1:
|
|
// **
|
|
// ** If all subterms are of the form T.C=expr for some single column of C and
|
|
// ** a single table T (as shown in example B above) then create a new virtual
|
|
// ** term that is an equivalent IN expression. In other words, if the term
|
|
// ** being analyzed is:
|
|
// **
|
|
// ** x = expr1 OR expr2 = x OR x = expr3
|
|
// **
|
|
// ** then create a new virtual term like this:
|
|
// **
|
|
// ** x IN (expr1,expr2,expr3)
|
|
// **
|
|
// ** CASE 2:
|
|
// **
|
|
// ** If there are exactly two disjuncts and one side has x>A and the other side
|
|
// ** has x=A (for the same x and A) then add a new virtual conjunct term to the
|
|
// ** WHERE clause of the form "x>=A". Example:
|
|
// **
|
|
// ** x>A OR (x=A AND y>B) adds: x>=A
|
|
// **
|
|
// ** The added conjunct can sometimes be helpful in query planning.
|
|
// **
|
|
// ** CASE 3:
|
|
// **
|
|
// ** If all subterms are indexable by a single table T, then set
|
|
// **
|
|
// ** WhereTerm.eOperator = WO_OR
|
|
// ** WhereTerm.u.pOrInfo->indexable |= the cursor number for table T
|
|
// **
|
|
// ** A subterm is "indexable" if it is of the form
|
|
// ** "T.C <op> <expr>" where C is any column of table T and
|
|
// ** <op> is one of "=", "<", "<=", ">", ">=", "IS NULL", or "IN".
|
|
// ** A subterm is also indexable if it is an AND of two or more
|
|
// ** subsubterms at least one of which is indexable. Indexable AND
|
|
// ** subterms have their eOperator set to WO_AND and they have
|
|
// ** u.pAndInfo set to a dynamically allocated WhereAndTerm object.
|
|
// **
|
|
// ** From another point of view, "indexable" means that the subterm could
|
|
// ** potentially be used with an index if an appropriate index exists.
|
|
// ** This analysis does not consider whether or not the index exists; that
|
|
// ** is decided elsewhere. This analysis only looks at whether subterms
|
|
// ** appropriate for indexing exist.
|
|
// **
|
|
// ** All examples A through E above satisfy case 3. But if a term
|
|
// ** also satisfies case 1 (such as B) we know that the optimizer will
|
|
// ** always prefer case 1, so in that case we pretend that case 3 is not
|
|
// ** satisfied.
|
|
// **
|
|
// ** It might be the case that multiple tables are indexable. For example,
|
|
// ** (E) above is indexable on tables P, Q, and R.
|
|
// **
|
|
// ** Terms that satisfy case 3 are candidates for lookup by using
|
|
// ** separate indices to find rowids for each subterm and composing
|
|
// ** the union of all rowids using a RowSet object. This is similar
|
|
// ** to "bitmap indices" in other database engines.
|
|
// **
|
|
// ** OTHERWISE:
|
|
// **
|
|
// ** If none of cases 1, 2, or 3 apply, then leave the eOperator set to
|
|
// ** zero. This term is not useful for search.
|
|
// */
|
|
func _exprAnalyzeOrTerm(tls *libc.TLS, pSrc uintptr, pWC uintptr, idxTerm int32) {
|
|
var affLeft, affRight, i, iColumn, iCursor, iOne, iTwo, idxNew, j, j1, okToChngToIN, v7, v9 int32
|
|
var b, b1, chngToIN, indexable TBitmask
|
|
var db, pAndInfo, pAndTerm, pAndWC, pDup, pExpr, pLeft, pLeft1, pList, pNew, pOne, pOrInfo, pOrTerm, pOrWc, pOther, pParse, pTerm, pTwo, pWInfo, v1, v2 uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = affLeft, affRight, b, b1, chngToIN, db, i, iColumn, iCursor, iOne, iTwo, idxNew, indexable, j, j1, okToChngToIN, pAndInfo, pAndTerm, pAndWC, pDup, pExpr, pLeft, pLeft1, pList, pNew, pOne, pOrInfo, pOrTerm, pOrWc, pOther, pParse, pTerm, pTwo, pWInfo, v1, v2, v7, v9
|
|
pWInfo = (*TWhereClause)(unsafe.Pointer(pWC)).FpWInfo /* WHERE clause processing context */
|
|
pParse = (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpParse /* Parser context */
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb /* Database connection */
|
|
pTerm = (*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(idxTerm)*56 /* The term to be analyzed */
|
|
pExpr = (*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr /* Tables that are indexable, satisfying case 2 */
|
|
/*
|
|
** Break the OR clause into its separate subterms. The subterms are
|
|
** stored in a WhereClause structure containing within the WhereOrInfo
|
|
** object that is attached to the original OR clause term.
|
|
*/
|
|
v1 = _sqlite3DbMallocZero(tls, db, uint64(496))
|
|
pOrInfo = v1
|
|
*(*uintptr)(unsafe.Pointer(pTerm + 32)) = v1
|
|
if pOrInfo == uintptr(0) {
|
|
return
|
|
}
|
|
v1 = pTerm + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(TERM_ORINFO))
|
|
pOrWc = pOrInfo
|
|
libc.Xmemset(tls, pOrWc+40, 0, uint64(448))
|
|
_sqlite3WhereClauseInit(tls, pOrWc, pWInfo)
|
|
_sqlite3WhereSplit(tls, pOrWc, pExpr, uint8(TK_OR))
|
|
_sqlite3WhereExprAnalyze(tls, pSrc, pOrWc)
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
|
|
return
|
|
}
|
|
/*
|
|
** Compute the set of tables that might satisfy cases 1 or 3.
|
|
*/
|
|
indexable = ^libc.Uint64FromInt32(0)
|
|
chngToIN = ^libc.Uint64FromInt32(0)
|
|
i = (*TWhereClause)(unsafe.Pointer(pOrWc)).FnTerm - int32(1)
|
|
pOrTerm = (*TWhereClause)(unsafe.Pointer(pOrWc)).Fa
|
|
for {
|
|
if !(i >= 0 && indexable != 0) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FeOperator)&int32(WO_SINGLE) == 0 {
|
|
chngToIN = uint64(0)
|
|
pAndInfo = _sqlite3DbMallocRawNN(tls, db, uint64(488))
|
|
if pAndInfo != 0 {
|
|
b = uint64(0)
|
|
*(*uintptr)(unsafe.Pointer(pOrTerm + 32)) = pAndInfo
|
|
v1 = pOrTerm + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(TERM_ANDINFO))
|
|
(*TWhereTerm)(unsafe.Pointer(pOrTerm)).FeOperator = uint16(WO_AND)
|
|
(*TWhereTerm)(unsafe.Pointer(pOrTerm)).FleftCursor = -int32(1)
|
|
pAndWC = pAndInfo
|
|
libc.Xmemset(tls, pAndWC+40, 0, uint64(448))
|
|
_sqlite3WhereClauseInit(tls, pAndWC, (*TWhereClause)(unsafe.Pointer(pWC)).FpWInfo)
|
|
_sqlite3WhereSplit(tls, pAndWC, (*TWhereTerm)(unsafe.Pointer(pOrTerm)).FpExpr, uint8(TK_AND))
|
|
_sqlite3WhereExprAnalyze(tls, pSrc, pAndWC)
|
|
(*TWhereClause)(unsafe.Pointer(pAndWC)).FpOuter = pWC
|
|
if !((*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0) {
|
|
j = 0
|
|
pAndTerm = (*TWhereClause)(unsafe.Pointer(pAndWC)).Fa
|
|
for {
|
|
if !(j < (*TWhereClause)(unsafe.Pointer(pAndWC)).FnTerm) {
|
|
break
|
|
}
|
|
if _allowedOp(tls, libc.Int32FromUint8((*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pAndTerm)).FpExpr)).Fop)) != 0 || libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pAndTerm)).FeOperator) == int32(WO_AUX) {
|
|
b = b | _sqlite3WhereGetMask(tls, pWInfo+592, (*TWhereTerm)(unsafe.Pointer(pAndTerm)).FleftCursor)
|
|
}
|
|
goto _5
|
|
_5:
|
|
;
|
|
j = j + 1
|
|
pAndTerm += 56
|
|
}
|
|
}
|
|
indexable = indexable & b
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FwtFlags)&int32(TERM_COPIED) != 0 {
|
|
/* Skip this term for now. We revisit it when we process the
|
|
** corresponding TERM_VIRTUAL term */
|
|
} else {
|
|
b1 = _sqlite3WhereGetMask(tls, pWInfo+592, (*TWhereTerm)(unsafe.Pointer(pOrTerm)).FleftCursor)
|
|
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FwtFlags)&int32(TERM_VIRTUAL) != 0 {
|
|
pOther = (*TWhereClause)(unsafe.Pointer(pOrWc)).Fa + uintptr((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FiParent)*56
|
|
b1 = b1 | _sqlite3WhereGetMask(tls, pWInfo+592, (*TWhereTerm)(unsafe.Pointer(pOther)).FleftCursor)
|
|
}
|
|
indexable = indexable & b1
|
|
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FeOperator)&int32(WO_EQ) == 0 {
|
|
chngToIN = uint64(0)
|
|
} else {
|
|
chngToIN = chngToIN & b1
|
|
}
|
|
}
|
|
}
|
|
goto _3
|
|
_3:
|
|
;
|
|
i = i - 1
|
|
pOrTerm += 56
|
|
}
|
|
/*
|
|
** Record the set of tables that satisfy case 3. The set might be
|
|
** empty.
|
|
*/
|
|
(*TWhereOrInfo)(unsafe.Pointer(pOrInfo)).Findexable = indexable
|
|
(*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator = uint16(WO_OR)
|
|
(*TWhereTerm)(unsafe.Pointer(pTerm)).FleftCursor = -int32(1)
|
|
if indexable != 0 {
|
|
(*TWhereClause)(unsafe.Pointer(pWC)).FhasOr = uint8(1)
|
|
}
|
|
/* For a two-way OR, attempt to implementation case 2.
|
|
*/
|
|
if indexable != 0 && (*TWhereClause)(unsafe.Pointer(pOrWc)).FnTerm == int32(2) {
|
|
iOne = 0
|
|
for {
|
|
v7 = iOne
|
|
iOne = iOne + 1
|
|
v1 = _whereNthSubterm(tls, (*TWhereClause)(unsafe.Pointer(pOrWc)).Fa, v7)
|
|
pOne = v1
|
|
if !(v1 != uintptr(0)) {
|
|
break
|
|
}
|
|
iTwo = 0
|
|
for {
|
|
v9 = iTwo
|
|
iTwo = iTwo + 1
|
|
v2 = _whereNthSubterm(tls, (*TWhereClause)(unsafe.Pointer(pOrWc)).Fa+1*56, v9)
|
|
pTwo = v2
|
|
if !(v2 != uintptr(0)) {
|
|
break
|
|
}
|
|
_whereCombineDisjuncts(tls, pSrc, pWC, pOne, pTwo)
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
** chngToIN holds a set of tables that *might* satisfy case 1. But
|
|
** we have to do some additional checking to see if case 1 really
|
|
** is satisfied.
|
|
**
|
|
** chngToIN will hold either 0, 1, or 2 bits. The 0-bit case means
|
|
** that there is no possibility of transforming the OR clause into an
|
|
** IN operator because one or more terms in the OR clause contain
|
|
** something other than == on a column in the single table. The 1-bit
|
|
** case means that every term of the OR clause is of the form
|
|
** "table.column=expr" for some single table. The one bit that is set
|
|
** will correspond to the common table. We still need to check to make
|
|
** sure the same column is used on all terms. The 2-bit case is when
|
|
** the all terms are of the form "table1.column=table2.column". It
|
|
** might be possible to form an IN operator with either table1.column
|
|
** or table2.column as the LHS if either is common to every term of
|
|
** the OR clause.
|
|
**
|
|
** Note that terms of the form "table.column1=table.column2" (the
|
|
** same table on both sizes of the ==) cannot be optimized.
|
|
*/
|
|
if chngToIN != 0 {
|
|
okToChngToIN = 0 /* True if the conversion to IN is valid */
|
|
iColumn = -int32(1) /* Column index on lhs of IN operator */
|
|
iCursor = -int32(1) /* Table cursor common to all terms */
|
|
j1 = 0 /* Loop counter */
|
|
/* Search for a table and column that appears on one side or the
|
|
** other of the == operator in every subterm. That table and column
|
|
** will be recorded in iCursor and iColumn. There might not be any
|
|
** such table and column. Set okToChngToIN if an appropriate table
|
|
** and column is found but leave okToChngToIN false if not found.
|
|
*/
|
|
j1 = 0
|
|
for {
|
|
if !(j1 < int32(2) && !(okToChngToIN != 0)) {
|
|
break
|
|
}
|
|
pLeft = uintptr(0)
|
|
pOrTerm = (*TWhereClause)(unsafe.Pointer(pOrWc)).Fa
|
|
i = (*TWhereClause)(unsafe.Pointer(pOrWc)).FnTerm - int32(1)
|
|
for {
|
|
if !(i >= 0) {
|
|
break
|
|
}
|
|
v1 = pOrTerm + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) & ^libc.Int32FromInt32(TERM_OK))
|
|
if (*TWhereTerm)(unsafe.Pointer(pOrTerm)).FleftCursor == iCursor {
|
|
/* This is the 2-bit case and we are on the second iteration and
|
|
** current term is from the first iteration. So skip this term. */
|
|
goto _11
|
|
}
|
|
if chngToIN&_sqlite3WhereGetMask(tls, pWInfo+592, (*TWhereTerm)(unsafe.Pointer(pOrTerm)).FleftCursor) == uint64(0) {
|
|
/* This term must be of the form t1.a==t2.b where t2 is in the
|
|
** chngToIN set but t1 is not. This term will be either preceded
|
|
** or followed by an inverted copy (t2.b==t1.a). Skip this term
|
|
** and use its inversion. */
|
|
goto _11
|
|
}
|
|
iColumn = (*(*struct {
|
|
FleftColumn int32
|
|
FiField int32
|
|
})(unsafe.Pointer(pOrTerm + 32))).FleftColumn
|
|
iCursor = (*TWhereTerm)(unsafe.Pointer(pOrTerm)).FleftCursor
|
|
pLeft = (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FpExpr)).FpLeft
|
|
break
|
|
goto _11
|
|
_11:
|
|
;
|
|
i = i - 1
|
|
pOrTerm += 56
|
|
}
|
|
if i < 0 {
|
|
/* No candidate table+column was found. This can only occur
|
|
** on the second iteration */
|
|
break
|
|
}
|
|
/* We have found a candidate table and column. Check to see if that
|
|
** table and column is common to every term in the OR clause */
|
|
okToChngToIN = int32(1)
|
|
for {
|
|
if !(i >= 0 && okToChngToIN != 0) {
|
|
break
|
|
}
|
|
if (*TWhereTerm)(unsafe.Pointer(pOrTerm)).FleftCursor != iCursor {
|
|
v1 = pOrTerm + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) & ^libc.Int32FromInt32(TERM_OK))
|
|
} else {
|
|
if (*(*struct {
|
|
FleftColumn int32
|
|
FiField int32
|
|
})(unsafe.Pointer(pOrTerm + 32))).FleftColumn != iColumn || iColumn == -int32(2) && _sqlite3ExprCompare(tls, pParse, (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FpExpr)).FpLeft, pLeft, -int32(1)) != 0 {
|
|
okToChngToIN = 0
|
|
} else {
|
|
/* If the right-hand side is also a column, then the affinities
|
|
** of both right and left sides must be such that no type
|
|
** conversions are required on the right. (Ticket #2249)
|
|
*/
|
|
affRight = libc.Int32FromUint8(_sqlite3ExprAffinity(tls, (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FpExpr)).FpRight))
|
|
affLeft = libc.Int32FromUint8(_sqlite3ExprAffinity(tls, (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FpExpr)).FpLeft))
|
|
if affRight != 0 && affRight != affLeft {
|
|
okToChngToIN = 0
|
|
} else {
|
|
v1 = pOrTerm + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(TERM_OK))
|
|
}
|
|
}
|
|
}
|
|
goto _13
|
|
_13:
|
|
;
|
|
i = i - 1
|
|
pOrTerm += 56
|
|
}
|
|
goto _10
|
|
_10:
|
|
;
|
|
j1 = j1 + 1
|
|
}
|
|
/* At this point, okToChngToIN is true if original pTerm satisfies
|
|
** case 1. In that case, construct a new virtual term that is
|
|
** pTerm converted into an IN operator.
|
|
*/
|
|
if okToChngToIN != 0 { /* A transient duplicate expression */
|
|
pList = uintptr(0) /* The RHS of the IN operator */
|
|
pLeft1 = uintptr(0) /* The complete IN operator */
|
|
i = (*TWhereClause)(unsafe.Pointer(pOrWc)).FnTerm - int32(1)
|
|
pOrTerm = (*TWhereClause)(unsafe.Pointer(pOrWc)).Fa
|
|
for {
|
|
if !(i >= 0) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FwtFlags)&int32(TERM_OK) == 0 {
|
|
goto _16
|
|
}
|
|
pDup = _sqlite3ExprDup(tls, db, (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FpExpr)).FpRight, 0)
|
|
pList = _sqlite3ExprListAppend(tls, (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpParse, pList, pDup)
|
|
pLeft1 = (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FpExpr)).FpLeft
|
|
goto _16
|
|
_16:
|
|
;
|
|
i = i - 1
|
|
pOrTerm += 56
|
|
}
|
|
pDup = _sqlite3ExprDup(tls, db, pLeft1, 0)
|
|
pNew = _sqlite3PExpr(tls, pParse, int32(TK_IN), pDup, uintptr(0))
|
|
if pNew != 0 {
|
|
_transferJoinMarkings(tls, pNew, pExpr)
|
|
*(*uintptr)(unsafe.Pointer(pNew + 32)) = pList
|
|
idxNew = _whereClauseInsert(tls, pWC, pNew, libc.Uint16FromInt32(libc.Int32FromInt32(TERM_VIRTUAL)|libc.Int32FromInt32(TERM_DYNAMIC)))
|
|
_exprAnalyze(tls, pSrc, pWC, idxNew)
|
|
/* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where reused */
|
|
_markTermAsChild(tls, pWC, idxNew, idxTerm)
|
|
} else {
|
|
_sqlite3ExprListDelete(tls, db, pList)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Argument pExpr is an (?, ?...) IN(...) expression. This
|
|
// ** function allocates and returns a nul-terminated string containing
|
|
// ** the affinities to be used for each column of the comparison.
|
|
// **
|
|
// ** It is the responsibility of the caller to ensure that the returned
|
|
// ** string is eventually freed using sqlite3DbFree().
|
|
// */
|
|
func _exprINAffinity(tls *libc.TLS, pParse uintptr, pExpr uintptr) (r uintptr) {
|
|
var a uint8
|
|
var i, nVal int32
|
|
var pA, pLeft, pSelect, zRet, v1 uintptr
|
|
_, _, _, _, _, _, _, _ = a, i, nVal, pA, pLeft, pSelect, zRet, v1
|
|
pLeft = (*TExpr)(unsafe.Pointer(pExpr)).FpLeft
|
|
nVal = _sqlite3ExprVectorSize(tls, pLeft)
|
|
if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&uint32(EP_xIsSelect) != uint32(0) {
|
|
v1 = *(*uintptr)(unsafe.Pointer(pExpr + 32))
|
|
} else {
|
|
v1 = uintptr(0)
|
|
}
|
|
pSelect = v1
|
|
zRet = _sqlite3DbMallocRaw(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, libc.Uint64FromInt64(int64(1)+int64(nVal)))
|
|
if zRet != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < nVal) {
|
|
break
|
|
}
|
|
pA = _sqlite3VectorFieldSubexpr(tls, pLeft, i)
|
|
a = _sqlite3ExprAffinity(tls, pA)
|
|
if pSelect != 0 {
|
|
**(**uint8)(__ccgo_up(zRet + uintptr(i))) = _sqlite3CompareAffinity(tls, (*(*TExprList_item)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pSelect)).FpEList + 8 + uintptr(i)*32))).FpExpr, a)
|
|
} else {
|
|
**(**uint8)(__ccgo_up(zRet + uintptr(i))) = a
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
**(**uint8)(__ccgo_up(zRet + uintptr(nVal))) = uint8('\000')
|
|
}
|
|
return zRet
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return true if all expressions in the expression-list passed as the
|
|
// ** only argument are both constant and have no affinity.
|
|
// */
|
|
func _exprListIsNoAffinity(tls *libc.TLS, pParse uintptr, pRow uintptr) (r int32) {
|
|
var ii int32
|
|
var pExpr uintptr
|
|
_, _ = ii, pExpr
|
|
if _exprListIsConstant(tls, pParse, pRow) == 0 {
|
|
return 0
|
|
}
|
|
ii = 0
|
|
for {
|
|
if !(ii < (*TExprList)(unsafe.Pointer(pRow)).FnExpr) {
|
|
break
|
|
}
|
|
pExpr = (*(*TExprList_item)(unsafe.Pointer(pRow + 8 + uintptr(ii)*32))).FpExpr
|
|
if 0 != libc.Int32FromUint8(_sqlite3ExprAffinity(tls, pExpr)) {
|
|
return 0
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
return int32(1)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return an Expr object that refers to a memory register corresponding
|
|
// ** to column iCol of table pTab.
|
|
// **
|
|
// ** regBase is the first of an array of register that contains the data
|
|
// ** for pTab. regBase itself holds the rowid. regBase+1 holds the first
|
|
// ** column. regBase+2 holds the second column, and so forth.
|
|
// */
|
|
func _exprTableRegister(tls *libc.TLS, pParse uintptr, pTab uintptr, regBase int32, iCol Ti16) (r uintptr) {
|
|
var db, pCol, pExpr, zColl uintptr
|
|
_, _, _, _ = db, pCol, pExpr, zColl
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
pExpr = _sqlite3Expr(tls, db, int32(TK_REGISTER), uintptr(0))
|
|
if pExpr != 0 {
|
|
if int32(iCol) >= 0 && int32(iCol) != int32((*TTable)(unsafe.Pointer(pTab)).FiPKey) {
|
|
pCol = (*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(iCol)*16
|
|
(*TExpr)(unsafe.Pointer(pExpr)).FiTable = regBase + int32(_sqlite3TableColumnToStorage(tls, pTab, iCol)) + int32(1)
|
|
(*TExpr)(unsafe.Pointer(pExpr)).FaffExpr = (*TColumn)(unsafe.Pointer(pCol)).Faffinity
|
|
zColl = _sqlite3ColumnColl(tls, pCol)
|
|
if zColl == uintptr(0) {
|
|
zColl = (*TCollSeq)(unsafe.Pointer((*Tsqlite3)(unsafe.Pointer(db)).FpDfltColl)).FzName
|
|
}
|
|
pExpr = _sqlite3ExprAddCollateString(tls, pParse, pExpr, zColl)
|
|
} else {
|
|
(*TExpr)(unsafe.Pointer(pExpr)).FiTable = regBase
|
|
(*TExpr)(unsafe.Pointer(pExpr)).FaffExpr = uint8(SQLITE_AFF_INTEGER)
|
|
}
|
|
}
|
|
return pExpr
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Gobble up the first bareword or quoted word from the input buffer zIn.
|
|
// ** Return a pointer to the character immediately following the last in
|
|
// ** the gobbled word if successful, or a NULL pointer otherwise (failed
|
|
// ** to find close-quote character).
|
|
// **
|
|
// ** Before returning, set pzOut to point to a new buffer containing a
|
|
// ** nul-terminated, dequoted copy of the gobbled word. If the word was
|
|
// ** quoted, *pbQuoted is also set to 1 before returning.
|
|
// **
|
|
// ** If *pRc is other than SQLITE_OK when this function is called, it is
|
|
// ** a no-op (NULL is returned). Otherwise, if an OOM occurs within this
|
|
// ** function, *pRc is set to SQLITE_NOMEM before returning. *pRc is *not*
|
|
// ** set if a parse error (failed to find close quote) occurs.
|
|
// */
|
|
func _fts5ConfigGobbleWord(tls *libc.TLS, pRc uintptr, zIn uintptr, pzOut uintptr, pbQuoted uintptr) (r uintptr) {
|
|
var ii int32
|
|
var nIn Tsqlite3_int64
|
|
var zOut, zRet uintptr
|
|
_, _, _, _ = ii, nIn, zOut, zRet
|
|
zRet = uintptr(0)
|
|
nIn = libc.Int64FromUint64(libc.Xstrlen(tls, zIn))
|
|
zOut = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(nIn+int64(1)))
|
|
**(**int32)(__ccgo_up(pbQuoted)) = 0
|
|
**(**uintptr)(__ccgo_up(pzOut)) = uintptr(0)
|
|
if zOut == uintptr(0) {
|
|
**(**int32)(__ccgo_up(pRc)) = int32(SQLITE_NOMEM)
|
|
} else {
|
|
libc.Xmemcpy(tls, zOut, zIn, libc.Uint64FromInt64(nIn+libc.Int64FromInt32(1)))
|
|
if _fts5_isopenquote(tls, **(**uint8)(__ccgo_up(zOut))) != 0 {
|
|
ii = _fts5Dequote(tls, zOut)
|
|
zRet = zIn + uintptr(ii)
|
|
**(**int32)(__ccgo_up(pbQuoted)) = int32(1)
|
|
} else {
|
|
zRet = _fts5ConfigSkipBareword(tls, zIn)
|
|
if zRet != 0 {
|
|
**(**uint8)(__ccgo_up(zOut + uintptr(int64(zRet)-int64(zIn)))) = uint8('\000')
|
|
}
|
|
}
|
|
}
|
|
if zRet == uintptr(0) {
|
|
Xsqlite3_free(tls, zOut)
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(pzOut)) = zOut
|
|
}
|
|
return zRet
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of fts5_locale(LOCALE, TEXT) function.
|
|
// **
|
|
// ** If parameter LOCALE is NULL, or a zero-length string, then a copy of
|
|
// ** TEXT is returned. Otherwise, both LOCALE and TEXT are interpreted as
|
|
// ** text, and the value returned is a blob consisting of:
|
|
// **
|
|
// ** * The 4 bytes 0x00, 0xE0, 0xB2, 0xEb (FTS5_LOCALE_HEADER).
|
|
// ** * The LOCALE, as utf-8 text, followed by
|
|
// ** * 0x00, followed by
|
|
// ** * The TEXT, as utf-8 text.
|
|
// **
|
|
// ** There is no final nul-terminator following the TEXT value.
|
|
// */
|
|
func _fts5LocaleFunc(tls *libc.TLS, pCtx uintptr, nArg int32, apArg uintptr) {
|
|
var nBlob, nLocale, nText Ti64
|
|
var p, pBlob, pCsr, zLocale, zText, v1 uintptr
|
|
_, _, _, _, _, _, _, _, _ = nBlob, nLocale, nText, p, pBlob, pCsr, zLocale, zText, v1
|
|
zLocale = uintptr(0)
|
|
nLocale = 0
|
|
zText = uintptr(0)
|
|
nText = 0
|
|
_ = nArg
|
|
zLocale = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(apArg)))
|
|
nLocale = int64(Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(apArg))))
|
|
zText = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(apArg + 1*8)))
|
|
nText = int64(Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(apArg + 1*8))))
|
|
if zLocale == uintptr(0) || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zLocale))) == int32('\000') {
|
|
Xsqlite3_result_text(tls, pCtx, zText, int32(nText), uintptr(-libc.Int32FromInt32(1)))
|
|
} else {
|
|
p = Xsqlite3_user_data(tls, pCtx)
|
|
pBlob = uintptr(0)
|
|
pCsr = uintptr(0)
|
|
nBlob = 0
|
|
nBlob = int64(libc.Int32FromInt64(16)) + nLocale + int64(1) + nText
|
|
pBlob = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(nBlob))
|
|
if pBlob == uintptr(0) {
|
|
Xsqlite3_result_error_nomem(tls, pCtx)
|
|
return
|
|
}
|
|
pCsr = pBlob
|
|
libc.Xmemcpy(tls, pCsr, p+96, libc.Uint64FromInt32(libc.Int32FromInt64(16)))
|
|
pCsr = pCsr + uintptr(libc.Int32FromInt64(16))
|
|
libc.Xmemcpy(tls, pCsr, zLocale, libc.Uint64FromInt64(nLocale))
|
|
pCsr = pCsr + uintptr(nLocale)
|
|
v1 = pCsr
|
|
pCsr = pCsr + 1
|
|
**(**Tu8)(__ccgo_up(v1)) = uint8(0x00)
|
|
if zText != 0 {
|
|
libc.Xmemcpy(tls, pCsr, zText, libc.Uint64FromInt64(nText))
|
|
}
|
|
Xsqlite3_result_blob(tls, pCtx, pBlob, int32(nBlob), __ccgo_fp(Xsqlite3_free))
|
|
}
|
|
}
|
|
|
|
func _fts5PorterCb(tls *libc.TLS, pCtx uintptr, tflags int32, pToken uintptr, nToken int32, iStart int32, iEnd int32) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var aBuf, p uintptr
|
|
var c uint8
|
|
var v1 int32
|
|
var _ /* nBuf at bp+0 */ int32
|
|
_, _, _, _ = aBuf, c, p, v1
|
|
p = pCtx
|
|
if nToken > int32(FTS5_PORTER_MAX_TOKEN) || nToken < int32(3) {
|
|
goto pass_through
|
|
}
|
|
aBuf = (*TPorterContext)(unsafe.Pointer(p)).FaBuf
|
|
**(**int32)(__ccgo_up(bp)) = nToken
|
|
libc.Xmemcpy(tls, aBuf, pToken, libc.Uint64FromInt32(**(**int32)(__ccgo_up(bp))))
|
|
/* Step 1. */
|
|
_fts5PorterStep1A(tls, aBuf, bp)
|
|
if _fts5PorterStep1B(tls, aBuf, bp) != 0 {
|
|
if _fts5PorterStep1B2(tls, aBuf, bp) == 0 {
|
|
c = **(**uint8)(__ccgo_up(aBuf + uintptr(**(**int32)(__ccgo_up(bp))-int32(1))))
|
|
if _fts5PorterIsVowel(tls, c, 0) == 0 && libc.Int32FromUint8(c) != int32('l') && libc.Int32FromUint8(c) != int32('s') && libc.Int32FromUint8(c) != int32('z') && libc.Int32FromUint8(c) == libc.Int32FromUint8(**(**uint8)(__ccgo_up(aBuf + uintptr(**(**int32)(__ccgo_up(bp))-int32(2))))) {
|
|
**(**int32)(__ccgo_up(bp)) = **(**int32)(__ccgo_up(bp)) - 1
|
|
} else {
|
|
if _fts5Porter_MEq1(tls, aBuf, **(**int32)(__ccgo_up(bp))) != 0 && _fts5Porter_Ostar(tls, aBuf, **(**int32)(__ccgo_up(bp))) != 0 {
|
|
v1 = **(**int32)(__ccgo_up(bp))
|
|
**(**int32)(__ccgo_up(bp)) = **(**int32)(__ccgo_up(bp)) + 1
|
|
**(**uint8)(__ccgo_up(aBuf + uintptr(v1))) = uint8('e')
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* Step 1C. */
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(aBuf + uintptr(**(**int32)(__ccgo_up(bp))-int32(1))))) == int32('y') && _fts5Porter_Vowel(tls, aBuf, **(**int32)(__ccgo_up(bp))-int32(1)) != 0 {
|
|
**(**uint8)(__ccgo_up(aBuf + uintptr(**(**int32)(__ccgo_up(bp))-int32(1)))) = uint8('i')
|
|
}
|
|
/* Steps 2 through 4. */
|
|
_fts5PorterStep2(tls, aBuf, bp)
|
|
_fts5PorterStep3(tls, aBuf, bp)
|
|
_fts5PorterStep4(tls, aBuf, bp)
|
|
/* Step 5a. */
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(aBuf + uintptr(**(**int32)(__ccgo_up(bp))-int32(1))))) == int32('e') {
|
|
if _fts5Porter_MGt1(tls, aBuf, **(**int32)(__ccgo_up(bp))-int32(1)) != 0 || _fts5Porter_MEq1(tls, aBuf, **(**int32)(__ccgo_up(bp))-int32(1)) != 0 && !(_fts5Porter_Ostar(tls, aBuf, **(**int32)(__ccgo_up(bp))-int32(1)) != 0) {
|
|
**(**int32)(__ccgo_up(bp)) = **(**int32)(__ccgo_up(bp)) - 1
|
|
}
|
|
}
|
|
/* Step 5b. */
|
|
if **(**int32)(__ccgo_up(bp)) > int32(1) && libc.Int32FromUint8(**(**uint8)(__ccgo_up(aBuf + uintptr(**(**int32)(__ccgo_up(bp))-int32(1))))) == int32('l') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(aBuf + uintptr(**(**int32)(__ccgo_up(bp))-int32(2))))) == int32('l') && _fts5Porter_MGt1(tls, aBuf, **(**int32)(__ccgo_up(bp))-int32(1)) != 0 {
|
|
**(**int32)(__ccgo_up(bp)) = **(**int32)(__ccgo_up(bp)) - 1
|
|
}
|
|
return (*(*func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32) int32)(unsafe.Pointer(&struct{ uintptr }{(*TPorterContext)(unsafe.Pointer(p)).FxToken})))(tls, (*TPorterContext)(unsafe.Pointer(p)).FpCtx, tflags, aBuf, **(**int32)(__ccgo_up(bp)), iStart, iEnd)
|
|
goto pass_through
|
|
pass_through:
|
|
;
|
|
return (*(*func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32) int32)(unsafe.Pointer(&struct{ uintptr }{(*TPorterContext)(unsafe.Pointer(p)).FxToken})))(tls, (*TPorterContext)(unsafe.Pointer(p)).FpCtx, tflags, pToken, nToken, iStart, iEnd)
|
|
return r
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Trigram tokenizer tokenize routine.
|
|
// */
|
|
func _fts5TriTokenize(tls *libc.TLS, pTok uintptr, pCtx uintptr, unusedFlags int32, pText uintptr, nText int32, __ccgo_fp_xToken uintptr) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var aStart [3]int32
|
|
var iCode Tu32
|
|
var iNext, ii, rc int32
|
|
var p, z1, zEof, zIn, zOut, v1 uintptr
|
|
var _ /* aBuf at bp+0 */ [32]uint8
|
|
_, _, _, _, _, _, _, _, _, _, _ = aStart, iCode, iNext, ii, p, rc, z1, zEof, zIn, zOut, v1
|
|
p = pTok
|
|
rc = SQLITE_OK
|
|
zOut = bp
|
|
zIn = pText
|
|
if zIn != 0 {
|
|
v1 = zIn + uintptr(nText)
|
|
} else {
|
|
v1 = uintptr(0)
|
|
}
|
|
zEof = v1
|
|
iCode = uint32(0) /* Input offset of each character in aBuf[] */
|
|
_ = unusedFlags
|
|
/* Populate aBuf[] with the characters for the first trigram. */
|
|
ii = 0
|
|
for {
|
|
if !(ii < int32(3)) {
|
|
break
|
|
}
|
|
for cond := true; cond; cond = iCode == uint32(0) {
|
|
aStart[ii] = int32(int64(zIn) - int64(pText))
|
|
if zIn >= zEof {
|
|
return SQLITE_OK
|
|
}
|
|
v1 = zIn
|
|
zIn = zIn + 1
|
|
iCode = uint32(**(**uint8)(__ccgo_up(v1)))
|
|
if iCode >= uint32(0xc0) {
|
|
iCode = uint32(_sqlite3Utf8Trans1[iCode-uint32(0xc0)])
|
|
for zIn < zEof && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn)))&int32(0xc0) == int32(0x80) {
|
|
v1 = zIn
|
|
zIn = zIn + 1
|
|
iCode = iCode<<libc.Int32FromInt32(6) + libc.Uint32FromInt32(libc.Int32FromInt32(0x3f)&libc.Int32FromUint8(**(**uint8)(__ccgo_up(v1))))
|
|
}
|
|
if iCode < uint32(0x80) || iCode&uint32(0xFFFFF800) == uint32(0xD800) || iCode&uint32(0xFFFFFFFE) == uint32(0xFFFE) {
|
|
iCode = uint32(0xFFFD)
|
|
}
|
|
}
|
|
if (*TTrigramTokenizer)(unsafe.Pointer(p)).FbFold != 0 {
|
|
iCode = libc.Uint32FromInt32(_sqlite3Fts5UnicodeFold(tls, libc.Int32FromUint32(iCode), (*TTrigramTokenizer)(unsafe.Pointer(p)).FiFoldParam))
|
|
}
|
|
}
|
|
if iCode < uint32(0x00080) {
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = uint8(iCode & libc.Uint32FromInt32(0xFF))
|
|
} else {
|
|
if iCode < uint32(0x00800) {
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = libc.Uint8FromInt32(int32(0xC0) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(6)&libc.Uint32FromInt32(0x1F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = libc.Uint8FromInt32(int32(0x80) + libc.Int32FromUint8(uint8(iCode&libc.Uint32FromInt32(0x3F))))
|
|
} else {
|
|
if iCode < uint32(0x10000) {
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = libc.Uint8FromInt32(int32(0xE0) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(12)&libc.Uint32FromInt32(0x0F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = libc.Uint8FromInt32(int32(0x80) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(6)&libc.Uint32FromInt32(0x3F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = libc.Uint8FromInt32(int32(0x80) + libc.Int32FromUint8(uint8(iCode&libc.Uint32FromInt32(0x3F))))
|
|
} else {
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = libc.Uint8FromInt32(int32(0xF0) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(18)&libc.Uint32FromInt32(0x07))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = libc.Uint8FromInt32(int32(0x80) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(12)&libc.Uint32FromInt32(0x3F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = libc.Uint8FromInt32(int32(0x80) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(6)&libc.Uint32FromInt32(0x3F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = libc.Uint8FromInt32(int32(0x80) + libc.Int32FromUint8(uint8(iCode&libc.Uint32FromInt32(0x3F))))
|
|
}
|
|
}
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
/* At the start of each iteration of this loop:
|
|
**
|
|
** aBuf: Contains 3 characters. The 3 characters of the next trigram.
|
|
** zOut: Points to the byte following the last character in aBuf.
|
|
** aStart[3]: Contains the byte offset in the input text corresponding
|
|
** to the start of each of the three characters in the buffer.
|
|
*/
|
|
for int32(1) != 0 {
|
|
/* Read characters from the input up until the first non-diacritic */
|
|
for cond := true; cond; cond = iCode == uint32(0) {
|
|
iNext = int32(int64(zIn) - int64(pText))
|
|
if zIn >= zEof {
|
|
iCode = uint32(0)
|
|
break
|
|
}
|
|
v1 = zIn
|
|
zIn = zIn + 1
|
|
iCode = uint32(**(**uint8)(__ccgo_up(v1)))
|
|
if iCode >= uint32(0xc0) {
|
|
iCode = uint32(_sqlite3Utf8Trans1[iCode-uint32(0xc0)])
|
|
for zIn < zEof && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn)))&int32(0xc0) == int32(0x80) {
|
|
v1 = zIn
|
|
zIn = zIn + 1
|
|
iCode = iCode<<libc.Int32FromInt32(6) + libc.Uint32FromInt32(libc.Int32FromInt32(0x3f)&libc.Int32FromUint8(**(**uint8)(__ccgo_up(v1))))
|
|
}
|
|
if iCode < uint32(0x80) || iCode&uint32(0xFFFFF800) == uint32(0xD800) || iCode&uint32(0xFFFFFFFE) == uint32(0xFFFE) {
|
|
iCode = uint32(0xFFFD)
|
|
}
|
|
}
|
|
if (*TTrigramTokenizer)(unsafe.Pointer(p)).FbFold != 0 {
|
|
iCode = libc.Uint32FromInt32(_sqlite3Fts5UnicodeFold(tls, libc.Int32FromUint32(iCode), (*TTrigramTokenizer)(unsafe.Pointer(p)).FiFoldParam))
|
|
}
|
|
}
|
|
/* Pass the current trigram back to fts5 */
|
|
rc = (*(*func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32) int32)(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xToken})))(tls, pCtx, 0, bp, int32(int64(zOut)-t__predefined_ptrdiff_t(bp)), aStart[0], iNext)
|
|
if iCode == uint32(0) || rc != SQLITE_OK {
|
|
break
|
|
}
|
|
/* Remove the first character from buffer aBuf[]. Append the character
|
|
** with codepoint iCode. */
|
|
z1 = bp
|
|
v1 = z1
|
|
z1 = z1 + 1
|
|
if libc.Int32FromUint8(uint8(**(**uint8)(__ccgo_up(v1)))) >= int32(0xc0) {
|
|
for libc.Int32FromUint8(uint8(**(**uint8)(__ccgo_up(z1))))&int32(0xc0) == int32(0x80) {
|
|
z1 = z1 + 1
|
|
}
|
|
}
|
|
libc.Xmemmove(tls, bp, z1, libc.Uint64FromInt64(int64(zOut)-int64(z1)))
|
|
zOut = zOut - uintptr(int64(z1)-t__predefined_ptrdiff_t(bp))
|
|
if iCode < uint32(0x00080) {
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = uint8(iCode & libc.Uint32FromInt32(0xFF))
|
|
} else {
|
|
if iCode < uint32(0x00800) {
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = libc.Uint8FromInt32(int32(0xC0) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(6)&libc.Uint32FromInt32(0x1F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = libc.Uint8FromInt32(int32(0x80) + libc.Int32FromUint8(uint8(iCode&libc.Uint32FromInt32(0x3F))))
|
|
} else {
|
|
if iCode < uint32(0x10000) {
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = libc.Uint8FromInt32(int32(0xE0) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(12)&libc.Uint32FromInt32(0x0F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = libc.Uint8FromInt32(int32(0x80) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(6)&libc.Uint32FromInt32(0x3F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = libc.Uint8FromInt32(int32(0x80) + libc.Int32FromUint8(uint8(iCode&libc.Uint32FromInt32(0x3F))))
|
|
} else {
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = libc.Uint8FromInt32(int32(0xF0) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(18)&libc.Uint32FromInt32(0x07))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = libc.Uint8FromInt32(int32(0x80) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(12)&libc.Uint32FromInt32(0x3F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = libc.Uint8FromInt32(int32(0x80) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(6)&libc.Uint32FromInt32(0x3F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = libc.Uint8FromInt32(int32(0x80) + libc.Int32FromUint8(uint8(iCode&libc.Uint32FromInt32(0x3F))))
|
|
}
|
|
}
|
|
}
|
|
/* Update the aStart[] array */
|
|
aStart[0] = aStart[int32(1)]
|
|
aStart[int32(1)] = aStart[int32(2)]
|
|
aStart[int32(2)] = iNext
|
|
}
|
|
return rc
|
|
}
|
|
|
|
func _fts5UnicodeTokenize(tls *libc.TLS, pTokenizer uintptr, pCtx uintptr, iUnused int32, pText uintptr, nText int32, __ccgo_fp_xToken uintptr) (r int32) {
|
|
var a, aFold, p, pEnd, zCsr, zOut, zTerm, v3 uintptr
|
|
var iCode Tu32
|
|
var ie, is, nFold, rc, v7 int32
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _ = a, aFold, iCode, ie, is, nFold, p, pEnd, rc, zCsr, zOut, zTerm, v3, v7
|
|
p = pTokenizer
|
|
rc = SQLITE_OK
|
|
a = p
|
|
zTerm = pText + uintptr(nText)
|
|
zCsr = pText
|
|
/* Output buffer */
|
|
aFold = (*TUnicode61Tokenizer)(unsafe.Pointer(p)).FaFold
|
|
nFold = (*TUnicode61Tokenizer)(unsafe.Pointer(p)).FnFold
|
|
pEnd = aFold + uintptr(nFold-int32(6))
|
|
_ = iUnused
|
|
/* Each iteration of this loop gobbles up a contiguous run of separators,
|
|
** then the next token. */
|
|
_2:
|
|
;
|
|
if !(rc == SQLITE_OK) {
|
|
goto _1
|
|
} /* non-ASCII codepoint read from input */
|
|
zOut = aFold
|
|
/* Skip any separator characters. */
|
|
for int32(1) != 0 {
|
|
if zCsr >= zTerm {
|
|
goto tokenize_done
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zCsr)))&int32(0x80) != 0 {
|
|
/* A character outside of the ascii range. Skip past it if it is
|
|
** a separator character. Or break out of the loop if it is not. */
|
|
is = int32(int64(zCsr) - int64(pText))
|
|
v3 = zCsr
|
|
zCsr = zCsr + 1
|
|
iCode = uint32(**(**uint8)(__ccgo_up(v3)))
|
|
if iCode >= uint32(0xc0) {
|
|
iCode = uint32(_sqlite3Utf8Trans1[iCode-uint32(0xc0)])
|
|
for zCsr < zTerm && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zCsr)))&int32(0xc0) == int32(0x80) {
|
|
v3 = zCsr
|
|
zCsr = zCsr + 1
|
|
iCode = iCode<<libc.Int32FromInt32(6) + libc.Uint32FromInt32(libc.Int32FromInt32(0x3f)&libc.Int32FromUint8(**(**uint8)(__ccgo_up(v3))))
|
|
}
|
|
if iCode < uint32(0x80) || iCode&uint32(0xFFFFF800) == uint32(0xD800) || iCode&uint32(0xFFFFFFFE) == uint32(0xFFFE) {
|
|
iCode = uint32(0xFFFD)
|
|
}
|
|
}
|
|
if _fts5UnicodeIsAlnum(tls, p, libc.Int32FromUint32(iCode)) != 0 {
|
|
goto non_ascii_tokenchar
|
|
}
|
|
} else {
|
|
if **(**uint8)(__ccgo_up(a + uintptr(**(**uint8)(__ccgo_up(zCsr))))) != 0 {
|
|
is = int32(int64(zCsr) - int64(pText))
|
|
goto ascii_tokenchar
|
|
}
|
|
zCsr = zCsr + 1
|
|
}
|
|
}
|
|
/* Run through the tokenchars. Fold them into the output buffer along
|
|
** the way. */
|
|
_6:
|
|
;
|
|
if !(zCsr < zTerm) {
|
|
goto _5
|
|
}
|
|
/* Grow the output buffer so that there is sufficient space to fit the
|
|
** largest possible utf-8 character. */
|
|
if zOut > pEnd {
|
|
aFold = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(int64(nFold)*int64(2)))
|
|
if aFold == uintptr(0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
goto tokenize_done
|
|
}
|
|
zOut = aFold + uintptr(int64(zOut)-int64((*TUnicode61Tokenizer)(unsafe.Pointer(p)).FaFold))
|
|
libc.Xmemcpy(tls, aFold, (*TUnicode61Tokenizer)(unsafe.Pointer(p)).FaFold, libc.Uint64FromInt32(nFold))
|
|
Xsqlite3_free(tls, (*TUnicode61Tokenizer)(unsafe.Pointer(p)).FaFold)
|
|
(*TUnicode61Tokenizer)(unsafe.Pointer(p)).FaFold = aFold
|
|
v7 = nFold * libc.Int32FromInt32(2)
|
|
nFold = v7
|
|
(*TUnicode61Tokenizer)(unsafe.Pointer(p)).FnFold = v7
|
|
pEnd = aFold + uintptr(nFold-int32(6))
|
|
}
|
|
if !(libc.Int32FromUint8(**(**uint8)(__ccgo_up(zCsr)))&int32(0x80) != 0) {
|
|
goto _8
|
|
}
|
|
/* An non-ascii-range character. Fold it into the output buffer if
|
|
** it is a token character, or break out of the loop if it is not. */
|
|
v3 = zCsr
|
|
zCsr = zCsr + 1
|
|
iCode = uint32(**(**uint8)(__ccgo_up(v3)))
|
|
if iCode >= uint32(0xc0) {
|
|
iCode = uint32(_sqlite3Utf8Trans1[iCode-uint32(0xc0)])
|
|
for zCsr < zTerm && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zCsr)))&int32(0xc0) == int32(0x80) {
|
|
v3 = zCsr
|
|
zCsr = zCsr + 1
|
|
iCode = iCode<<libc.Int32FromInt32(6) + libc.Uint32FromInt32(libc.Int32FromInt32(0x3f)&libc.Int32FromUint8(**(**uint8)(__ccgo_up(v3))))
|
|
}
|
|
if iCode < uint32(0x80) || iCode&uint32(0xFFFFF800) == uint32(0xD800) || iCode&uint32(0xFFFFFFFE) == uint32(0xFFFE) {
|
|
iCode = uint32(0xFFFD)
|
|
}
|
|
}
|
|
if !(_fts5UnicodeIsAlnum(tls, p, libc.Int32FromUint32(iCode)) != 0 || _sqlite3Fts5UnicodeIsdiacritic(tls, libc.Int32FromUint32(iCode)) != 0) {
|
|
goto _12
|
|
}
|
|
goto non_ascii_tokenchar
|
|
non_ascii_tokenchar:
|
|
;
|
|
iCode = libc.Uint32FromInt32(_sqlite3Fts5UnicodeFold(tls, libc.Int32FromUint32(iCode), (*TUnicode61Tokenizer)(unsafe.Pointer(p)).FeRemoveDiacritic))
|
|
if iCode != 0 {
|
|
if iCode < uint32(0x00080) {
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v3)) = uint8(iCode & libc.Uint32FromInt32(0xFF))
|
|
} else {
|
|
if iCode < uint32(0x00800) {
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v3)) = libc.Uint8FromInt32(int32(0xC0) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(6)&libc.Uint32FromInt32(0x1F))))
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v3)) = libc.Uint8FromInt32(int32(0x80) + libc.Int32FromUint8(uint8(iCode&libc.Uint32FromInt32(0x3F))))
|
|
} else {
|
|
if iCode < uint32(0x10000) {
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v3)) = libc.Uint8FromInt32(int32(0xE0) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(12)&libc.Uint32FromInt32(0x0F))))
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v3)) = libc.Uint8FromInt32(int32(0x80) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(6)&libc.Uint32FromInt32(0x3F))))
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v3)) = libc.Uint8FromInt32(int32(0x80) + libc.Int32FromUint8(uint8(iCode&libc.Uint32FromInt32(0x3F))))
|
|
} else {
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v3)) = libc.Uint8FromInt32(int32(0xF0) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(18)&libc.Uint32FromInt32(0x07))))
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v3)) = libc.Uint8FromInt32(int32(0x80) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(12)&libc.Uint32FromInt32(0x3F))))
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v3)) = libc.Uint8FromInt32(int32(0x80) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(6)&libc.Uint32FromInt32(0x3F))))
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v3)) = libc.Uint8FromInt32(int32(0x80) + libc.Int32FromUint8(uint8(iCode&libc.Uint32FromInt32(0x3F))))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
goto _13
|
|
_12:
|
|
;
|
|
goto _5
|
|
_13:
|
|
;
|
|
goto _9
|
|
_8:
|
|
;
|
|
if !(libc.Int32FromUint8(**(**uint8)(__ccgo_up(a + uintptr(**(**uint8)(__ccgo_up(zCsr)))))) == 0) {
|
|
goto _24
|
|
}
|
|
/* An ascii-range separator character. End of token. */
|
|
goto _5
|
|
goto _25
|
|
_24:
|
|
;
|
|
goto ascii_tokenchar
|
|
ascii_tokenchar:
|
|
;
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zCsr))) >= int32('A') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zCsr))) <= int32('Z') {
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v3)) = libc.Uint8FromInt32(libc.Int32FromUint8(**(**uint8)(__ccgo_up(zCsr))) + int32(32))
|
|
} else {
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v3)) = uint8(**(**uint8)(__ccgo_up(zCsr)))
|
|
}
|
|
zCsr = zCsr + 1
|
|
_25:
|
|
;
|
|
_9:
|
|
;
|
|
ie = int32(int64(zCsr) - int64(pText))
|
|
goto _6
|
|
_5:
|
|
;
|
|
/* Invoke the token callback */
|
|
rc = (*(*func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32) int32)(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xToken})))(tls, pCtx, 0, aFold, int32(int64(zOut)-int64(aFold)), is, ie)
|
|
goto _2
|
|
_1:
|
|
;
|
|
goto tokenize_done
|
|
tokenize_done:
|
|
;
|
|
if rc == int32(SQLITE_DONE) {
|
|
rc = SQLITE_OK
|
|
}
|
|
return rc
|
|
}
|
|
|
|
/**************************************************************************
|
|
** Start of porter stemmer implementation.
|
|
*/
|
|
|
|
/* Any tokens larger than this (in bytes) are passed through without
|
|
** stemming. */
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If the input is a well-formed JSON array of coordinates with at least
|
|
// ** four coordinates and where each coordinate is itself a two-value array,
|
|
// ** then convert the JSON into a GeoPoly object and return a pointer to
|
|
// ** that object.
|
|
// **
|
|
// ** If any error occurs, return NULL.
|
|
// */
|
|
func _geopolyParseJson(tls *libc.TLS, z uintptr, pRc uintptr) (r uintptr) {
|
|
bp := tls.Alloc(48)
|
|
defer tls.Free(48)
|
|
var aNew, pOut, v1 uintptr
|
|
var c uint8
|
|
var ii, rc int32
|
|
var v2 bool
|
|
var _ /* s at bp+0 */ TGeoParse
|
|
var _ /* x at bp+32 */ int32
|
|
_, _, _, _, _, _, _ = aNew, c, ii, pOut, rc, v1, v2
|
|
rc = SQLITE_OK
|
|
libc.Xmemset(tls, bp, 0, uint64(32))
|
|
(**(**TGeoParse)(__ccgo_up(bp))).Fz = z
|
|
if libc.Int32FromUint8(_geopolySkipSpace(tls, bp)) == int32('[') {
|
|
(**(**TGeoParse)(__ccgo_up(bp))).Fz = (**(**TGeoParse)(__ccgo_up(bp))).Fz + 1
|
|
for libc.Int32FromUint8(_geopolySkipSpace(tls, bp)) == int32('[') {
|
|
ii = 0
|
|
(**(**TGeoParse)(__ccgo_up(bp))).Fz = (**(**TGeoParse)(__ccgo_up(bp))).Fz + 1
|
|
if (**(**TGeoParse)(__ccgo_up(bp))).FnVertex >= (**(**TGeoParse)(__ccgo_up(bp))).FnAlloc {
|
|
(**(**TGeoParse)(__ccgo_up(bp))).FnAlloc = (**(**TGeoParse)(__ccgo_up(bp))).FnAlloc*int32(2) + int32(16)
|
|
aNew = Xsqlite3_realloc64(tls, (**(**TGeoParse)(__ccgo_up(bp))).Fa, uint64(libc.Uint64FromInt32((**(**TGeoParse)(__ccgo_up(bp))).FnAlloc)*uint64(4)*uint64(2)))
|
|
if aNew == uintptr(0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
(**(**TGeoParse)(__ccgo_up(bp))).FnErr = (**(**TGeoParse)(__ccgo_up(bp))).FnErr + 1
|
|
break
|
|
}
|
|
(**(**TGeoParse)(__ccgo_up(bp))).Fa = aNew
|
|
}
|
|
for {
|
|
if ii <= int32(1) {
|
|
v1 = (**(**TGeoParse)(__ccgo_up(bp))).Fa + uintptr((**(**TGeoParse)(__ccgo_up(bp))).FnVertex*int32(2)+ii)*4
|
|
} else {
|
|
v1 = uintptr(0)
|
|
}
|
|
if !(_geopolyParseNumber(tls, bp, v1) != 0) {
|
|
break
|
|
}
|
|
ii = ii + 1
|
|
if ii == int32(2) {
|
|
(**(**TGeoParse)(__ccgo_up(bp))).FnVertex = (**(**TGeoParse)(__ccgo_up(bp))).FnVertex + 1
|
|
}
|
|
c = _geopolySkipSpace(tls, bp)
|
|
(**(**TGeoParse)(__ccgo_up(bp))).Fz = (**(**TGeoParse)(__ccgo_up(bp))).Fz + 1
|
|
if libc.Int32FromUint8(c) == int32(',') {
|
|
continue
|
|
}
|
|
if libc.Int32FromUint8(c) == int32(']') && ii >= int32(2) {
|
|
break
|
|
}
|
|
(**(**TGeoParse)(__ccgo_up(bp))).FnErr = (**(**TGeoParse)(__ccgo_up(bp))).FnErr + 1
|
|
rc = int32(SQLITE_ERROR)
|
|
goto parse_json_err
|
|
}
|
|
if libc.Int32FromUint8(_geopolySkipSpace(tls, bp)) == int32(',') {
|
|
(**(**TGeoParse)(__ccgo_up(bp))).Fz = (**(**TGeoParse)(__ccgo_up(bp))).Fz + 1
|
|
continue
|
|
}
|
|
break
|
|
}
|
|
if v2 = libc.Int32FromUint8(_geopolySkipSpace(tls, bp)) == int32(']') && (**(**TGeoParse)(__ccgo_up(bp))).FnVertex >= int32(4) && **(**TGeoCoord)(__ccgo_up((**(**TGeoParse)(__ccgo_up(bp))).Fa)) == **(**TGeoCoord)(__ccgo_up((**(**TGeoParse)(__ccgo_up(bp))).Fa + uintptr((**(**TGeoParse)(__ccgo_up(bp))).FnVertex*int32(2)-int32(2))*4)) && **(**TGeoCoord)(__ccgo_up((**(**TGeoParse)(__ccgo_up(bp))).Fa + 1*4)) == **(**TGeoCoord)(__ccgo_up((**(**TGeoParse)(__ccgo_up(bp))).Fa + uintptr((**(**TGeoParse)(__ccgo_up(bp))).FnVertex*int32(2)-int32(1))*4)); v2 {
|
|
(**(**TGeoParse)(__ccgo_up(bp))).Fz = (**(**TGeoParse)(__ccgo_up(bp))).Fz + 1
|
|
}
|
|
if v2 && libc.Int32FromUint8(_geopolySkipSpace(tls, bp)) == libc.Int32FromInt32(0) {
|
|
**(**int32)(__ccgo_up(bp + 32)) = int32(1)
|
|
(**(**TGeoParse)(__ccgo_up(bp))).FnVertex = (**(**TGeoParse)(__ccgo_up(bp))).FnVertex - 1 /* Remove the redundant vertex at the end */
|
|
pOut = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(40)+uint64(libc.Uint64FromInt64(4)*libc.Uint64FromInt32(2))*libc.Uint64FromInt64(int64((**(**TGeoParse)(__ccgo_up(bp))).FnVertex)-libc.Int64FromInt32(4)))
|
|
**(**int32)(__ccgo_up(bp + 32)) = int32(1)
|
|
if pOut == uintptr(0) {
|
|
goto parse_json_err
|
|
}
|
|
(*TGeoPoly)(unsafe.Pointer(pOut)).FnVertex = (**(**TGeoParse)(__ccgo_up(bp))).FnVertex
|
|
libc.Xmemcpy(tls, pOut+8, (**(**TGeoParse)(__ccgo_up(bp))).Fa, libc.Uint64FromInt32((**(**TGeoParse)(__ccgo_up(bp))).FnVertex*int32(2))*uint64(4))
|
|
**(**uint8)(__ccgo_up(pOut + 4)) = **(**uint8)(__ccgo_up(bp + 32))
|
|
**(**uint8)(__ccgo_up(pOut + 4 + 1)) = libc.Uint8FromInt32((**(**TGeoParse)(__ccgo_up(bp))).FnVertex >> int32(16) & int32(0xff))
|
|
**(**uint8)(__ccgo_up(pOut + 4 + 2)) = libc.Uint8FromInt32((**(**TGeoParse)(__ccgo_up(bp))).FnVertex >> int32(8) & int32(0xff))
|
|
**(**uint8)(__ccgo_up(pOut + 4 + 3)) = libc.Uint8FromInt32((**(**TGeoParse)(__ccgo_up(bp))).FnVertex & int32(0xff))
|
|
Xsqlite3_free(tls, (**(**TGeoParse)(__ccgo_up(bp))).Fa)
|
|
if pRc != 0 {
|
|
**(**int32)(__ccgo_up(pRc)) = SQLITE_OK
|
|
}
|
|
return pOut
|
|
} else {
|
|
(**(**TGeoParse)(__ccgo_up(bp))).FnErr = (**(**TGeoParse)(__ccgo_up(bp))).FnErr + 1
|
|
rc = int32(SQLITE_ERROR)
|
|
}
|
|
}
|
|
goto parse_json_err
|
|
parse_json_err:
|
|
;
|
|
if pRc != 0 {
|
|
**(**int32)(__ccgo_up(pRc)) = rc
|
|
}
|
|
Xsqlite3_free(tls, (**(**TGeoParse)(__ccgo_up(bp))).Fa)
|
|
return uintptr(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Interpret the given string as a safety level. Return 0 for OFF,
|
|
// ** 1 for ON or NORMAL, 2 for FULL, and 3 for EXTRA. Return 1 for an empty or
|
|
// ** unrecognized string argument. The FULL and EXTRA option is disallowed
|
|
// ** if the omitFull parameter it 1.
|
|
// **
|
|
// ** Note that the values returned are one less that the values that
|
|
// ** should be passed into sqlite3BtreeSetSafetyLevel(). The is done
|
|
// ** to support legacy SQL code. The safety level used to be boolean
|
|
// ** and older scripts may have used numbers 0 for OFF and 1 for ON.
|
|
// */
|
|
func _getSafetyLevel(tls *libc.TLS, z uintptr, omitFull int32, dflt Tu8) (r Tu8) {
|
|
var i, n int32
|
|
_, _ = i, n
|
|
if libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(z)))])&int32(0x04) != 0 {
|
|
return libc.Uint8FromInt32(_sqlite3Atoi(tls, z))
|
|
}
|
|
n = _sqlite3Strlen30(tls, z)
|
|
i = 0
|
|
for {
|
|
if !(i < libc.Int32FromUint64(libc.Uint64FromInt64(8)/libc.Uint64FromInt64(1))) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint8(_iLength[i]) == n && Xsqlite3_strnicmp(tls, uintptr(unsafe.Pointer(&_zText))+uintptr(_iOffset[i]), z, n) == 0 && (!(omitFull != 0) || libc.Int32FromUint8(_iValue[i]) <= int32(1)) {
|
|
return _iValue[i]
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return dflt
|
|
}
|
|
|
|
func _groupConcatStep(tls *libc.TLS, context uintptr, argc int32, argv uintptr) {
|
|
var db, pGCC, pnsl, zSep, zVal uintptr
|
|
var firstTerm, i, nA, nSep, nVal, v1 int32
|
|
_, _, _, _, _, _, _, _, _, _, _ = db, firstTerm, i, nA, nSep, nVal, pGCC, pnsl, zSep, zVal, v1
|
|
if Xsqlite3_value_type(tls, **(**uintptr)(__ccgo_up(argv))) == int32(SQLITE_NULL) {
|
|
return
|
|
}
|
|
pGCC = Xsqlite3_aggregate_context(tls, context, int32(48))
|
|
if pGCC != 0 {
|
|
db = Xsqlite3_context_db_handle(tls, context)
|
|
firstTerm = libc.BoolInt32((*TGroupConcatCtx)(unsafe.Pointer(pGCC)).Fstr.FmxAlloc == uint32(0))
|
|
(*TGroupConcatCtx)(unsafe.Pointer(pGCC)).Fstr.FmxAlloc = libc.Uint32FromInt32(**(**int32)(__ccgo_up(db + 136)))
|
|
if argc == int32(1) {
|
|
if !(firstTerm != 0) {
|
|
Xsqlite3_str_appendchar(tls, pGCC, int32(1), uint8(','))
|
|
} else {
|
|
(*TGroupConcatCtx)(unsafe.Pointer(pGCC)).FnFirstSepLength = int32(1)
|
|
}
|
|
} else {
|
|
if !(firstTerm != 0) {
|
|
zSep = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv + 1*8)))
|
|
nSep = Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(argv + 1*8)))
|
|
if zSep != 0 {
|
|
Xsqlite3_str_append(tls, pGCC, zSep, nSep)
|
|
} else {
|
|
nSep = 0
|
|
}
|
|
if nSep != (*TGroupConcatCtx)(unsafe.Pointer(pGCC)).FnFirstSepLength || (*TGroupConcatCtx)(unsafe.Pointer(pGCC)).FpnSepLengths != uintptr(0) {
|
|
pnsl = (*TGroupConcatCtx)(unsafe.Pointer(pGCC)).FpnSepLengths
|
|
if pnsl == uintptr(0) {
|
|
/* First separator length variation seen, start tracking them. */
|
|
pnsl = Xsqlite3_malloc64(tls, uint64(libc.Uint64FromInt32((*TGroupConcatCtx)(unsafe.Pointer(pGCC)).FnAccum+libc.Int32FromInt32(1))*uint64(4)))
|
|
if pnsl != uintptr(0) {
|
|
i = 0
|
|
nA = (*TGroupConcatCtx)(unsafe.Pointer(pGCC)).FnAccum - int32(1)
|
|
for i < nA {
|
|
v1 = i
|
|
i = i + 1
|
|
**(**int32)(__ccgo_up(pnsl + uintptr(v1)*4)) = (*TGroupConcatCtx)(unsafe.Pointer(pGCC)).FnFirstSepLength
|
|
}
|
|
}
|
|
} else {
|
|
pnsl = Xsqlite3_realloc64(tls, pnsl, uint64(libc.Uint64FromInt32((*TGroupConcatCtx)(unsafe.Pointer(pGCC)).FnAccum)*uint64(4)))
|
|
}
|
|
if pnsl != uintptr(0) {
|
|
if (*TGroupConcatCtx)(unsafe.Pointer(pGCC)).FnAccum > 0 {
|
|
**(**int32)(__ccgo_up(pnsl + uintptr((*TGroupConcatCtx)(unsafe.Pointer(pGCC)).FnAccum-int32(1))*4)) = nSep
|
|
}
|
|
(*TGroupConcatCtx)(unsafe.Pointer(pGCC)).FpnSepLengths = pnsl
|
|
} else {
|
|
_sqlite3StrAccumSetError(tls, pGCC, uint8(SQLITE_NOMEM))
|
|
}
|
|
}
|
|
} else {
|
|
(*TGroupConcatCtx)(unsafe.Pointer(pGCC)).FnFirstSepLength = Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(argv + 1*8)))
|
|
}
|
|
}
|
|
**(**int32)(__ccgo_up(pGCC + 32)) += int32(1)
|
|
zVal = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
nVal = Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
if zVal != 0 {
|
|
Xsqlite3_str_append(tls, pGCC, zVal, nVal)
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The hex() function. Interpret the argument as a blob. Return
|
|
// ** a hexadecimal rendering as text.
|
|
// */
|
|
func _hexFunc(tls *libc.TLS, context uintptr, argc int32, argv uintptr) {
|
|
var c uint8
|
|
var i, n int32
|
|
var pBlob, z, zHex, v1 uintptr
|
|
_, _, _, _, _, _, _ = c, i, n, pBlob, z, zHex, v1
|
|
_ = argc
|
|
pBlob = Xsqlite3_value_blob(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
n = Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
/* No encoding change */
|
|
v1 = _contextMalloc(tls, context, int64(n)*int64(2)+int64(1))
|
|
zHex = v1
|
|
z = v1
|
|
if zHex != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < n) {
|
|
break
|
|
}
|
|
c = **(**uint8)(__ccgo_up(pBlob))
|
|
v1 = z
|
|
z = z + 1
|
|
**(**uint8)(__ccgo_up(v1)) = _hexdigits[libc.Int32FromUint8(c)>>int32(4)&int32(0xf)]
|
|
v1 = z
|
|
z = z + 1
|
|
**(**uint8)(__ccgo_up(v1)) = _hexdigits[libc.Int32FromUint8(c)&int32(0xf)]
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
pBlob = pBlob + 1
|
|
}
|
|
**(**uint8)(__ccgo_up(z)) = uint8(0)
|
|
Xsqlite3_result_text64(tls, context, zHex, libc.Uint64FromInt64(int64(z)-int64(zHex)), __ccgo_fp(Xsqlite3_free), uint8(SQLITE_UTF8_ZT))
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Term pTerm is guaranteed to be a WO_IN term. It may be a component term
|
|
// ** of a vector IN expression of the form "(x, y, ...) IN (SELECT ...)".
|
|
// ** This function checks to see if the term is compatible with an index
|
|
// ** column with affinity idxaff (one of the SQLITE_AFF_XYZ values). If so,
|
|
// ** it returns a pointer to the name of the collation sequence (e.g. "BINARY"
|
|
// ** or "NOCASE") used by the comparison in pTerm. If it is not compatible
|
|
// ** with affinity idxaff, NULL is returned.
|
|
// */
|
|
func _indexInAffinityOk(tls *libc.TLS, pParse uintptr, pTerm uintptr, idxaff Tu8) (r uintptr) {
|
|
bp := tls.Alloc(80)
|
|
defer tls.Free(80)
|
|
var iField int32
|
|
var pRet, pX, v1 uintptr
|
|
var _ /* inexpr at bp+0 */ TExpr
|
|
_, _, _, _ = iField, pRet, pX, v1
|
|
pX = (*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr
|
|
if _sqlite3ExprIsVector(tls, (*TExpr)(unsafe.Pointer(pX)).FpLeft) != 0 {
|
|
iField = (*(*struct {
|
|
FleftColumn int32
|
|
FiField int32
|
|
})(unsafe.Pointer(pTerm + 32))).FiField - int32(1)
|
|
(**(**TExpr)(__ccgo_up(bp))).Fflags = uint32(0)
|
|
(**(**TExpr)(__ccgo_up(bp))).Fop = uint8(TK_EQ)
|
|
(**(**TExpr)(__ccgo_up(bp))).FpLeft = (*(*TExprList_item)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer((*TExpr)(unsafe.Pointer(pX)).FpLeft + 32)) + 8 + uintptr(iField)*32))).FpExpr
|
|
(**(**TExpr)(__ccgo_up(bp))).FpRight = (*(*TExprList_item)(unsafe.Pointer((*TSelect)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pX + 32)))).FpEList + 8 + uintptr(iField)*32))).FpExpr
|
|
pX = bp
|
|
}
|
|
if _sqlite3IndexAffinityOk(tls, pX, idxaff) != 0 {
|
|
pRet = _sqlite3ExprCompareCollSeq(tls, pParse, pX)
|
|
if pRet != 0 {
|
|
v1 = (*TCollSeq)(unsafe.Pointer(pRet)).FzName
|
|
} else {
|
|
v1 = uintptr(unsafe.Pointer(&_sqlite3StrBINARY))
|
|
}
|
|
return v1
|
|
}
|
|
return uintptr(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Check to see if the given expression is a LIKE or GLOB operator that
|
|
// ** can be optimized using inequality constraints. Return TRUE if it is
|
|
// ** so and false if not.
|
|
// **
|
|
// ** In order for the operator to be optimizible, the RHS must be a string
|
|
// ** literal that does not begin with a wildcard. The LHS must be a column
|
|
// ** that may only be NULL, a string, or a BLOB, never a number. (This means
|
|
// ** that virtual tables cannot participate in the LIKE optimization.) The
|
|
// ** collating sequence for the column on the LHS must be appropriate for
|
|
// ** the operator.
|
|
// */
|
|
func _isLikeOrGlob(tls *libc.TLS, pParse uintptr, pExpr uintptr, ppPrefix uintptr, pisComplete uintptr, pnoCase uintptr) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var c, v1 Tu8
|
|
var cnt, iCol, iFrom, iTo, isNum, op, r1, rc, v3 int32
|
|
var db, pLeft, pList, pPrefix, pReprepare, pRight, pVal, v, z, zNew uintptr
|
|
var _ /* rDummy at bp+16 */ float64
|
|
var _ /* wc at bp+0 */ [4]Tu8
|
|
var _ /* z2 at bp+8 */ uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = c, cnt, db, iCol, iFrom, iTo, isNum, op, pLeft, pList, pPrefix, pReprepare, pRight, pVal, r1, rc, v, z, zNew, v1, v3
|
|
z = uintptr(0) /* Wildcard characters */
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb /* Database connection */
|
|
pVal = uintptr(0) /* Result code to return */
|
|
if !(_sqlite3IsLikeFunction(tls, db, pExpr, pnoCase, bp) != 0) {
|
|
return 0
|
|
}
|
|
pList = *(*uintptr)(unsafe.Pointer(pExpr + 32))
|
|
pLeft = (*(*TExprList_item)(unsafe.Pointer(pList + 8 + 1*32))).FpExpr
|
|
pRight = _sqlite3ExprSkipCollate(tls, (*(*TExprList_item)(unsafe.Pointer(pList + 8))).FpExpr)
|
|
op = libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pRight)).Fop)
|
|
if op == int32(TK_VARIABLE) && (*Tsqlite3)(unsafe.Pointer(db)).Fflags&uint64(SQLITE_EnableQPSG) == uint64(0) {
|
|
pReprepare = (*TParse)(unsafe.Pointer(pParse)).FpReprepare
|
|
iCol = int32((*TExpr)(unsafe.Pointer(pRight)).FiColumn)
|
|
pVal = _sqlite3VdbeGetBoundValue(tls, pReprepare, iCol, uint8(SQLITE_AFF_BLOB))
|
|
if pVal != 0 && Xsqlite3_value_type(tls, pVal) == int32(SQLITE_TEXT) {
|
|
z = Xsqlite3_value_text(tls, pVal)
|
|
}
|
|
_sqlite3VdbeSetVarmask(tls, (*TParse)(unsafe.Pointer(pParse)).FpVdbe, iCol)
|
|
} else {
|
|
if op == int32(TK_STRING) {
|
|
z = *(*uintptr)(unsafe.Pointer(pRight + 8))
|
|
}
|
|
}
|
|
if z != 0 {
|
|
/* Count the number of prefix bytes prior to the first wildcard,
|
|
** U+fffd character, or malformed utf-8. If the underlying database
|
|
** has a UTF16LE encoding, then only consider ASCII characters. Note that
|
|
** the encoding of z[] is UTF8 - we are dealing with only UTF8 here in this
|
|
** code, but the database engine itself might be processing content using a
|
|
** different encoding. */
|
|
cnt = 0
|
|
for {
|
|
v1 = **(**Tu8)(__ccgo_up(z + uintptr(cnt)))
|
|
c = v1
|
|
if !(libc.Int32FromUint8(v1) != 0 && libc.Int32FromUint8(c) != libc.Int32FromUint8((**(**[4]Tu8)(__ccgo_up(bp)))[0]) && libc.Int32FromUint8(c) != libc.Int32FromUint8((**(**[4]Tu8)(__ccgo_up(bp)))[int32(1)]) && libc.Int32FromUint8(c) != libc.Int32FromUint8((**(**[4]Tu8)(__ccgo_up(bp)))[int32(2)])) {
|
|
break
|
|
}
|
|
cnt = cnt + 1
|
|
if libc.Int32FromUint8(c) == libc.Int32FromUint8((**(**[4]Tu8)(__ccgo_up(bp)))[int32(3)]) && libc.Int32FromUint8(**(**Tu8)(__ccgo_up(z + uintptr(cnt)))) > 0 && libc.Int32FromUint8(**(**Tu8)(__ccgo_up(z + uintptr(cnt)))) < int32(0x80) {
|
|
cnt = cnt + 1
|
|
} else {
|
|
if libc.Int32FromUint8(c) >= int32(0x80) {
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = z + uintptr(cnt) - uintptr(1)
|
|
if libc.Int32FromUint8(c) == int32(0xff) || _sqlite3Utf8Read(tls, bp+8) == uint32(0xfffd) || libc.Int32FromUint8((*Tsqlite3)(unsafe.Pointer(db)).Fenc) == int32(SQLITE_UTF16LE) {
|
|
cnt = cnt - 1
|
|
break
|
|
} else {
|
|
cnt = int32(int64(**(**uintptr)(__ccgo_up(bp + 8))) - int64(z))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* The optimization is possible only if (1) the pattern does not begin
|
|
** with a wildcard and if (2) the non-wildcard prefix does not end with
|
|
** an (illegal 0xff) character, or (3) the pattern does not consist of
|
|
** a single escape character. The second condition is necessary so
|
|
** that we can increment the prefix key to find an upper bound for the
|
|
** range search. The third is because the caller assumes that the pattern
|
|
** consists of at least one character after all escapes have been
|
|
** removed. */
|
|
if (cnt > int32(1) || cnt > 0 && libc.Int32FromUint8(**(**Tu8)(__ccgo_up(z))) != libc.Int32FromUint8((**(**[4]Tu8)(__ccgo_up(bp)))[int32(3)])) && int32(255) != libc.Int32FromUint8(**(**Tu8)(__ccgo_up(z + uintptr(cnt-int32(1))))) {
|
|
/* A "complete" match if the pattern ends with "*" or "%" */
|
|
**(**int32)(__ccgo_up(pisComplete)) = libc.BoolInt32(libc.Int32FromUint8(c) == libc.Int32FromUint8((**(**[4]Tu8)(__ccgo_up(bp)))[0]) && libc.Int32FromUint8(**(**Tu8)(__ccgo_up(z + uintptr(cnt+int32(1))))) == 0 && libc.Int32FromUint8((*Tsqlite3)(unsafe.Pointer(db)).Fenc) != int32(SQLITE_UTF16LE))
|
|
/* Get the pattern prefix. Remove all escapes from the prefix. */
|
|
pPrefix = _sqlite3Expr(tls, db, int32(TK_STRING), z)
|
|
if pPrefix != 0 {
|
|
zNew = *(*uintptr)(unsafe.Pointer(pPrefix + 8))
|
|
**(**uint8)(__ccgo_up(zNew + uintptr(cnt))) = uint8(0)
|
|
v3 = libc.Int32FromInt32(0)
|
|
iTo = v3
|
|
iFrom = v3
|
|
for {
|
|
if !(iFrom < cnt) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zNew + uintptr(iFrom)))) == libc.Int32FromUint8((**(**[4]Tu8)(__ccgo_up(bp)))[int32(3)]) {
|
|
iFrom = iFrom + 1
|
|
}
|
|
v3 = iTo
|
|
iTo = iTo + 1
|
|
**(**uint8)(__ccgo_up(zNew + uintptr(v3))) = **(**uint8)(__ccgo_up(zNew + uintptr(iFrom)))
|
|
goto _2
|
|
_2:
|
|
;
|
|
iFrom = iFrom + 1
|
|
}
|
|
**(**uint8)(__ccgo_up(zNew + uintptr(iTo))) = uint8(0)
|
|
/* If the LHS is not an ordinary column with TEXT affinity, then the
|
|
** pattern prefix boundaries (both the start and end boundaries) must
|
|
** not look like a number. Otherwise the pattern might be treated as
|
|
** a number, which will invalidate the LIKE optimization.
|
|
**
|
|
** Getting this right has been a persistent source of bugs in the
|
|
** LIKE optimization. See, for example:
|
|
** 2018-09-10 https://sqlite.org/src/info/c94369cae9b561b1
|
|
** 2019-05-02 https://sqlite.org/src/info/b043a54c3de54b28
|
|
** 2019-06-10 https://sqlite.org/src/info/fd76310a5e843e07
|
|
** 2019-06-14 https://sqlite.org/src/info/ce8717f0885af975
|
|
** 2019-09-03 https://sqlite.org/src/info/0f0428096f17252a
|
|
*/
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pLeft)).Fop) != int32(TK_COLUMN) || libc.Int32FromUint8(_sqlite3ExprAffinity(tls, pLeft)) != int32(SQLITE_AFF_TEXT) || (*TExpr)(unsafe.Pointer(pLeft)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_WinFunc)|libc.Int32FromInt32(EP_Subrtn)) == uint32(0) && *(*uintptr)(unsafe.Pointer(pLeft + 64)) != 0 && libc.Int32FromUint8((*TTable)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pLeft + 64)))).FeTabType) == int32(TABTYP_VTAB) {
|
|
isNum = _sqlite3AtoF(tls, zNew, bp+16)
|
|
if isNum <= 0 {
|
|
if iTo == int32(1) && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zNew))) == int32('-') {
|
|
isNum = +libc.Int32FromInt32(1)
|
|
} else {
|
|
**(**uint8)(__ccgo_up(zNew + uintptr(iTo-int32(1)))) = **(**uint8)(__ccgo_up(zNew + uintptr(iTo-int32(1)))) + 1
|
|
isNum = _sqlite3AtoF(tls, zNew, bp+16)
|
|
**(**uint8)(__ccgo_up(zNew + uintptr(iTo-int32(1)))) = **(**uint8)(__ccgo_up(zNew + uintptr(iTo-int32(1)))) - 1
|
|
}
|
|
}
|
|
if isNum > 0 {
|
|
_sqlite3ExprDelete(tls, db, pPrefix)
|
|
_sqlite3ValueFree(tls, pVal)
|
|
return 0
|
|
}
|
|
}
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppPrefix)) = pPrefix
|
|
/* If the RHS pattern is a bound parameter, make arrangements to
|
|
** reprepare the statement when that parameter is rebound */
|
|
if op == int32(TK_VARIABLE) {
|
|
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
|
|
_sqlite3VdbeSetVarmask(tls, v, int32((*TExpr)(unsafe.Pointer(pRight)).FiColumn))
|
|
if **(**int32)(__ccgo_up(pisComplete)) != 0 && **(**uint8)(__ccgo_up(*(*uintptr)(unsafe.Pointer(pRight + 8)) + 1)) != 0 {
|
|
/* If the rhs of the LIKE expression is a variable, and the current
|
|
** value of the variable means there is no need to invoke the LIKE
|
|
** function, then no OP_Variable will be added to the program.
|
|
** This causes problems for the sqlite3_bind_parameter_name()
|
|
** API. To work around them, add a dummy OP_Variable here.
|
|
*/
|
|
r1 = _sqlite3GetTempReg(tls, pParse)
|
|
_sqlite3ExprCodeTarget(tls, pParse, pRight, r1)
|
|
_sqlite3VdbeChangeP3(tls, v, _sqlite3VdbeCurrentAddr(tls, v)-int32(1), 0)
|
|
_sqlite3ReleaseTempReg(tls, pParse, r1)
|
|
}
|
|
}
|
|
} else {
|
|
z = uintptr(0)
|
|
}
|
|
}
|
|
rc = libc.BoolInt32(z != uintptr(0))
|
|
_sqlite3ValueFree(tls, pVal)
|
|
return rc
|
|
}
|
|
|
|
func _jsonAppendChar(tls *libc.TLS, p uintptr, c uint8) {
|
|
var v1 Tu64
|
|
var v2 uintptr
|
|
_, _ = v1, v2
|
|
if (*TJsonString)(unsafe.Pointer(p)).FnUsed >= (*TJsonString)(unsafe.Pointer(p)).FnAlloc {
|
|
_jsonAppendCharExpand(tls, p, c)
|
|
} else {
|
|
v2 = p + 24
|
|
v1 = *(*Tu64)(unsafe.Pointer(v2))
|
|
*(*Tu64)(unsafe.Pointer(v2)) = *(*Tu64)(unsafe.Pointer(v2)) + 1
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr(v1))) = c
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Append a single character
|
|
// */
|
|
func _jsonAppendCharExpand(tls *libc.TLS, p uintptr, c uint8) {
|
|
var v1 Tu64
|
|
var v2 uintptr
|
|
_, _ = v1, v2
|
|
if _jsonStringGrow(tls, p, uint32(1)) != 0 {
|
|
return
|
|
}
|
|
v2 = p + 24
|
|
v1 = *(*Tu64)(unsafe.Pointer(v2))
|
|
*(*Tu64)(unsafe.Pointer(v2)) = *(*Tu64)(unsafe.Pointer(v2)) + 1
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr(v1))) = c
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Append the N-byte string in zIn to the end of the JsonString string
|
|
// ** under construction. Enclose the string in double-quotes ("...") and
|
|
// ** escape any double-quotes or backslash characters contained within the
|
|
// ** string.
|
|
// **
|
|
// ** This routine is a high-runner. There is a measurable performance
|
|
// ** increase associated with unwinding the jsonIsOk[] loop.
|
|
// */
|
|
func _jsonAppendString(tls *libc.TLS, p uintptr, zIn uintptr, N Tu32) {
|
|
var c Tu8
|
|
var k Tu32
|
|
var z, v2 uintptr
|
|
var v1 Tu64
|
|
_, _, _, _, _ = c, k, z, v1, v2
|
|
z = zIn
|
|
if z == uintptr(0) {
|
|
return
|
|
}
|
|
if uint64(N)+(*TJsonString)(unsafe.Pointer(p)).FnUsed+uint64(2) >= (*TJsonString)(unsafe.Pointer(p)).FnAlloc && _jsonStringGrow(tls, p, N+uint32(2)) != 0 {
|
|
return
|
|
}
|
|
v2 = p + 24
|
|
v1 = *(*Tu64)(unsafe.Pointer(v2))
|
|
*(*Tu64)(unsafe.Pointer(v2)) = *(*Tu64)(unsafe.Pointer(v2)) + 1
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr(v1))) = uint8('"')
|
|
for int32(1) != 0 {
|
|
k = uint32(0)
|
|
/* The following while() is the 4-way unwound equivalent of
|
|
**
|
|
** while( k<N && jsonIsOk[z[k]] ){ k++; }
|
|
*/
|
|
for int32(1) != 0 {
|
|
if k+uint32(3) >= N {
|
|
for k < N && _jsonIsOk[**(**Tu8)(__ccgo_up(z + uintptr(k)))] != 0 {
|
|
k = k + 1
|
|
}
|
|
break
|
|
}
|
|
if !(_jsonIsOk[**(**Tu8)(__ccgo_up(z + uintptr(k)))] != 0) {
|
|
break
|
|
}
|
|
if !(_jsonIsOk[**(**Tu8)(__ccgo_up(z + uintptr(k+uint32(1))))] != 0) {
|
|
k = k + uint32(1)
|
|
break
|
|
}
|
|
if !(_jsonIsOk[**(**Tu8)(__ccgo_up(z + uintptr(k+uint32(2))))] != 0) {
|
|
k = k + uint32(2)
|
|
break
|
|
}
|
|
if !(_jsonIsOk[**(**Tu8)(__ccgo_up(z + uintptr(k+uint32(3))))] != 0) {
|
|
k = k + uint32(3)
|
|
break
|
|
} else {
|
|
k = k + uint32(4)
|
|
}
|
|
}
|
|
if k >= N {
|
|
if k > uint32(0) {
|
|
libc.Xmemcpy(tls, (*TJsonString)(unsafe.Pointer(p)).FzBuf+uintptr((*TJsonString)(unsafe.Pointer(p)).FnUsed), z, uint64(k))
|
|
**(**Tu64)(__ccgo_up(p + 24)) += uint64(k)
|
|
}
|
|
break
|
|
}
|
|
if k > uint32(0) {
|
|
libc.Xmemcpy(tls, (*TJsonString)(unsafe.Pointer(p)).FzBuf+uintptr((*TJsonString)(unsafe.Pointer(p)).FnUsed), z, uint64(k))
|
|
**(**Tu64)(__ccgo_up(p + 24)) += uint64(k)
|
|
z = z + uintptr(k)
|
|
N = N - k
|
|
}
|
|
c = **(**Tu8)(__ccgo_up(z))
|
|
if libc.Int32FromUint8(c) == int32('"') || libc.Int32FromUint8(c) == int32('\\') {
|
|
if (*TJsonString)(unsafe.Pointer(p)).FnUsed+uint64(N)+uint64(3) > (*TJsonString)(unsafe.Pointer(p)).FnAlloc && _jsonStringGrow(tls, p, N+uint32(3)) != 0 {
|
|
return
|
|
}
|
|
v2 = p + 24
|
|
v1 = *(*Tu64)(unsafe.Pointer(v2))
|
|
*(*Tu64)(unsafe.Pointer(v2)) = *(*Tu64)(unsafe.Pointer(v2)) + 1
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr(v1))) = uint8('\\')
|
|
v2 = p + 24
|
|
v1 = *(*Tu64)(unsafe.Pointer(v2))
|
|
*(*Tu64)(unsafe.Pointer(v2)) = *(*Tu64)(unsafe.Pointer(v2)) + 1
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr(v1))) = c
|
|
} else {
|
|
if libc.Int32FromUint8(c) == int32('\'') {
|
|
v2 = p + 24
|
|
v1 = *(*Tu64)(unsafe.Pointer(v2))
|
|
*(*Tu64)(unsafe.Pointer(v2)) = *(*Tu64)(unsafe.Pointer(v2)) + 1
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr(v1))) = c
|
|
} else {
|
|
if (*TJsonString)(unsafe.Pointer(p)).FnUsed+uint64(N)+uint64(7) > (*TJsonString)(unsafe.Pointer(p)).FnAlloc && _jsonStringGrow(tls, p, N+uint32(7)) != 0 {
|
|
return
|
|
}
|
|
_jsonAppendControlChar(tls, p, c)
|
|
}
|
|
}
|
|
z = z + 1
|
|
N = N - 1
|
|
}
|
|
v2 = p + 24
|
|
v1 = *(*Tu64)(unsafe.Pointer(v2))
|
|
*(*Tu64)(unsafe.Pointer(v2)) = *(*Tu64)(unsafe.Pointer(v2)) + 1
|
|
**(**uint8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr(v1))) = uint8('"')
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of the json_array(VALUE,...) function. Return a JSON
|
|
// ** array that contains all values given in arguments. Or if any argument
|
|
// ** is a BLOB, throw an error.
|
|
// */
|
|
func _jsonArrayFunc(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
|
|
bp := tls.Alloc(144)
|
|
defer tls.Free(144)
|
|
var i int32
|
|
var _ /* jx at bp+0 */ TJsonString
|
|
_ = i
|
|
_jsonStringInit(tls, bp, ctx)
|
|
_jsonAppendChar(tls, bp, uint8('['))
|
|
i = 0
|
|
for {
|
|
if !(i < argc) {
|
|
break
|
|
}
|
|
_jsonAppendSeparator(tls, bp)
|
|
_jsonAppendSqlValue(tls, bp, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_jsonAppendChar(tls, bp, uint8(']'))
|
|
_jsonReturnString(tls, bp, uintptr(0), uintptr(0))
|
|
Xsqlite3_result_subtype(tls, ctx, uint32(JSON_SUBTYPE))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /****************************************************************************
|
|
// ** Aggregate SQL function implementations
|
|
// ****************************************************************************/
|
|
// /*
|
|
// ** json_group_array(VALUE)
|
|
// **
|
|
// ** Return a JSON array composed of all values in the aggregate.
|
|
// */
|
|
func _jsonArrayStep(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
|
|
var pStr uintptr
|
|
_ = pStr
|
|
_ = argc
|
|
pStr = Xsqlite3_aggregate_context(tls, ctx, int32(136))
|
|
if pStr != 0 {
|
|
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
|
|
_jsonAppendSqlValue(tls, pStr, **(**uintptr)(__ccgo_up(argv)))
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* This helper routine for jsonLookupStep() populates pIns with
|
|
// ** binary data that is to be inserted into pParse.
|
|
// **
|
|
// ** In the common case, pIns just points to pParse->aIns and pParse->nIns.
|
|
// ** But if the zPath of the original edit operation includes path elements
|
|
// ** that go deeper, additional substructure must be created.
|
|
// **
|
|
// ** For example:
|
|
// **
|
|
// ** json_insert('{}', '$.a.b.c', 123);
|
|
// **
|
|
// ** The search stops at '$.a' But additional substructure must be
|
|
// ** created for the ".b.c" part of the patch so that the final result
|
|
// ** is: {"a":{"b":{"c"::123}}}. This routine populates pIns with
|
|
// ** the binary equivalent of {"b":{"c":123}} so that it can be inserted.
|
|
// **
|
|
// ** The caller is responsible for resetting pIns when it has finished
|
|
// ** using the substructure.
|
|
// */
|
|
func _jsonCreateEditSubstructure(tls *libc.TLS, pParse uintptr, pIns uintptr, zTail uintptr) (r Tu32) {
|
|
var rc int32
|
|
var v1 uintptr
|
|
_, _ = rc, v1
|
|
libc.Xmemset(tls, pIns, 0, uint64(72))
|
|
(*TJsonParse)(unsafe.Pointer(pIns)).Fdb = (*TJsonParse)(unsafe.Pointer(pParse)).Fdb
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zTail))) == 0 {
|
|
/* No substructure. Just insert what is given in pParse. */
|
|
(*TJsonParse)(unsafe.Pointer(pIns)).FaBlob = (*TJsonParse)(unsafe.Pointer(pParse)).FaIns
|
|
(*TJsonParse)(unsafe.Pointer(pIns)).FnBlob = (*TJsonParse)(unsafe.Pointer(pParse)).FnIns
|
|
rc = 0
|
|
} else {
|
|
/* Construct the binary substructure */
|
|
(*TJsonParse)(unsafe.Pointer(pIns)).FnBlob = uint32(1)
|
|
(*TJsonParse)(unsafe.Pointer(pIns)).FaBlob = uintptr(unsafe.Pointer(&_emptyObject)) + libc.BoolUintptr(libc.Int32FromUint8(**(**uint8)(__ccgo_up(zTail))) == int32('.'))
|
|
(*TJsonParse)(unsafe.Pointer(pIns)).FeEdit = (*TJsonParse)(unsafe.Pointer(pParse)).FeEdit
|
|
(*TJsonParse)(unsafe.Pointer(pIns)).FnIns = (*TJsonParse)(unsafe.Pointer(pParse)).FnIns
|
|
(*TJsonParse)(unsafe.Pointer(pIns)).FaIns = (*TJsonParse)(unsafe.Pointer(pParse)).FaIns
|
|
(*TJsonParse)(unsafe.Pointer(pIns)).FiDepth = libc.Uint16FromInt32(libc.Int32FromUint16((*TJsonParse)(unsafe.Pointer(pParse)).FiDepth) + int32(1))
|
|
if libc.Int32FromUint16((*TJsonParse)(unsafe.Pointer(pIns)).FiDepth) >= int32(JSON_MAX_DEPTH) {
|
|
return uint32(JSON_LOOKUP_TOODEEP)
|
|
}
|
|
rc = libc.Int32FromUint32(_jsonLookupStep(tls, pIns, uint32(0), zTail, uint32(0)))
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiDepth = (*TJsonParse)(unsafe.Pointer(pParse)).FiDepth - 1
|
|
v1 = pParse + 47
|
|
*(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) | libc.Int32FromUint8((*TJsonParse)(unsafe.Pointer(pIns)).Foom))
|
|
}
|
|
return libc.Uint32FromInt32(rc) /* Error code only */
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Return the value of a column */
|
|
func _jsonEachColumn(tls *libc.TLS, cur uintptr, ctx uintptr, iColumn int32) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var eType Tu8
|
|
var i, i1, i2, j, n, n1 Tu32
|
|
var nBase Tu64
|
|
var p uintptr
|
|
var _ /* x at bp+0 */ Ti64
|
|
_, _, _, _, _, _, _, _, _ = eType, i, i1, i2, j, n, n1, nBase, p
|
|
p = cur
|
|
switch iColumn {
|
|
case JEACH_KEY:
|
|
if (*TJsonEachCursor)(unsafe.Pointer(p)).FnParent == uint32(0) {
|
|
if (*TJsonEachCursor)(unsafe.Pointer(p)).FnRoot == uint32(1) {
|
|
break
|
|
}
|
|
j = libc.Uint32FromInt32(_jsonEachPathLength(tls, p))
|
|
n = (*TJsonEachCursor)(unsafe.Pointer(p)).FnRoot - j
|
|
if n == uint32(0) {
|
|
break
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up((*TJsonEachCursor)(unsafe.Pointer(p)).Fpath.FzBuf + uintptr(j)))) == int32('[') {
|
|
_sqlite3Atoi64(tls, (*TJsonEachCursor)(unsafe.Pointer(p)).Fpath.FzBuf+uintptr(j+uint32(1)), bp, libc.Int32FromUint32(n-uint32(1)), uint8(SQLITE_UTF8))
|
|
Xsqlite3_result_int64(tls, ctx, **(**Ti64)(__ccgo_up(bp)))
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up((*TJsonEachCursor)(unsafe.Pointer(p)).Fpath.FzBuf + uintptr(j+uint32(1))))) == int32('"') {
|
|
Xsqlite3_result_text(tls, ctx, (*TJsonEachCursor)(unsafe.Pointer(p)).Fpath.FzBuf+uintptr(j+uint32(2)), libc.Int32FromUint32(n-uint32(3)), uintptr(-libc.Int32FromInt32(1)))
|
|
} else {
|
|
Xsqlite3_result_text(tls, ctx, (*TJsonEachCursor)(unsafe.Pointer(p)).Fpath.FzBuf+uintptr(j+uint32(1)), libc.Int32FromUint32(n-uint32(1)), uintptr(-libc.Int32FromInt32(1)))
|
|
}
|
|
}
|
|
}
|
|
break
|
|
}
|
|
if libc.Int32FromUint8((*TJsonEachCursor)(unsafe.Pointer(p)).FeType) == int32(JSONB_OBJECT) {
|
|
_jsonReturnFromBlob(tls, p+192, (*TJsonEachCursor)(unsafe.Pointer(p)).Fi, ctx, int32(1))
|
|
} else {
|
|
Xsqlite3_result_int64(tls, ctx, (**(**TJsonParent)(__ccgo_up((*TJsonEachCursor)(unsafe.Pointer(p)).FaParent + uintptr((*TJsonEachCursor)(unsafe.Pointer(p)).FnParent-uint32(1))*24))).FiKey)
|
|
}
|
|
case int32(JEACH_VALUE):
|
|
i = libc.Uint32FromInt32(_jsonSkipLabel(tls, p))
|
|
_jsonReturnFromBlob(tls, p+192, i, ctx, libc.Int32FromUint8((*TJsonEachCursor)(unsafe.Pointer(p)).FeMode))
|
|
if libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonEachCursor)(unsafe.Pointer(p)).FsParse.FaBlob + uintptr(i))))&int32(0x0f) >= int32(JSONB_ARRAY) {
|
|
Xsqlite3_result_subtype(tls, ctx, uint32(JSON_SUBTYPE))
|
|
}
|
|
case int32(JEACH_TYPE):
|
|
i1 = libc.Uint32FromInt32(_jsonSkipLabel(tls, p))
|
|
eType = libc.Uint8FromInt32(libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonEachCursor)(unsafe.Pointer(p)).FsParse.FaBlob + uintptr(i1)))) & int32(0x0f))
|
|
Xsqlite3_result_text(tls, ctx, _jsonbType[eType], -int32(1), libc.UintptrFromInt32(0))
|
|
case int32(JEACH_ATOM):
|
|
i2 = libc.Uint32FromInt32(_jsonSkipLabel(tls, p))
|
|
if libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonEachCursor)(unsafe.Pointer(p)).FsParse.FaBlob + uintptr(i2))))&int32(0x0f) < int32(JSONB_ARRAY) {
|
|
_jsonReturnFromBlob(tls, p+192, i2, ctx, int32(1))
|
|
}
|
|
case int32(JEACH_ID):
|
|
Xsqlite3_result_int64(tls, ctx, libc.Int64FromUint32((*TJsonEachCursor)(unsafe.Pointer(p)).Fi))
|
|
case int32(JEACH_PARENT):
|
|
if (*TJsonEachCursor)(unsafe.Pointer(p)).FnParent > uint32(0) && (*TJsonEachCursor)(unsafe.Pointer(p)).FbRecursive != 0 {
|
|
Xsqlite3_result_int64(tls, ctx, libc.Int64FromUint32((**(**TJsonParent)(__ccgo_up((*TJsonEachCursor)(unsafe.Pointer(p)).FaParent + uintptr((*TJsonEachCursor)(unsafe.Pointer(p)).FnParent-uint32(1))*24))).FiHead))
|
|
}
|
|
case int32(JEACH_FULLKEY):
|
|
nBase = (*TJsonEachCursor)(unsafe.Pointer(p)).Fpath.FnUsed
|
|
if (*TJsonEachCursor)(unsafe.Pointer(p)).FnParent != 0 {
|
|
_jsonAppendPathName(tls, p)
|
|
}
|
|
Xsqlite3_result_text64(tls, ctx, (*TJsonEachCursor)(unsafe.Pointer(p)).Fpath.FzBuf, (*TJsonEachCursor)(unsafe.Pointer(p)).Fpath.FnUsed, uintptr(-libc.Int32FromInt32(1)), uint8(SQLITE_UTF8))
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).Fpath.FnUsed = nBase
|
|
case int32(JEACH_PATH):
|
|
n1 = libc.Uint32FromInt32(_jsonEachPathLength(tls, p))
|
|
Xsqlite3_result_text64(tls, ctx, (*TJsonEachCursor)(unsafe.Pointer(p)).Fpath.FzBuf, uint64(n1), uintptr(-libc.Int32FromInt32(1)), uint8(SQLITE_UTF8))
|
|
default:
|
|
Xsqlite3_result_text(tls, ctx, (*TJsonEachCursor)(unsafe.Pointer(p)).Fpath.FzBuf, libc.Int32FromUint32((*TJsonEachCursor)(unsafe.Pointer(p)).FnRoot), libc.UintptrFromInt32(0))
|
|
case int32(JEACH_JSON):
|
|
if (*TJsonEachCursor)(unsafe.Pointer(p)).FsParse.FzJson == uintptr(0) {
|
|
Xsqlite3_result_blob(tls, ctx, (*TJsonEachCursor)(unsafe.Pointer(p)).FsParse.FaBlob, libc.Int32FromUint32((*TJsonEachCursor)(unsafe.Pointer(p)).FsParse.FnBlob), uintptr(-libc.Int32FromInt32(1)))
|
|
} else {
|
|
Xsqlite3_result_text(tls, ctx, (*TJsonEachCursor)(unsafe.Pointer(p)).FsParse.FzJson, -int32(1), uintptr(-libc.Int32FromInt32(1)))
|
|
}
|
|
break
|
|
}
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Length of the path for rowid==0 in bRecursive mode.
|
|
// */
|
|
func _jsonEachPathLength(tls *libc.TLS, p uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var cSaved uint8
|
|
var n, x Tu32
|
|
var z uintptr
|
|
var _ /* sz at bp+0 */ Tu32
|
|
_, _, _, _ = cSaved, n, x, z
|
|
n = uint32((*TJsonEachCursor)(unsafe.Pointer(p)).Fpath.FnUsed)
|
|
z = (*TJsonEachCursor)(unsafe.Pointer(p)).Fpath.FzBuf
|
|
if (*TJsonEachCursor)(unsafe.Pointer(p)).FiRowid == uint32(0) && (*TJsonEachCursor)(unsafe.Pointer(p)).FbRecursive != 0 && n >= uint32(2) {
|
|
for n > uint32(1) {
|
|
n = n - 1
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(n)))) == int32('[') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(n)))) == int32('.') {
|
|
**(**Tu32)(__ccgo_up(bp)) = uint32(0)
|
|
cSaved = **(**uint8)(__ccgo_up(z + uintptr(n)))
|
|
**(**uint8)(__ccgo_up(z + uintptr(n))) = uint8(0)
|
|
x = _jsonLookupStep(tls, p+192, uint32(0), z+uintptr(1), uint32(0))
|
|
**(**uint8)(__ccgo_up(z + uintptr(n))) = cSaved
|
|
if x >= uint32(JSON_LOOKUP_PATHERROR) {
|
|
continue
|
|
}
|
|
if x+_jsonbPayloadSize(tls, p+192, x, bp) == (*TJsonEachCursor)(unsafe.Pointer(p)).Fi {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return libc.Int32FromUint32(n)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** json_error_position(JSON)
|
|
// **
|
|
// ** If the argument is NULL, return NULL
|
|
// **
|
|
// ** If the argument is BLOB, do a full validity check and return non-zero
|
|
// ** if the check fails. The return value is the approximate 1-based offset
|
|
// ** to the byte of the element that contains the first error.
|
|
// **
|
|
// ** Otherwise interpret the argument is TEXT (even if it is numeric) and
|
|
// ** return the 1-based character position for where the parser first recognized
|
|
// ** that the input was not valid JSON, or return 0 if the input text looks
|
|
// ** ok. JSON-5 extensions are accepted.
|
|
// */
|
|
func _jsonErrorFunc(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
|
|
bp := tls.Alloc(80)
|
|
defer tls.Free(80)
|
|
var iErrPos Ti64
|
|
var k Tu32
|
|
var _ /* s at bp+0 */ TJsonParse
|
|
_, _ = iErrPos, k
|
|
iErrPos = 0
|
|
_ = argc
|
|
libc.Xmemset(tls, bp, 0, uint64(72))
|
|
(**(**TJsonParse)(__ccgo_up(bp))).Fdb = Xsqlite3_context_db_handle(tls, ctx)
|
|
if _jsonArgIsJsonb(tls, **(**uintptr)(__ccgo_up(argv)), bp) != 0 {
|
|
iErrPos = libc.Int64FromUint32(_jsonbValidityCheck(tls, bp, uint32(0), (**(**TJsonParse)(__ccgo_up(bp))).FnBlob, uint32(1)))
|
|
} else {
|
|
(**(**TJsonParse)(__ccgo_up(bp))).FzJson = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
if (**(**TJsonParse)(__ccgo_up(bp))).FzJson == uintptr(0) {
|
|
return
|
|
} /* NULL input or OOM */
|
|
(**(**TJsonParse)(__ccgo_up(bp))).FnJson = Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
if _jsonConvertTextToBlob(tls, bp, uintptr(0)) != 0 {
|
|
if (**(**TJsonParse)(__ccgo_up(bp))).Foom != 0 {
|
|
iErrPos = int64(-int32(1))
|
|
} else {
|
|
/* Because s.oom is false */
|
|
k = uint32(0)
|
|
for {
|
|
if !(k < (**(**TJsonParse)(__ccgo_up(bp))).FiErr && **(**uint8)(__ccgo_up((**(**TJsonParse)(__ccgo_up(bp))).FzJson + uintptr(k))) != 0) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up((**(**TJsonParse)(__ccgo_up(bp))).FzJson + uintptr(k))))&int32(0xc0) != int32(0x80) {
|
|
iErrPos = iErrPos + 1
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
k = k + 1
|
|
}
|
|
iErrPos = iErrPos + 1
|
|
}
|
|
}
|
|
}
|
|
_jsonParseReset(tls, bp)
|
|
if iErrPos < 0 {
|
|
Xsqlite3_result_error_nomem(tls, ctx)
|
|
} else {
|
|
Xsqlite3_result_int64(tls, ctx, iErrPos)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This method works for both json_group_array() and json_group_object().
|
|
// ** It works by removing the first element of the group by searching forward
|
|
// ** to the first comma (",") that is not within a string and deleting all
|
|
// ** text through that comma.
|
|
// */
|
|
func _jsonGroupInverse(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
|
|
var c, v2 uint8
|
|
var i uint32
|
|
var inStr, nNest int32
|
|
var pStr, z uintptr
|
|
var v3 bool
|
|
_, _, _, _, _, _, _, _ = c, i, inStr, nNest, pStr, z, v2, v3
|
|
inStr = 0
|
|
nNest = 0
|
|
_ = argc
|
|
_ = argv
|
|
pStr = Xsqlite3_aggregate_context(tls, ctx, 0)
|
|
/* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will
|
|
** always have been called to initialize it */
|
|
if !(pStr != 0) {
|
|
return
|
|
}
|
|
z = (*TJsonString)(unsafe.Pointer(pStr)).FzBuf
|
|
i = uint32(1)
|
|
for {
|
|
if v3 = uint64(i) < (*TJsonString)(unsafe.Pointer(pStr)).FnUsed; v3 {
|
|
v2 = **(**uint8)(__ccgo_up(z + uintptr(i)))
|
|
c = v2
|
|
}
|
|
if !(v3 && (libc.Int32FromUint8(v2) != int32(',') || inStr != 0 || nNest != 0)) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint8(c) == int32('"') {
|
|
inStr = libc.BoolInt32(!(inStr != 0))
|
|
} else {
|
|
if libc.Int32FromUint8(c) == int32('\\') {
|
|
i = i + 1
|
|
} else {
|
|
if !(inStr != 0) {
|
|
if libc.Int32FromUint8(c) == int32('{') || libc.Int32FromUint8(c) == int32('[') {
|
|
nNest = nNest + 1
|
|
}
|
|
if libc.Int32FromUint8(c) == int32('}') || libc.Int32FromUint8(c) == int32(']') {
|
|
nNest = nNest - 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if uint64(i) < (*TJsonString)(unsafe.Pointer(pStr)).FnUsed {
|
|
**(**Tu64)(__ccgo_up(pStr + 24)) -= uint64(i)
|
|
libc.Xmemmove(tls, z+1, z+uintptr(i+uint32(1)), (*TJsonString)(unsafe.Pointer(pStr)).FnUsed-uint64(1))
|
|
**(**uint8)(__ccgo_up(z + uintptr((*TJsonString)(unsafe.Pointer(pStr)).FnUsed))) = uint8(0)
|
|
} else {
|
|
(*TJsonString)(unsafe.Pointer(pStr)).FnUsed = uint64(1)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* argv[0] is a BLOB that seems likely to be a JSONB. Subsequent
|
|
// ** arguments come in pairs where each pair contains a JSON path and
|
|
// ** content to insert or set at that patch. Do the updates
|
|
// ** and return the result.
|
|
// **
|
|
// ** The specific operation is determined by eEdit, which can be one
|
|
// ** of JEDIT_INS, JEDIT_REPL, JEDIT_SET, or JEDIT_AINS.
|
|
// */
|
|
func _jsonInsertIntoBlob(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr, eEdit int32) {
|
|
bp := tls.Alloc(80)
|
|
defer tls.Free(80)
|
|
var flgs, i, v1 int32
|
|
var p, zPath uintptr
|
|
var rc Tu32
|
|
var _ /* ax at bp+0 */ TJsonParse
|
|
_, _, _, _, _, _ = flgs, i, p, rc, zPath, v1
|
|
rc = uint32(0)
|
|
zPath = uintptr(0)
|
|
if argc == int32(1) {
|
|
v1 = 0
|
|
} else {
|
|
v1 = int32(JSON_EDITABLE)
|
|
}
|
|
flgs = v1
|
|
p = _jsonParseFuncArg(tls, ctx, **(**uintptr)(__ccgo_up(argv)), libc.Uint32FromInt32(flgs))
|
|
if p == uintptr(0) {
|
|
return
|
|
}
|
|
i = int32(1)
|
|
for {
|
|
if !(i < argc-int32(1)) {
|
|
break
|
|
}
|
|
if Xsqlite3_value_type(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8))) == int32(SQLITE_NULL) {
|
|
goto _2
|
|
}
|
|
zPath = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8)))
|
|
if zPath == uintptr(0) {
|
|
Xsqlite3_result_error_nomem(tls, ctx)
|
|
_jsonParseFree(tls, p)
|
|
return
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath))) != int32('$') {
|
|
goto jsonInsertIntoBlob_patherror
|
|
}
|
|
if _jsonFunctionArgToBlob(tls, ctx, **(**uintptr)(__ccgo_up(argv + uintptr(i+int32(1))*8)), bp) != 0 {
|
|
_jsonParseReset(tls, bp)
|
|
_jsonParseFree(tls, p)
|
|
return
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath + 1))) == 0 {
|
|
if eEdit == int32(JEDIT_REPL) || eEdit == int32(JEDIT_SET) {
|
|
_jsonBlobEdit(tls, p, uint32(0), (*TJsonParse)(unsafe.Pointer(p)).FnBlob, (**(**TJsonParse)(__ccgo_up(bp))).FaBlob, (**(**TJsonParse)(__ccgo_up(bp))).FnBlob)
|
|
}
|
|
rc = uint32(0)
|
|
} else {
|
|
(*TJsonParse)(unsafe.Pointer(p)).FeEdit = libc.Uint8FromInt32(eEdit)
|
|
(*TJsonParse)(unsafe.Pointer(p)).FnIns = (**(**TJsonParse)(__ccgo_up(bp))).FnBlob
|
|
(*TJsonParse)(unsafe.Pointer(p)).FaIns = (**(**TJsonParse)(__ccgo_up(bp))).FaBlob
|
|
(*TJsonParse)(unsafe.Pointer(p)).Fdelta = 0
|
|
(*TJsonParse)(unsafe.Pointer(p)).FiDepth = uint16(0)
|
|
rc = _jsonLookupStep(tls, p, uint32(0), zPath+uintptr(1), uint32(0))
|
|
}
|
|
_jsonParseReset(tls, bp)
|
|
if rc == uint32(JSON_LOOKUP_NOTFOUND) {
|
|
goto _2
|
|
}
|
|
if rc >= uint32(JSON_LOOKUP_PATHERROR) {
|
|
goto jsonInsertIntoBlob_patherror
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + int32(2)
|
|
}
|
|
_jsonReturnParse(tls, ctx, p)
|
|
_jsonParseFree(tls, p)
|
|
return
|
|
goto jsonInsertIntoBlob_patherror
|
|
jsonInsertIntoBlob_patherror:
|
|
;
|
|
_jsonParseFree(tls, p)
|
|
_jsonBadPathError(tls, ctx, zPath, libc.Int32FromUint32(rc))
|
|
return
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** json_remove(JSON, PATH, ...)
|
|
// **
|
|
// ** Remove the named elements from JSON and return the result. malformed
|
|
// ** JSON or PATH arguments result in an error.
|
|
// */
|
|
func _jsonRemoveFunc(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
|
|
var i, v1 int32
|
|
var p, zPath uintptr
|
|
var rc Tu32
|
|
_, _, _, _, _ = i, p, rc, zPath, v1 /* The parse */
|
|
zPath = uintptr(0) /* Subroutine return code */
|
|
if argc < int32(1) {
|
|
return
|
|
}
|
|
if argc > int32(1) {
|
|
v1 = int32(JSON_EDITABLE)
|
|
} else {
|
|
v1 = 0
|
|
}
|
|
p = _jsonParseFuncArg(tls, ctx, **(**uintptr)(__ccgo_up(argv)), libc.Uint32FromInt32(v1))
|
|
if p == uintptr(0) {
|
|
return
|
|
}
|
|
i = int32(1)
|
|
for {
|
|
if !(i < argc) {
|
|
break
|
|
}
|
|
zPath = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8)))
|
|
if zPath == uintptr(0) {
|
|
goto json_remove_done
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath))) != int32('$') {
|
|
goto json_remove_patherror
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath + 1))) == 0 {
|
|
/* json_remove(j,'$') returns NULL */
|
|
goto json_remove_done
|
|
}
|
|
(*TJsonParse)(unsafe.Pointer(p)).FeEdit = uint8(JEDIT_DEL)
|
|
(*TJsonParse)(unsafe.Pointer(p)).Fdelta = 0
|
|
rc = _jsonLookupStep(tls, p, uint32(0), zPath+uintptr(1), uint32(0))
|
|
if rc >= uint32(JSON_LOOKUP_PATHERROR) {
|
|
if rc == uint32(JSON_LOOKUP_NOTFOUND) {
|
|
goto _2 /* No-op */
|
|
} else {
|
|
_jsonBadPathError(tls, ctx, zPath, libc.Int32FromUint32(rc))
|
|
}
|
|
goto json_remove_done
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_jsonReturnParse(tls, ctx, p)
|
|
_jsonParseFree(tls, p)
|
|
return
|
|
goto json_remove_patherror
|
|
json_remove_patherror:
|
|
;
|
|
_jsonBadPathError(tls, ctx, zPath, 0)
|
|
goto json_remove_done
|
|
json_remove_done:
|
|
;
|
|
_jsonParseFree(tls, p)
|
|
return
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** json_type(JSON)
|
|
// ** json_type(JSON, PATH)
|
|
// **
|
|
// ** Return the top-level "type" of a JSON string. json_type() raises an
|
|
// ** error if either the JSON or PATH inputs are not well-formed.
|
|
// */
|
|
func _jsonTypeFunc(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
|
|
var i Tu32
|
|
var p, zPath uintptr
|
|
_, _, _ = i, p, zPath /* The parse */
|
|
zPath = uintptr(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) {
|
|
goto json_type_done
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zPath))) != int32('$') {
|
|
_jsonBadPathError(tls, ctx, zPath, 0)
|
|
goto json_type_done
|
|
}
|
|
i = _jsonLookupStep(tls, p, uint32(0), zPath+uintptr(1), uint32(0))
|
|
if i >= uint32(JSON_LOOKUP_PATHERROR) {
|
|
if i == uint32(JSON_LOOKUP_NOTFOUND) {
|
|
/* no-op */
|
|
} else {
|
|
_jsonBadPathError(tls, ctx, zPath, libc.Int32FromUint32(i))
|
|
}
|
|
goto json_type_done
|
|
}
|
|
} else {
|
|
i = uint32(0)
|
|
}
|
|
Xsqlite3_result_text(tls, ctx, _jsonbType[libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(p)).FaBlob + uintptr(i))))&int32(0x0f)], -int32(1), libc.UintptrFromInt32(0))
|
|
goto json_type_done
|
|
json_type_done:
|
|
;
|
|
_jsonParseFree(tls, p)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Open an mem file handle.
|
|
// */
|
|
func _memdbOpen(tls *libc.TLS, pVfs uintptr, zName uintptr, pFd uintptr, flags int32, pOutFlags uintptr) (r int32) {
|
|
var apNew, p, pFile, pVfsMutex, v3 uintptr
|
|
var i, szName, v2 int32
|
|
_, _, _, _, _, _, _, _ = apNew, i, p, pFile, pVfsMutex, szName, v2, v3
|
|
pFile = pFd
|
|
p = uintptr(0)
|
|
_ = pVfs
|
|
libc.Xmemset(tls, pFile, 0, uint64(24))
|
|
szName = _sqlite3Strlen30(tls, zName)
|
|
if szName > int32(1) && (libc.Int32FromUint8(**(**uint8)(__ccgo_up(zName))) == int32('/') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zName))) == int32('\\')) {
|
|
pVfsMutex = _sqlite3MutexAlloc(tls, int32(SQLITE_MUTEX_STATIC_VFS1))
|
|
Xsqlite3_mutex_enter(tls, pVfsMutex)
|
|
i = 0
|
|
for {
|
|
if !(i < _memdb_g.FnMemStore) {
|
|
break
|
|
}
|
|
if libc.Xstrcmp(tls, (*TMemStore)(unsafe.Pointer(**(**uintptr)(__ccgo_up(_memdb_g.FapMemStore + uintptr(i)*8)))).FzFName, zName) == 0 {
|
|
p = **(**uintptr)(__ccgo_up(_memdb_g.FapMemStore + uintptr(i)*8))
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if p == uintptr(0) {
|
|
p = _sqlite3Malloc(tls, uint64(72)+libc.Uint64FromInt64(int64(szName))+uint64(3))
|
|
if p == uintptr(0) {
|
|
Xsqlite3_mutex_leave(tls, pVfsMutex)
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
apNew = _sqlite3Realloc(tls, _memdb_g.FapMemStore, uint64(8)*libc.Uint64FromInt64(libc.Int64FromInt32(1)+int64(_memdb_g.FnMemStore)))
|
|
if apNew == uintptr(0) {
|
|
Xsqlite3_free(tls, p)
|
|
Xsqlite3_mutex_leave(tls, pVfsMutex)
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
v3 = uintptr(unsafe.Pointer(&_memdb_g))
|
|
v2 = *(*int32)(unsafe.Pointer(v3))
|
|
*(*int32)(unsafe.Pointer(v3)) = *(*int32)(unsafe.Pointer(v3)) + 1
|
|
**(**uintptr)(__ccgo_up(apNew + uintptr(v2)*8)) = p
|
|
_memdb_g.FapMemStore = apNew
|
|
libc.Xmemset(tls, p, 0, uint64(72))
|
|
(*TMemStore)(unsafe.Pointer(p)).FmFlags = libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_DESERIALIZE_RESIZEABLE) | libc.Int32FromInt32(SQLITE_DESERIALIZE_FREEONCLOSE))
|
|
(*TMemStore)(unsafe.Pointer(p)).FszMax = _sqlite3Config.FmxMemdbSize
|
|
(*TMemStore)(unsafe.Pointer(p)).FzFName = p + 1*72
|
|
libc.Xmemcpy(tls, (*TMemStore)(unsafe.Pointer(p)).FzFName, zName, libc.Uint64FromInt32(szName+int32(1)))
|
|
(*TMemStore)(unsafe.Pointer(p)).FpMutex = Xsqlite3_mutex_alloc(tls, SQLITE_MUTEX_FAST)
|
|
if (*TMemStore)(unsafe.Pointer(p)).FpMutex == uintptr(0) {
|
|
_memdb_g.FnMemStore = _memdb_g.FnMemStore - 1
|
|
Xsqlite3_free(tls, p)
|
|
Xsqlite3_mutex_leave(tls, pVfsMutex)
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
(*TMemStore)(unsafe.Pointer(p)).FnRef = int32(1)
|
|
_memdbEnter(tls, p)
|
|
} else {
|
|
_memdbEnter(tls, p)
|
|
(*TMemStore)(unsafe.Pointer(p)).FnRef = (*TMemStore)(unsafe.Pointer(p)).FnRef + 1
|
|
}
|
|
Xsqlite3_mutex_leave(tls, pVfsMutex)
|
|
} else {
|
|
p = _sqlite3Malloc(tls, uint64(72))
|
|
if p == uintptr(0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
libc.Xmemset(tls, p, 0, uint64(72))
|
|
(*TMemStore)(unsafe.Pointer(p)).FmFlags = libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_DESERIALIZE_RESIZEABLE) | libc.Int32FromInt32(SQLITE_DESERIALIZE_FREEONCLOSE))
|
|
(*TMemStore)(unsafe.Pointer(p)).FszMax = _sqlite3Config.FmxMemdbSize
|
|
}
|
|
(*TMemFile)(unsafe.Pointer(pFile)).FpStore = p
|
|
if pOutFlags != uintptr(0) {
|
|
**(**int32)(__ccgo_up(pOutFlags)) = flags | int32(SQLITE_OPEN_MEMORY)
|
|
}
|
|
(*Tsqlite3_file)(unsafe.Pointer(pFd)).FpMethods = uintptr(unsafe.Pointer(&_memdb_io_methods))
|
|
_memdbLeave(tls, p)
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Parameter zSuper is the name of a super-journal file. A single journal
|
|
// ** file that referred to the super-journal file has just been rolled back.
|
|
// ** This routine checks if it is possible to delete the super-journal file,
|
|
// ** and does so if it is.
|
|
// **
|
|
// ** Argument zSuper may point to Pager.pTmpSpace. So that buffer is not
|
|
// ** available for use within this function.
|
|
// **
|
|
// ** When a super-journal file is created, it is populated with the names
|
|
// ** of all of its child journals, one after another, formatted as utf-8
|
|
// ** encoded text. The end of each child journal file is marked with a
|
|
// ** nul-terminator byte (0x00). i.e. the entire contents of a super-journal
|
|
// ** file for a transaction involving two databases might be:
|
|
// **
|
|
// ** "/home/bill/a.db-journal\x00/home/bill/b.db-journal\x00"
|
|
// **
|
|
// ** A super-journal file may only be deleted once all of its child
|
|
// ** journals have been rolled back.
|
|
// **
|
|
// ** This function reads the contents of the super-journal file into
|
|
// ** memory and loops through each of the child journal names. For
|
|
// ** each child journal, it checks if:
|
|
// **
|
|
// ** * if the child journal exists, and if so
|
|
// ** * if the child journal contains a reference to super-journal
|
|
// ** file zSuper
|
|
// **
|
|
// ** If a child journal can be found that matches both of the criteria
|
|
// ** above, this function returns without doing anything. Otherwise, if
|
|
// ** no such child journal can be found, file zSuper is deleted from
|
|
// ** the file-system using sqlite3OsDelete().
|
|
// **
|
|
// ** If an IO error within this function, an error code is returned. This
|
|
// ** function allocates memory by calling sqlite3Malloc(). If an allocation
|
|
// ** fails, SQLITE_NOMEM is returned. Otherwise, if no IO or malloc errors
|
|
// ** occur, SQLITE_OK is returned.
|
|
// **
|
|
// ** TODO: This function allocates a single block of memory to load
|
|
// ** the entire contents of the super-journal file. This could be
|
|
// ** a couple of kilobytes or so - potentially larger than the page
|
|
// ** size.
|
|
// */
|
|
func _pager_delsuper(tls *libc.TLS, pPager uintptr, zSuper uintptr) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var bSeen, c, flags, flags1, rc int32
|
|
var pJournal, pSuper, pVfs, zFree, zJournal, zSuperJournal uintptr
|
|
var v1, v2, v3 uint8
|
|
var _ /* exists at bp+8 */ int32
|
|
var _ /* nSuperJournal at bp+0 */ Ti64
|
|
var _ /* zSuperPtr at bp+16 */ uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _ = bSeen, c, flags, flags1, pJournal, pSuper, pVfs, rc, zFree, zJournal, zSuperJournal, v1, v2, v3
|
|
pVfs = (*TPager)(unsafe.Pointer(pPager)).FpVfs /* Malloc'd child-journal file descriptor */
|
|
zSuperJournal = uintptr(0) /* Pointer to one journal within MJ file */
|
|
zFree = uintptr(0) /* Free this buffer */
|
|
bSeen = 0 /* If super-journal contains pPager->zJournal */
|
|
/* Check if this looks like a real super-journal name. If it does not,
|
|
** return SQLITE_OK without attempting to delete it. This is to limit
|
|
** the degree to which a crafted journal file can be used to cause
|
|
** SQLite to delete arbitrary files. */
|
|
if _pagerIsSuperJrnlName(tls, zSuper) == 0 {
|
|
return SQLITE_OK
|
|
}
|
|
/* Allocate space for both the pJournal and pSuper file descriptors.
|
|
** If successful, open the super-journal file for reading.
|
|
*/
|
|
pSuper = _sqlite3MallocZero(tls, libc.Uint64FromInt64(int64(2)*int64((*Tsqlite3_vfs)(unsafe.Pointer(pVfs)).FszOsFile)))
|
|
if !(pSuper != 0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
pJournal = uintptr(0)
|
|
} else {
|
|
flags = libc.Int32FromInt32(SQLITE_OPEN_READONLY) | libc.Int32FromInt32(SQLITE_OPEN_SUPER_JOURNAL)
|
|
rc = _sqlite3OsOpen(tls, pVfs, zSuper, pSuper, flags, uintptr(0))
|
|
pJournal = pSuper + uintptr((*Tsqlite3_vfs)(unsafe.Pointer(pVfs)).FszOsFile)
|
|
}
|
|
if rc != SQLITE_OK {
|
|
goto delsuper_out
|
|
}
|
|
/* Load the entire super-journal file into space obtained from
|
|
** sqlite3_malloc() and pointed to by zSuperJournal. Also obtain
|
|
** sufficient space (in zSuperPtr) to hold the names of super-journal
|
|
** files extracted from regular rollback-journals.
|
|
*/
|
|
rc = _sqlite3OsFileSize(tls, pSuper, bp)
|
|
if rc != SQLITE_OK {
|
|
goto delsuper_out
|
|
}
|
|
zFree = _sqlite3Malloc(tls, libc.Uint64FromInt64(int64(4)+**(**Ti64)(__ccgo_up(bp))+int64(2)))
|
|
if !(zFree != 0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
goto delsuper_out
|
|
} else {
|
|
}
|
|
v3 = libc.Uint8FromInt32(0)
|
|
**(**uint8)(__ccgo_up(zFree + 3)) = v3
|
|
v2 = v3
|
|
**(**uint8)(__ccgo_up(zFree + 2)) = v2
|
|
v1 = v2
|
|
**(**uint8)(__ccgo_up(zFree + 1)) = v1
|
|
**(**uint8)(__ccgo_up(zFree)) = v1
|
|
zSuperJournal = zFree + 4
|
|
rc = _sqlite3OsRead(tls, pSuper, zSuperJournal, int32(**(**Ti64)(__ccgo_up(bp))), 0)
|
|
if rc != SQLITE_OK {
|
|
goto delsuper_out
|
|
}
|
|
**(**uint8)(__ccgo_up(zSuperJournal + uintptr(**(**Ti64)(__ccgo_up(bp))))) = uint8(0)
|
|
**(**uint8)(__ccgo_up(zSuperJournal + uintptr(**(**Ti64)(__ccgo_up(bp))+int64(1)))) = uint8(0)
|
|
zJournal = zSuperJournal
|
|
for int64(zJournal)-int64(zSuperJournal) < **(**Ti64)(__ccgo_up(bp)) {
|
|
if libc.Xstrcmp(tls, zJournal, (*TPager)(unsafe.Pointer(pPager)).FzJournal) == 0 {
|
|
bSeen = int32(1)
|
|
} else {
|
|
rc = _sqlite3OsAccess(tls, pVfs, zJournal, SQLITE_ACCESS_EXISTS, bp+8)
|
|
if rc != SQLITE_OK {
|
|
goto delsuper_out
|
|
}
|
|
if **(**int32)(__ccgo_up(bp + 8)) != 0 {
|
|
**(**uintptr)(__ccgo_up(bp + 16)) = uintptr(0)
|
|
flags1 = libc.Int32FromInt32(SQLITE_OPEN_READONLY) | libc.Int32FromInt32(SQLITE_OPEN_SUPER_JOURNAL)
|
|
rc = _sqlite3OsOpen(tls, pVfs, zJournal, pJournal, flags1, uintptr(0))
|
|
if rc != SQLITE_OK {
|
|
goto delsuper_out
|
|
}
|
|
rc = _readSuperJournal(tls, pJournal, uint64(1)+libc.Uint64FromInt32((*Tsqlite3_vfs)(unsafe.Pointer(pVfs)).FmxPathname), bp+16)
|
|
_sqlite3OsClose(tls, pJournal)
|
|
if rc != SQLITE_OK {
|
|
goto delsuper_out
|
|
}
|
|
c = libc.BoolInt32(**(**uintptr)(__ccgo_up(bp + 16)) != uintptr(0) && libc.Xstrcmp(tls, **(**uintptr)(__ccgo_up(bp + 16)), zSuper) == 0)
|
|
_freeSuperJournal(tls, **(**uintptr)(__ccgo_up(bp + 16)))
|
|
if c != 0 {
|
|
/* We have a match. Do not delete the super-journal file. */
|
|
goto delsuper_out
|
|
}
|
|
}
|
|
}
|
|
zJournal = zJournal + uintptr(_sqlite3Strlen30(tls, zJournal)+libc.Int32FromInt32(1))
|
|
}
|
|
_sqlite3OsClose(tls, pSuper)
|
|
if bSeen != 0 {
|
|
/* Only delete the super-journal if bSeen is true - indicating that
|
|
** the super-journal contained a pointer to this database's journal
|
|
** file. */
|
|
rc = _sqlite3OsDelete(tls, pVfs, zSuper, 0)
|
|
}
|
|
goto delsuper_out
|
|
delsuper_out:
|
|
;
|
|
Xsqlite3_free(tls, zFree)
|
|
if pSuper != 0 {
|
|
_sqlite3OsClose(tls, pSuper)
|
|
Xsqlite3_free(tls, pSuper)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Compare two UTF-8 strings for equality where the first string is
|
|
// ** a GLOB or LIKE expression. Return values:
|
|
// **
|
|
// ** SQLITE_MATCH: Match
|
|
// ** SQLITE_NOMATCH: No match
|
|
// ** SQLITE_NOWILDCARDMATCH: No match in spite of having * or % wildcards.
|
|
// **
|
|
// ** Globbing rules:
|
|
// **
|
|
// ** '*' Matches any sequence of zero or more characters.
|
|
// **
|
|
// ** '?' Matches exactly one character.
|
|
// **
|
|
// ** [...] Matches one character from the enclosed list of
|
|
// ** characters.
|
|
// **
|
|
// ** [^...] Matches one character not in the enclosed list.
|
|
// **
|
|
// ** With the [...] and [^...] matching, a ']' character can be included
|
|
// ** in the list by making it the first character after '[' or '^'. A
|
|
// ** range of characters can be specified using '-'. Example:
|
|
// ** "[a-z]" matches any single lower-case letter. To match a '-', make
|
|
// ** it the last character in the list.
|
|
// **
|
|
// ** Like matching rules:
|
|
// **
|
|
// ** '%' Matches any sequence of zero or more characters
|
|
// **
|
|
// *** '_' Matches any one character
|
|
// **
|
|
// ** Ec Where E is the "esc" character and c is any other
|
|
// ** character, including '%', '_', and esc, match exactly c.
|
|
// **
|
|
// ** The comments within this routine usually assume glob matching.
|
|
// **
|
|
// ** This routine is usually quick, but can be N**2 in the worst case.
|
|
// */
|
|
func _patternCompare(tls *libc.TLS, _zPattern uintptr, _zString uintptr, pInfo uintptr, matchOther Tu32) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
*(*uintptr)(unsafe.Pointer(bp)) = _zPattern
|
|
*(*uintptr)(unsafe.Pointer(bp + 8)) = _zString
|
|
var bMatch, bMatch1, bMatch2, invert, seen, v13 int32
|
|
var c, c2, matchAll, matchOne, prior_c, v1, v4 Tu32
|
|
var noCase Tu8
|
|
var zEscaped, v3, v6 uintptr
|
|
var v2, v5 uint32
|
|
var _ /* zStop at bp+18 */ [3]uint8
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = bMatch, bMatch1, bMatch2, c, c2, invert, matchAll, matchOne, noCase, prior_c, seen, zEscaped, v1, v13, v2, v3, v4, v5, v6 /* Next pattern and input string chars */
|
|
matchOne = uint32((*TcompareInfo)(unsafe.Pointer(pInfo)).FmatchOne) /* "?" or "_" */
|
|
matchAll = uint32((*TcompareInfo)(unsafe.Pointer(pInfo)).FmatchAll) /* "*" or "%" */
|
|
noCase = (*TcompareInfo)(unsafe.Pointer(pInfo)).FnoCase /* True if uppercase==lowercase */
|
|
zEscaped = uintptr(0) /* One past the last escaped input char */
|
|
for {
|
|
if libc.Int32FromUint8(**(**Tu8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp))))) < int32(0x80) {
|
|
v3 = **(**uintptr)(__ccgo_up(bp))
|
|
**(**uintptr)(__ccgo_up(bp)) = **(**uintptr)(__ccgo_up(bp)) + 1
|
|
v2 = uint32(**(**Tu8)(__ccgo_up(v3)))
|
|
} else {
|
|
v2 = _sqlite3Utf8Read(tls, bp)
|
|
}
|
|
v1 = v2
|
|
c = v1
|
|
if !(v1 != uint32(0)) {
|
|
break
|
|
}
|
|
if c == matchAll { /* Match "*" */
|
|
/* Skip over multiple "*" characters in the pattern. If there
|
|
** are also "?" characters, skip those as well, but consume a
|
|
** single character of the input string for each "?" skipped */
|
|
for {
|
|
if libc.Int32FromUint8(**(**Tu8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp))))) < int32(0x80) {
|
|
v6 = **(**uintptr)(__ccgo_up(bp))
|
|
**(**uintptr)(__ccgo_up(bp)) = **(**uintptr)(__ccgo_up(bp)) + 1
|
|
v5 = uint32(**(**Tu8)(__ccgo_up(v6)))
|
|
} else {
|
|
v5 = _sqlite3Utf8Read(tls, bp)
|
|
}
|
|
v4 = v5
|
|
c = v4
|
|
if !(v4 == matchAll || c == matchOne && matchOne != uint32(0)) {
|
|
break
|
|
}
|
|
if c == matchOne && _sqlite3Utf8Read(tls, bp+8) == uint32(0) {
|
|
return int32(SQLITE_NOWILDCARDMATCH)
|
|
}
|
|
}
|
|
if c == uint32(0) {
|
|
return SQLITE_MATCH /* "*" at the end of the pattern matches */
|
|
} else {
|
|
if c == matchOther {
|
|
if libc.Int32FromUint8((*TcompareInfo)(unsafe.Pointer(pInfo)).FmatchSet) == 0 {
|
|
c = _sqlite3Utf8Read(tls, bp)
|
|
if c == uint32(0) {
|
|
return int32(SQLITE_NOWILDCARDMATCH)
|
|
}
|
|
} else {
|
|
/* "[...]" immediately follows the "*". We have to do a slow
|
|
** recursive search in this case, but it is an unusual case. */
|
|
/* '[' is a single-byte character */
|
|
for **(**Tu8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp + 8)))) != 0 {
|
|
bMatch = _patternCompare(tls, **(**uintptr)(__ccgo_up(bp))+uintptr(-libc.Int32FromInt32(1)), **(**uintptr)(__ccgo_up(bp + 8)), pInfo, matchOther)
|
|
if bMatch != int32(SQLITE_NOMATCH) {
|
|
return bMatch
|
|
}
|
|
v3 = **(**uintptr)(__ccgo_up(bp + 8))
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = **(**uintptr)(__ccgo_up(bp + 8)) + 1
|
|
if libc.Int32FromUint8(**(**Tu8)(__ccgo_up(v3))) >= int32(0xc0) {
|
|
for libc.Int32FromUint8(**(**Tu8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp + 8)))))&int32(0xc0) == int32(0x80) {
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = **(**uintptr)(__ccgo_up(bp + 8)) + 1
|
|
}
|
|
}
|
|
}
|
|
return int32(SQLITE_NOWILDCARDMATCH)
|
|
}
|
|
}
|
|
}
|
|
/* At this point variable c contains the first character of the
|
|
** pattern string past the "*". Search in the input string for the
|
|
** first matching character and recursively continue the match from
|
|
** that point.
|
|
**
|
|
** For a case-insensitive search, set variable cx to be the same as
|
|
** c but in the other case and search the input string for either
|
|
** c or cx.
|
|
*/
|
|
if c < uint32(0x80) {
|
|
if noCase != 0 {
|
|
(**(**[3]uint8)(__ccgo_up(bp + 18)))[0] = uint8(c & libc.Uint32FromInt32(^(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(c)]) & libc.Int32FromInt32(0x20))))
|
|
(**(**[3]uint8)(__ccgo_up(bp + 18)))[int32(1)] = _sqlite3UpperToLower[uint8(c)]
|
|
(**(**[3]uint8)(__ccgo_up(bp + 18)))[int32(2)] = uint8(0)
|
|
} else {
|
|
(**(**[3]uint8)(__ccgo_up(bp + 18)))[0] = uint8(c)
|
|
(**(**[3]uint8)(__ccgo_up(bp + 18)))[int32(1)] = uint8(0)
|
|
}
|
|
for int32(1) != 0 {
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = **(**uintptr)(__ccgo_up(bp + 8)) + uintptr(libc.Xstrcspn(tls, **(**uintptr)(__ccgo_up(bp + 8)), bp+18))
|
|
if libc.Int32FromUint8(**(**Tu8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp + 8))))) == 0 {
|
|
break
|
|
}
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = **(**uintptr)(__ccgo_up(bp + 8)) + 1
|
|
bMatch1 = _patternCompare(tls, **(**uintptr)(__ccgo_up(bp)), **(**uintptr)(__ccgo_up(bp + 8)), pInfo, matchOther)
|
|
if bMatch1 != int32(SQLITE_NOMATCH) {
|
|
return bMatch1
|
|
}
|
|
}
|
|
} else {
|
|
for {
|
|
if libc.Int32FromUint8(**(**Tu8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp + 8))))) < int32(0x80) {
|
|
v3 = **(**uintptr)(__ccgo_up(bp + 8))
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = **(**uintptr)(__ccgo_up(bp + 8)) + 1
|
|
v2 = uint32(**(**Tu8)(__ccgo_up(v3)))
|
|
} else {
|
|
v2 = _sqlite3Utf8Read(tls, bp+8)
|
|
}
|
|
v1 = v2
|
|
c2 = v1
|
|
if !(v1 != uint32(0)) {
|
|
break
|
|
}
|
|
if c2 != c {
|
|
continue
|
|
}
|
|
bMatch2 = _patternCompare(tls, **(**uintptr)(__ccgo_up(bp)), **(**uintptr)(__ccgo_up(bp + 8)), pInfo, matchOther)
|
|
if bMatch2 != int32(SQLITE_NOMATCH) {
|
|
return bMatch2
|
|
}
|
|
}
|
|
}
|
|
return int32(SQLITE_NOWILDCARDMATCH)
|
|
}
|
|
if c == matchOther {
|
|
if libc.Int32FromUint8((*TcompareInfo)(unsafe.Pointer(pInfo)).FmatchSet) == 0 {
|
|
c = _sqlite3Utf8Read(tls, bp)
|
|
if c == uint32(0) {
|
|
return int32(SQLITE_NOMATCH)
|
|
}
|
|
zEscaped = **(**uintptr)(__ccgo_up(bp))
|
|
} else {
|
|
prior_c = uint32(0)
|
|
seen = 0
|
|
invert = 0
|
|
c = _sqlite3Utf8Read(tls, bp+8)
|
|
if c == uint32(0) {
|
|
return int32(SQLITE_NOMATCH)
|
|
}
|
|
c2 = _sqlite3Utf8Read(tls, bp)
|
|
if c2 == uint32('^') {
|
|
invert = int32(1)
|
|
c2 = _sqlite3Utf8Read(tls, bp)
|
|
}
|
|
if c2 == uint32(']') {
|
|
if c == uint32(']') {
|
|
seen = int32(1)
|
|
}
|
|
c2 = _sqlite3Utf8Read(tls, bp)
|
|
}
|
|
for c2 != 0 && c2 != uint32(']') {
|
|
if c2 == uint32('-') && libc.Int32FromUint8(**(**Tu8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp))))) != int32(']') && libc.Int32FromUint8(**(**Tu8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp))))) != 0 && prior_c > uint32(0) {
|
|
c2 = _sqlite3Utf8Read(tls, bp)
|
|
if c >= prior_c && c <= c2 {
|
|
seen = int32(1)
|
|
}
|
|
prior_c = uint32(0)
|
|
} else {
|
|
if c == c2 {
|
|
seen = int32(1)
|
|
}
|
|
prior_c = c2
|
|
}
|
|
c2 = _sqlite3Utf8Read(tls, bp)
|
|
}
|
|
if c2 == uint32(0) || seen^invert == 0 {
|
|
return int32(SQLITE_NOMATCH)
|
|
}
|
|
continue
|
|
}
|
|
}
|
|
if libc.Int32FromUint8(**(**Tu8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp + 8))))) < int32(0x80) {
|
|
v3 = **(**uintptr)(__ccgo_up(bp + 8))
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = **(**uintptr)(__ccgo_up(bp + 8)) + 1
|
|
v2 = uint32(**(**Tu8)(__ccgo_up(v3)))
|
|
} else {
|
|
v2 = _sqlite3Utf8Read(tls, bp+8)
|
|
}
|
|
c2 = v2
|
|
if c == c2 {
|
|
continue
|
|
}
|
|
if noCase != 0 && libc.Int32FromUint8(_sqlite3UpperToLower[uint8(c)]) == libc.Int32FromUint8(_sqlite3UpperToLower[uint8(c2)]) && c < uint32(0x80) && c2 < uint32(0x80) {
|
|
continue
|
|
}
|
|
if c == matchOne && **(**uintptr)(__ccgo_up(bp)) != zEscaped && c2 != uint32(0) {
|
|
continue
|
|
}
|
|
return int32(SQLITE_NOMATCH)
|
|
}
|
|
if libc.Int32FromUint8(**(**Tu8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp + 8))))) == 0 {
|
|
v13 = SQLITE_MATCH
|
|
} else {
|
|
v13 = int32(SQLITE_NOMATCH)
|
|
}
|
|
return v13
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This is a Walker expression callback. pExpr is a node from the WHERE
|
|
// ** clause of a SELECT statement. This function examines pExpr to see if
|
|
// ** any substitutions based on the contents of pWalker->u.pConst should
|
|
// ** be made to pExpr or its immediate children.
|
|
// **
|
|
// ** A substitution is made if:
|
|
// **
|
|
// ** + pExpr is a column with an affinity other than BLOB that matches
|
|
// ** one of the columns in pWalker->u.pConst, or
|
|
// **
|
|
// ** + pExpr is a binary comparison operator (=, <=, >=, <, >) that
|
|
// ** uses an affinity other than TEXT and one of its immediate
|
|
// ** children is a column that matches one of the columns in
|
|
// ** pWalker->u.pConst.
|
|
// */
|
|
func _propagateConstantExprRewrite(tls *libc.TLS, pWalker uintptr, pExpr uintptr) (r int32) {
|
|
var pConst uintptr
|
|
_ = pConst
|
|
pConst = *(*uintptr)(unsafe.Pointer(pWalker + 40))
|
|
if (*TWhereConst)(unsafe.Pointer(pConst)).FbHasAffBlob != 0 {
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) >= int32(TK_EQ) && libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) <= int32(TK_GE) || libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_IS) {
|
|
_propagateConstantExprRewriteOne(tls, pConst, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, 0)
|
|
if **(**Tu8)(__ccgo_up((*TWhereConst)(unsafe.Pointer(pConst)).FpOomFault)) != 0 {
|
|
return int32(WRC_Prune)
|
|
}
|
|
if libc.Int32FromUint8(_sqlite3ExprAffinity(tls, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft)) != int32(SQLITE_AFF_TEXT) {
|
|
_propagateConstantExprRewriteOne(tls, pConst, (*TExpr)(unsafe.Pointer(pExpr)).FpRight, 0)
|
|
}
|
|
}
|
|
}
|
|
return _propagateConstantExprRewriteOne(tls, pConst, pExpr, (*TWhereConst)(unsafe.Pointer(pConst)).FbHasAffBlob)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This is a helper function for Walker callback propagateConstantExprRewrite().
|
|
// **
|
|
// ** Argument pExpr is a candidate expression to be replaced by a value. If
|
|
// ** pExpr is equivalent to one of the columns named in pWalker->u.pConst,
|
|
// ** then overwrite it with the corresponding value. Except, do not do so
|
|
// ** if argument bIgnoreAffBlob is non-zero and the affinity of pExpr
|
|
// ** is SQLITE_AFF_BLOB.
|
|
// */
|
|
func _propagateConstantExprRewriteOne(tls *libc.TLS, pConst uintptr, pExpr uintptr, bIgnoreAffBlob int32) (r int32) {
|
|
var i int32
|
|
var pColumn uintptr
|
|
_, _ = i, pColumn
|
|
if **(**Tu8)(__ccgo_up((*TWhereConst)(unsafe.Pointer(pConst)).FpOomFault)) != 0 {
|
|
return int32(WRC_Prune)
|
|
}
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) != int32(TK_COLUMN) {
|
|
return WRC_Continue
|
|
}
|
|
if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&(libc.Uint32FromInt32(EP_FixedCol)|(*TWhereConst)(unsafe.Pointer(pConst)).FmExcludeOn) != uint32(0) {
|
|
return WRC_Continue
|
|
}
|
|
i = 0
|
|
for {
|
|
if !(i < (*TWhereConst)(unsafe.Pointer(pConst)).FnConst) {
|
|
break
|
|
}
|
|
pColumn = **(**uintptr)(__ccgo_up((*TWhereConst)(unsafe.Pointer(pConst)).FapExpr + uintptr(i*int32(2))*8))
|
|
if pColumn == pExpr {
|
|
goto _1
|
|
}
|
|
if (*TExpr)(unsafe.Pointer(pColumn)).FiTable != (*TExpr)(unsafe.Pointer(pExpr)).FiTable {
|
|
goto _1
|
|
}
|
|
if int32((*TExpr)(unsafe.Pointer(pColumn)).FiColumn) != int32((*TExpr)(unsafe.Pointer(pExpr)).FiColumn) {
|
|
goto _1
|
|
}
|
|
if bIgnoreAffBlob != 0 && libc.Int32FromUint8(_sqlite3ExprAffinity(tls, pColumn)) <= int32(SQLITE_AFF_BLOB) {
|
|
break
|
|
}
|
|
/* A match is found. Add the EP_FixedCol property */
|
|
(*TWhereConst)(unsafe.Pointer(pConst)).FnChng = (*TWhereConst)(unsafe.Pointer(pConst)).FnChng + 1
|
|
**(**Tu32)(__ccgo_up(pExpr + 4)) &= ^libc.Uint32FromInt32(libc.Int32FromInt32(EP_Leaf))
|
|
**(**Tu32)(__ccgo_up(pExpr + 4)) |= libc.Uint32FromInt32(libc.Int32FromInt32(EP_FixedCol))
|
|
(*TExpr)(unsafe.Pointer(pExpr)).FpLeft = _sqlite3ExprDup(tls, (*TParse)(unsafe.Pointer((*TWhereConst)(unsafe.Pointer(pConst)).FpParse)).Fdb, **(**uintptr)(__ccgo_up((*TWhereConst)(unsafe.Pointer(pConst)).FapExpr + uintptr(i*int32(2)+int32(1))*8)), 0)
|
|
if (*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer((*TWhereConst)(unsafe.Pointer(pConst)).FpParse)).Fdb)).FmallocFailed != 0 {
|
|
return int32(WRC_Prune)
|
|
}
|
|
break
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return int32(WRC_Prune)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Apply a delta.
|
|
// **
|
|
// ** The output buffer should be big enough to hold the whole output
|
|
// ** file and a NUL terminator at the end. The delta_output_size()
|
|
// ** routine will determine this size for you.
|
|
// **
|
|
// ** The delta string should be null-terminated. But the delta string
|
|
// ** may contain embedded NUL characters (if the input and output are
|
|
// ** binary files) so we also have to pass in the length of the delta in
|
|
// ** the lenDelta parameter.
|
|
// **
|
|
// ** This function returns the size of the output file in bytes (excluding
|
|
// ** the final NUL terminator character). Except, if the delta string is
|
|
// ** malformed or intended for use with a source file other than zSrc,
|
|
// ** then this routine returns -1.
|
|
// **
|
|
// ** Refer to the delta_create() documentation above for a description
|
|
// ** of the delta file format.
|
|
// */
|
|
func _rbuDeltaApply(tls *libc.TLS, zSrc uintptr, lenSrc int32, _zDelta uintptr, _lenDelta int32, zOut uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
*(*uintptr)(unsafe.Pointer(bp)) = _zDelta
|
|
*(*int32)(unsafe.Pointer(bp + 8)) = _lenDelta
|
|
var cnt, ofst uint32
|
|
var limit, total Tsqlite3_uint64
|
|
_, _, _, _ = cnt, limit, ofst, total
|
|
total = uint64(0)
|
|
limit = uint64(_rbuDeltaGetInt(tls, bp, bp+8))
|
|
if **(**int32)(__ccgo_up(bp + 8)) <= 0 || libc.Int32FromUint8(**(**uint8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp))))) != int32('\n') {
|
|
/* ERROR: size integer not terminated by "\n" */
|
|
return -int32(1)
|
|
}
|
|
**(**uintptr)(__ccgo_up(bp)) = **(**uintptr)(__ccgo_up(bp)) + 1
|
|
**(**int32)(__ccgo_up(bp + 8)) = **(**int32)(__ccgo_up(bp + 8)) - 1 /* Skip the \n */
|
|
for **(**int32)(__ccgo_up(bp + 8)) > 0 && **(**uint8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp)))) != 0 {
|
|
cnt = _rbuDeltaGetInt(tls, bp, bp+8)
|
|
if **(**int32)(__ccgo_up(bp + 8)) <= 0 {
|
|
return -int32(1)
|
|
}
|
|
switch libc.Int32FromUint8(**(**uint8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp))))) {
|
|
case int32('@'):
|
|
**(**uintptr)(__ccgo_up(bp)) = **(**uintptr)(__ccgo_up(bp)) + 1
|
|
**(**int32)(__ccgo_up(bp + 8)) = **(**int32)(__ccgo_up(bp + 8)) - 1
|
|
ofst = _rbuDeltaGetInt(tls, bp, bp+8)
|
|
if **(**int32)(__ccgo_up(bp + 8)) > 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp))))) != int32(',') {
|
|
/* ERROR: copy command not terminated by ',' */
|
|
return -int32(1)
|
|
}
|
|
**(**uintptr)(__ccgo_up(bp)) = **(**uintptr)(__ccgo_up(bp)) + 1
|
|
**(**int32)(__ccgo_up(bp + 8)) = **(**int32)(__ccgo_up(bp + 8)) - 1
|
|
total = total + uint64(cnt)
|
|
if total > limit {
|
|
/* ERROR: copy exceeds output file size */
|
|
return -int32(1)
|
|
}
|
|
if uint64(ofst)+uint64(cnt) > libc.Uint64FromInt32(lenSrc) {
|
|
/* ERROR: copy extends past end of input */
|
|
return -int32(1)
|
|
}
|
|
libc.Xmemcpy(tls, zOut, zSrc+uintptr(ofst), uint64(cnt))
|
|
zOut = zOut + uintptr(cnt)
|
|
case int32(':'):
|
|
**(**uintptr)(__ccgo_up(bp)) = **(**uintptr)(__ccgo_up(bp)) + 1
|
|
**(**int32)(__ccgo_up(bp + 8)) = **(**int32)(__ccgo_up(bp + 8)) - 1
|
|
total = total + uint64(cnt)
|
|
if total > limit {
|
|
/* ERROR: insert command gives an output larger than predicted */
|
|
return -int32(1)
|
|
}
|
|
if cnt > libc.Uint32FromInt32(**(**int32)(__ccgo_up(bp + 8))) {
|
|
/* ERROR: insert count exceeds size of delta */
|
|
return -int32(1)
|
|
}
|
|
libc.Xmemcpy(tls, zOut, **(**uintptr)(__ccgo_up(bp)), uint64(cnt))
|
|
zOut = zOut + uintptr(cnt)
|
|
**(**uintptr)(__ccgo_up(bp)) = **(**uintptr)(__ccgo_up(bp)) + uintptr(cnt)
|
|
**(**int32)(__ccgo_up(bp + 8)) = libc.Int32FromUint32(uint32(**(**int32)(__ccgo_up(bp + 8))) - cnt)
|
|
case int32(';'):
|
|
**(**uintptr)(__ccgo_up(bp)) = **(**uintptr)(__ccgo_up(bp)) + 1
|
|
**(**int32)(__ccgo_up(bp + 8)) = **(**int32)(__ccgo_up(bp + 8)) - 1
|
|
**(**uint8)(__ccgo_up(zOut)) = uint8(0)
|
|
if total != limit {
|
|
/* ERROR: generated size does not match predicted size */
|
|
return -int32(1)
|
|
}
|
|
return libc.Int32FromUint64(total)
|
|
default:
|
|
/* ERROR: unknown delta operator */
|
|
return -int32(1)
|
|
}
|
|
}
|
|
/* ERROR: unterminated delta */
|
|
return -int32(1)
|
|
}
|
|
|
|
func _rbuDeltaOutputSize(tls *libc.TLS, _zDelta uintptr, _lenDelta int32) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
*(*uintptr)(unsafe.Pointer(bp)) = _zDelta
|
|
*(*int32)(unsafe.Pointer(bp + 8)) = _lenDelta
|
|
var size int32
|
|
_ = size
|
|
size = libc.Int32FromUint32(_rbuDeltaGetInt(tls, bp, bp+8))
|
|
if **(**int32)(__ccgo_up(bp + 8)) <= 0 || libc.Int32FromUint8(**(**uint8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp))))) != int32('\n') {
|
|
/* ERROR: size integer not terminated by "\n" */
|
|
return -int32(1)
|
|
}
|
|
return size
|
|
}
|
|
|
|
/*
|
|
** End of code taken from fossil.
|
|
*************************************************************************/
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function does the work for an sqlite3rbu_step() call.
|
|
// **
|
|
// ** The object-iterator (p->objiter) currently points to a valid object,
|
|
// ** and the input cursor (p->objiter.pSelect) currently points to a valid
|
|
// ** input row. Perform whatever processing is required and return.
|
|
// **
|
|
// ** If no error occurs, SQLITE_OK is returned. Otherwise, an error code
|
|
// ** and message is left in the RBU handle and a copy of the error code
|
|
// ** returned.
|
|
// */
|
|
func _rbuStep(tls *libc.TLS, p uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var c uint8
|
|
var eType, i int32
|
|
var pIter, pVal uintptr
|
|
var _ /* pUpdate at bp+8 */ uintptr
|
|
var _ /* zMask at bp+0 */ uintptr
|
|
_, _, _, _, _ = c, eType, i, pIter, pVal
|
|
pIter = p + 88
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
eType = _rbuStepType(tls, p, bp)
|
|
if eType != 0 {
|
|
if (*TRbuObjIter)(unsafe.Pointer(pIter)).FzIdx == uintptr(0) && (eType == int32(RBU_IDX_DELETE) || eType == int32(RBU_IDX_INSERT)) {
|
|
_rbuBadControlError(tls, p)
|
|
} else {
|
|
if eType == int32(RBU_REPLACE) {
|
|
if (*TRbuObjIter)(unsafe.Pointer(pIter)).FzIdx == uintptr(0) {
|
|
**(**Ti64)(__ccgo_up(p + 312)) += int64((*Tsqlite3rbu)(unsafe.Pointer(p)).Fobjiter.FnIndex)
|
|
_rbuStepOneOp(tls, p, int32(RBU_DELETE))
|
|
}
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK {
|
|
_rbuStepOneOp(tls, p, int32(RBU_INSERT))
|
|
}
|
|
} else {
|
|
if eType != int32(RBU_UPDATE) {
|
|
_rbuStepOneOp(tls, p, eType)
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = uintptr(0)
|
|
**(**Ti64)(__ccgo_up(p + 312)) -= int64((*Tsqlite3rbu)(unsafe.Pointer(p)).Fobjiter.FnIndex)
|
|
_rbuGetUpdateStmt(tls, p, pIter, **(**uintptr)(__ccgo_up(bp)), bp+8)
|
|
if **(**uintptr)(__ccgo_up(bp + 8)) != 0 {
|
|
i = 0
|
|
for {
|
|
if !((*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK && i < (*TRbuObjIter)(unsafe.Pointer(pIter)).FnCol) {
|
|
break
|
|
}
|
|
c = **(**uint8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp)) + uintptr(**(**int32)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FaiSrcOrder + uintptr(i)*4)))))
|
|
pVal = Xsqlite3_column_value(tls, (*TRbuObjIter)(unsafe.Pointer(pIter)).FpSelect, i)
|
|
if **(**Tu8)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FabTblPk + uintptr(i))) != 0 || libc.Int32FromUint8(c) != int32('.') {
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = Xsqlite3_bind_value(tls, **(**uintptr)(__ccgo_up(bp + 8)), i+int32(1), pVal)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK && ((*TRbuObjIter)(unsafe.Pointer(pIter)).FeType == int32(RBU_PK_VTAB) || (*TRbuObjIter)(unsafe.Pointer(pIter)).FeType == int32(RBU_PK_NONE)) {
|
|
/* Bind the rbu_rowid value to column _rowid_ */
|
|
pVal = Xsqlite3_column_value(tls, (*TRbuObjIter)(unsafe.Pointer(pIter)).FpSelect, (*TRbuObjIter)(unsafe.Pointer(pIter)).FnCol+int32(1))
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = Xsqlite3_bind_value(tls, **(**uintptr)(__ccgo_up(bp + 8)), (*TRbuObjIter)(unsafe.Pointer(pIter)).FnCol+int32(1), pVal)
|
|
}
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK {
|
|
Xsqlite3_step(tls, **(**uintptr)(__ccgo_up(bp + 8)))
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = _resetAndCollectError(tls, **(**uintptr)(__ccgo_up(bp + 8)), p+64)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Parameter pJrnl is a file-handle open on a journal file. This function
|
|
// ** attempts to read a super-journal file name from the end of the journal
|
|
// ** file. If successful, it sets output parameter (*pzSuper) to point to a
|
|
// ** buffer containing the super-journal name as a nul-terminated string.
|
|
// ** The caller is responsible for freeing the buffer using freeSuperJournal().
|
|
// **
|
|
// ** Refer to comments above writeSuperJournal() for the format used to store
|
|
// ** a super-journal file name at the end of a journal file.
|
|
// **
|
|
// ** Parameter nSuper is passed the maximum allowable size of the super journal
|
|
// ** name in bytes. If the super-journal name in the journal is longer than
|
|
// ** nSuper bytes (including a nul-terminator), then this is handled as if no
|
|
// ** super-journal name were present in the journal.
|
|
// **
|
|
// ** If there is no super-journal name at the end of pJrnl, (*pzSuper) is
|
|
// ** set to 0 and SQLITE_OK is returned. Or, if an error occurs while reading
|
|
// ** the super-journal name, an SQLite error code is returned and (*pzSuper)
|
|
// ** is set to 0.
|
|
// */
|
|
func _readSuperJournal(tls *libc.TLS, pJrnl uintptr, nSuper Tu64, pzSuper uintptr) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var rc, v1, v2, v4, v6 int32
|
|
var u Tu32
|
|
var zOut uintptr
|
|
var v3, v5, v7 bool
|
|
var _ /* aMagic at bp+24 */ [8]uint8
|
|
var _ /* cksum at bp+16 */ Tu32
|
|
var _ /* len at bp+0 */ Tu32
|
|
var _ /* szJ at bp+8 */ Ti64
|
|
_, _, _, _, _, _, _, _, _, _ = rc, u, zOut, v1, v2, v3, v4, v5, v6, v7 /* A buffer to hold the magic header */
|
|
zOut = uintptr(0)
|
|
**(**uintptr)(__ccgo_up(pzSuper)) = uintptr(0)
|
|
v1 = _sqlite3OsFileSize(tls, pJrnl, bp+8)
|
|
rc = v1
|
|
if v3 = SQLITE_OK != v1 || **(**Ti64)(__ccgo_up(bp + 8)) < int64(16); !v3 {
|
|
v2 = _read32bits(tls, pJrnl, **(**Ti64)(__ccgo_up(bp + 8))-int64(16), bp)
|
|
rc = v2
|
|
}
|
|
if v5 = v3 || SQLITE_OK != v2 || uint64(**(**Tu32)(__ccgo_up(bp))) >= nSuper || libc.Int64FromUint32(**(**Tu32)(__ccgo_up(bp))) > **(**Ti64)(__ccgo_up(bp + 8))-int64(16) || **(**Tu32)(__ccgo_up(bp)) == uint32(0); !v5 {
|
|
v4 = _read32bits(tls, pJrnl, **(**Ti64)(__ccgo_up(bp + 8))-int64(12), bp+16)
|
|
rc = v4
|
|
}
|
|
if v7 = v5 || SQLITE_OK != v4; !v7 {
|
|
v6 = _sqlite3OsRead(tls, pJrnl, bp+24, int32(8), **(**Ti64)(__ccgo_up(bp + 8))-int64(8))
|
|
rc = v6
|
|
}
|
|
if v7 || SQLITE_OK != v6 || libc.Xmemcmp(tls, bp+24, uintptr(unsafe.Pointer(&_aJournalMagic)), uint64(8)) != 0 {
|
|
return rc
|
|
}
|
|
zOut = _sqlite3MallocZero(tls, uint64(uint32(4)+**(**Tu32)(__ccgo_up(bp))+uint32(2)))
|
|
if !(zOut != 0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
} else {
|
|
zOut = zOut + 4
|
|
v1 = _sqlite3OsRead(tls, pJrnl, zOut, libc.Int32FromUint32(**(**Tu32)(__ccgo_up(bp))), **(**Ti64)(__ccgo_up(bp + 8))-int64(16)-libc.Int64FromUint32(**(**Tu32)(__ccgo_up(bp))))
|
|
rc = v1
|
|
if SQLITE_OK == v1 { /* Unsigned loop counter */
|
|
/* See if the checksum matches the super-journal name */
|
|
u = uint32(0)
|
|
for {
|
|
if !(u < **(**Tu32)(__ccgo_up(bp))) {
|
|
break
|
|
}
|
|
**(**Tu32)(__ccgo_up(bp + 16)) = **(**Tu32)(__ccgo_up(bp + 16)) - uint32(**(**uint8)(__ccgo_up(zOut + uintptr(u))))
|
|
goto _9
|
|
_9:
|
|
;
|
|
u = u + 1
|
|
}
|
|
}
|
|
if rc != SQLITE_OK || **(**Tu32)(__ccgo_up(bp + 16)) != 0 || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zOut))) == 0 {
|
|
/* If the checksum doesn't add up, then one or more of the disk sectors
|
|
** containing the super-journal filename is corrupted. This means
|
|
** definitely roll back, so just return SQLITE_OK and report a (nul)
|
|
** super-journal filename. */
|
|
_freeSuperJournal(tls, zOut)
|
|
zOut = uintptr(0)
|
|
}
|
|
}
|
|
**(**uintptr)(__ccgo_up(pzSuper)) = zOut
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This is the routine that actually formats the sqlite3_log() message.
|
|
// ** We house it in a separate routine from sqlite3_log() to avoid using
|
|
// ** stack space on small-stack systems when logging is disabled.
|
|
// **
|
|
// ** sqlite3_log() must render into a static buffer. It cannot dynamically
|
|
// ** allocate memory because it might be called while the memory allocator
|
|
// ** mutex is held.
|
|
// **
|
|
// ** sqlite3_str_vappendf() might ask for *temporary* memory allocations for
|
|
// ** certain format characters (%q) or for very large precisions or widths.
|
|
// ** Care must be taken that any sqlite3_log() calls that occur while the
|
|
// ** memory mutex is held do not use these mechanisms.
|
|
// */
|
|
func _renderLogMsg(tls *libc.TLS, iErrCode int32, zFormat uintptr, ap Tva_list) {
|
|
bp := tls.Alloc(736)
|
|
defer tls.Free(736)
|
|
var _ /* acc at bp+0 */ TStrAccum
|
|
var _ /* zMsg at bp+32 */ [700]uint8 /* Complete log message */
|
|
_sqlite3StrAccumInit(tls, bp, uintptr(0), bp+32, int32(700), 0)
|
|
Xsqlite3_str_vappendf(tls, bp, zFormat, ap)
|
|
(*(*func(*libc.TLS, uintptr, int32, uintptr))(unsafe.Pointer(&struct{ uintptr }{_sqlite3Config.FxLog})))(tls, _sqlite3Config.FpLogArg, iErrCode, _sqlite3StrAccumFinish(tls, bp))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect.
|
|
// ** The Name context of the SELECT statement is pNC. zType is either
|
|
// ** "ORDER" or "GROUP" depending on which type of clause pOrderBy is.
|
|
// **
|
|
// ** This routine resolves each term of the clause into an expression.
|
|
// ** If the order-by term is an integer I between 1 and N (where N is the
|
|
// ** number of columns in the result set of the SELECT) then the expression
|
|
// ** in the resolution is a copy of the I-th result-set expression. If
|
|
// ** the order-by term is an identifier that corresponds to the AS-name of
|
|
// ** a result-set expression, then the term resolves to a copy of the
|
|
// ** result-set expression. Otherwise, the expression is resolved in
|
|
// ** the usual way - using sqlite3ResolveExprNames().
|
|
// **
|
|
// ** This routine returns the number of errors. If errors occur, then
|
|
// ** an appropriate error message might be left in pParse. (OOM errors
|
|
// ** excepted.)
|
|
// */
|
|
func _resolveOrderGroupBy(tls *libc.TLS, pNC uintptr, pSelect uintptr, pOrderBy uintptr, zType uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var i, j, nResult int32
|
|
var pE, pE2, pItem, pParse uintptr
|
|
var _ /* iCol at bp+0 */ int32
|
|
_, _, _, _, _, _, _ = i, j, nResult, pE, pE2, pItem, pParse /* Number of terms in the result set */
|
|
nResult = (*TExprList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pSelect)).FpEList)).FnExpr
|
|
pParse = (*TNameContext)(unsafe.Pointer(pNC)).FpParse
|
|
i = 0
|
|
pItem = pOrderBy + 8
|
|
for {
|
|
if !(i < (*TExprList)(unsafe.Pointer(pOrderBy)).FnExpr) {
|
|
break
|
|
}
|
|
pE = (*TExprList_item)(unsafe.Pointer(pItem)).FpExpr
|
|
pE2 = _sqlite3ExprSkipCollateAndLikely(tls, pE)
|
|
if pE2 == uintptr(0) {
|
|
goto _1
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zType))) != int32('G') {
|
|
**(**int32)(__ccgo_up(bp)) = _resolveAsName(tls, pParse, (*TSelect)(unsafe.Pointer(pSelect)).FpEList, pE2)
|
|
if **(**int32)(__ccgo_up(bp)) > 0 {
|
|
/* If an AS-name match is found, mark this ORDER BY column as being
|
|
** a copy of the iCol-th result-set column. The subsequent call to
|
|
** sqlite3ResolveOrderGroupBy() will convert the expression to a
|
|
** copy of the iCol-th result-set expression. */
|
|
(*(*struct {
|
|
FiOrderByCol Tu16
|
|
FiAlias Tu16
|
|
})(unsafe.Pointer(pItem + 24))).FiOrderByCol = libc.Uint16FromInt32(**(**int32)(__ccgo_up(bp)))
|
|
goto _1
|
|
}
|
|
}
|
|
if _sqlite3ExprIsInteger(tls, pE2, bp, uintptr(0)) != 0 {
|
|
/* The ORDER BY term is an integer constant. Again, set the column
|
|
** number so that sqlite3ResolveOrderGroupBy() will convert the
|
|
** order-by term to a copy of the result-set expression */
|
|
if **(**int32)(__ccgo_up(bp)) < int32(1) || **(**int32)(__ccgo_up(bp)) > int32(0xffff) {
|
|
_resolveOutOfRangeError(tls, pParse, zType, i+int32(1), nResult, pE2)
|
|
return int32(1)
|
|
}
|
|
(*(*struct {
|
|
FiOrderByCol Tu16
|
|
FiAlias Tu16
|
|
})(unsafe.Pointer(pItem + 24))).FiOrderByCol = libc.Uint16FromInt32(**(**int32)(__ccgo_up(bp)))
|
|
goto _1
|
|
}
|
|
/* Otherwise, treat the ORDER BY term as an ordinary expression */
|
|
(*(*struct {
|
|
FiOrderByCol Tu16
|
|
FiAlias Tu16
|
|
})(unsafe.Pointer(pItem + 24))).FiOrderByCol = uint16(0)
|
|
if _sqlite3ResolveExprNames(tls, pNC, pE) != 0 {
|
|
return int32(1)
|
|
}
|
|
j = 0
|
|
for {
|
|
if !(j < (*TExprList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pSelect)).FpEList)).FnExpr) {
|
|
break
|
|
}
|
|
if _sqlite3ExprCompare(tls, uintptr(0), pE, (*(*TExprList_item)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pSelect)).FpEList + 8 + uintptr(j)*32))).FpExpr, -int32(1)) == 0 {
|
|
/* Since this expression is being changed into a reference
|
|
** to an identical expression in the result set, remove all Window
|
|
** objects belonging to the expression from the Select.pWin list. */
|
|
_windowRemoveExprFromSelect(tls, pSelect, pE)
|
|
(*(*struct {
|
|
FiOrderByCol Tu16
|
|
FiAlias Tu16
|
|
})(unsafe.Pointer(pItem + 24))).FiOrderByCol = libc.Uint16FromInt32(j + int32(1))
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
j = j + 1
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
pItem += 32
|
|
}
|
|
return _sqlite3ResolveOrderGroupBy(tls, pParse, pSelect, pOrderBy, zType)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Rtree virtual table module xFilter method.
|
|
// */
|
|
func _rtreeFilter(tls *libc.TLS, pVtabCursor uintptr, idxNum int32, idxStr uintptr, argc int32, argv uintptr) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var eType, eType1, ii, rc int32
|
|
var iRowid Ti64
|
|
var iVal Tsqlite3_int64
|
|
var p, p1, pCsr, pNew, pRtree uintptr
|
|
var _ /* iCell at bp+8 */ int32
|
|
var _ /* iNode at bp+24 */ Ti64
|
|
var _ /* pLeaf at bp+16 */ uintptr
|
|
var _ /* pRoot at bp+0 */ uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _ = eType, eType1, iRowid, iVal, ii, p, p1, pCsr, pNew, pRtree, rc
|
|
pRtree = (*Tsqlite3_vtab_cursor)(unsafe.Pointer(pVtabCursor)).FpVtab
|
|
pCsr = pVtabCursor
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
rc = SQLITE_OK
|
|
**(**int32)(__ccgo_up(bp + 8)) = 0
|
|
_rtreeReference(tls, pRtree)
|
|
/* Reset the cursor to the same state as rtreeOpen() leaves it in. */
|
|
_resetCursor(tls, pCsr)
|
|
(*TRtreeCursor)(unsafe.Pointer(pCsr)).FiStrategy = idxNum
|
|
if idxNum == int32(1) { /* Search point for the leaf */
|
|
iRowid = Xsqlite3_value_int64(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
**(**Ti64)(__ccgo_up(bp + 24)) = 0
|
|
eType = Xsqlite3_value_numeric_type(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
if eType == int32(SQLITE_INTEGER) || eType == int32(SQLITE_FLOAT) && 0 == _sqlite3IntFloatCompare(tls, iRowid, Xsqlite3_value_double(tls, **(**uintptr)(__ccgo_up(argv)))) {
|
|
rc = _findLeafNode(tls, pRtree, iRowid, bp+16, bp+24)
|
|
} else {
|
|
rc = SQLITE_OK
|
|
**(**uintptr)(__ccgo_up(bp + 16)) = uintptr(0)
|
|
}
|
|
if rc == SQLITE_OK && **(**uintptr)(__ccgo_up(bp + 16)) != uintptr(0) {
|
|
p = _rtreeSearchPointNew(tls, pCsr, float64(0), uint8(0))
|
|
/* Always returns pCsr->sPoint */
|
|
**(**uintptr)(__ccgo_up(pCsr + 88)) = **(**uintptr)(__ccgo_up(bp + 16))
|
|
(*TRtreeSearchPoint)(unsafe.Pointer(p)).Fid = **(**Ti64)(__ccgo_up(bp + 24))
|
|
(*TRtreeSearchPoint)(unsafe.Pointer(p)).FeWithin = uint8(PARTLY_WITHIN)
|
|
rc = _nodeRowidIndex(tls, pRtree, **(**uintptr)(__ccgo_up(bp + 16)), iRowid, bp+8)
|
|
(*TRtreeSearchPoint)(unsafe.Pointer(p)).FiCell = libc.Uint8FromInt32(**(**int32)(__ccgo_up(bp + 8)))
|
|
} else {
|
|
(*TRtreeCursor)(unsafe.Pointer(pCsr)).FatEOF = uint8(1)
|
|
}
|
|
} else {
|
|
/* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array
|
|
** with the configured constraints.
|
|
*/
|
|
rc = _nodeAcquire(tls, pRtree, int64(1), uintptr(0), bp)
|
|
if rc == SQLITE_OK && argc > 0 {
|
|
(*TRtreeCursor)(unsafe.Pointer(pCsr)).FaConstraint = Xsqlite3_malloc64(tls, uint64(uint64(24)*libc.Uint64FromInt32(argc)))
|
|
(*TRtreeCursor)(unsafe.Pointer(pCsr)).FnConstraint = argc
|
|
if !((*TRtreeCursor)(unsafe.Pointer(pCsr)).FaConstraint != 0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
} else {
|
|
libc.Xmemset(tls, (*TRtreeCursor)(unsafe.Pointer(pCsr)).FaConstraint, 0, uint64(24)*libc.Uint64FromInt32(argc))
|
|
libc.Xmemset(tls, pCsr+128, 0, uint64(4)*libc.Uint64FromInt32((*TRtree)(unsafe.Pointer(pRtree)).FiDepth+libc.Int32FromInt32(1)))
|
|
ii = 0
|
|
for {
|
|
if !(ii < argc) {
|
|
break
|
|
}
|
|
p1 = (*TRtreeCursor)(unsafe.Pointer(pCsr)).FaConstraint + uintptr(ii)*24
|
|
eType1 = Xsqlite3_value_numeric_type(tls, **(**uintptr)(__ccgo_up(argv + uintptr(ii)*8)))
|
|
(*TRtreeConstraint)(unsafe.Pointer(p1)).Fop = libc.Int32FromUint8(**(**uint8)(__ccgo_up(idxStr + uintptr(ii*int32(2)))))
|
|
(*TRtreeConstraint)(unsafe.Pointer(p1)).FiCoord = libc.Int32FromUint8(**(**uint8)(__ccgo_up(idxStr + uintptr(ii*int32(2)+int32(1))))) - int32('0')
|
|
if (*TRtreeConstraint)(unsafe.Pointer(p1)).Fop >= int32(RTREE_MATCH) {
|
|
/* A MATCH operator. The right-hand-side must be a blob that
|
|
** can be cast into an RtreeMatchArg object. One created using
|
|
** an sqlite3_rtree_geometry_callback() SQL user function.
|
|
*/
|
|
rc = _deserializeGeometry(tls, **(**uintptr)(__ccgo_up(argv + uintptr(ii)*8)), p1)
|
|
if rc != SQLITE_OK {
|
|
break
|
|
}
|
|
(*Tsqlite3_rtree_query_info)(unsafe.Pointer((*TRtreeConstraint)(unsafe.Pointer(p1)).FpInfo)).FnCoord = libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FnDim2)
|
|
(*Tsqlite3_rtree_query_info)(unsafe.Pointer((*TRtreeConstraint)(unsafe.Pointer(p1)).FpInfo)).FanQueue = pCsr + 128
|
|
(*Tsqlite3_rtree_query_info)(unsafe.Pointer((*TRtreeConstraint)(unsafe.Pointer(p1)).FpInfo)).FmxLevel = (*TRtree)(unsafe.Pointer(pRtree)).FiDepth + int32(1)
|
|
} else {
|
|
if eType1 == int32(SQLITE_INTEGER) {
|
|
iVal = Xsqlite3_value_int64(tls, **(**uintptr)(__ccgo_up(argv + uintptr(ii)*8)))
|
|
*(*TRtreeDValue)(unsafe.Pointer(p1 + 8)) = float64(iVal)
|
|
if iVal >= libc.Int64FromInt32(1)<<libc.Int32FromInt32(48) || iVal <= -(libc.Int64FromInt32(1)<<libc.Int32FromInt32(48)) {
|
|
if (*TRtreeConstraint)(unsafe.Pointer(p1)).Fop == int32(RTREE_LT) {
|
|
(*TRtreeConstraint)(unsafe.Pointer(p1)).Fop = int32(RTREE_LE)
|
|
}
|
|
if (*TRtreeConstraint)(unsafe.Pointer(p1)).Fop == int32(RTREE_GT) {
|
|
(*TRtreeConstraint)(unsafe.Pointer(p1)).Fop = int32(RTREE_GE)
|
|
}
|
|
}
|
|
} else {
|
|
if eType1 == int32(SQLITE_FLOAT) {
|
|
*(*TRtreeDValue)(unsafe.Pointer(p1 + 8)) = Xsqlite3_value_double(tls, **(**uintptr)(__ccgo_up(argv + uintptr(ii)*8)))
|
|
} else {
|
|
*(*TRtreeDValue)(unsafe.Pointer(p1 + 8)) = float64(0)
|
|
if eType1 == int32(SQLITE_NULL) {
|
|
(*TRtreeConstraint)(unsafe.Pointer(p1)).Fop = int32(RTREE_FALSE)
|
|
} else {
|
|
if (*TRtreeConstraint)(unsafe.Pointer(p1)).Fop == int32(RTREE_LT) || (*TRtreeConstraint)(unsafe.Pointer(p1)).Fop == int32(RTREE_LE) {
|
|
(*TRtreeConstraint)(unsafe.Pointer(p1)).Fop = int32(RTREE_TRUE)
|
|
} else {
|
|
(*TRtreeConstraint)(unsafe.Pointer(p1)).Fop = int32(RTREE_FALSE)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
}
|
|
}
|
|
if rc == SQLITE_OK {
|
|
/* Due to the resetCursor() call above */
|
|
pNew = _rtreeSearchPointNew(tls, pCsr, float64(0), libc.Uint8FromInt32((*TRtree)(unsafe.Pointer(pRtree)).FiDepth+libc.Int32FromInt32(1)))
|
|
if pNew == uintptr(0) { /* Because pCsr->bPoint was FALSE */
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
(*TRtreeSearchPoint)(unsafe.Pointer(pNew)).Fid = int64(1)
|
|
(*TRtreeSearchPoint)(unsafe.Pointer(pNew)).FiCell = uint8(0)
|
|
(*TRtreeSearchPoint)(unsafe.Pointer(pNew)).FeWithin = uint8(PARTLY_WITHIN)
|
|
**(**uintptr)(__ccgo_up(pCsr + 88)) = **(**uintptr)(__ccgo_up(bp))
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
rc = _rtreeStepToLeaf(tls, pCsr)
|
|
}
|
|
}
|
|
_nodeRelease(tls, pRtree, **(**uintptr)(__ccgo_up(bp)))
|
|
_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 zStr enclosed in quotes (") and
|
|
// ** with any embedded quote characters escaped to the buffer. No
|
|
// ** nul-terminator byte is written.
|
|
// **
|
|
// ** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before
|
|
// ** returning.
|
|
// */
|
|
func _sessionAppendIdent(tls *libc.TLS, p uintptr, zStr uintptr, pRc uintptr) {
|
|
var nStr int32
|
|
var zIn, zOut, v1, v2 uintptr
|
|
_, _, _, _, _ = nStr, zIn, zOut, v1, v2
|
|
nStr = _sqlite3Strlen30(tls, zStr)*int32(2) + int32(2) + int32(2)
|
|
if 0 == _sessionBufferGrow(tls, p, int64(nStr), pRc) {
|
|
zOut = (*TSessionBuffer)(unsafe.Pointer(p)).FaBuf + uintptr((*TSessionBuffer)(unsafe.Pointer(p)).FnBuf)
|
|
zIn = zStr
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = uint8('"')
|
|
if zIn != uintptr(0) {
|
|
for **(**uint8)(__ccgo_up(zIn)) != 0 {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn))) == int32('"') {
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = uint8('"')
|
|
}
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
v2 = zIn
|
|
zIn = zIn + 1
|
|
**(**uint8)(__ccgo_up(v1)) = **(**uint8)(__ccgo_up(v2))
|
|
}
|
|
}
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**uint8)(__ccgo_up(v1)) = uint8('"')
|
|
(*TSessionBuffer)(unsafe.Pointer(p)).FnBuf = int32(int64(zOut) - int64((*TSessionBuffer)(unsafe.Pointer(p)).FaBuf))
|
|
**(**Tu8)(__ccgo_up((*TSessionBuffer)(unsafe.Pointer(p)).FaBuf + uintptr((*TSessionBuffer)(unsafe.Pointer(p)).FnBuf))) = uint8(0x00)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Add a new CHECK constraint to the table currently under construction.
|
|
// */
|
|
func _sqlite3AddCheckConstraint(tls *libc.TLS, pParse uintptr, pCheckExpr uintptr, zStart uintptr, zEnd uintptr) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var db, pTab uintptr
|
|
var _ /* t at bp+0 */ TToken
|
|
_, _ = db, pTab
|
|
pTab = (*TParse)(unsafe.Pointer(pParse)).FpNewTable
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
if pTab != 0 && !(libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) == libc.Int32FromInt32(PARSE_MODE_DECLARE_VTAB)) && !(_sqlite3BtreeIsReadonly(tls, (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr((*Tsqlite3)(unsafe.Pointer(db)).Finit1.FiDb)*32))).FpBt) != 0) {
|
|
(*TTable)(unsafe.Pointer(pTab)).FpCheck = _sqlite3ExprListAppend(tls, pParse, (*TTable)(unsafe.Pointer(pTab)).FpCheck, pCheckExpr)
|
|
if (*(*struct {
|
|
FaddrCrTab int32
|
|
FregRowid int32
|
|
FregRoot int32
|
|
FconstraintName TToken
|
|
})(unsafe.Pointer(pParse + 256))).FconstraintName.Fn != 0 {
|
|
_sqlite3ExprListSetName(tls, pParse, (*TTable)(unsafe.Pointer(pTab)).FpCheck, pParse+256+16, int32(1))
|
|
} else {
|
|
zStart = zStart + 1
|
|
for {
|
|
if !(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(zStart)))])&int32(0x01) != 0) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
zStart = zStart + 1
|
|
}
|
|
for libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(zEnd + uintptr(-libc.Int32FromInt32(1)))))])&int32(0x01) != 0 {
|
|
zEnd = zEnd - 1
|
|
}
|
|
(**(**TToken)(__ccgo_up(bp))).Fz = zStart
|
|
(**(**TToken)(__ccgo_up(bp))).Fn = libc.Uint32FromInt32(int32(int64(zEnd) - int64((**(**TToken)(__ccgo_up(bp))).Fz)))
|
|
_sqlite3ExprListSetName(tls, pParse, (*TTable)(unsafe.Pointer(pTab)).FpCheck, bp, int32(1))
|
|
}
|
|
} else {
|
|
_sqlite3ExprDelete(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pCheckExpr)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The most recently coded instruction was an OP_Column to retrieve the
|
|
// ** i-th column of table pTab. This routine sets the P4 parameter of the
|
|
// ** OP_Column to the default value, if any.
|
|
// **
|
|
// ** The default value of a column is specified by a DEFAULT clause in the
|
|
// ** column definition. This was either supplied by the user when the table
|
|
// ** was created, or added later to the table definition by an ALTER TABLE
|
|
// ** command. If the latter, then the row-records in the table btree on disk
|
|
// ** may not contain a value for the column and the default value, taken
|
|
// ** from the P4 parameter of the OP_Column instruction, is returned instead.
|
|
// ** If the former, then all row-records are guaranteed to include a value
|
|
// ** for the column and the P4 value is not required.
|
|
// **
|
|
// ** Column definitions created by an ALTER TABLE command may only have
|
|
// ** literal default values specified: a number, null or a string. (If a more
|
|
// ** complicated default expression value was provided, it is evaluated
|
|
// ** when the ALTER TABLE is executed and one of the literal values written
|
|
// ** into the sqlite_schema table.)
|
|
// **
|
|
// ** Therefore, the P4 parameter is only required if the default value for
|
|
// ** the column is a literal number, string or null. The sqlite3ValueFromExpr()
|
|
// ** function is capable of transforming these types of expressions into
|
|
// ** sqlite3_value objects.
|
|
// **
|
|
// ** If column as REAL affinity and the table is an ordinary b-tree table
|
|
// ** (not a virtual table) then the value might have been stored as an
|
|
// ** integer. In that case, add an OP_RealAffinity opcode to make sure
|
|
// ** it has been converted into REAL.
|
|
// */
|
|
func _sqlite3ColumnDefault(tls *libc.TLS, v uintptr, pTab uintptr, i int32, iReg int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var enc Tu8
|
|
var pCol uintptr
|
|
var _ /* pValue at bp+0 */ uintptr
|
|
_, _ = enc, pCol
|
|
pCol = (*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(i)*16
|
|
if (*TColumn)(unsafe.Pointer(pCol)).FiDflt != 0 {
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
enc = (*Tsqlite3)(unsafe.Pointer(_sqlite3VdbeDb(tls, v))).Fenc
|
|
_sqlite3ValueFromExpr(tls, _sqlite3VdbeDb(tls, v), _sqlite3ColumnExpr(tls, pTab, pCol), enc, (*TColumn)(unsafe.Pointer(pCol)).Faffinity, bp)
|
|
if **(**uintptr)(__ccgo_up(bp)) != 0 {
|
|
_sqlite3VdbeAppendP4(tls, v, **(**uintptr)(__ccgo_up(bp)), -int32(11))
|
|
}
|
|
}
|
|
if libc.Int32FromUint8((*TColumn)(unsafe.Pointer(pCol)).Faffinity) == int32(SQLITE_AFF_REAL) && !(libc.Int32FromUint8((*TTable)(unsafe.Pointer(pTab)).FeTabType) == libc.Int32FromInt32(TABTYP_VTAB)) {
|
|
_sqlite3VdbeAddOp1(tls, v, int32(OP_RealAffinity), iReg)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The text between zStart and zEnd represents a phrase within a larger
|
|
// ** SQL statement. Make a copy of this phrase in space obtained form
|
|
// ** sqlite3DbMalloc(). Omit leading and trailing whitespace.
|
|
// */
|
|
func _sqlite3DbSpanDup(tls *libc.TLS, db uintptr, zStart uintptr, zEnd uintptr) (r uintptr) {
|
|
var n int32
|
|
_ = n
|
|
for libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(zStart)))])&int32(0x01) != 0 {
|
|
zStart = zStart + 1
|
|
}
|
|
n = int32(int64(zEnd) - int64(zStart))
|
|
for libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(zStart + uintptr(n-int32(1)))))])&int32(0x01) != 0 {
|
|
n = n - 1
|
|
}
|
|
return _sqlite3DbStrNDup(tls, db, zStart, libc.Uint64FromInt32(n))
|
|
}
|
|
|
|
func _sqlite3DbStrNDup(tls *libc.TLS, db uintptr, z uintptr, n Tu64) (r uintptr) {
|
|
var zNew, v1 uintptr
|
|
_, _ = zNew, v1
|
|
if z != 0 {
|
|
v1 = _sqlite3DbMallocRawNN(tls, db, n+uint64(1))
|
|
} else {
|
|
v1 = uintptr(0)
|
|
}
|
|
zNew = v1
|
|
if zNew != 0 {
|
|
libc.Xmemcpy(tls, zNew, z, n)
|
|
**(**uint8)(__ccgo_up(zNew + uintptr(n))) = uint8(0)
|
|
}
|
|
return zNew
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If the input token p is quoted, try to adjust the token to remove
|
|
// ** the quotes. This is not always possible:
|
|
// **
|
|
// ** "abc" -> abc
|
|
// ** "ab""cd" -> (not possible because of the interior "")
|
|
// **
|
|
// ** Remove the quotes if possible. This is a optimization. The overall
|
|
// ** system should still return the correct answer even if this routine
|
|
// ** is always a no-op.
|
|
// */
|
|
func _sqlite3DequoteToken(tls *libc.TLS, p uintptr) {
|
|
var i uint32
|
|
_ = i
|
|
if (*TToken)(unsafe.Pointer(p)).Fn < uint32(2) {
|
|
return
|
|
}
|
|
if !(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up((*TToken)(unsafe.Pointer(p)).Fz)))])&libc.Int32FromInt32(0x80) != 0) {
|
|
return
|
|
}
|
|
i = uint32(1)
|
|
for {
|
|
if !(i < (*TToken)(unsafe.Pointer(p)).Fn-uint32(1)) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up((*TToken)(unsafe.Pointer(p)).Fz + uintptr(i))))])&int32(0x80) != 0 {
|
|
return
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
**(**uint32)(__ccgo_up(p + 8)) -= uint32(2)
|
|
(*TToken)(unsafe.Pointer(p)).Fz = (*TToken)(unsafe.Pointer(p)).Fz + 1
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the 'affinity' of the expression pExpr if any.
|
|
// **
|
|
// ** If pExpr is a column, a reference to a column via an 'AS' alias,
|
|
// ** or a sub-select with a column as the return value, then the
|
|
// ** affinity of that column is returned. Otherwise, 0x00 is returned,
|
|
// ** indicating no affinity for the expression.
|
|
// **
|
|
// ** i.e. the WHERE clause expressions in the following statements all
|
|
// ** have an affinity:
|
|
// **
|
|
// ** CREATE TABLE t1(a);
|
|
// ** SELECT * FROM t1 WHERE a;
|
|
// ** SELECT a AS b FROM t1 WHERE b;
|
|
// ** SELECT * FROM t1 WHERE (select a from t1);
|
|
// */
|
|
func _sqlite3ExprAffinity(tls *libc.TLS, pExpr uintptr) (r uint8) {
|
|
var op int32
|
|
_ = op
|
|
op = libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop)
|
|
for int32(1) != 0 {
|
|
if op == int32(TK_COLUMN) || op == int32(TK_AGG_COLUMN) && *(*uintptr)(unsafe.Pointer(pExpr + 64)) != uintptr(0) {
|
|
return _sqlite3TableColumnAffinity(tls, *(*uintptr)(unsafe.Pointer(pExpr + 64)), int32((*TExpr)(unsafe.Pointer(pExpr)).FiColumn))
|
|
}
|
|
if op == int32(TK_SELECT) {
|
|
return _sqlite3ExprAffinity(tls, (*(*TExprList_item)(unsafe.Pointer((*TSelect)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)))).FpEList + 8))).FpExpr)
|
|
}
|
|
if op == int32(TK_CAST) {
|
|
return _sqlite3AffinityType(tls, *(*uintptr)(unsafe.Pointer(pExpr + 8)), uintptr(0))
|
|
}
|
|
if op == int32(TK_SELECT_COLUMN) {
|
|
return _sqlite3ExprAffinity(tls, (*(*TExprList_item)(unsafe.Pointer((*TSelect)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer((*TExpr)(unsafe.Pointer(pExpr)).FpLeft + 32)))).FpEList + 8 + uintptr((*TExpr)(unsafe.Pointer(pExpr)).FiColumn)*32))).FpExpr)
|
|
}
|
|
if op == int32(TK_VECTOR) || op == int32(TK_FUNCTION) && libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).FaffExpr) == int32(SQLITE_AFF_DEFER) {
|
|
return _sqlite3ExprAffinity(tls, (*(*TExprList_item)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)) + 8))).FpExpr)
|
|
}
|
|
if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Skip)|libc.Int32FromInt32(EP_IfNullRow)) != uint32(0) {
|
|
pExpr = (*TExpr)(unsafe.Pointer(pExpr)).FpLeft
|
|
op = libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop)
|
|
continue
|
|
}
|
|
if op != int32(TK_REGISTER) {
|
|
break
|
|
}
|
|
op = libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop2)
|
|
if op == int32(TK_REGISTER) {
|
|
break
|
|
}
|
|
}
|
|
return (*TExpr)(unsafe.Pointer(pExpr)).FaffExpr
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This routine is the core allocator for Expr nodes.
|
|
// **
|
|
// ** Construct a new expression node and return a pointer to it. Memory
|
|
// ** for this node and for the pToken argument is a single allocation
|
|
// ** obtained from sqlite3DbMalloc(). The calling function
|
|
// ** is responsible for making sure the node eventually gets freed.
|
|
// **
|
|
// ** If dequote is true, then the token (if it exists) is dequoted.
|
|
// ** If dequote is false, no dequoting is performed. The deQuote
|
|
// ** parameter is ignored if pToken is NULL or if the token does not
|
|
// ** appear to be quoted. If the quotes were of the form "..." (double-quotes)
|
|
// ** then the EP_DblQuoted flag is set on the expression node.
|
|
// **
|
|
// ** Special case (tag-20240227-a): If op==TK_INTEGER and pToken points to
|
|
// ** a string that can be translated into a 32-bit integer, then the token is
|
|
// ** not stored in u.zToken. Instead, the integer values is written
|
|
// ** into u.iValue and the EP_IntValue flag is set. No extra storage
|
|
// ** is allocated to hold the integer text and the dequote flag is ignored.
|
|
// ** See also tag-20240227-b.
|
|
// */
|
|
func _sqlite3ExprAlloc(tls *libc.TLS, db uintptr, op int32, pToken uintptr, dequote int32) (r uintptr) {
|
|
var nExtra int32
|
|
var pNew uintptr
|
|
var v1 uint32
|
|
_, _, _ = nExtra, pNew, v1
|
|
if pToken != 0 {
|
|
v1 = (*TToken)(unsafe.Pointer(pToken)).Fn + uint32(1)
|
|
} else {
|
|
v1 = uint32(0)
|
|
}
|
|
nExtra = libc.Int32FromUint32(v1)
|
|
pNew = _sqlite3DbMallocRawNN(tls, db, uint64(uint64(72)+libc.Uint64FromInt32(nExtra)))
|
|
if pNew != 0 {
|
|
libc.Xmemset(tls, pNew, 0, uint64(72))
|
|
(*TExpr)(unsafe.Pointer(pNew)).Fop = libc.Uint8FromInt32(op)
|
|
(*TExpr)(unsafe.Pointer(pNew)).FiAgg = int16(-int32(1))
|
|
if nExtra != 0 {
|
|
*(*uintptr)(unsafe.Pointer(pNew + 8)) = pNew + 1*72
|
|
if (*TToken)(unsafe.Pointer(pToken)).Fn != 0 {
|
|
libc.Xmemcpy(tls, *(*uintptr)(unsafe.Pointer(pNew + 8)), (*TToken)(unsafe.Pointer(pToken)).Fz, uint64((*TToken)(unsafe.Pointer(pToken)).Fn))
|
|
}
|
|
**(**uint8)(__ccgo_up(*(*uintptr)(unsafe.Pointer(pNew + 8)) + uintptr((*TToken)(unsafe.Pointer(pToken)).Fn))) = uint8(0)
|
|
if dequote != 0 && libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(*(*uintptr)(unsafe.Pointer(pNew + 8)))))])&int32(0x80) != 0 {
|
|
_sqlite3DequoteExpr(tls, pNew)
|
|
}
|
|
}
|
|
(*TExpr)(unsafe.Pointer(pNew)).FnHeight = int32(1)
|
|
}
|
|
return pNew
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Generate code that will compute the value of generated column pCol
|
|
// ** and store the result in register regOut
|
|
// */
|
|
func _sqlite3ExprCodeGeneratedColumn(tls *libc.TLS, pParse uintptr, pTab uintptr, pCol uintptr, regOut int32) {
|
|
var iAddr, nErr, p3 int32
|
|
var v uintptr
|
|
_, _, _, _ = iAddr, nErr, p3, v
|
|
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
|
|
nErr = (*TParse)(unsafe.Pointer(pParse)).FnErr
|
|
if (*TParse)(unsafe.Pointer(pParse)).FiSelfTab > 0 {
|
|
iAddr = _sqlite3VdbeAddOp3(tls, v, int32(OP_IfNullRow), (*TParse)(unsafe.Pointer(pParse)).FiSelfTab-int32(1), 0, regOut)
|
|
} else {
|
|
iAddr = 0
|
|
}
|
|
_sqlite3ExprCodeCopy(tls, pParse, _sqlite3ColumnExpr(tls, pTab, pCol), regOut)
|
|
if libc.Int32FromUint16((*TColumn)(unsafe.Pointer(pCol)).FcolFlags)&int32(COLFLAG_VIRTUAL) != 0 && (*TTable)(unsafe.Pointer(pTab)).FtabFlags&uint32(TF_Strict) != uint32(0) {
|
|
p3 = int32(2) + int32((int64(pCol)-int64((*TTable)(unsafe.Pointer(pTab)).FaCol))/16)
|
|
_sqlite3VdbeAddOp4(tls, v, int32(OP_TypeCheck), regOut, int32(1), p3, pTab, -int32(5))
|
|
} else {
|
|
if libc.Int32FromUint8((*TColumn)(unsafe.Pointer(pCol)).Faffinity) >= int32(SQLITE_AFF_TEXT) {
|
|
_sqlite3VdbeAddOp4(tls, v, int32(OP_Affinity), regOut, int32(1), 0, pCol+9, int32(1))
|
|
}
|
|
}
|
|
if iAddr != 0 {
|
|
_sqlite3VdbeJumpHere(tls, v, iAddr)
|
|
}
|
|
if (*TParse)(unsafe.Pointer(pParse)).FnErr > nErr {
|
|
(*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer(pParse)).Fdb)).FerrByteOffset = -int32(1)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the collation sequence for the expression pExpr. If
|
|
// ** there is no defined collating sequence, return NULL.
|
|
// **
|
|
// ** See also: sqlite3ExprNNCollSeq()
|
|
// **
|
|
// ** The sqlite3ExprNNCollSeq() works the same exact that it returns the
|
|
// ** default collation if pExpr has no defined collation.
|
|
// **
|
|
// ** The collating sequence might be determined by a COLLATE operator
|
|
// ** or by the presence of a column with a defined collating sequence.
|
|
// ** COLLATE operators take first precedence. Left operands take
|
|
// ** precedence over right operands.
|
|
// */
|
|
func _sqlite3ExprCollSeq(tls *libc.TLS, pParse uintptr, pExpr uintptr) (r uintptr) {
|
|
var db, p, pColl, pNext, zColl uintptr
|
|
var i, j, op, v1 int32
|
|
_, _, _, _, _, _, _, _, _ = db, i, j, op, p, pColl, pNext, zColl, v1
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
pColl = uintptr(0)
|
|
p = pExpr
|
|
for p != 0 {
|
|
op = libc.Int32FromUint8((*TExpr)(unsafe.Pointer(p)).Fop)
|
|
if op == int32(TK_REGISTER) {
|
|
op = libc.Int32FromUint8((*TExpr)(unsafe.Pointer(p)).Fop2)
|
|
}
|
|
if op == int32(TK_AGG_COLUMN) && *(*uintptr)(unsafe.Pointer(p + 64)) != uintptr(0) || op == int32(TK_COLUMN) || op == int32(TK_TRIGGER) {
|
|
v1 = int32((*TExpr)(unsafe.Pointer(p)).FiColumn)
|
|
j = v1
|
|
if v1 >= 0 {
|
|
zColl = _sqlite3ColumnColl(tls, (*TTable)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(p + 64)))).FaCol+uintptr(j)*16)
|
|
pColl = _sqlite3FindCollSeq(tls, db, (*Tsqlite3)(unsafe.Pointer(db)).Fenc, zColl, 0)
|
|
}
|
|
break
|
|
}
|
|
if op == int32(TK_CAST) || op == int32(TK_UPLUS) {
|
|
p = (*TExpr)(unsafe.Pointer(p)).FpLeft
|
|
continue
|
|
}
|
|
if op == int32(TK_VECTOR) || op == int32(TK_FUNCTION) && libc.Int32FromUint8((*TExpr)(unsafe.Pointer(p)).FaffExpr) == int32(SQLITE_AFF_DEFER) {
|
|
p = (*(*TExprList_item)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(p + 32)) + 8))).FpExpr
|
|
continue
|
|
}
|
|
if op == int32(TK_COLLATE) {
|
|
pColl = _sqlite3GetCollSeq(tls, pParse, (*Tsqlite3)(unsafe.Pointer(db)).Fenc, uintptr(0), *(*uintptr)(unsafe.Pointer(p + 8)))
|
|
break
|
|
}
|
|
if (*TExpr)(unsafe.Pointer(p)).Fflags&uint32(EP_Collate) != 0 {
|
|
if (*TExpr)(unsafe.Pointer(p)).FpLeft != 0 && (*TExpr)(unsafe.Pointer((*TExpr)(unsafe.Pointer(p)).FpLeft)).Fflags&uint32(EP_Collate) != uint32(0) {
|
|
p = (*TExpr)(unsafe.Pointer(p)).FpLeft
|
|
} else {
|
|
pNext = (*TExpr)(unsafe.Pointer(p)).FpRight
|
|
/* The Expr.x union is never used at the same time as Expr.pRight */
|
|
if (*TExpr)(unsafe.Pointer(p)).Fflags&uint32(EP_xIsSelect) == uint32(0) && *(*uintptr)(unsafe.Pointer(p + 32)) != uintptr(0) && !((*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0) {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TExprList)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(p + 32)))).FnExpr) {
|
|
break
|
|
}
|
|
if (*TExpr)(unsafe.Pointer((*(*TExprList_item)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(p + 32)) + 8 + uintptr(i)*32))).FpExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Collate)) != uint32(0) {
|
|
pNext = (*(*TExprList_item)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(p + 32)) + 8 + uintptr(i)*32))).FpExpr
|
|
break
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
p = pNext
|
|
}
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
if _sqlite3CheckCollSeq(tls, pParse, pColl) != 0 {
|
|
pColl = uintptr(0)
|
|
}
|
|
return pColl
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Make a guess at all the possible datatypes of the result that could
|
|
// ** be returned by an expression. Return a bitmask indicating the answer:
|
|
// **
|
|
// ** 0x01 Numeric
|
|
// ** 0x02 Text
|
|
// ** 0x04 Blob
|
|
// **
|
|
// ** If the expression must return NULL, then 0x00 is returned.
|
|
// */
|
|
func _sqlite3ExprDataType(tls *libc.TLS, pExpr uintptr) (r int32) {
|
|
var aff, ii, res int32
|
|
var pList uintptr
|
|
_, _, _, _ = aff, ii, pList, res
|
|
for pExpr != 0 {
|
|
switch libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) {
|
|
case int32(TK_COLLATE):
|
|
fallthrough
|
|
case int32(TK_IF_NULL_ROW):
|
|
fallthrough
|
|
case int32(TK_UPLUS):
|
|
pExpr = (*TExpr)(unsafe.Pointer(pExpr)).FpLeft
|
|
case int32(TK_NULL):
|
|
pExpr = uintptr(0)
|
|
case int32(TK_STRING):
|
|
return int32(0x02)
|
|
case int32(TK_BLOB):
|
|
return int32(0x04)
|
|
case int32(TK_CONCAT):
|
|
return int32(0x06)
|
|
case int32(TK_VARIABLE):
|
|
fallthrough
|
|
case int32(TK_AGG_FUNCTION):
|
|
fallthrough
|
|
case int32(TK_FUNCTION):
|
|
return int32(0x07)
|
|
case int32(TK_COLUMN):
|
|
fallthrough
|
|
case int32(TK_AGG_COLUMN):
|
|
fallthrough
|
|
case int32(TK_SELECT):
|
|
fallthrough
|
|
case int32(TK_CAST):
|
|
fallthrough
|
|
case int32(TK_SELECT_COLUMN):
|
|
fallthrough
|
|
case int32(TK_VECTOR):
|
|
aff = libc.Int32FromUint8(_sqlite3ExprAffinity(tls, pExpr))
|
|
if aff >= int32(SQLITE_AFF_NUMERIC) {
|
|
return int32(0x05)
|
|
}
|
|
if aff == int32(SQLITE_AFF_TEXT) {
|
|
return int32(0x06)
|
|
}
|
|
return int32(0x07)
|
|
case int32(TK_CASE):
|
|
res = 0
|
|
pList = *(*uintptr)(unsafe.Pointer(pExpr + 32))
|
|
ii = int32(1)
|
|
for {
|
|
if !(ii < (*TExprList)(unsafe.Pointer(pList)).FnExpr) {
|
|
break
|
|
}
|
|
res = res | _sqlite3ExprDataType(tls, (*(*TExprList_item)(unsafe.Pointer(pList + 8 + uintptr(ii)*32))).FpExpr)
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + int32(2)
|
|
}
|
|
if (*TExprList)(unsafe.Pointer(pList)).FnExpr%int32(2) != 0 {
|
|
res = res | _sqlite3ExprDataType(tls, (*(*TExprList_item)(unsafe.Pointer(pList + 8 + uintptr((*TExprList)(unsafe.Pointer(pList)).FnExpr-int32(1))*32))).FpExpr)
|
|
}
|
|
return res
|
|
default:
|
|
return int32(0x01)
|
|
} /* End of switch(op) */
|
|
} /* End of while(pExpr) */
|
|
return 0x00
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return true if the expression is one of the following:
|
|
// **
|
|
// ** CASE WHEN x THEN y END
|
|
// ** CASE WHEN x THEN y ELSE NULL END
|
|
// ** CASE WHEN x THEN y ELSE false END
|
|
// ** iif(x,y)
|
|
// ** iif(x,y,NULL)
|
|
// ** iif(x,y,false)
|
|
// */
|
|
func _sqlite3ExprIsIIF(tls *libc.TLS, db uintptr, pExpr uintptr) (r int32) {
|
|
var pDef, pList, z uintptr
|
|
_, _, _ = pDef, pList, z
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_FUNCTION) {
|
|
z = *(*uintptr)(unsafe.Pointer(pExpr + 8))
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) != int32('i') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) != int32('I') {
|
|
return 0
|
|
}
|
|
if *(*uintptr)(unsafe.Pointer(pExpr + 32)) == uintptr(0) {
|
|
return 0
|
|
}
|
|
pDef = _sqlite3FindFunction(tls, db, z, (*TExprList)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)))).FnExpr, (*Tsqlite3)(unsafe.Pointer(db)).Fenc, uint8(0))
|
|
if pDef == uintptr(0) {
|
|
return 0
|
|
}
|
|
if (*TFuncDef)(unsafe.Pointer(pDef)).FfuncFlags&uint32(SQLITE_FUNC_INLINE) == uint32(0) {
|
|
return 0
|
|
}
|
|
if int32(int64((*TFuncDef)(unsafe.Pointer(pDef)).FpUserData)) != int32(INLINEFUNC_iif) {
|
|
return 0
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_CASE) {
|
|
if (*TExpr)(unsafe.Pointer(pExpr)).FpLeft != uintptr(0) {
|
|
return 0
|
|
}
|
|
} else {
|
|
return 0
|
|
}
|
|
}
|
|
pList = *(*uintptr)(unsafe.Pointer(pExpr + 32))
|
|
if (*TExprList)(unsafe.Pointer(pList)).FnExpr == int32(2) {
|
|
return int32(1)
|
|
}
|
|
if (*TExprList)(unsafe.Pointer(pList)).FnExpr == int32(3) && _sqlite3ExprIsNotTrue(tls, (*(*TExprList_item)(unsafe.Pointer(pList + 8 + 2*32))).FpExpr) != 0 {
|
|
return int32(1)
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Locate a user function given a name, a number of arguments and a flag
|
|
// ** indicating whether the function prefers UTF-16 over UTF-8. Return a
|
|
// ** pointer to the FuncDef structure that defines that function, or return
|
|
// ** NULL if the function does not exist.
|
|
// **
|
|
// ** If the createFlag argument is true, then a new (blank) FuncDef
|
|
// ** structure is created and liked into the "db" structure if a
|
|
// ** no matching function previously existed.
|
|
// **
|
|
// ** If nArg is -2, then the first valid function found is returned. A
|
|
// ** function is valid if xSFunc is non-zero. The nArg==(-2)
|
|
// ** case is used to see if zName is a valid function name for some number
|
|
// ** of arguments. If nArg is -2, then createFlag must be 0.
|
|
// **
|
|
// ** If createFlag is false, then a function with the required name and
|
|
// ** number of arguments may be returned even if the eTextRep flag does not
|
|
// ** match that requested.
|
|
// */
|
|
func _sqlite3FindFunction(tls *libc.TLS, db uintptr, zName uintptr, nArg int32, enc Tu8, createFlag Tu8) (r uintptr) {
|
|
var bestScore, h, nName, score, score1 int32
|
|
var p, pBest, pOther, z, v1 uintptr
|
|
var v2 bool
|
|
_, _, _, _, _, _, _, _, _, _, _ = bestScore, h, nName, p, pBest, pOther, score, score1, z, v1, v2 /* Iterator variable */
|
|
pBest = uintptr(0) /* Best match found so far */
|
|
bestScore = 0 /* Length of the name */
|
|
nName = _sqlite3Strlen30(tls, zName)
|
|
/* First search for a match amongst the application-defined functions.
|
|
*/
|
|
p = _sqlite3HashFind(tls, db+624, zName)
|
|
for p != 0 {
|
|
score = _matchQuality(tls, p, nArg, enc)
|
|
if score > bestScore {
|
|
pBest = p
|
|
bestScore = score
|
|
}
|
|
p = (*TFuncDef)(unsafe.Pointer(p)).FpNext
|
|
}
|
|
/* If no match is found, search the built-in functions.
|
|
**
|
|
** If the DBFLAG_PreferBuiltin flag is set, then search the built-in
|
|
** functions even if a prior app-defined function was found. And give
|
|
** priority to built-in functions.
|
|
**
|
|
** Except, if createFlag is true, that means that we are trying to
|
|
** install a new function. Whatever FuncDef structure is returned it will
|
|
** have fields overwritten with new information appropriate for the
|
|
** new function. But the FuncDefs for built-in functions are read-only.
|
|
** So we must not search for built-ins when creating a new function.
|
|
*/
|
|
if !(createFlag != 0) && (pBest == uintptr(0) || (*Tsqlite3)(unsafe.Pointer(db)).FmDbFlags&uint32(DBFLAG_PreferBuiltin) != uint32(0)) {
|
|
bestScore = 0
|
|
h = (libc.Int32FromUint8(_sqlite3UpperToLower[uint8(**(**uint8)(__ccgo_up(zName)))]) + nName) % int32(SQLITE_FUNC_HASH_SZ)
|
|
p = _sqlite3FunctionSearch(tls, h, zName)
|
|
for p != 0 {
|
|
score1 = _matchQuality(tls, p, nArg, enc)
|
|
if score1 > bestScore {
|
|
pBest = p
|
|
bestScore = score1
|
|
}
|
|
p = (*TFuncDef)(unsafe.Pointer(p)).FpNext
|
|
}
|
|
}
|
|
/* If the createFlag parameter is true and the search did not reveal an
|
|
** exact match for the name, number of arguments and encoding, then add a
|
|
** new entry to the hash table and return it.
|
|
*/
|
|
if v2 = createFlag != 0 && bestScore < int32(FUNC_PERFECT_MATCH); v2 {
|
|
v1 = _sqlite3DbMallocZero(tls, db, uint64(uint64(72)+libc.Uint64FromInt32(nName)+uint64(1)))
|
|
pBest = v1
|
|
}
|
|
if v2 && v1 != uintptr(0) {
|
|
(*TFuncDef)(unsafe.Pointer(pBest)).FzName = pBest + 1*72
|
|
(*TFuncDef)(unsafe.Pointer(pBest)).FnArg = libc.Int16FromUint16(libc.Uint16FromInt32(nArg))
|
|
(*TFuncDef)(unsafe.Pointer(pBest)).FfuncFlags = uint32(enc)
|
|
libc.Xmemcpy(tls, pBest+1*72, zName, libc.Uint64FromInt32(nName+int32(1)))
|
|
z = (*TFuncDef)(unsafe.Pointer(pBest)).FzName
|
|
for {
|
|
if !(**(**Tu8)(__ccgo_up(z)) != 0) {
|
|
break
|
|
}
|
|
**(**Tu8)(__ccgo_up(z)) = _sqlite3UpperToLower[**(**Tu8)(__ccgo_up(z))]
|
|
goto _3
|
|
_3:
|
|
;
|
|
z = z + 1
|
|
}
|
|
pOther = _sqlite3HashInsert(tls, db+624, (*TFuncDef)(unsafe.Pointer(pBest)).FzName, pBest)
|
|
if pOther == pBest {
|
|
_sqlite3DbFree(tls, db, pBest)
|
|
_sqlite3OomFault(tls, db)
|
|
return uintptr(0)
|
|
} else {
|
|
(*TFuncDef)(unsafe.Pointer(pBest)).FpNext = pOther
|
|
}
|
|
}
|
|
if pBest != 0 && ((*TFuncDef)(unsafe.Pointer(pBest)).FxSFunc != 0 || createFlag != 0) {
|
|
return pBest
|
|
}
|
|
return uintptr(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Parameter zIn contains a rank() function specification. The format of
|
|
// ** this is:
|
|
// **
|
|
// ** + Bareword (function name)
|
|
// ** + Open parenthesis - "("
|
|
// ** + Zero or more SQL literals in a comma separated list
|
|
// ** + Close parenthesis - ")"
|
|
// */
|
|
func _sqlite3Fts5ConfigParseRank(tls *libc.TLS, zIn uintptr, pzRank uintptr, pzRankArgs uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var p, pArgs, pRank, zRank, zRankArgs uintptr
|
|
var _ /* rc at bp+0 */ int32
|
|
_, _, _, _, _ = p, pArgs, pRank, zRank, zRankArgs
|
|
p = zIn
|
|
zRank = uintptr(0)
|
|
zRankArgs = uintptr(0)
|
|
**(**int32)(__ccgo_up(bp)) = SQLITE_OK
|
|
**(**uintptr)(__ccgo_up(pzRank)) = uintptr(0)
|
|
**(**uintptr)(__ccgo_up(pzRankArgs)) = uintptr(0)
|
|
if p == uintptr(0) {
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
} else {
|
|
p = _fts5ConfigSkipWhitespace(tls, p)
|
|
pRank = p
|
|
p = _fts5ConfigSkipBareword(tls, p)
|
|
if p != 0 {
|
|
zRank = _sqlite3Fts5MallocZero(tls, bp, int64(uintptr(1)+p)-int64(pRank))
|
|
if zRank != 0 {
|
|
libc.Xmemcpy(tls, zRank, pRank, libc.Uint64FromInt64(int64(p)-int64(pRank)))
|
|
}
|
|
} else {
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
}
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
p = _fts5ConfigSkipWhitespace(tls, p)
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) != int32('(') {
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
}
|
|
p = p + 1
|
|
}
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
p = _fts5ConfigSkipWhitespace(tls, p)
|
|
pArgs = p
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(p))) != int32(')') {
|
|
p = _fts5ConfigSkipArgs(tls, p)
|
|
if p == uintptr(0) {
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
} else {
|
|
zRankArgs = _sqlite3Fts5MallocZero(tls, bp, int64(uintptr(1)+p)-int64(pArgs))
|
|
if zRankArgs != 0 {
|
|
libc.Xmemcpy(tls, zRankArgs, pArgs, libc.Uint64FromInt64(int64(p)-int64(pArgs)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if **(**int32)(__ccgo_up(bp)) != SQLITE_OK {
|
|
Xsqlite3_free(tls, zRank)
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(pzRank)) = zRank
|
|
**(**uintptr)(__ccgo_up(pzRankArgs)) = zRankArgs
|
|
}
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is only called when using the special 'trigram' tokenizer.
|
|
// ** Argument zText contains the text of a LIKE or GLOB pattern matched
|
|
// ** against column iCol. This function creates and compiles an FTS5 MATCH
|
|
// ** expression that will match a superset of the rows matched by the LIKE or
|
|
// ** GLOB. If successful, SQLITE_OK is returned. Otherwise, an SQLite error
|
|
// ** code.
|
|
// */
|
|
func _sqlite3Fts5ExprPattern(tls *libc.TLS, pConfig uintptr, bGlob int32, iCol int32, zText uintptr, pp uintptr) (r int32) {
|
|
var aSpec [3]uint8
|
|
var bAnd, i, iFirst, iOut, jj, rc, v1 int32
|
|
var nText Ti64
|
|
var zExpr uintptr
|
|
_, _, _, _, _, _, _, _, _, _ = aSpec, bAnd, i, iFirst, iOut, jj, nText, rc, zExpr, v1
|
|
nText = libc.Int64FromUint64(libc.Xstrlen(tls, zText))
|
|
zExpr = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(nText*int64(4)+int64(1)))
|
|
rc = SQLITE_OK
|
|
if zExpr == uintptr(0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
} else {
|
|
iOut = 0
|
|
i = 0
|
|
iFirst = 0
|
|
if bGlob == 0 {
|
|
aSpec[0] = uint8('_')
|
|
aSpec[int32(1)] = uint8('%')
|
|
aSpec[int32(2)] = uint8(0)
|
|
} else {
|
|
aSpec[0] = uint8('*')
|
|
aSpec[int32(1)] = uint8('?')
|
|
aSpec[int32(2)] = uint8('[')
|
|
}
|
|
for int64(i) <= nText {
|
|
if int64(i) == nText || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zText + uintptr(i)))) == libc.Int32FromUint8(aSpec[0]) || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zText + uintptr(i)))) == libc.Int32FromUint8(aSpec[int32(1)]) || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zText + uintptr(i)))) == libc.Int32FromUint8(aSpec[int32(2)]) {
|
|
if _fts5ExprCountChar(tls, zText+uintptr(iFirst), i-iFirst) >= int32(3) {
|
|
v1 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zExpr + uintptr(v1))) = uint8('"')
|
|
jj = iFirst
|
|
for {
|
|
if !(jj < i) {
|
|
break
|
|
}
|
|
v1 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zExpr + uintptr(v1))) = **(**uint8)(__ccgo_up(zText + uintptr(jj)))
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zText + uintptr(jj)))) == int32('"') {
|
|
v1 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zExpr + uintptr(v1))) = uint8('"')
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
jj = jj + 1
|
|
}
|
|
v1 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zExpr + uintptr(v1))) = uint8('"')
|
|
v1 = iOut
|
|
iOut = iOut + 1
|
|
**(**uint8)(__ccgo_up(zExpr + uintptr(v1))) = uint8(' ')
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zText + uintptr(i)))) == libc.Int32FromUint8(aSpec[int32(2)]) {
|
|
i = i + int32(2)
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zText + uintptr(i-int32(1))))) == int32('^') {
|
|
i = i + 1
|
|
}
|
|
for int64(i) < nText && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zText + uintptr(i)))) != int32(']') {
|
|
i = i + 1
|
|
}
|
|
}
|
|
iFirst = i + int32(1)
|
|
}
|
|
i = i + 1
|
|
}
|
|
if iOut > 0 {
|
|
bAnd = 0
|
|
if (*TFts5Config)(unsafe.Pointer(pConfig)).FeDetail != FTS5_DETAIL_FULL {
|
|
bAnd = int32(1)
|
|
if (*TFts5Config)(unsafe.Pointer(pConfig)).FeDetail == int32(FTS5_DETAIL_NONE) {
|
|
iCol = (*TFts5Config)(unsafe.Pointer(pConfig)).FnCol
|
|
}
|
|
}
|
|
**(**uint8)(__ccgo_up(zExpr + uintptr(iOut))) = uint8('\000')
|
|
rc = _sqlite3Fts5ExprNew(tls, pConfig, bAnd, iCol, zExpr, pp, (*TFts5Config)(unsafe.Pointer(pConfig)).FpzErrmsg)
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(pp)) = uintptr(0)
|
|
}
|
|
Xsqlite3_free(tls, zExpr)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Add an entry to the in-memory hash table. The key is the concatenation
|
|
// ** of bByte and (pToken/nToken). The value is (iRowid/iCol/iPos).
|
|
// **
|
|
// ** (bByte || pToken) -> (iRowid,iCol,iPos)
|
|
// **
|
|
// ** Or, if iCol is negative, then the value is a delete marker.
|
|
// */
|
|
func _sqlite3Fts5HashWrite(tls *libc.TLS, pHash uintptr, iRowid Ti64, iCol int32, iPos int32, bByte uint8, pToken uintptr, nToken int32) (r int32) {
|
|
var bNew, nIncr, rc, v2 int32
|
|
var iDiff Tu64
|
|
var iHash uint32
|
|
var nByte, nNew Tsqlite3_int64
|
|
var p, pNew, pPtr, pp, zKey, zKey1, v6 uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = bNew, iDiff, iHash, nByte, nIncr, nNew, p, pNew, pPtr, pp, rc, zKey, zKey1, v2, v6
|
|
nIncr = 0 /* If non-delete entry should be written */
|
|
bNew = libc.BoolInt32((*TFts5Hash)(unsafe.Pointer(pHash)).FeDetail == FTS5_DETAIL_FULL)
|
|
/* Attempt to locate an existing hash entry */
|
|
iHash = _fts5HashKey2(tls, (*TFts5Hash)(unsafe.Pointer(pHash)).FnSlot, bByte, pToken, nToken)
|
|
p = **(**uintptr)(__ccgo_up((*TFts5Hash)(unsafe.Pointer(pHash)).FaSlot + uintptr(iHash)*8))
|
|
for {
|
|
if !(p != 0) {
|
|
break
|
|
}
|
|
zKey = p + 1*48
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zKey))) == libc.Int32FromUint8(bByte) && (*TFts5HashEntry)(unsafe.Pointer(p)).FnKey == nToken+int32(1) && libc.Xmemcmp(tls, zKey+1, pToken, libc.Uint64FromInt32(nToken)) == 0 {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
p = (*TFts5HashEntry)(unsafe.Pointer(p)).FpHashNext
|
|
}
|
|
/* If an existing hash entry cannot be found, create a new one. */
|
|
if p == uintptr(0) {
|
|
nByte = libc.Int64FromUint64(uint64(48) + libc.Uint64FromInt32(nToken+libc.Int32FromInt32(1)) + uint64(1) + uint64(64))
|
|
if nByte < int64(128) {
|
|
nByte = int64(128)
|
|
}
|
|
/* Grow the Fts5Hash.aSlot[] array if necessary. */
|
|
if (*TFts5Hash)(unsafe.Pointer(pHash)).FnEntry*int32(2) >= (*TFts5Hash)(unsafe.Pointer(pHash)).FnSlot {
|
|
rc = _fts5HashResize(tls, pHash)
|
|
if rc != SQLITE_OK {
|
|
return rc
|
|
}
|
|
iHash = _fts5HashKey2(tls, (*TFts5Hash)(unsafe.Pointer(pHash)).FnSlot, bByte, pToken, nToken)
|
|
}
|
|
/* Allocate new Fts5HashEntry and add it to the hash table. */
|
|
p = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(nByte))
|
|
if !(p != 0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
libc.Xmemset(tls, p, 0, uint64(48))
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FnAlloc = int32(nByte)
|
|
zKey1 = p + 1*48
|
|
**(**uint8)(__ccgo_up(zKey1)) = bByte
|
|
libc.Xmemcpy(tls, zKey1+1, pToken, libc.Uint64FromInt32(nToken))
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FnKey = nToken + int32(1)
|
|
**(**uint8)(__ccgo_up(zKey1 + uintptr(nToken+int32(1)))) = uint8('\000')
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FnData = libc.Int32FromUint64(libc.Uint64FromInt32(nToken+int32(1)) + uint64(48))
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FpHashNext = **(**uintptr)(__ccgo_up((*TFts5Hash)(unsafe.Pointer(pHash)).FaSlot + uintptr(iHash)*8))
|
|
**(**uintptr)(__ccgo_up((*TFts5Hash)(unsafe.Pointer(pHash)).FaSlot + uintptr(iHash)*8)) = p
|
|
(*TFts5Hash)(unsafe.Pointer(pHash)).FnEntry = (*TFts5Hash)(unsafe.Pointer(pHash)).FnEntry + 1
|
|
/* Add the first rowid field to the hash-entry */
|
|
**(**int32)(__ccgo_up(p + 24)) += _sqlite3Fts5PutVarint(tls, p+uintptr((*TFts5HashEntry)(unsafe.Pointer(p)).FnData), libc.Uint64FromInt64(iRowid))
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiRowid = iRowid
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiSzPoslist = (*TFts5HashEntry)(unsafe.Pointer(p)).FnData
|
|
if (*TFts5Hash)(unsafe.Pointer(pHash)).FeDetail != int32(FTS5_DETAIL_NONE) {
|
|
**(**int32)(__ccgo_up(p + 24)) += int32(1)
|
|
if (*TFts5Hash)(unsafe.Pointer(pHash)).FeDetail == FTS5_DETAIL_FULL {
|
|
v2 = 0
|
|
} else {
|
|
v2 = -int32(1)
|
|
}
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiCol = int16(v2)
|
|
}
|
|
} else {
|
|
/* Appending to an existing hash-entry. Check that there is enough
|
|
** space to append the largest possible new entry. Worst case scenario
|
|
** is:
|
|
**
|
|
** + 9 bytes for a new rowid,
|
|
** + 4 byte reserved for the "poslist size" varint.
|
|
** + 1 byte for a "new column" byte,
|
|
** + 3 bytes for a new column number (16-bit max) as a varint,
|
|
** + 5 bytes for the new position offset (32-bit max).
|
|
*/
|
|
if (*TFts5HashEntry)(unsafe.Pointer(p)).FnAlloc-(*TFts5HashEntry)(unsafe.Pointer(p)).FnData < libc.Int32FromInt32(9)+libc.Int32FromInt32(4)+libc.Int32FromInt32(1)+libc.Int32FromInt32(3)+libc.Int32FromInt32(5) {
|
|
nNew = int64((*TFts5HashEntry)(unsafe.Pointer(p)).FnAlloc * int32(2))
|
|
pNew = Xsqlite3_realloc64(tls, p, libc.Uint64FromInt64(nNew))
|
|
if pNew == uintptr(0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
(*TFts5HashEntry)(unsafe.Pointer(pNew)).FnAlloc = int32(nNew)
|
|
pp = (*TFts5Hash)(unsafe.Pointer(pHash)).FaSlot + uintptr(iHash)*8
|
|
for {
|
|
if !(**(**uintptr)(__ccgo_up(pp)) != p) {
|
|
break
|
|
}
|
|
goto _3
|
|
_3:
|
|
;
|
|
pp = **(**uintptr)(__ccgo_up(pp))
|
|
}
|
|
**(**uintptr)(__ccgo_up(pp)) = pNew
|
|
p = pNew
|
|
}
|
|
nIncr = nIncr - (*TFts5HashEntry)(unsafe.Pointer(p)).FnData
|
|
}
|
|
pPtr = p
|
|
/* If this is a new rowid, append the 4-byte size field for the previous
|
|
** entry, and the new rowid for this entry. */
|
|
if iRowid != (*TFts5HashEntry)(unsafe.Pointer(p)).FiRowid {
|
|
iDiff = libc.Uint64FromInt64(iRowid) - libc.Uint64FromInt64((*TFts5HashEntry)(unsafe.Pointer(p)).FiRowid)
|
|
_fts5HashAddPoslistSize(tls, pHash, p, uintptr(0))
|
|
**(**int32)(__ccgo_up(p + 24)) += _sqlite3Fts5PutVarint(tls, pPtr+uintptr((*TFts5HashEntry)(unsafe.Pointer(p)).FnData), iDiff)
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiRowid = iRowid
|
|
bNew = int32(1)
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiSzPoslist = (*TFts5HashEntry)(unsafe.Pointer(p)).FnData
|
|
if (*TFts5Hash)(unsafe.Pointer(pHash)).FeDetail != int32(FTS5_DETAIL_NONE) {
|
|
**(**int32)(__ccgo_up(p + 24)) += int32(1)
|
|
if (*TFts5Hash)(unsafe.Pointer(pHash)).FeDetail == FTS5_DETAIL_FULL {
|
|
v2 = 0
|
|
} else {
|
|
v2 = -int32(1)
|
|
}
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiCol = int16(v2)
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiPos = 0
|
|
}
|
|
}
|
|
if iCol >= 0 {
|
|
if (*TFts5Hash)(unsafe.Pointer(pHash)).FeDetail == int32(FTS5_DETAIL_NONE) {
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FbContent = uint8(1)
|
|
} else {
|
|
/* Append a new column value, if necessary */
|
|
if iCol != int32((*TFts5HashEntry)(unsafe.Pointer(p)).FiCol) {
|
|
if (*TFts5Hash)(unsafe.Pointer(pHash)).FeDetail == FTS5_DETAIL_FULL {
|
|
v6 = p + 24
|
|
v2 = *(*int32)(unsafe.Pointer(v6))
|
|
*(*int32)(unsafe.Pointer(v6)) = *(*int32)(unsafe.Pointer(v6)) + 1
|
|
**(**Tu8)(__ccgo_up(pPtr + uintptr(v2))) = uint8(0x01)
|
|
**(**int32)(__ccgo_up(p + 24)) += _sqlite3Fts5PutVarint(tls, pPtr+uintptr((*TFts5HashEntry)(unsafe.Pointer(p)).FnData), libc.Uint64FromInt32(iCol))
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiCol = int16(iCol)
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiPos = 0
|
|
} else {
|
|
bNew = int32(1)
|
|
v2 = iCol
|
|
iPos = v2
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiCol = int16(v2)
|
|
}
|
|
}
|
|
/* Append the new position offset, if necessary */
|
|
if bNew != 0 {
|
|
**(**int32)(__ccgo_up(p + 24)) += _sqlite3Fts5PutVarint(tls, pPtr+uintptr((*TFts5HashEntry)(unsafe.Pointer(p)).FnData), libc.Uint64FromInt32(iPos-(*TFts5HashEntry)(unsafe.Pointer(p)).FiPos+int32(2)))
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiPos = iPos
|
|
}
|
|
}
|
|
} else {
|
|
/* This is a delete. Set the delete flag. */
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FbDel = uint8(1)
|
|
}
|
|
nIncr = nIncr + (*TFts5HashEntry)(unsafe.Pointer(p)).FnData
|
|
**(**int32)(__ccgo_up((*TFts5Hash)(unsafe.Pointer(pHash)).FpnByte)) += nIncr
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return a nul-terminated copy of the string indicated by pIn. If nIn
|
|
// ** is non-negative, then it is the length of the string in bytes. Otherwise,
|
|
// ** the length of the string is determined using strlen().
|
|
// **
|
|
// ** It is the responsibility of the caller to eventually free the returned
|
|
// ** buffer using sqlite3_free(). If an OOM error occurs, NULL is returned.
|
|
// */
|
|
func _sqlite3Fts5Strndup(tls *libc.TLS, pRc uintptr, pIn uintptr, nIn int32) (r uintptr) {
|
|
var zRet uintptr
|
|
_ = zRet
|
|
zRet = uintptr(0)
|
|
if **(**int32)(__ccgo_up(pRc)) == SQLITE_OK {
|
|
if nIn < 0 {
|
|
nIn = libc.Int32FromUint64(libc.Xstrlen(tls, pIn))
|
|
}
|
|
zRet = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(int64(nIn)+int64(1)))
|
|
if zRet != 0 {
|
|
libc.Xmemcpy(tls, zRet, pIn, libc.Uint64FromInt32(nIn))
|
|
**(**uint8)(__ccgo_up(zRet + uintptr(nIn))) = uint8('\000')
|
|
} else {
|
|
**(**int32)(__ccgo_up(pRc)) = int32(SQLITE_NOMEM)
|
|
}
|
|
}
|
|
return zRet
|
|
}
|
|
|
|
func _sqlite3Fts5TermsetAdd(tls *libc.TLS, p uintptr, iIdx int32, pTerm uintptr, nTerm int32, pbPresent uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var hash Tu32
|
|
var i int32
|
|
var pEntry uintptr
|
|
var _ /* rc at bp+0 */ int32
|
|
_, _, _ = hash, i, pEntry
|
|
**(**int32)(__ccgo_up(bp)) = SQLITE_OK
|
|
**(**int32)(__ccgo_up(pbPresent)) = 0
|
|
if p != 0 {
|
|
hash = uint32(13)
|
|
/* Calculate a hash value for this term. This is the same hash checksum
|
|
** used by the fts5_hash.c module. This is not important for correct
|
|
** operation of the module, but is necessary to ensure that some tests
|
|
** designed to produce hash table collisions really do work. */
|
|
i = nTerm - int32(1)
|
|
for {
|
|
if !(i >= 0) {
|
|
break
|
|
}
|
|
hash = hash<<libc.Int32FromInt32(3) ^ hash ^ uint32(**(**uint8)(__ccgo_up(pTerm + uintptr(i))))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i - 1
|
|
}
|
|
hash = hash<<libc.Int32FromInt32(3) ^ hash ^ libc.Uint32FromInt32(iIdx)
|
|
hash = hash % libc.Uint32FromInt32(libc.Int32FromUint64(libc.Uint64FromInt64(4096)/libc.Uint64FromInt64(8)))
|
|
pEntry = **(**uintptr)(__ccgo_up(p + uintptr(hash)*8))
|
|
for {
|
|
if !(pEntry != 0) {
|
|
break
|
|
}
|
|
if (*TFts5TermsetEntry)(unsafe.Pointer(pEntry)).FiIdx == iIdx && (*TFts5TermsetEntry)(unsafe.Pointer(pEntry)).FnTerm == nTerm && libc.Xmemcmp(tls, (*TFts5TermsetEntry)(unsafe.Pointer(pEntry)).FpTerm, pTerm, libc.Uint64FromInt32(nTerm)) == 0 {
|
|
**(**int32)(__ccgo_up(pbPresent)) = int32(1)
|
|
break
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
pEntry = (*TFts5TermsetEntry)(unsafe.Pointer(pEntry)).FpNext
|
|
}
|
|
if pEntry == uintptr(0) {
|
|
pEntry = _sqlite3Fts5MallocZero(tls, bp, libc.Int64FromUint64(uint64(24)+libc.Uint64FromInt32(nTerm)))
|
|
if pEntry != 0 {
|
|
(*TFts5TermsetEntry)(unsafe.Pointer(pEntry)).FpTerm = pEntry + 1*24
|
|
(*TFts5TermsetEntry)(unsafe.Pointer(pEntry)).FnTerm = nTerm
|
|
(*TFts5TermsetEntry)(unsafe.Pointer(pEntry)).FiIdx = iIdx
|
|
libc.Xmemcpy(tls, (*TFts5TermsetEntry)(unsafe.Pointer(pEntry)).FpTerm, pTerm, libc.Uint64FromInt32(nTerm))
|
|
(*TFts5TermsetEntry)(unsafe.Pointer(pEntry)).FpNext = **(**uintptr)(__ccgo_up(p + uintptr(hash)*8))
|
|
**(**uintptr)(__ccgo_up(p + uintptr(hash)*8)) = pEntry
|
|
}
|
|
}
|
|
}
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If zNum represents an integer that will fit in 32-bits, then set
|
|
// ** *pValue to that integer and return true. Otherwise return false.
|
|
// **
|
|
// ** This routine accepts both decimal and hexadecimal notation for integers.
|
|
// **
|
|
// ** Any non-numeric characters that following zNum are ignored.
|
|
// ** This is different from sqlite3Atoi64() which requires the
|
|
// ** input number to be zero-terminated.
|
|
// */
|
|
func _sqlite3GetInt32(tls *libc.TLS, zNum uintptr, pValue uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var c, i, neg, v3 int32
|
|
var v Tsqlite_int64
|
|
var v4 bool
|
|
var _ /* u at bp+0 */ Tu32
|
|
_, _, _, _, _, _ = c, i, neg, v, v3, v4
|
|
v = 0
|
|
neg = 0
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zNum))) == int32('-') {
|
|
neg = int32(1)
|
|
zNum = zNum + 1
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zNum))) == int32('+') {
|
|
zNum = zNum + 1
|
|
} else {
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zNum))) == int32('0') && (libc.Int32FromUint8(**(**uint8)(__ccgo_up(zNum + 1))) == int32('x') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zNum + 1))) == int32('X')) && libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(zNum + 2)))])&int32(0x08) != 0 {
|
|
**(**Tu32)(__ccgo_up(bp)) = uint32(0)
|
|
zNum = zNum + uintptr(2)
|
|
for libc.Int32FromUint8(**(**uint8)(__ccgo_up(zNum))) == int32('0') {
|
|
zNum = zNum + 1
|
|
}
|
|
i = 0
|
|
for {
|
|
if !(i < int32(8) && libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(zNum + uintptr(i))))])&int32(0x08) != 0) {
|
|
break
|
|
}
|
|
**(**Tu32)(__ccgo_up(bp)) = **(**Tu32)(__ccgo_up(bp))*uint32(16) + uint32(_sqlite3HexToInt(tls, libc.Int32FromUint8(**(**uint8)(__ccgo_up(zNum + uintptr(i))))))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if **(**Tu32)(__ccgo_up(bp))&uint32(0x80000000) == uint32(0) && libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(zNum + uintptr(i))))])&int32(0x08) == 0 {
|
|
libc.Xmemcpy(tls, pValue, bp, uint64(4))
|
|
return int32(1)
|
|
} else {
|
|
return 0
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if !(libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(zNum)))])&libc.Int32FromInt32(0x04) != 0) {
|
|
return 0
|
|
}
|
|
for libc.Int32FromUint8(**(**uint8)(__ccgo_up(zNum))) == int32('0') {
|
|
zNum = zNum + 1
|
|
}
|
|
i = 0
|
|
for {
|
|
if v4 = i < int32(11); v4 {
|
|
v3 = libc.Int32FromUint8(**(**uint8)(__ccgo_up(zNum + uintptr(i)))) - libc.Int32FromUint8('0')
|
|
c = v3
|
|
}
|
|
if !(v4 && v3 >= 0 && c <= int32(9)) {
|
|
break
|
|
}
|
|
v = v*int64(10) + int64(c)
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
/* The longest decimal representation of a 32 bit integer is 10 digits:
|
|
**
|
|
** 1234567890
|
|
** 2^31 -> 2147483648
|
|
*/
|
|
if i > int32(10) {
|
|
return 0
|
|
}
|
|
if v-int64(neg) > int64(2147483647) {
|
|
return 0
|
|
}
|
|
if neg != 0 {
|
|
v = -v
|
|
}
|
|
**(**int32)(__ccgo_up(pValue)) = int32(v)
|
|
return int32(1)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Insert a new FuncDef into a FuncDefHash hash table.
|
|
// */
|
|
func _sqlite3InsertBuiltinFuncs(tls *libc.TLS, aDef uintptr, nDef int32) {
|
|
var h, i, nName int32
|
|
var pOther, zName uintptr
|
|
_, _, _, _, _ = h, i, nName, pOther, zName
|
|
i = 0
|
|
for {
|
|
if !(i < nDef) {
|
|
break
|
|
}
|
|
zName = (**(**TFuncDef)(__ccgo_up(aDef + uintptr(i)*72))).FzName
|
|
nName = _sqlite3Strlen30(tls, zName)
|
|
h = (libc.Int32FromUint8(**(**uint8)(__ccgo_up(zName))) + nName) % int32(SQLITE_FUNC_HASH_SZ)
|
|
pOther = _sqlite3FunctionSearch(tls, h, zName)
|
|
if pOther != 0 {
|
|
(**(**TFuncDef)(__ccgo_up(aDef + uintptr(i)*72))).FpNext = (*TFuncDef)(unsafe.Pointer(pOther)).FpNext
|
|
(*TFuncDef)(unsafe.Pointer(pOther)).FpNext = aDef + uintptr(i)*72
|
|
} else {
|
|
(**(**TFuncDef)(__ccgo_up(aDef + uintptr(i)*72))).FpNext = uintptr(0)
|
|
*(*uintptr)(unsafe.Pointer(aDef + uintptr(i)*72 + 64)) = **(**uintptr)(__ccgo_up(uintptr(unsafe.Pointer(&_sqlite3BuiltinFunctions)) + uintptr(h)*8))
|
|
**(**uintptr)(__ccgo_up(uintptr(unsafe.Pointer(&_sqlite3BuiltinFunctions)) + uintptr(h)*8)) = aDef + uintptr(i)*72
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Render an signed 64-bit integer as text. Store the result in zOut[] and
|
|
// ** return the length of the string that was stored, in bytes. The value
|
|
// ** returned does not include the zero terminator at the end of the output
|
|
// ** string.
|
|
// **
|
|
// ** The caller must ensure that zOut[] is at least 21 bytes in size.
|
|
// */
|
|
func _sqlite3Int64ToText(tls *libc.TLS, v Ti64, zOut uintptr) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var i, kk, v2 int32
|
|
var x Tu64
|
|
var v1 uint64
|
|
var _ /* u at bp+0 */ struct {
|
|
FforceAlignment [0]Tu16
|
|
Fa [21]uint8
|
|
F__ccgo_pad2 [1]byte
|
|
}
|
|
_, _, _, _, _ = i, kk, x, v1, v2
|
|
if v > 0 {
|
|
x = libc.Uint64FromInt64(v)
|
|
} else {
|
|
if v == 0 {
|
|
**(**uint8)(__ccgo_up(zOut)) = uint8('0')
|
|
**(**uint8)(__ccgo_up(zOut + 1)) = uint8(0)
|
|
return int32(1)
|
|
} else {
|
|
if v == int64(-libc.Int32FromInt32(1))-(libc.Int64FromUint32(0xffffffff)|libc.Int64FromInt32(0x7fffffff)<<libc.Int32FromInt32(32)) {
|
|
v1 = libc.Uint64FromInt32(1) << libc.Int32FromInt32(63)
|
|
} else {
|
|
v1 = libc.Uint64FromInt64(-v)
|
|
}
|
|
x = v1
|
|
}
|
|
}
|
|
i = libc.Int32FromUint64(libc.Uint64FromInt64(21) - libc.Uint64FromInt32(1))
|
|
**(**uint8)(__ccgo_up(bp + uintptr(i))) = uint8(0)
|
|
for x >= uint64(10) {
|
|
kk = libc.Int32FromUint64(x % uint64(100) * uint64(2))
|
|
**(**Tu16)(__ccgo_up(bp + uintptr(i-int32(2)))) = **(**Tu16)(__ccgo_up(uintptr(unsafe.Pointer(&_sqlite3DigitPairs)) + uintptr(kk)))
|
|
i = i - int32(2)
|
|
x = x / uint64(100)
|
|
}
|
|
if x != 0 {
|
|
i = i - 1
|
|
v2 = i
|
|
**(**uint8)(__ccgo_up(bp + uintptr(v2))) = uint8(x + uint64('0'))
|
|
}
|
|
if v < 0 {
|
|
i = i - 1
|
|
v2 = i
|
|
**(**uint8)(__ccgo_up(bp + uintptr(v2))) = uint8('-')
|
|
}
|
|
libc.Xmemcpy(tls, zOut, bp+uintptr(i), uint64(21)-libc.Uint64FromInt32(i))
|
|
return libc.Int32FromUint64(libc.Uint64FromInt64(21) - libc.Uint64FromInt32(1) - libc.Uint64FromInt32(i))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** pExpr points to an expression which implements a function. If
|
|
// ** it is appropriate to apply the LIKE optimization to that function
|
|
// ** then set aWc[0] through aWc[2] to the wildcard characters and the
|
|
// ** escape character and then return TRUE. If the function is not a
|
|
// ** LIKE-style function then return FALSE.
|
|
// **
|
|
// ** The expression "a LIKE b ESCAPE c" is only considered a valid LIKE
|
|
// ** operator if c is a string literal that is exactly one byte in length.
|
|
// ** That one byte is stored in aWc[3]. aWc[3] is set to zero if there is
|
|
// ** no ESCAPE clause.
|
|
// **
|
|
// ** *pIsNocase is set to true if uppercase and lowercase are equivalent for
|
|
// ** the function (default for LIKE). If the function makes the distinction
|
|
// ** between uppercase and lowercase (as does GLOB) then *pIsNocase is set to
|
|
// ** false.
|
|
// */
|
|
func _sqlite3IsLikeFunction(tls *libc.TLS, db uintptr, pExpr uintptr, pIsNocase uintptr, aWc uintptr) (r int32) {
|
|
var nExpr int32
|
|
var pDef, pEscape, zEscape uintptr
|
|
_, _, _, _ = nExpr, pDef, pEscape, zEscape
|
|
if !(*(*uintptr)(unsafe.Pointer(pExpr + 32)) != 0) {
|
|
return 0
|
|
}
|
|
nExpr = (*TExprList)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)))).FnExpr
|
|
pDef = _sqlite3FindFunction(tls, db, *(*uintptr)(unsafe.Pointer(pExpr + 8)), nExpr, uint8(SQLITE_UTF8), uint8(0))
|
|
if pDef == uintptr(0) || (*TFuncDef)(unsafe.Pointer(pDef)).FfuncFlags&uint32(SQLITE_FUNC_LIKE) == uint32(0) {
|
|
return 0
|
|
}
|
|
/* The memcpy() statement assumes that the wildcard characters are
|
|
** the first three statements in the compareInfo structure. The
|
|
** asserts() that follow verify that assumption
|
|
*/
|
|
libc.Xmemcpy(tls, aWc, (*TFuncDef)(unsafe.Pointer(pDef)).FpUserData, uint64(3))
|
|
if nExpr < int32(3) {
|
|
**(**uint8)(__ccgo_up(aWc + 3)) = uint8(0)
|
|
} else {
|
|
pEscape = (*(*TExprList_item)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)) + 8 + 2*32))).FpExpr
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pEscape)).Fop) != int32(TK_STRING) {
|
|
return 0
|
|
}
|
|
zEscape = *(*uintptr)(unsafe.Pointer(pEscape + 8))
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zEscape))) == 0 || libc.Int32FromUint8(**(**uint8)(__ccgo_up(zEscape + 1))) != 0 {
|
|
return 0
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zEscape))) == libc.Int32FromUint8(**(**uint8)(__ccgo_up(aWc))) {
|
|
return 0
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zEscape))) == libc.Int32FromUint8(**(**uint8)(__ccgo_up(aWc + 1))) {
|
|
return 0
|
|
}
|
|
**(**uint8)(__ccgo_up(aWc + 3)) = **(**uint8)(__ccgo_up(zEscape))
|
|
}
|
|
**(**int32)(__ccgo_up(pIsNocase)) = libc.BoolInt32((*TFuncDef)(unsafe.Pointer(pDef)).FfuncFlags&uint32(SQLITE_FUNC_CASE) == uint32(0))
|
|
return int32(1)
|
|
}
|
|
|
|
/* Mathematical Constants */
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return true if pTab is a virtual table and zName is a shadow table name
|
|
// ** for that virtual table.
|
|
// */
|
|
func _sqlite3IsShadowTableOf(tls *libc.TLS, db uintptr, pTab uintptr, zName uintptr) (r int32) {
|
|
var nName int32
|
|
var pMod uintptr
|
|
_, _ = nName, pMod /* Module for the virtual table */
|
|
if !(libc.Int32FromUint8((*TTable)(unsafe.Pointer(pTab)).FeTabType) == libc.Int32FromInt32(TABTYP_VTAB)) {
|
|
return 0
|
|
}
|
|
nName = _sqlite3Strlen30(tls, (*TTable)(unsafe.Pointer(pTab)).FzName)
|
|
if Xsqlite3_strnicmp(tls, zName, (*TTable)(unsafe.Pointer(pTab)).FzName, nName) != 0 {
|
|
return 0
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zName + uintptr(nName)))) != int32('_') {
|
|
return 0
|
|
}
|
|
pMod = _sqlite3HashFind(tls, db+576, **(**uintptr)(__ccgo_up((*(*struct {
|
|
FnArg int32
|
|
FazArg uintptr
|
|
Fp uintptr
|
|
})(unsafe.Pointer(pTab + 64))).FazArg)))
|
|
if pMod == uintptr(0) {
|
|
return 0
|
|
}
|
|
if (*Tsqlite3_module)(unsafe.Pointer((*TModule)(unsafe.Pointer(pMod)).FpModule)).FiVersion < int32(3) {
|
|
return 0
|
|
}
|
|
if (*Tsqlite3_module)(unsafe.Pointer((*TModule)(unsafe.Pointer(pMod)).FpModule)).FxShadowName == uintptr(0) {
|
|
return 0
|
|
}
|
|
return (*(*func(*libc.TLS, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{(*Tsqlite3_module)(unsafe.Pointer((*TModule)(unsafe.Pointer(pMod)).FpModule)).FxShadowName})))(tls, zName+uintptr(nName)+uintptr(1))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Table pTab is a virtual table. If it the virtual table implementation
|
|
// ** exists and has an xShadowName method, then loop over all other ordinary
|
|
// ** tables within the same schema looking for shadow tables of pTab, and mark
|
|
// ** any shadow tables seen using the TF_Shadow flag.
|
|
// */
|
|
func _sqlite3MarkAllShadowTablesOf(tls *libc.TLS, db uintptr, pTab uintptr) {
|
|
var k, pMod, pOther uintptr
|
|
var nName int32
|
|
_, _, _, _ = k, nName, pMod, pOther /* For looping through the symbol table */
|
|
pMod = _sqlite3HashFind(tls, db+576, **(**uintptr)(__ccgo_up((*(*struct {
|
|
FnArg int32
|
|
FazArg uintptr
|
|
Fp uintptr
|
|
})(unsafe.Pointer(pTab + 64))).FazArg)))
|
|
if pMod == uintptr(0) {
|
|
return
|
|
}
|
|
if (*TModule)(unsafe.Pointer(pMod)).FpModule == uintptr(0) {
|
|
return
|
|
}
|
|
if (*Tsqlite3_module)(unsafe.Pointer((*TModule)(unsafe.Pointer(pMod)).FpModule)).FiVersion < int32(3) {
|
|
return
|
|
}
|
|
if (*Tsqlite3_module)(unsafe.Pointer((*TModule)(unsafe.Pointer(pMod)).FpModule)).FxShadowName == uintptr(0) {
|
|
return
|
|
}
|
|
nName = _sqlite3Strlen30(tls, (*TTable)(unsafe.Pointer(pTab)).FzName)
|
|
k = (*THash)(unsafe.Pointer((*TTable)(unsafe.Pointer(pTab)).FpSchema + 8)).Ffirst
|
|
for {
|
|
if !(k != 0) {
|
|
break
|
|
}
|
|
pOther = (*THashElem)(unsafe.Pointer(k)).Fdata
|
|
if !(libc.Int32FromUint8((*TTable)(unsafe.Pointer(pOther)).FeTabType) == libc.Int32FromInt32(TABTYP_NORM)) {
|
|
goto _1
|
|
}
|
|
if (*TTable)(unsafe.Pointer(pOther)).FtabFlags&uint32(TF_Shadow) != 0 {
|
|
goto _1
|
|
}
|
|
if Xsqlite3_strnicmp(tls, (*TTable)(unsafe.Pointer(pOther)).FzName, (*TTable)(unsafe.Pointer(pTab)).FzName, nName) == 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up((*TTable)(unsafe.Pointer(pOther)).FzName + uintptr(nName)))) == int32('_') && (*(*func(*libc.TLS, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{(*Tsqlite3_module)(unsafe.Pointer((*TModule)(unsafe.Pointer(pMod)).FpModule)).FxShadowName})))(tls, (*TTable)(unsafe.Pointer(pOther)).FzName+uintptr(nName)+uintptr(1)) != 0 {
|
|
**(**Tu32)(__ccgo_up(pOther + 48)) |= uint32(TF_Shadow)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
k = (*THashElem)(unsafe.Pointer(k)).Fnext
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Run the parser and code generator recursively in order to generate
|
|
// ** code for the SQL statement given onto the end of the pParse context
|
|
// ** currently under construction. Notes:
|
|
// **
|
|
// ** * The final OP_Halt is not appended and other initialization
|
|
// ** and finalization steps are omitted because those are handling by the
|
|
// ** outermost parser.
|
|
// **
|
|
// ** * Built-in SQL functions always take precedence over application-defined
|
|
// ** SQL functions. In other words, it is not possible to override a
|
|
// ** built-in function.
|
|
// */
|
|
func _sqlite3NestedParse(tls *libc.TLS, pParse uintptr, zFormat uintptr, va uintptr) {
|
|
bp := tls.Alloc(144)
|
|
defer tls.Free(144)
|
|
var ap Tva_list
|
|
var db, zSql uintptr
|
|
var savedDbFlags Tu32
|
|
var _ /* saveBuf at bp+0 */ [136]uint8
|
|
_, _, _, _ = ap, db, savedDbFlags, zSql
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
savedDbFlags = (*Tsqlite3)(unsafe.Pointer(db)).FmDbFlags
|
|
if (*TParse)(unsafe.Pointer(pParse)).FnErr != 0 {
|
|
return
|
|
}
|
|
if (*TParse)(unsafe.Pointer(pParse)).FeParseMode != 0 {
|
|
return
|
|
}
|
|
/* Nesting should only be of limited depth */
|
|
ap = va
|
|
zSql = _sqlite3VMPrintf(tls, db, zFormat, ap)
|
|
_ = ap
|
|
if zSql == uintptr(0) {
|
|
/* This can result either from an OOM or because the formatted string
|
|
** exceeds SQLITE_LIMIT_LENGTH. In the latter case, we need to set
|
|
** an error */
|
|
if !((*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0) {
|
|
(*TParse)(unsafe.Pointer(pParse)).Frc = int32(SQLITE_TOOBIG)
|
|
}
|
|
(*TParse)(unsafe.Pointer(pParse)).FnErr = (*TParse)(unsafe.Pointer(pParse)).FnErr + 1
|
|
return
|
|
}
|
|
(*TParse)(unsafe.Pointer(pParse)).Fnested = (*TParse)(unsafe.Pointer(pParse)).Fnested + 1
|
|
libc.Xmemcpy(tls, bp, pParse+uintptr(uint64(libc.UintptrFromInt32(0)+288)), libc.Uint64FromInt64(424)-uint64(libc.UintptrFromInt32(0)+288))
|
|
libc.Xmemset(tls, pParse+uintptr(uint64(libc.UintptrFromInt32(0)+288)), 0, libc.Uint64FromInt64(424)-uint64(libc.UintptrFromInt32(0)+288))
|
|
**(**Tu32)(__ccgo_up(db + 44)) |= uint32(DBFLAG_PreferBuiltin)
|
|
_sqlite3RunParser(tls, pParse, zSql)
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FmDbFlags = savedDbFlags
|
|
_sqlite3DbFree(tls, db, zSql)
|
|
libc.Xmemcpy(tls, pParse+uintptr(uint64(libc.UintptrFromInt32(0)+288)), bp, libc.Uint64FromInt64(424)-uint64(libc.UintptrFromInt32(0)+288))
|
|
(*TParse)(unsafe.Pointer(pParse)).Fnested = (*TParse)(unsafe.Pointer(pParse)).Fnested - 1
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is used to allocate and populate UnpackedRecord
|
|
// ** structures intended to be compared against sample index keys stored
|
|
// ** in the sqlite_stat4 table.
|
|
// **
|
|
// ** A single call to this function populates zero or more fields of the
|
|
// ** record starting with field iVal (fields are numbered from left to
|
|
// ** right starting with 0). A single field is populated if:
|
|
// **
|
|
// ** * (pExpr==0). In this case the value is assumed to be an SQL NULL,
|
|
// **
|
|
// ** * The expression is a bound variable, and this is a reprepare, or
|
|
// **
|
|
// ** * The sqlite3ValueFromExpr() function is able to extract a value
|
|
// ** from the expression (i.e. the expression is a literal value).
|
|
// **
|
|
// ** Or, if pExpr is a TK_VECTOR, one field is populated for each of the
|
|
// ** vector components that match either of the two latter criteria listed
|
|
// ** above.
|
|
// **
|
|
// ** Before any value is appended to the record, the affinity of the
|
|
// ** corresponding column within index pIdx is applied to it. Before
|
|
// ** this function returns, output parameter *pnExtract is set to the
|
|
// ** number of values appended to the record.
|
|
// **
|
|
// ** When this function is called, *ppRec must either point to an object
|
|
// ** allocated by an earlier call to this function, or must be NULL. If it
|
|
// ** is NULL and a value can be successfully extracted, a new UnpackedRecord
|
|
// ** is allocated (and *ppRec set to point to it) before returning.
|
|
// **
|
|
// ** Unless an error is encountered, SQLITE_OK is returned. It is not an
|
|
// ** error if a value cannot be extracted from pExpr. If an error does
|
|
// ** occur, an SQLite error code is returned.
|
|
// */
|
|
func _sqlite3Stat4ProbeSetValue(tls *libc.TLS, pParse uintptr, pIdx uintptr, ppRec uintptr, pExpr uintptr, nElem int32, iVal int32, pnExtract uintptr) (r int32) {
|
|
bp := tls.Alloc(48)
|
|
defer tls.Free(48)
|
|
var aff Tu8
|
|
var i, nExtract, rc int32
|
|
var pElem, v2 uintptr
|
|
var _ /* alloc at bp+0 */ TValueNewStat4Ctx
|
|
var _ /* pVal at bp+32 */ uintptr
|
|
_, _, _, _, _, _ = aff, i, nExtract, pElem, rc, v2
|
|
rc = SQLITE_OK
|
|
nExtract = 0
|
|
if pExpr == uintptr(0) || libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) != int32(TK_SELECT) {
|
|
(**(**TValueNewStat4Ctx)(__ccgo_up(bp))).FpParse = pParse
|
|
(**(**TValueNewStat4Ctx)(__ccgo_up(bp))).FpIdx = pIdx
|
|
(**(**TValueNewStat4Ctx)(__ccgo_up(bp))).FppRec = ppRec
|
|
i = 0
|
|
for {
|
|
if !(i < nElem) {
|
|
break
|
|
}
|
|
**(**uintptr)(__ccgo_up(bp + 32)) = uintptr(0)
|
|
if pExpr != 0 {
|
|
v2 = _sqlite3VectorFieldSubexpr(tls, pExpr, i)
|
|
} else {
|
|
v2 = uintptr(0)
|
|
}
|
|
pElem = v2
|
|
aff = _sqlite3IndexColumnAffinity(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pIdx, iVal+i)
|
|
(**(**TValueNewStat4Ctx)(__ccgo_up(bp))).FiVal = iVal + i
|
|
rc = _stat4ValueFromExpr(tls, pParse, pElem, aff, bp, bp+32)
|
|
if !(**(**uintptr)(__ccgo_up(bp + 32)) != 0) {
|
|
break
|
|
}
|
|
nExtract = nExtract + 1
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
**(**int32)(__ccgo_up(pnExtract)) = nExtract
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Compute an affinity string for a table. Space is obtained
|
|
// ** from sqlite3DbMalloc(). The caller is responsible for freeing
|
|
// ** the space when done.
|
|
// */
|
|
func _sqlite3TableAffinityStr(tls *libc.TLS, db uintptr, pTab uintptr) (r uintptr) {
|
|
var i, j, v2, v3 int32
|
|
var zColAff uintptr
|
|
_, _, _, _, _ = i, j, zColAff, v2, v3
|
|
zColAff = _sqlite3DbMallocRaw(tls, db, libc.Uint64FromInt32(int32((*TTable)(unsafe.Pointer(pTab)).FnCol)+int32(1)))
|
|
if zColAff != 0 {
|
|
v2 = libc.Int32FromInt32(0)
|
|
j = v2
|
|
i = v2
|
|
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_VIRTUAL) == 0 {
|
|
v3 = j
|
|
j = j + 1
|
|
**(**uint8)(__ccgo_up(zColAff + uintptr(v3))) = (**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(i)*16))).Faffinity
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
for cond := true; cond; cond = j >= 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zColAff + uintptr(j)))) <= int32(SQLITE_AFF_BLOB) {
|
|
v2 = j
|
|
j = j - 1
|
|
**(**uint8)(__ccgo_up(zColAff + uintptr(v2))) = uint8(0)
|
|
}
|
|
}
|
|
return zColAff
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the affinity character for a single column of a table.
|
|
// */
|
|
func _sqlite3TableColumnAffinity(tls *libc.TLS, pTab uintptr, iCol int32) (r uint8) {
|
|
if iCol < 0 || iCol >= int32((*TTable)(unsafe.Pointer(pTab)).FnCol) {
|
|
return uint8(SQLITE_AFF_INTEGER)
|
|
}
|
|
return (**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(iCol)*16))).Faffinity
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Add a new name/number pair to a VList. This might require that the
|
|
// ** VList object be reallocated, so return the new VList. If an OOM
|
|
// ** error occurs, the original VList returned and the
|
|
// ** db->mallocFailed flag is set.
|
|
// **
|
|
// ** A VList is really just an array of integers. To destroy a VList,
|
|
// ** simply pass it to sqlite3DbFree().
|
|
// **
|
|
// ** The first integer is the number of integers allocated for the whole
|
|
// ** VList. The second integer is the number of integers actually used.
|
|
// ** Each name/number pair is encoded by subsequent groups of 3 or more
|
|
// ** integers.
|
|
// **
|
|
// ** Each name/number pair starts with two integers which are the numeric
|
|
// ** value for the pair and the size of the name/number pair, respectively.
|
|
// ** The text name overlays one or more following integers. The text name
|
|
// ** is always zero-terminated.
|
|
// **
|
|
// ** Conceptually:
|
|
// **
|
|
// ** struct VList {
|
|
// ** int nAlloc; // Number of allocated slots
|
|
// ** int nUsed; // Number of used slots
|
|
// ** struct VListEntry {
|
|
// ** int iValue; // Value for this entry
|
|
// ** int nSlot; // Slots used by this entry
|
|
// ** // ... variable name goes here
|
|
// ** } a[0];
|
|
// ** }
|
|
// **
|
|
// ** During code generation, pointers to the variable names within the
|
|
// ** VList are taken. When that happens, nAlloc is set to zero as an
|
|
// ** indication that the VList may never again be enlarged, since the
|
|
// ** accompanying realloc() would invalidate the pointers.
|
|
// */
|
|
func _sqlite3VListAdd(tls *libc.TLS, db uintptr, pIn uintptr, zName uintptr, nName int32, iVal int32) (r uintptr) {
|
|
var i, nInt int32
|
|
var nAlloc Tsqlite3_int64
|
|
var pOut, z uintptr
|
|
var v1 int64
|
|
_, _, _, _, _, _ = i, nAlloc, nInt, pOut, z, v1 /* Index in pIn[] where zName is stored */
|
|
nInt = nName/int32(4) + int32(3)
|
|
/* Verify ok to add new elements */
|
|
if pIn == uintptr(0) || **(**TVList)(__ccgo_up(pIn + 1*4))+nInt > **(**TVList)(__ccgo_up(pIn)) {
|
|
if pIn != 0 {
|
|
v1 = int64(2) * int64(**(**TVList)(__ccgo_up(pIn)))
|
|
} else {
|
|
v1 = int64(10)
|
|
}
|
|
/* Enlarge the allocation */
|
|
nAlloc = v1 + int64(nInt)
|
|
pOut = _sqlite3DbRealloc(tls, db, pIn, libc.Uint64FromInt64(nAlloc)*uint64(4))
|
|
if pOut == uintptr(0) {
|
|
return pIn
|
|
}
|
|
if pIn == uintptr(0) {
|
|
**(**TVList)(__ccgo_up(pOut + 1*4)) = int32(2)
|
|
}
|
|
pIn = pOut
|
|
**(**TVList)(__ccgo_up(pIn)) = int32(nAlloc)
|
|
}
|
|
i = **(**TVList)(__ccgo_up(pIn + 1*4))
|
|
**(**TVList)(__ccgo_up(pIn + uintptr(i)*4)) = iVal
|
|
**(**TVList)(__ccgo_up(pIn + uintptr(i+int32(1))*4)) = nInt
|
|
z = pIn + uintptr(i+int32(2))*4
|
|
**(**TVList)(__ccgo_up(pIn + 1*4)) = i + nInt
|
|
libc.Xmemcpy(tls, z, zName, libc.Uint64FromInt32(nName))
|
|
**(**uint8)(__ccgo_up(z + uintptr(nName))) = uint8(0)
|
|
return pIn
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the number of the variable named zName, if it is in VList.
|
|
// ** or return 0 if there is no such variable.
|
|
// */
|
|
func _sqlite3VListNameToNum(tls *libc.TLS, pIn uintptr, zName uintptr, nName int32) (r int32) {
|
|
var i, mx int32
|
|
var z uintptr
|
|
_, _, _ = i, mx, z
|
|
if pIn == uintptr(0) {
|
|
return 0
|
|
}
|
|
mx = **(**TVList)(__ccgo_up(pIn + 1*4))
|
|
i = int32(2)
|
|
for cond := true; cond; cond = i < mx {
|
|
z = pIn + uintptr(i+int32(2))*4
|
|
if libc.Xstrncmp(tls, z, zName, libc.Uint64FromInt32(nName)) == 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(nName)))) == 0 {
|
|
return **(**TVList)(__ccgo_up(pIn + uintptr(i)*4))
|
|
}
|
|
i = i + **(**TVList)(__ccgo_up(pIn + uintptr(i+int32(1))*4))
|
|
}
|
|
return 0
|
|
}
|
|
|
|
/************** End of util.c ************************************************/
|
|
/************** Begin file hash.c ********************************************/
|
|
/*
|
|
** 2001 September 22
|
|
**
|
|
** 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 is the implementation of generic hash-tables
|
|
** used in SQLite.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
/* #include <assert.h> */
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Print into memory obtained from sqliteMalloc(). Use the internal
|
|
// ** %-conversion extensions.
|
|
// */
|
|
func _sqlite3VMPrintf(tls *libc.TLS, db uintptr, zFormat uintptr, ap Tva_list) (r uintptr) {
|
|
bp := tls.Alloc(112)
|
|
defer tls.Free(112)
|
|
var z uintptr
|
|
var _ /* acc at bp+72 */ TStrAccum
|
|
var _ /* zBase at bp+0 */ [70]uint8
|
|
_ = z
|
|
_sqlite3StrAccumInit(tls, bp+72, db, bp, int32(70), **(**int32)(__ccgo_up(db + 136)))
|
|
(**(**TStrAccum)(__ccgo_up(bp + 72))).FprintfFlags = uint8(SQLITE_PRINTF_INTERNAL)
|
|
Xsqlite3_str_vappendf(tls, bp+72, zFormat, ap)
|
|
z = _sqlite3StrAccumFinish(tls, bp+72)
|
|
if libc.Int32FromUint8((**(**TStrAccum)(__ccgo_up(bp + 72))).FaccError) == int32(SQLITE_NOMEM) {
|
|
_sqlite3OomFault(tls, db)
|
|
}
|
|
return z
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This routine checks for a byte-order mark at the beginning of the
|
|
// ** UTF-16 string stored in *pMem. If one is present, it is removed and
|
|
// ** the encoding of the Mem adjusted. This routine does not do any
|
|
// ** byte-swapping, it just sets Mem.enc appropriately.
|
|
// **
|
|
// ** The allocation (static, dynamic etc.) and encoding of the Mem may be
|
|
// ** changed by this function.
|
|
// */
|
|
func _sqlite3VdbeMemHandleBom(tls *libc.TLS, pMem uintptr) (r int32) {
|
|
var b1, b2, bom Tu8
|
|
var rc int32
|
|
var v1 uintptr
|
|
_, _, _, _, _ = b1, b2, bom, rc, v1
|
|
rc = SQLITE_OK
|
|
bom = uint8(0)
|
|
if (*TMem)(unsafe.Pointer(pMem)).Fn > int32(1) {
|
|
b1 = **(**Tu8)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fz))
|
|
b2 = **(**Tu8)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fz + libc.UintptrFromInt32(1)))
|
|
if libc.Int32FromUint8(b1) == int32(0xFE) && libc.Int32FromUint8(b2) == int32(0xFF) {
|
|
bom = uint8(SQLITE_UTF16BE)
|
|
}
|
|
if libc.Int32FromUint8(b1) == int32(0xFF) && libc.Int32FromUint8(b2) == int32(0xFE) {
|
|
bom = uint8(SQLITE_UTF16LE)
|
|
}
|
|
}
|
|
if bom != 0 {
|
|
rc = _sqlite3VdbeMemMakeWriteable(tls, pMem)
|
|
if rc == SQLITE_OK {
|
|
**(**int32)(__ccgo_up(pMem + 16)) -= int32(2)
|
|
libc.Xmemmove(tls, (*TMem)(unsafe.Pointer(pMem)).Fz, (*TMem)(unsafe.Pointer(pMem)).Fz+2, libc.Uint64FromInt32((*TMem)(unsafe.Pointer(pMem)).Fn))
|
|
**(**uint8)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fz + uintptr((*TMem)(unsafe.Pointer(pMem)).Fn))) = uint8('\000')
|
|
**(**uint8)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fz + uintptr((*TMem)(unsafe.Pointer(pMem)).Fn+int32(1)))) = uint8('\000')
|
|
v1 = pMem + 20
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(MEM_Term))
|
|
(*TMem)(unsafe.Pointer(pMem)).Fenc = bom
|
|
}
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Change the value of a Mem to be a string or a BLOB.
|
|
// **
|
|
// ** The memory management strategy depends on the value of the xDel
|
|
// ** parameter. If the value passed is SQLITE_TRANSIENT, then the
|
|
// ** string is copied into a (possibly existing) buffer managed by the
|
|
// ** Mem structure. Otherwise, any existing buffer is freed and the
|
|
// ** pointer copied.
|
|
// **
|
|
// ** If the string is too large (if it exceeds the SQLITE_LIMIT_LENGTH
|
|
// ** size limit) then no memory allocation occurs. If the string can be
|
|
// ** stored without allocating memory, then it is. If a memory allocation
|
|
// ** is required to store the string, then value of pMem is unchanged. In
|
|
// ** either case, SQLITE_TOOBIG is returned.
|
|
// **
|
|
// ** The "enc" parameter is the text encoding for the string, or zero
|
|
// ** to store a blob.
|
|
// **
|
|
// ** If n is negative, then the string consists of all bytes up to but
|
|
// ** excluding the first zero character. The n parameter must be
|
|
// ** non-negative for blobs.
|
|
// */
|
|
func _sqlite3VdbeMemSetStr(tls *libc.TLS, pMem uintptr, z uintptr, n Ti64, enc Tu8, __ccgo_fp_xDel uintptr) (r int32) {
|
|
var flags Tu16
|
|
var iLimit, v2 int32
|
|
var nAlloc, nByte Ti64
|
|
var v3 int64
|
|
_, _, _, _, _, _ = flags, iLimit, nAlloc, nByte, v2, v3
|
|
nByte = n /* New value for pMem->flags */
|
|
/* If z is a NULL pointer, set pMem to contain an SQL NULL. */
|
|
if !(z != 0) {
|
|
_sqlite3VdbeMemSetNull(tls, pMem)
|
|
return SQLITE_OK
|
|
}
|
|
if (*TMem)(unsafe.Pointer(pMem)).Fdb != 0 {
|
|
iLimit = **(**int32)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fdb + 136))
|
|
} else {
|
|
iLimit = int32(SQLITE_MAX_LENGTH)
|
|
}
|
|
if nByte < 0 {
|
|
if libc.Int32FromUint8(enc) == int32(SQLITE_UTF8) {
|
|
nByte = libc.Int64FromUint64(libc.Xstrlen(tls, z))
|
|
} else {
|
|
nByte = 0
|
|
for {
|
|
if !(nByte <= int64(iLimit) && libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(nByte))))|libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(nByte+int64(1))))) != 0) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
nByte = nByte + int64(2)
|
|
}
|
|
}
|
|
flags = libc.Uint16FromInt32(libc.Int32FromInt32(MEM_Str) | libc.Int32FromInt32(MEM_Term))
|
|
} else {
|
|
if libc.Int32FromUint8(enc) == 0 {
|
|
flags = uint16(MEM_Blob)
|
|
enc = uint8(SQLITE_UTF8)
|
|
} else {
|
|
flags = uint16(MEM_Str)
|
|
}
|
|
}
|
|
if nByte > int64(iLimit) {
|
|
if __ccgo_fp_xDel != 0 && __ccgo_fp_xDel != uintptr(-libc.Int32FromInt32(1)) {
|
|
if __ccgo_fp_xDel == __ccgo_fp(_sqlite3RowSetClear) {
|
|
_sqlite3DbFree(tls, (*TMem)(unsafe.Pointer(pMem)).Fdb, z)
|
|
} else {
|
|
(*(*func(*libc.TLS, uintptr))(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xDel})))(tls, z)
|
|
}
|
|
}
|
|
_sqlite3VdbeMemSetNull(tls, pMem)
|
|
return _sqlite3ErrorToParser(tls, (*TMem)(unsafe.Pointer(pMem)).Fdb, int32(SQLITE_TOOBIG))
|
|
}
|
|
/* The following block sets the new values of Mem.z and Mem.xDel. It
|
|
** also sets a flag in local variable "flags" to indicate the memory
|
|
** management (one of MEM_Dyn or MEM_Static).
|
|
*/
|
|
if __ccgo_fp_xDel == uintptr(-libc.Int32FromInt32(1)) {
|
|
nAlloc = nByte
|
|
if libc.Int32FromUint16(flags)&int32(MEM_Term) != 0 {
|
|
if libc.Int32FromUint8(enc) == int32(SQLITE_UTF8) {
|
|
v2 = int32(1)
|
|
} else {
|
|
v2 = int32(2)
|
|
}
|
|
nAlloc = nAlloc + int64(v2)
|
|
}
|
|
if nAlloc > int64(libc.Int32FromInt32(32)) {
|
|
v3 = nAlloc
|
|
} else {
|
|
v3 = int64(libc.Int32FromInt32(32))
|
|
}
|
|
if _sqlite3VdbeMemClearAndResize(tls, pMem, int32(v3)) != 0 {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
libc.Xmemcpy(tls, (*TMem)(unsafe.Pointer(pMem)).Fz, z, libc.Uint64FromInt64(nAlloc))
|
|
} else {
|
|
_sqlite3VdbeMemRelease(tls, pMem)
|
|
(*TMem)(unsafe.Pointer(pMem)).Fz = z
|
|
if __ccgo_fp_xDel == __ccgo_fp(_sqlite3RowSetClear) {
|
|
(*TMem)(unsafe.Pointer(pMem)).FzMalloc = (*TMem)(unsafe.Pointer(pMem)).Fz
|
|
(*TMem)(unsafe.Pointer(pMem)).FszMalloc = _sqlite3DbMallocSize(tls, (*TMem)(unsafe.Pointer(pMem)).Fdb, (*TMem)(unsafe.Pointer(pMem)).FzMalloc)
|
|
} else {
|
|
(*TMem)(unsafe.Pointer(pMem)).FxDel = __ccgo_fp_xDel
|
|
if __ccgo_fp_xDel == libc.UintptrFromInt32(0) {
|
|
v2 = int32(MEM_Static)
|
|
} else {
|
|
v2 = int32(MEM_Dyn)
|
|
}
|
|
flags = libc.Uint16FromInt32(int32(flags) | v2)
|
|
}
|
|
}
|
|
(*TMem)(unsafe.Pointer(pMem)).Fn = int32(nByte & libc.Int64FromInt32(0x7fffffff))
|
|
(*TMem)(unsafe.Pointer(pMem)).Fflags = flags
|
|
(*TMem)(unsafe.Pointer(pMem)).Fenc = enc
|
|
if libc.Int32FromUint8(enc) > int32(SQLITE_UTF8) && _sqlite3VdbeMemHandleBom(tls, pMem) != 0 {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Like sqlite3VdbeMemSetStr() except:
|
|
// **
|
|
// ** enc is always SQLITE_UTF8
|
|
// ** pMem->db is always non-NULL
|
|
// */
|
|
func _sqlite3VdbeMemSetText(tls *libc.TLS, pMem uintptr, z uintptr, n Ti64, __ccgo_fp_xDel uintptr) (r int32) {
|
|
var flags Tu16
|
|
var nAlloc, nByte Ti64
|
|
var v1 int64
|
|
_, _, _, _ = flags, nAlloc, nByte, v1
|
|
nByte = n
|
|
/* If z is a NULL pointer, set pMem to contain an SQL NULL. */
|
|
if !(z != 0) {
|
|
_sqlite3VdbeMemSetNull(tls, pMem)
|
|
return SQLITE_OK
|
|
}
|
|
if nByte < 0 {
|
|
nByte = libc.Int64FromUint64(libc.Xstrlen(tls, z))
|
|
flags = libc.Uint16FromInt32(libc.Int32FromInt32(MEM_Str) | libc.Int32FromInt32(MEM_Term))
|
|
} else {
|
|
flags = uint16(MEM_Str)
|
|
}
|
|
if nByte > int64(**(**int32)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fdb + 136))) {
|
|
if __ccgo_fp_xDel != 0 && __ccgo_fp_xDel != uintptr(-libc.Int32FromInt32(1)) {
|
|
if __ccgo_fp_xDel == __ccgo_fp(_sqlite3RowSetClear) {
|
|
_sqlite3DbFree(tls, (*TMem)(unsafe.Pointer(pMem)).Fdb, z)
|
|
} else {
|
|
(*(*func(*libc.TLS, uintptr))(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xDel})))(tls, z)
|
|
}
|
|
}
|
|
_sqlite3VdbeMemSetNull(tls, pMem)
|
|
return _sqlite3ErrorToParser(tls, (*TMem)(unsafe.Pointer(pMem)).Fdb, int32(SQLITE_TOOBIG))
|
|
}
|
|
/* The following block sets the new values of Mem.z and Mem.xDel. It
|
|
** also sets a flag in local variable "flags" to indicate the memory
|
|
** management (one of MEM_Dyn or MEM_Static).
|
|
*/
|
|
if __ccgo_fp_xDel == uintptr(-libc.Int32FromInt32(1)) {
|
|
nAlloc = nByte + int64(1)
|
|
if nAlloc > int64(libc.Int32FromInt32(32)) {
|
|
v1 = nAlloc
|
|
} else {
|
|
v1 = int64(libc.Int32FromInt32(32))
|
|
}
|
|
if _sqlite3VdbeMemClearAndResize(tls, pMem, int32(v1)) != 0 {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
libc.Xmemcpy(tls, (*TMem)(unsafe.Pointer(pMem)).Fz, z, libc.Uint64FromInt64(nByte))
|
|
**(**uint8)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fz + uintptr(nByte))) = uint8(0)
|
|
} else {
|
|
_sqlite3VdbeMemRelease(tls, pMem)
|
|
(*TMem)(unsafe.Pointer(pMem)).Fz = z
|
|
if __ccgo_fp_xDel == __ccgo_fp(_sqlite3RowSetClear) {
|
|
(*TMem)(unsafe.Pointer(pMem)).FzMalloc = (*TMem)(unsafe.Pointer(pMem)).Fz
|
|
(*TMem)(unsafe.Pointer(pMem)).FszMalloc = _sqlite3DbMallocSize(tls, (*TMem)(unsafe.Pointer(pMem)).Fdb, (*TMem)(unsafe.Pointer(pMem)).FzMalloc)
|
|
(*TMem)(unsafe.Pointer(pMem)).FxDel = uintptr(0)
|
|
} else {
|
|
if __ccgo_fp_xDel == libc.UintptrFromInt32(0) {
|
|
(*TMem)(unsafe.Pointer(pMem)).FxDel = __ccgo_fp_xDel
|
|
flags = libc.Uint16FromInt32(int32(flags) | libc.Int32FromInt32(MEM_Static))
|
|
} else {
|
|
(*TMem)(unsafe.Pointer(pMem)).FxDel = __ccgo_fp_xDel
|
|
flags = libc.Uint16FromInt32(int32(flags) | libc.Int32FromInt32(MEM_Dyn))
|
|
}
|
|
}
|
|
}
|
|
(*TMem)(unsafe.Pointer(pMem)).Fflags = flags
|
|
(*TMem)(unsafe.Pointer(pMem)).Fn = int32(nByte & libc.Int64FromInt32(0x7fffffff))
|
|
(*TMem)(unsafe.Pointer(pMem)).Fenc = uint8(SQLITE_UTF8)
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If pMem is already a string, detect if it is a zero-terminated
|
|
// ** string, or make it into one if possible, and mark it as such.
|
|
// **
|
|
// ** This is an optimization. Correct operation continues even if
|
|
// ** this routine is a no-op.
|
|
// **
|
|
// ** Return true if the strig is zero-terminated after this routine is
|
|
// ** called and false if it is not.
|
|
// */
|
|
func _sqlite3VdbeMemZeroTerminateIfAble(tls *libc.TLS, pMem uintptr) (r int32) {
|
|
var v1 uintptr
|
|
_ = v1
|
|
if libc.Int32FromUint16((*TMem)(unsafe.Pointer(pMem)).Fflags)&(libc.Int32FromInt32(MEM_Str)|libc.Int32FromInt32(MEM_Term)|libc.Int32FromInt32(MEM_Ephem)|libc.Int32FromInt32(MEM_Static)) != int32(MEM_Str) {
|
|
/* pMem must be a string, and it cannot be an ephemeral or static string */
|
|
return 0
|
|
}
|
|
if libc.Int32FromUint8((*TMem)(unsafe.Pointer(pMem)).Fenc) != int32(SQLITE_UTF8) {
|
|
return 0
|
|
}
|
|
if libc.Int32FromUint16((*TMem)(unsafe.Pointer(pMem)).Fflags)&int32(MEM_Dyn) != 0 {
|
|
if (*TMem)(unsafe.Pointer(pMem)).FxDel == __ccgo_fp(Xsqlite3_free) && Xsqlite3_msize(tls, (*TMem)(unsafe.Pointer(pMem)).Fz) >= libc.Uint64FromInt32((*TMem)(unsafe.Pointer(pMem)).Fn+libc.Int32FromInt32(1)) {
|
|
**(**uint8)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fz + uintptr((*TMem)(unsafe.Pointer(pMem)).Fn))) = uint8(0)
|
|
v1 = pMem + 20
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(MEM_Term))
|
|
return int32(1)
|
|
}
|
|
if (*TMem)(unsafe.Pointer(pMem)).FxDel == __ccgo_fp(_sqlite3RCStrUnref) {
|
|
/* Blindly assume that all RCStr objects are zero-terminated */
|
|
v1 = pMem + 20
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(MEM_Term))
|
|
return int32(1)
|
|
}
|
|
} else {
|
|
if (*TMem)(unsafe.Pointer(pMem)).FszMalloc >= (*TMem)(unsafe.Pointer(pMem)).Fn+int32(1) {
|
|
**(**uint8)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fz + uintptr((*TMem)(unsafe.Pointer(pMem)).Fn))) = uint8(0)
|
|
v1 = pMem + 20
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(MEM_Term))
|
|
return int32(1)
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This is called by code in select.c before it calls sqlite3WhereBegin()
|
|
// ** to begin iterating through the sub-query results. It is used to allocate
|
|
// ** and initialize registers and cursors used by sqlite3WindowCodeStep().
|
|
// */
|
|
func _sqlite3WindowCodeInit(tls *libc.TLS, pParse uintptr, pSelect uintptr) {
|
|
var nEphExpr, nExpr, v1 int32
|
|
var p, pKeyInfo, pList, pMWin, pWin, v, v2 uintptr
|
|
_, _, _, _, _, _, _, _, _, _ = nEphExpr, nExpr, p, pKeyInfo, pList, pMWin, pWin, v, v1, v2
|
|
nEphExpr = (*TExprList)(unsafe.Pointer((*TSelect)(unsafe.Pointer((*TSubquery)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pSelect)).FpSrc + 8 + 72)))).FpSelect)).FpEList)).FnExpr
|
|
pMWin = (*TSelect)(unsafe.Pointer(pSelect)).FpWin
|
|
v = _sqlite3GetVdbe(tls, pParse)
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_OpenEphemeral), (*TWindow)(unsafe.Pointer(pMWin)).FiEphCsr, nEphExpr)
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_OpenDup), (*TWindow)(unsafe.Pointer(pMWin)).FiEphCsr+int32(1), (*TWindow)(unsafe.Pointer(pMWin)).FiEphCsr)
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_OpenDup), (*TWindow)(unsafe.Pointer(pMWin)).FiEphCsr+int32(2), (*TWindow)(unsafe.Pointer(pMWin)).FiEphCsr)
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_OpenDup), (*TWindow)(unsafe.Pointer(pMWin)).FiEphCsr+int32(3), (*TWindow)(unsafe.Pointer(pMWin)).FiEphCsr)
|
|
/* Allocate registers to use for PARTITION BY values, if any. Initialize
|
|
** said registers to NULL. */
|
|
if (*TWindow)(unsafe.Pointer(pMWin)).FpPartition != 0 {
|
|
nExpr = (*TExprList)(unsafe.Pointer((*TWindow)(unsafe.Pointer(pMWin)).FpPartition)).FnExpr
|
|
(*TWindow)(unsafe.Pointer(pMWin)).FregPart = (*TParse)(unsafe.Pointer(pParse)).FnMem + int32(1)
|
|
**(**int32)(__ccgo_up(pParse + 60)) += nExpr
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Null), 0, (*TWindow)(unsafe.Pointer(pMWin)).FregPart, (*TWindow)(unsafe.Pointer(pMWin)).FregPart+nExpr-int32(1))
|
|
}
|
|
v2 = pParse + 60
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
(*TWindow)(unsafe.Pointer(pMWin)).FregOne = v1
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Integer), int32(1), (*TWindow)(unsafe.Pointer(pMWin)).FregOne)
|
|
if (*TWindow)(unsafe.Pointer(pMWin)).FeExclude != 0 {
|
|
v2 = pParse + 60
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
(*TWindow)(unsafe.Pointer(pMWin)).FregStartRowid = v1
|
|
v2 = pParse + 60
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
(*TWindow)(unsafe.Pointer(pMWin)).FregEndRowid = v1
|
|
v2 = pParse + 56
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
(*TWindow)(unsafe.Pointer(pMWin)).FcsrApp = v1
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Integer), int32(1), (*TWindow)(unsafe.Pointer(pMWin)).FregStartRowid)
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Integer), 0, (*TWindow)(unsafe.Pointer(pMWin)).FregEndRowid)
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_OpenDup), (*TWindow)(unsafe.Pointer(pMWin)).FcsrApp, (*TWindow)(unsafe.Pointer(pMWin)).FiEphCsr)
|
|
return
|
|
}
|
|
pWin = pMWin
|
|
for {
|
|
if !(pWin != 0) {
|
|
break
|
|
}
|
|
p = (*TWindow)(unsafe.Pointer(pWin)).FpWFunc
|
|
if (*TFuncDef)(unsafe.Pointer(p)).FfuncFlags&uint32(SQLITE_FUNC_MINMAX) != 0 && libc.Int32FromUint8((*TWindow)(unsafe.Pointer(pWin)).FeStart) != int32(TK_UNBOUNDED) {
|
|
pList = *(*uintptr)(unsafe.Pointer((*TWindow)(unsafe.Pointer(pWin)).FpOwner + 32))
|
|
pKeyInfo = _sqlite3KeyInfoFromExprList(tls, pParse, pList, 0, 0)
|
|
v2 = pParse + 56
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
(*TWindow)(unsafe.Pointer(pWin)).FcsrApp = v1
|
|
(*TWindow)(unsafe.Pointer(pWin)).FregApp = (*TParse)(unsafe.Pointer(pParse)).FnMem + int32(1)
|
|
**(**int32)(__ccgo_up(pParse + 60)) += int32(3)
|
|
if pKeyInfo != 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up((*TFuncDef)(unsafe.Pointer((*TWindow)(unsafe.Pointer(pWin)).FpWFunc)).FzName + 1))) == int32('i') {
|
|
**(**Tu8)(__ccgo_up((*TKeyInfo)(unsafe.Pointer(pKeyInfo)).FaSortFlags)) = uint8(KEYINFO_ORDER_DESC)
|
|
}
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_OpenEphemeral), (*TWindow)(unsafe.Pointer(pWin)).FcsrApp, int32(2))
|
|
_sqlite3VdbeAppendP4(tls, v, pKeyInfo, -int32(9))
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Integer), 0, (*TWindow)(unsafe.Pointer(pWin)).FregApp+int32(1))
|
|
} else {
|
|
if (*TFuncDef)(unsafe.Pointer(p)).FzName == uintptr(unsafe.Pointer(&_nth_valueName)) || (*TFuncDef)(unsafe.Pointer(p)).FzName == uintptr(unsafe.Pointer(&_first_valueName)) {
|
|
/* Allocate two registers at pWin->regApp. These will be used to
|
|
** store the start and end index of the current frame. */
|
|
(*TWindow)(unsafe.Pointer(pWin)).FregApp = (*TParse)(unsafe.Pointer(pParse)).FnMem + int32(1)
|
|
v2 = pParse + 56
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
(*TWindow)(unsafe.Pointer(pWin)).FcsrApp = v1
|
|
**(**int32)(__ccgo_up(pParse + 60)) += int32(2)
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_OpenDup), (*TWindow)(unsafe.Pointer(pWin)).FcsrApp, (*TWindow)(unsafe.Pointer(pMWin)).FiEphCsr)
|
|
} else {
|
|
if (*TFuncDef)(unsafe.Pointer(p)).FzName == uintptr(unsafe.Pointer(&_leadName)) || (*TFuncDef)(unsafe.Pointer(p)).FzName == uintptr(unsafe.Pointer(&_lagName)) {
|
|
v2 = pParse + 56
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
(*TWindow)(unsafe.Pointer(pWin)).FcsrApp = v1
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_OpenDup), (*TWindow)(unsafe.Pointer(pWin)).FcsrApp, (*TWindow)(unsafe.Pointer(pMWin)).FiEphCsr)
|
|
}
|
|
}
|
|
}
|
|
goto _9
|
|
_9:
|
|
;
|
|
pWin = (*TWindow)(unsafe.Pointer(pWin)).FpNextWin
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return TRUE if the WHERE clause term pTerm is of a form where it
|
|
// ** could be used with an index to access pSrc, assuming an appropriate
|
|
// ** index existed.
|
|
// */
|
|
func _termCanDriveIndex(tls *libc.TLS, pTerm uintptr, pSrc uintptr, notReady TBitmask) (r int32) {
|
|
var aff uint8
|
|
var leftCol int32
|
|
_, _ = aff, leftCol
|
|
if (*TWhereTerm)(unsafe.Pointer(pTerm)).FleftCursor != (*TSrcItem)(unsafe.Pointer(pSrc)).FiCursor {
|
|
return 0
|
|
}
|
|
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator)&(libc.Int32FromInt32(WO_EQ)|libc.Int32FromInt32(WO_IS)) == 0 {
|
|
return 0
|
|
}
|
|
if libc.Int32FromUint8((*TSrcItem)(unsafe.Pointer(pSrc)).Ffg.Fjointype)&(libc.Int32FromInt32(JT_LEFT)|libc.Int32FromInt32(JT_LTORJ)|libc.Int32FromInt32(JT_RIGHT)) != 0 && !(_constraintCompatibleWithOuterJoin(tls, pTerm, pSrc) != 0) {
|
|
return 0 /* See https://sqlite.org/forum/forumpost/51e6959f61 */
|
|
}
|
|
if (*TWhereTerm)(unsafe.Pointer(pTerm)).FprereqRight¬Ready != uint64(0) {
|
|
return 0
|
|
}
|
|
leftCol = (*(*struct {
|
|
FleftColumn int32
|
|
FiField int32
|
|
})(unsafe.Pointer(pTerm + 32))).FleftColumn
|
|
if leftCol < 0 {
|
|
return 0
|
|
}
|
|
aff = (**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer((*TSrcItem)(unsafe.Pointer(pSrc)).FpSTab)).FaCol + uintptr(leftCol)*16))).Faffinity
|
|
if !(_sqlite3IndexAffinityOk(tls, (*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr, aff) != 0) {
|
|
return 0
|
|
}
|
|
return _columnIsGoodIndexCandidate(tls, (*TSrcItem)(unsafe.Pointer(pSrc)).FpSTab, leftCol)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Construct a new Expr object from a single token */
|
|
func _tokenExpr(tls *libc.TLS, pParse uintptr, op int32, _t TToken) (r uintptr) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
*(*TToken)(unsafe.Pointer(bp)) = _t
|
|
var p, v1 uintptr
|
|
_, _ = p, v1
|
|
p = _sqlite3DbMallocRawNN(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, uint64(72)+uint64((**(**TToken)(__ccgo_up(bp))).Fn)+uint64(1))
|
|
if p != 0 {
|
|
/* memset(p, 0, sizeof(Expr)); */
|
|
(*TExpr)(unsafe.Pointer(p)).Fop = libc.Uint8FromInt32(op)
|
|
(*TExpr)(unsafe.Pointer(p)).FaffExpr = uint8(0)
|
|
(*TExpr)(unsafe.Pointer(p)).Fflags = uint32(EP_Leaf)
|
|
/* p->iAgg = -1; // Not required */
|
|
v1 = libc.UintptrFromInt32(0)
|
|
(*TExpr)(unsafe.Pointer(p)).FpRight = v1
|
|
(*TExpr)(unsafe.Pointer(p)).FpLeft = v1
|
|
(*TExpr)(unsafe.Pointer(p)).FpAggInfo = uintptr(0)
|
|
libc.Xmemset(tls, p+32, 0, uint64(8))
|
|
libc.Xmemset(tls, p+64, 0, uint64(8))
|
|
(*TExpr)(unsafe.Pointer(p)).Fop2 = uint8(0)
|
|
(*TExpr)(unsafe.Pointer(p)).FiTable = 0
|
|
(*TExpr)(unsafe.Pointer(p)).FiColumn = 0
|
|
*(*uintptr)(unsafe.Pointer(p + 8)) = p + 1*72
|
|
libc.Xmemcpy(tls, *(*uintptr)(unsafe.Pointer(p + 8)), (**(**TToken)(__ccgo_up(bp))).Fz, uint64((**(**TToken)(__ccgo_up(bp))).Fn))
|
|
**(**uint8)(__ccgo_up(*(*uintptr)(unsafe.Pointer(p + 8)) + uintptr((**(**TToken)(__ccgo_up(bp))).Fn))) = uint8(0)
|
|
*(*int32)(unsafe.Pointer(p + 52)) = int32(int64((**(**TToken)(__ccgo_up(bp))).Fz) - int64((*TParse)(unsafe.Pointer(pParse)).FzTail))
|
|
if libc.Int32FromUint8(_sqlite3CtypeMap[uint8(**(**uint8)(__ccgo_up(*(*uintptr)(unsafe.Pointer(p + 8)))))])&int32(0x80) != 0 {
|
|
_sqlite3DequoteExpr(tls, p)
|
|
}
|
|
(*TExpr)(unsafe.Pointer(p)).FnHeight = int32(1)
|
|
if libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= int32(PARSE_MODE_RENAME) {
|
|
return _sqlite3RenameTokenMap(tls, pParse, p, bp)
|
|
}
|
|
}
|
|
return p
|
|
}
|
|
|
|
func _unicodeSetCategories(tls *libc.TLS, p uintptr, zCat uintptr) (r int32) {
|
|
var z uintptr
|
|
_ = z
|
|
z = zCat
|
|
for **(**uint8)(__ccgo_up(z)) != 0 {
|
|
for libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) == int32(' ') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) == int32('\t') {
|
|
z = z + 1
|
|
}
|
|
if **(**uint8)(__ccgo_up(z)) != 0 && _sqlite3Fts5UnicodeCatParse(tls, z, p+160) != 0 {
|
|
return int32(SQLITE_ERROR)
|
|
}
|
|
for libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) != int32(' ') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) != int32('\t') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) != int32('\000') {
|
|
z = z + 1
|
|
}
|
|
}
|
|
_sqlite3Fts5UnicodeAscii(tls, p+160, p)
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** It is already known that pMem contains an unterminated string.
|
|
// ** Add the zero terminator.
|
|
// **
|
|
// ** Three bytes of zero are added. In this way, there is guaranteed
|
|
// ** to be a double-zero byte at an even byte boundary in order to
|
|
// ** terminate a UTF16 string, even if the initial size of the buffer
|
|
// ** is an odd number of bytes.
|
|
// */
|
|
func _vdbeMemAddTerminator(tls *libc.TLS, pMem uintptr) (r int32) {
|
|
var v1 uintptr
|
|
_ = v1
|
|
if _sqlite3VdbeMemGrow(tls, pMem, (*TMem)(unsafe.Pointer(pMem)).Fn+int32(3), int32(1)) != 0 {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
**(**uint8)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fz + uintptr((*TMem)(unsafe.Pointer(pMem)).Fn))) = uint8(0)
|
|
**(**uint8)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fz + uintptr((*TMem)(unsafe.Pointer(pMem)).Fn+int32(1)))) = uint8(0)
|
|
**(**uint8)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fz + uintptr((*TMem)(unsafe.Pointer(pMem)).Fn+int32(2)))) = uint8(0)
|
|
v1 = pMem + 20
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(MEM_Term))
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The index pIdx is used by a query and contains one or more expressions.
|
|
// ** In other words pIdx is an index on an expression. iIdxCur is the cursor
|
|
// ** number for the index and iDataCur is the cursor number for the corresponding
|
|
// ** table.
|
|
// **
|
|
// ** This routine adds IndexedExpr entries to the Parse->pIdxEpr field for
|
|
// ** each of the expressions in the index so that the expression code generator
|
|
// ** will know to replace occurrences of the indexed expression with
|
|
// ** references to the corresponding column of the index.
|
|
// */
|
|
func _whereAddIndexedExpr(tls *libc.TLS, pParse uintptr, pIdx uintptr, iIdxCur int32, pTabItem uintptr) {
|
|
var i, j int32
|
|
var p, pArg, pExpr, pTab uintptr
|
|
_, _, _, _, _, _ = i, j, p, pArg, pExpr, pTab
|
|
pTab = (*TIndex)(unsafe.Pointer(pIdx)).FpTable
|
|
i = 0
|
|
for {
|
|
if !(i < libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnColumn)) {
|
|
break
|
|
}
|
|
j = int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(i)*2)))
|
|
if j == -int32(2) {
|
|
pExpr = (*(*TExprList_item)(unsafe.Pointer((*TIndex)(unsafe.Pointer(pIdx)).FaColExpr + 8 + uintptr(i)*32))).FpExpr
|
|
} else {
|
|
if j >= 0 && libc.Int32FromUint16((**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer(pTab)).FaCol + uintptr(j)*16))).FcolFlags)&int32(COLFLAG_VIRTUAL) != 0 {
|
|
pExpr = _sqlite3ColumnExpr(tls, pTab, (*TTable)(unsafe.Pointer(pTab)).FaCol+uintptr(j)*16)
|
|
} else {
|
|
goto _1
|
|
}
|
|
}
|
|
if _sqlite3ExprIsConstant(tls, uintptr(0), pExpr) != 0 {
|
|
goto _1
|
|
}
|
|
p = _sqlite3DbMallocRaw(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, uint64(32))
|
|
if p == uintptr(0) {
|
|
break
|
|
}
|
|
(*TIndexedExpr)(unsafe.Pointer(p)).FpIENext = (*TParse)(unsafe.Pointer(pParse)).FpIdxEpr
|
|
(*TIndexedExpr)(unsafe.Pointer(p)).FpExpr = _sqlite3ExprDup(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pExpr, 0)
|
|
(*TIndexedExpr)(unsafe.Pointer(p)).FiDataCur = (*TSrcItem)(unsafe.Pointer(pTabItem)).FiCursor
|
|
(*TIndexedExpr)(unsafe.Pointer(p)).FiIdxCur = iIdxCur
|
|
(*TIndexedExpr)(unsafe.Pointer(p)).FiIdxCol = i
|
|
(*TIndexedExpr)(unsafe.Pointer(p)).FbMaybeNullRow = libc.BoolUint8(libc.Int32FromUint8((*TSrcItem)(unsafe.Pointer(pTabItem)).Ffg.Fjointype)&(libc.Int32FromInt32(JT_LEFT)|libc.Int32FromInt32(JT_LTORJ)|libc.Int32FromInt32(JT_RIGHT)) != 0)
|
|
if _sqlite3IndexAffinityStr(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pIdx) != 0 {
|
|
(*TIndexedExpr)(unsafe.Pointer(p)).Faff = uint8(**(**uint8)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FzColAff + uintptr(i))))
|
|
}
|
|
(*TParse)(unsafe.Pointer(pParse)).FpIdxEpr = p
|
|
if (*TIndexedExpr)(unsafe.Pointer(p)).FpIENext == uintptr(0) {
|
|
pArg = pParse + 104
|
|
_sqlite3ParserAddCleanup(tls, pParse, __ccgo_fp(_whereIndexedExprCleanup), pArg)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is called for a partial index - one with a WHERE clause - in
|
|
// ** two scenarios. In both cases, it determines whether or not the WHERE
|
|
// ** clause on the index implies that a column of the table may be safely
|
|
// ** replaced by a constant expression. For example, in the following
|
|
// ** SELECT:
|
|
// **
|
|
// ** CREATE INDEX i1 ON t1(b, c) WHERE a=<expr>;
|
|
// ** SELECT a, b, c FROM t1 WHERE a=<expr> AND b=?;
|
|
// **
|
|
// ** The "a" in the select-list may be replaced by <expr>, iff:
|
|
// **
|
|
// ** (a) <expr> is a constant expression, and
|
|
// ** (b) The (a=<expr>) comparison uses the BINARY collation sequence, and
|
|
// ** (c) Column "a" has an affinity other than NONE or BLOB.
|
|
// **
|
|
// ** If argument pItem is NULL, then pMask must not be NULL. In this case this
|
|
// ** function is being called as part of determining whether or not pIdx
|
|
// ** is a covering index. This function clears any bits in (*pMask)
|
|
// ** corresponding to columns that may be replaced by constants as described
|
|
// ** above.
|
|
// **
|
|
// ** Otherwise, if pItem is not NULL, then this function is being called
|
|
// ** as part of coding a loop that uses index pIdx. In this case, add entries
|
|
// ** to the Parse.pIdxPartExpr list for each column that can be replaced
|
|
// ** by a constant.
|
|
// */
|
|
func _wherePartIdxExpr(tls *libc.TLS, pParse uintptr, pIdx uintptr, pPart uintptr, pMask uintptr, iIdxCur int32, pItem uintptr) {
|
|
var aff Tu8
|
|
var bNullRow int32
|
|
var db, p, pArg, pLeft, pRight uintptr
|
|
_, _, _, _, _, _, _ = aff, bNullRow, db, p, pArg, pLeft, pRight
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pPart)).Fop) == int32(TK_AND) {
|
|
_wherePartIdxExpr(tls, pParse, pIdx, (*TExpr)(unsafe.Pointer(pPart)).FpRight, pMask, iIdxCur, pItem)
|
|
pPart = (*TExpr)(unsafe.Pointer(pPart)).FpLeft
|
|
}
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pPart)).Fop) == int32(TK_EQ) || libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pPart)).Fop) == int32(TK_IS) {
|
|
pLeft = (*TExpr)(unsafe.Pointer(pPart)).FpLeft
|
|
pRight = (*TExpr)(unsafe.Pointer(pPart)).FpRight
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pLeft)).Fop) != int32(TK_COLUMN) {
|
|
return
|
|
}
|
|
if !(_sqlite3ExprIsConstant(tls, uintptr(0), pRight) != 0) {
|
|
return
|
|
}
|
|
if !(_sqlite3IsBinary(tls, _sqlite3ExprCompareCollSeq(tls, pParse, pPart)) != 0) {
|
|
return
|
|
}
|
|
if int32((*TExpr)(unsafe.Pointer(pLeft)).FiColumn) < 0 {
|
|
return
|
|
}
|
|
aff = uint8((**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer((*TIndex)(unsafe.Pointer(pIdx)).FpTable)).FaCol + uintptr((*TExpr)(unsafe.Pointer(pLeft)).FiColumn)*16))).Faffinity)
|
|
if libc.Int32FromUint8(aff) >= int32(SQLITE_AFF_TEXT) {
|
|
if pItem != 0 {
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
p = _sqlite3DbMallocRaw(tls, db, uint64(32))
|
|
if p != 0 {
|
|
bNullRow = libc.BoolInt32(libc.Int32FromUint8((*TSrcItem)(unsafe.Pointer(pItem)).Ffg.Fjointype)&(libc.Int32FromInt32(JT_LEFT)|libc.Int32FromInt32(JT_LTORJ)) != 0)
|
|
(*TIndexedExpr)(unsafe.Pointer(p)).FpExpr = _sqlite3ExprDup(tls, db, pRight, 0)
|
|
(*TIndexedExpr)(unsafe.Pointer(p)).FiDataCur = (*TSrcItem)(unsafe.Pointer(pItem)).FiCursor
|
|
(*TIndexedExpr)(unsafe.Pointer(p)).FiIdxCur = iIdxCur
|
|
(*TIndexedExpr)(unsafe.Pointer(p)).FiIdxCol = int32((*TExpr)(unsafe.Pointer(pLeft)).FiColumn)
|
|
(*TIndexedExpr)(unsafe.Pointer(p)).FbMaybeNullRow = libc.Uint8FromInt32(bNullRow)
|
|
(*TIndexedExpr)(unsafe.Pointer(p)).FpIENext = (*TParse)(unsafe.Pointer(pParse)).FpIdxPartExpr
|
|
(*TIndexedExpr)(unsafe.Pointer(p)).Faff = aff
|
|
(*TParse)(unsafe.Pointer(pParse)).FpIdxPartExpr = p
|
|
if (*TIndexedExpr)(unsafe.Pointer(p)).FpIENext == uintptr(0) {
|
|
pArg = pParse + 112
|
|
_sqlite3ParserAddCleanup(tls, pParse, __ccgo_fp(_whereIndexedExprCleanup), pArg)
|
|
}
|
|
}
|
|
} else {
|
|
if int32((*TExpr)(unsafe.Pointer(pLeft)).FiColumn) < libc.Int32FromUint64(libc.Uint64FromInt64(8)*libc.Uint64FromInt32(8))-libc.Int32FromInt32(1) {
|
|
**(**TBitmask)(__ccgo_up(pMask)) &= ^(libc.Uint64FromInt32(1) << (*TExpr)(unsafe.Pointer(pLeft)).FiColumn)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is called to estimate the number of rows visited by a
|
|
// ** range-scan on a skip-scan index. For example:
|
|
// **
|
|
// ** CREATE INDEX i1 ON t1(a, b, c);
|
|
// ** SELECT * FROM t1 WHERE a=? AND c BETWEEN ? AND ?;
|
|
// **
|
|
// ** Value pLoop->nOut is currently set to the estimated number of rows
|
|
// ** visited for scanning (a=? AND b=?). This function reduces that estimate
|
|
// ** by some factor to account for the (c BETWEEN ? AND ?) expression based
|
|
// ** on the stat4 data for the index. this scan will be performed multiple
|
|
// ** times (once for each (a,b) combination that matches a=?) is dealt with
|
|
// ** by the caller.
|
|
// **
|
|
// ** It does this by scanning through all stat4 samples, comparing values
|
|
// ** extracted from pLower and pUpper with the corresponding column in each
|
|
// ** sample. If L and U are the number of samples found to be less than or
|
|
// ** equal to the values extracted from pLower and pUpper respectively, and
|
|
// ** N is the total number of samples, the pLoop->nOut value is adjusted
|
|
// ** as follows:
|
|
// **
|
|
// ** nOut = nOut * ( min(U - L, 1) / N )
|
|
// **
|
|
// ** If pLower is NULL, or a value cannot be extracted from the term, L is
|
|
// ** set to zero. If pUpper is NULL, or a value cannot be extracted from it,
|
|
// ** U is set to N.
|
|
// **
|
|
// ** Normally, this function sets *pbDone to 1 before returning. However,
|
|
// ** if no value can be extracted from either pLower or pUpper (and so the
|
|
// ** estimate of the number of rows delivered remains unchanged), *pbDone
|
|
// ** is left as is.
|
|
// **
|
|
// ** If an error occurs, an SQLite error code is returned. Otherwise,
|
|
// ** SQLITE_OK.
|
|
// */
|
|
func _whereRangeSkipScanEst(tls *libc.TLS, pParse uintptr, pLower uintptr, pUpper uintptr, pLoop uintptr, pbDone uintptr) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var aff Tu8
|
|
var db, p, pColl, v3 uintptr
|
|
var i, nAdjust, nDiff, nEq, nLower, nUpper, rc, res, res1, v1 int32
|
|
var _ /* p1 at bp+0 */ uintptr
|
|
var _ /* p2 at bp+8 */ uintptr
|
|
var _ /* pVal at bp+16 */ uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = aff, db, i, nAdjust, nDiff, nEq, nLower, nUpper, p, pColl, rc, res, res1, v1, v3
|
|
p = (*(*struct {
|
|
FnEq Tu16
|
|
FnBtm Tu16
|
|
FnTop Tu16
|
|
FnDistinctCol Tu16
|
|
FpIndex uintptr
|
|
FpOrderBy uintptr
|
|
})(unsafe.Pointer(pLoop + 24))).FpIndex
|
|
nEq = libc.Int32FromUint16((*(*struct {
|
|
FnEq Tu16
|
|
FnBtm Tu16
|
|
FnTop Tu16
|
|
FnDistinctCol Tu16
|
|
FpIndex uintptr
|
|
FpOrderBy uintptr
|
|
})(unsafe.Pointer(pLoop + 24))).FnEq)
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
nLower = -int32(1)
|
|
nUpper = (*TIndex)(unsafe.Pointer(p)).FnSample + int32(1)
|
|
rc = SQLITE_OK
|
|
aff = _sqlite3IndexColumnAffinity(tls, db, p, nEq)
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0) /* Value extracted from pLower */
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = uintptr(0) /* Value extracted from pUpper */
|
|
**(**uintptr)(__ccgo_up(bp + 16)) = uintptr(0) /* Value extracted from record */
|
|
pColl = _sqlite3LocateCollSeq(tls, pParse, **(**uintptr)(__ccgo_up((*TIndex)(unsafe.Pointer(p)).FazColl + uintptr(nEq)*8)))
|
|
if pLower != 0 {
|
|
rc = _sqlite3Stat4ValueFromExpr(tls, pParse, (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pLower)).FpExpr)).FpRight, aff, bp)
|
|
nLower = 0
|
|
}
|
|
if pUpper != 0 && rc == SQLITE_OK {
|
|
rc = _sqlite3Stat4ValueFromExpr(tls, pParse, (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pUpper)).FpExpr)).FpRight, aff, bp+8)
|
|
if **(**uintptr)(__ccgo_up(bp + 8)) != 0 {
|
|
v1 = 0
|
|
} else {
|
|
v1 = (*TIndex)(unsafe.Pointer(p)).FnSample
|
|
}
|
|
nUpper = v1
|
|
}
|
|
if **(**uintptr)(__ccgo_up(bp)) != 0 || **(**uintptr)(__ccgo_up(bp + 8)) != 0 {
|
|
i = 0
|
|
for {
|
|
if !(rc == SQLITE_OK && i < (*TIndex)(unsafe.Pointer(p)).FnSample) {
|
|
break
|
|
}
|
|
rc = _sqlite3Stat4Column(tls, db, (**(**TIndexSample)(__ccgo_up((*TIndex)(unsafe.Pointer(p)).FaSample + uintptr(i)*40))).Fp, (**(**TIndexSample)(__ccgo_up((*TIndex)(unsafe.Pointer(p)).FaSample + uintptr(i)*40))).Fn, nEq, bp+16)
|
|
if rc == SQLITE_OK && **(**uintptr)(__ccgo_up(bp)) != 0 {
|
|
res = _sqlite3MemCompare(tls, **(**uintptr)(__ccgo_up(bp)), **(**uintptr)(__ccgo_up(bp + 16)), pColl)
|
|
if res >= 0 {
|
|
nLower = nLower + 1
|
|
}
|
|
}
|
|
if rc == SQLITE_OK && **(**uintptr)(__ccgo_up(bp + 8)) != 0 {
|
|
res1 = _sqlite3MemCompare(tls, **(**uintptr)(__ccgo_up(bp + 8)), **(**uintptr)(__ccgo_up(bp + 16)), pColl)
|
|
if res1 >= 0 {
|
|
nUpper = nUpper + 1
|
|
}
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
nDiff = nUpper - nLower
|
|
if nDiff <= 0 {
|
|
nDiff = int32(1)
|
|
}
|
|
/* If there is both an upper and lower bound specified, and the
|
|
** comparisons indicate that they are close together, use the fallback
|
|
** method (assume that the scan visits 1/64 of the rows) for estimating
|
|
** the number of rows visited. Otherwise, estimate the number of rows
|
|
** using the method described in the header comment for this function. */
|
|
if nDiff != int32(1) || pUpper == uintptr(0) || pLower == uintptr(0) {
|
|
nAdjust = int32(_sqlite3LogEst(tls, libc.Uint64FromInt32((*TIndex)(unsafe.Pointer(p)).FnSample))) - int32(_sqlite3LogEst(tls, libc.Uint64FromInt32(nDiff)))
|
|
v3 = pLoop + 22
|
|
*(*TLogEst)(unsafe.Pointer(v3)) = TLogEst(int32(*(*TLogEst)(unsafe.Pointer(v3))) - nAdjust)
|
|
**(**int32)(__ccgo_up(pbDone)) = int32(1)
|
|
}
|
|
} else {
|
|
}
|
|
_sqlite3ValueFree(tls, **(**uintptr)(__ccgo_up(bp)))
|
|
_sqlite3ValueFree(tls, **(**uintptr)(__ccgo_up(bp + 8)))
|
|
_sqlite3ValueFree(tls, **(**uintptr)(__ccgo_up(bp + 16)))
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Term pTerm is a vector range comparison operation. The first comparison
|
|
// ** in the vector can be optimized using column nEq of the index. This
|
|
// ** function returns the total number of vector elements that can be used
|
|
// ** as part of the range comparison.
|
|
// **
|
|
// ** For example, if the query is:
|
|
// **
|
|
// ** WHERE a = ? AND (b, c, d) > (?, ?, ?)
|
|
// **
|
|
// ** and the index:
|
|
// **
|
|
// ** CREATE INDEX ... ON (a, b, c, d, e)
|
|
// **
|
|
// ** then this function would be invoked with nEq=1. The value returned in
|
|
// ** this case is 3.
|
|
// */
|
|
func _whereRangeVectorLen(tls *libc.TLS, pParse uintptr, iCur int32, pIdx uintptr, nEq int32, pTerm uintptr) (r int32) {
|
|
var aff, idxaff uint8
|
|
var i, nCmp, v1 int32
|
|
var pColl, pLhs, pRhs, t uintptr
|
|
_, _, _, _, _, _, _, _, _ = aff, i, idxaff, nCmp, pColl, pLhs, pRhs, t, v1
|
|
nCmp = _sqlite3ExprVectorSize(tls, (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr)).FpLeft)
|
|
if nCmp < libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnColumn)-nEq {
|
|
v1 = nCmp
|
|
} else {
|
|
v1 = libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnColumn) - nEq
|
|
}
|
|
nCmp = v1
|
|
i = int32(1)
|
|
for {
|
|
if !(i < nCmp) {
|
|
break
|
|
} /* Comparison affinity */
|
|
idxaff = uint8(0)
|
|
pLhs = (*(*TExprList_item)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer((*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr)).FpLeft + 32)) + 8 + uintptr(i)*32))).FpExpr
|
|
pRhs = (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr)).FpRight
|
|
if (*TExpr)(unsafe.Pointer(pRhs)).Fflags&uint32(EP_xIsSelect) != uint32(0) {
|
|
pRhs = (*(*TExprList_item)(unsafe.Pointer((*TSelect)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pRhs + 32)))).FpEList + 8 + uintptr(i)*32))).FpExpr
|
|
} else {
|
|
pRhs = (*(*TExprList_item)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pRhs + 32)) + 8 + uintptr(i)*32))).FpExpr
|
|
}
|
|
/* Check that the LHS of the comparison is a column reference to
|
|
** the right column of the right source table. And that the sort
|
|
** order of the index column is the same as the sort order of the
|
|
** leftmost index column. */
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pLhs)).Fop) != int32(TK_COLUMN) || (*TExpr)(unsafe.Pointer(pLhs)).FiTable != iCur || int32((*TExpr)(unsafe.Pointer(pLhs)).FiColumn) != int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(i+nEq)*2))) || libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaSortOrder + uintptr(i+nEq)))) != libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaSortOrder + uintptr(nEq)))) {
|
|
break
|
|
}
|
|
aff = _sqlite3CompareAffinity(tls, pRhs, _sqlite3ExprAffinity(tls, pLhs))
|
|
idxaff = _sqlite3TableColumnAffinity(tls, (*TIndex)(unsafe.Pointer(pIdx)).FpTable, int32((*TExpr)(unsafe.Pointer(pLhs)).FiColumn))
|
|
if libc.Int32FromUint8(aff) != libc.Int32FromUint8(idxaff) {
|
|
break
|
|
}
|
|
if (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Commuted)) != uint32(0) {
|
|
t = pRhs
|
|
pRhs = pLhs
|
|
pLhs = t
|
|
}
|
|
pColl = _sqlite3BinaryCompareCollSeq(tls, pParse, pLhs, pRhs)
|
|
if pColl == uintptr(0) {
|
|
break
|
|
}
|
|
if _sqlite3StrICmp(tls, (*TCollSeq)(unsafe.Pointer(pColl)).FzName, **(**uintptr)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FazColl + uintptr(i+nEq)*8))) != 0 {
|
|
break
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return i
|
|
}
|
|
|
|
/*
|
|
** Adjust the cost C by the costMult factor T. This only occurs if
|
|
** compiled with -DSQLITE_ENABLE_COSTMULT
|
|
*/
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Initialize a WHERE clause scanner object. Return a pointer to the
|
|
// ** first match. Return NULL if there are no matches.
|
|
// **
|
|
// ** The scanner will be searching the WHERE clause pWC. It will look
|
|
// ** for terms of the form "X <op> <expr>" where X is column iColumn of table
|
|
// ** iCur. Or if pIdx!=0 then X is column iColumn of index pIdx. pIdx
|
|
// ** must be one of the indexes of table iCur.
|
|
// **
|
|
// ** The <op> must be one of the operators described by opMask.
|
|
// **
|
|
// ** If the search is for X and the WHERE clause contains terms of the
|
|
// ** form X=Y then this routine might also return terms of the form
|
|
// ** "Y <op> <expr>". The number of levels of transitivity is limited,
|
|
// ** but is enough to handle most commonly occurring SQL statements.
|
|
// **
|
|
// ** If X is not the INTEGER PRIMARY KEY then X must be compatible with
|
|
// ** index pIdx.
|
|
// */
|
|
func _whereScanInit(tls *libc.TLS, pScan uintptr, pWC uintptr, iCur int32, iColumn int32, opMask Tu32, pIdx uintptr) (r uintptr) {
|
|
var j int32
|
|
_ = j
|
|
(*TWhereScan)(unsafe.Pointer(pScan)).FpOrigWC = pWC
|
|
(*TWhereScan)(unsafe.Pointer(pScan)).FpWC = pWC
|
|
(*TWhereScan)(unsafe.Pointer(pScan)).FpIdxExpr = uintptr(0)
|
|
(*TWhereScan)(unsafe.Pointer(pScan)).Fidxaff = uint8(0)
|
|
(*TWhereScan)(unsafe.Pointer(pScan)).FzCollName = uintptr(0)
|
|
(*TWhereScan)(unsafe.Pointer(pScan)).FopMask = opMask
|
|
(*TWhereScan)(unsafe.Pointer(pScan)).Fk = 0
|
|
**(**int32)(__ccgo_up(pScan + 44)) = iCur
|
|
(*TWhereScan)(unsafe.Pointer(pScan)).FnEquiv = uint8(1)
|
|
(*TWhereScan)(unsafe.Pointer(pScan)).FiEquiv = uint8(1)
|
|
if pIdx != 0 {
|
|
j = iColumn
|
|
iColumn = int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(j)*2)))
|
|
if iColumn == int32((*TTable)(unsafe.Pointer((*TIndex)(unsafe.Pointer(pIdx)).FpTable)).FiPKey) {
|
|
iColumn = -int32(1)
|
|
} else {
|
|
if iColumn >= 0 {
|
|
(*TWhereScan)(unsafe.Pointer(pScan)).Fidxaff = (**(**TColumn)(__ccgo_up((*TTable)(unsafe.Pointer((*TIndex)(unsafe.Pointer(pIdx)).FpTable)).FaCol + uintptr(iColumn)*16))).Faffinity
|
|
(*TWhereScan)(unsafe.Pointer(pScan)).FzCollName = **(**uintptr)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FazColl + uintptr(j)*8))
|
|
} else {
|
|
if iColumn == -int32(2) {
|
|
(*TWhereScan)(unsafe.Pointer(pScan)).FpIdxExpr = (*(*TExprList_item)(unsafe.Pointer((*TIndex)(unsafe.Pointer(pIdx)).FaColExpr + 8 + uintptr(j)*32))).FpExpr
|
|
(*TWhereScan)(unsafe.Pointer(pScan)).FzCollName = **(**uintptr)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FazColl + uintptr(j)*8))
|
|
**(**Ti16)(__ccgo_up(pScan + 88)) = int16(-libc.Int32FromInt32(2))
|
|
return _whereScanInitIndexExpr(tls, pScan)
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if iColumn == -int32(2) {
|
|
return uintptr(0)
|
|
}
|
|
}
|
|
**(**Ti16)(__ccgo_up(pScan + 88)) = int16(iColumn)
|
|
return _whereScanNext(tls, pScan)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Advance to the next WhereTerm that matches according to the criteria
|
|
// ** established when the pScan object was initialized by whereScanInit().
|
|
// ** Return NULL if there are no more matching WhereTerms.
|
|
// */
|
|
func _whereScanNext(tls *libc.TLS, pScan uintptr) (r uintptr) {
|
|
var iColumn Ti16
|
|
var iCur, j, k int32
|
|
var pColl, pParse, pTerm, pWC, pX, zCollName, v2 uintptr
|
|
var v3 bool
|
|
_, _, _, _, _, _, _, _, _, _, _, _ = iColumn, iCur, j, k, pColl, pParse, pTerm, pWC, pX, zCollName, v2, v3 /* The term being tested */
|
|
k = (*TWhereScan)(unsafe.Pointer(pScan)).Fk /* Where to start scanning */
|
|
pWC = (*TWhereScan)(unsafe.Pointer(pScan)).FpWC
|
|
for int32(1) != 0 {
|
|
iColumn = **(**Ti16)(__ccgo_up(pScan + 88 + uintptr(libc.Int32FromUint8((*TWhereScan)(unsafe.Pointer(pScan)).FiEquiv)-int32(1))*2))
|
|
iCur = **(**int32)(__ccgo_up(pScan + 44 + uintptr(libc.Int32FromUint8((*TWhereScan)(unsafe.Pointer(pScan)).FiEquiv)-int32(1))*4))
|
|
for cond := true; cond; cond = pWC != uintptr(0) {
|
|
pTerm = (*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(k)*56
|
|
for {
|
|
if !(k < (*TWhereClause)(unsafe.Pointer(pWC)).FnTerm) {
|
|
break
|
|
}
|
|
if (*TWhereTerm)(unsafe.Pointer(pTerm)).FleftCursor == iCur && (*(*struct {
|
|
FleftColumn int32
|
|
FiField int32
|
|
})(unsafe.Pointer(pTerm + 32))).FleftColumn == int32(iColumn) && (int32(iColumn) != -int32(2) || _sqlite3ExprCompareSkip(tls, (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr)).FpLeft, (*TWhereScan)(unsafe.Pointer(pScan)).FpIdxExpr, iCur) == 0) && (libc.Int32FromUint8((*TWhereScan)(unsafe.Pointer(pScan)).FiEquiv) <= int32(1) || !((*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_OuterON)) != libc.Uint32FromInt32(0))) {
|
|
if v3 = libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator)&int32(WO_EQUIV) != 0 && libc.Int32FromUint8((*TWhereScan)(unsafe.Pointer(pScan)).FnEquiv) < libc.Int32FromUint64(libc.Uint64FromInt64(44)/libc.Uint64FromInt64(4)); v3 {
|
|
v2 = _whereRightSubexprIsColumn(tls, (*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr)
|
|
pX = v2
|
|
}
|
|
if v3 && v2 != uintptr(0) {
|
|
j = 0
|
|
for {
|
|
if !(j < libc.Int32FromUint8((*TWhereScan)(unsafe.Pointer(pScan)).FnEquiv)) {
|
|
break
|
|
}
|
|
if **(**int32)(__ccgo_up(pScan + 44 + uintptr(j)*4)) == (*TExpr)(unsafe.Pointer(pX)).FiTable && int32(**(**Ti16)(__ccgo_up(pScan + 88 + uintptr(j)*2))) == int32((*TExpr)(unsafe.Pointer(pX)).FiColumn) {
|
|
break
|
|
}
|
|
goto _4
|
|
_4:
|
|
;
|
|
j = j + 1
|
|
}
|
|
if j == libc.Int32FromUint8((*TWhereScan)(unsafe.Pointer(pScan)).FnEquiv) {
|
|
**(**int32)(__ccgo_up(pScan + 44 + uintptr(j)*4)) = (*TExpr)(unsafe.Pointer(pX)).FiTable
|
|
**(**Ti16)(__ccgo_up(pScan + 88 + uintptr(j)*2)) = (*TExpr)(unsafe.Pointer(pX)).FiColumn
|
|
(*TWhereScan)(unsafe.Pointer(pScan)).FnEquiv = (*TWhereScan)(unsafe.Pointer(pScan)).FnEquiv + 1
|
|
}
|
|
}
|
|
if uint32((*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator)&(*TWhereScan)(unsafe.Pointer(pScan)).FopMask != uint32(0) {
|
|
/* Verify the affinity and collating sequence match */
|
|
if (*TWhereScan)(unsafe.Pointer(pScan)).FzCollName != 0 && libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator)&int32(WO_ISNULL) == 0 {
|
|
pParse = (*TWhereInfo)(unsafe.Pointer((*TWhereClause)(unsafe.Pointer(pWC)).FpWInfo)).FpParse
|
|
pX = (*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr
|
|
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator)&int32(WO_IN) != 0 {
|
|
zCollName = _indexInAffinityOk(tls, pParse, pTerm, (*TWhereScan)(unsafe.Pointer(pScan)).Fidxaff)
|
|
if !(zCollName != 0) {
|
|
goto _1
|
|
}
|
|
} else {
|
|
if !(_sqlite3IndexAffinityOk(tls, pX, (*TWhereScan)(unsafe.Pointer(pScan)).Fidxaff) != 0) {
|
|
goto _1
|
|
}
|
|
pColl = _sqlite3ExprCompareCollSeq(tls, pParse, pX)
|
|
if pColl != 0 {
|
|
v2 = (*TCollSeq)(unsafe.Pointer(pColl)).FzName
|
|
} else {
|
|
v2 = uintptr(unsafe.Pointer(&_sqlite3StrBINARY))
|
|
}
|
|
zCollName = v2
|
|
}
|
|
if _sqlite3StrICmp(tls, zCollName, (*TWhereScan)(unsafe.Pointer(pScan)).FzCollName) != 0 {
|
|
goto _1
|
|
}
|
|
}
|
|
if v3 = libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator)&(libc.Int32FromInt32(WO_EQ)|libc.Int32FromInt32(WO_IS)) != 0; v3 {
|
|
pX = (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr)).FpRight
|
|
}
|
|
if v3 && pX != libc.UintptrFromInt32(0) && libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pX)).Fop) == int32(TK_COLUMN) && (*TExpr)(unsafe.Pointer(pX)).FiTable == **(**int32)(__ccgo_up(pScan + 44)) && int32((*TExpr)(unsafe.Pointer(pX)).FiColumn) == int32(**(**Ti16)(__ccgo_up(pScan + 88))) {
|
|
goto _1
|
|
}
|
|
(*TWhereScan)(unsafe.Pointer(pScan)).FpWC = pWC
|
|
(*TWhereScan)(unsafe.Pointer(pScan)).Fk = k + int32(1)
|
|
return pTerm
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
k = k + 1
|
|
pTerm += 56
|
|
}
|
|
pWC = (*TWhereClause)(unsafe.Pointer(pWC)).FpOuter
|
|
k = 0
|
|
}
|
|
if libc.Int32FromUint8((*TWhereScan)(unsafe.Pointer(pScan)).FiEquiv) >= libc.Int32FromUint8((*TWhereScan)(unsafe.Pointer(pScan)).FnEquiv) {
|
|
break
|
|
}
|
|
pWC = (*TWhereScan)(unsafe.Pointer(pScan)).FpOrigWC
|
|
k = 0
|
|
(*TWhereScan)(unsafe.Pointer(pScan)).FiEquiv = (*TWhereScan)(unsafe.Pointer(pScan)).FiEquiv + 1
|
|
}
|
|
return uintptr(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Write the supplied super-journal name into the journal file for pager
|
|
// ** pPager at the current location. The super-journal name must be the last
|
|
// ** thing written to a journal file. If the pager is in full-sync mode, the
|
|
// ** journal file descriptor is advanced to the next sector boundary before
|
|
// ** anything is written. The format is:
|
|
// **
|
|
// ** + 4 bytes: PAGER_SJ_PGNO.
|
|
// ** + N bytes: super-journal filename in utf-8.
|
|
// ** + 4 bytes: N (length of super-journal name in bytes, no nul-terminator).
|
|
// ** + 4 bytes: super-journal name checksum.
|
|
// ** + 8 bytes: aJournalMagic[].
|
|
// **
|
|
// ** The super-journal page checksum is the sum of the bytes in the super-journal
|
|
// ** name, where each byte is interpreted as a signed 8-bit integer.
|
|
// **
|
|
// ** If zSuper is a NULL pointer (occurs for a single database transaction),
|
|
// ** this call is a no-op.
|
|
// */
|
|
func _writeSuperJournal(tls *libc.TLS, pPager uintptr, zSuper uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var cksum Tu32
|
|
var iHdrOff Ti64
|
|
var nSuper, rc, v2, v3, v5, v7, v9 int32
|
|
var v10, v4, v6, v8 bool
|
|
var _ /* jrnlSize at bp+0 */ Ti64
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _ = cksum, iHdrOff, nSuper, rc, v10, v2, v3, v4, v5, v6, v7, v8, v9 /* Size of journal file on disk */
|
|
cksum = uint32(0) /* Checksum of string zSuper */
|
|
if !(zSuper != 0) || libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FjournalMode) == int32(PAGER_JOURNALMODE_MEMORY) || !((*Tsqlite3_file)(unsafe.Pointer((*TPager)(unsafe.Pointer(pPager)).Fjfd)).FpMethods != libc.UintptrFromInt32(0)) {
|
|
return SQLITE_OK
|
|
}
|
|
(*TPager)(unsafe.Pointer(pPager)).FsetSuper = uint8(1)
|
|
/* Calculate the length in bytes and the checksum of zSuper */
|
|
nSuper = 0
|
|
for {
|
|
if !(**(**uint8)(__ccgo_up(zSuper + uintptr(nSuper))) != 0) {
|
|
break
|
|
}
|
|
cksum = cksum + uint32(**(**uint8)(__ccgo_up(zSuper + uintptr(nSuper))))
|
|
goto _1
|
|
_1:
|
|
;
|
|
nSuper = nSuper + 1
|
|
}
|
|
/* If in full-sync mode, advance to the next disk sector before writing
|
|
** the super-journal name. This is in case the previous page written to
|
|
** the journal has already been synced.
|
|
*/
|
|
if (*TPager)(unsafe.Pointer(pPager)).FfullSync != 0 {
|
|
(*TPager)(unsafe.Pointer(pPager)).FjournalOff = _journalHdrOffset(tls, pPager)
|
|
}
|
|
iHdrOff = (*TPager)(unsafe.Pointer(pPager)).FjournalOff
|
|
/* Write the super-journal data to the end of the journal file. If
|
|
** an error occurs, return the error code to the caller.
|
|
*/
|
|
v2 = _write32bits(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, iHdrOff, (*TPager)(unsafe.Pointer(pPager)).FlckPgno)
|
|
rc = v2
|
|
if v4 = 0 != v2; !v4 {
|
|
v3 = _sqlite3OsWrite(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, zSuper, nSuper, iHdrOff+int64(4))
|
|
rc = v3
|
|
}
|
|
if v6 = v4 || 0 != v3; !v6 {
|
|
v5 = _write32bits(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, iHdrOff+int64(4)+int64(nSuper), libc.Uint32FromInt32(nSuper))
|
|
rc = v5
|
|
}
|
|
if v8 = v6 || 0 != v5; !v8 {
|
|
v7 = _write32bits(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, iHdrOff+int64(4)+int64(nSuper)+int64(4), cksum)
|
|
rc = v7
|
|
}
|
|
if v10 = v8 || 0 != v7; !v10 {
|
|
v9 = _sqlite3OsWrite(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, uintptr(unsafe.Pointer(&_aJournalMagic)), int32(8), iHdrOff+int64(4)+int64(nSuper)+int64(8))
|
|
rc = v9
|
|
}
|
|
if v10 || 0 != v9 {
|
|
return rc
|
|
}
|
|
**(**Ti64)(__ccgo_up(pPager + 96)) += int64(nSuper + libc.Int32FromInt32(20))
|
|
/* If the pager is in persistent-journal mode, then the physical
|
|
** journal-file may extend past the end of the super-journal name
|
|
** and 8 bytes of magic data just written to the file. This is
|
|
** dangerous because the code to rollback a hot-journal file
|
|
** will not be able to find the super-journal name to determine
|
|
** whether or not the journal is hot.
|
|
**
|
|
** Easiest thing to do in this scenario is to truncate the journal
|
|
** file to the required size.
|
|
*/
|
|
v2 = _sqlite3OsFileSize(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, bp)
|
|
rc = v2
|
|
if SQLITE_OK == v2 && **(**Ti64)(__ccgo_up(bp)) > (*TPager)(unsafe.Pointer(pPager)).FjournalOff {
|
|
rc = _sqlite3OsTruncate(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, (*TPager)(unsafe.Pointer(pPager)).FjournalOff)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Set up a raw page so that it looks like a database page holding
|
|
// ** no entries.
|
|
// */
|
|
func _zeroPage(tls *libc.TLS, pPage uintptr, flags int32) {
|
|
var data, pBt uintptr
|
|
var first, hdr, v1 int32
|
|
_, _, _, _, _ = data, first, hdr, pBt, v1
|
|
data = (*TMemPage)(unsafe.Pointer(pPage)).FaData
|
|
pBt = (*TMemPage)(unsafe.Pointer(pPage)).FpBt
|
|
hdr = libc.Int32FromUint8((*TMemPage)(unsafe.Pointer(pPage)).FhdrOffset)
|
|
if libc.Int32FromUint16((*TBtShared)(unsafe.Pointer(pBt)).FbtsFlags)&int32(BTS_FAST_SECURE) != 0 {
|
|
libc.Xmemset(tls, data+uintptr(hdr), 0, uint64((*TBtShared)(unsafe.Pointer(pBt)).FusableSize-libc.Uint32FromInt32(hdr)))
|
|
}
|
|
**(**uint8)(__ccgo_up(data + uintptr(hdr))) = uint8(libc.Uint8FromInt32(flags))
|
|
if flags&int32(PTF_LEAF) == 0 {
|
|
v1 = int32(12)
|
|
} else {
|
|
v1 = int32(8)
|
|
}
|
|
first = hdr + v1
|
|
libc.Xmemset(tls, data+uintptr(hdr+int32(1)), 0, uint64(4))
|
|
**(**uint8)(__ccgo_up(data + uintptr(hdr+int32(7)))) = uint8(0)
|
|
**(**uint8)(__ccgo_up(data + uintptr(hdr+int32(5)))) = uint8((*TBtShared)(unsafe.Pointer(pBt)).FusableSize >> libc.Int32FromInt32(8))
|
|
**(**uint8)(__ccgo_up(data + uintptr(hdr+int32(5)) + 1)) = uint8((*TBtShared)(unsafe.Pointer(pBt)).FusableSize)
|
|
(*TMemPage)(unsafe.Pointer(pPage)).FnFree = libc.Int32FromUint16(uint16((*TBtShared)(unsafe.Pointer(pBt)).FusableSize - libc.Uint32FromInt32(first)))
|
|
_decodeFlags(tls, pPage, flags)
|
|
(*TMemPage)(unsafe.Pointer(pPage)).FcellOffset = libc.Uint16FromInt32(first)
|
|
(*TMemPage)(unsafe.Pointer(pPage)).FaDataEnd = data + uintptr((*TBtShared)(unsafe.Pointer(pBt)).FpageSize)
|
|
(*TMemPage)(unsafe.Pointer(pPage)).FaCellIdx = data + uintptr(first)
|
|
(*TMemPage)(unsafe.Pointer(pPage)).FaDataOfst = data + uintptr((*TMemPage)(unsafe.Pointer(pPage)).FchildPtrSize)
|
|
(*TMemPage)(unsafe.Pointer(pPage)).FnOverflow = uint8(0)
|
|
(*TMemPage)(unsafe.Pointer(pPage)).FmaskPage = uint16((*TBtShared)(unsafe.Pointer(pBt)).FpageSize - libc.Uint32FromInt32(1))
|
|
(*TMemPage)(unsafe.Pointer(pPage)).FnCell = uint16(0)
|
|
(*TMemPage)(unsafe.Pointer(pPage)).FisInit = uint8(1)
|
|
}
|