6c92f85d10
Bring the Nexus/Praxis/Hexis integration in line with MAVEN_ECOSYSTEM_ARCHITECTURE.md: - Praxis over HTTP: drop the in-process praxis.db open (praxisstore/ praxistools) and call praxisd's /api/v1/tools/* API via a new praxisClient. Honors the "no component reads another's DB" invariant (AC#12). PraxisConfig.DBPath -> URL. - Hexis confirmation gate: mutating capabilities (ReadOnly=false) now park a bound pendingHexis confirmation and require a spoken "да" before executing; read-only run immediately (AC#7, no auto attention->action). - Capability safety: >1 verb match is ambiguous -> ask instead of firing the first; ambiguous Nexus resolution asks for clarification (AC#2). - Correlation IDs on Hexis execute, recorded in the cross-service trace. - Bug: importance arrives as JSON float64 over HTTP, not int. - Tests: confirm-gate, decline, read-only, and ambiguity paths. Build: vendor/ bakes in the hexis client (replace-directed at a sibling repo outside the Docker context); Dockerfile builds from vendor and no longer `go mod download`s the unreachable replace paths. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
16136 lines
581 KiB
Go
16136 lines
581 KiB
Go
// Code generated by modernc.org/undup from the per-target sqlite_*.go files; DO NOT EDIT.
|
|
|
|
//go:build (darwin && amd64) || (darwin && arm64) || (freebsd && amd64) || (freebsd && arm64) || (linux && amd64) || (linux && arm64) || (linux && loong64) || (linux && ppc64le) || (linux && riscv64) || (linux && s390x) || (netbsd && amd64) || (openbsd && amd64) || (openbsd && arm64) || (windows && (amd64 || arm64))
|
|
|
|
package sqlite3
|
|
|
|
import (
|
|
"unsafe"
|
|
|
|
"modernc.org/libc"
|
|
)
|
|
|
|
const INTPTR_MAX = 9223372036854775807
|
|
|
|
const INTPTR_MIN = -9223372036854775808
|
|
|
|
const PTRDIFF_MAX = 9223372036854775807
|
|
|
|
const PTRDIFF_MIN = -9223372036854775808
|
|
|
|
const SIZE_MAX = 18446744073709551615
|
|
|
|
const SQLITE_PTRSIZE = 8
|
|
|
|
type TBitvec = struct {
|
|
FiSize Tu32
|
|
FnSet Tu32
|
|
FiDivisor Tu32
|
|
Fu struct {
|
|
FaHash [0][124]Tu32
|
|
FapSub [0][62]uintptr
|
|
FaBitmap [496]Tu8
|
|
}
|
|
}
|
|
|
|
type TExprList = struct {
|
|
F__ccgo_align [0]uint64
|
|
FnExpr int32
|
|
FnAlloc int32
|
|
}
|
|
|
|
type TFts5DlidxIter = struct {
|
|
F__ccgo_align [0]uint64
|
|
FnLvl int32
|
|
FiSegid int32
|
|
}
|
|
|
|
type TFts5TombstoneArray = struct {
|
|
F__ccgo_align [0]uint64
|
|
FnRef int32
|
|
FnTombstone int32
|
|
}
|
|
|
|
type TIdList = struct {
|
|
F__ccgo_align [0]uint64
|
|
FnId int32
|
|
}
|
|
|
|
type TIndex = struct {
|
|
FzName uintptr
|
|
FaiColumn uintptr
|
|
FaiRowLogEst uintptr
|
|
FpTable uintptr
|
|
FzColAff uintptr
|
|
FpNext uintptr
|
|
FpSchema uintptr
|
|
FaSortOrder uintptr
|
|
FazColl uintptr
|
|
FpPartIdxWhere uintptr
|
|
FaColExpr uintptr
|
|
Ftnum TPgno
|
|
FszIdxRow TLogEst
|
|
FnKeyCol Tu16
|
|
FnColumn Tu16
|
|
FonError Tu8
|
|
F__ccgo100 uint16
|
|
FnSample int32
|
|
FmxSample int32
|
|
FnSampleCol int32
|
|
FaAvgEq uintptr
|
|
FaSample uintptr
|
|
FaiRowEst uintptr
|
|
FnRowEst0 TtRowcnt
|
|
FcolNotIdxed TBitmask
|
|
}
|
|
|
|
type TIndexIterator = struct {
|
|
FeType int32
|
|
Fi int32
|
|
Fu struct {
|
|
Fax [0]struct {
|
|
FnIdx int32
|
|
FaIdx uintptr
|
|
}
|
|
Flx struct {
|
|
FpIdx uintptr
|
|
}
|
|
F__ccgo_pad2 [8]byte
|
|
}
|
|
}
|
|
|
|
type TParse = struct {
|
|
Fdb uintptr
|
|
FzErrMsg uintptr
|
|
FpVdbe uintptr
|
|
Frc int32
|
|
FnQueryLoop TLogEst
|
|
Fnested Tu8
|
|
FnTempReg Tu8
|
|
FisMultiWrite Tu8
|
|
FdisableLookaside Tu8
|
|
FprepFlags Tu8
|
|
FwithinRJSubrtn Tu8
|
|
FmSubrtnSig Tu8
|
|
FeTriggerOp Tu8
|
|
FeOrconf Tu8
|
|
F__ccgo40 uint16
|
|
FnRangeReg int32
|
|
FiRangeReg int32
|
|
FnErr int32
|
|
FnTab int32
|
|
FnMem int32
|
|
FszOpAlloc int32
|
|
FiSelfTab int32
|
|
FnNestSel int32
|
|
FnLabel int32
|
|
FnLabelAlloc int32
|
|
FaLabel uintptr
|
|
FpConstExpr uintptr
|
|
FpIdxEpr uintptr
|
|
FpIdxPartExpr uintptr
|
|
FwriteMask TyDbMask
|
|
FcookieMask TyDbMask
|
|
FnMaxArg int32
|
|
FnSelect int32
|
|
FnProgressSteps Tu32
|
|
FnTableLock int32
|
|
FaTableLock uintptr
|
|
FpAinc uintptr
|
|
FpToplevel uintptr
|
|
FpTriggerTab uintptr
|
|
FpTriggerPrg uintptr
|
|
FpCleanup uintptr
|
|
FaTempReg [8]int32
|
|
FpOuterParse uintptr
|
|
FsNameToken TToken
|
|
Foldmask Tu32
|
|
Fnewmask Tu32
|
|
Fu1 struct {
|
|
Fd [0]struct {
|
|
FpReturning uintptr
|
|
}
|
|
Fcr struct {
|
|
FaddrCrTab int32
|
|
FregRowid int32
|
|
FregRoot int32
|
|
FconstraintName TToken
|
|
}
|
|
}
|
|
FsLastToken TToken
|
|
FnVar TynVar
|
|
FiPkSortOrder Tu8
|
|
Fexplain Tu8
|
|
FeParseMode Tu8
|
|
FnVtabLock int32
|
|
FnHeight int32
|
|
FaddrExplain int32
|
|
FpVList uintptr
|
|
FpReprepare uintptr
|
|
FzTail uintptr
|
|
FpNewTable uintptr
|
|
FpNewIndex uintptr
|
|
FpNewTrigger uintptr
|
|
FzAuthContext uintptr
|
|
FsArg TToken
|
|
FapVtabLock uintptr
|
|
FpWith uintptr
|
|
FpRename uintptr
|
|
}
|
|
|
|
type TPreUpdate = struct {
|
|
Fv uintptr
|
|
FpCsr uintptr
|
|
Fop int32
|
|
FaRecord uintptr
|
|
FpKeyinfo uintptr
|
|
FpUnpacked uintptr
|
|
FpNewUnpacked uintptr
|
|
FiNewReg int32
|
|
FiBlobWrite int32
|
|
FiKey1 Ti64
|
|
FiKey2 Ti64
|
|
Foldipk TMem
|
|
FaNew uintptr
|
|
FpTab uintptr
|
|
FpPk uintptr
|
|
FapDflt uintptr
|
|
FuKey struct {
|
|
FkeyinfoSpace [32]Tu8
|
|
}
|
|
}
|
|
|
|
/*
|
|
** RowSetEntry objects are allocated in large chunks (instances of the
|
|
** following structure) to reduce memory allocation overhead. The
|
|
** chunks are kept on a linked list so that they can be deallocated
|
|
** when the RowSet is destroyed.
|
|
*/
|
|
type TRowSetChunk = struct {
|
|
FpNextChunk uintptr
|
|
FaEntry [42]TRowSetEntry
|
|
}
|
|
|
|
type TSrcList = struct {
|
|
F__ccgo_align [0]uint64
|
|
FnSrc int32
|
|
FnAlloc Tu32
|
|
}
|
|
|
|
type TUnpackedRecord = struct {
|
|
FpKeyInfo uintptr
|
|
FaMem uintptr
|
|
Fu struct {
|
|
Fi [0]Ti64
|
|
Fz uintptr
|
|
}
|
|
Fn int32
|
|
FnField Tu16
|
|
Fdefault_rc Ti8
|
|
FerrCode Tu8
|
|
Fr1 Ti8
|
|
Fr2 Ti8
|
|
FeqSeen Tu8
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** A single VDBE is an opaque structure named "Vdbe". Only routines
|
|
// ** in the source file sqliteVdbe.c are allowed to see the insides
|
|
// ** of this structure.
|
|
// */
|
|
type TVdbe = struct {
|
|
Fdb uintptr
|
|
FppVPrev uintptr
|
|
FpVNext uintptr
|
|
FpParse uintptr
|
|
FnVar TynVar
|
|
FnMem int32
|
|
FnCursor int32
|
|
FcacheCtr Tu32
|
|
Fpc int32
|
|
Frc int32
|
|
FnChange Ti64
|
|
FiStatement int32
|
|
FiCurrentTime Ti64
|
|
FnFkConstraint Ti64
|
|
FnStmtDefCons Ti64
|
|
FnStmtDefImmCons Ti64
|
|
FaMem uintptr
|
|
FapArg uintptr
|
|
FapCsr uintptr
|
|
FaVar uintptr
|
|
FaOp uintptr
|
|
FnOp int32
|
|
FnOpAlloc int32
|
|
FaColName uintptr
|
|
FpResultRow uintptr
|
|
FzErrMsg uintptr
|
|
FpVList uintptr
|
|
FstartTime Ti64
|
|
FnResColumn Tu16
|
|
FnResAlloc Tu16
|
|
FerrorAction Tu8
|
|
FminWriteFileFormat Tu8
|
|
FprepFlags Tu8
|
|
FeVdbeState Tu8
|
|
F__ccgo200 uint16
|
|
FbtreeMask TyDbMask
|
|
FlockMask TyDbMask
|
|
FaCounter [9]Tu32
|
|
FzSql uintptr
|
|
FpFree uintptr
|
|
FpFrame uintptr
|
|
FpDelFrame uintptr
|
|
FnFrame int32
|
|
Fexpmask Tu32
|
|
FpProgram uintptr
|
|
FpAuxData uintptr
|
|
}
|
|
|
|
type TWalIterator = struct {
|
|
F__ccgo_align [0]uint64
|
|
FiPrior Tu32
|
|
FnSegment int32
|
|
}
|
|
|
|
type TWhereInfo = struct {
|
|
FpParse uintptr
|
|
FpTabList uintptr
|
|
FpOrderBy uintptr
|
|
FpResultSet uintptr
|
|
FpSelect uintptr
|
|
FaiCurOnePass [2]int32
|
|
FiContinue int32
|
|
FiBreak int32
|
|
FsavedNQueryLoop int32
|
|
FwctrlFlags Tu16
|
|
FiLimit TLogEst
|
|
FnLevel Tu8
|
|
FnOBSat Ti8
|
|
FeOnePass Tu8
|
|
FeDistinct Tu8
|
|
F__ccgo68 uint8
|
|
FnRowOut TLogEst
|
|
FiTop int32
|
|
FiEndWhere int32
|
|
FpLoops uintptr
|
|
FpMemToFree uintptr
|
|
FrevMask TBitmask
|
|
FsWC TWhereClause
|
|
FsMaskSet TWhereMaskSet
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* The next sections is a series of control #defines.
|
|
// ** various aspects of the generated parser.
|
|
// ** YYCODETYPE is the data type used to store the integer codes
|
|
// ** that represent terminal and non-terminal symbols.
|
|
// ** "unsigned char" is used if there are fewer than
|
|
// ** 256 symbols. Larger types otherwise.
|
|
// ** YYNOCODE is a number of type YYCODETYPE that is not used for
|
|
// ** any terminal or nonterminal symbol.
|
|
// ** YYFALLBACK If defined, this indicates that one or more tokens
|
|
// ** (also known as: "terminal symbols") have fall-back
|
|
// ** values which should be used if the original symbol
|
|
// ** would not parse. This permits keywords to sometimes
|
|
// ** be used as identifiers, for example.
|
|
// ** YYACTIONTYPE is the data type used for "action codes" - numbers
|
|
// ** that indicate what to do in response to the next
|
|
// ** token.
|
|
// ** sqlite3ParserTOKENTYPE is the data type used for minor type for terminal
|
|
// ** symbols. Background: A "minor type" is a semantic
|
|
// ** value associated with a terminal or non-terminal
|
|
// ** symbols. For example, for an "ID" terminal symbol,
|
|
// ** the minor type might be the name of the identifier.
|
|
// ** Each non-terminal can have a different minor type.
|
|
// ** Terminal symbols all have the same minor type, though.
|
|
// ** This macros defines the minor type for terminal
|
|
// ** symbols.
|
|
// ** YYMINORTYPE is the data type used for all minor types.
|
|
// ** This is typically a union of many types, one of
|
|
// ** which is sqlite3ParserTOKENTYPE. The entry in the union
|
|
// ** for terminal symbols is called "yy0".
|
|
// ** YYSTACKDEPTH is the maximum depth of the parser's stack. If
|
|
// ** zero the stack is dynamically sized using realloc()
|
|
// ** sqlite3ParserARG_SDECL A static variable declaration for the %extra_argument
|
|
// ** sqlite3ParserARG_PDECL A parameter declaration for the %extra_argument
|
|
// ** sqlite3ParserARG_PARAM Code to pass %extra_argument as a subroutine parameter
|
|
// ** sqlite3ParserARG_STORE Code to store %extra_argument into yypParser
|
|
// ** sqlite3ParserARG_FETCH Code to extract %extra_argument from yypParser
|
|
// ** sqlite3ParserCTX_* As sqlite3ParserARG_ except for %extra_context
|
|
// ** YYREALLOC Name of the realloc() function to use
|
|
// ** YYFREE Name of the free() function to use
|
|
// ** YYDYNSTACK True if stack space should be extended on heap
|
|
// ** YYERRORSYMBOL is the code number of the error symbol. If not
|
|
// ** defined, then do no error processing.
|
|
// ** YYNSTATE the combined number of states.
|
|
// ** YYNRULE the number of rules in the grammar
|
|
// ** YYNTOKEN Number of terminal symbols
|
|
// ** YY_MAX_SHIFT Maximum value for shift actions
|
|
// ** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
|
|
// ** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
|
|
// ** YY_ERROR_ACTION The yy_action[] code for syntax error
|
|
// ** YY_ACCEPT_ACTION The yy_action[] code for accept
|
|
// ** YY_NO_ACTION The yy_action[] code for no-op
|
|
// ** YY_MIN_REDUCE Minimum value for reduce actions
|
|
// ** YY_MAX_REDUCE Maximum value for reduce actions
|
|
// ** YY_MIN_DSTRCTR Minimum symbol value that has a destructor
|
|
// ** YY_MAX_DSTRCTR Maximum symbol value that has a destructor
|
|
// */
|
|
// /************* Begin control #defines *****************************************/
|
|
type TYYMINORTYPE = struct {
|
|
Fyy0 [0]TToken
|
|
Fyy14 [0]uintptr
|
|
Fyy59 [0]uintptr
|
|
Fyy67 [0]uintptr
|
|
Fyy122 [0]uintptr
|
|
Fyy132 [0]uintptr
|
|
Fyy144 [0]int32
|
|
Fyy168 [0]uintptr
|
|
Fyy203 [0]uintptr
|
|
Fyy211 [0]uintptr
|
|
Fyy269 [0]TOnOrUsing
|
|
Fyy286 [0]TTrigEvent
|
|
Fyy383 [0]struct {
|
|
Fvalue int32
|
|
Fmask int32
|
|
}
|
|
Fyy391 [0]Tu32
|
|
Fyy427 [0]uintptr
|
|
Fyy454 [0]uintptr
|
|
Fyy462 [0]Tu8
|
|
Fyy509 [0]TFrameBound
|
|
Fyy555 [0]uintptr
|
|
Fyyinit int32
|
|
F__ccgo_pad20 [12]byte
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* The next sections is a series of control #defines.
|
|
// ** various aspects of the generated parser.
|
|
// ** fts5YYCODETYPE is the data type used to store the integer codes
|
|
// ** that represent terminal and non-terminal symbols.
|
|
// ** "unsigned char" is used if there are fewer than
|
|
// ** 256 symbols. Larger types otherwise.
|
|
// ** fts5YYNOCODE is a number of type fts5YYCODETYPE that is not used for
|
|
// ** any terminal or nonterminal symbol.
|
|
// ** fts5YYFALLBACK If defined, this indicates that one or more tokens
|
|
// ** (also known as: "terminal symbols") have fall-back
|
|
// ** values which should be used if the original symbol
|
|
// ** would not parse. This permits keywords to sometimes
|
|
// ** be used as identifiers, for example.
|
|
// ** fts5YYACTIONTYPE is the data type used for "action codes" - numbers
|
|
// ** that indicate what to do in response to the next
|
|
// ** token.
|
|
// ** sqlite3Fts5ParserFTS5TOKENTYPE is the data type used for minor type for terminal
|
|
// ** symbols. Background: A "minor type" is a semantic
|
|
// ** value associated with a terminal or non-terminal
|
|
// ** symbols. For example, for an "ID" terminal symbol,
|
|
// ** the minor type might be the name of the identifier.
|
|
// ** Each non-terminal can have a different minor type.
|
|
// ** Terminal symbols all have the same minor type, though.
|
|
// ** This macros defines the minor type for terminal
|
|
// ** symbols.
|
|
// ** fts5YYMINORTYPE is the data type used for all minor types.
|
|
// ** This is typically a union of many types, one of
|
|
// ** which is sqlite3Fts5ParserFTS5TOKENTYPE. The entry in the union
|
|
// ** for terminal symbols is called "fts5yy0".
|
|
// ** fts5YYSTACKDEPTH is the maximum depth of the parser's stack. If
|
|
// ** zero the stack is dynamically sized using realloc()
|
|
// ** sqlite3Fts5ParserARG_SDECL A static variable declaration for the %extra_argument
|
|
// ** sqlite3Fts5ParserARG_PDECL A parameter declaration for the %extra_argument
|
|
// ** sqlite3Fts5ParserARG_PARAM Code to pass %extra_argument as a subroutine parameter
|
|
// ** sqlite3Fts5ParserARG_STORE Code to store %extra_argument into fts5yypParser
|
|
// ** sqlite3Fts5ParserARG_FETCH Code to extract %extra_argument from fts5yypParser
|
|
// ** sqlite3Fts5ParserCTX_* As sqlite3Fts5ParserARG_ except for %extra_context
|
|
// ** fts5YYREALLOC Name of the realloc() function to use
|
|
// ** fts5YYFREE Name of the free() function to use
|
|
// ** fts5YYDYNSTACK True if stack space should be extended on heap
|
|
// ** fts5YYERRORSYMBOL is the code number of the error symbol. If not
|
|
// ** defined, then do no error processing.
|
|
// ** fts5YYNSTATE the combined number of states.
|
|
// ** fts5YYNRULE the number of rules in the grammar
|
|
// ** fts5YYNFTS5TOKEN Number of terminal symbols
|
|
// ** fts5YY_MAX_SHIFT Maximum value for shift actions
|
|
// ** fts5YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
|
|
// ** fts5YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
|
|
// ** fts5YY_ERROR_ACTION The fts5yy_action[] code for syntax error
|
|
// ** fts5YY_ACCEPT_ACTION The fts5yy_action[] code for accept
|
|
// ** fts5YY_NO_ACTION The fts5yy_action[] code for no-op
|
|
// ** fts5YY_MIN_REDUCE Minimum value for reduce actions
|
|
// ** fts5YY_MAX_REDUCE Maximum value for reduce actions
|
|
// ** fts5YY_MIN_DSTRCTR Minimum symbol value that has a destructor
|
|
// ** fts5YY_MAX_DSTRCTR Maximum symbol value that has a destructor
|
|
// */
|
|
// /************* Begin control #defines *****************************************/
|
|
type Tfts5YYMINORTYPE = struct {
|
|
Ffts5yy0 [0]TFts5Token
|
|
Ffts5yy4 [0]int32
|
|
Ffts5yy11 [0]uintptr
|
|
Ffts5yy24 [0]uintptr
|
|
Ffts5yy46 [0]uintptr
|
|
Ffts5yy53 [0]uintptr
|
|
Ffts5yyinit int32
|
|
F__ccgo_pad7 [12]byte
|
|
}
|
|
|
|
type Tintptr_t = int64
|
|
|
|
type Tp4union = struct {
|
|
Fp [0]uintptr
|
|
Fz [0]uintptr
|
|
FpI64 [0]uintptr
|
|
FpReal [0]uintptr
|
|
FpFunc [0]uintptr
|
|
FpCtx [0]uintptr
|
|
FpColl [0]uintptr
|
|
FpMem [0]uintptr
|
|
FpVtab [0]uintptr
|
|
FpKeyInfo [0]uintptr
|
|
Fai [0]uintptr
|
|
FpProgram [0]uintptr
|
|
FpTab [0]uintptr
|
|
FpSubrtnSig [0]uintptr
|
|
FpIdx [0]uintptr
|
|
Fi int32
|
|
F__ccgo_pad16 [4]byte
|
|
}
|
|
|
|
type Tptrdiff_t = int64
|
|
|
|
type Tsize_t = uint64
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Variables in which to record status information.
|
|
// */
|
|
type Tsqlite3StatValueType = int64
|
|
|
|
type Tssize_t = int64
|
|
|
|
type Tuintptr_t = uint64
|
|
|
|
// C documentation
|
|
//
|
|
// /* The uptr type is an unsigned integer large enough to hold a pointer
|
|
// */
|
|
type Tuptr = uint64
|
|
|
|
const UINTPTR_MAX = 18446744073709551615
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Register a statically linked extension that is automatically
|
|
// ** loaded by every new database connection.
|
|
// */
|
|
func Xsqlite3_auto_extension(tls *libc.TLS, __ccgo_fp_xInit uintptr) (r int32) {
|
|
var aNew, mutex uintptr
|
|
var i Tu32
|
|
var nByte Tu64
|
|
var rc int32
|
|
_, _, _, _, _ = aNew, i, mutex, nByte, rc
|
|
rc = SQLITE_OK
|
|
rc = Xsqlite3_initialize(tls)
|
|
if rc != 0 {
|
|
return rc
|
|
} else {
|
|
mutex = _sqlite3MutexAlloc(tls, int32(SQLITE_MUTEX_STATIC_MAIN))
|
|
Xsqlite3_mutex_enter(tls, mutex)
|
|
i = uint32(0)
|
|
for {
|
|
if !(i < _sqlite3Autoext.FnExt) {
|
|
break
|
|
}
|
|
if **(**uintptr)(__ccgo_up(_sqlite3Autoext.FaExt + uintptr(i)*8)) == __ccgo_fp_xInit {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if i == _sqlite3Autoext.FnExt {
|
|
nByte = uint64(_sqlite3Autoext.FnExt+libc.Uint32FromInt32(1)) * uint64(8)
|
|
aNew = Xsqlite3_realloc64(tls, _sqlite3Autoext.FaExt, nByte)
|
|
if aNew == uintptr(0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
} else {
|
|
_sqlite3Autoext.FaExt = aNew
|
|
**(**uintptr)(__ccgo_up(_sqlite3Autoext.FaExt + uintptr(_sqlite3Autoext.FnExt)*8)) = __ccgo_fp_xInit
|
|
_sqlite3Autoext.FnExt = _sqlite3Autoext.FnExt + 1
|
|
}
|
|
}
|
|
Xsqlite3_mutex_leave(tls, mutex)
|
|
return rc
|
|
}
|
|
return r
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Release all resources associated with an sqlite3_backup* handle.
|
|
// */
|
|
func Xsqlite3_backup_finish(tls *libc.TLS, p uintptr) (r int32) {
|
|
var pSrcDb, pp uintptr
|
|
var rc, v1 int32
|
|
_, _, _, _ = pSrcDb, pp, rc, v1 /* Value to return */
|
|
/* Enter the mutexes */
|
|
if p == uintptr(0) {
|
|
return SQLITE_OK
|
|
}
|
|
pSrcDb = (*Tsqlite3_backup)(unsafe.Pointer(p)).FpSrcDb
|
|
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(pSrcDb)).Fmutex)
|
|
_sqlite3BtreeEnter(tls, (*Tsqlite3_backup)(unsafe.Pointer(p)).FpSrc)
|
|
if (*Tsqlite3_backup)(unsafe.Pointer(p)).FpDestDb != 0 {
|
|
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer((*Tsqlite3_backup)(unsafe.Pointer(p)).FpDestDb)).Fmutex)
|
|
}
|
|
/* Detach this backup from the source pager. */
|
|
if (*Tsqlite3_backup)(unsafe.Pointer(p)).FpDestDb != 0 {
|
|
(*TBtree)(unsafe.Pointer((*Tsqlite3_backup)(unsafe.Pointer(p)).FpSrc)).FnBackup = (*TBtree)(unsafe.Pointer((*Tsqlite3_backup)(unsafe.Pointer(p)).FpSrc)).FnBackup - 1
|
|
}
|
|
if (*Tsqlite3_backup)(unsafe.Pointer(p)).FisAttached != 0 {
|
|
pp = _sqlite3PagerBackupPtr(tls, _sqlite3BtreePager(tls, (*Tsqlite3_backup)(unsafe.Pointer(p)).FpSrc))
|
|
for **(**uintptr)(__ccgo_up(pp)) != p {
|
|
pp = **(**uintptr)(__ccgo_up(pp)) + 72
|
|
}
|
|
**(**uintptr)(__ccgo_up(pp)) = (*Tsqlite3_backup)(unsafe.Pointer(p)).FpNext
|
|
}
|
|
/* If a transaction is still open on the Btree, roll it back. */
|
|
if (*Tsqlite3_backup)(unsafe.Pointer(p)).FpDest != 0 {
|
|
_sqlite3BtreeRollback(tls, (*Tsqlite3_backup)(unsafe.Pointer(p)).FpDest, SQLITE_OK, 0)
|
|
}
|
|
/* Set the error code of the destination database handle. */
|
|
if (*Tsqlite3_backup)(unsafe.Pointer(p)).Frc == int32(SQLITE_DONE) {
|
|
v1 = SQLITE_OK
|
|
} else {
|
|
v1 = (*Tsqlite3_backup)(unsafe.Pointer(p)).Frc
|
|
}
|
|
rc = v1
|
|
if (*Tsqlite3_backup)(unsafe.Pointer(p)).FpDestDb != 0 {
|
|
_sqlite3Error(tls, (*Tsqlite3_backup)(unsafe.Pointer(p)).FpDestDb, rc)
|
|
/* Exit the mutexes and free the backup context structure. */
|
|
_sqlite3LeaveMutexAndCloseZombie(tls, (*Tsqlite3_backup)(unsafe.Pointer(p)).FpDestDb)
|
|
}
|
|
_sqlite3BtreeLeave(tls, (*Tsqlite3_backup)(unsafe.Pointer(p)).FpSrc)
|
|
if (*Tsqlite3_backup)(unsafe.Pointer(p)).FpDestDb != 0 {
|
|
/* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
|
|
** call to sqlite3_backup_init() and is destroyed by a call to
|
|
** sqlite3_backup_finish(). */
|
|
Xsqlite3_free(tls, p)
|
|
}
|
|
_sqlite3LeaveMutexAndCloseZombie(tls, pSrcDb)
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Set all the parameters in the compiled SQL statement to NULL.
|
|
// */
|
|
func Xsqlite3_clear_bindings(tls *libc.TLS, pStmt uintptr) (r int32) {
|
|
var i, rc int32
|
|
var mutex, p uintptr
|
|
_, _, _, _ = i, mutex, p, rc
|
|
rc = SQLITE_OK
|
|
p = pStmt
|
|
mutex = (*Tsqlite3)(unsafe.Pointer((*TVdbe)(unsafe.Pointer(p)).Fdb)).Fmutex
|
|
Xsqlite3_mutex_enter(tls, mutex)
|
|
i = 0
|
|
for {
|
|
if !(i < int32((*TVdbe)(unsafe.Pointer(p)).FnVar)) {
|
|
break
|
|
}
|
|
_sqlite3VdbeMemRelease(tls, (*TVdbe)(unsafe.Pointer(p)).FaVar+uintptr(i)*56)
|
|
(**(**TMem)(__ccgo_up((*TVdbe)(unsafe.Pointer(p)).FaVar + uintptr(i)*56))).Fflags = uint16(MEM_Null)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if (*TVdbe)(unsafe.Pointer(p)).Fexpmask != 0 {
|
|
libc.SetBitFieldPtr16Uint32(p+200, libc.Uint32FromInt32(1), 0, 0x3)
|
|
}
|
|
Xsqlite3_mutex_leave(tls, mutex)
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the N-th compile-time option string. If N is out of range,
|
|
// ** return a NULL pointer.
|
|
// */
|
|
func Xsqlite3_compileoption_get(tls *libc.TLS, N int32) (r uintptr) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var azCompileOpt uintptr
|
|
var _ /* nOpt at bp+0 */ int32
|
|
_ = azCompileOpt
|
|
azCompileOpt = _sqlite3CompileOptions(tls, bp)
|
|
if N >= 0 && N < **(**int32)(__ccgo_up(bp)) {
|
|
return **(**uintptr)(__ccgo_up(azCompileOpt + uintptr(N)*8))
|
|
}
|
|
return uintptr(0)
|
|
}
|
|
|
|
/************** End of main.c ************************************************/
|
|
/************** Begin file notify.c ******************************************/
|
|
/*
|
|
** 2009 March 3
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
**
|
|
** This file contains the implementation of the sqlite3_unlock_notify()
|
|
** API method and its associated functionality.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
/* #include "btreeInt.h" */
|
|
|
|
/* Omit this entire file if SQLITE_ENABLE_UNLOCK_NOTIFY is not defined. */
|
|
|
|
/*
|
|
** Public interfaces:
|
|
**
|
|
** sqlite3ConnectionBlocked()
|
|
** sqlite3ConnectionUnlocked()
|
|
** sqlite3ConnectionClosed()
|
|
** sqlite3_unlock_notify()
|
|
*/
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Flush any dirty pages in the pager-cache for any attached database
|
|
// ** to disk.
|
|
// */
|
|
func Xsqlite3_db_cacheflush(tls *libc.TLS, db uintptr) (r int32) {
|
|
var bSeenBusy, i, rc, v2 int32
|
|
var pBt, pPager uintptr
|
|
_, _, _, _, _, _ = bSeenBusy, i, pBt, pPager, rc, v2
|
|
rc = SQLITE_OK
|
|
bSeenBusy = 0
|
|
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
_sqlite3BtreeEnterAll(tls, db)
|
|
i = 0
|
|
for {
|
|
if !(rc == SQLITE_OK && i < (*Tsqlite3)(unsafe.Pointer(db)).FnDb) {
|
|
break
|
|
}
|
|
pBt = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(i)*32))).FpBt
|
|
if pBt != 0 && _sqlite3BtreeTxnState(tls, pBt) == int32(SQLITE_TXN_WRITE) {
|
|
pPager = _sqlite3BtreePager(tls, pBt)
|
|
rc = _sqlite3PagerFlush(tls, pPager)
|
|
if rc == int32(SQLITE_BUSY) {
|
|
bSeenBusy = int32(1)
|
|
rc = SQLITE_OK
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_sqlite3BtreeLeaveAll(tls, db)
|
|
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
if rc == SQLITE_OK && bSeenBusy != 0 {
|
|
v2 = int32(SQLITE_BUSY)
|
|
} else {
|
|
v2 = rc
|
|
}
|
|
return v2
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the name of the N-th database schema. Return NULL if N is out
|
|
// ** of range.
|
|
// */
|
|
func Xsqlite3_db_name(tls *libc.TLS, db uintptr, N int32) (r uintptr) {
|
|
var zRet uintptr
|
|
_ = zRet
|
|
zRet = uintptr(0)
|
|
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
if N >= 0 && N < (*Tsqlite3)(unsafe.Pointer(db)).FnDb {
|
|
zRet = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(N)*32))).FzDbSName
|
|
}
|
|
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
return zRet
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free up as much memory as we can from the given database
|
|
// ** connection.
|
|
// */
|
|
func Xsqlite3_db_release_memory(tls *libc.TLS, db uintptr) (r int32) {
|
|
var i int32
|
|
var pBt, pPager uintptr
|
|
_, _, _ = i, pBt, pPager
|
|
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
_sqlite3BtreeEnterAll(tls, db)
|
|
i = 0
|
|
for {
|
|
if !(i < (*Tsqlite3)(unsafe.Pointer(db)).FnDb) {
|
|
break
|
|
}
|
|
pBt = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(i)*32))).FpBt
|
|
if pBt != 0 {
|
|
pPager = _sqlite3BtreePager(tls, pBt)
|
|
_sqlite3PagerShrink(tls, pPager)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_sqlite3BtreeLeaveAll(tls, db)
|
|
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** External API to drop all virtual-table modules, except those named
|
|
// ** on the azNames list.
|
|
// */
|
|
func Xsqlite3_drop_modules(tls *libc.TLS, db uintptr, azNames uintptr) (r int32) {
|
|
var ii int32
|
|
var pMod, pNext, pThis uintptr
|
|
_, _, _, _ = ii, pMod, pNext, pThis
|
|
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
pThis = (*THash)(unsafe.Pointer(db + 576)).Ffirst
|
|
for {
|
|
if !(pThis != 0) {
|
|
break
|
|
}
|
|
pMod = (*THashElem)(unsafe.Pointer(pThis)).Fdata
|
|
pNext = (*THashElem)(unsafe.Pointer(pThis)).Fnext
|
|
if azNames != 0 {
|
|
ii = 0
|
|
for {
|
|
if !(**(**uintptr)(__ccgo_up(azNames + uintptr(ii)*8)) != uintptr(0) && libc.Xstrcmp(tls, **(**uintptr)(__ccgo_up(azNames + uintptr(ii)*8)), (*TModule)(unsafe.Pointer(pMod)).FzName) != 0) {
|
|
break
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
if **(**uintptr)(__ccgo_up(azNames + uintptr(ii)*8)) != uintptr(0) {
|
|
goto _1
|
|
}
|
|
}
|
|
_createModule(tls, db, (*TModule)(unsafe.Pointer(pMod)).FzName, uintptr(0), uintptr(0), uintptr(0))
|
|
goto _1
|
|
_1:
|
|
;
|
|
pThis = pNext
|
|
}
|
|
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return TRUE (non-zero) of the statement supplied as an argument needs
|
|
// ** to be recompiled. A statement needs to be recompiled whenever the
|
|
// ** execution environment changes in a way that would alter the program
|
|
// ** that sqlite3_prepare() generates. For example, if new functions or
|
|
// ** collating sequences are registered or if an authorizer function is
|
|
// ** added or changed.
|
|
// */
|
|
func Xsqlite3_expired(tls *libc.TLS, pStmt uintptr) (r int32) {
|
|
var iRet int32
|
|
var p uintptr
|
|
_, _ = iRet, p
|
|
iRet = int32(1)
|
|
if pStmt != 0 {
|
|
p = pStmt
|
|
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer((*TVdbe)(unsafe.Pointer(p)).Fdb)).Fmutex)
|
|
iRet = int32(Tbft(*(*uint16)(unsafe.Pointer(p + 200)) & 0x3 >> 0))
|
|
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer((*TVdbe)(unsafe.Pointer(p)).Fdb)).Fmutex)
|
|
}
|
|
return iRet
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This routine frees the space the sqlite3_get_table() malloced.
|
|
// */
|
|
func Xsqlite3_free_table(tls *libc.TLS, azResult uintptr) {
|
|
var i, n int32
|
|
_, _ = i, n
|
|
if azResult != 0 {
|
|
azResult -= 8
|
|
n = int32(int64(**(**uintptr)(__ccgo_up(azResult))))
|
|
i = int32(1)
|
|
for {
|
|
if !(i < n) {
|
|
break
|
|
}
|
|
if **(**uintptr)(__ccgo_up(azResult + uintptr(i)*8)) != 0 {
|
|
Xsqlite3_free(tls, **(**uintptr)(__ccgo_up(azResult + uintptr(i)*8)))
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
Xsqlite3_free(tls, azResult)
|
|
}
|
|
}
|
|
|
|
/************** End of table.c ***********************************************/
|
|
/************** Begin file trigger.c *****************************************/
|
|
/*
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** This file contains the implementation for TRIGGERs
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Find existing client data.
|
|
// */
|
|
func Xsqlite3_get_clientdata(tls *libc.TLS, db uintptr, zName uintptr) (r uintptr) {
|
|
var p, pResult uintptr
|
|
_, _ = p, pResult
|
|
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
p = (*Tsqlite3)(unsafe.Pointer(db)).FpDbData
|
|
for {
|
|
if !(p != 0) {
|
|
break
|
|
}
|
|
if libc.Xstrcmp(tls, p+24, zName) == 0 {
|
|
pResult = (*TDbClientData)(unsafe.Pointer(p)).FpData
|
|
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
return pResult
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
p = (*TDbClientData)(unsafe.Pointer(p)).FpNext
|
|
}
|
|
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
return uintptr(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Cause any pending operation to stop at its earliest opportunity.
|
|
// */
|
|
func Xsqlite3_interrupt(tls *libc.TLS, db uintptr) {
|
|
libc.AtomicStoreNInt32(db+432, libc.Int32FromInt32(1), libc.Int32FromInt32(__ATOMIC_RELAXED))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return true or false depending on whether or not an interrupt is
|
|
// ** pending on connection db.
|
|
// */
|
|
func Xsqlite3_is_interrupted(tls *libc.TLS, db uintptr) (r int32) {
|
|
return libc.BoolInt32(libc.AtomicLoadNInt32(db+432, libc.Int32FromInt32(__ATOMIC_RELAXED)) != 0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Change the value of a limit. Report the old value.
|
|
// ** If an invalid limit index is supplied, report -1.
|
|
// ** Make no changes but still report the old value if the
|
|
// ** new limit is negative.
|
|
// **
|
|
// ** A new lower limit does not shrink existing constructs.
|
|
// ** It merely prevents new constructs that exceed the limit
|
|
// ** from forming.
|
|
// */
|
|
func Xsqlite3_limit(tls *libc.TLS, db uintptr, limitId int32, newLimit int32) (r int32) {
|
|
var oldLimit int32
|
|
_ = oldLimit
|
|
/* EVIDENCE-OF: R-30189-54097 For each limit category SQLITE_LIMIT_NAME
|
|
** there is a hard upper bound set at compile-time by a C preprocessor
|
|
** macro called SQLITE_MAX_NAME. (The "_LIMIT_" in the name is changed to
|
|
** "_MAX_".)
|
|
*/
|
|
if limitId < 0 || limitId >= libc.Int32FromInt32(SQLITE_LIMIT_PARSER_DEPTH)+libc.Int32FromInt32(1) {
|
|
return -int32(1)
|
|
}
|
|
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
oldLimit = **(**int32)(__ccgo_up(db + 136 + uintptr(limitId)*4))
|
|
if newLimit >= 0 { /* IMP: R-52476-28732 */
|
|
if newLimit > _aHardLimit[limitId] {
|
|
newLimit = _aHardLimit[limitId] /* IMP: R-51463-25634 */
|
|
} else {
|
|
if newLimit < int32(SQLITE_MIN_LENGTH) && limitId == SQLITE_LIMIT_LENGTH {
|
|
newLimit = int32(SQLITE_MIN_LENGTH)
|
|
}
|
|
}
|
|
**(**int32)(__ccgo_up(db + 136 + uintptr(limitId)*4)) = newLimit
|
|
}
|
|
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
return oldLimit /* IMP: R-53341-35419 */
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Register a profile function. The pArg from the previously registered
|
|
// ** profile function is returned.
|
|
// **
|
|
// ** A NULL profile function means that no profiling is executes. A non-NULL
|
|
// ** profile is a pointer to a function that is invoked at the conclusion of
|
|
// ** each SQL statement that is run.
|
|
// */
|
|
func Xsqlite3_profile(tls *libc.TLS, db uintptr, __ccgo_fp_xProfile uintptr, pArg uintptr) (r uintptr) {
|
|
var pOld, v1 uintptr
|
|
_, _ = pOld, v1
|
|
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
pOld = (*Tsqlite3)(unsafe.Pointer(db)).FpProfileArg
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FxProfile = __ccgo_fp_xProfile
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FpProfileArg = pArg
|
|
v1 = db + 110
|
|
*(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) & libc.Int32FromInt32(SQLITE_TRACE_NONLEGACY_MASK))
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FxProfile != 0 {
|
|
v1 = db + 110
|
|
*(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) | libc.Int32FromInt32(SQLITE_TRACE_XPROFILE))
|
|
}
|
|
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
return pOld
|
|
}
|
|
|
|
func Xsqlite3_result_subtype(tls *libc.TLS, pCtx uintptr, eSubtype uint32) {
|
|
var pOut, v1 uintptr
|
|
_, _ = pOut, v1
|
|
pOut = (*Tsqlite3_context)(unsafe.Pointer(pCtx)).FpOut
|
|
(*TMem)(unsafe.Pointer(pOut)).FeSubtype = uint8(eSubtype & uint32(0xff))
|
|
v1 = pOut + 20
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(MEM_Subtype))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Register a new geometry function for use with the r-tree MATCH operator.
|
|
// */
|
|
func Xsqlite3_rtree_geometry_callback(tls *libc.TLS, db uintptr, zGeom uintptr, __ccgo_fp_xGeom uintptr, pContext uintptr) (r int32) {
|
|
var pGeomCtx uintptr
|
|
_ = pGeomCtx /* Context object for new user-function */
|
|
/* Allocate and populate the context object. */
|
|
pGeomCtx = Xsqlite3_malloc(tls, int32(32))
|
|
if !(pGeomCtx != 0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
(*TRtreeGeomCallback)(unsafe.Pointer(pGeomCtx)).FxGeom = __ccgo_fp_xGeom
|
|
(*TRtreeGeomCallback)(unsafe.Pointer(pGeomCtx)).FxQueryFunc = uintptr(0)
|
|
(*TRtreeGeomCallback)(unsafe.Pointer(pGeomCtx)).FxDestructor = uintptr(0)
|
|
(*TRtreeGeomCallback)(unsafe.Pointer(pGeomCtx)).FpContext = pContext
|
|
return Xsqlite3_create_function_v2(tls, db, zGeom, -int32(1), int32(SQLITE_ANY), pGeomCtx, __ccgo_fp(_geomCallback), uintptr(0), uintptr(0), __ccgo_fp(_rtreeFreeCallback))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Register a new 2nd-generation geometry function for use with the
|
|
// ** r-tree MATCH operator.
|
|
// */
|
|
func Xsqlite3_rtree_query_callback(tls *libc.TLS, db uintptr, zQueryFunc uintptr, __ccgo_fp_xQueryFunc uintptr, pContext uintptr, __ccgo_fp_xDestructor uintptr) (r int32) {
|
|
var pGeomCtx uintptr
|
|
_ = pGeomCtx /* Context object for new user-function */
|
|
/* Allocate and populate the context object. */
|
|
pGeomCtx = Xsqlite3_malloc(tls, int32(32))
|
|
if !(pGeomCtx != 0) {
|
|
if __ccgo_fp_xDestructor != 0 {
|
|
(*(*func(*libc.TLS, uintptr))(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xDestructor})))(tls, pContext)
|
|
}
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
(*TRtreeGeomCallback)(unsafe.Pointer(pGeomCtx)).FxGeom = uintptr(0)
|
|
(*TRtreeGeomCallback)(unsafe.Pointer(pGeomCtx)).FxQueryFunc = __ccgo_fp_xQueryFunc
|
|
(*TRtreeGeomCallback)(unsafe.Pointer(pGeomCtx)).FxDestructor = __ccgo_fp_xDestructor
|
|
(*TRtreeGeomCallback)(unsafe.Pointer(pGeomCtx)).FpContext = pContext
|
|
return Xsqlite3_create_function_v2(tls, db, zQueryFunc, -int32(1), int32(SQLITE_ANY), pGeomCtx, __ccgo_fp(_geomCallback), uintptr(0), uintptr(0), __ccgo_fp(_rtreeFreeCallback))
|
|
}
|
|
|
|
/************** End of rtree.c ***********************************************/
|
|
/************** Begin file icu.c *********************************************/
|
|
/*
|
|
** 2007 May 6
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** $Id: icu.c,v 1.7 2007/12/13 21:54:11 drh Exp $
|
|
**
|
|
** This file implements an integration between the ICU library
|
|
** ("International Components for Unicode", an open-source library
|
|
** for handling unicode data) and SQLite. The integration uses
|
|
** ICU to provide the following to SQLite:
|
|
**
|
|
** * An implementation of the SQL regexp() function (and hence REGEXP
|
|
** operator) using the ICU uregex_XX() APIs.
|
|
**
|
|
** * Implementations of the SQL scalar upper() and lower() functions
|
|
** for case mapping.
|
|
**
|
|
** * Integration of ICU and SQLite collation sequences.
|
|
**
|
|
** * An implementation of the LIKE operator that uses ICU to
|
|
** provide case-independent matching.
|
|
*/
|
|
|
|
/************** End of icu.c *************************************************/
|
|
/************** Begin file fts3_icu.c ****************************************/
|
|
/*
|
|
** 2007 June 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 file implements a tokenizer for fts3 based on the ICU library.
|
|
*/
|
|
/* #include "fts3Int.h" */
|
|
|
|
/************** End of fts3_icu.c ********************************************/
|
|
/************** Begin file sqlite3rbu.c **************************************/
|
|
/*
|
|
** 2014 August 30
|
|
**
|
|
** 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.
|
|
**
|
|
*************************************************************************
|
|
**
|
|
**
|
|
** OVERVIEW
|
|
**
|
|
** The RBU extension requires that the RBU update be packaged as an
|
|
** SQLite database. The tables it expects to find are described in
|
|
** sqlite3rbu.h. Essentially, for each table xyz in the target database
|
|
** that the user wishes to write to, a corresponding data_xyz table is
|
|
** created in the RBU database and populated with one row for each row to
|
|
** update, insert or delete from the target table.
|
|
**
|
|
** The update proceeds in three stages:
|
|
**
|
|
** 1) The database is updated. The modified database pages are written
|
|
** to a *-oal file. A *-oal file is just like a *-wal file, except
|
|
** that it is named "<database>-oal" instead of "<database>-wal".
|
|
** Because regular SQLite clients do not look for file named
|
|
** "<database>-oal", they go on using the original database in
|
|
** rollback mode while the *-oal file is being generated.
|
|
**
|
|
** During this stage RBU does not update the database by writing
|
|
** directly to the target tables. Instead it creates "imposter"
|
|
** tables using the SQLITE_TESTCTRL_IMPOSTER interface that it uses
|
|
** to update each b-tree individually. All updates required by each
|
|
** b-tree are completed before moving on to the next, and all
|
|
** updates are done in sorted key order.
|
|
**
|
|
** 2) The "<database>-oal" file is moved to the equivalent "<database>-wal"
|
|
** location using a call to rename(2). Before doing this the RBU
|
|
** module takes an EXCLUSIVE lock on the database file, ensuring
|
|
** that there are no other active readers.
|
|
**
|
|
** Once the EXCLUSIVE lock is released, any other database readers
|
|
** detect the new *-wal file and read the database in wal mode. At
|
|
** this point they see the new version of the database - including
|
|
** the updates made as part of the RBU update.
|
|
**
|
|
** 3) The new *-wal file is checkpointed. This proceeds in the same way
|
|
** as a regular database checkpoint, except that a single frame is
|
|
** checkpointed each time sqlite3rbu_step() is called. If the RBU
|
|
** handle is closed before the entire *-wal file is checkpointed,
|
|
** the checkpoint progress is saved in the RBU database and the
|
|
** checkpoint can be resumed by another RBU client at some point in
|
|
** the future.
|
|
**
|
|
** POTENTIAL PROBLEMS
|
|
**
|
|
** The rename() call might not be portable. And RBU is not currently
|
|
** syncing the directory after renaming the file.
|
|
**
|
|
** When state is saved, any commit to the *-oal file and the commit to
|
|
** the RBU update database are not atomic. So if the power fails at the
|
|
** wrong moment they might get out of sync. As the main database will be
|
|
** committed before the RBU update database this will likely either just
|
|
** pass unnoticed, or result in SQLITE_CONSTRAINT errors (due to UNIQUE
|
|
** constraint violations).
|
|
**
|
|
** If some client does modify the target database mid RBU update, or some
|
|
** other error occurs, the RBU extension will keep throwing errors. It's
|
|
** not really clear how to get out of this state. The system could just
|
|
** by delete the RBU update database and *-oal file and have the device
|
|
** download the update again and start over.
|
|
**
|
|
** At present, for an UPDATE, both the new.* and old.* records are
|
|
** collected in the rbu_xyz table. And for both UPDATEs and DELETEs all
|
|
** fields are collected. This means we're probably writing a lot more
|
|
** data to disk when saving the state of an ongoing update to the RBU
|
|
** update database than is strictly necessary.
|
|
**
|
|
*/
|
|
|
|
/* #include <assert.h> */
|
|
/* #include <string.h> */
|
|
/* #include <stdio.h> */
|
|
|
|
/* #include "sqlite3.h" */
|
|
|
|
/************** Include sqlite3rbu.h in the middle of sqlite3rbu.c ***********/
|
|
/************** Begin file sqlite3rbu.h **************************************/
|
|
/*
|
|
** 2014 August 30
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
**
|
|
** This file contains the public interface for the RBU extension.
|
|
*/
|
|
|
|
/*
|
|
** SUMMARY
|
|
**
|
|
** Writing a transaction containing a large number of operations on
|
|
** b-tree indexes that are collectively larger than the available cache
|
|
** memory can be very inefficient.
|
|
**
|
|
** The problem is that in order to update a b-tree, the leaf page (at least)
|
|
** containing the entry being inserted or deleted must be modified. If the
|
|
** working set of leaves is larger than the available cache memory, then a
|
|
** single leaf that is modified more than once as part of the transaction
|
|
** may be loaded from or written to the persistent media multiple times.
|
|
** Additionally, because the index updates are likely to be applied in
|
|
** random order, access to pages within the database is also likely to be in
|
|
** random order, which is itself quite inefficient.
|
|
**
|
|
** One way to improve the situation is to sort the operations on each index
|
|
** by index key before applying them to the b-tree. This leads to an IO
|
|
** pattern that resembles a single linear scan through the index b-tree,
|
|
** and all but guarantees each modified leaf page is loaded and stored
|
|
** exactly once. SQLite uses this trick to improve the performance of
|
|
** CREATE INDEX commands. This extension allows it to be used to improve
|
|
** the performance of large transactions on existing databases.
|
|
**
|
|
** Additionally, this extension allows the work involved in writing the
|
|
** large transaction to be broken down into sub-transactions performed
|
|
** sequentially by separate processes. This is useful if the system cannot
|
|
** guarantee that a single update process will run for long enough to apply
|
|
** the entire update, for example because the update is being applied on a
|
|
** mobile device that is frequently rebooted. Even after the writer process
|
|
** has committed one or more sub-transactions, other database clients continue
|
|
** to read from the original database snapshot. In other words, partially
|
|
** applied transactions are not visible to other clients.
|
|
**
|
|
** "RBU" stands for "Resumable Bulk Update". As in a large database update
|
|
** transmitted via a wireless network to a mobile device. A transaction
|
|
** applied using this extension is hence referred to as an "RBU update".
|
|
**
|
|
**
|
|
** LIMITATIONS
|
|
**
|
|
** An "RBU update" transaction is subject to the following limitations:
|
|
**
|
|
** * The transaction must consist of INSERT, UPDATE and DELETE operations
|
|
** only.
|
|
**
|
|
** * INSERT statements may not use any default values.
|
|
**
|
|
** * UPDATE and DELETE statements must identify their target rows by
|
|
** non-NULL PRIMARY KEY values. Rows with NULL values stored in PRIMARY
|
|
** KEY fields may not be updated or deleted. If the table being written
|
|
** has no PRIMARY KEY, affected rows must be identified by rowid.
|
|
**
|
|
** * UPDATE statements may not modify PRIMARY KEY columns.
|
|
**
|
|
** * No triggers will be fired.
|
|
**
|
|
** * No foreign key violations are detected or reported.
|
|
**
|
|
** * CHECK constraints are not enforced.
|
|
**
|
|
** * No constraint handling mode except for "OR ROLLBACK" is supported.
|
|
**
|
|
**
|
|
** PREPARATION
|
|
**
|
|
** An "RBU update" is stored as a separate SQLite database. A database
|
|
** containing an RBU update is an "RBU database". For each table in the
|
|
** target database to be updated, the RBU database should contain a table
|
|
** named "data_<target name>" containing the same set of columns as the
|
|
** target table, and one more - "rbu_control". The data_% table should
|
|
** have no PRIMARY KEY or UNIQUE constraints, but each column should have
|
|
** the same type as the corresponding column in the target database.
|
|
** The "rbu_control" column should have no type at all. For example, if
|
|
** the target database contains:
|
|
**
|
|
** CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c UNIQUE);
|
|
**
|
|
** Then the RBU database should contain:
|
|
**
|
|
** CREATE TABLE data_t1(a INTEGER, b TEXT, c, rbu_control);
|
|
**
|
|
** The order of the columns in the data_% table does not matter.
|
|
**
|
|
** Instead of a regular table, the RBU database may also contain virtual
|
|
** tables or views named using the data_<target> naming scheme.
|
|
**
|
|
** Instead of the plain data_<target> naming scheme, RBU database tables
|
|
** may also be named data<integer>_<target>, where <integer> is any sequence
|
|
** of zero or more numeric characters (0-9). This can be significant because
|
|
** tables within the RBU database are always processed in order sorted by
|
|
** name. By judicious selection of the <integer> portion of the names
|
|
** of the RBU tables the user can therefore control the order in which they
|
|
** are processed. This can be useful, for example, to ensure that "external
|
|
** content" FTS4 tables are updated before their underlying content tables.
|
|
**
|
|
** If the target database table is a virtual table or a table that has no
|
|
** PRIMARY KEY declaration, the data_% table must also contain a column
|
|
** named "rbu_rowid". This column is mapped to the table's implicit primary
|
|
** key column - "rowid". Virtual tables for which the "rowid" column does
|
|
** not function like a primary key value cannot be updated using RBU. For
|
|
** example, if the target db contains either of the following:
|
|
**
|
|
** CREATE VIRTUAL TABLE x1 USING fts3(a, b);
|
|
** CREATE TABLE x1(a, b)
|
|
**
|
|
** then the RBU database should contain:
|
|
**
|
|
** CREATE TABLE data_x1(a, b, rbu_rowid, rbu_control);
|
|
**
|
|
** All non-hidden columns (i.e. all columns matched by "SELECT *") of the
|
|
** target table must be present in the input table. For virtual tables,
|
|
** hidden columns are optional - they are updated by RBU if present in
|
|
** the input table, or not otherwise. For example, to write to an fts4
|
|
** table with a hidden languageid column such as:
|
|
**
|
|
** CREATE VIRTUAL TABLE ft1 USING fts4(a, b, languageid='langid');
|
|
**
|
|
** Either of the following input table schemas may be used:
|
|
**
|
|
** CREATE TABLE data_ft1(a, b, langid, rbu_rowid, rbu_control);
|
|
** CREATE TABLE data_ft1(a, b, rbu_rowid, rbu_control);
|
|
**
|
|
** For each row to INSERT into the target database as part of the RBU
|
|
** update, the corresponding data_% table should contain a single record
|
|
** with the "rbu_control" column set to contain integer value 0. The
|
|
** other columns should be set to the values that make up the new record
|
|
** to insert.
|
|
**
|
|
** If the target database table has an INTEGER PRIMARY KEY, it is not
|
|
** possible to insert a NULL value into the IPK column. Attempting to
|
|
** do so results in an SQLITE_MISMATCH error.
|
|
**
|
|
** For each row to DELETE from the target database as part of the RBU
|
|
** update, the corresponding data_% table should contain a single record
|
|
** with the "rbu_control" column set to contain integer value 1. The
|
|
** real primary key values of the row to delete should be stored in the
|
|
** corresponding columns of the data_% table. The values stored in the
|
|
** other columns are not used.
|
|
**
|
|
** For each row to UPDATE from the target database as part of the RBU
|
|
** update, the corresponding data_% table should contain a single record
|
|
** with the "rbu_control" column set to contain a value of type text.
|
|
** The real primary key values identifying the row to update should be
|
|
** stored in the corresponding columns of the data_% table row, as should
|
|
** the new values of all columns being update. The text value in the
|
|
** "rbu_control" column must contain the same number of characters as
|
|
** there are columns in the target database table, and must consist entirely
|
|
** of 'x' and '.' characters (or in some special cases 'd' - see below). For
|
|
** each column that is being updated, the corresponding character is set to
|
|
** 'x'. For those that remain as they are, the corresponding character of the
|
|
** rbu_control value should be set to '.'. For example, given the tables
|
|
** above, the update statement:
|
|
**
|
|
** UPDATE t1 SET c = 'usa' WHERE a = 4;
|
|
**
|
|
** is represented by the data_t1 row created by:
|
|
**
|
|
** INSERT INTO data_t1(a, b, c, rbu_control) VALUES(4, NULL, 'usa', '..x');
|
|
**
|
|
** Instead of an 'x' character, characters of the rbu_control value specified
|
|
** for UPDATEs may also be set to 'd'. In this case, instead of updating the
|
|
** target table with the value stored in the corresponding data_% column, the
|
|
** user-defined SQL function "rbu_delta()" is invoked and the result stored in
|
|
** the target table column. rbu_delta() is invoked with two arguments - the
|
|
** original value currently stored in the target table column and the
|
|
** value specified in the data_xxx table.
|
|
**
|
|
** For example, this row:
|
|
**
|
|
** INSERT INTO data_t1(a, b, c, rbu_control) VALUES(4, NULL, 'usa', '..d');
|
|
**
|
|
** is similar to an UPDATE statement such as:
|
|
**
|
|
** UPDATE t1 SET c = rbu_delta(c, 'usa') WHERE a = 4;
|
|
**
|
|
** Finally, if an 'f' character appears in place of a 'd' or 's' in an
|
|
** ota_control string, the contents of the data_xxx table column is assumed
|
|
** to be a "fossil delta" - a patch to be applied to a blob value in the
|
|
** format used by the fossil source-code management system. In this case
|
|
** the existing value within the target database table must be of type BLOB.
|
|
** It is replaced by the result of applying the specified fossil delta to
|
|
** itself.
|
|
**
|
|
** If the target database table is a virtual table or a table with no PRIMARY
|
|
** KEY, the rbu_control value should not include a character corresponding
|
|
** to the rbu_rowid value. For example, this:
|
|
**
|
|
** INSERT INTO data_ft1(a, b, rbu_rowid, rbu_control)
|
|
** VALUES(NULL, 'usa', 12, '.x');
|
|
**
|
|
** causes a result similar to:
|
|
**
|
|
** UPDATE ft1 SET b = 'usa' WHERE rowid = 12;
|
|
**
|
|
** The data_xxx tables themselves should have no PRIMARY KEY declarations.
|
|
** However, RBU is more efficient if reading the rows in from each data_xxx
|
|
** table in "rowid" order is roughly the same as reading them sorted by
|
|
** the PRIMARY KEY of the corresponding target database table. In other
|
|
** words, rows should be sorted using the destination table PRIMARY KEY
|
|
** fields before they are inserted into the data_xxx tables.
|
|
**
|
|
** USAGE
|
|
**
|
|
** The API declared below allows an application to apply an RBU update
|
|
** stored on disk to an existing target database. Essentially, the
|
|
** application:
|
|
**
|
|
** 1) Opens an RBU handle using the sqlite3rbu_open() function.
|
|
**
|
|
** 2) Registers any required virtual table modules with the database
|
|
** handle returned by sqlite3rbu_db(). Also, if required, register
|
|
** the rbu_delta() implementation.
|
|
**
|
|
** 3) Calls the sqlite3rbu_step() function one or more times on
|
|
** the new handle. Each call to sqlite3rbu_step() performs a single
|
|
** b-tree operation, so thousands of calls may be required to apply
|
|
** a complete update.
|
|
**
|
|
** 4) Calls sqlite3rbu_close() to close the RBU update handle. If
|
|
** sqlite3rbu_step() has been called enough times to completely
|
|
** apply the update to the target database, then the RBU database
|
|
** is marked as fully applied. Otherwise, the state of the RBU
|
|
** update application is saved in the RBU database for later
|
|
** resumption.
|
|
**
|
|
** See comments below for more detail on APIs.
|
|
**
|
|
** If an update is only partially applied to the target database by the
|
|
** time sqlite3rbu_close() is called, various state information is saved
|
|
** within the RBU database. This allows subsequent processes to automatically
|
|
** resume the RBU update from where it left off.
|
|
**
|
|
** To remove all RBU extension state information, returning an RBU database
|
|
** to its original contents, it is sufficient to drop all tables that begin
|
|
** with the prefix "rbu_"
|
|
**
|
|
** DATABASE LOCKING
|
|
**
|
|
** An RBU update may not be applied to a database in WAL mode. Attempting
|
|
** to do so is an error (SQLITE_ERROR).
|
|
**
|
|
** While an RBU handle is open, a SHARED lock may be held on the target
|
|
** database file. This means it is possible for other clients to read the
|
|
** database, but not to write it.
|
|
**
|
|
** If an RBU update is started and then suspended before it is completed,
|
|
** then an external client writes to the database, then attempting to resume
|
|
** the suspended RBU update is also an error (SQLITE_BUSY).
|
|
*/
|
|
|
|
/* #include "sqlite3.h" ** Required for error code definitions ** */
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Set the auxiliary data pointer and delete function, for the iArg'th
|
|
// ** argument to the user-function defined by pCtx. Any previous value is
|
|
// ** deleted by calling the delete function specified when it was set.
|
|
// **
|
|
// ** The left-most argument is 0.
|
|
// **
|
|
// ** Undocumented behavior: If iArg is negative then make the data available
|
|
// ** to all functions within the current prepared statement using iArg as an
|
|
// ** access code.
|
|
// */
|
|
func Xsqlite3_set_auxdata(tls *libc.TLS, pCtx uintptr, iArg int32, pAux uintptr, __ccgo_fp_xDelete uintptr) {
|
|
var pAuxData, pVdbe uintptr
|
|
_, _ = pAuxData, pVdbe
|
|
pVdbe = (*Tsqlite3_context)(unsafe.Pointer(pCtx)).FpVdbe
|
|
if pVdbe == uintptr(0) {
|
|
goto failed
|
|
}
|
|
pAuxData = (*TVdbe)(unsafe.Pointer(pVdbe)).FpAuxData
|
|
for {
|
|
if !(pAuxData != 0) {
|
|
break
|
|
}
|
|
if (*TAuxData)(unsafe.Pointer(pAuxData)).FiAuxArg == iArg && ((*TAuxData)(unsafe.Pointer(pAuxData)).FiAuxOp == (*Tsqlite3_context)(unsafe.Pointer(pCtx)).FiOp || iArg < 0) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pAuxData = (*TAuxData)(unsafe.Pointer(pAuxData)).FpNextAux
|
|
}
|
|
if pAuxData == uintptr(0) {
|
|
pAuxData = _sqlite3DbMallocZero(tls, (*TVdbe)(unsafe.Pointer(pVdbe)).Fdb, uint64(32))
|
|
if !(pAuxData != 0) {
|
|
goto failed
|
|
}
|
|
(*TAuxData)(unsafe.Pointer(pAuxData)).FiAuxOp = (*Tsqlite3_context)(unsafe.Pointer(pCtx)).FiOp
|
|
(*TAuxData)(unsafe.Pointer(pAuxData)).FiAuxArg = iArg
|
|
(*TAuxData)(unsafe.Pointer(pAuxData)).FpNextAux = (*TVdbe)(unsafe.Pointer(pVdbe)).FpAuxData
|
|
(*TVdbe)(unsafe.Pointer(pVdbe)).FpAuxData = pAuxData
|
|
if (*Tsqlite3_context)(unsafe.Pointer(pCtx)).FisError == 0 {
|
|
(*Tsqlite3_context)(unsafe.Pointer(pCtx)).FisError = -int32(1)
|
|
}
|
|
} else {
|
|
if (*TAuxData)(unsafe.Pointer(pAuxData)).FxDeleteAux != 0 {
|
|
(*(*func(*libc.TLS, uintptr))(unsafe.Pointer(&struct{ uintptr }{(*TAuxData)(unsafe.Pointer(pAuxData)).FxDeleteAux})))(tls, (*TAuxData)(unsafe.Pointer(pAuxData)).FpAux)
|
|
}
|
|
}
|
|
(*TAuxData)(unsafe.Pointer(pAuxData)).FpAux = pAux
|
|
(*TAuxData)(unsafe.Pointer(pAuxData)).FxDeleteAux = __ccgo_fp_xDelete
|
|
return
|
|
goto failed
|
|
failed:
|
|
;
|
|
if __ccgo_fp_xDelete != 0 {
|
|
(*(*func(*libc.TLS, uintptr))(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xDelete})))(tls, pAux)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Undo the effects of sqlite3_initialize(). Must not be called while
|
|
// ** there are outstanding database connections or memory allocations or
|
|
// ** while any part of SQLite is otherwise in use in any thread. This
|
|
// ** routine is not threadsafe. But it is safe to invoke this routine
|
|
// ** on when SQLite is already shut down. If SQLite is already shut down
|
|
// ** when this routine is invoked, then this routine is a harmless no-op.
|
|
// */
|
|
func Xsqlite3_shutdown(tls *libc.TLS) (r int32) {
|
|
if libc.AtomicLoadPInt32(uintptr(unsafe.Pointer(&_sqlite3Config))+340) != 0 {
|
|
Xsqlite3_os_end(tls)
|
|
Xsqlite3_reset_auto_extension(tls)
|
|
libc.AtomicStorePInt32(uintptr(unsafe.Pointer(&_sqlite3Config))+340, 0)
|
|
}
|
|
if _sqlite3Config.FisPCacheInit != 0 {
|
|
_sqlite3PcacheShutdown(tls)
|
|
_sqlite3Config.FisPCacheInit = 0
|
|
}
|
|
if _sqlite3Config.FisMallocInit != 0 {
|
|
_sqlite3MallocEnd(tls)
|
|
_sqlite3Config.FisMallocInit = 0
|
|
/* The heap subsystem has now been shutdown and these values are supposed
|
|
** to be NULL or point to memory that was obtained from sqlite3_malloc(),
|
|
** which would rely on that heap subsystem; therefore, make sure these
|
|
** values cannot refer to heap memory that was just invalidated when the
|
|
** heap subsystem was shutdown. This is only done if the current call to
|
|
** this function resulted in the heap subsystem actually being shutdown.
|
|
*/
|
|
Xsqlite3_data_directory = uintptr(0)
|
|
Xsqlite3_temp_directory = uintptr(0)
|
|
}
|
|
if _sqlite3Config.FisMutexInit != 0 {
|
|
_sqlite3MutexEnd(tls)
|
|
_sqlite3Config.FisMutexInit = 0
|
|
}
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Recover as many snapshots as possible from the wal file associated with
|
|
// ** schema zDb of database db.
|
|
// */
|
|
func Xsqlite3_snapshot_recover(tls *libc.TLS, db uintptr, zDb uintptr) (r int32) {
|
|
var iDb, rc int32
|
|
var pBt uintptr
|
|
_, _, _ = iDb, pBt, rc
|
|
rc = int32(SQLITE_ERROR)
|
|
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
iDb = _sqlite3FindDbName(tls, db, zDb)
|
|
if iDb == 0 || iDb > int32(1) {
|
|
pBt = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FpBt
|
|
if SQLITE_TXN_NONE == _sqlite3BtreeTxnState(tls, pBt) {
|
|
rc = _sqlite3BtreeBeginTrans(tls, pBt, 0, uintptr(0))
|
|
if rc == SQLITE_OK {
|
|
rc = _sqlite3PagerSnapshotRecover(tls, _sqlite3BtreePager(tls, pBt))
|
|
_sqlite3BtreeCommit(tls, pBt)
|
|
}
|
|
}
|
|
}
|
|
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return 1 if the statement is an EXPLAIN and return 2 if the
|
|
// ** statement is an EXPLAIN QUERY PLAN
|
|
// */
|
|
func Xsqlite3_stmt_isexplain(tls *libc.TLS, pStmt uintptr) (r int32) {
|
|
var v1 int32
|
|
_ = v1
|
|
if pStmt != 0 {
|
|
v1 = int32(Tbft(*(*uint16)(unsafe.Pointer(pStmt + 200)) & 0xc >> 2))
|
|
} else {
|
|
v1 = 0
|
|
}
|
|
return v1
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return true if the prepared statement is guaranteed to not modify the
|
|
// ** database.
|
|
// */
|
|
func Xsqlite3_stmt_readonly(tls *libc.TLS, pStmt uintptr) (r int32) {
|
|
var v1 int32
|
|
_ = v1
|
|
if pStmt != 0 {
|
|
v1 = int32(Tbft(*(*uint16)(unsafe.Pointer(pStmt + 200)) & 0x40 >> 6))
|
|
} else {
|
|
v1 = int32(1)
|
|
}
|
|
return v1
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Allocate and initialize a new dynamic string object */
|
|
func Xsqlite3_str_new(tls *libc.TLS, db uintptr) (r uintptr) {
|
|
var p uintptr
|
|
var v1 int32
|
|
_, _ = p, v1
|
|
p = Xsqlite3_malloc64(tls, uint64(32))
|
|
if p != 0 {
|
|
if db != 0 {
|
|
v1 = **(**int32)(__ccgo_up(db + 136))
|
|
} else {
|
|
v1 = int32(SQLITE_MAX_LENGTH)
|
|
}
|
|
_sqlite3StrAccumInit(tls, p, uintptr(0), uintptr(0), 0, v1)
|
|
} else {
|
|
p = uintptr(unsafe.Pointer(&_sqlite3OomStr))
|
|
}
|
|
return p
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Register a trace callback using the version-2 interface.
|
|
// */
|
|
func Xsqlite3_trace_v2(tls *libc.TLS, db uintptr, mTrace uint32, __ccgo_fp_xTrace uintptr, pArg uintptr) (r int32) {
|
|
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
if mTrace == uint32(0) {
|
|
__ccgo_fp_xTrace = uintptr(0)
|
|
}
|
|
if __ccgo_fp_xTrace == uintptr(0) {
|
|
mTrace = uint32(0)
|
|
}
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FmTrace = uint8(mTrace)
|
|
*(*uintptr)(unsafe.Pointer(db + 248)) = __ccgo_fp_xTrace
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FpTraceArg = pArg
|
|
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Deprecated external interface. Internal/core SQLite code
|
|
// ** should call sqlite3TransferBindings.
|
|
// **
|
|
// ** It is misuse to call this routine with statements from different
|
|
// ** database connections. But as this is a deprecated interface, we
|
|
// ** will not bother to check for that condition.
|
|
// **
|
|
// ** If the two statements contain a different number of bindings, then
|
|
// ** an SQLITE_ERROR is returned. Nothing else can go wrong, so otherwise
|
|
// ** SQLITE_OK is returned.
|
|
// */
|
|
func Xsqlite3_transfer_bindings(tls *libc.TLS, pFromStmt uintptr, pToStmt uintptr) (r int32) {
|
|
var pFrom, pTo uintptr
|
|
_, _ = pFrom, pTo
|
|
pFrom = pFromStmt
|
|
pTo = pToStmt
|
|
if int32((*TVdbe)(unsafe.Pointer(pFrom)).FnVar) != int32((*TVdbe)(unsafe.Pointer(pTo)).FnVar) {
|
|
return int32(SQLITE_ERROR)
|
|
}
|
|
if (*TVdbe)(unsafe.Pointer(pTo)).Fexpmask != 0 {
|
|
libc.SetBitFieldPtr16Uint32(pTo+200, libc.Uint32FromInt32(1), 0, 0x3)
|
|
}
|
|
if (*TVdbe)(unsafe.Pointer(pFrom)).Fexpmask != 0 {
|
|
libc.SetBitFieldPtr16Uint32(pFrom+200, libc.Uint32FromInt32(1), 0, 0x3)
|
|
}
|
|
return _sqlite3TransferBindings(tls, pFromStmt, pToStmt)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the transaction state for a single databse, or the maximum
|
|
// ** transaction state over all attached databases if zSchema is null.
|
|
// */
|
|
func Xsqlite3_txn_state(tls *libc.TLS, db uintptr, zSchema uintptr) (r int32) {
|
|
var iDb, iTxn, nDb, x, v1 int32
|
|
var pBt uintptr
|
|
_, _, _, _, _, _ = iDb, iTxn, nDb, pBt, x, v1
|
|
iTxn = -int32(1)
|
|
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
if zSchema != 0 {
|
|
v1 = _sqlite3FindDbName(tls, db, zSchema)
|
|
iDb = v1
|
|
nDb = v1
|
|
if iDb < 0 {
|
|
nDb = nDb - 1
|
|
}
|
|
} else {
|
|
iDb = 0
|
|
nDb = (*Tsqlite3)(unsafe.Pointer(db)).FnDb - int32(1)
|
|
}
|
|
for {
|
|
if !(iDb <= nDb) {
|
|
break
|
|
}
|
|
pBt = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FpBt
|
|
if pBt != uintptr(0) {
|
|
v1 = _sqlite3BtreeTxnState(tls, pBt)
|
|
} else {
|
|
v1 = SQLITE_TXN_NONE
|
|
}
|
|
x = v1
|
|
if x > iTxn {
|
|
iTxn = x
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
iDb = iDb + 1
|
|
}
|
|
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
return iTxn
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the collating sequence for a constraint passed into xBestIndex.
|
|
// **
|
|
// ** pIdxInfo must be an sqlite3_index_info structure passed into xBestIndex.
|
|
// ** This routine depends on there being a HiddenIndexInfo structure immediately
|
|
// ** following the sqlite3_index_info structure.
|
|
// **
|
|
// ** Return a pointer to the collation name:
|
|
// **
|
|
// ** 1. If there is an explicit COLLATE operator on the constraint, return it.
|
|
// **
|
|
// ** 2. Else, if the column has an alternative collation, return that.
|
|
// **
|
|
// ** 3. Otherwise, return "BINARY".
|
|
// */
|
|
func Xsqlite3_vtab_collation(tls *libc.TLS, pIdxInfo uintptr, iCons int32) (r uintptr) {
|
|
var iTerm int32
|
|
var pC, pHidden, pX, zRet, v1 uintptr
|
|
_, _, _, _, _, _ = iTerm, pC, pHidden, pX, zRet, v1
|
|
pHidden = pIdxInfo + 1*96
|
|
zRet = uintptr(0)
|
|
if iCons >= 0 && iCons < (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FnConstraint {
|
|
pC = uintptr(0)
|
|
iTerm = (**(**Tsqlite3_index_constraint)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraint + uintptr(iCons)*12))).FiTermOffset
|
|
pX = (*TWhereTerm)(unsafe.Pointer(_termFromWhereClause(tls, (*THiddenIndexInfo)(unsafe.Pointer(pHidden)).FpWC, iTerm))).FpExpr
|
|
if (*TExpr)(unsafe.Pointer(pX)).FpLeft != 0 {
|
|
pC = _sqlite3ExprCompareCollSeq(tls, (*THiddenIndexInfo)(unsafe.Pointer(pHidden)).FpParse, pX)
|
|
}
|
|
if pC != 0 {
|
|
v1 = (*TCollSeq)(unsafe.Pointer(pC)).FzName
|
|
} else {
|
|
v1 = uintptr(unsafe.Pointer(&_sqlite3StrBINARY))
|
|
}
|
|
zRet = v1
|
|
}
|
|
return zRet
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return true if ORDER BY clause may be handled as DISTINCT.
|
|
// */
|
|
func Xsqlite3_vtab_distinct(tls *libc.TLS, pIdxInfo uintptr) (r int32) {
|
|
var pHidden uintptr
|
|
_ = pHidden
|
|
pHidden = pIdxInfo + 1*96
|
|
return (*THiddenIndexInfo)(unsafe.Pointer(pHidden)).FeDistinct
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return true if constraint iCons is really an IN(...) constraint, or
|
|
// ** false otherwise. If iCons is an IN(...) constraint, set (if bHandle!=0)
|
|
// ** or clear (if bHandle==0) the flag to handle it using an iterator.
|
|
// */
|
|
func Xsqlite3_vtab_in(tls *libc.TLS, pIdxInfo uintptr, iCons int32, bHandle int32) (r int32) {
|
|
var m Tu32
|
|
var pHidden uintptr
|
|
var v1 uint32
|
|
_, _, _ = m, pHidden, v1
|
|
pHidden = pIdxInfo + 1*96
|
|
if iCons <= int32(31) {
|
|
v1 = libc.Uint32FromInt32(1) << iCons
|
|
} else {
|
|
v1 = uint32(0)
|
|
}
|
|
m = v1
|
|
if m&(*THiddenIndexInfo)(unsafe.Pointer(pHidden)).FmIn != 0 {
|
|
if bHandle == 0 {
|
|
**(**Tu32)(__ccgo_up(pHidden + 24)) &= ^m
|
|
} else {
|
|
if bHandle > 0 {
|
|
**(**Tu32)(__ccgo_up(pHidden + 24)) |= m
|
|
}
|
|
}
|
|
return int32(1)
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This interface is callable from within the xBestIndex callback only.
|
|
// **
|
|
// ** If possible, set (*ppVal) to point to an object containing the value
|
|
// ** on the right-hand-side of constraint iCons.
|
|
// */
|
|
func Xsqlite3_vtab_rhs_value(tls *libc.TLS, pIdxInfo uintptr, iCons int32, ppVal uintptr) (r int32) {
|
|
var pH, pTerm, pVal uintptr
|
|
var rc int32
|
|
_, _, _, _ = pH, pTerm, pVal, rc
|
|
pH = pIdxInfo + 1*96
|
|
pVal = uintptr(0)
|
|
rc = SQLITE_OK
|
|
if iCons < 0 || iCons >= (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FnConstraint {
|
|
rc = _sqlite3MisuseError(tls, int32(173448)) /* EV: R-30545-25046 */
|
|
} else {
|
|
if *(*uintptr)(unsafe.Pointer(pH + 32 + uintptr(iCons)*8)) == uintptr(0) {
|
|
pTerm = _termFromWhereClause(tls, (*THiddenIndexInfo)(unsafe.Pointer(pH)).FpWC, (**(**Tsqlite3_index_constraint)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraint + uintptr(iCons)*12))).FiTermOffset)
|
|
rc = _sqlite3ValueFromExpr(tls, (*TParse)(unsafe.Pointer((*THiddenIndexInfo)(unsafe.Pointer(pH)).FpParse)).Fdb, (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr)).FpRight, (*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer((*THiddenIndexInfo)(unsafe.Pointer(pH)).FpParse)).Fdb)).Fenc, uint8(SQLITE_AFF_BLOB), pH+32+uintptr(iCons)*8)
|
|
}
|
|
pVal = *(*uintptr)(unsafe.Pointer(pH + 32 + uintptr(iCons)*8))
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppVal)) = pVal
|
|
if rc == SQLITE_OK && pVal == uintptr(0) { /* IMP: R-19933-32160 */
|
|
rc = int32(SQLITE_NOTFOUND) /* IMP: R-36424-56542 */
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Configure an sqlite3_wal_hook() callback to automatically checkpoint
|
|
// ** a database after committing a transaction if there are nFrame or
|
|
// ** more frames in the log file. Passing zero or a negative value as the
|
|
// ** nFrame parameter disables automatic checkpoints entirely.
|
|
// **
|
|
// ** The callback registered by this function replaces any existing callback
|
|
// ** registered using sqlite3_wal_hook(). Likewise, registering a callback
|
|
// ** using sqlite3_wal_hook() disables the automatic checkpoint mechanism
|
|
// ** configured by this function.
|
|
// */
|
|
func Xsqlite3_wal_autocheckpoint(tls *libc.TLS, db uintptr, nFrame int32) (r int32) {
|
|
if nFrame > 0 {
|
|
Xsqlite3_wal_hook(tls, db, __ccgo_fp(_sqlite3WalDefaultHook), uintptr(int64(nFrame)))
|
|
} else {
|
|
Xsqlite3_wal_hook(tls, db, uintptr(0), uintptr(0))
|
|
}
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Delete a changegroup object.
|
|
// */
|
|
func Xsqlite3changegroup_delete(tls *libc.TLS, pGrp uintptr) {
|
|
var ii int32
|
|
_ = ii
|
|
if pGrp != 0 {
|
|
ii = 0
|
|
for {
|
|
if !(ii < (*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).Fcd.FnBufAlloc) {
|
|
break
|
|
}
|
|
Xsqlite3_free(tls, (**(**TSessionBuffer)(__ccgo_up((*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).Fcd.FaBuf + uintptr(ii)*16))).FaBuf)
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
Xsqlite3_free(tls, (*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).Fcd.Frecord.FaBuf)
|
|
Xsqlite3_free(tls, (*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).Fcd.FaBuf)
|
|
Xsqlite3_free(tls, (*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).FzDb)
|
|
_sessionDeleteTable(tls, uintptr(0), (*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).FpList)
|
|
Xsqlite3_free(tls, (*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).Frec.FaBuf)
|
|
Xsqlite3_free(tls, pGrp)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Finalize an iterator allocated with sqlite3changeset_start().
|
|
// **
|
|
// ** This function may not be called on iterators passed to a conflict handler
|
|
// ** callback by changeset_apply().
|
|
// */
|
|
func Xsqlite3changeset_finalize(tls *libc.TLS, p uintptr) (r int32) {
|
|
var i, rc int32
|
|
_, _ = i, rc
|
|
rc = SQLITE_OK
|
|
if p != 0 { /* Used to iterate through p->apValue[] */
|
|
rc = (*Tsqlite3_changeset_iter)(unsafe.Pointer(p)).Frc
|
|
if (*Tsqlite3_changeset_iter)(unsafe.Pointer(p)).FapValue != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*Tsqlite3_changeset_iter)(unsafe.Pointer(p)).FnCol*int32(2)) {
|
|
break
|
|
}
|
|
_sqlite3ValueFree(tls, **(**uintptr)(__ccgo_up((*Tsqlite3_changeset_iter)(unsafe.Pointer(p)).FapValue + uintptr(i)*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
Xsqlite3_free(tls, (*Tsqlite3_changeset_iter)(unsafe.Pointer(p)).Ftblhdr.FaBuf)
|
|
Xsqlite3_free(tls, (*Tsqlite3_changeset_iter)(unsafe.Pointer(p)).Fin.Fbuf.FaBuf)
|
|
Xsqlite3_free(tls, p)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function may only be called while the iterator is pointing to an
|
|
// ** SQLITE_UPDATE or SQLITE_INSERT change (see sqlite3changeset_op()).
|
|
// ** Otherwise, SQLITE_MISUSE is returned.
|
|
// **
|
|
// ** It sets *ppValue to point to an sqlite3_value structure containing the
|
|
// ** iVal'th value in the new.* record. Or, if that particular value is not
|
|
// ** included in the record (because the change is an UPDATE and the field
|
|
// ** was not modified), set *ppValue to NULL.
|
|
// **
|
|
// ** If value iVal is out-of-range, SQLITE_RANGE is returned and *ppValue is
|
|
// ** not modified. Otherwise, SQLITE_OK.
|
|
// */
|
|
func Xsqlite3changeset_new(tls *libc.TLS, pIter uintptr, iVal int32, ppValue uintptr) (r int32) {
|
|
if (*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).Fop != int32(SQLITE_UPDATE) && (*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).Fop != int32(SQLITE_INSERT) {
|
|
return int32(SQLITE_MISUSE)
|
|
}
|
|
if iVal < 0 || iVal >= (*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).FnCol {
|
|
return int32(SQLITE_RANGE)
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppValue)) = **(**uintptr)(__ccgo_up((*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).FapValue + uintptr((*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).FnCol+iVal)*8))
|
|
return SQLITE_OK
|
|
}
|
|
|
|
/*
|
|
** The following two macros are used internally. They are similar to the
|
|
** sqlite3changeset_new() and sqlite3changeset_old() functions, except that
|
|
** they omit all error checking and return a pointer to the requested value.
|
|
*/
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function may only be called while the iterator is pointing to an
|
|
// ** SQLITE_UPDATE or SQLITE_DELETE change (see sqlite3changeset_op()).
|
|
// ** Otherwise, SQLITE_MISUSE is returned.
|
|
// **
|
|
// ** It sets *ppValue to point to an sqlite3_value structure containing the
|
|
// ** iVal'th value in the old.* record. Or, if that particular value is not
|
|
// ** included in the record (because the change is an UPDATE and the field
|
|
// ** was not modified and is not a PK column), set *ppValue to NULL.
|
|
// **
|
|
// ** If value iVal is out-of-range, SQLITE_RANGE is returned and *ppValue is
|
|
// ** not modified. Otherwise, SQLITE_OK.
|
|
// */
|
|
func Xsqlite3changeset_old(tls *libc.TLS, pIter uintptr, iVal int32, ppValue uintptr) (r int32) {
|
|
if (*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).Fop != int32(SQLITE_UPDATE) && (*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).Fop != int32(SQLITE_DELETE) {
|
|
return int32(SQLITE_MISUSE)
|
|
}
|
|
if iVal < 0 || iVal >= (*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).FnCol {
|
|
return int32(SQLITE_RANGE)
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppValue)) = **(**uintptr)(__ccgo_up((*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).FapValue + uintptr(iVal)*8))
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Delete a session object previously allocated using sqlite3session_create().
|
|
// */
|
|
func Xsqlite3session_delete(tls *libc.TLS, pSession uintptr) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var db, pp uintptr
|
|
var _ /* pHead at bp+0 */ uintptr
|
|
_, _ = db, pp
|
|
db = (*Tsqlite3_session)(unsafe.Pointer(pSession)).Fdb
|
|
/* Unlink the session from the linked list of sessions attached to the
|
|
** database handle. Hold the db mutex while doing so. */
|
|
Xsqlite3_mutex_enter(tls, Xsqlite3_db_mutex(tls, db))
|
|
**(**uintptr)(__ccgo_up(bp)) = Xsqlite3_preupdate_hook(tls, db, uintptr(0), uintptr(0))
|
|
pp = bp
|
|
for {
|
|
if !(**(**uintptr)(__ccgo_up(pp)) != uintptr(0)) {
|
|
break
|
|
}
|
|
if **(**uintptr)(__ccgo_up(pp)) == pSession {
|
|
**(**uintptr)(__ccgo_up(pp)) = (*Tsqlite3_session)(unsafe.Pointer(**(**uintptr)(__ccgo_up(pp)))).FpNext
|
|
if **(**uintptr)(__ccgo_up(bp)) != 0 {
|
|
Xsqlite3_preupdate_hook(tls, db, __ccgo_fp(_xPreUpdate), **(**uintptr)(__ccgo_up(bp)))
|
|
}
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pp = **(**uintptr)(__ccgo_up(pp)) + 80
|
|
}
|
|
Xsqlite3_mutex_leave(tls, Xsqlite3_db_mutex(tls, db))
|
|
_sqlite3ValueFree(tls, (*Tsqlite3_session)(unsafe.Pointer(pSession)).FpZeroBlob)
|
|
/* Delete all attached table objects. And the contents of their
|
|
** associated hash-tables. */
|
|
_sessionDeleteTable(tls, pSession, (*Tsqlite3_session)(unsafe.Pointer(pSession)).FpTable)
|
|
/* Free the session object. */
|
|
Xsqlite3_free(tls, pSession)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function implements the ChooseLeaf algorithm from Gutman[84].
|
|
// ** ChooseSubTree in r*tree terminology.
|
|
// */
|
|
func _ChooseLeaf(tls *libc.TLS, pRtree uintptr, pCell uintptr, iHeight int32, ppLeaf uintptr) (r int32) {
|
|
bp := tls.Alloc(112)
|
|
defer tls.Free(112)
|
|
var area, area1, fMinArea, fMinGrowth, growth TRtreeDValue
|
|
var bFound, iCell, ii, nCell, rc int32
|
|
var iBest Tsqlite3_int64
|
|
var _ /* cell at bp+16 */ TRtreeCell
|
|
var _ /* cell at bp+64 */ TRtreeCell
|
|
var _ /* pChild at bp+8 */ uintptr
|
|
var _ /* pNode at bp+0 */ uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _ = area, area1, bFound, fMinArea, fMinGrowth, growth, iBest, iCell, ii, nCell, rc
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
rc = _nodeAcquire(tls, pRtree, int64(1), uintptr(0), bp)
|
|
ii = 0
|
|
for {
|
|
if !(rc == SQLITE_OK && ii < (*TRtree)(unsafe.Pointer(pRtree)).FiDepth-iHeight) {
|
|
break
|
|
}
|
|
iBest = 0
|
|
bFound = 0
|
|
fMinGrowth = float64(0)
|
|
fMinArea = float64(0)
|
|
nCell = _readInt16(tls, (*TRtreeNode)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FzData+2)
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = uintptr(0)
|
|
/* First check to see if there is are any cells in pNode that completely
|
|
** contains pCell. If two or more cells in pNode completely contain pCell
|
|
** then pick the smallest.
|
|
*/
|
|
iCell = 0
|
|
for {
|
|
if !(iCell < nCell) {
|
|
break
|
|
}
|
|
_nodeGetCell(tls, pRtree, **(**uintptr)(__ccgo_up(bp)), iCell, bp+16)
|
|
if _cellContains(tls, pRtree, bp+16, pCell) != 0 {
|
|
area = _cellArea(tls, pRtree, bp+16)
|
|
if bFound == 0 || area < fMinArea {
|
|
iBest = (**(**TRtreeCell)(__ccgo_up(bp + 16))).FiRowid
|
|
fMinArea = area
|
|
bFound = int32(1)
|
|
}
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
iCell = iCell + 1
|
|
}
|
|
if !(bFound != 0) {
|
|
/* No cells of pNode will completely contain pCell. So pick the
|
|
** cell of pNode that grows by the least amount when pCell is added.
|
|
** Break ties by selecting the smaller cell.
|
|
*/
|
|
iCell = 0
|
|
for {
|
|
if !(iCell < nCell) {
|
|
break
|
|
}
|
|
_nodeGetCell(tls, pRtree, **(**uintptr)(__ccgo_up(bp)), iCell, bp+64)
|
|
area1 = _cellArea(tls, pRtree, bp+64)
|
|
_cellUnion(tls, pRtree, bp+64, pCell)
|
|
growth = _cellArea(tls, pRtree, bp+64) - area1
|
|
if iCell == 0 || growth < fMinGrowth || growth == fMinGrowth && area1 < fMinArea {
|
|
fMinGrowth = growth
|
|
fMinArea = area1
|
|
iBest = (**(**TRtreeCell)(__ccgo_up(bp + 64))).FiRowid
|
|
}
|
|
goto _3
|
|
_3:
|
|
;
|
|
iCell = iCell + 1
|
|
}
|
|
}
|
|
rc = _nodeAcquire(tls, pRtree, iBest, **(**uintptr)(__ccgo_up(bp)), bp+8)
|
|
_nodeRelease(tls, pRtree, **(**uintptr)(__ccgo_up(bp)))
|
|
**(**uintptr)(__ccgo_up(bp)) = **(**uintptr)(__ccgo_up(bp + 8))
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppLeaf)) = **(**uintptr)(__ccgo_up(bp))
|
|
return rc
|
|
}
|
|
|
|
const __INTPTR_MAX__ = 9223372036854775807
|
|
|
|
const __INTPTR_WIDTH__ = 64
|
|
|
|
const __PTRDIFF_MAX__ = 9223372036854775807
|
|
|
|
const __PTRDIFF_WIDTH__ = 64
|
|
|
|
const __SIZEOF_INT128__ = 16
|
|
|
|
const __SIZEOF_POINTER__ = 8
|
|
|
|
const __SIZEOF_PTRDIFF_T__ = 8
|
|
|
|
const __SIZEOF_SIZE_T__ = 8
|
|
|
|
const __SIZE_MAX__ = 18446744073709551615
|
|
|
|
const __SIZE_WIDTH__ = 64
|
|
|
|
const __UINTPTR_MAX__ = 18446744073709551615
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Add a new element to the pAggInfo->aCol[] array. Return the index of
|
|
// ** the new element. Return a negative number if malloc fails.
|
|
// */
|
|
func _addAggInfoColumn(tls *libc.TLS, db uintptr, pInfo uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var _ /* i at bp+0 */ int32
|
|
(*TAggInfo)(unsafe.Pointer(pInfo)).FaCol = _sqlite3ArrayAllocate(tls, db, (*TAggInfo)(unsafe.Pointer(pInfo)).FaCol, int32(32), pInfo+40, bp)
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Add a new element to the pAggInfo->aFunc[] array. Return the index of
|
|
// ** the new element. Return a negative number if malloc fails.
|
|
// */
|
|
func _addAggInfoFunc(tls *libc.TLS, db uintptr, pInfo uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var _ /* i at bp+0 */ int32
|
|
(*TAggInfo)(unsafe.Pointer(pInfo)).FaFunc = _sqlite3ArrayAllocate(tls, db, (*TAggInfo)(unsafe.Pointer(pInfo)).FaFunc, int32(32), pInfo+56, bp)
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Add connection db to the blocked connections list. It is assumed
|
|
// ** that it is not already a part of the list.
|
|
// */
|
|
func _addToBlockedList(tls *libc.TLS, db uintptr) {
|
|
var pp uintptr
|
|
_ = pp
|
|
pp = uintptr(unsafe.Pointer(&_sqlite3BlockedList))
|
|
for {
|
|
if !(**(**uintptr)(__ccgo_up(pp)) != 0 && (*Tsqlite3)(unsafe.Pointer(**(**uintptr)(__ccgo_up(pp)))).FxUnlockNotify != (*Tsqlite3)(unsafe.Pointer(db)).FxUnlockNotify) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pp = **(**uintptr)(__ccgo_up(pp)) + 856
|
|
}
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FpNextBlocked = **(**uintptr)(__ccgo_up(pp))
|
|
**(**uintptr)(__ccgo_up(pp)) = db
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Set the bit number pgno in the PagerSavepoint.pInSavepoint
|
|
// ** bitvecs of all open savepoints. Return SQLITE_OK if successful
|
|
// ** or SQLITE_NOMEM if a malloc failure occurs.
|
|
// */
|
|
func _addToSavepointBitvecs(tls *libc.TLS, pPager uintptr, pgno TPgno) (r int32) {
|
|
var ii, rc int32
|
|
var p uintptr
|
|
_, _, _ = ii, p, rc /* Loop counter */
|
|
rc = SQLITE_OK /* Result code */
|
|
ii = 0
|
|
for {
|
|
if !(ii < (*TPager)(unsafe.Pointer(pPager)).FnSavepoint) {
|
|
break
|
|
}
|
|
p = (*TPager)(unsafe.Pointer(pPager)).FaSavepoint + uintptr(ii)*56
|
|
if pgno <= (*TPagerSavepoint)(unsafe.Pointer(p)).FnOrig {
|
|
rc = rc | _sqlite3BitvecSet(tls, (*TPagerSavepoint)(unsafe.Pointer(p)).FpInSavepoint, pgno)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Add the virtual table pVTab to the array sqlite3.aVTrans[]. Space should
|
|
// ** have already been reserved using growVTrans().
|
|
// */
|
|
func _addToVTrans(tls *libc.TLS, db uintptr, pVTab uintptr) {
|
|
var v1 int32
|
|
var v2 uintptr
|
|
_, _ = v1, v2
|
|
/* Add pVtab to the end of sqlite3.aVTrans */
|
|
v2 = db + 572
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
**(**uintptr)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaVTrans + uintptr(v1)*8)) = pVTab
|
|
_sqlite3VtabLock(tls, pVTab)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Try to allocate nByte bytes of 8-byte aligned bulk memory for pBuf
|
|
// ** from the ReusableSpace object. Return a pointer to the allocated
|
|
// ** memory on success. If insufficient memory is available in the
|
|
// ** ReusableSpace object, increase the ReusableSpace.nNeeded
|
|
// ** value by the amount needed and return NULL.
|
|
// **
|
|
// ** If pBuf is not initially NULL, that means that the memory has already
|
|
// ** been allocated by a prior call to this routine, so just return a copy
|
|
// ** of pBuf and leave ReusableSpace unchanged.
|
|
// **
|
|
// ** This allocator is employed to repurpose unused slots at the end of the
|
|
// ** opcode array of prepared state for other memory needs of the prepared
|
|
// ** statement.
|
|
// */
|
|
func _allocSpace(tls *libc.TLS, p uintptr, pBuf uintptr, nByte Tsqlite3_int64) (r uintptr) {
|
|
if pBuf == uintptr(0) {
|
|
nByte = nByte
|
|
if nByte <= (*TReusableSpace)(unsafe.Pointer(p)).FnFree {
|
|
**(**Tsqlite3_int64)(__ccgo_up(p + 8)) -= nByte
|
|
pBuf = (*TReusableSpace)(unsafe.Pointer(p)).FpSpace + uintptr((*TReusableSpace)(unsafe.Pointer(p)).FnFree)
|
|
} else {
|
|
**(**Tsqlite3_int64)(__ccgo_up(p + 16)) += nByte
|
|
}
|
|
}
|
|
return pBuf
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Find the table named by the first entry in source list pSrc. If successful,
|
|
// ** return a pointer to the Table structure and set output variable (*pzDb)
|
|
// ** to point to the name of the database containin the table (i.e. "main",
|
|
// ** "temp" or the name of an attached database).
|
|
// **
|
|
// ** If the table cannot be located, return NULL. The value of the two output
|
|
// ** parameters is undefined in this case.
|
|
// */
|
|
func _alterFindTable(tls *libc.TLS, pParse uintptr, pSrc uintptr, piDb uintptr, pzDb uintptr, bAuth int32) (r uintptr) {
|
|
var db, pTab uintptr
|
|
var iDb int32
|
|
_, _, _ = db, iDb, pTab
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
pTab = uintptr(0)
|
|
pTab = _sqlite3LocateTableItem(tls, pParse, uint32(0), pSrc+8)
|
|
if pTab != 0 {
|
|
iDb = _sqlite3SchemaToIndex(tls, db, (*TTable)(unsafe.Pointer(pTab)).FpSchema)
|
|
**(**uintptr)(__ccgo_up(pzDb)) = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FzDbSName
|
|
**(**int32)(__ccgo_up(piDb)) = iDb
|
|
if SQLITE_OK != _isRealTable(tls, pParse, pTab, int32(2)) || SQLITE_OK != _isAlterableTable(tls, pParse, pTab) {
|
|
pTab = uintptr(0)
|
|
}
|
|
}
|
|
if pTab != 0 && bAuth != 0 {
|
|
if _sqlite3AuthCheck(tls, pParse, int32(SQLITE_ALTER_TABLE), **(**uintptr)(__ccgo_up(pzDb)), (*TTable)(unsafe.Pointer(pTab)).FzName, uintptr(0)) != 0 {
|
|
pTab = uintptr(0)
|
|
}
|
|
}
|
|
_sqlite3SrcListDelete(tls, db, pSrc)
|
|
return pTab
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Generate code that will do an analysis of an entire database
|
|
// */
|
|
func _analyzeDatabase(tls *libc.TLS, pParse uintptr, iDb int32) {
|
|
var db, k, pSchema, pTab uintptr
|
|
var iMem, iStatCur, iTab int32
|
|
_, _, _, _, _, _, _ = db, iMem, iStatCur, iTab, k, pSchema, pTab
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
pSchema = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FpSchema
|
|
_sqlite3BeginWriteOperation(tls, pParse, 0, iDb)
|
|
iStatCur = (*TParse)(unsafe.Pointer(pParse)).FnTab
|
|
**(**int32)(__ccgo_up(pParse + 56)) += int32(3)
|
|
_openStatTable(tls, pParse, iDb, iStatCur, uintptr(0), uintptr(0))
|
|
iMem = (*TParse)(unsafe.Pointer(pParse)).FnMem + int32(1)
|
|
iTab = (*TParse)(unsafe.Pointer(pParse)).FnTab
|
|
k = (*THash)(unsafe.Pointer(pSchema + 8)).Ffirst
|
|
for {
|
|
if !(k != 0) {
|
|
break
|
|
}
|
|
pTab = (*THashElem)(unsafe.Pointer(k)).Fdata
|
|
_analyzeOneTable(tls, pParse, pTab, uintptr(0), iStatCur, iMem, iTab)
|
|
iMem = _sqlite3FirstAvailableRegister(tls, pParse, iMem)
|
|
goto _1
|
|
_1:
|
|
;
|
|
k = (*THashElem)(unsafe.Pointer(k)).Fnext
|
|
}
|
|
_loadAnalysis(tls, pParse, iDb)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Try to convert a value into a numeric representation if we can
|
|
// ** do so without loss of information. In other words, if the string
|
|
// ** looks like a number, convert it into a number. If it does not
|
|
// ** look like a number, leave it alone.
|
|
// **
|
|
// ** If the bTryForInt flag is true, then extra effort is made to give
|
|
// ** an integer representation. Strings that look like floating point
|
|
// ** values but which have no fractional component (example: '48.00')
|
|
// ** will have a MEM_Int representation when bTryForInt is true.
|
|
// **
|
|
// ** If bTryForInt is false, then if the input string contains a decimal
|
|
// ** point or exponential notation, the result is only MEM_Real, even
|
|
// ** if there is an exact integer representation of the quantity.
|
|
// */
|
|
func _applyNumericAffinity(tls *libc.TLS, pRec uintptr, bTryForInt int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var rc int32
|
|
var v1 uintptr
|
|
var _ /* rValue at bp+0 */ float64
|
|
_, _ = rc, v1
|
|
rc = _sqlite3MemRealValueRC(tls, pRec, bp)
|
|
if rc <= 0 {
|
|
return
|
|
}
|
|
if rc&int32(2) == 0 && _alsoAnInt(tls, pRec, **(**float64)(__ccgo_up(bp)), pRec) != 0 {
|
|
v1 = pRec + 20
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(MEM_Int))
|
|
} else {
|
|
*(*float64)(unsafe.Pointer(pRec)) = **(**float64)(__ccgo_up(bp))
|
|
v1 = pRec + 20
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(MEM_Real))
|
|
if bTryForInt != 0 {
|
|
_sqlite3VdbeIntegerAffinity(tls, pRec)
|
|
}
|
|
}
|
|
/* TEXT->NUMERIC is many->one. Hence, it is important to invalidate the
|
|
** string representation after computing a numeric equivalent, because the
|
|
** string representation might not be the canonical representation for the
|
|
** numeric value. Ticket [343634942dd54ab57b7024] 2018-01-31. */
|
|
v1 = pRec + 20
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) & ^libc.Int32FromInt32(MEM_Str))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Allocate a block of registers so that there is one register for each
|
|
// ** pAggInfo->aCol[] and pAggInfo->aFunc[] entry in pAggInfo. The first
|
|
// ** register in this block is stored in pAggInfo->iFirstReg.
|
|
// **
|
|
// ** This routine may only be called once for each AggInfo object. Prior
|
|
// ** to calling this routine:
|
|
// **
|
|
// ** * The aCol[] and aFunc[] arrays may be modified
|
|
// ** * The AggInfoColumnReg() and AggInfoFuncReg() macros may not be used
|
|
// **
|
|
// ** After calling this routine:
|
|
// **
|
|
// ** * The aCol[] and aFunc[] arrays are fixed
|
|
// ** * The AggInfoColumnReg() and AggInfoFuncReg() macros may be used
|
|
// **
|
|
// */
|
|
func _assignAggregateRegisters(tls *libc.TLS, pParse uintptr, pAggInfo uintptr) {
|
|
(*TAggInfo)(unsafe.Pointer(pAggInfo)).FiFirstReg = (*TParse)(unsafe.Pointer(pParse)).FnMem + int32(1)
|
|
**(**int32)(__ccgo_up(pParse + 60)) += (*TAggInfo)(unsafe.Pointer(pAggInfo)).FnColumn + (*TAggInfo)(unsafe.Pointer(pAggInfo)).FnFunc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Enter the mutex on every Btree associated with a database
|
|
// ** connection. This is needed (for example) prior to parsing
|
|
// ** a statement since we will be comparing table and column names
|
|
// ** against all schemas and we do not want those schemas being
|
|
// ** reset out from under us.
|
|
// **
|
|
// ** There is a corresponding leave-all procedures.
|
|
// **
|
|
// ** Enter the mutexes in ascending order by BtShared pointer address
|
|
// ** to avoid the possibility of deadlock when two threads with
|
|
// ** two or more btrees in common both try to lock all their btrees
|
|
// ** at the same instant.
|
|
// */
|
|
func _btreeEnterAll(tls *libc.TLS, db uintptr) {
|
|
var i int32
|
|
var p uintptr
|
|
var skipOk Tu8
|
|
_, _, _ = i, p, skipOk
|
|
skipOk = uint8(1)
|
|
i = 0
|
|
for {
|
|
if !(i < (*Tsqlite3)(unsafe.Pointer(db)).FnDb) {
|
|
break
|
|
}
|
|
p = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(i)*32))).FpBt
|
|
if p != 0 && (*TBtree)(unsafe.Pointer(p)).Fsharable != 0 {
|
|
_sqlite3BtreeEnter(tls, p)
|
|
skipOk = uint8(0)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FnoSharedCache = skipOk
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Invoke the busy handler for a btree.
|
|
// */
|
|
func _btreeInvokeBusyHandler(tls *libc.TLS, pArg uintptr) (r int32) {
|
|
var pBt uintptr
|
|
_ = pBt
|
|
pBt = pArg
|
|
return _sqlite3InvokeBusyHandler(tls, (*TBtShared)(unsafe.Pointer(pBt)).Fdb+672)
|
|
}
|
|
|
|
func _btreeLeaveAll(tls *libc.TLS, db uintptr) {
|
|
var i int32
|
|
var p uintptr
|
|
_, _ = i, p
|
|
i = 0
|
|
for {
|
|
if !(i < (*Tsqlite3)(unsafe.Pointer(db)).FnDb) {
|
|
break
|
|
}
|
|
p = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(i)*32))).FpBt
|
|
if p != 0 {
|
|
_sqlite3BtreeLeave(tls, p)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Release all of the apPage[] pages for a cursor.
|
|
// */
|
|
func _btreeReleaseAllCursorPages(tls *libc.TLS, pCur uintptr) {
|
|
var i int32
|
|
_ = i
|
|
if int32((*TBtCursor)(unsafe.Pointer(pCur)).FiPage) >= 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < int32((*TBtCursor)(unsafe.Pointer(pCur)).FiPage)) {
|
|
break
|
|
}
|
|
_releasePageNotNull(tls, **(**uintptr)(__ccgo_up(pCur + 144 + uintptr(i)*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_releasePageNotNull(tls, (*TBtCursor)(unsafe.Pointer(pCur)).FpPage)
|
|
(*TBtCursor)(unsafe.Pointer(pCur)).FiPage = int8(-int32(1))
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function invokes either the xRollback or xCommit method
|
|
// ** of each of the virtual tables in the sqlite3.aVTrans array. The method
|
|
// ** called is identified by the second argument, "offset", which is
|
|
// ** the offset of the method to call in the sqlite3_module structure.
|
|
// **
|
|
// ** The array is cleared after invoking the callbacks.
|
|
// */
|
|
func _callFinaliser(tls *libc.TLS, db uintptr, offset int32) {
|
|
var aVTrans, p, pVTab, x uintptr
|
|
var i int32
|
|
_, _, _, _, _ = aVTrans, i, p, pVTab, x
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FaVTrans != 0 {
|
|
aVTrans = (*Tsqlite3)(unsafe.Pointer(db)).FaVTrans
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FaVTrans = uintptr(0)
|
|
i = 0
|
|
for {
|
|
if !(i < (*Tsqlite3)(unsafe.Pointer(db)).FnVTrans) {
|
|
break
|
|
}
|
|
pVTab = **(**uintptr)(__ccgo_up(aVTrans + uintptr(i)*8))
|
|
p = (*TVTable)(unsafe.Pointer(pVTab)).FpVtab
|
|
if p != 0 {
|
|
x = **(**uintptr)(__ccgo_up((*Tsqlite3_vtab)(unsafe.Pointer(p)).FpModule + uintptr(offset)))
|
|
if x != 0 {
|
|
(*(*func(*libc.TLS, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{x})))(tls, p)
|
|
}
|
|
}
|
|
(*TVTable)(unsafe.Pointer(pVTab)).FiSavepoint = 0
|
|
_sqlite3VtabUnlock(tls, pVTab)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_sqlite3DbFree(tls, db, aVTrans)
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FnVTrans = 0
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function does processing common to the _change_int64(), _change_text()
|
|
// ** and other similar APIs.
|
|
// */
|
|
func _checkChangeParams(tls *libc.TLS, pGrp uintptr, bNew int32, iCol int32, nReq Tsqlite3_int64, ppBuf uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var pBuf uintptr
|
|
var _ /* rc at bp+0 */ int32
|
|
_ = pBuf
|
|
**(**int32)(__ccgo_up(bp)) = SQLITE_OK
|
|
if (*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).Fcd.FpTab == uintptr(0) {
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_MISUSE)
|
|
} else {
|
|
if iCol < 0 || iCol >= (*TSessionTable)(unsafe.Pointer((*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).Fcd.FpTab)).FnCol {
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_RANGE)
|
|
} else {
|
|
if bNew != 0 && (*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).Fcd.FeOp == int32(SQLITE_DELETE) || !(bNew != 0) && (*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).Fcd.FeOp == int32(SQLITE_INSERT) {
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
} else {
|
|
pBuf = (*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).Fcd.FaBuf + uintptr(iCol)*16
|
|
if (*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).Fcd.FeOp == int32(SQLITE_UPDATE) && bNew != 0 {
|
|
pBuf = pBuf + uintptr((*TSessionTable)(unsafe.Pointer((*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).Fcd.FpTab)).FnCol)*16
|
|
}
|
|
(*TSessionBuffer)(unsafe.Pointer(pBuf)).FnBuf = 0
|
|
_sessionBufferGrow(tls, pBuf, nReq, bp)
|
|
(*TSessionBuffer)(unsafe.Pointer(pBuf)).FnBuf = int32(nReq)
|
|
**(**uintptr)(__ccgo_up(ppBuf)) = pBuf
|
|
}
|
|
}
|
|
}
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** pEList is the SET clause of an UPDATE statement. Each entry
|
|
// ** in pEList is of the format <id>=<expr>. If any of the entries
|
|
// ** in pEList have an <id> which matches an identifier in pIdList,
|
|
// ** then return TRUE. If pIdList==NULL, then it is considered a
|
|
// ** wildcard that matches anything. Likewise if pEList==NULL then
|
|
// ** it matches anything so always return true. Return false only
|
|
// ** if there is no match.
|
|
// */
|
|
func _checkColumnOverlap(tls *libc.TLS, pIdList uintptr, pEList uintptr) (r int32) {
|
|
var e int32
|
|
_ = e
|
|
if pIdList == uintptr(0) || pEList == uintptr(0) {
|
|
return int32(1)
|
|
}
|
|
e = 0
|
|
for {
|
|
if !(e < (*TExprList)(unsafe.Pointer(pEList)).FnExpr) {
|
|
break
|
|
}
|
|
if _sqlite3IdListIndex(tls, pIdList, (*(*TExprList_item)(unsafe.Pointer(pEList + 8 + uintptr(e)*32))).FzEName) >= 0 {
|
|
return int32(1)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
e = e + 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Invoke the progress handler, if appropriate. Also check for an
|
|
// ** interrupt.
|
|
// */
|
|
func _checkProgress(tls *libc.TLS, pCheck uintptr) {
|
|
var db uintptr
|
|
_ = db
|
|
db = (*TIntegrityCk)(unsafe.Pointer(pCheck)).Fdb
|
|
if libc.AtomicLoadNInt32(db+432, libc.Int32FromInt32(__ATOMIC_RELAXED)) != 0 {
|
|
(*TIntegrityCk)(unsafe.Pointer(pCheck)).Frc = int32(SQLITE_INTERRUPT)
|
|
(*TIntegrityCk)(unsafe.Pointer(pCheck)).FnErr = (*TIntegrityCk)(unsafe.Pointer(pCheck)).FnErr + 1
|
|
(*TIntegrityCk)(unsafe.Pointer(pCheck)).FmxErr = 0
|
|
}
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FxProgress != 0 {
|
|
(*TIntegrityCk)(unsafe.Pointer(pCheck)).FnStep = (*TIntegrityCk)(unsafe.Pointer(pCheck)).FnStep + 1
|
|
if (*TIntegrityCk)(unsafe.Pointer(pCheck)).FnStep%(*Tsqlite3)(unsafe.Pointer(db)).FnProgressOps == uint32(0) && (*(*func(*libc.TLS, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{(*Tsqlite3)(unsafe.Pointer(db)).FxProgress})))(tls, (*Tsqlite3)(unsafe.Pointer(db)).FpProgressArg) != 0 {
|
|
(*TIntegrityCk)(unsafe.Pointer(pCheck)).Frc = int32(SQLITE_INTERRUPT)
|
|
(*TIntegrityCk)(unsafe.Pointer(pCheck)).FnErr = (*TIntegrityCk)(unsafe.Pointer(pCheck)).FnErr + 1
|
|
(*TIntegrityCk)(unsafe.Pointer(pCheck)).FmxErr = 0
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Release all the table locks (locks obtained via calls to
|
|
// ** the setSharedCacheTableLock() procedure) held by Btree object p.
|
|
// **
|
|
// ** This function assumes that Btree p has an open read or write
|
|
// ** transaction. If it does not, then the BTS_PENDING flag
|
|
// ** may be incorrectly cleared.
|
|
// */
|
|
func _clearAllSharedCacheTableLocks(tls *libc.TLS, p uintptr) {
|
|
var pBt, pLock, ppIter, v1 uintptr
|
|
_, _, _, _ = pBt, pLock, ppIter, v1
|
|
pBt = (*TBtree)(unsafe.Pointer(p)).FpBt
|
|
ppIter = pBt + 120
|
|
for **(**uintptr)(__ccgo_up(ppIter)) != 0 {
|
|
pLock = **(**uintptr)(__ccgo_up(ppIter))
|
|
if (*TBtLock)(unsafe.Pointer(pLock)).FpBtree == p {
|
|
**(**uintptr)(__ccgo_up(ppIter)) = (*TBtLock)(unsafe.Pointer(pLock)).FpNext
|
|
if (*TBtLock)(unsafe.Pointer(pLock)).FiTable != uint32(1) {
|
|
Xsqlite3_free(tls, pLock)
|
|
}
|
|
} else {
|
|
ppIter = pLock + 16
|
|
}
|
|
}
|
|
if (*TBtShared)(unsafe.Pointer(pBt)).FpWriter == p {
|
|
(*TBtShared)(unsafe.Pointer(pBt)).FpWriter = uintptr(0)
|
|
v1 = pBt + 40
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) & ^(libc.Int32FromInt32(BTS_EXCLUSIVE) | libc.Int32FromInt32(BTS_PENDING)))
|
|
} else {
|
|
if (*TBtShared)(unsafe.Pointer(pBt)).FnTransaction == int32(2) {
|
|
/* This function is called when Btree p is concluding its
|
|
** transaction. If there currently exists a writer, and p is not
|
|
** that writer, then the number of locks held by connections other
|
|
** than the writer must be about to drop to zero. In this case
|
|
** set the BTS_PENDING flag to 0.
|
|
**
|
|
** If there is not currently a writer, then BTS_PENDING must
|
|
** be zero already. So this next line is harmless in that case.
|
|
*/
|
|
v1 = pBt + 40
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) & ^libc.Int32FromInt32(BTS_PENDING))
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Close all cursors.
|
|
// **
|
|
// ** Also release any dynamic memory held by the VM in the Vdbe.aMem memory
|
|
// ** cell array. This is necessary as the memory cell array may contain
|
|
// ** pointers to VdbeFrame objects, which may in turn contain pointers to
|
|
// ** open cursors.
|
|
// */
|
|
func _closeAllCursors(tls *libc.TLS, p uintptr) {
|
|
var pDel, pFrame uintptr
|
|
_, _ = pDel, pFrame
|
|
if (*TVdbe)(unsafe.Pointer(p)).FpFrame != 0 {
|
|
pFrame = (*TVdbe)(unsafe.Pointer(p)).FpFrame
|
|
for {
|
|
if !((*TVdbeFrame)(unsafe.Pointer(pFrame)).FpParent != 0) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pFrame = (*TVdbeFrame)(unsafe.Pointer(pFrame)).FpParent
|
|
}
|
|
_sqlite3VdbeFrameRestore(tls, pFrame)
|
|
(*TVdbe)(unsafe.Pointer(p)).FpFrame = uintptr(0)
|
|
(*TVdbe)(unsafe.Pointer(p)).FnFrame = 0
|
|
}
|
|
_closeCursorsInFrame(tls, p)
|
|
_releaseMemArray(tls, (*TVdbe)(unsafe.Pointer(p)).FaMem, (*TVdbe)(unsafe.Pointer(p)).FnMem)
|
|
for (*TVdbe)(unsafe.Pointer(p)).FpDelFrame != 0 {
|
|
pDel = (*TVdbe)(unsafe.Pointer(p)).FpDelFrame
|
|
(*TVdbe)(unsafe.Pointer(p)).FpDelFrame = (*TVdbeFrame)(unsafe.Pointer(pDel)).FpParent
|
|
_sqlite3VdbeFrameDelete(tls, pDel)
|
|
}
|
|
/* Delete any auxdata allocations made by the VM */
|
|
if (*TVdbe)(unsafe.Pointer(p)).FpAuxData != 0 {
|
|
_sqlite3VdbeDeleteAuxData(tls, (*TVdbe)(unsafe.Pointer(p)).Fdb, p+296, -int32(1), 0)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Close all cursors in the current frame.
|
|
// */
|
|
func _closeCursorsInFrame(tls *libc.TLS, p uintptr) {
|
|
var i int32
|
|
var pC uintptr
|
|
_, _ = i, pC
|
|
i = 0
|
|
for {
|
|
if !(i < (*TVdbe)(unsafe.Pointer(p)).FnCursor) {
|
|
break
|
|
}
|
|
pC = **(**uintptr)(__ccgo_up((*TVdbe)(unsafe.Pointer(p)).FapCsr + uintptr(i)*8))
|
|
if pC != 0 {
|
|
_sqlite3VdbeFreeCursorNN(tls, p, pC)
|
|
**(**uintptr)(__ccgo_up((*TVdbe)(unsafe.Pointer(p)).FapCsr + uintptr(i)*8)) = uintptr(0)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Add code that will check to make sure the array of registers starting at
|
|
// ** iMem form a distinct entry. This is used by both "SELECT DISTINCT ..." and
|
|
// ** distinct aggregates ("SELECT count(DISTINCT <expr>) ..."). Three strategies
|
|
// ** are available. Which is used depends on the value of parameter eTnctType,
|
|
// ** as follows:
|
|
// **
|
|
// ** WHERE_DISTINCT_UNORDERED/WHERE_DISTINCT_NOOP:
|
|
// ** Build an ephemeral table that contains all entries seen before and
|
|
// ** skip entries which have been seen before.
|
|
// **
|
|
// ** Parameter iTab is the cursor number of an ephemeral table that must
|
|
// ** be opened before the VM code generated by this routine is executed.
|
|
// ** The ephemeral cursor table is queried for a record identical to the
|
|
// ** record formed by the current array of registers. If one is found,
|
|
// ** jump to VM address addrRepeat. Otherwise, insert a new record into
|
|
// ** the ephemeral cursor and proceed.
|
|
// **
|
|
// ** The returned value in this case is a copy of parameter iTab.
|
|
// **
|
|
// ** WHERE_DISTINCT_ORDERED:
|
|
// ** In this case rows are being delivered sorted order. The ephemeral
|
|
// ** table is not required. Instead, the current set of values
|
|
// ** is compared against previous row. If they match, the new row
|
|
// ** is not distinct and control jumps to VM address addrRepeat. Otherwise,
|
|
// ** the VM program proceeds with processing the new row.
|
|
// **
|
|
// ** The returned value in this case is the register number of the first
|
|
// ** in an array of registers used to store the previous result row so that
|
|
// ** it can be compared to the next. The caller must ensure that this
|
|
// ** register is initialized to NULL. (The fixDistinctOpenEph() routine
|
|
// ** will take care of this initialization.)
|
|
// **
|
|
// ** WHERE_DISTINCT_UNIQUE:
|
|
// ** In this case it has already been determined that the rows are distinct.
|
|
// ** No special action is required. The return value is zero.
|
|
// **
|
|
// ** Parameter pEList is the list of expressions used to generated the
|
|
// ** contents of each row. It is used by this routine to determine (a)
|
|
// ** how many elements there are in the array of registers and (b) the
|
|
// ** collation sequences that should be used for the comparisons if
|
|
// ** eTnctType is WHERE_DISTINCT_ORDERED.
|
|
// */
|
|
func _codeDistinct(tls *libc.TLS, pParse uintptr, eTnctType int32, iTab int32, addrRepeat int32, pEList uintptr, regElem int32) (r int32) {
|
|
var i, iJump, iRet, nResultCol, r1, regPrev, v1 int32
|
|
var pColl, v uintptr
|
|
_, _, _, _, _, _, _, _, _ = i, iJump, iRet, nResultCol, pColl, r1, regPrev, v, v1
|
|
iRet = 0
|
|
nResultCol = (*TExprList)(unsafe.Pointer(pEList)).FnExpr
|
|
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
|
|
switch eTnctType {
|
|
case int32(WHERE_DISTINCT_ORDERED): /* Previous row content */
|
|
/* Allocate space for the previous row */
|
|
v1 = (*TParse)(unsafe.Pointer(pParse)).FnMem + libc.Int32FromInt32(1)
|
|
regPrev = v1
|
|
iRet = v1
|
|
**(**int32)(__ccgo_up(pParse + 60)) += nResultCol
|
|
iJump = _sqlite3VdbeCurrentAddr(tls, v) + nResultCol
|
|
i = 0
|
|
for {
|
|
if !(i < nResultCol) {
|
|
break
|
|
}
|
|
pColl = _sqlite3ExprCollSeq(tls, pParse, (*(*TExprList_item)(unsafe.Pointer(pEList + 8 + uintptr(i)*32))).FpExpr)
|
|
if i < nResultCol-int32(1) {
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Ne), regElem+i, iJump, regPrev+i)
|
|
} else {
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Eq), regElem+i, addrRepeat, regPrev+i)
|
|
}
|
|
_sqlite3VdbeChangeP4(tls, v, -int32(1), pColl, -int32(2))
|
|
_sqlite3VdbeChangeP5(tls, v, uint16(SQLITE_NULLEQ))
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Copy), regElem, regPrev, nResultCol-int32(1))
|
|
case int32(WHERE_DISTINCT_UNIQUE):
|
|
/* nothing to do */
|
|
default:
|
|
r1 = _sqlite3GetTempReg(tls, pParse)
|
|
_sqlite3VdbeAddOp4Int(tls, v, int32(OP_Found), iTab, addrRepeat, regElem, nResultCol)
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_MakeRecord), regElem, nResultCol, r1)
|
|
_sqlite3VdbeAddOp4Int(tls, v, int32(OP_IdxInsert), iTab, r1, regElem, nResultCol)
|
|
_sqlite3VdbeChangeP5(tls, v, uint16(OPFLAG_USESEEKRESULT))
|
|
_sqlite3ReleaseTempReg(tls, pParse, r1)
|
|
iRet = iTab
|
|
break
|
|
}
|
|
return iRet
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If the expression passed as the second argument is a vector, generate
|
|
// ** code to write the first nReg elements of the vector into an array
|
|
// ** of registers starting with iReg.
|
|
// **
|
|
// ** If the expression is not a vector, then nReg must be passed 1. In
|
|
// ** this case, generate code to evaluate the expression and leave the
|
|
// ** result in register iReg.
|
|
// */
|
|
func _codeExprOrVector(tls *libc.TLS, pParse uintptr, p uintptr, iReg int32, nReg int32) {
|
|
var i, iSelect int32
|
|
var pList, v uintptr
|
|
_, _, _, _ = i, iSelect, pList, v
|
|
if p != 0 && _sqlite3ExprIsVector(tls, p) != 0 {
|
|
if (*TExpr)(unsafe.Pointer(p)).Fflags&uint32(EP_xIsSelect) != uint32(0) {
|
|
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
|
|
iSelect = _sqlite3CodeSubselect(tls, pParse, p)
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Copy), iSelect, iReg, nReg-int32(1))
|
|
} else {
|
|
pList = *(*uintptr)(unsafe.Pointer(p + 32))
|
|
i = 0
|
|
for {
|
|
if !(i < nReg) {
|
|
break
|
|
}
|
|
_sqlite3ExprCode(tls, pParse, (*(*TExprList_item)(unsafe.Pointer(pList + 8 + uintptr(i)*32))).FpExpr, iReg+i)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
} else {
|
|
_sqlite3ExprCode(tls, pParse, p, iReg)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the size of the Nth element of the cell array
|
|
// */
|
|
func _computeCellSize(tls *libc.TLS, p uintptr, N int32) (r Tu16) {
|
|
**(**Tu16)(__ccgo_up((*TCellArray)(unsafe.Pointer(p)).FszCell + uintptr(N)*2)) = (*(*func(*libc.TLS, uintptr, uintptr) Tu16)(unsafe.Pointer(&struct{ uintptr }{(*TMemPage)(unsafe.Pointer((*TCellArray)(unsafe.Pointer(p)).FpRef)).FxCellSize})))(tls, (*TCellArray)(unsafe.Pointer(p)).FpRef, **(**uintptr)(__ccgo_up((*TCellArray)(unsafe.Pointer(p)).FapCell + uintptr(N)*8)))
|
|
return **(**Tu16)(__ccgo_up((*TCellArray)(unsafe.Pointer(p)).FszCell + uintptr(N)*2))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The CONCAT_WS(separator, ...) function.
|
|
// **
|
|
// ** Generate a string that is the concatenation of 2nd through the Nth
|
|
// ** argument. Use the first argument (which must be non-NULL) as the
|
|
// ** separator.
|
|
// */
|
|
func _concatwsFunc(tls *libc.TLS, context uintptr, argc int32, argv uintptr) {
|
|
var nSep int32
|
|
var zSep uintptr
|
|
_, _ = nSep, zSep
|
|
nSep = Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
zSep = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
if zSep == uintptr(0) {
|
|
return
|
|
}
|
|
_concatFuncCore(tls, context, argc-int32(1), argv+uintptr(1)*8, nSep, zSep)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return TRUE if database connection db has unfinalized prepared
|
|
// ** statements or unfinished sqlite3_backup objects.
|
|
// */
|
|
func _connectionIsBusy(tls *libc.TLS, db uintptr) (r int32) {
|
|
var j int32
|
|
var pBt uintptr
|
|
_, _ = j, pBt
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FpVdbe != 0 {
|
|
return int32(1)
|
|
}
|
|
j = 0
|
|
for {
|
|
if !(j < (*Tsqlite3)(unsafe.Pointer(db)).FnDb) {
|
|
break
|
|
}
|
|
pBt = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(j)*32))).FpBt
|
|
if pBt != 0 && _sqlite3BtreeIsInBackup(tls, pBt) != 0 {
|
|
return int32(1)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
j = j + 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Worker function used by utf-8 APIs that create new functions:
|
|
// **
|
|
// ** sqlite3_create_function()
|
|
// ** sqlite3_create_function_v2()
|
|
// ** sqlite3_create_window_function()
|
|
// */
|
|
func _createFunctionApi(tls *libc.TLS, db uintptr, zFunc uintptr, nArg int32, enc int32, p uintptr, __ccgo_fp_xSFunc uintptr, __ccgo_fp_xStep uintptr, __ccgo_fp_xFinal uintptr, __ccgo_fp_xValue uintptr, __ccgo_fp_xInverse uintptr, __ccgo_fp_xDestroy uintptr) (r int32) {
|
|
var pArg uintptr
|
|
var rc int32
|
|
_, _ = pArg, rc
|
|
rc = int32(SQLITE_ERROR)
|
|
pArg = uintptr(0)
|
|
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
if __ccgo_fp_xDestroy != 0 {
|
|
pArg = _sqlite3Malloc(tls, uint64(24))
|
|
if !(pArg != 0) {
|
|
_sqlite3OomFault(tls, db)
|
|
(*(*func(*libc.TLS, uintptr))(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xDestroy})))(tls, p)
|
|
goto out
|
|
}
|
|
(*TFuncDestructor)(unsafe.Pointer(pArg)).FnRef = 0
|
|
(*TFuncDestructor)(unsafe.Pointer(pArg)).FxDestroy = __ccgo_fp_xDestroy
|
|
(*TFuncDestructor)(unsafe.Pointer(pArg)).FpUserData = p
|
|
}
|
|
rc = _sqlite3CreateFunc(tls, db, zFunc, nArg, enc, p, __ccgo_fp_xSFunc, __ccgo_fp_xStep, __ccgo_fp_xFinal, __ccgo_fp_xValue, __ccgo_fp_xInverse, pArg)
|
|
if pArg != 0 && (*TFuncDestructor)(unsafe.Pointer(pArg)).FnRef == 0 {
|
|
(*(*func(*libc.TLS, uintptr))(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xDestroy})))(tls, p)
|
|
Xsqlite3_free(tls, pArg)
|
|
}
|
|
goto out
|
|
out:
|
|
;
|
|
rc = _sqlite3ApiExit(tls, db, rc)
|
|
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex)
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Open write transactions. Since we do not know in advance which database
|
|
// ** files will be written by the sqlite_dbpage virtual table, start a write
|
|
// ** transaction on them all.
|
|
// **
|
|
// ** Return SQLITE_OK if successful, or an SQLite error code otherwise.
|
|
// */
|
|
func _dbpageBeginTrans(tls *libc.TLS, pTab uintptr) (r int32) {
|
|
var db, pBt uintptr
|
|
var i, rc int32
|
|
_, _, _, _ = db, i, pBt, rc
|
|
db = (*TDbpageTable)(unsafe.Pointer(pTab)).Fdb
|
|
rc = SQLITE_OK
|
|
i = 0
|
|
for {
|
|
if !(rc == SQLITE_OK && i < (*Tsqlite3)(unsafe.Pointer(db)).FnDb) {
|
|
break
|
|
}
|
|
pBt = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(i)*32))).FpBt
|
|
if pBt != 0 {
|
|
rc = _sqlite3BtreeBeginTrans(tls, pBt, int32(1), uintptr(0))
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Invoke sqlite3PagerTruncate() as necessary, just prior to COMMIT
|
|
// */
|
|
func _dbpageSync(tls *libc.TLS, pVtab uintptr) (r int32) {
|
|
var pBt, pPager, pTab uintptr
|
|
_, _, _ = pBt, pPager, pTab
|
|
pTab = pVtab
|
|
if (*TDbpageTable)(unsafe.Pointer(pTab)).FpgnoTrunc > uint32(0) {
|
|
pBt = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer((*TDbpageTable)(unsafe.Pointer(pTab)).Fdb)).FaDb + uintptr((*TDbpageTable)(unsafe.Pointer(pTab)).FiDbTrunc)*32))).FpBt
|
|
pPager = _sqlite3BtreePager(tls, pBt)
|
|
_sqlite3BtreeEnter(tls, pBt)
|
|
if (*TDbpageTable)(unsafe.Pointer(pTab)).FpgnoTrunc < _sqlite3BtreeLastPage(tls, pBt) {
|
|
_sqlite3PagerTruncateImage(tls, pPager, (*TDbpageTable)(unsafe.Pointer(pTab)).FpgnoTrunc)
|
|
}
|
|
_sqlite3BtreeLeave(tls, pBt)
|
|
}
|
|
(*TDbpageTable)(unsafe.Pointer(pTab)).FpgnoTrunc = uint32(0)
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is called after a transaction has been committed. It
|
|
// ** invokes callbacks registered with sqlite3_wal_hook() as required.
|
|
// */
|
|
func _doWalCallbacks(tls *libc.TLS, db uintptr) (r int32) {
|
|
var i, nEntry, rc int32
|
|
var pBt uintptr
|
|
_, _, _, _ = i, nEntry, pBt, rc
|
|
rc = SQLITE_OK
|
|
i = 0
|
|
for {
|
|
if !(i < (*Tsqlite3)(unsafe.Pointer(db)).FnDb) {
|
|
break
|
|
}
|
|
pBt = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(i)*32))).FpBt
|
|
if pBt != 0 {
|
|
_sqlite3BtreeEnter(tls, pBt)
|
|
nEntry = _sqlite3PagerWalCallback(tls, _sqlite3BtreePager(tls, pBt))
|
|
_sqlite3BtreeLeave(tls, pBt)
|
|
if nEntry > 0 && (*Tsqlite3)(unsafe.Pointer(db)).FxWalCallback != 0 && rc == SQLITE_OK {
|
|
rc = (*(*func(*libc.TLS, uintptr, uintptr, uintptr, int32) int32)(unsafe.Pointer(&struct{ uintptr }{(*Tsqlite3)(unsafe.Pointer(db)).FxWalCallback})))(tls, (*Tsqlite3)(unsafe.Pointer(db)).FpWalArg, db, (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(i)*32))).FzDbSName, nEntry)
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function changes all write-locks held by Btree p into read-locks.
|
|
// */
|
|
func _downgradeAllSharedCacheTableLocks(tls *libc.TLS, p uintptr) {
|
|
var pBt, pLock, v1 uintptr
|
|
_, _, _ = pBt, pLock, v1
|
|
pBt = (*TBtree)(unsafe.Pointer(p)).FpBt
|
|
if (*TBtShared)(unsafe.Pointer(pBt)).FpWriter == p {
|
|
(*TBtShared)(unsafe.Pointer(pBt)).FpWriter = uintptr(0)
|
|
v1 = pBt + 40
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) & ^(libc.Int32FromInt32(BTS_EXCLUSIVE) | libc.Int32FromInt32(BTS_PENDING)))
|
|
pLock = (*TBtShared)(unsafe.Pointer(pBt)).FpLock
|
|
for {
|
|
if !(pLock != 0) {
|
|
break
|
|
}
|
|
(*TBtLock)(unsafe.Pointer(pLock)).FeLock = uint8(READ_LOCK)
|
|
goto _2
|
|
_2:
|
|
;
|
|
pLock = (*TBtLock)(unsafe.Pointer(pLock)).FpNext
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Forward reference */
|
|
|
|
/*
|
|
***** This routine is used inside of assert() only ****
|
|
**
|
|
** Verify that the cursor holds the mutex on its BtShared
|
|
*/
|
|
|
|
/*
|
|
** Invalidate the overflow cache of the cursor passed as the first argument.
|
|
** on the shared btree structure pBt.
|
|
*/
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the length of the longest string literal in the given
|
|
// ** expression.
|
|
// **
|
|
// ** eCode indicates how to count characters:
|
|
// **
|
|
// ** eCode==0 Count as a GLOB pattern
|
|
// ** eCode==1 Count as a LIKE pattern
|
|
// */
|
|
func _estLikePatternLength(tls *libc.TLS, p uintptr, eCode Tu16) (r int32) {
|
|
bp := tls.Alloc(48)
|
|
defer tls.Free(48)
|
|
var _ /* w at bp+0 */ TWalker
|
|
*(*int32)(unsafe.Pointer(bp + 40)) = 0
|
|
(**(**TWalker)(__ccgo_up(bp))).FeCode = eCode
|
|
(**(**TWalker)(__ccgo_up(bp))).FxExprCallback = __ccgo_fp(_exprNodePatternLengthEst)
|
|
(**(**TWalker)(__ccgo_up(bp))).FxSelectCallback = __ccgo_fp(_sqlite3SelectWalkFail)
|
|
_sqlite3WalkExpr(tls, bp, p)
|
|
return *(*int32)(unsafe.Pointer(bp + 40))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Estimate the total row width for a table.
|
|
// */
|
|
func _estimateTableWidth(tls *libc.TLS, pTab uintptr) {
|
|
var i int32
|
|
var pTabCol uintptr
|
|
var wTable uint32
|
|
_, _, _ = i, pTabCol, wTable
|
|
wTable = uint32(0)
|
|
i = int32((*TTable)(unsafe.Pointer(pTab)).FnCol)
|
|
pTabCol = (*TTable)(unsafe.Pointer(pTab)).FaCol
|
|
for {
|
|
if !(i > 0) {
|
|
break
|
|
}
|
|
wTable = wTable + uint32((*TColumn)(unsafe.Pointer(pTabCol)).FszEst)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i - 1
|
|
pTabCol += 16
|
|
}
|
|
if int32((*TTable)(unsafe.Pointer(pTab)).FiPKey) < 0 {
|
|
wTable = wTable + 1
|
|
}
|
|
(*TTable)(unsafe.Pointer(pTab)).FszTabRow = _sqlite3LogEst(tls, uint64(wTable*uint32(4)))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Delete an entire expression list.
|
|
// */
|
|
func _exprListDeleteNN(tls *libc.TLS, db uintptr, pList uintptr) {
|
|
var i, v1 int32
|
|
var pItem uintptr
|
|
_, _, _ = i, pItem, v1
|
|
i = (*TExprList)(unsafe.Pointer(pList)).FnExpr
|
|
pItem = pList + 8
|
|
for {
|
|
_sqlite3ExprDelete(tls, db, (*TExprList_item)(unsafe.Pointer(pItem)).FpExpr)
|
|
if (*TExprList_item)(unsafe.Pointer(pItem)).FzEName != 0 {
|
|
_sqlite3DbNNFreeNN(tls, db, (*TExprList_item)(unsafe.Pointer(pItem)).FzEName)
|
|
}
|
|
pItem += 32
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i - 1
|
|
v1 = i
|
|
if !(v1 > 0) {
|
|
break
|
|
}
|
|
}
|
|
_sqlite3DbNNFreeNN(tls, db, pList)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return true if all expressions in the expression-list passed as the
|
|
// ** only argument are constant.
|
|
// */
|
|
func _exprListIsConstant(tls *libc.TLS, pParse uintptr, pRow uintptr) (r int32) {
|
|
var ii int32
|
|
_ = ii
|
|
ii = 0
|
|
for {
|
|
if !(ii < (*TExprList)(unsafe.Pointer(pRow)).FnExpr) {
|
|
break
|
|
}
|
|
if 0 == _sqlite3ExprIsConstant(tls, pParse, (*(*TExprList_item)(unsafe.Pointer(pRow + 8 + uintptr(ii)*32))).FpExpr) {
|
|
return 0
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
return int32(1)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy().
|
|
// */
|
|
func _exprNodeIsConstantOrGroupBy(tls *libc.TLS, pWalker uintptr, pExpr uintptr) (r int32) {
|
|
var i int32
|
|
var p, pColl, pGroupBy uintptr
|
|
_, _, _, _ = i, p, pColl, pGroupBy
|
|
pGroupBy = *(*uintptr)(unsafe.Pointer(pWalker + 40))
|
|
/* Check if pExpr is identical to any GROUP BY term. If so, consider
|
|
** it constant. */
|
|
i = 0
|
|
for {
|
|
if !(i < (*TExprList)(unsafe.Pointer(pGroupBy)).FnExpr) {
|
|
break
|
|
}
|
|
p = (*(*TExprList_item)(unsafe.Pointer(pGroupBy + 8 + uintptr(i)*32))).FpExpr
|
|
if _sqlite3ExprCompare(tls, uintptr(0), pExpr, p, -int32(1)) < int32(2) {
|
|
pColl = _sqlite3ExprNNCollSeq(tls, (*TWalker)(unsafe.Pointer(pWalker)).FpParse, p)
|
|
if _sqlite3IsBinary(tls, pColl) != 0 {
|
|
return int32(WRC_Prune)
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
/* Check if pExpr is a sub-select. If so, consider it variable. */
|
|
if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&uint32(EP_xIsSelect) != uint32(0) {
|
|
(*TWalker)(unsafe.Pointer(pWalker)).FeCode = uint16(0)
|
|
return int32(WRC_Abort)
|
|
}
|
|
return _exprNodeIsConstant(tls, pWalker, pExpr)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Expression pExpr is guaranteed to be a TK_COLUMN or equivalent. This
|
|
// ** function checks the Parse.pIdxPartExpr list to see if this column
|
|
// ** can be replaced with a constant value. If so, it generates code to
|
|
// ** put the constant value in a register (ideally, but not necessarily,
|
|
// ** register iTarget) and returns the register number.
|
|
// **
|
|
// ** Or, if the TK_COLUMN cannot be replaced by a constant, zero is
|
|
// ** returned.
|
|
// */
|
|
func _exprPartidxExprLookup(tls *libc.TLS, pParse uintptr, pExpr uintptr, iTarget int32) (r int32) {
|
|
var addr, ret int32
|
|
var p, v uintptr
|
|
_, _, _, _ = addr, p, ret, v
|
|
p = (*TParse)(unsafe.Pointer(pParse)).FpIdxPartExpr
|
|
for {
|
|
if !(p != 0) {
|
|
break
|
|
}
|
|
if int32((*TExpr)(unsafe.Pointer(pExpr)).FiColumn) == (*TIndexedExpr)(unsafe.Pointer(p)).FiIdxCol && (*TExpr)(unsafe.Pointer(pExpr)).FiTable == (*TIndexedExpr)(unsafe.Pointer(p)).FiDataCur {
|
|
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
|
|
addr = 0
|
|
if (*TIndexedExpr)(unsafe.Pointer(p)).FbMaybeNullRow != 0 {
|
|
addr = _sqlite3VdbeAddOp1(tls, v, int32(OP_IfNullRow), (*TIndexedExpr)(unsafe.Pointer(p)).FiIdxCur)
|
|
}
|
|
ret = _sqlite3ExprCodeTarget(tls, pParse, (*TIndexedExpr)(unsafe.Pointer(p)).FpExpr, iTarget)
|
|
_sqlite3VdbeAddOp4(tls, (*TParse)(unsafe.Pointer(pParse)).FpVdbe, int32(OP_Affinity), ret, int32(1), 0, p+21, int32(1))
|
|
if addr != 0 {
|
|
_sqlite3VdbeJumpHere(tls, v, addr)
|
|
_sqlite3VdbeChangeP3(tls, v, addr, ret)
|
|
}
|
|
return ret
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
p = (*TIndexedExpr)(unsafe.Pointer(p)).FpIENext
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Recursively walk the expressions of a SELECT statement and generate
|
|
// ** a bitmask indicating which tables are used in that expression
|
|
// ** tree.
|
|
// */
|
|
func _exprSelectUsage(tls *libc.TLS, pMaskSet uintptr, pS uintptr) (r TBitmask) {
|
|
var i int32
|
|
var mask TBitmask
|
|
var pSrc uintptr
|
|
_, _, _ = i, mask, pSrc
|
|
mask = uint64(0)
|
|
for pS != 0 {
|
|
pSrc = (*TSelect)(unsafe.Pointer(pS)).FpSrc
|
|
mask = mask | _sqlite3WhereExprListUsage(tls, pMaskSet, (*TSelect)(unsafe.Pointer(pS)).FpEList)
|
|
mask = mask | _sqlite3WhereExprListUsage(tls, pMaskSet, (*TSelect)(unsafe.Pointer(pS)).FpGroupBy)
|
|
mask = mask | _sqlite3WhereExprListUsage(tls, pMaskSet, (*TSelect)(unsafe.Pointer(pS)).FpOrderBy)
|
|
mask = mask | _sqlite3WhereExprUsage(tls, pMaskSet, (*TSelect)(unsafe.Pointer(pS)).FpWhere)
|
|
mask = mask | _sqlite3WhereExprUsage(tls, pMaskSet, (*TSelect)(unsafe.Pointer(pS)).FpHaving)
|
|
if pSrc != uintptr(0) {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TSrcList)(unsafe.Pointer(pSrc)).FnSrc) {
|
|
break
|
|
}
|
|
if int32(*(*uint32)(unsafe.Pointer(pSrc + 8 + uintptr(i)*80 + 24 + 4))&0x4>>2) != 0 {
|
|
mask = mask | _exprSelectUsage(tls, pMaskSet, (*TSubquery)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pSrc + 8 + uintptr(i)*80 + 72)))).FpSelect)
|
|
}
|
|
if int32(*(*uint32)(unsafe.Pointer(pSrc + 8 + uintptr(i)*80 + 24 + 4))&0x800>>11) == 0 {
|
|
mask = mask | _sqlite3WhereExprUsage(tls, pMaskSet, *(*uintptr)(unsafe.Pointer(pSrc + 8 + uintptr(i)*80 + 64)))
|
|
}
|
|
if int32(*(*uint32)(unsafe.Pointer(pSrc + 8 + uintptr(i)*80 + 24 + 4))&0x8>>3) != 0 {
|
|
mask = mask | _sqlite3WhereExprListUsage(tls, pMaskSet, *(*uintptr)(unsafe.Pointer(pSrc + 8 + uintptr(i)*80 + 48)))
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
pS = (*TSelect)(unsafe.Pointer(pS)).FpPrior
|
|
}
|
|
return mask
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return an Expr object that refers to column iCol of table pTab which
|
|
// ** has cursor iCur.
|
|
// */
|
|
func _exprTableColumn(tls *libc.TLS, db uintptr, pTab uintptr, iCursor int32, iCol Ti16) (r uintptr) {
|
|
var pExpr uintptr
|
|
_ = pExpr
|
|
pExpr = _sqlite3Expr(tls, db, int32(TK_COLUMN), uintptr(0))
|
|
if pExpr != 0 {
|
|
*(*uintptr)(unsafe.Pointer(pExpr + 64)) = pTab
|
|
(*TExpr)(unsafe.Pointer(pExpr)).FiTable = iCursor
|
|
(*TExpr)(unsafe.Pointer(pExpr)).FiColumn = iCol
|
|
}
|
|
return pExpr
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The implementation of SQL function sqlite_fail(MSG). This takes a single
|
|
// ** argument, and returns it as an error message with the error code set to
|
|
// ** SQLITE_CONSTRAINT.
|
|
// */
|
|
func _failConstraintFunc(tls *libc.TLS, ctx uintptr, NotUsed int32, argv uintptr) {
|
|
var err int32
|
|
var zText uintptr
|
|
_, _ = err, zText
|
|
zText = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
err = Xsqlite3_value_int(tls, **(**uintptr)(__ccgo_up(argv + 1*8)))
|
|
_ = NotUsed
|
|
Xsqlite3_result_error(tls, ctx, zText, -int32(1))
|
|
Xsqlite3_result_error_code(tls, ctx, err)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of internal SQL function:
|
|
// **
|
|
// ** sqlite_find_constraint(SQL, CONSTRAINT-NAME)
|
|
// **
|
|
// ** This function returns true if the SQL passed as the first argument is a
|
|
// ** CREATE TABLE that contains a constraint with the name CONSTRAINT-NAME,
|
|
// ** or false otherwise.
|
|
// */
|
|
func _findConstraintFunc(tls *libc.TLS, ctx uintptr, NotUsed int32, argv uintptr) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var iOff, nTok int32
|
|
var zCons, zSql uintptr
|
|
var _ /* cmp at bp+4 */ int32
|
|
var _ /* t at bp+0 */ int32
|
|
_, _, _, _ = iOff, nTok, zCons, zSql
|
|
zSql = uintptr(0)
|
|
zCons = uintptr(0)
|
|
iOff = 0
|
|
**(**int32)(__ccgo_up(bp)) = 0
|
|
_ = NotUsed
|
|
zSql = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
zCons = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv + 1*8)))
|
|
if zSql == uintptr(0) || zCons == uintptr(0) {
|
|
return
|
|
}
|
|
for **(**int32)(__ccgo_up(bp)) != int32(TK_LP) && **(**int32)(__ccgo_up(bp)) != int32(TK_ILLEGAL) {
|
|
iOff = int32(int64(iOff) + _sqlite3GetToken(tls, zSql+uintptr(iOff), bp))
|
|
}
|
|
for int32(1) != 0 {
|
|
iOff = iOff + _getConstraintToken(tls, zSql+uintptr(iOff), bp)
|
|
if **(**int32)(__ccgo_up(bp)) == int32(TK_CONSTRAINT) {
|
|
nTok = 0
|
|
**(**int32)(__ccgo_up(bp + 4)) = 0
|
|
iOff = iOff + _getWhitespace(tls, zSql+uintptr(iOff))
|
|
nTok = _getConstraintToken(tls, zSql+uintptr(iOff), bp)
|
|
if _quotedCompare(tls, ctx, **(**int32)(__ccgo_up(bp)), zSql+uintptr(iOff), nTok, zCons, bp+4) != 0 {
|
|
return
|
|
}
|
|
if **(**int32)(__ccgo_up(bp + 4)) == 0 {
|
|
Xsqlite3_result_int(tls, ctx, int32(1))
|
|
return
|
|
}
|
|
} else {
|
|
if **(**int32)(__ccgo_up(bp)) == int32(TK_ILLEGAL) {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
Xsqlite3_result_int(tls, ctx, 0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* This function (for internal use only) locates an element in an
|
|
// ** hash table that matches the given key. If no element is found,
|
|
// ** a pointer to a static null element with HashElem.data==0 is returned.
|
|
// ** If pH is not NULL, then the hash for this key is written to *pH.
|
|
// */
|
|
func _findElementWithHash(tls *libc.TLS, pH uintptr, pKey uintptr, pHash uintptr) (r uintptr) {
|
|
var count, h uint32
|
|
var elem, pEntry uintptr
|
|
_, _, _, _ = count, elem, h, pEntry /* The computed hash */
|
|
h = _strHash(tls, pKey)
|
|
if (*THash)(unsafe.Pointer(pH)).Fht != 0 {
|
|
pEntry = (*THash)(unsafe.Pointer(pH)).Fht + uintptr(h%(*THash)(unsafe.Pointer(pH)).Fhtsize)*16
|
|
elem = (*T_ht)(unsafe.Pointer(pEntry)).Fchain
|
|
count = (*T_ht)(unsafe.Pointer(pEntry)).Fcount
|
|
} else {
|
|
elem = (*THash)(unsafe.Pointer(pH)).Ffirst
|
|
count = (*THash)(unsafe.Pointer(pH)).Fcount
|
|
}
|
|
if pHash != 0 {
|
|
**(**uint32)(__ccgo_up(pHash)) = h
|
|
}
|
|
for count != 0 {
|
|
if h == (*THashElem)(unsafe.Pointer(elem)).Fh && _sqlite3StrICmp(tls, (*THashElem)(unsafe.Pointer(elem)).FpKey, pKey) == 0 {
|
|
return elem
|
|
}
|
|
elem = (*THashElem)(unsafe.Pointer(elem)).Fnext
|
|
count = count - 1
|
|
}
|
|
return uintptr(unsafe.Pointer(&_nullElement))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The second argument points to an FKey object representing a foreign key
|
|
// ** for which pTab is the child table. An UPDATE statement against pTab
|
|
// ** is currently being processed. For each column of the table that is
|
|
// ** actually updated, the corresponding element in the aChange[] array
|
|
// ** is zero or greater (if a column is unmodified the corresponding element
|
|
// ** is set to -1). If the rowid column is modified by the UPDATE statement
|
|
// ** the bChngRowid argument is non-zero.
|
|
// **
|
|
// ** This function returns true if any of the columns that are part of the
|
|
// ** child key for FK constraint *p are modified.
|
|
// */
|
|
func _fkChildIsModified(tls *libc.TLS, pTab uintptr, p uintptr, aChange uintptr, bChngRowid int32) (r int32) {
|
|
var i, iChildKey int32
|
|
_, _ = i, iChildKey
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFKey)(unsafe.Pointer(p)).FnCol) {
|
|
break
|
|
}
|
|
iChildKey = (*(*TsColMap)(unsafe.Pointer(p + 64 + uintptr(i)*16))).FiFrom
|
|
if **(**int32)(__ccgo_up(aChange + uintptr(iChildKey)*4)) >= 0 {
|
|
return int32(1)
|
|
}
|
|
if iChildKey == int32((*TTable)(unsafe.Pointer(pTab)).FiPKey) && bChngRowid != 0 {
|
|
return int32(1)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free an sqlite3_index_info structure allocated by allocateIndexInfo()
|
|
// ** and possibly modified by xBestIndex methods.
|
|
// */
|
|
func _freeIndexInfo(tls *libc.TLS, db uintptr, pIdxInfo uintptr) {
|
|
var i int32
|
|
var pHidden uintptr
|
|
_, _ = i, pHidden
|
|
pHidden = pIdxInfo + 1*96
|
|
i = 0
|
|
for {
|
|
if !(i < (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FnConstraint) {
|
|
break
|
|
}
|
|
_sqlite3ValueFree(tls, *(*uintptr)(unsafe.Pointer(pHidden + 32 + uintptr(i)*8))) /* IMP: R-14553-25174 */
|
|
*(*uintptr)(unsafe.Pointer(pHidden + 32 + uintptr(i)*8)) = uintptr(0)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_freeIdxStr(tls, pIdxInfo)
|
|
_sqlite3DbFree(tls, db, pIdxInfo)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free the pBt->pTmpSpace allocation
|
|
// */
|
|
func _freeTempSpace(tls *libc.TLS, pBt uintptr) {
|
|
if (*TBtShared)(unsafe.Pointer(pBt)).FpTmpSpace != 0 {
|
|
**(**uintptr)(__ccgo_up(pBt + 136)) -= uintptr(4)
|
|
_sqlite3PageFree(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpTmpSpace)
|
|
(*TBtShared)(unsafe.Pointer(pBt)).FpTmpSpace = uintptr(0)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of API function xQueryPhrase().
|
|
// */
|
|
func _fts5ApiQueryPhrase(tls *libc.TLS, pCtx uintptr, iPhrase int32, pUserData uintptr, __ccgo_fp_xCallback uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var pCsr, pTab uintptr
|
|
var rc int32
|
|
var _ /* pNew at bp+0 */ uintptr
|
|
_, _, _ = pCsr, pTab, rc
|
|
pCsr = pCtx
|
|
pTab = (*TFts5Cursor)(unsafe.Pointer(pCsr)).Fbase.FpVtab
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
rc = _fts5OpenMethod(tls, (*TFts5Cursor)(unsafe.Pointer(pCsr)).Fbase.FpVtab, bp)
|
|
if rc == SQLITE_OK {
|
|
(*TFts5Cursor)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FePlan = int32(FTS5_PLAN_MATCH)
|
|
(*TFts5Cursor)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FiFirstRowid = int64(-libc.Int32FromInt32(1)) - (libc.Int64FromUint32(0xffffffff) | libc.Int64FromInt32(0x7fffffff)<<libc.Int32FromInt32(32))
|
|
(*TFts5Cursor)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FiLastRowid = libc.Int64FromUint32(0xffffffff) | libc.Int64FromInt32(0x7fffffff)<<libc.Int32FromInt32(32)
|
|
(*TFts5Cursor)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).Fbase.FpVtab = pTab
|
|
rc = _sqlite3Fts5ExprClonePhrase(tls, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpExpr, iPhrase, **(**uintptr)(__ccgo_up(bp))+64)
|
|
}
|
|
if rc == SQLITE_OK {
|
|
rc = _fts5CursorFirst(tls, pTab, **(**uintptr)(__ccgo_up(bp)), 0)
|
|
for {
|
|
if !(rc == SQLITE_OK && (*TFts5Cursor)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).Fcsrflags&int32(FTS5CSR_EOF) == 0) {
|
|
break
|
|
}
|
|
rc = (*(*func(*libc.TLS, uintptr, uintptr, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xCallback})))(tls, uintptr(unsafe.Pointer(&_sFts5Api)), **(**uintptr)(__ccgo_up(bp)), pUserData)
|
|
if rc != SQLITE_OK {
|
|
if rc == int32(SQLITE_DONE) {
|
|
rc = SQLITE_OK
|
|
}
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
rc = _fts5NextMethod(tls, **(**uintptr)(__ccgo_up(bp)))
|
|
}
|
|
}
|
|
_fts5CloseMethod(tls, **(**uintptr)(__ccgo_up(bp)))
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of the xSetAuxdata() method.
|
|
// */
|
|
func _fts5ApiSetAuxdata(tls *libc.TLS, pCtx uintptr, pPtr uintptr, __ccgo_fp_xDelete uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var pCsr, pData uintptr
|
|
var _ /* rc at bp+0 */ int32
|
|
_, _ = pCsr, pData
|
|
pCsr = pCtx
|
|
/* Search through the cursors list of Fts5Auxdata objects for one that
|
|
** corresponds to the currently executing auxiliary function. */
|
|
pData = (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpAuxdata
|
|
for {
|
|
if !(pData != 0) {
|
|
break
|
|
}
|
|
if (*TFts5Auxdata)(unsafe.Pointer(pData)).FpAux == (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpAux {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pData = (*TFts5Auxdata)(unsafe.Pointer(pData)).FpNext
|
|
}
|
|
if pData != 0 {
|
|
if (*TFts5Auxdata)(unsafe.Pointer(pData)).FxDelete != 0 {
|
|
(*(*func(*libc.TLS, uintptr))(unsafe.Pointer(&struct{ uintptr }{(*TFts5Auxdata)(unsafe.Pointer(pData)).FxDelete})))(tls, (*TFts5Auxdata)(unsafe.Pointer(pData)).FpPtr)
|
|
}
|
|
} else {
|
|
**(**int32)(__ccgo_up(bp)) = SQLITE_OK
|
|
pData = _sqlite3Fts5MallocZero(tls, bp, int64(32))
|
|
if pData == uintptr(0) {
|
|
if __ccgo_fp_xDelete != 0 {
|
|
(*(*func(*libc.TLS, uintptr))(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xDelete})))(tls, pPtr)
|
|
}
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
(*TFts5Auxdata)(unsafe.Pointer(pData)).FpAux = (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpAux
|
|
(*TFts5Auxdata)(unsafe.Pointer(pData)).FpNext = (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpAuxdata
|
|
(*TFts5Cursor)(unsafe.Pointer(pCsr)).FpAuxdata = pData
|
|
}
|
|
(*TFts5Auxdata)(unsafe.Pointer(pData)).FxDelete = __ccgo_fp_xDelete
|
|
(*TFts5Auxdata)(unsafe.Pointer(pData)).FpPtr = pPtr
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Close the cursor. For additional information see the documentation
|
|
// ** on the xClose method of the virtual table interface.
|
|
// */
|
|
func _fts5CloseMethod(tls *libc.TLS, pCursor uintptr) (r int32) {
|
|
var pCsr, pTab, pp uintptr
|
|
_, _, _ = pCsr, pTab, pp
|
|
if pCursor != 0 {
|
|
pTab = (*Tsqlite3_vtab_cursor)(unsafe.Pointer(pCursor)).FpVtab
|
|
pCsr = pCursor
|
|
_fts5FreeCursorComponents(tls, pCsr)
|
|
/* Remove the cursor from the Fts5Global.pCsr list */
|
|
pp = (*TFts5FullTable)(unsafe.Pointer(pTab)).FpGlobal + 88
|
|
for {
|
|
if !(**(**uintptr)(__ccgo_up(pp)) != pCsr) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pp = **(**uintptr)(__ccgo_up(pp)) + 8
|
|
}
|
|
**(**uintptr)(__ccgo_up(pp)) = (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpNext
|
|
Xsqlite3_free(tls, pCsr)
|
|
}
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This is the xColumn method, called by SQLite to request a value from
|
|
// ** the row that the supplied cursor currently points to.
|
|
// */
|
|
func _fts5ColumnMethod(tls *libc.TLS, pCursor uintptr, pCtx uintptr, iCol int32) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var pConfig, pCsr, pTab, pVal uintptr
|
|
var rc, v1 int32
|
|
var v2 bool
|
|
var _ /* n at bp+8 */ int32
|
|
var _ /* z at bp+0 */ uintptr
|
|
_, _, _, _, _, _, _ = pConfig, pCsr, pTab, pVal, rc, v1, v2
|
|
pTab = (*Tsqlite3_vtab_cursor)(unsafe.Pointer(pCursor)).FpVtab
|
|
pConfig = (*TFts5FullTable)(unsafe.Pointer(pTab)).Fp.FpConfig
|
|
pCsr = pCursor
|
|
rc = SQLITE_OK
|
|
if (*TFts5Cursor)(unsafe.Pointer(pCsr)).FePlan == int32(FTS5_PLAN_SPECIAL) {
|
|
if iCol == (*TFts5Config)(unsafe.Pointer(pConfig)).FnCol {
|
|
Xsqlite3_result_int64(tls, pCtx, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FiSpecial)
|
|
}
|
|
} else {
|
|
if iCol == (*TFts5Config)(unsafe.Pointer(pConfig)).FnCol {
|
|
/* User is requesting the value of the special column with the same name
|
|
** as the table. Return the cursor integer id number. This value is only
|
|
** useful in that it may be passed as the first argument to an FTS5
|
|
** auxiliary function. */
|
|
Xsqlite3_result_int64(tls, pCtx, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FiCsrId)
|
|
} else {
|
|
if iCol == (*TFts5Config)(unsafe.Pointer(pConfig)).FnCol+int32(1) {
|
|
/* The value of the "rank" column. */
|
|
if (*TFts5Cursor)(unsafe.Pointer(pCsr)).FePlan == int32(FTS5_PLAN_SOURCE) {
|
|
_fts5PoslistBlob(tls, pCtx, pCsr)
|
|
} else {
|
|
if (*TFts5Cursor)(unsafe.Pointer(pCsr)).FePlan == int32(FTS5_PLAN_MATCH) || (*TFts5Cursor)(unsafe.Pointer(pCsr)).FePlan == int32(FTS5_PLAN_SORTED_MATCH) {
|
|
if v2 = (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpRank != 0; !v2 {
|
|
v1 = _fts5FindRankFunction(tls, pCsr)
|
|
rc = v1
|
|
}
|
|
if v2 || SQLITE_OK == v1 {
|
|
_fts5ApiInvoke(tls, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpRank, pCsr, pCtx, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FnRankArg, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FapRankArg)
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if !(Xsqlite3_vtab_nochange(tls, pCtx) != 0) && (*TFts5Config)(unsafe.Pointer(pConfig)).FeContent != int32(FTS5_CONTENT_NONE) {
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).FpzErrmsg = pTab + 16
|
|
rc = _fts5SeekCursor(tls, pCsr, int32(1))
|
|
if rc == SQLITE_OK {
|
|
pVal = Xsqlite3_column_value(tls, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpStmt, iCol+int32(1))
|
|
if (*TFts5Config)(unsafe.Pointer(pConfig)).FbLocale != 0 && (*TFts5Config)(unsafe.Pointer(pConfig)).FeContent == int32(FTS5_CONTENT_EXTERNAL) && _sqlite3Fts5IsLocaleValue(tls, pConfig, pVal) != 0 {
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
**(**int32)(__ccgo_up(bp + 8)) = 0
|
|
rc = _fts5TextFromStmt(tls, pConfig, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpStmt, iCol, bp, bp+8)
|
|
if rc == SQLITE_OK {
|
|
Xsqlite3_result_text(tls, pCtx, **(**uintptr)(__ccgo_up(bp)), **(**int32)(__ccgo_up(bp + 8)), uintptr(-libc.Int32FromInt32(1)))
|
|
}
|
|
_sqlite3Fts5ClearLocale(tls, pConfig)
|
|
} else {
|
|
Xsqlite3_result_value(tls, pCtx, pVal)
|
|
}
|
|
}
|
|
(*TFts5Config)(unsafe.Pointer(pConfig)).FpzErrmsg = uintptr(0)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is called after the cursor passed as the only argument
|
|
// ** is moved to point at a different row. It clears all cached data
|
|
// ** specific to the previous row stored by the cursor object.
|
|
// */
|
|
func _fts5CsrNewrow(tls *libc.TLS, pCsr uintptr) {
|
|
**(**int32)(__ccgo_up(pCsr + 80)) |= libc.Int32FromInt32(FTS5CSR_REQUIRE_CONTENT) | libc.Int32FromInt32(FTS5CSR_REQUIRE_DOCSIZE) | libc.Int32FromInt32(FTS5CSR_REQUIRE_INST) | libc.Int32FromInt32(FTS5CSR_REQUIRE_POSLIST)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This is called by various API functions - xInst, xPhraseFirst,
|
|
// ** xPhraseFirstColumn etc. - to obtain the position list for phrase iPhrase
|
|
// ** of the current row. This function works for both detail=full tables (in
|
|
// ** which case the position-list was read from the fts index) or for other
|
|
// ** detail= modes if the row content is available.
|
|
// */
|
|
func _fts5CsrPoslist(tls *libc.TLS, pCsr uintptr, iPhrase int32, pa uintptr, pn uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var aPopulator, pConfig, pSorter uintptr
|
|
var bLive, i, i1, rc, v2 int32
|
|
var _ /* n at bp+8 */ int32
|
|
var _ /* z at bp+0 */ uintptr
|
|
_, _, _, _, _, _, _, _ = aPopulator, bLive, i, i1, pConfig, pSorter, rc, v2
|
|
pConfig = (*TFts5Table)(unsafe.Pointer((*TFts5Cursor)(unsafe.Pointer(pCsr)).Fbase.FpVtab)).FpConfig
|
|
rc = SQLITE_OK
|
|
bLive = libc.BoolInt32((*TFts5Cursor)(unsafe.Pointer(pCsr)).FpSorter == uintptr(0))
|
|
if iPhrase < 0 || iPhrase >= _sqlite3Fts5ExprPhraseCount(tls, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpExpr) {
|
|
rc = int32(SQLITE_RANGE)
|
|
} else {
|
|
if (*TFts5Config)(unsafe.Pointer(pConfig)).FeDetail != FTS5_DETAIL_FULL && _fts5IsContentless(tls, (*TFts5Cursor)(unsafe.Pointer(pCsr)).Fbase.FpVtab, int32(1)) != 0 {
|
|
**(**uintptr)(__ccgo_up(pa)) = uintptr(0)
|
|
**(**int32)(__ccgo_up(pn)) = 0
|
|
return SQLITE_OK
|
|
} else {
|
|
if (*TFts5Cursor)(unsafe.Pointer(pCsr)).Fcsrflags&int32(FTS5CSR_REQUIRE_POSLIST) != 0 {
|
|
if (*TFts5Config)(unsafe.Pointer(pConfig)).FeDetail != FTS5_DETAIL_FULL {
|
|
aPopulator = _sqlite3Fts5ExprClearPoslists(tls, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpExpr, bLive)
|
|
if aPopulator == uintptr(0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
}
|
|
if rc == SQLITE_OK {
|
|
rc = _fts5SeekCursor(tls, pCsr, 0)
|
|
}
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5Config)(unsafe.Pointer(pConfig)).FnCol && rc == SQLITE_OK) {
|
|
break
|
|
}
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
**(**int32)(__ccgo_up(bp + 8)) = 0
|
|
rc = _fts5TextFromStmt(tls, pConfig, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpStmt, i, bp, bp+8)
|
|
if rc == SQLITE_OK {
|
|
rc = _sqlite3Fts5ExprPopulatePoslists(tls, pConfig, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpExpr, aPopulator, i, **(**uintptr)(__ccgo_up(bp)), **(**int32)(__ccgo_up(bp + 8)))
|
|
}
|
|
_sqlite3Fts5ClearLocale(tls, pConfig)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
Xsqlite3_free(tls, aPopulator)
|
|
if (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpSorter != 0 {
|
|
_sqlite3Fts5ExprCheckPoslists(tls, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpExpr, (*TFts5Sorter)(unsafe.Pointer((*TFts5Cursor)(unsafe.Pointer(pCsr)).FpSorter)).FiRowid)
|
|
}
|
|
}
|
|
**(**int32)(__ccgo_up(pCsr + 80)) &= ^libc.Int32FromInt32(FTS5CSR_REQUIRE_POSLIST)
|
|
}
|
|
}
|
|
}
|
|
if rc == SQLITE_OK {
|
|
if (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpSorter != 0 && (*TFts5Config)(unsafe.Pointer(pConfig)).FeDetail == FTS5_DETAIL_FULL {
|
|
pSorter = (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpSorter
|
|
if iPhrase == 0 {
|
|
v2 = 0
|
|
} else {
|
|
v2 = *(*int32)(unsafe.Pointer(pSorter + 28 + uintptr(iPhrase-int32(1))*4))
|
|
}
|
|
i1 = v2
|
|
**(**int32)(__ccgo_up(pn)) = *(*int32)(unsafe.Pointer(pSorter + 28 + uintptr(iPhrase)*4)) - i1
|
|
**(**uintptr)(__ccgo_up(pa)) = (*TFts5Sorter)(unsafe.Pointer(pSorter)).FaPoslist + uintptr(i1)
|
|
} else {
|
|
**(**int32)(__ccgo_up(pn)) = _sqlite3Fts5ExprPoslist(tls, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpExpr, iPhrase, pa)
|
|
}
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(pa)) = uintptr(0)
|
|
**(**int32)(__ccgo_up(pn)) = 0
|
|
}
|
|
return rc
|
|
}
|
|
|
|
func _fts5CursorFirst(tls *libc.TLS, pTab uintptr, pCsr uintptr, bDesc int32) (r int32) {
|
|
var pExpr uintptr
|
|
var rc int32
|
|
_, _ = pExpr, rc
|
|
pExpr = (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpExpr
|
|
rc = _sqlite3Fts5ExprFirst(tls, pExpr, (*TFts5FullTable)(unsafe.Pointer(pTab)).Fp.FpIndex, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FiFirstRowid, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FiLastRowid, bDesc)
|
|
if _sqlite3Fts5ExprEof(tls, pExpr) != 0 {
|
|
**(**int32)(__ccgo_up(pCsr + 80)) |= int32(FTS5CSR_EOF)
|
|
}
|
|
_fts5CsrNewrow(tls, pCsr)
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If the REQUIRE_RESEEK flag is set on the cursor passed as the first
|
|
// ** argument, close and reopen all Fts5IndexIter iterators that the cursor
|
|
// ** is using. Then attempt to move the cursor to a rowid equal to or laster
|
|
// ** (in the cursors sort order - ASC or DESC) than the current rowid.
|
|
// **
|
|
// ** If the new rowid is not equal to the old, set output parameter *pbSkip
|
|
// ** to 1 before returning. Otherwise, leave it unchanged.
|
|
// **
|
|
// ** Return SQLITE_OK if successful or if no reseek was required, or an
|
|
// ** error code if an error occurred.
|
|
// */
|
|
func _fts5CursorReseek(tls *libc.TLS, pCsr uintptr, pbSkip uintptr) (r int32) {
|
|
var bDesc, rc int32
|
|
var iRowid Ti64
|
|
var pTab uintptr
|
|
_, _, _, _ = bDesc, iRowid, pTab, rc
|
|
rc = SQLITE_OK
|
|
if (*TFts5Cursor)(unsafe.Pointer(pCsr)).Fcsrflags&int32(FTS5CSR_REQUIRE_RESEEK) != 0 {
|
|
pTab = (*TFts5Cursor)(unsafe.Pointer(pCsr)).Fbase.FpVtab
|
|
bDesc = (*TFts5Cursor)(unsafe.Pointer(pCsr)).FbDesc
|
|
iRowid = _sqlite3Fts5ExprRowid(tls, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpExpr)
|
|
rc = _sqlite3Fts5ExprFirst(tls, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpExpr, (*TFts5FullTable)(unsafe.Pointer(pTab)).Fp.FpIndex, iRowid, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FiLastRowid, bDesc)
|
|
if rc == SQLITE_OK && iRowid != _sqlite3Fts5ExprRowid(tls, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpExpr) {
|
|
**(**int32)(__ccgo_up(pbSkip)) = int32(1)
|
|
}
|
|
**(**int32)(__ccgo_up(pCsr + 80)) &= ^libc.Int32FromInt32(FTS5CSR_REQUIRE_RESEEK)
|
|
_fts5CsrNewrow(tls, pCsr)
|
|
if _sqlite3Fts5ExprEof(tls, (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpExpr) != 0 {
|
|
**(**int32)(__ccgo_up(pCsr + 80)) |= int32(FTS5CSR_EOF)
|
|
**(**int32)(__ccgo_up(pbSkip)) = int32(1)
|
|
}
|
|
}
|
|
return rc
|
|
}
|
|
|
|
func _fts5ExprCheckPoslists(tls *libc.TLS, pNode uintptr, iRowid Ti64) (r int32) {
|
|
var bRet, i, i1 int32
|
|
_, _, _ = bRet, i, i1
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FiRowid = iRowid
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FbEof = 0
|
|
switch (*TFts5ExprNode)(unsafe.Pointer(pNode)).FeType {
|
|
case 0:
|
|
fallthrough
|
|
case int32(FTS5_TERM):
|
|
fallthrough
|
|
case int32(FTS5_STRING):
|
|
return libc.BoolInt32((*TFts5ExprPhrase)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer((*TFts5ExprNode)(unsafe.Pointer(pNode)).FpNear + 24)))).Fposlist.Fn > 0)
|
|
case int32(FTS5_AND):
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5ExprNode)(unsafe.Pointer(pNode)).FnChild) {
|
|
break
|
|
}
|
|
if _fts5ExprCheckPoslists(tls, *(*uintptr)(unsafe.Pointer(pNode + 48 + uintptr(i)*8)), iRowid) == 0 {
|
|
_fts5ExprClearPoslists(tls, pNode)
|
|
return 0
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
case int32(FTS5_OR):
|
|
bRet = 0
|
|
i1 = 0
|
|
for {
|
|
if !(i1 < (*TFts5ExprNode)(unsafe.Pointer(pNode)).FnChild) {
|
|
break
|
|
}
|
|
if _fts5ExprCheckPoslists(tls, *(*uintptr)(unsafe.Pointer(pNode + 48 + uintptr(i1)*8)), iRowid) != 0 {
|
|
bRet = int32(1)
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i1 = i1 + 1
|
|
}
|
|
return bRet
|
|
default:
|
|
if 0 == _fts5ExprCheckPoslists(tls, *(*uintptr)(unsafe.Pointer(pNode + 48)), iRowid) || 0 != _fts5ExprCheckPoslists(tls, *(*uintptr)(unsafe.Pointer(pNode + 48 + 1*8)), iRowid) {
|
|
_fts5ExprClearPoslists(tls, pNode)
|
|
return 0
|
|
}
|
|
break
|
|
}
|
|
return int32(1)
|
|
}
|
|
|
|
func _fts5ExprClearPoslists(tls *libc.TLS, pNode uintptr) {
|
|
var i int32
|
|
_ = i
|
|
if (*TFts5ExprNode)(unsafe.Pointer(pNode)).FeType == int32(FTS5_TERM) || (*TFts5ExprNode)(unsafe.Pointer(pNode)).FeType == int32(FTS5_STRING) {
|
|
(*TFts5ExprPhrase)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer((*TFts5ExprNode)(unsafe.Pointer(pNode)).FpNear + 24)))).Fposlist.Fn = 0
|
|
} else {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5ExprNode)(unsafe.Pointer(pNode)).FnChild) {
|
|
break
|
|
}
|
|
_fts5ExprClearPoslists(tls, *(*uintptr)(unsafe.Pointer(pNode + 48 + uintptr(i)*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Set node pNode, which is part of expression pExpr, to point to the first
|
|
// ** match. If there are no matches, set the Node.bEof flag to indicate EOF.
|
|
// **
|
|
// ** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise.
|
|
// ** It is not an error if there are no matches.
|
|
// */
|
|
func _fts5ExprNodeFirst(tls *libc.TLS, pExpr uintptr, pNode uintptr) (r int32) {
|
|
var i, nEof, rc int32
|
|
var pChild uintptr
|
|
_, _, _, _ = i, nEof, pChild, rc
|
|
rc = SQLITE_OK
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FbEof = 0
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FbNomatch = 0
|
|
if (*TFts5ExprNode)(unsafe.Pointer(pNode)).FeType == int32(FTS5_TERM) || (*TFts5ExprNode)(unsafe.Pointer(pNode)).FeType == int32(FTS5_STRING) {
|
|
/* Initialize all term iterators in the NEAR object. */
|
|
rc = _fts5ExprNearInitAll(tls, pExpr, pNode)
|
|
} else {
|
|
if (*TFts5ExprNode)(unsafe.Pointer(pNode)).FxNext == uintptr(0) {
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FbEof = int32(1)
|
|
} else {
|
|
nEof = 0
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5ExprNode)(unsafe.Pointer(pNode)).FnChild && rc == SQLITE_OK) {
|
|
break
|
|
}
|
|
pChild = *(*uintptr)(unsafe.Pointer(pNode + 48 + uintptr(i)*8))
|
|
rc = _fts5ExprNodeFirst(tls, pExpr, *(*uintptr)(unsafe.Pointer(pNode + 48 + uintptr(i)*8)))
|
|
nEof = nEof + (*TFts5ExprNode)(unsafe.Pointer(pChild)).FbEof
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FiRowid = (*TFts5ExprNode)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pNode + 48)))).FiRowid
|
|
switch (*TFts5ExprNode)(unsafe.Pointer(pNode)).FeType {
|
|
case int32(FTS5_AND):
|
|
if nEof > 0 {
|
|
_fts5ExprSetEof(tls, pNode)
|
|
}
|
|
case int32(FTS5_OR):
|
|
if (*TFts5ExprNode)(unsafe.Pointer(pNode)).FnChild == nEof {
|
|
_fts5ExprSetEof(tls, pNode)
|
|
}
|
|
default:
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FbEof = (*TFts5ExprNode)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pNode + 48)))).FbEof
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if rc == SQLITE_OK {
|
|
rc = _fts5ExprNodeTest(tls, pExpr, pNode)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
func _fts5ExprNodeNext_AND(tls *libc.TLS, pExpr uintptr, pNode uintptr, bFromValid int32, iFrom Ti64) (r int32) {
|
|
var rc int32
|
|
_ = rc
|
|
rc = (*(*func(*libc.TLS, uintptr, uintptr, int32, Ti64) int32)(unsafe.Pointer(&struct{ uintptr }{(*TFts5ExprNode)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pNode + 48)))).FxNext})))(tls, pExpr, *(*uintptr)(unsafe.Pointer(pNode + 48)), bFromValid, iFrom)
|
|
if rc == SQLITE_OK {
|
|
rc = _fts5ExprNodeTest_AND(tls, pExpr, pNode)
|
|
} else {
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FbNomatch = 0
|
|
}
|
|
return rc
|
|
}
|
|
|
|
func _fts5ExprNodeNext_NOT(tls *libc.TLS, pExpr uintptr, pNode uintptr, bFromValid int32, iFrom Ti64) (r int32) {
|
|
var rc int32
|
|
_ = rc
|
|
rc = (*(*func(*libc.TLS, uintptr, uintptr, int32, Ti64) int32)(unsafe.Pointer(&struct{ uintptr }{(*TFts5ExprNode)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pNode + 48)))).FxNext})))(tls, pExpr, *(*uintptr)(unsafe.Pointer(pNode + 48)), bFromValid, iFrom)
|
|
if rc == SQLITE_OK {
|
|
rc = _fts5ExprNodeTest_NOT(tls, pExpr, pNode)
|
|
}
|
|
if rc != SQLITE_OK {
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FbNomatch = 0
|
|
}
|
|
return rc
|
|
}
|
|
|
|
func _fts5ExprNodeNext_OR(tls *libc.TLS, pExpr uintptr, pNode uintptr, bFromValid int32, iFrom Ti64) (r int32) {
|
|
var i, rc int32
|
|
var iLast Ti64
|
|
var p1 uintptr
|
|
_, _, _, _ = i, iLast, p1, rc
|
|
iLast = (*TFts5ExprNode)(unsafe.Pointer(pNode)).FiRowid
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5ExprNode)(unsafe.Pointer(pNode)).FnChild) {
|
|
break
|
|
}
|
|
p1 = *(*uintptr)(unsafe.Pointer(pNode + 48 + uintptr(i)*8))
|
|
if (*TFts5ExprNode)(unsafe.Pointer(p1)).FbEof == 0 {
|
|
if (*TFts5ExprNode)(unsafe.Pointer(p1)).FiRowid == iLast || bFromValid != 0 && _fts5RowidCmp(tls, pExpr, (*TFts5ExprNode)(unsafe.Pointer(p1)).FiRowid, iFrom) < 0 {
|
|
rc = (*(*func(*libc.TLS, uintptr, uintptr, int32, Ti64) int32)(unsafe.Pointer(&struct{ uintptr }{(*TFts5ExprNode)(unsafe.Pointer(p1)).FxNext})))(tls, pExpr, p1, bFromValid, iFrom)
|
|
if rc != SQLITE_OK {
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FbNomatch = 0
|
|
return rc
|
|
}
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_fts5ExprNodeTest_OR(tls, pExpr, pNode)
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Argument pNode is an FTS5_AND node.
|
|
// */
|
|
func _fts5ExprNodeTest_AND(tls *libc.TLS, pExpr uintptr, pAnd uintptr) (r int32) {
|
|
var bMatch, cmp, iChild, rc int32
|
|
var iLast Ti64
|
|
var pChild uintptr
|
|
_, _, _, _, _, _ = bMatch, cmp, iChild, iLast, pChild, rc
|
|
iLast = (*TFts5ExprNode)(unsafe.Pointer(pAnd)).FiRowid
|
|
rc = SQLITE_OK
|
|
for cond := true; cond; cond = bMatch == 0 {
|
|
(*TFts5ExprNode)(unsafe.Pointer(pAnd)).FbNomatch = 0
|
|
bMatch = int32(1)
|
|
iChild = 0
|
|
for {
|
|
if !(iChild < (*TFts5ExprNode)(unsafe.Pointer(pAnd)).FnChild) {
|
|
break
|
|
}
|
|
pChild = *(*uintptr)(unsafe.Pointer(pAnd + 48 + uintptr(iChild)*8))
|
|
cmp = _fts5RowidCmp(tls, pExpr, iLast, (*TFts5ExprNode)(unsafe.Pointer(pChild)).FiRowid)
|
|
if cmp > 0 {
|
|
/* Advance pChild until it points to iLast or laster */
|
|
rc = (*(*func(*libc.TLS, uintptr, uintptr, int32, Ti64) int32)(unsafe.Pointer(&struct{ uintptr }{(*TFts5ExprNode)(unsafe.Pointer(pChild)).FxNext})))(tls, pExpr, pChild, int32(1), iLast)
|
|
if rc != SQLITE_OK {
|
|
(*TFts5ExprNode)(unsafe.Pointer(pAnd)).FbNomatch = 0
|
|
return rc
|
|
}
|
|
}
|
|
/* If the child node is now at EOF, so is the parent AND node. Otherwise,
|
|
** the child node is guaranteed to have advanced at least as far as
|
|
** rowid iLast. So if it is not at exactly iLast, pChild->iRowid is the
|
|
** new lastest rowid seen so far. */
|
|
if (*TFts5ExprNode)(unsafe.Pointer(pChild)).FbEof != 0 {
|
|
_fts5ExprSetEof(tls, pAnd)
|
|
bMatch = int32(1)
|
|
break
|
|
} else {
|
|
if iLast != (*TFts5ExprNode)(unsafe.Pointer(pChild)).FiRowid {
|
|
bMatch = 0
|
|
iLast = (*TFts5ExprNode)(unsafe.Pointer(pChild)).FiRowid
|
|
}
|
|
}
|
|
if (*TFts5ExprNode)(unsafe.Pointer(pChild)).FbNomatch != 0 {
|
|
(*TFts5ExprNode)(unsafe.Pointer(pAnd)).FbNomatch = int32(1)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
iChild = iChild + 1
|
|
}
|
|
}
|
|
if (*TFts5ExprNode)(unsafe.Pointer(pAnd)).FbNomatch != 0 && pAnd != (*TFts5Expr)(unsafe.Pointer(pExpr)).FpRoot {
|
|
_fts5ExprNodeZeroPoslist(tls, pAnd)
|
|
}
|
|
(*TFts5ExprNode)(unsafe.Pointer(pAnd)).FiRowid = iLast
|
|
return SQLITE_OK
|
|
}
|
|
|
|
func _fts5ExprNodeTest_NOT(tls *libc.TLS, pExpr uintptr, pNode uintptr) (r int32) {
|
|
var cmp, rc int32
|
|
var p1, p2 uintptr
|
|
_, _, _, _ = cmp, p1, p2, rc
|
|
rc = SQLITE_OK
|
|
p1 = *(*uintptr)(unsafe.Pointer(pNode + 48))
|
|
p2 = *(*uintptr)(unsafe.Pointer(pNode + 48 + 1*8))
|
|
for rc == SQLITE_OK && (*TFts5ExprNode)(unsafe.Pointer(p1)).FbEof == 0 {
|
|
cmp = _fts5NodeCompare(tls, pExpr, p1, p2)
|
|
if cmp > 0 {
|
|
rc = (*(*func(*libc.TLS, uintptr, uintptr, int32, Ti64) int32)(unsafe.Pointer(&struct{ uintptr }{(*TFts5ExprNode)(unsafe.Pointer(p2)).FxNext})))(tls, pExpr, p2, int32(1), (*TFts5ExprNode)(unsafe.Pointer(p1)).FiRowid)
|
|
cmp = _fts5NodeCompare(tls, pExpr, p1, p2)
|
|
}
|
|
if cmp != 0 || (*TFts5ExprNode)(unsafe.Pointer(p2)).FbNomatch != 0 {
|
|
break
|
|
}
|
|
rc = (*(*func(*libc.TLS, uintptr, uintptr, int32, Ti64) int32)(unsafe.Pointer(&struct{ uintptr }{(*TFts5ExprNode)(unsafe.Pointer(p1)).FxNext})))(tls, pExpr, p1, 0, int64(libc.Int32FromInt32(0)))
|
|
}
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FbEof = (*TFts5ExprNode)(unsafe.Pointer(p1)).FbEof
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FbNomatch = (*TFts5ExprNode)(unsafe.Pointer(p1)).FbNomatch
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FiRowid = (*TFts5ExprNode)(unsafe.Pointer(p1)).FiRowid
|
|
if (*TFts5ExprNode)(unsafe.Pointer(p1)).FbEof != 0 {
|
|
_fts5ExprNodeZeroPoslist(tls, p2)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
func _fts5ExprNodeTest_OR(tls *libc.TLS, pExpr uintptr, pNode uintptr) {
|
|
var cmp, i int32
|
|
var pChild, pNext uintptr
|
|
_, _, _, _ = cmp, i, pChild, pNext
|
|
pNext = *(*uintptr)(unsafe.Pointer(pNode + 48))
|
|
i = int32(1)
|
|
for {
|
|
if !(i < (*TFts5ExprNode)(unsafe.Pointer(pNode)).FnChild) {
|
|
break
|
|
}
|
|
pChild = *(*uintptr)(unsafe.Pointer(pNode + 48 + uintptr(i)*8))
|
|
cmp = _fts5NodeCompare(tls, pExpr, pNext, pChild)
|
|
if cmp > 0 || cmp == 0 && (*TFts5ExprNode)(unsafe.Pointer(pChild)).FbNomatch == 0 {
|
|
pNext = pChild
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FiRowid = (*TFts5ExprNode)(unsafe.Pointer(pNext)).FiRowid
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FbEof = (*TFts5ExprNode)(unsafe.Pointer(pNext)).FbEof
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FbNomatch = (*TFts5ExprNode)(unsafe.Pointer(pNext)).FbNomatch
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** All individual term iterators in pNear are guaranteed to be valid when
|
|
// ** this function is called. This function checks if all term iterators
|
|
// ** point to the same rowid, and if not, advances them until they do.
|
|
// ** If an EOF is reached before this happens, *pbEof is set to true before
|
|
// ** returning.
|
|
// **
|
|
// ** SQLITE_OK is returned if an error occurs, or an SQLite error code
|
|
// ** otherwise. It is not considered an error code if an iterator reaches
|
|
// ** EOF.
|
|
// */
|
|
func _fts5ExprNodeTest_STRING(tls *libc.TLS, pExpr uintptr, pNode uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var bDesc, bMatch, i, j int32
|
|
var iRowid Ti64
|
|
var pIter, pLeft, pNear, pPhrase, pTerm uintptr
|
|
var _ /* iLast at bp+8 */ Ti64
|
|
var _ /* rc at bp+0 */ int32
|
|
_, _, _, _, _, _, _, _, _, _ = bDesc, bMatch, i, iRowid, j, pIter, pLeft, pNear, pPhrase, pTerm
|
|
pNear = (*TFts5ExprNode)(unsafe.Pointer(pNode)).FpNear
|
|
pLeft = *(*uintptr)(unsafe.Pointer(pNear + 24))
|
|
**(**int32)(__ccgo_up(bp)) = SQLITE_OK /* True if all terms are at the same rowid */
|
|
bDesc = (*TFts5Expr)(unsafe.Pointer(pExpr)).FbDesc
|
|
/* Check that this node should not be FTS5_TERM */
|
|
/* Initialize iLast, the "lastest" rowid any iterator points to. If the
|
|
** iterator skips through rowids in the default ascending order, this means
|
|
** the maximum rowid. Or, if the iterator is "ORDER BY rowid DESC", then it
|
|
** means the minimum rowid. */
|
|
if (*(*TFts5ExprTerm)(unsafe.Pointer(pLeft + 32))).FpSynonym != 0 {
|
|
**(**Ti64)(__ccgo_up(bp + 8)) = _fts5ExprSynonymRowid(tls, pLeft+32, bDesc, uintptr(0))
|
|
} else {
|
|
**(**Ti64)(__ccgo_up(bp + 8)) = (*TFts5IndexIter)(unsafe.Pointer((*(*TFts5ExprTerm)(unsafe.Pointer(pLeft + 32))).FpIter)).FiRowid
|
|
}
|
|
for cond := true; cond; cond = bMatch == 0 {
|
|
bMatch = int32(1)
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5ExprNearset)(unsafe.Pointer(pNear)).FnPhrase) {
|
|
break
|
|
}
|
|
pPhrase = *(*uintptr)(unsafe.Pointer(pNear + 24 + uintptr(i)*8))
|
|
j = 0
|
|
for {
|
|
if !(j < (*TFts5ExprPhrase)(unsafe.Pointer(pPhrase)).FnTerm) {
|
|
break
|
|
}
|
|
pTerm = pPhrase + 32 + uintptr(j)*40
|
|
if (*TFts5ExprTerm)(unsafe.Pointer(pTerm)).FpSynonym != 0 {
|
|
iRowid = _fts5ExprSynonymRowid(tls, pTerm, bDesc, uintptr(0))
|
|
if iRowid == **(**Ti64)(__ccgo_up(bp + 8)) {
|
|
goto _2
|
|
}
|
|
bMatch = 0
|
|
if _fts5ExprSynonymAdvanceto(tls, pTerm, bDesc, bp+8, bp) != 0 {
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FbNomatch = 0
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FbEof = int32(1)
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
} else {
|
|
pIter = (*(*TFts5ExprTerm)(unsafe.Pointer(pPhrase + 32 + uintptr(j)*40))).FpIter
|
|
if (*TFts5IndexIter)(unsafe.Pointer(pIter)).FiRowid == **(**Ti64)(__ccgo_up(bp + 8)) {
|
|
goto _2
|
|
}
|
|
bMatch = 0
|
|
if _fts5ExprAdvanceto(tls, pIter, bDesc, bp+8, bp, pNode+4) != 0 {
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
j = j + 1
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FiRowid = **(**Ti64)(__ccgo_up(bp + 8))
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FbNomatch = libc.BoolInt32(0 == _fts5ExprNearTest(tls, bp, pExpr, pNode) && **(**int32)(__ccgo_up(bp)) == SQLITE_OK)
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
|
|
func _fts5ExprNodeTest_TERM(tls *libc.TLS, pExpr uintptr, pNode uintptr) (r int32) {
|
|
var pIter, pPhrase uintptr
|
|
_, _ = pIter, pPhrase
|
|
/* As this "NEAR" object is actually a single phrase that consists
|
|
** of a single term only, grab pointers into the poslist managed by the
|
|
** fts5_index.c iterator object. This is much faster than synthesizing
|
|
** a new poslist the way we have to for more complicated phrase or NEAR
|
|
** expressions. */
|
|
pPhrase = *(*uintptr)(unsafe.Pointer((*TFts5ExprNode)(unsafe.Pointer(pNode)).FpNear + 24))
|
|
pIter = (*(*TFts5ExprTerm)(unsafe.Pointer(pPhrase + 32))).FpIter
|
|
(*TFts5ExprPhrase)(unsafe.Pointer(pPhrase)).Fposlist.Fn = (*TFts5IndexIter)(unsafe.Pointer(pIter)).FnData
|
|
if (*TFts5Config)(unsafe.Pointer((*TFts5Expr)(unsafe.Pointer(pExpr)).FpConfig)).FeDetail == FTS5_DETAIL_FULL {
|
|
(*TFts5ExprPhrase)(unsafe.Pointer(pPhrase)).Fposlist.Fp = (*TFts5IndexIter)(unsafe.Pointer(pIter)).FpData
|
|
}
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FiRowid = (*TFts5IndexIter)(unsafe.Pointer(pIter)).FiRowid
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FbNomatch = libc.BoolInt32((*TFts5ExprPhrase)(unsafe.Pointer(pPhrase)).Fposlist.Fn == 0)
|
|
return SQLITE_OK
|
|
}
|
|
|
|
func _fts5ExprNodeZeroPoslist(tls *libc.TLS, pNode uintptr) {
|
|
var i, i1 int32
|
|
var pNear, pPhrase uintptr
|
|
_, _, _, _ = i, i1, pNear, pPhrase
|
|
if (*TFts5ExprNode)(unsafe.Pointer(pNode)).FeType == int32(FTS5_STRING) || (*TFts5ExprNode)(unsafe.Pointer(pNode)).FeType == int32(FTS5_TERM) {
|
|
pNear = (*TFts5ExprNode)(unsafe.Pointer(pNode)).FpNear
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5ExprNearset)(unsafe.Pointer(pNear)).FnPhrase) {
|
|
break
|
|
}
|
|
pPhrase = *(*uintptr)(unsafe.Pointer(pNear + 24 + uintptr(i)*8))
|
|
(*TFts5ExprPhrase)(unsafe.Pointer(pPhrase)).Fposlist.Fn = 0
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
} else {
|
|
i1 = 0
|
|
for {
|
|
if !(i1 < (*TFts5ExprNode)(unsafe.Pointer(pNode)).FnChild) {
|
|
break
|
|
}
|
|
_fts5ExprNodeZeroPoslist(tls, *(*uintptr)(unsafe.Pointer(pNode + 48 + uintptr(i1)*8)))
|
|
goto _2
|
|
_2:
|
|
;
|
|
i1 = i1 + 1
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free the phrase object passed as the only argument.
|
|
// */
|
|
func _fts5ExprPhraseFree(tls *libc.TLS, pPhrase uintptr) {
|
|
var i int32
|
|
var pNext, pSyn, pTerm uintptr
|
|
_, _, _, _ = i, pNext, pSyn, pTerm
|
|
if pPhrase != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5ExprPhrase)(unsafe.Pointer(pPhrase)).FnTerm) {
|
|
break
|
|
}
|
|
pTerm = pPhrase + 32 + uintptr(i)*40
|
|
Xsqlite3_free(tls, (*TFts5ExprTerm)(unsafe.Pointer(pTerm)).FpTerm)
|
|
_sqlite3Fts5IterClose(tls, (*TFts5ExprTerm)(unsafe.Pointer(pTerm)).FpIter)
|
|
pSyn = (*TFts5ExprTerm)(unsafe.Pointer(pTerm)).FpSynonym
|
|
for {
|
|
if !(pSyn != 0) {
|
|
break
|
|
}
|
|
pNext = (*TFts5ExprTerm)(unsafe.Pointer(pSyn)).FpSynonym
|
|
_sqlite3Fts5IterClose(tls, (*TFts5ExprTerm)(unsafe.Pointer(pSyn)).FpIter)
|
|
_sqlite3Fts5BufferFree(tls, pSyn+1*40)
|
|
Xsqlite3_free(tls, pSyn)
|
|
goto _2
|
|
_2:
|
|
;
|
|
pSyn = pNext
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if (*TFts5ExprPhrase)(unsafe.Pointer(pPhrase)).Fposlist.FnSpace > 0 {
|
|
_sqlite3Fts5BufferFree(tls, pPhrase+8)
|
|
}
|
|
Xsqlite3_free(tls, pPhrase)
|
|
}
|
|
}
|
|
|
|
func _fts5ExprSetEof(tls *libc.TLS, pNode uintptr) {
|
|
var i int32
|
|
_ = i
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FbEof = int32(1)
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FbNomatch = 0
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5ExprNode)(unsafe.Pointer(pNode)).FnChild) {
|
|
break
|
|
}
|
|
_fts5ExprSetEof(tls, *(*uintptr)(unsafe.Pointer(pNode + 48 + uintptr(i)*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Find a tokenizer. This is the implementation of the
|
|
// ** fts5_api.xFindTokenizer_v2() method.
|
|
// */
|
|
func _fts5FindTokenizer_v2(tls *libc.TLS, pApi uintptr, zName uintptr, ppUserData uintptr, ppTokenizer uintptr) (r int32) {
|
|
var pMod uintptr
|
|
var rc int32
|
|
_, _ = pMod, rc
|
|
rc = SQLITE_OK
|
|
pMod = _fts5LocateTokenizer(tls, pApi, zName)
|
|
if pMod != 0 {
|
|
if (*TFts5TokenizerModule)(unsafe.Pointer(pMod)).FbV2Native != 0 {
|
|
**(**uintptr)(__ccgo_up(ppUserData)) = (*TFts5TokenizerModule)(unsafe.Pointer(pMod)).FpUserData
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(ppUserData)) = pMod
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppTokenizer)) = pMod + 48
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(ppTokenizer)) = uintptr(0)
|
|
**(**uintptr)(__ccgo_up(ppUserData)) = uintptr(0)
|
|
rc = int32(SQLITE_ERROR)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Tokenizer callback used by implementation of highlight() function.
|
|
// */
|
|
func _fts5HighlightCb(tls *libc.TLS, pContext uintptr, tflags int32, pToken uintptr, nToken int32, iStartOff int32, iEndOff int32) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var iPos, v1 int32
|
|
var p, v2 uintptr
|
|
var _ /* rc at bp+0 */ int32
|
|
_, _, _, _ = iPos, p, v1, v2
|
|
p = pContext
|
|
**(**int32)(__ccgo_up(bp)) = SQLITE_OK
|
|
_ = pToken
|
|
_ = nToken
|
|
if tflags&int32(FTS5_TOKEN_COLOCATED) != 0 {
|
|
return SQLITE_OK
|
|
}
|
|
v2 = p + 80
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
iPos = v1
|
|
if (*THighlightContext)(unsafe.Pointer(p)).FiRangeEnd >= 0 {
|
|
if iPos < (*THighlightContext)(unsafe.Pointer(p)).FiRangeStart || iPos > (*THighlightContext)(unsafe.Pointer(p)).FiRangeEnd {
|
|
return SQLITE_OK
|
|
}
|
|
if (*THighlightContext)(unsafe.Pointer(p)).FiRangeStart != 0 && iPos == (*THighlightContext)(unsafe.Pointer(p)).FiRangeStart {
|
|
(*THighlightContext)(unsafe.Pointer(p)).FiOff = iStartOff
|
|
}
|
|
}
|
|
/* If the parenthesis is open, and this token is not part of the current
|
|
** phrase, and the starting byte offset of this token is past the point
|
|
** that has currently been copied into the output buffer, close the
|
|
** parenthesis. */
|
|
if (*THighlightContext)(unsafe.Pointer(p)).FbOpen != 0 && (iPos <= (*THighlightContext)(unsafe.Pointer(p)).Fiter.FiStart || (*THighlightContext)(unsafe.Pointer(p)).Fiter.FiStart < 0) && iStartOff > (*THighlightContext)(unsafe.Pointer(p)).FiOff {
|
|
_fts5HighlightAppend(tls, bp, p, (*THighlightContext)(unsafe.Pointer(p)).FzClose, -int32(1))
|
|
(*THighlightContext)(unsafe.Pointer(p)).FbOpen = 0
|
|
}
|
|
/* If this is the start of a new phrase, and the highlight is not open:
|
|
**
|
|
** * copy text from the input up to the start of the phrase, and
|
|
** * open the highlight.
|
|
*/
|
|
if iPos == (*THighlightContext)(unsafe.Pointer(p)).Fiter.FiStart && (*THighlightContext)(unsafe.Pointer(p)).FbOpen == 0 {
|
|
_fts5HighlightAppend(tls, bp, p, (*THighlightContext)(unsafe.Pointer(p)).FzIn+uintptr((*THighlightContext)(unsafe.Pointer(p)).FiOff), iStartOff-(*THighlightContext)(unsafe.Pointer(p)).FiOff)
|
|
_fts5HighlightAppend(tls, bp, p, (*THighlightContext)(unsafe.Pointer(p)).FzOpen, -int32(1))
|
|
(*THighlightContext)(unsafe.Pointer(p)).FiOff = iStartOff
|
|
(*THighlightContext)(unsafe.Pointer(p)).FbOpen = int32(1)
|
|
}
|
|
if iPos == (*THighlightContext)(unsafe.Pointer(p)).Fiter.FiEnd {
|
|
if (*THighlightContext)(unsafe.Pointer(p)).FbOpen == 0 {
|
|
_fts5HighlightAppend(tls, bp, p, (*THighlightContext)(unsafe.Pointer(p)).FzOpen, -int32(1))
|
|
(*THighlightContext)(unsafe.Pointer(p)).FbOpen = int32(1)
|
|
}
|
|
_fts5HighlightAppend(tls, bp, p, (*THighlightContext)(unsafe.Pointer(p)).FzIn+uintptr((*THighlightContext)(unsafe.Pointer(p)).FiOff), iEndOff-(*THighlightContext)(unsafe.Pointer(p)).FiOff)
|
|
(*THighlightContext)(unsafe.Pointer(p)).FiOff = iEndOff
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
**(**int32)(__ccgo_up(bp)) = _fts5CInstIterNext(tls, p+40)
|
|
}
|
|
}
|
|
if iPos == (*THighlightContext)(unsafe.Pointer(p)).FiRangeEnd {
|
|
if (*THighlightContext)(unsafe.Pointer(p)).FbOpen != 0 {
|
|
if (*THighlightContext)(unsafe.Pointer(p)).Fiter.FiStart >= 0 && iPos >= (*THighlightContext)(unsafe.Pointer(p)).Fiter.FiStart {
|
|
_fts5HighlightAppend(tls, bp, p, (*THighlightContext)(unsafe.Pointer(p)).FzIn+uintptr((*THighlightContext)(unsafe.Pointer(p)).FiOff), iEndOff-(*THighlightContext)(unsafe.Pointer(p)).FiOff)
|
|
(*THighlightContext)(unsafe.Pointer(p)).FiOff = iEndOff
|
|
}
|
|
_fts5HighlightAppend(tls, bp, p, (*THighlightContext)(unsafe.Pointer(p)).FzClose, -int32(1))
|
|
(*THighlightContext)(unsafe.Pointer(p)).FbOpen = 0
|
|
}
|
|
_fts5HighlightAppend(tls, bp, p, (*THighlightContext)(unsafe.Pointer(p)).FzIn+uintptr((*THighlightContext)(unsafe.Pointer(p)).FiOff), iEndOff-(*THighlightContext)(unsafe.Pointer(p)).FiOff)
|
|
(*THighlightContext)(unsafe.Pointer(p)).FiOff = iEndOff
|
|
}
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Allocate and return a buffer at least nByte bytes in size.
|
|
// **
|
|
// ** If an OOM error is encountered, return NULL and set the error code in
|
|
// ** the Fts5Index handle passed as the first argument.
|
|
// */
|
|
func _fts5IdxMalloc(tls *libc.TLS, p uintptr, nByte Tsqlite3_int64) (r uintptr) {
|
|
return _sqlite3Fts5MallocZero(tls, p+60, nByte)
|
|
}
|
|
|
|
/*
|
|
** Compare the contents of the pLeft buffer with the pRight/nRight blob.
|
|
**
|
|
** Return -ve if pLeft is smaller than pRight, 0 if they are equal or
|
|
** +ve if pRight is smaller than pLeft. In other words:
|
|
**
|
|
** res = *pLeft - *pRight
|
|
*/
|
|
|
|
func _fts5IndexCrisismerge(tls *libc.TLS, p uintptr, ppStruct uintptr) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var iLvl, nCrisis int32
|
|
var _ /* pStruct at bp+0 */ uintptr
|
|
_, _ = iLvl, nCrisis
|
|
nCrisis = (*TFts5Config)(unsafe.Pointer((*TFts5Index)(unsafe.Pointer(p)).FpConfig)).FnCrisisMerge
|
|
**(**uintptr)(__ccgo_up(bp)) = **(**uintptr)(__ccgo_up(ppStruct))
|
|
if **(**uintptr)(__ccgo_up(bp)) != 0 && (*TFts5Structure)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FnLevel > 0 {
|
|
iLvl = 0
|
|
for (*TFts5Index)(unsafe.Pointer(p)).Frc == SQLITE_OK && (*(*TFts5StructureLevel)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)) + 32 + uintptr(iLvl)*16))).FnSeg >= nCrisis {
|
|
_fts5IndexMergeLevel(tls, p, bp, iLvl, uintptr(0))
|
|
_fts5StructurePromote(tls, p, iLvl+int32(1), **(**uintptr)(__ccgo_up(bp)))
|
|
iLvl = iLvl + 1
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppStruct)) = **(**uintptr)(__ccgo_up(bp))
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Array ap[] contains n elements. Release each of these elements using
|
|
// ** fts5DataRelease(). Then free the array itself using sqlite3_free().
|
|
// */
|
|
func _fts5IndexFreeArray(tls *libc.TLS, ap uintptr, n int32) {
|
|
var ii int32
|
|
_ = ii
|
|
if ap != 0 {
|
|
ii = 0
|
|
for {
|
|
if !(ii < n) {
|
|
break
|
|
}
|
|
_fts5DataRelease(tls, **(**uintptr)(__ccgo_up(ap + uintptr(ii)*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
Xsqlite3_free(tls, ap)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Do up to nPg pages of automerge work on the index.
|
|
// **
|
|
// ** Return true if any changes were actually made, or false otherwise.
|
|
// */
|
|
func _fts5IndexMerge(tls *libc.TLS, p uintptr, ppStruct uintptr, nPg int32, nMin int32) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var bRet, iBestLvl, iLvl, nBest int32
|
|
var pLvl uintptr
|
|
var _ /* nRem at bp+0 */ int32
|
|
var _ /* pStruct at bp+8 */ uintptr
|
|
_, _, _, _, _ = bRet, iBestLvl, iLvl, nBest, pLvl
|
|
**(**int32)(__ccgo_up(bp)) = nPg
|
|
bRet = 0
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = **(**uintptr)(__ccgo_up(ppStruct))
|
|
for **(**int32)(__ccgo_up(bp)) > 0 && (*TFts5Index)(unsafe.Pointer(p)).Frc == SQLITE_OK { /* To iterate through levels */
|
|
iBestLvl = 0 /* Level offering the most input segments */
|
|
nBest = 0 /* Number of input segments on best level */
|
|
/* Set iBestLvl to the level to read input segments from. Or to -1 if
|
|
** there is no level suitable to merge segments from. */
|
|
iLvl = 0
|
|
for {
|
|
if !(iLvl < (*TFts5Structure)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp + 8)))).FnLevel) {
|
|
break
|
|
}
|
|
pLvl = **(**uintptr)(__ccgo_up(bp + 8)) + 32 + uintptr(iLvl)*16
|
|
if (*TFts5StructureLevel)(unsafe.Pointer(pLvl)).FnMerge != 0 {
|
|
if (*TFts5StructureLevel)(unsafe.Pointer(pLvl)).FnMerge > nBest {
|
|
iBestLvl = iLvl
|
|
nBest = nMin
|
|
}
|
|
break
|
|
}
|
|
if (*TFts5StructureLevel)(unsafe.Pointer(pLvl)).FnSeg > nBest {
|
|
nBest = (*TFts5StructureLevel)(unsafe.Pointer(pLvl)).FnSeg
|
|
iBestLvl = iLvl
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
iLvl = iLvl + 1
|
|
}
|
|
if nBest < nMin {
|
|
iBestLvl = _fts5IndexFindDeleteMerge(tls, p, **(**uintptr)(__ccgo_up(bp + 8)))
|
|
}
|
|
if iBestLvl < 0 {
|
|
break
|
|
}
|
|
bRet = int32(1)
|
|
_fts5IndexMergeLevel(tls, p, bp+8, iBestLvl, bp)
|
|
if (*TFts5Index)(unsafe.Pointer(p)).Frc == SQLITE_OK && (*(*TFts5StructureLevel)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp + 8)) + 32 + uintptr(iBestLvl)*16))).FnMerge == 0 {
|
|
_fts5StructurePromote(tls, p, iBestLvl+int32(1), **(**uintptr)(__ccgo_up(bp + 8)))
|
|
}
|
|
if nMin == int32(1) {
|
|
nMin = int32(2)
|
|
}
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppStruct)) = **(**uintptr)(__ccgo_up(bp + 8))
|
|
return bRet
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is the implementation of both the xConnect and xCreate
|
|
// ** methods of the FTS3 virtual table.
|
|
// **
|
|
// ** The argv[] array contains the following:
|
|
// **
|
|
// ** argv[0] -> module name ("fts5")
|
|
// ** argv[1] -> database name
|
|
// ** argv[2] -> table name
|
|
// ** argv[...] -> "column name" and other module argument fields.
|
|
// */
|
|
func _fts5InitVtab(tls *libc.TLS, bCreate int32, db uintptr, pAux uintptr, argc int32, argv uintptr, ppVTab uintptr, pzErr uintptr) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var azConfig, pGlobal, pTab uintptr
|
|
var _ /* pConfig at bp+8 */ uintptr
|
|
var _ /* rc at bp+0 */ int32
|
|
_, _, _ = azConfig, pGlobal, pTab
|
|
pGlobal = pAux
|
|
azConfig = argv
|
|
**(**int32)(__ccgo_up(bp)) = SQLITE_OK /* Return code */
|
|
**(**uintptr)(__ccgo_up(bp + 8)) = uintptr(0) /* Results of parsing argc/argv */
|
|
pTab = uintptr(0) /* New virtual table object */
|
|
/* Allocate the new vtab object and parse the configuration */
|
|
pTab = _sqlite3Fts5MallocZero(tls, bp, int64(72))
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
**(**int32)(__ccgo_up(bp)) = _sqlite3Fts5ConfigParse(tls, pGlobal, db, argc, azConfig, bp+8, pzErr)
|
|
}
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
(*TFts5Config)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp + 8)))).FpzErrmsg = pzErr
|
|
(*TFts5FullTable)(unsafe.Pointer(pTab)).Fp.FpConfig = **(**uintptr)(__ccgo_up(bp + 8))
|
|
(*TFts5FullTable)(unsafe.Pointer(pTab)).FpGlobal = pGlobal
|
|
if bCreate != 0 || _sqlite3Fts5TokenizerPreload(tls, **(**uintptr)(__ccgo_up(bp + 8))+128) != 0 {
|
|
**(**int32)(__ccgo_up(bp)) = _sqlite3Fts5LoadTokenizer(tls, **(**uintptr)(__ccgo_up(bp + 8)))
|
|
}
|
|
}
|
|
/* Open the index sub-system */
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
**(**int32)(__ccgo_up(bp)) = _sqlite3Fts5IndexOpen(tls, **(**uintptr)(__ccgo_up(bp + 8)), bCreate, pTab+32, pzErr)
|
|
}
|
|
/* Open the storage sub-system */
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
**(**int32)(__ccgo_up(bp)) = _sqlite3Fts5StorageOpen(tls, **(**uintptr)(__ccgo_up(bp + 8)), (*TFts5FullTable)(unsafe.Pointer(pTab)).Fp.FpIndex, bCreate, pTab+40, pzErr)
|
|
}
|
|
/* Call sqlite3_declare_vtab() */
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
**(**int32)(__ccgo_up(bp)) = _sqlite3Fts5ConfigDeclareVtab(tls, **(**uintptr)(__ccgo_up(bp + 8)))
|
|
}
|
|
/* Load the initial configuration */
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
**(**int32)(__ccgo_up(bp)) = _sqlite3Fts5ConfigLoad(tls, (*TFts5FullTable)(unsafe.Pointer(pTab)).Fp.FpConfig, (*TFts5Config)(unsafe.Pointer((*TFts5FullTable)(unsafe.Pointer(pTab)).Fp.FpConfig)).FiCookie-int32(1))
|
|
}
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK && (*TFts5Config)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp + 8)))).FeContent == FTS5_CONTENT_NORMAL {
|
|
**(**int32)(__ccgo_up(bp)) = Xsqlite3_vtab_config(tls, db, int32(SQLITE_VTAB_CONSTRAINT_SUPPORT), libc.VaList(bp+24, libc.Int32FromInt32(1)))
|
|
}
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
**(**int32)(__ccgo_up(bp)) = Xsqlite3_vtab_config(tls, db, int32(SQLITE_VTAB_INNOCUOUS), 0)
|
|
}
|
|
if **(**uintptr)(__ccgo_up(bp + 8)) != 0 {
|
|
(*TFts5Config)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp + 8)))).FpzErrmsg = uintptr(0)
|
|
}
|
|
if **(**int32)(__ccgo_up(bp)) != SQLITE_OK {
|
|
_fts5FreeVtab(tls, pTab)
|
|
pTab = uintptr(0)
|
|
} else {
|
|
if bCreate != 0 {
|
|
}
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppVTab)) = pTab
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** xSetOutputs callback used by detail=col when there is a column filter
|
|
// ** and there are 100 or more columns. Also called as a fallback from
|
|
// ** fts5IterSetOutputs_Col100 if the column-list spans more than one page.
|
|
// */
|
|
func _fts5IterSetOutputs_Col(tls *libc.TLS, pIter uintptr, pSeg uintptr) {
|
|
_sqlite3Fts5BufferZero(tls, pIter+40)
|
|
_fts5SegiterPoslist(tls, (*TFts5Iter)(unsafe.Pointer(pIter)).FpIndex, pSeg, (*TFts5Iter)(unsafe.Pointer(pIter)).FpColset, pIter+40)
|
|
(*TFts5Iter)(unsafe.Pointer(pIter)).Fbase.FiRowid = (*TFts5SegIter)(unsafe.Pointer(pSeg)).FiRowid
|
|
(*TFts5Iter)(unsafe.Pointer(pIter)).Fbase.FpData = (*TFts5Iter)(unsafe.Pointer(pIter)).Fposlist.Fp
|
|
(*TFts5Iter)(unsafe.Pointer(pIter)).Fbase.FnData = (*TFts5Iter)(unsafe.Pointer(pIter)).Fposlist.Fn
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** xSetOutputs callback used by detail=full when there is a column filter.
|
|
// */
|
|
func _fts5IterSetOutputs_Full(tls *libc.TLS, pIter uintptr, pSeg uintptr) {
|
|
var a, pColset, pRc uintptr
|
|
_, _, _ = a, pColset, pRc
|
|
pColset = (*TFts5Iter)(unsafe.Pointer(pIter)).FpColset
|
|
(*TFts5Iter)(unsafe.Pointer(pIter)).Fbase.FiRowid = (*TFts5SegIter)(unsafe.Pointer(pSeg)).FiRowid
|
|
if (*TFts5SegIter)(unsafe.Pointer(pSeg)).FiLeafOffset+int64((*TFts5SegIter)(unsafe.Pointer(pSeg)).FnPos) <= int64((*TFts5Data)(unsafe.Pointer((*TFts5SegIter)(unsafe.Pointer(pSeg)).FpLeaf)).FszLeaf) {
|
|
/* All data is stored on the current page. Populate the output
|
|
** variables to point into the body of the page object. */
|
|
a = (*TFts5Data)(unsafe.Pointer((*TFts5SegIter)(unsafe.Pointer(pSeg)).FpLeaf)).Fp + uintptr((*TFts5SegIter)(unsafe.Pointer(pSeg)).FiLeafOffset)
|
|
pRc = (*TFts5Iter)(unsafe.Pointer(pIter)).FpIndex + 60
|
|
_sqlite3Fts5BufferZero(tls, pIter+40)
|
|
_fts5IndexExtractColset(tls, pRc, pColset, a, (*TFts5SegIter)(unsafe.Pointer(pSeg)).FnPos, pIter)
|
|
} else {
|
|
/* The data is distributed over two or more pages. Copy it into the
|
|
** Fts5Iter.poslist buffer and then set the output pointer to point
|
|
** to this buffer. */
|
|
_sqlite3Fts5BufferZero(tls, pIter+40)
|
|
_fts5SegiterPoslist(tls, (*TFts5Iter)(unsafe.Pointer(pIter)).FpIndex, pSeg, pColset, pIter+40)
|
|
(*TFts5Iter)(unsafe.Pointer(pIter)).Fbase.FpData = (*TFts5Iter)(unsafe.Pointer(pIter)).Fposlist.Fp
|
|
(*TFts5Iter)(unsafe.Pointer(pIter)).Fbase.FnData = (*TFts5Iter)(unsafe.Pointer(pIter)).Fposlist.Fn
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** xSetOutputs callback used by detail=full and detail=col tables when no
|
|
// ** column filters are specified.
|
|
// */
|
|
func _fts5IterSetOutputs_Nocolset(tls *libc.TLS, pIter uintptr, pSeg uintptr) {
|
|
(*TFts5Iter)(unsafe.Pointer(pIter)).Fbase.FiRowid = (*TFts5SegIter)(unsafe.Pointer(pSeg)).FiRowid
|
|
(*TFts5Iter)(unsafe.Pointer(pIter)).Fbase.FnData = (*TFts5SegIter)(unsafe.Pointer(pSeg)).FnPos
|
|
if (*TFts5SegIter)(unsafe.Pointer(pSeg)).FiLeafOffset+int64((*TFts5SegIter)(unsafe.Pointer(pSeg)).FnPos) <= int64((*TFts5Data)(unsafe.Pointer((*TFts5SegIter)(unsafe.Pointer(pSeg)).FpLeaf)).FszLeaf) {
|
|
/* All data is stored on the current page. Populate the output
|
|
** variables to point into the body of the page object. */
|
|
(*TFts5Iter)(unsafe.Pointer(pIter)).Fbase.FpData = (*TFts5Data)(unsafe.Pointer((*TFts5SegIter)(unsafe.Pointer(pSeg)).FpLeaf)).Fp + uintptr((*TFts5SegIter)(unsafe.Pointer(pSeg)).FiLeafOffset)
|
|
} else {
|
|
/* The data is distributed over two or more pages. Copy it into the
|
|
** Fts5Iter.poslist buffer and then set the output pointer to point
|
|
** to this buffer. */
|
|
_sqlite3Fts5BufferZero(tls, pIter+40)
|
|
_fts5SegiterPoslist(tls, (*TFts5Iter)(unsafe.Pointer(pIter)).FpIndex, pSeg, uintptr(0), pIter+40)
|
|
(*TFts5Iter)(unsafe.Pointer(pIter)).Fbase.FpData = (*TFts5Iter)(unsafe.Pointer(pIter)).Fposlist.Fp
|
|
}
|
|
}
|
|
|
|
func _fts5LookaheadReaderNext(tls *libc.TLS, p uintptr) (r int32) {
|
|
(*TFts5LookaheadReader)(unsafe.Pointer(p)).FiPos = (*TFts5LookaheadReader)(unsafe.Pointer(p)).FiLookahead
|
|
if _sqlite3Fts5PoslistNext64(tls, (*TFts5LookaheadReader)(unsafe.Pointer(p)).Fa, (*TFts5LookaheadReader)(unsafe.Pointer(p)).Fn, p+12, p+24) != 0 {
|
|
(*TFts5LookaheadReader)(unsafe.Pointer(p)).FiLookahead = libc.Int64FromInt32(1) << libc.Int32FromInt32(62)
|
|
}
|
|
return libc.BoolInt32((*TFts5LookaheadReader)(unsafe.Pointer(p)).FiPos == libc.Int64FromInt32(1)<<libc.Int32FromInt32(62))
|
|
}
|
|
|
|
func _fts5MultiIterAdvanced(tls *libc.TLS, p uintptr, pIter uintptr, iChanged int32, iMinset int32) {
|
|
var i, iEq, v2 int32
|
|
var pSeg uintptr
|
|
_, _, _, _ = i, iEq, pSeg, v2
|
|
i = ((*TFts5Iter)(unsafe.Pointer(pIter)).FnSeg + iChanged) / int32(2)
|
|
for {
|
|
if !(i >= iMinset && (*TFts5Index)(unsafe.Pointer(p)).Frc == SQLITE_OK) {
|
|
break
|
|
}
|
|
v2 = _fts5MultiIterDoCompare(tls, pIter, i)
|
|
iEq = v2
|
|
if v2 != 0 {
|
|
pSeg = pIter + 104 + uintptr(iEq)*128
|
|
(*(*func(*libc.TLS, uintptr, uintptr, uintptr))(unsafe.Pointer(&struct{ uintptr }{(*TFts5SegIter)(unsafe.Pointer(pSeg)).FxNext})))(tls, p, pSeg, uintptr(0))
|
|
i = (*TFts5Iter)(unsafe.Pointer(pIter)).FnSeg + iEq
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i / int32(2)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free the iterator object passed as the second argument.
|
|
// */
|
|
func _fts5MultiIterFree(tls *libc.TLS, pIter uintptr) {
|
|
var i int32
|
|
_ = i
|
|
if pIter != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5Iter)(unsafe.Pointer(pIter)).FnSeg) {
|
|
break
|
|
}
|
|
_fts5SegIterClear(tls, pIter+104+uintptr(i)*128)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_sqlite3Fts5BufferFree(tls, pIter+40)
|
|
Xsqlite3_free(tls, pIter)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return true if the iterator passed as the second argument currently
|
|
// ** points to a delete marker. A delete marker is an entry with a 0 byte
|
|
// ** position-list.
|
|
// */
|
|
func _fts5MultiIterIsEmpty(tls *libc.TLS, p uintptr, pIter uintptr) (r int32) {
|
|
var pSeg uintptr
|
|
_ = pSeg
|
|
pSeg = pIter + 104 + uintptr((**(**TFts5CResult)(__ccgo_up((*TFts5Iter)(unsafe.Pointer(pIter)).FaFirst + 1*4))).FiFirst)*128
|
|
return libc.BoolInt32((*TFts5Index)(unsafe.Pointer(p)).Frc == SQLITE_OK && (*TFts5SegIter)(unsafe.Pointer(pSeg)).FpLeaf != 0 && (*TFts5SegIter)(unsafe.Pointer(pSeg)).FnPos == 0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Allocate a new Fts5Iter object.
|
|
// **
|
|
// ** The new object will be used to iterate through data in structure pStruct.
|
|
// ** If iLevel is -ve, then all data in all segments is merged. Or, if iLevel
|
|
// ** is zero or greater, data from the first nSegment segments on level iLevel
|
|
// ** is merged.
|
|
// **
|
|
// ** The iterator initially points to the first term/rowid entry in the
|
|
// ** iterated data.
|
|
// */
|
|
func _fts5MultiIterNew(tls *libc.TLS, p uintptr, pStruct uintptr, flags int32, pColset uintptr, pTerm uintptr, nTerm int32, iLevel int32, nSegment int32, ppOut uintptr) {
|
|
var iIter, iSeg, nSeg, v1 int32
|
|
var pEnd, pIter, pIter1, pLvl, pNew, pSeg, v2 uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _ = iIter, iSeg, nSeg, pEnd, pIter, pIter1, pLvl, pNew, pSeg, v1, v2
|
|
nSeg = 0 /* Number of segment-iters in use */
|
|
iIter = 0
|
|
/* Allocate space for the new multi-seg-iterator. */
|
|
if (*TFts5Index)(unsafe.Pointer(p)).Frc == SQLITE_OK {
|
|
if iLevel < 0 {
|
|
nSeg = (*TFts5Structure)(unsafe.Pointer(pStruct)).FnSegment
|
|
nSeg = nSeg + libc.BoolInt32((*TFts5Index)(unsafe.Pointer(p)).FpHash != 0 && 0 == flags&int32(FTS5INDEX_QUERY_SKIPHASH))
|
|
} else {
|
|
if (*(*TFts5StructureLevel)(unsafe.Pointer(pStruct + 32 + uintptr(iLevel)*16))).FnSeg < nSegment {
|
|
v1 = (*(*TFts5StructureLevel)(unsafe.Pointer(pStruct + 32 + uintptr(iLevel)*16))).FnSeg
|
|
} else {
|
|
v1 = nSegment
|
|
}
|
|
nSeg = v1
|
|
}
|
|
}
|
|
v2 = _fts5MultiIterAlloc(tls, p, nSeg)
|
|
pNew = v2
|
|
**(**uintptr)(__ccgo_up(ppOut)) = v2
|
|
if pNew == uintptr(0) {
|
|
goto fts5MultiIterNew_post_check
|
|
}
|
|
(*TFts5Iter)(unsafe.Pointer(pNew)).FbRev = libc.BoolInt32(0 != flags&int32(FTS5INDEX_QUERY_DESC))
|
|
(*TFts5Iter)(unsafe.Pointer(pNew)).FbSkipEmpty = libc.BoolUint8(libc.Int32FromInt32(0) != flags&libc.Int32FromInt32(FTS5INDEX_QUERY_SKIPEMPTY))
|
|
(*TFts5Iter)(unsafe.Pointer(pNew)).FpColset = pColset
|
|
if flags&int32(FTS5INDEX_QUERY_NOOUTPUT) == 0 {
|
|
_fts5IterSetOutputCb(tls, p+60, pNew)
|
|
}
|
|
/* Initialize each of the component segment iterators. */
|
|
if (*TFts5Index)(unsafe.Pointer(p)).Frc == SQLITE_OK {
|
|
if iLevel < 0 {
|
|
pEnd = pStruct + 32 + uintptr((*TFts5Structure)(unsafe.Pointer(pStruct)).FnLevel)*16
|
|
if (*TFts5Index)(unsafe.Pointer(p)).FpHash != 0 && 0 == flags&int32(FTS5INDEX_QUERY_SKIPHASH) {
|
|
v1 = iIter
|
|
iIter = iIter + 1
|
|
/* Add a segment iterator for the current contents of the hash table. */
|
|
pIter = pNew + 104 + uintptr(v1)*128
|
|
_fts5SegIterHashInit(tls, p, pTerm, nTerm, flags, pIter)
|
|
}
|
|
pLvl = pStruct + 32
|
|
for {
|
|
if !(pLvl < pEnd) {
|
|
break
|
|
}
|
|
iSeg = (*TFts5StructureLevel)(unsafe.Pointer(pLvl)).FnSeg - int32(1)
|
|
for {
|
|
if !(iSeg >= 0) {
|
|
break
|
|
}
|
|
pSeg = (*TFts5StructureLevel)(unsafe.Pointer(pLvl)).FaSeg + uintptr(iSeg)*56
|
|
v1 = iIter
|
|
iIter = iIter + 1
|
|
pIter1 = pNew + 104 + uintptr(v1)*128
|
|
if pTerm == uintptr(0) {
|
|
_fts5SegIterInit(tls, p, pSeg, pIter1)
|
|
} else {
|
|
_fts5SegIterSeekInit(tls, p, pTerm, nTerm, flags, pSeg, pIter1)
|
|
}
|
|
goto _5
|
|
_5:
|
|
;
|
|
iSeg = iSeg - 1
|
|
}
|
|
goto _4
|
|
_4:
|
|
;
|
|
pLvl += 16
|
|
}
|
|
} else {
|
|
pLvl = pStruct + 32 + uintptr(iLevel)*16
|
|
iSeg = nSeg - int32(1)
|
|
for {
|
|
if !(iSeg >= 0) {
|
|
break
|
|
}
|
|
v1 = iIter
|
|
iIter = iIter + 1
|
|
_fts5SegIterInit(tls, p, (*TFts5StructureLevel)(unsafe.Pointer(pLvl)).FaSeg+uintptr(iSeg)*56, pNew+104+uintptr(v1)*128)
|
|
goto _7
|
|
_7:
|
|
;
|
|
iSeg = iSeg - 1
|
|
}
|
|
}
|
|
}
|
|
/* If the above was successful, each component iterator now points
|
|
** to the first entry in its segment. In this case initialize the
|
|
** aFirst[] array. Or, if an error has occurred, free the iterator
|
|
** object and set the output variable to NULL. */
|
|
if (*TFts5Index)(unsafe.Pointer(p)).Frc == SQLITE_OK {
|
|
_fts5MultiIterFinishSetup(tls, p, pNew)
|
|
} else {
|
|
_fts5MultiIterFree(tls, pNew)
|
|
**(**uintptr)(__ccgo_up(ppOut)) = uintptr(0)
|
|
}
|
|
goto fts5MultiIterNew_post_check
|
|
fts5MultiIterNew_post_check:
|
|
;
|
|
return
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the rowid of the entry that the iterator currently points
|
|
// ** to. If the iterator points to EOF when this function is called the
|
|
// ** results are undefined.
|
|
// */
|
|
func _fts5MultiIterRowid(tls *libc.TLS, pIter uintptr) (r Ti64) {
|
|
return (*(*TFts5SegIter)(unsafe.Pointer(pIter + 104 + uintptr((**(**TFts5CResult)(__ccgo_up((*TFts5Iter)(unsafe.Pointer(pIter)).FaFirst + 1*4))).FiFirst)*128))).FiRowid
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Set the pIter->bEof variable based on the state of the sub-iterators.
|
|
// */
|
|
func _fts5MultiIterSetEof(tls *libc.TLS, pIter uintptr) {
|
|
var pSeg uintptr
|
|
_ = pSeg
|
|
pSeg = pIter + 104 + uintptr((**(**TFts5CResult)(__ccgo_up((*TFts5Iter)(unsafe.Pointer(pIter)).FaFirst + 1*4))).FiFirst)*128
|
|
(*TFts5Iter)(unsafe.Pointer(pIter)).Fbase.FbEof = libc.BoolUint8((*TFts5SegIter)(unsafe.Pointer(pSeg)).FpLeaf == uintptr(0))
|
|
(*TFts5Iter)(unsafe.Pointer(pIter)).FiSwitchRowid = (*TFts5SegIter)(unsafe.Pointer(pSeg)).FiRowid
|
|
}
|
|
|
|
/*
|
|
** The argument to this macro must be an Fts5Data structure containing a
|
|
** tombstone hash page. This macro returns the key-size of the hash-page.
|
|
*/
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return a pointer to a buffer containing the term associated with the
|
|
// ** entry that the iterator currently points to.
|
|
// */
|
|
func _fts5MultiIterTerm(tls *libc.TLS, pIter uintptr, pn uintptr) (r uintptr) {
|
|
var p uintptr
|
|
_ = p
|
|
p = pIter + 104 + uintptr((**(**TFts5CResult)(__ccgo_up((*TFts5Iter)(unsafe.Pointer(pIter)).FaFirst + 1*4))).FiFirst)*128
|
|
**(**int32)(__ccgo_up(pn)) = (*TFts5SegIter)(unsafe.Pointer(p)).Fterm.Fn
|
|
return (*TFts5SegIter)(unsafe.Pointer(p)).Fterm.Fp
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Recursively apply colset pColset to expression node pNode and all of
|
|
// ** its decendents. If (*ppFree) is not NULL, it contains a spare copy
|
|
// ** of pColset. This function may use the spare copy and set (*ppFree) to
|
|
// ** zero, or it may create copies of pColset using fts5CloneColset().
|
|
// */
|
|
func _fts5ParseSetColset(tls *libc.TLS, pParse uintptr, pNode uintptr, pColset uintptr, ppFree uintptr) {
|
|
var i int32
|
|
var pNear uintptr
|
|
_, _ = i, pNear
|
|
if (*TFts5Parse)(unsafe.Pointer(pParse)).Frc == SQLITE_OK {
|
|
if (*TFts5ExprNode)(unsafe.Pointer(pNode)).FeType == int32(FTS5_STRING) || (*TFts5ExprNode)(unsafe.Pointer(pNode)).FeType == int32(FTS5_TERM) {
|
|
pNear = (*TFts5ExprNode)(unsafe.Pointer(pNode)).FpNear
|
|
if (*TFts5ExprNearset)(unsafe.Pointer(pNear)).FpColset != 0 {
|
|
_fts5MergeColset(tls, (*TFts5ExprNearset)(unsafe.Pointer(pNear)).FpColset, pColset)
|
|
if (*TFts5Colset)(unsafe.Pointer((*TFts5ExprNearset)(unsafe.Pointer(pNear)).FpColset)).FnCol == 0 {
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FeType = FTS5_EOF
|
|
(*TFts5ExprNode)(unsafe.Pointer(pNode)).FxNext = uintptr(0)
|
|
}
|
|
} else {
|
|
if **(**uintptr)(__ccgo_up(ppFree)) != 0 {
|
|
(*TFts5ExprNearset)(unsafe.Pointer(pNear)).FpColset = pColset
|
|
**(**uintptr)(__ccgo_up(ppFree)) = uintptr(0)
|
|
} else {
|
|
(*TFts5ExprNearset)(unsafe.Pointer(pNear)).FpColset = _fts5CloneColset(tls, pParse+16, pColset)
|
|
}
|
|
}
|
|
} else {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5ExprNode)(unsafe.Pointer(pNode)).FnChild) {
|
|
break
|
|
}
|
|
_fts5ParseSetColset(tls, pParse, *(*uintptr)(unsafe.Pointer(pNode + 48 + uintptr(i)*8)), pColset, ppFree)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Tokenize using the porter tokenizer.
|
|
// */
|
|
func _fts5PorterTokenize(tls *libc.TLS, pTokenizer uintptr, pCtx uintptr, flags int32, pText uintptr, nText int32, pLoc uintptr, nLoc int32, __ccgo_fp_xToken uintptr) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var p uintptr
|
|
var _ /* sCtx at bp+0 */ TPorterContext
|
|
_ = p
|
|
p = pTokenizer
|
|
(**(**TPorterContext)(__ccgo_up(bp))).FxToken = __ccgo_fp_xToken
|
|
(**(**TPorterContext)(__ccgo_up(bp))).FpCtx = pCtx
|
|
(**(**TPorterContext)(__ccgo_up(bp))).FaBuf = p + 40
|
|
return (*(*func(*libc.TLS, uintptr, uintptr, int32, uintptr, int32, uintptr, int32, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{(*TPorterTokenizer)(unsafe.Pointer(p)).Ftokenizer_v2.FxTokenize})))(tls, (*TPorterTokenizer)(unsafe.Pointer(p)).FpTokenizer, bp, flags, pText, nText, pLoc, nLoc, __ccgo_fp(_fts5PorterCb))
|
|
}
|
|
|
|
func _fts5PrefixMergerInsertByPosition(tls *libc.TLS, ppHead uintptr, p uintptr) {
|
|
var pp uintptr
|
|
_ = pp
|
|
if (*TPrefixMerger)(unsafe.Pointer(p)).FiPos >= 0 {
|
|
pp = ppHead
|
|
for **(**uintptr)(__ccgo_up(pp)) != 0 && (*TPrefixMerger)(unsafe.Pointer(p)).FiPos > (*TPrefixMerger)(unsafe.Pointer(**(**uintptr)(__ccgo_up(pp)))).FiPos {
|
|
pp = **(**uintptr)(__ccgo_up(pp)) + 56
|
|
}
|
|
(*TPrefixMerger)(unsafe.Pointer(p)).FpNext = **(**uintptr)(__ccgo_up(pp))
|
|
**(**uintptr)(__ccgo_up(pp)) = p
|
|
}
|
|
}
|
|
|
|
func _fts5PrefixMergerInsertByRowid(tls *libc.TLS, ppHead uintptr, p uintptr) {
|
|
var pp uintptr
|
|
_ = pp
|
|
if (*TPrefixMerger)(unsafe.Pointer(p)).Fiter.FaPoslist != 0 {
|
|
pp = ppHead
|
|
for **(**uintptr)(__ccgo_up(pp)) != 0 && (*TPrefixMerger)(unsafe.Pointer(p)).Fiter.FiRowid > (*TPrefixMerger)(unsafe.Pointer(**(**uintptr)(__ccgo_up(pp)))).Fiter.FiRowid {
|
|
pp = **(**uintptr)(__ccgo_up(pp)) + 56
|
|
}
|
|
(*TPrefixMerger)(unsafe.Pointer(p)).FpNext = **(**uintptr)(__ccgo_up(pp))
|
|
**(**uintptr)(__ccgo_up(pp)) = p
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Load the next leaf page into the segment iterator.
|
|
// */
|
|
func _fts5SegIterNextPage(tls *libc.TLS, p uintptr, pIter uintptr) {
|
|
var pLeaf, pSeg uintptr
|
|
_, _ = pLeaf, pSeg
|
|
pSeg = (*TFts5SegIter)(unsafe.Pointer(pIter)).FpSeg
|
|
_fts5DataRelease(tls, (*TFts5SegIter)(unsafe.Pointer(pIter)).FpLeaf)
|
|
(*TFts5SegIter)(unsafe.Pointer(pIter)).FiLeafPgno = (*TFts5SegIter)(unsafe.Pointer(pIter)).FiLeafPgno + 1
|
|
if (*TFts5SegIter)(unsafe.Pointer(pIter)).FpNextLeaf != 0 {
|
|
(*TFts5SegIter)(unsafe.Pointer(pIter)).FpLeaf = (*TFts5SegIter)(unsafe.Pointer(pIter)).FpNextLeaf
|
|
(*TFts5SegIter)(unsafe.Pointer(pIter)).FpNextLeaf = uintptr(0)
|
|
} else {
|
|
if (*TFts5SegIter)(unsafe.Pointer(pIter)).FiLeafPgno <= (*TFts5StructureSegment)(unsafe.Pointer(pSeg)).FpgnoLast {
|
|
(*TFts5SegIter)(unsafe.Pointer(pIter)).FpLeaf = _fts5LeafRead(tls, p, int64((*TFts5StructureSegment)(unsafe.Pointer(pSeg)).FiSegid)<<(libc.Int32FromInt32(FTS5_DATA_PAGE_B)+libc.Int32FromInt32(FTS5_DATA_HEIGHT_B)+libc.Int32FromInt32(FTS5_DATA_DLI_B))+int64(libc.Int32FromInt32(0))<<(libc.Int32FromInt32(FTS5_DATA_PAGE_B)+libc.Int32FromInt32(FTS5_DATA_HEIGHT_B))+int64(libc.Int32FromInt32(0))<<libc.Int32FromInt32(FTS5_DATA_PAGE_B)+int64((*TFts5SegIter)(unsafe.Pointer(pIter)).FiLeafPgno))
|
|
} else {
|
|
(*TFts5SegIter)(unsafe.Pointer(pIter)).FpLeaf = uintptr(0)
|
|
}
|
|
}
|
|
pLeaf = (*TFts5SegIter)(unsafe.Pointer(pIter)).FpLeaf
|
|
if pLeaf != 0 {
|
|
(*TFts5SegIter)(unsafe.Pointer(pIter)).FiPgidxOff = (*TFts5Data)(unsafe.Pointer(pLeaf)).FszLeaf
|
|
if (*TFts5Data)(unsafe.Pointer(pLeaf)).FszLeaf >= (*TFts5Data)(unsafe.Pointer(pLeaf)).Fnn {
|
|
(*TFts5SegIter)(unsafe.Pointer(pIter)).FiEndofDoclist = (*TFts5Data)(unsafe.Pointer(pLeaf)).Fnn + int32(1)
|
|
} else {
|
|
**(**int32)(__ccgo_up(pIter + 64)) += _sqlite3Fts5GetVarint32(tls, (*TFts5Data)(unsafe.Pointer(pLeaf)).Fp+uintptr((*TFts5SegIter)(unsafe.Pointer(pIter)).FiPgidxOff), pIter+68)
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Advance iterator pIter to the next entry.
|
|
// **
|
|
// ** This version of fts5SegIterNext() is only used by reverse iterators.
|
|
// */
|
|
func _fts5SegIterNext_Reverse(tls *libc.TLS, p uintptr, pIter uintptr, pbUnused uintptr) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var a, v1 uintptr
|
|
var iOff int32
|
|
var _ /* iDelta at bp+0 */ Tu64
|
|
_, _, _ = a, iOff, v1
|
|
_ = pbUnused
|
|
if (*TFts5SegIter)(unsafe.Pointer(pIter)).FiRowidOffset > 0 {
|
|
a = (*TFts5Data)(unsafe.Pointer((*TFts5SegIter)(unsafe.Pointer(pIter)).FpLeaf)).Fp
|
|
(*TFts5SegIter)(unsafe.Pointer(pIter)).FiRowidOffset = (*TFts5SegIter)(unsafe.Pointer(pIter)).FiRowidOffset - 1
|
|
(*TFts5SegIter)(unsafe.Pointer(pIter)).FiLeafOffset = int64(**(**int32)(__ccgo_up((*TFts5SegIter)(unsafe.Pointer(pIter)).FaRowidOffset + uintptr((*TFts5SegIter)(unsafe.Pointer(pIter)).FiRowidOffset)*4)))
|
|
_fts5SegIterLoadNPos(tls, p, pIter)
|
|
iOff = int32((*TFts5SegIter)(unsafe.Pointer(pIter)).FiLeafOffset)
|
|
if (*TFts5Config)(unsafe.Pointer((*TFts5Index)(unsafe.Pointer(p)).FpConfig)).FeDetail != int32(FTS5_DETAIL_NONE) {
|
|
iOff = iOff + (*TFts5SegIter)(unsafe.Pointer(pIter)).FnPos
|
|
}
|
|
_sqlite3Fts5GetVarint(tls, a+uintptr(iOff), bp)
|
|
v1 = pIter + 112
|
|
*(*Ti64)(unsafe.Pointer(v1)) = Ti64(uint64(*(*Ti64)(unsafe.Pointer(v1))) - **(**Tu64)(__ccgo_up(bp)))
|
|
} else {
|
|
_fts5SegIterReverseNewPage(tls, p, pIter)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this
|
|
// ** extension is currently being used by a version of SQLite too old to
|
|
// ** support index-info flags. In that case this function is a no-op.
|
|
// */
|
|
func _fts5SetUniqueFlag(tls *libc.TLS, pIdxInfo uintptr) {
|
|
**(**int32)(__ccgo_up(pIdxInfo + 80)) |= int32(SQLITE_INDEX_SCAN_UNIQUE)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return true if zName is the extension on one of the shadow tables used
|
|
// ** by this module.
|
|
// */
|
|
func _fts5ShadowName(tls *libc.TLS, zName uintptr) (r int32) {
|
|
var i uint32
|
|
_ = i
|
|
i = uint32(0)
|
|
for {
|
|
if !(uint64(i) < libc.Uint64FromInt64(40)/libc.Uint64FromInt64(8)) {
|
|
break
|
|
}
|
|
if Xsqlite3_stricmp(tls, zName, _azName2[i]) == 0 {
|
|
return int32(1)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func _fts5SorterNext(tls *libc.TLS, pCsr uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var a, aBlob, pSorter, v1 uintptr
|
|
var i, iOff, nBlob, rc int32
|
|
var _ /* iVal at bp+0 */ int32
|
|
_, _, _, _, _, _, _, _ = a, aBlob, i, iOff, nBlob, pSorter, rc, v1
|
|
pSorter = (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpSorter
|
|
rc = Xsqlite3_step(tls, (*TFts5Sorter)(unsafe.Pointer(pSorter)).FpStmt)
|
|
if rc == int32(SQLITE_DONE) {
|
|
rc = SQLITE_OK
|
|
**(**int32)(__ccgo_up(pCsr + 80)) |= libc.Int32FromInt32(FTS5CSR_EOF) | libc.Int32FromInt32(FTS5CSR_REQUIRE_CONTENT)
|
|
} else {
|
|
if rc == int32(SQLITE_ROW) {
|
|
iOff = 0
|
|
rc = SQLITE_OK
|
|
(*TFts5Sorter)(unsafe.Pointer(pSorter)).FiRowid = Xsqlite3_column_int64(tls, (*TFts5Sorter)(unsafe.Pointer(pSorter)).FpStmt, 0)
|
|
nBlob = Xsqlite3_column_bytes(tls, (*TFts5Sorter)(unsafe.Pointer(pSorter)).FpStmt, int32(1))
|
|
v1 = Xsqlite3_column_blob(tls, (*TFts5Sorter)(unsafe.Pointer(pSorter)).FpStmt, int32(1))
|
|
a = v1
|
|
aBlob = v1
|
|
/* nBlob==0 in detail=none mode. */
|
|
if nBlob > 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5Sorter)(unsafe.Pointer(pSorter)).FnIdx-int32(1)) {
|
|
break
|
|
}
|
|
a = a + uintptr(_sqlite3Fts5GetVarint32(tls, a, bp))
|
|
iOff = iOff + **(**int32)(__ccgo_up(bp))
|
|
*(*int32)(unsafe.Pointer(pSorter + 28 + uintptr(i)*4)) = iOff
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
*(*int32)(unsafe.Pointer(pSorter + 28 + uintptr(i)*4)) = int32(t__predefined_ptrdiff_t(aBlob+uintptr(nBlob)) - int64(a))
|
|
(*TFts5Sorter)(unsafe.Pointer(pSorter)).FaPoslist = a
|
|
}
|
|
_fts5CsrNewrow(tls, pCsr)
|
|
}
|
|
}
|
|
return rc
|
|
}
|
|
|
|
func _fts5SpecialDelete(tls *libc.TLS, pTab uintptr, apVal uintptr) (r int32) {
|
|
var eType1, rc int32
|
|
var iDel Tsqlite3_int64
|
|
_, _, _ = eType1, iDel, rc
|
|
rc = SQLITE_OK
|
|
eType1 = Xsqlite3_value_type(tls, **(**uintptr)(__ccgo_up(apVal + 1*8)))
|
|
if eType1 == int32(SQLITE_INTEGER) {
|
|
iDel = Xsqlite3_value_int64(tls, **(**uintptr)(__ccgo_up(apVal + 1*8)))
|
|
rc = _sqlite3Fts5StorageDelete(tls, (*TFts5FullTable)(unsafe.Pointer(pTab)).FpStorage, iDel, apVal+2*8, 0)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Load the contents of the "averages" record from disk into the
|
|
// ** p->nTotalRow and p->aTotalSize[] variables. If successful, and if
|
|
// ** argument bCache is true, set the p->bTotalsValid flag to indicate
|
|
// ** that the contents of aTotalSize[] and nTotalRow are valid until
|
|
// ** further notice.
|
|
// **
|
|
// ** Return SQLITE_OK if successful, or an SQLite error code if an error
|
|
// ** occurs.
|
|
// */
|
|
func _fts5StorageLoadTotals(tls *libc.TLS, p uintptr, bCache int32) (r int32) {
|
|
var rc int32
|
|
_ = rc
|
|
rc = SQLITE_OK
|
|
if (*TFts5Storage)(unsafe.Pointer(p)).FbTotalsValid == 0 {
|
|
rc = _sqlite3Fts5IndexGetAverages(tls, (*TFts5Storage)(unsafe.Pointer(p)).FpIndex, p+24, (*TFts5Storage)(unsafe.Pointer(p)).FaTotalSize)
|
|
(*TFts5Storage)(unsafe.Pointer(p)).FbTotalsValid = bCache
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** A new segment has just been written to level iLvl of index structure
|
|
// ** pStruct. This function determines if any segments should be promoted
|
|
// ** as a result. Segments are promoted in two scenarios:
|
|
// **
|
|
// ** a) If the segment just written is smaller than one or more segments
|
|
// ** within the previous populated level, it is promoted to the previous
|
|
// ** populated level.
|
|
// **
|
|
// ** b) If the segment just written is larger than the newest segment on
|
|
// ** the next populated level, then that segment, and any other adjacent
|
|
// ** segments that are also smaller than the one just written, are
|
|
// ** promoted.
|
|
// **
|
|
// ** If one or more segments are promoted, the structure object is updated
|
|
// ** to reflect this.
|
|
// */
|
|
func _fts5StructurePromote(tls *libc.TLS, p uintptr, iLvl int32, pStruct uintptr) {
|
|
var i, iPromote, iTst, nSeg, sz, szMax, szPromote, szSeg int32
|
|
var pSeg, pTst uintptr
|
|
_, _, _, _, _, _, _, _, _, _ = i, iPromote, iTst, nSeg, pSeg, pTst, sz, szMax, szPromote, szSeg
|
|
if (*TFts5Index)(unsafe.Pointer(p)).Frc == SQLITE_OK {
|
|
iPromote = -int32(1)
|
|
szPromote = 0 /* Size of segment just written */
|
|
nSeg = (*(*TFts5StructureLevel)(unsafe.Pointer(pStruct + 32 + uintptr(iLvl)*16))).FnSeg
|
|
if nSeg == 0 {
|
|
return
|
|
}
|
|
pSeg = (*(*TFts5StructureLevel)(unsafe.Pointer(pStruct + 32 + uintptr(iLvl)*16))).FaSeg + uintptr((*(*TFts5StructureLevel)(unsafe.Pointer(pStruct + 32 + uintptr(iLvl)*16))).FnSeg-int32(1))*56
|
|
szSeg = int32(1) + (*TFts5StructureSegment)(unsafe.Pointer(pSeg)).FpgnoLast - (*TFts5StructureSegment)(unsafe.Pointer(pSeg)).FpgnoFirst
|
|
/* Check for condition (a) */
|
|
iTst = iLvl - int32(1)
|
|
for {
|
|
if !(iTst >= 0 && (*(*TFts5StructureLevel)(unsafe.Pointer(pStruct + 32 + uintptr(iTst)*16))).FnSeg == 0) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
iTst = iTst - 1
|
|
}
|
|
if iTst >= 0 {
|
|
szMax = 0
|
|
pTst = pStruct + 32 + uintptr(iTst)*16
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5StructureLevel)(unsafe.Pointer(pTst)).FnSeg) {
|
|
break
|
|
}
|
|
sz = (**(**TFts5StructureSegment)(__ccgo_up((*TFts5StructureLevel)(unsafe.Pointer(pTst)).FaSeg + uintptr(i)*56))).FpgnoLast - (**(**TFts5StructureSegment)(__ccgo_up((*TFts5StructureLevel)(unsafe.Pointer(pTst)).FaSeg + uintptr(i)*56))).FpgnoFirst + int32(1)
|
|
if sz > szMax {
|
|
szMax = sz
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if szMax >= szSeg {
|
|
/* Condition (a) is true. Promote the newest segment on level
|
|
** iLvl to level iTst. */
|
|
iPromote = iTst
|
|
szPromote = szMax
|
|
}
|
|
}
|
|
/* If condition (a) is not met, assume (b) is true. StructurePromoteTo()
|
|
** is a no-op if it is not. */
|
|
if iPromote < 0 {
|
|
iPromote = iLvl
|
|
szPromote = szSeg
|
|
}
|
|
_fts5StructurePromoteTo(tls, p, iPromote, szPromote, pStruct)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Release a reference to an Fts5Structure object returned by an earlier
|
|
// ** call to fts5StructureRead() or fts5StructureDecode().
|
|
// */
|
|
func _fts5StructureRelease(tls *libc.TLS, pStruct uintptr) {
|
|
var i, v1 int32
|
|
var v2 uintptr
|
|
var v3 bool
|
|
_, _, _, _ = i, v1, v2, v3
|
|
if v3 = pStruct != 0; v3 {
|
|
v2 = pStruct
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) - 1
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
}
|
|
if v3 && 0 >= v1 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5Structure)(unsafe.Pointer(pStruct)).FnLevel) {
|
|
break
|
|
}
|
|
Xsqlite3_free(tls, (*(*TFts5StructureLevel)(unsafe.Pointer(pStruct + 32 + uintptr(i)*16))).FaSeg)
|
|
goto _4
|
|
_4:
|
|
;
|
|
i = i + 1
|
|
}
|
|
Xsqlite3_free(tls, pStruct)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of xSync() method.
|
|
// */
|
|
func _fts5SyncMethod(tls *libc.TLS, pVtab uintptr) (r int32) {
|
|
var pTab uintptr
|
|
var rc int32
|
|
_, _ = pTab, rc
|
|
pTab = pVtab
|
|
(*TFts5Config)(unsafe.Pointer((*TFts5FullTable)(unsafe.Pointer(pTab)).Fp.FpConfig)).FpzErrmsg = pTab + 16
|
|
rc = _sqlite3Fts5FlushToDisk(tls, pTab)
|
|
(*TFts5Config)(unsafe.Pointer((*TFts5FullTable)(unsafe.Pointer(pTab)).Fp.FpConfig)).FpzErrmsg = uintptr(0)
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Argument pStmt is an SQL statement of the type used by Fts5Cursor. This
|
|
// ** function extracts the text value of column iCol of the current row.
|
|
// ** Additionally, if there is an associated locale, it invokes
|
|
// ** sqlite3Fts5SetLocale() to configure the tokenizer. In all cases the caller
|
|
// ** should invoke sqlite3Fts5ClearLocale() to clear the locale at some point
|
|
// ** after this function returns.
|
|
// **
|
|
// ** If successful, (*ppText) is set to point to a buffer containing the text
|
|
// ** value as utf-8 and SQLITE_OK returned. (*pnText) is set to the size of that
|
|
// ** buffer in bytes. It is not guaranteed to be nul-terminated. If an error
|
|
// ** occurs, an SQLite error code is returned. The final values of the two
|
|
// ** output parameters are undefined in this case.
|
|
// */
|
|
func _fts5TextFromStmt(tls *libc.TLS, pConfig uintptr, pStmt uintptr, iCol int32, ppText uintptr, pnText uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var pVal uintptr
|
|
var rc int32
|
|
var _ /* nLoc at bp+8 */ int32
|
|
var _ /* pLoc at bp+0 */ uintptr
|
|
_, _ = pVal, rc
|
|
pVal = Xsqlite3_column_value(tls, pStmt, iCol+int32(1))
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
**(**int32)(__ccgo_up(bp + 8)) = 0
|
|
rc = SQLITE_OK
|
|
if (*TFts5Config)(unsafe.Pointer(pConfig)).FbLocale != 0 && (*TFts5Config)(unsafe.Pointer(pConfig)).FeContent == int32(FTS5_CONTENT_EXTERNAL) && _sqlite3Fts5IsLocaleValue(tls, pConfig, pVal) != 0 {
|
|
rc = _sqlite3Fts5DecodeLocaleValue(tls, pVal, ppText, pnText, bp, bp+8)
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(ppText)) = Xsqlite3_value_text(tls, pVal)
|
|
**(**int32)(__ccgo_up(pnText)) = Xsqlite3_value_bytes(tls, pVal)
|
|
if (*TFts5Config)(unsafe.Pointer(pConfig)).FbLocale != 0 && (*TFts5Config)(unsafe.Pointer(pConfig)).FeContent == FTS5_CONTENT_NORMAL {
|
|
**(**uintptr)(__ccgo_up(bp)) = Xsqlite3_column_text(tls, pStmt, iCol+int32(1)+(*TFts5Config)(unsafe.Pointer(pConfig)).FnCol)
|
|
**(**int32)(__ccgo_up(bp + 8)) = Xsqlite3_column_bytes(tls, pStmt, iCol+int32(1)+(*TFts5Config)(unsafe.Pointer(pConfig)).FnCol)
|
|
}
|
|
}
|
|
_sqlite3Fts5SetLocale(tls, pConfig, **(**uintptr)(__ccgo_up(bp)), **(**int32)(__ccgo_up(bp + 8)))
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Delete an Fts5TokenDataIter structure and its contents.
|
|
// */
|
|
func _fts5TokendataIterDelete(tls *libc.TLS, pSet uintptr) {
|
|
var ii int32
|
|
_ = ii
|
|
if pSet != 0 {
|
|
ii = 0
|
|
for {
|
|
if !(int64(ii) < (*TFts5TokenDataIter)(unsafe.Pointer(pSet)).FnIter) {
|
|
break
|
|
}
|
|
_fts5MultiIterFree(tls, *(*uintptr)(unsafe.Pointer(pSet + 72 + uintptr(ii)*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
_sqlite3Fts5BufferFree(tls, pSet+24)
|
|
Xsqlite3_free(tls, (*TFts5TokenDataIter)(unsafe.Pointer(pSet)).FaPoslistReader)
|
|
Xsqlite3_free(tls, (*TFts5TokenDataIter)(unsafe.Pointer(pSet)).FaMap)
|
|
Xsqlite3_free(tls, pSet)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If the segment-iterator passed as the first argument is at EOF, then
|
|
// ** set pIter->term to a copy of buffer pTerm.
|
|
// */
|
|
func _fts5TokendataSetTermIfEof(tls *libc.TLS, pIter uintptr, pTerm uintptr) {
|
|
if pIter != 0 && (*(*TFts5SegIter)(unsafe.Pointer(pIter + 104))).FpLeaf == uintptr(0) {
|
|
_sqlite3Fts5BufferSet(tls, (*TFts5Iter)(unsafe.Pointer(pIter)).FpIndex+60, pIter+104+96, (*TFts5Buffer)(unsafe.Pointer(pTerm)).Fn, (*TFts5Buffer)(unsafe.Pointer(pTerm)).Fp)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Decrement the ref-count of the object passed as the only argument. If it
|
|
// ** reaches 0, free it and its contents.
|
|
// */
|
|
func _fts5TombstoneArrayDelete(tls *libc.TLS, p uintptr) {
|
|
var ii int32
|
|
_ = ii
|
|
if p != 0 {
|
|
(*TFts5TombstoneArray)(unsafe.Pointer(p)).FnRef = (*TFts5TombstoneArray)(unsafe.Pointer(p)).FnRef - 1
|
|
if (*TFts5TombstoneArray)(unsafe.Pointer(p)).FnRef <= 0 {
|
|
ii = 0
|
|
for {
|
|
if !(ii < (*TFts5TombstoneArray)(unsafe.Pointer(p)).FnTombstone) {
|
|
break
|
|
}
|
|
_fts5DataRelease(tls, *(*uintptr)(unsafe.Pointer(p + 8 + uintptr(ii)*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
Xsqlite3_free(tls, p)
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Set the FTS5CSR_REQUIRE_RESEEK flag on all FTS5_PLAN_MATCH cursors
|
|
// ** open on table pTab.
|
|
// */
|
|
func _fts5TripCursors(tls *libc.TLS, pTab uintptr) {
|
|
var pCsr uintptr
|
|
_ = pCsr
|
|
pCsr = (*TFts5Global)(unsafe.Pointer((*TFts5FullTable)(unsafe.Pointer(pTab)).FpGlobal)).FpCsr
|
|
for {
|
|
if !(pCsr != 0) {
|
|
break
|
|
}
|
|
if (*TFts5Cursor)(unsafe.Pointer(pCsr)).FePlan == int32(FTS5_PLAN_MATCH) && (*TFts5Cursor)(unsafe.Pointer(pCsr)).Fbase.FpVtab == pTab {
|
|
**(**int32)(__ccgo_up(pCsr + 80)) |= int32(FTS5CSR_REQUIRE_RESEEK)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pCsr = (*TFts5Cursor)(unsafe.Pointer(pCsr)).FpNext
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Close the cursor. For additional information see the documentation
|
|
// ** on the xClose method of the virtual table interface.
|
|
// */
|
|
func _fts5VocabCloseMethod(tls *libc.TLS, pCursor uintptr) (r int32) {
|
|
var pCsr uintptr
|
|
_ = pCsr
|
|
pCsr = pCursor
|
|
_fts5VocabResetCursor(tls, pCsr)
|
|
_sqlite3Fts5BufferFree(tls, pCsr+96)
|
|
Xsqlite3_finalize(tls, (*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FpStmt)
|
|
Xsqlite3_free(tls, pCsr)
|
|
return SQLITE_OK
|
|
}
|
|
|
|
func _fts5VocabColumnMethod(tls *libc.TLS, pCursor uintptr, pCtx uintptr, iCol int32) (r int32) {
|
|
var eDetail, eType, ii, ii1 int32
|
|
var iVal Ti64
|
|
var pCsr, z, z1 uintptr
|
|
_, _, _, _, _, _, _, _ = eDetail, eType, iVal, ii, ii1, pCsr, z, z1
|
|
pCsr = pCursor
|
|
eDetail = (*TFts5Config)(unsafe.Pointer((*TFts5Table)(unsafe.Pointer((*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FpFts5)).FpConfig)).FeDetail
|
|
eType = (*TFts5VocabTable)(unsafe.Pointer((*Tsqlite3_vtab_cursor)(unsafe.Pointer(pCursor)).FpVtab)).FeType
|
|
iVal = 0
|
|
if iCol == 0 {
|
|
Xsqlite3_result_text(tls, pCtx, (*TFts5VocabCursor)(unsafe.Pointer(pCsr)).Fterm.Fp, (*TFts5VocabCursor)(unsafe.Pointer(pCsr)).Fterm.Fn, uintptr(-libc.Int32FromInt32(1)))
|
|
} else {
|
|
if eType == FTS5_VOCAB_COL {
|
|
if iCol == int32(1) {
|
|
if eDetail != int32(FTS5_DETAIL_NONE) {
|
|
z = **(**uintptr)(__ccgo_up((*TFts5Config)(unsafe.Pointer((*TFts5Table)(unsafe.Pointer((*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FpFts5)).FpConfig)).FazCol + uintptr((*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FiCol)*8))
|
|
Xsqlite3_result_text(tls, pCtx, z, -int32(1), libc.UintptrFromInt32(0))
|
|
}
|
|
} else {
|
|
if iCol == int32(2) {
|
|
iVal = **(**Ti64)(__ccgo_up((*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FaDoc + uintptr((*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FiCol)*8))
|
|
} else {
|
|
iVal = **(**Ti64)(__ccgo_up((*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FaCnt + uintptr((*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FiCol)*8))
|
|
}
|
|
}
|
|
} else {
|
|
if eType == int32(FTS5_VOCAB_ROW) {
|
|
if iCol == int32(1) {
|
|
iVal = **(**Ti64)(__ccgo_up((*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FaDoc))
|
|
} else {
|
|
iVal = **(**Ti64)(__ccgo_up((*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FaCnt))
|
|
}
|
|
} else {
|
|
switch iCol {
|
|
case int32(1):
|
|
Xsqlite3_result_int64(tls, pCtx, (*TFts5IndexIter)(unsafe.Pointer((*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FpIter)).FiRowid)
|
|
case int32(2):
|
|
ii = -int32(1)
|
|
if eDetail == FTS5_DETAIL_FULL {
|
|
ii = int32((*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FiInstPos >> libc.Int32FromInt32(32) & libc.Int64FromInt32(0x7FFFFFFF))
|
|
} else {
|
|
if eDetail == int32(FTS5_DETAIL_COLUMNS) {
|
|
ii = int32((*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FiInstPos)
|
|
}
|
|
}
|
|
if ii >= 0 && ii < (*TFts5Config)(unsafe.Pointer((*TFts5Table)(unsafe.Pointer((*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FpFts5)).FpConfig)).FnCol {
|
|
z1 = **(**uintptr)(__ccgo_up((*TFts5Config)(unsafe.Pointer((*TFts5Table)(unsafe.Pointer((*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FpFts5)).FpConfig)).FazCol + uintptr(ii)*8))
|
|
Xsqlite3_result_text(tls, pCtx, z1, -int32(1), libc.UintptrFromInt32(0))
|
|
}
|
|
default:
|
|
if eDetail == FTS5_DETAIL_FULL {
|
|
ii1 = int32((*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FiInstPos & libc.Int64FromInt32(0x7FFFFFFF))
|
|
Xsqlite3_result_int(tls, pCtx, ii1)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if iVal > 0 {
|
|
Xsqlite3_result_int64(tls, pCtx, iVal)
|
|
}
|
|
return SQLITE_OK
|
|
}
|
|
|
|
func _fts5VocabInstanceNext(tls *libc.TLS, pCsr uintptr) (r int32) {
|
|
var eDetail, rc int32
|
|
var pIter, po, pp uintptr
|
|
_, _, _, _, _ = eDetail, pIter, po, pp, rc
|
|
eDetail = (*TFts5Config)(unsafe.Pointer((*TFts5Table)(unsafe.Pointer((*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FpFts5)).FpConfig)).FeDetail
|
|
rc = SQLITE_OK
|
|
pIter = (*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FpIter
|
|
pp = pCsr + 112
|
|
po = pCsr + 120
|
|
for eDetail == int32(FTS5_DETAIL_NONE) || _sqlite3Fts5PoslistNext64(tls, (*TFts5IndexIter)(unsafe.Pointer(pIter)).FpData, (*TFts5IndexIter)(unsafe.Pointer(pIter)).FnData, po, pp) != 0 {
|
|
(*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FiInstPos = 0
|
|
(*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FiInstOff = 0
|
|
rc = _sqlite3Fts5IterNextScan(tls, (*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FpIter)
|
|
if rc == SQLITE_OK {
|
|
rc = _fts5VocabInstanceNewTerm(tls, pCsr)
|
|
if (*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FbEof != 0 || eDetail == int32(FTS5_DETAIL_NONE) {
|
|
break
|
|
}
|
|
}
|
|
if rc != 0 {
|
|
(*TFts5VocabCursor)(unsafe.Pointer(pCsr)).FbEof = int32(1)
|
|
break
|
|
}
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Create a wrapper tokenizer. The context argument pCtx points to the
|
|
// ** Fts5TokenizerModule object.
|
|
// */
|
|
func _fts5VtoVCreate(tls *libc.TLS, pCtx uintptr, azArg uintptr, nArg int32, ppOut uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var pMod, pNew uintptr
|
|
var _ /* rc at bp+0 */ int32
|
|
_, _ = pMod, pNew
|
|
pMod = pCtx
|
|
pNew = uintptr(0)
|
|
**(**int32)(__ccgo_up(bp)) = SQLITE_OK
|
|
pNew = _sqlite3Fts5MallocZero(tls, bp, int64(72))
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
(*TFts5VtoVTokenizer)(unsafe.Pointer(pNew)).Fx1 = (*TFts5TokenizerModule)(unsafe.Pointer(pMod)).Fx1
|
|
(*TFts5VtoVTokenizer)(unsafe.Pointer(pNew)).Fx2 = (*TFts5TokenizerModule)(unsafe.Pointer(pMod)).Fx2
|
|
(*TFts5VtoVTokenizer)(unsafe.Pointer(pNew)).FbV2Native = (*TFts5TokenizerModule)(unsafe.Pointer(pMod)).FbV2Native
|
|
if (*TFts5TokenizerModule)(unsafe.Pointer(pMod)).FbV2Native != 0 {
|
|
**(**int32)(__ccgo_up(bp)) = (*(*func(*libc.TLS, uintptr, uintptr, int32, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{(*TFts5TokenizerModule)(unsafe.Pointer(pMod)).Fx2.FxCreate})))(tls, (*TFts5TokenizerModule)(unsafe.Pointer(pMod)).FpUserData, azArg, nArg, pNew+64)
|
|
} else {
|
|
**(**int32)(__ccgo_up(bp)) = (*(*func(*libc.TLS, uintptr, uintptr, int32, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{(*TFts5TokenizerModule)(unsafe.Pointer(pMod)).Fx1.FxCreate})))(tls, (*TFts5TokenizerModule)(unsafe.Pointer(pMod)).FpUserData, azArg, nArg, pNew+64)
|
|
}
|
|
if **(**int32)(__ccgo_up(bp)) != SQLITE_OK {
|
|
Xsqlite3_free(tls, pNew)
|
|
pNew = uintptr(0)
|
|
}
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppOut)) = pNew
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is called when flushing a leaf page that contains no
|
|
// ** terms at all to disk.
|
|
// */
|
|
func _fts5WriteBtreeNoTerm(tls *libc.TLS, p uintptr, pWriter uintptr) {
|
|
var pDlidx uintptr
|
|
_ = pDlidx
|
|
/* If there were no rowids on the leaf page either and the doclist-index
|
|
** has already been started, append an 0x00 byte to it. */
|
|
if (*TFts5SegWriter)(unsafe.Pointer(pWriter)).FbFirstRowidInPage != 0 && (**(**TFts5DlidxWriter)(__ccgo_up((*TFts5SegWriter)(unsafe.Pointer(pWriter)).FaDlidx))).Fbuf.Fn > 0 {
|
|
pDlidx = (*TFts5SegWriter)(unsafe.Pointer(pWriter)).FaDlidx
|
|
_sqlite3Fts5BufferAppendVarint(tls, p+60, pDlidx+16, 0)
|
|
}
|
|
/* Increment the "number of sequential leaves without a term" counter. */
|
|
(*TFts5SegWriter)(unsafe.Pointer(pWriter)).FnEmpty = (*TFts5SegWriter)(unsafe.Pointer(pWriter)).FnEmpty + 1
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This is called once for each leaf page except the first that contains
|
|
// ** at least one term. Argument (nTerm/pTerm) is the split-key - a term that
|
|
// ** is larger than all terms written to earlier leaves, and equal to or
|
|
// ** smaller than the first term on the new leaf.
|
|
// **
|
|
// ** If an error occurs, an error code is left in Fts5Index.rc. If an error
|
|
// ** has already occurred when this function is called, it is a no-op.
|
|
// */
|
|
func _fts5WriteBtreeTerm(tls *libc.TLS, p uintptr, pWriter uintptr, nTerm int32, pTerm uintptr) {
|
|
_fts5WriteFlushBtree(tls, p, pWriter)
|
|
if (*TFts5Index)(unsafe.Pointer(p)).Frc == SQLITE_OK {
|
|
_sqlite3Fts5BufferSet(tls, p+60, pWriter+96, nTerm, pTerm)
|
|
(*TFts5SegWriter)(unsafe.Pointer(pWriter)).FiBtPage = (*TFts5SegWriter)(unsafe.Pointer(pWriter)).Fwriter.Fpgno
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Flush any data cached by the writer object to the database. Free any
|
|
// ** allocations associated with the writer.
|
|
// */
|
|
func _fts5WriteFinish(tls *libc.TLS, p uintptr, pWriter uintptr, pnLeaf uintptr) {
|
|
var i int32
|
|
var pLeaf uintptr
|
|
_, _ = i, pLeaf
|
|
pLeaf = pWriter + 8
|
|
if (*TFts5Index)(unsafe.Pointer(p)).Frc == SQLITE_OK {
|
|
if (*TFts5PageWriter)(unsafe.Pointer(pLeaf)).Fbuf.Fn > int32(4) {
|
|
_fts5WriteFlushLeaf(tls, p, pWriter)
|
|
}
|
|
**(**int32)(__ccgo_up(pnLeaf)) = (*TFts5PageWriter)(unsafe.Pointer(pLeaf)).Fpgno - int32(1)
|
|
if (*TFts5PageWriter)(unsafe.Pointer(pLeaf)).Fpgno > int32(1) {
|
|
_fts5WriteFlushBtree(tls, p, pWriter)
|
|
}
|
|
}
|
|
_sqlite3Fts5BufferFree(tls, pLeaf+40)
|
|
_sqlite3Fts5BufferFree(tls, pLeaf+8)
|
|
_sqlite3Fts5BufferFree(tls, pLeaf+24)
|
|
_sqlite3Fts5BufferFree(tls, pWriter+96)
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5SegWriter)(unsafe.Pointer(pWriter)).FnDlidx) {
|
|
break
|
|
}
|
|
_sqlite3Fts5BufferFree(tls, (*TFts5SegWriter)(unsafe.Pointer(pWriter)).FaDlidx+uintptr(i)*32+16)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
Xsqlite3_free(tls, (*TFts5SegWriter)(unsafe.Pointer(pWriter)).FaDlidx)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Pop the parser's stack once.
|
|
// **
|
|
// ** If there is a destructor routine associated with the token which
|
|
// ** is popped from the stack, then call it.
|
|
// */
|
|
func _fts5yy_pop_parser_stack(tls *libc.TLS, pParser uintptr) {
|
|
var fts5yytos, v1, v2 uintptr
|
|
_, _, _ = fts5yytos, v1, v2
|
|
v2 = pParser
|
|
v1 = *(*uintptr)(unsafe.Pointer(v2))
|
|
*(*uintptr)(unsafe.Pointer(v2)) -= 24
|
|
fts5yytos = v1
|
|
_fts5yy_destructor(tls, pParser, (*Tfts5yyStackEntry)(unsafe.Pointer(fts5yytos)).Fmajor, fts5yytos+8)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Invoke the destructor function associated with FuncDef p, if any. Except,
|
|
// ** if this is not the last copy of the function, do not invoke it. Multiple
|
|
// ** copies of a single function are created when create_function() is called
|
|
// ** with SQLITE_ANY as the encoding.
|
|
// */
|
|
func _functionDestroy(tls *libc.TLS, db uintptr, p uintptr) {
|
|
var pDestructor uintptr
|
|
_ = pDestructor
|
|
pDestructor = *(*uintptr)(unsafe.Pointer(p + 64))
|
|
if pDestructor != 0 {
|
|
(*TFuncDestructor)(unsafe.Pointer(pDestructor)).FnRef = (*TFuncDestructor)(unsafe.Pointer(pDestructor)).FnRef - 1
|
|
if (*TFuncDestructor)(unsafe.Pointer(pDestructor)).FnRef == 0 {
|
|
(*(*func(*libc.TLS, uintptr))(unsafe.Pointer(&struct{ uintptr }{(*TFuncDestructor)(unsafe.Pointer(pDestructor)).FxDestroy})))(tls, (*TFuncDestructor)(unsafe.Pointer(pDestructor)).FpUserData)
|
|
_sqlite3DbFree(tls, db, pDestructor)
|
|
}
|
|
}
|
|
}
|
|
|
|
func _gatherSelectWindows(tls *libc.TLS, p uintptr) {
|
|
bp := tls.Alloc(48)
|
|
defer tls.Free(48)
|
|
var _ /* w at bp+0 */ TWalker
|
|
(**(**TWalker)(__ccgo_up(bp))).FxExprCallback = __ccgo_fp(_gatherSelectWindowsCallback)
|
|
(**(**TWalker)(__ccgo_up(bp))).FxSelectCallback = __ccgo_fp(_gatherSelectWindowsSelectCallback)
|
|
(**(**TWalker)(__ccgo_up(bp))).FxSelectCallback2 = uintptr(0)
|
|
(**(**TWalker)(__ccgo_up(bp))).FpParse = uintptr(0)
|
|
*(*uintptr)(unsafe.Pointer(bp + 40)) = p
|
|
_sqlite3WalkSelect(tls, bp, p)
|
|
}
|
|
|
|
func _gatherSelectWindowsSelectCallback(tls *libc.TLS, pWalker uintptr, p uintptr) (r int32) {
|
|
var v1 int32
|
|
_ = v1
|
|
if p == *(*uintptr)(unsafe.Pointer(pWalker + 40)) {
|
|
v1 = WRC_Continue
|
|
} else {
|
|
v1 = int32(WRC_Prune)
|
|
}
|
|
return v1
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Generate code that will tell the VDBE the declaration types of columns
|
|
// ** in the result set.
|
|
// */
|
|
func _generateColumnTypes(tls *libc.TLS, pParse uintptr, pTabList uintptr, pEList uintptr) {
|
|
bp := tls.Alloc(80)
|
|
defer tls.Free(80)
|
|
var i int32
|
|
var p, v, zType uintptr
|
|
var _ /* sNC at bp+0 */ TNameContext
|
|
var _ /* zOrigCol at bp+72 */ uintptr
|
|
var _ /* zOrigDb at bp+56 */ uintptr
|
|
var _ /* zOrigTab at bp+64 */ uintptr
|
|
_, _, _, _ = i, p, v, zType
|
|
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
|
|
(**(**TNameContext)(__ccgo_up(bp))).FpSrcList = pTabList
|
|
(**(**TNameContext)(__ccgo_up(bp))).FpParse = pParse
|
|
(**(**TNameContext)(__ccgo_up(bp))).FpNext = uintptr(0)
|
|
i = 0
|
|
for {
|
|
if !(i < (*TExprList)(unsafe.Pointer(pEList)).FnExpr) {
|
|
break
|
|
}
|
|
p = (*(*TExprList_item)(unsafe.Pointer(pEList + 8 + uintptr(i)*32))).FpExpr
|
|
**(**uintptr)(__ccgo_up(bp + 56)) = uintptr(0)
|
|
**(**uintptr)(__ccgo_up(bp + 64)) = uintptr(0)
|
|
**(**uintptr)(__ccgo_up(bp + 72)) = uintptr(0)
|
|
zType = _columnTypeImpl(tls, bp, p, bp+56, bp+64, bp+72)
|
|
/* The vdbe must make its own copy of the column-type and other
|
|
** column specific strings, in case the schema is reset before this
|
|
** virtual machine is deleted.
|
|
*/
|
|
_sqlite3VdbeSetColName(tls, v, i, int32(COLNAME_DATABASE), **(**uintptr)(__ccgo_up(bp + 56)), uintptr(-libc.Int32FromInt32(1)))
|
|
_sqlite3VdbeSetColName(tls, v, i, int32(COLNAME_TABLE), **(**uintptr)(__ccgo_up(bp + 64)), uintptr(-libc.Int32FromInt32(1)))
|
|
_sqlite3VdbeSetColName(tls, v, i, int32(COLNAME_COLUMN), **(**uintptr)(__ccgo_up(bp + 72)), uintptr(-libc.Int32FromInt32(1)))
|
|
_sqlite3VdbeSetColName(tls, v, i, int32(COLNAME_DECLTYPE), zType, uintptr(-libc.Int32FromInt32(1)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** SQL function: geopoly_contains_point(P,X,Y)
|
|
// **
|
|
// ** Return +2 if point X,Y is within polygon P.
|
|
// ** Return +1 if point X,Y is on the polygon boundary.
|
|
// ** Return 0 if point X,Y is outside the polygon
|
|
// */
|
|
func _geopolyContainsPointFunc(tls *libc.TLS, context uintptr, argc int32, argv uintptr) {
|
|
var cnt, ii, v int32
|
|
var p1 uintptr
|
|
var x0, y0 float64
|
|
_, _, _, _, _, _ = cnt, ii, p1, v, x0, y0
|
|
p1 = _geopolyFuncParam(tls, context, **(**uintptr)(__ccgo_up(argv)), uintptr(0))
|
|
x0 = Xsqlite3_value_double(tls, **(**uintptr)(__ccgo_up(argv + 1*8)))
|
|
y0 = Xsqlite3_value_double(tls, **(**uintptr)(__ccgo_up(argv + 2*8)))
|
|
v = 0
|
|
cnt = 0
|
|
_ = argc
|
|
if p1 == uintptr(0) {
|
|
return
|
|
}
|
|
ii = 0
|
|
for {
|
|
if !(ii < (*TGeoPoly)(unsafe.Pointer(p1)).FnVertex-int32(1)) {
|
|
break
|
|
}
|
|
v = _pointBeneathLine(tls, x0, y0, float64(**(**TGeoCoord)(__ccgo_up(p1 + 8 + uintptr(ii*int32(2))*4))), float64(**(**TGeoCoord)(__ccgo_up(p1 + 8 + uintptr(ii*int32(2)+int32(1))*4))), float64(**(**TGeoCoord)(__ccgo_up(p1 + 8 + uintptr((ii+int32(1))*int32(2))*4))), float64(**(**TGeoCoord)(__ccgo_up(p1 + 8 + uintptr((ii+int32(1))*int32(2)+int32(1))*4))))
|
|
if v == int32(2) {
|
|
break
|
|
}
|
|
cnt = cnt + v
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
if v != int32(2) {
|
|
v = _pointBeneathLine(tls, x0, y0, float64(**(**TGeoCoord)(__ccgo_up(p1 + 8 + uintptr(ii*int32(2))*4))), float64(**(**TGeoCoord)(__ccgo_up(p1 + 8 + uintptr(ii*int32(2)+int32(1))*4))), float64(**(**TGeoCoord)(__ccgo_up(p1 + 8 + uintptr(libc.Int32FromInt32(0)*libc.Int32FromInt32(2))*4))), float64(**(**TGeoCoord)(__ccgo_up(p1 + 8 + uintptr(libc.Int32FromInt32(0)*libc.Int32FromInt32(2)+libc.Int32FromInt32(1))*4))))
|
|
}
|
|
if v == int32(2) {
|
|
Xsqlite3_result_int(tls, context, int32(1))
|
|
} else {
|
|
if (v+cnt)&int32(1) == 0 {
|
|
Xsqlite3_result_int(tls, context, 0)
|
|
} else {
|
|
Xsqlite3_result_int(tls, context, int32(2))
|
|
}
|
|
}
|
|
Xsqlite3_free(tls, p1)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** SQL function: geopoly_overlap(P1,P2)
|
|
// **
|
|
// ** Determine whether or not P1 and P2 overlap. Return value:
|
|
// **
|
|
// ** 0 The two polygons are disjoint
|
|
// ** 1 They overlap
|
|
// ** 2 P1 is completely contained within P2
|
|
// ** 3 P2 is completely contained within P1
|
|
// ** 4 P1 and P2 are the same polygon
|
|
// ** NULL Either P1 or P2 or both are not valid polygons
|
|
// */
|
|
func _geopolyOverlapFunc(tls *libc.TLS, context uintptr, argc int32, argv uintptr) {
|
|
var p1, p2 uintptr
|
|
var x int32
|
|
_, _, _ = p1, p2, x
|
|
p1 = _geopolyFuncParam(tls, context, **(**uintptr)(__ccgo_up(argv)), uintptr(0))
|
|
p2 = _geopolyFuncParam(tls, context, **(**uintptr)(__ccgo_up(argv + 1*8)), uintptr(0))
|
|
_ = argc
|
|
if p1 != 0 && p2 != 0 {
|
|
x = _geopolyOverlap(tls, p1, p2)
|
|
if x < 0 {
|
|
Xsqlite3_result_error_nomem(tls, context)
|
|
} else {
|
|
Xsqlite3_result_int(tls, context, x)
|
|
}
|
|
}
|
|
Xsqlite3_free(tls, p1)
|
|
Xsqlite3_free(tls, p2)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Sort an array of nEvent event objects into a list.
|
|
// */
|
|
func _geopolySortEventsByX(tls *libc.TLS, aEvent uintptr, nEvent int32) (r uintptr) {
|
|
var a [50]uintptr
|
|
var i, j, mx int32
|
|
var p uintptr
|
|
_, _, _, _, _ = a, i, j, mx, p
|
|
mx = 0
|
|
i = 0
|
|
for {
|
|
if !(i < nEvent) {
|
|
break
|
|
}
|
|
p = aEvent + uintptr(i)*32
|
|
(*TGeoEvent)(unsafe.Pointer(p)).FpNext = uintptr(0)
|
|
j = 0
|
|
for {
|
|
if !(j < mx && a[j] != 0) {
|
|
break
|
|
}
|
|
p = _geopolyEventMerge(tls, a[j], p)
|
|
a[j] = uintptr(0)
|
|
goto _2
|
|
_2:
|
|
;
|
|
j = j + 1
|
|
}
|
|
a[j] = p
|
|
if j >= mx {
|
|
mx = j + int32(1)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
p = uintptr(0)
|
|
i = 0
|
|
for {
|
|
if !(i < mx) {
|
|
break
|
|
}
|
|
p = _geopolyEventMerge(tls, a[i], p)
|
|
goto _3
|
|
_3:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return p
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** SQL function: geopoly_within(P1,P2)
|
|
// **
|
|
// ** Return +2 if P1 and P2 are the same polygon
|
|
// ** Return +1 if P2 is contained within P1
|
|
// ** Return 0 if any part of P2 is on the outside of P1
|
|
// **
|
|
// */
|
|
func _geopolyWithinFunc(tls *libc.TLS, context uintptr, argc int32, argv uintptr) {
|
|
var p1, p2 uintptr
|
|
var x, v1, v2 int32
|
|
_, _, _, _, _ = p1, p2, x, v1, v2
|
|
p1 = _geopolyFuncParam(tls, context, **(**uintptr)(__ccgo_up(argv)), uintptr(0))
|
|
p2 = _geopolyFuncParam(tls, context, **(**uintptr)(__ccgo_up(argv + 1*8)), uintptr(0))
|
|
_ = argc
|
|
if p1 != 0 && p2 != 0 {
|
|
x = _geopolyOverlap(tls, p1, p2)
|
|
if x < 0 {
|
|
Xsqlite3_result_error_nomem(tls, context)
|
|
} else {
|
|
if x == int32(2) {
|
|
v1 = int32(1)
|
|
} else {
|
|
if x == int32(4) {
|
|
v2 = int32(2)
|
|
} else {
|
|
v2 = 0
|
|
}
|
|
v1 = v2
|
|
}
|
|
Xsqlite3_result_int(tls, context, v1)
|
|
}
|
|
}
|
|
Xsqlite3_free(tls, p1)
|
|
Xsqlite3_free(tls, p2)
|
|
}
|
|
|
|
func _getDoubleArg(tls *libc.TLS, p uintptr) (r float64) {
|
|
var v1 int32
|
|
var v2 uintptr
|
|
_, _ = v1, v2
|
|
if (*TPrintfArguments)(unsafe.Pointer(p)).FnArg <= (*TPrintfArguments)(unsafe.Pointer(p)).FnUsed {
|
|
return float64(0)
|
|
}
|
|
v2 = p + 4
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
return Xsqlite3_value_double(tls, **(**uintptr)(__ccgo_up((*TPrintfArguments)(unsafe.Pointer(p)).FapArg + uintptr(v1)*8)))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Extra argument values from a PrintfArguments object
|
|
// */
|
|
func _getIntArg(tls *libc.TLS, p uintptr) (r Tsqlite3_int64) {
|
|
var v1 int32
|
|
var v2 uintptr
|
|
_, _ = v1, v2
|
|
if (*TPrintfArguments)(unsafe.Pointer(p)).FnArg <= (*TPrintfArguments)(unsafe.Pointer(p)).FnUsed {
|
|
return 0
|
|
}
|
|
v2 = p + 4
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
return Xsqlite3_value_int64(tls, **(**uintptr)(__ccgo_up((*TPrintfArguments)(unsafe.Pointer(p)).FapArg + uintptr(v1)*8)))
|
|
}
|
|
|
|
func _getTextArg(tls *libc.TLS, p uintptr) (r uintptr) {
|
|
var v1 int32
|
|
var v2 uintptr
|
|
_, _ = v1, v2
|
|
if (*TPrintfArguments)(unsafe.Pointer(p)).FnArg <= (*TPrintfArguments)(unsafe.Pointer(p)).FnUsed {
|
|
return uintptr(0)
|
|
}
|
|
v2 = p + 4
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
return Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up((*TPrintfArguments)(unsafe.Pointer(p)).FapArg + uintptr(v1)*8)))
|
|
}
|
|
|
|
func _heightOfExprList(tls *libc.TLS, p uintptr, pnHeight uintptr) {
|
|
var i int32
|
|
_ = i
|
|
if p != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TExprList)(unsafe.Pointer(p)).FnExpr) {
|
|
break
|
|
}
|
|
_heightOfExpr(tls, (*(*TExprList_item)(unsafe.Pointer(p + 8 + uintptr(i)*32))).FpExpr, pnHeight)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Check the N SrcItem objects to the right of pBase. (N might be zero!)
|
|
// ** If any of those SrcItem objects have a USING clause containing zName
|
|
// ** then return true.
|
|
// **
|
|
// ** If N is zero, or none of the N SrcItem objects to the right of pBase
|
|
// ** contains a USING clause, or if none of the USING clauses contain zName,
|
|
// ** then return false.
|
|
// */
|
|
func _inAnyUsingClause(tls *libc.TLS, zName uintptr, pBase uintptr, N int32) (r int32) {
|
|
for N > 0 {
|
|
N = N - 1
|
|
pBase += 80
|
|
if int32(*(*uint32)(unsafe.Pointer(pBase + 24 + 4))&0x800>>11) == 0 {
|
|
continue
|
|
}
|
|
if *(*uintptr)(unsafe.Pointer(pBase + 64)) == uintptr(0) {
|
|
continue
|
|
}
|
|
if _sqlite3IdListIndex(tls, *(*uintptr)(unsafe.Pointer(pBase + 64)), zName) >= 0 {
|
|
return int32(1)
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Check to see if column iCol of index pIdx references any of the
|
|
// ** columns defined by aXRef and chngRowid. Return true if it does
|
|
// ** and false if not. This is an optimization. False-positives are a
|
|
// ** performance degradation, but false-negatives can result in a corrupt
|
|
// ** index and incorrect answers.
|
|
// **
|
|
// ** aXRef[j] will be non-negative if column j of the original table is
|
|
// ** being updated. chngRowid will be true if the rowid of the table is
|
|
// ** being updated.
|
|
// */
|
|
func _indexColumnIsBeingUpdated(tls *libc.TLS, pIdx uintptr, iCol int32, aXRef uintptr, chngRowid int32) (r int32) {
|
|
var iIdxCol Ti16
|
|
_ = iIdxCol
|
|
iIdxCol = **(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(iCol)*2))
|
|
/* Cannot index rowid */
|
|
if int32(iIdxCol) >= 0 {
|
|
return libc.BoolInt32(**(**int32)(__ccgo_up(aXRef + uintptr(iIdxCol)*4)) >= 0)
|
|
}
|
|
return _sqlite3ExprReferencesUpdatedColumn(tls, (*(*TExprList_item)(unsafe.Pointer((*TIndex)(unsafe.Pointer(pIdx)).FaColExpr + 8 + uintptr(iCol)*32))).FpExpr, aXRef, chngRowid)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return TRUE if the iCol-th column of index pIdx is NOT NULL
|
|
// */
|
|
func _indexColumnNotNull(tls *libc.TLS, pIdx uintptr, iCol int32) (r int32) {
|
|
var j int32
|
|
_ = j
|
|
j = int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(iCol)*2)))
|
|
if j >= 0 {
|
|
return int32(uint32(*(*uint8)(unsafe.Pointer((*TTable)(unsafe.Pointer((*TIndex)(unsafe.Pointer(pIdx)).FpTable)).FaCol + uintptr(j)*16 + 8)) & 0xf >> 0))
|
|
} else {
|
|
if j == -int32(1) {
|
|
return int32(1)
|
|
} else {
|
|
return 0 /* Assume an indexed expression can always yield a NULL */
|
|
}
|
|
}
|
|
return r
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Return the next index from the list. Return NULL when out of indexes */
|
|
func _indexIteratorNext(tls *libc.TLS, pIter uintptr, pIx uintptr) (r uintptr) {
|
|
var i, v1 int32
|
|
var v2 uintptr
|
|
_, _, _ = i, v1, v2
|
|
if (*TIndexIterator)(unsafe.Pointer(pIter)).FeType != 0 {
|
|
v2 = pIter + 4
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
i = v1
|
|
if i >= (*(*struct {
|
|
FnIdx int32
|
|
FaIdx uintptr
|
|
})(unsafe.Pointer(pIter + 8))).FnIdx {
|
|
**(**int32)(__ccgo_up(pIx)) = i
|
|
return uintptr(0)
|
|
}
|
|
**(**int32)(__ccgo_up(pIx)) = (**(**TIndexListTerm)(__ccgo_up((*(*struct {
|
|
FnIdx int32
|
|
FaIdx uintptr
|
|
})(unsafe.Pointer(pIter + 8))).FaIdx + uintptr(i)*16))).Fix
|
|
return (**(**TIndexListTerm)(__ccgo_up((*(*struct {
|
|
FnIdx int32
|
|
FaIdx uintptr
|
|
})(unsafe.Pointer(pIter + 8))).FaIdx + uintptr(i)*16))).Fp
|
|
} else {
|
|
**(**int32)(__ccgo_up(pIx)) = **(**int32)(__ccgo_up(pIx)) + 1
|
|
(*TIndexIterator)(unsafe.Pointer(pIter)).Fu.Flx.FpIdx = (*TIndex)(unsafe.Pointer((*TIndexIterator)(unsafe.Pointer(pIter)).Fu.Flx.FpIdx)).FpNext
|
|
return (*TIndexIterator)(unsafe.Pointer(pIter)).Fu.Flx.FpIdx
|
|
}
|
|
return r
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Initialize an array of N Mem element.
|
|
// **
|
|
// ** This is a high-runner, so only those fields that really do need to
|
|
// ** be initialized are set. The Mem structure is organized so that
|
|
// ** the fields that get initialized are nearby and hopefully on the same
|
|
// ** cache line.
|
|
// **
|
|
// ** Mem.flags = flags
|
|
// ** Mem.db = db
|
|
// ** Mem.szMalloc = 0
|
|
// **
|
|
// ** All other fields of Mem can safely remain uninitialized for now. They
|
|
// ** will be initialized before use.
|
|
// */
|
|
func _initMemArray(tls *libc.TLS, p uintptr, N int32, db uintptr, flags Tu16) {
|
|
var v1 int32
|
|
_ = v1
|
|
if N > 0 {
|
|
for {
|
|
(*TMem)(unsafe.Pointer(p)).Fflags = flags
|
|
(*TMem)(unsafe.Pointer(p)).Fdb = db
|
|
(*TMem)(unsafe.Pointer(p)).FszMalloc = 0
|
|
p += 56
|
|
goto _2
|
|
_2:
|
|
;
|
|
N = N - 1
|
|
v1 = N
|
|
if !(v1 > 0) {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return true if any of the first nKey entries of index pIdx exactly
|
|
// ** match the iCol-th entry of pPk. pPk is always a WITHOUT ROWID
|
|
// ** PRIMARY KEY index. pIdx is an index on the same table. pIdx may
|
|
// ** or may not be the same index as pPk.
|
|
// **
|
|
// ** The first nKey entries of pIdx are guaranteed to be ordinary columns,
|
|
// ** not a rowid or expression.
|
|
// **
|
|
// ** This routine differs from hasColumn() in that both the column and the
|
|
// ** collating sequence must match for this routine, but for hasColumn() only
|
|
// ** the column name must match.
|
|
// */
|
|
func _isDupColumn(tls *libc.TLS, pIdx uintptr, nKey int32, pPk uintptr, iCol int32) (r int32) {
|
|
var i, j int32
|
|
_, _ = i, j
|
|
j = int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pPk)).FaiColumn + uintptr(iCol)*2)))
|
|
i = 0
|
|
for {
|
|
if !(i < nKey) {
|
|
break
|
|
}
|
|
if int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(i)*2))) == j && _sqlite3StrICmp(tls, **(**uintptr)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FazColl + uintptr(i)*8)), **(**uintptr)(__ccgo_up((*TIndex)(unsafe.Pointer(pPk)).FazColl + uintptr(iCol)*8))) == 0 {
|
|
return int32(1)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** TRUE if p is a lookaside memory allocation from db
|
|
// */
|
|
func _isLookaside(tls *libc.TLS, db uintptr, p uintptr) (r int32) {
|
|
return libc.BoolInt32(uint64(p) >= uint64((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpStart) && uint64(p) < uint64((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpTrueEnd))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Check to see if the pThis entry of pTabList is a self-join of another view.
|
|
// ** Search FROM-clause entries in the range of iFirst..iEnd, including iFirst
|
|
// ** but stopping before iEnd.
|
|
// **
|
|
// ** If pThis is a self-join, then return the SrcItem for the first other
|
|
// ** instance of that view found. If pThis is not a self-join then return 0.
|
|
// */
|
|
func _isSelfJoinView(tls *libc.TLS, pTabList uintptr, pThis uintptr, iFirst int32, iEnd int32) (r uintptr) {
|
|
var pItem, pS1, pSel uintptr
|
|
var v1 int32
|
|
_, _, _, _ = pItem, pS1, pSel, v1
|
|
pSel = (*TSubquery)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pThis + 72)))).FpSelect
|
|
if (*TSelect)(unsafe.Pointer(pSel)).FselFlags&uint32(SF_PushDown) != 0 {
|
|
return uintptr(0)
|
|
}
|
|
for iFirst < iEnd {
|
|
v1 = iFirst
|
|
iFirst = iFirst + 1
|
|
pItem = pTabList + 8 + uintptr(v1)*80
|
|
if !(int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x4>>2) != 0) {
|
|
continue
|
|
}
|
|
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x40>>6) != 0 {
|
|
continue
|
|
}
|
|
if (*TSrcItem)(unsafe.Pointer(pItem)).FzName == uintptr(0) {
|
|
continue
|
|
}
|
|
if (*TTable)(unsafe.Pointer((*TSrcItem)(unsafe.Pointer(pItem)).FpSTab)).FpSchema != (*TTable)(unsafe.Pointer((*TSrcItem)(unsafe.Pointer(pThis)).FpSTab)).FpSchema {
|
|
continue
|
|
}
|
|
if Xsqlite3_stricmp(tls, (*TSrcItem)(unsafe.Pointer(pItem)).FzName, (*TSrcItem)(unsafe.Pointer(pThis)).FzName) != 0 {
|
|
continue
|
|
}
|
|
pS1 = (*TSubquery)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pItem + 72)))).FpSelect
|
|
if (*TTable)(unsafe.Pointer((*TSrcItem)(unsafe.Pointer(pItem)).FpSTab)).FpSchema == uintptr(0) && (*TSelect)(unsafe.Pointer(pSel)).FselId != (*TSelect)(unsafe.Pointer(pS1)).FselId {
|
|
/* The query flattener left two different CTE tables with identical
|
|
** names in the same FROM clause. */
|
|
continue
|
|
}
|
|
if (*TSelect)(unsafe.Pointer(pS1)).FselFlags&uint32(SF_PushDown) != 0 {
|
|
/* The view was modified by some other optimization such as
|
|
** pushDownWhereTerms() */
|
|
continue
|
|
}
|
|
return pItem
|
|
}
|
|
return uintptr(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Append a single character.
|
|
// */
|
|
func _jsonBlobAppendOneByte(tls *libc.TLS, pParse uintptr, c Tu8) {
|
|
var v1 Tu32
|
|
var v2 uintptr
|
|
_, _ = v1, v2
|
|
if (*TJsonParse)(unsafe.Pointer(pParse)).FnBlob >= (*TJsonParse)(unsafe.Pointer(pParse)).FnBlobAlloc {
|
|
_jsonBlobExpandAndAppendOneByte(tls, pParse, c)
|
|
} else {
|
|
v2 = pParse + 8
|
|
v1 = *(*Tu32)(unsafe.Pointer(v2))
|
|
*(*Tu32)(unsafe.Pointer(v2)) = *(*Tu32)(unsafe.Pointer(v2)) + 1
|
|
**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(v1))) = c
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free a JsonCache object.
|
|
// */
|
|
func _jsonCacheDelete(tls *libc.TLS, p uintptr) {
|
|
var i int32
|
|
_ = i
|
|
i = 0
|
|
for {
|
|
if !(i < (*TJsonCache)(unsafe.Pointer(p)).FnUsed) {
|
|
break
|
|
}
|
|
_jsonParseFree(tls, **(**uintptr)(__ccgo_up(p + 16 + uintptr(i)*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_sqlite3DbFree(tls, (*TJsonCache)(unsafe.Pointer(p)).Fdb, p)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Reset a JsonEachCursor back to its original state. Free any memory
|
|
// ** held. */
|
|
func _jsonEachCursorReset(tls *libc.TLS, p uintptr) {
|
|
_jsonParseReset(tls, p+192)
|
|
_jsonStringReset(tls, p+56)
|
|
_sqlite3DbFree(tls, (*TJsonEachCursor)(unsafe.Pointer(p)).Fdb, (*TJsonEachCursor)(unsafe.Pointer(p)).FaParent)
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FiRowid = uint32(0)
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).Fi = uint32(0)
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FaParent = uintptr(0)
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FnParent = uint32(0)
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FnParentAlloc = uint32(0)
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FiEnd = uint32(0)
|
|
(*TJsonEachCursor)(unsafe.Pointer(p)).FeType = uint8(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* constructor for a JsonEachCursor object for json_each()/json_tree(). */
|
|
func _jsonEachOpen(tls *libc.TLS, p uintptr, ppCursor uintptr) (r int32) {
|
|
var pCur, pVtab uintptr
|
|
_, _ = pCur, pVtab
|
|
pVtab = p
|
|
_ = p
|
|
pCur = _sqlite3DbMallocZero(tls, (*TJsonEachConnection)(unsafe.Pointer(pVtab)).Fdb, uint64(264))
|
|
if pCur == uintptr(0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
(*TJsonEachCursor)(unsafe.Pointer(pCur)).Fdb = (*TJsonEachConnection)(unsafe.Pointer(pVtab)).Fdb
|
|
(*TJsonEachCursor)(unsafe.Pointer(pCur)).FeMode = (*TJsonEachConnection)(unsafe.Pointer(pVtab)).FeMode
|
|
(*TJsonEachCursor)(unsafe.Pointer(pCur)).FbRecursive = (*TJsonEachConnection)(unsafe.Pointer(pVtab)).FbRecursive
|
|
_jsonStringZero(tls, pCur+56)
|
|
**(**uintptr)(__ccgo_up(ppCursor)) = pCur
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Compare two object labels. Return 1 if they are equal and
|
|
// ** 0 if they differ. Return -1 if an OOM occurs.
|
|
// */
|
|
func _jsonLabelCompare(tls *libc.TLS, zLeft uintptr, nLeft Tu32, rawLeft int32, zRight uintptr, nRight Tu32, rawRight int32) (r int32) {
|
|
if rawLeft != 0 && rawRight != 0 {
|
|
/* Simpliest case: Neither label contains escapes. A simple
|
|
** memcmp() is sufficient. */
|
|
if nLeft != nRight {
|
|
return 0
|
|
}
|
|
return libc.BoolInt32(libc.Xmemcmp(tls, zLeft, zRight, uint64(nLeft)) == 0)
|
|
} else {
|
|
return _jsonLabelCompareEscaped(tls, zLeft, nLeft, rawLeft, zRight, nRight, rawRight)
|
|
}
|
|
return r
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of the json_quote(VALUE) function. Return a JSON value
|
|
// ** corresponding to the SQL value input. Mostly this means putting
|
|
// ** double-quotes around strings and returning the unquoted string "null"
|
|
// ** when given a NULL input.
|
|
// */
|
|
func _jsonQuoteFunc(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
|
|
bp := tls.Alloc(144)
|
|
defer tls.Free(144)
|
|
var _ /* jx at bp+0 */ TJsonString
|
|
_ = argc
|
|
_jsonStringInit(tls, bp, ctx)
|
|
_jsonAppendSqlValue(tls, bp, **(**uintptr)(__ccgo_up(argv)))
|
|
_jsonReturnString(tls, bp, uintptr(0), uintptr(0))
|
|
Xsqlite3_result_subtype(tls, ctx, uint32(JSON_SUBTYPE))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Report an out-of-memory (OOM) condition
|
|
// */
|
|
func _jsonStringOom(tls *libc.TLS, p uintptr) {
|
|
var v1 uintptr
|
|
_ = v1
|
|
v1 = p + 33
|
|
*(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) | libc.Int32FromInt32(JSTRING_OOM))
|
|
if (*TJsonString)(unsafe.Pointer(p)).FpCtx != 0 {
|
|
Xsqlite3_result_error_nomem(tls, (*TJsonString)(unsafe.Pointer(p)).FpCtx)
|
|
}
|
|
_jsonStringReset(tls, p)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Turn uninitialized bulk memory into a valid JsonString object
|
|
// ** holding a zero-length string.
|
|
// */
|
|
func _jsonStringZero(tls *libc.TLS, p uintptr) {
|
|
(*TJsonString)(unsafe.Pointer(p)).FzBuf = p + 34
|
|
(*TJsonString)(unsafe.Pointer(p)).FnAlloc = uint64(100)
|
|
(*TJsonString)(unsafe.Pointer(p)).FnUsed = uint64(0)
|
|
(*TJsonString)(unsafe.Pointer(p)).FbStatic = uint8(1)
|
|
}
|
|
|
|
func _last_valueFinalizeFunc(tls *libc.TLS, pCtx uintptr) {
|
|
var p uintptr
|
|
_ = p
|
|
p = Xsqlite3_aggregate_context(tls, pCtx, int32(16))
|
|
if p != 0 && (*TLastValueCtx)(unsafe.Pointer(p)).FpVal != 0 {
|
|
Xsqlite3_result_value(tls, pCtx, (*TLastValueCtx)(unsafe.Pointer(p)).FpVal)
|
|
Xsqlite3_value_free(tls, (*TLastValueCtx)(unsafe.Pointer(p)).FpVal)
|
|
(*TLastValueCtx)(unsafe.Pointer(p)).FpVal = uintptr(0)
|
|
}
|
|
}
|
|
|
|
func _last_valueInvFunc(tls *libc.TLS, pCtx uintptr, nArg int32, apArg uintptr) {
|
|
var p uintptr
|
|
_ = p
|
|
_ = nArg
|
|
_ = apArg
|
|
p = Xsqlite3_aggregate_context(tls, pCtx, int32(16))
|
|
if p != 0 {
|
|
(*TLastValueCtx)(unsafe.Pointer(p)).FnVal = (*TLastValueCtx)(unsafe.Pointer(p)).FnVal - 1
|
|
if (*TLastValueCtx)(unsafe.Pointer(p)).FnVal == 0 {
|
|
Xsqlite3_value_free(tls, (*TLastValueCtx)(unsafe.Pointer(p)).FpVal)
|
|
(*TLastValueCtx)(unsafe.Pointer(p)).FpVal = uintptr(0)
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of last_value().
|
|
// */
|
|
func _last_valueStepFunc(tls *libc.TLS, pCtx uintptr, nArg int32, apArg uintptr) {
|
|
var p uintptr
|
|
_ = p
|
|
_ = nArg
|
|
p = Xsqlite3_aggregate_context(tls, pCtx, int32(16))
|
|
if p != 0 {
|
|
Xsqlite3_value_free(tls, (*TLastValueCtx)(unsafe.Pointer(p)).FpVal)
|
|
(*TLastValueCtx)(unsafe.Pointer(p)).FpVal = Xsqlite3_value_dup(tls, **(**uintptr)(__ccgo_up(apArg)))
|
|
if (*TLastValueCtx)(unsafe.Pointer(p)).FpVal == uintptr(0) {
|
|
Xsqlite3_result_error_nomem(tls, pCtx)
|
|
} else {
|
|
(*TLastValueCtx)(unsafe.Pointer(p)).FnVal = (*TLastValueCtx)(unsafe.Pointer(p)).FnVal + 1
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of SQL functions:
|
|
// **
|
|
// ** ln(X) - natural logarithm
|
|
// ** log(X) - log X base 10
|
|
// ** log10(X) - log X base 10
|
|
// ** log(B,X) - log X base B
|
|
// */
|
|
func _logFunc(tls *libc.TLS, context uintptr, argc int32, argv uintptr) {
|
|
var ans, b, x float64
|
|
_, _, _ = ans, b, x
|
|
switch Xsqlite3_value_numeric_type(tls, **(**uintptr)(__ccgo_up(argv))) {
|
|
case int32(SQLITE_INTEGER):
|
|
fallthrough
|
|
case int32(SQLITE_FLOAT):
|
|
x = Xsqlite3_value_double(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
if x <= float64(0) {
|
|
return
|
|
}
|
|
default:
|
|
return
|
|
}
|
|
if argc == int32(2) {
|
|
switch Xsqlite3_value_numeric_type(tls, **(**uintptr)(__ccgo_up(argv))) {
|
|
case int32(SQLITE_INTEGER):
|
|
fallthrough
|
|
case int32(SQLITE_FLOAT):
|
|
b = libc.Xlog(tls, x)
|
|
if b <= float64(0) {
|
|
return
|
|
}
|
|
x = Xsqlite3_value_double(tls, **(**uintptr)(__ccgo_up(argv + 1*8)))
|
|
if x <= float64(0) {
|
|
return
|
|
}
|
|
default:
|
|
return
|
|
}
|
|
ans = libc.Xlog(tls, x) / b
|
|
} else {
|
|
switch int32(int64(Xsqlite3_user_data(tls, context))) {
|
|
case int32(1):
|
|
ans = libc.Xlog10(tls, x)
|
|
case int32(2):
|
|
ans = libc.X__builtin_log2(tls, x)
|
|
default:
|
|
ans = libc.Xlog(tls, x)
|
|
break
|
|
}
|
|
}
|
|
Xsqlite3_result_double(tls, context, ans)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Code the OP_MakeRecord instruction that generates the entry to be
|
|
// ** added into the sorter.
|
|
// **
|
|
// ** Return the register in which the result is stored.
|
|
// */
|
|
func _makeSorterRecord(tls *libc.TLS, pParse uintptr, pSort uintptr, pSelect uintptr, regBase int32, nBase int32) (r int32) {
|
|
var nOBSat, regOut, v1 int32
|
|
var v, v2 uintptr
|
|
_, _, _, _, _ = nOBSat, regOut, v, v1, v2
|
|
nOBSat = (*TSortCtx)(unsafe.Pointer(pSort)).FnOBSat
|
|
v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe
|
|
v2 = pParse + 60
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
regOut = v1
|
|
if (*TSortCtx)(unsafe.Pointer(pSort)).FpDeferredRowLoad != 0 {
|
|
_innerLoopLoadRow(tls, pParse, pSelect, (*TSortCtx)(unsafe.Pointer(pSort)).FpDeferredRowLoad)
|
|
}
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_MakeRecord), regBase+nOBSat, nBase-nOBSat, regOut)
|
|
return regOut
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Mark term iChild as being a child of term iParent
|
|
// */
|
|
func _markTermAsChild(tls *libc.TLS, pWC uintptr, iChild int32, iParent int32) {
|
|
(**(**TWhereTerm)(__ccgo_up((*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(iChild)*56))).FiParent = iParent
|
|
(**(**TWhereTerm)(__ccgo_up((*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(iChild)*56))).FtruthProb = (**(**TWhereTerm)(__ccgo_up((*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(iParent)*56))).FtruthProb
|
|
(**(**TWhereTerm)(__ccgo_up((*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(iParent)*56))).FnChild = (**(**TWhereTerm)(__ccgo_up((*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(iParent)*56))).FnChild + 1
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of 2-argument SQL math functions:
|
|
// **
|
|
// ** power(X,Y) - Compute X to the Y-th power
|
|
// */
|
|
func _math2Func(tls *libc.TLS, context uintptr, argc int32, argv uintptr) {
|
|
var ans, v0, v1 float64
|
|
var type0, type1 int32
|
|
var x uintptr
|
|
_, _, _, _, _, _ = ans, type0, type1, v0, v1, x
|
|
type0 = Xsqlite3_value_numeric_type(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
if type0 != int32(SQLITE_INTEGER) && type0 != int32(SQLITE_FLOAT) {
|
|
return
|
|
}
|
|
type1 = Xsqlite3_value_numeric_type(tls, **(**uintptr)(__ccgo_up(argv + 1*8)))
|
|
if type1 != int32(SQLITE_INTEGER) && type1 != int32(SQLITE_FLOAT) {
|
|
return
|
|
}
|
|
v0 = Xsqlite3_value_double(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
v1 = Xsqlite3_value_double(tls, **(**uintptr)(__ccgo_up(argv + 1*8)))
|
|
x = Xsqlite3_user_data(tls, context)
|
|
ans = (*(*func(*libc.TLS, float64, float64) float64)(unsafe.Pointer(&struct{ uintptr }{x})))(tls, v0, v1)
|
|
Xsqlite3_result_double(tls, context, ans)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Close an memdb-file.
|
|
// ** Free the underlying MemStore object when its refcount drops to zero
|
|
// ** or less.
|
|
// */
|
|
func _memdbClose(tls *libc.TLS, pFile uintptr) (r int32) {
|
|
var i, v2 int32
|
|
var p, pVfsMutex, v3 uintptr
|
|
_, _, _, _, _ = i, p, pVfsMutex, v2, v3
|
|
p = (*TMemFile)(unsafe.Pointer(pFile)).FpStore
|
|
if (*TMemStore)(unsafe.Pointer(p)).FzFName != 0 {
|
|
pVfsMutex = _sqlite3MutexAlloc(tls, int32(SQLITE_MUTEX_STATIC_VFS1))
|
|
Xsqlite3_mutex_enter(tls, pVfsMutex)
|
|
i = 0
|
|
for {
|
|
if !(i < _memdb_g.FnMemStore) {
|
|
break
|
|
}
|
|
if **(**uintptr)(__ccgo_up(_memdb_g.FapMemStore + uintptr(i)*8)) == p {
|
|
_memdbEnter(tls, p)
|
|
if (*TMemStore)(unsafe.Pointer(p)).FnRef == int32(1) {
|
|
v3 = uintptr(unsafe.Pointer(&_memdb_g))
|
|
*(*int32)(unsafe.Pointer(v3)) = *(*int32)(unsafe.Pointer(v3)) - 1
|
|
v2 = *(*int32)(unsafe.Pointer(v3))
|
|
**(**uintptr)(__ccgo_up(_memdb_g.FapMemStore + uintptr(i)*8)) = **(**uintptr)(__ccgo_up(_memdb_g.FapMemStore + uintptr(v2)*8))
|
|
if _memdb_g.FnMemStore == 0 {
|
|
Xsqlite3_free(tls, _memdb_g.FapMemStore)
|
|
_memdb_g.FapMemStore = uintptr(0)
|
|
}
|
|
}
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
Xsqlite3_mutex_leave(tls, pVfsMutex)
|
|
} else {
|
|
_memdbEnter(tls, p)
|
|
}
|
|
(*TMemStore)(unsafe.Pointer(p)).FnRef = (*TMemStore)(unsafe.Pointer(p)).FnRef - 1
|
|
if (*TMemStore)(unsafe.Pointer(p)).FnRef <= 0 {
|
|
if (*TMemStore)(unsafe.Pointer(p)).FmFlags&uint32(SQLITE_DESERIALIZE_FREEONCLOSE) != 0 {
|
|
Xsqlite3_free(tls, (*TMemStore)(unsafe.Pointer(p)).FaData)
|
|
}
|
|
_memdbLeave(tls, p)
|
|
Xsqlite3_mutex_free(tls, (*TMemStore)(unsafe.Pointer(p)).FpMutex)
|
|
Xsqlite3_free(tls, p)
|
|
} else {
|
|
_memdbLeave(tls, p)
|
|
}
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of the non-aggregate min() and max() functions
|
|
// */
|
|
func _minmaxFunc(tls *libc.TLS, context uintptr, argc int32, argv uintptr) {
|
|
var i, iBest, mask, v1 int32
|
|
var pColl uintptr
|
|
_, _, _, _, _ = i, iBest, mask, pColl, v1
|
|
if Xsqlite3_user_data(tls, context) == uintptr(0) {
|
|
v1 = 0
|
|
} else {
|
|
v1 = -int32(1)
|
|
}
|
|
mask = v1
|
|
pColl = _sqlite3GetFuncCollSeq(tls, context)
|
|
iBest = 0
|
|
if Xsqlite3_value_type(tls, **(**uintptr)(__ccgo_up(argv))) == int32(SQLITE_NULL) {
|
|
return
|
|
}
|
|
i = int32(1)
|
|
for {
|
|
if !(i < argc) {
|
|
break
|
|
}
|
|
if Xsqlite3_value_type(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8))) == int32(SQLITE_NULL) {
|
|
return
|
|
}
|
|
if _sqlite3MemCompare(tls, **(**uintptr)(__ccgo_up(argv + uintptr(iBest)*8)), **(**uintptr)(__ccgo_up(argv + uintptr(i)*8)), pColl)^mask >= 0 {
|
|
iBest = i
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
Xsqlite3_result_value(tls, context, **(**uintptr)(__ccgo_up(argv + uintptr(iBest)*8)))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Routines to implement min() and max() aggregate functions.
|
|
// */
|
|
func _minmaxStep(tls *libc.TLS, context uintptr, NotUsed int32, argv uintptr) {
|
|
var cmp, max int32
|
|
var pArg, pBest, pColl uintptr
|
|
_, _, _, _, _ = cmp, max, pArg, pBest, pColl
|
|
pArg = **(**uintptr)(__ccgo_up(argv))
|
|
_ = NotUsed
|
|
pBest = Xsqlite3_aggregate_context(tls, context, int32(56))
|
|
if !(pBest != 0) {
|
|
return
|
|
}
|
|
if Xsqlite3_value_type(tls, pArg) == int32(SQLITE_NULL) {
|
|
if (*TMem)(unsafe.Pointer(pBest)).Fflags != 0 {
|
|
_sqlite3SkipAccumulatorLoad(tls, context)
|
|
}
|
|
} else {
|
|
if (*TMem)(unsafe.Pointer(pBest)).Fflags != 0 {
|
|
pColl = _sqlite3GetFuncCollSeq(tls, context)
|
|
/* This step function is used for both the min() and max() aggregates,
|
|
** the only difference between the two being that the sense of the
|
|
** comparison is inverted. For the max() aggregate, the
|
|
** sqlite3_user_data() function returns (void *)-1. For min() it
|
|
** returns (void *)db, where db is the sqlite3* database pointer.
|
|
** Therefore the next statement sets variable 'max' to 1 for the max()
|
|
** aggregate, or 0 for min().
|
|
*/
|
|
max = libc.BoolInt32(Xsqlite3_user_data(tls, context) != uintptr(0))
|
|
cmp = _sqlite3MemCompare(tls, pBest, pArg, pColl)
|
|
if max != 0 && cmp < 0 || !(max != 0) && cmp > 0 {
|
|
_sqlite3VdbeMemCopy(tls, pBest, pArg)
|
|
} else {
|
|
_sqlite3SkipAccumulatorLoad(tls, context)
|
|
}
|
|
} else {
|
|
(*TMem)(unsafe.Pointer(pBest)).Fdb = Xsqlite3_context_db_handle(tls, context)
|
|
_sqlite3VdbeMemCopy(tls, pBest, pArg)
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Move the cursor up to the parent page.
|
|
// **
|
|
// ** pCur->idx is set to the cell index that contains the pointer
|
|
// ** to the page we are coming from. If we are coming from the
|
|
// ** right-most child page then pCur->idx is set to one more than
|
|
// ** the largest cell index.
|
|
// */
|
|
func _moveToParent(tls *libc.TLS, pCur uintptr) {
|
|
var pLeaf, v1 uintptr
|
|
var v2 Ti8
|
|
_, _, _ = pLeaf, v1, v2
|
|
(*TBtCursor)(unsafe.Pointer(pCur)).Finfo.FnSize = uint16(0)
|
|
v1 = pCur + 1
|
|
*(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) & ^(libc.Int32FromInt32(BTCF_ValidNKey) | libc.Int32FromInt32(BTCF_ValidOvfl)))
|
|
(*TBtCursor)(unsafe.Pointer(pCur)).Fix = **(**Tu16)(__ccgo_up(pCur + 88 + uintptr(int32((*TBtCursor)(unsafe.Pointer(pCur)).FiPage)-int32(1))*2))
|
|
pLeaf = (*TBtCursor)(unsafe.Pointer(pCur)).FpPage
|
|
v1 = pCur + 84
|
|
*(*Ti8)(unsafe.Pointer(v1)) = *(*Ti8)(unsafe.Pointer(v1)) - 1
|
|
v2 = *(*Ti8)(unsafe.Pointer(v1))
|
|
(*TBtCursor)(unsafe.Pointer(pCur)).FpPage = **(**uintptr)(__ccgo_up(pCur + 144 + uintptr(v2)*8))
|
|
_releasePageNotNull(tls, pLeaf)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the appropriate collating sequence for the iCol-th column of
|
|
// ** the result set for the compound-select statement "p". Return NULL if
|
|
// ** the column has no default collating sequence.
|
|
// **
|
|
// ** The collating sequence for the compound select is taken from the
|
|
// ** left-most term of the select that has a collating sequence.
|
|
// */
|
|
func _multiSelectCollSeq(tls *libc.TLS, pParse uintptr, p uintptr, iCol int32) (r uintptr) {
|
|
var pRet uintptr
|
|
_ = pRet
|
|
if (*TSelect)(unsafe.Pointer(p)).FpPrior != 0 {
|
|
pRet = _multiSelectCollSeq(tls, pParse, (*TSelect)(unsafe.Pointer(p)).FpPrior, iCol)
|
|
} else {
|
|
pRet = uintptr(0)
|
|
}
|
|
/* iCol must be less than p->pEList->nExpr. Otherwise an error would
|
|
** have been thrown during name resolution and we would not have gotten
|
|
** this far */
|
|
if pRet == uintptr(0) && iCol < (*TExprList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(p)).FpEList)).FnExpr {
|
|
pRet = _sqlite3ExprCollSeq(tls, pParse, (*(*TExprList_item)(unsafe.Pointer((*TSelect)(unsafe.Pointer(p)).FpEList + 8 + uintptr(iCol)*32))).FpExpr)
|
|
}
|
|
return pRet
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Remove node pNode from the node hash table.
|
|
// */
|
|
func _nodeHashDelete(tls *libc.TLS, pRtree uintptr, pNode uintptr) {
|
|
var pp uintptr
|
|
_ = pp
|
|
if (*TRtreeNode)(unsafe.Pointer(pNode)).FiNode != 0 {
|
|
pp = pRtree + 200 + uintptr(_nodeHash(tls, (*TRtreeNode)(unsafe.Pointer(pNode)).FiNode))*8
|
|
for {
|
|
if !(**(**uintptr)(__ccgo_up(pp)) != pNode) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pp = **(**uintptr)(__ccgo_up(pp)) + 32
|
|
}
|
|
**(**uintptr)(__ccgo_up(pp)) = (*TRtreeNode)(unsafe.Pointer(pNode)).FpNext
|
|
(*TRtreeNode)(unsafe.Pointer(pNode)).FpNext = uintptr(0)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Search the node hash table for node iNode. If found, return a pointer
|
|
// ** to it. Otherwise, return 0.
|
|
// */
|
|
func _nodeHashLookup(tls *libc.TLS, pRtree uintptr, iNode Ti64) (r uintptr) {
|
|
var p uintptr
|
|
_ = p
|
|
p = **(**uintptr)(__ccgo_up(pRtree + 200 + uintptr(_nodeHash(tls, iNode))*8))
|
|
for {
|
|
if !(p != 0 && (*TRtreeNode)(unsafe.Pointer(p)).FiNode != iNode) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
p = (*TRtreeNode)(unsafe.Pointer(p)).FpNext
|
|
}
|
|
return p
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of the NULLIF(x,y) function. The result is the first
|
|
// ** argument if the arguments are different. The result is NULL if the
|
|
// ** arguments are equal to each other.
|
|
// */
|
|
func _nullifFunc(tls *libc.TLS, context uintptr, NotUsed int32, argv uintptr) {
|
|
var pColl uintptr
|
|
_ = pColl
|
|
pColl = _sqlite3GetFuncCollSeq(tls, context)
|
|
_ = NotUsed
|
|
if _sqlite3MemCompare(tls, **(**uintptr)(__ccgo_up(argv)), **(**uintptr)(__ccgo_up(argv + 1*8)), pColl) != 0 {
|
|
Xsqlite3_result_value(tls, context, **(**uintptr)(__ccgo_up(argv)))
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Write page pPg onto the end of the rollback journal.
|
|
// */
|
|
func _pagerAddPageToRollbackJournal(tls *libc.TLS, pPg uintptr) (r int32) {
|
|
var cksum Tu32
|
|
var iOff Ti64
|
|
var pData2, pPager, v1 uintptr
|
|
var rc int32
|
|
_, _, _, _, _, _ = cksum, iOff, pData2, pPager, rc, v1
|
|
pPager = (*TPgHdr)(unsafe.Pointer(pPg)).FpPager
|
|
iOff = (*TPager)(unsafe.Pointer(pPager)).FjournalOff
|
|
/* We should never write to the journal file the page that
|
|
** contains the database locks. The following assert verifies
|
|
** that we do not. */
|
|
pData2 = (*TPgHdr)(unsafe.Pointer(pPg)).FpData
|
|
cksum = _pager_cksum(tls, pPager, pData2)
|
|
/* Even if an IO or diskfull error occurs while journalling the
|
|
** page in the block above, set the need-sync flag for the page.
|
|
** Otherwise, when the transaction is rolled back, the logic in
|
|
** playback_one_page() will think that the page needs to be restored
|
|
** in the database file. And if an IO error occurs while doing so,
|
|
** then corruption may follow.
|
|
*/
|
|
v1 = pPg + 52
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(PGHDR_NEED_SYNC))
|
|
rc = _write32bits(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, iOff, (*TPgHdr)(unsafe.Pointer(pPg)).Fpgno)
|
|
if rc != SQLITE_OK {
|
|
return rc
|
|
}
|
|
rc = _sqlite3OsWrite(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, pData2, int32((*TPager)(unsafe.Pointer(pPager)).FpageSize), iOff+int64(4))
|
|
if rc != SQLITE_OK {
|
|
return rc
|
|
}
|
|
rc = _write32bits(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, iOff+(*TPager)(unsafe.Pointer(pPager)).FpageSize+int64(4), cksum)
|
|
if rc != SQLITE_OK {
|
|
return rc
|
|
}
|
|
**(**Ti64)(__ccgo_up(pPager + 96)) += int64(8) + (*TPager)(unsafe.Pointer(pPager)).FpageSize
|
|
(*TPager)(unsafe.Pointer(pPager)).FnRec = (*TPager)(unsafe.Pointer(pPager)).FnRec + 1
|
|
rc = _sqlite3BitvecSet(tls, (*TPager)(unsafe.Pointer(pPager)).FpInJournal, (*TPgHdr)(unsafe.Pointer(pPg)).Fpgno)
|
|
rc = rc | _addToSavepointBitvecs(tls, pPager, (*TPgHdr)(unsafe.Pointer(pPg)).Fpgno)
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is called before attempting a hot-journal rollback. It
|
|
// ** syncs the journal file to disk, then sets pPager->journalHdr to the
|
|
// ** size of the journal file so that the pager_playback() routine knows
|
|
// ** that the entire journal file has been synced.
|
|
// **
|
|
// ** Syncing a hot-journal to disk before attempting to roll it back ensures
|
|
// ** that if a power-failure occurs during the rollback, the process that
|
|
// ** attempts rollback following system recovery sees the same journal
|
|
// ** content as this process.
|
|
// **
|
|
// ** If everything goes as planned, SQLITE_OK is returned. Otherwise,
|
|
// ** an SQLite error code.
|
|
// */
|
|
func _pagerSyncHotJournal(tls *libc.TLS, pPager uintptr) (r int32) {
|
|
var rc int32
|
|
_ = rc
|
|
rc = SQLITE_OK
|
|
if !((*TPager)(unsafe.Pointer(pPager)).FnoSync != 0) {
|
|
rc = _sqlite3OsSync(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, int32(SQLITE_SYNC_NORMAL))
|
|
}
|
|
if rc == SQLITE_OK {
|
|
rc = _sqlite3OsFileSize(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, pPager+104)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Update the value of the change-counter at offsets 24 and 92 in
|
|
// ** the header and the sqlite version number at offset 96.
|
|
// **
|
|
// ** This is an unconditional update. See also the pager_incr_changecounter()
|
|
// ** routine which only updates the change-counter if the update is actually
|
|
// ** needed, as determined by the pPager->changeCountDone state variable.
|
|
// */
|
|
func _pager_write_changecounter(tls *libc.TLS, pPg uintptr) {
|
|
var change_counter Tu32
|
|
_ = change_counter
|
|
if pPg == uintptr(0) {
|
|
return
|
|
}
|
|
/* Increment the value just read and write it back to byte 24. */
|
|
change_counter = _sqlite3Get4byte(tls, (*TPgHdr)(unsafe.Pointer(pPg)).FpPager+136) + uint32(1)
|
|
_sqlite3Put4byte(tls, (*TPgHdr)(unsafe.Pointer(pPg)).FpData+uintptr(24), change_counter)
|
|
/* Also store the SQLite version number in bytes 96..99 and in
|
|
** bytes 92..95 store the change counter for which the version number
|
|
** is valid. */
|
|
_sqlite3Put4byte(tls, (*TPgHdr)(unsafe.Pointer(pPg)).FpData+uintptr(92), change_counter)
|
|
_sqlite3Put4byte(tls, (*TPgHdr)(unsafe.Pointer(pPg)).FpData+uintptr(96), uint32(SQLITE_VERSION_NUMBER))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Return an integer that is the maximum allowed stack size */
|
|
func _parserStackSizeLimit(tls *libc.TLS, pParse uintptr) (r int32) {
|
|
return **(**int32)(__ccgo_up((*TParse)(unsafe.Pointer(pParse)).Fdb + 136 + 12*4))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of the sqlite3_pcache.xDestroy method.
|
|
// **
|
|
// ** Destroy a cache allocated using pcache1Create().
|
|
// */
|
|
func _pcache1Destroy(tls *libc.TLS, p uintptr) {
|
|
var pCache, pGroup uintptr
|
|
_, _ = pCache, pGroup
|
|
pCache = p
|
|
pGroup = (*TPCache1)(unsafe.Pointer(pCache)).FpGroup
|
|
Xsqlite3_mutex_enter(tls, (*TPGroup)(unsafe.Pointer(pGroup)).Fmutex)
|
|
if (*TPCache1)(unsafe.Pointer(pCache)).FnPage != 0 {
|
|
_pcache1TruncateUnsafe(tls, pCache, uint32(0))
|
|
}
|
|
**(**uint32)(__ccgo_up(pGroup + 8)) -= (*TPCache1)(unsafe.Pointer(pCache)).FnMax
|
|
**(**uint32)(__ccgo_up(pGroup + 12)) -= (*TPCache1)(unsafe.Pointer(pCache)).FnMin
|
|
(*TPGroup)(unsafe.Pointer(pGroup)).FmxPinned = (*TPGroup)(unsafe.Pointer(pGroup)).FnMaxPage + uint32(10) - (*TPGroup)(unsafe.Pointer(pGroup)).FnMinPage
|
|
_pcache1EnforceMaxPage(tls, pCache)
|
|
Xsqlite3_mutex_leave(tls, (*TPGroup)(unsafe.Pointer(pGroup)).Fmutex)
|
|
Xsqlite3_free(tls, (*TPCache1)(unsafe.Pointer(pCache)).FpBulk)
|
|
Xsqlite3_free(tls, (*TPCache1)(unsafe.Pointer(pCache)).FapHash)
|
|
Xsqlite3_free(tls, pCache)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of the sqlite3_pcache.xFetch method.
|
|
// **
|
|
// ** Fetch a page by key value.
|
|
// **
|
|
// ** Whether or not a new page may be allocated by this function depends on
|
|
// ** the value of the createFlag argument. 0 means do not allocate a new
|
|
// ** page. 1 means allocate a new page if space is easily available. 2
|
|
// ** means to try really hard to allocate a new page.
|
|
// **
|
|
// ** For a non-purgeable cache (a cache used as the storage for an in-memory
|
|
// ** database) there is really no difference between createFlag 1 and 2. So
|
|
// ** the calling function (pcache.c) will never have a createFlag of 1 on
|
|
// ** a non-purgeable cache.
|
|
// **
|
|
// ** There are three different approaches to obtaining space for a page,
|
|
// ** depending on the value of parameter createFlag (which may be 0, 1 or 2).
|
|
// **
|
|
// ** 1. Regardless of the value of createFlag, the cache is searched for a
|
|
// ** copy of the requested page. If one is found, it is returned.
|
|
// **
|
|
// ** 2. If createFlag==0 and the page is not already in the cache, NULL is
|
|
// ** returned.
|
|
// **
|
|
// ** 3. If createFlag is 1, and the page is not already in the cache, then
|
|
// ** return NULL (do not allocate a new page) if any of the following
|
|
// ** conditions are true:
|
|
// **
|
|
// ** (a) the number of pages pinned by the cache is greater than
|
|
// ** PCache1.nMax, or
|
|
// **
|
|
// ** (b) the number of pages pinned by the cache is greater than
|
|
// ** the sum of nMax for all purgeable caches, less the sum of
|
|
// ** nMin for all other purgeable caches, or
|
|
// **
|
|
// ** 4. If none of the first three conditions apply and the cache is marked
|
|
// ** as purgeable, and if one of the following is true:
|
|
// **
|
|
// ** (a) The number of pages allocated for the cache is already
|
|
// ** PCache1.nMax, or
|
|
// **
|
|
// ** (b) The number of pages allocated for all purgeable caches is
|
|
// ** already equal to or greater than the sum of nMax for all
|
|
// ** purgeable caches,
|
|
// **
|
|
// ** (c) The system is under memory pressure and wants to avoid
|
|
// ** unnecessary pages cache entry allocations
|
|
// **
|
|
// ** then attempt to recycle a page from the LRU list. If it is the right
|
|
// ** size, return the recycled buffer. Otherwise, free the buffer and
|
|
// ** proceed to step 5.
|
|
// **
|
|
// ** 5. Otherwise, allocate and return a new page buffer.
|
|
// **
|
|
// ** There are two versions of this routine. pcache1FetchWithMutex() is
|
|
// ** the general case. pcache1FetchNoMutex() is a faster implementation for
|
|
// ** the common case where pGroup->mutex is NULL. The pcache1Fetch() wrapper
|
|
// ** invokes the appropriate routine.
|
|
// */
|
|
func _pcache1FetchNoMutex(tls *libc.TLS, p uintptr, iKey uint32, createFlag int32) (r uintptr) {
|
|
var pCache, pPage uintptr
|
|
_, _ = pCache, pPage
|
|
pCache = p
|
|
pPage = uintptr(0)
|
|
/* Step 1: Search the hash table for an existing entry. */
|
|
pPage = **(**uintptr)(__ccgo_up((*TPCache1)(unsafe.Pointer(pCache)).FapHash + uintptr(iKey%(*TPCache1)(unsafe.Pointer(pCache)).FnHash)*8))
|
|
for pPage != 0 && (*TPgHdr1)(unsafe.Pointer(pPage)).FiKey != iKey {
|
|
pPage = (*TPgHdr1)(unsafe.Pointer(pPage)).FpNext
|
|
}
|
|
/* Step 2: If the page was found in the hash table, then return it.
|
|
** If the page was not in the hash table and createFlag is 0, abort.
|
|
** Otherwise (page not in hash and createFlag!=0) continue with
|
|
** subsequent steps to try to create the page. */
|
|
if pPage != 0 {
|
|
if (*TPgHdr1)(unsafe.Pointer(pPage)).FpLruNext != uintptr(0) {
|
|
return _pcache1PinPage(tls, pPage)
|
|
} else {
|
|
return pPage
|
|
}
|
|
} else {
|
|
if createFlag != 0 {
|
|
/* Steps 3, 4, and 5 implemented by this subroutine */
|
|
return _pcache1FetchStage2(tls, pCache, iKey, createFlag)
|
|
} else {
|
|
return uintptr(0)
|
|
}
|
|
}
|
|
return r
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free an allocated buffer obtained from pcache1Alloc().
|
|
// */
|
|
func _pcache1Free(tls *libc.TLS, p uintptr) {
|
|
var nFreed int32
|
|
var pSlot uintptr
|
|
_, _ = nFreed, pSlot
|
|
if p == uintptr(0) {
|
|
return
|
|
}
|
|
if uint64(p) >= uint64(_pcache1_g.FpStart) && uint64(p) < uint64(_pcache1_g.FpEnd) {
|
|
Xsqlite3_mutex_enter(tls, _pcache1_g.Fmutex)
|
|
_sqlite3StatusDown(tls, int32(SQLITE_STATUS_PAGECACHE_USED), int32(1))
|
|
pSlot = p
|
|
(*TPgFreeslot)(unsafe.Pointer(pSlot)).FpNext = _pcache1_g.FpFree
|
|
_pcache1_g.FpFree = pSlot
|
|
_pcache1_g.FnFreeSlot = _pcache1_g.FnFreeSlot + 1
|
|
libc.AtomicStoreNInt32(uintptr(unsafe.Pointer(&_pcache1_g))+140, libc.BoolInt32(_pcache1_g.FnFreeSlot < _pcache1_g.FnReserve), libc.Int32FromInt32(__ATOMIC_RELAXED))
|
|
Xsqlite3_mutex_leave(tls, _pcache1_g.Fmutex)
|
|
} else {
|
|
nFreed = 0
|
|
nFreed = _sqlite3MallocSize(tls, p)
|
|
Xsqlite3_mutex_enter(tls, _pcache1_g.Fmutex)
|
|
_sqlite3StatusDown(tls, int32(SQLITE_STATUS_PAGECACHE_OVERFLOW), nFreed)
|
|
Xsqlite3_mutex_leave(tls, _pcache1_g.Fmutex)
|
|
Xsqlite3_free(tls, p)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of the sqlite3_pcache.xRekey method.
|
|
// */
|
|
func _pcache1Rekey(tls *libc.TLS, p uintptr, pPg uintptr, iOld uint32, iNew uint32) {
|
|
var hNew, hOld uint32
|
|
var pCache, pPage, pp uintptr
|
|
_, _, _, _, _ = hNew, hOld, pCache, pPage, pp
|
|
pCache = p
|
|
pPage = pPg
|
|
/* The page number really is changing */
|
|
Xsqlite3_mutex_enter(tls, (*TPGroup)(unsafe.Pointer((*TPCache1)(unsafe.Pointer(pCache)).FpGroup)).Fmutex)
|
|
/* pPg really is iOld */
|
|
hOld = iOld % (*TPCache1)(unsafe.Pointer(pCache)).FnHash
|
|
pp = (*TPCache1)(unsafe.Pointer(pCache)).FapHash + uintptr(hOld)*8
|
|
for **(**uintptr)(__ccgo_up(pp)) != pPage {
|
|
pp = **(**uintptr)(__ccgo_up(pp)) + 24
|
|
}
|
|
**(**uintptr)(__ccgo_up(pp)) = (*TPgHdr1)(unsafe.Pointer(pPage)).FpNext
|
|
/* iNew not in cache */
|
|
hNew = iNew % (*TPCache1)(unsafe.Pointer(pCache)).FnHash
|
|
(*TPgHdr1)(unsafe.Pointer(pPage)).FiKey = iNew
|
|
(*TPgHdr1)(unsafe.Pointer(pPage)).FpNext = **(**uintptr)(__ccgo_up((*TPCache1)(unsafe.Pointer(pCache)).FapHash + uintptr(hNew)*8))
|
|
**(**uintptr)(__ccgo_up((*TPCache1)(unsafe.Pointer(pCache)).FapHash + uintptr(hNew)*8)) = pPage
|
|
if iNew > (*TPCache1)(unsafe.Pointer(pCache)).FiMaxKey {
|
|
(*TPCache1)(unsafe.Pointer(pCache)).FiMaxKey = iNew
|
|
}
|
|
Xsqlite3_mutex_leave(tls, (*TPGroup)(unsafe.Pointer((*TPCache1)(unsafe.Pointer(pCache)).FpGroup)).Fmutex)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Remove the page supplied as an argument from the hash table
|
|
// ** (PCache1.apHash structure) that it is currently stored in.
|
|
// ** Also free the page if freePage is true.
|
|
// **
|
|
// ** The PGroup mutex must be held when this function is called.
|
|
// */
|
|
func _pcache1RemoveFromHash(tls *libc.TLS, pPage uintptr, freeFlag int32) {
|
|
var h uint32
|
|
var pCache, pp uintptr
|
|
_, _, _ = h, pCache, pp
|
|
pCache = (*TPgHdr1)(unsafe.Pointer(pPage)).FpCache
|
|
h = (*TPgHdr1)(unsafe.Pointer(pPage)).FiKey % (*TPCache1)(unsafe.Pointer(pCache)).FnHash
|
|
pp = (*TPCache1)(unsafe.Pointer(pCache)).FapHash + uintptr(h)*8
|
|
for {
|
|
if !(**(**uintptr)(__ccgo_up(pp)) != pPage) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pp = **(**uintptr)(__ccgo_up(pp)) + 24
|
|
}
|
|
**(**uintptr)(__ccgo_up(pp)) = (*TPgHdr1)(unsafe.Pointer(**(**uintptr)(__ccgo_up(pp)))).FpNext
|
|
(*TPCache1)(unsafe.Pointer(pCache)).FnPage = (*TPCache1)(unsafe.Pointer(pCache)).FnPage - 1
|
|
if freeFlag != 0 {
|
|
_pcache1FreePage(tls, pPage)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is used to resize the hash table used by the cache passed
|
|
// ** as the first argument.
|
|
// **
|
|
// ** The PCache mutex must be held when this function is called.
|
|
// */
|
|
func _pcache1ResizeHash(tls *libc.TLS, p uintptr) {
|
|
var apNew, pNext, pPage, v2 uintptr
|
|
var h uint32
|
|
var i Tu32
|
|
var nNew Tu64
|
|
_, _, _, _, _, _, _ = apNew, h, i, nNew, pNext, pPage, v2
|
|
nNew = uint64(2) * uint64((*TPCache1)(unsafe.Pointer(p)).FnHash)
|
|
if nNew < uint64(256) {
|
|
nNew = uint64(256)
|
|
}
|
|
Xsqlite3_mutex_leave(tls, (*TPGroup)(unsafe.Pointer((*TPCache1)(unsafe.Pointer(p)).FpGroup)).Fmutex)
|
|
if (*TPCache1)(unsafe.Pointer(p)).FnHash != 0 {
|
|
_sqlite3BeginBenignMalloc(tls)
|
|
}
|
|
apNew = _sqlite3MallocZero(tls, uint64(8)*nNew)
|
|
if (*TPCache1)(unsafe.Pointer(p)).FnHash != 0 {
|
|
_sqlite3EndBenignMalloc(tls)
|
|
}
|
|
Xsqlite3_mutex_enter(tls, (*TPGroup)(unsafe.Pointer((*TPCache1)(unsafe.Pointer(p)).FpGroup)).Fmutex)
|
|
if apNew != 0 {
|
|
i = uint32(0)
|
|
for {
|
|
if !(i < (*TPCache1)(unsafe.Pointer(p)).FnHash) {
|
|
break
|
|
}
|
|
pNext = **(**uintptr)(__ccgo_up((*TPCache1)(unsafe.Pointer(p)).FapHash + uintptr(i)*8))
|
|
for {
|
|
v2 = pNext
|
|
pPage = v2
|
|
if !(v2 != uintptr(0)) {
|
|
break
|
|
}
|
|
h = uint32(uint64((*TPgHdr1)(unsafe.Pointer(pPage)).FiKey) % nNew)
|
|
pNext = (*TPgHdr1)(unsafe.Pointer(pPage)).FpNext
|
|
(*TPgHdr1)(unsafe.Pointer(pPage)).FpNext = **(**uintptr)(__ccgo_up(apNew + uintptr(h)*8))
|
|
**(**uintptr)(__ccgo_up(apNew + uintptr(h)*8)) = pPage
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
Xsqlite3_free(tls, (*TPCache1)(unsafe.Pointer(p)).FapHash)
|
|
(*TPCache1)(unsafe.Pointer(p)).FapHash = apNew
|
|
(*TPCache1)(unsafe.Pointer(p)).FnHash = uint32(nNew)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Discard all pages from cache pCache with a page number (key value)
|
|
// ** greater than or equal to iLimit. Any pinned pages that meet this
|
|
// ** criteria are unpinned before they are discarded.
|
|
// **
|
|
// ** The PCache mutex must be held when this function is called.
|
|
// */
|
|
func _pcache1TruncateUnsafe(tls *libc.TLS, pCache uintptr, iLimit uint32) {
|
|
var h, iStop uint32
|
|
var pPage, pp, v2 uintptr
|
|
_, _, _, _, _ = h, iStop, pPage, pp, v2
|
|
if (*TPCache1)(unsafe.Pointer(pCache)).FiMaxKey-iLimit < (*TPCache1)(unsafe.Pointer(pCache)).FnHash {
|
|
/* If we are just shaving the last few pages off the end of the
|
|
** cache, then there is no point in scanning the entire hash table.
|
|
** Only scan those hash slots that might contain pages that need to
|
|
** be removed. */
|
|
h = iLimit % (*TPCache1)(unsafe.Pointer(pCache)).FnHash
|
|
iStop = (*TPCache1)(unsafe.Pointer(pCache)).FiMaxKey % (*TPCache1)(unsafe.Pointer(pCache)).FnHash
|
|
/* Disable the pCache->nPage validity check */
|
|
} else {
|
|
/* This is the general case where many pages are being removed.
|
|
** It is necessary to scan the entire hash table */
|
|
h = (*TPCache1)(unsafe.Pointer(pCache)).FnHash / uint32(2)
|
|
iStop = h - uint32(1)
|
|
}
|
|
for {
|
|
pp = (*TPCache1)(unsafe.Pointer(pCache)).FapHash + uintptr(h)*8
|
|
for {
|
|
v2 = **(**uintptr)(__ccgo_up(pp))
|
|
pPage = v2
|
|
if !(v2 != uintptr(0)) {
|
|
break
|
|
}
|
|
if (*TPgHdr1)(unsafe.Pointer(pPage)).FiKey >= iLimit {
|
|
(*TPCache1)(unsafe.Pointer(pCache)).FnPage = (*TPCache1)(unsafe.Pointer(pCache)).FnPage - 1
|
|
**(**uintptr)(__ccgo_up(pp)) = (*TPgHdr1)(unsafe.Pointer(pPage)).FpNext
|
|
if (*TPgHdr1)(unsafe.Pointer(pPage)).FpLruNext != uintptr(0) {
|
|
_pcache1PinPage(tls, pPage)
|
|
}
|
|
_pcache1FreePage(tls, pPage)
|
|
} else {
|
|
pp = pPage + 24
|
|
}
|
|
}
|
|
if h == iStop {
|
|
break
|
|
}
|
|
h = (h + uint32(1)) % (*TPCache1)(unsafe.Pointer(pCache)).FnHash
|
|
goto _1
|
|
_1:
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/******** sqlite3_pcache Methods **********************************************/
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return true if it desirable to avoid allocating a new page cache
|
|
// ** entry.
|
|
// **
|
|
// ** If memory was allocated specifically to the page cache using
|
|
// ** SQLITE_CONFIG_PAGECACHE but that memory has all been used, then
|
|
// ** it is desirable to avoid allocating a new page cache entry because
|
|
// ** presumably SQLITE_CONFIG_PAGECACHE was suppose to be sufficient
|
|
// ** for all page cache needs and we should not need to spill the
|
|
// ** allocation onto the heap.
|
|
// **
|
|
// ** Or, the heap is used for all page cache memory but the heap is
|
|
// ** under memory pressure, then again it is desirable to avoid
|
|
// ** allocating a new page cache entry in order to avoid stressing
|
|
// ** the heap even further.
|
|
// */
|
|
func _pcache1UnderMemoryPressure(tls *libc.TLS, pCache uintptr) (r int32) {
|
|
if _pcache1_g.FnSlot != 0 && (*TPCache1)(unsafe.Pointer(pCache)).FszPage+(*TPCache1)(unsafe.Pointer(pCache)).FszExtra <= _pcache1_g.FszSlot {
|
|
return libc.AtomicLoadNInt32(uintptr(unsafe.Pointer(&_pcache1_g))+140, libc.Int32FromInt32(__ATOMIC_RELAXED))
|
|
} else {
|
|
return _sqlite3HeapNearlyFull(tls)
|
|
}
|
|
return r
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/******** General Implementation Functions ************************************/
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of the sqlite3_pcache.xUnpin method.
|
|
// **
|
|
// ** Mark a page as unpinned (eligible for asynchronous recycling).
|
|
// */
|
|
func _pcache1Unpin(tls *libc.TLS, p uintptr, pPg uintptr, reuseUnlikely int32) {
|
|
var pCache, pGroup, pPage, ppFirst, v1 uintptr
|
|
_, _, _, _, _ = pCache, pGroup, pPage, ppFirst, v1
|
|
pCache = p
|
|
pPage = pPg
|
|
pGroup = (*TPCache1)(unsafe.Pointer(pCache)).FpGroup
|
|
Xsqlite3_mutex_enter(tls, (*TPGroup)(unsafe.Pointer(pGroup)).Fmutex)
|
|
/* It is an error to call this function if the page is already
|
|
** part of the PGroup LRU list.
|
|
*/
|
|
if reuseUnlikely != 0 || (*TPGroup)(unsafe.Pointer(pGroup)).FnPurgeable > (*TPGroup)(unsafe.Pointer(pGroup)).FnMaxPage {
|
|
_pcache1RemoveFromHash(tls, pPage, int32(1))
|
|
} else {
|
|
/* Add the page to the PGroup LRU list. */
|
|
ppFirst = pGroup + 24 + 40
|
|
(*TPgHdr1)(unsafe.Pointer(pPage)).FpLruPrev = pGroup + 24
|
|
v1 = **(**uintptr)(__ccgo_up(ppFirst))
|
|
(*TPgHdr1)(unsafe.Pointer(pPage)).FpLruNext = v1
|
|
(*TPgHdr1)(unsafe.Pointer(v1)).FpLruPrev = pPage
|
|
**(**uintptr)(__ccgo_up(ppFirst)) = pPage
|
|
(*TPCache1)(unsafe.Pointer(pCache)).FnRecyclable = (*TPCache1)(unsafe.Pointer(pCache)).FnRecyclable + 1
|
|
}
|
|
Xsqlite3_mutex_leave(tls, (*TPGroup)(unsafe.Pointer((*TPCache1)(unsafe.Pointer(pCache)).FpGroup)).Fmutex)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Merge two lists of pages connected by pDirty and in pgno order.
|
|
// ** Do not bother fixing the pDirtyPrev pointers.
|
|
// */
|
|
func _pcacheMergeDirtyList(tls *libc.TLS, pA uintptr, pB uintptr) (r uintptr) {
|
|
bp := tls.Alloc(80)
|
|
defer tls.Free(80)
|
|
var pTail uintptr
|
|
var _ /* result at bp+0 */ TPgHdr
|
|
_ = pTail
|
|
pTail = bp
|
|
for {
|
|
if (*TPgHdr)(unsafe.Pointer(pA)).Fpgno < (*TPgHdr)(unsafe.Pointer(pB)).Fpgno {
|
|
(*TPgHdr)(unsafe.Pointer(pTail)).FpDirty = pA
|
|
pTail = pA
|
|
pA = (*TPgHdr)(unsafe.Pointer(pA)).FpDirty
|
|
if pA == uintptr(0) {
|
|
(*TPgHdr)(unsafe.Pointer(pTail)).FpDirty = pB
|
|
break
|
|
}
|
|
} else {
|
|
(*TPgHdr)(unsafe.Pointer(pTail)).FpDirty = pB
|
|
pTail = pB
|
|
pB = (*TPgHdr)(unsafe.Pointer(pB)).FpDirty
|
|
if pB == uintptr(0) {
|
|
(*TPgHdr)(unsafe.Pointer(pTail)).FpDirty = pA
|
|
break
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
}
|
|
return (**(**TPgHdr)(__ccgo_up(bp))).FpDirty
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Argument zFmt is a sqlite3_mprintf() style format string. The trailing
|
|
// ** arguments are the usual subsitution values. This function performs
|
|
// ** the printf() style substitutions and executes the result as an SQL
|
|
// ** statement on the RBU handles database.
|
|
// **
|
|
// ** If an error occurs, an error code and error message is stored in the
|
|
// ** RBU handle. If an error has already occurred when this function is
|
|
// ** called, it is a no-op.
|
|
// */
|
|
func _rbuMPrintfExec(tls *libc.TLS, p uintptr, db uintptr, zFmt uintptr, va uintptr) (r int32) {
|
|
var ap Tva_list
|
|
var zSql uintptr
|
|
_, _ = ap, zSql
|
|
ap = va
|
|
zSql = Xsqlite3_vmprintf(tls, zFmt, ap)
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK {
|
|
if zSql == uintptr(0) {
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = int32(SQLITE_NOMEM)
|
|
} else {
|
|
(*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = Xsqlite3_exec(tls, db, zSql, uintptr(0), uintptr(0), p+64)
|
|
}
|
|
}
|
|
Xsqlite3_free(tls, zSql)
|
|
_ = ap
|
|
return (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Remove an item from the main-db lists.
|
|
// */
|
|
func _rbuMainlistRemove(tls *libc.TLS, p uintptr) {
|
|
var pp uintptr
|
|
_ = pp
|
|
Xsqlite3_mutex_enter(tls, (*Trbu_vfs)(unsafe.Pointer((*Trbu_file)(unsafe.Pointer(p)).FpRbuVfs)).Fmutex)
|
|
pp = (*Trbu_file)(unsafe.Pointer(p)).FpRbuVfs + 192
|
|
for {
|
|
if !(**(**uintptr)(__ccgo_up(pp)) != 0 && **(**uintptr)(__ccgo_up(pp)) != p) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pp = **(**uintptr)(__ccgo_up(pp)) + 88
|
|
}
|
|
if **(**uintptr)(__ccgo_up(pp)) != 0 {
|
|
**(**uintptr)(__ccgo_up(pp)) = (*Trbu_file)(unsafe.Pointer(p)).FpMainNext
|
|
}
|
|
(*Trbu_file)(unsafe.Pointer(p)).FpMainNext = uintptr(0)
|
|
pp = (*Trbu_file)(unsafe.Pointer(p)).FpRbuVfs + 200
|
|
for {
|
|
if !(**(**uintptr)(__ccgo_up(pp)) != 0 && **(**uintptr)(__ccgo_up(pp)) != p) {
|
|
break
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
pp = **(**uintptr)(__ccgo_up(pp)) + 96
|
|
}
|
|
if **(**uintptr)(__ccgo_up(pp)) != 0 {
|
|
**(**uintptr)(__ccgo_up(pp)) = (*Trbu_file)(unsafe.Pointer(p)).FpMainRbuNext
|
|
}
|
|
(*Trbu_file)(unsafe.Pointer(p)).FpMainRbuNext = uintptr(0)
|
|
Xsqlite3_mutex_leave(tls, (*Trbu_vfs)(unsafe.Pointer((*Trbu_file)(unsafe.Pointer(p)).FpRbuVfs)).Fmutex)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free the RbuObjIter.azTblCol[] and RbuObjIter.abTblPk[] arrays allocated
|
|
// ** by an earlier call to rbuObjIterCacheTableInfo().
|
|
// */
|
|
func _rbuObjIterFreeCols(tls *libc.TLS, pIter uintptr) {
|
|
var i int32
|
|
_ = i
|
|
i = 0
|
|
for {
|
|
if !(i < (*TRbuObjIter)(unsafe.Pointer(pIter)).FnTblCol) {
|
|
break
|
|
}
|
|
Xsqlite3_free(tls, **(**uintptr)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FazTblCol + uintptr(i)*8)))
|
|
Xsqlite3_free(tls, **(**uintptr)(__ccgo_up((*TRbuObjIter)(unsafe.Pointer(pIter)).FazTblType + uintptr(i)*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
Xsqlite3_free(tls, (*TRbuObjIter)(unsafe.Pointer(pIter)).FazTblCol)
|
|
(*TRbuObjIter)(unsafe.Pointer(pIter)).FazTblCol = uintptr(0)
|
|
(*TRbuObjIter)(unsafe.Pointer(pIter)).FazTblType = uintptr(0)
|
|
(*TRbuObjIter)(unsafe.Pointer(pIter)).FaiSrcOrder = uintptr(0)
|
|
(*TRbuObjIter)(unsafe.Pointer(pIter)).FabTblPk = uintptr(0)
|
|
(*TRbuObjIter)(unsafe.Pointer(pIter)).FabNotNull = uintptr(0)
|
|
(*TRbuObjIter)(unsafe.Pointer(pIter)).FnTblCol = 0
|
|
(*TRbuObjIter)(unsafe.Pointer(pIter)).FeType = 0 /* Invalid value */
|
|
}
|
|
|
|
func _rbuTmpInsertFunc(tls *libc.TLS, pCtx uintptr, nVal int32, apVal uintptr) {
|
|
var i, rc int32
|
|
var p uintptr
|
|
_, _, _ = i, p, rc
|
|
p = Xsqlite3_user_data(tls, pCtx)
|
|
rc = SQLITE_OK
|
|
if Xsqlite3_value_int(tls, **(**uintptr)(__ccgo_up(apVal))) != 0 {
|
|
**(**Ti64)(__ccgo_up(p + 312)) += int64((*Tsqlite3rbu)(unsafe.Pointer(p)).Fobjiter.FnIndex)
|
|
}
|
|
i = 0
|
|
for {
|
|
if !(rc == SQLITE_OK && i < nVal) {
|
|
break
|
|
}
|
|
rc = Xsqlite3_bind_value(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).Fobjiter.FpTmpInsert, i+int32(1), **(**uintptr)(__ccgo_up(apVal + uintptr(i)*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if rc == SQLITE_OK {
|
|
Xsqlite3_step(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).Fobjiter.FpTmpInsert)
|
|
rc = Xsqlite3_reset(tls, (*Tsqlite3rbu)(unsafe.Pointer(p)).Fobjiter.FpTmpInsert)
|
|
}
|
|
if rc != SQLITE_OK {
|
|
Xsqlite3_result_error_code(tls, pCtx, rc)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// */
|
|
func _rbuUpdateTempSize(tls *libc.TLS, pFd uintptr, nNew Tsqlite3_int64) (r int32) {
|
|
var nDiff Ti64
|
|
var pRbu uintptr
|
|
_, _ = nDiff, pRbu
|
|
pRbu = (*Trbu_file)(unsafe.Pointer(pFd)).FpRbu
|
|
nDiff = nNew - (*Trbu_file)(unsafe.Pointer(pFd)).Fsz
|
|
**(**Ti64)(__ccgo_up(pRbu + 384)) += nDiff
|
|
(*Trbu_file)(unsafe.Pointer(pFd)).Fsz = nNew
|
|
if (*Tsqlite3rbu)(unsafe.Pointer(pRbu)).FszTempLimit != 0 && (*Tsqlite3rbu)(unsafe.Pointer(pRbu)).FszTemp > (*Tsqlite3rbu)(unsafe.Pointer(pRbu)).FszTempLimit {
|
|
return int32(SQLITE_FULL)
|
|
}
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Close an rbu file.
|
|
// */
|
|
func _rbuVfsClose(tls *libc.TLS, pFile uintptr) (r int32) {
|
|
var i, rc int32
|
|
var p, pMeth uintptr
|
|
_, _, _, _ = i, p, pMeth, rc
|
|
p = pFile
|
|
/* Free the contents of the apShm[] array. And the array itself. */
|
|
i = 0
|
|
for {
|
|
if !(i < (*Trbu_file)(unsafe.Pointer(p)).FnShm) {
|
|
break
|
|
}
|
|
Xsqlite3_free(tls, **(**uintptr)(__ccgo_up((*Trbu_file)(unsafe.Pointer(p)).FapShm + uintptr(i)*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
Xsqlite3_free(tls, (*Trbu_file)(unsafe.Pointer(p)).FapShm)
|
|
(*Trbu_file)(unsafe.Pointer(p)).FapShm = uintptr(0)
|
|
Xsqlite3_free(tls, (*Trbu_file)(unsafe.Pointer(p)).FzDel)
|
|
if (*Trbu_file)(unsafe.Pointer(p)).FopenFlags&int32(SQLITE_OPEN_MAIN_DB) != 0 {
|
|
pMeth = (*Tsqlite3_file)(unsafe.Pointer((*Trbu_file)(unsafe.Pointer(p)).FpReal)).FpMethods
|
|
_rbuMainlistRemove(tls, p)
|
|
_rbuUnlockShm(tls, p)
|
|
if (*Tsqlite3_io_methods)(unsafe.Pointer(pMeth)).FiVersion > int32(1) && (*Tsqlite3_io_methods)(unsafe.Pointer(pMeth)).FxShmUnmap != 0 {
|
|
(*(*func(*libc.TLS, uintptr, int32) int32)(unsafe.Pointer(&struct{ uintptr }{(*Tsqlite3_io_methods)(unsafe.Pointer(pMeth)).FxShmUnmap})))(tls, (*Trbu_file)(unsafe.Pointer(p)).FpReal, 0)
|
|
}
|
|
} else {
|
|
if (*Trbu_file)(unsafe.Pointer(p)).FopenFlags&int32(SQLITE_OPEN_DELETEONCLOSE) != 0 && (*Trbu_file)(unsafe.Pointer(p)).FpRbu != 0 {
|
|
_rbuUpdateTempSize(tls, p, 0)
|
|
}
|
|
}
|
|
/* Close the underlying file handle */
|
|
rc = (*(*func(*libc.TLS, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{(*Tsqlite3_io_methods)(unsafe.Pointer((*Tsqlite3_file)(unsafe.Pointer((*Trbu_file)(unsafe.Pointer(p)).FpReal)).FpMethods)).FxClose})))(tls, (*Trbu_file)(unsafe.Pointer(p)).FpReal)
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free all structures in the Pager.aSavepoint[] array and set both
|
|
// ** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal
|
|
// ** if it is open and the pager is not in exclusive mode.
|
|
// */
|
|
func _releaseAllSavepoints(tls *libc.TLS, pPager uintptr) {
|
|
var ii int32
|
|
_ = ii /* Iterator for looping through Pager.aSavepoint */
|
|
ii = 0
|
|
for {
|
|
if !(ii < (*TPager)(unsafe.Pointer(pPager)).FnSavepoint) {
|
|
break
|
|
}
|
|
_sqlite3BitvecDestroy(tls, (**(**TPagerSavepoint)(__ccgo_up((*TPager)(unsafe.Pointer(pPager)).FaSavepoint + uintptr(ii)*56))).FpInSavepoint)
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
if !((*TPager)(unsafe.Pointer(pPager)).FexclusiveMode != 0) || _sqlite3JournalIsInMemory(tls, (*TPager)(unsafe.Pointer(pPager)).Fsjfd) != 0 {
|
|
_sqlite3OsClose(tls, (*TPager)(unsafe.Pointer(pPager)).Fsjfd)
|
|
}
|
|
Xsqlite3_free(tls, (*TPager)(unsafe.Pointer(pPager)).FaSavepoint)
|
|
(*TPager)(unsafe.Pointer(pPager)).FaSavepoint = uintptr(0)
|
|
(*TPager)(unsafe.Pointer(pPager)).FnSavepoint = 0
|
|
(*TPager)(unsafe.Pointer(pPager)).FnSubRec = uint32(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Remove a single entry from the hash table given a pointer to that
|
|
// ** element and a hash on the element's key.
|
|
// */
|
|
func _removeElement(tls *libc.TLS, pH uintptr, elem uintptr) {
|
|
var pEntry uintptr
|
|
_ = pEntry
|
|
if (*THashElem)(unsafe.Pointer(elem)).Fprev != 0 {
|
|
(*THashElem)(unsafe.Pointer((*THashElem)(unsafe.Pointer(elem)).Fprev)).Fnext = (*THashElem)(unsafe.Pointer(elem)).Fnext
|
|
} else {
|
|
(*THash)(unsafe.Pointer(pH)).Ffirst = (*THashElem)(unsafe.Pointer(elem)).Fnext
|
|
}
|
|
if (*THashElem)(unsafe.Pointer(elem)).Fnext != 0 {
|
|
(*THashElem)(unsafe.Pointer((*THashElem)(unsafe.Pointer(elem)).Fnext)).Fprev = (*THashElem)(unsafe.Pointer(elem)).Fprev
|
|
}
|
|
if (*THash)(unsafe.Pointer(pH)).Fht != 0 {
|
|
pEntry = (*THash)(unsafe.Pointer(pH)).Fht + uintptr((*THashElem)(unsafe.Pointer(elem)).Fh%(*THash)(unsafe.Pointer(pH)).Fhtsize)*16
|
|
if (*T_ht)(unsafe.Pointer(pEntry)).Fchain == elem {
|
|
(*T_ht)(unsafe.Pointer(pEntry)).Fchain = (*THashElem)(unsafe.Pointer(elem)).Fnext
|
|
}
|
|
(*T_ht)(unsafe.Pointer(pEntry)).Fcount = (*T_ht)(unsafe.Pointer(pEntry)).Fcount - 1
|
|
}
|
|
Xsqlite3_free(tls, elem)
|
|
(*THash)(unsafe.Pointer(pH)).Fcount = (*THash)(unsafe.Pointer(pH)).Fcount - 1
|
|
if (*THash)(unsafe.Pointer(pH)).Fcount == uint32(0) {
|
|
_sqlite3HashClear(tls, pH)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Remove connection db from the blocked connections list. If connection
|
|
// ** db is not currently a part of the list, this function is a no-op.
|
|
// */
|
|
func _removeFromBlockedList(tls *libc.TLS, db uintptr) {
|
|
var pp uintptr
|
|
_ = pp
|
|
pp = uintptr(unsafe.Pointer(&_sqlite3BlockedList))
|
|
for {
|
|
if !(**(**uintptr)(__ccgo_up(pp)) != 0) {
|
|
break
|
|
}
|
|
if **(**uintptr)(__ccgo_up(pp)) == db {
|
|
**(**uintptr)(__ccgo_up(pp)) = (*Tsqlite3)(unsafe.Pointer(**(**uintptr)(__ccgo_up(pp)))).FpNextBlocked
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pp = **(**uintptr)(__ccgo_up(pp)) + 856
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** For each name in the the expression-list pEList (i.e. each
|
|
// ** pEList->a[i].zName) that matches the string in zOld, extract the
|
|
// ** corresponding rename-token from Parse object pParse and add it
|
|
// ** to the RenameCtx pCtx.
|
|
// */
|
|
func _renameColumnElistNames(tls *libc.TLS, pParse uintptr, pCtx uintptr, pEList uintptr, zOld uintptr) {
|
|
var i int32
|
|
var zName uintptr
|
|
_, _ = i, zName
|
|
if pEList != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TExprList)(unsafe.Pointer(pEList)).FnExpr) {
|
|
break
|
|
}
|
|
zName = (*(*TExprList_item)(unsafe.Pointer(pEList + 8 + uintptr(i)*32))).FzEName
|
|
if int32(uint32(*(*uint16)(unsafe.Pointer(pEList + 8 + uintptr(i)*32 + 16 + 4))&0x3>>0)) == ENAME_NAME && zName != uintptr(0) && 0 == Xsqlite3_stricmp(tls, zName, zOld) {
|
|
_renameTokenFind(tls, pParse, pCtx, zName)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** For each name in the the id-list pIdList (i.e. each pIdList->a[i].zName)
|
|
// ** that matches the string in zOld, extract the corresponding rename-token
|
|
// ** from Parse object pParse and add it to the RenameCtx pCtx.
|
|
// */
|
|
func _renameColumnIdlistNames(tls *libc.TLS, pParse uintptr, pCtx uintptr, pIdList uintptr, zOld uintptr) {
|
|
var i int32
|
|
var zName uintptr
|
|
_, _ = i, zName
|
|
if pIdList != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TIdList)(unsafe.Pointer(pIdList)).FnId) {
|
|
break
|
|
}
|
|
zName = (*(*TIdList_item)(unsafe.Pointer(pIdList + 8 + uintptr(i)*8))).FzName
|
|
if 0 == Xsqlite3_stricmp(tls, zName, zOld) {
|
|
_renameTokenFind(tls, pParse, pCtx, zName)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The RenameCtx contains a list of tokens that reference a column that
|
|
// ** is being renamed by an ALTER TABLE statement. Return the "last"
|
|
// ** RenameToken in the RenameCtx and remove that RenameToken from the
|
|
// ** RenameContext. "Last" means the last RenameToken encountered when
|
|
// ** the input SQL is parsed from left to right. Repeated calls to this routine
|
|
// ** return all column name tokens in the order that they are encountered
|
|
// ** in the SQL statement.
|
|
// */
|
|
func _renameColumnTokenNext(tls *libc.TLS, pCtx uintptr) (r uintptr) {
|
|
var pBest, pToken, pp uintptr
|
|
_, _, _ = pBest, pToken, pp
|
|
pBest = (*TRenameCtx)(unsafe.Pointer(pCtx)).FpList
|
|
pToken = (*TRenameToken)(unsafe.Pointer(pBest)).FpNext
|
|
for {
|
|
if !(pToken != 0) {
|
|
break
|
|
}
|
|
if (*TRenameToken)(unsafe.Pointer(pToken)).Ft.Fz > (*TRenameToken)(unsafe.Pointer(pBest)).Ft.Fz {
|
|
pBest = pToken
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pToken = (*TRenameToken)(unsafe.Pointer(pToken)).FpNext
|
|
}
|
|
pp = pCtx
|
|
for {
|
|
if !(**(**uintptr)(__ccgo_up(pp)) != pBest) {
|
|
break
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
pp = **(**uintptr)(__ccgo_up(pp)) + 24
|
|
}
|
|
**(**uintptr)(__ccgo_up(pp)) = (*TRenameToken)(unsafe.Pointer(pBest)).FpNext
|
|
return pBest
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Search the Parse object passed as the first argument for a RenameToken
|
|
// ** object associated with parse tree element pPtr. If found, return a pointer
|
|
// ** to it. Otherwise, return NULL.
|
|
// **
|
|
// ** If the second argument passed to this function is not NULL and a matching
|
|
// ** RenameToken object is found, remove it from the Parse object and add it to
|
|
// ** the list maintained by the RenameCtx object.
|
|
// */
|
|
func _renameTokenFind(tls *libc.TLS, pParse uintptr, pCtx uintptr, pPtr uintptr) (r uintptr) {
|
|
var pToken, pp uintptr
|
|
_, _ = pToken, pp
|
|
if pPtr == uintptr(0) {
|
|
return uintptr(0)
|
|
}
|
|
pp = pParse + 416
|
|
for {
|
|
if !(**(**uintptr)(__ccgo_up(pp)) != 0) {
|
|
break
|
|
}
|
|
if (*TRenameToken)(unsafe.Pointer(**(**uintptr)(__ccgo_up(pp)))).Fp == pPtr {
|
|
pToken = **(**uintptr)(__ccgo_up(pp))
|
|
if pCtx != 0 {
|
|
**(**uintptr)(__ccgo_up(pp)) = (*TRenameToken)(unsafe.Pointer(pToken)).FpNext
|
|
(*TRenameToken)(unsafe.Pointer(pToken)).FpNext = (*TRenameCtx)(unsafe.Pointer(pCtx)).FpList
|
|
(*TRenameCtx)(unsafe.Pointer(pCtx)).FpList = pToken
|
|
(*TRenameCtx)(unsafe.Pointer(pCtx)).FnList = (*TRenameCtx)(unsafe.Pointer(pCtx)).FnList + 1
|
|
}
|
|
return pToken
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pp = **(**uintptr)(__ccgo_up(pp)) + 24
|
|
}
|
|
return uintptr(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Invoke sqlite3WalkExpr() or sqlite3WalkSelect() on all Select or Expr
|
|
// ** objects that are part of the trigger passed as the second argument.
|
|
// */
|
|
func _renameWalkTrigger(tls *libc.TLS, pWalker uintptr, pTrigger uintptr) {
|
|
var i int32
|
|
var pSrc, pStep, pUpsert uintptr
|
|
_, _, _, _ = i, pSrc, pStep, pUpsert
|
|
/* Find tokens to edit in WHEN clause */
|
|
_sqlite3WalkExpr(tls, pWalker, (*TTrigger)(unsafe.Pointer(pTrigger)).FpWhen)
|
|
/* Find tokens to edit in trigger steps */
|
|
pStep = (*TTrigger)(unsafe.Pointer(pTrigger)).Fstep_list
|
|
for {
|
|
if !(pStep != 0) {
|
|
break
|
|
}
|
|
_sqlite3WalkSelect(tls, pWalker, (*TTriggerStep)(unsafe.Pointer(pStep)).FpSelect)
|
|
_sqlite3WalkExpr(tls, pWalker, (*TTriggerStep)(unsafe.Pointer(pStep)).FpWhere)
|
|
_sqlite3WalkExprList(tls, pWalker, (*TTriggerStep)(unsafe.Pointer(pStep)).FpExprList)
|
|
if (*TTriggerStep)(unsafe.Pointer(pStep)).FpUpsert != 0 {
|
|
pUpsert = (*TTriggerStep)(unsafe.Pointer(pStep)).FpUpsert
|
|
_sqlite3WalkExprList(tls, pWalker, (*TUpsert)(unsafe.Pointer(pUpsert)).FpUpsertTarget)
|
|
_sqlite3WalkExprList(tls, pWalker, (*TUpsert)(unsafe.Pointer(pUpsert)).FpUpsertSet)
|
|
_sqlite3WalkExpr(tls, pWalker, (*TUpsert)(unsafe.Pointer(pUpsert)).FpUpsertWhere)
|
|
_sqlite3WalkExpr(tls, pWalker, (*TUpsert)(unsafe.Pointer(pUpsert)).FpUpsertTargetWhere)
|
|
}
|
|
if (*TTriggerStep)(unsafe.Pointer(pStep)).FpSrc != 0 {
|
|
pSrc = (*TTriggerStep)(unsafe.Pointer(pStep)).FpSrc
|
|
i = 0
|
|
for {
|
|
if !(i < (*TSrcList)(unsafe.Pointer(pSrc)).FnSrc) {
|
|
break
|
|
}
|
|
if int32(*(*uint32)(unsafe.Pointer(pSrc + 8 + uintptr(i)*80 + 24 + 4))&0x4>>2) != 0 {
|
|
_sqlite3WalkSelect(tls, pWalker, (*TSubquery)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pSrc + 8 + uintptr(i)*80 + 72)))).FpSelect)
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pStep = (*TTriggerStep)(unsafe.Pointer(pStep)).FpNext
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** *piCursor is a cursor number. Change it if it needs to be mapped.
|
|
// */
|
|
func _renumberCursorDoMapping(tls *libc.TLS, pWalker uintptr, piCursor uintptr) {
|
|
var aCsrMap uintptr
|
|
var iCsr int32
|
|
_, _ = aCsrMap, iCsr
|
|
aCsrMap = *(*uintptr)(unsafe.Pointer(pWalker + 40))
|
|
iCsr = **(**int32)(__ccgo_up(piCursor))
|
|
if iCsr < **(**int32)(__ccgo_up(aCsrMap)) && **(**int32)(__ccgo_up(aCsrMap + uintptr(iCsr+int32(1))*4)) > 0 {
|
|
**(**int32)(__ccgo_up(piCursor)) = **(**int32)(__ccgo_up(aCsrMap + uintptr(iCsr+int32(1))*4))
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Merge two lists of RowSetEntry objects. Remove duplicates.
|
|
// **
|
|
// ** The input lists are connected via pRight pointers and are
|
|
// ** assumed to each already be in sorted order.
|
|
// */
|
|
func _rowSetEntryMerge(tls *libc.TLS, pA uintptr, pB uintptr) (r uintptr) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var pTail, v2 uintptr
|
|
var _ /* head at bp+0 */ TRowSetEntry
|
|
_, _ = pTail, v2
|
|
pTail = bp
|
|
for {
|
|
if (*TRowSetEntry)(unsafe.Pointer(pA)).Fv <= (*TRowSetEntry)(unsafe.Pointer(pB)).Fv {
|
|
if (*TRowSetEntry)(unsafe.Pointer(pA)).Fv < (*TRowSetEntry)(unsafe.Pointer(pB)).Fv {
|
|
v2 = pA
|
|
(*TRowSetEntry)(unsafe.Pointer(pTail)).FpRight = v2
|
|
pTail = v2
|
|
}
|
|
pA = (*TRowSetEntry)(unsafe.Pointer(pA)).FpRight
|
|
if pA == uintptr(0) {
|
|
(*TRowSetEntry)(unsafe.Pointer(pTail)).FpRight = pB
|
|
break
|
|
}
|
|
} else {
|
|
v2 = pB
|
|
(*TRowSetEntry)(unsafe.Pointer(pTail)).FpRight = v2
|
|
pTail = v2
|
|
pB = (*TRowSetEntry)(unsafe.Pointer(pB)).FpRight
|
|
if pB == uintptr(0) {
|
|
(*TRowSetEntry)(unsafe.Pointer(pTail)).FpRight = pA
|
|
break
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
}
|
|
return (**(**TRowSetEntry)(__ccgo_up(bp))).FpRight
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Remove the entry with rowid=iDelete from the r-tree structure.
|
|
// */
|
|
func _rtreeDeleteRowid(tls *libc.TLS, pRtree uintptr, iDelete Tsqlite3_int64) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var iChild Ti64
|
|
var rc, rc2, rc21 int32
|
|
var _ /* iCell at bp+8 */ int32
|
|
var _ /* pChild at bp+24 */ uintptr
|
|
var _ /* pLeaf at bp+0 */ uintptr
|
|
var _ /* pRoot at bp+16 */ uintptr
|
|
_, _, _, _ = iChild, rc, rc2, rc21 /* Return code */
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0) /* Index of iDelete cell in pLeaf */
|
|
**(**uintptr)(__ccgo_up(bp + 16)) = uintptr(0) /* Root node of rtree structure */
|
|
/* Obtain a reference to the root node to initialize Rtree.iDepth */
|
|
rc = _nodeAcquire(tls, pRtree, int64(1), uintptr(0), bp+16)
|
|
/* Obtain a reference to the leaf node that contains the entry
|
|
** about to be deleted.
|
|
*/
|
|
if rc == SQLITE_OK {
|
|
rc = _findLeafNode(tls, pRtree, iDelete, bp, uintptr(0))
|
|
}
|
|
/* Delete the cell in question from the leaf node. */
|
|
if rc == SQLITE_OK && **(**uintptr)(__ccgo_up(bp)) != 0 {
|
|
rc = _nodeRowidIndex(tls, pRtree, **(**uintptr)(__ccgo_up(bp)), iDelete, bp+8)
|
|
if rc == SQLITE_OK {
|
|
rc = _deleteCell(tls, pRtree, **(**uintptr)(__ccgo_up(bp)), **(**int32)(__ccgo_up(bp + 8)), 0)
|
|
}
|
|
rc2 = _nodeRelease(tls, pRtree, **(**uintptr)(__ccgo_up(bp)))
|
|
if rc == SQLITE_OK {
|
|
rc = rc2
|
|
}
|
|
}
|
|
/* Delete the corresponding entry in the <rtree>_rowid table. */
|
|
if rc == SQLITE_OK {
|
|
Xsqlite3_bind_int64(tls, (*TRtree)(unsafe.Pointer(pRtree)).FpDeleteRowid, int32(1), iDelete)
|
|
Xsqlite3_step(tls, (*TRtree)(unsafe.Pointer(pRtree)).FpDeleteRowid)
|
|
rc = Xsqlite3_reset(tls, (*TRtree)(unsafe.Pointer(pRtree)).FpDeleteRowid)
|
|
}
|
|
/* Check if the root node now has exactly one child. If so, remove
|
|
** it, schedule the contents of the child for reinsertion and
|
|
** reduce the tree height by one.
|
|
**
|
|
** This is equivalent to copying the contents of the child into
|
|
** the root node (the operation that Gutman's paper says to perform
|
|
** in this scenario).
|
|
*/
|
|
if rc == SQLITE_OK && (*TRtree)(unsafe.Pointer(pRtree)).FiDepth > 0 && _readInt16(tls, (*TRtreeNode)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp + 16)))).FzData+2) == int32(1) {
|
|
**(**uintptr)(__ccgo_up(bp + 24)) = uintptr(0)
|
|
iChild = _nodeGetRowid(tls, pRtree, **(**uintptr)(__ccgo_up(bp + 16)), 0)
|
|
rc = _nodeAcquire(tls, pRtree, iChild, **(**uintptr)(__ccgo_up(bp + 16)), bp+24) /* tag-20210916a */
|
|
if rc == SQLITE_OK {
|
|
rc = _removeNode(tls, pRtree, **(**uintptr)(__ccgo_up(bp + 24)), (*TRtree)(unsafe.Pointer(pRtree)).FiDepth-int32(1))
|
|
}
|
|
rc21 = _nodeRelease(tls, pRtree, **(**uintptr)(__ccgo_up(bp + 24)))
|
|
if rc == SQLITE_OK {
|
|
rc = rc21
|
|
}
|
|
if rc == SQLITE_OK {
|
|
(*TRtree)(unsafe.Pointer(pRtree)).FiDepth = (*TRtree)(unsafe.Pointer(pRtree)).FiDepth - 1
|
|
_writeInt16(tls, (*TRtreeNode)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp + 16)))).FzData, (*TRtree)(unsafe.Pointer(pRtree)).FiDepth)
|
|
(*TRtreeNode)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp + 16)))).FisDirty = int32(1)
|
|
}
|
|
}
|
|
/* Re-insert the contents of any underfull nodes removed from the tree. */
|
|
**(**uintptr)(__ccgo_up(bp)) = (*TRtree)(unsafe.Pointer(pRtree)).FpDeleted
|
|
for {
|
|
if !(**(**uintptr)(__ccgo_up(bp)) != 0) {
|
|
break
|
|
}
|
|
if rc == SQLITE_OK {
|
|
rc = _reinsertNodeContent(tls, pRtree, **(**uintptr)(__ccgo_up(bp)))
|
|
}
|
|
(*TRtree)(unsafe.Pointer(pRtree)).FpDeleted = (*TRtreeNode)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FpNext
|
|
(*TRtree)(unsafe.Pointer(pRtree)).FnNodeRef = (*TRtree)(unsafe.Pointer(pRtree)).FnNodeRef - 1
|
|
Xsqlite3_free(tls, **(**uintptr)(__ccgo_up(bp)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
**(**uintptr)(__ccgo_up(bp)) = (*TRtree)(unsafe.Pointer(pRtree)).FpDeleted
|
|
}
|
|
/* Release the reference to the root node. */
|
|
if rc == SQLITE_OK {
|
|
rc = _nodeRelease(tls, pRtree, **(**uintptr)(__ccgo_up(bp + 16)))
|
|
} else {
|
|
_nodeRelease(tls, pRtree, **(**uintptr)(__ccgo_up(bp + 16)))
|
|
}
|
|
return rc
|
|
}
|
|
|
|
/*
|
|
** Rounding constants for float->double conversion.
|
|
*/
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This routine frees the BLOB that is returned by geomCallback().
|
|
// */
|
|
func _rtreeMatchArgFree(tls *libc.TLS, pArg uintptr) {
|
|
var i int32
|
|
var p uintptr
|
|
_, _ = i, p
|
|
p = pArg
|
|
i = 0
|
|
for {
|
|
if !(i < (*TRtreeMatchArg)(unsafe.Pointer(p)).FnParam) {
|
|
break
|
|
}
|
|
Xsqlite3_value_free(tls, **(**uintptr)(__ccgo_up((*TRtreeMatchArg)(unsafe.Pointer(p)).FapSqlParam + uintptr(i)*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
Xsqlite3_free(tls, p)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Decrement the r-tree reference count. When the reference count reaches
|
|
// ** zero the structure is deleted.
|
|
// */
|
|
func _rtreeRelease(tls *libc.TLS, pRtree uintptr) {
|
|
var i int32
|
|
var pNext uintptr
|
|
_, _ = i, pNext
|
|
(*TRtree)(unsafe.Pointer(pRtree)).FnBusy = (*TRtree)(unsafe.Pointer(pRtree)).FnBusy - 1
|
|
if (*TRtree)(unsafe.Pointer(pRtree)).FnBusy == uint32(0) {
|
|
(*TRtree)(unsafe.Pointer(pRtree)).FinWrTrans = uint8(0)
|
|
_nodeBlobReset(tls, pRtree)
|
|
if (*TRtree)(unsafe.Pointer(pRtree)).FnNodeRef != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < int32(HASHSIZE)) {
|
|
break
|
|
}
|
|
for **(**uintptr)(__ccgo_up(pRtree + 200 + uintptr(i)*8)) != 0 {
|
|
pNext = (*TRtreeNode)(unsafe.Pointer(**(**uintptr)(__ccgo_up(pRtree + 200 + uintptr(i)*8)))).FpNext
|
|
Xsqlite3_free(tls, **(**uintptr)(__ccgo_up(pRtree + 200 + uintptr(i)*8)))
|
|
**(**uintptr)(__ccgo_up(pRtree + 200 + uintptr(i)*8)) = pNext
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
Xsqlite3_finalize(tls, (*TRtree)(unsafe.Pointer(pRtree)).FpWriteNode)
|
|
Xsqlite3_finalize(tls, (*TRtree)(unsafe.Pointer(pRtree)).FpDeleteNode)
|
|
Xsqlite3_finalize(tls, (*TRtree)(unsafe.Pointer(pRtree)).FpReadRowid)
|
|
Xsqlite3_finalize(tls, (*TRtree)(unsafe.Pointer(pRtree)).FpWriteRowid)
|
|
Xsqlite3_finalize(tls, (*TRtree)(unsafe.Pointer(pRtree)).FpDeleteRowid)
|
|
Xsqlite3_finalize(tls, (*TRtree)(unsafe.Pointer(pRtree)).FpReadParent)
|
|
Xsqlite3_finalize(tls, (*TRtree)(unsafe.Pointer(pRtree)).FpWriteParent)
|
|
Xsqlite3_finalize(tls, (*TRtree)(unsafe.Pointer(pRtree)).FpDeleteParent)
|
|
Xsqlite3_finalize(tls, (*TRtree)(unsafe.Pointer(pRtree)).FpWriteAux)
|
|
Xsqlite3_free(tls, (*TRtree)(unsafe.Pointer(pRtree)).FzReadAuxSql)
|
|
Xsqlite3_free(tls, pRtree)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the search point with the lowest current score.
|
|
// */
|
|
func _rtreeSearchPointFirst(tls *libc.TLS, pCur uintptr) (r uintptr) {
|
|
var v1, v2 uintptr
|
|
_, _ = v1, v2
|
|
if (*TRtreeCursor)(unsafe.Pointer(pCur)).FbPoint != 0 {
|
|
v1 = pCur + 64
|
|
} else {
|
|
if (*TRtreeCursor)(unsafe.Pointer(pCur)).FnPoint != 0 {
|
|
v2 = (*TRtreeCursor)(unsafe.Pointer(pCur)).FaPoint
|
|
} else {
|
|
v2 = uintptr(0)
|
|
}
|
|
v1 = v2
|
|
}
|
|
return v1
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Interchange two search points in a cursor.
|
|
// */
|
|
func _rtreeSearchPointSwap(tls *libc.TLS, p uintptr, i int32, j int32) {
|
|
var pTemp uintptr
|
|
var t TRtreeSearchPoint
|
|
_, _ = pTemp, t
|
|
t = **(**TRtreeSearchPoint)(__ccgo_up((*TRtreeCursor)(unsafe.Pointer(p)).FaPoint + uintptr(i)*24))
|
|
**(**TRtreeSearchPoint)(__ccgo_up((*TRtreeCursor)(unsafe.Pointer(p)).FaPoint + uintptr(i)*24)) = **(**TRtreeSearchPoint)(__ccgo_up((*TRtreeCursor)(unsafe.Pointer(p)).FaPoint + uintptr(j)*24))
|
|
**(**TRtreeSearchPoint)(__ccgo_up((*TRtreeCursor)(unsafe.Pointer(p)).FaPoint + uintptr(j)*24)) = t
|
|
i = i + 1
|
|
j = j + 1
|
|
if i < int32(RTREE_CACHE_SZ) {
|
|
if j >= int32(RTREE_CACHE_SZ) {
|
|
_nodeRelease(tls, (*TRtreeCursor)(unsafe.Pointer(p)).Fbase.FpVtab, **(**uintptr)(__ccgo_up(p + 88 + uintptr(i)*8)))
|
|
**(**uintptr)(__ccgo_up(p + 88 + uintptr(i)*8)) = uintptr(0)
|
|
} else {
|
|
pTemp = **(**uintptr)(__ccgo_up(p + 88 + uintptr(i)*8))
|
|
**(**uintptr)(__ccgo_up(p + 88 + uintptr(i)*8)) = **(**uintptr)(__ccgo_up(p + 88 + uintptr(j)*8))
|
|
**(**uintptr)(__ccgo_up(p + 88 + uintptr(j)*8)) = pTemp
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return true if zName is the extension on one of the shadow tables used
|
|
// ** by this module.
|
|
// */
|
|
func _rtreeShadowName(tls *libc.TLS, zName uintptr) (r int32) {
|
|
var i uint32
|
|
_ = i
|
|
i = uint32(0)
|
|
for {
|
|
if !(uint64(i) < libc.Uint64FromInt64(24)/libc.Uint64FromInt64(8)) {
|
|
break
|
|
}
|
|
if Xsqlite3_stricmp(tls, zName, _azName1[i]) == 0 {
|
|
return int32(1)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If any term of pSrc, or any SF_NestedFrom sub-query, is not the same
|
|
// ** as pSrcItem but has the same alias as p0, then return true.
|
|
// ** Otherwise return false.
|
|
// */
|
|
func _sameSrcAlias(tls *libc.TLS, p0 uintptr, pSrc uintptr) (r int32) {
|
|
var i int32
|
|
var p1 uintptr
|
|
_, _ = i, p1
|
|
i = 0
|
|
for {
|
|
if !(i < (*TSrcList)(unsafe.Pointer(pSrc)).FnSrc) {
|
|
break
|
|
}
|
|
p1 = pSrc + 8 + uintptr(i)*80
|
|
if p1 == p0 {
|
|
goto _1
|
|
}
|
|
if (*TSrcItem)(unsafe.Pointer(p0)).FpSTab == (*TSrcItem)(unsafe.Pointer(p1)).FpSTab && 0 == Xsqlite3_stricmp(tls, (*TSrcItem)(unsafe.Pointer(p0)).FzAlias, (*TSrcItem)(unsafe.Pointer(p1)).FzAlias) {
|
|
return int32(1)
|
|
}
|
|
if int32(*(*uint32)(unsafe.Pointer(p1 + 24 + 4))&0x4>>2) != 0 && (*TSelect)(unsafe.Pointer((*TSubquery)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(p1 + 72)))).FpSelect)).FselFlags&uint32(SF_NestedFrom) != uint32(0) && _sameSrcAlias(tls, p0, (*TSelect)(unsafe.Pointer((*TSubquery)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(p1 + 72)))).FpSelect)).FpSrc) != 0 {
|
|
return int32(1)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Reclaim memory used by a StatSample
|
|
// */
|
|
func _sampleClear(tls *libc.TLS, db uintptr, p uintptr) {
|
|
if (*TStatSample)(unsafe.Pointer(p)).FnRowid != 0 {
|
|
_sqlite3DbFree(tls, db, *(*uintptr)(unsafe.Pointer(p + 24)))
|
|
(*TStatSample)(unsafe.Pointer(p)).FnRowid = uint32(0)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Field iChng of the index being scanned has changed. So at this point
|
|
// ** p->current contains a sample that reflects the previous row of the
|
|
// ** index. The value of anEq[iChng] and subsequent anEq[] elements are
|
|
// ** correct at this point.
|
|
// */
|
|
func _samplePushPrevious(tls *libc.TLS, p uintptr, iChng int32) {
|
|
var i, j, j1 int32
|
|
var pBest uintptr
|
|
_, _, _, _ = i, j, j1, pBest
|
|
/* Check if any samples from the aBest[] array should be pushed
|
|
** into IndexSample.a[] at this point. */
|
|
i = (*TStatAccum)(unsafe.Pointer(p)).FnCol - int32(2)
|
|
for {
|
|
if !(i >= iChng) {
|
|
break
|
|
}
|
|
pBest = (*TStatAccum)(unsafe.Pointer(p)).FaBest + uintptr(i)*48
|
|
**(**TtRowcnt)(__ccgo_up((*TStatSample)(unsafe.Pointer(pBest)).FanEq + uintptr(i)*8)) = **(**TtRowcnt)(__ccgo_up((*TStatAccum)(unsafe.Pointer(p)).Fcurrent.FanEq + uintptr(i)*8))
|
|
if (*TStatAccum)(unsafe.Pointer(p)).FnSample < (*TStatAccum)(unsafe.Pointer(p)).FmxSample || _sampleIsBetter(tls, p, pBest, (*TStatAccum)(unsafe.Pointer(p)).Fa+uintptr((*TStatAccum)(unsafe.Pointer(p)).FiMin)*48) != 0 {
|
|
_sampleInsert(tls, p, pBest, i)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i - 1
|
|
}
|
|
/* Check that no sample contains an anEq[] entry with an index of
|
|
** p->nMaxEqZero or greater set to zero. */
|
|
i = (*TStatAccum)(unsafe.Pointer(p)).FnSample - int32(1)
|
|
for {
|
|
if !(i >= 0) {
|
|
break
|
|
}
|
|
j = (*TStatAccum)(unsafe.Pointer(p)).FnMaxEqZero
|
|
for {
|
|
if !(j < (*TStatAccum)(unsafe.Pointer(p)).FnCol) {
|
|
break
|
|
}
|
|
goto _3
|
|
_3:
|
|
;
|
|
j = j + 1
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i - 1
|
|
}
|
|
/* Update the anEq[] fields of any samples already collected. */
|
|
if iChng < (*TStatAccum)(unsafe.Pointer(p)).FnMaxEqZero {
|
|
i = (*TStatAccum)(unsafe.Pointer(p)).FnSample - int32(1)
|
|
for {
|
|
if !(i >= 0) {
|
|
break
|
|
}
|
|
j1 = iChng
|
|
for {
|
|
if !(j1 < (*TStatAccum)(unsafe.Pointer(p)).FnCol) {
|
|
break
|
|
}
|
|
if **(**TtRowcnt)(__ccgo_up((**(**TStatSample)(__ccgo_up((*TStatAccum)(unsafe.Pointer(p)).Fa + uintptr(i)*48))).FanEq + uintptr(j1)*8)) == uint64(0) {
|
|
**(**TtRowcnt)(__ccgo_up((**(**TStatSample)(__ccgo_up((*TStatAccum)(unsafe.Pointer(p)).Fa + uintptr(i)*48))).FanEq + uintptr(j1)*8)) = **(**TtRowcnt)(__ccgo_up((*TStatAccum)(unsafe.Pointer(p)).Fcurrent.FanEq + uintptr(j1)*8))
|
|
}
|
|
goto _5
|
|
_5:
|
|
;
|
|
j1 = j1 + 1
|
|
}
|
|
goto _4
|
|
_4:
|
|
;
|
|
i = i - 1
|
|
}
|
|
(*TStatAccum)(unsafe.Pointer(p)).FnMaxEqZero = iChng
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Initialize the INTEGER value of a ROWID.
|
|
// */
|
|
func _sampleSetRowidInt64(tls *libc.TLS, db uintptr, p uintptr, iRowid Ti64) {
|
|
if (*TStatSample)(unsafe.Pointer(p)).FnRowid != 0 {
|
|
_sqlite3DbFree(tls, db, *(*uintptr)(unsafe.Pointer(p + 24)))
|
|
}
|
|
(*TStatSample)(unsafe.Pointer(p)).FnRowid = uint32(0)
|
|
*(*Ti64)(unsafe.Pointer(p + 24)) = iRowid
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Argument pWith (which may be NULL) points to a linked list of nested
|
|
// ** WITH contexts, from inner to outermost. If the table identified by
|
|
// ** FROM clause element pItem is really a common-table-expression (CTE)
|
|
// ** then return a pointer to the CTE definition for that table. Otherwise
|
|
// ** return NULL.
|
|
// **
|
|
// ** If a non-NULL value is returned, set *ppContext to point to the With
|
|
// ** object that the returned CTE belongs to.
|
|
// */
|
|
func _searchWith(tls *libc.TLS, pWith uintptr, pItem uintptr, ppContext uintptr) (r uintptr) {
|
|
var i int32
|
|
var p, zName uintptr
|
|
_, _, _ = i, p, zName
|
|
zName = (*TSrcItem)(unsafe.Pointer(pItem)).FzName
|
|
p = pWith
|
|
for {
|
|
if !(p != 0) {
|
|
break
|
|
}
|
|
i = 0
|
|
for {
|
|
if !(i < (*TWith)(unsafe.Pointer(p)).FnCte) {
|
|
break
|
|
}
|
|
if _sqlite3StrICmp(tls, zName, (*(*TCte)(unsafe.Pointer(p + 16 + uintptr(i)*48))).FzName) == 0 {
|
|
**(**uintptr)(__ccgo_up(ppContext)) = p
|
|
return p + 16 + uintptr(i)*48
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if (*TWith)(unsafe.Pointer(p)).FbView != 0 {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
p = (*TWith)(unsafe.Pointer(p)).FpOuter
|
|
}
|
|
return uintptr(0)
|
|
}
|
|
|
|
func _selectRefLeave(tls *libc.TLS, pWalker uintptr, pSelect uintptr) {
|
|
var p, pSrc uintptr
|
|
_, _ = p, pSrc
|
|
p = *(*uintptr)(unsafe.Pointer(pWalker + 40))
|
|
pSrc = (*TSelect)(unsafe.Pointer(pSelect)).FpSrc
|
|
if (*TRefSrcList)(unsafe.Pointer(p)).FnExclude != 0 {
|
|
**(**Ti64)(__ccgo_up(p + 16)) -= int64((*TSrcList)(unsafe.Pointer(pSrc)).FnSrc)
|
|
}
|
|
}
|
|
|
|
func _selectWindowRewriteSelectCb(tls *libc.TLS, pWalker uintptr, pSelect uintptr) (r int32) {
|
|
var p, pSave uintptr
|
|
_, _ = p, pSave
|
|
p = *(*uintptr)(unsafe.Pointer(pWalker + 40))
|
|
pSave = (*TWindowRewrite)(unsafe.Pointer(p)).FpSubSelect
|
|
if pSave == pSelect {
|
|
return WRC_Continue
|
|
} else {
|
|
(*TWindowRewrite)(unsafe.Pointer(p)).FpSubSelect = pSelect
|
|
_sqlite3WalkSelect(tls, pWalker, pSelect)
|
|
(*TWindowRewrite)(unsafe.Pointer(p)).FpSubSelect = pSave
|
|
}
|
|
return int32(WRC_Prune)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is a no-op if *pRc is other than SQLITE_OK when it is
|
|
// ** called. Otherwise, append a single byte to the buffer.
|
|
// **
|
|
// ** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before
|
|
// ** returning.
|
|
// */
|
|
func _sessionAppendByte(tls *libc.TLS, p uintptr, v Tu8, pRc uintptr) {
|
|
var v1 int32
|
|
var v2 uintptr
|
|
_, _ = v1, v2
|
|
if 0 == _sessionBufferGrow(tls, p, int64(1), pRc) {
|
|
v2 = p + 8
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
**(**Tu8)(__ccgo_up((*TSessionBuffer)(unsafe.Pointer(p)).FaBuf + uintptr(v1))) = v
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Append the value passed as the second argument to the buffer passed
|
|
// ** as the first.
|
|
// **
|
|
// ** This function is a no-op if *pRc is non-zero when it is called.
|
|
// ** Otherwise, if an error occurs, *pRc is set to an SQLite error code
|
|
// ** before returning.
|
|
// */
|
|
func _sessionAppendValue(tls *libc.TLS, p uintptr, pVal uintptr, pRc uintptr) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var v1 uintptr
|
|
var _ /* nByte at bp+8 */ Tsqlite3_int64
|
|
var _ /* rc at bp+0 */ int32
|
|
_ = v1
|
|
**(**int32)(__ccgo_up(bp)) = **(**int32)(__ccgo_up(pRc))
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
**(**Tsqlite3_int64)(__ccgo_up(bp + 8)) = 0
|
|
**(**int32)(__ccgo_up(bp)) = _sessionSerializeValue(tls, uintptr(0), pVal, bp+8)
|
|
_sessionBufferGrow(tls, p, **(**Tsqlite3_int64)(__ccgo_up(bp + 8)), bp)
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
**(**int32)(__ccgo_up(bp)) = _sessionSerializeValue(tls, (*TSessionBuffer)(unsafe.Pointer(p)).FaBuf+uintptr((*TSessionBuffer)(unsafe.Pointer(p)).FnBuf), pVal, uintptr(0))
|
|
v1 = p + 8
|
|
*(*int32)(unsafe.Pointer(v1)) = int32(int64(*(*int32)(unsafe.Pointer(v1))) + **(**Tsqlite3_int64)(__ccgo_up(bp + 8)))
|
|
} else {
|
|
**(**int32)(__ccgo_up(pRc)) = **(**int32)(__ccgo_up(bp))
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is a no-op if *pRc is other than SQLITE_OK when it is
|
|
// ** called. Otherwise, append a single varint to the buffer.
|
|
// **
|
|
// ** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before
|
|
// ** returning.
|
|
// */
|
|
func _sessionAppendVarint(tls *libc.TLS, p uintptr, v int32, pRc uintptr) {
|
|
if 0 == _sessionBufferGrow(tls, p, int64(9), pRc) {
|
|
**(**int32)(__ccgo_up(p + 8)) += _sessionVarintPut(tls, (*TSessionBuffer)(unsafe.Pointer(p)).FaBuf+uintptr((*TSessionBuffer)(unsafe.Pointer(p)).FnBuf), v)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Attempt to apply the change that the iterator passed as the first argument
|
|
// ** currently points to to the database. If a conflict is encountered, invoke
|
|
// ** the conflict handler callback.
|
|
// **
|
|
// ** If argument pbRetry is NULL, then ignore any CHANGESET_DATA conflict. If
|
|
// ** one is encountered, update or delete the row with the matching primary key
|
|
// ** instead. Or, if pbRetry is not NULL and a CHANGESET_DATA conflict occurs,
|
|
// ** invoke the conflict handler. If it returns CHANGESET_REPLACE, set *pbRetry
|
|
// ** to true before returning. In this case the caller will invoke this function
|
|
// ** again, this time with pbRetry set to NULL.
|
|
// **
|
|
// ** If argument pbReplace is NULL and a CHANGESET_CONFLICT conflict is
|
|
// ** encountered invoke the conflict handler with CHANGESET_CONSTRAINT instead.
|
|
// ** Or, if pbReplace is not NULL, invoke it with CHANGESET_CONFLICT. If such
|
|
// ** an invocation returns SQLITE_CHANGESET_REPLACE, set *pbReplace to true
|
|
// ** before retrying. In this case the caller attempts to remove the conflicting
|
|
// ** row before invoking this function again, this time with pbReplace set
|
|
// ** to NULL.
|
|
// **
|
|
// ** If any conflict handler returns SQLITE_CHANGESET_ABORT, this function
|
|
// ** returns SQLITE_ABORT. Otherwise, if no error occurs, SQLITE_OK is
|
|
// ** returned.
|
|
// */
|
|
func _sessionApplyOneOp(tls *libc.TLS, pIter uintptr, p uintptr, __ccgo_fp_xConflict uintptr, pCtx uintptr, pbReplace uintptr, pbRetry uintptr) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var abPK, pNew, pOld, v1 uintptr
|
|
var bPatchset, i, rc int32
|
|
var _ /* nCol at bp+12 */ int32
|
|
var _ /* op at bp+8 */ int32
|
|
var _ /* pUp at bp+16 */ uintptr
|
|
var _ /* zDummy at bp+0 */ uintptr
|
|
_, _, _, _, _, _, _ = abPK, bPatchset, i, pNew, pOld, rc, v1
|
|
rc = SQLITE_OK
|
|
Xsqlite3changeset_op(tls, pIter, bp, bp+12, bp+8, uintptr(0))
|
|
if **(**int32)(__ccgo_up(bp + 8)) == int32(SQLITE_DELETE) {
|
|
if (*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).FbPatchset != 0 {
|
|
v1 = (*TSessionApplyCtx)(unsafe.Pointer(p)).FabPK
|
|
} else {
|
|
v1 = uintptr(0)
|
|
}
|
|
/* Bind values to the DELETE statement. If conflict handling is required,
|
|
** bind values for all columns and set bound variable (nCol+1) to true.
|
|
** Or, if conflict handling is not required, bind just the PK column
|
|
** values and, if it exists, set (nCol+1) to false. Conflict handling
|
|
** is not required if:
|
|
**
|
|
** * this is a patchset, or
|
|
** * (pbRetry==0), or
|
|
** * all columns of the table are PK columns (in this case there is
|
|
** no (nCol+1) variable to bind to).
|
|
*/
|
|
abPK = v1
|
|
rc = _sessionBindRow(tls, pIter, __ccgo_fp(Xsqlite3changeset_old), **(**int32)(__ccgo_up(bp + 12)), abPK, (*TSessionApplyCtx)(unsafe.Pointer(p)).FpDelete)
|
|
if rc == SQLITE_OK && Xsqlite3_bind_parameter_count(tls, (*TSessionApplyCtx)(unsafe.Pointer(p)).FpDelete) > **(**int32)(__ccgo_up(bp + 12)) {
|
|
rc = Xsqlite3_bind_int(tls, (*TSessionApplyCtx)(unsafe.Pointer(p)).FpDelete, **(**int32)(__ccgo_up(bp + 12))+int32(1), libc.BoolInt32(pbRetry == uintptr(0) || abPK != 0))
|
|
}
|
|
if rc != SQLITE_OK {
|
|
return rc
|
|
}
|
|
Xsqlite3_step(tls, (*TSessionApplyCtx)(unsafe.Pointer(p)).FpDelete)
|
|
rc = Xsqlite3_reset(tls, (*TSessionApplyCtx)(unsafe.Pointer(p)).FpDelete)
|
|
if rc == SQLITE_OK && Xsqlite3_changes(tls, (*TSessionApplyCtx)(unsafe.Pointer(p)).Fdb) == 0 {
|
|
rc = _sessionConflictHandler(tls, int32(SQLITE_CHANGESET_DATA), p, pIter, __ccgo_fp_xConflict, pCtx, pbRetry)
|
|
} else {
|
|
if rc&int32(0xff) == int32(SQLITE_CONSTRAINT) {
|
|
rc = _sessionConflictHandler(tls, int32(SQLITE_CHANGESET_CONFLICT), p, pIter, __ccgo_fp_xConflict, pCtx, uintptr(0))
|
|
}
|
|
}
|
|
} else {
|
|
if **(**int32)(__ccgo_up(bp + 8)) == int32(SQLITE_UPDATE) {
|
|
**(**uintptr)(__ccgo_up(bp + 16)) = uintptr(0)
|
|
bPatchset = libc.BoolInt32(pbRetry == uintptr(0) || (*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).FbPatchset != 0)
|
|
rc = _sessionUpdateFind(tls, pIter, p, bPatchset, bp+16)
|
|
/* Bind values to the UPDATE statement. */
|
|
i = 0
|
|
for {
|
|
if !(rc == SQLITE_OK && i < **(**int32)(__ccgo_up(bp + 12))) {
|
|
break
|
|
}
|
|
pOld = **(**uintptr)(__ccgo_up((*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).FapValue + uintptr(i)*8))
|
|
pNew = **(**uintptr)(__ccgo_up((*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).FapValue + uintptr((*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).FnCol+i)*8))
|
|
if pOld != 0 && (**(**Tu8)(__ccgo_up((*TSessionApplyCtx)(unsafe.Pointer(p)).FabPK + uintptr(i))) != 0 || bPatchset == 0) {
|
|
rc = _sessionBindValue(tls, **(**uintptr)(__ccgo_up(bp + 16)), i*int32(2)+int32(2), pOld)
|
|
}
|
|
if rc == SQLITE_OK && pNew != 0 {
|
|
rc = _sessionBindValue(tls, **(**uintptr)(__ccgo_up(bp + 16)), i*int32(2)+int32(1), pNew)
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if rc != SQLITE_OK {
|
|
return rc
|
|
}
|
|
/* Attempt the UPDATE. In the case of a NOTFOUND or DATA conflict,
|
|
** the result will be SQLITE_OK with 0 rows modified. */
|
|
Xsqlite3_step(tls, **(**uintptr)(__ccgo_up(bp + 16)))
|
|
rc = Xsqlite3_reset(tls, **(**uintptr)(__ccgo_up(bp + 16)))
|
|
if rc == SQLITE_OK && Xsqlite3_changes(tls, (*TSessionApplyCtx)(unsafe.Pointer(p)).Fdb) == 0 {
|
|
/* A NOTFOUND or DATA error. Search the table to see if it contains
|
|
** a row with a matching primary key. If so, this is a DATA conflict.
|
|
** Otherwise, if there is no primary key match, it is a NOTFOUND. */
|
|
rc = _sessionConflictHandler(tls, int32(SQLITE_CHANGESET_DATA), p, pIter, __ccgo_fp_xConflict, pCtx, pbRetry)
|
|
} else {
|
|
if rc&int32(0xff) == int32(SQLITE_CONSTRAINT) {
|
|
/* This is always a CONSTRAINT conflict. */
|
|
rc = _sessionConflictHandler(tls, int32(SQLITE_CHANGESET_CONFLICT), p, pIter, __ccgo_fp_xConflict, pCtx, uintptr(0))
|
|
}
|
|
}
|
|
} else {
|
|
if (*TSessionApplyCtx)(unsafe.Pointer(p)).FbStat1 != 0 {
|
|
/* Check if there is a conflicting row. For sqlite_stat1, this needs
|
|
** to be done using a SELECT, as there is no PRIMARY KEY in the
|
|
** database schema to throw an exception if a duplicate is inserted. */
|
|
rc = _sessionSeekToRow(tls, pIter, p)
|
|
if rc == int32(SQLITE_ROW) {
|
|
rc = int32(SQLITE_CONSTRAINT)
|
|
Xsqlite3_reset(tls, (*TSessionApplyCtx)(unsafe.Pointer(p)).FpSelect)
|
|
}
|
|
}
|
|
if rc == SQLITE_OK {
|
|
rc = _sessionBindRow(tls, pIter, __ccgo_fp(Xsqlite3changeset_new), **(**int32)(__ccgo_up(bp + 12)), uintptr(0), (*TSessionApplyCtx)(unsafe.Pointer(p)).FpInsert)
|
|
if rc != SQLITE_OK {
|
|
return rc
|
|
}
|
|
Xsqlite3_step(tls, (*TSessionApplyCtx)(unsafe.Pointer(p)).FpInsert)
|
|
rc = Xsqlite3_reset(tls, (*TSessionApplyCtx)(unsafe.Pointer(p)).FpInsert)
|
|
}
|
|
if rc&int32(0xff) == int32(SQLITE_CONSTRAINT) {
|
|
rc = _sessionConflictHandler(tls, int32(SQLITE_CHANGESET_CONFLICT), p, pIter, __ccgo_fp_xConflict, pCtx, pbReplace)
|
|
}
|
|
}
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Serialize a changeset (or patchset) based on all changesets (or patchsets)
|
|
// ** added to the changegroup object passed as the first argument.
|
|
// **
|
|
// ** If xOutput is not NULL, then the changeset/patchset is returned to the
|
|
// ** user via one or more calls to xOutput, as with the other streaming
|
|
// ** interfaces.
|
|
// **
|
|
// ** Or, if xOutput is NULL, then (*ppOut) is populated with a pointer to a
|
|
// ** buffer containing the output changeset before this function returns. In
|
|
// ** this case (*pnOut) is set to the size of the output buffer in bytes. It
|
|
// ** is the responsibility of the caller to free the output buffer using
|
|
// ** sqlite3_free() when it is no longer required.
|
|
// **
|
|
// ** If successful, SQLITE_OK is returned. Or, if an error occurs, an SQLite
|
|
// ** error code. If an error occurs and xOutput is NULL, (*ppOut) and (*pnOut)
|
|
// ** are both set to 0 before returning.
|
|
// */
|
|
func _sessionChangegroupOutput(tls *libc.TLS, pGrp uintptr, __ccgo_fp_xOutput uintptr, pOut uintptr, pnOut uintptr, ppOut uintptr) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var i int32
|
|
var p, pTab uintptr
|
|
var _ /* buf at bp+8 */ TSessionBuffer
|
|
var _ /* rc at bp+0 */ int32
|
|
_, _, _ = i, p, pTab
|
|
**(**int32)(__ccgo_up(bp)) = SQLITE_OK
|
|
**(**TSessionBuffer)(__ccgo_up(bp + 8)) = TSessionBuffer{}
|
|
/* Create the serialized output changeset based on the contents of the
|
|
** hash tables attached to the SessionTable objects in list p->pList.
|
|
*/
|
|
pTab = (*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).FpList
|
|
for {
|
|
if !(**(**int32)(__ccgo_up(bp)) == SQLITE_OK && pTab != 0) {
|
|
break
|
|
}
|
|
if (*TSessionTable)(unsafe.Pointer(pTab)).FnEntry == 0 {
|
|
goto _1
|
|
}
|
|
_sessionAppendTableHdr(tls, bp+8, (*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).FbPatch, pTab, bp)
|
|
i = 0
|
|
for {
|
|
if !(i < (*TSessionTable)(unsafe.Pointer(pTab)).FnChange) {
|
|
break
|
|
}
|
|
p = **(**uintptr)(__ccgo_up((*TSessionTable)(unsafe.Pointer(pTab)).FapChange + uintptr(i)*8))
|
|
for {
|
|
if !(p != 0) {
|
|
break
|
|
}
|
|
_sessionAppendByte(tls, bp+8, (*TSessionChange)(unsafe.Pointer(p)).Fop, bp)
|
|
_sessionAppendByte(tls, bp+8, (*TSessionChange)(unsafe.Pointer(p)).FbIndirect, bp)
|
|
_sessionAppendBlob(tls, bp+8, (*TSessionChange)(unsafe.Pointer(p)).FaRecord, (*TSessionChange)(unsafe.Pointer(p)).FnRecord, bp)
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK && __ccgo_fp_xOutput != 0 && (**(**TSessionBuffer)(__ccgo_up(bp + 8))).FnBuf >= _sessions_strm_chunk_size {
|
|
**(**int32)(__ccgo_up(bp)) = (*(*func(*libc.TLS, uintptr, uintptr, int32) int32)(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xOutput})))(tls, pOut, (**(**TSessionBuffer)(__ccgo_up(bp + 8))).FaBuf, (**(**TSessionBuffer)(__ccgo_up(bp + 8))).FnBuf)
|
|
(**(**TSessionBuffer)(__ccgo_up(bp + 8))).FnBuf = 0
|
|
}
|
|
goto _3
|
|
_3:
|
|
;
|
|
p = (*TSessionChange)(unsafe.Pointer(p)).FpNext
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pTab = (*TSessionTable)(unsafe.Pointer(pTab)).FpNext
|
|
}
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
if __ccgo_fp_xOutput != 0 {
|
|
if (**(**TSessionBuffer)(__ccgo_up(bp + 8))).FnBuf > 0 {
|
|
**(**int32)(__ccgo_up(bp)) = (*(*func(*libc.TLS, uintptr, uintptr, int32) int32)(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xOutput})))(tls, pOut, (**(**TSessionBuffer)(__ccgo_up(bp + 8))).FaBuf, (**(**TSessionBuffer)(__ccgo_up(bp + 8))).FnBuf)
|
|
}
|
|
} else {
|
|
if ppOut != 0 {
|
|
**(**uintptr)(__ccgo_up(ppOut)) = (**(**TSessionBuffer)(__ccgo_up(bp + 8))).FaBuf
|
|
if pnOut != 0 {
|
|
**(**int32)(__ccgo_up(pnOut)) = (**(**TSessionBuffer)(__ccgo_up(bp + 8))).FnBuf
|
|
}
|
|
(**(**TSessionBuffer)(__ccgo_up(bp + 8))).FaBuf = uintptr(0)
|
|
}
|
|
}
|
|
}
|
|
Xsqlite3_free(tls, (**(**TSessionBuffer)(__ccgo_up(bp + 8))).FaBuf)
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Add all changes in the changeset traversed by the iterator passed as
|
|
// ** the first argument to the changegroup hash tables.
|
|
// */
|
|
func _sessionChangesetToHash(tls *libc.TLS, pIter uintptr, pGrp uintptr, bRebase int32) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var rc int32
|
|
var _ /* aRec at bp+0 */ uintptr
|
|
var _ /* nRec at bp+8 */ int32
|
|
_ = rc
|
|
rc = SQLITE_OK
|
|
(*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).Fin.FbNoDiscard = int32(1)
|
|
for int32(SQLITE_ROW) == _sessionChangesetNext(tls, pIter, bp, bp+8, uintptr(0)) {
|
|
rc = _sessionOneChangeIterToHash(tls, pGrp, pIter, bRebase)
|
|
if rc != SQLITE_OK {
|
|
break
|
|
}
|
|
}
|
|
if rc == SQLITE_OK {
|
|
rc = (*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).Frc
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free the list of table objects passed as the first argument. The contents
|
|
// ** of the changed-rows hash tables are also deleted.
|
|
// */
|
|
func _sessionDeleteTable(tls *libc.TLS, pSession uintptr, pList uintptr) {
|
|
var i int32
|
|
var p, pNext, pNextChange, pTab uintptr
|
|
_, _, _, _, _ = i, p, pNext, pNextChange, pTab
|
|
pTab = pList
|
|
for {
|
|
if !(pTab != 0) {
|
|
break
|
|
}
|
|
pNext = (*TSessionTable)(unsafe.Pointer(pTab)).FpNext
|
|
i = 0
|
|
for {
|
|
if !(i < (*TSessionTable)(unsafe.Pointer(pTab)).FnChange) {
|
|
break
|
|
}
|
|
p = **(**uintptr)(__ccgo_up((*TSessionTable)(unsafe.Pointer(pTab)).FapChange + uintptr(i)*8))
|
|
for {
|
|
if !(p != 0) {
|
|
break
|
|
}
|
|
pNextChange = (*TSessionChange)(unsafe.Pointer(p)).FpNext
|
|
_sessionFree(tls, pSession, p)
|
|
goto _3
|
|
_3:
|
|
;
|
|
p = pNextChange
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
Xsqlite3_finalize(tls, (*TSessionTable)(unsafe.Pointer(pTab)).FpDfltStmt)
|
|
_sessionFree(tls, pSession, (*TSessionTable)(unsafe.Pointer(pTab)).FazCol) /* cast works around VC++ bug */
|
|
_sessionFree(tls, pSession, (*TSessionTable)(unsafe.Pointer(pTab)).FapChange)
|
|
_sessionFree(tls, pSession, pTab)
|
|
goto _1
|
|
_1:
|
|
;
|
|
pTab = pNext
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free buffer pFree, which must have been allocated by an earlier
|
|
// ** call to sessionMalloc64(). If pSession is not NULL, decrease the
|
|
// ** sqlite3_session.nMalloc counter by the number of bytes freed.
|
|
// */
|
|
func _sessionFree(tls *libc.TLS, pSession uintptr, pFree uintptr) {
|
|
var v1 uintptr
|
|
_ = v1
|
|
if pSession != 0 {
|
|
v1 = pSession + 56
|
|
*(*Ti64)(unsafe.Pointer(v1)) = Ti64(uint64(*(*Ti64)(unsafe.Pointer(v1))) - Xsqlite3_msize(tls, pFree))
|
|
}
|
|
Xsqlite3_free(tls, pFree)
|
|
}
|
|
|
|
/*
|
|
** This macro is used to calculate hash key values for data structures. In
|
|
** order to use this macro, the entire data structure must be represented
|
|
** as a series of unsigned integers. In order to calculate a hash-key value
|
|
** for a data structure represented as three such integers, the macro may
|
|
** then be used as follows:
|
|
**
|
|
** int hash_key_value;
|
|
** hash_key_value = HASH_APPEND(0, <value 1>);
|
|
** hash_key_value = HASH_APPEND(hash_key_value, <value 2>);
|
|
** hash_key_value = HASH_APPEND(hash_key_value, <value 3>);
|
|
**
|
|
** In practice, the data structures this macro is used for are the primary
|
|
** key values of modified rows.
|
|
*/
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Ensure that there are at least nByte bytes available in the buffer. Or,
|
|
// ** if there are not nByte bytes remaining in the input, that all available
|
|
// ** data is in the buffer.
|
|
// **
|
|
// ** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise.
|
|
// */
|
|
func _sessionInputBuffer(tls *libc.TLS, pIn uintptr, nByte int32) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var _ /* nNew at bp+4 */ int32
|
|
var _ /* rc at bp+0 */ int32
|
|
**(**int32)(__ccgo_up(bp)) = SQLITE_OK
|
|
if (*TSessionInput)(unsafe.Pointer(pIn)).FxInput != 0 {
|
|
for !((*TSessionInput)(unsafe.Pointer(pIn)).FbEof != 0) && (*TSessionInput)(unsafe.Pointer(pIn)).FiNext+nByte >= (*TSessionInput)(unsafe.Pointer(pIn)).FnData && **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
**(**int32)(__ccgo_up(bp + 4)) = _sessions_strm_chunk_size
|
|
if (*TSessionInput)(unsafe.Pointer(pIn)).FbNoDiscard == 0 {
|
|
_sessionDiscardData(tls, pIn)
|
|
}
|
|
if SQLITE_OK == _sessionBufferGrow(tls, pIn+32, int64(**(**int32)(__ccgo_up(bp + 4))), bp) {
|
|
**(**int32)(__ccgo_up(bp)) = (*(*func(*libc.TLS, uintptr, uintptr, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{(*TSessionInput)(unsafe.Pointer(pIn)).FxInput})))(tls, (*TSessionInput)(unsafe.Pointer(pIn)).FpIn, (*TSessionInput)(unsafe.Pointer(pIn)).Fbuf.FaBuf+uintptr((*TSessionInput)(unsafe.Pointer(pIn)).Fbuf.FnBuf), bp+4)
|
|
if **(**int32)(__ccgo_up(bp + 4)) == 0 {
|
|
(*TSessionInput)(unsafe.Pointer(pIn)).FbEof = int32(1)
|
|
} else {
|
|
(*TSessionInput)(unsafe.Pointer(pIn)).Fbuf.FnBuf += **(**int32)(__ccgo_up(bp + 4))
|
|
}
|
|
}
|
|
(*TSessionInput)(unsafe.Pointer(pIn)).FaData = (*TSessionInput)(unsafe.Pointer(pIn)).Fbuf.FaBuf
|
|
(*TSessionInput)(unsafe.Pointer(pIn)).FnData = (*TSessionInput)(unsafe.Pointer(pIn)).Fbuf.FnBuf
|
|
}
|
|
}
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Add the change currently indicated by iterator pIter to the hash table
|
|
// ** belonging to changegroup pGrp.
|
|
// */
|
|
func _sessionOneChangeIterToHash(tls *libc.TLS, pGrp uintptr, pIter uintptr, bRebase int32) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var aRec uintptr
|
|
var nRec, rc int32
|
|
var _ /* bIndirect at bp+16 */ int32
|
|
var _ /* nCol at bp+8 */ int32
|
|
var _ /* op at bp+12 */ int32
|
|
var _ /* pTab at bp+24 */ uintptr
|
|
var _ /* zTab at bp+0 */ uintptr
|
|
_, _, _ = aRec, nRec, rc
|
|
aRec = (*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).Fin.FaData + uintptr((*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).Fin.FiCurrent+int32(2))
|
|
nRec = (*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).Fin.FiNext - (*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).Fin.FiCurrent - int32(2)
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
**(**int32)(__ccgo_up(bp + 8)) = 0
|
|
**(**int32)(__ccgo_up(bp + 12)) = 0
|
|
**(**int32)(__ccgo_up(bp + 16)) = 0
|
|
rc = SQLITE_OK
|
|
**(**uintptr)(__ccgo_up(bp + 24)) = uintptr(0)
|
|
/* Ensure that only changesets, or only patchsets, but not a mixture
|
|
** of both, are being combined. It is an error to try to combine a
|
|
** changeset and a patchset. */
|
|
if (*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).FpList == uintptr(0) {
|
|
(*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).FbPatch = (*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).FbPatchset
|
|
} else {
|
|
if (*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).FbPatchset != (*Tsqlite3_changegroup)(unsafe.Pointer(pGrp)).FbPatch {
|
|
rc = int32(SQLITE_ERROR)
|
|
}
|
|
}
|
|
if rc == SQLITE_OK {
|
|
Xsqlite3changeset_op(tls, pIter, bp, bp+8, bp+12, bp+16)
|
|
rc = _sessionChangesetFindTable(tls, pGrp, **(**uintptr)(__ccgo_up(bp)), pIter, bp+24)
|
|
}
|
|
if rc == SQLITE_OK {
|
|
rc = _sessionOneChangeToHash(tls, pGrp, **(**uintptr)(__ccgo_up(bp + 24)), **(**int32)(__ccgo_up(bp + 12)), **(**int32)(__ccgo_up(bp + 16)), **(**int32)(__ccgo_up(bp + 8)), aRec, nRec, bRebase)
|
|
}
|
|
if rc == SQLITE_OK {
|
|
rc = (*Tsqlite3_changeset_iter)(unsafe.Pointer(pIter)).Frc
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Set the safety_level and pager flags for pager iDb. Or if iDb<0
|
|
// ** set these values for all pagers.
|
|
// */
|
|
func _setAllPagerFlags(tls *libc.TLS, db uintptr) {
|
|
var n, v1 int32
|
|
var pDb uintptr
|
|
_, _, _ = n, pDb, v1
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FautoCommit != 0 {
|
|
pDb = (*Tsqlite3)(unsafe.Pointer(db)).FaDb
|
|
n = (*Tsqlite3)(unsafe.Pointer(db)).FnDb
|
|
for {
|
|
v1 = n
|
|
n = n - 1
|
|
if !(v1 > 0) {
|
|
break
|
|
}
|
|
if (*TDb)(unsafe.Pointer(pDb)).FpBt != 0 {
|
|
_sqlite3BtreeSetPagerFlags(tls, (*TDb)(unsafe.Pointer(pDb)).FpBt, uint32(uint64((*TDb)(unsafe.Pointer(pDb)).Fsafety_level)|(*Tsqlite3)(unsafe.Pointer(db)).Fflags&uint64(PAGER_FLAGS_MASK)))
|
|
}
|
|
pDb += 32
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Generate VDBE code that prepares for doing an operation that
|
|
// ** might change the database.
|
|
// **
|
|
// ** This routine starts a new transaction if we are not already within
|
|
// ** a transaction. If we are already within a transaction, then a checkpoint
|
|
// ** is set if the setStatement parameter is true. A checkpoint should
|
|
// ** be set for operations that might fail (due to a constraint) part of
|
|
// ** the way through and which will need to undo some writes without having to
|
|
// ** rollback the whole transaction. For operations where all constraints
|
|
// ** can be checked before any changes are made to the database, it is never
|
|
// ** necessary to undo a write and the checkpoint should not be set.
|
|
// */
|
|
func _sqlite3BeginWriteOperation(tls *libc.TLS, pParse uintptr, setStatement int32, iDb int32) {
|
|
var pToplevel, v1 uintptr
|
|
_, _ = pToplevel, v1
|
|
if (*TParse)(unsafe.Pointer(pParse)).FpToplevel != 0 {
|
|
v1 = (*TParse)(unsafe.Pointer(pParse)).FpToplevel
|
|
} else {
|
|
v1 = pParse
|
|
}
|
|
pToplevel = v1
|
|
_sqlite3CodeVerifySchemaAtToplevel(tls, pToplevel, iDb)
|
|
**(**TyDbMask)(__ccgo_up(pToplevel + 120)) |= libc.Uint32FromInt32(1) << iDb
|
|
v1 = pToplevel + 32
|
|
*(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) | setStatement)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Destroy a bitmap object. Reclaim all memory used.
|
|
// */
|
|
func _sqlite3BitvecDestroy(tls *libc.TLS, p uintptr) {
|
|
var i uint32
|
|
_ = i
|
|
if p == uintptr(0) {
|
|
return
|
|
}
|
|
if (*TBitvec)(unsafe.Pointer(p)).FiDivisor != 0 {
|
|
i = uint32(0)
|
|
for {
|
|
if !(i < uint32((libc.Uint64FromInt32(BITVEC_SZ)-libc.Uint64FromInt32(3)*libc.Uint64FromInt64(4))/libc.Uint64FromInt64(8)*libc.Uint64FromInt64(8)/libc.Uint64FromInt64(8))) {
|
|
break
|
|
}
|
|
_sqlite3BitvecDestroy(tls, **(**uintptr)(__ccgo_up(p + 16 + uintptr(i)*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
Xsqlite3_free(tls, p)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Run a checkpoint on database iDb. This is a no-op if database iDb is
|
|
// ** not currently open in WAL mode.
|
|
// **
|
|
// ** If a transaction is open on the database being checkpointed, this
|
|
// ** function returns SQLITE_LOCKED and a checkpoint is not attempted. If
|
|
// ** an error occurs while running the checkpoint, an SQLite error code is
|
|
// ** returned (i.e. SQLITE_IOERR). Otherwise, SQLITE_OK.
|
|
// **
|
|
// ** The mutex on database handle db should be held by the caller. The mutex
|
|
// ** associated with the specific b-tree being checkpointed is taken by
|
|
// ** this function while the checkpoint is running.
|
|
// **
|
|
// ** If iDb is passed SQLITE_MAX_DB then all attached databases are
|
|
// ** checkpointed. If an error is encountered it is returned immediately -
|
|
// ** no attempt is made to checkpoint any remaining databases.
|
|
// **
|
|
// ** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL, RESTART
|
|
// ** or TRUNCATE.
|
|
// */
|
|
func _sqlite3Checkpoint(tls *libc.TLS, db uintptr, iDb int32, eMode int32, pnLog uintptr, pnCkpt uintptr) (r int32) {
|
|
var bBusy, i, rc, v2 int32
|
|
_, _, _, _ = bBusy, i, rc, v2
|
|
rc = SQLITE_OK /* Used to iterate through attached dbs */
|
|
bBusy = 0 /* True if SQLITE_BUSY has been encountered */
|
|
/* See forum post a006d86f72 */
|
|
i = 0
|
|
for {
|
|
if !(i < (*Tsqlite3)(unsafe.Pointer(db)).FnDb && rc == SQLITE_OK) {
|
|
break
|
|
}
|
|
if i == iDb || iDb == libc.Int32FromInt32(SQLITE_MAX_ATTACHED)+libc.Int32FromInt32(2) {
|
|
rc = _sqlite3BtreeCheckpoint(tls, (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(i)*32))).FpBt, eMode, pnLog, pnCkpt)
|
|
pnLog = uintptr(0)
|
|
pnCkpt = uintptr(0)
|
|
if rc == int32(SQLITE_BUSY) {
|
|
bBusy = int32(1)
|
|
rc = SQLITE_OK
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if rc == SQLITE_OK && bBusy != 0 {
|
|
v2 = int32(SQLITE_BUSY)
|
|
} else {
|
|
v2 = rc
|
|
}
|
|
return v2
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Call this routine when the database connection is closing in order
|
|
// ** to clean up loaded extensions
|
|
// */
|
|
func _sqlite3CloseExtensions(tls *libc.TLS, db uintptr) {
|
|
var i int32
|
|
_ = i
|
|
i = 0
|
|
for {
|
|
if !(i < (*Tsqlite3)(unsafe.Pointer(db)).FnExtension) {
|
|
break
|
|
}
|
|
_sqlite3OsDlClose(tls, (*Tsqlite3)(unsafe.Pointer(db)).FpVfs, **(**uintptr)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaExtension + uintptr(i)*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_sqlite3DbFree(tls, db, (*Tsqlite3)(unsafe.Pointer(db)).FaExtension)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If argument zDb is NULL, then call sqlite3CodeVerifySchema() for each
|
|
// ** attached database. Otherwise, invoke it for the database named zDb only.
|
|
// */
|
|
func _sqlite3CodeVerifyNamedSchema(tls *libc.TLS, pParse uintptr, zDb uintptr) {
|
|
var db, pDb uintptr
|
|
var i int32
|
|
_, _, _ = db, i, pDb
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
i = 0
|
|
for {
|
|
if !(i < (*Tsqlite3)(unsafe.Pointer(db)).FnDb) {
|
|
break
|
|
}
|
|
pDb = (*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(i)*32
|
|
if (*TDb)(unsafe.Pointer(pDb)).FpBt != 0 && (!(zDb != 0) || 0 == _sqlite3StrICmp(tls, zDb, (*TDb)(unsafe.Pointer(pDb)).FzDbSName)) {
|
|
_sqlite3CodeVerifySchema(tls, pParse, i)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Record the fact that the schema cookie will need to be verified
|
|
// ** for database iDb. The code to actually verify the schema cookie
|
|
// ** will occur at the end of the top-level VDBE and will be generated
|
|
// ** later, by sqlite3FinishCoding().
|
|
// */
|
|
func _sqlite3CodeVerifySchemaAtToplevel(tls *libc.TLS, pToplevel uintptr, iDb int32) {
|
|
if libc.BoolInt32((*TParse)(unsafe.Pointer(pToplevel)).FcookieMask&(libc.Uint32FromInt32(1)<<iDb) != uint32(0)) == 0 {
|
|
**(**TyDbMask)(__ccgo_up(pToplevel + 124)) |= libc.Uint32FromInt32(1) << iDb
|
|
if libc.Bool(!(libc.Int32FromInt32(OMIT_TEMPDB) != 0)) && iDb == int32(1) {
|
|
_sqlite3OpenTempDatabase(tls, pToplevel)
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Create a new CTE object
|
|
// */
|
|
func _sqlite3CteNew(tls *libc.TLS, pParse uintptr, pName uintptr, pArglist uintptr, pQuery uintptr, eM10d Tu8) (r uintptr) {
|
|
var db, pNew uintptr
|
|
_, _ = db, pNew
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
pNew = _sqlite3DbMallocZero(tls, db, uint64(48))
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
|
|
_sqlite3ExprListDelete(tls, db, pArglist)
|
|
_sqlite3SelectDelete(tls, db, pQuery)
|
|
} else {
|
|
(*TCte)(unsafe.Pointer(pNew)).FpSelect = pQuery
|
|
(*TCte)(unsafe.Pointer(pNew)).FpCols = pArglist
|
|
(*TCte)(unsafe.Pointer(pNew)).FzName = _sqlite3NameFromToken(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pName)
|
|
(*TCte)(unsafe.Pointer(pNew)).FeM10d = eM10d
|
|
}
|
|
return pNew
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free memory that might be associated with a particular database
|
|
// ** connection. Calling sqlite3DbFree(D,X) for X==0 is a harmless no-op.
|
|
// ** The sqlite3DbFreeNN(D,X) version requires that X be non-NULL.
|
|
// */
|
|
func _sqlite3DbFreeNN(tls *libc.TLS, db uintptr, p uintptr) {
|
|
var pBuf, pBuf1 uintptr
|
|
_, _ = pBuf, pBuf1
|
|
if db != 0 {
|
|
if uint64(p) < uint64((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpEnd) {
|
|
if uint64(p) >= uint64((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpMiddle) {
|
|
pBuf = p
|
|
(*TLookasideSlot)(unsafe.Pointer(pBuf)).FpNext = (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpSmallFree
|
|
(*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpSmallFree = pBuf
|
|
return
|
|
}
|
|
if uint64(p) >= uint64((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpStart) {
|
|
pBuf1 = p
|
|
(*TLookasideSlot)(unsafe.Pointer(pBuf1)).FpNext = (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpFree
|
|
(*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpFree = pBuf1
|
|
return
|
|
}
|
|
}
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FpnBytesFreed != 0 {
|
|
_measureAllocationSize(tls, db, p)
|
|
return
|
|
}
|
|
}
|
|
Xsqlite3_free(tls, p)
|
|
}
|
|
|
|
func _sqlite3DbMallocRawNN(tls *libc.TLS, db uintptr, n Tu64) (r uintptr) {
|
|
var pBuf, v1 uintptr
|
|
_, _ = pBuf, v1
|
|
if n > uint64((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.Fsz) {
|
|
if !((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FbDisable != 0) {
|
|
**(**Tu32)(__ccgo_up(db + 440 + 16 + 1*4)) = **(**Tu32)(__ccgo_up(db + 440 + 16 + 1*4)) + 1
|
|
} else {
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
|
|
return uintptr(0)
|
|
}
|
|
}
|
|
return _dbMallocRawFinish(tls, db, n)
|
|
}
|
|
if n <= uint64(LOOKASIDE_SMALL) {
|
|
v1 = (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpSmallFree
|
|
pBuf = v1
|
|
if v1 != uintptr(0) {
|
|
(*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpSmallFree = (*TLookasideSlot)(unsafe.Pointer(pBuf)).FpNext
|
|
**(**Tu32)(__ccgo_up(db + 440 + 16)) = **(**Tu32)(__ccgo_up(db + 440 + 16)) + 1
|
|
return pBuf
|
|
} else {
|
|
v1 = (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpSmallInit
|
|
pBuf = v1
|
|
if v1 != uintptr(0) {
|
|
(*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpSmallInit = (*TLookasideSlot)(unsafe.Pointer(pBuf)).FpNext
|
|
**(**Tu32)(__ccgo_up(db + 440 + 16)) = **(**Tu32)(__ccgo_up(db + 440 + 16)) + 1
|
|
return pBuf
|
|
}
|
|
}
|
|
}
|
|
v1 = (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpFree
|
|
pBuf = v1
|
|
if v1 != uintptr(0) {
|
|
(*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpFree = (*TLookasideSlot)(unsafe.Pointer(pBuf)).FpNext
|
|
**(**Tu32)(__ccgo_up(db + 440 + 16)) = **(**Tu32)(__ccgo_up(db + 440 + 16)) + 1
|
|
return pBuf
|
|
} else {
|
|
v1 = (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpInit
|
|
pBuf = v1
|
|
if v1 != uintptr(0) {
|
|
(*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpInit = (*TLookasideSlot)(unsafe.Pointer(pBuf)).FpNext
|
|
**(**Tu32)(__ccgo_up(db + 440 + 16)) = **(**Tu32)(__ccgo_up(db + 440 + 16)) + 1
|
|
return pBuf
|
|
} else {
|
|
**(**Tu32)(__ccgo_up(db + 440 + 16 + 2*4)) = **(**Tu32)(__ccgo_up(db + 440 + 16 + 2*4)) + 1
|
|
}
|
|
}
|
|
return _dbMallocRawFinish(tls, db, n)
|
|
}
|
|
|
|
func _sqlite3DbNNFreeNN(tls *libc.TLS, db uintptr, p uintptr) {
|
|
var pBuf, pBuf1 uintptr
|
|
_, _ = pBuf, pBuf1
|
|
if uint64(p) < uint64((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpEnd) {
|
|
if uint64(p) >= uint64((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpMiddle) {
|
|
pBuf = p
|
|
(*TLookasideSlot)(unsafe.Pointer(pBuf)).FpNext = (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpSmallFree
|
|
(*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpSmallFree = pBuf
|
|
return
|
|
}
|
|
if uint64(p) >= uint64((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpStart) {
|
|
pBuf1 = p
|
|
(*TLookasideSlot)(unsafe.Pointer(pBuf1)).FpNext = (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpFree
|
|
(*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpFree = pBuf1
|
|
return
|
|
}
|
|
}
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FpnBytesFreed != 0 {
|
|
_measureAllocationSize(tls, db, p)
|
|
return
|
|
}
|
|
Xsqlite3_free(tls, p)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the Btree pointer identified by zDbName. Return NULL if not found.
|
|
// */
|
|
func _sqlite3DbNameToBtree(tls *libc.TLS, db uintptr, zDbName uintptr) (r uintptr) {
|
|
var iDb, v1 int32
|
|
var v2 uintptr
|
|
_, _, _ = iDb, v1, v2
|
|
if zDbName != 0 {
|
|
v1 = _sqlite3FindDbName(tls, db, zDbName)
|
|
} else {
|
|
v1 = 0
|
|
}
|
|
iDb = v1
|
|
if iDb < 0 {
|
|
v2 = uintptr(0)
|
|
} else {
|
|
v2 = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FpBt
|
|
}
|
|
return v2
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Resize the block of memory pointed to by p to n bytes. If the
|
|
// ** resize fails, set the mallocFailed flag in the connection object.
|
|
// */
|
|
func _sqlite3DbRealloc(tls *libc.TLS, db uintptr, p uintptr, n Tu64) (r uintptr) {
|
|
if p == uintptr(0) {
|
|
return _sqlite3DbMallocRawNN(tls, db, n)
|
|
}
|
|
if uint64(p) < uint64((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpEnd) {
|
|
if uint64(p) >= uint64((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpMiddle) {
|
|
if n <= uint64(LOOKASIDE_SMALL) {
|
|
return p
|
|
}
|
|
} else {
|
|
if uint64(p) >= uint64((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpStart) {
|
|
if n <= uint64((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FszTrue) {
|
|
return p
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return _dbReallocFinish(tls, db, p, n)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If the Index.aSample variable is not NULL, delete the aSample[] array
|
|
// ** and its contents.
|
|
// */
|
|
func _sqlite3DeleteIndexSamples(tls *libc.TLS, db uintptr, pIdx uintptr) {
|
|
var j int32
|
|
var p uintptr
|
|
_, _ = j, p
|
|
if (*TIndex)(unsafe.Pointer(pIdx)).FaSample != 0 {
|
|
j = 0
|
|
for {
|
|
if !(j < (*TIndex)(unsafe.Pointer(pIdx)).FnSample) {
|
|
break
|
|
}
|
|
p = (*TIndex)(unsafe.Pointer(pIdx)).FaSample + uintptr(j)*40
|
|
_sqlite3DbFree(tls, db, (*TIndexSample)(unsafe.Pointer(p)).Fp)
|
|
goto _1
|
|
_1:
|
|
;
|
|
j = j + 1
|
|
}
|
|
_sqlite3DbFree(tls, db, (*TIndex)(unsafe.Pointer(pIdx)).FaSample)
|
|
}
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FpnBytesFreed == uintptr(0) {
|
|
(*TIndex)(unsafe.Pointer(pIdx)).FnSample = 0
|
|
(*TIndex)(unsafe.Pointer(pIdx)).FaSample = uintptr(0)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Clean up the data structures associated with the RETURNING clause.
|
|
// */
|
|
func _sqlite3DeleteReturning(tls *libc.TLS, db uintptr, pArg uintptr) {
|
|
var pHash, pRet uintptr
|
|
_, _ = pHash, pRet
|
|
pRet = pArg
|
|
pHash = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + 1*32))).FpSchema + 56
|
|
_sqlite3HashInsert(tls, pHash, pRet+188, uintptr(0))
|
|
_sqlite3ExprListDelete(tls, db, (*TReturning)(unsafe.Pointer(pRet)).FpReturnEL)
|
|
_sqlite3DbFree(tls, db, pRet)
|
|
}
|
|
|
|
func _sqlite3DeleteTable(tls *libc.TLS, db uintptr, pTable uintptr) {
|
|
var v1 Tu32
|
|
var v2 uintptr
|
|
var v3 bool
|
|
_, _, _ = v1, v2, v3
|
|
/* Do not delete the table until the reference count reaches zero. */
|
|
if !(pTable != 0) {
|
|
return
|
|
}
|
|
if v3 = (*Tsqlite3)(unsafe.Pointer(db)).FpnBytesFreed == uintptr(0); v3 {
|
|
v2 = pTable + 44
|
|
*(*Tu32)(unsafe.Pointer(v2)) = *(*Tu32)(unsafe.Pointer(v2)) - 1
|
|
v1 = *(*Tu32)(unsafe.Pointer(v2))
|
|
}
|
|
if v3 && v1 > uint32(0) {
|
|
return
|
|
}
|
|
_deleteTable(tls, db, pTable)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Call sqlite3ExprAnalyzeAggregates() for every expression in an
|
|
// ** expression list. Return the number of errors.
|
|
// **
|
|
// ** If an error is found, the analysis is cut short.
|
|
// */
|
|
func _sqlite3ExprAnalyzeAggList(tls *libc.TLS, pNC uintptr, pList uintptr) {
|
|
var i int32
|
|
var pItem uintptr
|
|
_, _ = i, pItem
|
|
if pList != 0 {
|
|
pItem = pList + 8
|
|
i = libc.Int32FromInt32(0)
|
|
for {
|
|
if !(i < (*TExprList)(unsafe.Pointer(pList)).FnExpr) {
|
|
break
|
|
}
|
|
_sqlite3ExprAnalyzeAggregates(tls, pNC, (*TExprList_item)(unsafe.Pointer(pItem)).FpExpr)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
pItem += 32
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Analyze the pExpr expression looking for aggregate functions and
|
|
// ** for variables that need to be added to AggInfo object that pNC->pAggInfo
|
|
// ** points to. Additional entries are made on the AggInfo object as
|
|
// ** necessary.
|
|
// **
|
|
// ** This routine should only be called after the expression has been
|
|
// ** analyzed by sqlite3ResolveExprNames().
|
|
// */
|
|
func _sqlite3ExprAnalyzeAggregates(tls *libc.TLS, pNC uintptr, pExpr uintptr) {
|
|
bp := tls.Alloc(48)
|
|
defer tls.Free(48)
|
|
var _ /* w at bp+0 */ TWalker
|
|
(**(**TWalker)(__ccgo_up(bp))).FxExprCallback = __ccgo_fp(_analyzeAggregate)
|
|
(**(**TWalker)(__ccgo_up(bp))).FxSelectCallback = __ccgo_fp(_sqlite3WalkerDepthIncrease)
|
|
(**(**TWalker)(__ccgo_up(bp))).FxSelectCallback2 = __ccgo_fp(_sqlite3WalkerDepthDecrease)
|
|
(**(**TWalker)(__ccgo_up(bp))).FwalkerDepth = 0
|
|
*(*uintptr)(unsafe.Pointer(bp + 40)) = pNC
|
|
(**(**TWalker)(__ccgo_up(bp))).FpParse = uintptr(0)
|
|
_sqlite3WalkExpr(tls, bp, pExpr)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Expr pIn is an IN(...) expression. This function checks that the
|
|
// ** sub-select on the RHS of the IN() operator has the same number of
|
|
// ** columns as the vector on the LHS. Or, if the RHS of the IN() is not
|
|
// ** a sub-query, that the LHS is a vector of size 1.
|
|
// */
|
|
func _sqlite3ExprCheckIN(tls *libc.TLS, pParse uintptr, pIn uintptr) (r int32) {
|
|
var nVector int32
|
|
_ = nVector
|
|
nVector = _sqlite3ExprVectorSize(tls, (*TExpr)(unsafe.Pointer(pIn)).FpLeft)
|
|
if (*TExpr)(unsafe.Pointer(pIn)).Fflags&uint32(EP_xIsSelect) != uint32(0) && !((*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer(pParse)).Fdb)).FmallocFailed != 0) {
|
|
if nVector != (*TExprList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pIn + 32)))).FpEList)).FnExpr {
|
|
_sqlite3SubselectError(tls, pParse, (*TExprList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pIn + 32)))).FpEList)).FnExpr, nVector)
|
|
return int32(1)
|
|
}
|
|
} else {
|
|
if nVector != int32(1) {
|
|
_sqlite3VectorErrorMsg(tls, pParse, (*TExpr)(unsafe.Pointer(pIn)).FpLeft)
|
|
return int32(1)
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Generate code that will evaluate expression pExpr and store the
|
|
// ** results in register target. The results are guaranteed to appear
|
|
// ** in register target. If the expression is constant, then this routine
|
|
// ** might choose to code the expression at initialization time.
|
|
// */
|
|
func _sqlite3ExprCodeFactorable(tls *libc.TLS, pParse uintptr, pExpr uintptr, target int32) {
|
|
if int32(Tbft(*(*uint16)(unsafe.Pointer(pParse + 40))&0x80>>7)) != 0 && _sqlite3ExprIsConstantNotJoin(tls, pParse, pExpr) != 0 {
|
|
_sqlite3ExprCodeRunJustOnce(tls, pParse, pExpr, target)
|
|
} else {
|
|
_sqlite3ExprCodeCopy(tls, pParse, pExpr, target)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Generate code that will load into register regOut a value that is
|
|
// ** appropriate for the iIdxCol-th column of index pIdx.
|
|
// */
|
|
func _sqlite3ExprCodeLoadIndexColumn(tls *libc.TLS, pParse uintptr, pIdx uintptr, iTabCur int32, iIdxCol int32, regOut int32) {
|
|
var iTabCol Ti16
|
|
_ = iTabCol
|
|
iTabCol = **(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(iIdxCol)*2))
|
|
if int32(iTabCol) == -int32(2) {
|
|
(*TParse)(unsafe.Pointer(pParse)).FiSelfTab = iTabCur + int32(1)
|
|
_sqlite3ExprCodeCopy(tls, pParse, (*(*TExprList_item)(unsafe.Pointer((*TIndex)(unsafe.Pointer(pIdx)).FaColExpr + 8 + uintptr(iIdxCol)*32))).FpExpr, regOut)
|
|
(*TParse)(unsafe.Pointer(pParse)).FiSelfTab = 0
|
|
} else {
|
|
_sqlite3ExprCodeGetColumnOfTable(tls, (*TParse)(unsafe.Pointer(pParse)).FpVdbe, (*TIndex)(unsafe.Pointer(pIdx)).FpTable, iTabCur, int32(iTabCol), regOut)
|
|
}
|
|
}
|
|
|
|
func _sqlite3ExprListAppend(tls *libc.TLS, pParse uintptr, pList uintptr, pExpr uintptr) (r uintptr) {
|
|
var pItem, v2 uintptr
|
|
var v1 int32
|
|
_, _, _ = pItem, v1, v2
|
|
if pList == uintptr(0) {
|
|
return _sqlite3ExprListAppendNew(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pExpr)
|
|
}
|
|
if (*TExprList)(unsafe.Pointer(pList)).FnAlloc < (*TExprList)(unsafe.Pointer(pList)).FnExpr+int32(1) {
|
|
return _sqlite3ExprListAppendGrow(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pList, pExpr)
|
|
}
|
|
v2 = pList
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
pItem = pList + 8 + uintptr(v1)*32
|
|
**(**TExprList_item)(__ccgo_up(pItem)) = _zeroItem
|
|
(*TExprList_item)(unsafe.Pointer(pItem)).FpExpr = pExpr
|
|
return pList
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the bitwise-OR of all Expr.flags fields in the given
|
|
// ** ExprList.
|
|
// */
|
|
func _sqlite3ExprListFlags(tls *libc.TLS, pList uintptr) (r Tu32) {
|
|
var i int32
|
|
var m Tu32
|
|
var pExpr uintptr
|
|
_, _, _ = i, m, pExpr
|
|
m = uint32(0)
|
|
i = 0
|
|
for {
|
|
if !(i < (*TExprList)(unsafe.Pointer(pList)).FnExpr) {
|
|
break
|
|
}
|
|
pExpr = (*(*TExprList_item)(unsafe.Pointer(pList + 8 + uintptr(i)*32))).FpExpr
|
|
m = m | (*TExpr)(unsafe.Pointer(pExpr)).Fflags
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return m
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Set the ExprList.a[].zSpan element of the most recently added item
|
|
// ** on the expression list.
|
|
// **
|
|
// ** pList might be NULL following an OOM error. But pSpan should never be
|
|
// ** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag
|
|
// ** is set.
|
|
// */
|
|
func _sqlite3ExprListSetSpan(tls *libc.TLS, pParse uintptr, pList uintptr, zStart uintptr, zEnd uintptr) {
|
|
var db, pItem uintptr
|
|
_, _ = db, pItem
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
if pList != 0 {
|
|
pItem = pList + 8 + uintptr((*TExprList)(unsafe.Pointer(pList)).FnExpr-int32(1))*32
|
|
if (*TExprList_item)(unsafe.Pointer(pItem)).FzEName == uintptr(0) {
|
|
(*TExprList_item)(unsafe.Pointer(pItem)).FzEName = _sqlite3DbSpanDup(tls, db, zStart, zEnd)
|
|
libc.SetBitFieldPtr16Uint32(pItem+16+4, libc.Uint32FromInt32(ENAME_SPAN), 0, 0x3)
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Locate the in-memory structure that describes
|
|
// ** a particular index given the name of that index
|
|
// ** and the name of the database that contains the index.
|
|
// ** Return NULL if not found.
|
|
// **
|
|
// ** If zDatabase is 0, all databases are searched for the
|
|
// ** table and the first matching index is returned. (No checking
|
|
// ** for duplicate index names is done.) The search order is
|
|
// ** TEMP first, then MAIN, then any auxiliary databases added
|
|
// ** using the ATTACH command.
|
|
// */
|
|
func _sqlite3FindIndex(tls *libc.TLS, db uintptr, zName uintptr, zDb uintptr) (r uintptr) {
|
|
var i, j, v2 int32
|
|
var p, pSchema uintptr
|
|
_, _, _, _, _ = i, j, p, pSchema, v2
|
|
p = uintptr(0)
|
|
/* All mutexes are required for schema access. Make sure we hold them. */
|
|
i = OMIT_TEMPDB
|
|
for {
|
|
if !(i < (*Tsqlite3)(unsafe.Pointer(db)).FnDb) {
|
|
break
|
|
}
|
|
if i < int32(2) {
|
|
v2 = i ^ int32(1)
|
|
} else {
|
|
v2 = i
|
|
}
|
|
j = v2 /* Search TEMP before MAIN */
|
|
pSchema = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(j)*32))).FpSchema
|
|
if zDb != 0 && _sqlite3DbIsNamed(tls, db, j, zDb) == 0 {
|
|
goto _1
|
|
}
|
|
p = _sqlite3HashFind(tls, pSchema+32, zName)
|
|
if p != 0 {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return p
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the latest reusable register in the set of all registers.
|
|
// ** The value returned is no less than iMin. If any register iMin or
|
|
// ** greater is in permanent use, then return one more than that last
|
|
// ** permanent register.
|
|
// */
|
|
func _sqlite3FirstAvailableRegister(tls *libc.TLS, pParse uintptr, iMin int32) (r int32) {
|
|
var i int32
|
|
var pList uintptr
|
|
_, _ = i, pList
|
|
pList = (*TParse)(unsafe.Pointer(pParse)).FpConstExpr
|
|
if pList != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TExprList)(unsafe.Pointer(pList)).FnExpr) {
|
|
break
|
|
}
|
|
if *(*int32)(unsafe.Pointer(pList + 8 + uintptr(i)*32 + 24)) >= iMin {
|
|
iMin = *(*int32)(unsafe.Pointer(pList + 8 + uintptr(i)*32 + 24)) + int32(1)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
(*TParse)(unsafe.Pointer(pParse)).FnTempReg = uint8(0)
|
|
(*TParse)(unsafe.Pointer(pParse)).FnRangeReg = 0
|
|
return iMin
|
|
}
|
|
|
|
/*
|
|
** Validate that no temporary register falls within the range of
|
|
** iFirst..iLast, inclusive. This routine is only call from within assert()
|
|
** statements.
|
|
*/
|
|
|
|
/************** End of expr.c ************************************************/
|
|
/************** Begin file alter.c *******************************************/
|
|
/*
|
|
** 2005 February 15
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** This file contains C code routines that used to generate VDBE code
|
|
** that implements the ALTER TABLE command.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/*
|
|
** The code in this file only exists if we are not omitting the
|
|
** ALTER TABLE logic from the build.
|
|
*/
|
|
|
|
func _sqlite3FixExpr(tls *libc.TLS, pFix uintptr, pExpr uintptr) (r int32) {
|
|
return _sqlite3WalkExpr(tls, pFix+8, pExpr)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Initialize a DbFixer structure. This routine must be called prior
|
|
// ** to passing the structure to one of the sqliteFixAAAA() routines below.
|
|
// */
|
|
func _sqlite3FixInit(tls *libc.TLS, pFix uintptr, pParse uintptr, iDb int32, zType uintptr, pName uintptr) {
|
|
var db uintptr
|
|
_ = db
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
(*TDbFixer)(unsafe.Pointer(pFix)).FpParse = pParse
|
|
(*TDbFixer)(unsafe.Pointer(pFix)).FzDb = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FzDbSName
|
|
(*TDbFixer)(unsafe.Pointer(pFix)).FpSchema = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FpSchema
|
|
(*TDbFixer)(unsafe.Pointer(pFix)).FzType = zType
|
|
(*TDbFixer)(unsafe.Pointer(pFix)).FpName = pName
|
|
(*TDbFixer)(unsafe.Pointer(pFix)).FbTemp = libc.BoolUint8(iDb == libc.Int32FromInt32(1))
|
|
(*TDbFixer)(unsafe.Pointer(pFix)).Fw.FpParse = pParse
|
|
(*TDbFixer)(unsafe.Pointer(pFix)).Fw.FxExprCallback = __ccgo_fp(_fixExprCb)
|
|
(*TDbFixer)(unsafe.Pointer(pFix)).Fw.FxSelectCallback = __ccgo_fp(_fixSelectCb)
|
|
(*TDbFixer)(unsafe.Pointer(pFix)).Fw.FxSelectCallback2 = __ccgo_fp(_sqlite3WalkWinDefnDummyCallback)
|
|
(*TDbFixer)(unsafe.Pointer(pFix)).Fw.FwalkerDepth = 0
|
|
(*TDbFixer)(unsafe.Pointer(pFix)).Fw.FeCode = uint16(0)
|
|
*(*uintptr)(unsafe.Pointer(pFix + 8 + 40)) = pFix
|
|
}
|
|
|
|
func _sqlite3FixSelect(tls *libc.TLS, pFix uintptr, pSelect uintptr) (r int32) {
|
|
return _sqlite3WalkSelect(tls, pFix+8, pSelect)
|
|
}
|
|
|
|
func _sqlite3FixTriggerStep(tls *libc.TLS, pFix uintptr, pStep uintptr) (r int32) {
|
|
var pUp uintptr
|
|
_ = pUp
|
|
for pStep != 0 {
|
|
if _sqlite3WalkSelect(tls, pFix+8, (*TTriggerStep)(unsafe.Pointer(pStep)).FpSelect) != 0 || _sqlite3WalkExpr(tls, pFix+8, (*TTriggerStep)(unsafe.Pointer(pStep)).FpWhere) != 0 || _sqlite3WalkExprList(tls, pFix+8, (*TTriggerStep)(unsafe.Pointer(pStep)).FpExprList) != 0 || _sqlite3FixSrcList(tls, pFix, (*TTriggerStep)(unsafe.Pointer(pStep)).FpSrc) != 0 {
|
|
return int32(1)
|
|
}
|
|
pUp = (*TTriggerStep)(unsafe.Pointer(pStep)).FpUpsert
|
|
for {
|
|
if !(pUp != 0) {
|
|
break
|
|
}
|
|
if _sqlite3WalkExprList(tls, pFix+8, (*TUpsert)(unsafe.Pointer(pUp)).FpUpsertTarget) != 0 || _sqlite3WalkExpr(tls, pFix+8, (*TUpsert)(unsafe.Pointer(pUp)).FpUpsertTargetWhere) != 0 || _sqlite3WalkExprList(tls, pFix+8, (*TUpsert)(unsafe.Pointer(pUp)).FpUpsertSet) != 0 || _sqlite3WalkExpr(tls, pFix+8, (*TUpsert)(unsafe.Pointer(pUp)).FpUpsertWhere) != 0 {
|
|
return int32(1)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pUp = (*TUpsert)(unsafe.Pointer(pUp)).FpNextUpsert
|
|
}
|
|
pStep = (*TTriggerStep)(unsafe.Pointer(pStep)).FpNext
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free all memory associated with foreign key definitions attached to
|
|
// ** table pTab. Remove the deleted foreign keys from the Schema.fkeyHash
|
|
// ** hash table.
|
|
// */
|
|
func _sqlite3FkDelete(tls *libc.TLS, db uintptr, pTab uintptr) {
|
|
var pFKey, pNext, z, v2 uintptr
|
|
_, _, _, _ = pFKey, pNext, z, v2 /* Copy of pFKey->pNextFrom */
|
|
pFKey = (*(*struct {
|
|
FaddColOffset int32
|
|
FpFKey uintptr
|
|
FpDfltList uintptr
|
|
})(unsafe.Pointer(pTab + 64))).FpFKey
|
|
for {
|
|
if !(pFKey != 0) {
|
|
break
|
|
}
|
|
/* Remove the FK from the fkeyHash hash table. */
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FpnBytesFreed == uintptr(0) {
|
|
if (*TFKey)(unsafe.Pointer(pFKey)).FpPrevTo != 0 {
|
|
(*TFKey)(unsafe.Pointer((*TFKey)(unsafe.Pointer(pFKey)).FpPrevTo)).FpNextTo = (*TFKey)(unsafe.Pointer(pFKey)).FpNextTo
|
|
} else {
|
|
if (*TFKey)(unsafe.Pointer(pFKey)).FpNextTo != 0 {
|
|
v2 = (*TFKey)(unsafe.Pointer((*TFKey)(unsafe.Pointer(pFKey)).FpNextTo)).FzTo
|
|
} else {
|
|
v2 = (*TFKey)(unsafe.Pointer(pFKey)).FzTo
|
|
}
|
|
z = v2
|
|
_sqlite3HashInsert(tls, (*TTable)(unsafe.Pointer(pTab)).FpSchema+80, z, (*TFKey)(unsafe.Pointer(pFKey)).FpNextTo)
|
|
}
|
|
if (*TFKey)(unsafe.Pointer(pFKey)).FpNextTo != 0 {
|
|
(*TFKey)(unsafe.Pointer((*TFKey)(unsafe.Pointer(pFKey)).FpNextTo)).FpPrevTo = (*TFKey)(unsafe.Pointer(pFKey)).FpPrevTo
|
|
}
|
|
}
|
|
/* EV: R-30323-21917 Each foreign key constraint in SQLite is
|
|
** classified as either immediate or deferred.
|
|
*/
|
|
/* Delete any triggers created to implement actions for this FK. */
|
|
_fkTriggerDelete(tls, db, **(**uintptr)(__ccgo_up(pFKey + 48)))
|
|
_fkTriggerDelete(tls, db, **(**uintptr)(__ccgo_up(pFKey + 48 + 1*8)))
|
|
pNext = (*TFKey)(unsafe.Pointer(pFKey)).FpNextFrom
|
|
_sqlite3DbFree(tls, db, pFKey)
|
|
goto _1
|
|
_1:
|
|
;
|
|
pFKey = pNext
|
|
}
|
|
}
|
|
|
|
/************** End of fkey.c ************************************************/
|
|
/************** Begin file insert.c ******************************************/
|
|
/*
|
|
** 2001 September 15
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** This file contains C code routines that are called by the parser
|
|
** to handle INSERT statements in SQLite.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function returns a linked list of FKey objects (connected by
|
|
// ** FKey.pNextTo) holding all children of table pTab. For example,
|
|
// ** given the following schema:
|
|
// **
|
|
// ** CREATE TABLE t1(a PRIMARY KEY);
|
|
// ** CREATE TABLE t2(b REFERENCES t1(a);
|
|
// **
|
|
// ** Calling this function with table "t1" as an argument returns a pointer
|
|
// ** to the FKey structure representing the foreign key constraint on table
|
|
// ** "t2". Calling this function with "t2" as the argument would return a
|
|
// ** NULL pointer (as there are no FK constraints for which t2 is the parent
|
|
// ** table).
|
|
// */
|
|
func _sqlite3FkReferences(tls *libc.TLS, pTab uintptr) (r uintptr) {
|
|
return _sqlite3HashFind(tls, (*TTable)(unsafe.Pointer(pTab)).FpSchema+80, (*TTable)(unsafe.Pointer(pTab)).FzName)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Insert a single OP_JournalMode query opcode in order to force the
|
|
// ** prepared statement to return false for sqlite3_stmt_readonly(). This
|
|
// ** is used by CREATE TABLE IF NOT EXISTS and similar if the table already
|
|
// ** exists, so that the prepared statement for CREATE TABLE IF NOT EXISTS
|
|
// ** will return false for sqlite3_stmt_readonly() even if that statement
|
|
// ** is a read-only no-op.
|
|
// */
|
|
func _sqlite3ForceNotReadOnly(tls *libc.TLS, pParse uintptr) {
|
|
var iReg, v1 int32
|
|
var v, v2 uintptr
|
|
_, _, _, _ = iReg, v, v1, v2
|
|
v2 = pParse + 60
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
iReg = v1
|
|
v = _sqlite3GetVdbe(tls, pParse)
|
|
if v != 0 {
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_JournalMode), 0, iReg, -int32(1))
|
|
_sqlite3VdbeUsesBtree(tls, v, 0)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Reclaim the memory used by an index
|
|
// */
|
|
func _sqlite3FreeIndex(tls *libc.TLS, db uintptr, p uintptr) {
|
|
_sqlite3DeleteIndexSamples(tls, db, p)
|
|
_sqlite3ExprDelete(tls, db, (*TIndex)(unsafe.Pointer(p)).FpPartIdxWhere)
|
|
_sqlite3ExprListDelete(tls, db, (*TIndex)(unsafe.Pointer(p)).FaColExpr)
|
|
_sqlite3DbFree(tls, db, (*TIndex)(unsafe.Pointer(p)).FzColAff)
|
|
if int32(uint32(*(*uint16)(unsafe.Pointer(p + 100))&0x10>>4)) != 0 {
|
|
_sqlite3DbFree(tls, db, (*TIndex)(unsafe.Pointer(p)).FazColl)
|
|
}
|
|
Xsqlite3_free(tls, (*TIndex)(unsafe.Pointer(p)).FaiRowEst)
|
|
_sqlite3DbFree(tls, db, p)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free the configuration object passed as the only argument.
|
|
// */
|
|
func _sqlite3Fts5ConfigFree(tls *libc.TLS, pConfig uintptr) {
|
|
var i int32
|
|
_ = i
|
|
if pConfig != 0 {
|
|
if (*TFts5Config)(unsafe.Pointer(pConfig)).Ft.FpTok != 0 {
|
|
if (*TFts5Config)(unsafe.Pointer(pConfig)).Ft.FpApi1 != 0 {
|
|
(*(*func(*libc.TLS, uintptr))(unsafe.Pointer(&struct{ uintptr }{(*Tfts5_tokenizer)(unsafe.Pointer((*TFts5Config)(unsafe.Pointer(pConfig)).Ft.FpApi1)).FxDelete})))(tls, (*TFts5Config)(unsafe.Pointer(pConfig)).Ft.FpTok)
|
|
} else {
|
|
(*(*func(*libc.TLS, uintptr))(unsafe.Pointer(&struct{ uintptr }{(*Tfts5_tokenizer_v2)(unsafe.Pointer((*TFts5Config)(unsafe.Pointer(pConfig)).Ft.FpApi2)).FxDelete})))(tls, (*TFts5Config)(unsafe.Pointer(pConfig)).Ft.FpTok)
|
|
}
|
|
}
|
|
Xsqlite3_free(tls, (*TFts5Config)(unsafe.Pointer(pConfig)).Ft.FazArg)
|
|
Xsqlite3_free(tls, (*TFts5Config)(unsafe.Pointer(pConfig)).FzDb)
|
|
Xsqlite3_free(tls, (*TFts5Config)(unsafe.Pointer(pConfig)).FzName)
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5Config)(unsafe.Pointer(pConfig)).FnCol) {
|
|
break
|
|
}
|
|
Xsqlite3_free(tls, **(**uintptr)(__ccgo_up((*TFts5Config)(unsafe.Pointer(pConfig)).FazCol + uintptr(i)*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
Xsqlite3_free(tls, (*TFts5Config)(unsafe.Pointer(pConfig)).FazCol)
|
|
Xsqlite3_free(tls, (*TFts5Config)(unsafe.Pointer(pConfig)).FaPrefix)
|
|
Xsqlite3_free(tls, (*TFts5Config)(unsafe.Pointer(pConfig)).FzRank)
|
|
Xsqlite3_free(tls, (*TFts5Config)(unsafe.Pointer(pConfig)).FzRankArgs)
|
|
Xsqlite3_free(tls, (*TFts5Config)(unsafe.Pointer(pConfig)).FzContent)
|
|
Xsqlite3_free(tls, (*TFts5Config)(unsafe.Pointer(pConfig)).FzContentRowid)
|
|
Xsqlite3_free(tls, (*TFts5Config)(unsafe.Pointer(pConfig)).FzContentExprlist)
|
|
Xsqlite3_free(tls, pConfig)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Clear the token mappings for all Fts5IndexIter objects managed by
|
|
// ** the expression passed as the only argument.
|
|
// */
|
|
func _sqlite3Fts5ExprClearTokens(tls *libc.TLS, pExpr uintptr) {
|
|
var ii int32
|
|
var pT uintptr
|
|
_, _ = ii, pT
|
|
ii = 0
|
|
for {
|
|
if !(ii < (*TFts5Expr)(unsafe.Pointer(pExpr)).FnPhrase) {
|
|
break
|
|
}
|
|
pT = **(**uintptr)(__ccgo_up((*TFts5Expr)(unsafe.Pointer(pExpr)).FapExprPhrase + uintptr(ii)*8)) + 32
|
|
for {
|
|
if !(pT != 0) {
|
|
break
|
|
}
|
|
_sqlite3Fts5IndexIterClearTokendata(tls, (*TFts5ExprTerm)(unsafe.Pointer(pT)).FpIter)
|
|
goto _2
|
|
_2:
|
|
;
|
|
pT = (*TFts5ExprTerm)(unsafe.Pointer(pT)).FpSynonym
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
}
|
|
|
|
/*
|
|
** 2014 August 11
|
|
**
|
|
** 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.
|
|
**
|
|
******************************************************************************
|
|
**
|
|
*/
|
|
|
|
/* #include "fts5Int.h" */
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Does the work of the fts5_api.xInstToken() API method.
|
|
// */
|
|
func _sqlite3Fts5ExprInstToken(tls *libc.TLS, pExpr uintptr, iRowid Ti64, iPhrase int32, iCol int32, iOff int32, iToken int32, ppOut uintptr, pnOut uintptr) (r int32) {
|
|
var pPhrase, pTerm uintptr
|
|
var rc int32
|
|
_, _, _ = pPhrase, pTerm, rc
|
|
pPhrase = uintptr(0)
|
|
pTerm = uintptr(0)
|
|
rc = SQLITE_OK
|
|
if iPhrase < 0 || iPhrase >= (*TFts5Expr)(unsafe.Pointer(pExpr)).FnPhrase {
|
|
return int32(SQLITE_RANGE)
|
|
}
|
|
pPhrase = **(**uintptr)(__ccgo_up((*TFts5Expr)(unsafe.Pointer(pExpr)).FapExprPhrase + uintptr(iPhrase)*8))
|
|
if iToken < 0 || iToken >= (*TFts5ExprPhrase)(unsafe.Pointer(pPhrase)).FnTerm {
|
|
return int32(SQLITE_RANGE)
|
|
}
|
|
pTerm = pPhrase + 32 + uintptr(iToken)*40
|
|
if (*TFts5Config)(unsafe.Pointer((*TFts5Expr)(unsafe.Pointer(pExpr)).FpConfig)).FbTokendata != 0 || (*TFts5ExprTerm)(unsafe.Pointer(pTerm)).FbPrefix != 0 {
|
|
rc = _sqlite3Fts5IterToken(tls, (*TFts5ExprTerm)(unsafe.Pointer(pTerm)).FpIter, (*TFts5ExprTerm)(unsafe.Pointer(pTerm)).FpTerm, (*TFts5ExprTerm)(unsafe.Pointer(pTerm)).FnQueryTerm, iRowid, iCol, iOff+iToken, ppOut, pnOut)
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(ppOut)) = (*TFts5ExprTerm)(unsafe.Pointer(pTerm)).FpTerm
|
|
**(**int32)(__ccgo_up(pnOut)) = (*TFts5ExprTerm)(unsafe.Pointer(pTerm)).FnFullTerm
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is only called for detail=columns tables.
|
|
// */
|
|
func _sqlite3Fts5ExprPhraseCollist(tls *libc.TLS, pExpr uintptr, iPhrase int32, ppCollist uintptr, pnCollist uintptr) (r int32) {
|
|
var pBuf, pNode, pPhrase, pTerm uintptr
|
|
var rc int32
|
|
_, _, _, _, _ = pBuf, pNode, pPhrase, pTerm, rc
|
|
pPhrase = **(**uintptr)(__ccgo_up((*TFts5Expr)(unsafe.Pointer(pExpr)).FapExprPhrase + uintptr(iPhrase)*8))
|
|
pNode = (*TFts5ExprPhrase)(unsafe.Pointer(pPhrase)).FpNode
|
|
rc = SQLITE_OK
|
|
if (*TFts5ExprNode)(unsafe.Pointer(pNode)).FbEof == 0 && (*TFts5ExprNode)(unsafe.Pointer(pNode)).FiRowid == (*TFts5ExprNode)(unsafe.Pointer((*TFts5Expr)(unsafe.Pointer(pExpr)).FpRoot)).FiRowid && (*TFts5ExprPhrase)(unsafe.Pointer(pPhrase)).Fposlist.Fn > 0 {
|
|
pTerm = pPhrase + 32
|
|
if (*TFts5ExprTerm)(unsafe.Pointer(pTerm)).FpSynonym != 0 {
|
|
pBuf = (*TFts5ExprTerm)(unsafe.Pointer(pTerm)).FpSynonym + 1*40
|
|
rc = _fts5ExprSynonymList(tls, pTerm, (*TFts5ExprNode)(unsafe.Pointer(pNode)).FiRowid, pBuf, ppCollist, pnCollist)
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(ppCollist)) = (*TFts5IndexIter)(unsafe.Pointer((*(*TFts5ExprTerm)(unsafe.Pointer(pPhrase + 32))).FpIter)).FpData
|
|
**(**int32)(__ccgo_up(pnCollist)) = (*TFts5IndexIter)(unsafe.Pointer((*(*TFts5ExprTerm)(unsafe.Pointer(pPhrase + 32))).FpIter)).FnData
|
|
}
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(ppCollist)) = uintptr(0)
|
|
**(**int32)(__ccgo_up(pnCollist)) = 0
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the number of terms in the iPhrase'th phrase in pExpr.
|
|
// */
|
|
func _sqlite3Fts5ExprPhraseSize(tls *libc.TLS, pExpr uintptr, iPhrase int32) (r int32) {
|
|
if iPhrase < 0 || iPhrase >= (*TFts5Expr)(unsafe.Pointer(pExpr)).FnPhrase {
|
|
return 0
|
|
}
|
|
return (*TFts5ExprPhrase)(unsafe.Pointer(**(**uintptr)(__ccgo_up((*TFts5Expr)(unsafe.Pointer(pExpr)).FapExprPhrase + uintptr(iPhrase)*8)))).FnTerm
|
|
}
|
|
|
|
func _sqlite3Fts5ExprPopulatePoslists(tls *libc.TLS, pConfig uintptr, pExpr uintptr, aPopulator uintptr, iCol int32, z uintptr, n int32) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var i int32
|
|
var pColset, pNode uintptr
|
|
var _ /* sCtx at bp+0 */ TFts5ExprCtx
|
|
_, _, _ = i, pColset, pNode
|
|
(**(**TFts5ExprCtx)(__ccgo_up(bp))).FpExpr = pExpr
|
|
(**(**TFts5ExprCtx)(__ccgo_up(bp))).FaPopulator = aPopulator
|
|
(**(**TFts5ExprCtx)(__ccgo_up(bp))).FiOff = int64(iCol)<<libc.Int32FromInt32(32) - int64(1)
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5Expr)(unsafe.Pointer(pExpr)).FnPhrase) {
|
|
break
|
|
}
|
|
pNode = (*TFts5ExprPhrase)(unsafe.Pointer(**(**uintptr)(__ccgo_up((*TFts5Expr)(unsafe.Pointer(pExpr)).FapExprPhrase + uintptr(i)*8)))).FpNode
|
|
pColset = (*TFts5ExprNearset)(unsafe.Pointer((*TFts5ExprNode)(unsafe.Pointer(pNode)).FpNear)).FpColset
|
|
if pColset != 0 && 0 == _fts5ExprColsetTest(tls, pColset, iCol) || (**(**TFts5PoslistPopulator)(__ccgo_up(aPopulator + uintptr(i)*16))).FbMiss != 0 {
|
|
(**(**TFts5PoslistPopulator)(__ccgo_up(aPopulator + uintptr(i)*16))).FbOk = 0
|
|
} else {
|
|
(**(**TFts5PoslistPopulator)(__ccgo_up(aPopulator + uintptr(i)*16))).FbOk = int32(1)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return _sqlite3Fts5Tokenize(tls, pConfig, int32(FTS5_TOKENIZE_DOCUMENT), z, n, bp, __ccgo_fp(_fts5ExprPopulatePoslistsCb))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is used to access the current position list for phrase
|
|
// ** iPhrase.
|
|
// */
|
|
func _sqlite3Fts5ExprPoslist(tls *libc.TLS, pExpr uintptr, iPhrase int32, pa uintptr) (r int32) {
|
|
var nRet int32
|
|
var pNode, pPhrase uintptr
|
|
_, _, _ = nRet, pNode, pPhrase
|
|
pPhrase = **(**uintptr)(__ccgo_up((*TFts5Expr)(unsafe.Pointer(pExpr)).FapExprPhrase + uintptr(iPhrase)*8))
|
|
pNode = (*TFts5ExprPhrase)(unsafe.Pointer(pPhrase)).FpNode
|
|
if (*TFts5ExprNode)(unsafe.Pointer(pNode)).FbEof == 0 && (*TFts5ExprNode)(unsafe.Pointer(pNode)).FiRowid == (*TFts5ExprNode)(unsafe.Pointer((*TFts5Expr)(unsafe.Pointer(pExpr)).FpRoot)).FiRowid {
|
|
**(**uintptr)(__ccgo_up(pa)) = (*TFts5ExprPhrase)(unsafe.Pointer(pPhrase)).Fposlist.Fp
|
|
nRet = (*TFts5ExprPhrase)(unsafe.Pointer(pPhrase)).Fposlist.Fn
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(pa)) = uintptr(0)
|
|
nRet = 0
|
|
}
|
|
return nRet
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Does the work of the fts5_api.xQueryToken() API method.
|
|
// */
|
|
func _sqlite3Fts5ExprQueryToken(tls *libc.TLS, pExpr uintptr, iPhrase int32, iToken int32, ppOut uintptr, pnOut uintptr) (r int32) {
|
|
var pPhrase uintptr
|
|
_ = pPhrase
|
|
pPhrase = uintptr(0)
|
|
if iPhrase < 0 || iPhrase >= (*TFts5Expr)(unsafe.Pointer(pExpr)).FnPhrase {
|
|
return int32(SQLITE_RANGE)
|
|
}
|
|
pPhrase = **(**uintptr)(__ccgo_up((*TFts5Expr)(unsafe.Pointer(pExpr)).FapExprPhrase + uintptr(iPhrase)*8))
|
|
if iToken < 0 || iToken >= (*TFts5ExprPhrase)(unsafe.Pointer(pPhrase)).FnTerm {
|
|
return int32(SQLITE_RANGE)
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppOut)) = (*(*TFts5ExprTerm)(unsafe.Pointer(pPhrase + 32 + uintptr(iToken)*40))).FpTerm
|
|
**(**int32)(__ccgo_up(pnOut)) = (*(*TFts5ExprTerm)(unsafe.Pointer(pPhrase + 32 + uintptr(iToken)*40))).FnFullTerm
|
|
return SQLITE_OK
|
|
}
|
|
|
|
func _sqlite3Fts5HashScanInit(tls *libc.TLS, p uintptr, pTerm uintptr, nTerm int32) (r int32) {
|
|
return _fts5HashEntrySort(tls, p, pTerm, nTerm, p+24)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Indicate that all subsequent calls to sqlite3Fts5IndexWrite() pertain
|
|
// ** to the document with rowid iRowid.
|
|
// */
|
|
func _sqlite3Fts5IndexBeginWrite(tls *libc.TLS, p uintptr, bDelete int32, iRowid Ti64) (r int32) {
|
|
/* Allocate the hash table if it has not already been allocated */
|
|
if (*TFts5Index)(unsafe.Pointer(p)).FpHash == uintptr(0) {
|
|
(*TFts5Index)(unsafe.Pointer(p)).Frc = _sqlite3Fts5HashNew(tls, (*TFts5Index)(unsafe.Pointer(p)).FpConfig, p+24, p+32)
|
|
}
|
|
/* Flush the hash table to disk if required */
|
|
if iRowid < (*TFts5Index)(unsafe.Pointer(p)).FiWriteRowid || iRowid == (*TFts5Index)(unsafe.Pointer(p)).FiWriteRowid && (*TFts5Index)(unsafe.Pointer(p)).FbDelete == 0 || (*TFts5Index)(unsafe.Pointer(p)).FnPendingData > (*TFts5Config)(unsafe.Pointer((*TFts5Index)(unsafe.Pointer(p)).FpConfig)).FnHashSize {
|
|
_fts5IndexFlush(tls, p)
|
|
}
|
|
(*TFts5Index)(unsafe.Pointer(p)).FiWriteRowid = iRowid
|
|
(*TFts5Index)(unsafe.Pointer(p)).FbDelete = bDelete
|
|
if bDelete == 0 {
|
|
(*TFts5Index)(unsafe.Pointer(p)).FnPendingRow = (*TFts5Index)(unsafe.Pointer(p)).FnPendingRow + 1
|
|
}
|
|
return _fts5IndexReturn(tls, p)
|
|
}
|
|
|
|
func _sqlite3Fts5IndexOptimize(tls *libc.TLS, p uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var iLvl int32
|
|
var pStruct uintptr
|
|
var _ /* nRem at bp+8 */ int32
|
|
var _ /* pNew at bp+0 */ uintptr
|
|
_, _ = iLvl, pStruct
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
_fts5IndexFlush(tls, p)
|
|
pStruct = _fts5StructureRead(tls, p)
|
|
_fts5StructureInvalidate(tls, p)
|
|
if pStruct != 0 {
|
|
**(**uintptr)(__ccgo_up(bp)) = _fts5IndexOptimizeStruct(tls, p, pStruct)
|
|
}
|
|
_fts5StructureRelease(tls, pStruct)
|
|
if **(**uintptr)(__ccgo_up(bp)) != 0 {
|
|
iLvl = 0
|
|
for {
|
|
if !((*(*TFts5StructureLevel)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)) + 32 + uintptr(iLvl)*16))).FnSeg == 0) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
iLvl = iLvl + 1
|
|
}
|
|
for (*TFts5Index)(unsafe.Pointer(p)).Frc == SQLITE_OK && (*(*TFts5StructureLevel)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)) + 32 + uintptr(iLvl)*16))).FnSeg > 0 {
|
|
**(**int32)(__ccgo_up(bp + 8)) = int32(FTS5_OPT_WORK_UNIT)
|
|
_fts5IndexMergeLevel(tls, p, bp, iLvl, bp+8)
|
|
}
|
|
_fts5StructureWrite(tls, p, **(**uintptr)(__ccgo_up(bp)))
|
|
_fts5StructureRelease(tls, **(**uintptr)(__ccgo_up(bp)))
|
|
}
|
|
return _fts5IndexReturn(tls, p)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This is used by xInstToken() to access the token at offset iOff, column
|
|
// ** iCol of row iRowid. The token is returned via output variables *ppOut
|
|
// ** and *pnOut. The iterator passed as the first argument must be a tokendata=1
|
|
// ** iterator (pIter->pTokenDataIter!=0).
|
|
// **
|
|
// ** pToken/nToken:
|
|
// */
|
|
func _sqlite3Fts5IterToken(tls *libc.TLS, pIndexIter uintptr, pToken uintptr, nToken int32, iRowid Ti64, iCol int32, iOff int32, ppOut uintptr, pnOut uintptr) (r int32) {
|
|
var aMap, p, pIter, pMap, pT uintptr
|
|
var i1, i2, iTest, rc int32
|
|
var iPos Ti64
|
|
_, _, _, _, _, _, _, _, _, _ = aMap, i1, i2, iPos, iTest, p, pIter, pMap, pT, rc
|
|
pIter = pIndexIter
|
|
pT = (*TFts5Iter)(unsafe.Pointer(pIter)).FpTokenDataIter
|
|
iPos = int64(iCol)<<libc.Int32FromInt32(32) + int64(iOff)
|
|
aMap = uintptr(0)
|
|
i1 = 0
|
|
i2 = 0
|
|
iTest = 0
|
|
if pT == uintptr(0) {
|
|
rc = _fts5SetupPrefixIterTokendata(tls, pIter, pToken, nToken)
|
|
if rc != SQLITE_OK {
|
|
return rc
|
|
}
|
|
pT = (*TFts5Iter)(unsafe.Pointer(pIter)).FpTokenDataIter
|
|
}
|
|
i2 = int32((*TFts5TokenDataIter)(unsafe.Pointer(pT)).FnMap)
|
|
aMap = (*TFts5TokenDataIter)(unsafe.Pointer(pT)).FaMap
|
|
for i2 > i1 {
|
|
iTest = (i1 + i2) / int32(2)
|
|
if (**(**TFts5TokenDataMap)(__ccgo_up(aMap + uintptr(iTest)*24))).FiRowid < iRowid {
|
|
i1 = iTest + int32(1)
|
|
} else {
|
|
if (**(**TFts5TokenDataMap)(__ccgo_up(aMap + uintptr(iTest)*24))).FiRowid > iRowid {
|
|
i2 = iTest
|
|
} else {
|
|
if (**(**TFts5TokenDataMap)(__ccgo_up(aMap + uintptr(iTest)*24))).FiPos < iPos {
|
|
if (**(**TFts5TokenDataMap)(__ccgo_up(aMap + uintptr(iTest)*24))).FiPos < 0 {
|
|
break
|
|
}
|
|
i1 = iTest + int32(1)
|
|
} else {
|
|
if (**(**TFts5TokenDataMap)(__ccgo_up(aMap + uintptr(iTest)*24))).FiPos > iPos {
|
|
i2 = iTest
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if i2 > i1 {
|
|
if (*TFts5Iter)(unsafe.Pointer(pIter)).FnSeg == 0 {
|
|
pMap = *(*uintptr)(unsafe.Pointer(pT + 72 + uintptr((**(**TFts5TokenDataMap)(__ccgo_up(aMap + uintptr(iTest)*24))).FiIter)*8))
|
|
**(**uintptr)(__ccgo_up(ppOut)) = (*(*TFts5SegIter)(unsafe.Pointer(pMap + 104))).Fterm.Fp + uintptr(1)
|
|
**(**int32)(__ccgo_up(pnOut)) = (*(*TFts5SegIter)(unsafe.Pointer(pMap + 104))).Fterm.Fn - int32(1)
|
|
} else {
|
|
p = aMap + uintptr(iTest)*24
|
|
**(**uintptr)(__ccgo_up(ppOut)) = (*TFts5TokenDataIter)(unsafe.Pointer(pT)).Fterms.Fp + uintptr((*TFts5TokenDataMap)(unsafe.Pointer(p)).FiIter)
|
|
**(**int32)(__ccgo_up(pnOut)) = (**(**TFts5TokenDataMap)(__ccgo_up(aMap + uintptr(iTest)*24))).FnByte
|
|
}
|
|
}
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free the phrase object passed as the second argument.
|
|
// */
|
|
func _sqlite3Fts5ParseNearsetFree(tls *libc.TLS, pNear uintptr) {
|
|
var i int32
|
|
_ = i
|
|
if pNear != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5ExprNearset)(unsafe.Pointer(pNear)).FnPhrase) {
|
|
break
|
|
}
|
|
_fts5ExprPhraseFree(tls, *(*uintptr)(unsafe.Pointer(pNear + 24 + uintptr(i)*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
Xsqlite3_free(tls, (*TFts5ExprNearset)(unsafe.Pointer(pNear)).FpColset)
|
|
Xsqlite3_free(tls, pNear)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free the expression node object passed as the only argument.
|
|
// */
|
|
func _sqlite3Fts5ParseNodeFree(tls *libc.TLS, p uintptr) {
|
|
var i int32
|
|
_ = i
|
|
if p != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TFts5ExprNode)(unsafe.Pointer(p)).FnChild) {
|
|
break
|
|
}
|
|
_sqlite3Fts5ParseNodeFree(tls, *(*uintptr)(unsafe.Pointer(p + 48 + uintptr(i)*8)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_sqlite3Fts5ParseNearsetFree(tls, (*TFts5ExprNode)(unsafe.Pointer(p)).FpNear)
|
|
Xsqlite3_free(tls, p)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Set the "bFirst" flag on the first token of the phrase passed as the
|
|
// ** only argument.
|
|
// */
|
|
func _sqlite3Fts5ParseSetCaret(tls *libc.TLS, pPhrase uintptr) {
|
|
if pPhrase != 0 && (*TFts5ExprPhrase)(unsafe.Pointer(pPhrase)).FnTerm != 0 {
|
|
(*(*TFts5ExprTerm)(unsafe.Pointer(pPhrase + 32))).FbFirst = uint8(1)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function allocates a new parser.
|
|
// ** The only argument is a pointer to a function which works like
|
|
// ** malloc.
|
|
// **
|
|
// ** Inputs:
|
|
// ** A pointer to the function used to allocate memory.
|
|
// **
|
|
// ** Outputs:
|
|
// ** A pointer to a parser. This pointer is used in subsequent calls
|
|
// ** to sqlite3Fts5Parser and sqlite3Fts5ParserFree.
|
|
// */
|
|
func _sqlite3Fts5ParserAlloc(tls *libc.TLS, __ccgo_fp_mallocProc uintptr) (r uintptr) {
|
|
var fts5yypParser uintptr
|
|
_ = fts5yypParser
|
|
fts5yypParser = (*(*func(*libc.TLS, Tu64) uintptr)(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_mallocProc})))(tls, libc.Uint64FromInt64(2432))
|
|
if fts5yypParser != 0 {
|
|
_sqlite3Fts5ParserInit(tls, fts5yypParser)
|
|
}
|
|
return fts5yypParser
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Initialize a new parser that has already been allocated.
|
|
// */
|
|
func _sqlite3Fts5ParserInit(tls *libc.TLS, fts5yypRawParser uintptr) {
|
|
var fts5yypParser uintptr
|
|
_ = fts5yypParser
|
|
fts5yypParser = fts5yypRawParser
|
|
(*Tfts5yyParser)(unsafe.Pointer(fts5yypParser)).Ffts5yystack = fts5yypParser + 32
|
|
(*Tfts5yyParser)(unsafe.Pointer(fts5yypParser)).Ffts5yystackEnd = (*Tfts5yyParser)(unsafe.Pointer(fts5yypParser)).Ffts5yystack + uintptr(libc.Int32FromInt32(fts5YYSTACKDEPTH)-libc.Int32FromInt32(1))*24
|
|
(*Tfts5yyParser)(unsafe.Pointer(fts5yypParser)).Ffts5yytos = (*Tfts5yyParser)(unsafe.Pointer(fts5yypParser)).Ffts5yystack
|
|
(**(**Tfts5yyStackEntry)(__ccgo_up((*Tfts5yyParser)(unsafe.Pointer(fts5yypParser)).Ffts5yystack))).Fstateno = uint8(0)
|
|
(**(**Tfts5yyStackEntry)(__ccgo_up((*Tfts5yyParser)(unsafe.Pointer(fts5yypParser)).Ffts5yystack))).Fmajor = uint8(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Arrange for subsequent calls to sqlite3Fts5Tokenize() to use the locale
|
|
// ** specified by pLocale/nLocale. The buffer indicated by pLocale must remain
|
|
// ** valid until after the final call to sqlite3Fts5Tokenize() that will use
|
|
// ** the locale.
|
|
// */
|
|
func _sqlite3Fts5SetLocale(tls *libc.TLS, pConfig uintptr, zLocale uintptr, nLocale int32) {
|
|
var pT uintptr
|
|
_ = pT
|
|
pT = pConfig + 128
|
|
(*TFts5TokenizerConfig)(unsafe.Pointer(pT)).FpLocale = zLocale
|
|
(*TFts5TokenizerConfig)(unsafe.Pointer(pT)).FnLocale = nLocale
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Obtain an SQLite statement handle that may be used to read data from the
|
|
// ** %_content table.
|
|
// */
|
|
func _sqlite3Fts5StorageStmt(tls *libc.TLS, p uintptr, eStmt int32, pp uintptr, pzErrMsg uintptr) (r int32) {
|
|
var rc int32
|
|
_ = rc
|
|
rc = _fts5StorageGetStmt(tls, p, eStmt, pp, pzErrMsg)
|
|
if rc == SQLITE_OK {
|
|
**(**uintptr)(__ccgo_up(p + 48 + uintptr(eStmt)*8)) = uintptr(0)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Release an SQLite statement handle obtained via an earlier call to
|
|
// ** sqlite3Fts5StorageStmt(). The eStmt parameter passed to this function
|
|
// ** must match that passed to the sqlite3Fts5StorageStmt() call.
|
|
// */
|
|
func _sqlite3Fts5StorageStmtRelease(tls *libc.TLS, p uintptr, eStmt int32, pStmt uintptr) {
|
|
if **(**uintptr)(__ccgo_up(p + 48 + uintptr(eStmt)*8)) == uintptr(0) {
|
|
Xsqlite3_reset(tls, pStmt)
|
|
**(**uintptr)(__ccgo_up(p + 48 + uintptr(eStmt)*8)) = pStmt
|
|
} else {
|
|
Xsqlite3_finalize(tls, pStmt)
|
|
}
|
|
}
|
|
|
|
func _sqlite3Fts5TermsetNew(tls *libc.TLS, pp uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var _ /* rc at bp+0 */ int32
|
|
**(**int32)(__ccgo_up(bp)) = SQLITE_OK
|
|
**(**uintptr)(__ccgo_up(pp)) = _sqlite3Fts5MallocZero(tls, bp, int64(4096))
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Search a FuncDefHash for a function with the given name. Return
|
|
// ** a pointer to the matching FuncDef if found, or 0 if there is no match.
|
|
// */
|
|
func _sqlite3FunctionSearch(tls *libc.TLS, h int32, zFunc uintptr) (r uintptr) {
|
|
var p uintptr
|
|
_ = p
|
|
p = **(**uintptr)(__ccgo_up(uintptr(unsafe.Pointer(&_sqlite3BuiltinFunctions)) + uintptr(h)*8))
|
|
for {
|
|
if !(p != 0) {
|
|
break
|
|
}
|
|
if _sqlite3StrICmp(tls, (*TFuncDef)(unsafe.Pointer(p)).FzName, zFunc) == 0 {
|
|
return p
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
p = *(*uintptr)(unsafe.Pointer(p + 64))
|
|
}
|
|
return uintptr(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the collating function associated with a function.
|
|
// */
|
|
func _sqlite3GetFuncCollSeq(tls *libc.TLS, context uintptr) (r uintptr) {
|
|
var pOp uintptr
|
|
_ = pOp
|
|
pOp = (*TVdbe)(unsafe.Pointer((*Tsqlite3_context)(unsafe.Pointer(context)).FpVdbe)).FaOp + uintptr((*Tsqlite3_context)(unsafe.Pointer(context)).FiOp-int32(1))*24
|
|
return *(*uintptr)(unsafe.Pointer(pOp + 16))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Allocate or deallocate a block of nReg consecutive registers.
|
|
// */
|
|
func _sqlite3GetTempRange(tls *libc.TLS, pParse uintptr, nReg int32) (r int32) {
|
|
var i, n int32
|
|
_, _ = i, n
|
|
if nReg == int32(1) {
|
|
return _sqlite3GetTempReg(tls, pParse)
|
|
}
|
|
i = (*TParse)(unsafe.Pointer(pParse)).FiRangeReg
|
|
n = (*TParse)(unsafe.Pointer(pParse)).FnRangeReg
|
|
if nReg <= n {
|
|
**(**int32)(__ccgo_up(pParse + 48)) += nReg
|
|
**(**int32)(__ccgo_up(pParse + 44)) -= nReg
|
|
} else {
|
|
i = (*TParse)(unsafe.Pointer(pParse)).FnMem + int32(1)
|
|
**(**int32)(__ccgo_up(pParse + 60)) += nReg
|
|
}
|
|
return i
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** pTab is a pointer to a Table structure representing a virtual-table.
|
|
// ** Return a pointer to the VTable object used by connection db to access
|
|
// ** this virtual-table, if one has been created, or NULL otherwise.
|
|
// */
|
|
func _sqlite3GetVTable(tls *libc.TLS, db uintptr, pTab uintptr) (r uintptr) {
|
|
var pVtab uintptr
|
|
_ = pVtab
|
|
pVtab = (*(*struct {
|
|
FnArg int32
|
|
FazArg uintptr
|
|
Fp uintptr
|
|
})(unsafe.Pointer(pTab + 64))).Fp
|
|
for {
|
|
if !(pVtab != 0 && (*TVTable)(unsafe.Pointer(pVtab)).Fdb != db) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pVtab = (*TVTable)(unsafe.Pointer(pVtab)).FpNext
|
|
}
|
|
return pVtab
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Insert an element into the hash table pH. The key is pKey
|
|
// ** and the data is "data".
|
|
// **
|
|
// ** If no element exists with a matching key, then a new
|
|
// ** element is created and NULL is returned.
|
|
// **
|
|
// ** If another element already exists with the same key, then the
|
|
// ** new data replaces the old data and the old data is returned.
|
|
// ** The key is not copied in this instance. If a malloc fails, then
|
|
// ** the new data is returned and the hash table is unchanged.
|
|
// **
|
|
// ** If the "data" parameter to this function is NULL, then the
|
|
// ** element corresponding to "key" is removed from the hash table.
|
|
// */
|
|
func _sqlite3HashInsert(tls *libc.TLS, pH uintptr, pKey uintptr, data uintptr) (r uintptr) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var elem, new_elem, old_data, v1 uintptr
|
|
var _ /* h at bp+0 */ uint32
|
|
_, _, _, _ = elem, new_elem, old_data, v1 /* New element added to the pH */
|
|
elem = _findElementWithHash(tls, pH, pKey, bp)
|
|
if (*THashElem)(unsafe.Pointer(elem)).Fdata != 0 {
|
|
old_data = (*THashElem)(unsafe.Pointer(elem)).Fdata
|
|
if data == uintptr(0) {
|
|
_removeElement(tls, pH, elem)
|
|
} else {
|
|
(*THashElem)(unsafe.Pointer(elem)).Fdata = data
|
|
(*THashElem)(unsafe.Pointer(elem)).FpKey = pKey
|
|
}
|
|
return old_data
|
|
}
|
|
if data == uintptr(0) {
|
|
return uintptr(0)
|
|
}
|
|
new_elem = _sqlite3Malloc(tls, uint64(40))
|
|
if new_elem == uintptr(0) {
|
|
return data
|
|
}
|
|
(*THashElem)(unsafe.Pointer(new_elem)).FpKey = pKey
|
|
(*THashElem)(unsafe.Pointer(new_elem)).Fh = **(**uint32)(__ccgo_up(bp))
|
|
(*THashElem)(unsafe.Pointer(new_elem)).Fdata = data
|
|
(*THash)(unsafe.Pointer(pH)).Fcount = (*THash)(unsafe.Pointer(pH)).Fcount + 1
|
|
if (*THash)(unsafe.Pointer(pH)).Fcount >= uint32(5) && (*THash)(unsafe.Pointer(pH)).Fcount > uint32(2)*(*THash)(unsafe.Pointer(pH)).Fhtsize {
|
|
_rehash(tls, pH, (*THash)(unsafe.Pointer(pH)).Fcount*uint32(3))
|
|
}
|
|
if (*THash)(unsafe.Pointer(pH)).Fht != 0 {
|
|
v1 = (*THash)(unsafe.Pointer(pH)).Fht + uintptr((*THashElem)(unsafe.Pointer(new_elem)).Fh%(*THash)(unsafe.Pointer(pH)).Fhtsize)*16
|
|
} else {
|
|
v1 = uintptr(0)
|
|
}
|
|
_insertElement(tls, pH, v1, new_elem)
|
|
return uintptr(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Delete an IdList.
|
|
// */
|
|
func _sqlite3IdListDelete(tls *libc.TLS, db uintptr, pList uintptr) {
|
|
var i int32
|
|
_ = i
|
|
if pList == uintptr(0) {
|
|
return
|
|
}
|
|
i = 0
|
|
for {
|
|
if !(i < (*TIdList)(unsafe.Pointer(pList)).FnId) {
|
|
break
|
|
}
|
|
_sqlite3DbFree(tls, db, (*(*TIdList_item)(unsafe.Pointer(pList + 8 + uintptr(i)*8))).FzName)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_sqlite3DbNNFreeNN(tls, db, pList)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the index in pList of the identifier named zId. Return -1
|
|
// ** if not found.
|
|
// */
|
|
func _sqlite3IdListIndex(tls *libc.TLS, pList uintptr, zName uintptr) (r int32) {
|
|
var i int32
|
|
_ = i
|
|
i = 0
|
|
for {
|
|
if !(i < (*TIdList)(unsafe.Pointer(pList)).FnId) {
|
|
break
|
|
}
|
|
if _sqlite3StrICmp(tls, (*(*TIdList_item)(unsafe.Pointer(pList + 8 + uintptr(i)*8))).FzName, zName) == 0 {
|
|
return i
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return -int32(1)
|
|
}
|
|
|
|
/*
|
|
** Maximum size of a SrcList object.
|
|
** The SrcList object is used to represent the FROM clause of a
|
|
** SELECT statement, and the query planner cannot deal with more
|
|
** than 64 tables in a join. So any value larger than 64 here
|
|
** is sufficient for most uses. Smaller values, like say 10, are
|
|
** appropriate for small and memory-limited applications.
|
|
*/
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the number of bytes required to store a JournalFile that uses vfs
|
|
// ** pVfs to create the underlying on-disk files.
|
|
// */
|
|
func _sqlite3JournalSize(tls *libc.TLS, pVfs uintptr) (r int32) {
|
|
var v1 int32
|
|
_ = v1
|
|
if (*Tsqlite3_vfs)(unsafe.Pointer(pVfs)).FszOsFile > libc.Int32FromInt64(80) {
|
|
v1 = (*Tsqlite3_vfs)(unsafe.Pointer(pVfs)).FszOsFile
|
|
} else {
|
|
v1 = libc.Int32FromInt64(80)
|
|
}
|
|
return v1
|
|
}
|
|
|
|
/************** End of memjournal.c ******************************************/
|
|
/************** Begin file walker.c ******************************************/
|
|
/*
|
|
** 2008 August 16
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** This file contains routines used for walking the parser tree for
|
|
** an SQL statement.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
/* #include <stdlib.h> */
|
|
/* #include <string.h> */
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Register the JSON table-valued function named zName and return a
|
|
// ** pointer to its Module object. Return NULL if something goes wrong.
|
|
// */
|
|
func _sqlite3JsonVtabRegister(tls *libc.TLS, db uintptr, zName uintptr) (r uintptr) {
|
|
var i uint32
|
|
_ = i
|
|
i = uint32(0)
|
|
for {
|
|
if !(uint64(i) < libc.Uint64FromInt64(32)/libc.Uint64FromInt64(8)) {
|
|
break
|
|
}
|
|
if _sqlite3StrICmp(tls, _azModule[i], zName) == 0 {
|
|
return _sqlite3VtabCreateModule(tls, db, _azModule[i], uintptr(unsafe.Pointer(&_jsonEachModule)), uintptr(0), uintptr(0))
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return uintptr(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Given an expression list, generate a KeyInfo structure that records
|
|
// ** the collating sequence for each expression in that expression list.
|
|
// **
|
|
// ** If the ExprList is an ORDER BY or GROUP BY clause then the resulting
|
|
// ** KeyInfo structure is appropriate for initializing a virtual index to
|
|
// ** implement that clause. If the ExprList is the result set of a SELECT
|
|
// ** then the KeyInfo structure is appropriate for initializing a virtual
|
|
// ** index to implement a DISTINCT test.
|
|
// **
|
|
// ** Space to hold the KeyInfo structure is obtained from malloc. The calling
|
|
// ** function is responsible for seeing that this structure is eventually
|
|
// ** freed.
|
|
// */
|
|
func _sqlite3KeyInfoFromExprList(tls *libc.TLS, pParse uintptr, pList uintptr, iStart int32, nExtra int32) (r uintptr) {
|
|
var db, pInfo, pItem uintptr
|
|
var i, nExpr int32
|
|
_, _, _, _, _ = db, i, nExpr, pInfo, pItem
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
nExpr = (*TExprList)(unsafe.Pointer(pList)).FnExpr
|
|
pInfo = _sqlite3KeyInfoAlloc(tls, db, nExpr-iStart, nExtra+int32(1))
|
|
if pInfo != 0 {
|
|
i = iStart
|
|
pItem = pList + 8 + uintptr(iStart)*32
|
|
for {
|
|
if !(i < nExpr) {
|
|
break
|
|
}
|
|
*(*uintptr)(unsafe.Pointer(pInfo + 32 + uintptr(i-iStart)*8)) = _sqlite3ExprNNCollSeq(tls, pParse, (*TExprList_item)(unsafe.Pointer(pItem)).FpExpr)
|
|
**(**Tu8)(__ccgo_up((*TKeyInfo)(unsafe.Pointer(pInfo)).FaSortFlags + uintptr(i-iStart))) = (*TExprList_item)(unsafe.Pointer(pItem)).Ffg.FsortFlags
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
pItem += 32
|
|
}
|
|
}
|
|
return pInfo
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Locate the table identified by *p.
|
|
// **
|
|
// ** This is a wrapper around sqlite3LocateTable(). The difference between
|
|
// ** sqlite3LocateTable() and this function is that this function restricts
|
|
// ** the search to schema (p->pSchema) if it is not NULL. p->pSchema may be
|
|
// ** non-NULL if it is part of a view or trigger program definition. See
|
|
// ** sqlite3FixSrcList() for details.
|
|
// */
|
|
func _sqlite3LocateTableItem(tls *libc.TLS, pParse uintptr, flags Tu32, p uintptr) (r uintptr) {
|
|
var iDb int32
|
|
var zDb uintptr
|
|
_, _ = iDb, zDb
|
|
if int32(*(*uint32)(unsafe.Pointer(p + 24 + 4))&0x10000>>16) != 0 {
|
|
iDb = _sqlite3SchemaToIndex(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, *(*uintptr)(unsafe.Pointer(p + 72)))
|
|
zDb = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer(pParse)).Fdb)).FaDb + uintptr(iDb)*32))).FzDbSName
|
|
} else {
|
|
zDb = *(*uintptr)(unsafe.Pointer(p + 72))
|
|
}
|
|
return _sqlite3LocateTable(tls, pParse, flags, (*TSrcItem)(unsafe.Pointer(p)).FzName, zDb)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Evaluate a view and store its result in an ephemeral table. The
|
|
// ** pWhere argument is an optional WHERE clause that restricts the
|
|
// ** set of rows in the view that are to be added to the ephemeral table.
|
|
// */
|
|
func _sqlite3MaterializeView(tls *libc.TLS, pParse uintptr, pView uintptr, pWhere uintptr, pOrderBy uintptr, pLimit uintptr, iCur int32) {
|
|
bp := tls.Alloc(48)
|
|
defer tls.Free(48)
|
|
var db, pFrom, pSel uintptr
|
|
var iDb int32
|
|
var _ /* dest at bp+0 */ TSelectDest
|
|
_, _, _, _ = db, iDb, pFrom, pSel
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
iDb = _sqlite3SchemaToIndex(tls, db, (*TTable)(unsafe.Pointer(pView)).FpSchema)
|
|
pWhere = _sqlite3ExprDup(tls, db, pWhere, 0)
|
|
pFrom = _sqlite3SrcListAppend(tls, pParse, uintptr(0), uintptr(0), uintptr(0))
|
|
if pFrom != 0 {
|
|
(*(*TSrcItem)(unsafe.Pointer(pFrom + 8))).FzName = _sqlite3DbStrDup(tls, db, (*TTable)(unsafe.Pointer(pView)).FzName)
|
|
*(*uintptr)(unsafe.Pointer(pFrom + 8 + 72)) = _sqlite3DbStrDup(tls, db, (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FzDbSName)
|
|
}
|
|
pSel = _sqlite3SelectNew(tls, pParse, uintptr(0), pFrom, pWhere, uintptr(0), uintptr(0), pOrderBy, uint32(SF_IncludeHidden), pLimit)
|
|
_sqlite3SelectDestInit(tls, bp, int32(SRT_EphemTab), iCur)
|
|
_sqlite3Select(tls, pParse, pSel, bp)
|
|
_sqlite3SelectDelete(tls, db, pSel)
|
|
}
|
|
|
|
/* && !defined(SQLITE_OMIT_SUBQUERY) */
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The code generator calls this routine if is discovers that it is
|
|
// ** possible to abort a statement prior to completion. In order to
|
|
// ** perform this abort without corrupting the database, we need to make
|
|
// ** sure that the statement is protected by a statement transaction.
|
|
// **
|
|
// ** Technically, we only need to set the mayAbort flag if the
|
|
// ** isMultiWrite flag was previously set. There is a time dependency
|
|
// ** such that the abort must occur after the multiwrite. This makes
|
|
// ** some statements involving the REPLACE conflict resolution algorithm
|
|
// ** go a little faster. But taking advantage of this time dependency
|
|
// ** makes it more difficult to prove that the code is correct (in
|
|
// ** particular, it prevents us from writing an effective
|
|
// ** implementation of sqlite3AssertMayAbort()) and so we have chosen
|
|
// ** to take the safe route and skip the optimization.
|
|
// */
|
|
func _sqlite3MayAbort(tls *libc.TLS, pParse uintptr) {
|
|
var pToplevel, v1 uintptr
|
|
_, _ = pToplevel, v1
|
|
if (*TParse)(unsafe.Pointer(pParse)).FpToplevel != 0 {
|
|
v1 = (*TParse)(unsafe.Pointer(pParse)).FpToplevel
|
|
} else {
|
|
v1 = pParse
|
|
}
|
|
pToplevel = v1
|
|
libc.SetBitFieldPtr16Uint32(pToplevel+40, libc.Uint32FromInt32(1), 1, 0x2)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Set the iIdx'th entry of array aMem[] to contain integer value val.
|
|
// */
|
|
func _sqlite3MemSetArrayInt64(tls *libc.TLS, aMem uintptr, iIdx int32, val Ti64) {
|
|
_sqlite3VdbeMemSetInt64(tls, aMem+uintptr(iIdx)*56, val)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If argument pVal is a Select object returned by an sqlite3MultiValues()
|
|
// ** that was able to use the co-routine optimization, finish coding the
|
|
// ** co-routine.
|
|
// */
|
|
func _sqlite3MultiValuesEnd(tls *libc.TLS, pParse uintptr, pVal uintptr) {
|
|
var pItem uintptr
|
|
_ = pItem
|
|
if pVal != 0 && (*TSrcList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pVal)).FpSrc)).FnSrc > 0 {
|
|
pItem = (*TSelect)(unsafe.Pointer(pVal)).FpSrc + 8
|
|
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x4>>2) != 0 {
|
|
_sqlite3VdbeEndCoroutine(tls, (*TParse)(unsafe.Pointer(pParse)).FpVdbe, (*TSubquery)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pItem + 72)))).FregReturn)
|
|
_sqlite3VdbeJumpHere(tls, (*TParse)(unsafe.Pointer(pParse)).FpVdbe, (*TSubquery)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pItem + 72)))).FaddrFillSub-int32(1))
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is called during initialization if a static buffer is
|
|
// ** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE
|
|
// ** verb to sqlite3_config(). Parameter pBuf points to an allocation large
|
|
// ** enough to contain 'n' buffers of 'sz' bytes each.
|
|
// **
|
|
// ** This routine is called from sqlite3_initialize() and so it is guaranteed
|
|
// ** to be serialized already. There is no need for further mutexing.
|
|
// */
|
|
func _sqlite3PCacheBufferSetup(tls *libc.TLS, pBuf uintptr, sz int32, n int32) {
|
|
var p uintptr
|
|
var v1 int32
|
|
_, _ = p, v1
|
|
if libc.AtomicLoadPInt32(uintptr(unsafe.Pointer(&_pcache1_g))+80) != 0 {
|
|
if pBuf == uintptr(0) {
|
|
v1 = libc.Int32FromInt32(0)
|
|
n = v1
|
|
sz = v1
|
|
}
|
|
if n == 0 {
|
|
sz = 0
|
|
}
|
|
sz = sz & ^libc.Int32FromInt32(7)
|
|
_pcache1_g.FszSlot = sz
|
|
v1 = n
|
|
_pcache1_g.FnFreeSlot = v1
|
|
_pcache1_g.FnSlot = v1
|
|
if n > int32(90) {
|
|
v1 = int32(10)
|
|
} else {
|
|
v1 = n/int32(10) + int32(1)
|
|
}
|
|
_pcache1_g.FnReserve = v1
|
|
_pcache1_g.FpStart = pBuf
|
|
_pcache1_g.FpFree = uintptr(0)
|
|
libc.AtomicStoreNInt32(uintptr(unsafe.Pointer(&_pcache1_g))+140, libc.Int32FromInt32(0), libc.Int32FromInt32(__ATOMIC_RELAXED))
|
|
for {
|
|
v1 = n
|
|
n = n - 1
|
|
if !(v1 != 0) {
|
|
break
|
|
}
|
|
p = pBuf
|
|
(*TPgFreeslot)(unsafe.Pointer(p)).FpNext = _pcache1_g.FpFree
|
|
_pcache1_g.FpFree = p
|
|
pBuf = pBuf + uintptr(sz)
|
|
}
|
|
_pcache1_g.FpEnd = pBuf
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return a pointer to the pPager->pBackup variable. The backup module
|
|
// ** in backup.c maintains the content of this variable. This module
|
|
// ** uses it opaquely as an argument to sqlite3BackupRestart() and
|
|
// ** sqlite3BackupUpdate() only.
|
|
// */
|
|
func _sqlite3PagerBackupPtr(tls *libc.TLS, pPager uintptr) (r uintptr) {
|
|
return pPager + 112
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Parameter eStat must be one of SQLITE_DBSTATUS_CACHE_HIT, _MISS, _WRITE,
|
|
// ** or _WRITE+1. The SQLITE_DBSTATUS_CACHE_WRITE+1 case is a translation
|
|
// ** of SQLITE_DBSTATUS_CACHE_SPILL. The _SPILL case is not contiguous because
|
|
// ** it was added later.
|
|
// **
|
|
// ** Before returning, *pnVal is incremented by the
|
|
// ** current cache hit or miss count, according to the value of eStat. If the
|
|
// ** reset parameter is non-zero, the cache hit or miss count is zeroed before
|
|
// ** returning.
|
|
// */
|
|
func _sqlite3PagerCacheStat(tls *libc.TLS, pPager uintptr, eStat int32, reset int32, pnVal uintptr) {
|
|
eStat = eStat - int32(SQLITE_DBSTATUS_CACHE_HIT)
|
|
**(**Tu64)(__ccgo_up(pnVal)) += uint64(**(**Tu32)(__ccgo_up(pPager + 248 + uintptr(eStat)*4)))
|
|
if reset != 0 {
|
|
**(**Tu32)(__ccgo_up(pPager + 248 + uintptr(eStat)*4)) = uint32(0)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Set the busy handler function.
|
|
// **
|
|
// ** The pager invokes the busy-handler if sqlite3OsLock() returns
|
|
// ** SQLITE_BUSY when trying to upgrade from no-lock to a SHARED lock,
|
|
// ** or when trying to upgrade from a RESERVED lock to an EXCLUSIVE
|
|
// ** lock. It does *not* invoke the busy handler when upgrading from
|
|
// ** SHARED to RESERVED, or when upgrading from SHARED to EXCLUSIVE
|
|
// ** (which occurs during hot-journal rollback). Summary:
|
|
// **
|
|
// ** Transition | Invokes xBusyHandler
|
|
// ** --------------------------------------------------------
|
|
// ** NO_LOCK -> SHARED_LOCK | Yes
|
|
// ** SHARED_LOCK -> RESERVED_LOCK | No
|
|
// ** SHARED_LOCK -> EXCLUSIVE_LOCK | No
|
|
// ** RESERVED_LOCK -> EXCLUSIVE_LOCK | Yes
|
|
// **
|
|
// ** If the busy-handler callback returns non-zero, the lock is
|
|
// ** retried. If it returns zero, then the SQLITE_BUSY error is
|
|
// ** returned to the caller of the pager API function.
|
|
// */
|
|
func _sqlite3PagerSetBusyHandler(tls *libc.TLS, pPager uintptr, __ccgo_fp_xBusyHandler uintptr, pBusyHandlerArg uintptr) {
|
|
var ap uintptr
|
|
_ = ap
|
|
(*TPager)(unsafe.Pointer(pPager)).FxBusyHandler = __ccgo_fp_xBusyHandler
|
|
(*TPager)(unsafe.Pointer(pPager)).FpBusyHandlerArg = pBusyHandlerArg
|
|
ap = pPager + 232
|
|
_sqlite3OsFileControlHint(tls, (*TPager)(unsafe.Pointer(pPager)).Ffd, int32(SQLITE_FCNTL_BUSYHANDLER), ap)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Add a new cleanup operation to a Parser. The cleanup should happen when
|
|
// ** the parser object is destroyed. But, beware: the cleanup might happen
|
|
// ** immediately.
|
|
// **
|
|
// ** Use this mechanism for uncommon cleanups. There is a higher setup
|
|
// ** cost for this mechanism (an extra malloc), so it should not be used
|
|
// ** for common cleanups that happen on most calls. But for less
|
|
// ** common cleanups, we save a single NULL-pointer comparison in
|
|
// ** sqlite3ParseObjectReset(), which reduces the total CPU cycle count.
|
|
// **
|
|
// ** If a memory allocation error occurs, then the cleanup happens immediately.
|
|
// ** When either SQLITE_DEBUG or SQLITE_COVERAGE_TEST are defined, the
|
|
// ** pParse->earlyCleanup flag is set in that case. Calling code show verify
|
|
// ** that test cases exist for which this happens, to guard against possible
|
|
// ** use-after-free errors following an OOM. The preferred way to do this is
|
|
// ** to immediately follow the call to this routine with:
|
|
// **
|
|
// ** testcase( pParse->earlyCleanup );
|
|
// **
|
|
// ** This routine returns a copy of its pPtr input (the third parameter)
|
|
// ** except if an early cleanup occurs, in which case it returns NULL. So
|
|
// ** another way to check for early cleanup is to check the return value.
|
|
// ** Or, stop using the pPtr parameter with this call and use only its
|
|
// ** return value thereafter. Something like this:
|
|
// **
|
|
// ** pObj = sqlite3ParserAddCleanup(pParse, destructor, pObj);
|
|
// */
|
|
func _sqlite3ParserAddCleanup(tls *libc.TLS, pParse uintptr, __ccgo_fp_xCleanup uintptr, pPtr uintptr) (r uintptr) {
|
|
var pCleanup uintptr
|
|
_ = pCleanup
|
|
if _sqlite3FaultSim(tls, int32(300)) != 0 {
|
|
pCleanup = uintptr(0)
|
|
_sqlite3OomFault(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb)
|
|
} else {
|
|
pCleanup = _sqlite3DbMallocRaw(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, uint64(24))
|
|
}
|
|
if pCleanup != 0 {
|
|
(*TParseCleanup)(unsafe.Pointer(pCleanup)).FpNext = (*TParse)(unsafe.Pointer(pParse)).FpCleanup
|
|
(*TParse)(unsafe.Pointer(pParse)).FpCleanup = pCleanup
|
|
(*TParseCleanup)(unsafe.Pointer(pCleanup)).FpPtr = pPtr
|
|
(*TParseCleanup)(unsafe.Pointer(pCleanup)).FxCleanup = __ccgo_fp_xCleanup
|
|
} else {
|
|
(*(*func(*libc.TLS, uintptr, uintptr))(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xCleanup})))(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pPtr)
|
|
pPtr = uintptr(0)
|
|
}
|
|
return pPtr
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Initialize a new parser that has already been allocated.
|
|
// */
|
|
func _sqlite3ParserInit(tls *libc.TLS, yypRawParser uintptr, pParse uintptr) {
|
|
var yypParser uintptr
|
|
_ = yypParser
|
|
yypParser = yypRawParser
|
|
(*TyyParser)(unsafe.Pointer(yypParser)).FpParse = pParse
|
|
(*TyyParser)(unsafe.Pointer(yypParser)).Fyystack = yypParser + 32
|
|
(*TyyParser)(unsafe.Pointer(yypParser)).FyystackEnd = (*TyyParser)(unsafe.Pointer(yypParser)).Fyystack + uintptr(libc.Int32FromInt32(YYSTACKDEPTH)-libc.Int32FromInt32(1))*24
|
|
(*TyyParser)(unsafe.Pointer(yypParser)).Fyytos = (*TyyParser)(unsafe.Pointer(yypParser)).Fyystack
|
|
(**(**TyyStackEntry)(__ccgo_up((*TyyParser)(unsafe.Pointer(yypParser)).Fyystack))).Fstateno = uint16(0)
|
|
(**(**TyyStackEntry)(__ccgo_up((*TyyParser)(unsafe.Pointer(yypParser)).Fyystack))).Fmajor = uint16(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Clear the PGHDR_NEED_SYNC flag from all dirty pages.
|
|
// */
|
|
func _sqlite3PcacheClearSyncFlags(tls *libc.TLS, pCache uintptr) {
|
|
var p, v2 uintptr
|
|
_, _ = p, v2
|
|
p = (*TPCache)(unsafe.Pointer(pCache)).FpDirty
|
|
for {
|
|
if !(p != 0) {
|
|
break
|
|
}
|
|
v2 = p + 52
|
|
*(*Tu16)(unsafe.Pointer(v2)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v2))) & ^libc.Int32FromInt32(PGHDR_NEED_SYNC))
|
|
goto _1
|
|
_1:
|
|
;
|
|
p = (*TPgHdr)(unsafe.Pointer(p)).FpDirtyNext
|
|
}
|
|
(*TPCache)(unsafe.Pointer(pCache)).FpSynced = (*TPCache)(unsafe.Pointer(pCache)).FpDirtyTail
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Clear the PGHDR_NEED_SYNC and PGHDR_WRITEABLE flag from all dirty pages.
|
|
// */
|
|
func _sqlite3PcacheClearWritable(tls *libc.TLS, pCache uintptr) {
|
|
var p, v2 uintptr
|
|
_, _ = p, v2
|
|
p = (*TPCache)(unsafe.Pointer(pCache)).FpDirty
|
|
for {
|
|
if !(p != 0) {
|
|
break
|
|
}
|
|
v2 = p + 52
|
|
*(*Tu16)(unsafe.Pointer(v2)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v2))) & ^(libc.Int32FromInt32(PGHDR_NEED_SYNC) | libc.Int32FromInt32(PGHDR_WRITEABLE)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
p = (*TPgHdr)(unsafe.Pointer(p)).FpDirtyNext
|
|
}
|
|
(*TPCache)(unsafe.Pointer(pCache)).FpSynced = (*TPCache)(unsafe.Pointer(pCache)).FpDirtyTail
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Make sure the page is marked as clean. If it isn't clean already,
|
|
// ** make it so.
|
|
// */
|
|
func _sqlite3PcacheMakeClean(tls *libc.TLS, p uintptr) {
|
|
var v1 uintptr
|
|
_ = v1
|
|
_pcacheManageDirtyList(tls, p, uint8(PCACHE_DIRTYLIST_REMOVE))
|
|
v1 = p + 52
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) & ^(libc.Int32FromInt32(PGHDR_DIRTY) | libc.Int32FromInt32(PGHDR_NEED_SYNC) | libc.Int32FromInt32(PGHDR_WRITEABLE)))
|
|
v1 = p + 52
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(PGHDR_CLEAN))
|
|
if (*TPgHdr)(unsafe.Pointer(p)).FnRef == 0 {
|
|
_pcacheUnpin(tls, p)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the size in bytes of a PCache object.
|
|
// */
|
|
func _sqlite3PcacheSize(tls *libc.TLS) (r int32) {
|
|
return int32(80)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the PRIMARY KEY index of a table
|
|
// */
|
|
func _sqlite3PrimaryKeyIndex(tls *libc.TLS, pTab uintptr) (r uintptr) {
|
|
var p uintptr
|
|
_ = p
|
|
p = (*TTable)(unsafe.Pointer(pTab)).FpIndex
|
|
for {
|
|
if !(p != 0 && !(int32(uint32(*(*uint16)(unsafe.Pointer(p + 100))&0x3>>0)) == libc.Int32FromInt32(SQLITE_IDXTYPE_PRIMARYKEY))) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
p = (*TIndex)(unsafe.Pointer(p)).FpNext
|
|
}
|
|
return p
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Check for interrupts and invoke progress callback.
|
|
// */
|
|
func _sqlite3ProgressCheck(tls *libc.TLS, p uintptr) {
|
|
var db, v2 uintptr
|
|
var v1 Tu32
|
|
_, _, _ = db, v1, v2
|
|
db = (*TParse)(unsafe.Pointer(p)).Fdb
|
|
if libc.AtomicLoadNInt32(db+432, libc.Int32FromInt32(__ATOMIC_RELAXED)) != 0 {
|
|
(*TParse)(unsafe.Pointer(p)).FnErr = (*TParse)(unsafe.Pointer(p)).FnErr + 1
|
|
(*TParse)(unsafe.Pointer(p)).Frc = int32(SQLITE_INTERRUPT)
|
|
}
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FxProgress != 0 {
|
|
if (*TParse)(unsafe.Pointer(p)).Frc == int32(SQLITE_INTERRUPT) {
|
|
(*TParse)(unsafe.Pointer(p)).FnProgressSteps = uint32(0)
|
|
} else {
|
|
v2 = p + 136
|
|
*(*Tu32)(unsafe.Pointer(v2)) = *(*Tu32)(unsafe.Pointer(v2)) + 1
|
|
v1 = *(*Tu32)(unsafe.Pointer(v2))
|
|
if v1 >= (*Tsqlite3)(unsafe.Pointer(db)).FnProgressOps {
|
|
if (*(*func(*libc.TLS, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{(*Tsqlite3)(unsafe.Pointer(db)).FxProgress})))(tls, (*Tsqlite3)(unsafe.Pointer(db)).FpProgressArg) != 0 {
|
|
(*TParse)(unsafe.Pointer(p)).FnErr = (*TParse)(unsafe.Pointer(p)).FnErr + 1
|
|
(*TParse)(unsafe.Pointer(p)).Frc = int32(SQLITE_INTERRUPT)
|
|
}
|
|
(*TParse)(unsafe.Pointer(p)).FnProgressSteps = uint32(0)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This routine is a no-op if the database schema is already initialized.
|
|
// ** Otherwise, the schema is loaded. An error code is returned.
|
|
// */
|
|
func _sqlite3ReadSchema(tls *libc.TLS, pParse uintptr) (r int32) {
|
|
var db uintptr
|
|
var rc int32
|
|
_, _ = db, rc
|
|
rc = SQLITE_OK
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
if !((*Tsqlite3)(unsafe.Pointer(db)).Finit1.Fbusy != 0) {
|
|
rc = _sqlite3Init(tls, db, pParse+8)
|
|
if rc != SQLITE_OK {
|
|
(*TParse)(unsafe.Pointer(pParse)).Frc = rc
|
|
(*TParse)(unsafe.Pointer(pParse)).FnErr = (*TParse)(unsafe.Pointer(pParse)).FnErr + 1
|
|
} else {
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FnoSharedCache != 0 {
|
|
**(**Tu32)(__ccgo_up(db + 44)) |= uint32(DBFLAG_SchemaKnownOk)
|
|
}
|
|
}
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Compare a floating point value to an integer. Return true if the two
|
|
// ** values are the same within the precision of the floating point value.
|
|
// **
|
|
// ** This function assumes that i was obtained by assignment from r1.
|
|
// **
|
|
// ** For some versions of GCC on 32-bit machines, if you do the more obvious
|
|
// ** comparison of "r1==(double)i" you sometimes get an answer of false even
|
|
// ** though the r1 and (double)i values are bit-for-bit the same.
|
|
// */
|
|
func _sqlite3RealSameAsInt(tls *libc.TLS, _r1 float64, i Tsqlite3_int64) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
*(*float64)(unsafe.Pointer(bp)) = _r1
|
|
var _ /* r2 at bp+8 */ float64
|
|
**(**float64)(__ccgo_up(bp + 8)) = float64(i)
|
|
return libc.BoolInt32(**(**float64)(__ccgo_up(bp)) == float64(0) || libc.Xmemcmp(tls, bp, bp+8, uint64(8)) == 0 && i >= -int64(2251799813685248) && i < int64(2251799813685248))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The z string points to the first character of a token that is
|
|
// ** associated with an error. If db does not already have an error
|
|
// ** byte offset recorded, try to compute the error byte offset for
|
|
// ** z and set the error byte offset in db.
|
|
// */
|
|
func _sqlite3RecordErrorByteOffset(tls *libc.TLS, db uintptr, z uintptr) {
|
|
var pParse, zEnd, zText uintptr
|
|
_, _, _ = pParse, zEnd, zText
|
|
if db == uintptr(0) {
|
|
return
|
|
}
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FerrByteOffset != -int32(2) {
|
|
return
|
|
}
|
|
pParse = (*Tsqlite3)(unsafe.Pointer(db)).FpParse
|
|
if pParse == uintptr(0) {
|
|
return
|
|
}
|
|
zText = (*TParse)(unsafe.Pointer(pParse)).FzTail
|
|
if zText == uintptr(0) {
|
|
return
|
|
}
|
|
zEnd = zText + uintptr(libc.Xstrlen(tls, zText))
|
|
if uint64(z) >= uint64(zText) && uint64(z) < uint64(zEnd) {
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FerrByteOffset = int32(int64(z) - int64(zText))
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Resolve all names in all expressions of a SELECT and in all
|
|
// ** descendants of the SELECT, including compounds off of p->pPrior,
|
|
// ** subqueries in expressions, and subqueries used as FROM clause
|
|
// ** terms.
|
|
// **
|
|
// ** See sqlite3ResolveExprNames() for a description of the kinds of
|
|
// ** transformations that occur.
|
|
// **
|
|
// ** All SELECT statements should have been expanded using
|
|
// ** sqlite3SelectExpand() prior to invoking this routine.
|
|
// */
|
|
func _sqlite3ResolveSelectNames(tls *libc.TLS, pParse uintptr, p uintptr, pOuterNC uintptr) {
|
|
bp := tls.Alloc(48)
|
|
defer tls.Free(48)
|
|
var _ /* w at bp+0 */ TWalker
|
|
(**(**TWalker)(__ccgo_up(bp))).FxExprCallback = __ccgo_fp(_resolveExprStep)
|
|
(**(**TWalker)(__ccgo_up(bp))).FxSelectCallback = __ccgo_fp(_resolveSelectStep)
|
|
(**(**TWalker)(__ccgo_up(bp))).FxSelectCallback2 = uintptr(0)
|
|
(**(**TWalker)(__ccgo_up(bp))).FpParse = pParse
|
|
*(*uintptr)(unsafe.Pointer(bp + 40)) = pOuterNC
|
|
_sqlite3WalkSelect(tls, bp, p)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If the SELECT references the table pWalker->u.pTab, then do two things:
|
|
// **
|
|
// ** (1) Mark the SELECT as as SF_Correlated.
|
|
// ** (2) Set pWalker->eCode to non-zero so that the caller will know
|
|
// ** that (1) has happened.
|
|
// */
|
|
func _sqlite3ReturningSubqueryCorrelated(tls *libc.TLS, pWalker uintptr, pSelect uintptr) (r int32) {
|
|
var i int32
|
|
var pSrc uintptr
|
|
_, _ = i, pSrc
|
|
pSrc = (*TSelect)(unsafe.Pointer(pSelect)).FpSrc
|
|
i = 0
|
|
for {
|
|
if !(i < (*TSrcList)(unsafe.Pointer(pSrc)).FnSrc) {
|
|
break
|
|
}
|
|
if (*(*TSrcItem)(unsafe.Pointer(pSrc + 8 + uintptr(i)*80))).FpSTab == *(*uintptr)(unsafe.Pointer(pWalker + 40)) {
|
|
**(**Tu32)(__ccgo_up(pSelect + 4)) |= uint32(SF_Correlated)
|
|
(*TWalker)(unsafe.Pointer(pWalker)).FeCode = uint16(1)
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return WRC_Continue
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is called by the VDBE to adjust the internal schema
|
|
// ** used by SQLite when the btree layer moves a table root page. The
|
|
// ** root-page of a table or index in database iDb has changed from iFrom
|
|
// ** to iTo.
|
|
// **
|
|
// ** Ticket #1728: The symbol table might still contain information
|
|
// ** on tables and/or indices that are the process of being deleted.
|
|
// ** If you are unlucky, one of those deleted indices or tables might
|
|
// ** have the same rootpage number as the real table or index that is
|
|
// ** being moved. So we cannot stop searching after the first match
|
|
// ** because the first match might be for one of the deleted indices
|
|
// ** or tables and not the table/index that is actually being moved.
|
|
// ** We must continue looping until all tables and indices with
|
|
// ** rootpage==iFrom have been converted to have a rootpage of iTo
|
|
// ** in order to be certain that we got the right one.
|
|
// */
|
|
func _sqlite3RootPageMoved(tls *libc.TLS, db uintptr, iDb int32, iFrom TPgno, iTo TPgno) {
|
|
var pDb, pElem, pHash, pIdx, pTab uintptr
|
|
_, _, _, _, _ = pDb, pElem, pHash, pIdx, pTab
|
|
pDb = (*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32
|
|
pHash = (*TDb)(unsafe.Pointer(pDb)).FpSchema + 8
|
|
pElem = (*THash)(unsafe.Pointer(pHash)).Ffirst
|
|
for {
|
|
if !(pElem != 0) {
|
|
break
|
|
}
|
|
pTab = (*THashElem)(unsafe.Pointer(pElem)).Fdata
|
|
if (*TTable)(unsafe.Pointer(pTab)).Ftnum == iFrom {
|
|
(*TTable)(unsafe.Pointer(pTab)).Ftnum = iTo
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pElem = (*THashElem)(unsafe.Pointer(pElem)).Fnext
|
|
}
|
|
pHash = (*TDb)(unsafe.Pointer(pDb)).FpSchema + 32
|
|
pElem = (*THash)(unsafe.Pointer(pHash)).Ffirst
|
|
for {
|
|
if !(pElem != 0) {
|
|
break
|
|
}
|
|
pIdx = (*THashElem)(unsafe.Pointer(pElem)).Fdata
|
|
if (*TIndex)(unsafe.Pointer(pIdx)).Ftnum == iFrom {
|
|
(*TIndex)(unsafe.Pointer(pIdx)).Ftnum = iTo
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
pElem = (*THashElem)(unsafe.Pointer(pElem)).Fnext
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Insert a new value into a RowSet.
|
|
// **
|
|
// ** The mallocFailed flag of the database connection is set if a
|
|
// ** memory allocation fails.
|
|
// */
|
|
func _sqlite3RowSetInsert(tls *libc.TLS, p uintptr, rowid Ti64) {
|
|
var pEntry, pLast, v1 uintptr
|
|
_, _, _ = pEntry, pLast, v1 /* The last prior entry */
|
|
/* This routine is never called after sqlite3RowSetNext() */
|
|
pEntry = _rowSetEntryAlloc(tls, p)
|
|
if pEntry == uintptr(0) {
|
|
return
|
|
}
|
|
(*TRowSetEntry)(unsafe.Pointer(pEntry)).Fv = rowid
|
|
(*TRowSetEntry)(unsafe.Pointer(pEntry)).FpRight = uintptr(0)
|
|
pLast = (*TRowSet)(unsafe.Pointer(p)).FpLast
|
|
if pLast != 0 {
|
|
if rowid <= (*TRowSetEntry)(unsafe.Pointer(pLast)).Fv { /*OPTIMIZATION-IF-FALSE*/
|
|
/* Avoid unnecessary sorts by preserving the ROWSET_SORTED flags
|
|
** where possible */
|
|
v1 = p + 50
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) & ^libc.Int32FromInt32(ROWSET_SORTED))
|
|
}
|
|
(*TRowSetEntry)(unsafe.Pointer(pLast)).FpRight = pEntry
|
|
} else {
|
|
(*TRowSet)(unsafe.Pointer(p)).FpEntry = pEntry
|
|
}
|
|
(*TRowSet)(unsafe.Pointer(p)).FpLast = pEntry
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Convert a schema pointer into the iDb index that indicates
|
|
// ** which database file in db->aDb[] the schema refers to.
|
|
// **
|
|
// ** If the same database is attached more than once, the first
|
|
// ** attached database is returned.
|
|
// */
|
|
func _sqlite3SchemaToIndex(tls *libc.TLS, db uintptr, pSchema uintptr) (r int32) {
|
|
var i int32
|
|
_ = i
|
|
i = -int32(32768)
|
|
/* If pSchema is NULL, then return -32768. This happens when code in
|
|
** expr.c is trying to resolve a reference to a transient table (i.e. one
|
|
** created by a sub-select). In this case the return value of this
|
|
** function should never be used.
|
|
**
|
|
** We return -32768 instead of the more usual -1 simply because using
|
|
** -32768 as the incorrect index into db->aDb[] is much
|
|
** more likely to cause a segfault than -1 (of course there are assert()
|
|
** statements too, but it never hurts to play the odds) and
|
|
** -32768 will still fit into a 16-bit signed integer.
|
|
*/
|
|
if pSchema != 0 {
|
|
i = 0
|
|
for {
|
|
if !(int32(1) != 0) {
|
|
break
|
|
}
|
|
if (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(i)*32))).FpSchema == pSchema {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
return i
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This routine adds datatype and collating sequence information to
|
|
// ** the Table structures of all FROM-clause subqueries in a
|
|
// ** SELECT statement.
|
|
// **
|
|
// ** Use this routine after name resolution.
|
|
// */
|
|
func _sqlite3SelectAddTypeInfo(tls *libc.TLS, pParse uintptr, pSelect uintptr) {
|
|
bp := tls.Alloc(48)
|
|
defer tls.Free(48)
|
|
var _ /* w at bp+0 */ TWalker
|
|
(**(**TWalker)(__ccgo_up(bp))).FxSelectCallback = __ccgo_fp(_sqlite3SelectWalkNoop)
|
|
(**(**TWalker)(__ccgo_up(bp))).FxSelectCallback2 = __ccgo_fp(_selectAddSubqueryTypeInfo)
|
|
(**(**TWalker)(__ccgo_up(bp))).FxExprCallback = __ccgo_fp(_sqlite3ExprWalkNoop)
|
|
(**(**TWalker)(__ccgo_up(bp))).FpParse = pParse
|
|
_sqlite3WalkSelect(tls, bp, pSelect)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This routine "expands" a SELECT statement and all of its subqueries.
|
|
// ** For additional information on what it means to "expand" a SELECT
|
|
// ** statement, see the comment on the selectExpand worker callback above.
|
|
// **
|
|
// ** Expanding a SELECT statement is the first step in processing a
|
|
// ** SELECT statement. The SELECT statement must be expanded before
|
|
// ** name resolution is performed.
|
|
// **
|
|
// ** If anything goes wrong, an error message is written into pParse.
|
|
// ** The calling function can detect the problem by looking at pParse->nErr
|
|
// ** and/or pParse->db->mallocFailed.
|
|
// */
|
|
func _sqlite3SelectExpand(tls *libc.TLS, pParse uintptr, pSelect uintptr) {
|
|
bp := tls.Alloc(48)
|
|
defer tls.Free(48)
|
|
var _ /* w at bp+0 */ TWalker
|
|
(**(**TWalker)(__ccgo_up(bp))).FxExprCallback = __ccgo_fp(_sqlite3ExprWalkNoop)
|
|
(**(**TWalker)(__ccgo_up(bp))).FpParse = pParse
|
|
if int32(Tbft(*(*uint16)(unsafe.Pointer(pParse + 40))&0x4>>2)) != 0 {
|
|
(**(**TWalker)(__ccgo_up(bp))).FxSelectCallback = __ccgo_fp(_convertCompoundSelectToSubquery)
|
|
(**(**TWalker)(__ccgo_up(bp))).FxSelectCallback2 = uintptr(0)
|
|
_sqlite3WalkSelect(tls, bp, pSelect)
|
|
}
|
|
(**(**TWalker)(__ccgo_up(bp))).FxSelectCallback = __ccgo_fp(_selectExpander)
|
|
(**(**TWalker)(__ccgo_up(bp))).FxSelectCallback2 = __ccgo_fp(_sqlite3SelectPopWith)
|
|
(**(**TWalker)(__ccgo_up(bp))).FeCode = uint16(0)
|
|
_sqlite3WalkSelect(tls, bp, pSelect)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Set the EP_OuterON property on all terms of the given expression.
|
|
// ** And set the Expr.w.iJoin to iTable for every term in the
|
|
// ** expression.
|
|
// **
|
|
// ** The EP_OuterON property is used on terms of an expression to tell
|
|
// ** the OUTER JOIN processing logic that this term is part of the
|
|
// ** join restriction specified in the ON or USING clause and not a part
|
|
// ** of the more general WHERE clause. These terms are moved over to the
|
|
// ** WHERE clause during join processing but we need to remember that they
|
|
// ** originated in the ON or USING clause.
|
|
// **
|
|
// ** The Expr.w.iJoin tells the WHERE clause processing that the
|
|
// ** expression depends on table w.iJoin even if that table is not
|
|
// ** explicitly mentioned in the expression. That information is needed
|
|
// ** for cases like this:
|
|
// **
|
|
// ** SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5
|
|
// **
|
|
// ** The where clause needs to defer the handling of the t1.x=5
|
|
// ** term until after the t2 loop of the join. In that way, a
|
|
// ** NULL t2 row will be inserted whenever t1.x!=5. If we do not
|
|
// ** defer the handling of t1.x=5, it will be processed immediately
|
|
// ** after the t1 loop and rows with t1.x!=5 will never appear in
|
|
// ** the output, which is incorrect.
|
|
// */
|
|
func _sqlite3SetJoinExpr(tls *libc.TLS, p uintptr, iTable int32, joinFlag Tu32) {
|
|
var i int32
|
|
_ = i
|
|
for p != 0 {
|
|
**(**Tu32)(__ccgo_up(p + 4)) |= joinFlag
|
|
*(*int32)(unsafe.Pointer(p + 52)) = iTable
|
|
if (*TExpr)(unsafe.Pointer(p)).Fflags&uint32(EP_xIsSelect) == uint32(0) {
|
|
if *(*uintptr)(unsafe.Pointer(p + 32)) != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TExprList)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(p + 32)))).FnExpr) {
|
|
break
|
|
}
|
|
_sqlite3SetJoinExpr(tls, (*(*TExprList_item)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(p + 32)) + 8 + uintptr(i)*32))).FpExpr, iTable, joinFlag)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
}
|
|
_sqlite3SetJoinExpr(tls, (*TExpr)(unsafe.Pointer(p)).FpLeft, iTable, joinFlag)
|
|
p = (*TExpr)(unsafe.Pointer(p)).FpRight
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Mark a subquery result column as having been used.
|
|
// */
|
|
func _sqlite3SrcItemColumnUsed(tls *libc.TLS, pItem uintptr, iCol int32) {
|
|
var pResults uintptr
|
|
_ = pResults
|
|
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x4000>>14) != 0 {
|
|
pResults = (*TSelect)(unsafe.Pointer((*TSubquery)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pItem + 72)))).FpSelect)).FpEList
|
|
libc.SetBitFieldPtr16Uint32(pResults+8+uintptr(iCol)*32+16+4, libc.Uint32FromInt32(1), 6, 0x40)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Assign VdbeCursor index numbers to all tables in a SrcList
|
|
// */
|
|
func _sqlite3SrcListAssignCursors(tls *libc.TLS, pParse uintptr, pList uintptr) {
|
|
var i, v2 int32
|
|
var pItem, v3 uintptr
|
|
_, _, _, _ = i, pItem, v2, v3
|
|
if pList != 0 {
|
|
i = 0
|
|
pItem = pList + 8
|
|
for {
|
|
if !(i < (*TSrcList)(unsafe.Pointer(pList)).FnSrc) {
|
|
break
|
|
}
|
|
if (*TSrcItem)(unsafe.Pointer(pItem)).FiCursor >= 0 {
|
|
goto _1
|
|
}
|
|
v3 = pParse + 56
|
|
v2 = *(*int32)(unsafe.Pointer(v3))
|
|
*(*int32)(unsafe.Pointer(v3)) = *(*int32)(unsafe.Pointer(v3)) + 1
|
|
(*TSrcItem)(unsafe.Pointer(pItem)).FiCursor = v2
|
|
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x4>>2) != 0 {
|
|
_sqlite3SrcListAssignCursors(tls, pParse, (*TSelect)(unsafe.Pointer((*TSubquery)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pItem + 72)))).FpSelect)).FpSrc)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
pItem += 80
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Delete an entire SrcList including all its substructure.
|
|
// */
|
|
func _sqlite3SrcListDelete(tls *libc.TLS, db uintptr, pList uintptr) {
|
|
var i int32
|
|
var pItem uintptr
|
|
_, _ = i, pItem
|
|
if pList == uintptr(0) {
|
|
return
|
|
}
|
|
pItem = pList + 8
|
|
i = libc.Int32FromInt32(0)
|
|
for {
|
|
if !(i < (*TSrcList)(unsafe.Pointer(pList)).FnSrc) {
|
|
break
|
|
}
|
|
/* Check invariants on SrcItem */
|
|
if (*TSrcItem)(unsafe.Pointer(pItem)).FzName != 0 {
|
|
_sqlite3DbNNFreeNN(tls, db, (*TSrcItem)(unsafe.Pointer(pItem)).FzName)
|
|
}
|
|
if (*TSrcItem)(unsafe.Pointer(pItem)).FzAlias != 0 {
|
|
_sqlite3DbNNFreeNN(tls, db, (*TSrcItem)(unsafe.Pointer(pItem)).FzAlias)
|
|
}
|
|
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x4>>2) != 0 {
|
|
_sqlite3SubqueryDelete(tls, db, *(*uintptr)(unsafe.Pointer(pItem + 72)))
|
|
} else {
|
|
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x10000>>16) == 0 && *(*uintptr)(unsafe.Pointer(pItem + 72)) != uintptr(0) {
|
|
_sqlite3DbNNFreeNN(tls, db, *(*uintptr)(unsafe.Pointer(pItem + 72)))
|
|
}
|
|
}
|
|
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x2>>1) != 0 {
|
|
_sqlite3DbFree(tls, db, *(*uintptr)(unsafe.Pointer(pItem + 48)))
|
|
}
|
|
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x8>>3) != 0 {
|
|
_sqlite3ExprListDelete(tls, db, *(*uintptr)(unsafe.Pointer(pItem + 48)))
|
|
}
|
|
_sqlite3DeleteTable(tls, db, (*TSrcItem)(unsafe.Pointer(pItem)).FpSTab)
|
|
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x800>>11) != 0 {
|
|
_sqlite3IdListDelete(tls, db, *(*uintptr)(unsafe.Pointer(pItem + 64)))
|
|
} else {
|
|
if *(*uintptr)(unsafe.Pointer(pItem + 64)) != 0 {
|
|
_sqlite3ExprDelete(tls, db, *(*uintptr)(unsafe.Pointer(pItem + 64)))
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
pItem += 80
|
|
}
|
|
_sqlite3DbNNFreeNN(tls, db, pList)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Add the list of function arguments to the SrcList entry for a
|
|
// ** table-valued-function.
|
|
// */
|
|
func _sqlite3SrcListFuncArgs(tls *libc.TLS, pParse uintptr, p uintptr, pList uintptr) {
|
|
var pItem uintptr
|
|
_ = pItem
|
|
if p != 0 {
|
|
pItem = p + 8 + uintptr((*TSrcList)(unsafe.Pointer(p)).FnSrc-int32(1))*80
|
|
*(*uintptr)(unsafe.Pointer(pItem + 48)) = pList
|
|
libc.SetBitFieldPtr32Uint32(pItem+24+4, libc.Uint32FromInt32(1), 3, 0x8)
|
|
} else {
|
|
_sqlite3ExprListDelete(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pList)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Add an INDEXED BY or NOT INDEXED clause to the most recently added
|
|
// ** element of the source-list passed as the second argument.
|
|
// */
|
|
func _sqlite3SrcListIndexedBy(tls *libc.TLS, pParse uintptr, p uintptr, pIndexedBy uintptr) {
|
|
var pItem uintptr
|
|
_ = pItem
|
|
if p != 0 && (*TToken)(unsafe.Pointer(pIndexedBy)).Fn > uint32(0) {
|
|
pItem = p + 8 + uintptr((*TSrcList)(unsafe.Pointer(p)).FnSrc-int32(1))*80
|
|
if (*TToken)(unsafe.Pointer(pIndexedBy)).Fn == uint32(1) && !((*TToken)(unsafe.Pointer(pIndexedBy)).Fz != 0) {
|
|
/* A "NOT INDEXED" clause was supplied. See parse.y
|
|
** construct "indexed_opt" for details. */
|
|
libc.SetBitFieldPtr32Uint32(pItem+24+4, libc.Uint32FromInt32(1), 0, 0x1)
|
|
} else {
|
|
*(*uintptr)(unsafe.Pointer(pItem + 48)) = _sqlite3NameFromToken(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pIndexedBy)
|
|
libc.SetBitFieldPtr32Uint32(pItem+24+4, libc.Uint32FromInt32(1), 1, 0x2)
|
|
/* No collision on union u2 */
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** While a SrcList can in general represent multiple tables and subqueries
|
|
// ** (as in the FROM clause of a SELECT statement) in this case it contains
|
|
// ** the name of a single table, as one might find in an INSERT, DELETE,
|
|
// ** or UPDATE statement. Look up that table in the symbol table and
|
|
// ** return a pointer. Set an error message and return NULL if the table
|
|
// ** name is not found or if any other error occurs.
|
|
// **
|
|
// ** The following fields are initialized appropriate in pSrc:
|
|
// **
|
|
// ** pSrc->a[0].spTab Pointer to the Table object
|
|
// ** pSrc->a[0].u2.pIBIndex Pointer to the INDEXED BY index, if there is one
|
|
// **
|
|
// */
|
|
func _sqlite3SrcListLookup(tls *libc.TLS, pParse uintptr, pSrc uintptr) (r uintptr) {
|
|
var pItem, pTab uintptr
|
|
_, _ = pItem, pTab
|
|
pItem = pSrc + 8
|
|
pTab = _sqlite3LocateTableItem(tls, pParse, uint32(0), pItem)
|
|
if (*TSrcItem)(unsafe.Pointer(pItem)).FpSTab != 0 {
|
|
_sqlite3DeleteTable(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, (*TSrcItem)(unsafe.Pointer(pItem)).FpSTab)
|
|
}
|
|
(*TSrcItem)(unsafe.Pointer(pItem)).FpSTab = pTab
|
|
libc.SetBitFieldPtr32Uint32(pItem+24+4, libc.Uint32FromInt32(1), 10, 0x400)
|
|
if pTab != 0 {
|
|
(*TTable)(unsafe.Pointer(pTab)).FnTabRef = (*TTable)(unsafe.Pointer(pTab)).FnTabRef + 1
|
|
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x2>>1) != 0 && _sqlite3IndexedByLookup(tls, pParse, pItem) != 0 {
|
|
pTab = uintptr(0)
|
|
}
|
|
}
|
|
return pTab
|
|
}
|
|
|
|
func _sqlite3StatusDown(tls *libc.TLS, op int32, N int32) {
|
|
**(**Tsqlite3StatValueType)(__ccgo_up(uintptr(unsafe.Pointer(&_sqlite3Stat)) + uintptr(op)*8)) -= int64(N)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Adjust the highwater mark if necessary.
|
|
// ** The caller must hold the appropriate mutex.
|
|
// */
|
|
func _sqlite3StatusHighwater(tls *libc.TLS, op int32, X int32) {
|
|
var newValue Tsqlite3StatValueType
|
|
_ = newValue
|
|
newValue = int64(X)
|
|
if newValue > **(**Tsqlite3StatValueType)(__ccgo_up(uintptr(unsafe.Pointer(&_sqlite3Stat)) + 80 + uintptr(op)*8)) {
|
|
**(**Tsqlite3StatValueType)(__ccgo_up(uintptr(unsafe.Pointer(&_sqlite3Stat)) + 80 + uintptr(op)*8)) = newValue
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Add N to the value of a status record. The caller must hold the
|
|
// ** appropriate mutex. (Locking is checked by assert()).
|
|
// **
|
|
// ** The StatusUp() routine can accept positive or negative values for N.
|
|
// ** The value of N is added to the current status value and the high-water
|
|
// ** mark is adjusted if necessary.
|
|
// **
|
|
// ** The StatusDown() routine lowers the current value by N. The highwater
|
|
// ** mark is unchanged. N must be non-negative for StatusDown().
|
|
// */
|
|
func _sqlite3StatusUp(tls *libc.TLS, op int32, N int32) {
|
|
**(**Tsqlite3StatValueType)(__ccgo_up(uintptr(unsafe.Pointer(&_sqlite3Stat)) + uintptr(op)*8)) += int64(N)
|
|
if **(**Tsqlite3StatValueType)(__ccgo_up(uintptr(unsafe.Pointer(&_sqlite3Stat)) + uintptr(op)*8)) > **(**Tsqlite3StatValueType)(__ccgo_up(uintptr(unsafe.Pointer(&_sqlite3Stat)) + 80 + uintptr(op)*8)) {
|
|
**(**Tsqlite3StatValueType)(__ccgo_up(uintptr(unsafe.Pointer(&_sqlite3Stat)) + 80 + uintptr(op)*8)) = **(**Tsqlite3StatValueType)(__ccgo_up(uintptr(unsafe.Pointer(&_sqlite3Stat)) + uintptr(op)*8))
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the current value of a status parameter. The caller must
|
|
// ** be holding the appropriate mutex.
|
|
// */
|
|
func _sqlite3StatusValue(tls *libc.TLS, op int32) (r Tsqlite3_int64) {
|
|
return **(**Tsqlite3StatValueType)(__ccgo_up(uintptr(unsafe.Pointer(&_sqlite3Stat)) + uintptr(op)*8))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the current time for a statement. If the current time
|
|
// ** is requested more than once within the same run of a single prepared
|
|
// ** statement, the exact same time is returned for each invocation regardless
|
|
// ** of the amount of time that elapses between invocations. In other words,
|
|
// ** the time returned is always the time of the first call.
|
|
// */
|
|
func _sqlite3StmtCurrentTime(tls *libc.TLS, p uintptr) (r Tsqlite3_int64) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var piTime, v1 uintptr
|
|
var rc int32
|
|
var _ /* iTime at bp+0 */ Tsqlite3_int64
|
|
_, _, _ = piTime, rc, v1
|
|
**(**Tsqlite3_int64)(__ccgo_up(bp)) = 0
|
|
if (*Tsqlite3_context)(unsafe.Pointer(p)).FpVdbe != uintptr(0) {
|
|
v1 = (*Tsqlite3_context)(unsafe.Pointer(p)).FpVdbe + 72
|
|
} else {
|
|
v1 = bp
|
|
}
|
|
piTime = v1
|
|
if **(**Tsqlite3_int64)(__ccgo_up(piTime)) == 0 {
|
|
rc = _sqlite3OsCurrentTimeInt64(tls, (*Tsqlite3)(unsafe.Pointer((*TMem)(unsafe.Pointer((*Tsqlite3_context)(unsafe.Pointer(p)).FpOut)).Fdb)).FpVfs, piTime)
|
|
if rc != 0 {
|
|
**(**Tsqlite3_int64)(__ccgo_up(piTime)) = 0
|
|
}
|
|
}
|
|
return **(**Tsqlite3_int64)(__ccgo_up(piTime))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Remove a Subquery from a SrcItem. Return the associated Select object.
|
|
// ** The returned Select becomes the responsibility of the caller.
|
|
// */
|
|
func _sqlite3SubqueryDetach(tls *libc.TLS, db uintptr, pItem uintptr) (r uintptr) {
|
|
var pSel uintptr
|
|
_ = pSel
|
|
pSel = (*TSubquery)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pItem + 72)))).FpSelect
|
|
_sqlite3DbFree(tls, db, *(*uintptr)(unsafe.Pointer(pItem + 72)))
|
|
*(*uintptr)(unsafe.Pointer(pItem + 72)) = uintptr(0)
|
|
libc.SetBitFieldPtr32Uint32(pItem+24+4, libc.Uint32FromInt32(0), 2, 0x4)
|
|
return pSel
|
|
}
|
|
|
|
func _sqlite3TableLock(tls *libc.TLS, pParse uintptr, iDb int32, iTab TPgno, isWriteLock Tu8, zName uintptr) {
|
|
if iDb == int32(1) {
|
|
return
|
|
}
|
|
if !(_sqlite3BtreeSharable(tls, (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer(pParse)).Fdb)).FaDb + uintptr(iDb)*32))).FpBt) != 0) {
|
|
return
|
|
}
|
|
_lockTable(tls, pParse, iDb, iTab, isWriteLock, zName)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Transfer all bindings from the first statement over to the second.
|
|
// */
|
|
func _sqlite3TransferBindings(tls *libc.TLS, pFromStmt uintptr, pToStmt uintptr) (r int32) {
|
|
var i int32
|
|
var pFrom, pTo uintptr
|
|
_, _, _ = i, pFrom, pTo
|
|
pFrom = pFromStmt
|
|
pTo = pToStmt
|
|
Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer((*TVdbe)(unsafe.Pointer(pTo)).Fdb)).Fmutex)
|
|
i = 0
|
|
for {
|
|
if !(i < int32((*TVdbe)(unsafe.Pointer(pFrom)).FnVar)) {
|
|
break
|
|
}
|
|
_sqlite3VdbeMemMove(tls, (*TVdbe)(unsafe.Pointer(pTo)).FaVar+uintptr(i)*56, (*TVdbe)(unsafe.Pointer(pFrom)).FaVar+uintptr(i)*56)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer((*TVdbe)(unsafe.Pointer(pTo)).Fdb)).Fmutex)
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Turn a SELECT statement (that the pSelect parameter points to) into
|
|
// ** a trigger step. Return a pointer to a TriggerStep structure.
|
|
// **
|
|
// ** The parser calls this routine when it finds a SELECT statement in
|
|
// ** body of a TRIGGER.
|
|
// */
|
|
func _sqlite3TriggerSelectStep(tls *libc.TLS, db uintptr, pSelect uintptr, zStart uintptr, zEnd uintptr) (r uintptr) {
|
|
var pTriggerStep uintptr
|
|
_ = pTriggerStep
|
|
pTriggerStep = _sqlite3DbMallocZero(tls, db, uint64(88))
|
|
if pTriggerStep == uintptr(0) {
|
|
_sqlite3SelectDelete(tls, db, pSelect)
|
|
return uintptr(0)
|
|
}
|
|
(*TTriggerStep)(unsafe.Pointer(pTriggerStep)).Fop = uint8(TK_SELECT)
|
|
(*TTriggerStep)(unsafe.Pointer(pTriggerStep)).FpSelect = pSelect
|
|
(*TTriggerStep)(unsafe.Pointer(pTriggerStep)).Forconf = uint8(OE_Default)
|
|
(*TTriggerStep)(unsafe.Pointer(pTriggerStep)).FzSpan = _triggerSpanDup(tls, db, zStart, zEnd)
|
|
return pTriggerStep
|
|
}
|
|
|
|
func _sqlite3TriggersExist(tls *libc.TLS, pParse uintptr, pTab uintptr, op int32, pChanges uintptr, pMask uintptr) (r uintptr) {
|
|
if (*TTable)(unsafe.Pointer(pTab)).FpTrigger == uintptr(0) && !(_tempTriggersExist(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb) != 0) || int32(Tbft(*(*uint16)(unsafe.Pointer(pParse + 40))&0x1>>0)) != 0 {
|
|
if pMask != 0 {
|
|
**(**int32)(__ccgo_up(pMask)) = 0
|
|
}
|
|
return uintptr(0)
|
|
}
|
|
return _triggersReallyExist(tls, pParse, pTab, op, pChanges, pMask)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** For the index called zIdxName which is found in the database iDb,
|
|
// ** unlike that index from its Table then remove the index from
|
|
// ** the index hash table and free all memory structures associated
|
|
// ** with the index.
|
|
// */
|
|
func _sqlite3UnlinkAndDeleteIndex(tls *libc.TLS, db uintptr, iDb int32, zIdxName uintptr) {
|
|
var p, pHash, pIndex uintptr
|
|
_, _, _ = p, pHash, pIndex
|
|
pHash = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FpSchema + 32
|
|
pIndex = _sqlite3HashInsert(tls, pHash, zIdxName, uintptr(0))
|
|
if pIndex != 0 {
|
|
if (*TTable)(unsafe.Pointer((*TIndex)(unsafe.Pointer(pIndex)).FpTable)).FpIndex == pIndex {
|
|
(*TTable)(unsafe.Pointer((*TIndex)(unsafe.Pointer(pIndex)).FpTable)).FpIndex = (*TIndex)(unsafe.Pointer(pIndex)).FpNext
|
|
} else {
|
|
/* Justification of ALWAYS(); The index must be on the list of
|
|
** indices. */
|
|
p = (*TTable)(unsafe.Pointer((*TIndex)(unsafe.Pointer(pIndex)).FpTable)).FpIndex
|
|
for p != 0 && (*TIndex)(unsafe.Pointer(p)).FpNext != pIndex {
|
|
p = (*TIndex)(unsafe.Pointer(p)).FpNext
|
|
}
|
|
if p != 0 && (*TIndex)(unsafe.Pointer(p)).FpNext == pIndex {
|
|
(*TIndex)(unsafe.Pointer(p)).FpNext = (*TIndex)(unsafe.Pointer(pIndex)).FpNext
|
|
}
|
|
}
|
|
_sqlite3FreeIndex(tls, db, pIndex)
|
|
}
|
|
**(**Tu32)(__ccgo_up(db + 44)) |= uint32(DBFLAG_SchemaChange)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Unlink the given table from the hash tables and the delete the
|
|
// ** table structure with all its indices and foreign keys.
|
|
// */
|
|
func _sqlite3UnlinkAndDeleteTable(tls *libc.TLS, db uintptr, iDb int32, zTabName uintptr) {
|
|
var p, pDb uintptr
|
|
_, _ = p, pDb
|
|
/* Zero-length table names are allowed */
|
|
pDb = (*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32
|
|
p = _sqlite3HashInsert(tls, (*TDb)(unsafe.Pointer(pDb)).FpSchema+8, zTabName, uintptr(0))
|
|
_sqlite3DeleteTable(tls, db, p)
|
|
**(**Tu32)(__ccgo_up(db + 44)) |= uint32(DBFLAG_SchemaChange)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Remove a trigger from the hash tables of the sqlite* pointer.
|
|
// */
|
|
func _sqlite3UnlinkAndDeleteTrigger(tls *libc.TLS, db uintptr, iDb int32, zName uintptr) {
|
|
var pHash, pTab, pTrigger, pp uintptr
|
|
_, _, _, _ = pHash, pTab, pTrigger, pp
|
|
pHash = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(iDb)*32))).FpSchema + 56
|
|
pTrigger = _sqlite3HashInsert(tls, pHash, zName, uintptr(0))
|
|
if pTrigger != 0 {
|
|
if (*TTrigger)(unsafe.Pointer(pTrigger)).FpSchema == (*TTrigger)(unsafe.Pointer(pTrigger)).FpTabSchema {
|
|
pTab = _tableOfTrigger(tls, pTrigger)
|
|
if pTab != 0 {
|
|
pp = pTab + 88
|
|
for {
|
|
if !(**(**uintptr)(__ccgo_up(pp)) != 0) {
|
|
break
|
|
}
|
|
if **(**uintptr)(__ccgo_up(pp)) == pTrigger {
|
|
**(**uintptr)(__ccgo_up(pp)) = (*TTrigger)(unsafe.Pointer(**(**uintptr)(__ccgo_up(pp)))).FpNext
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pp = **(**uintptr)(__ccgo_up(pp)) + 64
|
|
}
|
|
}
|
|
}
|
|
_sqlite3DeleteTrigger(tls, db, pTrigger)
|
|
**(**Tu32)(__ccgo_up(db + 44)) |= uint32(DBFLAG_SchemaChange)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Create a new Upsert object.
|
|
// */
|
|
func _sqlite3UpsertNew(tls *libc.TLS, db uintptr, pTarget uintptr, pTargetWhere uintptr, pSet uintptr, pWhere uintptr, pNext uintptr) (r uintptr) {
|
|
var pNew uintptr
|
|
_ = pNew
|
|
pNew = _sqlite3DbMallocZero(tls, db, uint64(88))
|
|
if pNew == uintptr(0) {
|
|
_sqlite3ExprListDelete(tls, db, pTarget)
|
|
_sqlite3ExprDelete(tls, db, pTargetWhere)
|
|
_sqlite3ExprListDelete(tls, db, pSet)
|
|
_sqlite3ExprDelete(tls, db, pWhere)
|
|
_sqlite3UpsertDelete(tls, db, pNext)
|
|
return uintptr(0)
|
|
} else {
|
|
(*TUpsert)(unsafe.Pointer(pNew)).FpUpsertTarget = pTarget
|
|
(*TUpsert)(unsafe.Pointer(pNew)).FpUpsertTargetWhere = pTargetWhere
|
|
(*TUpsert)(unsafe.Pointer(pNew)).FpUpsertSet = pSet
|
|
(*TUpsert)(unsafe.Pointer(pNew)).FpUpsertWhere = pWhere
|
|
(*TUpsert)(unsafe.Pointer(pNew)).FisDoUpdate = libc.BoolUint8(pSet != uintptr(0))
|
|
(*TUpsert)(unsafe.Pointer(pNew)).FpNextUpsert = pNext
|
|
}
|
|
return pNew
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The VACUUM command is used to clean up the database,
|
|
// ** collapse free space, etc. It is modelled after the VACUUM command
|
|
// ** in PostgreSQL. The VACUUM command works as follows:
|
|
// **
|
|
// ** (1) Create a new transient database file
|
|
// ** (2) Copy all content from the database being vacuumed into
|
|
// ** the new transient database file
|
|
// ** (3) Copy content from the transient database back into the
|
|
// ** original database.
|
|
// **
|
|
// ** The transient database requires temporary disk space approximately
|
|
// ** equal to the size of the original database. The copy operation of
|
|
// ** step (3) requires additional temporary disk space approximately equal
|
|
// ** to the size of the original database for the rollback journal.
|
|
// ** Hence, temporary disk space that is approximately 2x the size of the
|
|
// ** original database is required. Every page of the database is written
|
|
// ** approximately 3 times: Once for step (2) and twice for step (3).
|
|
// ** Two writes per page are required in step (3) because the original
|
|
// ** database content must be written into the rollback journal prior to
|
|
// ** overwriting the database with the vacuumed content.
|
|
// **
|
|
// ** Only 1x temporary space and only 1x writes would be required if
|
|
// ** the copy of step (3) were replaced by deleting the original database
|
|
// ** and renaming the transient database as the original. But that will
|
|
// ** not work if other processes are attached to the original database.
|
|
// ** And a power loss in between deleting the original and renaming the
|
|
// ** transient would cause the database file to appear to be deleted
|
|
// ** following reboot.
|
|
// */
|
|
func _sqlite3Vacuum(tls *libc.TLS, pParse uintptr, _pNm uintptr, pInto uintptr) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
*(*uintptr)(unsafe.Pointer(bp)) = _pNm
|
|
var iDb, iIntoReg, v1 int32
|
|
var v, v2 uintptr
|
|
_, _, _, _, _ = iDb, iIntoReg, v, v1, v2
|
|
v = _sqlite3GetVdbe(tls, pParse)
|
|
iDb = 0
|
|
if v == uintptr(0) {
|
|
goto build_vacuum_end
|
|
}
|
|
if (*TParse)(unsafe.Pointer(pParse)).FnErr != 0 {
|
|
goto build_vacuum_end
|
|
}
|
|
if **(**uintptr)(__ccgo_up(bp)) != 0 {
|
|
/* Default behavior: Report an error if the argument to VACUUM is
|
|
** not recognized */
|
|
iDb = _sqlite3TwoPartName(tls, pParse, **(**uintptr)(__ccgo_up(bp)), **(**uintptr)(__ccgo_up(bp)), bp)
|
|
if iDb < 0 {
|
|
goto build_vacuum_end
|
|
}
|
|
}
|
|
if iDb != int32(1) {
|
|
iIntoReg = 0
|
|
if pInto != 0 && _sqlite3ResolveSelfReference(tls, pParse, uintptr(0), 0, pInto, uintptr(0)) == 0 {
|
|
v2 = pParse + 60
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
iIntoReg = v1
|
|
_sqlite3ExprCode(tls, pParse, pInto, iIntoReg)
|
|
}
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Vacuum), iDb, iIntoReg)
|
|
_sqlite3VdbeUsesBtree(tls, v, iDb)
|
|
}
|
|
goto build_vacuum_end
|
|
build_vacuum_end:
|
|
;
|
|
_sqlite3ExprDelete(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pInto)
|
|
return
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Create a new sqlite3_value object.
|
|
// */
|
|
func _sqlite3ValueNew(tls *libc.TLS, db uintptr) (r uintptr) {
|
|
var p uintptr
|
|
_ = p
|
|
p = _sqlite3DbMallocZero(tls, db, uint64(56))
|
|
if p != 0 {
|
|
(*TMem)(unsafe.Pointer(p)).Fflags = uint16(MEM_Null)
|
|
(*TMem)(unsafe.Pointer(p)).Fdb = db
|
|
}
|
|
return p
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Change the P4 operand of the most recently coded instruction
|
|
// ** to the value defined by the arguments. This is a high-speed
|
|
// ** version of sqlite3VdbeChangeP4().
|
|
// **
|
|
// ** The P4 operand must not have been previously defined. And the new
|
|
// ** P4 must not be P4_INT32. Use sqlite3VdbeChangeP4() in either of
|
|
// ** those cases.
|
|
// */
|
|
func _sqlite3VdbeAppendP4(tls *libc.TLS, p uintptr, pP4 uintptr, n int32) {
|
|
var pOp uintptr
|
|
_ = pOp
|
|
if (*Tsqlite3)(unsafe.Pointer((*TVdbe)(unsafe.Pointer(p)).Fdb)).FmallocFailed != 0 {
|
|
_freeP4(tls, (*TVdbe)(unsafe.Pointer(p)).Fdb, n, pP4)
|
|
} else {
|
|
pOp = (*TVdbe)(unsafe.Pointer(p)).FaOp + uintptr((*TVdbe)(unsafe.Pointer(p)).FnOp-int32(1))*24
|
|
(*TVdbeOp)(unsafe.Pointer(pOp)).Fp4type = int8(n)
|
|
*(*uintptr)(unsafe.Pointer(pOp + 16)) = pP4
|
|
}
|
|
}
|
|
|
|
func _sqlite3VdbeChangeP4(tls *libc.TLS, p uintptr, addr int32, _zP4 uintptr, n int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
*(*uintptr)(unsafe.Pointer(bp)) = _zP4
|
|
var db, pOp uintptr
|
|
_, _ = db, pOp
|
|
db = (*TVdbe)(unsafe.Pointer(p)).Fdb
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
|
|
if n != -int32(12) {
|
|
_freeP4(tls, db, n, **(**uintptr)(__ccgo_up(bp)))
|
|
}
|
|
return
|
|
}
|
|
if addr < 0 {
|
|
addr = (*TVdbe)(unsafe.Pointer(p)).FnOp - int32(1)
|
|
}
|
|
pOp = (*TVdbe)(unsafe.Pointer(p)).FaOp + uintptr(addr)*24
|
|
if n >= 0 || (*TOp)(unsafe.Pointer(pOp)).Fp4type != 0 {
|
|
_vdbeChangeP4Full(tls, p, pOp, **(**uintptr)(__ccgo_up(bp)), n)
|
|
return
|
|
}
|
|
if n == -int32(3) {
|
|
/* Note: this cast is safe, because the origin data point was an int
|
|
** that was cast to a (const char *). */
|
|
(*TOp)(unsafe.Pointer(pOp)).Fp4.Fi = int32(int64(**(**uintptr)(__ccgo_up(bp))))
|
|
(*TOp)(unsafe.Pointer(pOp)).Fp4type = int8(-libc.Int32FromInt32(3))
|
|
} else {
|
|
if **(**uintptr)(__ccgo_up(bp)) != uintptr(0) {
|
|
*(*uintptr)(unsafe.Pointer(pOp + 16)) = **(**uintptr)(__ccgo_up(bp))
|
|
(*TOp)(unsafe.Pointer(pOp)).Fp4type = int8(n)
|
|
if n == -int32(12) {
|
|
_sqlite3VtabLock(tls, **(**uintptr)(__ccgo_up(bp)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func _sqlite3VdbeChangeP5(tls *libc.TLS, p uintptr, p5 Tu16) {
|
|
if (*TVdbe)(unsafe.Pointer(p)).FnOp > 0 {
|
|
(**(**TOp)(__ccgo_up((*TVdbe)(unsafe.Pointer(p)).FaOp + uintptr((*TVdbe)(unsafe.Pointer(p)).FnOp-int32(1))*24))).Fp5 = p5
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Change the opcode at addr into OP_Noop
|
|
// */
|
|
func _sqlite3VdbeChangeToNoop(tls *libc.TLS, p uintptr, addr int32) (r int32) {
|
|
var pOp uintptr
|
|
_ = pOp
|
|
if (*Tsqlite3)(unsafe.Pointer((*TVdbe)(unsafe.Pointer(p)).Fdb)).FmallocFailed != 0 {
|
|
return 0
|
|
}
|
|
pOp = (*TVdbe)(unsafe.Pointer(p)).FaOp + uintptr(addr)*24
|
|
_freeP4(tls, (*TVdbe)(unsafe.Pointer(p)).Fdb, int32((*TVdbeOp)(unsafe.Pointer(pOp)).Fp4type), *(*uintptr)(unsafe.Pointer(pOp + 16)))
|
|
(*TVdbeOp)(unsafe.Pointer(pOp)).Fp4type = P4_NOTUSED
|
|
*(*uintptr)(unsafe.Pointer(pOp + 16)) = uintptr(0)
|
|
(*TVdbeOp)(unsafe.Pointer(pOp)).Fopcode = uint8(OP_Noop)
|
|
return int32(1)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Set a flag in the vdbe to update the change counter when it is finalised
|
|
// ** or reset.
|
|
// */
|
|
func _sqlite3VdbeCountChanges(tls *libc.TLS, v uintptr) {
|
|
libc.SetBitFieldPtr16Uint32(v+200, libc.Uint32FromInt32(1), 4, 0x10)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Check to ensure that the cursor is valid. Restore the cursor
|
|
// ** if need be. Return any I/O error from the restore operation.
|
|
// */
|
|
func _sqlite3VdbeCursorRestore(tls *libc.TLS, p uintptr) (r int32) {
|
|
if _sqlite3BtreeCursorHasMoved(tls, *(*uintptr)(unsafe.Pointer(p + 48))) != 0 {
|
|
return _sqlite3VdbeHandleMovedCursor(tls, p)
|
|
}
|
|
return SQLITE_OK
|
|
}
|
|
|
|
/*
|
|
** The following functions:
|
|
**
|
|
** sqlite3VdbeSerialType()
|
|
** sqlite3VdbeSerialTypeLen()
|
|
** sqlite3VdbeSerialLen()
|
|
** sqlite3VdbeSerialPut() <--- in-lined into OP_MakeRecord as of 2022-04-02
|
|
** sqlite3VdbeSerialGet()
|
|
**
|
|
** encapsulate the code that serializes values for storage in SQLite
|
|
** data and index records. Each serialized value consists of a
|
|
** 'serial-type' and a blob of data. The serial type is an 8-byte unsigned
|
|
** integer, stored as a varint.
|
|
**
|
|
** In an SQLite index record, the serial type is stored directly before
|
|
** the blob of data that it corresponds to. In a table record, all serial
|
|
** types are stored at the start of the record, and the blobs of data at
|
|
** the end. Hence these functions allow the caller to handle the
|
|
** serial-type and data blob separately.
|
|
**
|
|
** The following table describes the various storage classes for data:
|
|
**
|
|
** serial type bytes of data type
|
|
** -------------- --------------- ---------------
|
|
** 0 0 NULL
|
|
** 1 1 signed integer
|
|
** 2 2 signed integer
|
|
** 3 3 signed integer
|
|
** 4 4 signed integer
|
|
** 5 6 signed integer
|
|
** 6 8 signed integer
|
|
** 7 8 IEEE float
|
|
** 8 0 Integer constant 0
|
|
** 9 0 Integer constant 1
|
|
** 10,11 reserved for expansion
|
|
** N>=12 and even (N-12)/2 BLOB
|
|
** N>=13 and odd (N-13)/2 text
|
|
**
|
|
** The 8 and 9 types were added in 3.3.0, file format 4. Prior versions
|
|
** of SQLite will not understand those serial types.
|
|
*/
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If SQLite is compiled to support shared-cache mode and to be threadsafe,
|
|
// ** this routine obtains the mutex associated with each BtShared structure
|
|
// ** that may be accessed by the VM passed as an argument. In doing so it also
|
|
// ** sets the BtShared.db member of each of the BtShared structures, ensuring
|
|
// ** that the correct busy-handler callback is invoked if required.
|
|
// **
|
|
// ** If SQLite is not threadsafe but does support shared-cache mode, then
|
|
// ** sqlite3BtreeEnter() is invoked to set the BtShared.db variables
|
|
// ** of all of BtShared structures accessible via the database handle
|
|
// ** associated with the VM.
|
|
// **
|
|
// ** If SQLite is not threadsafe and does not support shared-cache mode, this
|
|
// ** function is a no-op.
|
|
// **
|
|
// ** The p->btreeMask field is a bitmask of all btrees that the prepared
|
|
// ** statement p will ever use. Let N be the number of bits in p->btreeMask
|
|
// ** corresponding to btrees that use shared cache. Then the runtime of
|
|
// ** this routine is N*N. But as N is rarely more than 1, this should not
|
|
// ** be a problem.
|
|
// */
|
|
func _sqlite3VdbeEnter(tls *libc.TLS, p uintptr) {
|
|
var aDb, db uintptr
|
|
var i, nDb int32
|
|
_, _, _, _ = aDb, db, i, nDb
|
|
if (*TVdbe)(unsafe.Pointer(p)).FlockMask == uint32(0) {
|
|
return
|
|
} /* The common case */
|
|
db = (*TVdbe)(unsafe.Pointer(p)).Fdb
|
|
aDb = (*Tsqlite3)(unsafe.Pointer(db)).FaDb
|
|
nDb = (*Tsqlite3)(unsafe.Pointer(db)).FnDb
|
|
i = 0
|
|
for {
|
|
if !(i < nDb) {
|
|
break
|
|
}
|
|
if i != int32(1) && (*TVdbe)(unsafe.Pointer(p)).FlockMask&(libc.Uint32FromInt32(1)<<i) != uint32(0) && (**(**TDb)(__ccgo_up(aDb + uintptr(i)*32))).FpBt != uintptr(0) {
|
|
_sqlite3BtreeEnter(tls, (**(**TDb)(__ccgo_up(aDb + uintptr(i)*32))).FpBt)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The cursor "p" has a pending seek operation that has not yet been
|
|
// ** carried out. Seek the cursor now. If an error occurs, return
|
|
// ** the appropriate error code.
|
|
// */
|
|
func _sqlite3VdbeFinishMoveto(tls *libc.TLS, p uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var rc int32
|
|
var _ /* res at bp+0 */ int32
|
|
_ = rc
|
|
rc = _sqlite3BtreeTableMoveto(tls, *(*uintptr)(unsafe.Pointer(p + 48)), (*TVdbeCursor)(unsafe.Pointer(p)).FmovetoTarget, 0, bp)
|
|
if rc != 0 {
|
|
return rc
|
|
}
|
|
if **(**int32)(__ccgo_up(bp)) != 0 {
|
|
return _sqlite3CorruptError(tls, int32(91686))
|
|
}
|
|
(*TVdbeCursor)(unsafe.Pointer(p)).FdeferredMoveto = uint8(0)
|
|
(*TVdbeCursor)(unsafe.Pointer(p)).FcacheStatus = uint32(CACHE_STALE)
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Copy the values stored in the VdbeFrame structure to its Vdbe. This
|
|
// ** is used, for example, when a trigger sub-program is halted to restore
|
|
// ** control to the main program.
|
|
// */
|
|
func _sqlite3VdbeFrameRestore(tls *libc.TLS, pFrame uintptr) (r int32) {
|
|
var v uintptr
|
|
_ = v
|
|
v = (*TVdbeFrame)(unsafe.Pointer(pFrame)).Fv
|
|
_closeCursorsInFrame(tls, v)
|
|
(*TVdbe)(unsafe.Pointer(v)).FaOp = (*TVdbeFrame)(unsafe.Pointer(pFrame)).FaOp
|
|
(*TVdbe)(unsafe.Pointer(v)).FnOp = (*TVdbeFrame)(unsafe.Pointer(pFrame)).FnOp
|
|
(*TVdbe)(unsafe.Pointer(v)).FaMem = (*TVdbeFrame)(unsafe.Pointer(pFrame)).FaMem
|
|
(*TVdbe)(unsafe.Pointer(v)).FnMem = (*TVdbeFrame)(unsafe.Pointer(pFrame)).FnMem
|
|
(*TVdbe)(unsafe.Pointer(v)).FapCsr = (*TVdbeFrame)(unsafe.Pointer(pFrame)).FapCsr
|
|
(*TVdbe)(unsafe.Pointer(v)).FnCursor = (*TVdbeFrame)(unsafe.Pointer(pFrame)).FnCursor
|
|
(*Tsqlite3)(unsafe.Pointer((*TVdbe)(unsafe.Pointer(v)).Fdb)).FlastRowid = (*TVdbeFrame)(unsafe.Pointer(pFrame)).FlastRowid
|
|
(*TVdbe)(unsafe.Pointer(v)).FnChange = (*TVdbeFrame)(unsafe.Pointer(pFrame)).FnChange
|
|
(*Tsqlite3)(unsafe.Pointer((*TVdbe)(unsafe.Pointer(v)).Fdb)).FnChange = (*TVdbeFrame)(unsafe.Pointer(pFrame)).FnDbChange
|
|
_sqlite3VdbeDeleteAuxData(tls, (*TVdbe)(unsafe.Pointer(v)).Fdb, v+296, -int32(1), 0)
|
|
(*TVdbe)(unsafe.Pointer(v)).FpAuxData = (*TVdbeFrame)(unsafe.Pointer(pFrame)).FpAuxData
|
|
(*TVdbeFrame)(unsafe.Pointer(pFrame)).FpAuxData = uintptr(0)
|
|
return (*TVdbeFrame)(unsafe.Pointer(pFrame)).Fpc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the opcode for a given address. The address must be non-negative.
|
|
// ** See sqlite3VdbeGetLastOp() to get the most recently added opcode.
|
|
// **
|
|
// ** If a memory allocation error has occurred prior to the calling of this
|
|
// ** routine, then a pointer to a dummy VdbeOp will be returned. That opcode
|
|
// ** is readable but not writable, though it is cast to a writable value.
|
|
// ** The return of a dummy opcode allows the call to continue functioning
|
|
// ** after an OOM fault without having to check to see if the return from
|
|
// ** this routine is a valid pointer. But because the dummy.opcode is 0,
|
|
// ** dummy will never be written to. This is verified by code inspection and
|
|
// ** by running with Valgrind.
|
|
// */
|
|
func _sqlite3VdbeGetOp(tls *libc.TLS, p uintptr, addr int32) (r uintptr) {
|
|
if (*Tsqlite3)(unsafe.Pointer((*TVdbe)(unsafe.Pointer(p)).Fdb)).FmallocFailed != 0 {
|
|
return uintptr(unsafe.Pointer(&_dummy))
|
|
} else {
|
|
return (*TVdbe)(unsafe.Pointer(p)).FaOp + uintptr(addr)*24
|
|
}
|
|
return r
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Something has moved cursor "p" out of place. Maybe the row it was
|
|
// ** pointed to was deleted out from under it. Or maybe the btree was
|
|
// ** rebalanced. Whatever the cause, try to restore "p" to the place it
|
|
// ** is supposed to be pointing. If the row was deleted out from under the
|
|
// ** cursor, set the cursor to point to a NULL row.
|
|
// */
|
|
func _sqlite3VdbeHandleMovedCursor(tls *libc.TLS, p uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var rc int32
|
|
var _ /* isDifferentRow at bp+0 */ int32
|
|
_ = rc
|
|
rc = _sqlite3BtreeCursorRestore(tls, *(*uintptr)(unsafe.Pointer(p + 48)), bp)
|
|
(*TVdbeCursor)(unsafe.Pointer(p)).FcacheStatus = uint32(CACHE_STALE)
|
|
if **(**int32)(__ccgo_up(bp)) != 0 {
|
|
(*TVdbeCursor)(unsafe.Pointer(p)).FnullRow = uint8(1)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Create a new symbolic label for an instruction that has yet to be
|
|
// ** coded. The symbolic label is really just a negative number. The
|
|
// ** label can be used as the P2 value of an operation. Later, when
|
|
// ** the label is resolved to a specific address, the VDBE will scan
|
|
// ** through its operation list and change all values of P2 which match
|
|
// ** the label into the resolved address.
|
|
// **
|
|
// ** The VDBE knows that a P2 value is a label because labels are
|
|
// ** always negative and P2 values are suppose to be non-negative.
|
|
// ** Hence, a negative P2 value is a label that has yet to be resolved.
|
|
// ** (Later:) This is only true for opcodes that have the OPFLG_JUMP
|
|
// ** property.
|
|
// **
|
|
// ** Variable usage notes:
|
|
// **
|
|
// ** Parse.aLabel[x] Stores the address that the x-th label resolves
|
|
// ** into. For testing (SQLITE_DEBUG), unresolved
|
|
// ** labels stores -1, but that is not required.
|
|
// ** Parse.nLabelAlloc Number of slots allocated to Parse.aLabel[]
|
|
// ** Parse.nLabel The *negative* of the number of labels that have
|
|
// ** been issued. The negative is stored because
|
|
// ** that gives a performance improvement over storing
|
|
// ** the equivalent positive value.
|
|
// */
|
|
func _sqlite3VdbeMakeLabel(tls *libc.TLS, pParse uintptr) (r int32) {
|
|
var v1 int32
|
|
var v2 uintptr
|
|
_, _ = v1, v2
|
|
v2 = pParse + 76
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) - 1
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
return v1
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Change the pMem->zMalloc allocation to be at least szNew bytes.
|
|
// ** If pMem->zMalloc already meets or exceeds the requested size, this
|
|
// ** routine is a no-op.
|
|
// **
|
|
// ** Any prior string or blob content in the pMem object may be discarded.
|
|
// ** The pMem->xDel destructor is called, if it exists. Though MEM_Str
|
|
// ** and MEM_Blob values may be discarded, MEM_Int, MEM_Real, MEM_IntReal,
|
|
// ** and MEM_Null values are preserved.
|
|
// **
|
|
// ** Return SQLITE_OK on success or an error code (probably SQLITE_NOMEM)
|
|
// ** if unable to complete the resizing.
|
|
// */
|
|
func _sqlite3VdbeMemClearAndResize(tls *libc.TLS, pMem uintptr, szNew int32) (r int32) {
|
|
var v1 uintptr
|
|
_ = v1
|
|
if (*TMem)(unsafe.Pointer(pMem)).FszMalloc < szNew {
|
|
return _sqlite3VdbeMemGrow(tls, pMem, szNew, 0)
|
|
}
|
|
(*TMem)(unsafe.Pointer(pMem)).Fz = (*TMem)(unsafe.Pointer(pMem)).FzMalloc
|
|
v1 = pMem + 20
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) & (libc.Int32FromInt32(MEM_Null) | libc.Int32FromInt32(MEM_Int) | libc.Int32FromInt32(MEM_Real) | libc.Int32FromInt32(MEM_IntReal)))
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This routine sets the value to be returned by subsequent calls to
|
|
// ** sqlite3_changes() on the database handle 'db'.
|
|
// */
|
|
func _sqlite3VdbeSetChanges(tls *libc.TLS, db uintptr, nChange Ti64) {
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FnChange = nChange
|
|
**(**Ti64)(__ccgo_up(db + 128)) += nChange
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Configure SQL variable iVar so that binding a new value to it signals
|
|
// ** to sqlite3_reoptimize() that re-preparing the statement may result
|
|
// ** in a better query plan.
|
|
// */
|
|
func _sqlite3VdbeSetVarmask(tls *libc.TLS, v uintptr, iVar int32) {
|
|
if iVar >= int32(32) {
|
|
**(**Tu32)(__ccgo_up(v + 284)) |= uint32(0x80000000)
|
|
} else {
|
|
**(**Tu32)(__ccgo_up(v + 284)) |= libc.Uint32FromInt32(1) << (iVar - libc.Int32FromInt32(1))
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Advance to the next element in the sorter. Return value:
|
|
// **
|
|
// ** SQLITE_OK success
|
|
// ** SQLITE_DONE end of data
|
|
// ** otherwise some kind of error.
|
|
// */
|
|
func _sqlite3VdbeSorterNext(tls *libc.TLS, db uintptr, pCsr uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var pFree, pSorter uintptr
|
|
var rc, v1 int32
|
|
var _ /* res at bp+0 */ int32
|
|
_, _, _, _ = pFree, pSorter, rc, v1 /* Return code */
|
|
pSorter = *(*uintptr)(unsafe.Pointer(pCsr + 48))
|
|
if (*TVdbeSorter)(unsafe.Pointer(pSorter)).FbUsePMA != 0 {
|
|
if (*TVdbeSorter)(unsafe.Pointer(pSorter)).FbUseThreads != 0 {
|
|
rc = _vdbePmaReaderNext(tls, (*TVdbeSorter)(unsafe.Pointer(pSorter)).FpReader)
|
|
if rc == SQLITE_OK && (*TPmaReader)(unsafe.Pointer((*TVdbeSorter)(unsafe.Pointer(pSorter)).FpReader)).FpFd == uintptr(0) {
|
|
rc = int32(SQLITE_DONE)
|
|
}
|
|
} else {
|
|
/*if( !pSorter->bUseThreads )*/
|
|
**(**int32)(__ccgo_up(bp)) = 0
|
|
rc = _vdbeMergeEngineStep(tls, (*TVdbeSorter)(unsafe.Pointer(pSorter)).FpMerger, bp)
|
|
if rc == SQLITE_OK && **(**int32)(__ccgo_up(bp)) != 0 {
|
|
rc = int32(SQLITE_DONE)
|
|
}
|
|
}
|
|
} else {
|
|
pFree = (*TVdbeSorter)(unsafe.Pointer(pSorter)).Flist.FpList
|
|
(*TVdbeSorter)(unsafe.Pointer(pSorter)).Flist.FpList = *(*uintptr)(unsafe.Pointer(pFree + 8))
|
|
*(*uintptr)(unsafe.Pointer(pFree + 8)) = uintptr(0)
|
|
if (*TVdbeSorter)(unsafe.Pointer(pSorter)).Flist.FaMemory == uintptr(0) {
|
|
_vdbeSorterRecordFree(tls, db, pFree)
|
|
}
|
|
if (*TVdbeSorter)(unsafe.Pointer(pSorter)).Flist.FpList != 0 {
|
|
v1 = SQLITE_OK
|
|
} else {
|
|
v1 = int32(SQLITE_DONE)
|
|
}
|
|
rc = v1
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Declare to the Vdbe that the BTree object at db->aDb[i] is used.
|
|
// **
|
|
// ** The prepared statements need to know in advance the complete set of
|
|
// ** attached databases that will be use. A mask of these databases
|
|
// ** is maintained in p->btreeMask. The p->lockMask value is the subset of
|
|
// ** p->btreeMask of databases that will require a lock.
|
|
// */
|
|
func _sqlite3VdbeUsesBtree(tls *libc.TLS, p uintptr, i int32) {
|
|
**(**TyDbMask)(__ccgo_up(p + 204)) |= libc.Uint32FromInt32(1) << i
|
|
if i != int32(1) && _sqlite3BtreeSharable(tls, (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer((*TVdbe)(unsafe.Pointer(p)).Fdb)).FaDb + uintptr(i)*32))).FpBt) != 0 {
|
|
**(**TyDbMask)(__ccgo_up(p + 208)) |= libc.Uint32FromInt32(1) << i
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If the virtual table pVtab supports the transaction interface
|
|
// ** (xBegin/xRollback/xCommit and optionally xSync) and a transaction is
|
|
// ** not currently open, invoke the xBegin method now.
|
|
// **
|
|
// ** If the xBegin call is successful, place the sqlite3_vtab pointer
|
|
// ** in the sqlite3.aVTrans array.
|
|
// */
|
|
func _sqlite3VtabBegin(tls *libc.TLS, db uintptr, pVTab uintptr) (r int32) {
|
|
var i, iSvpt, rc int32
|
|
var pModule uintptr
|
|
_, _, _, _ = i, iSvpt, pModule, rc
|
|
rc = SQLITE_OK
|
|
/* Special case: If db->aVTrans is NULL and db->nVTrans is greater
|
|
** than zero, then this function is being called from within a
|
|
** virtual module xSync() callback. It is illegal to write to
|
|
** virtual module tables in this case, so return SQLITE_LOCKED.
|
|
*/
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FnVTrans > 0 && (*Tsqlite3)(unsafe.Pointer(db)).FaVTrans == uintptr(0) {
|
|
return int32(SQLITE_LOCKED)
|
|
}
|
|
if !(pVTab != 0) {
|
|
return SQLITE_OK
|
|
}
|
|
pModule = (*Tsqlite3_vtab)(unsafe.Pointer((*TVTable)(unsafe.Pointer(pVTab)).FpVtab)).FpModule
|
|
if (*Tsqlite3_module)(unsafe.Pointer(pModule)).FxBegin != 0 {
|
|
/* If pVtab is already in the aVTrans array, return early */
|
|
i = 0
|
|
for {
|
|
if !(i < (*Tsqlite3)(unsafe.Pointer(db)).FnVTrans) {
|
|
break
|
|
}
|
|
if **(**uintptr)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaVTrans + uintptr(i)*8)) == pVTab {
|
|
return SQLITE_OK
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
/* Invoke the xBegin method. If successful, add the vtab to the
|
|
** sqlite3.aVTrans[] array. */
|
|
rc = _growVTrans(tls, db)
|
|
if rc == SQLITE_OK {
|
|
rc = (*(*func(*libc.TLS, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{(*Tsqlite3_module)(unsafe.Pointer(pModule)).FxBegin})))(tls, (*TVTable)(unsafe.Pointer(pVTab)).FpVtab)
|
|
if rc == SQLITE_OK {
|
|
iSvpt = (*Tsqlite3)(unsafe.Pointer(db)).FnStatement + (*Tsqlite3)(unsafe.Pointer(db)).FnSavepoint
|
|
_addToVTrans(tls, db, pVTab)
|
|
if iSvpt != 0 && (*Tsqlite3_module)(unsafe.Pointer(pModule)).FxSavepoint != 0 {
|
|
(*TVTable)(unsafe.Pointer(pVTab)).FiSavepoint = iSvpt
|
|
rc = (*(*func(*libc.TLS, uintptr, int32) int32)(unsafe.Pointer(&struct{ uintptr }{(*Tsqlite3_module)(unsafe.Pointer(pModule)).FxSavepoint})))(tls, (*TVTable)(unsafe.Pointer(pVTab)).FpVtab, iSvpt-int32(1))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Clear any and all virtual-table information from the Table record.
|
|
// ** This routine is called, for example, just before deleting the Table
|
|
// ** record.
|
|
// **
|
|
// ** Since it is a virtual-table, the Table structure contains a pointer
|
|
// ** to the head of a linked list of VTable structures. Each VTable
|
|
// ** structure is associated with a single sqlite3* user of the schema.
|
|
// ** The reference count of the VTable structure associated with database
|
|
// ** connection db is decremented immediately (which may lead to the
|
|
// ** structure being xDisconnected and free). Any other VTable structures
|
|
// ** in the list are moved to the sqlite3.pDisconnect list of the associated
|
|
// ** database connection.
|
|
// */
|
|
func _sqlite3VtabClear(tls *libc.TLS, db uintptr, p uintptr) {
|
|
var i int32
|
|
_ = i
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FpnBytesFreed == uintptr(0) {
|
|
_vtabDisconnectAll(tls, uintptr(0), p)
|
|
}
|
|
if (*(*struct {
|
|
FnArg int32
|
|
FazArg uintptr
|
|
Fp uintptr
|
|
})(unsafe.Pointer(p + 64))).FazArg != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*(*struct {
|
|
FnArg int32
|
|
FazArg uintptr
|
|
Fp uintptr
|
|
})(unsafe.Pointer(p + 64))).FnArg) {
|
|
break
|
|
}
|
|
if i != int32(1) {
|
|
_sqlite3DbFree(tls, db, **(**uintptr)(__ccgo_up((*(*struct {
|
|
FnArg int32
|
|
FazArg uintptr
|
|
Fp uintptr
|
|
})(unsafe.Pointer(p + 64))).FazArg + uintptr(i)*8)))
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_sqlite3DbFree(tls, db, (*(*struct {
|
|
FnArg int32
|
|
FazArg uintptr
|
|
Fp uintptr
|
|
})(unsafe.Pointer(p + 64))).FazArg)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Table *p is a virtual table. This function removes the VTable object
|
|
// ** for table *p associated with database connection db from the linked
|
|
// ** list in p->pVTab. It also decrements the VTable ref count. This is
|
|
// ** used when closing database connection db to free all of its VTable
|
|
// ** objects without disturbing the rest of the Schema object (which may
|
|
// ** be being used by other shared-cache connections).
|
|
// */
|
|
func _sqlite3VtabDisconnect(tls *libc.TLS, db uintptr, p uintptr) {
|
|
var pVTab, ppVTab uintptr
|
|
_, _ = pVTab, ppVTab
|
|
ppVTab = p + 64 + 16
|
|
for {
|
|
if !(**(**uintptr)(__ccgo_up(ppVTab)) != 0) {
|
|
break
|
|
}
|
|
if (*TVTable)(unsafe.Pointer(**(**uintptr)(__ccgo_up(ppVTab)))).Fdb == db {
|
|
pVTab = **(**uintptr)(__ccgo_up(ppVTab))
|
|
**(**uintptr)(__ccgo_up(ppVTab)) = (*TVTable)(unsafe.Pointer(pVTab)).FpNext
|
|
_sqlite3VtabUnlock(tls, pVTab)
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
ppVTab = **(**uintptr)(__ccgo_up(ppVTab)) + 40
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Erase the eponymous virtual table instance associated with
|
|
// ** virtual table module pMod, if it exists.
|
|
// */
|
|
func _sqlite3VtabEponymousTableClear(tls *libc.TLS, db uintptr, pMod uintptr) {
|
|
var pTab uintptr
|
|
_ = pTab
|
|
pTab = (*TModule)(unsafe.Pointer(pMod)).FpEpoTab
|
|
if pTab != uintptr(0) {
|
|
/* Mark the table as Ephemeral prior to deleting it, so that the
|
|
** sqlite3DeleteTable() routine will know that it is not stored in
|
|
** the schema. */
|
|
**(**Tu32)(__ccgo_up(pTab + 48)) |= uint32(TF_Ephemeral)
|
|
_sqlite3DeleteTable(tls, db, pTab)
|
|
(*TModule)(unsafe.Pointer(pMod)).FpEpoTab = uintptr(0)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Invoke either the xSavepoint, xRollbackTo or xRelease method of all
|
|
// ** virtual tables that currently have an open transaction. Pass iSavepoint
|
|
// ** as the second argument to the virtual table method invoked.
|
|
// **
|
|
// ** If op is SAVEPOINT_BEGIN, the xSavepoint method is invoked. If it is
|
|
// ** SAVEPOINT_ROLLBACK, the xRollbackTo method. Otherwise, if op is
|
|
// ** SAVEPOINT_RELEASE, then the xRelease method of each virtual table with
|
|
// ** an open transaction is invoked.
|
|
// **
|
|
// ** If any virtual table method returns an error code other than SQLITE_OK,
|
|
// ** processing is abandoned and the error returned to the caller of this
|
|
// ** function immediately. If all calls to virtual table methods are successful,
|
|
// ** SQLITE_OK is returned.
|
|
// */
|
|
func _sqlite3VtabSavepoint(tls *libc.TLS, db uintptr, op int32, iSavepoint int32) (r int32) {
|
|
var i, rc int32
|
|
var pMod, pVTab, xMethod uintptr
|
|
var savedFlags Tu64
|
|
_, _, _, _, _, _ = i, pMod, pVTab, rc, savedFlags, xMethod
|
|
rc = SQLITE_OK
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FaVTrans != 0 {
|
|
i = 0
|
|
for {
|
|
if !(rc == SQLITE_OK && i < (*Tsqlite3)(unsafe.Pointer(db)).FnVTrans) {
|
|
break
|
|
}
|
|
pVTab = **(**uintptr)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaVTrans + uintptr(i)*8))
|
|
pMod = (*TModule)(unsafe.Pointer((*TVTable)(unsafe.Pointer(pVTab)).FpMod)).FpModule
|
|
if (*TVTable)(unsafe.Pointer(pVTab)).FpVtab != 0 && (*Tsqlite3_module)(unsafe.Pointer(pMod)).FiVersion >= int32(2) {
|
|
_sqlite3VtabLock(tls, pVTab)
|
|
switch op {
|
|
case SAVEPOINT_BEGIN:
|
|
xMethod = (*Tsqlite3_module)(unsafe.Pointer(pMod)).FxSavepoint
|
|
(*TVTable)(unsafe.Pointer(pVTab)).FiSavepoint = iSavepoint + int32(1)
|
|
case int32(SAVEPOINT_ROLLBACK):
|
|
xMethod = (*Tsqlite3_module)(unsafe.Pointer(pMod)).FxRollbackTo
|
|
default:
|
|
xMethod = (*Tsqlite3_module)(unsafe.Pointer(pMod)).FxRelease
|
|
break
|
|
}
|
|
if xMethod != 0 && (*TVTable)(unsafe.Pointer(pVTab)).FiSavepoint > iSavepoint {
|
|
savedFlags = (*Tsqlite3)(unsafe.Pointer(db)).Fflags & libc.Uint64FromInt32(SQLITE_Defensive)
|
|
**(**Tu64)(__ccgo_up(db + 48)) &= ^libc.Uint64FromInt32(SQLITE_Defensive)
|
|
rc = (*(*func(*libc.TLS, uintptr, int32) int32)(unsafe.Pointer(&struct{ uintptr }{xMethod})))(tls, (*TVTable)(unsafe.Pointer(pVTab)).FpVtab, iSavepoint)
|
|
**(**Tu64)(__ccgo_up(db + 48)) |= savedFlags
|
|
}
|
|
_sqlite3VtabUnlock(tls, pVTab)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Invoke the xSync method of all virtual tables in the sqlite3.aVTrans
|
|
// ** array. Return the error code for the first error that occurs, or
|
|
// ** SQLITE_OK if all xSync operations are successful.
|
|
// **
|
|
// ** If an error message is available, leave it in p->zErrMsg.
|
|
// */
|
|
func _sqlite3VtabSync(tls *libc.TLS, db uintptr, p uintptr) (r int32) {
|
|
var aVTrans, pVtab, x, v2 uintptr
|
|
var i, rc int32
|
|
var v3 bool
|
|
_, _, _, _, _, _, _ = aVTrans, i, pVtab, rc, x, v2, v3
|
|
rc = SQLITE_OK
|
|
aVTrans = (*Tsqlite3)(unsafe.Pointer(db)).FaVTrans
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FaVTrans = uintptr(0)
|
|
i = 0
|
|
for {
|
|
if !(rc == SQLITE_OK && i < (*Tsqlite3)(unsafe.Pointer(db)).FnVTrans) {
|
|
break
|
|
}
|
|
pVtab = (*TVTable)(unsafe.Pointer(**(**uintptr)(__ccgo_up(aVTrans + uintptr(i)*8)))).FpVtab
|
|
if v3 = pVtab != 0; v3 {
|
|
v2 = (*Tsqlite3_module)(unsafe.Pointer((*Tsqlite3_vtab)(unsafe.Pointer(pVtab)).FpModule)).FxSync
|
|
x = v2
|
|
}
|
|
if v3 && v2 != uintptr(0) {
|
|
rc = (*(*func(*libc.TLS, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{x})))(tls, pVtab)
|
|
_sqlite3VtabImportErrmsg(tls, p, pVtab)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FaVTrans = aVTrans
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function starts a write transaction on the WAL.
|
|
// **
|
|
// ** A read transaction must have already been started by a prior call
|
|
// ** to sqlite3WalBeginReadTransaction().
|
|
// **
|
|
// ** If another thread or process has written into the database since
|
|
// ** the read transaction was started, then it is not possible for this
|
|
// ** thread to write as doing so would cause a fork. So this routine
|
|
// ** returns SQLITE_BUSY in that case and no write transaction is started.
|
|
// **
|
|
// ** There can only be a single writer active at a time.
|
|
// */
|
|
func _sqlite3WalBeginWriteTransaction(tls *libc.TLS, pWal uintptr) (r int32) {
|
|
var rc int32
|
|
_ = rc
|
|
/* Cannot start a write transaction without first holding a read
|
|
** transaction. */
|
|
if (*TWal)(unsafe.Pointer(pWal)).FreadOnly != 0 {
|
|
return int32(SQLITE_READONLY)
|
|
}
|
|
/* Only one writer allowed at a time. Get the write lock. Return
|
|
** SQLITE_BUSY if unable.
|
|
*/
|
|
rc = _walLockExclusive(tls, pWal, WAL_WRITE_LOCK, int32(1))
|
|
if rc != 0 {
|
|
return rc
|
|
}
|
|
(*TWal)(unsafe.Pointer(pWal)).FwriteLock = uint8(1)
|
|
/* If another connection has written to the database file since the
|
|
** time the read transaction on this connection was started, then
|
|
** the write is disallowed.
|
|
*/
|
|
if libc.Xmemcmp(tls, pWal+72, _walIndexHdr(tls, pWal), uint64(48)) != 0 {
|
|
rc = libc.Int32FromInt32(SQLITE_BUSY) | libc.Int32FromInt32(2)<<libc.Int32FromInt32(8)
|
|
}
|
|
if rc != SQLITE_OK {
|
|
_walUnlockExclusive(tls, pWal, WAL_WRITE_LOCK, int32(1))
|
|
(*TWal)(unsafe.Pointer(pWal)).FwriteLock = uint8(0)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint().
|
|
// ** Invoke sqlite3_wal_checkpoint if the number of frames in the log file
|
|
// ** is greater than sqlite3.pWalArg cast to an integer (the value configured by
|
|
// ** wal_autocheckpoint()).
|
|
// */
|
|
func _sqlite3WalDefaultHook(tls *libc.TLS, pClientData uintptr, db uintptr, zDb uintptr, nFrame int32) (r int32) {
|
|
if nFrame >= int32(int64(pClientData)) {
|
|
_sqlite3BeginBenignMalloc(tls)
|
|
Xsqlite3_wal_checkpoint(tls, db, zDb)
|
|
_sqlite3EndBenignMalloc(tls)
|
|
}
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32
|
|
// ** values. This function populates the array with values required to
|
|
// ** "rollback" the write position of the WAL handle back to the current
|
|
// ** point in the event of a savepoint rollback (via WalSavepointUndo()).
|
|
// */
|
|
func _sqlite3WalSavepoint(tls *libc.TLS, pWal uintptr, aWalData uintptr) {
|
|
**(**Tu32)(__ccgo_up(aWalData)) = (*TWal)(unsafe.Pointer(pWal)).Fhdr.FmxFrame
|
|
**(**Tu32)(__ccgo_up(aWalData + 1*4)) = **(**Tu32)(__ccgo_up(pWal + 72 + 24))
|
|
**(**Tu32)(__ccgo_up(aWalData + 2*4)) = **(**Tu32)(__ccgo_up(pWal + 72 + 24 + 1*4))
|
|
**(**Tu32)(__ccgo_up(aWalData + 3*4)) = (*TWal)(unsafe.Pointer(pWal)).FnCkpt
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Move the write position of the WAL back to the point identified by
|
|
// ** the values in the aWalData[] array. aWalData must point to an array
|
|
// ** of WAL_SAVEPOINT_NDATA u32 values that has been previously populated
|
|
// ** by a call to WalSavepoint().
|
|
// */
|
|
func _sqlite3WalSavepointUndo(tls *libc.TLS, pWal uintptr, aWalData uintptr) (r int32) {
|
|
var rc int32
|
|
_ = rc
|
|
rc = SQLITE_OK
|
|
if **(**Tu32)(__ccgo_up(aWalData + 3*4)) != (*TWal)(unsafe.Pointer(pWal)).FnCkpt {
|
|
/* This savepoint was opened immediately after the write-transaction
|
|
** was started. Right after that, the writer decided to wrap around
|
|
** to the start of the log. Update the savepoint values to match.
|
|
*/
|
|
**(**Tu32)(__ccgo_up(aWalData)) = uint32(0)
|
|
**(**Tu32)(__ccgo_up(aWalData + 3*4)) = (*TWal)(unsafe.Pointer(pWal)).FnCkpt
|
|
}
|
|
if **(**Tu32)(__ccgo_up(aWalData)) < (*TWal)(unsafe.Pointer(pWal)).Fhdr.FmxFrame {
|
|
(*TWal)(unsafe.Pointer(pWal)).Fhdr.FmxFrame = **(**Tu32)(__ccgo_up(aWalData))
|
|
**(**Tu32)(__ccgo_up(pWal + 72 + 24)) = **(**Tu32)(__ccgo_up(aWalData + 1*4))
|
|
**(**Tu32)(__ccgo_up(pWal + 72 + 24 + 1*4)) = **(**Tu32)(__ccgo_up(aWalData + 2*4))
|
|
_walCleanupHash(tls, pWal)
|
|
if (*TWal)(unsafe.Pointer(pWal)).FiReCksum > (*TWal)(unsafe.Pointer(pWal)).Fhdr.FmxFrame {
|
|
(*TWal)(unsafe.Pointer(pWal)).FiReCksum = uint32(0)
|
|
}
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The caller currently has a read transaction open on the database.
|
|
// ** This function takes a SHARED lock on the CHECKPOINTER slot and then
|
|
// ** checks if the snapshot passed as the second argument is still
|
|
// ** available. If so, SQLITE_OK is returned.
|
|
// **
|
|
// ** If the snapshot is not available, SQLITE_ERROR is returned. Or, if
|
|
// ** the CHECKPOINTER lock cannot be obtained, SQLITE_BUSY. If any error
|
|
// ** occurs (any value other than SQLITE_OK is returned), the CHECKPOINTER
|
|
// ** lock is released before returning.
|
|
// */
|
|
func _sqlite3WalSnapshotCheck(tls *libc.TLS, pWal uintptr, pSnapshot uintptr) (r int32) {
|
|
var pNew uintptr
|
|
var rc int32
|
|
_, _ = pNew, rc
|
|
rc = _walLockShared(tls, pWal, int32(WAL_CKPT_LOCK))
|
|
if rc == SQLITE_OK {
|
|
pNew = pSnapshot
|
|
if libc.Xmemcmp(tls, pNew+32, pWal+72+32, uint64(8)) != 0 || (*TWalIndexHdr)(unsafe.Pointer(pNew)).FmxFrame < (*TWalCkptInfo)(unsafe.Pointer(_walCkptInfo(tls, pWal))).FnBackfillAttempted {
|
|
rc = libc.Int32FromInt32(SQLITE_ERROR) | libc.Int32FromInt32(3)<<libc.Int32FromInt32(8)
|
|
_walUnlockShared(tls, pWal, int32(WAL_CKPT_LOCK))
|
|
}
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Call sqlite3WalkExpr() for every expression in list p or until
|
|
// ** an abort request is seen.
|
|
// */
|
|
func _sqlite3WalkExprList(tls *libc.TLS, pWalker uintptr, p uintptr) (r int32) {
|
|
var i int32
|
|
var pItem uintptr
|
|
_, _ = i, pItem
|
|
if p != 0 {
|
|
i = (*TExprList)(unsafe.Pointer(p)).FnExpr
|
|
pItem = p + 8
|
|
for {
|
|
if !(i > 0) {
|
|
break
|
|
}
|
|
if _sqlite3WalkExpr(tls, pWalker, (*TExprList_item)(unsafe.Pointer(pItem)).FpExpr) != 0 {
|
|
return int32(WRC_Abort)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i - 1
|
|
pItem += 32
|
|
}
|
|
}
|
|
return WRC_Continue
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Walk the parse trees associated with all subqueries in the
|
|
// ** FROM clause of SELECT statement p. Do not invoke the select
|
|
// ** callback on p, but do invoke it on each FROM clause subquery
|
|
// ** and on any subqueries further down in the tree. Return
|
|
// ** WRC_Abort or WRC_Continue;
|
|
// */
|
|
func _sqlite3WalkSelectFrom(tls *libc.TLS, pWalker uintptr, p uintptr) (r int32) {
|
|
var i int32
|
|
var pItem, pSrc uintptr
|
|
_, _, _ = i, pItem, pSrc
|
|
pSrc = (*TSelect)(unsafe.Pointer(p)).FpSrc
|
|
if pSrc != 0 {
|
|
i = (*TSrcList)(unsafe.Pointer(pSrc)).FnSrc
|
|
pItem = pSrc + 8
|
|
for {
|
|
if !(i > 0) {
|
|
break
|
|
}
|
|
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x4>>2) != 0 && _sqlite3WalkSelect(tls, pWalker, (*TSubquery)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pItem + 72)))).FpSelect) != 0 {
|
|
return int32(WRC_Abort)
|
|
}
|
|
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x8>>3) != 0 && _sqlite3WalkExprList(tls, pWalker, *(*uintptr)(unsafe.Pointer(pItem + 48))) != 0 {
|
|
return int32(WRC_Abort)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i - 1
|
|
pItem += 80
|
|
}
|
|
}
|
|
return WRC_Continue
|
|
}
|
|
|
|
func _sqlite3WhereExprListUsage(tls *libc.TLS, pMaskSet uintptr, pList uintptr) (r TBitmask) {
|
|
var i int32
|
|
var mask TBitmask
|
|
_, _ = i, mask
|
|
mask = uint64(0)
|
|
if pList != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TExprList)(unsafe.Pointer(pList)).FnExpr) {
|
|
break
|
|
}
|
|
mask = mask | _sqlite3WhereExprUsage(tls, pMaskSet, (*(*TExprList_item)(unsafe.Pointer(pList + 8 + uintptr(i)*32))).FpExpr)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
return mask
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If the WHERE_GROUPBY flag is set in the mask passed to sqlite3WhereBegin(),
|
|
// ** the planner assumes that the specified pOrderBy list is actually a GROUP
|
|
// ** BY clause - and so any order that groups rows as required satisfies the
|
|
// ** request.
|
|
// **
|
|
// ** Normally, in this case it is not possible for the caller to determine
|
|
// ** whether or not the rows are really being delivered in sorted order, or
|
|
// ** just in some other order that provides the required grouping. However,
|
|
// ** if the WHERE_SORTBYGROUP flag is also passed to sqlite3WhereBegin(), then
|
|
// ** this function may be called on the returned WhereInfo object. It returns
|
|
// ** true if the rows really will be sorted in the specified order, or false
|
|
// ** otherwise.
|
|
// **
|
|
// ** For example, assuming:
|
|
// **
|
|
// ** CREATE INDEX i1 ON t1(x, Y);
|
|
// **
|
|
// ** then
|
|
// **
|
|
// ** SELECT * FROM t1 GROUP BY x,y ORDER BY x,y; -- IsSorted()==1
|
|
// ** SELECT * FROM t1 GROUP BY y,x ORDER BY y,x; -- IsSorted()==0
|
|
// */
|
|
func _sqlite3WhereIsSorted(tls *libc.TLS, pWInfo uintptr) (r int32) {
|
|
return int32(uint32(*(*uint8)(unsafe.Pointer(pWInfo + 68)) & 0x8 >> 3))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return TRUE if the WHERE loop uses the OP_DeferredSeek opcode to move
|
|
// ** the data cursor to the row selected by the index cursor.
|
|
// */
|
|
func _sqlite3WhereUsesDeferredSeek(tls *libc.TLS, pWInfo uintptr) (r int32) {
|
|
return int32(uint32(*(*uint8)(unsafe.Pointer(pWInfo + 68)) & 0x1 >> 0))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Allocate and return a duplicate of the Window object indicated by the
|
|
// ** third argument. Set the Window.pOwner field of the new object to
|
|
// ** pOwner.
|
|
// */
|
|
func _sqlite3WindowDup(tls *libc.TLS, db uintptr, pOwner uintptr, p uintptr) (r uintptr) {
|
|
var pNew uintptr
|
|
_ = pNew
|
|
pNew = uintptr(0)
|
|
if p != 0 {
|
|
pNew = _sqlite3DbMallocZero(tls, db, uint64(144))
|
|
if pNew != 0 {
|
|
(*TWindow)(unsafe.Pointer(pNew)).FzName = _sqlite3DbStrDup(tls, db, (*TWindow)(unsafe.Pointer(p)).FzName)
|
|
(*TWindow)(unsafe.Pointer(pNew)).FzBase = _sqlite3DbStrDup(tls, db, (*TWindow)(unsafe.Pointer(p)).FzBase)
|
|
(*TWindow)(unsafe.Pointer(pNew)).FpFilter = _sqlite3ExprDup(tls, db, (*TWindow)(unsafe.Pointer(p)).FpFilter, 0)
|
|
(*TWindow)(unsafe.Pointer(pNew)).FpWFunc = (*TWindow)(unsafe.Pointer(p)).FpWFunc
|
|
(*TWindow)(unsafe.Pointer(pNew)).FpPartition = _sqlite3ExprListDup(tls, db, (*TWindow)(unsafe.Pointer(p)).FpPartition, 0)
|
|
(*TWindow)(unsafe.Pointer(pNew)).FpOrderBy = _sqlite3ExprListDup(tls, db, (*TWindow)(unsafe.Pointer(p)).FpOrderBy, 0)
|
|
(*TWindow)(unsafe.Pointer(pNew)).FeFrmType = (*TWindow)(unsafe.Pointer(p)).FeFrmType
|
|
(*TWindow)(unsafe.Pointer(pNew)).FeEnd = (*TWindow)(unsafe.Pointer(p)).FeEnd
|
|
(*TWindow)(unsafe.Pointer(pNew)).FeStart = (*TWindow)(unsafe.Pointer(p)).FeStart
|
|
(*TWindow)(unsafe.Pointer(pNew)).FeExclude = (*TWindow)(unsafe.Pointer(p)).FeExclude
|
|
(*TWindow)(unsafe.Pointer(pNew)).FregResult = (*TWindow)(unsafe.Pointer(p)).FregResult
|
|
(*TWindow)(unsafe.Pointer(pNew)).FregAccum = (*TWindow)(unsafe.Pointer(p)).FregAccum
|
|
(*TWindow)(unsafe.Pointer(pNew)).FiArgCol = (*TWindow)(unsafe.Pointer(p)).FiArgCol
|
|
(*TWindow)(unsafe.Pointer(pNew)).FiEphCsr = (*TWindow)(unsafe.Pointer(p)).FiEphCsr
|
|
(*TWindow)(unsafe.Pointer(pNew)).FbExprArgs = (*TWindow)(unsafe.Pointer(p)).FbExprArgs
|
|
(*TWindow)(unsafe.Pointer(pNew)).FpStart = _sqlite3ExprDup(tls, db, (*TWindow)(unsafe.Pointer(p)).FpStart, 0)
|
|
(*TWindow)(unsafe.Pointer(pNew)).FpEnd = _sqlite3ExprDup(tls, db, (*TWindow)(unsafe.Pointer(p)).FpEnd, 0)
|
|
(*TWindow)(unsafe.Pointer(pNew)).FpOwner = pOwner
|
|
(*TWindow)(unsafe.Pointer(pNew)).FbImplicitFrame = (*TWindow)(unsafe.Pointer(p)).FbImplicitFrame
|
|
}
|
|
}
|
|
return pNew
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Possibly link window pWin into the list at pSel->pWin (window functions
|
|
// ** to be processed as part of SELECT statement pSel). The window is linked
|
|
// ** in if either (a) there are no other windows already linked to this
|
|
// ** SELECT, or (b) the windows already linked use a compatible window frame.
|
|
// */
|
|
func _sqlite3WindowLink(tls *libc.TLS, pSel uintptr, pWin uintptr) {
|
|
if pSel != 0 {
|
|
if uintptr(0) == (*TSelect)(unsafe.Pointer(pSel)).FpWin || 0 == _sqlite3WindowCompare(tls, uintptr(0), (*TSelect)(unsafe.Pointer(pSel)).FpWin, pWin, 0) {
|
|
(*TWindow)(unsafe.Pointer(pWin)).FpNextWin = (*TSelect)(unsafe.Pointer(pSel)).FpWin
|
|
if (*TSelect)(unsafe.Pointer(pSel)).FpWin != 0 {
|
|
(*TWindow)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pSel)).FpWin)).FppThis = pWin + 64
|
|
}
|
|
(*TSelect)(unsafe.Pointer(pSel)).FpWin = pWin
|
|
(*TWindow)(unsafe.Pointer(pWin)).FppThis = pSel + 104
|
|
} else {
|
|
if _sqlite3ExprListCompare(tls, (*TWindow)(unsafe.Pointer(pWin)).FpPartition, (*TWindow)(unsafe.Pointer((*TSelect)(unsafe.Pointer(pSel)).FpWin)).FpPartition, -int32(1)) != 0 {
|
|
**(**Tu32)(__ccgo_up(pSel + 4)) |= uint32(SF_MultiPart)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return a copy of the linked list of Window objects passed as the
|
|
// ** second argument.
|
|
// */
|
|
func _sqlite3WindowListDup(tls *libc.TLS, db uintptr, p uintptr) (r uintptr) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var pWin, pp uintptr
|
|
var _ /* pRet at bp+0 */ uintptr
|
|
_, _ = pWin, pp
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
pp = bp
|
|
pWin = p
|
|
for {
|
|
if !(pWin != 0) {
|
|
break
|
|
}
|
|
**(**uintptr)(__ccgo_up(pp)) = _sqlite3WindowDup(tls, db, uintptr(0), pWin)
|
|
if **(**uintptr)(__ccgo_up(pp)) == uintptr(0) {
|
|
break
|
|
}
|
|
pp = **(**uintptr)(__ccgo_up(pp)) + 64
|
|
goto _1
|
|
_1:
|
|
;
|
|
pWin = (*TWindow)(unsafe.Pointer(pWin)).FpNextWin
|
|
}
|
|
return **(**uintptr)(__ccgo_up(bp))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free the contents of the With object passed as the second argument.
|
|
// */
|
|
func _sqlite3WithDelete(tls *libc.TLS, db uintptr, pWith uintptr) {
|
|
var i int32
|
|
_ = i
|
|
if pWith != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TWith)(unsafe.Pointer(pWith)).FnCte) {
|
|
break
|
|
}
|
|
_cteClear(tls, db, pWith+16+uintptr(i)*48)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_sqlite3DbFree(tls, db, pWith)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Assign new cursor numbers to each of the items in pSrc. For each
|
|
// ** new cursor number assigned, set an entry in the aCsrMap[] array
|
|
// ** to map the old cursor number to the new:
|
|
// **
|
|
// ** aCsrMap[iOld+1] = iNew;
|
|
// **
|
|
// ** The array is guaranteed by the caller to be large enough for all
|
|
// ** existing cursor numbers in pSrc. aCsrMap[0] is the array size.
|
|
// **
|
|
// ** If pSrc contains any sub-selects, call this routine recursively
|
|
// ** on the FROM clause of each such sub-select, with iExcept set to -1.
|
|
// */
|
|
func _srclistRenumberCursors(tls *libc.TLS, pParse uintptr, aCsrMap uintptr, pSrc uintptr, iExcept int32) {
|
|
var i, v2 int32
|
|
var p, pItem, v3 uintptr
|
|
_, _, _, _, _ = i, p, pItem, v2, v3
|
|
i = 0
|
|
pItem = pSrc + 8
|
|
for {
|
|
if !(i < (*TSrcList)(unsafe.Pointer(pSrc)).FnSrc) {
|
|
break
|
|
}
|
|
if i != iExcept {
|
|
if !(int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x80>>7) != 0) || **(**int32)(__ccgo_up(aCsrMap + uintptr((*TSrcItem)(unsafe.Pointer(pItem)).FiCursor+int32(1))*4)) == 0 {
|
|
v3 = pParse + 56
|
|
v2 = *(*int32)(unsafe.Pointer(v3))
|
|
*(*int32)(unsafe.Pointer(v3)) = *(*int32)(unsafe.Pointer(v3)) + 1
|
|
**(**int32)(__ccgo_up(aCsrMap + uintptr((*TSrcItem)(unsafe.Pointer(pItem)).FiCursor+int32(1))*4)) = v2
|
|
}
|
|
(*TSrcItem)(unsafe.Pointer(pItem)).FiCursor = **(**int32)(__ccgo_up(aCsrMap + uintptr((*TSrcItem)(unsafe.Pointer(pItem)).FiCursor+int32(1))*4))
|
|
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x4>>2) != 0 {
|
|
p = (*TSubquery)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pItem + 72)))).FpSelect
|
|
for {
|
|
if !(p != 0) {
|
|
break
|
|
}
|
|
_srclistRenumberCursors(tls, pParse, aCsrMap, (*TSelect)(unsafe.Pointer(p)).FpSrc, -int32(1))
|
|
goto _4
|
|
_4:
|
|
;
|
|
p = (*TSelect)(unsafe.Pointer(p)).FpPrior
|
|
}
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
pItem += 80
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Reclaim all memory of a StatAccum structure.
|
|
// */
|
|
func _statAccumDestructor(tls *libc.TLS, pOld uintptr) {
|
|
var i int32
|
|
var p uintptr
|
|
_, _ = i, p
|
|
p = pOld
|
|
if (*TStatAccum)(unsafe.Pointer(p)).FmxSample != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TStatAccum)(unsafe.Pointer(p)).FnCol) {
|
|
break
|
|
}
|
|
_sampleClear(tls, (*TStatAccum)(unsafe.Pointer(p)).Fdb, (*TStatAccum)(unsafe.Pointer(p)).FaBest+uintptr(i)*48)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
i = 0
|
|
for {
|
|
if !(i < (*TStatAccum)(unsafe.Pointer(p)).FmxSample) {
|
|
break
|
|
}
|
|
_sampleClear(tls, (*TStatAccum)(unsafe.Pointer(p)).Fdb, (*TStatAccum)(unsafe.Pointer(p)).Fa+uintptr(i)*48)
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_sampleClear(tls, (*TStatAccum)(unsafe.Pointer(p)).Fdb, p+40)
|
|
}
|
|
_sqlite3DbFree(tls, (*TStatAccum)(unsafe.Pointer(p)).Fdb, p)
|
|
}
|
|
|
|
func _statClearCells(tls *libc.TLS, p uintptr) {
|
|
var i int32
|
|
_ = i
|
|
if (*TStatPage)(unsafe.Pointer(p)).FaCell != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TStatPage)(unsafe.Pointer(p)).FnCell) {
|
|
break
|
|
}
|
|
Xsqlite3_free(tls, (**(**TStatCell)(__ccgo_up((*TStatPage)(unsafe.Pointer(p)).FaCell + uintptr(i)*32))).FaOvfl)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
Xsqlite3_free(tls, (*TStatPage)(unsafe.Pointer(p)).FaCell)
|
|
}
|
|
(*TStatPage)(unsafe.Pointer(p)).FnCell = 0
|
|
(*TStatPage)(unsafe.Pointer(p)).FaCell = uintptr(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return true if it is necessary to write page *pPg into the sub-journal.
|
|
// ** A page needs to be written into the sub-journal if there exists one
|
|
// ** or more open savepoints for which:
|
|
// **
|
|
// ** * The page-number is less than or equal to PagerSavepoint.nOrig, and
|
|
// ** * The bit corresponding to the page-number is not set in
|
|
// ** PagerSavepoint.pInSavepoint.
|
|
// */
|
|
func _subjRequiresPage(tls *libc.TLS, pPg uintptr) (r int32) {
|
|
var i int32
|
|
var p, pPager uintptr
|
|
var pgno TPgno
|
|
_, _, _, _ = i, p, pPager, pgno
|
|
pPager = (*TPgHdr)(unsafe.Pointer(pPg)).FpPager
|
|
pgno = (*TPgHdr)(unsafe.Pointer(pPg)).Fpgno
|
|
i = 0
|
|
for {
|
|
if !(i < (*TPager)(unsafe.Pointer(pPager)).FnSavepoint) {
|
|
break
|
|
}
|
|
p = (*TPager)(unsafe.Pointer(pPager)).FaSavepoint + uintptr(i)*56
|
|
if (*TPagerSavepoint)(unsafe.Pointer(p)).FnOrig >= pgno && 0 == _sqlite3BitvecTestNotNull(tls, (*TPagerSavepoint)(unsafe.Pointer(p)).FpInSavepoint, pgno) {
|
|
i = i + int32(1)
|
|
for {
|
|
if !(i < (*TPager)(unsafe.Pointer(pPager)).FnSavepoint) {
|
|
break
|
|
}
|
|
(**(**TPagerSavepoint)(__ccgo_up((*TPager)(unsafe.Pointer(pPager)).FaSavepoint + uintptr(i)*56))).FbTruncateOnRelease = 0
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return int32(1)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func _substExprList(tls *libc.TLS, pSubst uintptr, pList uintptr) {
|
|
var i int32
|
|
_ = i
|
|
if pList == uintptr(0) {
|
|
return
|
|
}
|
|
i = 0
|
|
for {
|
|
if !(i < (*TExprList)(unsafe.Pointer(pList)).FnExpr) {
|
|
break
|
|
}
|
|
(*(*TExprList_item)(unsafe.Pointer(pList + 8 + uintptr(i)*32))).FpExpr = _substExpr(tls, pSubst, (*(*TExprList_item)(unsafe.Pointer(pList + 8 + uintptr(i)*32))).FpExpr)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
|
|
func _substSelect(tls *libc.TLS, pSubst uintptr, p uintptr, doPrior int32) {
|
|
var i int32
|
|
var pItem, pSrc, v1 uintptr
|
|
var v2 bool
|
|
_, _, _, _, _ = i, pItem, pSrc, v1, v2
|
|
if !(p != 0) {
|
|
return
|
|
}
|
|
(*TSubstContext)(unsafe.Pointer(pSubst)).FnSelDepth = (*TSubstContext)(unsafe.Pointer(pSubst)).FnSelDepth + 1
|
|
for {
|
|
_substExprList(tls, pSubst, (*TSelect)(unsafe.Pointer(p)).FpEList)
|
|
_substExprList(tls, pSubst, (*TSelect)(unsafe.Pointer(p)).FpGroupBy)
|
|
_substExprList(tls, pSubst, (*TSelect)(unsafe.Pointer(p)).FpOrderBy)
|
|
(*TSelect)(unsafe.Pointer(p)).FpHaving = _substExpr(tls, pSubst, (*TSelect)(unsafe.Pointer(p)).FpHaving)
|
|
(*TSelect)(unsafe.Pointer(p)).FpWhere = _substExpr(tls, pSubst, (*TSelect)(unsafe.Pointer(p)).FpWhere)
|
|
pSrc = (*TSelect)(unsafe.Pointer(p)).FpSrc
|
|
i = (*TSrcList)(unsafe.Pointer(pSrc)).FnSrc
|
|
pItem = pSrc + 8
|
|
for {
|
|
if !(i > 0) {
|
|
break
|
|
}
|
|
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x4>>2) != 0 {
|
|
_substSelect(tls, pSubst, (*TSubquery)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pItem + 72)))).FpSelect, int32(1))
|
|
}
|
|
if int32(*(*uint32)(unsafe.Pointer(pItem + 24 + 4))&0x8>>3) != 0 {
|
|
_substExprList(tls, pSubst, *(*uintptr)(unsafe.Pointer(pItem + 48)))
|
|
}
|
|
goto _4
|
|
_4:
|
|
;
|
|
i = i - 1
|
|
pItem += 80
|
|
}
|
|
goto _3
|
|
_3:
|
|
;
|
|
if v2 = doPrior != 0; v2 {
|
|
v1 = (*TSelect)(unsafe.Pointer(p)).FpPrior
|
|
p = v1
|
|
}
|
|
if !(v2 && v1 != uintptr(0)) {
|
|
break
|
|
}
|
|
}
|
|
(*TSubstContext)(unsafe.Pointer(pSubst)).FnSelDepth = (*TSubstContext)(unsafe.Pointer(pSubst)).FnSelDepth - 1
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return true if any TEMP triggers exist
|
|
// */
|
|
func _tempTriggersExist(tls *libc.TLS, db uintptr) (r int32) {
|
|
if (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + 1*32))).FpSchema == uintptr(0) {
|
|
return 0
|
|
}
|
|
if (*THash)(unsafe.Pointer((**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + 1*32))).FpSchema+56)).Ffirst == uintptr(0) {
|
|
return 0
|
|
}
|
|
return int32(1)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return term iTerm of the WhereClause passed as the first argument. Terms
|
|
// ** are numbered from 0 upwards, starting with the terms in pWC->a[], then
|
|
// ** those in pWC->pOuter->a[] (if any), and so on.
|
|
// */
|
|
func _termFromWhereClause(tls *libc.TLS, pWC uintptr, iTerm int32) (r uintptr) {
|
|
var p uintptr
|
|
_ = p
|
|
p = pWC
|
|
for {
|
|
if !(p != 0) {
|
|
break
|
|
}
|
|
if iTerm < (*TWhereClause)(unsafe.Pointer(p)).FnTerm {
|
|
return (*TWhereClause)(unsafe.Pointer(p)).Fa + uintptr(iTerm)*56
|
|
}
|
|
iTerm = iTerm - (*TWhereClause)(unsafe.Pointer(p)).FnTerm
|
|
goto _1
|
|
_1:
|
|
;
|
|
p = (*TWhereClause)(unsafe.Pointer(p)).FpOuter
|
|
}
|
|
return uintptr(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Unmap all tokens in the IdList object passed as the second argument.
|
|
// */
|
|
func _unmapColumnIdlistNames(tls *libc.TLS, pParse uintptr, pIdList uintptr) {
|
|
var ii int32
|
|
_ = ii
|
|
ii = 0
|
|
for {
|
|
if !(ii < (*TIdList)(unsafe.Pointer(pIdList)).FnId) {
|
|
break
|
|
}
|
|
_sqlite3RenameTokenRemap(tls, pParse, uintptr(0), (*(*TIdList_item)(unsafe.Pointer(pIdList + 8 + uintptr(ii)*8))).FzName)
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If the Vdbe passed as the first argument opened a statement-transaction,
|
|
// ** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or
|
|
// ** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement
|
|
// ** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the
|
|
// ** statement transaction is committed.
|
|
// **
|
|
// ** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned.
|
|
// ** Otherwise SQLITE_OK.
|
|
// */
|
|
func _vdbeCloseStatement(tls *libc.TLS, p uintptr, eOp int32) (r int32) {
|
|
var db, pBt uintptr
|
|
var i, iSavepoint, rc, rc2 int32
|
|
_, _, _, _, _, _ = db, i, iSavepoint, pBt, rc, rc2
|
|
db = (*TVdbe)(unsafe.Pointer(p)).Fdb
|
|
rc = SQLITE_OK
|
|
iSavepoint = (*TVdbe)(unsafe.Pointer(p)).FiStatement - int32(1)
|
|
i = 0
|
|
for {
|
|
if !(i < (*Tsqlite3)(unsafe.Pointer(db)).FnDb) {
|
|
break
|
|
}
|
|
rc2 = SQLITE_OK
|
|
pBt = (**(**TDb)(__ccgo_up((*Tsqlite3)(unsafe.Pointer(db)).FaDb + uintptr(i)*32))).FpBt
|
|
if pBt != 0 {
|
|
if eOp == int32(SAVEPOINT_ROLLBACK) {
|
|
rc2 = _sqlite3BtreeSavepoint(tls, pBt, int32(SAVEPOINT_ROLLBACK), iSavepoint)
|
|
}
|
|
if rc2 == SQLITE_OK {
|
|
rc2 = _sqlite3BtreeSavepoint(tls, pBt, int32(SAVEPOINT_RELEASE), iSavepoint)
|
|
}
|
|
if rc == SQLITE_OK {
|
|
rc = rc2
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FnStatement = (*Tsqlite3)(unsafe.Pointer(db)).FnStatement - 1
|
|
(*TVdbe)(unsafe.Pointer(p)).FiStatement = 0
|
|
if rc == SQLITE_OK {
|
|
if eOp == int32(SAVEPOINT_ROLLBACK) {
|
|
rc = _sqlite3VtabSavepoint(tls, db, int32(SAVEPOINT_ROLLBACK), iSavepoint)
|
|
}
|
|
if rc == SQLITE_OK {
|
|
rc = _sqlite3VtabSavepoint(tls, db, int32(SAVEPOINT_RELEASE), iSavepoint)
|
|
}
|
|
}
|
|
/* If the statement transaction is being rolled back, also restore the
|
|
** database handles deferred constraint counter to the value it had when
|
|
** the statement transaction was opened. */
|
|
if eOp == int32(SAVEPOINT_ROLLBACK) {
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FnDeferredCons = (*TVdbe)(unsafe.Pointer(p)).FnStmtDefCons
|
|
(*Tsqlite3)(unsafe.Pointer(db)).FnDeferredImmCons = (*TVdbe)(unsafe.Pointer(p)).FnStmtDefImmCons
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Both *pMem1 and *pMem2 contain string values. Compare the two values
|
|
// ** using the collation sequence pColl. As usual, return a negative , zero
|
|
// ** or positive value if *pMem1 is less than, equal to or greater than
|
|
// ** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);".
|
|
// */
|
|
func _vdbeCompareMemStringWithEncodingChange(tls *libc.TLS, pMem1 uintptr, pMem2 uintptr, pColl uintptr, prcErr uintptr) (r int32) {
|
|
bp := tls.Alloc(112)
|
|
defer tls.Free(112)
|
|
var rc int32
|
|
var v1, v2 uintptr
|
|
var _ /* c1 at bp+0 */ TMem
|
|
var _ /* c2 at bp+56 */ TMem
|
|
_, _, _ = rc, v1, v2
|
|
_sqlite3VdbeMemInit(tls, bp, (*TMem)(unsafe.Pointer(pMem1)).Fdb, uint16(MEM_Null))
|
|
_sqlite3VdbeMemInit(tls, bp+56, (*TMem)(unsafe.Pointer(pMem1)).Fdb, uint16(MEM_Null))
|
|
_sqlite3VdbeMemShallowCopy(tls, bp, pMem1, int32(MEM_Ephem))
|
|
_sqlite3VdbeMemShallowCopy(tls, bp+56, pMem2, int32(MEM_Ephem))
|
|
v1 = _sqlite3ValueText(tls, bp, (*TCollSeq)(unsafe.Pointer(pColl)).Fenc)
|
|
v2 = _sqlite3ValueText(tls, bp+56, (*TCollSeq)(unsafe.Pointer(pColl)).Fenc)
|
|
if v1 == uintptr(0) || v2 == uintptr(0) {
|
|
if prcErr != 0 {
|
|
**(**Tu8)(__ccgo_up(prcErr)) = uint8(SQLITE_NOMEM)
|
|
}
|
|
rc = 0
|
|
} else {
|
|
rc = (*(*func(*libc.TLS, uintptr, int32, uintptr, int32, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{(*TCollSeq)(unsafe.Pointer(pColl)).FxCmp})))(tls, (*TCollSeq)(unsafe.Pointer(pColl)).FpUser, (**(**TMem)(__ccgo_up(bp))).Fn, v1, (**(**TMem)(__ccgo_up(bp + 56))).Fn, v2)
|
|
}
|
|
_sqlite3VdbeMemReleaseMalloc(tls, bp)
|
|
_sqlite3VdbeMemReleaseMalloc(tls, bp+56)
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free the space allocated for aOp and any p4 values allocated for the
|
|
// ** opcodes contained within. If aOp is not NULL it is assumed to contain
|
|
// ** nOp entries.
|
|
// */
|
|
func _vdbeFreeOpArray(tls *libc.TLS, db uintptr, aOp uintptr, nOp int32) {
|
|
var pOp uintptr
|
|
_ = pOp
|
|
if aOp != 0 {
|
|
pOp = aOp + uintptr(nOp-int32(1))*24
|
|
for int32(1) != 0 { /* Exit via break */
|
|
if int32((*TOp)(unsafe.Pointer(pOp)).Fp4type) <= -int32(7) {
|
|
_freeP4(tls, db, int32((*TOp)(unsafe.Pointer(pOp)).Fp4type), *(*uintptr)(unsafe.Pointer(pOp + 16)))
|
|
}
|
|
if pOp == aOp {
|
|
break
|
|
}
|
|
pOp -= 24
|
|
}
|
|
_sqlite3DbNNFreeNN(tls, db, aOp)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If the second argument is not NULL, release any allocations associated
|
|
// ** with the memory cells in the p->aMem[] array. Also free the UnpackedRecord
|
|
// ** structure itself, using sqlite3DbFree().
|
|
// **
|
|
// ** This function is used to free UnpackedRecord structures allocated by
|
|
// ** the vdbeUnpackRecord() function found in vdbeapi.c.
|
|
// */
|
|
func _vdbeFreeUnpacked(tls *libc.TLS, db uintptr, nField int32, p uintptr) {
|
|
var i int32
|
|
var pMem uintptr
|
|
_, _ = i, pMem
|
|
if p != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < nField) {
|
|
break
|
|
}
|
|
pMem = (*TUnpackedRecord)(unsafe.Pointer(p)).FaMem + uintptr(i)*56
|
|
if (*TMem)(unsafe.Pointer(pMem)).FzMalloc != 0 {
|
|
_sqlite3VdbeMemReleaseMalloc(tls, pMem)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
_sqlite3DbNNFreeNN(tls, db, p)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free all resources associated with the IncrMerger object indicated by
|
|
// ** the first argument.
|
|
// */
|
|
func _vdbeIncrFree(tls *libc.TLS, pIncr uintptr) {
|
|
if pIncr != 0 {
|
|
if (*TIncrMerger)(unsafe.Pointer(pIncr)).FbUseThread != 0 {
|
|
_vdbeSorterJoinThread(tls, (*TIncrMerger)(unsafe.Pointer(pIncr)).FpTask)
|
|
if (**(**TSorterFile)(__ccgo_up(pIncr + 40))).FpFd != 0 {
|
|
_sqlite3OsCloseFree(tls, (**(**TSorterFile)(__ccgo_up(pIncr + 40))).FpFd)
|
|
}
|
|
if (**(**TSorterFile)(__ccgo_up(pIncr + 40 + 1*16))).FpFd != 0 {
|
|
_sqlite3OsCloseFree(tls, (**(**TSorterFile)(__ccgo_up(pIncr + 40 + 1*16))).FpFd)
|
|
}
|
|
}
|
|
_vdbeMergeEngineFree(tls, (*TIncrMerger)(unsafe.Pointer(pIncr)).FpMerger)
|
|
Xsqlite3_free(tls, pIncr)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Allocate and return a new IncrMerger object to read data from pMerger.
|
|
// **
|
|
// ** If an OOM condition is encountered, return NULL. In this case free the
|
|
// ** pMerger argument before returning.
|
|
// */
|
|
func _vdbeIncrMergerNew(tls *libc.TLS, pTask uintptr, pMerger uintptr, ppOut uintptr) (r int32) {
|
|
var pIncr, v1, v2 uintptr
|
|
var rc, v3 int32
|
|
_, _, _, _, _ = pIncr, rc, v1, v2, v3
|
|
rc = SQLITE_OK
|
|
if _sqlite3FaultSim(tls, int32(100)) != 0 {
|
|
v2 = uintptr(0)
|
|
} else {
|
|
v2 = _sqlite3MallocZero(tls, uint64(72))
|
|
}
|
|
v1 = v2
|
|
**(**uintptr)(__ccgo_up(ppOut)) = v1
|
|
pIncr = v1
|
|
if pIncr != 0 {
|
|
(*TIncrMerger)(unsafe.Pointer(pIncr)).FpMerger = pMerger
|
|
(*TIncrMerger)(unsafe.Pointer(pIncr)).FpTask = pTask
|
|
if (*TVdbeSorter)(unsafe.Pointer((*TSortSubtask)(unsafe.Pointer(pTask)).FpSorter)).FmxKeysize+int32(9) > (*TVdbeSorter)(unsafe.Pointer((*TSortSubtask)(unsafe.Pointer(pTask)).FpSorter)).FmxPmaSize/int32(2) {
|
|
v3 = (*TVdbeSorter)(unsafe.Pointer((*TSortSubtask)(unsafe.Pointer(pTask)).FpSorter)).FmxKeysize + int32(9)
|
|
} else {
|
|
v3 = (*TVdbeSorter)(unsafe.Pointer((*TSortSubtask)(unsafe.Pointer(pTask)).FpSorter)).FmxPmaSize / int32(2)
|
|
}
|
|
(*TIncrMerger)(unsafe.Pointer(pIncr)).FmxSz = v3
|
|
(*TSortSubtask)(unsafe.Pointer(pTask)).Ffile2.FiEof += int64((*TIncrMerger)(unsafe.Pointer(pIncr)).FmxSz)
|
|
} else {
|
|
_vdbeMergeEngineFree(tls, pMerger)
|
|
rc = int32(SQLITE_NOMEM)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The main routine for background threads that populate aFile[1] of
|
|
// ** multi-threaded IncrMerger objects.
|
|
// */
|
|
func _vdbeIncrPopulateThread(tls *libc.TLS, pCtx uintptr) (r uintptr) {
|
|
var pIncr, pRet uintptr
|
|
_, _ = pIncr, pRet
|
|
pIncr = pCtx
|
|
pRet = uintptr(int64(_vdbeIncrPopulate(tls, pIncr)))
|
|
(*TSortSubtask)(unsafe.Pointer((*TIncrMerger)(unsafe.Pointer(pIncr)).FpTask)).FbDone = int32(1)
|
|
return pRet
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This function is called when the PmaReader corresponding to pIncr has
|
|
// ** finished reading the contents of aFile[0]. Its purpose is to "refill"
|
|
// ** aFile[0] such that the PmaReader should start rereading it from the
|
|
// ** beginning.
|
|
// **
|
|
// ** For single-threaded objects, this is accomplished by literally reading
|
|
// ** keys from pIncr->pMerger and repopulating aFile[0].
|
|
// **
|
|
// ** For multi-threaded objects, all that is required is to wait until the
|
|
// ** background thread is finished (if it is not already) and then swap
|
|
// ** aFile[0] and aFile[1] in place. If the contents of pMerger have not
|
|
// ** been exhausted, this function also launches a new background thread
|
|
// ** to populate the new aFile[1].
|
|
// **
|
|
// ** SQLITE_OK is returned on success, or an SQLite error code otherwise.
|
|
// */
|
|
func _vdbeIncrSwap(tls *libc.TLS, pIncr uintptr) (r int32) {
|
|
var f0 TSorterFile
|
|
var rc int32
|
|
_, _ = f0, rc
|
|
rc = SQLITE_OK
|
|
if (*TIncrMerger)(unsafe.Pointer(pIncr)).FbUseThread != 0 {
|
|
rc = _vdbeSorterJoinThread(tls, (*TIncrMerger)(unsafe.Pointer(pIncr)).FpTask)
|
|
if rc == SQLITE_OK {
|
|
f0 = **(**TSorterFile)(__ccgo_up(pIncr + 40))
|
|
**(**TSorterFile)(__ccgo_up(pIncr + 40)) = **(**TSorterFile)(__ccgo_up(pIncr + 40 + 1*16))
|
|
**(**TSorterFile)(__ccgo_up(pIncr + 40 + 1*16)) = f0
|
|
}
|
|
if rc == SQLITE_OK {
|
|
if (**(**TSorterFile)(__ccgo_up(pIncr + 40))).FiEof == (*TIncrMerger)(unsafe.Pointer(pIncr)).FiStartOff {
|
|
(*TIncrMerger)(unsafe.Pointer(pIncr)).FbEof = int32(1)
|
|
} else {
|
|
rc = _vdbeIncrBgPopulate(tls, pIncr)
|
|
}
|
|
}
|
|
} else {
|
|
rc = _vdbeIncrPopulate(tls, pIncr)
|
|
**(**TSorterFile)(__ccgo_up(pIncr + 40)) = **(**TSorterFile)(__ccgo_up(pIncr + 40 + 1*16))
|
|
if (**(**TSorterFile)(__ccgo_up(pIncr + 40))).FiEof == (*TIncrMerger)(unsafe.Pointer(pIncr)).FiStartOff {
|
|
(*TIncrMerger)(unsafe.Pointer(pIncr)).FbEof = int32(1)
|
|
}
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Unlock all of the btrees previously locked by a call to sqlite3VdbeEnter().
|
|
// */
|
|
func _vdbeLeave(tls *libc.TLS, p uintptr) {
|
|
var aDb, db uintptr
|
|
var i, nDb int32
|
|
_, _, _, _ = aDb, db, i, nDb
|
|
db = (*TVdbe)(unsafe.Pointer(p)).Fdb
|
|
aDb = (*Tsqlite3)(unsafe.Pointer(db)).FaDb
|
|
nDb = (*Tsqlite3)(unsafe.Pointer(db)).FnDb
|
|
i = 0
|
|
for {
|
|
if !(i < nDb) {
|
|
break
|
|
}
|
|
if i != int32(1) && (*TVdbe)(unsafe.Pointer(p)).FlockMask&(libc.Uint32FromInt32(1)<<i) != uint32(0) && (**(**TDb)(__ccgo_up(aDb + uintptr(i)*32))).FpBt != uintptr(0) {
|
|
_sqlite3BtreeLeave(tls, (**(**TDb)(__ccgo_up(aDb + uintptr(i)*32))).FpBt)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Recompute pMerger->aTree[iOut] by comparing the next keys on the
|
|
// ** two PmaReaders that feed that entry. Neither of the PmaReaders
|
|
// ** are advanced. This routine merely does the comparison.
|
|
// */
|
|
func _vdbeMergeEngineCompare(tls *libc.TLS, pMerger uintptr, iOut int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var i1, i2, iRes, res int32
|
|
var p1, p2, pTask uintptr
|
|
var _ /* bCached at bp+0 */ int32
|
|
_, _, _, _, _, _, _ = i1, i2, iRes, p1, p2, pTask, res
|
|
if iOut >= (*TMergeEngine)(unsafe.Pointer(pMerger)).FnTree/int32(2) {
|
|
i1 = (iOut - (*TMergeEngine)(unsafe.Pointer(pMerger)).FnTree/int32(2)) * int32(2)
|
|
i2 = i1 + int32(1)
|
|
} else {
|
|
i1 = **(**int32)(__ccgo_up((*TMergeEngine)(unsafe.Pointer(pMerger)).FaTree + uintptr(iOut*int32(2))*4))
|
|
i2 = **(**int32)(__ccgo_up((*TMergeEngine)(unsafe.Pointer(pMerger)).FaTree + uintptr(iOut*int32(2)+int32(1))*4))
|
|
}
|
|
p1 = (*TMergeEngine)(unsafe.Pointer(pMerger)).FaReadr + uintptr(i1)*80
|
|
p2 = (*TMergeEngine)(unsafe.Pointer(pMerger)).FaReadr + uintptr(i2)*80
|
|
if (*TPmaReader)(unsafe.Pointer(p1)).FpFd == uintptr(0) {
|
|
iRes = i2
|
|
} else {
|
|
if (*TPmaReader)(unsafe.Pointer(p2)).FpFd == uintptr(0) {
|
|
iRes = i1
|
|
} else {
|
|
pTask = (*TMergeEngine)(unsafe.Pointer(pMerger)).FpTask
|
|
**(**int32)(__ccgo_up(bp)) = 0
|
|
/* from vdbeSortSubtaskMain() */
|
|
res = (*(*func(*libc.TLS, uintptr, uintptr, uintptr, int32, uintptr, int32) int32)(unsafe.Pointer(&struct{ uintptr }{(*TSortSubtask)(unsafe.Pointer(pTask)).FxCompare})))(tls, pTask, bp, (*TPmaReader)(unsafe.Pointer(p1)).FaKey, (*TPmaReader)(unsafe.Pointer(p1)).FnKey, (*TPmaReader)(unsafe.Pointer(p2)).FaKey, (*TPmaReader)(unsafe.Pointer(p2)).FnKey)
|
|
if res <= 0 {
|
|
iRes = i1
|
|
} else {
|
|
iRes = i2
|
|
}
|
|
}
|
|
}
|
|
**(**int32)(__ccgo_up((*TMergeEngine)(unsafe.Pointer(pMerger)).FaTree + uintptr(iOut)*4)) = iRes
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free the MergeEngine object passed as the only argument.
|
|
// */
|
|
func _vdbeMergeEngineFree(tls *libc.TLS, pMerger uintptr) {
|
|
var i int32
|
|
_ = i
|
|
if pMerger != 0 {
|
|
i = 0
|
|
for {
|
|
if !(i < (*TMergeEngine)(unsafe.Pointer(pMerger)).FnTree) {
|
|
break
|
|
}
|
|
_vdbePmaReaderClear(tls, (*TMergeEngine)(unsafe.Pointer(pMerger)).FaReadr+uintptr(i)*80)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
}
|
|
Xsqlite3_free(tls, pMerger)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Allocate a new MergeEngine object to merge the contents of nPMA level-0
|
|
// ** PMAs from pTask->file. If no error occurs, set *ppOut to point to
|
|
// ** the new object and return SQLITE_OK. Or, if an error does occur, set *ppOut
|
|
// ** to NULL and return an SQLite error code.
|
|
// **
|
|
// ** When this function is called, *piOffset is set to the offset of the
|
|
// ** first PMA to read from pTask->file. Assuming no error occurs, it is
|
|
// ** set to the offset immediately following the last byte of the last
|
|
// ** PMA before returning. If an error does occur, then the final value of
|
|
// ** *piOffset is undefined.
|
|
// */
|
|
func _vdbeMergeEngineLevel0(tls *libc.TLS, pTask uintptr, nPMA int32, piOffset uintptr, ppOut uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var i, rc int32
|
|
var iOff Ti64
|
|
var pNew, pReadr, v1 uintptr
|
|
var _ /* nDummy at bp+0 */ Ti64
|
|
_, _, _, _, _, _ = i, iOff, pNew, pReadr, rc, v1 /* Merge engine to return */
|
|
iOff = **(**Ti64)(__ccgo_up(piOffset))
|
|
rc = SQLITE_OK
|
|
v1 = _vdbeMergeEngineNew(tls, nPMA)
|
|
pNew = v1
|
|
**(**uintptr)(__ccgo_up(ppOut)) = v1
|
|
if pNew == uintptr(0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
}
|
|
i = 0
|
|
for {
|
|
if !(i < nPMA && rc == SQLITE_OK) {
|
|
break
|
|
}
|
|
**(**Ti64)(__ccgo_up(bp)) = 0
|
|
pReadr = (*TMergeEngine)(unsafe.Pointer(pNew)).FaReadr + uintptr(i)*80
|
|
rc = _vdbePmaReaderInit(tls, pTask, pTask+64, iOff, pReadr, bp)
|
|
iOff = (*TPmaReader)(unsafe.Pointer(pReadr)).FiEof
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if rc != SQLITE_OK {
|
|
_vdbeMergeEngineFree(tls, pNew)
|
|
**(**uintptr)(__ccgo_up(ppOut)) = uintptr(0)
|
|
}
|
|
**(**Ti64)(__ccgo_up(piOffset)) = iOff
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The main routine for vdbePmaReaderIncrMergeInit() operations run in
|
|
// ** background threads.
|
|
// */
|
|
func _vdbePmaReaderBgIncrInit(tls *libc.TLS, pCtx uintptr) (r uintptr) {
|
|
var pReader, pRet uintptr
|
|
_, _ = pReader, pRet
|
|
pReader = pCtx
|
|
pRet = uintptr(int64(_vdbePmaReaderIncrMergeInit(tls, pReader, int32(INCRINIT_TASK))))
|
|
(*TSortSubtask)(unsafe.Pointer((*TIncrMerger)(unsafe.Pointer((*TPmaReader)(unsafe.Pointer(pReader)).FpIncr)).FpTask)).FbDone = int32(1)
|
|
return pRet
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The PmaReader passed as the first argument is guaranteed to be an
|
|
// ** incremental-reader (pReadr->pIncr!=0). This function serves to open
|
|
// ** and/or initialize the temp file related fields of the IncrMerge
|
|
// ** object at (pReadr->pIncr).
|
|
// **
|
|
// ** If argument eMode is set to INCRINIT_NORMAL, then all PmaReaders
|
|
// ** in the sub-tree headed by pReadr are also initialized. Data is then
|
|
// ** loaded into the buffers belonging to pReadr and it is set to point to
|
|
// ** the first key in its range.
|
|
// **
|
|
// ** If argument eMode is set to INCRINIT_TASK, then pReadr is guaranteed
|
|
// ** to be a multi-threaded PmaReader and this function is being called in a
|
|
// ** background thread. In this case all PmaReaders in the sub-tree are
|
|
// ** initialized as for INCRINIT_NORMAL and the aFile[1] buffer belonging to
|
|
// ** pReadr is populated. However, pReadr itself is not set up to point
|
|
// ** to its first key. A call to vdbePmaReaderNext() is still required to do
|
|
// ** that.
|
|
// **
|
|
// ** The reason this function does not call vdbePmaReaderNext() immediately
|
|
// ** in the INCRINIT_TASK case is that vdbePmaReaderNext() assumes that it has
|
|
// ** to block on thread (pTask->thread) before accessing aFile[1]. But, since
|
|
// ** this entire function is being run by thread (pTask->thread), that will
|
|
// ** lead to the current background thread attempting to join itself.
|
|
// **
|
|
// ** Finally, if argument eMode is set to INCRINIT_ROOT, it may be assumed
|
|
// ** that pReadr->pIncr is a multi-threaded IncrMerge objects, and that all
|
|
// ** child-trees have already been initialized using IncrInit(INCRINIT_TASK).
|
|
// ** In this case vdbePmaReaderNext() is called on all child PmaReaders and
|
|
// ** the current PmaReader set to point to the first key in its range.
|
|
// **
|
|
// ** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
|
|
// */
|
|
func _vdbePmaReaderIncrMergeInit(tls *libc.TLS, pReadr uintptr, eMode int32) (r int32) {
|
|
var db, pIncr, pTask uintptr
|
|
var mxSz, rc int32
|
|
_, _, _, _, _ = db, mxSz, pIncr, pTask, rc
|
|
rc = SQLITE_OK
|
|
pIncr = (*TPmaReader)(unsafe.Pointer(pReadr)).FpIncr
|
|
pTask = (*TIncrMerger)(unsafe.Pointer(pIncr)).FpTask
|
|
db = (*TVdbeSorter)(unsafe.Pointer((*TSortSubtask)(unsafe.Pointer(pTask)).FpSorter)).Fdb
|
|
/* eMode is always INCRINIT_NORMAL in single-threaded mode */
|
|
rc = _vdbeMergeEngineInit(tls, pTask, (*TIncrMerger)(unsafe.Pointer(pIncr)).FpMerger, eMode)
|
|
/* Set up the required files for pIncr. A multi-threaded IncrMerge object
|
|
** requires two temp files to itself, whereas a single-threaded object
|
|
** only requires a region of pTask->file2. */
|
|
if rc == SQLITE_OK {
|
|
mxSz = (*TIncrMerger)(unsafe.Pointer(pIncr)).FmxSz
|
|
if (*TIncrMerger)(unsafe.Pointer(pIncr)).FbUseThread != 0 {
|
|
rc = _vdbeSorterOpenTempFile(tls, db, int64(mxSz), pIncr+40)
|
|
if rc == SQLITE_OK {
|
|
rc = _vdbeSorterOpenTempFile(tls, db, int64(mxSz), pIncr+40+1*16)
|
|
}
|
|
} else {
|
|
/*if( !pIncr->bUseThread )*/
|
|
if (*TSortSubtask)(unsafe.Pointer(pTask)).Ffile2.FpFd == uintptr(0) {
|
|
rc = _vdbeSorterOpenTempFile(tls, db, (*TSortSubtask)(unsafe.Pointer(pTask)).Ffile2.FiEof, pTask+80)
|
|
(*TSortSubtask)(unsafe.Pointer(pTask)).Ffile2.FiEof = 0
|
|
}
|
|
if rc == SQLITE_OK {
|
|
(**(**TSorterFile)(__ccgo_up(pIncr + 40 + 1*16))).FpFd = (*TSortSubtask)(unsafe.Pointer(pTask)).Ffile2.FpFd
|
|
(*TIncrMerger)(unsafe.Pointer(pIncr)).FiStartOff = (*TSortSubtask)(unsafe.Pointer(pTask)).Ffile2.FiEof
|
|
(*TSortSubtask)(unsafe.Pointer(pTask)).Ffile2.FiEof += int64(mxSz)
|
|
}
|
|
}
|
|
}
|
|
if rc == SQLITE_OK && (*TIncrMerger)(unsafe.Pointer(pIncr)).FbUseThread != 0 {
|
|
/* Use the current thread to populate aFile[1], even though this
|
|
** PmaReader is multi-threaded. If this is an INCRINIT_TASK object,
|
|
** then this function is already running in background thread
|
|
** pIncr->pTask->thread.
|
|
**
|
|
** If this is the INCRINIT_ROOT object, then it is running in the
|
|
** main VDBE thread. But that is Ok, as that thread cannot return
|
|
** control to the VDBE or proceed with anything useful until the
|
|
** first results are ready from this merger object anyway.
|
|
*/
|
|
rc = _vdbeIncrPopulate(tls, pIncr)
|
|
}
|
|
if rc == SQLITE_OK && (libc.Bool(false) || eMode != int32(INCRINIT_TASK)) {
|
|
rc = _vdbePmaReaderNext(tls, pReadr)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** pRoot is the root of an incremental merge-tree with depth nDepth (according
|
|
// ** to vdbeSorterTreeDepth()). pLeaf is the iSeq'th leaf to be added to the
|
|
// ** tree, counting from zero. This function adds pLeaf to the tree.
|
|
// **
|
|
// ** If successful, SQLITE_OK is returned. If an error occurs, an SQLite error
|
|
// ** code is returned and pLeaf is freed.
|
|
// */
|
|
func _vdbeSorterAddToTree(tls *libc.TLS, pTask uintptr, nDepth int32, iSeq int32, pRoot uintptr, pLeaf uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var i, iIter, nDiv, rc int32
|
|
var p, pNew, pReadr uintptr
|
|
var _ /* pIncr at bp+0 */ uintptr
|
|
_, _, _, _, _, _, _ = i, iIter, nDiv, p, pNew, pReadr, rc
|
|
rc = SQLITE_OK
|
|
nDiv = int32(1)
|
|
p = pRoot
|
|
rc = _vdbeIncrMergerNew(tls, pTask, pLeaf, bp)
|
|
i = int32(1)
|
|
for {
|
|
if !(i < nDepth) {
|
|
break
|
|
}
|
|
nDiv = nDiv * int32(SORTER_MAX_MERGE_COUNT)
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
i = int32(1)
|
|
for {
|
|
if !(i < nDepth && rc == SQLITE_OK) {
|
|
break
|
|
}
|
|
iIter = iSeq / nDiv % int32(SORTER_MAX_MERGE_COUNT)
|
|
pReadr = (*TMergeEngine)(unsafe.Pointer(p)).FaReadr + uintptr(iIter)*80
|
|
if (*TPmaReader)(unsafe.Pointer(pReadr)).FpIncr == uintptr(0) {
|
|
pNew = _vdbeMergeEngineNew(tls, int32(SORTER_MAX_MERGE_COUNT))
|
|
if pNew == uintptr(0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
} else {
|
|
rc = _vdbeIncrMergerNew(tls, pTask, pNew, pReadr+72)
|
|
}
|
|
}
|
|
if rc == SQLITE_OK {
|
|
p = (*TIncrMerger)(unsafe.Pointer((*TPmaReader)(unsafe.Pointer(pReadr)).FpIncr)).FpMerger
|
|
nDiv = nDiv / int32(SORTER_MAX_MERGE_COUNT)
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if rc == SQLITE_OK {
|
|
(**(**TPmaReader)(__ccgo_up((*TMergeEngine)(unsafe.Pointer(p)).FaReadr + uintptr(iSeq%int32(SORTER_MAX_MERGE_COUNT))*80))).FpIncr = **(**uintptr)(__ccgo_up(bp))
|
|
} else {
|
|
_vdbeIncrFree(tls, **(**uintptr)(__ccgo_up(bp)))
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** The main routine for background threads that write level-0 PMAs.
|
|
// */
|
|
func _vdbeSorterFlushThread(tls *libc.TLS, pCtx uintptr) (r uintptr) {
|
|
var pTask uintptr
|
|
var rc int32
|
|
_, _ = pTask, rc
|
|
pTask = pCtx /* Return code */
|
|
rc = _vdbeSorterListToPMA(tls, pTask, pTask+32)
|
|
(*TSortSubtask)(unsafe.Pointer(pTask)).FbDone = int32(1)
|
|
return uintptr(int64(rc))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Join thread pTask->thread.
|
|
// */
|
|
func _vdbeSorterJoinThread(tls *libc.TLS, pTask uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var rc int32
|
|
var _ /* pRet at bp+0 */ uintptr
|
|
_ = rc
|
|
rc = SQLITE_OK
|
|
if (*TSortSubtask)(unsafe.Pointer(pTask)).FpThread != 0 {
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(int64(libc.Int32FromInt32(SQLITE_ERROR)))
|
|
_sqlite3ThreadJoin(tls, (*TSortSubtask)(unsafe.Pointer(pTask)).FpThread, bp)
|
|
rc = int32(int64(**(**uintptr)(__ccgo_up(bp))))
|
|
(*TSortSubtask)(unsafe.Pointer(pTask)).FbDone = 0
|
|
(*TSortSubtask)(unsafe.Pointer(pTask)).FpThread = uintptr(0)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Merge the two sorted lists p1 and p2 into a single list.
|
|
// */
|
|
func _vdbeSorterMerge(tls *libc.TLS, pTask uintptr, p1 uintptr, p2 uintptr) (r uintptr) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var pp uintptr
|
|
var res int32
|
|
var _ /* bCached at bp+8 */ int32
|
|
var _ /* pFinal at bp+0 */ uintptr
|
|
_, _ = pp, res
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
pp = bp
|
|
**(**int32)(__ccgo_up(bp + 8)) = 0
|
|
for {
|
|
res = (*(*func(*libc.TLS, uintptr, uintptr, uintptr, int32, uintptr, int32) int32)(unsafe.Pointer(&struct{ uintptr }{(*TSortSubtask)(unsafe.Pointer(pTask)).FxCompare})))(tls, pTask, bp+8, p1+libc.UintptrFromInt32(1)*16, (*TSorterRecord)(unsafe.Pointer(p1)).FnVal, p2+libc.UintptrFromInt32(1)*16, (*TSorterRecord)(unsafe.Pointer(p2)).FnVal)
|
|
if res <= 0 {
|
|
**(**uintptr)(__ccgo_up(pp)) = p1
|
|
pp = p1 + 8
|
|
p1 = *(*uintptr)(unsafe.Pointer(p1 + 8))
|
|
if p1 == uintptr(0) {
|
|
**(**uintptr)(__ccgo_up(pp)) = p2
|
|
break
|
|
}
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(pp)) = p2
|
|
pp = p2 + 8
|
|
p2 = *(*uintptr)(unsafe.Pointer(p2 + 8))
|
|
**(**int32)(__ccgo_up(bp + 8)) = 0
|
|
if p2 == uintptr(0) {
|
|
**(**uintptr)(__ccgo_up(pp)) = p1
|
|
break
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
}
|
|
return **(**uintptr)(__ccgo_up(bp))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free the list of sorted records starting at pRecord.
|
|
// */
|
|
func _vdbeSorterRecordFree(tls *libc.TLS, db uintptr, pRecord uintptr) {
|
|
var p, pNext uintptr
|
|
_, _ = p, pNext
|
|
p = pRecord
|
|
for {
|
|
if !(p != 0) {
|
|
break
|
|
}
|
|
pNext = *(*uintptr)(unsafe.Pointer(p + 8))
|
|
_sqlite3DbFree(tls, db, p)
|
|
goto _1
|
|
_1:
|
|
;
|
|
p = pNext
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return a pointer to a buffer owned by the sorter that contains the
|
|
// ** current key.
|
|
// */
|
|
func _vdbeSorterRowkey(tls *libc.TLS, pSorter uintptr, pnKey uintptr) (r uintptr) {
|
|
var pKey, pReader uintptr
|
|
_, _ = pKey, pReader
|
|
if (*TVdbeSorter)(unsafe.Pointer(pSorter)).FbUsePMA != 0 {
|
|
if (*TVdbeSorter)(unsafe.Pointer(pSorter)).FbUseThreads != 0 {
|
|
pReader = (*TVdbeSorter)(unsafe.Pointer(pSorter)).FpReader
|
|
} else {
|
|
/*if( !pSorter->bUseThreads )*/
|
|
pReader = (*TMergeEngine)(unsafe.Pointer((*TVdbeSorter)(unsafe.Pointer(pSorter)).FpMerger)).FaReadr + uintptr(**(**int32)(__ccgo_up((*TMergeEngine)(unsafe.Pointer((*TVdbeSorter)(unsafe.Pointer(pSorter)).FpMerger)).FaTree + 1*4)))*80
|
|
}
|
|
**(**int32)(__ccgo_up(pnKey)) = (*TPmaReader)(unsafe.Pointer(pReader)).FnKey
|
|
pKey = (*TPmaReader)(unsafe.Pointer(pReader)).FaKey
|
|
} else {
|
|
**(**int32)(__ccgo_up(pnKey)) = (*TSorterRecord)(unsafe.Pointer((*TVdbeSorter)(unsafe.Pointer(pSorter)).Flist.FpList)).FnVal
|
|
pKey = (*TVdbeSorter)(unsafe.Pointer(pSorter)).Flist.FpList + libc.UintptrFromInt32(1)*16
|
|
}
|
|
return pKey
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Table p is a virtual table. This function moves all elements in the
|
|
// ** p->u.vtab.p list to the sqlite3.pDisconnect lists of their associated
|
|
// ** database connections to be disconnected at the next opportunity.
|
|
// ** Except, if argument db is not NULL, then the entry associated with
|
|
// ** connection db is left in the p->u.vtab.p list.
|
|
// */
|
|
func _vtabDisconnectAll(tls *libc.TLS, db uintptr, p uintptr) (r uintptr) {
|
|
var db2, pNext, pRet, pVTable uintptr
|
|
_, _, _, _ = db2, pNext, pRet, pVTable
|
|
pRet = uintptr(0)
|
|
pVTable = (*(*struct {
|
|
FnArg int32
|
|
FazArg uintptr
|
|
Fp uintptr
|
|
})(unsafe.Pointer(p + 64))).Fp
|
|
(*(*struct {
|
|
FnArg int32
|
|
FazArg uintptr
|
|
Fp uintptr
|
|
})(unsafe.Pointer(p + 64))).Fp = uintptr(0)
|
|
/* Assert that the mutex (if any) associated with the BtShared database
|
|
** that contains table p is held by the caller. See header comments
|
|
** above function sqlite3VtabUnlockList() for an explanation of why
|
|
** this makes it safe to access the sqlite3.pDisconnect list of any
|
|
** database connection that may have an entry in the p->u.vtab.p list.
|
|
*/
|
|
for pVTable != 0 {
|
|
db2 = (*TVTable)(unsafe.Pointer(pVTable)).Fdb
|
|
pNext = (*TVTable)(unsafe.Pointer(pVTable)).FpNext
|
|
if db2 == db {
|
|
pRet = pVTable
|
|
(*(*struct {
|
|
FnArg int32
|
|
FazArg uintptr
|
|
Fp uintptr
|
|
})(unsafe.Pointer(p + 64))).Fp = pRet
|
|
(*TVTable)(unsafe.Pointer(pRet)).FpNext = uintptr(0)
|
|
} else {
|
|
(*TVTable)(unsafe.Pointer(pVTable)).FpNext = (*Tsqlite3)(unsafe.Pointer(db2)).FpDisconnect
|
|
(*Tsqlite3)(unsafe.Pointer(db2)).FpDisconnect = pVTable
|
|
}
|
|
pVTable = pNext
|
|
}
|
|
return pRet
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return a pointer to the WalCkptInfo structure in the wal-index.
|
|
// */
|
|
func _walCkptInfo(tls *libc.TLS, pWal uintptr) (r uintptr) {
|
|
return **(**uintptr)(__ccgo_up((*TWal)(unsafe.Pointer(pWal)).FapWiData)) + uintptr(libc.Uint64FromInt64(48)/libc.Uint64FromInt32(2))*4
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the page number associated with frame iFrame in this WAL.
|
|
// */
|
|
func _walFramePgno(tls *libc.TLS, pWal uintptr, iFrame Tu32) (r Tu32) {
|
|
var iHash int32
|
|
_ = iHash
|
|
iHash = _walFramePage(tls, iFrame)
|
|
if iHash == 0 {
|
|
return **(**Tu32)(__ccgo_up(**(**uintptr)(__ccgo_up((*TWal)(unsafe.Pointer(pWal)).FapWiData)) + uintptr((libc.Uint64FromInt64(48)*libc.Uint64FromInt32(2)+libc.Uint64FromInt64(40))/libc.Uint64FromInt64(4)+uint64(iFrame)-uint64(1))*4))
|
|
}
|
|
return **(**Tu32)(__ccgo_up(**(**uintptr)(__ccgo_up((*TWal)(unsafe.Pointer(pWal)).FapWiData + uintptr(iHash)*8)) + uintptr((uint64(iFrame-uint32(1))-(libc.Uint64FromInt32(HASHTABLE_NPAGE)-(libc.Uint64FromInt64(48)*libc.Uint64FromInt32(2)+libc.Uint64FromInt64(40))/libc.Uint64FromInt64(4)))%uint64(HASHTABLE_NPAGE))*4))
|
|
}
|
|
|
|
func _walIndexPage(tls *libc.TLS, pWal uintptr, iPage int32, ppPage uintptr) (r int32) {
|
|
var v1 uintptr
|
|
var v2 bool
|
|
_, _ = v1, v2
|
|
if v2 = (*TWal)(unsafe.Pointer(pWal)).FnWiData <= iPage; !v2 {
|
|
v1 = **(**uintptr)(__ccgo_up((*TWal)(unsafe.Pointer(pWal)).FapWiData + uintptr(iPage)*8))
|
|
**(**uintptr)(__ccgo_up(ppPage)) = v1
|
|
}
|
|
if v2 || v1 == uintptr(0) {
|
|
return _walIndexPageRealloc(tls, pWal, iPage, ppPage)
|
|
}
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Free a WhereInfo structure
|
|
// */
|
|
func _whereInfoFree(tls *libc.TLS, db uintptr, pWInfo uintptr) {
|
|
var p, pNext uintptr
|
|
_, _ = p, pNext
|
|
_sqlite3WhereClauseClear(tls, pWInfo+104)
|
|
for (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpLoops != 0 {
|
|
p = (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpLoops
|
|
(*TWhereInfo)(unsafe.Pointer(pWInfo)).FpLoops = (*TWhereLoop)(unsafe.Pointer(p)).FpNextLoop
|
|
_whereLoopDelete(tls, db, p)
|
|
}
|
|
for (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpMemToFree != 0 {
|
|
pNext = (*TWhereMemBlock)(unsafe.Pointer((*TWhereInfo)(unsafe.Pointer(pWInfo)).FpMemToFree)).FpNext
|
|
_sqlite3DbNNFreeNN(tls, db, (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpMemToFree)
|
|
(*TWhereInfo)(unsafe.Pointer(pWInfo)).FpMemToFree = pNext
|
|
}
|
|
_sqlite3DbNNFreeNN(tls, db, pWInfo)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Insert or replace a WhereLoop entry using the template supplied.
|
|
// **
|
|
// ** An existing WhereLoop entry might be overwritten if the new template
|
|
// ** is better and has fewer dependencies. Or the template will be ignored
|
|
// ** and no insert will occur if an existing WhereLoop is faster and has
|
|
// ** fewer dependencies than the template. Otherwise a new WhereLoop is
|
|
// ** added based on the template.
|
|
// **
|
|
// ** If pBuilder->pOrSet is not NULL then we care about only the
|
|
// ** prerequisites and rRun and nOut costs of the N best loops. That
|
|
// ** information is gathered in the pBuilder->pOrSet object. This special
|
|
// ** processing mode is used only for OR clause processing.
|
|
// **
|
|
// ** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we
|
|
// ** still might overwrite similar loops with the new template if the
|
|
// ** new template is better. Loops may be overwritten if the following
|
|
// ** conditions are met:
|
|
// **
|
|
// ** (1) They have the same iTab.
|
|
// ** (2) They have the same iSortIdx.
|
|
// ** (3) The template has same or fewer dependencies than the current loop
|
|
// ** (4) The template has the same or lower cost than the current loop
|
|
// */
|
|
func _whereLoopInsert(tls *libc.TLS, pBuilder uintptr, pTemplate uintptr) (r int32) {
|
|
var db, p, pIndex, pToDel, pWInfo, ppPrev, ppTail, v1 uintptr
|
|
var rc int32
|
|
_, _, _, _, _, _, _, _, _ = db, p, pIndex, pToDel, pWInfo, ppPrev, ppTail, rc, v1
|
|
pWInfo = (*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FpWInfo
|
|
db = (*TParse)(unsafe.Pointer((*TWhereInfo)(unsafe.Pointer(pWInfo)).FpParse)).Fdb
|
|
/* Stop the search once we hit the query planner search limit */
|
|
if (*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FiPlanLimit == uint32(0) {
|
|
if (*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FpOrSet != 0 {
|
|
(*TWhereOrSet)(unsafe.Pointer((*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FpOrSet)).Fn = uint16(0)
|
|
}
|
|
return int32(SQLITE_DONE)
|
|
}
|
|
(*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FiPlanLimit = (*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FiPlanLimit - 1
|
|
_whereLoopAdjustCost(tls, (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpLoops, pTemplate)
|
|
/* If pBuilder->pOrSet is defined, then only keep track of the costs
|
|
** and prereqs.
|
|
*/
|
|
if (*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FpOrSet != uintptr(0) {
|
|
if (*TWhereLoop)(unsafe.Pointer(pTemplate)).FnLTerm != 0 {
|
|
_whereOrInsert(tls, (*TWhereLoopBuilder)(unsafe.Pointer(pBuilder)).FpOrSet, (*TWhereLoop)(unsafe.Pointer(pTemplate)).Fprereq, (*TWhereLoop)(unsafe.Pointer(pTemplate)).FrRun, (*TWhereLoop)(unsafe.Pointer(pTemplate)).FnOut)
|
|
}
|
|
return SQLITE_OK
|
|
}
|
|
/* Look for an existing WhereLoop to replace with pTemplate
|
|
*/
|
|
ppPrev = _whereLoopFindLesser(tls, pWInfo+80, pTemplate)
|
|
if ppPrev == uintptr(0) {
|
|
/* There already exists a WhereLoop on the list that is better
|
|
** than pTemplate, so just ignore pTemplate */
|
|
return SQLITE_OK
|
|
} else {
|
|
p = **(**uintptr)(__ccgo_up(ppPrev))
|
|
}
|
|
/* If we reach this point it means that either p[] should be overwritten
|
|
** with pTemplate[] if p[] exists, or if p==NULL then allocate a new
|
|
** WhereLoop and insert it.
|
|
*/
|
|
if p == uintptr(0) {
|
|
/* Allocate a new WhereLoop to add to the end of the list */
|
|
v1 = _sqlite3DbMallocRawNN(tls, db, uint64(104))
|
|
p = v1
|
|
**(**uintptr)(__ccgo_up(ppPrev)) = v1
|
|
if p == uintptr(0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
_whereLoopInit(tls, p)
|
|
(*TWhereLoop)(unsafe.Pointer(p)).FpNextLoop = uintptr(0)
|
|
} else {
|
|
/* We will be overwriting WhereLoop p[]. But before we do, first
|
|
** go through the rest of the list and delete any other entries besides
|
|
** p[] that are also supplanted by pTemplate */
|
|
ppTail = p + 72
|
|
for **(**uintptr)(__ccgo_up(ppTail)) != 0 {
|
|
ppTail = _whereLoopFindLesser(tls, ppTail, pTemplate)
|
|
if ppTail == uintptr(0) {
|
|
break
|
|
}
|
|
pToDel = **(**uintptr)(__ccgo_up(ppTail))
|
|
if pToDel == uintptr(0) {
|
|
break
|
|
}
|
|
**(**uintptr)(__ccgo_up(ppTail)) = (*TWhereLoop)(unsafe.Pointer(pToDel)).FpNextLoop
|
|
_whereLoopDelete(tls, db, pToDel)
|
|
}
|
|
}
|
|
rc = _whereLoopXfer(tls, db, p, pTemplate)
|
|
if (*TWhereLoop)(unsafe.Pointer(p)).FwsFlags&uint32(WHERE_VIRTUALTABLE) == uint32(0) {
|
|
pIndex = (*(*struct {
|
|
FnEq Tu16
|
|
FnBtm Tu16
|
|
FnTop Tu16
|
|
FnDistinctCol Tu16
|
|
FpIndex uintptr
|
|
FpOrderBy uintptr
|
|
})(unsafe.Pointer(p + 24))).FpIndex
|
|
if pIndex != 0 && int32(uint32(*(*uint16)(unsafe.Pointer(pIndex + 100))&0x3>>0)) == int32(SQLITE_IDXTYPE_IPK) {
|
|
(*(*struct {
|
|
FnEq Tu16
|
|
FnBtm Tu16
|
|
FnTop Tu16
|
|
FnDistinctCol Tu16
|
|
FpIndex uintptr
|
|
FpOrderBy uintptr
|
|
})(unsafe.Pointer(p + 24))).FpIndex = uintptr(0)
|
|
}
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return the number of arguments passed to the window-function associated
|
|
// ** with the object passed as the only argument to this function.
|
|
// */
|
|
func _windowArgCount(tls *libc.TLS, pWin uintptr) (r int32) {
|
|
var pList uintptr
|
|
var v1 int32
|
|
_, _ = pList, v1
|
|
pList = *(*uintptr)(unsafe.Pointer((*TWindow)(unsafe.Pointer(pWin)).FpOwner + 32))
|
|
if pList != 0 {
|
|
v1 = (*TExprList)(unsafe.Pointer(pList)).FnExpr
|
|
} else {
|
|
v1 = 0
|
|
}
|
|
return v1
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Generate code to set the accumulator register for each window function
|
|
// ** in the linked list passed as the second argument to NULL. And perform
|
|
// ** any equivalent initialization required by any built-in window functions
|
|
// ** in the list.
|
|
// */
|
|
func _windowInitAccum(tls *libc.TLS, pParse uintptr, pMWin uintptr) (r int32) {
|
|
var nArg, regArg, v2 int32
|
|
var pFunc, pWin, v uintptr
|
|
_, _, _, _, _, _ = nArg, pFunc, pWin, regArg, v, v2
|
|
v = _sqlite3GetVdbe(tls, pParse)
|
|
nArg = 0
|
|
pWin = pMWin
|
|
for {
|
|
if !(pWin != 0) {
|
|
break
|
|
}
|
|
pFunc = (*TWindow)(unsafe.Pointer(pWin)).FpWFunc
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Null), 0, (*TWindow)(unsafe.Pointer(pWin)).FregAccum)
|
|
if nArg > _windowArgCount(tls, pWin) {
|
|
v2 = nArg
|
|
} else {
|
|
v2 = _windowArgCount(tls, pWin)
|
|
}
|
|
nArg = v2
|
|
if (*TWindow)(unsafe.Pointer(pMWin)).FregStartRowid == 0 {
|
|
if (*TFuncDef)(unsafe.Pointer(pFunc)).FzName == uintptr(unsafe.Pointer(&_nth_valueName)) || (*TFuncDef)(unsafe.Pointer(pFunc)).FzName == uintptr(unsafe.Pointer(&_first_valueName)) {
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Integer), 0, (*TWindow)(unsafe.Pointer(pWin)).FregApp)
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Integer), 0, (*TWindow)(unsafe.Pointer(pWin)).FregApp+int32(1))
|
|
}
|
|
if (*TFuncDef)(unsafe.Pointer(pFunc)).FfuncFlags&uint32(SQLITE_FUNC_MINMAX) != 0 && (*TWindow)(unsafe.Pointer(pWin)).FcsrApp != 0 {
|
|
_sqlite3VdbeAddOp1(tls, v, int32(OP_ResetSorter), (*TWindow)(unsafe.Pointer(pWin)).FcsrApp)
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Integer), 0, (*TWindow)(unsafe.Pointer(pWin)).FregApp+int32(1))
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pWin = (*TWindow)(unsafe.Pointer(pWin)).FpNextWin
|
|
}
|
|
regArg = (*TParse)(unsafe.Pointer(pParse)).FnMem + int32(1)
|
|
**(**int32)(__ccgo_up(pParse + 60)) += nArg
|
|
return regArg
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Invoke the sub-routine at regGosub (generated by code in select.c) to
|
|
// ** return the current row of Window.iEphCsr. If all window functions are
|
|
// ** aggregate window functions that use the standard API, a single
|
|
// ** OP_Gosub instruction is all that this routine generates. Extra VM code
|
|
// ** for per-row processing is only generated for the following built-in window
|
|
// ** functions:
|
|
// **
|
|
// ** nth_value()
|
|
// ** first_value()
|
|
// ** lag()
|
|
// ** lead()
|
|
// */
|
|
func _windowReturnOneRow(tls *libc.TLS, p uintptr) {
|
|
var csr, csr1, iEph, lbl, lbl1, nArg, op, tmpReg, tmpReg1, tmpReg2, val, v2 int32
|
|
var pFunc, pMWin, pParse, pWin, v uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = csr, csr1, iEph, lbl, lbl1, nArg, op, pFunc, pMWin, pParse, pWin, tmpReg, tmpReg1, tmpReg2, v, val, v2
|
|
pMWin = (*TWindowCodeArg)(unsafe.Pointer(p)).FpMWin
|
|
v = (*TWindowCodeArg)(unsafe.Pointer(p)).FpVdbe
|
|
if (*TWindow)(unsafe.Pointer(pMWin)).FregStartRowid != 0 {
|
|
_windowFullScan(tls, p)
|
|
} else {
|
|
pParse = (*TWindowCodeArg)(unsafe.Pointer(p)).FpParse
|
|
pWin = pMWin
|
|
for {
|
|
if !(pWin != 0) {
|
|
break
|
|
}
|
|
pFunc = (*TWindow)(unsafe.Pointer(pWin)).FpWFunc
|
|
if (*TFuncDef)(unsafe.Pointer(pFunc)).FzName == uintptr(unsafe.Pointer(&_nth_valueName)) || (*TFuncDef)(unsafe.Pointer(pFunc)).FzName == uintptr(unsafe.Pointer(&_first_valueName)) {
|
|
csr = (*TWindow)(unsafe.Pointer(pWin)).FcsrApp
|
|
lbl = _sqlite3VdbeMakeLabel(tls, pParse)
|
|
tmpReg = _sqlite3GetTempReg(tls, pParse)
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Null), 0, (*TWindow)(unsafe.Pointer(pWin)).FregResult)
|
|
if (*TFuncDef)(unsafe.Pointer(pFunc)).FzName == uintptr(unsafe.Pointer(&_nth_valueName)) {
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Column), (*TWindow)(unsafe.Pointer(pMWin)).FiEphCsr, (*TWindow)(unsafe.Pointer(pWin)).FiArgCol+int32(1), tmpReg)
|
|
_windowCheckValue(tls, pParse, tmpReg, int32(2))
|
|
} else {
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Integer), int32(1), tmpReg)
|
|
}
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Add), tmpReg, (*TWindow)(unsafe.Pointer(pWin)).FregApp, tmpReg)
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Gt), (*TWindow)(unsafe.Pointer(pWin)).FregApp+int32(1), lbl, tmpReg)
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_SeekRowid), csr, 0, tmpReg)
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Column), csr, (*TWindow)(unsafe.Pointer(pWin)).FiArgCol, (*TWindow)(unsafe.Pointer(pWin)).FregResult)
|
|
_sqlite3VdbeResolveLabel(tls, v, lbl)
|
|
_sqlite3ReleaseTempReg(tls, pParse, tmpReg)
|
|
} else {
|
|
if (*TFuncDef)(unsafe.Pointer(pFunc)).FzName == uintptr(unsafe.Pointer(&_leadName)) || (*TFuncDef)(unsafe.Pointer(pFunc)).FzName == uintptr(unsafe.Pointer(&_lagName)) {
|
|
nArg = (*TExprList)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer((*TWindow)(unsafe.Pointer(pWin)).FpOwner + 32)))).FnExpr
|
|
csr1 = (*TWindow)(unsafe.Pointer(pWin)).FcsrApp
|
|
lbl1 = _sqlite3VdbeMakeLabel(tls, pParse)
|
|
tmpReg1 = _sqlite3GetTempReg(tls, pParse)
|
|
iEph = (*TWindow)(unsafe.Pointer(pMWin)).FiEphCsr
|
|
if nArg < int32(3) {
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Null), 0, (*TWindow)(unsafe.Pointer(pWin)).FregResult)
|
|
} else {
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Column), iEph, (*TWindow)(unsafe.Pointer(pWin)).FiArgCol+int32(2), (*TWindow)(unsafe.Pointer(pWin)).FregResult)
|
|
}
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Rowid), iEph, tmpReg1)
|
|
if nArg < int32(2) {
|
|
if (*TFuncDef)(unsafe.Pointer(pFunc)).FzName == uintptr(unsafe.Pointer(&_leadName)) {
|
|
v2 = int32(1)
|
|
} else {
|
|
v2 = -int32(1)
|
|
}
|
|
val = v2
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_AddImm), tmpReg1, val)
|
|
} else {
|
|
if (*TFuncDef)(unsafe.Pointer(pFunc)).FzName == uintptr(unsafe.Pointer(&_leadName)) {
|
|
v2 = int32(OP_Add)
|
|
} else {
|
|
v2 = int32(OP_Subtract)
|
|
}
|
|
op = v2
|
|
tmpReg2 = _sqlite3GetTempReg(tls, pParse)
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Column), iEph, (*TWindow)(unsafe.Pointer(pWin)).FiArgCol+int32(1), tmpReg2)
|
|
_sqlite3VdbeAddOp3(tls, v, op, tmpReg2, tmpReg1, tmpReg1)
|
|
_sqlite3ReleaseTempReg(tls, pParse, tmpReg2)
|
|
}
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_SeekRowid), csr1, lbl1, tmpReg1)
|
|
_sqlite3VdbeAddOp3(tls, v, int32(OP_Column), csr1, (*TWindow)(unsafe.Pointer(pWin)).FiArgCol, (*TWindow)(unsafe.Pointer(pWin)).FregResult)
|
|
_sqlite3VdbeResolveLabel(tls, v, lbl1)
|
|
_sqlite3ReleaseTempReg(tls, pParse, tmpReg1)
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
pWin = (*TWindow)(unsafe.Pointer(pWin)).FpNextWin
|
|
}
|
|
}
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Gosub), (*TWindowCodeArg)(unsafe.Pointer(p)).FregGosub, (*TWindowCodeArg)(unsafe.Pointer(p)).FaddrGosub)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Pop the parser's stack once.
|
|
// **
|
|
// ** If there is a destructor routine associated with the token which
|
|
// ** is popped from the stack, then call it.
|
|
// */
|
|
func _yy_pop_parser_stack(tls *libc.TLS, pParser uintptr) {
|
|
var yytos, v1, v2 uintptr
|
|
_, _, _ = yytos, v1, v2
|
|
v2 = pParser
|
|
v1 = *(*uintptr)(unsafe.Pointer(v2))
|
|
*(*uintptr)(unsafe.Pointer(v2)) -= 24
|
|
yytos = v1
|
|
_yy_destructor(tls, pParser, (*TyyStackEntry)(unsafe.Pointer(yytos)).Fmajor, yytos+8)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_defaultMethods)
|
|
*(*uintptr)(unsafe.Add(p, 0)) = __ccgo_fp(_sqlite3MemMalloc)
|
|
*(*uintptr)(unsafe.Add(p, 8)) = __ccgo_fp(_sqlite3MemFree)
|
|
*(*uintptr)(unsafe.Add(p, 16)) = __ccgo_fp(_sqlite3MemRealloc)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_sqlite3MemSize)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(_sqlite3MemRoundup)
|
|
*(*uintptr)(unsafe.Add(p, 40)) = __ccgo_fp(_sqlite3MemInit)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_sqlite3MemShutdown)
|
|
}
|
|
|
|
/************** End of mem1.c ************************************************/
|
|
/************** Begin file mem2.c ********************************************/
|
|
/*
|
|
** 2007 August 15
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
**
|
|
** This file contains low-level memory allocation drivers for when
|
|
** SQLite will use the standard C-library malloc/realloc/free interface
|
|
** to obtain the memory it needs while adding lots of additional debugging
|
|
** information to each allocation in order to help detect and fix memory
|
|
** leaks and memory usage errors.
|
|
**
|
|
** This file contains implementations of the low-level memory allocation
|
|
** routines specified in the sqlite3_mem_methods object.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/*
|
|
** This version of the memory allocator is used only if the
|
|
** SQLITE_MEMDEBUG macro is defined
|
|
*/
|
|
|
|
/************** End of mem2.c ************************************************/
|
|
/************** Begin file mem3.c ********************************************/
|
|
/*
|
|
** 2007 October 14
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** This file contains the C functions that implement a memory
|
|
** allocation subsystem for use by SQLite.
|
|
**
|
|
** This version of the memory allocation subsystem omits all
|
|
** use of malloc(). The SQLite user supplies a block of memory
|
|
** before calling sqlite3_initialize() from which allocations
|
|
** are made and returned by the xMalloc() and xRealloc()
|
|
** implementations. Once sqlite3_initialize() has been called,
|
|
** the amount of memory available to SQLite is fixed and cannot
|
|
** be changed.
|
|
**
|
|
** This version of the memory allocation subsystem is included
|
|
** in the build only if SQLITE_ENABLE_MEMSYS3 is defined.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/*
|
|
** This version of the memory allocator is only built into the library
|
|
** SQLITE_ENABLE_MEMSYS3 is defined. Defining this symbol does not
|
|
** mean that the library will use a memory-pool by default, just that
|
|
** it is available. The mempool allocator is activated by calling
|
|
** sqlite3_config().
|
|
*/
|
|
|
|
/************** End of mem3.c ************************************************/
|
|
/************** Begin file mem5.c ********************************************/
|
|
/*
|
|
** 2007 October 14
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** This file contains the C functions that implement a memory
|
|
** allocation subsystem for use by SQLite.
|
|
**
|
|
** This version of the memory allocation subsystem omits all
|
|
** use of malloc(). The application gives SQLite a block of memory
|
|
** before calling sqlite3_initialize() from which allocations
|
|
** are made and returned by the xMalloc() and xRealloc()
|
|
** implementations. Once sqlite3_initialize() has been called,
|
|
** the amount of memory available to SQLite is fixed and cannot
|
|
** be changed.
|
|
**
|
|
** This version of the memory allocation subsystem is included
|
|
** in the build only if SQLITE_ENABLE_MEMSYS5 is defined.
|
|
**
|
|
** This memory allocator uses the following algorithm:
|
|
**
|
|
** 1. All memory allocation sizes are rounded up to a power of 2.
|
|
**
|
|
** 2. If two adjacent free blocks are the halves of a larger block,
|
|
** then the two blocks are coalesced into the single larger block.
|
|
**
|
|
** 3. New memory is allocated from the first available free block.
|
|
**
|
|
** This algorithm is described in: J. M. Robson. "Bounds for Some Functions
|
|
** Concerning Dynamic Storage Allocation". Journal of the Association for
|
|
** Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499.
|
|
**
|
|
** Let n be the size of the largest allocation divided by the minimum
|
|
** allocation size (after rounding all sizes up to a power of 2.) Let M
|
|
** be the maximum amount of memory ever outstanding at one time. Let
|
|
** N be the total amount of memory available for allocation. Robson
|
|
** proved that this memory allocator will never breakdown due to
|
|
** fragmentation as long as the following constraint holds:
|
|
**
|
|
** N >= M*(1 + log2(n)/2) - n + 1
|
|
**
|
|
** The sqlite3_status() logic tracks the maximum values of n and M so
|
|
** that an application can, at any time, verify this constraint.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/*
|
|
** This version of the memory allocator is used only when
|
|
** SQLITE_ENABLE_MEMSYS5 is defined.
|
|
*/
|
|
|
|
/************** End of mem5.c ************************************************/
|
|
/************** Begin file mutex.c *******************************************/
|
|
/*
|
|
** 2007 August 14
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** This file contains the C functions that implement mutexes.
|
|
**
|
|
** This file contains code that is common across all mutex implementations.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_statPushFuncdef)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_statPush)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_sFts5Api)
|
|
*(*uintptr)(unsafe.Add(p, 8)) = __ccgo_fp(_fts5ApiUserData)
|
|
*(*uintptr)(unsafe.Add(p, 16)) = __ccgo_fp(_fts5ApiColumnCount)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_fts5ApiRowCount)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(_fts5ApiColumnTotalSize)
|
|
*(*uintptr)(unsafe.Add(p, 40)) = __ccgo_fp(_fts5ApiTokenize)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_fts5ApiPhraseCount)
|
|
*(*uintptr)(unsafe.Add(p, 56)) = __ccgo_fp(_fts5ApiPhraseSize)
|
|
*(*uintptr)(unsafe.Add(p, 64)) = __ccgo_fp(_fts5ApiInstCount)
|
|
*(*uintptr)(unsafe.Add(p, 72)) = __ccgo_fp(_fts5ApiInst)
|
|
*(*uintptr)(unsafe.Add(p, 80)) = __ccgo_fp(_fts5ApiRowid)
|
|
*(*uintptr)(unsafe.Add(p, 88)) = __ccgo_fp(_fts5ApiColumnText)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_fts5ApiColumnSize)
|
|
*(*uintptr)(unsafe.Add(p, 104)) = __ccgo_fp(_fts5ApiQueryPhrase)
|
|
*(*uintptr)(unsafe.Add(p, 112)) = __ccgo_fp(_fts5ApiSetAuxdata)
|
|
*(*uintptr)(unsafe.Add(p, 120)) = __ccgo_fp(_fts5ApiGetAuxdata)
|
|
*(*uintptr)(unsafe.Add(p, 128)) = __ccgo_fp(_fts5ApiPhraseFirst)
|
|
*(*uintptr)(unsafe.Add(p, 136)) = __ccgo_fp(_fts5ApiPhraseNext)
|
|
*(*uintptr)(unsafe.Add(p, 144)) = __ccgo_fp(_fts5ApiPhraseFirstColumn)
|
|
*(*uintptr)(unsafe.Add(p, 152)) = __ccgo_fp(_fts5ApiPhraseNextColumn)
|
|
*(*uintptr)(unsafe.Add(p, 160)) = __ccgo_fp(_fts5ApiQueryToken)
|
|
*(*uintptr)(unsafe.Add(p, 168)) = __ccgo_fp(_fts5ApiInstToken)
|
|
*(*uintptr)(unsafe.Add(p, 176)) = __ccgo_fp(_fts5ApiColumnLocale)
|
|
*(*uintptr)(unsafe.Add(p, 184)) = __ccgo_fp(_fts5ApiTokenize_v2)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_aAgg)
|
|
*(*uintptr)(unsafe.Add(p, 0)) = __ccgo_fp(_geopolyBBoxStep)
|
|
*(*uintptr)(unsafe.Add(p, 8)) = __ccgo_fp(_geopolyBBoxFinal)
|
|
}
|
|
|
|
/************** End of geopoly.c *********************************************/
|
|
/************** Continuing where we left off in rtree.c **********************/
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_aFunc)
|
|
*(*uintptr)(unsafe.Add(p, 0)) = __ccgo_fp(_geopolyAreaFunc)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_geopolyBlobFunc)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_geopolyJsonFunc)
|
|
*(*uintptr)(unsafe.Add(p, 72)) = __ccgo_fp(_geopolySvgFunc)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_geopolyWithinFunc)
|
|
*(*uintptr)(unsafe.Add(p, 120)) = __ccgo_fp(_geopolyContainsPointFunc)
|
|
*(*uintptr)(unsafe.Add(p, 144)) = __ccgo_fp(_geopolyOverlapFunc)
|
|
*(*uintptr)(unsafe.Add(p, 168)) = __ccgo_fp(_geopolyDebugFunc)
|
|
*(*uintptr)(unsafe.Add(p, 192)) = __ccgo_fp(_geopolyBBoxFunc)
|
|
*(*uintptr)(unsafe.Add(p, 216)) = __ccgo_fp(_geopolyXformFunc)
|
|
*(*uintptr)(unsafe.Add(p, 240)) = __ccgo_fp(_geopolyRegularFunc)
|
|
*(*uintptr)(unsafe.Add(p, 264)) = __ccgo_fp(_geopolyCcwFunc)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_attach_func)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_attachFunc)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_sMutex)
|
|
*(*uintptr)(unsafe.Add(p, 0)) = __ccgo_fp(_noopMutexInit)
|
|
*(*uintptr)(unsafe.Add(p, 8)) = __ccgo_fp(_noopMutexEnd)
|
|
*(*uintptr)(unsafe.Add(p, 16)) = __ccgo_fp(_noopMutexAlloc)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_noopMutexFree)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(_noopMutexEnter)
|
|
*(*uintptr)(unsafe.Add(p, 40)) = __ccgo_fp(_noopMutexTry)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_noopMutexLeave)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_aAlterTableFuncs)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_renameColumnFunc)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_renameTableFunc)
|
|
*(*uintptr)(unsafe.Add(p, 168)) = __ccgo_fp(_renameTableTest)
|
|
*(*uintptr)(unsafe.Add(p, 240)) = __ccgo_fp(_dropColumnFunc)
|
|
*(*uintptr)(unsafe.Add(p, 312)) = __ccgo_fp(_renameQuotefixFunc)
|
|
*(*uintptr)(unsafe.Add(p, 384)) = __ccgo_fp(_dropConstraintFunc)
|
|
*(*uintptr)(unsafe.Add(p, 456)) = __ccgo_fp(_failConstraintFunc)
|
|
*(*uintptr)(unsafe.Add(p, 528)) = __ccgo_fp(_addConstraintFunc)
|
|
*(*uintptr)(unsafe.Add(p, 600)) = __ccgo_fp(_findConstraintFunc)
|
|
}
|
|
|
|
/************** End of alter.c ***********************************************/
|
|
/************** Begin file analyze.c *****************************************/
|
|
/*
|
|
** 2005-07-08
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** This file contains code associated with the ANALYZE command.
|
|
**
|
|
** The ANALYZE command gather statistics about the content of tables
|
|
** and indices. These statistics are made available to the query planner
|
|
** to help it make better decisions about how to perform queries.
|
|
**
|
|
** The following system tables are or have been supported:
|
|
**
|
|
** CREATE TABLE sqlite_stat1(tbl, idx, stat);
|
|
** CREATE TABLE sqlite_stat2(tbl, idx, sampleno, sample);
|
|
** CREATE TABLE sqlite_stat3(tbl, idx, nEq, nLt, nDLt, sample);
|
|
** CREATE TABLE sqlite_stat4(tbl, idx, nEq, nLt, nDLt, sample);
|
|
**
|
|
** Additional tables might be added in future releases of SQLite.
|
|
** The sqlite_stat2 table is not created or used unless the SQLite version
|
|
** is between 3.6.18 and 3.7.8, inclusive, and unless SQLite is compiled
|
|
** with SQLITE_ENABLE_STAT2. The sqlite_stat2 table is deprecated.
|
|
** The sqlite_stat2 table is superseded by sqlite_stat3, which is only
|
|
** created and used by SQLite versions 3.7.9 through 3.29.0 when
|
|
** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3
|
|
** is a superset of sqlite_stat2 and is also now deprecated. The
|
|
** sqlite_stat4 is an enhanced version of sqlite_stat3 and is only
|
|
** available when compiled with SQLITE_ENABLE_STAT4 and in SQLite
|
|
** versions 3.8.1 and later. STAT4 is the only variant that is still
|
|
** supported.
|
|
**
|
|
** For most applications, sqlite_stat1 provides all the statistics required
|
|
** for the query planner to make good choices.
|
|
**
|
|
** Format of sqlite_stat1:
|
|
**
|
|
** There is normally one row per index, with the index identified by the
|
|
** name in the idx column. The tbl column is the name of the table to
|
|
** which the index belongs. In each such row, the stat column will be
|
|
** a string consisting of a list of integers. The first integer in this
|
|
** list is the number of rows in the index. (This is the same as the
|
|
** number of rows in the table, except for partial indices.) The second
|
|
** integer is the average number of rows in the index that have the same
|
|
** value in the first column of the index. The third integer is the average
|
|
** number of rows in the index that have the same value for the first two
|
|
** columns. The N-th integer (for N>1) is the average number of rows in
|
|
** the index which have the same value for the first N-1 columns. For
|
|
** a K-column index, there will be K+1 integers in the stat column. If
|
|
** the index is unique, then the last integer will be 1.
|
|
**
|
|
** The list of integers in the stat column can optionally be followed
|
|
** by the keyword "unordered". The "unordered" keyword, if it is present,
|
|
** must be separated from the last integer by a single space. If the
|
|
** "unordered" keyword is present, then the query planner assumes that
|
|
** the index is unordered and will not use the index for a range query.
|
|
**
|
|
** If the sqlite_stat1.idx column is NULL, then the sqlite_stat1.stat
|
|
** column contains a single integer which is the (estimated) number of
|
|
** rows in the table identified by sqlite_stat1.tbl.
|
|
**
|
|
** Format of sqlite_stat2:
|
|
**
|
|
** The sqlite_stat2 is only created and is only used if SQLite is compiled
|
|
** with SQLITE_ENABLE_STAT2 and if the SQLite version number is between
|
|
** 3.6.18 and 3.7.8. The "stat2" table contains additional information
|
|
** about the distribution of keys within an index. The index is identified by
|
|
** the "idx" column and the "tbl" column is the name of the table to which
|
|
** the index belongs. There are usually 10 rows in the sqlite_stat2
|
|
** table for each index.
|
|
**
|
|
** The sqlite_stat2 entries for an index that have sampleno between 0 and 9
|
|
** inclusive are samples of the left-most key value in the index taken at
|
|
** evenly spaced points along the index. Let the number of samples be S
|
|
** (10 in the standard build) and let C be the number of rows in the index.
|
|
** Then the sampled rows are given by:
|
|
**
|
|
** rownumber = (i*C*2 + C)/(S*2)
|
|
**
|
|
** For i between 0 and S-1. Conceptually, the index space is divided into
|
|
** S uniform buckets and the samples are the middle row from each bucket.
|
|
**
|
|
** The format for sqlite_stat2 is recorded here for legacy reference. This
|
|
** version of SQLite does not support sqlite_stat2. It neither reads nor
|
|
** writes the sqlite_stat2 table. This version of SQLite only supports
|
|
** sqlite_stat3.
|
|
**
|
|
** Format for sqlite_stat3:
|
|
**
|
|
** The sqlite_stat3 format is a subset of sqlite_stat4. Hence, the
|
|
** sqlite_stat4 format will be described first. Further information
|
|
** about sqlite_stat3 follows the sqlite_stat4 description.
|
|
**
|
|
** Format for sqlite_stat4:
|
|
**
|
|
** As with sqlite_stat2, the sqlite_stat4 table contains histogram data
|
|
** to aid the query planner in choosing good indices based on the values
|
|
** that indexed columns are compared against in the WHERE clauses of
|
|
** queries.
|
|
**
|
|
** The sqlite_stat4 table contains multiple entries for each index.
|
|
** The idx column names the index and the tbl column is the table of the
|
|
** index. If the idx and tbl columns are the same, then the sample is
|
|
** of the INTEGER PRIMARY KEY. The sample column is a blob which is the
|
|
** binary encoding of a key from the index. The nEq column is a
|
|
** list of integers. The first integer is the approximate number
|
|
** of entries in the index whose left-most column exactly matches
|
|
** the left-most column of the sample. The second integer in nEq
|
|
** is the approximate number of entries in the index where the
|
|
** first two columns match the first two columns of the sample.
|
|
** And so forth. nLt is another list of integers that show the approximate
|
|
** number of entries that are strictly less than the sample. The first
|
|
** integer in nLt contains the number of entries in the index where the
|
|
** left-most column is less than the left-most column of the sample.
|
|
** The K-th integer in the nLt entry is the number of index entries
|
|
** where the first K columns are less than the first K columns of the
|
|
** sample. The nDLt column is like nLt except that it contains the
|
|
** number of distinct entries in the index that are less than the
|
|
** sample.
|
|
**
|
|
** There can be an arbitrary number of sqlite_stat4 entries per index.
|
|
** The ANALYZE command will typically generate sqlite_stat4 tables
|
|
** that contain between 10 and 40 samples which are distributed across
|
|
** the key space, though not uniformly, and which include samples with
|
|
** large nEq values.
|
|
**
|
|
** Format for sqlite_stat3 redux:
|
|
**
|
|
** The sqlite_stat3 table is like sqlite_stat4 except that it only
|
|
** looks at the left-most column of the index. The sqlite_stat3.sample
|
|
** column contains the actual value of the left-most column instead
|
|
** of a blob encoding of the complete index key as is found in
|
|
** sqlite_stat4.sample. The nEq, nLt, and nDLt entries of sqlite_stat3
|
|
** all contain just a single integer which is the same as the first
|
|
** integer in the equivalent columns in sqlite_stat4.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_detach_func)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_detachFunc)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_sqlite3Apis)
|
|
*(*uintptr)(unsafe.Add(p, 0)) = __ccgo_fp(Xsqlite3_aggregate_context)
|
|
*(*uintptr)(unsafe.Add(p, 8)) = __ccgo_fp(Xsqlite3_aggregate_count)
|
|
*(*uintptr)(unsafe.Add(p, 16)) = __ccgo_fp(Xsqlite3_bind_blob)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(Xsqlite3_bind_double)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(Xsqlite3_bind_int)
|
|
*(*uintptr)(unsafe.Add(p, 40)) = __ccgo_fp(Xsqlite3_bind_int64)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(Xsqlite3_bind_null)
|
|
*(*uintptr)(unsafe.Add(p, 56)) = __ccgo_fp(Xsqlite3_bind_parameter_count)
|
|
*(*uintptr)(unsafe.Add(p, 64)) = __ccgo_fp(Xsqlite3_bind_parameter_index)
|
|
*(*uintptr)(unsafe.Add(p, 72)) = __ccgo_fp(Xsqlite3_bind_parameter_name)
|
|
*(*uintptr)(unsafe.Add(p, 80)) = __ccgo_fp(Xsqlite3_bind_text)
|
|
*(*uintptr)(unsafe.Add(p, 88)) = __ccgo_fp(Xsqlite3_bind_text16)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(Xsqlite3_bind_value)
|
|
*(*uintptr)(unsafe.Add(p, 104)) = __ccgo_fp(Xsqlite3_busy_handler)
|
|
*(*uintptr)(unsafe.Add(p, 112)) = __ccgo_fp(Xsqlite3_busy_timeout)
|
|
*(*uintptr)(unsafe.Add(p, 120)) = __ccgo_fp(Xsqlite3_changes)
|
|
*(*uintptr)(unsafe.Add(p, 128)) = __ccgo_fp(Xsqlite3_close)
|
|
*(*uintptr)(unsafe.Add(p, 136)) = __ccgo_fp(Xsqlite3_collation_needed)
|
|
*(*uintptr)(unsafe.Add(p, 144)) = __ccgo_fp(Xsqlite3_collation_needed16)
|
|
*(*uintptr)(unsafe.Add(p, 152)) = __ccgo_fp(Xsqlite3_column_blob)
|
|
*(*uintptr)(unsafe.Add(p, 160)) = __ccgo_fp(Xsqlite3_column_bytes)
|
|
*(*uintptr)(unsafe.Add(p, 168)) = __ccgo_fp(Xsqlite3_column_bytes16)
|
|
*(*uintptr)(unsafe.Add(p, 176)) = __ccgo_fp(Xsqlite3_column_count)
|
|
*(*uintptr)(unsafe.Add(p, 184)) = __ccgo_fp(Xsqlite3_column_database_name)
|
|
*(*uintptr)(unsafe.Add(p, 192)) = __ccgo_fp(Xsqlite3_column_database_name16)
|
|
*(*uintptr)(unsafe.Add(p, 200)) = __ccgo_fp(Xsqlite3_column_decltype)
|
|
*(*uintptr)(unsafe.Add(p, 208)) = __ccgo_fp(Xsqlite3_column_decltype16)
|
|
*(*uintptr)(unsafe.Add(p, 216)) = __ccgo_fp(Xsqlite3_column_double)
|
|
*(*uintptr)(unsafe.Add(p, 224)) = __ccgo_fp(Xsqlite3_column_int)
|
|
*(*uintptr)(unsafe.Add(p, 232)) = __ccgo_fp(Xsqlite3_column_int64)
|
|
*(*uintptr)(unsafe.Add(p, 240)) = __ccgo_fp(Xsqlite3_column_name)
|
|
*(*uintptr)(unsafe.Add(p, 248)) = __ccgo_fp(Xsqlite3_column_name16)
|
|
*(*uintptr)(unsafe.Add(p, 256)) = __ccgo_fp(Xsqlite3_column_origin_name)
|
|
*(*uintptr)(unsafe.Add(p, 264)) = __ccgo_fp(Xsqlite3_column_origin_name16)
|
|
*(*uintptr)(unsafe.Add(p, 272)) = __ccgo_fp(Xsqlite3_column_table_name)
|
|
*(*uintptr)(unsafe.Add(p, 280)) = __ccgo_fp(Xsqlite3_column_table_name16)
|
|
*(*uintptr)(unsafe.Add(p, 288)) = __ccgo_fp(Xsqlite3_column_text)
|
|
*(*uintptr)(unsafe.Add(p, 296)) = __ccgo_fp(Xsqlite3_column_text16)
|
|
*(*uintptr)(unsafe.Add(p, 304)) = __ccgo_fp(Xsqlite3_column_type)
|
|
*(*uintptr)(unsafe.Add(p, 312)) = __ccgo_fp(Xsqlite3_column_value)
|
|
*(*uintptr)(unsafe.Add(p, 320)) = __ccgo_fp(Xsqlite3_commit_hook)
|
|
*(*uintptr)(unsafe.Add(p, 328)) = __ccgo_fp(Xsqlite3_complete)
|
|
*(*uintptr)(unsafe.Add(p, 336)) = __ccgo_fp(Xsqlite3_complete16)
|
|
*(*uintptr)(unsafe.Add(p, 344)) = __ccgo_fp(Xsqlite3_create_collation)
|
|
*(*uintptr)(unsafe.Add(p, 352)) = __ccgo_fp(Xsqlite3_create_collation16)
|
|
*(*uintptr)(unsafe.Add(p, 360)) = __ccgo_fp(Xsqlite3_create_function)
|
|
*(*uintptr)(unsafe.Add(p, 368)) = __ccgo_fp(Xsqlite3_create_function16)
|
|
*(*uintptr)(unsafe.Add(p, 376)) = __ccgo_fp(Xsqlite3_create_module)
|
|
*(*uintptr)(unsafe.Add(p, 384)) = __ccgo_fp(Xsqlite3_data_count)
|
|
*(*uintptr)(unsafe.Add(p, 392)) = __ccgo_fp(Xsqlite3_db_handle)
|
|
*(*uintptr)(unsafe.Add(p, 400)) = __ccgo_fp(Xsqlite3_declare_vtab)
|
|
*(*uintptr)(unsafe.Add(p, 408)) = __ccgo_fp(Xsqlite3_enable_shared_cache)
|
|
*(*uintptr)(unsafe.Add(p, 416)) = __ccgo_fp(Xsqlite3_errcode)
|
|
*(*uintptr)(unsafe.Add(p, 424)) = __ccgo_fp(Xsqlite3_errmsg)
|
|
*(*uintptr)(unsafe.Add(p, 432)) = __ccgo_fp(Xsqlite3_errmsg16)
|
|
*(*uintptr)(unsafe.Add(p, 440)) = __ccgo_fp(Xsqlite3_exec)
|
|
*(*uintptr)(unsafe.Add(p, 448)) = __ccgo_fp(Xsqlite3_expired)
|
|
*(*uintptr)(unsafe.Add(p, 456)) = __ccgo_fp(Xsqlite3_finalize)
|
|
*(*uintptr)(unsafe.Add(p, 464)) = __ccgo_fp(Xsqlite3_free)
|
|
*(*uintptr)(unsafe.Add(p, 472)) = __ccgo_fp(Xsqlite3_free_table)
|
|
*(*uintptr)(unsafe.Add(p, 480)) = __ccgo_fp(Xsqlite3_get_autocommit)
|
|
*(*uintptr)(unsafe.Add(p, 488)) = __ccgo_fp(Xsqlite3_get_auxdata)
|
|
*(*uintptr)(unsafe.Add(p, 496)) = __ccgo_fp(Xsqlite3_get_table)
|
|
*(*uintptr)(unsafe.Add(p, 512)) = __ccgo_fp(Xsqlite3_interrupt)
|
|
*(*uintptr)(unsafe.Add(p, 520)) = __ccgo_fp(Xsqlite3_last_insert_rowid)
|
|
*(*uintptr)(unsafe.Add(p, 528)) = __ccgo_fp(Xsqlite3_libversion)
|
|
*(*uintptr)(unsafe.Add(p, 536)) = __ccgo_fp(Xsqlite3_libversion_number)
|
|
*(*uintptr)(unsafe.Add(p, 544)) = __ccgo_fp(Xsqlite3_malloc)
|
|
*(*uintptr)(unsafe.Add(p, 552)) = __ccgo_fp(Xsqlite3_mprintf)
|
|
*(*uintptr)(unsafe.Add(p, 560)) = __ccgo_fp(Xsqlite3_open)
|
|
*(*uintptr)(unsafe.Add(p, 568)) = __ccgo_fp(Xsqlite3_open16)
|
|
*(*uintptr)(unsafe.Add(p, 576)) = __ccgo_fp(Xsqlite3_prepare)
|
|
*(*uintptr)(unsafe.Add(p, 584)) = __ccgo_fp(Xsqlite3_prepare16)
|
|
*(*uintptr)(unsafe.Add(p, 592)) = __ccgo_fp(Xsqlite3_profile)
|
|
*(*uintptr)(unsafe.Add(p, 600)) = __ccgo_fp(Xsqlite3_progress_handler)
|
|
*(*uintptr)(unsafe.Add(p, 608)) = __ccgo_fp(Xsqlite3_realloc)
|
|
*(*uintptr)(unsafe.Add(p, 616)) = __ccgo_fp(Xsqlite3_reset)
|
|
*(*uintptr)(unsafe.Add(p, 624)) = __ccgo_fp(Xsqlite3_result_blob)
|
|
*(*uintptr)(unsafe.Add(p, 632)) = __ccgo_fp(Xsqlite3_result_double)
|
|
*(*uintptr)(unsafe.Add(p, 640)) = __ccgo_fp(Xsqlite3_result_error)
|
|
*(*uintptr)(unsafe.Add(p, 648)) = __ccgo_fp(Xsqlite3_result_error16)
|
|
*(*uintptr)(unsafe.Add(p, 656)) = __ccgo_fp(Xsqlite3_result_int)
|
|
*(*uintptr)(unsafe.Add(p, 664)) = __ccgo_fp(Xsqlite3_result_int64)
|
|
*(*uintptr)(unsafe.Add(p, 672)) = __ccgo_fp(Xsqlite3_result_null)
|
|
*(*uintptr)(unsafe.Add(p, 680)) = __ccgo_fp(Xsqlite3_result_text)
|
|
*(*uintptr)(unsafe.Add(p, 688)) = __ccgo_fp(Xsqlite3_result_text16)
|
|
*(*uintptr)(unsafe.Add(p, 696)) = __ccgo_fp(Xsqlite3_result_text16be)
|
|
*(*uintptr)(unsafe.Add(p, 704)) = __ccgo_fp(Xsqlite3_result_text16le)
|
|
*(*uintptr)(unsafe.Add(p, 712)) = __ccgo_fp(Xsqlite3_result_value)
|
|
*(*uintptr)(unsafe.Add(p, 720)) = __ccgo_fp(Xsqlite3_rollback_hook)
|
|
*(*uintptr)(unsafe.Add(p, 728)) = __ccgo_fp(Xsqlite3_set_authorizer)
|
|
*(*uintptr)(unsafe.Add(p, 736)) = __ccgo_fp(Xsqlite3_set_auxdata)
|
|
*(*uintptr)(unsafe.Add(p, 744)) = __ccgo_fp(Xsqlite3_snprintf)
|
|
*(*uintptr)(unsafe.Add(p, 752)) = __ccgo_fp(Xsqlite3_step)
|
|
*(*uintptr)(unsafe.Add(p, 760)) = __ccgo_fp(Xsqlite3_table_column_metadata)
|
|
*(*uintptr)(unsafe.Add(p, 768)) = __ccgo_fp(Xsqlite3_thread_cleanup)
|
|
*(*uintptr)(unsafe.Add(p, 776)) = __ccgo_fp(Xsqlite3_total_changes)
|
|
*(*uintptr)(unsafe.Add(p, 784)) = __ccgo_fp(Xsqlite3_trace)
|
|
*(*uintptr)(unsafe.Add(p, 792)) = __ccgo_fp(Xsqlite3_transfer_bindings)
|
|
*(*uintptr)(unsafe.Add(p, 800)) = __ccgo_fp(Xsqlite3_update_hook)
|
|
*(*uintptr)(unsafe.Add(p, 808)) = __ccgo_fp(Xsqlite3_user_data)
|
|
*(*uintptr)(unsafe.Add(p, 816)) = __ccgo_fp(Xsqlite3_value_blob)
|
|
*(*uintptr)(unsafe.Add(p, 824)) = __ccgo_fp(Xsqlite3_value_bytes)
|
|
*(*uintptr)(unsafe.Add(p, 832)) = __ccgo_fp(Xsqlite3_value_bytes16)
|
|
*(*uintptr)(unsafe.Add(p, 840)) = __ccgo_fp(Xsqlite3_value_double)
|
|
*(*uintptr)(unsafe.Add(p, 848)) = __ccgo_fp(Xsqlite3_value_int)
|
|
*(*uintptr)(unsafe.Add(p, 856)) = __ccgo_fp(Xsqlite3_value_int64)
|
|
*(*uintptr)(unsafe.Add(p, 864)) = __ccgo_fp(Xsqlite3_value_numeric_type)
|
|
*(*uintptr)(unsafe.Add(p, 872)) = __ccgo_fp(Xsqlite3_value_text)
|
|
*(*uintptr)(unsafe.Add(p, 880)) = __ccgo_fp(Xsqlite3_value_text16)
|
|
*(*uintptr)(unsafe.Add(p, 888)) = __ccgo_fp(Xsqlite3_value_text16be)
|
|
*(*uintptr)(unsafe.Add(p, 896)) = __ccgo_fp(Xsqlite3_value_text16le)
|
|
*(*uintptr)(unsafe.Add(p, 904)) = __ccgo_fp(Xsqlite3_value_type)
|
|
*(*uintptr)(unsafe.Add(p, 912)) = __ccgo_fp(Xsqlite3_vmprintf)
|
|
*(*uintptr)(unsafe.Add(p, 920)) = __ccgo_fp(Xsqlite3_overload_function)
|
|
*(*uintptr)(unsafe.Add(p, 928)) = __ccgo_fp(Xsqlite3_prepare_v2)
|
|
*(*uintptr)(unsafe.Add(p, 936)) = __ccgo_fp(Xsqlite3_prepare16_v2)
|
|
*(*uintptr)(unsafe.Add(p, 944)) = __ccgo_fp(Xsqlite3_clear_bindings)
|
|
*(*uintptr)(unsafe.Add(p, 952)) = __ccgo_fp(Xsqlite3_create_module_v2)
|
|
*(*uintptr)(unsafe.Add(p, 960)) = __ccgo_fp(Xsqlite3_bind_zeroblob)
|
|
*(*uintptr)(unsafe.Add(p, 968)) = __ccgo_fp(Xsqlite3_blob_bytes)
|
|
*(*uintptr)(unsafe.Add(p, 976)) = __ccgo_fp(Xsqlite3_blob_close)
|
|
*(*uintptr)(unsafe.Add(p, 984)) = __ccgo_fp(Xsqlite3_blob_open)
|
|
*(*uintptr)(unsafe.Add(p, 992)) = __ccgo_fp(Xsqlite3_blob_read)
|
|
*(*uintptr)(unsafe.Add(p, 1000)) = __ccgo_fp(Xsqlite3_blob_write)
|
|
*(*uintptr)(unsafe.Add(p, 1008)) = __ccgo_fp(Xsqlite3_create_collation_v2)
|
|
*(*uintptr)(unsafe.Add(p, 1016)) = __ccgo_fp(Xsqlite3_file_control)
|
|
*(*uintptr)(unsafe.Add(p, 1024)) = __ccgo_fp(Xsqlite3_memory_highwater)
|
|
*(*uintptr)(unsafe.Add(p, 1032)) = __ccgo_fp(Xsqlite3_memory_used)
|
|
*(*uintptr)(unsafe.Add(p, 1040)) = __ccgo_fp(Xsqlite3_mutex_alloc)
|
|
*(*uintptr)(unsafe.Add(p, 1048)) = __ccgo_fp(Xsqlite3_mutex_enter)
|
|
*(*uintptr)(unsafe.Add(p, 1056)) = __ccgo_fp(Xsqlite3_mutex_free)
|
|
*(*uintptr)(unsafe.Add(p, 1064)) = __ccgo_fp(Xsqlite3_mutex_leave)
|
|
*(*uintptr)(unsafe.Add(p, 1072)) = __ccgo_fp(Xsqlite3_mutex_try)
|
|
*(*uintptr)(unsafe.Add(p, 1080)) = __ccgo_fp(Xsqlite3_open_v2)
|
|
*(*uintptr)(unsafe.Add(p, 1088)) = __ccgo_fp(Xsqlite3_release_memory)
|
|
*(*uintptr)(unsafe.Add(p, 1096)) = __ccgo_fp(Xsqlite3_result_error_nomem)
|
|
*(*uintptr)(unsafe.Add(p, 1104)) = __ccgo_fp(Xsqlite3_result_error_toobig)
|
|
*(*uintptr)(unsafe.Add(p, 1112)) = __ccgo_fp(Xsqlite3_sleep)
|
|
*(*uintptr)(unsafe.Add(p, 1120)) = __ccgo_fp(Xsqlite3_soft_heap_limit)
|
|
*(*uintptr)(unsafe.Add(p, 1128)) = __ccgo_fp(Xsqlite3_vfs_find)
|
|
*(*uintptr)(unsafe.Add(p, 1136)) = __ccgo_fp(Xsqlite3_vfs_register)
|
|
*(*uintptr)(unsafe.Add(p, 1144)) = __ccgo_fp(Xsqlite3_vfs_unregister)
|
|
*(*uintptr)(unsafe.Add(p, 1152)) = __ccgo_fp(Xsqlite3_threadsafe)
|
|
*(*uintptr)(unsafe.Add(p, 1160)) = __ccgo_fp(Xsqlite3_result_zeroblob)
|
|
*(*uintptr)(unsafe.Add(p, 1168)) = __ccgo_fp(Xsqlite3_result_error_code)
|
|
*(*uintptr)(unsafe.Add(p, 1176)) = __ccgo_fp(Xsqlite3_test_control)
|
|
*(*uintptr)(unsafe.Add(p, 1184)) = __ccgo_fp(Xsqlite3_randomness)
|
|
*(*uintptr)(unsafe.Add(p, 1192)) = __ccgo_fp(Xsqlite3_context_db_handle)
|
|
*(*uintptr)(unsafe.Add(p, 1200)) = __ccgo_fp(Xsqlite3_extended_result_codes)
|
|
*(*uintptr)(unsafe.Add(p, 1208)) = __ccgo_fp(Xsqlite3_limit)
|
|
*(*uintptr)(unsafe.Add(p, 1216)) = __ccgo_fp(Xsqlite3_next_stmt)
|
|
*(*uintptr)(unsafe.Add(p, 1224)) = __ccgo_fp(Xsqlite3_sql)
|
|
*(*uintptr)(unsafe.Add(p, 1232)) = __ccgo_fp(Xsqlite3_status)
|
|
*(*uintptr)(unsafe.Add(p, 1240)) = __ccgo_fp(Xsqlite3_backup_finish)
|
|
*(*uintptr)(unsafe.Add(p, 1248)) = __ccgo_fp(Xsqlite3_backup_init)
|
|
*(*uintptr)(unsafe.Add(p, 1256)) = __ccgo_fp(Xsqlite3_backup_pagecount)
|
|
*(*uintptr)(unsafe.Add(p, 1264)) = __ccgo_fp(Xsqlite3_backup_remaining)
|
|
*(*uintptr)(unsafe.Add(p, 1272)) = __ccgo_fp(Xsqlite3_backup_step)
|
|
*(*uintptr)(unsafe.Add(p, 1280)) = __ccgo_fp(Xsqlite3_compileoption_get)
|
|
*(*uintptr)(unsafe.Add(p, 1288)) = __ccgo_fp(Xsqlite3_compileoption_used)
|
|
*(*uintptr)(unsafe.Add(p, 1296)) = __ccgo_fp(Xsqlite3_create_function_v2)
|
|
*(*uintptr)(unsafe.Add(p, 1304)) = __ccgo_fp(Xsqlite3_db_config)
|
|
*(*uintptr)(unsafe.Add(p, 1312)) = __ccgo_fp(Xsqlite3_db_mutex)
|
|
*(*uintptr)(unsafe.Add(p, 1320)) = __ccgo_fp(Xsqlite3_db_status)
|
|
*(*uintptr)(unsafe.Add(p, 1328)) = __ccgo_fp(Xsqlite3_extended_errcode)
|
|
*(*uintptr)(unsafe.Add(p, 1336)) = __ccgo_fp(Xsqlite3_log)
|
|
*(*uintptr)(unsafe.Add(p, 1344)) = __ccgo_fp(Xsqlite3_soft_heap_limit64)
|
|
*(*uintptr)(unsafe.Add(p, 1352)) = __ccgo_fp(Xsqlite3_sourceid)
|
|
*(*uintptr)(unsafe.Add(p, 1360)) = __ccgo_fp(Xsqlite3_stmt_status)
|
|
*(*uintptr)(unsafe.Add(p, 1368)) = __ccgo_fp(Xsqlite3_strnicmp)
|
|
*(*uintptr)(unsafe.Add(p, 1376)) = __ccgo_fp(Xsqlite3_unlock_notify)
|
|
*(*uintptr)(unsafe.Add(p, 1384)) = __ccgo_fp(Xsqlite3_wal_autocheckpoint)
|
|
*(*uintptr)(unsafe.Add(p, 1392)) = __ccgo_fp(Xsqlite3_wal_checkpoint)
|
|
*(*uintptr)(unsafe.Add(p, 1400)) = __ccgo_fp(Xsqlite3_wal_hook)
|
|
*(*uintptr)(unsafe.Add(p, 1408)) = __ccgo_fp(Xsqlite3_blob_reopen)
|
|
*(*uintptr)(unsafe.Add(p, 1416)) = __ccgo_fp(Xsqlite3_vtab_config)
|
|
*(*uintptr)(unsafe.Add(p, 1424)) = __ccgo_fp(Xsqlite3_vtab_on_conflict)
|
|
*(*uintptr)(unsafe.Add(p, 1432)) = __ccgo_fp(Xsqlite3_close_v2)
|
|
*(*uintptr)(unsafe.Add(p, 1440)) = __ccgo_fp(Xsqlite3_db_filename)
|
|
*(*uintptr)(unsafe.Add(p, 1448)) = __ccgo_fp(Xsqlite3_db_readonly)
|
|
*(*uintptr)(unsafe.Add(p, 1456)) = __ccgo_fp(Xsqlite3_db_release_memory)
|
|
*(*uintptr)(unsafe.Add(p, 1464)) = __ccgo_fp(Xsqlite3_errstr)
|
|
*(*uintptr)(unsafe.Add(p, 1472)) = __ccgo_fp(Xsqlite3_stmt_busy)
|
|
*(*uintptr)(unsafe.Add(p, 1480)) = __ccgo_fp(Xsqlite3_stmt_readonly)
|
|
*(*uintptr)(unsafe.Add(p, 1488)) = __ccgo_fp(Xsqlite3_stricmp)
|
|
*(*uintptr)(unsafe.Add(p, 1496)) = __ccgo_fp(Xsqlite3_uri_boolean)
|
|
*(*uintptr)(unsafe.Add(p, 1504)) = __ccgo_fp(Xsqlite3_uri_int64)
|
|
*(*uintptr)(unsafe.Add(p, 1512)) = __ccgo_fp(Xsqlite3_uri_parameter)
|
|
*(*uintptr)(unsafe.Add(p, 1520)) = __ccgo_fp(Xsqlite3_vsnprintf)
|
|
*(*uintptr)(unsafe.Add(p, 1528)) = __ccgo_fp(Xsqlite3_wal_checkpoint_v2)
|
|
*(*uintptr)(unsafe.Add(p, 1536)) = __ccgo_fp(Xsqlite3_auto_extension)
|
|
*(*uintptr)(unsafe.Add(p, 1544)) = __ccgo_fp(Xsqlite3_bind_blob64)
|
|
*(*uintptr)(unsafe.Add(p, 1552)) = __ccgo_fp(Xsqlite3_bind_text64)
|
|
*(*uintptr)(unsafe.Add(p, 1560)) = __ccgo_fp(Xsqlite3_cancel_auto_extension)
|
|
*(*uintptr)(unsafe.Add(p, 1568)) = __ccgo_fp(Xsqlite3_load_extension)
|
|
*(*uintptr)(unsafe.Add(p, 1576)) = __ccgo_fp(Xsqlite3_malloc64)
|
|
*(*uintptr)(unsafe.Add(p, 1584)) = __ccgo_fp(Xsqlite3_msize)
|
|
*(*uintptr)(unsafe.Add(p, 1592)) = __ccgo_fp(Xsqlite3_realloc64)
|
|
*(*uintptr)(unsafe.Add(p, 1600)) = __ccgo_fp(Xsqlite3_reset_auto_extension)
|
|
*(*uintptr)(unsafe.Add(p, 1608)) = __ccgo_fp(Xsqlite3_result_blob64)
|
|
*(*uintptr)(unsafe.Add(p, 1616)) = __ccgo_fp(Xsqlite3_result_text64)
|
|
*(*uintptr)(unsafe.Add(p, 1624)) = __ccgo_fp(Xsqlite3_strglob)
|
|
*(*uintptr)(unsafe.Add(p, 1632)) = __ccgo_fp(Xsqlite3_value_dup)
|
|
*(*uintptr)(unsafe.Add(p, 1640)) = __ccgo_fp(Xsqlite3_value_free)
|
|
*(*uintptr)(unsafe.Add(p, 1648)) = __ccgo_fp(Xsqlite3_result_zeroblob64)
|
|
*(*uintptr)(unsafe.Add(p, 1656)) = __ccgo_fp(Xsqlite3_bind_zeroblob64)
|
|
*(*uintptr)(unsafe.Add(p, 1664)) = __ccgo_fp(Xsqlite3_value_subtype)
|
|
*(*uintptr)(unsafe.Add(p, 1672)) = __ccgo_fp(Xsqlite3_result_subtype)
|
|
*(*uintptr)(unsafe.Add(p, 1680)) = __ccgo_fp(Xsqlite3_status64)
|
|
*(*uintptr)(unsafe.Add(p, 1688)) = __ccgo_fp(Xsqlite3_strlike)
|
|
*(*uintptr)(unsafe.Add(p, 1696)) = __ccgo_fp(Xsqlite3_db_cacheflush)
|
|
*(*uintptr)(unsafe.Add(p, 1704)) = __ccgo_fp(Xsqlite3_system_errno)
|
|
*(*uintptr)(unsafe.Add(p, 1712)) = __ccgo_fp(Xsqlite3_trace_v2)
|
|
*(*uintptr)(unsafe.Add(p, 1720)) = __ccgo_fp(Xsqlite3_expanded_sql)
|
|
*(*uintptr)(unsafe.Add(p, 1728)) = __ccgo_fp(Xsqlite3_set_last_insert_rowid)
|
|
*(*uintptr)(unsafe.Add(p, 1736)) = __ccgo_fp(Xsqlite3_prepare_v3)
|
|
*(*uintptr)(unsafe.Add(p, 1744)) = __ccgo_fp(Xsqlite3_prepare16_v3)
|
|
*(*uintptr)(unsafe.Add(p, 1752)) = __ccgo_fp(Xsqlite3_bind_pointer)
|
|
*(*uintptr)(unsafe.Add(p, 1760)) = __ccgo_fp(Xsqlite3_result_pointer)
|
|
*(*uintptr)(unsafe.Add(p, 1768)) = __ccgo_fp(Xsqlite3_value_pointer)
|
|
*(*uintptr)(unsafe.Add(p, 1776)) = __ccgo_fp(Xsqlite3_vtab_nochange)
|
|
*(*uintptr)(unsafe.Add(p, 1784)) = __ccgo_fp(Xsqlite3_value_nochange)
|
|
*(*uintptr)(unsafe.Add(p, 1792)) = __ccgo_fp(Xsqlite3_vtab_collation)
|
|
*(*uintptr)(unsafe.Add(p, 1800)) = __ccgo_fp(Xsqlite3_keyword_count)
|
|
*(*uintptr)(unsafe.Add(p, 1808)) = __ccgo_fp(Xsqlite3_keyword_name)
|
|
*(*uintptr)(unsafe.Add(p, 1816)) = __ccgo_fp(Xsqlite3_keyword_check)
|
|
*(*uintptr)(unsafe.Add(p, 1824)) = __ccgo_fp(Xsqlite3_str_new)
|
|
*(*uintptr)(unsafe.Add(p, 1832)) = __ccgo_fp(Xsqlite3_str_finish)
|
|
*(*uintptr)(unsafe.Add(p, 1840)) = __ccgo_fp(Xsqlite3_str_appendf)
|
|
*(*uintptr)(unsafe.Add(p, 1848)) = __ccgo_fp(Xsqlite3_str_vappendf)
|
|
*(*uintptr)(unsafe.Add(p, 1856)) = __ccgo_fp(Xsqlite3_str_append)
|
|
*(*uintptr)(unsafe.Add(p, 1864)) = __ccgo_fp(Xsqlite3_str_appendall)
|
|
*(*uintptr)(unsafe.Add(p, 1872)) = __ccgo_fp(Xsqlite3_str_appendchar)
|
|
*(*uintptr)(unsafe.Add(p, 1880)) = __ccgo_fp(Xsqlite3_str_reset)
|
|
*(*uintptr)(unsafe.Add(p, 1888)) = __ccgo_fp(Xsqlite3_str_errcode)
|
|
*(*uintptr)(unsafe.Add(p, 1896)) = __ccgo_fp(Xsqlite3_str_length)
|
|
*(*uintptr)(unsafe.Add(p, 1904)) = __ccgo_fp(Xsqlite3_str_value)
|
|
*(*uintptr)(unsafe.Add(p, 1912)) = __ccgo_fp(Xsqlite3_create_window_function)
|
|
*(*uintptr)(unsafe.Add(p, 1928)) = __ccgo_fp(Xsqlite3_stmt_isexplain)
|
|
*(*uintptr)(unsafe.Add(p, 1936)) = __ccgo_fp(Xsqlite3_value_frombind)
|
|
*(*uintptr)(unsafe.Add(p, 1944)) = __ccgo_fp(Xsqlite3_drop_modules)
|
|
*(*uintptr)(unsafe.Add(p, 1952)) = __ccgo_fp(Xsqlite3_hard_heap_limit64)
|
|
*(*uintptr)(unsafe.Add(p, 1960)) = __ccgo_fp(Xsqlite3_uri_key)
|
|
*(*uintptr)(unsafe.Add(p, 1968)) = __ccgo_fp(Xsqlite3_filename_database)
|
|
*(*uintptr)(unsafe.Add(p, 1976)) = __ccgo_fp(Xsqlite3_filename_journal)
|
|
*(*uintptr)(unsafe.Add(p, 1984)) = __ccgo_fp(Xsqlite3_filename_wal)
|
|
*(*uintptr)(unsafe.Add(p, 1992)) = __ccgo_fp(Xsqlite3_create_filename)
|
|
*(*uintptr)(unsafe.Add(p, 2000)) = __ccgo_fp(Xsqlite3_free_filename)
|
|
*(*uintptr)(unsafe.Add(p, 2008)) = __ccgo_fp(Xsqlite3_database_file_object)
|
|
*(*uintptr)(unsafe.Add(p, 2016)) = __ccgo_fp(Xsqlite3_txn_state)
|
|
*(*uintptr)(unsafe.Add(p, 2024)) = __ccgo_fp(Xsqlite3_changes64)
|
|
*(*uintptr)(unsafe.Add(p, 2032)) = __ccgo_fp(Xsqlite3_total_changes64)
|
|
*(*uintptr)(unsafe.Add(p, 2040)) = __ccgo_fp(Xsqlite3_autovacuum_pages)
|
|
*(*uintptr)(unsafe.Add(p, 2048)) = __ccgo_fp(Xsqlite3_error_offset)
|
|
*(*uintptr)(unsafe.Add(p, 2056)) = __ccgo_fp(Xsqlite3_vtab_rhs_value)
|
|
*(*uintptr)(unsafe.Add(p, 2064)) = __ccgo_fp(Xsqlite3_vtab_distinct)
|
|
*(*uintptr)(unsafe.Add(p, 2072)) = __ccgo_fp(Xsqlite3_vtab_in)
|
|
*(*uintptr)(unsafe.Add(p, 2080)) = __ccgo_fp(Xsqlite3_vtab_in_first)
|
|
*(*uintptr)(unsafe.Add(p, 2088)) = __ccgo_fp(Xsqlite3_vtab_in_next)
|
|
*(*uintptr)(unsafe.Add(p, 2096)) = __ccgo_fp(Xsqlite3_deserialize)
|
|
*(*uintptr)(unsafe.Add(p, 2104)) = __ccgo_fp(Xsqlite3_serialize)
|
|
*(*uintptr)(unsafe.Add(p, 2112)) = __ccgo_fp(Xsqlite3_db_name)
|
|
*(*uintptr)(unsafe.Add(p, 2120)) = __ccgo_fp(Xsqlite3_value_encoding)
|
|
*(*uintptr)(unsafe.Add(p, 2128)) = __ccgo_fp(Xsqlite3_is_interrupted)
|
|
*(*uintptr)(unsafe.Add(p, 2136)) = __ccgo_fp(Xsqlite3_stmt_explain)
|
|
*(*uintptr)(unsafe.Add(p, 2144)) = __ccgo_fp(Xsqlite3_get_clientdata)
|
|
*(*uintptr)(unsafe.Add(p, 2152)) = __ccgo_fp(Xsqlite3_set_clientdata)
|
|
*(*uintptr)(unsafe.Add(p, 2160)) = __ccgo_fp(Xsqlite3_setlk_timeout)
|
|
*(*uintptr)(unsafe.Add(p, 2168)) = __ccgo_fp(Xsqlite3_set_errmsg)
|
|
*(*uintptr)(unsafe.Add(p, 2176)) = __ccgo_fp(Xsqlite3_db_status64)
|
|
*(*uintptr)(unsafe.Add(p, 2184)) = __ccgo_fp(Xsqlite3_str_truncate)
|
|
*(*uintptr)(unsafe.Add(p, 2192)) = __ccgo_fp(Xsqlite3_str_free)
|
|
}
|
|
|
|
/* True if x is the directory separator character
|
|
*/
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_vfs_template)
|
|
*(*uintptr)(unsafe.Add(p, 40)) = __ccgo_fp(_rbuVfsOpen)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_rbuVfsDelete)
|
|
*(*uintptr)(unsafe.Add(p, 56)) = __ccgo_fp(_rbuVfsAccess)
|
|
*(*uintptr)(unsafe.Add(p, 64)) = __ccgo_fp(_rbuVfsFullPathname)
|
|
*(*uintptr)(unsafe.Add(p, 72)) = __ccgo_fp(_rbuVfsDlOpen)
|
|
*(*uintptr)(unsafe.Add(p, 80)) = __ccgo_fp(_rbuVfsDlError)
|
|
*(*uintptr)(unsafe.Add(p, 88)) = __ccgo_fp(_rbuVfsDlSym)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_rbuVfsDlClose)
|
|
*(*uintptr)(unsafe.Add(p, 104)) = __ccgo_fp(_rbuVfsRandomness)
|
|
*(*uintptr)(unsafe.Add(p, 112)) = __ccgo_fp(_rbuVfsSleep)
|
|
*(*uintptr)(unsafe.Add(p, 120)) = __ccgo_fp(_rbuVfsCurrentTime)
|
|
*(*uintptr)(unsafe.Add(p, 128)) = __ccgo_fp(_rbuVfsGetLastError)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_statGetFuncdef)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_statGet)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_jsonEachModule)
|
|
*(*uintptr)(unsafe.Add(p, 16)) = __ccgo_fp(_jsonEachConnect)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_jsonEachBestIndex)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(_jsonEachDisconnect)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_jsonEachOpen)
|
|
*(*uintptr)(unsafe.Add(p, 56)) = __ccgo_fp(_jsonEachClose)
|
|
*(*uintptr)(unsafe.Add(p, 64)) = __ccgo_fp(_jsonEachFilter)
|
|
*(*uintptr)(unsafe.Add(p, 72)) = __ccgo_fp(_jsonEachNext)
|
|
*(*uintptr)(unsafe.Add(p, 80)) = __ccgo_fp(_jsonEachEof)
|
|
*(*uintptr)(unsafe.Add(p, 88)) = __ccgo_fp(_jsonEachColumn)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_jsonEachRowid)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_memdb_vfs)
|
|
*(*uintptr)(unsafe.Add(p, 40)) = __ccgo_fp(_memdbOpen)
|
|
*(*uintptr)(unsafe.Add(p, 56)) = __ccgo_fp(_memdbAccess)
|
|
*(*uintptr)(unsafe.Add(p, 64)) = __ccgo_fp(_memdbFullPathname)
|
|
*(*uintptr)(unsafe.Add(p, 72)) = __ccgo_fp(_memdbDlOpen)
|
|
*(*uintptr)(unsafe.Add(p, 80)) = __ccgo_fp(_memdbDlError)
|
|
*(*uintptr)(unsafe.Add(p, 88)) = __ccgo_fp(_memdbDlSym)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_memdbDlClose)
|
|
*(*uintptr)(unsafe.Add(p, 104)) = __ccgo_fp(_memdbRandomness)
|
|
*(*uintptr)(unsafe.Add(p, 112)) = __ccgo_fp(_memdbSleep)
|
|
*(*uintptr)(unsafe.Add(p, 128)) = __ccgo_fp(_memdbGetLastError)
|
|
*(*uintptr)(unsafe.Add(p, 136)) = __ccgo_fp(_memdbCurrentTimeInt64)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_aBuiltinFunc)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_versionFunc)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_versionFunc)
|
|
*(*uintptr)(unsafe.Add(p, 168)) = __ccgo_fp(_versionFunc)
|
|
*(*uintptr)(unsafe.Add(p, 240)) = __ccgo_fp(_versionFunc)
|
|
*(*uintptr)(unsafe.Add(p, 312)) = __ccgo_fp(_soundexFunc)
|
|
*(*uintptr)(unsafe.Add(p, 384)) = __ccgo_fp(_loadExt)
|
|
*(*uintptr)(unsafe.Add(p, 456)) = __ccgo_fp(_loadExt)
|
|
*(*uintptr)(unsafe.Add(p, 528)) = __ccgo_fp(_compileoptionusedFunc)
|
|
*(*uintptr)(unsafe.Add(p, 600)) = __ccgo_fp(_compileoptiongetFunc)
|
|
*(*uintptr)(unsafe.Add(p, 672)) = __ccgo_fp(_versionFunc)
|
|
*(*uintptr)(unsafe.Add(p, 744)) = __ccgo_fp(_versionFunc)
|
|
*(*uintptr)(unsafe.Add(p, 816)) = __ccgo_fp(_versionFunc)
|
|
*(*uintptr)(unsafe.Add(p, 888)) = __ccgo_fp(_versionFunc)
|
|
*(*uintptr)(unsafe.Add(p, 960)) = __ccgo_fp(_trimFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1032)) = __ccgo_fp(_trimFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1104)) = __ccgo_fp(_trimFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1176)) = __ccgo_fp(_trimFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1248)) = __ccgo_fp(_trimFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1320)) = __ccgo_fp(_trimFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1392)) = __ccgo_fp(_minmaxFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1464)) = __ccgo_fp(_minmaxStep)
|
|
*(*uintptr)(unsafe.Add(p, 1472)) = __ccgo_fp(_minMaxFinalize)
|
|
*(*uintptr)(unsafe.Add(p, 1480)) = __ccgo_fp(_minMaxValue)
|
|
*(*uintptr)(unsafe.Add(p, 1536)) = __ccgo_fp(_minmaxFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1608)) = __ccgo_fp(_minmaxStep)
|
|
*(*uintptr)(unsafe.Add(p, 1616)) = __ccgo_fp(_minMaxFinalize)
|
|
*(*uintptr)(unsafe.Add(p, 1624)) = __ccgo_fp(_minMaxValue)
|
|
*(*uintptr)(unsafe.Add(p, 1680)) = __ccgo_fp(_typeofFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1752)) = __ccgo_fp(_subtypeFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1824)) = __ccgo_fp(_lengthFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1896)) = __ccgo_fp(_bytelengthFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1968)) = __ccgo_fp(_instrFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2040)) = __ccgo_fp(_printfFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2112)) = __ccgo_fp(_printfFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2184)) = __ccgo_fp(_unicodeFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2256)) = __ccgo_fp(_charFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2328)) = __ccgo_fp(_absFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2400)) = __ccgo_fp(_roundFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2472)) = __ccgo_fp(_roundFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2544)) = __ccgo_fp(_upperFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2616)) = __ccgo_fp(_lowerFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2688)) = __ccgo_fp(_hexFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2760)) = __ccgo_fp(_unhexFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2832)) = __ccgo_fp(_unhexFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2904)) = __ccgo_fp(_concatFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2976)) = __ccgo_fp(_concatwsFunc)
|
|
*(*uintptr)(unsafe.Add(p, 3048)) = __ccgo_fp(_versionFunc)
|
|
*(*uintptr)(unsafe.Add(p, 3120)) = __ccgo_fp(_randomFunc)
|
|
*(*uintptr)(unsafe.Add(p, 3192)) = __ccgo_fp(_randomBlob)
|
|
*(*uintptr)(unsafe.Add(p, 3264)) = __ccgo_fp(_nullifFunc)
|
|
*(*uintptr)(unsafe.Add(p, 3336)) = __ccgo_fp(_versionFunc)
|
|
*(*uintptr)(unsafe.Add(p, 3408)) = __ccgo_fp(_sourceidFunc)
|
|
*(*uintptr)(unsafe.Add(p, 3480)) = __ccgo_fp(_errlogFunc)
|
|
*(*uintptr)(unsafe.Add(p, 3552)) = __ccgo_fp(_unistrFunc)
|
|
*(*uintptr)(unsafe.Add(p, 3624)) = __ccgo_fp(_quoteFunc)
|
|
*(*uintptr)(unsafe.Add(p, 3696)) = __ccgo_fp(_quoteFunc)
|
|
*(*uintptr)(unsafe.Add(p, 3768)) = __ccgo_fp(_last_insert_rowid)
|
|
*(*uintptr)(unsafe.Add(p, 3840)) = __ccgo_fp(_changes)
|
|
*(*uintptr)(unsafe.Add(p, 3912)) = __ccgo_fp(_total_changes)
|
|
*(*uintptr)(unsafe.Add(p, 3984)) = __ccgo_fp(_replaceFunc)
|
|
*(*uintptr)(unsafe.Add(p, 4056)) = __ccgo_fp(_zeroblobFunc)
|
|
*(*uintptr)(unsafe.Add(p, 4128)) = __ccgo_fp(_substrFunc)
|
|
*(*uintptr)(unsafe.Add(p, 4200)) = __ccgo_fp(_substrFunc)
|
|
*(*uintptr)(unsafe.Add(p, 4272)) = __ccgo_fp(_substrFunc)
|
|
*(*uintptr)(unsafe.Add(p, 4344)) = __ccgo_fp(_substrFunc)
|
|
*(*uintptr)(unsafe.Add(p, 4416)) = __ccgo_fp(_sumStep)
|
|
*(*uintptr)(unsafe.Add(p, 4424)) = __ccgo_fp(_sumFinalize)
|
|
*(*uintptr)(unsafe.Add(p, 4432)) = __ccgo_fp(_sumFinalize)
|
|
*(*uintptr)(unsafe.Add(p, 4440)) = __ccgo_fp(_sumInverse)
|
|
*(*uintptr)(unsafe.Add(p, 4488)) = __ccgo_fp(_sumStep)
|
|
*(*uintptr)(unsafe.Add(p, 4496)) = __ccgo_fp(_totalFinalize)
|
|
*(*uintptr)(unsafe.Add(p, 4504)) = __ccgo_fp(_totalFinalize)
|
|
*(*uintptr)(unsafe.Add(p, 4512)) = __ccgo_fp(_sumInverse)
|
|
*(*uintptr)(unsafe.Add(p, 4560)) = __ccgo_fp(_sumStep)
|
|
*(*uintptr)(unsafe.Add(p, 4568)) = __ccgo_fp(_avgFinalize)
|
|
*(*uintptr)(unsafe.Add(p, 4576)) = __ccgo_fp(_avgFinalize)
|
|
*(*uintptr)(unsafe.Add(p, 4584)) = __ccgo_fp(_sumInverse)
|
|
*(*uintptr)(unsafe.Add(p, 4632)) = __ccgo_fp(_countStep)
|
|
*(*uintptr)(unsafe.Add(p, 4640)) = __ccgo_fp(_countFinalize)
|
|
*(*uintptr)(unsafe.Add(p, 4648)) = __ccgo_fp(_countFinalize)
|
|
*(*uintptr)(unsafe.Add(p, 4656)) = __ccgo_fp(_countInverse)
|
|
*(*uintptr)(unsafe.Add(p, 4704)) = __ccgo_fp(_countStep)
|
|
*(*uintptr)(unsafe.Add(p, 4712)) = __ccgo_fp(_countFinalize)
|
|
*(*uintptr)(unsafe.Add(p, 4720)) = __ccgo_fp(_countFinalize)
|
|
*(*uintptr)(unsafe.Add(p, 4728)) = __ccgo_fp(_countInverse)
|
|
*(*uintptr)(unsafe.Add(p, 4776)) = __ccgo_fp(_groupConcatStep)
|
|
*(*uintptr)(unsafe.Add(p, 4784)) = __ccgo_fp(_groupConcatFinalize)
|
|
*(*uintptr)(unsafe.Add(p, 4792)) = __ccgo_fp(_groupConcatValue)
|
|
*(*uintptr)(unsafe.Add(p, 4800)) = __ccgo_fp(_groupConcatInverse)
|
|
*(*uintptr)(unsafe.Add(p, 4848)) = __ccgo_fp(_groupConcatStep)
|
|
*(*uintptr)(unsafe.Add(p, 4856)) = __ccgo_fp(_groupConcatFinalize)
|
|
*(*uintptr)(unsafe.Add(p, 4864)) = __ccgo_fp(_groupConcatValue)
|
|
*(*uintptr)(unsafe.Add(p, 4872)) = __ccgo_fp(_groupConcatInverse)
|
|
*(*uintptr)(unsafe.Add(p, 4920)) = __ccgo_fp(_groupConcatStep)
|
|
*(*uintptr)(unsafe.Add(p, 4928)) = __ccgo_fp(_groupConcatFinalize)
|
|
*(*uintptr)(unsafe.Add(p, 4936)) = __ccgo_fp(_groupConcatValue)
|
|
*(*uintptr)(unsafe.Add(p, 4944)) = __ccgo_fp(_groupConcatInverse)
|
|
*(*uintptr)(unsafe.Add(p, 4992)) = __ccgo_fp(_likeFunc)
|
|
*(*uintptr)(unsafe.Add(p, 5064)) = __ccgo_fp(_likeFunc)
|
|
*(*uintptr)(unsafe.Add(p, 5136)) = __ccgo_fp(_likeFunc)
|
|
*(*uintptr)(unsafe.Add(p, 5192)) = __ccgo_fp(_xCeil)
|
|
*(*uintptr)(unsafe.Add(p, 5208)) = __ccgo_fp(_ceilingFunc)
|
|
*(*uintptr)(unsafe.Add(p, 5264)) = __ccgo_fp(_xCeil)
|
|
*(*uintptr)(unsafe.Add(p, 5280)) = __ccgo_fp(_ceilingFunc)
|
|
*(*uintptr)(unsafe.Add(p, 5336)) = __ccgo_fp(_xFloor)
|
|
*(*uintptr)(unsafe.Add(p, 5352)) = __ccgo_fp(_ceilingFunc)
|
|
*(*uintptr)(unsafe.Add(p, 5408)) = __ccgo_fp(libc.Xtrunc)
|
|
*(*uintptr)(unsafe.Add(p, 5424)) = __ccgo_fp(_ceilingFunc)
|
|
*(*uintptr)(unsafe.Add(p, 5496)) = __ccgo_fp(_logFunc)
|
|
*(*uintptr)(unsafe.Add(p, 5568)) = __ccgo_fp(_logFunc)
|
|
*(*uintptr)(unsafe.Add(p, 5640)) = __ccgo_fp(_logFunc)
|
|
*(*uintptr)(unsafe.Add(p, 5712)) = __ccgo_fp(_logFunc)
|
|
*(*uintptr)(unsafe.Add(p, 5784)) = __ccgo_fp(_logFunc)
|
|
*(*uintptr)(unsafe.Add(p, 5840)) = __ccgo_fp(libc.Xexp)
|
|
*(*uintptr)(unsafe.Add(p, 5856)) = __ccgo_fp(_math1Func)
|
|
*(*uintptr)(unsafe.Add(p, 5912)) = __ccgo_fp(libc.Xpow)
|
|
*(*uintptr)(unsafe.Add(p, 5928)) = __ccgo_fp(_math2Func)
|
|
*(*uintptr)(unsafe.Add(p, 5984)) = __ccgo_fp(libc.Xpow)
|
|
*(*uintptr)(unsafe.Add(p, 6000)) = __ccgo_fp(_math2Func)
|
|
*(*uintptr)(unsafe.Add(p, 6056)) = __ccgo_fp(libc.Xfmod)
|
|
*(*uintptr)(unsafe.Add(p, 6072)) = __ccgo_fp(_math2Func)
|
|
*(*uintptr)(unsafe.Add(p, 6128)) = __ccgo_fp(libc.Xacos)
|
|
*(*uintptr)(unsafe.Add(p, 6144)) = __ccgo_fp(_math1Func)
|
|
*(*uintptr)(unsafe.Add(p, 6200)) = __ccgo_fp(libc.Xasin)
|
|
*(*uintptr)(unsafe.Add(p, 6216)) = __ccgo_fp(_math1Func)
|
|
*(*uintptr)(unsafe.Add(p, 6272)) = __ccgo_fp(libc.Xatan)
|
|
*(*uintptr)(unsafe.Add(p, 6288)) = __ccgo_fp(_math1Func)
|
|
*(*uintptr)(unsafe.Add(p, 6344)) = __ccgo_fp(libc.Xatan2)
|
|
*(*uintptr)(unsafe.Add(p, 6360)) = __ccgo_fp(_math2Func)
|
|
*(*uintptr)(unsafe.Add(p, 6416)) = __ccgo_fp(libc.Xcos)
|
|
*(*uintptr)(unsafe.Add(p, 6432)) = __ccgo_fp(_math1Func)
|
|
*(*uintptr)(unsafe.Add(p, 6488)) = __ccgo_fp(libc.Xsin)
|
|
*(*uintptr)(unsafe.Add(p, 6504)) = __ccgo_fp(_math1Func)
|
|
*(*uintptr)(unsafe.Add(p, 6560)) = __ccgo_fp(libc.Xtan)
|
|
*(*uintptr)(unsafe.Add(p, 6576)) = __ccgo_fp(_math1Func)
|
|
*(*uintptr)(unsafe.Add(p, 6632)) = __ccgo_fp(libc.Xcosh)
|
|
*(*uintptr)(unsafe.Add(p, 6648)) = __ccgo_fp(_math1Func)
|
|
*(*uintptr)(unsafe.Add(p, 6704)) = __ccgo_fp(libc.Xsinh)
|
|
*(*uintptr)(unsafe.Add(p, 6720)) = __ccgo_fp(_math1Func)
|
|
*(*uintptr)(unsafe.Add(p, 6776)) = __ccgo_fp(libc.Xtanh)
|
|
*(*uintptr)(unsafe.Add(p, 6792)) = __ccgo_fp(_math1Func)
|
|
*(*uintptr)(unsafe.Add(p, 6848)) = __ccgo_fp(libc.Xacosh)
|
|
*(*uintptr)(unsafe.Add(p, 6864)) = __ccgo_fp(_math1Func)
|
|
*(*uintptr)(unsafe.Add(p, 6920)) = __ccgo_fp(libc.Xasinh)
|
|
*(*uintptr)(unsafe.Add(p, 6936)) = __ccgo_fp(_math1Func)
|
|
*(*uintptr)(unsafe.Add(p, 6992)) = __ccgo_fp(libc.Xatanh)
|
|
*(*uintptr)(unsafe.Add(p, 7008)) = __ccgo_fp(_math1Func)
|
|
*(*uintptr)(unsafe.Add(p, 7064)) = __ccgo_fp(libc.Xsqrt)
|
|
*(*uintptr)(unsafe.Add(p, 7080)) = __ccgo_fp(_math1Func)
|
|
*(*uintptr)(unsafe.Add(p, 7136)) = __ccgo_fp(_degToRad)
|
|
*(*uintptr)(unsafe.Add(p, 7152)) = __ccgo_fp(_math1Func)
|
|
*(*uintptr)(unsafe.Add(p, 7208)) = __ccgo_fp(_radToDeg)
|
|
*(*uintptr)(unsafe.Add(p, 7224)) = __ccgo_fp(_math1Func)
|
|
*(*uintptr)(unsafe.Add(p, 7296)) = __ccgo_fp(_piFunc)
|
|
*(*uintptr)(unsafe.Add(p, 7368)) = __ccgo_fp(_signFunc)
|
|
*(*uintptr)(unsafe.Add(p, 7440)) = __ccgo_fp(_versionFunc)
|
|
*(*uintptr)(unsafe.Add(p, 7512)) = __ccgo_fp(_versionFunc)
|
|
*(*uintptr)(unsafe.Add(p, 7584)) = __ccgo_fp(_versionFunc)
|
|
}
|
|
|
|
/************** End of func.c ************************************************/
|
|
/************** Begin file fkey.c ********************************************/
|
|
/*
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** This file contains code used by the compiler to add foreign key
|
|
** support to compiled SQL statements.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/*
|
|
** Deferred and Immediate FKs
|
|
** --------------------------
|
|
**
|
|
** Foreign keys in SQLite come in two flavours: deferred and immediate.
|
|
** If an immediate foreign key constraint is violated,
|
|
** SQLITE_CONSTRAINT_FOREIGNKEY is returned and the current
|
|
** statement transaction rolled back. If a
|
|
** deferred foreign key constraint is violated, no action is taken
|
|
** immediately. However if the application attempts to commit the
|
|
** transaction before fixing the constraint violation, the attempt fails.
|
|
**
|
|
** Deferred constraints are implemented using a simple counter associated
|
|
** with the database handle. The counter is set to zero each time a
|
|
** database transaction is opened. Each time a statement is executed
|
|
** that causes a foreign key violation, the counter is incremented. Each
|
|
** time a statement is executed that removes an existing violation from
|
|
** the database, the counter is decremented. When the transaction is
|
|
** committed, the commit fails if the current value of the counter is
|
|
** greater than zero. This scheme has two big drawbacks:
|
|
**
|
|
** * When a commit fails due to a deferred foreign key constraint,
|
|
** there is no way to tell which foreign constraint is not satisfied,
|
|
** or which row it is not satisfied for.
|
|
**
|
|
** * If the database contains foreign key violations when the
|
|
** transaction is opened, this may cause the mechanism to malfunction.
|
|
**
|
|
** Despite these problems, this approach is adopted as it seems simpler
|
|
** than the alternatives.
|
|
**
|
|
** INSERT operations:
|
|
**
|
|
** I.1) For each FK for which the table is the child table, search
|
|
** the parent table for a match. If none is found increment the
|
|
** constraint counter.
|
|
**
|
|
** I.2) For each FK for which the table is the parent table,
|
|
** search the child table for rows that correspond to the new
|
|
** row in the parent table. Decrement the counter for each row
|
|
** found (as the constraint is now satisfied).
|
|
**
|
|
** DELETE operations:
|
|
**
|
|
** D.1) For each FK for which the table is the child table,
|
|
** search the parent table for a row that corresponds to the
|
|
** deleted row in the child table. If such a row is not found,
|
|
** decrement the counter.
|
|
**
|
|
** D.2) For each FK for which the table is the parent table, search
|
|
** the child table for rows that correspond to the deleted row
|
|
** in the parent table. For each found increment the counter.
|
|
**
|
|
** UPDATE operations:
|
|
**
|
|
** An UPDATE command requires that all 4 steps above are taken, but only
|
|
** for FK constraints for which the affected columns are actually
|
|
** modified (values must be compared at runtime).
|
|
**
|
|
** Note that I.1 and D.1 are very similar operations, as are I.2 and D.2.
|
|
** This simplifies the implementation a bit.
|
|
**
|
|
** For the purposes of immediate FK constraints, the OR REPLACE conflict
|
|
** resolution is considered to delete rows before the new row is inserted.
|
|
** If a delete caused by OR REPLACE violates an FK constraint, an exception
|
|
** is thrown, even if the FK constraint would be satisfied after the new
|
|
** row is inserted.
|
|
**
|
|
** Immediate constraints are usually handled similarly. The only difference
|
|
** is that the counter used is stored as part of each individual statement
|
|
** object (struct Vdbe). If, after the statement has run, its immediate
|
|
** constraint counter is greater than zero,
|
|
** it returns SQLITE_CONSTRAINT_FOREIGNKEY
|
|
** and the statement transaction is rolled back. An exception is an INSERT
|
|
** statement that inserts a single row only (no triggers). In this case,
|
|
** instead of using a counter, an exception is thrown immediately if the
|
|
** INSERT violates a foreign key constraint. This is necessary as such
|
|
** an INSERT does not open a statement transaction.
|
|
**
|
|
** TODO: How should dropping a table be handled? How should renaming a
|
|
** table be handled?
|
|
**
|
|
**
|
|
** Query API Notes
|
|
** ---------------
|
|
**
|
|
** Before coding an UPDATE or DELETE row operation, the code-generator
|
|
** for those two operations needs to know whether or not the operation
|
|
** requires any FK processing and, if so, which columns of the original
|
|
** row are required by the FK processing VDBE code (i.e. if FKs were
|
|
** implemented using triggers, which of the old.* columns would be
|
|
** accessed). No information is required by the code-generator before
|
|
** coding an INSERT operation. The functions used by the UPDATE/DELETE
|
|
** generation code to query for this information are:
|
|
**
|
|
** sqlite3FkRequired() - Test to see if FK processing is required.
|
|
** sqlite3FkOldmask() - Query for the set of required old.* columns.
|
|
**
|
|
**
|
|
** Externally accessible module functions
|
|
** --------------------------------------
|
|
**
|
|
** sqlite3FkCheck() - Check for foreign key violations.
|
|
** sqlite3FkActions() - Code triggers for ON UPDATE/ON DELETE actions.
|
|
** sqlite3FkDelete() - Delete an FKey structure.
|
|
*/
|
|
|
|
/*
|
|
** VDBE Calling Convention
|
|
** -----------------------
|
|
**
|
|
** Example:
|
|
**
|
|
** For the following INSERT statement:
|
|
**
|
|
** CREATE TABLE t1(a, b INTEGER PRIMARY KEY, c);
|
|
** INSERT INTO t1 VALUES(1, 2, 3.1);
|
|
**
|
|
** Register (x): 2 (type integer)
|
|
** Register (x+1): 1 (type integer)
|
|
** Register (x+2): NULL (type NULL)
|
|
** Register (x+3): 3.1 (type real)
|
|
*/
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_fts5Mod)
|
|
*(*uintptr)(unsafe.Add(p, 8)) = __ccgo_fp(_fts5CreateMethod)
|
|
*(*uintptr)(unsafe.Add(p, 16)) = __ccgo_fp(_fts5ConnectMethod)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_fts5BestIndexMethod)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(_fts5DisconnectMethod)
|
|
*(*uintptr)(unsafe.Add(p, 40)) = __ccgo_fp(_fts5DestroyMethod)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_fts5OpenMethod)
|
|
*(*uintptr)(unsafe.Add(p, 56)) = __ccgo_fp(_fts5CloseMethod)
|
|
*(*uintptr)(unsafe.Add(p, 64)) = __ccgo_fp(_fts5FilterMethod)
|
|
*(*uintptr)(unsafe.Add(p, 72)) = __ccgo_fp(_fts5NextMethod)
|
|
*(*uintptr)(unsafe.Add(p, 80)) = __ccgo_fp(_fts5EofMethod)
|
|
*(*uintptr)(unsafe.Add(p, 88)) = __ccgo_fp(_fts5ColumnMethod)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_fts5RowidMethod)
|
|
*(*uintptr)(unsafe.Add(p, 104)) = __ccgo_fp(_fts5UpdateMethod)
|
|
*(*uintptr)(unsafe.Add(p, 112)) = __ccgo_fp(_fts5BeginMethod)
|
|
*(*uintptr)(unsafe.Add(p, 120)) = __ccgo_fp(_fts5SyncMethod)
|
|
*(*uintptr)(unsafe.Add(p, 128)) = __ccgo_fp(_fts5CommitMethod)
|
|
*(*uintptr)(unsafe.Add(p, 136)) = __ccgo_fp(_fts5RollbackMethod)
|
|
*(*uintptr)(unsafe.Add(p, 144)) = __ccgo_fp(_fts5FindFunctionMethod)
|
|
*(*uintptr)(unsafe.Add(p, 152)) = __ccgo_fp(_fts5RenameMethod)
|
|
*(*uintptr)(unsafe.Add(p, 160)) = __ccgo_fp(_fts5SavepointMethod)
|
|
*(*uintptr)(unsafe.Add(p, 168)) = __ccgo_fp(_fts5ReleaseMethod)
|
|
*(*uintptr)(unsafe.Add(p, 176)) = __ccgo_fp(_fts5RollbackToMethod)
|
|
*(*uintptr)(unsafe.Add(p, 184)) = __ccgo_fp(_fts5ShadowName)
|
|
*(*uintptr)(unsafe.Add(p, 192)) = __ccgo_fp(_fts5IntegrityMethod)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_rbuvfs_io_methods1)
|
|
*(*uintptr)(unsafe.Add(p, 8)) = __ccgo_fp(_rbuVfsClose)
|
|
*(*uintptr)(unsafe.Add(p, 16)) = __ccgo_fp(_rbuVfsRead)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_rbuVfsWrite)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(_rbuVfsTruncate)
|
|
*(*uintptr)(unsafe.Add(p, 40)) = __ccgo_fp(_rbuVfsSync)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_rbuVfsFileSize)
|
|
*(*uintptr)(unsafe.Add(p, 56)) = __ccgo_fp(_rbuVfsLock)
|
|
*(*uintptr)(unsafe.Add(p, 64)) = __ccgo_fp(_rbuVfsUnlock)
|
|
*(*uintptr)(unsafe.Add(p, 72)) = __ccgo_fp(_rbuVfsCheckReservedLock)
|
|
*(*uintptr)(unsafe.Add(p, 80)) = __ccgo_fp(_rbuVfsFileControl)
|
|
*(*uintptr)(unsafe.Add(p, 88)) = __ccgo_fp(_rbuVfsSectorSize)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_rbuVfsDeviceCharacteristics)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_rbuvfs_io_methods)
|
|
*(*uintptr)(unsafe.Add(p, 8)) = __ccgo_fp(_rbuVfsClose)
|
|
*(*uintptr)(unsafe.Add(p, 16)) = __ccgo_fp(_rbuVfsRead)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_rbuVfsWrite)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(_rbuVfsTruncate)
|
|
*(*uintptr)(unsafe.Add(p, 40)) = __ccgo_fp(_rbuVfsSync)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_rbuVfsFileSize)
|
|
*(*uintptr)(unsafe.Add(p, 56)) = __ccgo_fp(_rbuVfsLock)
|
|
*(*uintptr)(unsafe.Add(p, 64)) = __ccgo_fp(_rbuVfsUnlock)
|
|
*(*uintptr)(unsafe.Add(p, 72)) = __ccgo_fp(_rbuVfsCheckReservedLock)
|
|
*(*uintptr)(unsafe.Add(p, 80)) = __ccgo_fp(_rbuVfsFileControl)
|
|
*(*uintptr)(unsafe.Add(p, 88)) = __ccgo_fp(_rbuVfsSectorSize)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_rbuVfsDeviceCharacteristics)
|
|
*(*uintptr)(unsafe.Add(p, 104)) = __ccgo_fp(_rbuVfsShmMap)
|
|
*(*uintptr)(unsafe.Add(p, 112)) = __ccgo_fp(_rbuVfsShmLock)
|
|
*(*uintptr)(unsafe.Add(p, 120)) = __ccgo_fp(_rbuVfsShmBarrier)
|
|
*(*uintptr)(unsafe.Add(p, 128)) = __ccgo_fp(_rbuVfsShmUnmap)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_aWindowFuncs)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_row_numberStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(_row_numberValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 40)) = __ccgo_fp(_row_numberValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_noopStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_dense_rankStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 104)) = __ccgo_fp(_dense_rankValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 112)) = __ccgo_fp(_dense_rankValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 120)) = __ccgo_fp(_noopStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 168)) = __ccgo_fp(_rankStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 176)) = __ccgo_fp(_rankValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 184)) = __ccgo_fp(_rankValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 192)) = __ccgo_fp(_noopStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 240)) = __ccgo_fp(_percent_rankStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 248)) = __ccgo_fp(_percent_rankValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 256)) = __ccgo_fp(_percent_rankValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 264)) = __ccgo_fp(_percent_rankInvFunc)
|
|
*(*uintptr)(unsafe.Add(p, 312)) = __ccgo_fp(_cume_distStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 320)) = __ccgo_fp(_cume_distValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 328)) = __ccgo_fp(_cume_distValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 336)) = __ccgo_fp(_cume_distInvFunc)
|
|
*(*uintptr)(unsafe.Add(p, 384)) = __ccgo_fp(_ntileStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 392)) = __ccgo_fp(_ntileValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 400)) = __ccgo_fp(_ntileValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 408)) = __ccgo_fp(_ntileInvFunc)
|
|
*(*uintptr)(unsafe.Add(p, 456)) = __ccgo_fp(_last_valueStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 464)) = __ccgo_fp(_last_valueFinalizeFunc)
|
|
*(*uintptr)(unsafe.Add(p, 472)) = __ccgo_fp(_last_valueValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 480)) = __ccgo_fp(_last_valueInvFunc)
|
|
*(*uintptr)(unsafe.Add(p, 528)) = __ccgo_fp(_nth_valueStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 536)) = __ccgo_fp(_nth_valueFinalizeFunc)
|
|
*(*uintptr)(unsafe.Add(p, 544)) = __ccgo_fp(_noopValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 552)) = __ccgo_fp(_noopStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 600)) = __ccgo_fp(_first_valueStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 608)) = __ccgo_fp(_first_valueFinalizeFunc)
|
|
*(*uintptr)(unsafe.Add(p, 616)) = __ccgo_fp(_noopValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 624)) = __ccgo_fp(_noopStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 672)) = __ccgo_fp(_noopStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 680)) = __ccgo_fp(_noopValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 688)) = __ccgo_fp(_noopValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 696)) = __ccgo_fp(_noopStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 744)) = __ccgo_fp(_noopStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 752)) = __ccgo_fp(_noopValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 760)) = __ccgo_fp(_noopValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 768)) = __ccgo_fp(_noopStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 816)) = __ccgo_fp(_noopStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 824)) = __ccgo_fp(_noopValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 832)) = __ccgo_fp(_noopValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 840)) = __ccgo_fp(_noopStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 888)) = __ccgo_fp(_noopStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 896)) = __ccgo_fp(_noopValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 904)) = __ccgo_fp(_noopValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 912)) = __ccgo_fp(_noopStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 960)) = __ccgo_fp(_noopStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 968)) = __ccgo_fp(_noopValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 976)) = __ccgo_fp(_noopValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 984)) = __ccgo_fp(_noopStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1032)) = __ccgo_fp(_noopStepFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1040)) = __ccgo_fp(_noopValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1048)) = __ccgo_fp(_noopValueFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1056)) = __ccgo_fp(_noopStepFunc)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_rtreeModule)
|
|
*(*uintptr)(unsafe.Add(p, 8)) = __ccgo_fp(_rtreeCreate)
|
|
*(*uintptr)(unsafe.Add(p, 16)) = __ccgo_fp(_rtreeConnect)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_rtreeBestIndex)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(_rtreeDisconnect)
|
|
*(*uintptr)(unsafe.Add(p, 40)) = __ccgo_fp(_rtreeDestroy)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_rtreeOpen)
|
|
*(*uintptr)(unsafe.Add(p, 56)) = __ccgo_fp(_rtreeClose)
|
|
*(*uintptr)(unsafe.Add(p, 64)) = __ccgo_fp(_rtreeFilter)
|
|
*(*uintptr)(unsafe.Add(p, 72)) = __ccgo_fp(_rtreeNext)
|
|
*(*uintptr)(unsafe.Add(p, 80)) = __ccgo_fp(_rtreeEof)
|
|
*(*uintptr)(unsafe.Add(p, 88)) = __ccgo_fp(_rtreeColumn)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_rtreeRowid)
|
|
*(*uintptr)(unsafe.Add(p, 104)) = __ccgo_fp(_rtreeUpdate)
|
|
*(*uintptr)(unsafe.Add(p, 112)) = __ccgo_fp(_rtreeBeginTransaction)
|
|
*(*uintptr)(unsafe.Add(p, 120)) = __ccgo_fp(_rtreeEndTransaction)
|
|
*(*uintptr)(unsafe.Add(p, 128)) = __ccgo_fp(_rtreeEndTransaction)
|
|
*(*uintptr)(unsafe.Add(p, 136)) = __ccgo_fp(_rtreeRollback)
|
|
*(*uintptr)(unsafe.Add(p, 152)) = __ccgo_fp(_rtreeRename)
|
|
*(*uintptr)(unsafe.Add(p, 160)) = __ccgo_fp(_rtreeSavepoint)
|
|
*(*uintptr)(unsafe.Add(p, 184)) = __ccgo_fp(_rtreeShadowName)
|
|
*(*uintptr)(unsafe.Add(p, 192)) = __ccgo_fp(_rtreeIntegrity)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_MemJournalMethods)
|
|
*(*uintptr)(unsafe.Add(p, 8)) = __ccgo_fp(_memjrnlClose)
|
|
*(*uintptr)(unsafe.Add(p, 16)) = __ccgo_fp(_memjrnlRead)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_memjrnlWrite)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(_memjrnlTruncate)
|
|
*(*uintptr)(unsafe.Add(p, 40)) = __ccgo_fp(_memjrnlSync)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_memjrnlFileSize)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_defaultMethods1)
|
|
*(*uintptr)(unsafe.Add(p, 16)) = __ccgo_fp(_pcache1Init)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_pcache1Shutdown)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(_pcache1Create)
|
|
*(*uintptr)(unsafe.Add(p, 40)) = __ccgo_fp(_pcache1Cachesize)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_pcache1Pagecount)
|
|
*(*uintptr)(unsafe.Add(p, 56)) = __ccgo_fp(_pcache1Fetch)
|
|
*(*uintptr)(unsafe.Add(p, 64)) = __ccgo_fp(_pcache1Unpin)
|
|
*(*uintptr)(unsafe.Add(p, 72)) = __ccgo_fp(_pcache1Rekey)
|
|
*(*uintptr)(unsafe.Add(p, 80)) = __ccgo_fp(_pcache1Truncate)
|
|
*(*uintptr)(unsafe.Add(p, 88)) = __ccgo_fp(_pcache1Destroy)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_pcache1Shrink)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_dbstat_module)
|
|
*(*uintptr)(unsafe.Add(p, 8)) = __ccgo_fp(_statConnect)
|
|
*(*uintptr)(unsafe.Add(p, 16)) = __ccgo_fp(_statConnect)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_statBestIndex)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(_statDisconnect)
|
|
*(*uintptr)(unsafe.Add(p, 40)) = __ccgo_fp(_statDisconnect)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_statOpen)
|
|
*(*uintptr)(unsafe.Add(p, 56)) = __ccgo_fp(_statClose)
|
|
*(*uintptr)(unsafe.Add(p, 64)) = __ccgo_fp(_statFilter)
|
|
*(*uintptr)(unsafe.Add(p, 72)) = __ccgo_fp(_statNext)
|
|
*(*uintptr)(unsafe.Add(p, 80)) = __ccgo_fp(_statEof)
|
|
*(*uintptr)(unsafe.Add(p, 88)) = __ccgo_fp(_statColumn)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_statRowid)
|
|
}
|
|
|
|
/************** End of dbstat.c **********************************************/
|
|
/************** Begin file dbpage.c ******************************************/
|
|
/*
|
|
** 2017-10-11
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
******************************************************************************
|
|
**
|
|
** This file contains an implementation of the "sqlite_dbpage" virtual table.
|
|
**
|
|
** The sqlite_dbpage virtual table is used to read or write whole raw
|
|
** pages of the database file. The pager interface is used so that
|
|
** uncommitted changes and changes recorded in the WAL file are correctly
|
|
** retrieved.
|
|
**
|
|
** Usage example:
|
|
**
|
|
** SELECT data FROM sqlite_dbpage('aux1') WHERE pgno=123;
|
|
**
|
|
** This is an eponymous virtual table so it does not need to be created before
|
|
** use. The optional argument to the sqlite_dbpage() table name is the
|
|
** schema for the database file that is to be read. The default schema is
|
|
** "main".
|
|
**
|
|
** The data field of sqlite_dbpage table can be updated. The new
|
|
** value must be a BLOB which is the correct page size, otherwise the
|
|
** update fails. INSERT operations also work, and operate as if they
|
|
** where REPLACE. The size of the database can be extended by INSERT-ing
|
|
** new pages on the end.
|
|
**
|
|
** Rows may not be deleted. However, doing an INSERT to page number N
|
|
** with NULL page data causes the N-th page and all subsequent pages to be
|
|
** deleted and the database to be truncated.
|
|
*/
|
|
|
|
/* #include "sqliteInt.h" ** Requires access to internal data structures ** */
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_aDateTimeFuncs)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_juliandayFunc)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_unixepochFunc)
|
|
*(*uintptr)(unsafe.Add(p, 168)) = __ccgo_fp(_dateFunc)
|
|
*(*uintptr)(unsafe.Add(p, 240)) = __ccgo_fp(_timeFunc)
|
|
*(*uintptr)(unsafe.Add(p, 312)) = __ccgo_fp(_datetimeFunc)
|
|
*(*uintptr)(unsafe.Add(p, 384)) = __ccgo_fp(_strftimeFunc)
|
|
*(*uintptr)(unsafe.Add(p, 456)) = __ccgo_fp(_timediffFunc)
|
|
*(*uintptr)(unsafe.Add(p, 528)) = __ccgo_fp(_ctimeFunc)
|
|
*(*uintptr)(unsafe.Add(p, 600)) = __ccgo_fp(_ctimestampFunc)
|
|
*(*uintptr)(unsafe.Add(p, 672)) = __ccgo_fp(_cdateFunc)
|
|
}
|
|
|
|
/************** End of date.c ************************************************/
|
|
/************** Begin file os.c **********************************************/
|
|
/*
|
|
** 2005 November 29
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
******************************************************************************
|
|
**
|
|
** This file contains OS interface code that is common to all
|
|
** architectures.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/*
|
|
** If we compile with the SQLITE_TEST macro set, then the following block
|
|
** of code will give us the ability to simulate a disk I/O error. This
|
|
** is used for testing the I/O recovery logic.
|
|
*/
|
|
|
|
/*
|
|
** When testing, also keep a count of the number of open files.
|
|
*/
|
|
|
|
/*
|
|
** The default SQLite sqlite3_vfs implementations do not allocate
|
|
** memory (actually, os_unix.c allocates a small amount of memory
|
|
** from within OsOpen()), but some third-party implementations may.
|
|
** So we test the effects of a malloc() failing and the sqlite3OsXXX()
|
|
** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro.
|
|
**
|
|
** The following functions are instrumented for malloc() failure
|
|
** testing:
|
|
**
|
|
** sqlite3OsRead()
|
|
** sqlite3OsWrite()
|
|
** sqlite3OsSync()
|
|
** sqlite3OsFileSize()
|
|
** sqlite3OsLock()
|
|
** sqlite3OsCheckReservedLock()
|
|
** sqlite3OsFileControl()
|
|
** sqlite3OsShmMap()
|
|
** sqlite3OsOpen()
|
|
** sqlite3OsDelete()
|
|
** sqlite3OsAccess()
|
|
** sqlite3OsFullPathname()
|
|
**
|
|
*/
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_pragmaVtabModule)
|
|
*(*uintptr)(unsafe.Add(p, 16)) = __ccgo_fp(_pragmaVtabConnect)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_pragmaVtabBestIndex)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(_pragmaVtabDisconnect)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_pragmaVtabOpen)
|
|
*(*uintptr)(unsafe.Add(p, 56)) = __ccgo_fp(_pragmaVtabClose)
|
|
*(*uintptr)(unsafe.Add(p, 64)) = __ccgo_fp(_pragmaVtabFilter)
|
|
*(*uintptr)(unsafe.Add(p, 72)) = __ccgo_fp(_pragmaVtabNext)
|
|
*(*uintptr)(unsafe.Add(p, 80)) = __ccgo_fp(_pragmaVtabEof)
|
|
*(*uintptr)(unsafe.Add(p, 88)) = __ccgo_fp(_pragmaVtabColumn)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_pragmaVtabRowid)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_geopolyModule)
|
|
*(*uintptr)(unsafe.Add(p, 8)) = __ccgo_fp(_geopolyCreate)
|
|
*(*uintptr)(unsafe.Add(p, 16)) = __ccgo_fp(_geopolyConnect)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_geopolyBestIndex)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(_rtreeDisconnect)
|
|
*(*uintptr)(unsafe.Add(p, 40)) = __ccgo_fp(_rtreeDestroy)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_rtreeOpen)
|
|
*(*uintptr)(unsafe.Add(p, 56)) = __ccgo_fp(_rtreeClose)
|
|
*(*uintptr)(unsafe.Add(p, 64)) = __ccgo_fp(_geopolyFilter)
|
|
*(*uintptr)(unsafe.Add(p, 72)) = __ccgo_fp(_rtreeNext)
|
|
*(*uintptr)(unsafe.Add(p, 80)) = __ccgo_fp(_rtreeEof)
|
|
*(*uintptr)(unsafe.Add(p, 88)) = __ccgo_fp(_geopolyColumn)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_rtreeRowid)
|
|
*(*uintptr)(unsafe.Add(p, 104)) = __ccgo_fp(_geopolyUpdate)
|
|
*(*uintptr)(unsafe.Add(p, 112)) = __ccgo_fp(_rtreeBeginTransaction)
|
|
*(*uintptr)(unsafe.Add(p, 120)) = __ccgo_fp(_rtreeEndTransaction)
|
|
*(*uintptr)(unsafe.Add(p, 128)) = __ccgo_fp(_rtreeEndTransaction)
|
|
*(*uintptr)(unsafe.Add(p, 136)) = __ccgo_fp(_rtreeEndTransaction)
|
|
*(*uintptr)(unsafe.Add(p, 144)) = __ccgo_fp(_geopolyFindFunction)
|
|
*(*uintptr)(unsafe.Add(p, 152)) = __ccgo_fp(_rtreeRename)
|
|
*(*uintptr)(unsafe.Add(p, 160)) = __ccgo_fp(_rtreeSavepoint)
|
|
*(*uintptr)(unsafe.Add(p, 184)) = __ccgo_fp(_rtreeShadowName)
|
|
*(*uintptr)(unsafe.Add(p, 192)) = __ccgo_fp(_rtreeIntegrity)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_dbpage_module)
|
|
*(*uintptr)(unsafe.Add(p, 8)) = __ccgo_fp(_dbpageConnect)
|
|
*(*uintptr)(unsafe.Add(p, 16)) = __ccgo_fp(_dbpageConnect)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_dbpageBestIndex)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(_dbpageDisconnect)
|
|
*(*uintptr)(unsafe.Add(p, 40)) = __ccgo_fp(_dbpageDisconnect)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_dbpageOpen)
|
|
*(*uintptr)(unsafe.Add(p, 56)) = __ccgo_fp(_dbpageClose)
|
|
*(*uintptr)(unsafe.Add(p, 64)) = __ccgo_fp(_dbpageFilter)
|
|
*(*uintptr)(unsafe.Add(p, 72)) = __ccgo_fp(_dbpageNext)
|
|
*(*uintptr)(unsafe.Add(p, 80)) = __ccgo_fp(_dbpageEof)
|
|
*(*uintptr)(unsafe.Add(p, 88)) = __ccgo_fp(_dbpageColumn)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_dbpageRowid)
|
|
*(*uintptr)(unsafe.Add(p, 104)) = __ccgo_fp(_dbpageUpdate)
|
|
*(*uintptr)(unsafe.Add(p, 112)) = __ccgo_fp(_dbpageBegin)
|
|
*(*uintptr)(unsafe.Add(p, 120)) = __ccgo_fp(_dbpageSync)
|
|
*(*uintptr)(unsafe.Add(p, 176)) = __ccgo_fp(_dbpageRollbackTo)
|
|
}
|
|
|
|
/************** End of dbpage.c **********************************************/
|
|
/************** Begin file carray.c ******************************************/
|
|
/*
|
|
** 2016-06-29
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
**
|
|
** This file implements a table-valued-function that
|
|
** returns the values in a C-language array.
|
|
** Examples:
|
|
**
|
|
** SELECT * FROM carray($ptr,5)
|
|
**
|
|
** The query above returns 5 integers contained in a C-language array
|
|
** at the address $ptr. $ptr is a pointer to the array of integers.
|
|
** The pointer value must be assigned to $ptr using the
|
|
** sqlite3_bind_pointer() interface with a pointer type of "carray".
|
|
** For example:
|
|
**
|
|
** static int aX[] = { 53, 9, 17, 2231, 4, 99 };
|
|
** int i = sqlite3_bind_parameter_index(pStmt, "$ptr");
|
|
** sqlite3_bind_pointer(pStmt, i, aX, "carray", 0);
|
|
**
|
|
** There is an optional third parameter to determine the datatype of
|
|
** the C-language array. Allowed values of the third parameter are
|
|
** 'int32', 'int64', 'double', 'char*', 'struct iovec'. Example:
|
|
**
|
|
** SELECT * FROM carray($ptr,10,'char*');
|
|
**
|
|
** The default value of the third parameter is 'int32'.
|
|
**
|
|
** HOW IT WORKS
|
|
**
|
|
** The carray "function" is really a virtual table with the
|
|
** following schema:
|
|
**
|
|
** CREATE TABLE carray(
|
|
** value,
|
|
** pointer HIDDEN,
|
|
** count HIDDEN,
|
|
** ctype TEXT HIDDEN
|
|
** );
|
|
**
|
|
** If the hidden columns "pointer" and "count" are unconstrained, then
|
|
** the virtual table has no rows. Otherwise, the virtual table interprets
|
|
** the integer value of "pointer" as a pointer to the array and "count"
|
|
** as the number of elements in the array. The virtual table steps through
|
|
** the array, element by element.
|
|
*/
|
|
|
|
/************** End of carray.c **********************************************/
|
|
/************** Begin file sqlite3session.c **********************************/
|
|
|
|
/* #include "sqlite3session.h" */
|
|
/* #include <assert.h> */
|
|
/* #include <string.h> */
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_aJsonFunc)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_jsonRemoveFunc)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_jsonRemoveFunc)
|
|
*(*uintptr)(unsafe.Add(p, 168)) = __ccgo_fp(_jsonArrayFunc)
|
|
*(*uintptr)(unsafe.Add(p, 240)) = __ccgo_fp(_jsonArrayFunc)
|
|
*(*uintptr)(unsafe.Add(p, 312)) = __ccgo_fp(_jsonSetFunc)
|
|
*(*uintptr)(unsafe.Add(p, 384)) = __ccgo_fp(_jsonSetFunc)
|
|
*(*uintptr)(unsafe.Add(p, 456)) = __ccgo_fp(_jsonArrayLengthFunc)
|
|
*(*uintptr)(unsafe.Add(p, 528)) = __ccgo_fp(_jsonArrayLengthFunc)
|
|
*(*uintptr)(unsafe.Add(p, 600)) = __ccgo_fp(_jsonErrorFunc)
|
|
*(*uintptr)(unsafe.Add(p, 672)) = __ccgo_fp(_jsonExtractFunc)
|
|
*(*uintptr)(unsafe.Add(p, 744)) = __ccgo_fp(_jsonExtractFunc)
|
|
*(*uintptr)(unsafe.Add(p, 816)) = __ccgo_fp(_jsonExtractFunc)
|
|
*(*uintptr)(unsafe.Add(p, 888)) = __ccgo_fp(_jsonExtractFunc)
|
|
*(*uintptr)(unsafe.Add(p, 960)) = __ccgo_fp(_jsonSetFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1032)) = __ccgo_fp(_jsonSetFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1104)) = __ccgo_fp(_jsonObjectFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1176)) = __ccgo_fp(_jsonObjectFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1248)) = __ccgo_fp(_jsonPatchFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1320)) = __ccgo_fp(_jsonPatchFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1392)) = __ccgo_fp(_jsonPrettyFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1464)) = __ccgo_fp(_jsonPrettyFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1536)) = __ccgo_fp(_jsonQuoteFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1608)) = __ccgo_fp(_jsonRemoveFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1680)) = __ccgo_fp(_jsonRemoveFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1752)) = __ccgo_fp(_jsonReplaceFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1824)) = __ccgo_fp(_jsonReplaceFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1896)) = __ccgo_fp(_jsonSetFunc)
|
|
*(*uintptr)(unsafe.Add(p, 1968)) = __ccgo_fp(_jsonSetFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2040)) = __ccgo_fp(_jsonTypeFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2112)) = __ccgo_fp(_jsonTypeFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2184)) = __ccgo_fp(_jsonValidFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2256)) = __ccgo_fp(_jsonValidFunc)
|
|
*(*uintptr)(unsafe.Add(p, 2328)) = __ccgo_fp(_jsonArrayStep)
|
|
*(*uintptr)(unsafe.Add(p, 2336)) = __ccgo_fp(_jsonArrayFinal)
|
|
*(*uintptr)(unsafe.Add(p, 2344)) = __ccgo_fp(_jsonArrayValue)
|
|
*(*uintptr)(unsafe.Add(p, 2352)) = __ccgo_fp(_jsonGroupInverse)
|
|
*(*uintptr)(unsafe.Add(p, 2400)) = __ccgo_fp(_jsonArrayStep)
|
|
*(*uintptr)(unsafe.Add(p, 2408)) = __ccgo_fp(_jsonArrayFinal)
|
|
*(*uintptr)(unsafe.Add(p, 2416)) = __ccgo_fp(_jsonArrayValue)
|
|
*(*uintptr)(unsafe.Add(p, 2424)) = __ccgo_fp(_jsonGroupInverse)
|
|
*(*uintptr)(unsafe.Add(p, 2472)) = __ccgo_fp(_jsonObjectStep)
|
|
*(*uintptr)(unsafe.Add(p, 2480)) = __ccgo_fp(_jsonObjectFinal)
|
|
*(*uintptr)(unsafe.Add(p, 2488)) = __ccgo_fp(_jsonObjectValue)
|
|
*(*uintptr)(unsafe.Add(p, 2496)) = __ccgo_fp(_jsonGroupInverse)
|
|
*(*uintptr)(unsafe.Add(p, 2544)) = __ccgo_fp(_jsonObjectStep)
|
|
*(*uintptr)(unsafe.Add(p, 2552)) = __ccgo_fp(_jsonObjectFinal)
|
|
*(*uintptr)(unsafe.Add(p, 2560)) = __ccgo_fp(_jsonObjectValue)
|
|
*(*uintptr)(unsafe.Add(p, 2568)) = __ccgo_fp(_jsonGroupInverse)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_statInitFuncdef)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_statInit)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_memdb_io_methods)
|
|
*(*uintptr)(unsafe.Add(p, 8)) = __ccgo_fp(_memdbClose)
|
|
*(*uintptr)(unsafe.Add(p, 16)) = __ccgo_fp(_memdbRead)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_memdbWrite)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(_memdbTruncate)
|
|
*(*uintptr)(unsafe.Add(p, 40)) = __ccgo_fp(_memdbSync)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_memdbFileSize)
|
|
*(*uintptr)(unsafe.Add(p, 56)) = __ccgo_fp(_memdbLock)
|
|
*(*uintptr)(unsafe.Add(p, 64)) = __ccgo_fp(_memdbUnlock)
|
|
*(*uintptr)(unsafe.Add(p, 80)) = __ccgo_fp(_memdbFileControl)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_memdbDeviceCharacteristics)
|
|
*(*uintptr)(unsafe.Add(p, 136)) = __ccgo_fp(_memdbFetch)
|
|
*(*uintptr)(unsafe.Add(p, 144)) = __ccgo_fp(_memdbUnfetch)
|
|
}
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_fts5Vocab)
|
|
*(*uintptr)(unsafe.Add(p, 8)) = __ccgo_fp(_fts5VocabCreateMethod)
|
|
*(*uintptr)(unsafe.Add(p, 16)) = __ccgo_fp(_fts5VocabConnectMethod)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_fts5VocabBestIndexMethod)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(_fts5VocabDisconnectMethod)
|
|
*(*uintptr)(unsafe.Add(p, 40)) = __ccgo_fp(_fts5VocabDestroyMethod)
|
|
*(*uintptr)(unsafe.Add(p, 48)) = __ccgo_fp(_fts5VocabOpenMethod)
|
|
*(*uintptr)(unsafe.Add(p, 56)) = __ccgo_fp(_fts5VocabCloseMethod)
|
|
*(*uintptr)(unsafe.Add(p, 64)) = __ccgo_fp(_fts5VocabFilterMethod)
|
|
*(*uintptr)(unsafe.Add(p, 72)) = __ccgo_fp(_fts5VocabNextMethod)
|
|
*(*uintptr)(unsafe.Add(p, 80)) = __ccgo_fp(_fts5VocabEofMethod)
|
|
*(*uintptr)(unsafe.Add(p, 88)) = __ccgo_fp(_fts5VocabColumnMethod)
|
|
*(*uintptr)(unsafe.Add(p, 96)) = __ccgo_fp(_fts5VocabRowidMethod)
|
|
}
|
|
|
|
/* Here ends the fts5.c composite file. */
|
|
|
|
/************** End of fts5.c ************************************************/
|
|
/************** Begin file stmt.c ********************************************/
|
|
/*
|
|
** 2017-05-31
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
**
|
|
** This file demonstrates an eponymous virtual table that returns information
|
|
** about all prepared statements for the database connection.
|
|
**
|
|
** Usage example:
|
|
**
|
|
** .load ./stmt
|
|
** .mode line
|
|
** .header on
|
|
** SELECT * FROM stmt;
|
|
*/
|
|
|
|
func init() {
|
|
p := unsafe.Pointer(&_sqlite3BuiltinExtensions)
|
|
*(*uintptr)(unsafe.Add(p, 0)) = __ccgo_fp(_sqlite3Fts5Init)
|
|
*(*uintptr)(unsafe.Add(p, 8)) = __ccgo_fp(_sqlite3RtreeInit)
|
|
*(*uintptr)(unsafe.Add(p, 16)) = __ccgo_fp(_sqlite3DbpageRegister)
|
|
*(*uintptr)(unsafe.Add(p, 24)) = __ccgo_fp(_sqlite3DbstatRegister)
|
|
*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(_sqlite3TestExtInit)
|
|
}
|
|
|
|
type t__predefined_ptrdiff_t = int64
|
|
|
|
type t__predefined_size_t = uint64
|