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>
3157 lines
126 KiB
Go
3157 lines
126 KiB
Go
// Code generated by modernc.org/undup from the per-target sqlite_*.go files; DO NOT EDIT.
|
|
|
|
//go:build (freebsd && amd64) || (linux && amd64) || (linux && loong64) || (netbsd && amd64) || (openbsd && amd64)
|
|
|
|
package sqlite3
|
|
|
|
import (
|
|
"unsafe"
|
|
|
|
"modernc.org/libc"
|
|
)
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Allocate memory to hold names for a database, journal file, WAL file,
|
|
// ** and query parameters. The pointer returned is valid for use by
|
|
// ** sqlite3_filename_database() and sqlite3_uri_parameter() and related
|
|
// ** functions.
|
|
// **
|
|
// ** Memory layout must be compatible with that generated by the pager
|
|
// ** and expected by sqlite3_uri_parameter() and databaseName().
|
|
// */
|
|
func Xsqlite3_create_filename(tls *libc.TLS, zDatabase uintptr, zJournal uintptr, zWal uintptr, nParam int32, azParam uintptr) (r uintptr) {
|
|
var i int32
|
|
var nByte Tsqlite3_int64
|
|
var p, pResult, v2 uintptr
|
|
_, _, _, _, _ = i, nByte, p, pResult, v2
|
|
nByte = libc.Int64FromUint64(libc.Xstrlen(tls, zDatabase) + libc.Xstrlen(tls, zJournal) + libc.Xstrlen(tls, zWal) + uint64(10))
|
|
i = 0
|
|
for {
|
|
if !(i < nParam*int32(2)) {
|
|
break
|
|
}
|
|
nByte = libc.Int64FromUint64(uint64(nByte) + uint64(libc.Xstrlen(tls, **(**uintptr)(__ccgo_up(azParam + uintptr(i)*8)))+libc.Uint64FromInt32(1)))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
v2 = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(nByte))
|
|
p = v2
|
|
pResult = v2
|
|
if p == uintptr(0) {
|
|
return uintptr(0)
|
|
}
|
|
libc.Xmemset(tls, p, 0, uint64(4))
|
|
p = p + uintptr(4)
|
|
p = _appendText(tls, p, zDatabase)
|
|
i = 0
|
|
for {
|
|
if !(i < nParam*int32(2)) {
|
|
break
|
|
}
|
|
p = _appendText(tls, p, **(**uintptr)(__ccgo_up(azParam + uintptr(i)*8)))
|
|
goto _3
|
|
_3:
|
|
;
|
|
i = i + 1
|
|
}
|
|
v2 = p
|
|
p = p + 1
|
|
**(**int8)(__ccgo_up(v2)) = 0
|
|
p = _appendText(tls, p, zJournal)
|
|
p = _appendText(tls, p, zWal)
|
|
v2 = p
|
|
p = p + 1
|
|
**(**int8)(__ccgo_up(v2)) = 0
|
|
v2 = p
|
|
p = p + 1
|
|
**(**int8)(__ccgo_up(v2)) = 0
|
|
return pResult + uintptr(4)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* The core implementation of the CONCAT(...) and CONCAT_WS(SEP,...)
|
|
// ** functions.
|
|
// **
|
|
// ** Return a string value that is the concatenation of all non-null
|
|
// ** entries in argv[]. Use zSep as the separator.
|
|
// */
|
|
func _concatFuncCore(tls *libc.TLS, context uintptr, argc int32, argv uintptr, nSep int32, zSep uintptr) {
|
|
var bNotNull, i, k int32
|
|
var j, n Ti64
|
|
var v, z uintptr
|
|
_, _, _, _, _, _, _ = bNotNull, i, j, k, n, v, z
|
|
n = 0
|
|
bNotNull = 0
|
|
i = 0
|
|
for {
|
|
if !(i < argc) {
|
|
break
|
|
}
|
|
n = n + int64(Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8))))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
n = n + int64(argc-libc.Int32FromInt32(1))*int64(nSep)
|
|
z = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(n+int64(1)))
|
|
if z == uintptr(0) {
|
|
Xsqlite3_result_error_nomem(tls, context)
|
|
return
|
|
}
|
|
j = 0
|
|
i = 0
|
|
for {
|
|
if !(i < argc) {
|
|
break
|
|
}
|
|
if Xsqlite3_value_type(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8))) != int32(SQLITE_NULL) {
|
|
k = Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8)))
|
|
v = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i)*8)))
|
|
if v != uintptr(0) {
|
|
if bNotNull != 0 && nSep > 0 {
|
|
libc.Xmemcpy(tls, z+uintptr(j), zSep, libc.Uint64FromInt32(nSep))
|
|
j = j + int64(nSep)
|
|
}
|
|
libc.Xmemcpy(tls, z+uintptr(j), v, libc.Uint64FromInt32(k))
|
|
j = j + int64(k)
|
|
bNotNull = int32(1)
|
|
}
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
**(**int8)(__ccgo_up(z + uintptr(j))) = 0
|
|
Xsqlite3_result_text64(tls, context, z, libc.Uint64FromInt64(j), __ccgo_fp(Xsqlite3_free), uint8(SQLITE_UTF8_ZT))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Analyze a term that consists of two or more OR-connected
|
|
// ** subterms. So in:
|
|
// **
|
|
// ** ... WHERE (a=5) AND (b=7 OR c=9 OR d=13) AND (d=13)
|
|
// ** ^^^^^^^^^^^^^^^^^^^^
|
|
// **
|
|
// ** This routine analyzes terms such as the middle term in the above example.
|
|
// ** A WhereOrTerm object is computed and attached to the term under
|
|
// ** analysis, regardless of the outcome of the analysis. Hence:
|
|
// **
|
|
// ** WhereTerm.wtFlags |= TERM_ORINFO
|
|
// ** WhereTerm.u.pOrInfo = a dynamically allocated WhereOrTerm object
|
|
// **
|
|
// ** The term being analyzed must have two or more of OR-connected subterms.
|
|
// ** A single subterm might be a set of AND-connected sub-subterms.
|
|
// ** Examples of terms under analysis:
|
|
// **
|
|
// ** (A) t1.x=t2.y OR t1.x=t2.z OR t1.y=15 OR t1.z=t3.a+5
|
|
// ** (B) x=expr1 OR expr2=x OR x=expr3
|
|
// ** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15)
|
|
// ** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*')
|
|
// ** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6)
|
|
// ** (F) x>A OR (x=A AND y>=B)
|
|
// **
|
|
// ** CASE 1:
|
|
// **
|
|
// ** If all subterms are of the form T.C=expr for some single column of C and
|
|
// ** a single table T (as shown in example B above) then create a new virtual
|
|
// ** term that is an equivalent IN expression. In other words, if the term
|
|
// ** being analyzed is:
|
|
// **
|
|
// ** x = expr1 OR expr2 = x OR x = expr3
|
|
// **
|
|
// ** then create a new virtual term like this:
|
|
// **
|
|
// ** x IN (expr1,expr2,expr3)
|
|
// **
|
|
// ** CASE 2:
|
|
// **
|
|
// ** If there are exactly two disjuncts and one side has x>A and the other side
|
|
// ** has x=A (for the same x and A) then add a new virtual conjunct term to the
|
|
// ** WHERE clause of the form "x>=A". Example:
|
|
// **
|
|
// ** x>A OR (x=A AND y>B) adds: x>=A
|
|
// **
|
|
// ** The added conjunct can sometimes be helpful in query planning.
|
|
// **
|
|
// ** CASE 3:
|
|
// **
|
|
// ** If all subterms are indexable by a single table T, then set
|
|
// **
|
|
// ** WhereTerm.eOperator = WO_OR
|
|
// ** WhereTerm.u.pOrInfo->indexable |= the cursor number for table T
|
|
// **
|
|
// ** A subterm is "indexable" if it is of the form
|
|
// ** "T.C <op> <expr>" where C is any column of table T and
|
|
// ** <op> is one of "=", "<", "<=", ">", ">=", "IS NULL", or "IN".
|
|
// ** A subterm is also indexable if it is an AND of two or more
|
|
// ** subsubterms at least one of which is indexable. Indexable AND
|
|
// ** subterms have their eOperator set to WO_AND and they have
|
|
// ** u.pAndInfo set to a dynamically allocated WhereAndTerm object.
|
|
// **
|
|
// ** From another point of view, "indexable" means that the subterm could
|
|
// ** potentially be used with an index if an appropriate index exists.
|
|
// ** This analysis does not consider whether or not the index exists; that
|
|
// ** is decided elsewhere. This analysis only looks at whether subterms
|
|
// ** appropriate for indexing exist.
|
|
// **
|
|
// ** All examples A through E above satisfy case 3. But if a term
|
|
// ** also satisfies case 1 (such as B) we know that the optimizer will
|
|
// ** always prefer case 1, so in that case we pretend that case 3 is not
|
|
// ** satisfied.
|
|
// **
|
|
// ** It might be the case that multiple tables are indexable. For example,
|
|
// ** (E) above is indexable on tables P, Q, and R.
|
|
// **
|
|
// ** Terms that satisfy case 3 are candidates for lookup by using
|
|
// ** separate indices to find rowids for each subterm and composing
|
|
// ** the union of all rowids using a RowSet object. This is similar
|
|
// ** to "bitmap indices" in other database engines.
|
|
// **
|
|
// ** OTHERWISE:
|
|
// **
|
|
// ** If none of cases 1, 2, or 3 apply, then leave the eOperator set to
|
|
// ** zero. This term is not useful for search.
|
|
// */
|
|
func _exprAnalyzeOrTerm(tls *libc.TLS, pSrc uintptr, pWC uintptr, idxTerm int32) {
|
|
var affLeft, affRight, i, iColumn, iCursor, iOne, iTwo, idxNew, j, j1, okToChngToIN, v7, v9 int32
|
|
var b, b1, chngToIN, indexable TBitmask
|
|
var db, pAndInfo, pAndTerm, pAndWC, pDup, pExpr, pLeft, pLeft1, pList, pNew, pOne, pOrInfo, pOrTerm, pOrWc, pOther, pParse, pTerm, pTwo, pWInfo, v1, v2 uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = affLeft, affRight, b, b1, chngToIN, db, i, iColumn, iCursor, iOne, iTwo, idxNew, indexable, j, j1, okToChngToIN, pAndInfo, pAndTerm, pAndWC, pDup, pExpr, pLeft, pLeft1, pList, pNew, pOne, pOrInfo, pOrTerm, pOrWc, pOther, pParse, pTerm, pTwo, pWInfo, v1, v2, v7, v9
|
|
pWInfo = (*TWhereClause)(unsafe.Pointer(pWC)).FpWInfo /* WHERE clause processing context */
|
|
pParse = (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpParse /* Parser context */
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb /* Database connection */
|
|
pTerm = (*TWhereClause)(unsafe.Pointer(pWC)).Fa + uintptr(idxTerm)*56 /* The term to be analyzed */
|
|
pExpr = (*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr /* Tables that are indexable, satisfying case 2 */
|
|
/*
|
|
** Break the OR clause into its separate subterms. The subterms are
|
|
** stored in a WhereClause structure containing within the WhereOrInfo
|
|
** object that is attached to the original OR clause term.
|
|
*/
|
|
v1 = _sqlite3DbMallocZero(tls, db, uint64(496))
|
|
pOrInfo = v1
|
|
*(*uintptr)(unsafe.Pointer(pTerm + 32)) = v1
|
|
if pOrInfo == uintptr(0) {
|
|
return
|
|
}
|
|
v1 = pTerm + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(TERM_ORINFO))
|
|
pOrWc = pOrInfo
|
|
libc.Xmemset(tls, pOrWc+40, 0, uint64(448))
|
|
_sqlite3WhereClauseInit(tls, pOrWc, pWInfo)
|
|
_sqlite3WhereSplit(tls, pOrWc, pExpr, uint8(TK_OR))
|
|
_sqlite3WhereExprAnalyze(tls, pSrc, pOrWc)
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
|
|
return
|
|
}
|
|
/*
|
|
** Compute the set of tables that might satisfy cases 1 or 3.
|
|
*/
|
|
indexable = ^libc.Uint64FromInt32(0)
|
|
chngToIN = ^libc.Uint64FromInt32(0)
|
|
i = (*TWhereClause)(unsafe.Pointer(pOrWc)).FnTerm - int32(1)
|
|
pOrTerm = (*TWhereClause)(unsafe.Pointer(pOrWc)).Fa
|
|
for {
|
|
if !(i >= 0 && indexable != 0) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FeOperator)&int32(WO_SINGLE) == 0 {
|
|
chngToIN = uint64(0)
|
|
pAndInfo = _sqlite3DbMallocRawNN(tls, db, uint64(488))
|
|
if pAndInfo != 0 {
|
|
b = uint64(0)
|
|
*(*uintptr)(unsafe.Pointer(pOrTerm + 32)) = pAndInfo
|
|
v1 = pOrTerm + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(TERM_ANDINFO))
|
|
(*TWhereTerm)(unsafe.Pointer(pOrTerm)).FeOperator = uint16(WO_AND)
|
|
(*TWhereTerm)(unsafe.Pointer(pOrTerm)).FleftCursor = -int32(1)
|
|
pAndWC = pAndInfo
|
|
libc.Xmemset(tls, pAndWC+40, 0, uint64(448))
|
|
_sqlite3WhereClauseInit(tls, pAndWC, (*TWhereClause)(unsafe.Pointer(pWC)).FpWInfo)
|
|
_sqlite3WhereSplit(tls, pAndWC, (*TWhereTerm)(unsafe.Pointer(pOrTerm)).FpExpr, uint8(TK_AND))
|
|
_sqlite3WhereExprAnalyze(tls, pSrc, pAndWC)
|
|
(*TWhereClause)(unsafe.Pointer(pAndWC)).FpOuter = pWC
|
|
if !((*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0) {
|
|
j = 0
|
|
pAndTerm = (*TWhereClause)(unsafe.Pointer(pAndWC)).Fa
|
|
for {
|
|
if !(j < (*TWhereClause)(unsafe.Pointer(pAndWC)).FnTerm) {
|
|
break
|
|
}
|
|
if _allowedOp(tls, libc.Int32FromUint8((*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pAndTerm)).FpExpr)).Fop)) != 0 || libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pAndTerm)).FeOperator) == int32(WO_AUX) {
|
|
b = b | _sqlite3WhereGetMask(tls, pWInfo+592, (*TWhereTerm)(unsafe.Pointer(pAndTerm)).FleftCursor)
|
|
}
|
|
goto _5
|
|
_5:
|
|
;
|
|
j = j + 1
|
|
pAndTerm += 56
|
|
}
|
|
}
|
|
indexable = indexable & b
|
|
}
|
|
} else {
|
|
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FwtFlags)&int32(TERM_COPIED) != 0 {
|
|
/* Skip this term for now. We revisit it when we process the
|
|
** corresponding TERM_VIRTUAL term */
|
|
} else {
|
|
b1 = _sqlite3WhereGetMask(tls, pWInfo+592, (*TWhereTerm)(unsafe.Pointer(pOrTerm)).FleftCursor)
|
|
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FwtFlags)&int32(TERM_VIRTUAL) != 0 {
|
|
pOther = (*TWhereClause)(unsafe.Pointer(pOrWc)).Fa + uintptr((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FiParent)*56
|
|
b1 = b1 | _sqlite3WhereGetMask(tls, pWInfo+592, (*TWhereTerm)(unsafe.Pointer(pOther)).FleftCursor)
|
|
}
|
|
indexable = indexable & b1
|
|
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FeOperator)&int32(WO_EQ) == 0 {
|
|
chngToIN = uint64(0)
|
|
} else {
|
|
chngToIN = chngToIN & b1
|
|
}
|
|
}
|
|
}
|
|
goto _3
|
|
_3:
|
|
;
|
|
i = i - 1
|
|
pOrTerm += 56
|
|
}
|
|
/*
|
|
** Record the set of tables that satisfy case 3. The set might be
|
|
** empty.
|
|
*/
|
|
(*TWhereOrInfo)(unsafe.Pointer(pOrInfo)).Findexable = indexable
|
|
(*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator = uint16(WO_OR)
|
|
(*TWhereTerm)(unsafe.Pointer(pTerm)).FleftCursor = -int32(1)
|
|
if indexable != 0 {
|
|
(*TWhereClause)(unsafe.Pointer(pWC)).FhasOr = uint8(1)
|
|
}
|
|
/* For a two-way OR, attempt to implementation case 2.
|
|
*/
|
|
if indexable != 0 && (*TWhereClause)(unsafe.Pointer(pOrWc)).FnTerm == int32(2) {
|
|
iOne = 0
|
|
for {
|
|
v7 = iOne
|
|
iOne = iOne + 1
|
|
v1 = _whereNthSubterm(tls, (*TWhereClause)(unsafe.Pointer(pOrWc)).Fa, v7)
|
|
pOne = v1
|
|
if !(v1 != uintptr(0)) {
|
|
break
|
|
}
|
|
iTwo = 0
|
|
for {
|
|
v9 = iTwo
|
|
iTwo = iTwo + 1
|
|
v2 = _whereNthSubterm(tls, (*TWhereClause)(unsafe.Pointer(pOrWc)).Fa+1*56, v9)
|
|
pTwo = v2
|
|
if !(v2 != uintptr(0)) {
|
|
break
|
|
}
|
|
_whereCombineDisjuncts(tls, pSrc, pWC, pOne, pTwo)
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
** chngToIN holds a set of tables that *might* satisfy case 1. But
|
|
** we have to do some additional checking to see if case 1 really
|
|
** is satisfied.
|
|
**
|
|
** chngToIN will hold either 0, 1, or 2 bits. The 0-bit case means
|
|
** that there is no possibility of transforming the OR clause into an
|
|
** IN operator because one or more terms in the OR clause contain
|
|
** something other than == on a column in the single table. The 1-bit
|
|
** case means that every term of the OR clause is of the form
|
|
** "table.column=expr" for some single table. The one bit that is set
|
|
** will correspond to the common table. We still need to check to make
|
|
** sure the same column is used on all terms. The 2-bit case is when
|
|
** the all terms are of the form "table1.column=table2.column". It
|
|
** might be possible to form an IN operator with either table1.column
|
|
** or table2.column as the LHS if either is common to every term of
|
|
** the OR clause.
|
|
**
|
|
** Note that terms of the form "table.column1=table.column2" (the
|
|
** same table on both sizes of the ==) cannot be optimized.
|
|
*/
|
|
if chngToIN != 0 {
|
|
okToChngToIN = 0 /* True if the conversion to IN is valid */
|
|
iColumn = -int32(1) /* Column index on lhs of IN operator */
|
|
iCursor = -int32(1) /* Table cursor common to all terms */
|
|
j1 = 0 /* Loop counter */
|
|
/* Search for a table and column that appears on one side or the
|
|
** other of the == operator in every subterm. That table and column
|
|
** will be recorded in iCursor and iColumn. There might not be any
|
|
** such table and column. Set okToChngToIN if an appropriate table
|
|
** and column is found but leave okToChngToIN false if not found.
|
|
*/
|
|
j1 = 0
|
|
for {
|
|
if !(j1 < int32(2) && !(okToChngToIN != 0)) {
|
|
break
|
|
}
|
|
pLeft = uintptr(0)
|
|
pOrTerm = (*TWhereClause)(unsafe.Pointer(pOrWc)).Fa
|
|
i = (*TWhereClause)(unsafe.Pointer(pOrWc)).FnTerm - int32(1)
|
|
for {
|
|
if !(i >= 0) {
|
|
break
|
|
}
|
|
v1 = pOrTerm + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) & ^libc.Int32FromInt32(TERM_OK))
|
|
if (*TWhereTerm)(unsafe.Pointer(pOrTerm)).FleftCursor == iCursor {
|
|
/* This is the 2-bit case and we are on the second iteration and
|
|
** current term is from the first iteration. So skip this term. */
|
|
goto _11
|
|
}
|
|
if chngToIN&_sqlite3WhereGetMask(tls, pWInfo+592, (*TWhereTerm)(unsafe.Pointer(pOrTerm)).FleftCursor) == uint64(0) {
|
|
/* This term must be of the form t1.a==t2.b where t2 is in the
|
|
** chngToIN set but t1 is not. This term will be either preceded
|
|
** or followed by an inverted copy (t2.b==t1.a). Skip this term
|
|
** and use its inversion. */
|
|
goto _11
|
|
}
|
|
iColumn = (*(*struct {
|
|
FleftColumn int32
|
|
FiField int32
|
|
})(unsafe.Pointer(pOrTerm + 32))).FleftColumn
|
|
iCursor = (*TWhereTerm)(unsafe.Pointer(pOrTerm)).FleftCursor
|
|
pLeft = (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FpExpr)).FpLeft
|
|
break
|
|
goto _11
|
|
_11:
|
|
;
|
|
i = i - 1
|
|
pOrTerm += 56
|
|
}
|
|
if i < 0 {
|
|
/* No candidate table+column was found. This can only occur
|
|
** on the second iteration */
|
|
break
|
|
}
|
|
/* We have found a candidate table and column. Check to see if that
|
|
** table and column is common to every term in the OR clause */
|
|
okToChngToIN = int32(1)
|
|
for {
|
|
if !(i >= 0 && okToChngToIN != 0) {
|
|
break
|
|
}
|
|
if (*TWhereTerm)(unsafe.Pointer(pOrTerm)).FleftCursor != iCursor {
|
|
v1 = pOrTerm + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) & ^libc.Int32FromInt32(TERM_OK))
|
|
} else {
|
|
if (*(*struct {
|
|
FleftColumn int32
|
|
FiField int32
|
|
})(unsafe.Pointer(pOrTerm + 32))).FleftColumn != iColumn || iColumn == -int32(2) && _sqlite3ExprCompare(tls, pParse, (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FpExpr)).FpLeft, pLeft, -int32(1)) != 0 {
|
|
okToChngToIN = 0
|
|
} else {
|
|
/* If the right-hand side is also a column, then the affinities
|
|
** of both right and left sides must be such that no type
|
|
** conversions are required on the right. (Ticket #2249)
|
|
*/
|
|
affRight = int32(_sqlite3ExprAffinity(tls, (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FpExpr)).FpRight))
|
|
affLeft = int32(_sqlite3ExprAffinity(tls, (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FpExpr)).FpLeft))
|
|
if affRight != 0 && affRight != affLeft {
|
|
okToChngToIN = 0
|
|
} else {
|
|
v1 = pOrTerm + 18
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(TERM_OK))
|
|
}
|
|
}
|
|
}
|
|
goto _13
|
|
_13:
|
|
;
|
|
i = i - 1
|
|
pOrTerm += 56
|
|
}
|
|
goto _10
|
|
_10:
|
|
;
|
|
j1 = j1 + 1
|
|
}
|
|
/* At this point, okToChngToIN is true if original pTerm satisfies
|
|
** case 1. In that case, construct a new virtual term that is
|
|
** pTerm converted into an IN operator.
|
|
*/
|
|
if okToChngToIN != 0 { /* A transient duplicate expression */
|
|
pList = uintptr(0) /* The RHS of the IN operator */
|
|
pLeft1 = uintptr(0) /* The complete IN operator */
|
|
i = (*TWhereClause)(unsafe.Pointer(pOrWc)).FnTerm - int32(1)
|
|
pOrTerm = (*TWhereClause)(unsafe.Pointer(pOrWc)).Fa
|
|
for {
|
|
if !(i >= 0) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FwtFlags)&int32(TERM_OK) == 0 {
|
|
goto _16
|
|
}
|
|
pDup = _sqlite3ExprDup(tls, db, (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FpExpr)).FpRight, 0)
|
|
pList = _sqlite3ExprListAppend(tls, (*TWhereInfo)(unsafe.Pointer(pWInfo)).FpParse, pList, pDup)
|
|
pLeft1 = (*TExpr)(unsafe.Pointer((*TWhereTerm)(unsafe.Pointer(pOrTerm)).FpExpr)).FpLeft
|
|
goto _16
|
|
_16:
|
|
;
|
|
i = i - 1
|
|
pOrTerm += 56
|
|
}
|
|
pDup = _sqlite3ExprDup(tls, db, pLeft1, 0)
|
|
pNew = _sqlite3PExpr(tls, pParse, int32(TK_IN), pDup, uintptr(0))
|
|
if pNew != 0 {
|
|
_transferJoinMarkings(tls, pNew, pExpr)
|
|
*(*uintptr)(unsafe.Pointer(pNew + 32)) = pList
|
|
idxNew = _whereClauseInsert(tls, pWC, pNew, libc.Uint16FromInt32(libc.Int32FromInt32(TERM_VIRTUAL)|libc.Int32FromInt32(TERM_DYNAMIC)))
|
|
_exprAnalyze(tls, pSrc, pWC, idxNew)
|
|
/* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where reused */
|
|
_markTermAsChild(tls, pWC, idxNew, idxTerm)
|
|
} else {
|
|
_sqlite3ExprListDelete(tls, db, pList)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Gobble up the first bareword or quoted word from the input buffer zIn.
|
|
// ** Return a pointer to the character immediately following the last in
|
|
// ** the gobbled word if successful, or a NULL pointer otherwise (failed
|
|
// ** to find close-quote character).
|
|
// **
|
|
// ** Before returning, set pzOut to point to a new buffer containing a
|
|
// ** nul-terminated, dequoted copy of the gobbled word. If the word was
|
|
// ** quoted, *pbQuoted is also set to 1 before returning.
|
|
// **
|
|
// ** If *pRc is other than SQLITE_OK when this function is called, it is
|
|
// ** a no-op (NULL is returned). Otherwise, if an OOM occurs within this
|
|
// ** function, *pRc is set to SQLITE_NOMEM before returning. *pRc is *not*
|
|
// ** set if a parse error (failed to find close quote) occurs.
|
|
// */
|
|
func _fts5ConfigGobbleWord(tls *libc.TLS, pRc uintptr, zIn uintptr, pzOut uintptr, pbQuoted uintptr) (r uintptr) {
|
|
var ii int32
|
|
var nIn Tsqlite3_int64
|
|
var zOut, zRet uintptr
|
|
_, _, _, _ = ii, nIn, zOut, zRet
|
|
zRet = uintptr(0)
|
|
nIn = libc.Int64FromUint64(libc.Xstrlen(tls, zIn))
|
|
zOut = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(nIn+int64(1)))
|
|
**(**int32)(__ccgo_up(pbQuoted)) = 0
|
|
**(**uintptr)(__ccgo_up(pzOut)) = uintptr(0)
|
|
if zOut == uintptr(0) {
|
|
**(**int32)(__ccgo_up(pRc)) = int32(SQLITE_NOMEM)
|
|
} else {
|
|
libc.Xmemcpy(tls, zOut, zIn, libc.Uint64FromInt64(nIn+libc.Int64FromInt32(1)))
|
|
if _fts5_isopenquote(tls, **(**int8)(__ccgo_up(zOut))) != 0 {
|
|
ii = _fts5Dequote(tls, zOut)
|
|
zRet = zIn + uintptr(ii)
|
|
**(**int32)(__ccgo_up(pbQuoted)) = int32(1)
|
|
} else {
|
|
zRet = _fts5ConfigSkipBareword(tls, zIn)
|
|
if zRet != 0 {
|
|
**(**int8)(__ccgo_up(zOut + uintptr(int64(zRet)-int64(zIn)))) = int8('\000')
|
|
}
|
|
}
|
|
}
|
|
if zRet == uintptr(0) {
|
|
Xsqlite3_free(tls, zOut)
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(pzOut)) = zOut
|
|
}
|
|
return zRet
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Implementation of fts5_locale(LOCALE, TEXT) function.
|
|
// **
|
|
// ** If parameter LOCALE is NULL, or a zero-length string, then a copy of
|
|
// ** TEXT is returned. Otherwise, both LOCALE and TEXT are interpreted as
|
|
// ** text, and the value returned is a blob consisting of:
|
|
// **
|
|
// ** * The 4 bytes 0x00, 0xE0, 0xB2, 0xEb (FTS5_LOCALE_HEADER).
|
|
// ** * The LOCALE, as utf-8 text, followed by
|
|
// ** * 0x00, followed by
|
|
// ** * The TEXT, as utf-8 text.
|
|
// **
|
|
// ** There is no final nul-terminator following the TEXT value.
|
|
// */
|
|
func _fts5LocaleFunc(tls *libc.TLS, pCtx uintptr, nArg int32, apArg uintptr) {
|
|
var nBlob, nLocale, nText Ti64
|
|
var p, pBlob, pCsr, zLocale, zText, v1 uintptr
|
|
_, _, _, _, _, _, _, _, _ = nBlob, nLocale, nText, p, pBlob, pCsr, zLocale, zText, v1
|
|
zLocale = uintptr(0)
|
|
nLocale = 0
|
|
zText = uintptr(0)
|
|
nText = 0
|
|
_ = nArg
|
|
zLocale = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(apArg)))
|
|
nLocale = int64(Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(apArg))))
|
|
zText = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(apArg + 1*8)))
|
|
nText = int64(Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(apArg + 1*8))))
|
|
if zLocale == uintptr(0) || int32(**(**int8)(__ccgo_up(zLocale))) == int32('\000') {
|
|
Xsqlite3_result_text(tls, pCtx, zText, int32(nText), uintptr(-libc.Int32FromInt32(1)))
|
|
} else {
|
|
p = Xsqlite3_user_data(tls, pCtx)
|
|
pBlob = uintptr(0)
|
|
pCsr = uintptr(0)
|
|
nBlob = 0
|
|
nBlob = int64(libc.Int32FromInt64(16)) + nLocale + int64(1) + nText
|
|
pBlob = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(nBlob))
|
|
if pBlob == uintptr(0) {
|
|
Xsqlite3_result_error_nomem(tls, pCtx)
|
|
return
|
|
}
|
|
pCsr = pBlob
|
|
libc.Xmemcpy(tls, pCsr, p+96, libc.Uint64FromInt32(libc.Int32FromInt64(16)))
|
|
pCsr = pCsr + uintptr(libc.Int32FromInt64(16))
|
|
libc.Xmemcpy(tls, pCsr, zLocale, libc.Uint64FromInt64(nLocale))
|
|
pCsr = pCsr + uintptr(nLocale)
|
|
v1 = pCsr
|
|
pCsr = pCsr + 1
|
|
**(**Tu8)(__ccgo_up(v1)) = uint8(0x00)
|
|
if zText != 0 {
|
|
libc.Xmemcpy(tls, pCsr, zText, libc.Uint64FromInt64(nText))
|
|
}
|
|
Xsqlite3_result_blob(tls, pCtx, pBlob, int32(nBlob), __ccgo_fp(Xsqlite3_free))
|
|
}
|
|
}
|
|
|
|
func _fts5PorterCb(tls *libc.TLS, pCtx uintptr, tflags int32, pToken uintptr, nToken int32, iStart int32, iEnd int32) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var aBuf, p uintptr
|
|
var c int8
|
|
var v1 int32
|
|
var _ /* nBuf at bp+0 */ int32
|
|
_, _, _, _ = aBuf, c, p, v1
|
|
p = pCtx
|
|
if nToken > int32(FTS5_PORTER_MAX_TOKEN) || nToken < int32(3) {
|
|
goto pass_through
|
|
}
|
|
aBuf = (*TPorterContext)(unsafe.Pointer(p)).FaBuf
|
|
**(**int32)(__ccgo_up(bp)) = nToken
|
|
libc.Xmemcpy(tls, aBuf, pToken, libc.Uint64FromInt32(**(**int32)(__ccgo_up(bp))))
|
|
/* Step 1. */
|
|
_fts5PorterStep1A(tls, aBuf, bp)
|
|
if _fts5PorterStep1B(tls, aBuf, bp) != 0 {
|
|
if _fts5PorterStep1B2(tls, aBuf, bp) == 0 {
|
|
c = **(**int8)(__ccgo_up(aBuf + uintptr(**(**int32)(__ccgo_up(bp))-int32(1))))
|
|
if _fts5PorterIsVowel(tls, c, 0) == 0 && int32(c) != int32('l') && int32(c) != int32('s') && int32(c) != int32('z') && int32(c) == int32(**(**int8)(__ccgo_up(aBuf + uintptr(**(**int32)(__ccgo_up(bp))-int32(2))))) {
|
|
**(**int32)(__ccgo_up(bp)) = **(**int32)(__ccgo_up(bp)) - 1
|
|
} else {
|
|
if _fts5Porter_MEq1(tls, aBuf, **(**int32)(__ccgo_up(bp))) != 0 && _fts5Porter_Ostar(tls, aBuf, **(**int32)(__ccgo_up(bp))) != 0 {
|
|
v1 = **(**int32)(__ccgo_up(bp))
|
|
**(**int32)(__ccgo_up(bp)) = **(**int32)(__ccgo_up(bp)) + 1
|
|
**(**int8)(__ccgo_up(aBuf + uintptr(v1))) = int8('e')
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* Step 1C. */
|
|
if int32(**(**int8)(__ccgo_up(aBuf + uintptr(**(**int32)(__ccgo_up(bp))-int32(1))))) == int32('y') && _fts5Porter_Vowel(tls, aBuf, **(**int32)(__ccgo_up(bp))-int32(1)) != 0 {
|
|
**(**int8)(__ccgo_up(aBuf + uintptr(**(**int32)(__ccgo_up(bp))-int32(1)))) = int8('i')
|
|
}
|
|
/* Steps 2 through 4. */
|
|
_fts5PorterStep2(tls, aBuf, bp)
|
|
_fts5PorterStep3(tls, aBuf, bp)
|
|
_fts5PorterStep4(tls, aBuf, bp)
|
|
/* Step 5a. */
|
|
if int32(**(**int8)(__ccgo_up(aBuf + uintptr(**(**int32)(__ccgo_up(bp))-int32(1))))) == int32('e') {
|
|
if _fts5Porter_MGt1(tls, aBuf, **(**int32)(__ccgo_up(bp))-int32(1)) != 0 || _fts5Porter_MEq1(tls, aBuf, **(**int32)(__ccgo_up(bp))-int32(1)) != 0 && !(_fts5Porter_Ostar(tls, aBuf, **(**int32)(__ccgo_up(bp))-int32(1)) != 0) {
|
|
**(**int32)(__ccgo_up(bp)) = **(**int32)(__ccgo_up(bp)) - 1
|
|
}
|
|
}
|
|
/* Step 5b. */
|
|
if **(**int32)(__ccgo_up(bp)) > int32(1) && int32(**(**int8)(__ccgo_up(aBuf + uintptr(**(**int32)(__ccgo_up(bp))-int32(1))))) == int32('l') && int32(**(**int8)(__ccgo_up(aBuf + uintptr(**(**int32)(__ccgo_up(bp))-int32(2))))) == int32('l') && _fts5Porter_MGt1(tls, aBuf, **(**int32)(__ccgo_up(bp))-int32(1)) != 0 {
|
|
**(**int32)(__ccgo_up(bp)) = **(**int32)(__ccgo_up(bp)) - 1
|
|
}
|
|
return (*(*func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32) int32)(unsafe.Pointer(&struct{ uintptr }{(*TPorterContext)(unsafe.Pointer(p)).FxToken})))(tls, (*TPorterContext)(unsafe.Pointer(p)).FpCtx, tflags, aBuf, **(**int32)(__ccgo_up(bp)), iStart, iEnd)
|
|
goto pass_through
|
|
pass_through:
|
|
;
|
|
return (*(*func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32) int32)(unsafe.Pointer(&struct{ uintptr }{(*TPorterContext)(unsafe.Pointer(p)).FxToken})))(tls, (*TPorterContext)(unsafe.Pointer(p)).FpCtx, tflags, pToken, nToken, iStart, iEnd)
|
|
return r
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Trigram tokenizer tokenize routine.
|
|
// */
|
|
func _fts5TriTokenize(tls *libc.TLS, pTok uintptr, pCtx uintptr, unusedFlags int32, pText uintptr, nText int32, __ccgo_fp_xToken uintptr) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var aStart [3]int32
|
|
var iCode Tu32
|
|
var iNext, ii, rc int32
|
|
var p, z1, zEof, zIn, zOut, v1 uintptr
|
|
var _ /* aBuf at bp+0 */ [32]int8
|
|
_, _, _, _, _, _, _, _, _, _, _ = aStart, iCode, iNext, ii, p, rc, z1, zEof, zIn, zOut, v1
|
|
p = pTok
|
|
rc = SQLITE_OK
|
|
zOut = bp
|
|
zIn = pText
|
|
if zIn != 0 {
|
|
v1 = zIn + uintptr(nText)
|
|
} else {
|
|
v1 = uintptr(0)
|
|
}
|
|
zEof = v1
|
|
iCode = uint32(0) /* Input offset of each character in aBuf[] */
|
|
_ = unusedFlags
|
|
/* Populate aBuf[] with the characters for the first trigram. */
|
|
ii = 0
|
|
for {
|
|
if !(ii < int32(3)) {
|
|
break
|
|
}
|
|
for cond := true; cond; cond = iCode == uint32(0) {
|
|
aStart[ii] = int32(int64(zIn) - int64(pText))
|
|
if zIn >= zEof {
|
|
return SQLITE_OK
|
|
}
|
|
v1 = zIn
|
|
zIn = zIn + 1
|
|
iCode = uint32(**(**uint8)(__ccgo_up(v1)))
|
|
if iCode >= uint32(0xc0) {
|
|
iCode = uint32(_sqlite3Utf8Trans1[iCode-uint32(0xc0)])
|
|
for zIn < zEof && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn)))&int32(0xc0) == int32(0x80) {
|
|
v1 = zIn
|
|
zIn = zIn + 1
|
|
iCode = iCode<<libc.Int32FromInt32(6) + libc.Uint32FromInt32(libc.Int32FromInt32(0x3f)&libc.Int32FromUint8(**(**uint8)(__ccgo_up(v1))))
|
|
}
|
|
if iCode < uint32(0x80) || iCode&uint32(0xFFFFF800) == uint32(0xD800) || iCode&uint32(0xFFFFFFFE) == uint32(0xFFFE) {
|
|
iCode = uint32(0xFFFD)
|
|
}
|
|
}
|
|
if (*TTrigramTokenizer)(unsafe.Pointer(p)).FbFold != 0 {
|
|
iCode = libc.Uint32FromInt32(_sqlite3Fts5UnicodeFold(tls, libc.Int32FromUint32(iCode), (*TTrigramTokenizer)(unsafe.Pointer(p)).FiFoldParam))
|
|
}
|
|
}
|
|
if iCode < uint32(0x00080) {
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = libc.Int8FromUint8(uint8(iCode & libc.Uint32FromInt32(0xFF)))
|
|
} else {
|
|
if iCode < uint32(0x00800) {
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = int8(int32(0xC0) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(6)&libc.Uint32FromInt32(0x1F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = int8(int32(0x80) + libc.Int32FromUint8(uint8(iCode&libc.Uint32FromInt32(0x3F))))
|
|
} else {
|
|
if iCode < uint32(0x10000) {
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = int8(int32(0xE0) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(12)&libc.Uint32FromInt32(0x0F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = int8(int32(0x80) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(6)&libc.Uint32FromInt32(0x3F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = int8(int32(0x80) + libc.Int32FromUint8(uint8(iCode&libc.Uint32FromInt32(0x3F))))
|
|
} else {
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = int8(int32(0xF0) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(18)&libc.Uint32FromInt32(0x07))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = int8(int32(0x80) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(12)&libc.Uint32FromInt32(0x3F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = int8(int32(0x80) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(6)&libc.Uint32FromInt32(0x3F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = int8(int32(0x80) + libc.Int32FromUint8(uint8(iCode&libc.Uint32FromInt32(0x3F))))
|
|
}
|
|
}
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
/* At the start of each iteration of this loop:
|
|
**
|
|
** aBuf: Contains 3 characters. The 3 characters of the next trigram.
|
|
** zOut: Points to the byte following the last character in aBuf.
|
|
** aStart[3]: Contains the byte offset in the input text corresponding
|
|
** to the start of each of the three characters in the buffer.
|
|
*/
|
|
for int32(1) != 0 {
|
|
/* Read characters from the input up until the first non-diacritic */
|
|
for cond := true; cond; cond = iCode == uint32(0) {
|
|
iNext = int32(int64(zIn) - int64(pText))
|
|
if zIn >= zEof {
|
|
iCode = uint32(0)
|
|
break
|
|
}
|
|
v1 = zIn
|
|
zIn = zIn + 1
|
|
iCode = uint32(**(**uint8)(__ccgo_up(v1)))
|
|
if iCode >= uint32(0xc0) {
|
|
iCode = uint32(_sqlite3Utf8Trans1[iCode-uint32(0xc0)])
|
|
for zIn < zEof && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zIn)))&int32(0xc0) == int32(0x80) {
|
|
v1 = zIn
|
|
zIn = zIn + 1
|
|
iCode = iCode<<libc.Int32FromInt32(6) + libc.Uint32FromInt32(libc.Int32FromInt32(0x3f)&libc.Int32FromUint8(**(**uint8)(__ccgo_up(v1))))
|
|
}
|
|
if iCode < uint32(0x80) || iCode&uint32(0xFFFFF800) == uint32(0xD800) || iCode&uint32(0xFFFFFFFE) == uint32(0xFFFE) {
|
|
iCode = uint32(0xFFFD)
|
|
}
|
|
}
|
|
if (*TTrigramTokenizer)(unsafe.Pointer(p)).FbFold != 0 {
|
|
iCode = libc.Uint32FromInt32(_sqlite3Fts5UnicodeFold(tls, libc.Int32FromUint32(iCode), (*TTrigramTokenizer)(unsafe.Pointer(p)).FiFoldParam))
|
|
}
|
|
}
|
|
/* Pass the current trigram back to fts5 */
|
|
rc = (*(*func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32) int32)(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xToken})))(tls, pCtx, 0, bp, int32(int64(zOut)-t__predefined_ptrdiff_t(bp)), aStart[0], iNext)
|
|
if iCode == uint32(0) || rc != SQLITE_OK {
|
|
break
|
|
}
|
|
/* Remove the first character from buffer aBuf[]. Append the character
|
|
** with codepoint iCode. */
|
|
z1 = bp
|
|
v1 = z1
|
|
z1 = z1 + 1
|
|
if libc.Int32FromUint8(libc.Uint8FromInt8(**(**int8)(__ccgo_up(v1)))) >= int32(0xc0) {
|
|
for libc.Int32FromUint8(libc.Uint8FromInt8(**(**int8)(__ccgo_up(z1))))&int32(0xc0) == int32(0x80) {
|
|
z1 = z1 + 1
|
|
}
|
|
}
|
|
libc.Xmemmove(tls, bp, z1, libc.Uint64FromInt64(int64(zOut)-int64(z1)))
|
|
zOut = zOut - uintptr(int64(z1)-t__predefined_ptrdiff_t(bp))
|
|
if iCode < uint32(0x00080) {
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = libc.Int8FromUint8(uint8(iCode & libc.Uint32FromInt32(0xFF)))
|
|
} else {
|
|
if iCode < uint32(0x00800) {
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = int8(int32(0xC0) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(6)&libc.Uint32FromInt32(0x1F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = int8(int32(0x80) + libc.Int32FromUint8(uint8(iCode&libc.Uint32FromInt32(0x3F))))
|
|
} else {
|
|
if iCode < uint32(0x10000) {
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = int8(int32(0xE0) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(12)&libc.Uint32FromInt32(0x0F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = int8(int32(0x80) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(6)&libc.Uint32FromInt32(0x3F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = int8(int32(0x80) + libc.Int32FromUint8(uint8(iCode&libc.Uint32FromInt32(0x3F))))
|
|
} else {
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = int8(int32(0xF0) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(18)&libc.Uint32FromInt32(0x07))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = int8(int32(0x80) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(12)&libc.Uint32FromInt32(0x3F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = int8(int32(0x80) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(6)&libc.Uint32FromInt32(0x3F))))
|
|
v1 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v1)) = int8(int32(0x80) + libc.Int32FromUint8(uint8(iCode&libc.Uint32FromInt32(0x3F))))
|
|
}
|
|
}
|
|
}
|
|
/* Update the aStart[] array */
|
|
aStart[0] = aStart[int32(1)]
|
|
aStart[int32(1)] = aStart[int32(2)]
|
|
aStart[int32(2)] = iNext
|
|
}
|
|
return rc
|
|
}
|
|
|
|
func _fts5UnicodeTokenize(tls *libc.TLS, pTokenizer uintptr, pCtx uintptr, iUnused int32, pText uintptr, nText int32, __ccgo_fp_xToken uintptr) (r int32) {
|
|
var a, aFold, p, pEnd, zCsr, zOut, zTerm, v3 uintptr
|
|
var iCode Tu32
|
|
var ie, is, nFold, rc, v7 int32
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _ = a, aFold, iCode, ie, is, nFold, p, pEnd, rc, zCsr, zOut, zTerm, v3, v7
|
|
p = pTokenizer
|
|
rc = SQLITE_OK
|
|
a = p
|
|
zTerm = pText + uintptr(nText)
|
|
zCsr = pText
|
|
/* Output buffer */
|
|
aFold = (*TUnicode61Tokenizer)(unsafe.Pointer(p)).FaFold
|
|
nFold = (*TUnicode61Tokenizer)(unsafe.Pointer(p)).FnFold
|
|
pEnd = aFold + uintptr(nFold-int32(6))
|
|
_ = iUnused
|
|
/* Each iteration of this loop gobbles up a contiguous run of separators,
|
|
** then the next token. */
|
|
_2:
|
|
;
|
|
if !(rc == SQLITE_OK) {
|
|
goto _1
|
|
} /* non-ASCII codepoint read from input */
|
|
zOut = aFold
|
|
/* Skip any separator characters. */
|
|
for int32(1) != 0 {
|
|
if zCsr >= zTerm {
|
|
goto tokenize_done
|
|
}
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zCsr)))&int32(0x80) != 0 {
|
|
/* A character outside of the ascii range. Skip past it if it is
|
|
** a separator character. Or break out of the loop if it is not. */
|
|
is = int32(int64(zCsr) - int64(pText))
|
|
v3 = zCsr
|
|
zCsr = zCsr + 1
|
|
iCode = uint32(**(**uint8)(__ccgo_up(v3)))
|
|
if iCode >= uint32(0xc0) {
|
|
iCode = uint32(_sqlite3Utf8Trans1[iCode-uint32(0xc0)])
|
|
for zCsr < zTerm && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zCsr)))&int32(0xc0) == int32(0x80) {
|
|
v3 = zCsr
|
|
zCsr = zCsr + 1
|
|
iCode = iCode<<libc.Int32FromInt32(6) + libc.Uint32FromInt32(libc.Int32FromInt32(0x3f)&libc.Int32FromUint8(**(**uint8)(__ccgo_up(v3))))
|
|
}
|
|
if iCode < uint32(0x80) || iCode&uint32(0xFFFFF800) == uint32(0xD800) || iCode&uint32(0xFFFFFFFE) == uint32(0xFFFE) {
|
|
iCode = uint32(0xFFFD)
|
|
}
|
|
}
|
|
if _fts5UnicodeIsAlnum(tls, p, libc.Int32FromUint32(iCode)) != 0 {
|
|
goto non_ascii_tokenchar
|
|
}
|
|
} else {
|
|
if **(**uint8)(__ccgo_up(a + uintptr(**(**uint8)(__ccgo_up(zCsr))))) != 0 {
|
|
is = int32(int64(zCsr) - int64(pText))
|
|
goto ascii_tokenchar
|
|
}
|
|
zCsr = zCsr + 1
|
|
}
|
|
}
|
|
/* Run through the tokenchars. Fold them into the output buffer along
|
|
** the way. */
|
|
_6:
|
|
;
|
|
if !(zCsr < zTerm) {
|
|
goto _5
|
|
}
|
|
/* Grow the output buffer so that there is sufficient space to fit the
|
|
** largest possible utf-8 character. */
|
|
if zOut > pEnd {
|
|
aFold = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(int64(nFold)*int64(2)))
|
|
if aFold == uintptr(0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
goto tokenize_done
|
|
}
|
|
zOut = aFold + uintptr(int64(zOut)-int64((*TUnicode61Tokenizer)(unsafe.Pointer(p)).FaFold))
|
|
libc.Xmemcpy(tls, aFold, (*TUnicode61Tokenizer)(unsafe.Pointer(p)).FaFold, libc.Uint64FromInt32(nFold))
|
|
Xsqlite3_free(tls, (*TUnicode61Tokenizer)(unsafe.Pointer(p)).FaFold)
|
|
(*TUnicode61Tokenizer)(unsafe.Pointer(p)).FaFold = aFold
|
|
v7 = nFold * libc.Int32FromInt32(2)
|
|
nFold = v7
|
|
(*TUnicode61Tokenizer)(unsafe.Pointer(p)).FnFold = v7
|
|
pEnd = aFold + uintptr(nFold-int32(6))
|
|
}
|
|
if !(libc.Int32FromUint8(**(**uint8)(__ccgo_up(zCsr)))&int32(0x80) != 0) {
|
|
goto _8
|
|
}
|
|
/* An non-ascii-range character. Fold it into the output buffer if
|
|
** it is a token character, or break out of the loop if it is not. */
|
|
v3 = zCsr
|
|
zCsr = zCsr + 1
|
|
iCode = uint32(**(**uint8)(__ccgo_up(v3)))
|
|
if iCode >= uint32(0xc0) {
|
|
iCode = uint32(_sqlite3Utf8Trans1[iCode-uint32(0xc0)])
|
|
for zCsr < zTerm && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zCsr)))&int32(0xc0) == int32(0x80) {
|
|
v3 = zCsr
|
|
zCsr = zCsr + 1
|
|
iCode = iCode<<libc.Int32FromInt32(6) + libc.Uint32FromInt32(libc.Int32FromInt32(0x3f)&libc.Int32FromUint8(**(**uint8)(__ccgo_up(v3))))
|
|
}
|
|
if iCode < uint32(0x80) || iCode&uint32(0xFFFFF800) == uint32(0xD800) || iCode&uint32(0xFFFFFFFE) == uint32(0xFFFE) {
|
|
iCode = uint32(0xFFFD)
|
|
}
|
|
}
|
|
if !(_fts5UnicodeIsAlnum(tls, p, libc.Int32FromUint32(iCode)) != 0 || _sqlite3Fts5UnicodeIsdiacritic(tls, libc.Int32FromUint32(iCode)) != 0) {
|
|
goto _12
|
|
}
|
|
goto non_ascii_tokenchar
|
|
non_ascii_tokenchar:
|
|
;
|
|
iCode = libc.Uint32FromInt32(_sqlite3Fts5UnicodeFold(tls, libc.Int32FromUint32(iCode), (*TUnicode61Tokenizer)(unsafe.Pointer(p)).FeRemoveDiacritic))
|
|
if iCode != 0 {
|
|
if iCode < uint32(0x00080) {
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v3)) = libc.Int8FromUint8(uint8(iCode & libc.Uint32FromInt32(0xFF)))
|
|
} else {
|
|
if iCode < uint32(0x00800) {
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v3)) = int8(int32(0xC0) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(6)&libc.Uint32FromInt32(0x1F))))
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v3)) = int8(int32(0x80) + libc.Int32FromUint8(uint8(iCode&libc.Uint32FromInt32(0x3F))))
|
|
} else {
|
|
if iCode < uint32(0x10000) {
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v3)) = int8(int32(0xE0) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(12)&libc.Uint32FromInt32(0x0F))))
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v3)) = int8(int32(0x80) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(6)&libc.Uint32FromInt32(0x3F))))
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v3)) = int8(int32(0x80) + libc.Int32FromUint8(uint8(iCode&libc.Uint32FromInt32(0x3F))))
|
|
} else {
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v3)) = int8(int32(0xF0) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(18)&libc.Uint32FromInt32(0x07))))
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v3)) = int8(int32(0x80) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(12)&libc.Uint32FromInt32(0x3F))))
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v3)) = int8(int32(0x80) + libc.Int32FromUint8(uint8(iCode>>libc.Int32FromInt32(6)&libc.Uint32FromInt32(0x3F))))
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v3)) = int8(int32(0x80) + libc.Int32FromUint8(uint8(iCode&libc.Uint32FromInt32(0x3F))))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
goto _13
|
|
_12:
|
|
;
|
|
goto _5
|
|
_13:
|
|
;
|
|
goto _9
|
|
_8:
|
|
;
|
|
if !(libc.Int32FromUint8(**(**uint8)(__ccgo_up(a + uintptr(**(**uint8)(__ccgo_up(zCsr)))))) == 0) {
|
|
goto _24
|
|
}
|
|
/* An ascii-range separator character. End of token. */
|
|
goto _5
|
|
goto _25
|
|
_24:
|
|
;
|
|
goto ascii_tokenchar
|
|
ascii_tokenchar:
|
|
;
|
|
if libc.Int32FromUint8(**(**uint8)(__ccgo_up(zCsr))) >= int32('A') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(zCsr))) <= int32('Z') {
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v3)) = int8(libc.Int32FromUint8(**(**uint8)(__ccgo_up(zCsr))) + int32(32))
|
|
} else {
|
|
v3 = zOut
|
|
zOut = zOut + 1
|
|
**(**int8)(__ccgo_up(v3)) = libc.Int8FromUint8(**(**uint8)(__ccgo_up(zCsr)))
|
|
}
|
|
zCsr = zCsr + 1
|
|
_25:
|
|
;
|
|
_9:
|
|
;
|
|
ie = int32(int64(zCsr) - int64(pText))
|
|
goto _6
|
|
_5:
|
|
;
|
|
/* Invoke the token callback */
|
|
rc = (*(*func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32) int32)(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xToken})))(tls, pCtx, 0, aFold, int32(int64(zOut)-int64(aFold)), is, ie)
|
|
goto _2
|
|
_1:
|
|
;
|
|
goto tokenize_done
|
|
tokenize_done:
|
|
;
|
|
if rc == int32(SQLITE_DONE) {
|
|
rc = SQLITE_OK
|
|
}
|
|
return rc
|
|
}
|
|
|
|
/**************************************************************************
|
|
** Start of porter stemmer implementation.
|
|
*/
|
|
|
|
/* Any tokens larger than this (in bytes) are passed through without
|
|
** stemming. */
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If the input is a well-formed JSON array of coordinates with at least
|
|
// ** four coordinates and where each coordinate is itself a two-value array,
|
|
// ** then convert the JSON into a GeoPoly object and return a pointer to
|
|
// ** that object.
|
|
// **
|
|
// ** If any error occurs, return NULL.
|
|
// */
|
|
func _geopolyParseJson(tls *libc.TLS, z uintptr, pRc uintptr) (r uintptr) {
|
|
bp := tls.Alloc(48)
|
|
defer tls.Free(48)
|
|
var aNew, pOut, v1 uintptr
|
|
var c int8
|
|
var ii, rc int32
|
|
var v2 bool
|
|
var _ /* s at bp+0 */ TGeoParse
|
|
var _ /* x at bp+32 */ int32
|
|
_, _, _, _, _, _, _ = aNew, c, ii, pOut, rc, v1, v2
|
|
rc = SQLITE_OK
|
|
libc.Xmemset(tls, bp, 0, uint64(32))
|
|
(**(**TGeoParse)(__ccgo_up(bp))).Fz = z
|
|
if int32(_geopolySkipSpace(tls, bp)) == int32('[') {
|
|
(**(**TGeoParse)(__ccgo_up(bp))).Fz = (**(**TGeoParse)(__ccgo_up(bp))).Fz + 1
|
|
for int32(_geopolySkipSpace(tls, bp)) == int32('[') {
|
|
ii = 0
|
|
(**(**TGeoParse)(__ccgo_up(bp))).Fz = (**(**TGeoParse)(__ccgo_up(bp))).Fz + 1
|
|
if (**(**TGeoParse)(__ccgo_up(bp))).FnVertex >= (**(**TGeoParse)(__ccgo_up(bp))).FnAlloc {
|
|
(**(**TGeoParse)(__ccgo_up(bp))).FnAlloc = (**(**TGeoParse)(__ccgo_up(bp))).FnAlloc*int32(2) + int32(16)
|
|
aNew = Xsqlite3_realloc64(tls, (**(**TGeoParse)(__ccgo_up(bp))).Fa, uint64(libc.Uint64FromInt32((**(**TGeoParse)(__ccgo_up(bp))).FnAlloc)*uint64(4)*uint64(2)))
|
|
if aNew == uintptr(0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
(**(**TGeoParse)(__ccgo_up(bp))).FnErr = (**(**TGeoParse)(__ccgo_up(bp))).FnErr + 1
|
|
break
|
|
}
|
|
(**(**TGeoParse)(__ccgo_up(bp))).Fa = aNew
|
|
}
|
|
for {
|
|
if ii <= int32(1) {
|
|
v1 = (**(**TGeoParse)(__ccgo_up(bp))).Fa + uintptr((**(**TGeoParse)(__ccgo_up(bp))).FnVertex*int32(2)+ii)*4
|
|
} else {
|
|
v1 = uintptr(0)
|
|
}
|
|
if !(_geopolyParseNumber(tls, bp, v1) != 0) {
|
|
break
|
|
}
|
|
ii = ii + 1
|
|
if ii == int32(2) {
|
|
(**(**TGeoParse)(__ccgo_up(bp))).FnVertex = (**(**TGeoParse)(__ccgo_up(bp))).FnVertex + 1
|
|
}
|
|
c = _geopolySkipSpace(tls, bp)
|
|
(**(**TGeoParse)(__ccgo_up(bp))).Fz = (**(**TGeoParse)(__ccgo_up(bp))).Fz + 1
|
|
if int32(c) == int32(',') {
|
|
continue
|
|
}
|
|
if int32(c) == int32(']') && ii >= int32(2) {
|
|
break
|
|
}
|
|
(**(**TGeoParse)(__ccgo_up(bp))).FnErr = (**(**TGeoParse)(__ccgo_up(bp))).FnErr + 1
|
|
rc = int32(SQLITE_ERROR)
|
|
goto parse_json_err
|
|
}
|
|
if int32(_geopolySkipSpace(tls, bp)) == int32(',') {
|
|
(**(**TGeoParse)(__ccgo_up(bp))).Fz = (**(**TGeoParse)(__ccgo_up(bp))).Fz + 1
|
|
continue
|
|
}
|
|
break
|
|
}
|
|
if v2 = int32(_geopolySkipSpace(tls, bp)) == int32(']') && (**(**TGeoParse)(__ccgo_up(bp))).FnVertex >= int32(4) && **(**TGeoCoord)(__ccgo_up((**(**TGeoParse)(__ccgo_up(bp))).Fa)) == **(**TGeoCoord)(__ccgo_up((**(**TGeoParse)(__ccgo_up(bp))).Fa + uintptr((**(**TGeoParse)(__ccgo_up(bp))).FnVertex*int32(2)-int32(2))*4)) && **(**TGeoCoord)(__ccgo_up((**(**TGeoParse)(__ccgo_up(bp))).Fa + 1*4)) == **(**TGeoCoord)(__ccgo_up((**(**TGeoParse)(__ccgo_up(bp))).Fa + uintptr((**(**TGeoParse)(__ccgo_up(bp))).FnVertex*int32(2)-int32(1))*4)); v2 {
|
|
(**(**TGeoParse)(__ccgo_up(bp))).Fz = (**(**TGeoParse)(__ccgo_up(bp))).Fz + 1
|
|
}
|
|
if v2 && int32(_geopolySkipSpace(tls, bp)) == libc.Int32FromInt32(0) {
|
|
**(**int32)(__ccgo_up(bp + 32)) = int32(1)
|
|
(**(**TGeoParse)(__ccgo_up(bp))).FnVertex = (**(**TGeoParse)(__ccgo_up(bp))).FnVertex - 1 /* Remove the redundant vertex at the end */
|
|
pOut = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(40)+uint64(libc.Uint64FromInt64(4)*libc.Uint64FromInt32(2))*libc.Uint64FromInt64(int64((**(**TGeoParse)(__ccgo_up(bp))).FnVertex)-libc.Int64FromInt32(4)))
|
|
**(**int32)(__ccgo_up(bp + 32)) = int32(1)
|
|
if pOut == uintptr(0) {
|
|
goto parse_json_err
|
|
}
|
|
(*TGeoPoly)(unsafe.Pointer(pOut)).FnVertex = (**(**TGeoParse)(__ccgo_up(bp))).FnVertex
|
|
libc.Xmemcpy(tls, pOut+8, (**(**TGeoParse)(__ccgo_up(bp))).Fa, libc.Uint64FromInt32((**(**TGeoParse)(__ccgo_up(bp))).FnVertex*int32(2))*uint64(4))
|
|
**(**uint8)(__ccgo_up(pOut + 4)) = **(**uint8)(__ccgo_up(bp + 32))
|
|
**(**uint8)(__ccgo_up(pOut + 4 + 1)) = libc.Uint8FromInt32((**(**TGeoParse)(__ccgo_up(bp))).FnVertex >> int32(16) & int32(0xff))
|
|
**(**uint8)(__ccgo_up(pOut + 4 + 2)) = libc.Uint8FromInt32((**(**TGeoParse)(__ccgo_up(bp))).FnVertex >> int32(8) & int32(0xff))
|
|
**(**uint8)(__ccgo_up(pOut + 4 + 3)) = libc.Uint8FromInt32((**(**TGeoParse)(__ccgo_up(bp))).FnVertex & int32(0xff))
|
|
Xsqlite3_free(tls, (**(**TGeoParse)(__ccgo_up(bp))).Fa)
|
|
if pRc != 0 {
|
|
**(**int32)(__ccgo_up(pRc)) = SQLITE_OK
|
|
}
|
|
return pOut
|
|
} else {
|
|
(**(**TGeoParse)(__ccgo_up(bp))).FnErr = (**(**TGeoParse)(__ccgo_up(bp))).FnErr + 1
|
|
rc = int32(SQLITE_ERROR)
|
|
}
|
|
}
|
|
goto parse_json_err
|
|
parse_json_err:
|
|
;
|
|
if pRc != 0 {
|
|
**(**int32)(__ccgo_up(pRc)) = rc
|
|
}
|
|
Xsqlite3_free(tls, (**(**TGeoParse)(__ccgo_up(bp))).Fa)
|
|
return uintptr(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Append the N-byte string in zIn to the end of the JsonString string
|
|
// ** under construction. Enclose the string in double-quotes ("...") and
|
|
// ** escape any double-quotes or backslash characters contained within the
|
|
// ** string.
|
|
// **
|
|
// ** This routine is a high-runner. There is a measurable performance
|
|
// ** increase associated with unwinding the jsonIsOk[] loop.
|
|
// */
|
|
func _jsonAppendString(tls *libc.TLS, p uintptr, zIn uintptr, N Tu32) {
|
|
var c Tu8
|
|
var k Tu32
|
|
var z, v2 uintptr
|
|
var v1 Tu64
|
|
_, _, _, _, _ = c, k, z, v1, v2
|
|
z = zIn
|
|
if z == uintptr(0) {
|
|
return
|
|
}
|
|
if uint64(N)+(*TJsonString)(unsafe.Pointer(p)).FnUsed+uint64(2) >= (*TJsonString)(unsafe.Pointer(p)).FnAlloc && _jsonStringGrow(tls, p, N+uint32(2)) != 0 {
|
|
return
|
|
}
|
|
v2 = p + 24
|
|
v1 = *(*Tu64)(unsafe.Pointer(v2))
|
|
*(*Tu64)(unsafe.Pointer(v2)) = *(*Tu64)(unsafe.Pointer(v2)) + 1
|
|
**(**int8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr(v1))) = int8('"')
|
|
for int32(1) != 0 {
|
|
k = uint32(0)
|
|
/* The following while() is the 4-way unwound equivalent of
|
|
**
|
|
** while( k<N && jsonIsOk[z[k]] ){ k++; }
|
|
*/
|
|
for int32(1) != 0 {
|
|
if k+uint32(3) >= N {
|
|
for k < N && _jsonIsOk[**(**Tu8)(__ccgo_up(z + uintptr(k)))] != 0 {
|
|
k = k + 1
|
|
}
|
|
break
|
|
}
|
|
if !(_jsonIsOk[**(**Tu8)(__ccgo_up(z + uintptr(k)))] != 0) {
|
|
break
|
|
}
|
|
if !(_jsonIsOk[**(**Tu8)(__ccgo_up(z + uintptr(k+uint32(1))))] != 0) {
|
|
k = k + uint32(1)
|
|
break
|
|
}
|
|
if !(_jsonIsOk[**(**Tu8)(__ccgo_up(z + uintptr(k+uint32(2))))] != 0) {
|
|
k = k + uint32(2)
|
|
break
|
|
}
|
|
if !(_jsonIsOk[**(**Tu8)(__ccgo_up(z + uintptr(k+uint32(3))))] != 0) {
|
|
k = k + uint32(3)
|
|
break
|
|
} else {
|
|
k = k + uint32(4)
|
|
}
|
|
}
|
|
if k >= N {
|
|
if k > uint32(0) {
|
|
libc.Xmemcpy(tls, (*TJsonString)(unsafe.Pointer(p)).FzBuf+uintptr((*TJsonString)(unsafe.Pointer(p)).FnUsed), z, uint64(k))
|
|
**(**Tu64)(__ccgo_up(p + 24)) += uint64(k)
|
|
}
|
|
break
|
|
}
|
|
if k > uint32(0) {
|
|
libc.Xmemcpy(tls, (*TJsonString)(unsafe.Pointer(p)).FzBuf+uintptr((*TJsonString)(unsafe.Pointer(p)).FnUsed), z, uint64(k))
|
|
**(**Tu64)(__ccgo_up(p + 24)) += uint64(k)
|
|
z = z + uintptr(k)
|
|
N = N - k
|
|
}
|
|
c = **(**Tu8)(__ccgo_up(z))
|
|
if libc.Int32FromUint8(c) == int32('"') || libc.Int32FromUint8(c) == int32('\\') {
|
|
if (*TJsonString)(unsafe.Pointer(p)).FnUsed+uint64(N)+uint64(3) > (*TJsonString)(unsafe.Pointer(p)).FnAlloc && _jsonStringGrow(tls, p, N+uint32(3)) != 0 {
|
|
return
|
|
}
|
|
v2 = p + 24
|
|
v1 = *(*Tu64)(unsafe.Pointer(v2))
|
|
*(*Tu64)(unsafe.Pointer(v2)) = *(*Tu64)(unsafe.Pointer(v2)) + 1
|
|
**(**int8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr(v1))) = int8('\\')
|
|
v2 = p + 24
|
|
v1 = *(*Tu64)(unsafe.Pointer(v2))
|
|
*(*Tu64)(unsafe.Pointer(v2)) = *(*Tu64)(unsafe.Pointer(v2)) + 1
|
|
**(**int8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr(v1))) = libc.Int8FromUint8(c)
|
|
} else {
|
|
if libc.Int32FromUint8(c) == int32('\'') {
|
|
v2 = p + 24
|
|
v1 = *(*Tu64)(unsafe.Pointer(v2))
|
|
*(*Tu64)(unsafe.Pointer(v2)) = *(*Tu64)(unsafe.Pointer(v2)) + 1
|
|
**(**int8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr(v1))) = libc.Int8FromUint8(c)
|
|
} else {
|
|
if (*TJsonString)(unsafe.Pointer(p)).FnUsed+uint64(N)+uint64(7) > (*TJsonString)(unsafe.Pointer(p)).FnAlloc && _jsonStringGrow(tls, p, N+uint32(7)) != 0 {
|
|
return
|
|
}
|
|
_jsonAppendControlChar(tls, p, c)
|
|
}
|
|
}
|
|
z = z + 1
|
|
N = N - 1
|
|
}
|
|
v2 = p + 24
|
|
v1 = *(*Tu64)(unsafe.Pointer(v2))
|
|
*(*Tu64)(unsafe.Pointer(v2)) = *(*Tu64)(unsafe.Pointer(v2)) + 1
|
|
**(**int8)(__ccgo_up((*TJsonString)(unsafe.Pointer(p)).FzBuf + uintptr(v1))) = int8('"')
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* This helper routine for jsonLookupStep() populates pIns with
|
|
// ** binary data that is to be inserted into pParse.
|
|
// **
|
|
// ** In the common case, pIns just points to pParse->aIns and pParse->nIns.
|
|
// ** But if the zPath of the original edit operation includes path elements
|
|
// ** that go deeper, additional substructure must be created.
|
|
// **
|
|
// ** For example:
|
|
// **
|
|
// ** json_insert('{}', '$.a.b.c', 123);
|
|
// **
|
|
// ** The search stops at '$.a' But additional substructure must be
|
|
// ** created for the ".b.c" part of the patch so that the final result
|
|
// ** is: {"a":{"b":{"c"::123}}}. This routine populates pIns with
|
|
// ** the binary equivalent of {"b":{"c":123}} so that it can be inserted.
|
|
// **
|
|
// ** The caller is responsible for resetting pIns when it has finished
|
|
// ** using the substructure.
|
|
// */
|
|
func _jsonCreateEditSubstructure(tls *libc.TLS, pParse uintptr, pIns uintptr, zTail uintptr) (r Tu32) {
|
|
var rc int32
|
|
var v1 uintptr
|
|
_, _ = rc, v1
|
|
libc.Xmemset(tls, pIns, 0, uint64(72))
|
|
(*TJsonParse)(unsafe.Pointer(pIns)).Fdb = (*TJsonParse)(unsafe.Pointer(pParse)).Fdb
|
|
if int32(**(**int8)(__ccgo_up(zTail))) == 0 {
|
|
/* No substructure. Just insert what is given in pParse. */
|
|
(*TJsonParse)(unsafe.Pointer(pIns)).FaBlob = (*TJsonParse)(unsafe.Pointer(pParse)).FaIns
|
|
(*TJsonParse)(unsafe.Pointer(pIns)).FnBlob = (*TJsonParse)(unsafe.Pointer(pParse)).FnIns
|
|
rc = 0
|
|
} else {
|
|
/* Construct the binary substructure */
|
|
(*TJsonParse)(unsafe.Pointer(pIns)).FnBlob = uint32(1)
|
|
(*TJsonParse)(unsafe.Pointer(pIns)).FaBlob = uintptr(unsafe.Pointer(&_emptyObject)) + libc.BoolUintptr(int32(**(**int8)(__ccgo_up(zTail))) == int32('.'))
|
|
(*TJsonParse)(unsafe.Pointer(pIns)).FeEdit = (*TJsonParse)(unsafe.Pointer(pParse)).FeEdit
|
|
(*TJsonParse)(unsafe.Pointer(pIns)).FnIns = (*TJsonParse)(unsafe.Pointer(pParse)).FnIns
|
|
(*TJsonParse)(unsafe.Pointer(pIns)).FaIns = (*TJsonParse)(unsafe.Pointer(pParse)).FaIns
|
|
(*TJsonParse)(unsafe.Pointer(pIns)).FiDepth = libc.Uint16FromInt32(libc.Int32FromUint16((*TJsonParse)(unsafe.Pointer(pParse)).FiDepth) + int32(1))
|
|
if libc.Int32FromUint16((*TJsonParse)(unsafe.Pointer(pIns)).FiDepth) >= int32(JSON_MAX_DEPTH) {
|
|
return uint32(JSON_LOOKUP_TOODEEP)
|
|
}
|
|
rc = libc.Int32FromUint32(_jsonLookupStep(tls, pIns, uint32(0), zTail, uint32(0)))
|
|
(*TJsonParse)(unsafe.Pointer(pParse)).FiDepth = (*TJsonParse)(unsafe.Pointer(pParse)).FiDepth - 1
|
|
v1 = pParse + 47
|
|
*(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) | libc.Int32FromUint8((*TJsonParse)(unsafe.Pointer(pIns)).Foom))
|
|
}
|
|
return libc.Uint32FromInt32(rc) /* Error code only */
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** json_error_position(JSON)
|
|
// **
|
|
// ** If the argument is NULL, return NULL
|
|
// **
|
|
// ** If the argument is BLOB, do a full validity check and return non-zero
|
|
// ** if the check fails. The return value is the approximate 1-based offset
|
|
// ** to the byte of the element that contains the first error.
|
|
// **
|
|
// ** Otherwise interpret the argument is TEXT (even if it is numeric) and
|
|
// ** return the 1-based character position for where the parser first recognized
|
|
// ** that the input was not valid JSON, or return 0 if the input text looks
|
|
// ** ok. JSON-5 extensions are accepted.
|
|
// */
|
|
func _jsonErrorFunc(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
|
|
bp := tls.Alloc(80)
|
|
defer tls.Free(80)
|
|
var iErrPos Ti64
|
|
var k Tu32
|
|
var _ /* s at bp+0 */ TJsonParse
|
|
_, _ = iErrPos, k
|
|
iErrPos = 0
|
|
_ = argc
|
|
libc.Xmemset(tls, bp, 0, uint64(72))
|
|
(**(**TJsonParse)(__ccgo_up(bp))).Fdb = Xsqlite3_context_db_handle(tls, ctx)
|
|
if _jsonArgIsJsonb(tls, **(**uintptr)(__ccgo_up(argv)), bp) != 0 {
|
|
iErrPos = libc.Int64FromUint32(_jsonbValidityCheck(tls, bp, uint32(0), (**(**TJsonParse)(__ccgo_up(bp))).FnBlob, uint32(1)))
|
|
} else {
|
|
(**(**TJsonParse)(__ccgo_up(bp))).FzJson = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
if (**(**TJsonParse)(__ccgo_up(bp))).FzJson == uintptr(0) {
|
|
return
|
|
} /* NULL input or OOM */
|
|
(**(**TJsonParse)(__ccgo_up(bp))).FnJson = Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
if _jsonConvertTextToBlob(tls, bp, uintptr(0)) != 0 {
|
|
if (**(**TJsonParse)(__ccgo_up(bp))).Foom != 0 {
|
|
iErrPos = int64(-int32(1))
|
|
} else {
|
|
/* Because s.oom is false */
|
|
k = uint32(0)
|
|
for {
|
|
if !(k < (**(**TJsonParse)(__ccgo_up(bp))).FiErr && **(**int8)(__ccgo_up((**(**TJsonParse)(__ccgo_up(bp))).FzJson + uintptr(k))) != 0) {
|
|
break
|
|
}
|
|
if int32(**(**int8)(__ccgo_up((**(**TJsonParse)(__ccgo_up(bp))).FzJson + uintptr(k))))&int32(0xc0) != int32(0x80) {
|
|
iErrPos = iErrPos + 1
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
k = k + 1
|
|
}
|
|
iErrPos = iErrPos + 1
|
|
}
|
|
}
|
|
}
|
|
_jsonParseReset(tls, bp)
|
|
if iErrPos < 0 {
|
|
Xsqlite3_result_error_nomem(tls, ctx)
|
|
} else {
|
|
Xsqlite3_result_int64(tls, ctx, iErrPos)
|
|
}
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Open an mem file handle.
|
|
// */
|
|
func _memdbOpen(tls *libc.TLS, pVfs uintptr, zName uintptr, pFd uintptr, flags int32, pOutFlags uintptr) (r int32) {
|
|
var apNew, p, pFile, pVfsMutex, v3 uintptr
|
|
var i, szName, v2 int32
|
|
_, _, _, _, _, _, _, _ = apNew, i, p, pFile, pVfsMutex, szName, v2, v3
|
|
pFile = pFd
|
|
p = uintptr(0)
|
|
_ = pVfs
|
|
libc.Xmemset(tls, pFile, 0, uint64(24))
|
|
szName = _sqlite3Strlen30(tls, zName)
|
|
if szName > int32(1) && (int32(**(**int8)(__ccgo_up(zName))) == int32('/') || int32(**(**int8)(__ccgo_up(zName))) == int32('\\')) {
|
|
pVfsMutex = _sqlite3MutexAlloc(tls, int32(SQLITE_MUTEX_STATIC_VFS1))
|
|
Xsqlite3_mutex_enter(tls, pVfsMutex)
|
|
i = 0
|
|
for {
|
|
if !(i < _memdb_g.FnMemStore) {
|
|
break
|
|
}
|
|
if libc.Xstrcmp(tls, (*TMemStore)(unsafe.Pointer(**(**uintptr)(__ccgo_up(_memdb_g.FapMemStore + uintptr(i)*8)))).FzFName, zName) == 0 {
|
|
p = **(**uintptr)(__ccgo_up(_memdb_g.FapMemStore + uintptr(i)*8))
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if p == uintptr(0) {
|
|
p = _sqlite3Malloc(tls, uint64(72)+libc.Uint64FromInt64(int64(szName))+uint64(3))
|
|
if p == uintptr(0) {
|
|
Xsqlite3_mutex_leave(tls, pVfsMutex)
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
apNew = _sqlite3Realloc(tls, _memdb_g.FapMemStore, uint64(8)*libc.Uint64FromInt64(libc.Int64FromInt32(1)+int64(_memdb_g.FnMemStore)))
|
|
if apNew == uintptr(0) {
|
|
Xsqlite3_free(tls, p)
|
|
Xsqlite3_mutex_leave(tls, pVfsMutex)
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
v3 = uintptr(unsafe.Pointer(&_memdb_g))
|
|
v2 = *(*int32)(unsafe.Pointer(v3))
|
|
*(*int32)(unsafe.Pointer(v3)) = *(*int32)(unsafe.Pointer(v3)) + 1
|
|
**(**uintptr)(__ccgo_up(apNew + uintptr(v2)*8)) = p
|
|
_memdb_g.FapMemStore = apNew
|
|
libc.Xmemset(tls, p, 0, uint64(72))
|
|
(*TMemStore)(unsafe.Pointer(p)).FmFlags = libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_DESERIALIZE_RESIZEABLE) | libc.Int32FromInt32(SQLITE_DESERIALIZE_FREEONCLOSE))
|
|
(*TMemStore)(unsafe.Pointer(p)).FszMax = _sqlite3Config.FmxMemdbSize
|
|
(*TMemStore)(unsafe.Pointer(p)).FzFName = p + 1*72
|
|
libc.Xmemcpy(tls, (*TMemStore)(unsafe.Pointer(p)).FzFName, zName, libc.Uint64FromInt32(szName+int32(1)))
|
|
(*TMemStore)(unsafe.Pointer(p)).FpMutex = Xsqlite3_mutex_alloc(tls, SQLITE_MUTEX_FAST)
|
|
if (*TMemStore)(unsafe.Pointer(p)).FpMutex == uintptr(0) {
|
|
_memdb_g.FnMemStore = _memdb_g.FnMemStore - 1
|
|
Xsqlite3_free(tls, p)
|
|
Xsqlite3_mutex_leave(tls, pVfsMutex)
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
(*TMemStore)(unsafe.Pointer(p)).FnRef = int32(1)
|
|
_memdbEnter(tls, p)
|
|
} else {
|
|
_memdbEnter(tls, p)
|
|
(*TMemStore)(unsafe.Pointer(p)).FnRef = (*TMemStore)(unsafe.Pointer(p)).FnRef + 1
|
|
}
|
|
Xsqlite3_mutex_leave(tls, pVfsMutex)
|
|
} else {
|
|
p = _sqlite3Malloc(tls, uint64(72))
|
|
if p == uintptr(0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
libc.Xmemset(tls, p, 0, uint64(72))
|
|
(*TMemStore)(unsafe.Pointer(p)).FmFlags = libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_DESERIALIZE_RESIZEABLE) | libc.Int32FromInt32(SQLITE_DESERIALIZE_FREEONCLOSE))
|
|
(*TMemStore)(unsafe.Pointer(p)).FszMax = _sqlite3Config.FmxMemdbSize
|
|
}
|
|
(*TMemFile)(unsafe.Pointer(pFile)).FpStore = p
|
|
if pOutFlags != uintptr(0) {
|
|
**(**int32)(__ccgo_up(pOutFlags)) = flags | int32(SQLITE_OPEN_MEMORY)
|
|
}
|
|
(*Tsqlite3_file)(unsafe.Pointer(pFd)).FpMethods = uintptr(unsafe.Pointer(&_memdb_io_methods))
|
|
_memdbLeave(tls, p)
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Apply a delta.
|
|
// **
|
|
// ** The output buffer should be big enough to hold the whole output
|
|
// ** file and a NUL terminator at the end. The delta_output_size()
|
|
// ** routine will determine this size for you.
|
|
// **
|
|
// ** The delta string should be null-terminated. But the delta string
|
|
// ** may contain embedded NUL characters (if the input and output are
|
|
// ** binary files) so we also have to pass in the length of the delta in
|
|
// ** the lenDelta parameter.
|
|
// **
|
|
// ** This function returns the size of the output file in bytes (excluding
|
|
// ** the final NUL terminator character). Except, if the delta string is
|
|
// ** malformed or intended for use with a source file other than zSrc,
|
|
// ** then this routine returns -1.
|
|
// **
|
|
// ** Refer to the delta_create() documentation above for a description
|
|
// ** of the delta file format.
|
|
// */
|
|
func _rbuDeltaApply(tls *libc.TLS, zSrc uintptr, lenSrc int32, _zDelta uintptr, _lenDelta int32, zOut uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
*(*uintptr)(unsafe.Pointer(bp)) = _zDelta
|
|
*(*int32)(unsafe.Pointer(bp + 8)) = _lenDelta
|
|
var cnt, limit, ofst, total uint32
|
|
_, _, _, _ = cnt, limit, ofst, total
|
|
total = uint32(0)
|
|
limit = _rbuDeltaGetInt(tls, bp, bp+8)
|
|
if **(**int32)(__ccgo_up(bp + 8)) <= 0 || int32(**(**int8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp))))) != int32('\n') {
|
|
/* ERROR: size integer not terminated by "\n" */
|
|
return -int32(1)
|
|
}
|
|
**(**uintptr)(__ccgo_up(bp)) = **(**uintptr)(__ccgo_up(bp)) + 1
|
|
**(**int32)(__ccgo_up(bp + 8)) = **(**int32)(__ccgo_up(bp + 8)) - 1
|
|
for **(**int8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp)))) != 0 && **(**int32)(__ccgo_up(bp + 8)) > 0 {
|
|
cnt = _rbuDeltaGetInt(tls, bp, bp+8)
|
|
if **(**int32)(__ccgo_up(bp + 8)) <= 0 {
|
|
return -int32(1)
|
|
}
|
|
switch int32(**(**int8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp))))) {
|
|
case int32('@'):
|
|
**(**uintptr)(__ccgo_up(bp)) = **(**uintptr)(__ccgo_up(bp)) + 1
|
|
**(**int32)(__ccgo_up(bp + 8)) = **(**int32)(__ccgo_up(bp + 8)) - 1
|
|
ofst = _rbuDeltaGetInt(tls, bp, bp+8)
|
|
if **(**int32)(__ccgo_up(bp + 8)) > 0 || int32(**(**int8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp))))) != int32(',') {
|
|
/* ERROR: copy command not terminated by ',' */
|
|
return -int32(1)
|
|
}
|
|
**(**uintptr)(__ccgo_up(bp)) = **(**uintptr)(__ccgo_up(bp)) + 1
|
|
**(**int32)(__ccgo_up(bp + 8)) = **(**int32)(__ccgo_up(bp + 8)) - 1
|
|
total = total + cnt
|
|
if total > limit {
|
|
/* ERROR: copy exceeds output file size */
|
|
return -int32(1)
|
|
}
|
|
if uint64(ofst)+uint64(cnt) > libc.Uint64FromInt32(lenSrc) {
|
|
/* ERROR: copy extends past end of input */
|
|
return -int32(1)
|
|
}
|
|
libc.Xmemcpy(tls, zOut, zSrc+uintptr(ofst), uint64(cnt))
|
|
zOut = zOut + uintptr(cnt)
|
|
case int32(':'):
|
|
**(**uintptr)(__ccgo_up(bp)) = **(**uintptr)(__ccgo_up(bp)) + 1
|
|
**(**int32)(__ccgo_up(bp + 8)) = **(**int32)(__ccgo_up(bp + 8)) - 1
|
|
total = total + cnt
|
|
if total > limit {
|
|
/* ERROR: insert command gives an output larger than predicted */
|
|
return -int32(1)
|
|
}
|
|
if libc.Int64FromUint32(cnt) > int64(**(**int32)(__ccgo_up(bp + 8))) {
|
|
/* ERROR: insert count exceeds size of delta */
|
|
return -int32(1)
|
|
}
|
|
libc.Xmemcpy(tls, zOut, **(**uintptr)(__ccgo_up(bp)), uint64(cnt))
|
|
zOut = zOut + uintptr(cnt)
|
|
**(**uintptr)(__ccgo_up(bp)) = **(**uintptr)(__ccgo_up(bp)) + uintptr(cnt)
|
|
**(**int32)(__ccgo_up(bp + 8)) = libc.Int32FromUint32(uint32(**(**int32)(__ccgo_up(bp + 8))) - cnt)
|
|
case int32(';'):
|
|
**(**uintptr)(__ccgo_up(bp)) = **(**uintptr)(__ccgo_up(bp)) + 1
|
|
**(**int32)(__ccgo_up(bp + 8)) = **(**int32)(__ccgo_up(bp + 8)) - 1
|
|
**(**int8)(__ccgo_up(zOut)) = 0
|
|
if total != limit {
|
|
/* ERROR: generated size does not match predicted size */
|
|
return -int32(1)
|
|
}
|
|
return libc.Int32FromUint32(total)
|
|
default:
|
|
/* ERROR: unknown delta operator */
|
|
return -int32(1)
|
|
}
|
|
}
|
|
/* ERROR: unterminated delta */
|
|
return -int32(1)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Rtree virtual table module xBestIndex method. There are three
|
|
// ** table scan strategies to choose from (in order from most to
|
|
// ** least desirable):
|
|
// **
|
|
// ** idxNum idxStr Strategy
|
|
// ** ------------------------------------------------
|
|
// ** 1 Unused Direct lookup by rowid.
|
|
// ** 2 See below R-tree query or full-table scan.
|
|
// ** ------------------------------------------------
|
|
// **
|
|
// ** If strategy 1 is used, then idxStr is not meaningful. If strategy
|
|
// ** 2 is used, idxStr is formatted to contain 2 bytes for each
|
|
// ** constraint used. The first two bytes of idxStr correspond to
|
|
// ** the constraint in sqlite3_index_info.aConstraintUsage[] with
|
|
// ** (argvIndex==1) etc.
|
|
// **
|
|
// ** The first of each pair of bytes in idxStr identifies the constraint
|
|
// ** operator as follows:
|
|
// **
|
|
// ** Operator Byte Value
|
|
// ** ----------------------
|
|
// ** = 0x41 ('A')
|
|
// ** <= 0x42 ('B')
|
|
// ** < 0x43 ('C')
|
|
// ** >= 0x44 ('D')
|
|
// ** > 0x45 ('E')
|
|
// ** MATCH 0x46 ('F')
|
|
// ** ----------------------
|
|
// **
|
|
// ** The second of each pair of bytes identifies the coordinate column
|
|
// ** to which the constraint applies. The leftmost coordinate column
|
|
// ** is 'a', the second from the left 'b' etc.
|
|
// */
|
|
func _rtreeBestIndex(tls *libc.TLS, tab uintptr, pIdxInfo uintptr) (r int32) {
|
|
bp := tls.Alloc(48)
|
|
defer tls.Free(48)
|
|
var bMatch, iIdx, ii, jj, rc, v4 int32
|
|
var doOmit, op Tu8
|
|
var nRow Ti64
|
|
var p, pRtree uintptr
|
|
var _ /* zIdxStr at bp+0 */ [41]int8
|
|
_, _, _, _, _, _, _, _, _, _, _ = bMatch, doOmit, iIdx, ii, jj, nRow, op, p, pRtree, rc, v4
|
|
pRtree = tab
|
|
rc = SQLITE_OK
|
|
bMatch = 0 /* Estimated rows returned by this scan */
|
|
iIdx = 0
|
|
libc.Xmemset(tls, bp, 0, uint64(41))
|
|
/* Check if there exists a MATCH constraint - even an unusable one. If there
|
|
** is, do not consider the lookup-by-rowid plan as using such a plan would
|
|
** require the VDBE to evaluate the MATCH constraint, which is not currently
|
|
** possible. */
|
|
ii = 0
|
|
for {
|
|
if !(ii < (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FnConstraint) {
|
|
break
|
|
}
|
|
if libc.Int32FromUint8((**(**Tsqlite3_index_constraint)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraint + uintptr(ii)*12))).Fop) == int32(SQLITE_INDEX_CONSTRAINT_MATCH) {
|
|
bMatch = int32(1)
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
ii = 0
|
|
for {
|
|
if !(ii < (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FnConstraint && iIdx < libc.Int32FromUint64(libc.Uint64FromInt64(41)-libc.Uint64FromInt32(1))) {
|
|
break
|
|
}
|
|
p = (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraint + uintptr(ii)*12
|
|
if bMatch == 0 && (*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fusable != 0 && (*Tsqlite3_index_constraint)(unsafe.Pointer(p)).FiColumn <= 0 && libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fop) == int32(SQLITE_INDEX_CONSTRAINT_EQ) {
|
|
jj = 0
|
|
for {
|
|
if !(jj < ii) {
|
|
break
|
|
}
|
|
(**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraintUsage + uintptr(jj)*8))).FargvIndex = 0
|
|
(**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraintUsage + uintptr(jj)*8))).Fomit = uint8(0)
|
|
goto _3
|
|
_3:
|
|
;
|
|
jj = jj + 1
|
|
}
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FidxNum = int32(1)
|
|
(**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraintUsage + uintptr(ii)*8))).FargvIndex = int32(1)
|
|
(**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraintUsage + uintptr(jj)*8))).Fomit = uint8(1)
|
|
/* This strategy involves a two rowid lookups on an B-Tree structures
|
|
** and then a linear search of an R-Tree node. This should be
|
|
** considered almost as quick as a direct rowid lookup (for which
|
|
** sqlite uses an internal cost of 0.0). It is expected to return
|
|
** a single row.
|
|
*/
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FestimatedCost = float64(30)
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FestimatedRows = int64(1)
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FidxFlags = int32(SQLITE_INDEX_SCAN_UNIQUE)
|
|
return SQLITE_OK
|
|
}
|
|
if (*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fusable != 0 && ((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).FiColumn > 0 && (*Tsqlite3_index_constraint)(unsafe.Pointer(p)).FiColumn <= libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FnDim2) || libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fop) == int32(SQLITE_INDEX_CONSTRAINT_MATCH)) {
|
|
doOmit = uint8(1)
|
|
switch libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fop) {
|
|
case int32(SQLITE_INDEX_CONSTRAINT_EQ):
|
|
op = uint8(RTREE_EQ)
|
|
doOmit = uint8(0)
|
|
case int32(SQLITE_INDEX_CONSTRAINT_GT):
|
|
op = uint8(RTREE_GT)
|
|
doOmit = uint8(0)
|
|
case int32(SQLITE_INDEX_CONSTRAINT_LE):
|
|
op = uint8(RTREE_LE)
|
|
case int32(SQLITE_INDEX_CONSTRAINT_LT):
|
|
op = uint8(RTREE_LT)
|
|
doOmit = uint8(0)
|
|
case int32(SQLITE_INDEX_CONSTRAINT_GE):
|
|
op = uint8(RTREE_GE)
|
|
case int32(SQLITE_INDEX_CONSTRAINT_MATCH):
|
|
op = uint8(RTREE_MATCH)
|
|
default:
|
|
op = uint8(0)
|
|
break
|
|
}
|
|
if op != 0 {
|
|
v4 = iIdx
|
|
iIdx = iIdx + 1
|
|
(**(**[41]int8)(__ccgo_up(bp)))[v4] = libc.Int8FromUint8(op)
|
|
v4 = iIdx
|
|
iIdx = iIdx + 1
|
|
(**(**[41]int8)(__ccgo_up(bp)))[v4] = int8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).FiColumn - libc.Int32FromInt32(1) + libc.Int32FromUint8('0'))
|
|
(**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraintUsage + uintptr(ii)*8))).FargvIndex = iIdx / int32(2)
|
|
(**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraintUsage + uintptr(ii)*8))).Fomit = doOmit
|
|
}
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FidxNum = int32(2)
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FneedToFreeIdxStr = int32(1)
|
|
if iIdx > 0 {
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FidxStr = Xsqlite3_malloc(tls, iIdx+int32(1))
|
|
if (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FidxStr == uintptr(0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
libc.Xmemcpy(tls, (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FidxStr, bp, libc.Uint64FromInt32(iIdx+int32(1)))
|
|
}
|
|
nRow = (*TRtree)(unsafe.Pointer(pRtree)).FnRowEst >> (iIdx / int32(2))
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FestimatedCost = float64(libc.Float64FromFloat64(6) * float64(nRow))
|
|
(*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FestimatedRows = nRow
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Rtree virtual table module xFilter method.
|
|
// */
|
|
func _rtreeFilter(tls *libc.TLS, pVtabCursor uintptr, idxNum int32, idxStr uintptr, argc int32, argv uintptr) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var eType, eType1, ii, rc int32
|
|
var iRowid Ti64
|
|
var iVal Tsqlite3_int64
|
|
var p, p1, pCsr, pNew, pRtree uintptr
|
|
var _ /* iCell at bp+8 */ int32
|
|
var _ /* iNode at bp+24 */ Ti64
|
|
var _ /* pLeaf at bp+16 */ uintptr
|
|
var _ /* pRoot at bp+0 */ uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _ = eType, eType1, iRowid, iVal, ii, p, p1, pCsr, pNew, pRtree, rc
|
|
pRtree = (*Tsqlite3_vtab_cursor)(unsafe.Pointer(pVtabCursor)).FpVtab
|
|
pCsr = pVtabCursor
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
rc = SQLITE_OK
|
|
**(**int32)(__ccgo_up(bp + 8)) = 0
|
|
_rtreeReference(tls, pRtree)
|
|
/* Reset the cursor to the same state as rtreeOpen() leaves it in. */
|
|
_resetCursor(tls, pCsr)
|
|
(*TRtreeCursor)(unsafe.Pointer(pCsr)).FiStrategy = idxNum
|
|
if idxNum == int32(1) { /* Search point for the leaf */
|
|
iRowid = Xsqlite3_value_int64(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
**(**Ti64)(__ccgo_up(bp + 24)) = 0
|
|
eType = Xsqlite3_value_numeric_type(tls, **(**uintptr)(__ccgo_up(argv)))
|
|
if eType == int32(SQLITE_INTEGER) || eType == int32(SQLITE_FLOAT) && 0 == _sqlite3IntFloatCompare(tls, iRowid, Xsqlite3_value_double(tls, **(**uintptr)(__ccgo_up(argv)))) {
|
|
rc = _findLeafNode(tls, pRtree, iRowid, bp+16, bp+24)
|
|
} else {
|
|
rc = SQLITE_OK
|
|
**(**uintptr)(__ccgo_up(bp + 16)) = uintptr(0)
|
|
}
|
|
if rc == SQLITE_OK && **(**uintptr)(__ccgo_up(bp + 16)) != uintptr(0) {
|
|
p = _rtreeSearchPointNew(tls, pCsr, float64(0), uint8(0))
|
|
/* Always returns pCsr->sPoint */
|
|
**(**uintptr)(__ccgo_up(pCsr + 88)) = **(**uintptr)(__ccgo_up(bp + 16))
|
|
(*TRtreeSearchPoint)(unsafe.Pointer(p)).Fid = **(**Ti64)(__ccgo_up(bp + 24))
|
|
(*TRtreeSearchPoint)(unsafe.Pointer(p)).FeWithin = uint8(PARTLY_WITHIN)
|
|
rc = _nodeRowidIndex(tls, pRtree, **(**uintptr)(__ccgo_up(bp + 16)), iRowid, bp+8)
|
|
(*TRtreeSearchPoint)(unsafe.Pointer(p)).FiCell = libc.Uint8FromInt32(**(**int32)(__ccgo_up(bp + 8)))
|
|
} else {
|
|
(*TRtreeCursor)(unsafe.Pointer(pCsr)).FatEOF = uint8(1)
|
|
}
|
|
} else {
|
|
/* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array
|
|
** with the configured constraints.
|
|
*/
|
|
rc = _nodeAcquire(tls, pRtree, int64(1), uintptr(0), bp)
|
|
if rc == SQLITE_OK && argc > 0 {
|
|
(*TRtreeCursor)(unsafe.Pointer(pCsr)).FaConstraint = Xsqlite3_malloc64(tls, uint64(uint64(24)*libc.Uint64FromInt32(argc)))
|
|
(*TRtreeCursor)(unsafe.Pointer(pCsr)).FnConstraint = argc
|
|
if !((*TRtreeCursor)(unsafe.Pointer(pCsr)).FaConstraint != 0) {
|
|
rc = int32(SQLITE_NOMEM)
|
|
} else {
|
|
libc.Xmemset(tls, (*TRtreeCursor)(unsafe.Pointer(pCsr)).FaConstraint, 0, uint64(24)*libc.Uint64FromInt32(argc))
|
|
libc.Xmemset(tls, pCsr+128, 0, uint64(4)*libc.Uint64FromInt32((*TRtree)(unsafe.Pointer(pRtree)).FiDepth+libc.Int32FromInt32(1)))
|
|
ii = 0
|
|
for {
|
|
if !(ii < argc) {
|
|
break
|
|
}
|
|
p1 = (*TRtreeCursor)(unsafe.Pointer(pCsr)).FaConstraint + uintptr(ii)*24
|
|
eType1 = Xsqlite3_value_numeric_type(tls, **(**uintptr)(__ccgo_up(argv + uintptr(ii)*8)))
|
|
(*TRtreeConstraint)(unsafe.Pointer(p1)).Fop = int32(**(**int8)(__ccgo_up(idxStr + uintptr(ii*int32(2)))))
|
|
(*TRtreeConstraint)(unsafe.Pointer(p1)).FiCoord = int32(**(**int8)(__ccgo_up(idxStr + uintptr(ii*int32(2)+int32(1))))) - int32('0')
|
|
if (*TRtreeConstraint)(unsafe.Pointer(p1)).Fop >= int32(RTREE_MATCH) {
|
|
/* A MATCH operator. The right-hand-side must be a blob that
|
|
** can be cast into an RtreeMatchArg object. One created using
|
|
** an sqlite3_rtree_geometry_callback() SQL user function.
|
|
*/
|
|
rc = _deserializeGeometry(tls, **(**uintptr)(__ccgo_up(argv + uintptr(ii)*8)), p1)
|
|
if rc != SQLITE_OK {
|
|
break
|
|
}
|
|
(*Tsqlite3_rtree_query_info)(unsafe.Pointer((*TRtreeConstraint)(unsafe.Pointer(p1)).FpInfo)).FnCoord = libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FnDim2)
|
|
(*Tsqlite3_rtree_query_info)(unsafe.Pointer((*TRtreeConstraint)(unsafe.Pointer(p1)).FpInfo)).FanQueue = pCsr + 128
|
|
(*Tsqlite3_rtree_query_info)(unsafe.Pointer((*TRtreeConstraint)(unsafe.Pointer(p1)).FpInfo)).FmxLevel = (*TRtree)(unsafe.Pointer(pRtree)).FiDepth + int32(1)
|
|
} else {
|
|
if eType1 == int32(SQLITE_INTEGER) {
|
|
iVal = Xsqlite3_value_int64(tls, **(**uintptr)(__ccgo_up(argv + uintptr(ii)*8)))
|
|
*(*TRtreeDValue)(unsafe.Pointer(p1 + 8)) = float64(iVal)
|
|
if iVal >= libc.Int64FromInt32(1)<<libc.Int32FromInt32(48) || iVal <= -(libc.Int64FromInt32(1)<<libc.Int32FromInt32(48)) {
|
|
if (*TRtreeConstraint)(unsafe.Pointer(p1)).Fop == int32(RTREE_LT) {
|
|
(*TRtreeConstraint)(unsafe.Pointer(p1)).Fop = int32(RTREE_LE)
|
|
}
|
|
if (*TRtreeConstraint)(unsafe.Pointer(p1)).Fop == int32(RTREE_GT) {
|
|
(*TRtreeConstraint)(unsafe.Pointer(p1)).Fop = int32(RTREE_GE)
|
|
}
|
|
}
|
|
} else {
|
|
if eType1 == int32(SQLITE_FLOAT) {
|
|
*(*TRtreeDValue)(unsafe.Pointer(p1 + 8)) = Xsqlite3_value_double(tls, **(**uintptr)(__ccgo_up(argv + uintptr(ii)*8)))
|
|
} else {
|
|
*(*TRtreeDValue)(unsafe.Pointer(p1 + 8)) = float64(0)
|
|
if eType1 == int32(SQLITE_NULL) {
|
|
(*TRtreeConstraint)(unsafe.Pointer(p1)).Fop = int32(RTREE_FALSE)
|
|
} else {
|
|
if (*TRtreeConstraint)(unsafe.Pointer(p1)).Fop == int32(RTREE_LT) || (*TRtreeConstraint)(unsafe.Pointer(p1)).Fop == int32(RTREE_LE) {
|
|
(*TRtreeConstraint)(unsafe.Pointer(p1)).Fop = int32(RTREE_TRUE)
|
|
} else {
|
|
(*TRtreeConstraint)(unsafe.Pointer(p1)).Fop = int32(RTREE_FALSE)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
ii = ii + 1
|
|
}
|
|
}
|
|
}
|
|
if rc == SQLITE_OK {
|
|
/* Due to the resetCursor() call above */
|
|
pNew = _rtreeSearchPointNew(tls, pCsr, float64(0), libc.Uint8FromInt32((*TRtree)(unsafe.Pointer(pRtree)).FiDepth+libc.Int32FromInt32(1)))
|
|
if pNew == uintptr(0) { /* Because pCsr->bPoint was FALSE */
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
(*TRtreeSearchPoint)(unsafe.Pointer(pNew)).Fid = int64(1)
|
|
(*TRtreeSearchPoint)(unsafe.Pointer(pNew)).FiCell = uint8(0)
|
|
(*TRtreeSearchPoint)(unsafe.Pointer(pNew)).FeWithin = uint8(PARTLY_WITHIN)
|
|
**(**uintptr)(__ccgo_up(pCsr + 88)) = **(**uintptr)(__ccgo_up(bp))
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0)
|
|
rc = _rtreeStepToLeaf(tls, pCsr)
|
|
}
|
|
}
|
|
_nodeRelease(tls, pRtree, **(**uintptr)(__ccgo_up(bp)))
|
|
_rtreeRelease(tls, pRtree)
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This routine is the core allocator for Expr nodes.
|
|
// **
|
|
// ** Construct a new expression node and return a pointer to it. Memory
|
|
// ** for this node and for the pToken argument is a single allocation
|
|
// ** obtained from sqlite3DbMalloc(). The calling function
|
|
// ** is responsible for making sure the node eventually gets freed.
|
|
// **
|
|
// ** If dequote is true, then the token (if it exists) is dequoted.
|
|
// ** If dequote is false, no dequoting is performed. The deQuote
|
|
// ** parameter is ignored if pToken is NULL or if the token does not
|
|
// ** appear to be quoted. If the quotes were of the form "..." (double-quotes)
|
|
// ** then the EP_DblQuoted flag is set on the expression node.
|
|
// **
|
|
// ** Special case (tag-20240227-a): If op==TK_INTEGER and pToken points to
|
|
// ** a string that can be translated into a 32-bit integer, then the token is
|
|
// ** not stored in u.zToken. Instead, the integer values is written
|
|
// ** into u.iValue and the EP_IntValue flag is set. No extra storage
|
|
// ** is allocated to hold the integer text and the dequote flag is ignored.
|
|
// ** See also tag-20240227-b.
|
|
// */
|
|
func _sqlite3ExprAlloc(tls *libc.TLS, db uintptr, op int32, pToken uintptr, dequote int32) (r uintptr) {
|
|
var nExtra int32
|
|
var pNew uintptr
|
|
var v1 uint32
|
|
_, _, _ = nExtra, pNew, v1
|
|
if pToken != 0 {
|
|
v1 = (*TToken)(unsafe.Pointer(pToken)).Fn + uint32(1)
|
|
} else {
|
|
v1 = uint32(0)
|
|
}
|
|
nExtra = libc.Int32FromUint32(v1)
|
|
pNew = _sqlite3DbMallocRawNN(tls, db, uint64(uint64(72)+libc.Uint64FromInt32(nExtra)))
|
|
if pNew != 0 {
|
|
libc.Xmemset(tls, pNew, 0, uint64(72))
|
|
(*TExpr)(unsafe.Pointer(pNew)).Fop = libc.Uint8FromInt32(op)
|
|
(*TExpr)(unsafe.Pointer(pNew)).FiAgg = int16(-int32(1))
|
|
if nExtra != 0 {
|
|
*(*uintptr)(unsafe.Pointer(pNew + 8)) = pNew + 1*72
|
|
if (*TToken)(unsafe.Pointer(pToken)).Fn != 0 {
|
|
libc.Xmemcpy(tls, *(*uintptr)(unsafe.Pointer(pNew + 8)), (*TToken)(unsafe.Pointer(pToken)).Fz, uint64((*TToken)(unsafe.Pointer(pToken)).Fn))
|
|
}
|
|
**(**int8)(__ccgo_up(*(*uintptr)(unsafe.Pointer(pNew + 8)) + uintptr((*TToken)(unsafe.Pointer(pToken)).Fn))) = 0
|
|
if dequote != 0 && libc.Int32FromUint8(_sqlite3CtypeMap[libc.Uint8FromInt8(**(**int8)(__ccgo_up(*(*uintptr)(unsafe.Pointer(pNew + 8)))))])&int32(0x80) != 0 {
|
|
_sqlite3DequoteExpr(tls, pNew)
|
|
}
|
|
}
|
|
(*TExpr)(unsafe.Pointer(pNew)).FnHeight = int32(1)
|
|
}
|
|
return pNew
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Locate a user function given a name, a number of arguments and a flag
|
|
// ** indicating whether the function prefers UTF-16 over UTF-8. Return a
|
|
// ** pointer to the FuncDef structure that defines that function, or return
|
|
// ** NULL if the function does not exist.
|
|
// **
|
|
// ** If the createFlag argument is true, then a new (blank) FuncDef
|
|
// ** structure is created and liked into the "db" structure if a
|
|
// ** no matching function previously existed.
|
|
// **
|
|
// ** If nArg is -2, then the first valid function found is returned. A
|
|
// ** function is valid if xSFunc is non-zero. The nArg==(-2)
|
|
// ** case is used to see if zName is a valid function name for some number
|
|
// ** of arguments. If nArg is -2, then createFlag must be 0.
|
|
// **
|
|
// ** If createFlag is false, then a function with the required name and
|
|
// ** number of arguments may be returned even if the eTextRep flag does not
|
|
// ** match that requested.
|
|
// */
|
|
func _sqlite3FindFunction(tls *libc.TLS, db uintptr, zName uintptr, nArg int32, enc Tu8, createFlag Tu8) (r uintptr) {
|
|
var bestScore, h, nName, score, score1 int32
|
|
var p, pBest, pOther, z, v1 uintptr
|
|
var v2 bool
|
|
_, _, _, _, _, _, _, _, _, _, _ = bestScore, h, nName, p, pBest, pOther, score, score1, z, v1, v2 /* Iterator variable */
|
|
pBest = uintptr(0) /* Best match found so far */
|
|
bestScore = 0 /* Length of the name */
|
|
nName = _sqlite3Strlen30(tls, zName)
|
|
/* First search for a match amongst the application-defined functions.
|
|
*/
|
|
p = _sqlite3HashFind(tls, db+624, zName)
|
|
for p != 0 {
|
|
score = _matchQuality(tls, p, nArg, enc)
|
|
if score > bestScore {
|
|
pBest = p
|
|
bestScore = score
|
|
}
|
|
p = (*TFuncDef)(unsafe.Pointer(p)).FpNext
|
|
}
|
|
/* If no match is found, search the built-in functions.
|
|
**
|
|
** If the DBFLAG_PreferBuiltin flag is set, then search the built-in
|
|
** functions even if a prior app-defined function was found. And give
|
|
** priority to built-in functions.
|
|
**
|
|
** Except, if createFlag is true, that means that we are trying to
|
|
** install a new function. Whatever FuncDef structure is returned it will
|
|
** have fields overwritten with new information appropriate for the
|
|
** new function. But the FuncDefs for built-in functions are read-only.
|
|
** So we must not search for built-ins when creating a new function.
|
|
*/
|
|
if !(createFlag != 0) && (pBest == uintptr(0) || (*Tsqlite3)(unsafe.Pointer(db)).FmDbFlags&uint32(DBFLAG_PreferBuiltin) != uint32(0)) {
|
|
bestScore = 0
|
|
h = (libc.Int32FromUint8(_sqlite3UpperToLower[libc.Uint8FromInt8(**(**int8)(__ccgo_up(zName)))]) + nName) % int32(SQLITE_FUNC_HASH_SZ)
|
|
p = _sqlite3FunctionSearch(tls, h, zName)
|
|
for p != 0 {
|
|
score1 = _matchQuality(tls, p, nArg, enc)
|
|
if score1 > bestScore {
|
|
pBest = p
|
|
bestScore = score1
|
|
}
|
|
p = (*TFuncDef)(unsafe.Pointer(p)).FpNext
|
|
}
|
|
}
|
|
/* If the createFlag parameter is true and the search did not reveal an
|
|
** exact match for the name, number of arguments and encoding, then add a
|
|
** new entry to the hash table and return it.
|
|
*/
|
|
if v2 = createFlag != 0 && bestScore < int32(FUNC_PERFECT_MATCH); v2 {
|
|
v1 = _sqlite3DbMallocZero(tls, db, uint64(uint64(72)+libc.Uint64FromInt32(nName)+uint64(1)))
|
|
pBest = v1
|
|
}
|
|
if v2 && v1 != uintptr(0) {
|
|
(*TFuncDef)(unsafe.Pointer(pBest)).FzName = pBest + 1*72
|
|
(*TFuncDef)(unsafe.Pointer(pBest)).FnArg = libc.Int16FromUint16(libc.Uint16FromInt32(nArg))
|
|
(*TFuncDef)(unsafe.Pointer(pBest)).FfuncFlags = uint32(enc)
|
|
libc.Xmemcpy(tls, pBest+1*72, zName, libc.Uint64FromInt32(nName+int32(1)))
|
|
z = (*TFuncDef)(unsafe.Pointer(pBest)).FzName
|
|
for {
|
|
if !(**(**Tu8)(__ccgo_up(z)) != 0) {
|
|
break
|
|
}
|
|
**(**Tu8)(__ccgo_up(z)) = _sqlite3UpperToLower[**(**Tu8)(__ccgo_up(z))]
|
|
goto _3
|
|
_3:
|
|
;
|
|
z = z + 1
|
|
}
|
|
pOther = _sqlite3HashInsert(tls, db+624, (*TFuncDef)(unsafe.Pointer(pBest)).FzName, pBest)
|
|
if pOther == pBest {
|
|
_sqlite3DbFree(tls, db, pBest)
|
|
_sqlite3OomFault(tls, db)
|
|
return uintptr(0)
|
|
} else {
|
|
(*TFuncDef)(unsafe.Pointer(pBest)).FpNext = pOther
|
|
}
|
|
}
|
|
if pBest != 0 && ((*TFuncDef)(unsafe.Pointer(pBest)).FxSFunc != 0 || createFlag != 0) {
|
|
return pBest
|
|
}
|
|
return uintptr(0)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Parameter zIn contains a rank() function specification. The format of
|
|
// ** this is:
|
|
// **
|
|
// ** + Bareword (function name)
|
|
// ** + Open parenthesis - "("
|
|
// ** + Zero or more SQL literals in a comma separated list
|
|
// ** + Close parenthesis - ")"
|
|
// */
|
|
func _sqlite3Fts5ConfigParseRank(tls *libc.TLS, zIn uintptr, pzRank uintptr, pzRankArgs uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var p, pArgs, pRank, zRank, zRankArgs uintptr
|
|
var _ /* rc at bp+0 */ int32
|
|
_, _, _, _, _ = p, pArgs, pRank, zRank, zRankArgs
|
|
p = zIn
|
|
zRank = uintptr(0)
|
|
zRankArgs = uintptr(0)
|
|
**(**int32)(__ccgo_up(bp)) = SQLITE_OK
|
|
**(**uintptr)(__ccgo_up(pzRank)) = uintptr(0)
|
|
**(**uintptr)(__ccgo_up(pzRankArgs)) = uintptr(0)
|
|
if p == uintptr(0) {
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
} else {
|
|
p = _fts5ConfigSkipWhitespace(tls, p)
|
|
pRank = p
|
|
p = _fts5ConfigSkipBareword(tls, p)
|
|
if p != 0 {
|
|
zRank = _sqlite3Fts5MallocZero(tls, bp, int64(uintptr(1)+p)-int64(pRank))
|
|
if zRank != 0 {
|
|
libc.Xmemcpy(tls, zRank, pRank, libc.Uint64FromInt64(int64(p)-int64(pRank)))
|
|
}
|
|
} else {
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
}
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
p = _fts5ConfigSkipWhitespace(tls, p)
|
|
if int32(**(**int8)(__ccgo_up(p))) != int32('(') {
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
}
|
|
p = p + 1
|
|
}
|
|
if **(**int32)(__ccgo_up(bp)) == SQLITE_OK {
|
|
p = _fts5ConfigSkipWhitespace(tls, p)
|
|
pArgs = p
|
|
if int32(**(**int8)(__ccgo_up(p))) != int32(')') {
|
|
p = _fts5ConfigSkipArgs(tls, p)
|
|
if p == uintptr(0) {
|
|
**(**int32)(__ccgo_up(bp)) = int32(SQLITE_ERROR)
|
|
} else {
|
|
zRankArgs = _sqlite3Fts5MallocZero(tls, bp, int64(uintptr(1)+p)-int64(pArgs))
|
|
if zRankArgs != 0 {
|
|
libc.Xmemcpy(tls, zRankArgs, pArgs, libc.Uint64FromInt64(int64(p)-int64(pArgs)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if **(**int32)(__ccgo_up(bp)) != SQLITE_OK {
|
|
Xsqlite3_free(tls, zRank)
|
|
} else {
|
|
**(**uintptr)(__ccgo_up(pzRank)) = zRank
|
|
**(**uintptr)(__ccgo_up(pzRankArgs)) = zRankArgs
|
|
}
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Add an entry to the in-memory hash table. The key is the concatenation
|
|
// ** of bByte and (pToken/nToken). The value is (iRowid/iCol/iPos).
|
|
// **
|
|
// ** (bByte || pToken) -> (iRowid,iCol,iPos)
|
|
// **
|
|
// ** Or, if iCol is negative, then the value is a delete marker.
|
|
// */
|
|
func _sqlite3Fts5HashWrite(tls *libc.TLS, pHash uintptr, iRowid Ti64, iCol int32, iPos int32, bByte int8, pToken uintptr, nToken int32) (r int32) {
|
|
var bNew, nIncr, rc, v2 int32
|
|
var iDiff Tu64
|
|
var iHash uint32
|
|
var nByte, nNew Tsqlite3_int64
|
|
var p, pNew, pPtr, pp, zKey, zKey1, v6 uintptr
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = bNew, iDiff, iHash, nByte, nIncr, nNew, p, pNew, pPtr, pp, rc, zKey, zKey1, v2, v6
|
|
nIncr = 0 /* If non-delete entry should be written */
|
|
bNew = libc.BoolInt32((*TFts5Hash)(unsafe.Pointer(pHash)).FeDetail == FTS5_DETAIL_FULL)
|
|
/* Attempt to locate an existing hash entry */
|
|
iHash = _fts5HashKey2(tls, (*TFts5Hash)(unsafe.Pointer(pHash)).FnSlot, libc.Uint8FromInt8(bByte), pToken, nToken)
|
|
p = **(**uintptr)(__ccgo_up((*TFts5Hash)(unsafe.Pointer(pHash)).FaSlot + uintptr(iHash)*8))
|
|
for {
|
|
if !(p != 0) {
|
|
break
|
|
}
|
|
zKey = p + 1*48
|
|
if int32(**(**int8)(__ccgo_up(zKey))) == int32(bByte) && (*TFts5HashEntry)(unsafe.Pointer(p)).FnKey == nToken+int32(1) && libc.Xmemcmp(tls, zKey+1, pToken, libc.Uint64FromInt32(nToken)) == 0 {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
p = (*TFts5HashEntry)(unsafe.Pointer(p)).FpHashNext
|
|
}
|
|
/* If an existing hash entry cannot be found, create a new one. */
|
|
if p == uintptr(0) {
|
|
nByte = libc.Int64FromUint64(uint64(48) + libc.Uint64FromInt32(nToken+libc.Int32FromInt32(1)) + uint64(1) + uint64(64))
|
|
if nByte < int64(128) {
|
|
nByte = int64(128)
|
|
}
|
|
/* Grow the Fts5Hash.aSlot[] array if necessary. */
|
|
if (*TFts5Hash)(unsafe.Pointer(pHash)).FnEntry*int32(2) >= (*TFts5Hash)(unsafe.Pointer(pHash)).FnSlot {
|
|
rc = _fts5HashResize(tls, pHash)
|
|
if rc != SQLITE_OK {
|
|
return rc
|
|
}
|
|
iHash = _fts5HashKey2(tls, (*TFts5Hash)(unsafe.Pointer(pHash)).FnSlot, libc.Uint8FromInt8(bByte), pToken, nToken)
|
|
}
|
|
/* Allocate new Fts5HashEntry and add it to the hash table. */
|
|
p = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(nByte))
|
|
if !(p != 0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
libc.Xmemset(tls, p, 0, uint64(48))
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FnAlloc = int32(nByte)
|
|
zKey1 = p + 1*48
|
|
**(**int8)(__ccgo_up(zKey1)) = bByte
|
|
libc.Xmemcpy(tls, zKey1+1, pToken, libc.Uint64FromInt32(nToken))
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FnKey = nToken + int32(1)
|
|
**(**int8)(__ccgo_up(zKey1 + uintptr(nToken+int32(1)))) = int8('\000')
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FnData = libc.Int32FromUint64(libc.Uint64FromInt32(nToken+int32(1)) + uint64(48))
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FpHashNext = **(**uintptr)(__ccgo_up((*TFts5Hash)(unsafe.Pointer(pHash)).FaSlot + uintptr(iHash)*8))
|
|
**(**uintptr)(__ccgo_up((*TFts5Hash)(unsafe.Pointer(pHash)).FaSlot + uintptr(iHash)*8)) = p
|
|
(*TFts5Hash)(unsafe.Pointer(pHash)).FnEntry = (*TFts5Hash)(unsafe.Pointer(pHash)).FnEntry + 1
|
|
/* Add the first rowid field to the hash-entry */
|
|
**(**int32)(__ccgo_up(p + 24)) += _sqlite3Fts5PutVarint(tls, p+uintptr((*TFts5HashEntry)(unsafe.Pointer(p)).FnData), libc.Uint64FromInt64(iRowid))
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiRowid = iRowid
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiSzPoslist = (*TFts5HashEntry)(unsafe.Pointer(p)).FnData
|
|
if (*TFts5Hash)(unsafe.Pointer(pHash)).FeDetail != int32(FTS5_DETAIL_NONE) {
|
|
**(**int32)(__ccgo_up(p + 24)) += int32(1)
|
|
if (*TFts5Hash)(unsafe.Pointer(pHash)).FeDetail == FTS5_DETAIL_FULL {
|
|
v2 = 0
|
|
} else {
|
|
v2 = -int32(1)
|
|
}
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiCol = int16(v2)
|
|
}
|
|
} else {
|
|
/* Appending to an existing hash-entry. Check that there is enough
|
|
** space to append the largest possible new entry. Worst case scenario
|
|
** is:
|
|
**
|
|
** + 9 bytes for a new rowid,
|
|
** + 4 byte reserved for the "poslist size" varint.
|
|
** + 1 byte for a "new column" byte,
|
|
** + 3 bytes for a new column number (16-bit max) as a varint,
|
|
** + 5 bytes for the new position offset (32-bit max).
|
|
*/
|
|
if (*TFts5HashEntry)(unsafe.Pointer(p)).FnAlloc-(*TFts5HashEntry)(unsafe.Pointer(p)).FnData < libc.Int32FromInt32(9)+libc.Int32FromInt32(4)+libc.Int32FromInt32(1)+libc.Int32FromInt32(3)+libc.Int32FromInt32(5) {
|
|
nNew = int64((*TFts5HashEntry)(unsafe.Pointer(p)).FnAlloc * int32(2))
|
|
pNew = Xsqlite3_realloc64(tls, p, libc.Uint64FromInt64(nNew))
|
|
if pNew == uintptr(0) {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
(*TFts5HashEntry)(unsafe.Pointer(pNew)).FnAlloc = int32(nNew)
|
|
pp = (*TFts5Hash)(unsafe.Pointer(pHash)).FaSlot + uintptr(iHash)*8
|
|
for {
|
|
if !(**(**uintptr)(__ccgo_up(pp)) != p) {
|
|
break
|
|
}
|
|
goto _3
|
|
_3:
|
|
;
|
|
pp = **(**uintptr)(__ccgo_up(pp))
|
|
}
|
|
**(**uintptr)(__ccgo_up(pp)) = pNew
|
|
p = pNew
|
|
}
|
|
nIncr = nIncr - (*TFts5HashEntry)(unsafe.Pointer(p)).FnData
|
|
}
|
|
pPtr = p
|
|
/* If this is a new rowid, append the 4-byte size field for the previous
|
|
** entry, and the new rowid for this entry. */
|
|
if iRowid != (*TFts5HashEntry)(unsafe.Pointer(p)).FiRowid {
|
|
iDiff = libc.Uint64FromInt64(iRowid) - libc.Uint64FromInt64((*TFts5HashEntry)(unsafe.Pointer(p)).FiRowid)
|
|
_fts5HashAddPoslistSize(tls, pHash, p, uintptr(0))
|
|
**(**int32)(__ccgo_up(p + 24)) += _sqlite3Fts5PutVarint(tls, pPtr+uintptr((*TFts5HashEntry)(unsafe.Pointer(p)).FnData), iDiff)
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiRowid = iRowid
|
|
bNew = int32(1)
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiSzPoslist = (*TFts5HashEntry)(unsafe.Pointer(p)).FnData
|
|
if (*TFts5Hash)(unsafe.Pointer(pHash)).FeDetail != int32(FTS5_DETAIL_NONE) {
|
|
**(**int32)(__ccgo_up(p + 24)) += int32(1)
|
|
if (*TFts5Hash)(unsafe.Pointer(pHash)).FeDetail == FTS5_DETAIL_FULL {
|
|
v2 = 0
|
|
} else {
|
|
v2 = -int32(1)
|
|
}
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiCol = int16(v2)
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiPos = 0
|
|
}
|
|
}
|
|
if iCol >= 0 {
|
|
if (*TFts5Hash)(unsafe.Pointer(pHash)).FeDetail == int32(FTS5_DETAIL_NONE) {
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FbContent = uint8(1)
|
|
} else {
|
|
/* Append a new column value, if necessary */
|
|
if iCol != int32((*TFts5HashEntry)(unsafe.Pointer(p)).FiCol) {
|
|
if (*TFts5Hash)(unsafe.Pointer(pHash)).FeDetail == FTS5_DETAIL_FULL {
|
|
v6 = p + 24
|
|
v2 = *(*int32)(unsafe.Pointer(v6))
|
|
*(*int32)(unsafe.Pointer(v6)) = *(*int32)(unsafe.Pointer(v6)) + 1
|
|
**(**Tu8)(__ccgo_up(pPtr + uintptr(v2))) = uint8(0x01)
|
|
**(**int32)(__ccgo_up(p + 24)) += _sqlite3Fts5PutVarint(tls, pPtr+uintptr((*TFts5HashEntry)(unsafe.Pointer(p)).FnData), libc.Uint64FromInt32(iCol))
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiCol = int16(iCol)
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiPos = 0
|
|
} else {
|
|
bNew = int32(1)
|
|
v2 = iCol
|
|
iPos = v2
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiCol = int16(v2)
|
|
}
|
|
}
|
|
/* Append the new position offset, if necessary */
|
|
if bNew != 0 {
|
|
**(**int32)(__ccgo_up(p + 24)) += _sqlite3Fts5PutVarint(tls, pPtr+uintptr((*TFts5HashEntry)(unsafe.Pointer(p)).FnData), libc.Uint64FromInt32(iPos-(*TFts5HashEntry)(unsafe.Pointer(p)).FiPos+int32(2)))
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FiPos = iPos
|
|
}
|
|
}
|
|
} else {
|
|
/* This is a delete. Set the delete flag. */
|
|
(*TFts5HashEntry)(unsafe.Pointer(p)).FbDel = uint8(1)
|
|
}
|
|
nIncr = nIncr + (*TFts5HashEntry)(unsafe.Pointer(p)).FnData
|
|
**(**int32)(__ccgo_up((*TFts5Hash)(unsafe.Pointer(pHash)).FpnByte)) += nIncr
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Return a nul-terminated copy of the string indicated by pIn. If nIn
|
|
// ** is non-negative, then it is the length of the string in bytes. Otherwise,
|
|
// ** the length of the string is determined using strlen().
|
|
// **
|
|
// ** It is the responsibility of the caller to eventually free the returned
|
|
// ** buffer using sqlite3_free(). If an OOM error occurs, NULL is returned.
|
|
// */
|
|
func _sqlite3Fts5Strndup(tls *libc.TLS, pRc uintptr, pIn uintptr, nIn int32) (r uintptr) {
|
|
var zRet uintptr
|
|
_ = zRet
|
|
zRet = uintptr(0)
|
|
if **(**int32)(__ccgo_up(pRc)) == SQLITE_OK {
|
|
if nIn < 0 {
|
|
nIn = libc.Int32FromUint64(libc.Xstrlen(tls, pIn))
|
|
}
|
|
zRet = Xsqlite3_malloc64(tls, libc.Uint64FromInt64(int64(nIn)+int64(1)))
|
|
if zRet != 0 {
|
|
libc.Xmemcpy(tls, zRet, pIn, libc.Uint64FromInt32(nIn))
|
|
**(**int8)(__ccgo_up(zRet + uintptr(nIn))) = int8('\000')
|
|
} else {
|
|
**(**int32)(__ccgo_up(pRc)) = int32(SQLITE_NOMEM)
|
|
}
|
|
}
|
|
return zRet
|
|
}
|
|
|
|
func _sqlite3Fts5TermsetAdd(tls *libc.TLS, p uintptr, iIdx int32, pTerm uintptr, nTerm int32, pbPresent uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var hash Tu32
|
|
var i int32
|
|
var pEntry uintptr
|
|
var _ /* rc at bp+0 */ int32
|
|
_, _, _ = hash, i, pEntry
|
|
**(**int32)(__ccgo_up(bp)) = SQLITE_OK
|
|
**(**int32)(__ccgo_up(pbPresent)) = 0
|
|
if p != 0 {
|
|
hash = uint32(13)
|
|
/* Calculate a hash value for this term. This is the same hash checksum
|
|
** used by the fts5_hash.c module. This is not important for correct
|
|
** operation of the module, but is necessary to ensure that some tests
|
|
** designed to produce hash table collisions really do work. */
|
|
i = nTerm - int32(1)
|
|
for {
|
|
if !(i >= 0) {
|
|
break
|
|
}
|
|
hash = hash<<libc.Int32FromInt32(3) ^ hash ^ libc.Uint32FromInt8(**(**int8)(__ccgo_up(pTerm + uintptr(i))))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i - 1
|
|
}
|
|
hash = hash<<libc.Int32FromInt32(3) ^ hash ^ libc.Uint32FromInt32(iIdx)
|
|
hash = hash % libc.Uint32FromInt32(libc.Int32FromUint64(libc.Uint64FromInt64(4096)/libc.Uint64FromInt64(8)))
|
|
pEntry = **(**uintptr)(__ccgo_up(p + uintptr(hash)*8))
|
|
for {
|
|
if !(pEntry != 0) {
|
|
break
|
|
}
|
|
if (*TFts5TermsetEntry)(unsafe.Pointer(pEntry)).FiIdx == iIdx && (*TFts5TermsetEntry)(unsafe.Pointer(pEntry)).FnTerm == nTerm && libc.Xmemcmp(tls, (*TFts5TermsetEntry)(unsafe.Pointer(pEntry)).FpTerm, pTerm, libc.Uint64FromInt32(nTerm)) == 0 {
|
|
**(**int32)(__ccgo_up(pbPresent)) = int32(1)
|
|
break
|
|
}
|
|
goto _2
|
|
_2:
|
|
;
|
|
pEntry = (*TFts5TermsetEntry)(unsafe.Pointer(pEntry)).FpNext
|
|
}
|
|
if pEntry == uintptr(0) {
|
|
pEntry = _sqlite3Fts5MallocZero(tls, bp, libc.Int64FromUint64(uint64(24)+libc.Uint64FromInt32(nTerm)))
|
|
if pEntry != 0 {
|
|
(*TFts5TermsetEntry)(unsafe.Pointer(pEntry)).FpTerm = pEntry + 1*24
|
|
(*TFts5TermsetEntry)(unsafe.Pointer(pEntry)).FnTerm = nTerm
|
|
(*TFts5TermsetEntry)(unsafe.Pointer(pEntry)).FiIdx = iIdx
|
|
libc.Xmemcpy(tls, (*TFts5TermsetEntry)(unsafe.Pointer(pEntry)).FpTerm, pTerm, libc.Uint64FromInt32(nTerm))
|
|
(*TFts5TermsetEntry)(unsafe.Pointer(pEntry)).FpNext = **(**uintptr)(__ccgo_up(p + uintptr(hash)*8))
|
|
**(**uintptr)(__ccgo_up(p + uintptr(hash)*8)) = pEntry
|
|
}
|
|
}
|
|
}
|
|
return **(**int32)(__ccgo_up(bp))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If zNum represents an integer that will fit in 32-bits, then set
|
|
// ** *pValue to that integer and return true. Otherwise return false.
|
|
// **
|
|
// ** This routine accepts both decimal and hexadecimal notation for integers.
|
|
// **
|
|
// ** Any non-numeric characters that following zNum are ignored.
|
|
// ** This is different from sqlite3Atoi64() which requires the
|
|
// ** input number to be zero-terminated.
|
|
// */
|
|
func _sqlite3GetInt32(tls *libc.TLS, zNum uintptr, pValue uintptr) (r int32) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
var c, i, neg, v3 int32
|
|
var v Tsqlite_int64
|
|
var v4 bool
|
|
var _ /* u at bp+0 */ Tu32
|
|
_, _, _, _, _, _ = c, i, neg, v, v3, v4
|
|
v = 0
|
|
neg = 0
|
|
if int32(**(**int8)(__ccgo_up(zNum))) == int32('-') {
|
|
neg = int32(1)
|
|
zNum = zNum + 1
|
|
} else {
|
|
if int32(**(**int8)(__ccgo_up(zNum))) == int32('+') {
|
|
zNum = zNum + 1
|
|
} else {
|
|
if int32(**(**int8)(__ccgo_up(zNum))) == int32('0') && (int32(**(**int8)(__ccgo_up(zNum + 1))) == int32('x') || int32(**(**int8)(__ccgo_up(zNum + 1))) == int32('X')) && libc.Int32FromUint8(_sqlite3CtypeMap[libc.Uint8FromInt8(**(**int8)(__ccgo_up(zNum + 2)))])&int32(0x08) != 0 {
|
|
**(**Tu32)(__ccgo_up(bp)) = uint32(0)
|
|
zNum = zNum + uintptr(2)
|
|
for int32(**(**int8)(__ccgo_up(zNum))) == int32('0') {
|
|
zNum = zNum + 1
|
|
}
|
|
i = 0
|
|
for {
|
|
if !(i < int32(8) && libc.Int32FromUint8(_sqlite3CtypeMap[libc.Uint8FromInt8(**(**int8)(__ccgo_up(zNum + uintptr(i))))])&int32(0x08) != 0) {
|
|
break
|
|
}
|
|
**(**Tu32)(__ccgo_up(bp)) = **(**Tu32)(__ccgo_up(bp))*uint32(16) + uint32(_sqlite3HexToInt(tls, int32(**(**int8)(__ccgo_up(zNum + uintptr(i))))))
|
|
goto _1
|
|
_1:
|
|
;
|
|
i = i + 1
|
|
}
|
|
if **(**Tu32)(__ccgo_up(bp))&uint32(0x80000000) == uint32(0) && libc.Int32FromUint8(_sqlite3CtypeMap[libc.Uint8FromInt8(**(**int8)(__ccgo_up(zNum + uintptr(i))))])&int32(0x08) == 0 {
|
|
libc.Xmemcpy(tls, pValue, bp, uint64(4))
|
|
return int32(1)
|
|
} else {
|
|
return 0
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if !(libc.Int32FromUint8(_sqlite3CtypeMap[libc.Uint8FromInt8(**(**int8)(__ccgo_up(zNum)))])&libc.Int32FromInt32(0x04) != 0) {
|
|
return 0
|
|
}
|
|
for int32(**(**int8)(__ccgo_up(zNum))) == int32('0') {
|
|
zNum = zNum + 1
|
|
}
|
|
i = 0
|
|
for {
|
|
if v4 = i < int32(11); v4 {
|
|
v3 = int32(**(**int8)(__ccgo_up(zNum + uintptr(i)))) - libc.Int32FromUint8('0')
|
|
c = v3
|
|
}
|
|
if !(v4 && v3 >= 0 && c <= int32(9)) {
|
|
break
|
|
}
|
|
v = v*int64(10) + int64(c)
|
|
goto _2
|
|
_2:
|
|
;
|
|
i = i + 1
|
|
}
|
|
/* The longest decimal representation of a 32 bit integer is 10 digits:
|
|
**
|
|
** 1234567890
|
|
** 2^31 -> 2147483648
|
|
*/
|
|
if i > int32(10) {
|
|
return 0
|
|
}
|
|
if v-int64(neg) > int64(2147483647) {
|
|
return 0
|
|
}
|
|
if neg != 0 {
|
|
v = -v
|
|
}
|
|
**(**int32)(__ccgo_up(pValue)) = int32(v)
|
|
return int32(1)
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Render an signed 64-bit integer as text. Store the result in zOut[] and
|
|
// ** return the length of the string that was stored, in bytes. The value
|
|
// ** returned does not include the zero terminator at the end of the output
|
|
// ** string.
|
|
// **
|
|
// ** The caller must ensure that zOut[] is at least 21 bytes in size.
|
|
// */
|
|
func _sqlite3Int64ToText(tls *libc.TLS, v Ti64, zOut uintptr) (r int32) {
|
|
bp := tls.Alloc(32)
|
|
defer tls.Free(32)
|
|
var i, kk, v2 int32
|
|
var x Tu64
|
|
var v1 uint64
|
|
var _ /* u at bp+0 */ struct {
|
|
FforceAlignment [0]Tu16
|
|
Fa [21]int8
|
|
F__ccgo_pad2 [1]byte
|
|
}
|
|
_, _, _, _, _ = i, kk, x, v1, v2
|
|
if v > 0 {
|
|
x = libc.Uint64FromInt64(v)
|
|
} else {
|
|
if v == 0 {
|
|
**(**int8)(__ccgo_up(zOut)) = int8('0')
|
|
**(**int8)(__ccgo_up(zOut + 1)) = 0
|
|
return int32(1)
|
|
} else {
|
|
if v == int64(-libc.Int32FromInt32(1))-(libc.Int64FromUint32(0xffffffff)|libc.Int64FromInt32(0x7fffffff)<<libc.Int32FromInt32(32)) {
|
|
v1 = libc.Uint64FromInt32(1) << libc.Int32FromInt32(63)
|
|
} else {
|
|
v1 = libc.Uint64FromInt64(-v)
|
|
}
|
|
x = v1
|
|
}
|
|
}
|
|
i = libc.Int32FromUint64(libc.Uint64FromInt64(21) - libc.Uint64FromInt32(1))
|
|
**(**int8)(__ccgo_up(bp + uintptr(i))) = 0
|
|
for x >= uint64(10) {
|
|
kk = libc.Int32FromUint64(x % uint64(100) * uint64(2))
|
|
**(**Tu16)(__ccgo_up(bp + uintptr(i-int32(2)))) = **(**Tu16)(__ccgo_up(uintptr(unsafe.Pointer(&_sqlite3DigitPairs)) + uintptr(kk)))
|
|
i = i - int32(2)
|
|
x = x / uint64(100)
|
|
}
|
|
if x != 0 {
|
|
i = i - 1
|
|
v2 = i
|
|
**(**int8)(__ccgo_up(bp + uintptr(v2))) = libc.Int8FromUint64(x + uint64('0'))
|
|
}
|
|
if v < 0 {
|
|
i = i - 1
|
|
v2 = i
|
|
**(**int8)(__ccgo_up(bp + uintptr(v2))) = int8('-')
|
|
}
|
|
libc.Xmemcpy(tls, zOut, bp+uintptr(i), uint64(21)-libc.Uint64FromInt32(i))
|
|
return libc.Int32FromUint64(libc.Uint64FromInt64(21) - libc.Uint64FromInt32(1) - libc.Uint64FromInt32(i))
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** pExpr points to an expression which implements a function. If
|
|
// ** it is appropriate to apply the LIKE optimization to that function
|
|
// ** then set aWc[0] through aWc[2] to the wildcard characters and the
|
|
// ** escape character and then return TRUE. If the function is not a
|
|
// ** LIKE-style function then return FALSE.
|
|
// **
|
|
// ** The expression "a LIKE b ESCAPE c" is only considered a valid LIKE
|
|
// ** operator if c is a string literal that is exactly one byte in length.
|
|
// ** That one byte is stored in aWc[3]. aWc[3] is set to zero if there is
|
|
// ** no ESCAPE clause.
|
|
// **
|
|
// ** *pIsNocase is set to true if uppercase and lowercase are equivalent for
|
|
// ** the function (default for LIKE). If the function makes the distinction
|
|
// ** between uppercase and lowercase (as does GLOB) then *pIsNocase is set to
|
|
// ** false.
|
|
// */
|
|
func _sqlite3IsLikeFunction(tls *libc.TLS, db uintptr, pExpr uintptr, pIsNocase uintptr, aWc uintptr) (r int32) {
|
|
var nExpr int32
|
|
var pDef, pEscape, zEscape uintptr
|
|
_, _, _, _ = nExpr, pDef, pEscape, zEscape
|
|
if !(*(*uintptr)(unsafe.Pointer(pExpr + 32)) != 0) {
|
|
return 0
|
|
}
|
|
nExpr = (*TExprList)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)))).FnExpr
|
|
pDef = _sqlite3FindFunction(tls, db, *(*uintptr)(unsafe.Pointer(pExpr + 8)), nExpr, uint8(SQLITE_UTF8), uint8(0))
|
|
if pDef == uintptr(0) || (*TFuncDef)(unsafe.Pointer(pDef)).FfuncFlags&uint32(SQLITE_FUNC_LIKE) == uint32(0) {
|
|
return 0
|
|
}
|
|
/* The memcpy() statement assumes that the wildcard characters are
|
|
** the first three statements in the compareInfo structure. The
|
|
** asserts() that follow verify that assumption
|
|
*/
|
|
libc.Xmemcpy(tls, aWc, (*TFuncDef)(unsafe.Pointer(pDef)).FpUserData, uint64(3))
|
|
if nExpr < int32(3) {
|
|
**(**int8)(__ccgo_up(aWc + 3)) = 0
|
|
} else {
|
|
pEscape = (*(*TExprList_item)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(pExpr + 32)) + 8 + 2*32))).FpExpr
|
|
if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pEscape)).Fop) != int32(TK_STRING) {
|
|
return 0
|
|
}
|
|
zEscape = *(*uintptr)(unsafe.Pointer(pEscape + 8))
|
|
if int32(**(**int8)(__ccgo_up(zEscape))) == 0 || int32(**(**int8)(__ccgo_up(zEscape + 1))) != 0 {
|
|
return 0
|
|
}
|
|
if int32(**(**int8)(__ccgo_up(zEscape))) == int32(**(**int8)(__ccgo_up(aWc))) {
|
|
return 0
|
|
}
|
|
if int32(**(**int8)(__ccgo_up(zEscape))) == int32(**(**int8)(__ccgo_up(aWc + 1))) {
|
|
return 0
|
|
}
|
|
**(**int8)(__ccgo_up(aWc + 3)) = **(**int8)(__ccgo_up(zEscape))
|
|
}
|
|
**(**int32)(__ccgo_up(pIsNocase)) = libc.BoolInt32((*TFuncDef)(unsafe.Pointer(pDef)).FfuncFlags&uint32(SQLITE_FUNC_CASE) == uint32(0))
|
|
return int32(1)
|
|
}
|
|
|
|
/* Mathematical Constants */
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Add a new name/number pair to a VList. This might require that the
|
|
// ** VList object be reallocated, so return the new VList. If an OOM
|
|
// ** error occurs, the original VList returned and the
|
|
// ** db->mallocFailed flag is set.
|
|
// **
|
|
// ** A VList is really just an array of integers. To destroy a VList,
|
|
// ** simply pass it to sqlite3DbFree().
|
|
// **
|
|
// ** The first integer is the number of integers allocated for the whole
|
|
// ** VList. The second integer is the number of integers actually used.
|
|
// ** Each name/number pair is encoded by subsequent groups of 3 or more
|
|
// ** integers.
|
|
// **
|
|
// ** Each name/number pair starts with two integers which are the numeric
|
|
// ** value for the pair and the size of the name/number pair, respectively.
|
|
// ** The text name overlays one or more following integers. The text name
|
|
// ** is always zero-terminated.
|
|
// **
|
|
// ** Conceptually:
|
|
// **
|
|
// ** struct VList {
|
|
// ** int nAlloc; // Number of allocated slots
|
|
// ** int nUsed; // Number of used slots
|
|
// ** struct VListEntry {
|
|
// ** int iValue; // Value for this entry
|
|
// ** int nSlot; // Slots used by this entry
|
|
// ** // ... variable name goes here
|
|
// ** } a[0];
|
|
// ** }
|
|
// **
|
|
// ** During code generation, pointers to the variable names within the
|
|
// ** VList are taken. When that happens, nAlloc is set to zero as an
|
|
// ** indication that the VList may never again be enlarged, since the
|
|
// ** accompanying realloc() would invalidate the pointers.
|
|
// */
|
|
func _sqlite3VListAdd(tls *libc.TLS, db uintptr, pIn uintptr, zName uintptr, nName int32, iVal int32) (r uintptr) {
|
|
var i, nInt int32
|
|
var nAlloc Tsqlite3_int64
|
|
var pOut, z uintptr
|
|
var v1 int64
|
|
_, _, _, _, _, _ = i, nAlloc, nInt, pOut, z, v1 /* Index in pIn[] where zName is stored */
|
|
nInt = nName/int32(4) + int32(3)
|
|
/* Verify ok to add new elements */
|
|
if pIn == uintptr(0) || **(**TVList)(__ccgo_up(pIn + 1*4))+nInt > **(**TVList)(__ccgo_up(pIn)) {
|
|
if pIn != 0 {
|
|
v1 = int64(2) * int64(**(**TVList)(__ccgo_up(pIn)))
|
|
} else {
|
|
v1 = int64(10)
|
|
}
|
|
/* Enlarge the allocation */
|
|
nAlloc = v1 + int64(nInt)
|
|
pOut = _sqlite3DbRealloc(tls, db, pIn, libc.Uint64FromInt64(nAlloc)*uint64(4))
|
|
if pOut == uintptr(0) {
|
|
return pIn
|
|
}
|
|
if pIn == uintptr(0) {
|
|
**(**TVList)(__ccgo_up(pOut + 1*4)) = int32(2)
|
|
}
|
|
pIn = pOut
|
|
**(**TVList)(__ccgo_up(pIn)) = int32(nAlloc)
|
|
}
|
|
i = **(**TVList)(__ccgo_up(pIn + 1*4))
|
|
**(**TVList)(__ccgo_up(pIn + uintptr(i)*4)) = iVal
|
|
**(**TVList)(__ccgo_up(pIn + uintptr(i+int32(1))*4)) = nInt
|
|
z = pIn + uintptr(i+int32(2))*4
|
|
**(**TVList)(__ccgo_up(pIn + 1*4)) = i + nInt
|
|
libc.Xmemcpy(tls, z, zName, libc.Uint64FromInt32(nName))
|
|
**(**int8)(__ccgo_up(z + uintptr(nName))) = 0
|
|
return pIn
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** This routine checks for a byte-order mark at the beginning of the
|
|
// ** UTF-16 string stored in *pMem. If one is present, it is removed and
|
|
// ** the encoding of the Mem adjusted. This routine does not do any
|
|
// ** byte-swapping, it just sets Mem.enc appropriately.
|
|
// **
|
|
// ** The allocation (static, dynamic etc.) and encoding of the Mem may be
|
|
// ** changed by this function.
|
|
// */
|
|
func _sqlite3VdbeMemHandleBom(tls *libc.TLS, pMem uintptr) (r int32) {
|
|
var b1, b2, bom Tu8
|
|
var rc int32
|
|
var v1 uintptr
|
|
_, _, _, _, _ = b1, b2, bom, rc, v1
|
|
rc = SQLITE_OK
|
|
bom = uint8(0)
|
|
if (*TMem)(unsafe.Pointer(pMem)).Fn > int32(1) {
|
|
b1 = **(**Tu8)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fz))
|
|
b2 = **(**Tu8)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fz + libc.UintptrFromInt32(1)))
|
|
if libc.Int32FromUint8(b1) == int32(0xFE) && libc.Int32FromUint8(b2) == int32(0xFF) {
|
|
bom = uint8(SQLITE_UTF16BE)
|
|
}
|
|
if libc.Int32FromUint8(b1) == int32(0xFF) && libc.Int32FromUint8(b2) == int32(0xFE) {
|
|
bom = uint8(SQLITE_UTF16LE)
|
|
}
|
|
}
|
|
if bom != 0 {
|
|
rc = _sqlite3VdbeMemMakeWriteable(tls, pMem)
|
|
if rc == SQLITE_OK {
|
|
**(**int32)(__ccgo_up(pMem + 16)) -= int32(2)
|
|
libc.Xmemmove(tls, (*TMem)(unsafe.Pointer(pMem)).Fz, (*TMem)(unsafe.Pointer(pMem)).Fz+2, libc.Uint64FromInt32((*TMem)(unsafe.Pointer(pMem)).Fn))
|
|
**(**int8)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fz + uintptr((*TMem)(unsafe.Pointer(pMem)).Fn))) = int8('\000')
|
|
**(**int8)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fz + uintptr((*TMem)(unsafe.Pointer(pMem)).Fn+int32(1)))) = int8('\000')
|
|
v1 = pMem + 20
|
|
*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromInt32(MEM_Term))
|
|
(*TMem)(unsafe.Pointer(pMem)).Fenc = bom
|
|
}
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Change the value of a Mem to be a string or a BLOB.
|
|
// **
|
|
// ** The memory management strategy depends on the value of the xDel
|
|
// ** parameter. If the value passed is SQLITE_TRANSIENT, then the
|
|
// ** string is copied into a (possibly existing) buffer managed by the
|
|
// ** Mem structure. Otherwise, any existing buffer is freed and the
|
|
// ** pointer copied.
|
|
// **
|
|
// ** If the string is too large (if it exceeds the SQLITE_LIMIT_LENGTH
|
|
// ** size limit) then no memory allocation occurs. If the string can be
|
|
// ** stored without allocating memory, then it is. If a memory allocation
|
|
// ** is required to store the string, then value of pMem is unchanged. In
|
|
// ** either case, SQLITE_TOOBIG is returned.
|
|
// **
|
|
// ** The "enc" parameter is the text encoding for the string, or zero
|
|
// ** to store a blob.
|
|
// **
|
|
// ** If n is negative, then the string consists of all bytes up to but
|
|
// ** excluding the first zero character. The n parameter must be
|
|
// ** non-negative for blobs.
|
|
// */
|
|
func _sqlite3VdbeMemSetStr(tls *libc.TLS, pMem uintptr, z uintptr, n Ti64, enc Tu8, __ccgo_fp_xDel uintptr) (r int32) {
|
|
var flags Tu16
|
|
var iLimit, v2 int32
|
|
var nAlloc, nByte Ti64
|
|
var v3 int64
|
|
_, _, _, _, _, _ = flags, iLimit, nAlloc, nByte, v2, v3
|
|
nByte = n /* New value for pMem->flags */
|
|
/* If z is a NULL pointer, set pMem to contain an SQL NULL. */
|
|
if !(z != 0) {
|
|
_sqlite3VdbeMemSetNull(tls, pMem)
|
|
return SQLITE_OK
|
|
}
|
|
if (*TMem)(unsafe.Pointer(pMem)).Fdb != 0 {
|
|
iLimit = **(**int32)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fdb + 136))
|
|
} else {
|
|
iLimit = int32(SQLITE_MAX_LENGTH)
|
|
}
|
|
if nByte < 0 {
|
|
if libc.Int32FromUint8(enc) == int32(SQLITE_UTF8) {
|
|
nByte = libc.Int64FromUint64(libc.Xstrlen(tls, z))
|
|
} else {
|
|
nByte = 0
|
|
for {
|
|
if !(nByte <= int64(iLimit) && int32(**(**int8)(__ccgo_up(z + uintptr(nByte))))|int32(**(**int8)(__ccgo_up(z + uintptr(nByte+int64(1))))) != 0) {
|
|
break
|
|
}
|
|
goto _1
|
|
_1:
|
|
;
|
|
nByte = nByte + int64(2)
|
|
}
|
|
}
|
|
flags = libc.Uint16FromInt32(libc.Int32FromInt32(MEM_Str) | libc.Int32FromInt32(MEM_Term))
|
|
} else {
|
|
if libc.Int32FromUint8(enc) == 0 {
|
|
flags = uint16(MEM_Blob)
|
|
enc = uint8(SQLITE_UTF8)
|
|
} else {
|
|
flags = uint16(MEM_Str)
|
|
}
|
|
}
|
|
if nByte > int64(iLimit) {
|
|
if __ccgo_fp_xDel != 0 && __ccgo_fp_xDel != uintptr(-libc.Int32FromInt32(1)) {
|
|
if __ccgo_fp_xDel == __ccgo_fp(_sqlite3RowSetClear) {
|
|
_sqlite3DbFree(tls, (*TMem)(unsafe.Pointer(pMem)).Fdb, z)
|
|
} else {
|
|
(*(*func(*libc.TLS, uintptr))(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xDel})))(tls, z)
|
|
}
|
|
}
|
|
_sqlite3VdbeMemSetNull(tls, pMem)
|
|
return _sqlite3ErrorToParser(tls, (*TMem)(unsafe.Pointer(pMem)).Fdb, int32(SQLITE_TOOBIG))
|
|
}
|
|
/* The following block sets the new values of Mem.z and Mem.xDel. It
|
|
** also sets a flag in local variable "flags" to indicate the memory
|
|
** management (one of MEM_Dyn or MEM_Static).
|
|
*/
|
|
if __ccgo_fp_xDel == uintptr(-libc.Int32FromInt32(1)) {
|
|
nAlloc = nByte
|
|
if libc.Int32FromUint16(flags)&int32(MEM_Term) != 0 {
|
|
if libc.Int32FromUint8(enc) == int32(SQLITE_UTF8) {
|
|
v2 = int32(1)
|
|
} else {
|
|
v2 = int32(2)
|
|
}
|
|
nAlloc = nAlloc + int64(v2)
|
|
}
|
|
if nAlloc > int64(libc.Int32FromInt32(32)) {
|
|
v3 = nAlloc
|
|
} else {
|
|
v3 = int64(libc.Int32FromInt32(32))
|
|
}
|
|
if _sqlite3VdbeMemClearAndResize(tls, pMem, int32(v3)) != 0 {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
libc.Xmemcpy(tls, (*TMem)(unsafe.Pointer(pMem)).Fz, z, libc.Uint64FromInt64(nAlloc))
|
|
} else {
|
|
_sqlite3VdbeMemRelease(tls, pMem)
|
|
(*TMem)(unsafe.Pointer(pMem)).Fz = z
|
|
if __ccgo_fp_xDel == __ccgo_fp(_sqlite3RowSetClear) {
|
|
(*TMem)(unsafe.Pointer(pMem)).FzMalloc = (*TMem)(unsafe.Pointer(pMem)).Fz
|
|
(*TMem)(unsafe.Pointer(pMem)).FszMalloc = _sqlite3DbMallocSize(tls, (*TMem)(unsafe.Pointer(pMem)).Fdb, (*TMem)(unsafe.Pointer(pMem)).FzMalloc)
|
|
} else {
|
|
(*TMem)(unsafe.Pointer(pMem)).FxDel = __ccgo_fp_xDel
|
|
if __ccgo_fp_xDel == libc.UintptrFromInt32(0) {
|
|
v2 = int32(MEM_Static)
|
|
} else {
|
|
v2 = int32(MEM_Dyn)
|
|
}
|
|
flags = libc.Uint16FromInt32(int32(flags) | v2)
|
|
}
|
|
}
|
|
(*TMem)(unsafe.Pointer(pMem)).Fn = int32(nByte & libc.Int64FromInt32(0x7fffffff))
|
|
(*TMem)(unsafe.Pointer(pMem)).Fflags = flags
|
|
(*TMem)(unsafe.Pointer(pMem)).Fenc = enc
|
|
if libc.Int32FromUint8(enc) > int32(SQLITE_UTF8) && _sqlite3VdbeMemHandleBom(tls, pMem) != 0 {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Like sqlite3VdbeMemSetStr() except:
|
|
// **
|
|
// ** enc is always SQLITE_UTF8
|
|
// ** pMem->db is always non-NULL
|
|
// */
|
|
func _sqlite3VdbeMemSetText(tls *libc.TLS, pMem uintptr, z uintptr, n Ti64, __ccgo_fp_xDel uintptr) (r int32) {
|
|
var flags Tu16
|
|
var nAlloc, nByte Ti64
|
|
var v1 int64
|
|
_, _, _, _ = flags, nAlloc, nByte, v1
|
|
nByte = n
|
|
/* If z is a NULL pointer, set pMem to contain an SQL NULL. */
|
|
if !(z != 0) {
|
|
_sqlite3VdbeMemSetNull(tls, pMem)
|
|
return SQLITE_OK
|
|
}
|
|
if nByte < 0 {
|
|
nByte = libc.Int64FromUint64(libc.Xstrlen(tls, z))
|
|
flags = libc.Uint16FromInt32(libc.Int32FromInt32(MEM_Str) | libc.Int32FromInt32(MEM_Term))
|
|
} else {
|
|
flags = uint16(MEM_Str)
|
|
}
|
|
if nByte > int64(**(**int32)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fdb + 136))) {
|
|
if __ccgo_fp_xDel != 0 && __ccgo_fp_xDel != uintptr(-libc.Int32FromInt32(1)) {
|
|
if __ccgo_fp_xDel == __ccgo_fp(_sqlite3RowSetClear) {
|
|
_sqlite3DbFree(tls, (*TMem)(unsafe.Pointer(pMem)).Fdb, z)
|
|
} else {
|
|
(*(*func(*libc.TLS, uintptr))(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xDel})))(tls, z)
|
|
}
|
|
}
|
|
_sqlite3VdbeMemSetNull(tls, pMem)
|
|
return _sqlite3ErrorToParser(tls, (*TMem)(unsafe.Pointer(pMem)).Fdb, int32(SQLITE_TOOBIG))
|
|
}
|
|
/* The following block sets the new values of Mem.z and Mem.xDel. It
|
|
** also sets a flag in local variable "flags" to indicate the memory
|
|
** management (one of MEM_Dyn or MEM_Static).
|
|
*/
|
|
if __ccgo_fp_xDel == uintptr(-libc.Int32FromInt32(1)) {
|
|
nAlloc = nByte + int64(1)
|
|
if nAlloc > int64(libc.Int32FromInt32(32)) {
|
|
v1 = nAlloc
|
|
} else {
|
|
v1 = int64(libc.Int32FromInt32(32))
|
|
}
|
|
if _sqlite3VdbeMemClearAndResize(tls, pMem, int32(v1)) != 0 {
|
|
return int32(SQLITE_NOMEM)
|
|
}
|
|
libc.Xmemcpy(tls, (*TMem)(unsafe.Pointer(pMem)).Fz, z, libc.Uint64FromInt64(nByte))
|
|
**(**int8)(__ccgo_up((*TMem)(unsafe.Pointer(pMem)).Fz + uintptr(nByte))) = 0
|
|
} else {
|
|
_sqlite3VdbeMemRelease(tls, pMem)
|
|
(*TMem)(unsafe.Pointer(pMem)).Fz = z
|
|
if __ccgo_fp_xDel == __ccgo_fp(_sqlite3RowSetClear) {
|
|
(*TMem)(unsafe.Pointer(pMem)).FzMalloc = (*TMem)(unsafe.Pointer(pMem)).Fz
|
|
(*TMem)(unsafe.Pointer(pMem)).FszMalloc = _sqlite3DbMallocSize(tls, (*TMem)(unsafe.Pointer(pMem)).Fdb, (*TMem)(unsafe.Pointer(pMem)).FzMalloc)
|
|
(*TMem)(unsafe.Pointer(pMem)).FxDel = uintptr(0)
|
|
} else {
|
|
if __ccgo_fp_xDel == libc.UintptrFromInt32(0) {
|
|
(*TMem)(unsafe.Pointer(pMem)).FxDel = __ccgo_fp_xDel
|
|
flags = libc.Uint16FromInt32(int32(flags) | libc.Int32FromInt32(MEM_Static))
|
|
} else {
|
|
(*TMem)(unsafe.Pointer(pMem)).FxDel = __ccgo_fp_xDel
|
|
flags = libc.Uint16FromInt32(int32(flags) | libc.Int32FromInt32(MEM_Dyn))
|
|
}
|
|
}
|
|
}
|
|
(*TMem)(unsafe.Pointer(pMem)).Fflags = flags
|
|
(*TMem)(unsafe.Pointer(pMem)).Fn = int32(nByte & libc.Int64FromInt32(0x7fffffff))
|
|
(*TMem)(unsafe.Pointer(pMem)).Fenc = uint8(SQLITE_UTF8)
|
|
return SQLITE_OK
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** If the SELECT statement passed as the second argument does not invoke
|
|
// ** any SQL window functions, this function is a no-op. Otherwise, it
|
|
// ** rewrites the SELECT statement so that window function xStep functions
|
|
// ** are invoked in the correct order as described under "SELECT REWRITING"
|
|
// ** at the top of this file.
|
|
// */
|
|
func _sqlite3WindowRewrite(tls *libc.TLS, pParse uintptr, p uintptr) (r int32) {
|
|
bp := tls.Alloc(64)
|
|
defer tls.Free(64)
|
|
var db, pArgs, pFilter, pGroupBy, pHaving, pMWin, pSort, pSrc, pSub, pTab, pTab2, pWhere, pWin, v, v2 uintptr
|
|
var nSave, rc, v1 int32
|
|
var selFlags Tu32
|
|
var _ /* pSublist at bp+0 */ uintptr
|
|
var _ /* w at bp+8 */ TWalker
|
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = db, nSave, pArgs, pFilter, pGroupBy, pHaving, pMWin, pSort, pSrc, pSub, pTab, pTab2, pWhere, pWin, rc, selFlags, v, v1, v2
|
|
rc = SQLITE_OK
|
|
if (*TSelect)(unsafe.Pointer(p)).FpWin != 0 && (*TSelect)(unsafe.Pointer(p)).FpPrior == uintptr(0) && (*TSelect)(unsafe.Pointer(p)).FselFlags&uint32(SF_WinRewrite) == uint32(0) && !(libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= libc.Int32FromInt32(PARSE_MODE_RENAME)) {
|
|
v = _sqlite3GetVdbe(tls, pParse)
|
|
db = (*TParse)(unsafe.Pointer(pParse)).Fdb
|
|
pSub = uintptr(0) /* The subquery */
|
|
pSrc = (*TSelect)(unsafe.Pointer(p)).FpSrc
|
|
pWhere = (*TSelect)(unsafe.Pointer(p)).FpWhere
|
|
pGroupBy = (*TSelect)(unsafe.Pointer(p)).FpGroupBy
|
|
pHaving = (*TSelect)(unsafe.Pointer(p)).FpHaving
|
|
pSort = uintptr(0)
|
|
**(**uintptr)(__ccgo_up(bp)) = uintptr(0) /* Expression list for sub-query */
|
|
pMWin = (*TSelect)(unsafe.Pointer(p)).FpWin
|
|
selFlags = (*TSelect)(unsafe.Pointer(p)).FselFlags
|
|
pTab = _sqlite3DbMallocZero(tls, db, uint64(120))
|
|
if pTab == uintptr(0) {
|
|
return _sqlite3ErrorToParser(tls, db, int32(SQLITE_NOMEM))
|
|
}
|
|
_sqlite3AggInfoPersistWalkerInit(tls, bp+8, pParse)
|
|
_sqlite3WalkSelect(tls, bp+8, p)
|
|
if (*TSelect)(unsafe.Pointer(p)).FselFlags&uint32(SF_Aggregate) == uint32(0) {
|
|
(**(**TWalker)(__ccgo_up(bp + 8))).FxExprCallback = __ccgo_fp(_disallowAggregatesInOrderByCb)
|
|
(**(**TWalker)(__ccgo_up(bp + 8))).FxSelectCallback = uintptr(0)
|
|
_sqlite3WalkExprList(tls, bp+8, (*TSelect)(unsafe.Pointer(p)).FpOrderBy)
|
|
}
|
|
(*TSelect)(unsafe.Pointer(p)).FpSrc = uintptr(0)
|
|
(*TSelect)(unsafe.Pointer(p)).FpWhere = uintptr(0)
|
|
(*TSelect)(unsafe.Pointer(p)).FpGroupBy = uintptr(0)
|
|
(*TSelect)(unsafe.Pointer(p)).FpHaving = uintptr(0)
|
|
**(**Tu32)(__ccgo_up(p + 4)) &= ^libc.Uint32FromInt32(SF_Aggregate)
|
|
**(**Tu32)(__ccgo_up(p + 4)) |= uint32(SF_WinRewrite)
|
|
/* Create the ORDER BY clause for the sub-select. This is the concatenation
|
|
** of the window PARTITION and ORDER BY clauses. Then, if this makes it
|
|
** redundant, remove the ORDER BY from the parent SELECT. */
|
|
pSort = _exprListAppendList(tls, pParse, uintptr(0), (*TWindow)(unsafe.Pointer(pMWin)).FpPartition, int32(1))
|
|
pSort = _exprListAppendList(tls, pParse, pSort, (*TWindow)(unsafe.Pointer(pMWin)).FpOrderBy, int32(1))
|
|
if pSort != 0 && (*TSelect)(unsafe.Pointer(p)).FpOrderBy != 0 && (*TExprList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(p)).FpOrderBy)).FnExpr <= (*TExprList)(unsafe.Pointer(pSort)).FnExpr {
|
|
nSave = (*TExprList)(unsafe.Pointer(pSort)).FnExpr
|
|
(*TExprList)(unsafe.Pointer(pSort)).FnExpr = (*TExprList)(unsafe.Pointer((*TSelect)(unsafe.Pointer(p)).FpOrderBy)).FnExpr
|
|
if _sqlite3ExprListCompare(tls, pSort, (*TSelect)(unsafe.Pointer(p)).FpOrderBy, -int32(1)) == 0 {
|
|
_sqlite3ExprListDelete(tls, db, (*TSelect)(unsafe.Pointer(p)).FpOrderBy)
|
|
(*TSelect)(unsafe.Pointer(p)).FpOrderBy = uintptr(0)
|
|
}
|
|
(*TExprList)(unsafe.Pointer(pSort)).FnExpr = nSave
|
|
}
|
|
/* Assign a cursor number for the ephemeral table used to buffer rows.
|
|
** The OpenEphemeral instruction is coded later, after it is known how
|
|
** many columns the table will have. */
|
|
v2 = pParse + 56
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
(*TWindow)(unsafe.Pointer(pMWin)).FiEphCsr = v1
|
|
**(**int32)(__ccgo_up(pParse + 56)) += int32(3)
|
|
_selectWindowRewriteEList(tls, pParse, pMWin, pSrc, (*TSelect)(unsafe.Pointer(p)).FpEList, pTab, bp)
|
|
_selectWindowRewriteEList(tls, pParse, pMWin, pSrc, (*TSelect)(unsafe.Pointer(p)).FpOrderBy, pTab, bp)
|
|
if **(**uintptr)(__ccgo_up(bp)) != 0 {
|
|
v1 = (*TExprList)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FnExpr
|
|
} else {
|
|
v1 = 0
|
|
}
|
|
(*TWindow)(unsafe.Pointer(pMWin)).FnBufferCol = v1
|
|
/* Append the PARTITION BY and ORDER BY expressions to the to the
|
|
** sub-select expression list. They are required to figure out where
|
|
** boundaries for partitions and sets of peer rows lie. */
|
|
**(**uintptr)(__ccgo_up(bp)) = _exprListAppendList(tls, pParse, **(**uintptr)(__ccgo_up(bp)), (*TWindow)(unsafe.Pointer(pMWin)).FpPartition, 0)
|
|
**(**uintptr)(__ccgo_up(bp)) = _exprListAppendList(tls, pParse, **(**uintptr)(__ccgo_up(bp)), (*TWindow)(unsafe.Pointer(pMWin)).FpOrderBy, 0)
|
|
/* Append the arguments passed to each window function to the
|
|
** sub-select expression list. Also allocate two registers for each
|
|
** window function - one for the accumulator, another for interim
|
|
** results. */
|
|
pWin = pMWin
|
|
for {
|
|
if !(pWin != 0) {
|
|
break
|
|
}
|
|
pArgs = *(*uintptr)(unsafe.Pointer((*TWindow)(unsafe.Pointer(pWin)).FpOwner + 32))
|
|
if (*TFuncDef)(unsafe.Pointer((*TWindow)(unsafe.Pointer(pWin)).FpWFunc)).FfuncFlags&uint32(SQLITE_SUBTYPE) != 0 {
|
|
_selectWindowRewriteEList(tls, pParse, pMWin, pSrc, pArgs, pTab, bp)
|
|
if **(**uintptr)(__ccgo_up(bp)) != 0 {
|
|
v1 = (*TExprList)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FnExpr
|
|
} else {
|
|
v1 = 0
|
|
}
|
|
(*TWindow)(unsafe.Pointer(pWin)).FiArgCol = v1
|
|
(*TWindow)(unsafe.Pointer(pWin)).FbExprArgs = uint8(1)
|
|
} else {
|
|
if **(**uintptr)(__ccgo_up(bp)) != 0 {
|
|
v1 = (*TExprList)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FnExpr
|
|
} else {
|
|
v1 = 0
|
|
}
|
|
(*TWindow)(unsafe.Pointer(pWin)).FiArgCol = v1
|
|
**(**uintptr)(__ccgo_up(bp)) = _exprListAppendList(tls, pParse, **(**uintptr)(__ccgo_up(bp)), pArgs, 0)
|
|
}
|
|
if (*TWindow)(unsafe.Pointer(pWin)).FpFilter != 0 {
|
|
pFilter = _sqlite3ExprDup(tls, db, (*TWindow)(unsafe.Pointer(pWin)).FpFilter, 0)
|
|
**(**uintptr)(__ccgo_up(bp)) = _sqlite3ExprListAppend(tls, pParse, **(**uintptr)(__ccgo_up(bp)), pFilter)
|
|
}
|
|
v2 = pParse + 60
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
(*TWindow)(unsafe.Pointer(pWin)).FregAccum = v1
|
|
v2 = pParse + 60
|
|
*(*int32)(unsafe.Pointer(v2)) = *(*int32)(unsafe.Pointer(v2)) + 1
|
|
v1 = *(*int32)(unsafe.Pointer(v2))
|
|
(*TWindow)(unsafe.Pointer(pWin)).FregResult = v1
|
|
_sqlite3VdbeAddOp2(tls, v, int32(OP_Null), 0, (*TWindow)(unsafe.Pointer(pWin)).FregAccum)
|
|
goto _4
|
|
_4:
|
|
;
|
|
pWin = (*TWindow)(unsafe.Pointer(pWin)).FpNextWin
|
|
}
|
|
/* If there is no ORDER BY or PARTITION BY clause, and the window
|
|
** function accepts zero arguments, and there are no other columns
|
|
** selected (e.g. "SELECT row_number() OVER () FROM t1"), it is possible
|
|
** that pSublist is still NULL here. Add a constant expression here to
|
|
** keep everything legal in this case.
|
|
*/
|
|
if **(**uintptr)(__ccgo_up(bp)) == uintptr(0) {
|
|
**(**uintptr)(__ccgo_up(bp)) = _sqlite3ExprListAppend(tls, pParse, uintptr(0), _sqlite3ExprInt32(tls, db, 0))
|
|
}
|
|
pSub = _sqlite3SelectNew(tls, pParse, **(**uintptr)(__ccgo_up(bp)), pSrc, pWhere, pGroupBy, pHaving, pSort, uint32(0), uintptr(0))
|
|
(*TSelect)(unsafe.Pointer(p)).FpSrc = _sqlite3SrcListAppend(tls, pParse, uintptr(0), uintptr(0), uintptr(0))
|
|
/* Due to db->mallocFailed test inside
|
|
** of sqlite3DbMallocRawNN() called from
|
|
** sqlite3SrcListAppend() */
|
|
if (*TSelect)(unsafe.Pointer(p)).FpSrc == uintptr(0) {
|
|
_sqlite3SelectDelete(tls, db, pSub)
|
|
} else {
|
|
if _sqlite3SrcItemAttachSubquery(tls, pParse, (*TSelect)(unsafe.Pointer(p)).FpSrc+8, pSub, 0) != 0 {
|
|
libc.SetBitFieldPtr32Uint32((*TSelect)(unsafe.Pointer(p)).FpSrc+8+24+4, libc.Uint32FromInt32(1), 4, 0x10)
|
|
_sqlite3SrcListAssignCursors(tls, pParse, (*TSelect)(unsafe.Pointer(p)).FpSrc)
|
|
**(**Tu32)(__ccgo_up(pSub + 4)) |= libc.Uint32FromInt32(libc.Int32FromInt32(SF_Expanded) | libc.Int32FromInt32(SF_OrderByReqd))
|
|
pTab2 = _sqlite3ResultSetOfSelect(tls, pParse, pSub, int8(SQLITE_AFF_NONE))
|
|
**(**Tu32)(__ccgo_up(pSub + 4)) |= selFlags & uint32(SF_Aggregate)
|
|
if pTab2 == uintptr(0) {
|
|
/* Might actually be some other kind of error, but in that case
|
|
** pParse->nErr will be set, so if SQLITE_NOMEM is set, we will get
|
|
** the correct error message regardless. */
|
|
rc = int32(SQLITE_NOMEM)
|
|
} else {
|
|
libc.Xmemcpy(tls, pTab, pTab2, uint64(120))
|
|
**(**Tu32)(__ccgo_up(pTab + 48)) |= uint32(TF_Ephemeral)
|
|
(*(*TSrcItem)(unsafe.Pointer((*TSelect)(unsafe.Pointer(p)).FpSrc + 8))).FpSTab = pTab
|
|
pTab = pTab2
|
|
libc.Xmemset(tls, bp+8, 0, uint64(48))
|
|
(**(**TWalker)(__ccgo_up(bp + 8))).FxExprCallback = __ccgo_fp(_sqlite3WindowExtraAggFuncDepth)
|
|
(**(**TWalker)(__ccgo_up(bp + 8))).FxSelectCallback = __ccgo_fp(_sqlite3WalkerDepthIncrease)
|
|
(**(**TWalker)(__ccgo_up(bp + 8))).FxSelectCallback2 = __ccgo_fp(_sqlite3WalkerDepthDecrease)
|
|
_sqlite3WalkSelect(tls, bp+8, pSub)
|
|
}
|
|
}
|
|
}
|
|
if (*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed != 0 {
|
|
rc = int32(SQLITE_NOMEM)
|
|
}
|
|
/* Defer deleting the temporary table pTab because if an error occurred,
|
|
** there could still be references to that table embedded in the
|
|
** result-set or ORDER BY clause of the SELECT statement p. */
|
|
_sqlite3ParserAddCleanup(tls, pParse, __ccgo_fp(_sqlite3DbFree), pTab)
|
|
}
|
|
return rc
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /* Construct a new Expr object from a single token */
|
|
func _tokenExpr(tls *libc.TLS, pParse uintptr, op int32, _t TToken) (r uintptr) {
|
|
bp := tls.Alloc(16)
|
|
defer tls.Free(16)
|
|
*(*TToken)(unsafe.Pointer(bp)) = _t
|
|
var p, v1 uintptr
|
|
_, _ = p, v1
|
|
p = _sqlite3DbMallocRawNN(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, uint64(72)+uint64((**(**TToken)(__ccgo_up(bp))).Fn)+uint64(1))
|
|
if p != 0 {
|
|
/* memset(p, 0, sizeof(Expr)); */
|
|
(*TExpr)(unsafe.Pointer(p)).Fop = libc.Uint8FromInt32(op)
|
|
(*TExpr)(unsafe.Pointer(p)).FaffExpr = 0
|
|
(*TExpr)(unsafe.Pointer(p)).Fflags = uint32(EP_Leaf)
|
|
/* p->iAgg = -1; // Not required */
|
|
v1 = libc.UintptrFromInt32(0)
|
|
(*TExpr)(unsafe.Pointer(p)).FpRight = v1
|
|
(*TExpr)(unsafe.Pointer(p)).FpLeft = v1
|
|
(*TExpr)(unsafe.Pointer(p)).FpAggInfo = uintptr(0)
|
|
libc.Xmemset(tls, p+32, 0, uint64(8))
|
|
libc.Xmemset(tls, p+64, 0, uint64(8))
|
|
(*TExpr)(unsafe.Pointer(p)).Fop2 = uint8(0)
|
|
(*TExpr)(unsafe.Pointer(p)).FiTable = 0
|
|
(*TExpr)(unsafe.Pointer(p)).FiColumn = 0
|
|
*(*uintptr)(unsafe.Pointer(p + 8)) = p + 1*72
|
|
libc.Xmemcpy(tls, *(*uintptr)(unsafe.Pointer(p + 8)), (**(**TToken)(__ccgo_up(bp))).Fz, uint64((**(**TToken)(__ccgo_up(bp))).Fn))
|
|
**(**int8)(__ccgo_up(*(*uintptr)(unsafe.Pointer(p + 8)) + uintptr((**(**TToken)(__ccgo_up(bp))).Fn))) = 0
|
|
*(*int32)(unsafe.Pointer(p + 52)) = int32(int64((**(**TToken)(__ccgo_up(bp))).Fz) - int64((*TParse)(unsafe.Pointer(pParse)).FzTail))
|
|
if libc.Int32FromUint8(_sqlite3CtypeMap[libc.Uint8FromInt8(**(**int8)(__ccgo_up(*(*uintptr)(unsafe.Pointer(p + 8)))))])&int32(0x80) != 0 {
|
|
_sqlite3DequoteExpr(tls, p)
|
|
}
|
|
(*TExpr)(unsafe.Pointer(p)).FnHeight = int32(1)
|
|
if libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= int32(PARSE_MODE_RENAME) {
|
|
return _sqlite3RenameTokenMap(tls, pParse, p, bp)
|
|
}
|
|
}
|
|
return p
|
|
}
|
|
|
|
// C documentation
|
|
//
|
|
// /*
|
|
// ** Set up a raw page so that it looks like a database page holding
|
|
// ** no entries.
|
|
// */
|
|
func _zeroPage(tls *libc.TLS, pPage uintptr, flags int32) {
|
|
var data, pBt uintptr
|
|
var first, hdr, v1 int32
|
|
_, _, _, _, _ = data, first, hdr, pBt, v1
|
|
data = (*TMemPage)(unsafe.Pointer(pPage)).FaData
|
|
pBt = (*TMemPage)(unsafe.Pointer(pPage)).FpBt
|
|
hdr = libc.Int32FromUint8((*TMemPage)(unsafe.Pointer(pPage)).FhdrOffset)
|
|
if libc.Int32FromUint16((*TBtShared)(unsafe.Pointer(pBt)).FbtsFlags)&int32(BTS_FAST_SECURE) != 0 {
|
|
libc.Xmemset(tls, data+uintptr(hdr), 0, uint64((*TBtShared)(unsafe.Pointer(pBt)).FusableSize-libc.Uint32FromInt32(hdr)))
|
|
}
|
|
**(**uint8)(__ccgo_up(data + uintptr(hdr))) = libc.Uint8FromInt8(int8(flags))
|
|
if flags&int32(PTF_LEAF) == 0 {
|
|
v1 = int32(12)
|
|
} else {
|
|
v1 = int32(8)
|
|
}
|
|
first = hdr + v1
|
|
libc.Xmemset(tls, data+uintptr(hdr+int32(1)), 0, uint64(4))
|
|
**(**uint8)(__ccgo_up(data + uintptr(hdr+int32(7)))) = uint8(0)
|
|
**(**uint8)(__ccgo_up(data + uintptr(hdr+int32(5)))) = uint8((*TBtShared)(unsafe.Pointer(pBt)).FusableSize >> libc.Int32FromInt32(8))
|
|
**(**uint8)(__ccgo_up(data + uintptr(hdr+int32(5)) + 1)) = uint8((*TBtShared)(unsafe.Pointer(pBt)).FusableSize)
|
|
(*TMemPage)(unsafe.Pointer(pPage)).FnFree = libc.Int32FromUint16(uint16((*TBtShared)(unsafe.Pointer(pBt)).FusableSize - libc.Uint32FromInt32(first)))
|
|
_decodeFlags(tls, pPage, flags)
|
|
(*TMemPage)(unsafe.Pointer(pPage)).FcellOffset = libc.Uint16FromInt32(first)
|
|
(*TMemPage)(unsafe.Pointer(pPage)).FaDataEnd = data + uintptr((*TBtShared)(unsafe.Pointer(pBt)).FpageSize)
|
|
(*TMemPage)(unsafe.Pointer(pPage)).FaCellIdx = data + uintptr(first)
|
|
(*TMemPage)(unsafe.Pointer(pPage)).FaDataOfst = data + uintptr((*TMemPage)(unsafe.Pointer(pPage)).FchildPtrSize)
|
|
(*TMemPage)(unsafe.Pointer(pPage)).FnOverflow = uint8(0)
|
|
(*TMemPage)(unsafe.Pointer(pPage)).FmaskPage = uint16((*TBtShared)(unsafe.Pointer(pBt)).FpageSize - libc.Uint32FromInt32(1))
|
|
(*TMemPage)(unsafe.Pointer(pPage)).FnCell = uint16(0)
|
|
(*TMemPage)(unsafe.Pointer(pPage)).FisInit = uint8(1)
|
|
}
|