mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Upgrade SQLite to 3.40 (#699)
This commit is contained in:
parent
bcae817215
commit
0dc0758574
151 changed files with 27917 additions and 22169 deletions
2
third_party/sqlite3/README.cosmo
vendored
2
third_party/sqlite3/README.cosmo
vendored
|
@ -5,7 +5,7 @@ DESCRIPTION
|
|||
|
||||
ORIGIN
|
||||
|
||||
https://www.sqlite.org/2021/sqlite-preprocessed-3350500.zip
|
||||
https://www.sqlite.org/2022/sqlite-preprocessed-3400000.zip
|
||||
|
||||
LICENSE
|
||||
|
||||
|
|
664
third_party/sqlite3/alter.c
vendored
664
third_party/sqlite3/alter.c
vendored
File diff suppressed because it is too large
Load diff
83
third_party/sqlite3/analyze.c
vendored
83
third_party/sqlite3/analyze.c
vendored
|
@ -30,7 +30,7 @@
|
|||
** created and used by SQLite versions 3.7.9 through 3.29.0 when
|
||||
** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3
|
||||
** is a superset of sqlite_stat2 and is also now deprecated. The
|
||||
** sqlite_stat4 is an enhanced version of sqlite_stat3 and is only
|
||||
** sqlite_stat4 is an enhanced version of sqlite_stat3 and is only
|
||||
** available when compiled with SQLITE_ENABLE_STAT4 and in SQLite
|
||||
** versions 3.8.1 and later. STAT4 is the only variant that is still
|
||||
** supported.
|
||||
|
@ -49,7 +49,7 @@
|
|||
** integer is the average number of rows in the index that have the same
|
||||
** value in the first column of the index. The third integer is the average
|
||||
** number of rows in the index that have the same value for the first two
|
||||
** columns. The N-th integer (for N>1) is the average number of rows in
|
||||
** columns. The N-th integer (for N>1) is the average number of rows in
|
||||
** the index which have the same value for the first N-1 columns. For
|
||||
** a K-column index, there will be K+1 integers in the stat column. If
|
||||
** the index is unique, then the last integer will be 1.
|
||||
|
@ -59,7 +59,7 @@
|
|||
** must be separated from the last integer by a single space. If the
|
||||
** "unordered" keyword is present, then the query planner assumes that
|
||||
** the index is unordered and will not use the index for a range query.
|
||||
**
|
||||
**
|
||||
** If the sqlite_stat1.idx column is NULL, then the sqlite_stat1.stat
|
||||
** column contains a single integer which is the (estimated) number of
|
||||
** rows in the table identified by sqlite_stat1.tbl.
|
||||
|
@ -117,9 +117,9 @@
|
|||
** number of entries that are strictly less than the sample. The first
|
||||
** integer in nLt contains the number of entries in the index where the
|
||||
** left-most column is less than the left-most column of the sample.
|
||||
** The K-th integer in the nLt entry is the number of index entries
|
||||
** The K-th integer in the nLt entry is the number of index entries
|
||||
** where the first K columns are less than the first K columns of the
|
||||
** sample. The nDLt column is like nLt except that it contains the
|
||||
** sample. The nDLt column is like nLt except that it contains the
|
||||
** number of distinct entries in the index that are less than the
|
||||
** sample.
|
||||
**
|
||||
|
@ -140,8 +140,7 @@
|
|||
** integer in the equivalent columns in sqlite_stat4.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_ANALYZE
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
#if defined(SQLITE_ENABLE_STAT4)
|
||||
# define IsStat4 1
|
||||
|
@ -434,7 +433,6 @@ static void statInit(
|
|||
+ sizeof(tRowcnt)*3*nColUp*(nCol+mxSample);
|
||||
}
|
||||
#endif
|
||||
db = sqlite3_context_db_handle(context);
|
||||
p = sqlite3DbMallocZero(db, n);
|
||||
if( p==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
|
@ -849,32 +847,29 @@ static void statGet(
|
|||
** * "WHERE a=? AND b=?" matches 2 rows.
|
||||
**
|
||||
** If D is the count of distinct values and K is the total number of
|
||||
** rows, then each estimate is computed as:
|
||||
** rows, then each estimate is usually computed as:
|
||||
**
|
||||
** I = (K+D-1)/D
|
||||
**
|
||||
** In other words, I is K/D rounded up to the next whole integer.
|
||||
** However, if I is between 1.0 and 1.1 (in other words if I is
|
||||
** close to 1.0 but just a little larger) then do not round up but
|
||||
** instead keep the I value at 1.0.
|
||||
*/
|
||||
char *z;
|
||||
int i;
|
||||
sqlite3_str sStat; /* Text of the constructed "stat" line */
|
||||
int i; /* Loop counter */
|
||||
|
||||
char *zRet = sqlite3MallocZero( (p->nKeyCol+1)*25 );
|
||||
if( zRet==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
|
||||
sqlite3_snprintf(24, zRet, "%llu",
|
||||
sqlite3StrAccumInit(&sStat, 0, 0, 0, (p->nKeyCol+1)*100);
|
||||
sqlite3_str_appendf(&sStat, "%llu",
|
||||
p->nSkipAhead ? (u64)p->nEst : (u64)p->nRow);
|
||||
z = zRet + sqlite3Strlen30(zRet);
|
||||
for(i=0; i<p->nKeyCol; i++){
|
||||
u64 nDistinct = p->current.anDLt[i] + 1;
|
||||
u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
|
||||
sqlite3_snprintf(24, z, " %llu", iVal);
|
||||
z += sqlite3Strlen30(z);
|
||||
if( iVal==2 && p->nRow*10 <= nDistinct*11 ) iVal = 1;
|
||||
sqlite3_str_appendf(&sStat, " %llu", iVal);
|
||||
assert( p->current.anEq[i] );
|
||||
}
|
||||
assert( z[0]=='\0' && z>zRet );
|
||||
|
||||
sqlite3_result_text(context, zRet, -1, sqlite3_free);
|
||||
sqlite3ResultStrAccum(context, &sStat);
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
else if( eCall==STAT_GET_ROWID ){
|
||||
|
@ -893,6 +888,8 @@ static void statGet(
|
|||
}
|
||||
}else{
|
||||
tRowcnt *aCnt = 0;
|
||||
sqlite3_str sStat;
|
||||
int i;
|
||||
|
||||
assert( p->iGet<p->nSample );
|
||||
switch( eCall ){
|
||||
|
@ -904,23 +901,12 @@ static void statGet(
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
char *zRet = sqlite3MallocZero(p->nCol * 25);
|
||||
if( zRet==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else{
|
||||
int i;
|
||||
char *z = zRet;
|
||||
for(i=0; i<p->nCol; i++){
|
||||
sqlite3_snprintf(24, z, "%llu ", (u64)aCnt[i]);
|
||||
z += sqlite3Strlen30(z);
|
||||
}
|
||||
assert( z[0]=='\0' && z>zRet );
|
||||
z[-1] = '\0';
|
||||
sqlite3_result_text(context, zRet, -1, sqlite3_free);
|
||||
}
|
||||
sqlite3StrAccumInit(&sStat, 0, 0, 0, p->nCol*100);
|
||||
for(i=0; i<p->nCol; i++){
|
||||
sqlite3_str_appendf(&sStat, "%llu ", (u64)aCnt[i]);
|
||||
}
|
||||
if( sStat.nChar ) sStat.nChar--;
|
||||
sqlite3ResultStrAccum(context, &sStat);
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_STAT4 */
|
||||
#ifndef SQLITE_DEBUG
|
||||
|
@ -967,9 +953,10 @@ static void analyzeVdbeCommentIndexWithColumnName(
|
|||
if( NEVER(i==XN_ROWID) ){
|
||||
VdbeComment((v,"%s.rowid",pIdx->zName));
|
||||
}else if( i==XN_EXPR ){
|
||||
assert( pIdx->bHasExpr );
|
||||
VdbeComment((v,"%s.expr(%d)",pIdx->zName, k));
|
||||
}else{
|
||||
VdbeComment((v,"%s.%s", pIdx->zName, pIdx->pTable->aCol[i].zName));
|
||||
VdbeComment((v,"%s.%s", pIdx->zName, pIdx->pTable->aCol[i].zCnName));
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@ -1016,7 +1003,7 @@ static void analyzeOneTable(
|
|||
if( v==0 || NEVER(pTab==0) ){
|
||||
return;
|
||||
}
|
||||
if( pTab->tnum==0 ){
|
||||
if( !IsOrdinaryTable(pTab) ){
|
||||
/* Do not gather statistics on views or virtual tables */
|
||||
return;
|
||||
}
|
||||
|
@ -1043,7 +1030,7 @@ static void analyzeOneTable(
|
|||
memcpy(pStat1->zName, "sqlite_stat1", 13);
|
||||
pStat1->nCol = 3;
|
||||
pStat1->iPKey = -1;
|
||||
sqlite3VdbeAddOp4(pParse->pVdbe, OP_Noop, 0, 0, 0,(char*)pStat1,P4_DYNBLOB);
|
||||
sqlite3VdbeAddOp4(pParse->pVdbe, OP_Noop, 0, 0, 0,(char*)pStat1,P4_DYNAMIC);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1841,9 +1828,12 @@ static int loadStatTbl(
|
|||
*/
|
||||
static int loadStat4(sqlite3 *db, const char *zDb){
|
||||
int rc = SQLITE_OK; /* Result codes from subroutines */
|
||||
const Table *pStat4;
|
||||
|
||||
assert( db->lookaside.bDisable );
|
||||
if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){
|
||||
if( (pStat4 = sqlite3FindTable(db, "sqlite_stat4", zDb))!=0
|
||||
&& IsOrdinaryTable(pStat4)
|
||||
){
|
||||
rc = loadStatTbl(db,
|
||||
"SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx",
|
||||
"SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4",
|
||||
|
@ -1880,6 +1870,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
|
|||
char *zSql;
|
||||
int rc = SQLITE_OK;
|
||||
Schema *pSchema = db->aDb[iDb].pSchema;
|
||||
const Table *pStat1;
|
||||
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
assert( db->aDb[iDb].pBt!=0 );
|
||||
|
@ -1902,7 +1893,9 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
|
|||
/* Load new statistics out of the sqlite_stat1 table */
|
||||
sInfo.db = db;
|
||||
sInfo.zDatabase = db->aDb[iDb].zDbSName;
|
||||
if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)!=0 ){
|
||||
if( (pStat1 = sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase))
|
||||
&& IsOrdinaryTable(pStat1)
|
||||
){
|
||||
zSql = sqlite3MPrintf(db,
|
||||
"SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
|
||||
if( zSql==0 ){
|
||||
|
|
57
third_party/sqlite3/attach.c
vendored
57
third_party/sqlite3/attach.c
vendored
|
@ -11,8 +11,7 @@
|
|||
*************************************************************************
|
||||
** This file contains code used to implement the ATTACH and DETACH commands.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
#ifndef SQLITE_OMIT_ATTACH
|
||||
/*
|
||||
|
@ -96,7 +95,7 @@ static void attachFunc(
|
|||
if( zFile==0 ) zFile = "";
|
||||
if( zName==0 ) zName = "";
|
||||
|
||||
#ifdef SQLITE_ENABLE_DESERIALIZE
|
||||
#ifndef SQLITE_OMIT_DESERIALIZE
|
||||
# define REOPEN_AS_MEMDB(db) (db->init.reopenMemdb)
|
||||
#else
|
||||
# define REOPEN_AS_MEMDB(db) (0)
|
||||
|
@ -347,17 +346,18 @@ static void codeAttach(
|
|||
sName.pParse = pParse;
|
||||
|
||||
if(
|
||||
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) ||
|
||||
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) ||
|
||||
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey))
|
||||
SQLITE_OK!=resolveAttachExpr(&sName, pFilename) ||
|
||||
SQLITE_OK!=resolveAttachExpr(&sName, pDbname) ||
|
||||
SQLITE_OK!=resolveAttachExpr(&sName, pKey)
|
||||
){
|
||||
goto attach_end;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
if( pAuthArg ){
|
||||
if( ALWAYS(pAuthArg) ){
|
||||
char *zAuthArg;
|
||||
if( pAuthArg->op==TK_STRING ){
|
||||
assert( !ExprHasProperty(pAuthArg, EP_IntValue) );
|
||||
zAuthArg = pAuthArg->u.zToken;
|
||||
}else{
|
||||
zAuthArg = 0;
|
||||
|
@ -465,19 +465,26 @@ static int fixSelectCb(Walker *p, Select *pSelect){
|
|||
if( NEVER(pList==0) ) return WRC_Continue;
|
||||
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
|
||||
if( pFix->bTemp==0 ){
|
||||
if( pItem->zDatabase && iDb!=sqlite3FindDbName(db, pItem->zDatabase) ){
|
||||
sqlite3ErrorMsg(pFix->pParse,
|
||||
"%s %T cannot reference objects in database %s",
|
||||
pFix->zType, pFix->pName, pItem->zDatabase);
|
||||
return WRC_Abort;
|
||||
if( pItem->zDatabase ){
|
||||
if( iDb!=sqlite3FindDbName(db, pItem->zDatabase) ){
|
||||
sqlite3ErrorMsg(pFix->pParse,
|
||||
"%s %T cannot reference objects in database %s",
|
||||
pFix->zType, pFix->pName, pItem->zDatabase);
|
||||
return WRC_Abort;
|
||||
}
|
||||
sqlite3DbFree(db, pItem->zDatabase);
|
||||
pItem->zDatabase = 0;
|
||||
pItem->fg.notCte = 1;
|
||||
}
|
||||
sqlite3DbFree(db, pItem->zDatabase);
|
||||
pItem->zDatabase = 0;
|
||||
pItem->pSchema = pFix->pSchema;
|
||||
pItem->fg.fromDDL = 1;
|
||||
}
|
||||
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
|
||||
if( sqlite3WalkExpr(&pFix->w, pList->a[i].pOn) ) return WRC_Abort;
|
||||
if( pList->a[i].fg.isUsing==0
|
||||
&& sqlite3WalkExpr(&pFix->w, pList->a[i].u3.pOn)
|
||||
){
|
||||
return WRC_Abort;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if( pSelect->pWith ){
|
||||
|
@ -512,7 +519,7 @@ void sqlite3FixInit(
|
|||
pFix->w.pParse = pParse;
|
||||
pFix->w.xExprCallback = fixExprCb;
|
||||
pFix->w.xSelectCallback = fixSelectCb;
|
||||
pFix->w.xSelectCallback2 = 0;
|
||||
pFix->w.xSelectCallback2 = sqlite3WalkWinDefnDummyCallback;
|
||||
pFix->w.walkerDepth = 0;
|
||||
pFix->w.eCode = 0;
|
||||
pFix->w.u.pFix = pFix;
|
||||
|
@ -574,14 +581,16 @@ int sqlite3FixTriggerStep(
|
|||
return 1;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_UPSERT
|
||||
if( pStep->pUpsert ){
|
||||
Upsert *pUp = pStep->pUpsert;
|
||||
if( sqlite3WalkExprList(&pFix->w, pUp->pUpsertTarget)
|
||||
|| sqlite3WalkExpr(&pFix->w, pUp->pUpsertTargetWhere)
|
||||
|| sqlite3WalkExprList(&pFix->w, pUp->pUpsertSet)
|
||||
|| sqlite3WalkExpr(&pFix->w, pUp->pUpsertWhere)
|
||||
){
|
||||
return 1;
|
||||
{
|
||||
Upsert *pUp;
|
||||
for(pUp=pStep->pUpsert; pUp; pUp=pUp->pNextUpsert){
|
||||
if( sqlite3WalkExprList(&pFix->w, pUp->pUpsertTarget)
|
||||
|| sqlite3WalkExpr(&pFix->w, pUp->pUpsertTargetWhere)
|
||||
|| sqlite3WalkExprList(&pFix->w, pUp->pUpsertSet)
|
||||
|| sqlite3WalkExpr(&pFix->w, pUp->pUpsertWhere)
|
||||
){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
7
third_party/sqlite3/auth.c
vendored
7
third_party/sqlite3/auth.c
vendored
|
@ -14,8 +14,7 @@
|
|||
** systems that do not need this facility may omit it by recompiling
|
||||
** the library with -DSQLITE_OMIT_AUTHORIZATION=1
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/*
|
||||
** All of the code in this file may be omitted by defining a single
|
||||
|
@ -176,10 +175,10 @@ void sqlite3AuthRead(
|
|||
|
||||
if( iCol>=0 ){
|
||||
assert( iCol<pTab->nCol );
|
||||
zCol = pTab->aCol[iCol].zName;
|
||||
zCol = pTab->aCol[iCol].zCnName;
|
||||
}else if( pTab->iPKey>=0 ){
|
||||
assert( pTab->iPKey<pTab->nCol );
|
||||
zCol = pTab->aCol[pTab->iPKey].zName;
|
||||
zCol = pTab->aCol[pTab->iPKey].zCnName;
|
||||
}else{
|
||||
zCol = "ROWID";
|
||||
}
|
||||
|
|
12
third_party/sqlite3/backup.c
vendored
12
third_party/sqlite3/backup.c
vendored
|
@ -9,12 +9,11 @@
|
|||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** This file contains the implementation of the sqlite3_backup_XXX()
|
||||
** This file contains the implementation of the sqlite3_backup_XXX()
|
||||
** API functions and the related features.
|
||||
*/
|
||||
#include "third_party/sqlite3/btreeInt.inc"
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
#include "third_party/sqlite3/btreeInt.h"
|
||||
|
||||
/*
|
||||
** Structure allocated for each backup operation.
|
||||
|
@ -86,14 +85,13 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
|
|||
if( i==1 ){
|
||||
Parse sParse;
|
||||
int rc = 0;
|
||||
memset(&sParse, 0, sizeof(sParse));
|
||||
sParse.db = pDb;
|
||||
sqlite3ParseObjectInit(&sParse,pDb);
|
||||
if( sqlite3OpenTempDatabase(&sParse) ){
|
||||
sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
sqlite3DbFree(pErrorDb, sParse.zErrMsg);
|
||||
sqlite3ParserReset(&sParse);
|
||||
sqlite3ParseObjectReset(&sParse);
|
||||
if( rc ){
|
||||
return 0;
|
||||
}
|
||||
|
|
9
third_party/sqlite3/bitvec.c
vendored
9
third_party/sqlite3/bitvec.c
vendored
|
@ -17,8 +17,8 @@
|
|||
** property. Usually only a few pages are meet either condition.
|
||||
** So the bitmap is usually sparse and has low cardinality.
|
||||
** But sometimes (for example when during a DROP of a large table) most
|
||||
** or all of the pages in a database can get journalled. In those cases,
|
||||
** the bitmap becomes dense with high cardinality. The algorithm needs
|
||||
** or all of the pages in a database can get journalled. In those cases,
|
||||
** the bitmap becomes dense with high cardinality. The algorithm needs
|
||||
** to handle both cases well.
|
||||
**
|
||||
** The size of the bitmap is fixed when the object is created.
|
||||
|
@ -34,8 +34,7 @@
|
|||
** start of a transaction, and is thus usually less than a few thousand,
|
||||
** but can be as large as 2 billion for a really big database.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/* Size of the Bitvec structure in bytes. */
|
||||
#define BITVEC_SZ 512
|
||||
|
@ -354,7 +353,7 @@ int sqlite3BitvecBuiltinTest(int sz, int *aOp){
|
|||
sqlite3BitvecClear(0, 1, pTmpSpace);
|
||||
|
||||
/* Run the program */
|
||||
pc = 0;
|
||||
pc = i = 0;
|
||||
while( (op = aOp[pc])!=0 ){
|
||||
switch( op ){
|
||||
case 1:
|
||||
|
|
5
third_party/sqlite3/btmutex.c
vendored
5
third_party/sqlite3/btmutex.c
vendored
|
@ -15,9 +15,7 @@
|
|||
** big and we want to break it down some. This packaged seemed like
|
||||
** a good breakout.
|
||||
*/
|
||||
#include "third_party/sqlite3/btreeInt.inc"
|
||||
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/btreeInt.h"
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
#if SQLITE_THREADSAFE
|
||||
|
||||
|
@ -254,6 +252,7 @@ int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){
|
|||
int sqlite3SchemaMutexHeld(sqlite3 *db, int iDb, Schema *pSchema){
|
||||
Btree *p;
|
||||
assert( db!=0 );
|
||||
if( db->pVfs==0 && db->nDb==0 ) return 1;
|
||||
if( pSchema ) iDb = sqlite3SchemaToIndex(db, pSchema);
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
if( !sqlite3_mutex_held(db->mutex) ) return 0;
|
||||
|
|
1250
third_party/sqlite3/btree.c
vendored
1250
third_party/sqlite3/btree.c
vendored
File diff suppressed because it is too large
Load diff
28
third_party/sqlite3/btree.inc
vendored
28
third_party/sqlite3/btree.inc
vendored
|
@ -1,6 +1,20 @@
|
|||
/*
|
||||
** 2001 September 15
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** This header file defines the interface that the sqlite B-Tree file
|
||||
** subsystem. See comments in the source code for a detailed description
|
||||
** of what each interface routine does.
|
||||
*/
|
||||
#ifndef SQLITE_BTREE_H
|
||||
#define SQLITE_BTREE_H
|
||||
/* clang-format off */
|
||||
|
||||
/* TODO: This definition is just included so other modules compile. It
|
||||
** needs to be revisited.
|
||||
|
@ -109,7 +123,7 @@ int sqlite3BtreeIncrVacuum(Btree *);
|
|||
#define BTREE_BLOBKEY 2 /* Table has keys only - no data */
|
||||
|
||||
int sqlite3BtreeDropTable(Btree*, int, int*);
|
||||
int sqlite3BtreeClearTable(Btree*, int, int*);
|
||||
int sqlite3BtreeClearTable(Btree*, int, i64*);
|
||||
int sqlite3BtreeClearTableOfCursor(BtCursor*);
|
||||
int sqlite3BtreeTripAllCursors(Btree*, int, int);
|
||||
|
||||
|
@ -233,13 +247,17 @@ void sqlite3BtreeCursorHint(BtCursor*, int, ...);
|
|||
#endif
|
||||
|
||||
int sqlite3BtreeCloseCursor(BtCursor*);
|
||||
int sqlite3BtreeMovetoUnpacked(
|
||||
int sqlite3BtreeTableMoveto(
|
||||
BtCursor*,
|
||||
UnpackedRecord *pUnKey,
|
||||
i64 intKey,
|
||||
int bias,
|
||||
int *pRes
|
||||
);
|
||||
int sqlite3BtreeIndexMoveto(
|
||||
BtCursor*,
|
||||
UnpackedRecord *pUnKey,
|
||||
int *pRes
|
||||
);
|
||||
int sqlite3BtreeCursorHasMoved(BtCursor*);
|
||||
int sqlite3BtreeCursorRestore(BtCursor*, int*);
|
||||
int sqlite3BtreeDelete(BtCursor*, u8 flags);
|
||||
|
@ -345,7 +363,7 @@ void sqlite3BtreeCursorList(Btree*);
|
|||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
/* int sqlite3BtreeCheckpoint(Btree*, int, int *, int *); */
|
||||
int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
|
||||
#endif
|
||||
|
||||
int sqlite3BtreeTransferRow(BtCursor*, BtCursor*, i64);
|
||||
|
|
|
@ -29,16 +29,16 @@
|
|||
** on Ptr(N) and its subpages have values greater than Key(N-1). And
|
||||
** so forth.
|
||||
**
|
||||
** Finding a particular key requires reading O(log(M)) pages from the
|
||||
** Finding a particular key requires reading O(log(M)) pages from the
|
||||
** disk where M is the number of entries in the tree.
|
||||
**
|
||||
** In this implementation, a single file can hold one or more separate
|
||||
** In this implementation, a single file can hold one or more separate
|
||||
** BTrees. Each BTree is identified by the index of its root page. The
|
||||
** key and data for any entry are combined to form the "payload". A
|
||||
** fixed amount of payload can be carried directly on the database
|
||||
** page. If the payload is larger than the preset amount then surplus
|
||||
** bytes are stored on overflow pages. The payload for an entry
|
||||
** and the preceding pointer are combined to form a "Cell". Each
|
||||
** and the preceding pointer are combined to form a "Cell". Each
|
||||
** page has a small header which contains the Ptr(N) pointer and other
|
||||
** information such as the size of key and data.
|
||||
**
|
||||
|
@ -168,7 +168,7 @@
|
|||
** contiguous or in order, but cell pointers are contiguous and in order.
|
||||
**
|
||||
** Cell content makes use of variable length integers. A variable
|
||||
** length integer is 1 to 9 bytes where the lower 7 bits of each
|
||||
** length integer is 1 to 9 bytes where the lower 7 bits of each
|
||||
** byte are used. The integer consists of all bytes that have bit 8 set and
|
||||
** the first byte with bit 8 clear. The most significant byte of the integer
|
||||
** appears first. A variable-length integer may not be more than 9 bytes long.
|
||||
|
@ -213,9 +213,8 @@
|
|||
** 4 Number of leaf pointers on this page
|
||||
** * zero or more pages numbers of leaves
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
/* The following value is the maximum cell size assuming a maximum page
|
||||
** size give above.
|
||||
|
@ -273,7 +272,6 @@ typedef struct CellInfo CellInfo;
|
|||
*/
|
||||
struct MemPage {
|
||||
u8 isInit; /* True if previously initialized. MUST BE FIRST! */
|
||||
u8 bBusy; /* Prevent endless loops on corrupt database files */
|
||||
u8 intKey; /* True if table b-trees. False for index b-trees */
|
||||
u8 intKeyLeaf; /* True if the leaf of an intKey table */
|
||||
Pgno pgno; /* Page number for this page */
|
||||
|
@ -295,7 +293,9 @@ struct MemPage {
|
|||
u8 *apOvfl[4]; /* Pointers to the body of overflow cells */
|
||||
BtShared *pBt; /* Pointer to BtShared that this page is part of */
|
||||
u8 *aData; /* Pointer to disk image of the page data */
|
||||
u8 *aDataEnd; /* One byte past the end of usable data */
|
||||
u8 *aDataEnd; /* One byte past the end of the entire page - not just
|
||||
** the usable space, the entire page. Used to prevent
|
||||
** corruption-induced buffer overflow. */
|
||||
u8 *aCellIdx; /* The cell index area */
|
||||
u8 *aDataOfst; /* Same as aData for leaves. aData+4 for interior */
|
||||
DbPage *pDbPage; /* Pager page handle */
|
||||
|
@ -600,7 +600,7 @@ struct BtCursor {
|
|||
/*
|
||||
** The database page the PENDING_BYTE occupies. This page is never used.
|
||||
*/
|
||||
# define PENDING_BYTE_PAGE(pBt) PAGER_MJ_PGNO(pBt)
|
||||
#define PENDING_BYTE_PAGE(pBt) ((Pgno)((PENDING_BYTE/((pBt)->pageSize))+1))
|
||||
|
||||
/*
|
||||
** These macros define the location of the pointer-map entry for a
|
912
third_party/sqlite3/build.c
vendored
912
third_party/sqlite3/build.c
vendored
File diff suppressed because it is too large
Load diff
14
third_party/sqlite3/callback.c
vendored
14
third_party/sqlite3/callback.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** 2005 May 23
|
||||
** 2005 May 23
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
|
@ -13,9 +13,8 @@
|
|||
** This file contains functions used to access the internal hash tables
|
||||
** of user defined functions and collation sequences.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/*
|
||||
** Invoke the 'collation needed' callback to request a collation sequence
|
||||
|
@ -338,6 +337,7 @@ FuncDef *sqlite3FunctionSearch(
|
|||
){
|
||||
FuncDef *p;
|
||||
for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){
|
||||
assert( p->funcFlags & SQLITE_FUNC_BUILTIN );
|
||||
if( sqlite3StrICmp(p->zName, zFunc)==0 ){
|
||||
return p;
|
||||
}
|
||||
|
@ -358,7 +358,7 @@ void sqlite3InsertBuiltinFuncs(
|
|||
const char *zName = aDef[i].zName;
|
||||
int nName = sqlite3Strlen30(zName);
|
||||
int h = SQLITE_FUNC_HASH(zName[0], nName);
|
||||
assert( zName[0]>='a' && zName[0]<='z' );
|
||||
assert( aDef[i].funcFlags & SQLITE_FUNC_BUILTIN );
|
||||
pOther = sqlite3FunctionSearch(h, zName);
|
||||
if( pOther ){
|
||||
assert( pOther!=&aDef[i] && pOther->pNext!=&aDef[i] );
|
||||
|
@ -490,19 +490,21 @@ void sqlite3SchemaClear(void *p){
|
|||
Hash temp2;
|
||||
HashElem *pElem;
|
||||
Schema *pSchema = (Schema *)p;
|
||||
sqlite3 xdb;
|
||||
|
||||
memset(&xdb, 0, sizeof(xdb));
|
||||
temp1 = pSchema->tblHash;
|
||||
temp2 = pSchema->trigHash;
|
||||
sqlite3HashInit(&pSchema->trigHash);
|
||||
sqlite3HashClear(&pSchema->idxHash);
|
||||
for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
|
||||
sqlite3DeleteTrigger(0, (Trigger*)sqliteHashData(pElem));
|
||||
sqlite3DeleteTrigger(&xdb, (Trigger*)sqliteHashData(pElem));
|
||||
}
|
||||
sqlite3HashClear(&temp2);
|
||||
sqlite3HashInit(&pSchema->tblHash);
|
||||
for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
|
||||
Table *pTab = sqliteHashData(pElem);
|
||||
sqlite3DeleteTable(0, pTab);
|
||||
sqlite3DeleteTable(&xdb, pTab);
|
||||
}
|
||||
sqlite3HashClear(&temp1);
|
||||
sqlite3HashClear(&pSchema->fkeyHash);
|
||||
|
|
5
third_party/sqlite3/complete.c
vendored
5
third_party/sqlite3/complete.c
vendored
|
@ -16,10 +16,7 @@
|
|||
** separating it out, the code will be automatically omitted from
|
||||
** static links that do not use it.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
#ifndef SQLITE_OMIT_COMPLETE
|
||||
|
||||
/*
|
||||
|
|
446
third_party/sqlite3/ctime.c
vendored
446
third_party/sqlite3/ctime.c
vendored
|
@ -1,3 +1,11 @@
|
|||
/* DO NOT EDIT!
|
||||
** This file is automatically generated by the script in the canonical
|
||||
** SQLite source tree at tool/mkctimec.tcl.
|
||||
**
|
||||
** To modify this header, edit any of the various lists in that script
|
||||
** which specify categories of generated conditionals in this file.
|
||||
*/
|
||||
|
||||
/*
|
||||
** 2010 February 23
|
||||
**
|
||||
|
@ -13,10 +21,17 @@
|
|||
** This file implements routines used to report what compile-time options
|
||||
** SQLite was built with.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* IMP: R-16824-07538 */
|
||||
|
||||
/*
|
||||
** Include the configuration header output by 'configure' if we're using the
|
||||
** autoconf-based build
|
||||
*/
|
||||
#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
|
||||
#include "sqlite_cfg.h"
|
||||
#define SQLITECONFIG_H 1
|
||||
#endif
|
||||
|
||||
/* These macros are provided to "stringify" the value of the define
|
||||
** for those options in which the value is meaningful. */
|
||||
#define CTIMEOPT_VAL_(opt) #opt
|
||||
|
@ -27,6 +42,7 @@
|
|||
** comma. e.g. (-DSQLITE_DEFAULT_LOOKASIDE="100,100") */
|
||||
#define CTIMEOPT_VAL2_(opt1,opt2) #opt1 "," #opt2
|
||||
#define CTIMEOPT_VAL2(opt) CTIMEOPT_VAL2_(opt)
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/*
|
||||
** An array of names of all compile-time options. This array should
|
||||
|
@ -38,34 +54,36 @@
|
|||
*/
|
||||
static const char * const sqlite3azCompileOpt[] = {
|
||||
|
||||
/*
|
||||
** BEGIN CODE GENERATED BY tool/mkctime.tcl
|
||||
*/
|
||||
#if SQLITE_32BIT_ROWID
|
||||
#ifdef SQLITE_32BIT_ROWID
|
||||
"32BIT_ROWID",
|
||||
#endif
|
||||
#if SQLITE_4_BYTE_ALIGNED_MALLOC
|
||||
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
|
||||
"4_BYTE_ALIGNED_MALLOC",
|
||||
#endif
|
||||
#if SQLITE_64BIT_STATS
|
||||
#ifdef SQLITE_64BIT_STATS
|
||||
"64BIT_STATS",
|
||||
#endif
|
||||
#if SQLITE_ALLOW_COVERING_INDEX_SCAN
|
||||
"ALLOW_COVERING_INDEX_SCAN",
|
||||
#ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN
|
||||
# if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1
|
||||
"ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
|
||||
# endif
|
||||
#endif
|
||||
#if SQLITE_ALLOW_URI_AUTHORITY
|
||||
#ifdef SQLITE_ALLOW_URI_AUTHORITY
|
||||
"ALLOW_URI_AUTHORITY",
|
||||
#endif
|
||||
#ifdef SQLITE_ATOMIC_INTRINSICS
|
||||
"ATOMIC_INTRINSICS=" CTIMEOPT_VAL(SQLITE_ATOMIC_INTRINSICS),
|
||||
#endif
|
||||
#ifdef SQLITE_BITMASK_TYPE
|
||||
"BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
|
||||
#endif
|
||||
#if SQLITE_BUG_COMPATIBLE_20160819
|
||||
#ifdef SQLITE_BUG_COMPATIBLE_20160819
|
||||
"BUG_COMPATIBLE_20160819",
|
||||
#endif
|
||||
#if SQLITE_CASE_SENSITIVE_LIKE
|
||||
#ifdef SQLITE_CASE_SENSITIVE_LIKE
|
||||
"CASE_SENSITIVE_LIKE",
|
||||
#endif
|
||||
#if SQLITE_CHECK_PAGES
|
||||
#ifdef SQLITE_CHECK_PAGES
|
||||
"CHECK_PAGES",
|
||||
#endif
|
||||
#if defined(__clang__) && defined(__clang_major__)
|
||||
|
@ -77,22 +95,22 @@ static const char * const sqlite3azCompileOpt[] = {
|
|||
#elif defined(__GNUC__) && defined(__VERSION__)
|
||||
"COMPILER=gcc-" __VERSION__,
|
||||
#endif
|
||||
#if SQLITE_COVERAGE_TEST
|
||||
#ifdef SQLITE_COVERAGE_TEST
|
||||
"COVERAGE_TEST",
|
||||
#endif
|
||||
#if SQLITE_DEBUG
|
||||
#ifdef SQLITE_DEBUG
|
||||
"DEBUG",
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_AUTOMATIC_INDEX
|
||||
#ifdef SQLITE_DEFAULT_AUTOMATIC_INDEX
|
||||
"DEFAULT_AUTOMATIC_INDEX",
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_AUTOVACUUM
|
||||
#ifdef SQLITE_DEFAULT_AUTOVACUUM
|
||||
"DEFAULT_AUTOVACUUM",
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_CACHE_SIZE
|
||||
"DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE),
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_CKPTFULLFSYNC
|
||||
#ifdef SQLITE_DEFAULT_CKPTFULLFSYNC
|
||||
"DEFAULT_CKPTFULLFSYNC",
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_FILE_FORMAT
|
||||
|
@ -101,7 +119,7 @@ static const char * const sqlite3azCompileOpt[] = {
|
|||
#ifdef SQLITE_DEFAULT_FILE_PERMISSIONS
|
||||
"DEFAULT_FILE_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_PERMISSIONS),
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_FOREIGN_KEYS
|
||||
#ifdef SQLITE_DEFAULT_FOREIGN_KEYS
|
||||
"DEFAULT_FOREIGN_KEYS",
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
|
||||
|
@ -113,8 +131,10 @@ static const char * const sqlite3azCompileOpt[] = {
|
|||
#ifdef SQLITE_DEFAULT_LOOKASIDE
|
||||
"DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE),
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_MEMSTATUS
|
||||
"DEFAULT_MEMSTATUS",
|
||||
#ifdef SQLITE_DEFAULT_MEMSTATUS
|
||||
# if SQLITE_DEFAULT_MEMSTATUS != 1
|
||||
"DEFAULT_MEMSTATUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_MEMSTATUS),
|
||||
# endif
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_MMAP_SIZE
|
||||
"DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
|
||||
|
@ -128,7 +148,7 @@ static const char * const sqlite3azCompileOpt[] = {
|
|||
#ifdef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
|
||||
"DEFAULT_PROXYDIR_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_PROXYDIR_PERMISSIONS),
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_RECURSIVE_TRIGGERS
|
||||
#ifdef SQLITE_DEFAULT_RECURSIVE_TRIGGERS
|
||||
"DEFAULT_RECURSIVE_TRIGGERS",
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_ROWEST
|
||||
|
@ -149,193 +169,196 @@ static const char * const sqlite3azCompileOpt[] = {
|
|||
#ifdef SQLITE_DEFAULT_WORKER_THREADS
|
||||
"DEFAULT_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WORKER_THREADS),
|
||||
#endif
|
||||
#if SQLITE_DIRECT_OVERFLOW_READ
|
||||
#ifdef SQLITE_DIRECT_OVERFLOW_READ
|
||||
"DIRECT_OVERFLOW_READ",
|
||||
#endif
|
||||
#if SQLITE_DISABLE_DIRSYNC
|
||||
#ifdef SQLITE_DISABLE_DIRSYNC
|
||||
"DISABLE_DIRSYNC",
|
||||
#endif
|
||||
#if SQLITE_DISABLE_FTS3_UNICODE
|
||||
#ifdef SQLITE_DISABLE_FTS3_UNICODE
|
||||
"DISABLE_FTS3_UNICODE",
|
||||
#endif
|
||||
#if SQLITE_DISABLE_FTS4_DEFERRED
|
||||
#ifdef SQLITE_DISABLE_FTS4_DEFERRED
|
||||
"DISABLE_FTS4_DEFERRED",
|
||||
#endif
|
||||
#if SQLITE_DISABLE_INTRINSIC
|
||||
#ifdef SQLITE_DISABLE_INTRINSIC
|
||||
"DISABLE_INTRINSIC",
|
||||
#endif
|
||||
#if SQLITE_DISABLE_LFS
|
||||
#ifdef SQLITE_DISABLE_LFS
|
||||
"DISABLE_LFS",
|
||||
#endif
|
||||
#if SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
|
||||
#ifdef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
|
||||
"DISABLE_PAGECACHE_OVERFLOW_STATS",
|
||||
#endif
|
||||
#if SQLITE_DISABLE_SKIPAHEAD_DISTINCT
|
||||
#ifdef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
|
||||
"DISABLE_SKIPAHEAD_DISTINCT",
|
||||
#endif
|
||||
#ifdef SQLITE_DQS
|
||||
"DQS=" CTIMEOPT_VAL(SQLITE_DQS),
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_8_3_NAMES
|
||||
"ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES),
|
||||
#endif
|
||||
#if SQLITE_ENABLE_API_ARMOR
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
"ENABLE_API_ARMOR",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_ATOMIC_WRITE
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
"ENABLE_ATOMIC_WRITE",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_BATCH_ATOMIC_WRITE
|
||||
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
|
||||
"ENABLE_BATCH_ATOMIC_WRITE",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_BYTECODE_VTAB
|
||||
#ifdef SQLITE_ENABLE_BYTECODE_VTAB
|
||||
"ENABLE_BYTECODE_VTAB",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_CEROD
|
||||
#ifdef SQLITE_ENABLE_CEROD
|
||||
"ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
|
||||
#endif
|
||||
#if SQLITE_ENABLE_COLUMN_METADATA
|
||||
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||
"ENABLE_COLUMN_METADATA",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_COLUMN_USED_MASK
|
||||
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
|
||||
"ENABLE_COLUMN_USED_MASK",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_COSTMULT
|
||||
#ifdef SQLITE_ENABLE_COSTMULT
|
||||
"ENABLE_COSTMULT",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_CURSOR_HINTS
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
"ENABLE_CURSOR_HINTS",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_DBSTAT_VTAB
|
||||
#ifdef SQLITE_ENABLE_DBPAGE_VTAB
|
||||
"ENABLE_DBPAGE_VTAB",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_DBSTAT_VTAB
|
||||
"ENABLE_DBSTAT_VTAB",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_EXPENSIVE_ASSERT
|
||||
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
|
||||
"ENABLE_EXPENSIVE_ASSERT",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_FTS1
|
||||
"ENABLE_FTS1",
|
||||
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
"ENABLE_EXPLAIN_COMMENTS",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_FTS2
|
||||
"ENABLE_FTS2",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_FTS3
|
||||
#ifdef SQLITE_ENABLE_FTS3
|
||||
"ENABLE_FTS3",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_FTS3_PARENTHESIS
|
||||
#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
|
||||
"ENABLE_FTS3_PARENTHESIS",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_FTS3_TOKENIZER
|
||||
#ifdef SQLITE_ENABLE_FTS3_TOKENIZER
|
||||
"ENABLE_FTS3_TOKENIZER",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_FTS4
|
||||
#ifdef SQLITE_ENABLE_FTS4
|
||||
"ENABLE_FTS4",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_FTS5
|
||||
#ifdef SQLITE_ENABLE_FTS5
|
||||
"ENABLE_FTS5",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_GEOPOLY
|
||||
#ifdef SQLITE_ENABLE_GEOPOLY
|
||||
"ENABLE_GEOPOLY",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_HIDDEN_COLUMNS
|
||||
#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS
|
||||
"ENABLE_HIDDEN_COLUMNS",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_ICU
|
||||
#ifdef SQLITE_ENABLE_ICU
|
||||
"ENABLE_ICU",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_IOTRACE
|
||||
#ifdef SQLITE_ENABLE_IOTRACE
|
||||
"ENABLE_IOTRACE",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_JSON1
|
||||
"ENABLE_JSON1",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_LOAD_EXTENSION
|
||||
#ifdef SQLITE_ENABLE_LOAD_EXTENSION
|
||||
"ENABLE_LOAD_EXTENSION",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_LOCKING_STYLE
|
||||
"ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
|
||||
#endif
|
||||
#if SQLITE_ENABLE_MATH_FUNCTIONS
|
||||
#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
|
||||
"ENABLE_MATH_FUNCTIONS",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
"ENABLE_MEMORY_MANAGEMENT",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_MEMSYS3
|
||||
#ifdef SQLITE_ENABLE_MEMSYS3
|
||||
"ENABLE_MEMSYS3",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_MEMSYS5
|
||||
#ifdef SQLITE_ENABLE_MEMSYS5
|
||||
"ENABLE_MEMSYS5",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_MULTIPLEX
|
||||
#ifdef SQLITE_ENABLE_MULTIPLEX
|
||||
"ENABLE_MULTIPLEX",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_NORMALIZE
|
||||
#ifdef SQLITE_ENABLE_NORMALIZE
|
||||
"ENABLE_NORMALIZE",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_NULL_TRIM
|
||||
#ifdef SQLITE_ENABLE_NULL_TRIM
|
||||
"ENABLE_NULL_TRIM",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK
|
||||
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
"ENABLE_OFFSET_SQL_FUNC",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
|
||||
"ENABLE_OVERSIZE_CELL_CHECK",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
"ENABLE_PREUPDATE_HOOK",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_QPSG
|
||||
#ifdef SQLITE_ENABLE_QPSG
|
||||
"ENABLE_QPSG",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_RBU
|
||||
#ifdef SQLITE_ENABLE_RBU
|
||||
"ENABLE_RBU",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_RTREE
|
||||
#ifdef SQLITE_ENABLE_RTREE
|
||||
"ENABLE_RTREE",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_SELECTTRACE
|
||||
"ENABLE_SELECTTRACE",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_SESSION
|
||||
#ifdef SQLITE_ENABLE_SESSION
|
||||
"ENABLE_SESSION",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_SNAPSHOT
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
"ENABLE_SNAPSHOT",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_SORTER_REFERENCES
|
||||
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
|
||||
"ENABLE_SORTER_REFERENCES",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_SQLLOG
|
||||
#ifdef SQLITE_ENABLE_SQLLOG
|
||||
"ENABLE_SQLLOG",
|
||||
#endif
|
||||
#if defined(SQLITE_ENABLE_STAT4)
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
"ENABLE_STAT4",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_STMTVTAB
|
||||
#ifdef SQLITE_ENABLE_STMTVTAB
|
||||
"ENABLE_STMTVTAB",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
"ENABLE_STMT_SCANSTATUS",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||
#ifdef SQLITE_ENABLE_TREETRACE
|
||||
"ENABLE_TREETRACE",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||
"ENABLE_UNKNOWN_SQL_FUNCTION",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
"ENABLE_UNLOCK_NOTIFY",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
|
||||
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
|
||||
"ENABLE_UPDATE_DELETE_LIMIT",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_URI_00_ERROR
|
||||
#ifdef SQLITE_ENABLE_URI_00_ERROR
|
||||
"ENABLE_URI_00_ERROR",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_VFSTRACE
|
||||
#ifdef SQLITE_ENABLE_VFSTRACE
|
||||
"ENABLE_VFSTRACE",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_WHERETRACE
|
||||
#ifdef SQLITE_ENABLE_WHERETRACE
|
||||
"ENABLE_WHERETRACE",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_ZIPVFS
|
||||
#ifdef SQLITE_ENABLE_ZIPVFS
|
||||
"ENABLE_ZIPVFS",
|
||||
#endif
|
||||
#if SQLITE_EXPLAIN_ESTIMATED_ROWS
|
||||
#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS
|
||||
"EXPLAIN_ESTIMATED_ROWS",
|
||||
#endif
|
||||
#if SQLITE_EXTRA_IFNULLROW
|
||||
#ifdef SQLITE_EXTRA_IFNULLROW
|
||||
"EXTRA_IFNULLROW",
|
||||
#endif
|
||||
#ifdef SQLITE_EXTRA_INIT
|
||||
|
@ -347,40 +370,42 @@ static const char * const sqlite3azCompileOpt[] = {
|
|||
#ifdef SQLITE_FTS3_MAX_EXPR_DEPTH
|
||||
"FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH),
|
||||
#endif
|
||||
#if SQLITE_FTS5_ENABLE_TEST_MI
|
||||
#ifdef SQLITE_FTS5_ENABLE_TEST_MI
|
||||
"FTS5_ENABLE_TEST_MI",
|
||||
#endif
|
||||
#if SQLITE_FTS5_NO_WITHOUT_ROWID
|
||||
#ifdef SQLITE_FTS5_NO_WITHOUT_ROWID
|
||||
"FTS5_NO_WITHOUT_ROWID",
|
||||
#endif
|
||||
#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
|
||||
"HAVE_ISNAN",
|
||||
#endif
|
||||
#if SQLITE_HOMEGROWN_RECURSIVE_MUTEX
|
||||
"HOMEGROWN_RECURSIVE_MUTEX",
|
||||
#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
|
||||
# if SQLITE_HOMEGROWN_RECURSIVE_MUTEX != 1
|
||||
"HOMEGROWN_RECURSIVE_MUTEX=" CTIMEOPT_VAL(SQLITE_HOMEGROWN_RECURSIVE_MUTEX),
|
||||
# endif
|
||||
#endif
|
||||
#if SQLITE_IGNORE_AFP_LOCK_ERRORS
|
||||
#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
|
||||
"IGNORE_AFP_LOCK_ERRORS",
|
||||
#endif
|
||||
#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS
|
||||
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
|
||||
"IGNORE_FLOCK_LOCK_ERRORS",
|
||||
#endif
|
||||
#if SQLITE_INLINE_MEMCPY
|
||||
#ifdef SQLITE_INLINE_MEMCPY
|
||||
"INLINE_MEMCPY",
|
||||
#endif
|
||||
#if SQLITE_INT64_TYPE
|
||||
#ifdef SQLITE_INT64_TYPE
|
||||
"INT64_TYPE",
|
||||
#endif
|
||||
#ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX
|
||||
"INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX),
|
||||
#endif
|
||||
#if SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
"LIKE_DOESNT_MATCH_BLOBS",
|
||||
#endif
|
||||
#if SQLITE_LOCK_TRACE
|
||||
#ifdef SQLITE_LOCK_TRACE
|
||||
"LOCK_TRACE",
|
||||
#endif
|
||||
#if SQLITE_LOG_CACHE_SPILL
|
||||
#ifdef SQLITE_LOG_CACHE_SPILL
|
||||
"LOG_CACHE_SPILL",
|
||||
#endif
|
||||
#ifdef SQLITE_MALLOC_SOFT_LIMIT
|
||||
|
@ -443,250 +468,254 @@ static const char * const sqlite3azCompileOpt[] = {
|
|||
#ifdef SQLITE_MAX_WORKER_THREADS
|
||||
"MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS),
|
||||
#endif
|
||||
#if SQLITE_MEMDEBUG
|
||||
#ifdef SQLITE_MEMDEBUG
|
||||
"MEMDEBUG",
|
||||
#endif
|
||||
#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
|
||||
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
|
||||
"MIXED_ENDIAN_64BIT_FLOAT",
|
||||
#endif
|
||||
#if SQLITE_MMAP_READWRITE
|
||||
#ifdef SQLITE_MMAP_READWRITE
|
||||
"MMAP_READWRITE",
|
||||
#endif
|
||||
#if SQLITE_MUTEX_NOOP
|
||||
#ifdef SQLITE_MUTEX_NOOP
|
||||
"MUTEX_NOOP",
|
||||
#endif
|
||||
#if SQLITE_MUTEX_NREF
|
||||
"MUTEX_NREF",
|
||||
#endif
|
||||
#if SQLITE_MUTEX_OMIT
|
||||
#ifdef SQLITE_MUTEX_OMIT
|
||||
"MUTEX_OMIT",
|
||||
#endif
|
||||
#if SQLITE_MUTEX_PTHREADS
|
||||
#ifdef SQLITE_MUTEX_PTHREADS
|
||||
"MUTEX_PTHREADS",
|
||||
#endif
|
||||
#if SQLITE_MUTEX_W32
|
||||
#ifdef SQLITE_MUTEX_W32
|
||||
"MUTEX_W32",
|
||||
#endif
|
||||
#if SQLITE_NEED_ERR_NAME
|
||||
#ifdef SQLITE_NEED_ERR_NAME
|
||||
"NEED_ERR_NAME",
|
||||
#endif
|
||||
#if SQLITE_NOINLINE
|
||||
"NOINLINE",
|
||||
#endif
|
||||
#if SQLITE_NO_SYNC
|
||||
#ifdef SQLITE_NO_SYNC
|
||||
"NO_SYNC",
|
||||
#endif
|
||||
#if SQLITE_OMIT_ALTERTABLE
|
||||
#ifdef SQLITE_OMIT_ALTERTABLE
|
||||
"OMIT_ALTERTABLE",
|
||||
#endif
|
||||
#if SQLITE_OMIT_ANALYZE
|
||||
#ifdef SQLITE_OMIT_ANALYZE
|
||||
"OMIT_ANALYZE",
|
||||
#endif
|
||||
#if SQLITE_OMIT_ATTACH
|
||||
#ifdef SQLITE_OMIT_ATTACH
|
||||
"OMIT_ATTACH",
|
||||
#endif
|
||||
#if SQLITE_OMIT_AUTHORIZATION
|
||||
#ifdef SQLITE_OMIT_AUTHORIZATION
|
||||
"OMIT_AUTHORIZATION",
|
||||
#endif
|
||||
#if SQLITE_OMIT_AUTOINCREMENT
|
||||
#ifdef SQLITE_OMIT_AUTOINCREMENT
|
||||
"OMIT_AUTOINCREMENT",
|
||||
#endif
|
||||
#if SQLITE_OMIT_AUTOINIT
|
||||
#ifdef SQLITE_OMIT_AUTOINIT
|
||||
"OMIT_AUTOINIT",
|
||||
#endif
|
||||
#if SQLITE_OMIT_AUTOMATIC_INDEX
|
||||
#ifdef SQLITE_OMIT_AUTOMATIC_INDEX
|
||||
"OMIT_AUTOMATIC_INDEX",
|
||||
#endif
|
||||
#if SQLITE_OMIT_AUTORESET
|
||||
#ifdef SQLITE_OMIT_AUTORESET
|
||||
"OMIT_AUTORESET",
|
||||
#endif
|
||||
#if SQLITE_OMIT_AUTOVACUUM
|
||||
#ifdef SQLITE_OMIT_AUTOVACUUM
|
||||
"OMIT_AUTOVACUUM",
|
||||
#endif
|
||||
#if SQLITE_OMIT_BETWEEN_OPTIMIZATION
|
||||
#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
|
||||
"OMIT_BETWEEN_OPTIMIZATION",
|
||||
#endif
|
||||
#if SQLITE_OMIT_BLOB_LITERAL
|
||||
#ifdef SQLITE_OMIT_BLOB_LITERAL
|
||||
"OMIT_BLOB_LITERAL",
|
||||
#endif
|
||||
#if SQLITE_OMIT_CAST
|
||||
#ifdef SQLITE_OMIT_CAST
|
||||
"OMIT_CAST",
|
||||
#endif
|
||||
#if SQLITE_OMIT_CHECK
|
||||
#ifdef SQLITE_OMIT_CHECK
|
||||
"OMIT_CHECK",
|
||||
#endif
|
||||
#if SQLITE_OMIT_COMPLETE
|
||||
#ifdef SQLITE_OMIT_COMPLETE
|
||||
"OMIT_COMPLETE",
|
||||
#endif
|
||||
#if SQLITE_OMIT_COMPOUND_SELECT
|
||||
#ifdef SQLITE_OMIT_COMPOUND_SELECT
|
||||
"OMIT_COMPOUND_SELECT",
|
||||
#endif
|
||||
#if SQLITE_OMIT_CONFLICT_CLAUSE
|
||||
#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
|
||||
"OMIT_CONFLICT_CLAUSE",
|
||||
#endif
|
||||
#if SQLITE_OMIT_CTE
|
||||
#ifdef SQLITE_OMIT_CTE
|
||||
"OMIT_CTE",
|
||||
#endif
|
||||
#if SQLITE_OMIT_DATETIME_FUNCS
|
||||
#if defined(SQLITE_OMIT_DATETIME_FUNCS) || defined(SQLITE_OMIT_FLOATING_POINT)
|
||||
"OMIT_DATETIME_FUNCS",
|
||||
#endif
|
||||
#if SQLITE_OMIT_DECLTYPE
|
||||
#ifdef SQLITE_OMIT_DECLTYPE
|
||||
"OMIT_DECLTYPE",
|
||||
#endif
|
||||
#if SQLITE_OMIT_DEPRECATED
|
||||
#ifdef SQLITE_OMIT_DEPRECATED
|
||||
"OMIT_DEPRECATED",
|
||||
#endif
|
||||
#if SQLITE_OMIT_DISKIO
|
||||
#ifdef SQLITE_OMIT_DESERIALIZE
|
||||
"OMIT_DESERIALIZE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_DISKIO
|
||||
"OMIT_DISKIO",
|
||||
#endif
|
||||
#if SQLITE_OMIT_EXPLAIN
|
||||
#ifdef SQLITE_OMIT_EXPLAIN
|
||||
"OMIT_EXPLAIN",
|
||||
#endif
|
||||
#if SQLITE_OMIT_FLAG_PRAGMAS
|
||||
#ifdef SQLITE_OMIT_FLAG_PRAGMAS
|
||||
"OMIT_FLAG_PRAGMAS",
|
||||
#endif
|
||||
#if SQLITE_OMIT_FLOATING_POINT
|
||||
#ifdef SQLITE_OMIT_FLOATING_POINT
|
||||
"OMIT_FLOATING_POINT",
|
||||
#endif
|
||||
#if SQLITE_OMIT_FOREIGN_KEY
|
||||
#ifdef SQLITE_OMIT_FOREIGN_KEY
|
||||
"OMIT_FOREIGN_KEY",
|
||||
#endif
|
||||
#if SQLITE_OMIT_GET_TABLE
|
||||
#ifdef SQLITE_OMIT_GET_TABLE
|
||||
"OMIT_GET_TABLE",
|
||||
#endif
|
||||
#if SQLITE_OMIT_HEX_INTEGER
|
||||
#ifdef SQLITE_OMIT_HEX_INTEGER
|
||||
"OMIT_HEX_INTEGER",
|
||||
#endif
|
||||
#if SQLITE_OMIT_INCRBLOB
|
||||
#ifdef SQLITE_OMIT_INCRBLOB
|
||||
"OMIT_INCRBLOB",
|
||||
#endif
|
||||
#if SQLITE_OMIT_INTEGRITY_CHECK
|
||||
#ifdef SQLITE_OMIT_INTEGRITY_CHECK
|
||||
"OMIT_INTEGRITY_CHECK",
|
||||
#endif
|
||||
#if SQLITE_OMIT_LIKE_OPTIMIZATION
|
||||
#ifdef SQLITE_OMIT_INTROSPECTION_PRAGMAS
|
||||
"OMIT_INTROSPECTION_PRAGMAS",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_JSON
|
||||
"OMIT_JSON",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
|
||||
"OMIT_LIKE_OPTIMIZATION",
|
||||
#endif
|
||||
#if SQLITE_OMIT_LOAD_EXTENSION
|
||||
#ifdef SQLITE_OMIT_LOAD_EXTENSION
|
||||
"OMIT_LOAD_EXTENSION",
|
||||
#endif
|
||||
#if SQLITE_OMIT_LOCALTIME
|
||||
#ifdef SQLITE_OMIT_LOCALTIME
|
||||
"OMIT_LOCALTIME",
|
||||
#endif
|
||||
#if SQLITE_OMIT_LOOKASIDE
|
||||
#ifdef SQLITE_OMIT_LOOKASIDE
|
||||
"OMIT_LOOKASIDE",
|
||||
#endif
|
||||
#if SQLITE_OMIT_MEMORYDB
|
||||
#ifdef SQLITE_OMIT_MEMORYDB
|
||||
"OMIT_MEMORYDB",
|
||||
#endif
|
||||
#if SQLITE_OMIT_OR_OPTIMIZATION
|
||||
#ifdef SQLITE_OMIT_OR_OPTIMIZATION
|
||||
"OMIT_OR_OPTIMIZATION",
|
||||
#endif
|
||||
#if SQLITE_OMIT_PAGER_PRAGMAS
|
||||
#ifdef SQLITE_OMIT_PAGER_PRAGMAS
|
||||
"OMIT_PAGER_PRAGMAS",
|
||||
#endif
|
||||
#if SQLITE_OMIT_PARSER_TRACE
|
||||
#ifdef SQLITE_OMIT_PARSER_TRACE
|
||||
"OMIT_PARSER_TRACE",
|
||||
#endif
|
||||
#if SQLITE_OMIT_POPEN
|
||||
#ifdef SQLITE_OMIT_POPEN
|
||||
"OMIT_POPEN",
|
||||
#endif
|
||||
#if SQLITE_OMIT_PRAGMA
|
||||
#ifdef SQLITE_OMIT_PRAGMA
|
||||
"OMIT_PRAGMA",
|
||||
#endif
|
||||
#if SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
"OMIT_PROGRESS_CALLBACK",
|
||||
#endif
|
||||
#if SQLITE_OMIT_QUICKBALANCE
|
||||
#ifdef SQLITE_OMIT_QUICKBALANCE
|
||||
"OMIT_QUICKBALANCE",
|
||||
#endif
|
||||
#if SQLITE_OMIT_REINDEX
|
||||
#ifdef SQLITE_OMIT_REINDEX
|
||||
"OMIT_REINDEX",
|
||||
#endif
|
||||
#if SQLITE_OMIT_SCHEMA_PRAGMAS
|
||||
#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
|
||||
"OMIT_SCHEMA_PRAGMAS",
|
||||
#endif
|
||||
#if SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
|
||||
#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
|
||||
"OMIT_SCHEMA_VERSION_PRAGMAS",
|
||||
#endif
|
||||
#if SQLITE_OMIT_SHARED_CACHE
|
||||
#ifdef SQLITE_OMIT_SHARED_CACHE
|
||||
"OMIT_SHARED_CACHE",
|
||||
#endif
|
||||
#if SQLITE_OMIT_SHUTDOWN_DIRECTORIES
|
||||
#ifdef SQLITE_OMIT_SHUTDOWN_DIRECTORIES
|
||||
"OMIT_SHUTDOWN_DIRECTORIES",
|
||||
#endif
|
||||
#if SQLITE_OMIT_SUBQUERY
|
||||
#ifdef SQLITE_OMIT_SUBQUERY
|
||||
"OMIT_SUBQUERY",
|
||||
#endif
|
||||
#if SQLITE_OMIT_TCL_VARIABLE
|
||||
#ifdef SQLITE_OMIT_TCL_VARIABLE
|
||||
"OMIT_TCL_VARIABLE",
|
||||
#endif
|
||||
#if SQLITE_OMIT_TEMPDB
|
||||
#ifdef SQLITE_OMIT_TEMPDB
|
||||
"OMIT_TEMPDB",
|
||||
#endif
|
||||
#if SQLITE_OMIT_TEST_CONTROL
|
||||
#ifdef SQLITE_OMIT_TEST_CONTROL
|
||||
"OMIT_TEST_CONTROL",
|
||||
#endif
|
||||
#if SQLITE_OMIT_TRACE
|
||||
"OMIT_TRACE",
|
||||
#ifdef SQLITE_OMIT_TRACE
|
||||
# if SQLITE_OMIT_TRACE != 1
|
||||
"OMIT_TRACE=" CTIMEOPT_VAL(SQLITE_OMIT_TRACE),
|
||||
# endif
|
||||
#endif
|
||||
#if SQLITE_OMIT_TRIGGER
|
||||
#ifdef SQLITE_OMIT_TRIGGER
|
||||
"OMIT_TRIGGER",
|
||||
#endif
|
||||
#if SQLITE_OMIT_TRUNCATE_OPTIMIZATION
|
||||
#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
|
||||
"OMIT_TRUNCATE_OPTIMIZATION",
|
||||
#endif
|
||||
#if SQLITE_OMIT_UTF16
|
||||
#ifdef SQLITE_OMIT_UTF16
|
||||
"OMIT_UTF16",
|
||||
#endif
|
||||
#if SQLITE_OMIT_VACUUM
|
||||
#ifdef SQLITE_OMIT_VACUUM
|
||||
"OMIT_VACUUM",
|
||||
#endif
|
||||
#if SQLITE_OMIT_VIEW
|
||||
#ifdef SQLITE_OMIT_VIEW
|
||||
"OMIT_VIEW",
|
||||
#endif
|
||||
#if SQLITE_OMIT_VIRTUALTABLE
|
||||
#ifdef SQLITE_OMIT_VIRTUALTABLE
|
||||
"OMIT_VIRTUALTABLE",
|
||||
#endif
|
||||
#if SQLITE_OMIT_WAL
|
||||
#ifdef SQLITE_OMIT_WAL
|
||||
"OMIT_WAL",
|
||||
#endif
|
||||
#if SQLITE_OMIT_WSD
|
||||
#ifdef SQLITE_OMIT_WSD
|
||||
"OMIT_WSD",
|
||||
#endif
|
||||
#if SQLITE_OMIT_XFER_OPT
|
||||
#ifdef SQLITE_OMIT_XFER_OPT
|
||||
"OMIT_XFER_OPT",
|
||||
#endif
|
||||
#if SQLITE_PCACHE_SEPARATE_HEADER
|
||||
"PCACHE_SEPARATE_HEADER",
|
||||
#endif
|
||||
#if SQLITE_PERFORMANCE_TRACE
|
||||
#ifdef SQLITE_PERFORMANCE_TRACE
|
||||
"PERFORMANCE_TRACE",
|
||||
#endif
|
||||
#if SQLITE_POWERSAFE_OVERWRITE
|
||||
"POWERSAFE_OVERWRITE",
|
||||
#ifdef SQLITE_POWERSAFE_OVERWRITE
|
||||
# if SQLITE_POWERSAFE_OVERWRITE != 1
|
||||
"POWERSAFE_OVERWRITE=" CTIMEOPT_VAL(SQLITE_POWERSAFE_OVERWRITE),
|
||||
# endif
|
||||
#endif
|
||||
#if SQLITE_PREFER_PROXY_LOCKING
|
||||
#ifdef SQLITE_PREFER_PROXY_LOCKING
|
||||
"PREFER_PROXY_LOCKING",
|
||||
#endif
|
||||
#if SQLITE_PROXY_DEBUG
|
||||
#ifdef SQLITE_PROXY_DEBUG
|
||||
"PROXY_DEBUG",
|
||||
#endif
|
||||
#if SQLITE_REVERSE_UNORDERED_SELECTS
|
||||
#ifdef SQLITE_REVERSE_UNORDERED_SELECTS
|
||||
"REVERSE_UNORDERED_SELECTS",
|
||||
#endif
|
||||
#if SQLITE_RTREE_INT_ONLY
|
||||
#ifdef SQLITE_RTREE_INT_ONLY
|
||||
"RTREE_INT_ONLY",
|
||||
#endif
|
||||
#if SQLITE_SECURE_DELETE
|
||||
#ifdef SQLITE_SECURE_DELETE
|
||||
"SECURE_DELETE",
|
||||
#endif
|
||||
#if SQLITE_SMALL_STACK
|
||||
#ifdef SQLITE_SMALL_STACK
|
||||
"SMALL_STACK",
|
||||
#endif
|
||||
#ifdef SQLITE_SORTER_PMASZ
|
||||
"SORTER_PMASZ=" CTIMEOPT_VAL(SQLITE_SORTER_PMASZ),
|
||||
#endif
|
||||
#if SQLITE_SOUNDEX
|
||||
#ifdef SQLITE_SOUNDEX
|
||||
"SOUNDEX",
|
||||
#endif
|
||||
#ifdef SQLITE_STAT4_SAMPLES
|
||||
|
@ -695,19 +724,22 @@ static const char * const sqlite3azCompileOpt[] = {
|
|||
#ifdef SQLITE_STMTJRNL_SPILL
|
||||
"STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL),
|
||||
#endif
|
||||
#if SQLITE_SUBSTR_COMPATIBILITY
|
||||
#ifdef SQLITE_SUBSTR_COMPATIBILITY
|
||||
"SUBSTR_COMPATIBILITY",
|
||||
#endif
|
||||
#if SQLITE_SYSTEM_MALLOC
|
||||
#if (!defined(SQLITE_WIN32_MALLOC) \
|
||||
&& !defined(SQLITE_ZERO_MALLOC) \
|
||||
&& !defined(SQLITE_MEMDEBUG) \
|
||||
) || defined(SQLITE_SYSTEM_MALLOC)
|
||||
"SYSTEM_MALLOC",
|
||||
#endif
|
||||
#if SQLITE_TCL
|
||||
#ifdef SQLITE_TCL
|
||||
"TCL",
|
||||
#endif
|
||||
#ifdef SQLITE_TEMP_STORE
|
||||
"TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
|
||||
#endif
|
||||
#if SQLITE_TEST
|
||||
#ifdef SQLITE_TEST
|
||||
"TEST",
|
||||
#endif
|
||||
#if defined(SQLITE_THREADSAFE)
|
||||
|
@ -717,37 +749,35 @@ static const char * const sqlite3azCompileOpt[] = {
|
|||
#else
|
||||
"THREADSAFE=1",
|
||||
#endif
|
||||
#if SQLITE_UNLINK_AFTER_CLOSE
|
||||
#ifdef SQLITE_UNLINK_AFTER_CLOSE
|
||||
"UNLINK_AFTER_CLOSE",
|
||||
#endif
|
||||
#if SQLITE_UNTESTABLE
|
||||
#ifdef SQLITE_UNTESTABLE
|
||||
"UNTESTABLE",
|
||||
#endif
|
||||
#if SQLITE_USER_AUTHENTICATION
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
"USER_AUTHENTICATION",
|
||||
#endif
|
||||
#if SQLITE_USE_ALLOCA
|
||||
#ifdef SQLITE_USE_ALLOCA
|
||||
"USE_ALLOCA",
|
||||
#endif
|
||||
#if SQLITE_USE_FCNTL_TRACE
|
||||
#ifdef SQLITE_USE_FCNTL_TRACE
|
||||
"USE_FCNTL_TRACE",
|
||||
#endif
|
||||
#if SQLITE_USE_URI
|
||||
#ifdef SQLITE_USE_URI
|
||||
"USE_URI",
|
||||
#endif
|
||||
#if SQLITE_VDBE_COVERAGE
|
||||
#ifdef SQLITE_VDBE_COVERAGE
|
||||
"VDBE_COVERAGE",
|
||||
#endif
|
||||
#if SQLITE_WIN32_MALLOC
|
||||
#ifdef SQLITE_WIN32_MALLOC
|
||||
"WIN32_MALLOC",
|
||||
#endif
|
||||
#if SQLITE_ZERO_MALLOC
|
||||
#ifdef SQLITE_ZERO_MALLOC
|
||||
"ZERO_MALLOC",
|
||||
#endif
|
||||
/*
|
||||
** END CODE GENERATED BY tool/mkctime.tcl
|
||||
*/
|
||||
};
|
||||
|
||||
} ;
|
||||
|
||||
const char **sqlite3CompileOptions(int *pnOpt){
|
||||
*pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]);
|
||||
|
|
515
third_party/sqlite3/date.c
vendored
515
third_party/sqlite3/date.c
vendored
|
@ -10,7 +10,7 @@
|
|||
**
|
||||
*************************************************************************
|
||||
** This file contains the C functions that implement date and time
|
||||
** functions for SQLite.
|
||||
** functions for SQLite.
|
||||
**
|
||||
** There is only one exported symbol in this file - the function
|
||||
** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
|
||||
|
@ -19,7 +19,7 @@
|
|||
** SQLite processes all times and dates as julian day numbers. The
|
||||
** dates and times are stored as the number of days since noon
|
||||
** in Greenwich on November 24, 4714 B.C. according to the Gregorian
|
||||
** calendar system.
|
||||
** calendar system.
|
||||
**
|
||||
** 1970-01-01 00:00:00 is JD 2440587.5
|
||||
** 2000-01-01 00:00:00 is JD 2451544.5
|
||||
|
@ -48,9 +48,7 @@
|
|||
#include "libc/mem/mem.h"
|
||||
#include "libc/time/struct/tm.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
#ifndef SQLITE_OMIT_DATETIME_FUNCS
|
||||
|
||||
|
@ -280,7 +278,7 @@ static void computeJD(DateTime *p){
|
|||
p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
|
||||
p->validJD = 1;
|
||||
if( p->validHMS ){
|
||||
p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000);
|
||||
p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000 + 0.5);
|
||||
if( p->validTZ ){
|
||||
p->iJD -= p->tz*60000;
|
||||
p->validYMD = 0;
|
||||
|
@ -507,8 +505,10 @@ static void clearYMD_HMS_TZ(DateTime *p){
|
|||
** is available. This routine returns 0 on success and
|
||||
** non-zero on any kind of error.
|
||||
**
|
||||
** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
|
||||
** routine will always fail.
|
||||
** If the sqlite3GlobalConfig.bLocaltimeFault variable is non-zero then this
|
||||
** routine will always fail. If bLocaltimeFault is nonzero and
|
||||
** sqlite3GlobalConfig.xAltLocaltime is not NULL, then xAltLocaltime() is
|
||||
** invoked in place of the OS-defined localtime() function.
|
||||
**
|
||||
** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C
|
||||
** library function localtime_r() is used to assist in the calculation of
|
||||
|
@ -524,14 +524,30 @@ static int osLocaltime(time_t *t, struct tm *pTm){
|
|||
sqlite3_mutex_enter(mutex);
|
||||
pX = localtime(t);
|
||||
#ifndef SQLITE_UNTESTABLE
|
||||
if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
|
||||
if( sqlite3GlobalConfig.bLocaltimeFault ){
|
||||
if( sqlite3GlobalConfig.xAltLocaltime!=0
|
||||
&& 0==sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm)
|
||||
){
|
||||
pX = pTm;
|
||||
}else{
|
||||
pX = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if( pX ) *pTm = *pX;
|
||||
#if SQLITE_THREADSAFE>0
|
||||
sqlite3_mutex_leave(mutex);
|
||||
#endif
|
||||
rc = pX==0;
|
||||
#else
|
||||
#ifndef SQLITE_UNTESTABLE
|
||||
if( sqlite3GlobalConfig.bLocaltimeFault ) return 1;
|
||||
if( sqlite3GlobalConfig.bLocaltimeFault ){
|
||||
if( sqlite3GlobalConfig.xAltLocaltime!=0 ){
|
||||
return sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm);
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if HAVE_LOCALTIME_R
|
||||
rc = localtime_r(t, pTm)==0;
|
||||
|
@ -546,67 +562,56 @@ static int osLocaltime(time_t *t, struct tm *pTm){
|
|||
|
||||
#ifndef SQLITE_OMIT_LOCALTIME
|
||||
/*
|
||||
** Compute the difference (in milliseconds) between localtime and UTC
|
||||
** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs,
|
||||
** return this value and set *pRc to SQLITE_OK.
|
||||
**
|
||||
** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value
|
||||
** is undefined in this case.
|
||||
** Assuming the input DateTime is UTC, move it to its localtime equivalent.
|
||||
*/
|
||||
static sqlite3_int64 localtimeOffset(
|
||||
DateTime *p, /* Date at which to calculate offset */
|
||||
sqlite3_context *pCtx, /* Write error here if one occurs */
|
||||
int *pRc /* OUT: Error code. SQLITE_OK or ERROR */
|
||||
static int toLocaltime(
|
||||
DateTime *p, /* Date at which to calculate offset */
|
||||
sqlite3_context *pCtx /* Write error here if one occurs */
|
||||
){
|
||||
DateTime x, y;
|
||||
time_t t;
|
||||
struct tm sLocal;
|
||||
int iYearDiff;
|
||||
|
||||
/* Initialize the contents of sLocal to avoid a compiler warning. */
|
||||
memset(&sLocal, 0, sizeof(sLocal));
|
||||
|
||||
x = *p;
|
||||
computeYMD_HMS(&x);
|
||||
if( x.Y<1971 || x.Y>=2038 ){
|
||||
computeJD(p);
|
||||
if( p->iJD<2108667600*(i64)100000 /* 1970-01-01 */
|
||||
|| p->iJD>2130141456*(i64)100000 /* 2038-01-18 */
|
||||
){
|
||||
/* EVIDENCE-OF: R-55269-29598 The localtime_r() C function normally only
|
||||
** works for years between 1970 and 2037. For dates outside this range,
|
||||
** SQLite attempts to map the year into an equivalent year within this
|
||||
** range, do the calculation, then map the year back.
|
||||
*/
|
||||
x.Y = 2000;
|
||||
x.M = 1;
|
||||
x.D = 1;
|
||||
x.h = 0;
|
||||
x.m = 0;
|
||||
x.s = 0.0;
|
||||
} else {
|
||||
int s = (int)(x.s + 0.5);
|
||||
x.s = s;
|
||||
DateTime x = *p;
|
||||
computeYMD_HMS(&x);
|
||||
iYearDiff = (2000 + x.Y%4) - x.Y;
|
||||
x.Y += iYearDiff;
|
||||
x.validJD = 0;
|
||||
computeJD(&x);
|
||||
t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
|
||||
}else{
|
||||
iYearDiff = 0;
|
||||
t = (time_t)(p->iJD/1000 - 21086676*(i64)10000);
|
||||
}
|
||||
x.tz = 0;
|
||||
x.validJD = 0;
|
||||
computeJD(&x);
|
||||
t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
|
||||
if( osLocaltime(&t, &sLocal) ){
|
||||
sqlite3_result_error(pCtx, "local time unavailable", -1);
|
||||
*pRc = SQLITE_ERROR;
|
||||
return 0;
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
y.Y = sLocal.tm_year + 1900;
|
||||
y.M = sLocal.tm_mon + 1;
|
||||
y.D = sLocal.tm_mday;
|
||||
y.h = sLocal.tm_hour;
|
||||
y.m = sLocal.tm_min;
|
||||
y.s = sLocal.tm_sec;
|
||||
y.validYMD = 1;
|
||||
y.validHMS = 1;
|
||||
y.validJD = 0;
|
||||
y.rawS = 0;
|
||||
y.validTZ = 0;
|
||||
y.isError = 0;
|
||||
computeJD(&y);
|
||||
*pRc = SQLITE_OK;
|
||||
return y.iJD - x.iJD;
|
||||
p->Y = sLocal.tm_year + 1900 - iYearDiff;
|
||||
p->M = sLocal.tm_mon + 1;
|
||||
p->D = sLocal.tm_mday;
|
||||
p->h = sLocal.tm_hour;
|
||||
p->m = sLocal.tm_min;
|
||||
p->s = sLocal.tm_sec + (p->iJD%1000)*0.001;
|
||||
p->validYMD = 1;
|
||||
p->validHMS = 1;
|
||||
p->validJD = 0;
|
||||
p->rawS = 0;
|
||||
p->validTZ = 0;
|
||||
p->isError = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_LOCALTIME */
|
||||
|
||||
|
@ -619,18 +624,17 @@ static sqlite3_int64 localtimeOffset(
|
|||
** of several units of time.
|
||||
*/
|
||||
static const struct {
|
||||
u8 eType; /* Transformation type code */
|
||||
u8 nName; /* Length of th name */
|
||||
char *zName; /* Name of the transformation */
|
||||
double rLimit; /* Maximum NNN value for this transform */
|
||||
double rXform; /* Constant used for this transform */
|
||||
u8 nName; /* Length of the name */
|
||||
char zName[7]; /* Name of the transformation */
|
||||
float rLimit; /* Maximum NNN value for this transform */
|
||||
float rXform; /* Constant used for this transform */
|
||||
} aXformType[] = {
|
||||
{ 0, 6, "second", 464269060800.0, 1000.0 },
|
||||
{ 0, 6, "minute", 7737817680.0, 60000.0 },
|
||||
{ 0, 4, "hour", 128963628.0, 3600000.0 },
|
||||
{ 0, 3, "day", 5373485.0, 86400000.0 },
|
||||
{ 1, 5, "month", 176546.0, 2592000000.0 },
|
||||
{ 2, 4, "year", 14713.0, 31536000000.0 },
|
||||
{ 6, "second", 4.6427e+14, 1.0 },
|
||||
{ 6, "minute", 7.7379e+12, 60.0 },
|
||||
{ 4, "hour", 1.2897e+11, 3600.0 },
|
||||
{ 3, "day", 5373485.0, 86400.0 },
|
||||
{ 5, "month", 176546.0, 2592000.0 },
|
||||
{ 4, "year", 14713.0, 31536000.0 },
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -661,11 +665,55 @@ static int parseModifier(
|
|||
sqlite3_context *pCtx, /* Function context */
|
||||
const char *z, /* The text of the modifier */
|
||||
int n, /* Length of zMod in bytes */
|
||||
DateTime *p /* The date/time value to be modified */
|
||||
DateTime *p, /* The date/time value to be modified */
|
||||
int idx /* Parameter index of the modifier */
|
||||
){
|
||||
int rc = 1;
|
||||
double r;
|
||||
switch(sqlite3UpperToLower[(u8)z[0]] ){
|
||||
case 'a': {
|
||||
/*
|
||||
** auto
|
||||
**
|
||||
** If rawS is available, then interpret as a julian day number, or
|
||||
** a unix timestamp, depending on its magnitude.
|
||||
*/
|
||||
if( sqlite3_stricmp(z, "auto")==0 ){
|
||||
if( idx>1 ) return 1; /* IMP: R-33611-57934 */
|
||||
if( !p->rawS || p->validJD ){
|
||||
rc = 0;
|
||||
p->rawS = 0;
|
||||
}else if( p->s>=-21086676*(i64)10000 /* -4713-11-24 12:00:00 */
|
||||
&& p->s<=(25340230*(i64)10000)+799 /* 9999-12-31 23:59:59 */
|
||||
){
|
||||
r = p->s*1000.0 + 210866760000000.0;
|
||||
clearYMD_HMS_TZ(p);
|
||||
p->iJD = (sqlite3_int64)(r + 0.5);
|
||||
p->validJD = 1;
|
||||
p->rawS = 0;
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'j': {
|
||||
/*
|
||||
** julianday
|
||||
**
|
||||
** Always interpret the prior number as a julian-day value. If this
|
||||
** is not the first modifier, or if the prior argument is not a numeric
|
||||
** value in the allowed range of julian day numbers understood by
|
||||
** SQLite (0..5373484.5) then the result will be NULL.
|
||||
*/
|
||||
if( sqlite3_stricmp(z, "julianday")==0 ){
|
||||
if( idx>1 ) return 1; /* IMP: R-31176-64601 */
|
||||
if( p->validJD && p->rawS ){
|
||||
rc = 0;
|
||||
p->rawS = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_LOCALTIME
|
||||
case 'l': {
|
||||
/* localtime
|
||||
|
@ -674,9 +722,7 @@ static int parseModifier(
|
|||
** show local time.
|
||||
*/
|
||||
if( sqlite3_stricmp(z, "localtime")==0 && sqlite3NotPureFunc(pCtx) ){
|
||||
computeJD(p);
|
||||
p->iJD += localtimeOffset(p, pCtx, &rc);
|
||||
clearYMD_HMS_TZ(p);
|
||||
rc = toLocaltime(p, pCtx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -689,6 +735,7 @@ static int parseModifier(
|
|||
** seconds since 1970. Convert to a real julian day number.
|
||||
*/
|
||||
if( sqlite3_stricmp(z, "unixepoch")==0 && p->rawS ){
|
||||
if( idx>1 ) return 1; /* IMP: R-49255-55373 */
|
||||
r = p->s*1000.0 + 210866760000000.0;
|
||||
if( r>=0.0 && r<464269060800000.0 ){
|
||||
clearYMD_HMS_TZ(p);
|
||||
|
@ -701,18 +748,31 @@ static int parseModifier(
|
|||
#ifndef SQLITE_OMIT_LOCALTIME
|
||||
else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){
|
||||
if( p->tzSet==0 ){
|
||||
sqlite3_int64 c1;
|
||||
i64 iOrigJD; /* Original localtime */
|
||||
i64 iGuess; /* Guess at the corresponding utc time */
|
||||
int cnt = 0; /* Safety to prevent infinite loop */
|
||||
int iErr; /* Guess is off by this much */
|
||||
|
||||
computeJD(p);
|
||||
c1 = localtimeOffset(p, pCtx, &rc);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->iJD -= c1;
|
||||
clearYMD_HMS_TZ(p);
|
||||
p->iJD += c1 - localtimeOffset(p, pCtx, &rc);
|
||||
}
|
||||
iGuess = iOrigJD = p->iJD;
|
||||
iErr = 0;
|
||||
do{
|
||||
DateTime new;
|
||||
memset(&new, 0, sizeof(new));
|
||||
iGuess -= iErr;
|
||||
new.iJD = iGuess;
|
||||
new.validJD = 1;
|
||||
rc = toLocaltime(&new, pCtx);
|
||||
if( rc ) return rc;
|
||||
computeJD(&new);
|
||||
iErr = new.iJD - iOrigJD;
|
||||
}while( iErr && cnt++<3 );
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->iJD = iGuess;
|
||||
p->validJD = 1;
|
||||
p->tzSet = 1;
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
@ -727,7 +787,7 @@ static int parseModifier(
|
|||
*/
|
||||
if( sqlite3_strnicmp(z, "weekday ", 8)==0
|
||||
&& sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)>0
|
||||
&& (n=(int)r)==r && n>=0 && r<7 ){
|
||||
&& r>=0.0 && r<7.0 && (n=(int)r)==r ){
|
||||
sqlite3_int64 Z;
|
||||
computeYMD_HMS(p);
|
||||
p->validTZ = 0;
|
||||
|
@ -828,9 +888,10 @@ static int parseModifier(
|
|||
&& sqlite3_strnicmp(aXformType[i].zName, z, n)==0
|
||||
&& r>-aXformType[i].rLimit && r<aXformType[i].rLimit
|
||||
){
|
||||
switch( aXformType[i].eType ){
|
||||
case 1: { /* Special processing to add months */
|
||||
switch( i ){
|
||||
case 4: { /* Special processing to add months */
|
||||
int x;
|
||||
assert( strcmp(aXformType[i].zName,"month")==0 );
|
||||
computeYMD_HMS(p);
|
||||
p->M += (int)r;
|
||||
x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
|
||||
|
@ -840,8 +901,9 @@ static int parseModifier(
|
|||
r -= (int)r;
|
||||
break;
|
||||
}
|
||||
case 2: { /* Special processing to add years */
|
||||
case 5: { /* Special processing to add years */
|
||||
int y = (int)r;
|
||||
assert( strcmp(aXformType[i].zName,"year")==0 );
|
||||
computeYMD_HMS(p);
|
||||
p->Y += y;
|
||||
p->validJD = 0;
|
||||
|
@ -850,7 +912,7 @@ static int parseModifier(
|
|||
}
|
||||
}
|
||||
computeJD(p);
|
||||
p->iJD += (sqlite3_int64)(r*aXformType[i].rXform + rRounder);
|
||||
p->iJD += (sqlite3_int64)(r*1000.0*aXformType[i].rXform + rRounder);
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -900,7 +962,7 @@ static int isDate(
|
|||
for(i=1; i<argc; i++){
|
||||
z = sqlite3_value_text(argv[i]);
|
||||
n = sqlite3_value_bytes(argv[i]);
|
||||
if( z==0 || parseModifier(context, (char*)z, n, p) ) return 1;
|
||||
if( z==0 || parseModifier(context, (char*)z, n, p, i) ) return 1;
|
||||
}
|
||||
computeJD(p);
|
||||
if( p->isError || !validJulianDay(p->iJD) ) return 1;
|
||||
|
@ -930,6 +992,24 @@ static void juliandayFunc(
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** unixepoch( TIMESTRING, MOD, MOD, ...)
|
||||
**
|
||||
** Return the number of seconds (including fractional seconds) since
|
||||
** the unix epoch of 1970-01-01 00:00:00 GMT.
|
||||
*/
|
||||
static void unixepochFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
DateTime x;
|
||||
if( isDate(context, argc, argv, &x)==0 ){
|
||||
computeJD(&x);
|
||||
sqlite3_result_int64(context, x.iJD/1000 - 21086676*(i64)10000);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** datetime( TIMESTRING, MOD, MOD, ...)
|
||||
**
|
||||
|
@ -942,11 +1022,38 @@ static void datetimeFunc(
|
|||
){
|
||||
DateTime x;
|
||||
if( isDate(context, argc, argv, &x)==0 ){
|
||||
char zBuf[100];
|
||||
int Y, s;
|
||||
char zBuf[24];
|
||||
computeYMD_HMS(&x);
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d",
|
||||
x.Y, x.M, x.D, x.h, x.m, (int)(x.s));
|
||||
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
|
||||
Y = x.Y;
|
||||
if( Y<0 ) Y = -Y;
|
||||
zBuf[1] = '0' + (Y/1000)%10;
|
||||
zBuf[2] = '0' + (Y/100)%10;
|
||||
zBuf[3] = '0' + (Y/10)%10;
|
||||
zBuf[4] = '0' + (Y)%10;
|
||||
zBuf[5] = '-';
|
||||
zBuf[6] = '0' + (x.M/10)%10;
|
||||
zBuf[7] = '0' + (x.M)%10;
|
||||
zBuf[8] = '-';
|
||||
zBuf[9] = '0' + (x.D/10)%10;
|
||||
zBuf[10] = '0' + (x.D)%10;
|
||||
zBuf[11] = ' ';
|
||||
zBuf[12] = '0' + (x.h/10)%10;
|
||||
zBuf[13] = '0' + (x.h)%10;
|
||||
zBuf[14] = ':';
|
||||
zBuf[15] = '0' + (x.m/10)%10;
|
||||
zBuf[16] = '0' + (x.m)%10;
|
||||
zBuf[17] = ':';
|
||||
s = (int)x.s;
|
||||
zBuf[18] = '0' + (s/10)%10;
|
||||
zBuf[19] = '0' + (s)%10;
|
||||
zBuf[20] = 0;
|
||||
if( x.Y<0 ){
|
||||
zBuf[0] = '-';
|
||||
sqlite3_result_text(context, zBuf, 20, SQLITE_TRANSIENT);
|
||||
}else{
|
||||
sqlite3_result_text(context, &zBuf[1], 19, SQLITE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -962,10 +1069,20 @@ static void timeFunc(
|
|||
){
|
||||
DateTime x;
|
||||
if( isDate(context, argc, argv, &x)==0 ){
|
||||
char zBuf[100];
|
||||
int s;
|
||||
char zBuf[16];
|
||||
computeHMS(&x);
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
|
||||
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
|
||||
zBuf[0] = '0' + (x.h/10)%10;
|
||||
zBuf[1] = '0' + (x.h)%10;
|
||||
zBuf[2] = ':';
|
||||
zBuf[3] = '0' + (x.m/10)%10;
|
||||
zBuf[4] = '0' + (x.m)%10;
|
||||
zBuf[5] = ':';
|
||||
s = (int)x.s;
|
||||
zBuf[6] = '0' + (s/10)%10;
|
||||
zBuf[7] = '0' + (s)%10;
|
||||
zBuf[8] = 0;
|
||||
sqlite3_result_text(context, zBuf, 8, SQLITE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -981,10 +1098,28 @@ static void dateFunc(
|
|||
){
|
||||
DateTime x;
|
||||
if( isDate(context, argc, argv, &x)==0 ){
|
||||
char zBuf[100];
|
||||
int Y;
|
||||
char zBuf[16];
|
||||
computeYMD(&x);
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
|
||||
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
|
||||
Y = x.Y;
|
||||
if( Y<0 ) Y = -Y;
|
||||
zBuf[1] = '0' + (Y/1000)%10;
|
||||
zBuf[2] = '0' + (Y/100)%10;
|
||||
zBuf[3] = '0' + (Y/10)%10;
|
||||
zBuf[4] = '0' + (Y)%10;
|
||||
zBuf[5] = '-';
|
||||
zBuf[6] = '0' + (x.M/10)%10;
|
||||
zBuf[7] = '0' + (x.M)%10;
|
||||
zBuf[8] = '-';
|
||||
zBuf[9] = '0' + (x.D/10)%10;
|
||||
zBuf[10] = '0' + (x.D)%10;
|
||||
zBuf[11] = 0;
|
||||
if( x.Y<0 ){
|
||||
zBuf[0] = '-';
|
||||
sqlite3_result_text(context, zBuf, 11, SQLITE_TRANSIENT);
|
||||
}else{
|
||||
sqlite3_result_text(context, &zBuf[1], 10, SQLITE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1013,131 +1148,100 @@ static void strftimeFunc(
|
|||
sqlite3_value **argv
|
||||
){
|
||||
DateTime x;
|
||||
u64 n;
|
||||
size_t i,j;
|
||||
char *z;
|
||||
sqlite3 *db;
|
||||
const char *zFmt;
|
||||
char zBuf[100];
|
||||
sqlite3_str sRes;
|
||||
|
||||
|
||||
if( argc==0 ) return;
|
||||
zFmt = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
|
||||
db = sqlite3_context_db_handle(context);
|
||||
for(i=0, n=1; zFmt[i]; i++, n++){
|
||||
if( zFmt[i]=='%' ){
|
||||
switch( zFmt[i+1] ){
|
||||
case 'd':
|
||||
case 'H':
|
||||
case 'm':
|
||||
case 'M':
|
||||
case 'S':
|
||||
case 'W':
|
||||
n++;
|
||||
/* fall thru */
|
||||
case 'w':
|
||||
case '%':
|
||||
break;
|
||||
case 'f':
|
||||
n += 8;
|
||||
break;
|
||||
case 'j':
|
||||
n += 3;
|
||||
break;
|
||||
case 'Y':
|
||||
n += 8;
|
||||
break;
|
||||
case 's':
|
||||
case 'J':
|
||||
n += 50;
|
||||
break;
|
||||
default:
|
||||
return; /* ERROR. return a NULL */
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
testcase( n==sizeof(zBuf)-1 );
|
||||
testcase( n==sizeof(zBuf) );
|
||||
testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
|
||||
testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH] );
|
||||
if( n<sizeof(zBuf) ){
|
||||
z = zBuf;
|
||||
}else if( n>(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
sqlite3_result_error_toobig(context);
|
||||
return;
|
||||
}else{
|
||||
z = sqlite3DbMallocRawNN(db, (int)n);
|
||||
if( z==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
}
|
||||
sqlite3StrAccumInit(&sRes, 0, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
|
||||
|
||||
computeJD(&x);
|
||||
computeYMD_HMS(&x);
|
||||
for(i=j=0; zFmt[i]; i++){
|
||||
if( zFmt[i]!='%' ){
|
||||
z[j++] = zFmt[i];
|
||||
}else{
|
||||
i++;
|
||||
switch( zFmt[i] ){
|
||||
case 'd': sqlite3_snprintf(3, &z[j],"%02d",x.D); j+=2; break;
|
||||
case 'f': {
|
||||
double s = x.s;
|
||||
if( s>59.999 ) s = 59.999;
|
||||
sqlite3_snprintf(7, &z[j],"%06.3f", s);
|
||||
j += sqlite3Strlen30(&z[j]);
|
||||
break;
|
||||
if( zFmt[i]!='%' ) continue;
|
||||
if( j<i ) sqlite3_str_append(&sRes, zFmt+j, (int)(i-j));
|
||||
i++;
|
||||
j = i + 1;
|
||||
switch( zFmt[i] ){
|
||||
case 'd': {
|
||||
sqlite3_str_appendf(&sRes, "%02d", x.D);
|
||||
break;
|
||||
}
|
||||
case 'f': {
|
||||
double s = x.s;
|
||||
if( s>59.999 ) s = 59.999;
|
||||
sqlite3_str_appendf(&sRes, "%06.3f", s);
|
||||
break;
|
||||
}
|
||||
case 'H': {
|
||||
sqlite3_str_appendf(&sRes, "%02d", x.h);
|
||||
break;
|
||||
}
|
||||
case 'W': /* Fall thru */
|
||||
case 'j': {
|
||||
int nDay; /* Number of days since 1st day of year */
|
||||
DateTime y = x;
|
||||
y.validJD = 0;
|
||||
y.M = 1;
|
||||
y.D = 1;
|
||||
computeJD(&y);
|
||||
nDay = (int)((x.iJD-y.iJD+43200000)/86400000);
|
||||
if( zFmt[i]=='W' ){
|
||||
int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
|
||||
wd = (int)(((x.iJD+43200000)/86400000)%7);
|
||||
sqlite3_str_appendf(&sRes,"%02d",(nDay+7-wd)/7);
|
||||
}else{
|
||||
sqlite3_str_appendf(&sRes,"%03d",nDay+1);
|
||||
}
|
||||
case 'H': sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break;
|
||||
case 'W': /* Fall thru */
|
||||
case 'j': {
|
||||
int nDay; /* Number of days since 1st day of year */
|
||||
DateTime y = x;
|
||||
y.validJD = 0;
|
||||
y.M = 1;
|
||||
y.D = 1;
|
||||
computeJD(&y);
|
||||
nDay = (int)((x.iJD-y.iJD+43200000)/86400000);
|
||||
if( zFmt[i]=='W' ){
|
||||
int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
|
||||
wd = (int)(((x.iJD+43200000)/86400000)%7);
|
||||
sqlite3_snprintf(3, &z[j],"%02d",(nDay+7-wd)/7);
|
||||
j += 2;
|
||||
}else{
|
||||
sqlite3_snprintf(4, &z[j],"%03d",nDay+1);
|
||||
j += 3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'J': {
|
||||
sqlite3_snprintf(20, &z[j],"%.16g",x.iJD/86400000.0);
|
||||
j+=sqlite3Strlen30(&z[j]);
|
||||
break;
|
||||
}
|
||||
case 'm': sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break;
|
||||
case 'M': sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break;
|
||||
case 's': {
|
||||
i64 iS = (i64)(x.iJD/1000 - 21086676*(i64)10000);
|
||||
sqlite3Int64ToText(iS, &z[j]);
|
||||
j += sqlite3Strlen30(&z[j]);
|
||||
break;
|
||||
}
|
||||
case 'S': sqlite3_snprintf(3,&z[j],"%02d",(int)x.s); j+=2; break;
|
||||
case 'w': {
|
||||
z[j++] = (char)(((x.iJD+129600000)/86400000) % 7) + '0';
|
||||
break;
|
||||
}
|
||||
case 'Y': {
|
||||
sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=sqlite3Strlen30(&z[j]);
|
||||
break;
|
||||
}
|
||||
default: z[j++] = '%'; break;
|
||||
break;
|
||||
}
|
||||
case 'J': {
|
||||
sqlite3_str_appendf(&sRes,"%.16g",x.iJD/86400000.0);
|
||||
break;
|
||||
}
|
||||
case 'm': {
|
||||
sqlite3_str_appendf(&sRes,"%02d",x.M);
|
||||
break;
|
||||
}
|
||||
case 'M': {
|
||||
sqlite3_str_appendf(&sRes,"%02d",x.m);
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
i64 iS = (i64)(x.iJD/1000 - 21086676*(i64)10000);
|
||||
sqlite3_str_appendf(&sRes,"%lld",iS);
|
||||
break;
|
||||
}
|
||||
case 'S': {
|
||||
sqlite3_str_appendf(&sRes,"%02d",(int)x.s);
|
||||
break;
|
||||
}
|
||||
case 'w': {
|
||||
sqlite3_str_appendchar(&sRes, 1,
|
||||
(char)(((x.iJD+129600000)/86400000) % 7) + '0');
|
||||
break;
|
||||
}
|
||||
case 'Y': {
|
||||
sqlite3_str_appendf(&sRes,"%04d",x.Y);
|
||||
break;
|
||||
}
|
||||
case '%': {
|
||||
sqlite3_str_appendchar(&sRes, 1, '%');
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
sqlite3_str_reset(&sRes);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
z[j] = 0;
|
||||
sqlite3_result_text(context, z, -1,
|
||||
z==zBuf ? SQLITE_TRANSIENT : SQLITE_DYNAMIC);
|
||||
if( j<i ) sqlite3_str_append(&sRes, zFmt+j, (int)(i-j));
|
||||
sqlite3ResultStrAccum(context, &sRes);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1237,6 +1341,7 @@ void sqlite3RegisterDateTimeFunctions(void){
|
|||
static FuncDef aDateTimeFuncs[] = {
|
||||
#ifndef SQLITE_OMIT_DATETIME_FUNCS
|
||||
PURE_DATE(julianday, -1, 0, 0, juliandayFunc ),
|
||||
PURE_DATE(unixepoch, -1, 0, 0, unixepochFunc ),
|
||||
PURE_DATE(date, -1, 0, 0, dateFunc ),
|
||||
PURE_DATE(time, -1, 0, 0, timeFunc ),
|
||||
PURE_DATE(datetime, -1, 0, 0, datetimeFunc ),
|
||||
|
|
49
third_party/sqlite3/dbpage.c
vendored
49
third_party/sqlite3/dbpage.c
vendored
|
@ -13,7 +13,7 @@
|
|||
** This file contains an implementation of the "sqlite_dbpage" virtual table.
|
||||
**
|
||||
** The sqlite_dbpage virtual table is used to read or write whole raw
|
||||
** pages of the database file. The pager interface is used so that
|
||||
** pages of the database file. The pager interface is used so that
|
||||
** uncommitted changes and changes recorded in the WAL file are correctly
|
||||
** retrieved.
|
||||
**
|
||||
|
@ -30,12 +30,10 @@
|
|||
** value must be a BLOB which is the correct page size, otherwise the
|
||||
** update fails. Rows may not be deleted or inserted.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc" /* Requires access to internal data inc */
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) && \
|
||||
!defined(SQLITE_OMIT_VIRTUALTABLE)
|
||||
#include "third_party/sqlite3/sqliteInt.h" /* Requires access to internal data structures */
|
||||
#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \
|
||||
&& !defined(SQLITE_OMIT_VIRTUALTABLE)
|
||||
|
||||
typedef struct DbpageTable DbpageTable;
|
||||
typedef struct DbpageCursor DbpageCursor;
|
||||
|
@ -158,6 +156,7 @@ static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
|||
){
|
||||
pIdxInfo->orderByConsumed = 1;
|
||||
}
|
||||
sqlite3VtabUsesAllSchemas(pIdxInfo);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
@ -275,12 +274,18 @@ static int dbpageColumn(
|
|||
}
|
||||
case 1: { /* data */
|
||||
DbPage *pDbPage = 0;
|
||||
rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage,
|
||||
SQLITE_TRANSIENT);
|
||||
if( pCsr->pgno==((PENDING_BYTE/pCsr->szPage)+1) ){
|
||||
/* The pending byte page. Assume it is zeroed out. Attempting to
|
||||
** request this page from the page is an SQLITE_CORRUPT error. */
|
||||
sqlite3_result_zeroblob(ctx, pCsr->szPage);
|
||||
}else{
|
||||
rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage,
|
||||
SQLITE_TRANSIENT);
|
||||
}
|
||||
sqlite3PagerUnref(pDbPage);
|
||||
}
|
||||
sqlite3PagerUnref(pDbPage);
|
||||
break;
|
||||
}
|
||||
default: { /* schema */
|
||||
|
@ -289,7 +294,7 @@ static int dbpageColumn(
|
|||
break;
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dbpageRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
|
||||
|
@ -335,7 +340,7 @@ static int dbpageUpdate(
|
|||
goto update_fail;
|
||||
}
|
||||
pBt = pTab->db->aDb[iDb].pBt;
|
||||
if( pgno<1 || pBt==0 || pgno>(int)sqlite3BtreeLastPage(pBt) ){
|
||||
if( pgno<1 || pBt==0 || pgno>sqlite3BtreeLastPage(pBt) ){
|
||||
zErr = "bad page number";
|
||||
goto update_fail;
|
||||
}
|
||||
|
@ -349,11 +354,12 @@ static int dbpageUpdate(
|
|||
pPager = sqlite3BtreePager(pBt);
|
||||
rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3PagerWrite(pDbPage);
|
||||
if( rc==SQLITE_OK ){
|
||||
memcpy(sqlite3PagerGetData(pDbPage),
|
||||
sqlite3_value_blob(argv[3]),
|
||||
szPage);
|
||||
const void *pData = sqlite3_value_blob(argv[3]);
|
||||
assert( pData!=0 || pTab->db->mallocFailed );
|
||||
if( pData
|
||||
&& (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK
|
||||
){
|
||||
memcpy(sqlite3PagerGetData(pDbPage), pData, szPage);
|
||||
}
|
||||
}
|
||||
sqlite3PagerUnref(pDbPage);
|
||||
|
@ -373,11 +379,12 @@ static int dbpageBegin(sqlite3_vtab *pVtab){
|
|||
DbpageTable *pTab = (DbpageTable *)pVtab;
|
||||
sqlite3 *db = pTab->db;
|
||||
int i;
|
||||
for(i=0; i<db->nDb; i++){
|
||||
int rc = SQLITE_OK;
|
||||
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
|
||||
Btree *pBt = db->aDb[i].pBt;
|
||||
if( pBt ) sqlite3BtreeBeginTrans(pBt, 1, 0);
|
||||
if( pBt ) rc = sqlite3BtreeBeginTrans(pBt, 1, 0);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
|
77
third_party/sqlite3/dbstat.c
vendored
77
third_party/sqlite3/dbstat.c
vendored
|
@ -20,12 +20,19 @@
|
|||
** Additional information is available on the "dbstat.html" page of the
|
||||
** official SQLite documentation.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc" /* Requires access to internal data inc */
|
||||
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h" /* Requires access to internal data structures */
|
||||
#if (defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)) \
|
||||
&& !defined(SQLITE_OMIT_VIRTUALTABLE)
|
||||
|
||||
#if (defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)) && \
|
||||
!defined(SQLITE_OMIT_VIRTUALTABLE)
|
||||
/*
|
||||
** The pager and btree modules arrange objects in memory so that there are
|
||||
** always approximately 200 bytes of addressable memory following each page
|
||||
** buffer. This way small buffer overreads caused by corrupt database pages
|
||||
** do not cause undefined behaviour. This module pads each page buffer
|
||||
** by the following number of bytes for the same purpose.
|
||||
*/
|
||||
#define DBSTAT_PAGE_PADDING_BYTES 256
|
||||
|
||||
/*
|
||||
** Page paths:
|
||||
|
@ -94,9 +101,8 @@ struct StatCell {
|
|||
/* Size information for a single btree page */
|
||||
struct StatPage {
|
||||
u32 iPgno; /* Page number */
|
||||
DbPage *pPg; /* Page content */
|
||||
u8 *aPg; /* Page buffer from sqlite3_malloc() */
|
||||
int iCell; /* Current cell */
|
||||
|
||||
char *zPath; /* Path to this page */
|
||||
|
||||
/* Variables populated by statDecodePage(): */
|
||||
|
@ -308,18 +314,25 @@ static void statClearCells(StatPage *p){
|
|||
}
|
||||
|
||||
static void statClearPage(StatPage *p){
|
||||
u8 *aPg = p->aPg;
|
||||
statClearCells(p);
|
||||
sqlite3PagerUnref(p->pPg);
|
||||
sqlite3_free(p->zPath);
|
||||
memset(p, 0, sizeof(StatPage));
|
||||
p->aPg = aPg;
|
||||
}
|
||||
|
||||
static void statResetCsr(StatCursor *pCsr){
|
||||
int i;
|
||||
sqlite3_reset(pCsr->pStmt);
|
||||
/* In some circumstances, specifically if an OOM has occurred, the call
|
||||
** to sqlite3_reset() may cause the pager to be reset (emptied). It is
|
||||
** important that statClearPage() is called to free any page refs before
|
||||
** this happens. dbsqlfuzz 9ed3e4e3816219d3509d711636c38542bf3f40b1. */
|
||||
for(i=0; i<ArraySize(pCsr->aPage); i++){
|
||||
statClearPage(&pCsr->aPage[i]);
|
||||
sqlite3_free(pCsr->aPage[i].aPg);
|
||||
pCsr->aPage[i].aPg = 0;
|
||||
}
|
||||
sqlite3_reset(pCsr->pStmt);
|
||||
pCsr->iPage = 0;
|
||||
sqlite3_free(pCsr->zPath);
|
||||
pCsr->zPath = 0;
|
||||
|
@ -384,7 +397,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){
|
|||
int isLeaf;
|
||||
int szPage;
|
||||
|
||||
u8 *aData = sqlite3PagerGetData(p->pPg);
|
||||
u8 *aData = p->aPg;
|
||||
u8 *aHdr = &aData[p->iPgno==1 ? 100 : 0];
|
||||
|
||||
p->flags = aHdr[0];
|
||||
|
@ -455,7 +468,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){
|
|||
if( nPayload>(u32)nLocal ){
|
||||
int j;
|
||||
int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4);
|
||||
if( iOff+nLocal>nUsable || nPayload>0x7fffffff ){
|
||||
if( iOff+nLocal+4>nUsable || nPayload>0x7fffffff ){
|
||||
goto statPageIsCorrupt;
|
||||
}
|
||||
pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4);
|
||||
|
@ -514,6 +527,38 @@ static void statSizeAndOffset(StatCursor *pCsr){
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Load a copy of the page data for page iPg into the buffer belonging
|
||||
** to page object pPg. Allocate the buffer if necessary. Return SQLITE_OK
|
||||
** if successful, or an SQLite error code otherwise.
|
||||
*/
|
||||
static int statGetPage(
|
||||
Btree *pBt, /* Load page from this b-tree */
|
||||
u32 iPg, /* Page number to load */
|
||||
StatPage *pPg /* Load page into this object */
|
||||
){
|
||||
int pgsz = sqlite3BtreeGetPageSize(pBt);
|
||||
DbPage *pDbPage = 0;
|
||||
int rc;
|
||||
|
||||
if( pPg->aPg==0 ){
|
||||
pPg->aPg = (u8*)sqlite3_malloc(pgsz + DBSTAT_PAGE_PADDING_BYTES);
|
||||
if( pPg->aPg==0 ){
|
||||
return SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
memset(&pPg->aPg[pgsz], 0, DBSTAT_PAGE_PADDING_BYTES);
|
||||
}
|
||||
|
||||
rc = sqlite3PagerGet(sqlite3BtreePager(pBt), iPg, &pDbPage, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
const u8 *a = sqlite3PagerGetData(pDbPage);
|
||||
memcpy(pPg->aPg, a, pgsz);
|
||||
sqlite3PagerUnref(pDbPage);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Move a DBSTAT cursor to the next entry. Normally, the next
|
||||
** entry will be the next page, but in aggregated mode (pCsr->isAgg!=0),
|
||||
|
@ -532,7 +577,7 @@ static int statNext(sqlite3_vtab_cursor *pCursor){
|
|||
pCsr->zPath = 0;
|
||||
|
||||
statNextRestart:
|
||||
if( pCsr->aPage[0].pPg==0 ){
|
||||
if( pCsr->iPage<0 ){
|
||||
/* Start measuring space on the next btree */
|
||||
statResetCounts(pCsr);
|
||||
rc = sqlite3_step(pCsr->pStmt);
|
||||
|
@ -544,7 +589,7 @@ statNextRestart:
|
|||
pCsr->isEof = 1;
|
||||
return sqlite3_reset(pCsr->pStmt);
|
||||
}
|
||||
rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg, 0);
|
||||
rc = statGetPage(pBt, iRoot, &pCsr->aPage[0]);
|
||||
pCsr->aPage[0].iPgno = iRoot;
|
||||
pCsr->aPage[0].iCell = 0;
|
||||
if( !pCsr->isAgg ){
|
||||
|
@ -595,9 +640,8 @@ statNextRestart:
|
|||
|
||||
if( !p->iRightChildPg || p->iCell>p->nCell ){
|
||||
statClearPage(p);
|
||||
if( pCsr->iPage>0 ){
|
||||
pCsr->iPage--;
|
||||
}else if( pCsr->isAgg ){
|
||||
pCsr->iPage--;
|
||||
if( pCsr->isAgg && pCsr->iPage<0 ){
|
||||
/* label-statNext-done: When computing aggregate space usage over
|
||||
** an entire btree, this is the exit point from this function */
|
||||
return SQLITE_OK;
|
||||
|
@ -616,7 +660,7 @@ statNextRestart:
|
|||
}else{
|
||||
p[1].iPgno = p->aCell[p->iCell].iChildPg;
|
||||
}
|
||||
rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg, 0);
|
||||
rc = statGetPage(pBt, p[1].iPgno, &p[1]);
|
||||
pCsr->nPage++;
|
||||
p[1].iCell = 0;
|
||||
if( !pCsr->isAgg ){
|
||||
|
@ -746,6 +790,7 @@ static int statFilter(
|
|||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
pCsr->iPage = -1;
|
||||
rc = statNext(pCursor);
|
||||
}
|
||||
return rc;
|
||||
|
|
112
third_party/sqlite3/delete.c
vendored
112
third_party/sqlite3/delete.c
vendored
|
@ -12,9 +12,7 @@
|
|||
** This file contains C code routines that are called by the parser
|
||||
** in order to generate code for DELETE FROM statements.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/*
|
||||
** While a SrcList can in general represent multiple tables and subqueries
|
||||
|
@ -46,6 +44,16 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
|
|||
return pTab;
|
||||
}
|
||||
|
||||
/* Generate byte-code that will report the number of rows modified
|
||||
** by a DELETE, INSERT, or UPDATE statement.
|
||||
*/
|
||||
void sqlite3CodeChangeCount(Vdbe *v, int regCounter, const char *zColName){
|
||||
sqlite3VdbeAddOp0(v, OP_FkCheck);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, regCounter, 1);
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zColName, SQLITE_STATIC);
|
||||
}
|
||||
|
||||
/* Return true if table pTab is read-only.
|
||||
**
|
||||
** A table is read-only if any of the following are true:
|
||||
|
@ -53,18 +61,42 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
|
|||
** 1) It is a virtual table and no implementation of the xUpdate method
|
||||
** has been provided
|
||||
**
|
||||
** 2) It is a system table (i.e. sqlite_schema), this call is not
|
||||
** 2) A trigger is currently being coded and the table is a virtual table
|
||||
** that is SQLITE_VTAB_DIRECTONLY or if PRAGMA trusted_schema=OFF and
|
||||
** the table is not SQLITE_VTAB_INNOCUOUS.
|
||||
**
|
||||
** 3) It is a system table (i.e. sqlite_schema), this call is not
|
||||
** part of a nested parse and writable_schema pragma has not
|
||||
** been specified
|
||||
**
|
||||
** 3) The table is a shadow table, the database connection is in
|
||||
** 4) The table is a shadow table, the database connection is in
|
||||
** defensive mode, and the current sqlite3_prepare()
|
||||
** is for a top-level SQL statement.
|
||||
*/
|
||||
static int vtabIsReadOnly(Parse *pParse, Table *pTab){
|
||||
if( sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ){
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Within triggers:
|
||||
** * Do not allow DELETE, INSERT, or UPDATE of SQLITE_VTAB_DIRECTONLY
|
||||
** virtual tables
|
||||
** * Only allow DELETE, INSERT, or UPDATE of non-SQLITE_VTAB_INNOCUOUS
|
||||
** virtual tables if PRAGMA trusted_schema=ON.
|
||||
*/
|
||||
if( pParse->pToplevel!=0
|
||||
&& pTab->u.vtab.p->eVtabRisk >
|
||||
((pParse->db->flags & SQLITE_TrustedSchema)!=0)
|
||||
){
|
||||
sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
|
||||
pTab->zName);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int tabIsReadOnly(Parse *pParse, Table *pTab){
|
||||
sqlite3 *db;
|
||||
if( IsVirtual(pTab) ){
|
||||
return sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0;
|
||||
return vtabIsReadOnly(pParse, pTab);
|
||||
}
|
||||
if( (pTab->tabFlags & (TF_Readonly|TF_Shadow))==0 ) return 0;
|
||||
db = pParse->db;
|
||||
|
@ -76,9 +108,11 @@ static int tabIsReadOnly(Parse *pParse, Table *pTab){
|
|||
}
|
||||
|
||||
/*
|
||||
** Check to make sure the given table is writable. If it is not
|
||||
** writable, generate an error message and return 1. If it is
|
||||
** writable return 0;
|
||||
** Check to make sure the given table is writable.
|
||||
**
|
||||
** If pTab is not writable -> generate an error message and return 1.
|
||||
** If pTab is writable but other errors have occurred -> return 1.
|
||||
** If pTab is writable and no prior errors -> return 0;
|
||||
*/
|
||||
int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
|
||||
if( tabIsReadOnly(pParse, pTab) ){
|
||||
|
@ -86,7 +120,7 @@ int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
|
|||
return 1;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_VIEW
|
||||
if( !viewOk && pTab->pSelect ){
|
||||
if( !viewOk && IsView(pTab) ){
|
||||
sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
|
||||
return 1;
|
||||
}
|
||||
|
@ -120,8 +154,8 @@ void sqlite3MaterializeView(
|
|||
assert( pFrom->nSrc==1 );
|
||||
pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
|
||||
pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
|
||||
assert( pFrom->a[0].pOn==0 );
|
||||
assert( pFrom->a[0].pUsing==0 );
|
||||
assert( pFrom->a[0].fg.isUsing==0 );
|
||||
assert( pFrom->a[0].u3.pOn==0 );
|
||||
}
|
||||
pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, pOrderBy,
|
||||
SF_IncludeHidden, pLimit);
|
||||
|
@ -190,13 +224,13 @@ Expr *sqlite3LimitWhere(
|
|||
}else{
|
||||
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
if( pPk->nKeyCol==1 ){
|
||||
const char *zName = pTab->aCol[pPk->aiColumn[0]].zName;
|
||||
const char *zName = pTab->aCol[pPk->aiColumn[0]].zCnName;
|
||||
pLhs = sqlite3Expr(db, TK_ID, zName);
|
||||
pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, zName));
|
||||
}else{
|
||||
int i;
|
||||
for(i=0; i<pPk->nKeyCol; i++){
|
||||
Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zName);
|
||||
Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zCnName);
|
||||
pEList = sqlite3ExprListAppend(pParse, pEList, p);
|
||||
}
|
||||
pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
|
||||
|
@ -212,6 +246,7 @@ Expr *sqlite3LimitWhere(
|
|||
pSelectSrc = sqlite3SrcListDup(db, pSrc, 0);
|
||||
pSrc->a[0].pTab = pTab;
|
||||
if( pSrc->a[0].fg.isIndexedBy ){
|
||||
assert( pSrc->a[0].fg.isCte==0 );
|
||||
pSrc->a[0].u2.pIBIndex = 0;
|
||||
pSrc->a[0].fg.isIndexedBy = 0;
|
||||
sqlite3DbFree(db, pSrc->a[0].u1.zIndexedBy);
|
||||
|
@ -284,12 +319,13 @@ void sqlite3DeleteFrom(
|
|||
|
||||
memset(&sContext, 0, sizeof(sContext));
|
||||
db = pParse->db;
|
||||
if( pParse->nErr || db->mallocFailed ){
|
||||
assert( db->pParse==pParse );
|
||||
if( pParse->nErr ){
|
||||
goto delete_from_cleanup;
|
||||
}
|
||||
assert( db->mallocFailed==0 );
|
||||
assert( pTabList->nSrc==1 );
|
||||
|
||||
|
||||
/* Locate the table which we want to delete. This table has to be
|
||||
** put in an SrcList structure because some of the subroutines we
|
||||
** will be calling are designed to work with multiple tables and expect
|
||||
|
@ -303,7 +339,7 @@ void sqlite3DeleteFrom(
|
|||
*/
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
|
||||
isView = pTab->pSelect!=0;
|
||||
isView = IsView(pTab);
|
||||
#else
|
||||
# define pTrigger 0
|
||||
# define isView 0
|
||||
|
@ -314,6 +350,14 @@ void sqlite3DeleteFrom(
|
|||
# define isView 0
|
||||
#endif
|
||||
|
||||
#if TREETRACE_ENABLED
|
||||
if( sqlite3TreeTrace & 0x10000 ){
|
||||
sqlite3TreeViewLine(0, "In sqlite3Delete() at %s:%d", __FILE__, __LINE__);
|
||||
sqlite3TreeViewDelete(pParse->pWith, pTabList, pWhere,
|
||||
pOrderBy, pLimit, pTrigger);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
|
||||
if( !isView ){
|
||||
pWhere = sqlite3LimitWhere(
|
||||
|
@ -429,7 +473,11 @@ void sqlite3DeleteFrom(
|
|||
}
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
assert( pIdx->pSchema==pTab->pSchema );
|
||||
sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
|
||||
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
|
||||
sqlite3VdbeAddOp3(v, OP_Clear, pIdx->tnum, iDb, memCnt ? memCnt : -1);
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
|
||||
}
|
||||
}
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
|
||||
|
@ -464,7 +512,7 @@ void sqlite3DeleteFrom(
|
|||
** ONEPASS_SINGLE: One-pass approach - at most one row deleted.
|
||||
** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted.
|
||||
*/
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,0,wcf,iTabCur+1);
|
||||
if( pWInfo==0 ) goto delete_from_cleanup;
|
||||
eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
|
||||
assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI );
|
||||
|
@ -550,7 +598,7 @@ void sqlite3DeleteFrom(
|
|||
if( eOnePass!=ONEPASS_OFF ){
|
||||
assert( nKey==nPk ); /* OP_Found will use an unpacked key */
|
||||
if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){
|
||||
assert( pPk!=0 || pTab->pSelect!=0 );
|
||||
assert( pPk!=0 || IsView(pTab) );
|
||||
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
|
@ -617,9 +665,7 @@ void sqlite3DeleteFrom(
|
|||
** invoke the callback function.
|
||||
*/
|
||||
if( memCnt ){
|
||||
sqlite3VdbeAddOp2(v, OP_ChngCntRow, memCnt, 1);
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC);
|
||||
sqlite3CodeChangeCount(v, memCnt, "rows deleted");
|
||||
}
|
||||
|
||||
delete_from_cleanup:
|
||||
|
@ -630,7 +676,7 @@ delete_from_cleanup:
|
|||
sqlite3ExprListDelete(db, pOrderBy);
|
||||
sqlite3ExprDelete(db, pLimit);
|
||||
#endif
|
||||
sqlite3DbFree(db, aToOpen);
|
||||
if( aToOpen ) sqlite3DbNNFreeNN(db, aToOpen);
|
||||
return;
|
||||
}
|
||||
/* Make sure "isView" and other macros defined above are undefined. Otherwise
|
||||
|
@ -784,7 +830,7 @@ void sqlite3GenerateRowDelete(
|
|||
** the update-hook is not invoked for rows removed by REPLACE, but the
|
||||
** pre-update-hook is.
|
||||
*/
|
||||
if( pTab->pSelect==0 ){
|
||||
if( !IsView(pTab) ){
|
||||
u8 p5 = 0;
|
||||
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek);
|
||||
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
|
||||
|
@ -941,13 +987,15 @@ int sqlite3GenerateIndexKey(
|
|||
continue;
|
||||
}
|
||||
sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iDataCur, j, regBase+j);
|
||||
/* If the column affinity is REAL but the number is an integer, then it
|
||||
** might be stored in the table as an integer (using a compact
|
||||
** representation) then converted to REAL by an OP_RealAffinity opcode.
|
||||
** But we are getting ready to store this value back into an index, where
|
||||
** it should be converted by to INTEGER again. So omit the OP_RealAffinity
|
||||
** opcode if it is present */
|
||||
sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity);
|
||||
if( pIdx->aiColumn[j]>=0 ){
|
||||
/* If the column affinity is REAL but the number is an integer, then it
|
||||
** might be stored in the table as an integer (using a compact
|
||||
** representation) then converted to REAL by an OP_RealAffinity opcode.
|
||||
** But we are getting ready to store this value back into an index, where
|
||||
** it should be converted by to INTEGER again. So omit the
|
||||
** OP_RealAffinity opcode if it is present */
|
||||
sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity);
|
||||
}
|
||||
}
|
||||
if( regOut ){
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
|
||||
|
|
2
third_party/sqlite3/dog.py
vendored
2
third_party/sqlite3/dog.py
vendored
|
@ -43,7 +43,7 @@ hash
|
|||
icu
|
||||
ieee754
|
||||
insert
|
||||
json1
|
||||
json
|
||||
legacy
|
||||
loadext
|
||||
main
|
||||
|
|
1191
third_party/sqlite3/expr.c
vendored
1191
third_party/sqlite3/expr.c
vendored
File diff suppressed because it is too large
Load diff
13
third_party/sqlite3/fault.c
vendored
13
third_party/sqlite3/fault.c
vendored
|
@ -10,22 +10,21 @@
|
|||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** This file contains code to support the concept of "benign"
|
||||
** This file contains code to support the concept of "benign"
|
||||
** malloc failures (when the xMalloc() or xRealloc() method of the
|
||||
** sqlite3_mem_methods structure fails to allocate a block of memory
|
||||
** and returns 0).
|
||||
** and returns 0).
|
||||
**
|
||||
** Most malloc failures are non-benign. After they occur, SQLite
|
||||
** abandons the current operation and returns an error code (usually
|
||||
** SQLITE_NOMEM) to the user. However, sometimes a fault is not necessarily
|
||||
** fatal. For example, if a malloc fails while resizing a hash table, this
|
||||
** is completely recoverable simply by not carrying out the resize. The
|
||||
** hash table will continue to function normally. So a malloc failure
|
||||
** fatal. For example, if a malloc fails while resizing a hash table, this
|
||||
** is completely recoverable simply by not carrying out the resize. The
|
||||
** hash table will continue to function normally. So a malloc failure
|
||||
** during a hash table resize is a benign fault.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
#ifndef SQLITE_UNTESTABLE
|
||||
|
||||
|
|
30
third_party/sqlite3/fileio.c
vendored
30
third_party/sqlite3/fileio.c
vendored
|
@ -1,18 +1,3 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/stat.macros.h"
|
||||
#include "libc/calls/weirdtypes.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "third_party/sqlite3/sqlite3ext.h"
|
||||
// clang-format off
|
||||
|
||||
/*
|
||||
** 2014-06-13
|
||||
**
|
||||
|
@ -88,6 +73,21 @@
|
|||
** And the paths returned in the "name" column of the table are also
|
||||
** relative to directory $dir.
|
||||
*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/stat.macros.h"
|
||||
#include "libc/calls/weirdtypes.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/isystem/unistd.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "third_party/sqlite3/sqlite3ext.h"
|
||||
// clang-format off
|
||||
|
||||
SQLITE_EXTENSION_INIT1
|
||||
|
||||
|
|
105
third_party/sqlite3/fkey.c
vendored
105
third_party/sqlite3/fkey.c
vendored
|
@ -11,9 +11,7 @@
|
|||
** This file contains code used by the compiler to add foreign key
|
||||
** support to compiled SQL statements.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
#ifndef SQLITE_OMIT_FOREIGN_KEY
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
|
@ -217,7 +215,9 @@ int sqlite3FkLocateIndex(
|
|||
*/
|
||||
if( pParent->iPKey>=0 ){
|
||||
if( !zKey ) return 0;
|
||||
if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zName, zKey) ) return 0;
|
||||
if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zCnName, zKey) ){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}else if( paiCol ){
|
||||
assert( nCol>1 );
|
||||
|
@ -259,11 +259,11 @@ int sqlite3FkLocateIndex(
|
|||
/* If the index uses a collation sequence that is different from
|
||||
** the default collation sequence for the column, this index is
|
||||
** unusable. Bail out early in this case. */
|
||||
zDfltColl = pParent->aCol[iCol].zColl;
|
||||
zDfltColl = sqlite3ColumnColl(&pParent->aCol[iCol]);
|
||||
if( !zDfltColl ) zDfltColl = sqlite3StrBINARY;
|
||||
if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break;
|
||||
|
||||
zIdxCol = pParent->aCol[iCol].zName;
|
||||
zIdxCol = pParent->aCol[iCol].zCnName;
|
||||
for(j=0; j<nCol; j++){
|
||||
if( sqlite3StrICmp(pFKey->aCol[j].zCol, zIdxCol)==0 ){
|
||||
if( aiCol ) aiCol[i] = pFKey->aCol[j].iFrom;
|
||||
|
@ -390,7 +390,6 @@ static void fkLookupParent(
|
|||
}else{
|
||||
int nCol = pFKey->nCol;
|
||||
int regTemp = sqlite3GetTempRange(pParse, nCol);
|
||||
int regRec = sqlite3GetTempReg(pParse);
|
||||
|
||||
sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb);
|
||||
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
|
||||
|
@ -429,12 +428,11 @@ static void fkLookupParent(
|
|||
}
|
||||
sqlite3VdbeGoto(v, iOk);
|
||||
}
|
||||
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec,
|
||||
|
||||
sqlite3VdbeAddOp4(v, OP_Affinity, regTemp, nCol, 0,
|
||||
sqlite3IndexAffinityStr(pParse->db,pIdx), nCol);
|
||||
sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); VdbeCoverage(v);
|
||||
|
||||
sqlite3ReleaseTempReg(pParse, regRec);
|
||||
sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regTemp, nCol);
|
||||
VdbeCoverage(v);
|
||||
sqlite3ReleaseTempRange(pParse, regTemp, nCol);
|
||||
}
|
||||
}
|
||||
|
@ -487,7 +485,7 @@ static Expr *exprTableRegister(
|
|||
pCol = &pTab->aCol[iCol];
|
||||
pExpr->iTable = regBase + sqlite3TableColumnToStorage(pTab,iCol) + 1;
|
||||
pExpr->affExpr = pCol->affinity;
|
||||
zColl = pCol->zColl;
|
||||
zColl = sqlite3ColumnColl(pCol);
|
||||
if( zColl==0 ) zColl = db->pDfltColl->zName;
|
||||
pExpr = sqlite3ExprAddCollateString(pParse, pExpr, zColl);
|
||||
}else{
|
||||
|
@ -510,6 +508,7 @@ static Expr *exprTableColumn(
|
|||
){
|
||||
Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0);
|
||||
if( pExpr ){
|
||||
assert( ExprUseYTab(pExpr) );
|
||||
pExpr->y.pTab = pTab;
|
||||
pExpr->iTable = iCursor;
|
||||
pExpr->iColumn = iCol;
|
||||
|
@ -535,14 +534,10 @@ static Expr *exprTableColumn(
|
|||
** Operation | FK type | Action taken
|
||||
** --------------------------------------------------------------------------
|
||||
** DELETE immediate Increment the "immediate constraint counter".
|
||||
** Or, if the ON (UPDATE|DELETE) action is RESTRICT,
|
||||
** throw a "FOREIGN KEY constraint failed" exception.
|
||||
**
|
||||
** INSERT immediate Decrement the "immediate constraint counter".
|
||||
**
|
||||
** DELETE deferred Increment the "deferred constraint counter".
|
||||
** Or, if the ON (UPDATE|DELETE) action is RESTRICT,
|
||||
** throw a "FOREIGN KEY constraint failed" exception.
|
||||
**
|
||||
** INSERT deferred Decrement the "deferred constraint counter".
|
||||
**
|
||||
|
@ -596,7 +591,7 @@ static void fkScanChildren(
|
|||
pLeft = exprTableRegister(pParse, pTab, regData, iCol);
|
||||
iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
|
||||
assert( iCol>=0 );
|
||||
zCol = pFKey->pFrom->aCol[iCol].zName;
|
||||
zCol = pFKey->pFrom->aCol[iCol].zCnName;
|
||||
pRight = sqlite3Expr(db, TK_ID, zCol);
|
||||
pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
|
||||
pWhere = sqlite3ExprAnd(pParse, pWhere, pEq);
|
||||
|
@ -631,7 +626,7 @@ static void fkScanChildren(
|
|||
i16 iCol = pIdx->aiColumn[i];
|
||||
assert( iCol>=0 );
|
||||
pLeft = exprTableRegister(pParse, pTab, regData, iCol);
|
||||
pRight = sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zName);
|
||||
pRight = sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zCnName);
|
||||
pEq = sqlite3PExpr(pParse, TK_IS, pLeft, pRight);
|
||||
pAll = sqlite3ExprAnd(pParse, pAll, pEq);
|
||||
}
|
||||
|
@ -650,7 +645,7 @@ static void fkScanChildren(
|
|||
** clause. For each row found, increment either the deferred or immediate
|
||||
** foreign key constraint counter. */
|
||||
if( pParse->nErr==0 ){
|
||||
pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
|
||||
if( pWInfo ){
|
||||
sqlite3WhereEnd(pWInfo);
|
||||
|
@ -701,6 +696,25 @@ static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Clear the apTrigger[] cache of CASCADE triggers for all foreign keys
|
||||
** in a particular database. This needs to happen when the schema
|
||||
** changes.
|
||||
*/
|
||||
void sqlite3FkClearTriggerCache(sqlite3 *db, int iDb){
|
||||
HashElem *k;
|
||||
Hash *pHash = &db->aDb[iDb].pSchema->tblHash;
|
||||
for(k=sqliteHashFirst(pHash); k; k=sqliteHashNext(k)){
|
||||
Table *pTab = sqliteHashData(k);
|
||||
FKey *pFKey;
|
||||
if( !IsOrdinaryTable(pTab) ) continue;
|
||||
for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
|
||||
fkTriggerDelete(db, pFKey->apTrigger[0]); pFKey->apTrigger[0] = 0;
|
||||
fkTriggerDelete(db, pFKey->apTrigger[1]); pFKey->apTrigger[1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is called to generate code that runs when table pTab is
|
||||
** being dropped from the database. The SrcList passed as the second argument
|
||||
|
@ -720,12 +734,12 @@ static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){
|
|||
*/
|
||||
void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
|
||||
sqlite3 *db = pParse->db;
|
||||
if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) ){
|
||||
if( (db->flags&SQLITE_ForeignKeys) && IsOrdinaryTable(pTab) ){
|
||||
int iSkip = 0;
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
|
||||
assert( v ); /* VDBE has already been allocated */
|
||||
assert( pTab->pSelect==0 ); /* Not a view */
|
||||
assert( IsOrdinaryTable(pTab) );
|
||||
if( sqlite3FkReferences(pTab)==0 ){
|
||||
/* Search for a deferred foreign key constraint for which this table
|
||||
** is the child table. If one cannot be found, return without
|
||||
|
@ -733,7 +747,7 @@ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
|
|||
** the entire DELETE if there are no outstanding deferred constraints
|
||||
** when this statement is run. */
|
||||
FKey *p;
|
||||
for(p=pTab->pFKey; p; p=p->pNextFrom){
|
||||
for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
|
||||
if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break;
|
||||
}
|
||||
if( !p ) return;
|
||||
|
@ -822,7 +836,7 @@ static int fkParentIsModified(
|
|||
if( aChange[iKey]>=0 || (iKey==pTab->iPKey && bChngRowid) ){
|
||||
Column *pCol = &pTab->aCol[iKey];
|
||||
if( zKey ){
|
||||
if( 0==sqlite3StrICmp(pCol->zName, zKey) ) return 1;
|
||||
if( 0==sqlite3StrICmp(pCol->zCnName, zKey) ) return 1;
|
||||
}else if( pCol->colFlags & COLFLAG_PRIMKEY ){
|
||||
return 1;
|
||||
}
|
||||
|
@ -889,13 +903,14 @@ void sqlite3FkCheck(
|
|||
|
||||
/* If foreign-keys are disabled, this function is a no-op. */
|
||||
if( (db->flags&SQLITE_ForeignKeys)==0 ) return;
|
||||
if( !IsOrdinaryTable(pTab) ) return;
|
||||
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
zDb = db->aDb[iDb].zDbSName;
|
||||
|
||||
/* Loop through all the foreign key constraints for which pTab is the
|
||||
** child table (the table that the foreign key definition is part of). */
|
||||
for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
|
||||
for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
|
||||
Table *pTo; /* Parent table of foreign key pFKey */
|
||||
Index *pIdx = 0; /* Index on key columns in pTo */
|
||||
int *aiFree = 0;
|
||||
|
@ -962,7 +977,7 @@ void sqlite3FkCheck(
|
|||
** values read from the parent table are NULL. */
|
||||
if( db->xAuth ){
|
||||
int rcauth;
|
||||
char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName;
|
||||
char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zCnName;
|
||||
rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb);
|
||||
bIgnore = (rcauth==SQLITE_IGNORE);
|
||||
}
|
||||
|
@ -1077,10 +1092,10 @@ u32 sqlite3FkOldmask(
|
|||
Table *pTab /* Table being modified */
|
||||
){
|
||||
u32 mask = 0;
|
||||
if( pParse->db->flags&SQLITE_ForeignKeys ){
|
||||
if( pParse->db->flags&SQLITE_ForeignKeys && IsOrdinaryTable(pTab) ){
|
||||
FKey *p;
|
||||
int i;
|
||||
for(p=pTab->pFKey; p; p=p->pNextFrom){
|
||||
for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
|
||||
for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom);
|
||||
}
|
||||
for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
|
||||
|
@ -1130,19 +1145,19 @@ int sqlite3FkRequired(
|
|||
){
|
||||
int eRet = 1; /* Value to return if bHaveFK is true */
|
||||
int bHaveFK = 0; /* If FK processing is required */
|
||||
if( pParse->db->flags&SQLITE_ForeignKeys ){
|
||||
if( pParse->db->flags&SQLITE_ForeignKeys && IsOrdinaryTable(pTab) ){
|
||||
if( !aChange ){
|
||||
/* A DELETE operation. Foreign key processing is required if the
|
||||
** table in question is either the child or parent table for any
|
||||
** foreign key constraint. */
|
||||
bHaveFK = (sqlite3FkReferences(pTab) || pTab->pFKey);
|
||||
bHaveFK = (sqlite3FkReferences(pTab) || pTab->u.tab.pFKey);
|
||||
}else{
|
||||
/* This is an UPDATE. Foreign key processing is only required if the
|
||||
** operation modifies one or more child or parent key columns. */
|
||||
FKey *p;
|
||||
|
||||
/* Check if any child key columns are being modified. */
|
||||
for(p=pTab->pFKey; p; p=p->pNextFrom){
|
||||
for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
|
||||
if( fkChildIsModified(pTab, p, aChange, chngRowid) ){
|
||||
if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) eRet = 2;
|
||||
bHaveFK = 1;
|
||||
|
@ -1170,9 +1185,9 @@ int sqlite3FkRequired(
|
|||
**
|
||||
** It returns a pointer to a Trigger structure containing a trigger
|
||||
** equivalent to the ON UPDATE or ON DELETE action specified by pFKey.
|
||||
** If the action is "NO ACTION" or "RESTRICT", then a NULL pointer is
|
||||
** returned (these actions require no special handling by the triggers
|
||||
** sub-system, code for them is created by fkScanChildren()).
|
||||
** If the action is "NO ACTION" then a NULL pointer is returned (these actions
|
||||
** require no special handling by the triggers sub-system, code for them is
|
||||
** created by fkScanChildren()).
|
||||
**
|
||||
** For example, if pFKey is the foreign key and pTab is table "p" in
|
||||
** the following schema:
|
||||
|
@ -1235,8 +1250,8 @@ static Trigger *fkActionTrigger(
|
|||
assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) );
|
||||
assert( pIdx==0 || pIdx->aiColumn[i]>=0 );
|
||||
sqlite3TokenInit(&tToCol,
|
||||
pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName);
|
||||
sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zName);
|
||||
pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zCnName);
|
||||
sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zCnName);
|
||||
|
||||
/* Create the expression "OLD.zToCol = zFromCol". It is important
|
||||
** that the "OLD.zToCol" term is on the LHS of the = operator, so
|
||||
|
@ -1281,7 +1296,7 @@ static Trigger *fkActionTrigger(
|
|||
testcase( pCol->colFlags & COLFLAG_STORED );
|
||||
pDflt = 0;
|
||||
}else{
|
||||
pDflt = pCol->pDflt;
|
||||
pDflt = sqlite3ColumnExpr(pFKey->pFrom, pCol);
|
||||
}
|
||||
if( pDflt ){
|
||||
pNew = sqlite3ExprDup(db, pDflt, 0);
|
||||
|
@ -1301,18 +1316,23 @@ static Trigger *fkActionTrigger(
|
|||
nFrom = sqlite3Strlen30(zFrom);
|
||||
|
||||
if( action==OE_Restrict ){
|
||||
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
Token tFrom;
|
||||
Token tDb;
|
||||
Expr *pRaise;
|
||||
|
||||
tFrom.z = zFrom;
|
||||
tFrom.n = nFrom;
|
||||
tDb.z = db->aDb[iDb].zDbSName;
|
||||
tDb.n = sqlite3Strlen30(tDb.z);
|
||||
|
||||
pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed");
|
||||
if( pRaise ){
|
||||
pRaise->affExpr = OE_Abort;
|
||||
}
|
||||
pSelect = sqlite3SelectNew(pParse,
|
||||
sqlite3ExprListAppend(pParse, 0, pRaise),
|
||||
sqlite3SrcListAppend(pParse, 0, &tFrom, 0),
|
||||
sqlite3SrcListAppend(pParse, 0, &tDb, &tFrom),
|
||||
pWhere,
|
||||
0, 0, 0, 0, 0
|
||||
);
|
||||
|
@ -1418,12 +1438,13 @@ void sqlite3FkDelete(sqlite3 *db, Table *pTab){
|
|||
FKey *pFKey; /* Iterator variable */
|
||||
FKey *pNext; /* Copy of pFKey->pNextFrom */
|
||||
|
||||
assert( db==0 || IsVirtual(pTab)
|
||||
|| sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );
|
||||
for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){
|
||||
assert( IsOrdinaryTable(pTab) );
|
||||
assert( db!=0 );
|
||||
for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pNext){
|
||||
assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );
|
||||
|
||||
/* Remove the FK from the fkeyHash hash table. */
|
||||
if( !db || db->pnBytesFreed==0 ){
|
||||
if( db->pnBytesFreed==0 ){
|
||||
if( pFKey->pPrevTo ){
|
||||
pFKey->pPrevTo->pNextTo = pFKey->pNextTo;
|
||||
}else{
|
||||
|
|
130
third_party/sqlite3/fts3.c
vendored
130
third_party/sqlite3/fts3.c
vendored
|
@ -61,7 +61,7 @@
|
|||
** A doclist (document list) holds a docid-sorted list of hits for a
|
||||
** given term. Doclists hold docids and associated token positions.
|
||||
** A docid is the unique integer identifier for a single document.
|
||||
** A position is the index of a word within the document. The first
|
||||
** A position is the index of a word within the document. The first
|
||||
** word of the document has a position of 0.
|
||||
**
|
||||
** FTS3 used to optionally store character offsets using a compile-time
|
||||
|
@ -86,7 +86,7 @@
|
|||
**
|
||||
** Here, array { X } means zero or more occurrences of X, adjacent in
|
||||
** memory. A "position" is an index of a token in the token stream
|
||||
** generated by the tokenizer. Note that POS_END and POS_COLUMN occur
|
||||
** generated by the tokenizer. Note that POS_END and POS_COLUMN occur
|
||||
** in the same logical place as the position element, and act as sentinals
|
||||
** ending a position list array. POS_END is 0. POS_COLUMN is 1.
|
||||
** The positions numbers are not stored literally but rather as two more
|
||||
|
@ -110,7 +110,7 @@
|
|||
** a document record consists of a docid followed by a position-list and
|
||||
** a doclist consists of one or more document records.
|
||||
**
|
||||
** A bare doclist omits the position information, becoming an
|
||||
** A bare doclist omits the position information, becoming an
|
||||
** array of varint-encoded docids.
|
||||
**
|
||||
**** Segment leaf nodes ****
|
||||
|
@ -287,9 +287,8 @@
|
|||
** query logic likewise merges doclists so that newer data knocks out
|
||||
** older data.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
#include "third_party/sqlite3/fts3Int.inc"
|
||||
#include "third_party/sqlite3/fts3Int.h"
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
|
||||
|
||||
#if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE)
|
||||
|
@ -300,31 +299,33 @@
|
|||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "third_party/sqlite3/fts3.inc"
|
||||
#ifndef SQLITE_CORE
|
||||
#include "third_party/sqlite3/sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
|
||||
#include "third_party/sqlite3/fts3.h"
|
||||
#ifndef SQLITE_CORE
|
||||
# include "third_party/sqlite3/sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#endif
|
||||
|
||||
typedef struct Fts3HashWrapper Fts3HashWrapper;
|
||||
struct Fts3HashWrapper {
|
||||
Fts3Hash hash; /* Hash table */
|
||||
int nRef; /* Number of pointers to this object */
|
||||
};
|
||||
|
||||
static int fts3EvalNext(Fts3Cursor *pCsr);
|
||||
static int fts3EvalStart(Fts3Cursor *pCsr);
|
||||
static int fts3TermSegReaderCursor(
|
||||
Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);
|
||||
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
# if defined(SQLITE_DEBUG)
|
||||
int sqlite3Fts3Always(int b) { assert( b ); return b; }
|
||||
int sqlite3Fts3Never(int b) { assert( !b ); return b; }
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This variable is set to false when running tests for which the on disk
|
||||
** structures should not be corrupt. Otherwise, true. If it is false, extra
|
||||
** assert() conditions in the fts3 code are activated - conditions that are
|
||||
** only true if it is guaranteed that the fts3 database is not corrupt.
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
int sqlite3_fts3_may_be_corrupt = 1;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Write a 64-bit variable-length integer to memory starting at p[0].
|
||||
|
@ -1175,7 +1176,7 @@ static int fts3InitVtab(
|
|||
sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */
|
||||
char **pzErr /* Write any error message here */
|
||||
){
|
||||
Fts3Hash *pHash = (Fts3Hash *)pAux;
|
||||
Fts3Hash *pHash = &((Fts3HashWrapper*)pAux)->hash;
|
||||
Fts3Table *p = 0; /* Pointer to allocated vtab */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
int i; /* Iterator variable */
|
||||
|
@ -1895,7 +1896,7 @@ static int fts3ScanInteriorNode(
|
|||
char *zBuffer = 0; /* Buffer to load terms into */
|
||||
i64 nAlloc = 0; /* Size of allocated buffer */
|
||||
int isFirstTerm = 1; /* True when processing first term on page */
|
||||
sqlite3_int64 iChild; /* Block id of child node to descend to */
|
||||
u64 iChild; /* Block id of child node to descend to */
|
||||
int nBuffer = 0; /* Total term size */
|
||||
|
||||
/* Skip over the 'height' varint that occurs at the start of every
|
||||
|
@ -1911,8 +1912,8 @@ static int fts3ScanInteriorNode(
|
|||
** table, then there are always 20 bytes of zeroed padding following the
|
||||
** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
|
||||
*/
|
||||
zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
|
||||
zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
|
||||
zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
|
||||
zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
|
||||
if( zCsr>zEnd ){
|
||||
return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
|
@ -1965,20 +1966,20 @@ static int fts3ScanInteriorNode(
|
|||
*/
|
||||
cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
|
||||
if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
|
||||
*piFirst = iChild;
|
||||
*piFirst = (i64)iChild;
|
||||
piFirst = 0;
|
||||
}
|
||||
|
||||
if( piLast && cmp<0 ){
|
||||
*piLast = iChild;
|
||||
*piLast = (i64)iChild;
|
||||
piLast = 0;
|
||||
}
|
||||
|
||||
iChild++;
|
||||
};
|
||||
|
||||
if( piFirst ) *piFirst = iChild;
|
||||
if( piLast ) *piLast = iChild;
|
||||
if( piFirst ) *piFirst = (i64)iChild;
|
||||
if( piLast ) *piLast = (i64)iChild;
|
||||
|
||||
finish_scan:
|
||||
sqlite3_free(zBuffer);
|
||||
|
@ -2885,7 +2886,7 @@ static int fts3TermSelectMerge(
|
|||
**
|
||||
** Similar padding is added in the fts3DoclistOrMerge() function.
|
||||
*/
|
||||
pTS->aaOutput[0] = sqlite3_malloc(nDoclist + FTS3_VARINT_MAX + 1);
|
||||
pTS->aaOutput[0] = sqlite3_malloc64((i64)nDoclist + FTS3_VARINT_MAX + 1);
|
||||
pTS->anOutput[0] = nDoclist;
|
||||
if( pTS->aaOutput[0] ){
|
||||
memcpy(pTS->aaOutput[0], aDoclist, nDoclist);
|
||||
|
@ -3584,14 +3585,20 @@ static int fts3SetHasStat(Fts3Table *p){
|
|||
*/
|
||||
static int fts3BeginMethod(sqlite3_vtab *pVtab){
|
||||
Fts3Table *p = (Fts3Table*)pVtab;
|
||||
int rc;
|
||||
UNUSED_PARAMETER(pVtab);
|
||||
assert( p->pSegments==0 );
|
||||
assert( p->nPendingData==0 );
|
||||
assert( p->inTransaction!=1 );
|
||||
TESTONLY( p->inTransaction = 1 );
|
||||
TESTONLY( p->mxSavepoint = -1; );
|
||||
p->nLeafAdd = 0;
|
||||
return fts3SetHasStat(p);
|
||||
rc = fts3SetHasStat(p);
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( rc==SQLITE_OK ){
|
||||
p->inTransaction = 1;
|
||||
p->mxSavepoint = -1;
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4004,9 +4011,12 @@ static const sqlite3_module fts3Module = {
|
|||
** allocated for the tokenizer hash table.
|
||||
*/
|
||||
static void hashDestroy(void *p){
|
||||
Fts3Hash *pHash = (Fts3Hash *)p;
|
||||
sqlite3Fts3HashClear(pHash);
|
||||
sqlite3_free(pHash);
|
||||
Fts3HashWrapper *pHash = (Fts3HashWrapper *)p;
|
||||
pHash->nRef--;
|
||||
if( pHash->nRef<=0 ){
|
||||
sqlite3Fts3HashClear(&pHash->hash);
|
||||
sqlite3_free(pHash);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4036,7 +4046,7 @@ void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule);
|
|||
*/
|
||||
int sqlite3Fts3Init(sqlite3 *db){
|
||||
int rc = SQLITE_OK;
|
||||
Fts3Hash *pHash = 0;
|
||||
Fts3HashWrapper *pHash = 0;
|
||||
const sqlite3_tokenizer_module *pSimple = 0;
|
||||
const sqlite3_tokenizer_module *pPorter = 0;
|
||||
#ifndef SQLITE_DISABLE_FTS3_UNICODE
|
||||
|
@ -4064,23 +4074,24 @@ int sqlite3Fts3Init(sqlite3 *db){
|
|||
sqlite3Fts3PorterTokenizerModule(&pPorter);
|
||||
|
||||
/* Allocate and initialize the hash-table used to store tokenizers. */
|
||||
pHash = sqlite3_malloc(sizeof(Fts3Hash));
|
||||
pHash = sqlite3_malloc(sizeof(Fts3HashWrapper));
|
||||
if( !pHash ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
|
||||
sqlite3Fts3HashInit(&pHash->hash, FTS3_HASH_STRING, 1);
|
||||
pHash->nRef = 0;
|
||||
}
|
||||
|
||||
/* Load the built-in tokenizers into the hash table */
|
||||
if( rc==SQLITE_OK ){
|
||||
if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple)
|
||||
|| sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter)
|
||||
if( sqlite3Fts3HashInsert(&pHash->hash, "simple", 7, (void *)pSimple)
|
||||
|| sqlite3Fts3HashInsert(&pHash->hash, "porter", 7, (void *)pPorter)
|
||||
|
||||
#ifndef SQLITE_DISABLE_FTS3_UNICODE
|
||||
|| sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode)
|
||||
|| sqlite3Fts3HashInsert(&pHash->hash, "unicode61", 10, (void *)pUnicode)
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_ICU
|
||||
|| (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu))
|
||||
|| (pIcu && sqlite3Fts3HashInsert(&pHash->hash, "icu", 4, (void *)pIcu))
|
||||
#endif
|
||||
){
|
||||
rc = SQLITE_NOMEM;
|
||||
|
@ -4089,7 +4100,7 @@ int sqlite3Fts3Init(sqlite3 *db){
|
|||
|
||||
#ifdef SQLITE_TEST
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts3ExprInitTestInterface(db, pHash);
|
||||
rc = sqlite3Fts3ExprInitTestInterface(db, &pHash->hash);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -4098,23 +4109,26 @@ int sqlite3Fts3Init(sqlite3 *db){
|
|||
** module with sqlite.
|
||||
*/
|
||||
if( SQLITE_OK==rc
|
||||
&& SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer"))
|
||||
&& SQLITE_OK==(rc=sqlite3Fts3InitHashTable(db,&pHash->hash,"fts3_tokenizer"))
|
||||
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
|
||||
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1))
|
||||
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1))
|
||||
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 2))
|
||||
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1))
|
||||
){
|
||||
pHash->nRef++;
|
||||
rc = sqlite3_create_module_v2(
|
||||
db, "fts3", &fts3Module, (void *)pHash, hashDestroy
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
pHash->nRef++;
|
||||
rc = sqlite3_create_module_v2(
|
||||
db, "fts4", &fts3Module, (void *)pHash, 0
|
||||
db, "fts4", &fts3Module, (void *)pHash, hashDestroy
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts3InitTok(db, (void *)pHash);
|
||||
pHash->nRef++;
|
||||
rc = sqlite3Fts3InitTok(db, (void *)pHash, hashDestroy);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -4123,7 +4137,7 @@ int sqlite3Fts3Init(sqlite3 *db){
|
|||
/* An error has occurred. Delete the hash table and return the error code. */
|
||||
assert( rc!=SQLITE_OK );
|
||||
if( pHash ){
|
||||
sqlite3Fts3HashClear(pHash);
|
||||
sqlite3Fts3HashClear(&pHash->hash);
|
||||
sqlite3_free(pHash);
|
||||
}
|
||||
return rc;
|
||||
|
@ -4292,8 +4306,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
|
|||
char *aPoslist = 0; /* Position list for deferred tokens */
|
||||
int nPoslist = 0; /* Number of bytes in aPoslist */
|
||||
int iPrev = -1; /* Token number of previous deferred token */
|
||||
|
||||
assert( pPhrase->doclist.bFreeList==0 );
|
||||
char *aFree = (pPhrase->doclist.bFreeList ? pPhrase->doclist.pList : 0);
|
||||
|
||||
for(iToken=0; iToken<pPhrase->nToken; iToken++){
|
||||
Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
|
||||
|
@ -4307,6 +4320,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
|
|||
|
||||
if( pList==0 ){
|
||||
sqlite3_free(aPoslist);
|
||||
sqlite3_free(aFree);
|
||||
pPhrase->doclist.pList = 0;
|
||||
pPhrase->doclist.nList = 0;
|
||||
return SQLITE_OK;
|
||||
|
@ -4327,6 +4341,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
|
|||
nPoslist = (int)(aOut - aPoslist);
|
||||
if( nPoslist==0 ){
|
||||
sqlite3_free(aPoslist);
|
||||
sqlite3_free(aFree);
|
||||
pPhrase->doclist.pList = 0;
|
||||
pPhrase->doclist.nList = 0;
|
||||
return SQLITE_OK;
|
||||
|
@ -4359,13 +4374,14 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
|
|||
nDistance = iPrev - nMaxUndeferred;
|
||||
}
|
||||
|
||||
aOut = (char *)sqlite3_malloc(nPoslist+8);
|
||||
aOut = (char *)sqlite3Fts3MallocZero(nPoslist+FTS3_BUFFER_PADDING);
|
||||
if( !aOut ){
|
||||
sqlite3_free(aPoslist);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
pPhrase->doclist.pList = aOut;
|
||||
assert( p1 && p2 );
|
||||
if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){
|
||||
pPhrase->doclist.bFreeList = 1;
|
||||
pPhrase->doclist.nList = (int)(aOut - pPhrase->doclist.pList);
|
||||
|
@ -4378,6 +4394,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
|
|||
}
|
||||
}
|
||||
|
||||
if( pPhrase->doclist.pList!=aFree ) sqlite3_free(aFree);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#endif /* SQLITE_DISABLE_FTS4_DEFERRED */
|
||||
|
@ -4470,7 +4487,7 @@ void sqlite3Fts3DoclistPrev(
|
|||
|
||||
assert( nDoclist>0 );
|
||||
assert( *pbEof==0 );
|
||||
assert( p || *piDocid==0 );
|
||||
assert_fts3_nc( p || *piDocid==0 );
|
||||
assert( !p || (p>aDoclist && p<&aDoclist[nDoclist]) );
|
||||
|
||||
if( p==0 ){
|
||||
|
@ -4726,7 +4743,7 @@ static int fts3EvalIncrPhraseNext(
|
|||
if( bEof==0 ){
|
||||
int nList = 0;
|
||||
int nByte = a[p->nToken-1].nList;
|
||||
char *aDoclist = sqlite3_malloc(nByte+FTS3_BUFFER_PADDING);
|
||||
char *aDoclist = sqlite3_malloc64((i64)nByte+FTS3_BUFFER_PADDING);
|
||||
if( !aDoclist ) return SQLITE_NOMEM;
|
||||
memcpy(aDoclist, a[p->nToken-1].pList, nByte+1);
|
||||
memset(&aDoclist[nByte], 0, FTS3_BUFFER_PADDING);
|
||||
|
@ -5120,16 +5137,15 @@ static int fts3EvalStart(Fts3Cursor *pCsr){
|
|||
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
|
||||
if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
|
||||
Fts3TokenAndCost *aTC;
|
||||
Fts3Expr **apOr;
|
||||
aTC = (Fts3TokenAndCost *)sqlite3_malloc64(
|
||||
sizeof(Fts3TokenAndCost) * nToken
|
||||
+ sizeof(Fts3Expr *) * nOr * 2
|
||||
);
|
||||
apOr = (Fts3Expr **)&aTC[nToken];
|
||||
|
||||
if( !aTC ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
Fts3Expr **apOr = (Fts3Expr **)&aTC[nToken];
|
||||
int ii;
|
||||
Fts3TokenAndCost *pTC = aTC;
|
||||
Fts3Expr **ppOr = apOr;
|
||||
|
@ -5335,8 +5351,8 @@ static void fts3EvalNextRow(
|
|||
Fts3Expr *pRight = pExpr->pRight;
|
||||
sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
|
||||
|
||||
assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
|
||||
assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
|
||||
assert_fts3_nc( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
|
||||
assert_fts3_nc( pRight->bStart || pLeft->iDocid==pRight->iDocid );
|
||||
|
||||
if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
|
||||
fts3EvalNextRow(pCsr, pLeft, pRc);
|
||||
|
@ -5553,11 +5569,10 @@ static int fts3EvalTestExpr(
|
|||
|
||||
default: {
|
||||
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
|
||||
if( pCsr->pDeferred
|
||||
&& (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
|
||||
){
|
||||
if( pCsr->pDeferred && (pExpr->bDeferred || (
|
||||
pExpr->iDocid==pCsr->iPrevId && pExpr->pPhrase->doclist.pList
|
||||
))){
|
||||
Fts3Phrase *pPhrase = pExpr->pPhrase;
|
||||
assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
|
||||
if( pExpr->bDeferred ){
|
||||
fts3EvalInvalidatePoslist(pPhrase);
|
||||
}
|
||||
|
@ -5974,6 +5989,9 @@ int sqlite3Fts3EvalPhrasePoslist(
|
|||
if( bEofSave==0 && pNear->iDocid==iDocid ) break;
|
||||
}
|
||||
assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
|
||||
if( rc==SQLITE_OK && pNear->bEof!=bEofSave ){
|
||||
rc = FTS_CORRUPT_VTAB;
|
||||
}
|
||||
}
|
||||
if( bTreeEof ){
|
||||
while( rc==SQLITE_OK && !pNear->bEof ){
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
*/
|
||||
#ifndef _FTSINT_H
|
||||
#define _FTSINT_H
|
||||
/* clang-format off */
|
||||
|
||||
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
|
||||
# define NDEBUG 1
|
||||
|
@ -38,13 +37,13 @@
|
|||
|
||||
/* If not building as part of the core, include sqlite3ext.h. */
|
||||
#ifndef SQLITE_CORE
|
||||
#include "third_party/sqlite3/sqlite3ext.h"
|
||||
# include "third_party/sqlite3/sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT3
|
||||
#endif
|
||||
|
||||
#include "third_party/sqlite3/fts3_hash.inc"
|
||||
#include "third_party/sqlite3/fts3_tokenizer.inc"
|
||||
#include "third_party/sqlite3/sqlite3.h"
|
||||
#include "third_party/sqlite3/fts3_tokenizer.h"
|
||||
#include "third_party/sqlite3/fts3_hash.h"
|
||||
|
||||
/*
|
||||
** This constant determines the maximum depth of an FTS expression tree
|
||||
|
@ -135,7 +134,7 @@ SQLITE_EXTENSION_INIT3
|
|||
** is used for assert() conditions that are true only if it can be
|
||||
** guranteed that the database is not corrupt.
|
||||
*/
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
#ifdef SQLITE_DEBUG
|
||||
extern int sqlite3_fts3_may_be_corrupt;
|
||||
# define assert_fts3_nc(x) assert(sqlite3_fts3_may_be_corrupt || (x))
|
||||
#else
|
||||
|
@ -152,17 +151,18 @@ extern int sqlite3_fts3_may_be_corrupt;
|
|||
** Macros indicating that conditional expressions are always true or
|
||||
** false.
|
||||
*/
|
||||
#ifdef SQLITE_COVERAGE_TEST
|
||||
# define ALWAYS(x) (1)
|
||||
# define NEVER(X) (0)
|
||||
#elif defined(SQLITE_DEBUG)
|
||||
# define ALWAYS(x) sqlite3Fts3Always((x)!=0)
|
||||
# define NEVER(x) sqlite3Fts3Never((x)!=0)
|
||||
int sqlite3Fts3Always(int b);
|
||||
int sqlite3Fts3Never(int b);
|
||||
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
|
||||
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
|
||||
#endif
|
||||
#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
|
||||
# define ALWAYS(X) (1)
|
||||
# define NEVER(X) (0)
|
||||
#elif !defined(NDEBUG)
|
||||
# define ALWAYS(X) ((X)?1:(assert(0),0))
|
||||
# define NEVER(X) ((X)?(assert(0),1):0)
|
||||
#else
|
||||
# define ALWAYS(x) (x)
|
||||
# define NEVER(x) (x)
|
||||
# define ALWAYS(X) (X)
|
||||
# define NEVER(X) (X)
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -558,7 +558,7 @@ struct Fts3MultiSegReader {
|
|||
int nAdvance; /* How many seg-readers to advance */
|
||||
Fts3SegFilter *pFilter; /* Pointer to filter object */
|
||||
char *aBuffer; /* Buffer to merge doclists in */
|
||||
int nBuffer; /* Allocated size of aBuffer[] in bytes */
|
||||
i64 nBuffer; /* Allocated size of aBuffer[] in bytes */
|
||||
|
||||
int iColFilter; /* If >=0, filter for this column */
|
||||
int bRestart;
|
||||
|
@ -621,6 +621,7 @@ void sqlite3Fts3ExprFree(Fts3Expr *);
|
|||
int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash*);
|
||||
int sqlite3Fts3InitTerm(sqlite3 *db);
|
||||
#endif
|
||||
void *sqlite3Fts3MallocZero(i64 nByte);
|
||||
|
||||
int sqlite3Fts3OpenTokenizer(sqlite3_tokenizer *, int, const char *, int,
|
||||
sqlite3_tokenizer_cursor **
|
||||
|
@ -640,7 +641,7 @@ int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
|
|||
int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
|
||||
|
||||
/* fts3_tokenize_vtab.c */
|
||||
int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *);
|
||||
int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *, void(*xDestroy)(void*));
|
||||
|
||||
/* fts3_unicode2.c (functions generated by parsing unicode text files) */
|
||||
#ifndef SQLITE_DISABLE_FTS3_UNICODE
|
10
third_party/sqlite3/fts3_aux.c
vendored
10
third_party/sqlite3/fts3_aux.c
vendored
|
@ -11,8 +11,7 @@
|
|||
******************************************************************************
|
||||
**
|
||||
*/
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/fts3Int.inc"
|
||||
#include "third_party/sqlite3/fts3Int.h"
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
|
||||
|
||||
#include "libc/assert.h"
|
||||
|
@ -298,6 +297,7 @@ static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){
|
|||
if( fts3auxGrowStatArray(pCsr, 2) ) return SQLITE_NOMEM;
|
||||
memset(pCsr->aStat, 0, sizeof(struct Fts3auxColstats) * pCsr->nStat);
|
||||
iCol = 0;
|
||||
rc = SQLITE_OK;
|
||||
|
||||
while( i<nDoclist ){
|
||||
sqlite3_int64 v = 0;
|
||||
|
@ -341,6 +341,10 @@ static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){
|
|||
/* State 3. The integer just read is a column number. */
|
||||
default: assert( eState==3 );
|
||||
iCol = (int)v;
|
||||
if( iCol<1 ){
|
||||
rc = SQLITE_CORRUPT_VTAB;
|
||||
break;
|
||||
}
|
||||
if( fts3auxGrowStatArray(pCsr, iCol+2) ) return SQLITE_NOMEM;
|
||||
pCsr->aStat[iCol+1].nDoc++;
|
||||
eState = 2;
|
||||
|
@ -349,7 +353,6 @@ static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){
|
|||
}
|
||||
|
||||
pCsr->iCol = 0;
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
pCsr->isEof = 1;
|
||||
}
|
||||
|
@ -407,6 +410,7 @@ static int fts3auxFilterMethod(
|
|||
sqlite3Fts3SegReaderFinish(&pCsr->csr);
|
||||
sqlite3_free((void *)pCsr->filter.zTerm);
|
||||
sqlite3_free(pCsr->aStat);
|
||||
sqlite3_free(pCsr->zStop);
|
||||
memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr);
|
||||
|
||||
pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
|
||||
|
|
19
third_party/sqlite3/fts3_expr.c
vendored
19
third_party/sqlite3/fts3_expr.c
vendored
|
@ -11,13 +11,12 @@
|
|||
******************************************************************************
|
||||
**
|
||||
** This module contains code that implements a parser for fts3 query strings
|
||||
** (the right-hand argument to the MATCH operator). Because the supported
|
||||
** (the right-hand argument to the MATCH operator). Because the supported
|
||||
** syntax is relatively simple, the whole tokenizer/parser system is
|
||||
** hand-coded.
|
||||
** hand-coded.
|
||||
*/
|
||||
#include "third_party/sqlite3/fts3Int.inc"
|
||||
#include "third_party/sqlite3/fts3Int.h"
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
|
||||
/* clang-format off */
|
||||
|
||||
/*
|
||||
** By default, this module parses the legacy syntax that has been
|
||||
|
@ -123,7 +122,7 @@ static int fts3isspace(char c){
|
|||
** zero the memory before returning a pointer to it. If unsuccessful,
|
||||
** return NULL.
|
||||
*/
|
||||
static void *fts3MallocZero(sqlite3_int64 nByte){
|
||||
void *sqlite3Fts3MallocZero(sqlite3_int64 nByte){
|
||||
void *pRet = sqlite3_malloc64(nByte);
|
||||
if( pRet ) memset(pRet, 0, nByte);
|
||||
return pRet;
|
||||
|
@ -204,7 +203,7 @@ static int getNextToken(
|
|||
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
|
||||
if( rc==SQLITE_OK ){
|
||||
nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
|
||||
pRet = (Fts3Expr *)fts3MallocZero(nByte);
|
||||
pRet = (Fts3Expr *)sqlite3Fts3MallocZero(nByte);
|
||||
if( !pRet ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
|
@ -459,7 +458,7 @@ static int getNextNode(
|
|||
if( fts3isspace(cNext)
|
||||
|| cNext=='"' || cNext=='(' || cNext==')' || cNext==0
|
||||
){
|
||||
pRet = (Fts3Expr *)fts3MallocZero(sizeof(Fts3Expr));
|
||||
pRet = (Fts3Expr *)sqlite3Fts3MallocZero(sizeof(Fts3Expr));
|
||||
if( !pRet ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
@ -638,7 +637,7 @@ static int fts3ExprParse(
|
|||
&& p->eType==FTSQUERY_PHRASE && pParse->isNot
|
||||
){
|
||||
/* Create an implicit NOT operator. */
|
||||
Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
|
||||
Fts3Expr *pNot = sqlite3Fts3MallocZero(sizeof(Fts3Expr));
|
||||
if( !pNot ){
|
||||
sqlite3Fts3ExprFree(p);
|
||||
rc = SQLITE_NOMEM;
|
||||
|
@ -672,7 +671,7 @@ static int fts3ExprParse(
|
|||
/* Insert an implicit AND operator. */
|
||||
Fts3Expr *pAnd;
|
||||
assert( pRet && pPrev );
|
||||
pAnd = fts3MallocZero(sizeof(Fts3Expr));
|
||||
pAnd = sqlite3Fts3MallocZero(sizeof(Fts3Expr));
|
||||
if( !pAnd ){
|
||||
sqlite3Fts3ExprFree(p);
|
||||
rc = SQLITE_NOMEM;
|
||||
|
@ -1108,7 +1107,7 @@ void sqlite3Fts3ExprFree(Fts3Expr *pDel){
|
|||
|
||||
#ifdef SQLITE_TEST
|
||||
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
** Return a pointer to a buffer containing a text representation of the
|
||||
|
|
8
third_party/sqlite3/fts3_hash.c
vendored
8
third_party/sqlite3/fts3_hash.c
vendored
|
@ -13,7 +13,6 @@
|
|||
** We've modified it slightly to serve as a standalone hash table
|
||||
** implementation for the full-text indexing module.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
/*
|
||||
** The code in this file is only compiled if:
|
||||
|
@ -24,13 +23,14 @@
|
|||
** * The FTS3 module is being built into the core of
|
||||
** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
|
||||
*/
|
||||
#include "third_party/sqlite3/fts3Int.inc"
|
||||
#include "third_party/sqlite3/fts3Int.h"
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
|
||||
|
||||
#include "libc/assert.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "third_party/sqlite3/fts3_hash.inc"
|
||||
|
||||
#include "third_party/sqlite3/fts3_hash.h"
|
||||
|
||||
/*
|
||||
** Malloc and Free functions
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
#ifndef _FTS3_HASH_H_
|
||||
#define _FTS3_HASH_H_
|
||||
/* clang-format off */
|
||||
|
||||
/* Forward declarations of structures. */
|
||||
typedef struct Fts3Hash Fts3Hash;
|
5
third_party/sqlite3/fts3_icu.c
vendored
5
third_party/sqlite3/fts3_icu.c
vendored
|
@ -11,15 +11,14 @@
|
|||
*************************************************************************
|
||||
** This file implements a tokenizer for fts3 based on the ICU library.
|
||||
*/
|
||||
#include "third_party/sqlite3/fts3Int.inc"
|
||||
#include "third_party/sqlite3/fts3Int.h"
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
|
||||
#ifdef SQLITE_ENABLE_ICU
|
||||
/* clang-format off */
|
||||
|
||||
#include "libc/assert.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/unicode.h"
|
||||
#include "third_party/sqlite3/fts3_tokenizer.inc"
|
||||
#include "third_party/sqlite3/fts3_tokenizer.h"
|
||||
|
||||
typedef struct IcuTokenizer IcuTokenizer;
|
||||
typedef struct IcuCursor IcuCursor;
|
||||
|
|
8
third_party/sqlite3/fts3_porter.c
vendored
8
third_party/sqlite3/fts3_porter.c
vendored
|
@ -12,7 +12,6 @@
|
|||
** Implementation of the full-text-search tokenizer that implements
|
||||
** a Porter stemmer.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
/*
|
||||
** The code in this file is only compiled if:
|
||||
|
@ -23,14 +22,15 @@
|
|||
** * The FTS3 module is being built into the core of
|
||||
** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
|
||||
*/
|
||||
#include "third_party/sqlite3/fts3Int.inc"
|
||||
#include "third_party/sqlite3/fts3Int.h"
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
|
||||
|
||||
#include "libc/assert.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "third_party/sqlite3/fts3_tokenizer.inc"
|
||||
|
||||
#include "third_party/sqlite3/fts3_tokenizer.h"
|
||||
|
||||
/*
|
||||
** Class derived from sqlite3_tokenizer
|
||||
|
@ -621,7 +621,7 @@ static int porterNext(
|
|||
if( n>c->nAllocated ){
|
||||
char *pNew;
|
||||
c->nAllocated = n+20;
|
||||
pNew = sqlite3_realloc(c->zToken, c->nAllocated);
|
||||
pNew = sqlite3_realloc64(c->zToken, c->nAllocated);
|
||||
if( !pNew ) return SQLITE_NOMEM;
|
||||
c->zToken = pNew;
|
||||
}
|
||||
|
|
52
third_party/sqlite3/fts3_snippet.c
vendored
52
third_party/sqlite3/fts3_snippet.c
vendored
|
@ -10,13 +10,16 @@
|
|||
**
|
||||
******************************************************************************
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
#include "third_party/sqlite3/fts3Int.inc"
|
||||
#include "third_party/sqlite3/fts3Int.h"
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
|
||||
|
||||
#include "libc/assert.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/assert.h"
|
||||
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
typedef sqlite3_int64 i64;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Characters that may appear in the second argument to matchinfo().
|
||||
|
@ -68,9 +71,9 @@ struct SnippetIter {
|
|||
struct SnippetPhrase {
|
||||
int nToken; /* Number of tokens in phrase */
|
||||
char *pList; /* Pointer to start of phrase position list */
|
||||
int iHead; /* Next value in position list */
|
||||
i64 iHead; /* Next value in position list */
|
||||
char *pHead; /* Position list data following iHead */
|
||||
int iTail; /* Next value in trailing position list */
|
||||
i64 iTail; /* Next value in trailing position list */
|
||||
char *pTail; /* Position list data following iTail */
|
||||
};
|
||||
|
||||
|
@ -135,9 +138,8 @@ static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
|
|||
+ sizeof(MatchinfoBuffer);
|
||||
sqlite3_int64 nStr = strlen(zMatchinfo);
|
||||
|
||||
pRet = sqlite3_malloc64(nByte + nStr+1);
|
||||
pRet = sqlite3Fts3MallocZero(nByte + nStr+1);
|
||||
if( pRet ){
|
||||
memset(pRet, 0, nByte);
|
||||
pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet;
|
||||
pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0]
|
||||
+ sizeof(u32)*((int)nElem+1);
|
||||
|
@ -235,7 +237,7 @@ void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p){
|
|||
** After it returns, *piPos contains the value of the next element of the
|
||||
** list and *pp is advanced to the following varint.
|
||||
*/
|
||||
static void fts3GetDeltaPosition(char **pp, int *piPos){
|
||||
static void fts3GetDeltaPosition(char **pp, i64 *piPos){
|
||||
int iVal;
|
||||
*pp += fts3GetVarint32(*pp, &iVal);
|
||||
*piPos += (iVal-2);
|
||||
|
@ -344,10 +346,10 @@ static int fts3ExprPhraseCount(Fts3Expr *pExpr){
|
|||
** arguments so that it points to the first element with a value greater
|
||||
** than or equal to parameter iNext.
|
||||
*/
|
||||
static void fts3SnippetAdvance(char **ppIter, int *piIter, int iNext){
|
||||
static void fts3SnippetAdvance(char **ppIter, i64 *piIter, int iNext){
|
||||
char *pIter = *ppIter;
|
||||
if( pIter ){
|
||||
int iIter = *piIter;
|
||||
i64 iIter = *piIter;
|
||||
|
||||
while( iIter<iNext ){
|
||||
if( 0==(*pIter & 0xFE) ){
|
||||
|
@ -430,7 +432,7 @@ static void fts3SnippetDetails(
|
|||
SnippetPhrase *pPhrase = &pIter->aPhrase[i];
|
||||
if( pPhrase->pTail ){
|
||||
char *pCsr = pPhrase->pTail;
|
||||
int iCsr = pPhrase->iTail;
|
||||
i64 iCsr = pPhrase->iTail;
|
||||
|
||||
while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){
|
||||
int j;
|
||||
|
@ -476,7 +478,7 @@ static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
|
|||
rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pCsr);
|
||||
assert( rc==SQLITE_OK || pCsr==0 );
|
||||
if( pCsr ){
|
||||
int iFirst = 0;
|
||||
i64 iFirst = 0;
|
||||
pPhrase->pList = pCsr;
|
||||
fts3GetDeltaPosition(&pCsr, &iFirst);
|
||||
if( iFirst<0 ){
|
||||
|
@ -541,11 +543,10 @@ static int fts3BestSnippet(
|
|||
** the required space using malloc().
|
||||
*/
|
||||
nByte = sizeof(SnippetPhrase) * nList;
|
||||
sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc64(nByte);
|
||||
sIter.aPhrase = (SnippetPhrase *)sqlite3Fts3MallocZero(nByte);
|
||||
if( !sIter.aPhrase ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
memset(sIter.aPhrase, 0, nByte);
|
||||
|
||||
/* Initialize the contents of the SnippetIter object. Then iterate through
|
||||
** the set of phrases in the expression to populate the aPhrase[] array.
|
||||
|
@ -1109,10 +1110,12 @@ static int fts3MatchinfoLcsCb(
|
|||
** position list for the next column.
|
||||
*/
|
||||
static int fts3LcsIteratorAdvance(LcsIterator *pIter){
|
||||
char *pRead = pIter->pRead;
|
||||
char *pRead;
|
||||
sqlite3_int64 iRead;
|
||||
int rc = 0;
|
||||
|
||||
if( NEVER(pIter==0) ) return 1;
|
||||
pRead = pIter->pRead;
|
||||
pRead += sqlite3Fts3GetVarint(pRead, &iRead);
|
||||
if( iRead==0 || iRead==1 ){
|
||||
pRead = 0;
|
||||
|
@ -1146,9 +1149,8 @@ static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
|
|||
/* Allocate and populate the array of LcsIterator objects. The array
|
||||
** contains one element for each matchable phrase in the query.
|
||||
**/
|
||||
aIter = sqlite3_malloc64(sizeof(LcsIterator) * pCsr->nPhrase);
|
||||
aIter = sqlite3Fts3MallocZero(sizeof(LcsIterator) * pCsr->nPhrase);
|
||||
if( !aIter ) return SQLITE_NOMEM;
|
||||
memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase);
|
||||
(void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);
|
||||
|
||||
for(i=0; i<pInfo->nPhrase; i++){
|
||||
|
@ -1540,8 +1542,8 @@ typedef struct TermOffsetCtx TermOffsetCtx;
|
|||
|
||||
struct TermOffset {
|
||||
char *pList; /* Position-list */
|
||||
int iPos; /* Position just read from pList */
|
||||
int iOff; /* Offset of this term from read positions */
|
||||
i64 iPos; /* Position just read from pList */
|
||||
i64 iOff; /* Offset of this term from read positions */
|
||||
};
|
||||
|
||||
struct TermOffsetCtx {
|
||||
|
@ -1560,7 +1562,7 @@ static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
|
|||
int nTerm; /* Number of tokens in phrase */
|
||||
int iTerm; /* For looping through nTerm phrase terms */
|
||||
char *pList; /* Pointer to position list for phrase */
|
||||
int iPos = 0; /* First position in position-list */
|
||||
i64 iPos = 0; /* First position in position-list */
|
||||
int rc;
|
||||
|
||||
UNUSED_PARAMETER(iPhrase);
|
||||
|
@ -1609,7 +1611,7 @@ void sqlite3Fts3Offsets(
|
|||
if( rc!=SQLITE_OK ) goto offsets_out;
|
||||
|
||||
/* Allocate the array of TermOffset iterators. */
|
||||
sCtx.aTerm = (TermOffset *)sqlite3_malloc64(sizeof(TermOffset)*nToken);
|
||||
sCtx.aTerm = (TermOffset *)sqlite3Fts3MallocZero(sizeof(TermOffset)*nToken);
|
||||
if( 0==sCtx.aTerm ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto offsets_out;
|
||||
|
@ -1630,13 +1632,13 @@ void sqlite3Fts3Offsets(
|
|||
const char *zDoc;
|
||||
int nDoc;
|
||||
|
||||
/* Initialize the contents of sCtx.aTerm[] for column iCol. There is
|
||||
** no way that this operation can fail, so the return code from
|
||||
** fts3ExprIterate() can be discarded.
|
||||
/* Initialize the contents of sCtx.aTerm[] for column iCol. This
|
||||
** operation may fail if the database contains corrupt records.
|
||||
*/
|
||||
sCtx.iCol = iCol;
|
||||
sCtx.iTerm = 0;
|
||||
(void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx);
|
||||
rc = fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx);
|
||||
if( rc!=SQLITE_OK ) goto offsets_out;
|
||||
|
||||
/* Retreive the text stored in column iCol. If an SQL NULL is stored
|
||||
** in column iCol, jump immediately to the next iteration of the loop.
|
||||
|
|
15
third_party/sqlite3/fts3_tokenize_vtab.c
vendored
15
third_party/sqlite3/fts3_tokenize_vtab.c
vendored
|
@ -25,8 +25,8 @@
|
|||
**
|
||||
** input = <string>
|
||||
**
|
||||
** The virtual table module tokenizes this <string>, using the FTS3
|
||||
** tokenizer specified by the arguments to the CREATE VIRTUAL TABLE
|
||||
** The virtual table module tokenizes this <string>, using the FTS3
|
||||
** tokenizer specified by the arguments to the CREATE VIRTUAL TABLE
|
||||
** statement and returns one row for each token in the result. With
|
||||
** fields set as follows:
|
||||
**
|
||||
|
@ -38,12 +38,11 @@
|
|||
** pos: Token offset of token within input.
|
||||
**
|
||||
*/
|
||||
#include "third_party/sqlite3/fts3Int.inc"
|
||||
#include "third_party/sqlite3/fts3Int.h"
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
|
||||
/* clang-format off */
|
||||
|
||||
#include "libc/assert.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/assert.h"
|
||||
|
||||
typedef struct Fts3tokTable Fts3tokTable;
|
||||
typedef struct Fts3tokCursor Fts3tokCursor;
|
||||
|
@ -421,7 +420,7 @@ static int fts3tokRowidMethod(
|
|||
** Register the fts3tok module with database connection db. Return SQLITE_OK
|
||||
** if successful or an error code if sqlite3_create_module() fails.
|
||||
*/
|
||||
int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){
|
||||
int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash, void(*xDestroy)(void*)){
|
||||
static const sqlite3_module fts3tok_module = {
|
||||
0, /* iVersion */
|
||||
fts3tokConnectMethod, /* xCreate */
|
||||
|
@ -450,7 +449,9 @@ int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){
|
|||
};
|
||||
int rc; /* Return code */
|
||||
|
||||
rc = sqlite3_create_module(db, "fts3tokenize", &fts3tok_module, (void*)pHash);
|
||||
rc = sqlite3_create_module_v2(
|
||||
db, "fts3tokenize", &fts3tok_module, (void*)pHash, xDestroy
|
||||
);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
13
third_party/sqlite3/fts3_tokenizer.c
vendored
13
third_party/sqlite3/fts3_tokenizer.c
vendored
|
@ -13,7 +13,6 @@
|
|||
** This is part of an SQLite module implementing full-text search.
|
||||
** This particular file implements the generic tokenizer interface.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
/*
|
||||
** The code in this file is only compiled if:
|
||||
|
@ -24,11 +23,11 @@
|
|||
** * The FTS3 module is being built into the core of
|
||||
** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
|
||||
*/
|
||||
#include "third_party/sqlite3/fts3Int.inc"
|
||||
#include "third_party/sqlite3/fts3Int.h"
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
|
||||
|
||||
#include "libc/assert.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/assert.h"
|
||||
|
||||
/*
|
||||
** Return true if the two-argument version of fts3_tokenizer()
|
||||
|
@ -226,7 +225,13 @@ int sqlite3Fts3InitTokenizer(
|
|||
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#if defined(INCLUDE_SQLITE_TCL_H)
|
||||
# include "sqlite_tcl.h"
|
||||
#else
|
||||
# include "tcl.h"
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
** Implementation of a special SQL scalar function for testing tokenizers
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*/
|
||||
#ifndef _FTS3_TOKENIZER_H_
|
||||
#define _FTS3_TOKENIZER_H_
|
||||
/* clang-format off */
|
||||
|
||||
/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time.
|
||||
** If tokenizers are to be allowed to call sqlite3_*() functions, then
|
8
third_party/sqlite3/fts3_tokenizer1.c
vendored
8
third_party/sqlite3/fts3_tokenizer1.c
vendored
|
@ -12,7 +12,6 @@
|
|||
**
|
||||
** Implementation of the "simple" full-text-search tokenizer.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
/*
|
||||
** The code in this file is only compiled if:
|
||||
|
@ -23,14 +22,15 @@
|
|||
** * The FTS3 module is being built into the core of
|
||||
** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
|
||||
*/
|
||||
#include "third_party/sqlite3/fts3Int.inc"
|
||||
#include "third_party/sqlite3/fts3Int.h"
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
|
||||
|
||||
#include "libc/assert.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "third_party/sqlite3/fts3_tokenizer.inc"
|
||||
|
||||
#include "third_party/sqlite3/fts3_tokenizer.h"
|
||||
|
||||
typedef struct simple_tokenizer {
|
||||
sqlite3_tokenizer base;
|
||||
|
@ -185,7 +185,7 @@ static int simpleNext(
|
|||
if( n>c->nTokenAllocated ){
|
||||
char *pNew;
|
||||
c->nTokenAllocated = n+20;
|
||||
pNew = sqlite3_realloc(c->pToken, c->nTokenAllocated);
|
||||
pNew = sqlite3_realloc64(c->pToken, c->nTokenAllocated);
|
||||
if( !pNew ) return SQLITE_NOMEM;
|
||||
c->pToken = pNew;
|
||||
}
|
||||
|
|
6
third_party/sqlite3/fts3_unicode.c
vendored
6
third_party/sqlite3/fts3_unicode.c
vendored
|
@ -12,18 +12,18 @@
|
|||
**
|
||||
** Implementation of the "unicode" full-text-search tokenizer.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
#ifndef SQLITE_DISABLE_FTS3_UNICODE
|
||||
|
||||
#include "third_party/sqlite3/fts3Int.inc"
|
||||
#include "third_party/sqlite3/fts3Int.h"
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
|
||||
|
||||
#include "libc/assert.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "third_party/sqlite3/fts3_tokenizer.inc"
|
||||
|
||||
#include "third_party/sqlite3/fts3_tokenizer.h"
|
||||
|
||||
/*
|
||||
** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied
|
||||
|
|
1
third_party/sqlite3/fts3_unicode2.c
vendored
1
third_party/sqlite3/fts3_unicode2.c
vendored
|
@ -10,7 +10,6 @@
|
|||
**
|
||||
******************************************************************************
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
/*
|
||||
** DO NOT EDIT THIS MACHINE GENERATED FILE.
|
||||
|
|
106
third_party/sqlite3/fts3_write.c
vendored
106
third_party/sqlite3/fts3_write.c
vendored
|
@ -13,17 +13,16 @@
|
|||
** This file is part of the SQLite FTS3 extension module. Specifically,
|
||||
** this file contains code to insert, update and delete rows from FTS3
|
||||
** tables. It also contains code to merge FTS3 b-tree segments. Some
|
||||
** of the sub-routines used to merge segments are also used by the query
|
||||
** of the sub-routines used to merge segments are also used by the query
|
||||
** code in fts3.c.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "third_party/sqlite3/fts3Int.inc"
|
||||
#include "third_party/sqlite3/fts3Int.h"
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
|
||||
|
||||
#include "libc/mem/alg.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/mem/alg.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -652,7 +651,7 @@ static int fts3PendingListAppendVarint(
|
|||
|
||||
/* Allocate or grow the PendingList as required. */
|
||||
if( !p ){
|
||||
p = sqlite3_malloc(sizeof(*p) + 100);
|
||||
p = sqlite3_malloc64(sizeof(*p) + 100);
|
||||
if( !p ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
@ -661,14 +660,14 @@ static int fts3PendingListAppendVarint(
|
|||
p->nData = 0;
|
||||
}
|
||||
else if( p->nData+FTS3_VARINT_MAX+1>p->nSpace ){
|
||||
int nNew = p->nSpace * 2;
|
||||
p = sqlite3_realloc(p, sizeof(*p) + nNew);
|
||||
i64 nNew = p->nSpace * 2;
|
||||
p = sqlite3_realloc64(p, sizeof(*p) + nNew);
|
||||
if( !p ){
|
||||
sqlite3_free(*pp);
|
||||
*pp = 0;
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
p->nSpace = nNew;
|
||||
p->nSpace = (int)nNew;
|
||||
p->aData = (char *)&p[1];
|
||||
}
|
||||
|
||||
|
@ -1225,7 +1224,7 @@ int sqlite3Fts3ReadBlock(
|
|||
int nByte = sqlite3_blob_bytes(p->pSegments);
|
||||
*pnBlob = nByte;
|
||||
if( paBlob ){
|
||||
char *aByte = sqlite3_malloc(nByte + FTS3_NODE_PADDING);
|
||||
char *aByte = sqlite3_malloc64((i64)nByte + FTS3_NODE_PADDING);
|
||||
if( !aByte ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
|
@ -1338,9 +1337,19 @@ static int fts3SegReaderNext(
|
|||
char *aCopy;
|
||||
PendingList *pList = (PendingList *)fts3HashData(pElem);
|
||||
int nCopy = pList->nData+1;
|
||||
pReader->zTerm = (char *)fts3HashKey(pElem);
|
||||
pReader->nTerm = fts3HashKeysize(pElem);
|
||||
aCopy = (char*)sqlite3_malloc(nCopy);
|
||||
|
||||
int nTerm = fts3HashKeysize(pElem);
|
||||
if( (nTerm+1)>pReader->nTermAlloc ){
|
||||
sqlite3_free(pReader->zTerm);
|
||||
pReader->zTerm = (char*)sqlite3_malloc64(((i64)nTerm+1)*2);
|
||||
if( !pReader->zTerm ) return SQLITE_NOMEM;
|
||||
pReader->nTermAlloc = (nTerm+1)*2;
|
||||
}
|
||||
memcpy(pReader->zTerm, fts3HashKey(pElem), nTerm);
|
||||
pReader->zTerm[nTerm] = '\0';
|
||||
pReader->nTerm = nTerm;
|
||||
|
||||
aCopy = (char*)sqlite3_malloc64(nCopy);
|
||||
if( !aCopy ) return SQLITE_NOMEM;
|
||||
memcpy(aCopy, pList->aData, nCopy);
|
||||
pReader->nNode = pReader->nDoclist = nCopy;
|
||||
|
@ -1592,9 +1601,7 @@ int sqlite3Fts3MsrOvfl(
|
|||
*/
|
||||
void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){
|
||||
if( pReader ){
|
||||
if( !fts3SegReaderIsPending(pReader) ){
|
||||
sqlite3_free(pReader->zTerm);
|
||||
}
|
||||
sqlite3_free(pReader->zTerm);
|
||||
if( !fts3SegReaderIsRootOnly(pReader) ){
|
||||
sqlite3_free(pReader->aNode);
|
||||
}
|
||||
|
@ -1629,7 +1636,7 @@ int sqlite3Fts3SegReaderNew(
|
|||
nExtra = nRoot + FTS3_NODE_PADDING;
|
||||
}
|
||||
|
||||
pReader = (Fts3SegReader *)sqlite3_malloc(sizeof(Fts3SegReader) + nExtra);
|
||||
pReader = (Fts3SegReader *)sqlite3_malloc64(sizeof(Fts3SegReader) + nExtra);
|
||||
if( !pReader ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
@ -1721,7 +1728,7 @@ int sqlite3Fts3SegReaderPending(
|
|||
if( nElem==nAlloc ){
|
||||
Fts3HashElem **aElem2;
|
||||
nAlloc += 16;
|
||||
aElem2 = (Fts3HashElem **)sqlite3_realloc(
|
||||
aElem2 = (Fts3HashElem **)sqlite3_realloc64(
|
||||
aElem, nAlloc*sizeof(Fts3HashElem *)
|
||||
);
|
||||
if( !aElem2 ){
|
||||
|
@ -1810,7 +1817,7 @@ static int fts3SegReaderCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
|
|||
if( rc==0 ){
|
||||
rc = pRhs->iIdx - pLhs->iIdx;
|
||||
}
|
||||
assert( rc!=0 );
|
||||
assert_fts3_nc( rc!=0 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -2006,8 +2013,8 @@ static int fts3PrefixCompress(
|
|||
int nNext /* Size of buffer zNext in bytes */
|
||||
){
|
||||
int n;
|
||||
UNUSED_PARAMETER(nNext);
|
||||
for(n=0; n<nPrev && zPrev[n]==zNext[n]; n++);
|
||||
for(n=0; n<nPrev && n<nNext && zPrev[n]==zNext[n]; n++);
|
||||
assert_fts3_nc( n<nNext );
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -2055,7 +2062,7 @@ static int fts3NodeAddTerm(
|
|||
** this is not expected to be a serious problem.
|
||||
*/
|
||||
assert( pTree->aData==(char *)&pTree[1] );
|
||||
pTree->aData = (char *)sqlite3_malloc(nReq);
|
||||
pTree->aData = (char *)sqlite3_malloc64(nReq);
|
||||
if( !pTree->aData ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
@ -2073,7 +2080,7 @@ static int fts3NodeAddTerm(
|
|||
|
||||
if( isCopyTerm ){
|
||||
if( pTree->nMalloc<nTerm ){
|
||||
char *zNew = sqlite3_realloc(pTree->zMalloc, nTerm*2);
|
||||
char *zNew = sqlite3_realloc64(pTree->zMalloc, (i64)nTerm*2);
|
||||
if( !zNew ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
@ -2099,7 +2106,7 @@ static int fts3NodeAddTerm(
|
|||
** now. Instead, the term is inserted into the parent of pTree. If pTree
|
||||
** has no parent, one is created here.
|
||||
*/
|
||||
pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + p->nNodeSize);
|
||||
pNew = (SegmentNode *)sqlite3_malloc64(sizeof(SegmentNode) + p->nNodeSize);
|
||||
if( !pNew ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
@ -2237,7 +2244,7 @@ static int fts3SegWriterAdd(
|
|||
){
|
||||
int nPrefix; /* Size of term prefix in bytes */
|
||||
int nSuffix; /* Size of term suffix in bytes */
|
||||
int nReq; /* Number of bytes required on leaf page */
|
||||
i64 nReq; /* Number of bytes required on leaf page */
|
||||
int nData;
|
||||
SegmentWriter *pWriter = *ppWriter;
|
||||
|
||||
|
@ -2246,13 +2253,13 @@ static int fts3SegWriterAdd(
|
|||
sqlite3_stmt *pStmt;
|
||||
|
||||
/* Allocate the SegmentWriter structure */
|
||||
pWriter = (SegmentWriter *)sqlite3_malloc(sizeof(SegmentWriter));
|
||||
pWriter = (SegmentWriter *)sqlite3_malloc64(sizeof(SegmentWriter));
|
||||
if( !pWriter ) return SQLITE_NOMEM;
|
||||
memset(pWriter, 0, sizeof(SegmentWriter));
|
||||
*ppWriter = pWriter;
|
||||
|
||||
/* Allocate a buffer in which to accumulate data */
|
||||
pWriter->aData = (char *)sqlite3_malloc(p->nNodeSize);
|
||||
pWriter->aData = (char *)sqlite3_malloc64(p->nNodeSize);
|
||||
if( !pWriter->aData ) return SQLITE_NOMEM;
|
||||
pWriter->nSize = p->nNodeSize;
|
||||
|
||||
|
@ -2327,7 +2334,7 @@ static int fts3SegWriterAdd(
|
|||
** the buffer to make it large enough.
|
||||
*/
|
||||
if( nReq>pWriter->nSize ){
|
||||
char *aNew = sqlite3_realloc(pWriter->aData, nReq);
|
||||
char *aNew = sqlite3_realloc64(pWriter->aData, nReq);
|
||||
if( !aNew ) return SQLITE_NOMEM;
|
||||
pWriter->aData = aNew;
|
||||
pWriter->nSize = nReq;
|
||||
|
@ -2352,7 +2359,7 @@ static int fts3SegWriterAdd(
|
|||
*/
|
||||
if( isCopyTerm ){
|
||||
if( nTerm>pWriter->nMalloc ){
|
||||
char *zNew = sqlite3_realloc(pWriter->zMalloc, nTerm*2);
|
||||
char *zNew = sqlite3_realloc64(pWriter->zMalloc, (i64)nTerm*2);
|
||||
if( !zNew ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
@ -2660,12 +2667,12 @@ static void fts3ColumnFilter(
|
|||
static int fts3MsrBufferData(
|
||||
Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */
|
||||
char *pList,
|
||||
int nList
|
||||
i64 nList
|
||||
){
|
||||
if( nList>pMsr->nBuffer ){
|
||||
char *pNew;
|
||||
pMsr->nBuffer = nList*2;
|
||||
pNew = (char *)sqlite3_realloc(pMsr->aBuffer, pMsr->nBuffer);
|
||||
pNew = (char *)sqlite3_realloc64(pMsr->aBuffer, pMsr->nBuffer);
|
||||
if( !pNew ) return SQLITE_NOMEM;
|
||||
pMsr->aBuffer = pNew;
|
||||
}
|
||||
|
@ -2721,7 +2728,7 @@ int sqlite3Fts3MsrIncrNext(
|
|||
fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp);
|
||||
|
||||
if( nList>0 && fts3SegReaderIsPending(apSegment[0]) ){
|
||||
rc = fts3MsrBufferData(pMsr, pList, nList+1);
|
||||
rc = fts3MsrBufferData(pMsr, pList, (i64)nList+1);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
|
||||
pList = pMsr->aBuffer;
|
||||
|
@ -2858,11 +2865,11 @@ int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){
|
|||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int fts3GrowSegReaderBuffer(Fts3MultiSegReader *pCsr, int nReq){
|
||||
static int fts3GrowSegReaderBuffer(Fts3MultiSegReader *pCsr, i64 nReq){
|
||||
if( nReq>pCsr->nBuffer ){
|
||||
char *aNew;
|
||||
pCsr->nBuffer = nReq*2;
|
||||
aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer);
|
||||
aNew = sqlite3_realloc64(pCsr->aBuffer, pCsr->nBuffer);
|
||||
if( !aNew ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
@ -2953,7 +2960,8 @@ int sqlite3Fts3SegReaderStep(
|
|||
){
|
||||
pCsr->nDoclist = apSegment[0]->nDoclist;
|
||||
if( fts3SegReaderIsPending(apSegment[0]) ){
|
||||
rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, pCsr->nDoclist);
|
||||
rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist,
|
||||
(i64)pCsr->nDoclist);
|
||||
pCsr->aDoclist = pCsr->aBuffer;
|
||||
}else{
|
||||
pCsr->aDoclist = apSegment[0]->aDoclist;
|
||||
|
@ -3006,7 +3014,8 @@ int sqlite3Fts3SegReaderStep(
|
|||
|
||||
nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
|
||||
|
||||
rc = fts3GrowSegReaderBuffer(pCsr, nByte+nDoclist);
|
||||
rc = fts3GrowSegReaderBuffer(pCsr,
|
||||
(i64)nByte+nDoclist+FTS3_NODE_PADDING);
|
||||
if( rc ) return rc;
|
||||
|
||||
if( isFirst ){
|
||||
|
@ -3032,7 +3041,7 @@ int sqlite3Fts3SegReaderStep(
|
|||
fts3SegReaderSort(apSegment, nMerge, j, xCmp);
|
||||
}
|
||||
if( nDoclist>0 ){
|
||||
rc = fts3GrowSegReaderBuffer(pCsr, nDoclist+FTS3_NODE_PADDING);
|
||||
rc = fts3GrowSegReaderBuffer(pCsr, (i64)nDoclist+FTS3_NODE_PADDING);
|
||||
if( rc ) return rc;
|
||||
memset(&pCsr->aBuffer[nDoclist], 0, FTS3_NODE_PADDING);
|
||||
pCsr->aDoclist = pCsr->aBuffer;
|
||||
|
@ -3745,7 +3754,7 @@ struct NodeReader {
|
|||
static void blobGrowBuffer(Blob *pBlob, int nMin, int *pRc){
|
||||
if( *pRc==SQLITE_OK && nMin>pBlob->nAlloc ){
|
||||
int nAlloc = nMin;
|
||||
char *a = (char *)sqlite3_realloc(pBlob->a, nAlloc);
|
||||
char *a = (char *)sqlite3_realloc64(pBlob->a, nAlloc);
|
||||
if( a ){
|
||||
pBlob->nAlloc = nAlloc;
|
||||
pBlob->a = a;
|
||||
|
@ -3786,7 +3795,7 @@ static int nodeReaderNext(NodeReader *p){
|
|||
return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( rc==SQLITE_OK && ALWAYS(p->term.a!=0) ){
|
||||
memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix);
|
||||
p->term.n = nPrefix+nSuffix;
|
||||
p->iOff += nSuffix;
|
||||
|
@ -3894,6 +3903,8 @@ static int fts3IncrmergePush(
|
|||
pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nPrefix);
|
||||
}
|
||||
pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nSuffix);
|
||||
assert( nPrefix+nSuffix<=nTerm );
|
||||
assert( nPrefix>=0 );
|
||||
memcpy(&pBlk->a[pBlk->n], &zTerm[nPrefix], nSuffix);
|
||||
pBlk->n += nSuffix;
|
||||
|
||||
|
@ -4016,6 +4027,7 @@ static int fts3IncrmergeAppend(
|
|||
pLeaf = &pWriter->aNodeWriter[0];
|
||||
nPrefix = fts3PrefixCompress(pLeaf->key.a, pLeaf->key.n, zTerm, nTerm);
|
||||
nSuffix = nTerm - nPrefix;
|
||||
if(nSuffix<=0 ) return FTS_CORRUPT_VTAB;
|
||||
|
||||
nSpace = sqlite3Fts3VarintLen(nPrefix);
|
||||
nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
|
||||
|
@ -4180,7 +4192,11 @@ static int fts3TermCmp(
|
|||
int nCmp = MIN(nLhs, nRhs);
|
||||
int res;
|
||||
|
||||
res = (nCmp ? memcmp(zLhs, zRhs, nCmp) : 0);
|
||||
if( nCmp && ALWAYS(zLhs) && ALWAYS(zRhs) ){
|
||||
res = memcmp(zLhs, zRhs, nCmp);
|
||||
}else{
|
||||
res = 0;
|
||||
}
|
||||
if( res==0 ) res = nLhs - nRhs;
|
||||
|
||||
return res;
|
||||
|
@ -4535,7 +4551,7 @@ static int fts3RepackSegdirLevel(
|
|||
if( nIdx>=nAlloc ){
|
||||
int *aNew;
|
||||
nAlloc += 16;
|
||||
aNew = sqlite3_realloc(aIdx, nAlloc*sizeof(int));
|
||||
aNew = sqlite3_realloc64(aIdx, nAlloc*sizeof(int));
|
||||
if( !aNew ){
|
||||
rc = SQLITE_NOMEM;
|
||||
break;
|
||||
|
@ -4824,7 +4840,7 @@ static int fts3IncrmergeHintLoad(Fts3Table *p, Blob *pHint){
|
|||
if( aHint ){
|
||||
blobGrowBuffer(pHint, nHint, &rc);
|
||||
if( rc==SQLITE_OK ){
|
||||
memcpy(pHint->a, aHint, nHint);
|
||||
if( ALWAYS(pHint->a!=0) ) memcpy(pHint->a, aHint, nHint);
|
||||
pHint->n = nHint;
|
||||
}
|
||||
}
|
||||
|
@ -4909,7 +4925,7 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
|
|||
|
||||
/* Allocate space for the cursor, filter and writer objects */
|
||||
const int nAlloc = sizeof(*pCsr) + sizeof(*pFilter) + sizeof(*pWriter);
|
||||
pWriter = (IncrmergeWriter *)sqlite3_malloc(nAlloc);
|
||||
pWriter = (IncrmergeWriter *)sqlite3_malloc64(nAlloc);
|
||||
if( !pWriter ) return SQLITE_NOMEM;
|
||||
pFilter = (Fts3SegFilter *)&pWriter[1];
|
||||
pCsr = (Fts3MultiSegReader *)&pFilter[1];
|
||||
|
@ -5545,7 +5561,7 @@ int sqlite3Fts3DeferredTokenList(
|
|||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
pRet = (char *)sqlite3_malloc(p->pList->nData);
|
||||
pRet = (char *)sqlite3_malloc64(p->pList->nData);
|
||||
if( !pRet ) return SQLITE_NOMEM;
|
||||
|
||||
nSkip = sqlite3Fts3GetVarint(p->pList->aData, &dummy);
|
||||
|
@ -5565,7 +5581,7 @@ int sqlite3Fts3DeferToken(
|
|||
int iCol /* Column that token must appear in (or -1) */
|
||||
){
|
||||
Fts3DeferredToken *pDeferred;
|
||||
pDeferred = sqlite3_malloc(sizeof(*pDeferred));
|
||||
pDeferred = sqlite3_malloc64(sizeof(*pDeferred));
|
||||
if( !pDeferred ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
|
440
third_party/sqlite3/fts5.c
vendored
440
third_party/sqlite3/fts5.c
vendored
File diff suppressed because it is too large
Load diff
|
@ -10,13 +10,12 @@
|
|||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** Interfaces to extend FTS5. Using the interfaces defined in this file,
|
||||
** Interfaces to extend FTS5. Using the interfaces defined in this file,
|
||||
** FTS5 may be extended with:
|
||||
**
|
||||
** * custom tokenizers, and
|
||||
** * custom auxiliary functions.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
|
||||
#ifndef _FTS5_H
|
366
third_party/sqlite3/func.c
vendored
366
third_party/sqlite3/func.c
vendored
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
#include "libc/math.h"
|
||||
#endif
|
||||
|
@ -98,6 +98,18 @@ static void typeofFunc(
|
|||
sqlite3_result_text(context, azType[i], -1, SQLITE_STATIC);
|
||||
}
|
||||
|
||||
/* subtype(X)
|
||||
**
|
||||
** Return the subtype of X
|
||||
*/
|
||||
static void subtypeFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
UNUSED_PARAMETER(argc);
|
||||
sqlite3_result_int(context, sqlite3_value_subtype(argv[0]));
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the length() function
|
||||
|
@ -259,7 +271,7 @@ endInstrOOM:
|
|||
}
|
||||
|
||||
/*
|
||||
** Implementation of the printf() function.
|
||||
** Implementation of the printf() (a.k.a. format()) SQL function.
|
||||
*/
|
||||
static void printfFunc(
|
||||
sqlite3_context *context,
|
||||
|
@ -572,9 +584,9 @@ static void last_insert_rowid(
|
|||
/*
|
||||
** Implementation of the changes() SQL function.
|
||||
**
|
||||
** IMP: R-62073-11209 The changes() SQL function is a wrapper
|
||||
** around the sqlite3_changes() C/C++ function and hence follows the same
|
||||
** rules for counting changes.
|
||||
** IMP: R-32760-32347 The changes() SQL function is a wrapper
|
||||
** around the sqlite3_changes64() C/C++ function and hence follows the
|
||||
** same rules for counting changes.
|
||||
*/
|
||||
static void changes(
|
||||
sqlite3_context *context,
|
||||
|
@ -583,12 +595,12 @@ static void changes(
|
|||
){
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
||||
sqlite3_result_int(context, sqlite3_changes(db));
|
||||
sqlite3_result_int64(context, sqlite3_changes64(db));
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the total_changes() SQL function. The return value is
|
||||
** the same as the sqlite3_total_changes() API function.
|
||||
** the same as the sqlite3_total_changes64() API function.
|
||||
*/
|
||||
static void total_changes(
|
||||
sqlite3_context *context,
|
||||
|
@ -597,9 +609,9 @@ static void total_changes(
|
|||
){
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
||||
/* IMP: R-52756-41993 This function is a wrapper around the
|
||||
** sqlite3_total_changes() C/C++ interface. */
|
||||
sqlite3_result_int(context, sqlite3_total_changes(db));
|
||||
/* IMP: R-11217-42568 This function is a wrapper around the
|
||||
** sqlite3_total_changes64() C/C++ interface. */
|
||||
sqlite3_result_int64(context, sqlite3_total_changes64(db));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -729,7 +741,7 @@ static int patternCompare(
|
|||
** c but in the other case and search the input string for either
|
||||
** c or cx.
|
||||
*/
|
||||
if( c<=0x80 ){
|
||||
if( c<0x80 ){
|
||||
char zStop[3];
|
||||
int bMatch;
|
||||
if( noCase ){
|
||||
|
@ -812,7 +824,13 @@ static int patternCompare(
|
|||
** non-zero if there is no match.
|
||||
*/
|
||||
int sqlite3_strglob(const char *zGlobPattern, const char *zString){
|
||||
return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[');
|
||||
if( zString==0 ){
|
||||
return zGlobPattern!=0;
|
||||
}else if( zGlobPattern==0 ){
|
||||
return 1;
|
||||
}else {
|
||||
return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -820,7 +838,13 @@ int sqlite3_strglob(const char *zGlobPattern, const char *zString){
|
|||
** a miss - like strcmp().
|
||||
*/
|
||||
int sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){
|
||||
return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc);
|
||||
if( zStr==0 ){
|
||||
return zPattern!=0;
|
||||
}else if( zPattern==0 ){
|
||||
return 1;
|
||||
}else{
|
||||
return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1028,39 +1052,42 @@ static const char hexdigits[] = {
|
|||
};
|
||||
|
||||
/*
|
||||
** Implementation of the QUOTE() function. This function takes a single
|
||||
** argument. If the argument is numeric, the return value is the same as
|
||||
** the argument. If the argument is NULL, the return value is the string
|
||||
** "NULL". Otherwise, the argument is enclosed in single quotes with
|
||||
** single-quote escapes.
|
||||
** Append to pStr text that is the SQL literal representation of the
|
||||
** value contained in pValue.
|
||||
*/
|
||||
static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
assert( argc==1 );
|
||||
UNUSED_PARAMETER(argc);
|
||||
switch( sqlite3_value_type(argv[0]) ){
|
||||
void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
|
||||
/* As currently implemented, the string must be initially empty.
|
||||
** we might relax this requirement in the future, but that will
|
||||
** require enhancements to the implementation. */
|
||||
assert( pStr!=0 && pStr->nChar==0 );
|
||||
|
||||
switch( sqlite3_value_type(pValue) ){
|
||||
case SQLITE_FLOAT: {
|
||||
double r1, r2;
|
||||
char zBuf[50];
|
||||
r1 = sqlite3_value_double(argv[0]);
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1);
|
||||
sqlite3AtoF(zBuf, &r2, 20, SQLITE_UTF8);
|
||||
if( r1!=r2 ){
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.20e", r1);
|
||||
const char *zVal;
|
||||
r1 = sqlite3_value_double(pValue);
|
||||
sqlite3_str_appendf(pStr, "%!.15g", r1);
|
||||
zVal = sqlite3_str_value(pStr);
|
||||
if( zVal ){
|
||||
sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8);
|
||||
if( r1!=r2 ){
|
||||
sqlite3_str_reset(pStr);
|
||||
sqlite3_str_appendf(pStr, "%!.20e", r1);
|
||||
}
|
||||
}
|
||||
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
|
||||
break;
|
||||
}
|
||||
case SQLITE_INTEGER: {
|
||||
sqlite3_result_value(context, argv[0]);
|
||||
sqlite3_str_appendf(pStr, "%lld", sqlite3_value_int64(pValue));
|
||||
break;
|
||||
}
|
||||
case SQLITE_BLOB: {
|
||||
char *zText = 0;
|
||||
char const *zBlob = sqlite3_value_blob(argv[0]);
|
||||
int nBlob = sqlite3_value_bytes(argv[0]);
|
||||
assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */
|
||||
zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4);
|
||||
if( zText ){
|
||||
char const *zBlob = sqlite3_value_blob(pValue);
|
||||
int nBlob = sqlite3_value_bytes(pValue);
|
||||
assert( zBlob==sqlite3_value_blob(pValue) ); /* No encoding change */
|
||||
sqlite3StrAccumEnlarge(pStr, nBlob*2 + 4);
|
||||
if( pStr->accError==0 ){
|
||||
char *zText = pStr->zText;
|
||||
int i;
|
||||
for(i=0; i<nBlob; i++){
|
||||
zText[(i*2)+2] = hexdigits[(zBlob[i]>>4)&0x0F];
|
||||
|
@ -1070,42 +1097,48 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
|||
zText[(nBlob*2)+3] = '\0';
|
||||
zText[0] = 'X';
|
||||
zText[1] = '\'';
|
||||
sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_free(zText);
|
||||
pStr->nChar = nBlob*2 + 3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SQLITE_TEXT: {
|
||||
int i,j;
|
||||
u64 n;
|
||||
const unsigned char *zArg = sqlite3_value_text(argv[0]);
|
||||
char *z;
|
||||
|
||||
if( zArg==0 ) return;
|
||||
for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; }
|
||||
z = contextMalloc(context, ((i64)i)+((i64)n)+3);
|
||||
if( z ){
|
||||
z[0] = '\'';
|
||||
for(i=0, j=1; zArg[i]; i++){
|
||||
z[j++] = zArg[i];
|
||||
if( zArg[i]=='\'' ){
|
||||
z[j++] = '\'';
|
||||
}
|
||||
}
|
||||
z[j++] = '\'';
|
||||
z[j] = 0;
|
||||
sqlite3_result_text(context, z, j, sqlite3_free);
|
||||
}
|
||||
const unsigned char *zArg = sqlite3_value_text(pValue);
|
||||
sqlite3_str_appendf(pStr, "%Q", zArg);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assert( sqlite3_value_type(argv[0])==SQLITE_NULL );
|
||||
sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC);
|
||||
assert( sqlite3_value_type(pValue)==SQLITE_NULL );
|
||||
sqlite3_str_append(pStr, "NULL", 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the QUOTE() function.
|
||||
**
|
||||
** The quote(X) function returns the text of an SQL literal which is the
|
||||
** value of its argument suitable for inclusion into an SQL statement.
|
||||
** Strings are surrounded by single-quotes with escapes on interior quotes
|
||||
** as needed. BLOBs are encoded as hexadecimal literals. Strings with
|
||||
** embedded NUL characters cannot be represented as string literals in SQL
|
||||
** and hence the returned string literal is truncated prior to the first NUL.
|
||||
*/
|
||||
static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
sqlite3_str str;
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
assert( argc==1 );
|
||||
UNUSED_PARAMETER(argc);
|
||||
sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
|
||||
sqlite3QuoteValue(&str,argv[0]);
|
||||
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar,
|
||||
SQLITE_DYNAMIC);
|
||||
if( str.accError!=SQLITE_OK ){
|
||||
sqlite3_result_null(context);
|
||||
sqlite3_result_error_code(context, str.accError);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The unicode() function. Return the integer unicode code-point value
|
||||
** for the first character of the input string.
|
||||
|
@ -1317,10 +1350,10 @@ static void trimFunc(
|
|||
){
|
||||
const unsigned char *zIn; /* Input string */
|
||||
const unsigned char *zCharSet; /* Set of characters to trim */
|
||||
int nIn; /* Number of bytes in input */
|
||||
unsigned int nIn; /* Number of bytes in input */
|
||||
int flags; /* 1: trimleft 2: trimright 3: trim */
|
||||
int i; /* Loop counter */
|
||||
unsigned char *aLen = 0; /* Length of each character in zCharSet */
|
||||
unsigned int *aLen = 0; /* Length of each character in zCharSet */
|
||||
unsigned char **azChar = 0; /* Individual characters in zCharSet */
|
||||
int nChar; /* Number of characters in zCharSet */
|
||||
|
||||
|
@ -1329,13 +1362,13 @@ static void trimFunc(
|
|||
}
|
||||
zIn = sqlite3_value_text(argv[0]);
|
||||
if( zIn==0 ) return;
|
||||
nIn = sqlite3_value_bytes(argv[0]);
|
||||
nIn = (unsigned)sqlite3_value_bytes(argv[0]);
|
||||
assert( zIn==sqlite3_value_text(argv[0]) );
|
||||
if( argc==1 ){
|
||||
static const unsigned char lenOne[] = { 1 };
|
||||
static const unsigned lenOne[] = { 1 };
|
||||
static unsigned char * const azOne[] = { (u8*)" " };
|
||||
nChar = 1;
|
||||
aLen = (u8*)lenOne;
|
||||
aLen = (unsigned*)lenOne;
|
||||
azChar = (unsigned char **)azOne;
|
||||
zCharSet = 0;
|
||||
}else if( (zCharSet = sqlite3_value_text(argv[1]))==0 ){
|
||||
|
@ -1346,15 +1379,16 @@ static void trimFunc(
|
|||
SQLITE_SKIP_UTF8(z);
|
||||
}
|
||||
if( nChar>0 ){
|
||||
azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1));
|
||||
azChar = contextMalloc(context,
|
||||
((i64)nChar)*(sizeof(char*)+sizeof(unsigned)));
|
||||
if( azChar==0 ){
|
||||
return;
|
||||
}
|
||||
aLen = (unsigned char*)&azChar[nChar];
|
||||
aLen = (unsigned*)&azChar[nChar];
|
||||
for(z=zCharSet, nChar=0; *z; nChar++){
|
||||
azChar[nChar] = (unsigned char *)z;
|
||||
SQLITE_SKIP_UTF8(z);
|
||||
aLen[nChar] = (u8)(z - azChar[nChar]);
|
||||
aLen[nChar] = (unsigned)(z - azChar[nChar]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1362,7 +1396,7 @@ static void trimFunc(
|
|||
flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context));
|
||||
if( flags & 1 ){
|
||||
while( nIn>0 ){
|
||||
int len = 0;
|
||||
unsigned int len = 0;
|
||||
for(i=0; i<nChar; i++){
|
||||
len = aLen[i];
|
||||
if( len<=nIn && memcmp(zIn, azChar[i], len)==0 ) break;
|
||||
|
@ -1374,7 +1408,7 @@ static void trimFunc(
|
|||
}
|
||||
if( flags & 2 ){
|
||||
while( nIn>0 ){
|
||||
int len = 0;
|
||||
unsigned int len = 0;
|
||||
for(i=0; i<nChar; i++){
|
||||
len = aLen[i];
|
||||
if( len<=nIn && memcmp(&zIn[nIn-len],azChar[i],len)==0 ) break;
|
||||
|
@ -1715,97 +1749,167 @@ static void minMaxFinalize(sqlite3_context *context){
|
|||
|
||||
/*
|
||||
** group_concat(EXPR, ?SEPARATOR?)
|
||||
**
|
||||
** The SEPARATOR goes before the EXPR string. This is tragic. The
|
||||
** groupConcatInverse() implementation would have been easier if the
|
||||
** SEPARATOR were appended after EXPR. And the order is undocumented,
|
||||
** so we could change it, in theory. But the old behavior has been
|
||||
** around for so long that we dare not, for fear of breaking something.
|
||||
*/
|
||||
typedef struct {
|
||||
StrAccum str; /* The accumulated concatenation */
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
int nAccum; /* Number of strings presently concatenated */
|
||||
int nFirstSepLength; /* Used to detect separator length change */
|
||||
/* If pnSepLengths!=0, refs an array of inter-string separator lengths,
|
||||
** stored as actually incorporated into presently accumulated result.
|
||||
** (Hence, its slots in use number nAccum-1 between method calls.)
|
||||
** If pnSepLengths==0, nFirstSepLength is the length used throughout.
|
||||
*/
|
||||
int *pnSepLengths;
|
||||
#endif
|
||||
} GroupConcatCtx;
|
||||
|
||||
static void groupConcatStep(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const char *zVal;
|
||||
StrAccum *pAccum;
|
||||
GroupConcatCtx *pGCC;
|
||||
const char *zSep;
|
||||
int nVal, nSep;
|
||||
assert( argc==1 || argc==2 );
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
|
||||
pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum));
|
||||
|
||||
if( pAccum ){
|
||||
pGCC = (GroupConcatCtx*)sqlite3_aggregate_context(context, sizeof(*pGCC));
|
||||
if( pGCC ){
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
int firstTerm = pAccum->mxAlloc==0;
|
||||
pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
|
||||
if( !firstTerm ){
|
||||
if( argc==2 ){
|
||||
zSep = (char*)sqlite3_value_text(argv[1]);
|
||||
nSep = sqlite3_value_bytes(argv[1]);
|
||||
}else{
|
||||
zSep = ",";
|
||||
nSep = 1;
|
||||
int firstTerm = pGCC->str.mxAlloc==0;
|
||||
pGCC->str.mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
|
||||
if( argc==1 ){
|
||||
if( !firstTerm ){
|
||||
sqlite3_str_appendchar(&pGCC->str, 1, ',');
|
||||
}
|
||||
if( zSep ) sqlite3_str_append(pAccum, zSep, nSep);
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
else{
|
||||
pGCC->nFirstSepLength = 1;
|
||||
}
|
||||
#endif
|
||||
}else if( !firstTerm ){
|
||||
zSep = (char*)sqlite3_value_text(argv[1]);
|
||||
nSep = sqlite3_value_bytes(argv[1]);
|
||||
if( zSep ){
|
||||
sqlite3_str_append(&pGCC->str, zSep, nSep);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
else{
|
||||
nSep = 0;
|
||||
}
|
||||
if( nSep != pGCC->nFirstSepLength || pGCC->pnSepLengths != 0 ){
|
||||
int *pnsl = pGCC->pnSepLengths;
|
||||
if( pnsl == 0 ){
|
||||
/* First separator length variation seen, start tracking them. */
|
||||
pnsl = (int*)sqlite3_malloc64((pGCC->nAccum+1) * sizeof(int));
|
||||
if( pnsl!=0 ){
|
||||
int i = 0, nA = pGCC->nAccum-1;
|
||||
while( i<nA ) pnsl[i++] = pGCC->nFirstSepLength;
|
||||
}
|
||||
}else{
|
||||
pnsl = (int*)sqlite3_realloc64(pnsl, pGCC->nAccum * sizeof(int));
|
||||
}
|
||||
if( pnsl!=0 ){
|
||||
if( ALWAYS(pGCC->nAccum>0) ){
|
||||
pnsl[pGCC->nAccum-1] = nSep;
|
||||
}
|
||||
pGCC->pnSepLengths = pnsl;
|
||||
}else{
|
||||
sqlite3StrAccumSetError(&pGCC->str, SQLITE_NOMEM);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
else{
|
||||
pGCC->nFirstSepLength = sqlite3_value_bytes(argv[1]);
|
||||
}
|
||||
pGCC->nAccum += 1;
|
||||
#endif
|
||||
zVal = (char*)sqlite3_value_text(argv[0]);
|
||||
nVal = sqlite3_value_bytes(argv[0]);
|
||||
if( zVal ) sqlite3_str_append(pAccum, zVal, nVal);
|
||||
if( zVal ) sqlite3_str_append(&pGCC->str, zVal, nVal);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
static void groupConcatInverse(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
int n;
|
||||
StrAccum *pAccum;
|
||||
GroupConcatCtx *pGCC;
|
||||
assert( argc==1 || argc==2 );
|
||||
(void)argc; /* Suppress unused parameter warning */
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
|
||||
pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum));
|
||||
/* pAccum is always non-NULL since groupConcatStep() will have always
|
||||
pGCC = (GroupConcatCtx*)sqlite3_aggregate_context(context, sizeof(*pGCC));
|
||||
/* pGCC is always non-NULL since groupConcatStep() will have always
|
||||
** run frist to initialize it */
|
||||
if( ALWAYS(pAccum) ){
|
||||
n = sqlite3_value_bytes(argv[0]);
|
||||
if( argc==2 ){
|
||||
n += sqlite3_value_bytes(argv[1]);
|
||||
if( ALWAYS(pGCC) ){
|
||||
int nVS;
|
||||
/* Must call sqlite3_value_text() to convert the argument into text prior
|
||||
** to invoking sqlite3_value_bytes(), in case the text encoding is UTF16 */
|
||||
(void)sqlite3_value_text(argv[0]);
|
||||
nVS = sqlite3_value_bytes(argv[0]);
|
||||
pGCC->nAccum -= 1;
|
||||
if( pGCC->pnSepLengths!=0 ){
|
||||
assert(pGCC->nAccum >= 0);
|
||||
if( pGCC->nAccum>0 ){
|
||||
nVS += *pGCC->pnSepLengths;
|
||||
memmove(pGCC->pnSepLengths, pGCC->pnSepLengths+1,
|
||||
(pGCC->nAccum-1)*sizeof(int));
|
||||
}
|
||||
}else{
|
||||
n++;
|
||||
/* If removing single accumulated string, harmlessly over-do. */
|
||||
nVS += pGCC->nFirstSepLength;
|
||||
}
|
||||
if( n>=(int)pAccum->nChar ){
|
||||
pAccum->nChar = 0;
|
||||
if( nVS>=(int)pGCC->str.nChar ){
|
||||
pGCC->str.nChar = 0;
|
||||
}else{
|
||||
pAccum->nChar -= n;
|
||||
memmove(pAccum->zText, &pAccum->zText[n], pAccum->nChar);
|
||||
pGCC->str.nChar -= nVS;
|
||||
memmove(pGCC->str.zText, &pGCC->str.zText[nVS], pGCC->str.nChar);
|
||||
}
|
||||
if( pGCC->str.nChar==0 ){
|
||||
pGCC->str.mxAlloc = 0;
|
||||
sqlite3_free(pGCC->pnSepLengths);
|
||||
pGCC->pnSepLengths = 0;
|
||||
}
|
||||
if( pAccum->nChar==0 ) pAccum->mxAlloc = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define groupConcatInverse 0
|
||||
#endif /* SQLITE_OMIT_WINDOWFUNC */
|
||||
static void groupConcatFinalize(sqlite3_context *context){
|
||||
StrAccum *pAccum;
|
||||
pAccum = sqlite3_aggregate_context(context, 0);
|
||||
if( pAccum ){
|
||||
if( pAccum->accError==SQLITE_TOOBIG ){
|
||||
sqlite3_result_error_toobig(context);
|
||||
}else if( pAccum->accError==SQLITE_NOMEM ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else{
|
||||
sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1,
|
||||
sqlite3_free);
|
||||
}
|
||||
GroupConcatCtx *pGCC
|
||||
= (GroupConcatCtx*)sqlite3_aggregate_context(context, 0);
|
||||
if( pGCC ){
|
||||
sqlite3ResultStrAccum(context, &pGCC->str);
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
sqlite3_free(pGCC->pnSepLengths);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
static void groupConcatValue(sqlite3_context *context){
|
||||
sqlite3_str *pAccum;
|
||||
pAccum = (sqlite3_str*)sqlite3_aggregate_context(context, 0);
|
||||
if( pAccum ){
|
||||
GroupConcatCtx *pGCC
|
||||
= (GroupConcatCtx*)sqlite3_aggregate_context(context, 0);
|
||||
if( pGCC ){
|
||||
StrAccum *pAccum = &pGCC->str;
|
||||
if( pAccum->accError==SQLITE_TOOBIG ){
|
||||
sqlite3_result_error_toobig(context);
|
||||
}else if( pAccum->accError==SQLITE_NOMEM ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else{
|
||||
const char *zText = sqlite3_str_value(pAccum);
|
||||
sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1869,11 +1973,12 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
|
|||
int nExpr;
|
||||
assert( pExpr!=0 );
|
||||
assert( pExpr->op==TK_FUNCTION );
|
||||
assert( ExprUseXList(pExpr) );
|
||||
if( !pExpr->x.pList ){
|
||||
return 0;
|
||||
}
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
nExpr = pExpr->x.pList->nExpr;
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0);
|
||||
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||
if( pDef==0 ) return 0;
|
||||
|
@ -1897,6 +2002,7 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
|
|||
Expr *pEscape = pExpr->x.pList->a[2].pExpr;
|
||||
char *zEscape;
|
||||
if( pEscape->op!=TK_STRING ) return 0;
|
||||
assert( !ExprHasProperty(pEscape, EP_IntValue) );
|
||||
zEscape = pEscape->u.zToken;
|
||||
if( zEscape[0]==0 || zEscape[1]!=0 ) return 0;
|
||||
if( zEscape[0]==aWc[0] ) return 0;
|
||||
|
@ -2005,11 +2111,11 @@ static void logFunc(
|
|||
switch( SQLITE_PTR_TO_INT(sqlite3_user_data(context)) ){
|
||||
case 1:
|
||||
/* Convert from natural logarithm to log base 10 */
|
||||
ans *= 1.0/M_LN10;
|
||||
ans /= M_LN10;
|
||||
break;
|
||||
case 2:
|
||||
/* Convert from natural logarithm to log base 2 */
|
||||
ans *= 1.0/M_LN2;
|
||||
ans /= M_LN2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -2072,9 +2178,7 @@ static void math2Func(
|
|||
}
|
||||
|
||||
/*
|
||||
** Implementation of 2-argument SQL math functions:
|
||||
**
|
||||
** power(X,Y) - Compute X to the Y-th power
|
||||
** Implementation of 0-argument pi() function.
|
||||
*/
|
||||
static void piFunc(
|
||||
sqlite3_context *context,
|
||||
|
@ -2125,12 +2229,12 @@ void sqlite3RegisterBuiltinFunctions(void){
|
|||
*/
|
||||
static FuncDef aBuiltinFunc[] = {
|
||||
/***** Functions only available with SQLITE_TESTCTRL_INTERNAL_FUNCTIONS *****/
|
||||
#if !defined(SQLITE_UNTESTABLE)
|
||||
TEST_FUNC(implies_nonnull_row, 2, INLINEFUNC_implies_nonnull_row, 0),
|
||||
TEST_FUNC(expr_compare, 2, INLINEFUNC_expr_compare, 0),
|
||||
TEST_FUNC(expr_implies_expr, 2, INLINEFUNC_expr_implies_expr, 0),
|
||||
#ifdef SQLITE_DEBUG
|
||||
TEST_FUNC(affinity, 1, INLINEFUNC_affinity, 0),
|
||||
#endif
|
||||
TEST_FUNC(affinity, 1, INLINEFUNC_affinity, 0),
|
||||
#endif /* !defined(SQLITE_UNTESTABLE) */
|
||||
/***** Regular functions *****/
|
||||
#ifdef SQLITE_SOUNDEX
|
||||
FUNCTION(soundex, 1, 0, 0, soundexFunc ),
|
||||
|
@ -2150,8 +2254,7 @@ void sqlite3RegisterBuiltinFunctions(void){
|
|||
INLINE_FUNC(likelihood, 2, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
|
||||
INLINE_FUNC(likely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
|
||||
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
FUNCTION2(sqlite_offset, 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET|
|
||||
SQLITE_FUNC_TYPEOF),
|
||||
INLINE_FUNC(sqlite_offset, 1, INLINEFUNC_sqlite_offset, 0 ),
|
||||
#endif
|
||||
FUNCTION(ltrim, 1, 1, 0, trimFunc ),
|
||||
FUNCTION(ltrim, 2, 1, 0, trimFunc ),
|
||||
|
@ -2162,15 +2265,17 @@ void sqlite3RegisterBuiltinFunctions(void){
|
|||
FUNCTION(min, -1, 0, 1, minmaxFunc ),
|
||||
FUNCTION(min, 0, 0, 1, 0 ),
|
||||
WAGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
|
||||
SQLITE_FUNC_MINMAX ),
|
||||
SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
|
||||
FUNCTION(max, -1, 1, 1, minmaxFunc ),
|
||||
FUNCTION(max, 0, 1, 1, 0 ),
|
||||
WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
|
||||
SQLITE_FUNC_MINMAX ),
|
||||
SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
|
||||
FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
|
||||
FUNCTION2(subtype, 1, 0, 0, subtypeFunc, SQLITE_FUNC_TYPEOF),
|
||||
FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
|
||||
FUNCTION(instr, 2, 0, 0, instrFunc ),
|
||||
FUNCTION(printf, -1, 0, 0, printfFunc ),
|
||||
FUNCTION(format, -1, 0, 0, printfFunc ),
|
||||
FUNCTION(unicode, 1, 0, 0, unicodeFunc ),
|
||||
FUNCTION(char, -1, 0, 0, charFunc ),
|
||||
FUNCTION(abs, 1, 0, 0, absFunc ),
|
||||
|
@ -2202,9 +2307,10 @@ void sqlite3RegisterBuiltinFunctions(void){
|
|||
WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0),
|
||||
WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0),
|
||||
WAGGREGATE(count, 0,0,0, countStep,
|
||||
countFinalize, countFinalize, countInverse, SQLITE_FUNC_COUNT ),
|
||||
countFinalize, countFinalize, countInverse,
|
||||
SQLITE_FUNC_COUNT|SQLITE_FUNC_ANYORDER ),
|
||||
WAGGREGATE(count, 1,0,0, countStep,
|
||||
countFinalize, countFinalize, countInverse, 0 ),
|
||||
countFinalize, countFinalize, countInverse, SQLITE_FUNC_ANYORDER ),
|
||||
WAGGREGATE(group_concat, 1, 0, 0, groupConcatStep,
|
||||
groupConcatFinalize, groupConcatValue, groupConcatInverse, 0),
|
||||
WAGGREGATE(group_concat, 2, 0, 0, groupConcatStep,
|
||||
|
@ -2268,6 +2374,7 @@ void sqlite3RegisterBuiltinFunctions(void){
|
|||
#endif
|
||||
sqlite3WindowFunctions();
|
||||
sqlite3RegisterDateTimeFunctions();
|
||||
sqlite3RegisterJsonFunctions();
|
||||
sqlite3InsertBuiltinFuncs(aBuiltinFunc, ArraySize(aBuiltinFunc));
|
||||
|
||||
#if 0 /* Enable to print out how the built-in functions are hashed */
|
||||
|
@ -2279,6 +2386,7 @@ void sqlite3RegisterBuiltinFunctions(void){
|
|||
for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash){
|
||||
int n = sqlite3Strlen30(p->zName);
|
||||
int h = p->zName[0] + n;
|
||||
assert( p->funcFlags & SQLITE_FUNC_BUILTIN );
|
||||
printf(" %s(%d)", p->zName, h);
|
||||
}
|
||||
printf("\n");
|
||||
|
|
38
third_party/sqlite3/geopoly.inc
vendored
38
third_party/sqlite3/geopoly.inc
vendored
|
@ -27,11 +27,11 @@
|
|||
# define GEODEBUG(X)
|
||||
#endif
|
||||
|
||||
#ifndef JSON_NULL /* The following stuff repeats things found in json1 */
|
||||
/*
|
||||
** Versions of isspace(), isalnum() and isdigit() to which it is safe
|
||||
** to pass signed char values.
|
||||
*/
|
||||
#if defined(__GNUC__) && !defined(__llvm__)
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
|
||||
/* Character class routines */
|
||||
#ifdef sqlite3Isdigit
|
||||
/* Use the SQLite core versions if this routine is part of the
|
||||
** SQLite amalgamation */
|
||||
|
@ -39,13 +39,14 @@
|
|||
# define safe_isalnum(x) sqlite3Isalnum(x)
|
||||
# define safe_isxdigit(x) sqlite3Isxdigit(x)
|
||||
#else
|
||||
/* Use the standard library for separate compilation */
|
||||
/* Use the standard library for separate compilation */
|
||||
#include "libc/str/str.h" /* amalgamator: keep */
|
||||
#define safe_isdigit(x) isdigit((unsigned char)(x))
|
||||
#define safe_isalnum(x) isalnum((unsigned char)(x))
|
||||
#define safe_isxdigit(x) isxdigit((unsigned char)(x))
|
||||
# define safe_isdigit(x) isdigit((unsigned char)(x))
|
||||
# define safe_isalnum(x) isalnum((unsigned char)(x))
|
||||
# define safe_isxdigit(x) isxdigit((unsigned char)(x))
|
||||
#endif
|
||||
|
||||
#ifndef JSON_NULL /* The following stuff repeats things found in json1 */
|
||||
/*
|
||||
** Growing our own isspace() routine this way is twice as fast as
|
||||
** the library isspace() function.
|
||||
|
@ -68,7 +69,7 @@ static const char geopolyIsSpace[] = {
|
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
#define safe_isspace(x) (geopolyIsSpace[(unsigned char)x])
|
||||
#define fast_isspace(x) (geopolyIsSpace[(unsigned char)x])
|
||||
#endif /* JSON NULL - back to original code */
|
||||
|
||||
/* Compiler and version */
|
||||
|
@ -157,7 +158,7 @@ static void geopolySwab32(unsigned char *a){
|
|||
|
||||
/* Skip whitespace. Return the next non-whitespace character. */
|
||||
static char geopolySkipSpace(GeoParse *p){
|
||||
while( safe_isspace(p->z[0]) ) p->z++;
|
||||
while( fast_isspace(p->z[0]) ) p->z++;
|
||||
return p->z[0];
|
||||
}
|
||||
|
||||
|
@ -306,11 +307,16 @@ static GeoPoly *geopolyFuncParam(
|
|||
){
|
||||
GeoPoly *p = 0;
|
||||
int nByte;
|
||||
testcase( pCtx==0 );
|
||||
if( sqlite3_value_type(pVal)==SQLITE_BLOB
|
||||
&& (nByte = sqlite3_value_bytes(pVal))>=(4+6*sizeof(GeoCoord))
|
||||
){
|
||||
const unsigned char *a = sqlite3_value_blob(pVal);
|
||||
int nVertex;
|
||||
if( a==0 ){
|
||||
if( pCtx ) sqlite3_result_error_nomem(pCtx);
|
||||
return 0;
|
||||
}
|
||||
nVertex = (a[1]<<16) + (a[2]<<8) + a[3];
|
||||
if( (a[0]==0 || a[0]==1)
|
||||
&& (nVertex*2*sizeof(GeoCoord) + 4)==(unsigned int)nByte
|
||||
|
@ -684,7 +690,7 @@ static GeoPoly *geopolyBBox(
|
|||
aCoord[2].f = mnY;
|
||||
aCoord[3].f = mxY;
|
||||
}
|
||||
}else{
|
||||
}else if( aCoord ){
|
||||
memset(aCoord, 0, sizeof(RtreeCoord)*4);
|
||||
}
|
||||
return pOut;
|
||||
|
@ -1135,11 +1141,11 @@ static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2){
|
|||
}else{
|
||||
/* Remove a segment */
|
||||
if( pActive==pThisEvent->pSeg ){
|
||||
pActive = pActive->pNext;
|
||||
pActive = ALWAYS(pActive) ? pActive->pNext : 0;
|
||||
}else{
|
||||
for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){
|
||||
if( pSeg->pNext==pThisEvent->pSeg ){
|
||||
pSeg->pNext = pSeg->pNext->pNext;
|
||||
pSeg->pNext = ALWAYS(pSeg->pNext) ? pSeg->pNext->pNext : 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1383,6 +1389,7 @@ static int geopolyFilter(
|
|||
RtreeCoord bbox[4];
|
||||
RtreeConstraint *p;
|
||||
assert( argc==1 );
|
||||
assert( argv[0]!=0 );
|
||||
geopolyBBox(0, argv[0], bbox, &rc);
|
||||
if( rc ){
|
||||
goto geopoly_filter_end;
|
||||
|
@ -1610,6 +1617,7 @@ static int geopolyUpdate(
|
|||
|| !sqlite3_value_nochange(aData[2]) /* UPDATE _shape */
|
||||
|| oldRowid!=newRowid) /* Rowid change */
|
||||
){
|
||||
assert( aData[2]!=0 );
|
||||
geopolyBBox(0, aData[2], cell.aCoord, &rc);
|
||||
if( rc ){
|
||||
if( rc==SQLITE_ERROR ){
|
||||
|
@ -1692,7 +1700,7 @@ static int geopolyUpdate(
|
|||
sqlite3_free(p);
|
||||
nChange = 1;
|
||||
}
|
||||
for(jj=1; jj<pRtree->nAux; jj++){
|
||||
for(jj=1; jj<nData-2; jj++){
|
||||
nChange++;
|
||||
sqlite3_bind_value(pUp, jj+2, aData[jj+2]);
|
||||
}
|
||||
|
|
85
third_party/sqlite3/global.c
vendored
85
third_party/sqlite3/global.c
vendored
|
@ -12,8 +12,7 @@
|
|||
**
|
||||
** This file contains definitions of global variables and constants.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/* An array to map all upper-case characters into their corresponding
|
||||
** lower-case character.
|
||||
|
@ -38,7 +37,7 @@ const unsigned char sqlite3UpperToLower[] = {
|
|||
198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
|
||||
216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
|
||||
234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
|
||||
252,253,254,255
|
||||
252,253,254,255,
|
||||
#endif
|
||||
#ifdef SQLITE_EBCDIC
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 0x */
|
||||
|
@ -58,7 +57,35 @@ const unsigned char sqlite3UpperToLower[] = {
|
|||
224,225,162,163,164,165,166,167,168,169,234,235,236,237,238,239, /* Ex */
|
||||
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, /* Fx */
|
||||
#endif
|
||||
/* All of the upper-to-lower conversion data is above. The following
|
||||
** 18 integers are completely unrelated. They are appended to the
|
||||
** sqlite3UpperToLower[] array to avoid UBSAN warnings. Here's what is
|
||||
** going on:
|
||||
**
|
||||
** The SQL comparison operators (<>, =, >, <=, <, and >=) are implemented
|
||||
** by invoking sqlite3MemCompare(A,B) which compares values A and B and
|
||||
** returns negative, zero, or positive if A is less then, equal to, or
|
||||
** greater than B, respectively. Then the true false results is found by
|
||||
** consulting sqlite3aLTb[opcode], sqlite3aEQb[opcode], or
|
||||
** sqlite3aGTb[opcode] depending on whether the result of compare(A,B)
|
||||
** is negative, zero, or positive, where opcode is the specific opcode.
|
||||
** The only works because the comparison opcodes are consecutive and in
|
||||
** this order: NE EQ GT LE LT GE. Various assert()s throughout the code
|
||||
** ensure that is the case.
|
||||
**
|
||||
** These elements must be appended to another array. Otherwise the
|
||||
** index (here shown as [256-OP_Ne]) would be out-of-bounds and thus
|
||||
** be undefined behavior. That's goofy, but the C-standards people thought
|
||||
** it was a good idea, so here we are.
|
||||
*/
|
||||
/* NE EQ GT LE LT GE */
|
||||
1, 0, 0, 1, 1, 0, /* aLTb[]: Use when compare(A,B) less than zero */
|
||||
0, 1, 0, 1, 0, 1, /* aEQb[]: Use when compare(A,B) equals zero */
|
||||
1, 0, 1, 0, 0, 1 /* aGTb[]: Use when compare(A,B) greater than zero*/
|
||||
};
|
||||
const unsigned char *sqlite3aLTb = &sqlite3UpperToLower[256-OP_Ne];
|
||||
const unsigned char *sqlite3aEQb = &sqlite3UpperToLower[256+6-OP_Ne];
|
||||
const unsigned char *sqlite3aGTb = &sqlite3UpperToLower[256+12-OP_Ne];
|
||||
|
||||
/*
|
||||
** The following 256 byte lookup table is used to support SQLites built-in
|
||||
|
@ -252,16 +279,20 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
|||
0, /* xVdbeBranch */
|
||||
0, /* pVbeBranchArg */
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_DESERIALIZE
|
||||
#ifndef SQLITE_OMIT_DESERIALIZE
|
||||
SQLITE_MEMDB_DEFAULT_MAXSIZE, /* mxMemdbSize */
|
||||
#endif
|
||||
#ifndef SQLITE_UNTESTABLE
|
||||
0, /* xTestCallback */
|
||||
#endif
|
||||
0, /* bLocaltimeFault */
|
||||
0, /* xAltLocaltime */
|
||||
0x7ffffffe, /* iOnceResetThreshold */
|
||||
SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */
|
||||
0, /* iPrngSeed */
|
||||
#ifdef SQLITE_DEBUG
|
||||
{0,0,0,0,0,0} /* aTune */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -271,6 +302,18 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
|||
*/
|
||||
FuncDefHash sqlite3BuiltinFunctions;
|
||||
|
||||
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
|
||||
/*
|
||||
** Counter used for coverage testing. Does not come into play for
|
||||
** release builds.
|
||||
**
|
||||
** Access to this global variable is not mutex protected. This might
|
||||
** result in TSAN warnings. But as the variable does not exist in
|
||||
** release builds, that should not be a concern.
|
||||
*/
|
||||
unsigned int sqlite3CoverageCounter;
|
||||
#endif /* SQLITE_COVERAGE_TEST || SQLITE_DEBUG */
|
||||
|
||||
#ifdef VDBE_PROFILE
|
||||
/*
|
||||
** The following performance counter can be used in place of
|
||||
|
@ -304,10 +347,10 @@ int sqlite3PendingByte = 0x40000000;
|
|||
/*
|
||||
** Tracing flags set by SQLITE_TESTCTRL_TRACEFLAGS.
|
||||
*/
|
||||
u32 sqlite3SelectTrace = 0;
|
||||
u32 sqlite3TreeTrace = 0;
|
||||
u32 sqlite3WhereTrace = 0;
|
||||
|
||||
#include "third_party/sqlite3/opcodes.inc"
|
||||
#include "third_party/sqlite3/opcodes.h"
|
||||
/*
|
||||
** Properties of opcodes. The OPFLG_INITIALIZER macro is
|
||||
** created by mkopcodeh.awk during compilation. Data is obtained
|
||||
|
@ -320,3 +363,33 @@ const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;
|
|||
** Name of the default collating sequence
|
||||
*/
|
||||
const char sqlite3StrBINARY[] = "BINARY";
|
||||
|
||||
/*
|
||||
** Standard typenames. These names must match the COLTYPE_* definitions.
|
||||
** Adjust the SQLITE_N_STDTYPE value if adding or removing entries.
|
||||
**
|
||||
** sqlite3StdType[] The actual names of the datatypes.
|
||||
**
|
||||
** sqlite3StdTypeLen[] The length (in bytes) of each entry
|
||||
** in sqlite3StdType[].
|
||||
**
|
||||
** sqlite3StdTypeAffinity[] The affinity associated with each entry
|
||||
** in sqlite3StdType[].
|
||||
*/
|
||||
const unsigned char sqlite3StdTypeLen[] = { 3, 4, 3, 7, 4, 4 };
|
||||
const char sqlite3StdTypeAffinity[] = {
|
||||
SQLITE_AFF_NUMERIC,
|
||||
SQLITE_AFF_BLOB,
|
||||
SQLITE_AFF_INTEGER,
|
||||
SQLITE_AFF_INTEGER,
|
||||
SQLITE_AFF_REAL,
|
||||
SQLITE_AFF_TEXT
|
||||
};
|
||||
const char *sqlite3StdType[] = {
|
||||
"ANY",
|
||||
"BLOB",
|
||||
"INT",
|
||||
"INTEGER",
|
||||
"REAL",
|
||||
"TEXT"
|
||||
};
|
||||
|
|
3
third_party/sqlite3/hash.c
vendored
3
third_party/sqlite3/hash.c
vendored
|
@ -12,9 +12,8 @@
|
|||
** This is the implementation of generic hash-tables
|
||||
** used in SQLite.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
#include "libc/assert.h"
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
|
||||
/* Turn bulk memory into a hash table object by initializing the
|
||||
** fields of the Hash structure.
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
*/
|
||||
#ifndef SQLITE_HASH_H
|
||||
#define SQLITE_HASH_H
|
||||
/* clang-format off */
|
||||
|
||||
/* Forward declarations of structures. */
|
||||
typedef struct Hash Hash;
|
||||
|
@ -92,6 +91,6 @@ void sqlite3HashClear(Hash*);
|
|||
/*
|
||||
** Number of entries in a hash table
|
||||
*/
|
||||
/* #define sqliteHashCount(H) ((H)->count) // NOT USED */
|
||||
#define sqliteHashCount(H) ((H)->count)
|
||||
|
||||
#endif /* SQLITE_HASH_H */
|
1
third_party/sqlite3/hwtime.inc
vendored
1
third_party/sqlite3/hwtime.inc
vendored
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
#ifndef SQLITE_HWTIME_H
|
||||
#define SQLITE_HWTIME_H
|
||||
/* clang-format off */
|
||||
|
||||
/*
|
||||
** The following routine only works on pentium-class (or newer) processors.
|
||||
|
|
25
third_party/sqlite3/icu.c
vendored
25
third_party/sqlite3/icu.c
vendored
|
@ -11,9 +11,9 @@
|
|||
*************************************************************************
|
||||
** $Id: icu.c,v 1.7 2007/12/13 21:54:11 drh Exp $
|
||||
**
|
||||
** This file implements an integration between the ICU library
|
||||
** ("International Components for Unicode", an open-source library
|
||||
** for handling unicode data) and SQLite. The integration uses
|
||||
** This file implements an integration between the ICU library
|
||||
** ("International Components for Unicode", an open-source library
|
||||
** for handling unicode data) and SQLite. The integration uses
|
||||
** ICU to provide the following to SQLite:
|
||||
**
|
||||
** * An implementation of the SQL regexp() function (and hence REGEXP
|
||||
|
@ -24,23 +24,23 @@
|
|||
**
|
||||
** * Integration of ICU and SQLite collation sequences.
|
||||
**
|
||||
** * An implementation of the LIKE operator that uses ICU to
|
||||
** * An implementation of the LIKE operator that uses ICU to
|
||||
** provide case-independent matching.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
#if 0 && !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) || \
|
||||
defined(SQLITE_ENABLE_ICU_COLLATIONS)
|
||||
#if !defined(SQLITE_CORE) \
|
||||
|| defined(SQLITE_ENABLE_ICU) \
|
||||
|| defined(SQLITE_ENABLE_ICU_COLLATIONS)
|
||||
|
||||
/* Include ICU headers */
|
||||
#include "libc/assert.h"
|
||||
#include "libc/str/unicode.h"
|
||||
|
||||
#ifndef SQLITE_CORE
|
||||
#include "third_party/sqlite3/sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include "third_party/sqlite3/sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#else
|
||||
#include "third_party/sqlite3/sqlite3.h"
|
||||
#include "third_party/sqlite3/sqlite3.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -295,8 +295,9 @@ static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
|||
|
||||
if( U_SUCCESS(status) ){
|
||||
sqlite3_set_auxdata(p, 0, pExpr, icuRegexpDelete);
|
||||
}else{
|
||||
assert(!pExpr);
|
||||
pExpr = sqlite3_get_auxdata(p, 0);
|
||||
}
|
||||
if( !pExpr ){
|
||||
icuFunctionError(p, "uregex_open", status);
|
||||
return;
|
||||
}
|
||||
|
|
326
third_party/sqlite3/insert.c
vendored
326
third_party/sqlite3/insert.c
vendored
|
@ -12,8 +12,7 @@
|
|||
** This file contains C code routines that are called by the parser
|
||||
** to handle INSERT statements in SQLite.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/*
|
||||
** Generate code that will
|
||||
|
@ -44,7 +43,7 @@ void sqlite3OpenTable(
|
|||
}else{
|
||||
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
assert( pPk!=0 );
|
||||
assert( pPk->tnum==pTab->tnum );
|
||||
assert( pPk->tnum==pTab->tnum || CORRUPT_DB );
|
||||
sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, iDb);
|
||||
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
|
||||
VdbeComment((v, "%s", pTab->zName));
|
||||
|
@ -97,6 +96,7 @@ const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){
|
|||
aff = SQLITE_AFF_INTEGER;
|
||||
}else{
|
||||
assert( x==XN_EXPR );
|
||||
assert( pIdx->bHasExpr );
|
||||
assert( pIdx->aColExpr!=0 );
|
||||
aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr);
|
||||
}
|
||||
|
@ -111,38 +111,16 @@ const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){
|
|||
}
|
||||
|
||||
/*
|
||||
** Compute the affinity string for table pTab, if it has not already been
|
||||
** computed. As an optimization, omit trailing SQLITE_AFF_BLOB affinities.
|
||||
**
|
||||
** If the affinity exists (if it is no entirely SQLITE_AFF_BLOB values) and
|
||||
** if iReg>0 then code an OP_Affinity opcode that will set the affinities
|
||||
** for register iReg and following. Or if affinities exists and iReg==0,
|
||||
** then just set the P4 operand of the previous opcode (which should be
|
||||
** an OP_MakeRecord) to the affinity string.
|
||||
**
|
||||
** A column affinity string has one character per column:
|
||||
**
|
||||
** Character Column affinity
|
||||
** ------------------------------
|
||||
** 'A' BLOB
|
||||
** 'B' TEXT
|
||||
** 'C' NUMERIC
|
||||
** 'D' INTEGER
|
||||
** 'E' REAL
|
||||
** Compute an affinity string for a table. Space is obtained
|
||||
** from sqlite3DbMalloc(). The caller is responsible for freeing
|
||||
** the space when done.
|
||||
*/
|
||||
void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
|
||||
int i, j;
|
||||
char *zColAff = pTab->zColAff;
|
||||
if( zColAff==0 ){
|
||||
sqlite3 *db = sqlite3VdbeDb(v);
|
||||
zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1);
|
||||
if( !zColAff ){
|
||||
sqlite3OomFault(db);
|
||||
return;
|
||||
}
|
||||
|
||||
char *sqlite3TableAffinityStr(sqlite3 *db, const Table *pTab){
|
||||
char *zColAff;
|
||||
zColAff = (char *)sqlite3DbMallocRaw(db, pTab->nCol+1);
|
||||
if( zColAff ){
|
||||
int i, j;
|
||||
for(i=j=0; i<pTab->nCol; i++){
|
||||
assert( pTab->aCol[i].affinity!=0 );
|
||||
if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){
|
||||
zColAff[j++] = pTab->aCol[i].affinity;
|
||||
}
|
||||
|
@ -150,6 +128,79 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
|
|||
do{
|
||||
zColAff[j--] = 0;
|
||||
}while( j>=0 && zColAff[j]<=SQLITE_AFF_BLOB );
|
||||
}
|
||||
return zColAff;
|
||||
}
|
||||
|
||||
/*
|
||||
** Make changes to the evolving bytecode to do affinity transformations
|
||||
** of values that are about to be gathered into a row for table pTab.
|
||||
**
|
||||
** For ordinary (legacy, non-strict) tables:
|
||||
** -----------------------------------------
|
||||
**
|
||||
** Compute the affinity string for table pTab, if it has not already been
|
||||
** computed. As an optimization, omit trailing SQLITE_AFF_BLOB affinities.
|
||||
**
|
||||
** If the affinity string is empty (because it was all SQLITE_AFF_BLOB entries
|
||||
** which were then optimized out) then this routine becomes a no-op.
|
||||
**
|
||||
** Otherwise if iReg>0 then code an OP_Affinity opcode that will set the
|
||||
** affinities for register iReg and following. Or if iReg==0,
|
||||
** then just set the P4 operand of the previous opcode (which should be
|
||||
** an OP_MakeRecord) to the affinity string.
|
||||
**
|
||||
** A column affinity string has one character per column:
|
||||
**
|
||||
** Character Column affinity
|
||||
** --------- ---------------
|
||||
** 'A' BLOB
|
||||
** 'B' TEXT
|
||||
** 'C' NUMERIC
|
||||
** 'D' INTEGER
|
||||
** 'E' REAL
|
||||
**
|
||||
** For STRICT tables:
|
||||
** ------------------
|
||||
**
|
||||
** Generate an appropropriate OP_TypeCheck opcode that will verify the
|
||||
** datatypes against the column definitions in pTab. If iReg==0, that
|
||||
** means an OP_MakeRecord opcode has already been generated and should be
|
||||
** the last opcode generated. The new OP_TypeCheck needs to be inserted
|
||||
** before the OP_MakeRecord. The new OP_TypeCheck should use the same
|
||||
** register set as the OP_MakeRecord. If iReg>0 then register iReg is
|
||||
** the first of a series of registers that will form the new record.
|
||||
** Apply the type checking to that array of registers.
|
||||
*/
|
||||
void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
|
||||
int i;
|
||||
char *zColAff;
|
||||
if( pTab->tabFlags & TF_Strict ){
|
||||
if( iReg==0 ){
|
||||
/* Move the previous opcode (which should be OP_MakeRecord) forward
|
||||
** by one slot and insert a new OP_TypeCheck where the current
|
||||
** OP_MakeRecord is found */
|
||||
VdbeOp *pPrev;
|
||||
sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
|
||||
pPrev = sqlite3VdbeGetLastOp(v);
|
||||
assert( pPrev!=0 );
|
||||
assert( pPrev->opcode==OP_MakeRecord || sqlite3VdbeDb(v)->mallocFailed );
|
||||
pPrev->opcode = OP_TypeCheck;
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, pPrev->p1, pPrev->p2, pPrev->p3);
|
||||
}else{
|
||||
/* Insert an isolated OP_Typecheck */
|
||||
sqlite3VdbeAddOp2(v, OP_TypeCheck, iReg, pTab->nNVCol);
|
||||
sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
zColAff = pTab->zColAff;
|
||||
if( zColAff==0 ){
|
||||
zColAff = sqlite3TableAffinityStr(0, pTab);
|
||||
if( !zColAff ){
|
||||
sqlite3OomFault(sqlite3VdbeDb(v));
|
||||
return;
|
||||
}
|
||||
pTab->zColAff = zColAff;
|
||||
}
|
||||
assert( zColAff!=0 );
|
||||
|
@ -158,6 +209,8 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
|
|||
if( iReg ){
|
||||
sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i);
|
||||
}else{
|
||||
assert( sqlite3VdbeGetLastOp(v)->opcode==OP_MakeRecord
|
||||
|| sqlite3VdbeDb(v)->mallocFailed );
|
||||
sqlite3VdbeChangeP4(v, -1, zColAff, i);
|
||||
}
|
||||
}
|
||||
|
@ -241,24 +294,30 @@ void sqlite3ComputeGeneratedColumns(
|
|||
** that appropriate affinity has been applied to the regular columns
|
||||
*/
|
||||
sqlite3TableAffinity(pParse->pVdbe, pTab, iRegStore);
|
||||
if( (pTab->tabFlags & TF_HasStored)!=0
|
||||
&& (pOp = sqlite3VdbeGetOp(pParse->pVdbe,-1))->opcode==OP_Affinity
|
||||
){
|
||||
/* Change the OP_Affinity argument to '@' (NONE) for all stored
|
||||
** columns. '@' is the no-op affinity and those columns have not
|
||||
** yet been computed. */
|
||||
int ii, jj;
|
||||
char *zP4 = pOp->p4.z;
|
||||
assert( zP4!=0 );
|
||||
assert( pOp->p4type==P4_DYNAMIC );
|
||||
for(ii=jj=0; zP4[jj]; ii++){
|
||||
if( pTab->aCol[ii].colFlags & COLFLAG_VIRTUAL ){
|
||||
continue;
|
||||
if( (pTab->tabFlags & TF_HasStored)!=0 ){
|
||||
pOp = sqlite3VdbeGetLastOp(pParse->pVdbe);
|
||||
if( pOp->opcode==OP_Affinity ){
|
||||
/* Change the OP_Affinity argument to '@' (NONE) for all stored
|
||||
** columns. '@' is the no-op affinity and those columns have not
|
||||
** yet been computed. */
|
||||
int ii, jj;
|
||||
char *zP4 = pOp->p4.z;
|
||||
assert( zP4!=0 );
|
||||
assert( pOp->p4type==P4_DYNAMIC );
|
||||
for(ii=jj=0; zP4[jj]; ii++){
|
||||
if( pTab->aCol[ii].colFlags & COLFLAG_VIRTUAL ){
|
||||
continue;
|
||||
}
|
||||
if( pTab->aCol[ii].colFlags & COLFLAG_STORED ){
|
||||
zP4[jj] = SQLITE_AFF_NONE;
|
||||
}
|
||||
jj++;
|
||||
}
|
||||
if( pTab->aCol[ii].colFlags & COLFLAG_STORED ){
|
||||
zP4[jj] = SQLITE_AFF_NONE;
|
||||
}
|
||||
jj++;
|
||||
}else if( pOp->opcode==OP_TypeCheck ){
|
||||
/* If an OP_TypeCheck was generated because the table is STRICT,
|
||||
** then set the P3 operand to indicate that generated columns should
|
||||
** not be checked */
|
||||
pOp->p3 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,7 +353,7 @@ void sqlite3ComputeGeneratedColumns(
|
|||
int x;
|
||||
pCol->colFlags |= COLFLAG_BUSY;
|
||||
w.eCode = 0;
|
||||
sqlite3WalkExpr(&w, pCol->pDflt);
|
||||
sqlite3WalkExpr(&w, sqlite3ColumnExpr(pTab, pCol));
|
||||
pCol->colFlags &= ~COLFLAG_BUSY;
|
||||
if( w.eCode & COLFLAG_NOTAVAIL ){
|
||||
pRedo = pCol;
|
||||
|
@ -303,13 +362,13 @@ void sqlite3ComputeGeneratedColumns(
|
|||
eProgress = 1;
|
||||
assert( pCol->colFlags & COLFLAG_GENERATED );
|
||||
x = sqlite3TableColumnToStorage(pTab, i) + iRegStore;
|
||||
sqlite3ExprCodeGeneratedColumn(pParse, pCol, x);
|
||||
sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, x);
|
||||
pCol->colFlags &= ~COLFLAG_NOTAVAIL;
|
||||
}
|
||||
}
|
||||
}while( pRedo && eProgress );
|
||||
if( pRedo ){
|
||||
sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pRedo->zName);
|
||||
sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pRedo->zCnName);
|
||||
}
|
||||
pParse->iSelfTab = 0;
|
||||
}
|
||||
|
@ -359,7 +418,7 @@ static int autoIncBegin(
|
|||
** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */
|
||||
if( pSeqTab==0
|
||||
|| !HasRowid(pSeqTab)
|
||||
|| IsVirtual(pSeqTab)
|
||||
|| NEVER(IsVirtual(pSeqTab))
|
||||
|| pSeqTab->nCol!=2
|
||||
){
|
||||
pParse->nErr++;
|
||||
|
@ -668,9 +727,11 @@ void sqlite3Insert(
|
|||
#endif
|
||||
|
||||
db = pParse->db;
|
||||
if( pParse->nErr || db->mallocFailed ){
|
||||
assert( db->pParse==pParse );
|
||||
if( pParse->nErr ){
|
||||
goto insert_cleanup;
|
||||
}
|
||||
assert( db->mallocFailed==0 );
|
||||
dest.iSDParm = 0; /* Suppress a harmless compiler warning */
|
||||
|
||||
/* If the Select object is really just a simple VALUES() list with a
|
||||
|
@ -704,7 +765,7 @@ void sqlite3Insert(
|
|||
*/
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask);
|
||||
isView = pTab->pSelect!=0;
|
||||
isView = IsView(pTab);
|
||||
#else
|
||||
# define pTrigger 0
|
||||
# define tmask 0
|
||||
|
@ -716,6 +777,14 @@ void sqlite3Insert(
|
|||
#endif
|
||||
assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) );
|
||||
|
||||
#if TREETRACE_ENABLED
|
||||
if( sqlite3TreeTrace & 0x10000 ){
|
||||
sqlite3TreeViewLine(0, "In sqlite3Insert() at %s:%d", __FILE__, __LINE__);
|
||||
sqlite3TreeViewInsert(pParse->pWith, pTabList, pColumn, pSelect, pList,
|
||||
onError, pUpsert, pTrigger);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If pTab is really a view, make sure it has been initialized.
|
||||
** ViewGetColumnNames() is a no-op if pTab is not a view.
|
||||
*/
|
||||
|
@ -746,7 +815,11 @@ void sqlite3Insert(
|
|||
**
|
||||
** This is the 2nd template.
|
||||
*/
|
||||
if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){
|
||||
if( pColumn==0
|
||||
&& pSelect!=0
|
||||
&& pTrigger==0
|
||||
&& xferOptimization(pParse, pTab, pSelect, onError, iDb)
|
||||
){
|
||||
assert( !pTrigger );
|
||||
assert( pList==0 );
|
||||
goto insert_end;
|
||||
|
@ -790,13 +863,15 @@ void sqlite3Insert(
|
|||
*/
|
||||
bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0;
|
||||
if( pColumn ){
|
||||
assert( pColumn->eU4!=EU4_EXPR );
|
||||
pColumn->eU4 = EU4_IDX;
|
||||
for(i=0; i<pColumn->nId; i++){
|
||||
pColumn->a[i].idx = -1;
|
||||
pColumn->a[i].u4.idx = -1;
|
||||
}
|
||||
for(i=0; i<pColumn->nId; i++){
|
||||
for(j=0; j<pTab->nCol; j++){
|
||||
if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){
|
||||
pColumn->a[i].idx = j;
|
||||
if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zCnName)==0 ){
|
||||
pColumn->a[i].u4.idx = j;
|
||||
if( i!=j ) bIdListInOrder = 0;
|
||||
if( j==pTab->iPKey ){
|
||||
ipkColumn = i; assert( !withoutRowid );
|
||||
|
@ -805,7 +880,7 @@ void sqlite3Insert(
|
|||
if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){
|
||||
sqlite3ErrorMsg(pParse,
|
||||
"cannot INSERT into generated column \"%s\"",
|
||||
pTab->aCol[j].zName);
|
||||
pTab->aCol[j].zCnName);
|
||||
goto insert_cleanup;
|
||||
}
|
||||
#endif
|
||||
|
@ -818,7 +893,7 @@ void sqlite3Insert(
|
|||
bIdListInOrder = 0;
|
||||
}else{
|
||||
sqlite3ErrorMsg(pParse, "table %S has no column named %s",
|
||||
pTabList, 0, pColumn->a[i].zName);
|
||||
pTabList->a, pColumn->a[i].zName);
|
||||
pParse->checkSchema = 1;
|
||||
goto insert_cleanup;
|
||||
}
|
||||
|
@ -846,7 +921,9 @@ void sqlite3Insert(
|
|||
dest.nSdst = pTab->nCol;
|
||||
rc = sqlite3Select(pParse, pSelect, &dest);
|
||||
regFromSelect = dest.iSdst;
|
||||
if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup;
|
||||
assert( db->pParse==pParse );
|
||||
if( rc || pParse->nErr ) goto insert_cleanup;
|
||||
assert( db->mallocFailed==0 );
|
||||
sqlite3VdbeEndCoroutine(v, regYield);
|
||||
sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */
|
||||
assert( pSelect->pEList );
|
||||
|
@ -946,7 +1023,7 @@ void sqlite3Insert(
|
|||
if( nColumn!=(pTab->nCol-nHidden) ){
|
||||
sqlite3ErrorMsg(pParse,
|
||||
"table %S has %d columns but %d values were supplied",
|
||||
pTabList, 0, pTab->nCol-nHidden, nColumn);
|
||||
pTabList->a, pTab->nCol-nHidden, nColumn);
|
||||
goto insert_cleanup;
|
||||
}
|
||||
}
|
||||
|
@ -990,7 +1067,7 @@ void sqlite3Insert(
|
|||
pTab->zName);
|
||||
goto insert_cleanup;
|
||||
}
|
||||
if( pTab->pSelect ){
|
||||
if( IsView(pTab) ){
|
||||
sqlite3ErrorMsg(pParse, "cannot UPSERT a view");
|
||||
goto insert_cleanup;
|
||||
}
|
||||
|
@ -1089,22 +1166,29 @@ void sqlite3Insert(
|
|||
}else if( pColumn==0 ){
|
||||
/* Hidden columns that are not explicitly named in the INSERT
|
||||
** get there default value */
|
||||
sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
|
||||
sqlite3ExprCodeFactorable(pParse,
|
||||
sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
|
||||
iRegStore);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( pColumn ){
|
||||
for(j=0; j<pColumn->nId && pColumn->a[j].idx!=i; j++){}
|
||||
assert( pColumn->eU4==EU4_IDX );
|
||||
for(j=0; j<pColumn->nId && pColumn->a[j].u4.idx!=i; j++){}
|
||||
if( j>=pColumn->nId ){
|
||||
/* A column not named in the insert column list gets its
|
||||
** default value */
|
||||
sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
|
||||
sqlite3ExprCodeFactorable(pParse,
|
||||
sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
|
||||
iRegStore);
|
||||
continue;
|
||||
}
|
||||
k = j;
|
||||
}else if( nColumn==0 ){
|
||||
/* This is INSERT INTO ... DEFAULT VALUES. Load the default value. */
|
||||
sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
|
||||
sqlite3ExprCodeFactorable(pParse,
|
||||
sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
|
||||
iRegStore);
|
||||
continue;
|
||||
}else{
|
||||
k = i - nHidden;
|
||||
|
@ -1117,7 +1201,12 @@ void sqlite3Insert(
|
|||
sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+k, iRegStore);
|
||||
}
|
||||
}else{
|
||||
sqlite3ExprCode(pParse, pList->a[k].pExpr, iRegStore);
|
||||
Expr *pX = pList->a[k].pExpr;
|
||||
int y = sqlite3ExprCodeTarget(pParse, pX, iRegStore);
|
||||
if( y!=iRegStore ){
|
||||
sqlite3VdbeAddOp2(v,
|
||||
ExprHasProperty(pX, EP_Subquery) ? OP_Copy : OP_SCopy, y, iRegStore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1249,12 +1338,14 @@ void sqlite3Insert(
|
|||
}else
|
||||
#endif
|
||||
{
|
||||
int isReplace; /* Set to true if constraints may cause a replace */
|
||||
int isReplace = 0;/* Set to true if constraints may cause a replace */
|
||||
int bUseSeek; /* True to use OPFLAG_SEEKRESULT */
|
||||
sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
|
||||
regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert
|
||||
);
|
||||
sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0);
|
||||
if( db->flags & SQLITE_ForeignKeys ){
|
||||
sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0);
|
||||
}
|
||||
|
||||
/* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE
|
||||
** constraints or (b) there are no triggers and this table is not a
|
||||
|
@ -1269,6 +1360,13 @@ void sqlite3Insert(
|
|||
regIns, aRegIdx, 0, appendFlag, bUseSeek
|
||||
);
|
||||
}
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
}else if( pParse->bReturning ){
|
||||
/* If there is a RETURNING clause, populate the rowid register with
|
||||
** constant value -1, in case one or more of the returned expressions
|
||||
** refer to the "rowid" of the view. */
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, -1, regRowid);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Update the count of rows that are inserted
|
||||
|
@ -1322,9 +1420,7 @@ insert_end:
|
|||
** invoke the callback function.
|
||||
*/
|
||||
if( regRowCount ){
|
||||
sqlite3VdbeAddOp2(v, OP_ChngCntRow, regRowCount, 1);
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC);
|
||||
sqlite3CodeChangeCount(v, regRowCount, "rows inserted");
|
||||
}
|
||||
|
||||
insert_cleanup:
|
||||
|
@ -1333,7 +1429,7 @@ insert_cleanup:
|
|||
sqlite3UpsertDelete(db, pUpsert);
|
||||
sqlite3SelectDelete(db, pSelect);
|
||||
sqlite3IdListDelete(db, pColumn);
|
||||
sqlite3DbFree(db, aRegIdx);
|
||||
if( aRegIdx ) sqlite3DbNNFreeNN(db, aRegIdx);
|
||||
}
|
||||
|
||||
/* Make sure "isView" and other macros defined above are undefined. Otherwise
|
||||
|
@ -1612,7 +1708,7 @@ void sqlite3GenerateConstraintChecks(
|
|||
db = pParse->db;
|
||||
v = pParse->pVdbe;
|
||||
assert( v!=0 );
|
||||
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
|
||||
assert( !IsView(pTab) ); /* This table is not a VIEW */
|
||||
nCol = pTab->nCol;
|
||||
|
||||
/* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for
|
||||
|
@ -1663,7 +1759,7 @@ void sqlite3GenerateConstraintChecks(
|
|||
}
|
||||
if( onError==OE_Replace ){
|
||||
if( b2ndPass /* REPLACE becomes ABORT on the 2nd pass */
|
||||
|| pCol->pDflt==0 /* REPLACE is ABORT if no DEFAULT value */
|
||||
|| pCol->iDflt==0 /* REPLACE is ABORT if no DEFAULT value */
|
||||
){
|
||||
testcase( pCol->colFlags & COLFLAG_VIRTUAL );
|
||||
testcase( pCol->colFlags & COLFLAG_STORED );
|
||||
|
@ -1685,7 +1781,8 @@ void sqlite3GenerateConstraintChecks(
|
|||
VdbeCoverage(v);
|
||||
assert( (pCol->colFlags & COLFLAG_GENERATED)==0 );
|
||||
nSeenReplace++;
|
||||
sqlite3ExprCodeCopy(pParse, pCol->pDflt, iReg);
|
||||
sqlite3ExprCodeCopy(pParse,
|
||||
sqlite3ColumnExpr(pTab, pCol), iReg);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
break;
|
||||
}
|
||||
|
@ -1695,7 +1792,7 @@ void sqlite3GenerateConstraintChecks(
|
|||
case OE_Rollback:
|
||||
case OE_Fail: {
|
||||
char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
|
||||
pCol->zName);
|
||||
pCol->zCnName);
|
||||
sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL,
|
||||
onError, iReg);
|
||||
sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
|
||||
|
@ -1948,6 +2045,7 @@ void sqlite3GenerateConstraintChecks(
|
|||
if( onError==OE_Replace /* IPK rule is REPLACE */
|
||||
&& onError!=overrideError /* Rules for other constraints are different */
|
||||
&& pTab->pIndex /* There exist other constraints */
|
||||
&& !upsertIpkDelay /* IPK check already deferred by UPSERT */
|
||||
){
|
||||
ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1;
|
||||
VdbeComment((v, "defer IPK REPLACE until last"));
|
||||
|
@ -2113,7 +2211,7 @@ void sqlite3GenerateConstraintChecks(
|
|||
testcase( sqlite3TableColumnToStorage(pTab, iField)!=iField );
|
||||
x = sqlite3TableColumnToStorage(pTab, iField) + regNewData + 1;
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, x, regIdx+i);
|
||||
VdbeComment((v, "%s", pTab->aCol[iField].zName));
|
||||
VdbeComment((v, "%s", pTab->aCol[iField].zCnName));
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
|
||||
|
@ -2164,7 +2262,8 @@ void sqlite3GenerateConstraintChecks(
|
|||
**
|
||||
** This is not possible for ENABLE_PREUPDATE_HOOK builds, as the row
|
||||
** must be explicitly deleted in order to ensure any pre-update hook
|
||||
** is invoked. */
|
||||
** is invoked. */
|
||||
assert( IsOrdinaryTable(pTab) );
|
||||
#ifndef SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
if( (ix==0 && pIdx->pNext==0) /* Condition 3 */
|
||||
&& pPk==pIdx /* Condition 2 */
|
||||
|
@ -2172,7 +2271,7 @@ void sqlite3GenerateConstraintChecks(
|
|||
&& ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */
|
||||
0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0))
|
||||
&& ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */
|
||||
(0==pTab->pFKey && 0==sqlite3FkReferences(pTab)))
|
||||
(0==pTab->u.tab.pFKey && 0==sqlite3FkReferences(pTab)))
|
||||
){
|
||||
sqlite3VdbeResolveLabel(v, addrUniqueOk);
|
||||
continue;
|
||||
|
@ -2207,13 +2306,13 @@ void sqlite3GenerateConstraintChecks(
|
|||
x = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i);
|
||||
VdbeComment((v, "%s.%s", pTab->zName,
|
||||
pTab->aCol[pPk->aiColumn[i]].zName));
|
||||
pTab->aCol[pPk->aiColumn[i]].zCnName));
|
||||
}
|
||||
}
|
||||
if( isUpdate ){
|
||||
/* If currently processing the PRIMARY KEY of a WITHOUT ROWID
|
||||
** table, only conflict if the new PRIMARY KEY values are actually
|
||||
** different from the old.
|
||||
** different from the old. See TH3 withoutrowid04.test.
|
||||
**
|
||||
** For a UNIQUE index, only conflict if the PRIMARY KEY values
|
||||
** of the matched index row are different from the original PRIMARY
|
||||
|
@ -2271,7 +2370,8 @@ void sqlite3GenerateConstraintChecks(
|
|||
|
||||
assert( onError==OE_Replace );
|
||||
nConflictCk = sqlite3VdbeCurrentAddr(v) - addrConflictCk;
|
||||
assert( nConflictCk>0 );
|
||||
assert( nConflictCk>0 || db->mallocFailed );
|
||||
testcase( nConflictCk<=0 );
|
||||
testcase( nConflictCk>1 );
|
||||
if( regTrigCnt ){
|
||||
sqlite3MultiWrite(pParse);
|
||||
|
@ -2354,6 +2454,7 @@ void sqlite3GenerateConstraintChecks(
|
|||
if( ipkTop ){
|
||||
sqlite3VdbeGoto(v, ipkTop);
|
||||
VdbeComment((v, "Do IPK REPLACE"));
|
||||
assert( ipkBottom>0 );
|
||||
sqlite3VdbeJumpHere(v, ipkBottom);
|
||||
}
|
||||
|
||||
|
@ -2406,7 +2507,7 @@ void sqlite3SetMakeRecordP5(Vdbe *v, Table *pTab){
|
|||
if( pTab->pSchema->file_format<2 ) return;
|
||||
|
||||
for(i=pTab->nCol-1; i>0; i--){
|
||||
if( pTab->aCol[i].pDflt!=0 ) break;
|
||||
if( pTab->aCol[i].iDflt!=0 ) break;
|
||||
if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break;
|
||||
}
|
||||
sqlite3VdbeChangeP5(v, i+1);
|
||||
|
@ -2471,7 +2572,7 @@ void sqlite3CompleteInsertion(
|
|||
|
||||
v = pParse->pVdbe;
|
||||
assert( v!=0 );
|
||||
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
|
||||
assert( !IsView(pTab) ); /* This table is not a VIEW */
|
||||
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
||||
/* All REPLACE indexes are at the end of the list */
|
||||
assert( pIdx->onError!=OE_Replace
|
||||
|
@ -2484,7 +2585,6 @@ void sqlite3CompleteInsertion(
|
|||
}
|
||||
pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0);
|
||||
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
|
||||
assert( pParse->nested==0 );
|
||||
pik_flags |= OPFLAG_NCHANGE;
|
||||
pik_flags |= (update_flags & OPFLAG_SAVEPOSITION);
|
||||
if( update_flags==0 ){
|
||||
|
@ -2557,8 +2657,9 @@ int sqlite3OpenTableAndIndices(
|
|||
assert( op==OP_OpenWrite || p5==0 );
|
||||
if( IsVirtual(pTab) ){
|
||||
/* This routine is a no-op for virtual tables. Leave the output
|
||||
** variables *piDataCur and *piIdxCur uninitialized so that valgrind
|
||||
** can detect if they are used by mistake in the caller. */
|
||||
** variables *piDataCur and *piIdxCur set to illegal cursor numbers
|
||||
** for improved error detection. */
|
||||
*piDataCur = *piIdxCur = -999;
|
||||
return 0;
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
||||
|
@ -2699,18 +2800,13 @@ static int xferOptimization(
|
|||
int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */
|
||||
int regData, regRowid; /* Registers holding data and rowid */
|
||||
|
||||
if( pSelect==0 ){
|
||||
return 0; /* Must be of the form INSERT INTO ... SELECT ... */
|
||||
}
|
||||
assert( pSelect!=0 );
|
||||
if( pParse->pWith || pSelect->pWith ){
|
||||
/* Do not attempt to process this query if there are an WITH clauses
|
||||
** attached to it. Proceeding may generate a false "no such table: xxx"
|
||||
** error if pSelect reads from a CTE named "xxx". */
|
||||
return 0;
|
||||
}
|
||||
if( sqlite3TriggerList(pParse, pDest) ){
|
||||
return 0; /* tab1 must not have triggers */
|
||||
}
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
if( IsVirtual(pDest) ){
|
||||
return 0; /* tab1 must not be a virtual table */
|
||||
|
@ -2773,13 +2869,8 @@ static int xferOptimization(
|
|||
if( HasRowid(pDest)!=HasRowid(pSrc) ){
|
||||
return 0; /* source and destination must both be WITHOUT ROWID or not */
|
||||
}
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
if( IsVirtual(pSrc) ){
|
||||
return 0; /* tab2 must not be a virtual table */
|
||||
}
|
||||
#endif
|
||||
if( pSrc->pSelect ){
|
||||
return 0; /* tab2 may not be a view */
|
||||
if( !IsOrdinaryTable(pSrc) ){
|
||||
return 0; /* tab2 may not be a view or virtual table */
|
||||
}
|
||||
if( pDest->nCol!=pSrc->nCol ){
|
||||
return 0; /* Number of columns must be the same in tab1 and tab2 */
|
||||
|
@ -2787,6 +2878,9 @@ static int xferOptimization(
|
|||
if( pDest->iPKey!=pSrc->iPKey ){
|
||||
return 0; /* Both tables must have the same INTEGER PRIMARY KEY */
|
||||
}
|
||||
if( (pDest->tabFlags & TF_Strict)!=0 && (pSrc->tabFlags & TF_Strict)==0 ){
|
||||
return 0; /* Cannot feed from a non-strict into a strict table */
|
||||
}
|
||||
for(i=0; i<pDest->nCol; i++){
|
||||
Column *pDestCol = &pDest->aCol[i];
|
||||
Column *pSrcCol = &pSrc->aCol[i];
|
||||
|
@ -2823,7 +2917,9 @@ static int xferOptimization(
|
|||
** This requirement could be relaxed for VIRTUAL columns, I suppose.
|
||||
*/
|
||||
if( (pDestCol->colFlags & COLFLAG_GENERATED)!=0 ){
|
||||
if( sqlite3ExprCompare(0, pSrcCol->pDflt, pDestCol->pDflt, -1)!=0 ){
|
||||
if( sqlite3ExprCompare(0,
|
||||
sqlite3ColumnExpr(pSrc, pSrcCol),
|
||||
sqlite3ColumnExpr(pDest, pDestCol), -1)!=0 ){
|
||||
testcase( pDestCol->colFlags & COLFLAG_VIRTUAL );
|
||||
testcase( pDestCol->colFlags & COLFLAG_STORED );
|
||||
return 0; /* Different generator expressions */
|
||||
|
@ -2833,7 +2929,8 @@ static int xferOptimization(
|
|||
if( pDestCol->affinity!=pSrcCol->affinity ){
|
||||
return 0; /* Affinity must be the same on all columns */
|
||||
}
|
||||
if( sqlite3_stricmp(pDestCol->zColl, pSrcCol->zColl)!=0 ){
|
||||
if( sqlite3_stricmp(sqlite3ColumnColl(pDestCol),
|
||||
sqlite3ColumnColl(pSrcCol))!=0 ){
|
||||
return 0; /* Collating sequence must be the same on all columns */
|
||||
}
|
||||
if( pDestCol->notNull && !pSrcCol->notNull ){
|
||||
|
@ -2841,11 +2938,15 @@ static int xferOptimization(
|
|||
}
|
||||
/* Default values for second and subsequent columns need to match. */
|
||||
if( (pDestCol->colFlags & COLFLAG_GENERATED)==0 && i>0 ){
|
||||
assert( pDestCol->pDflt==0 || pDestCol->pDflt->op==TK_SPAN );
|
||||
assert( pSrcCol->pDflt==0 || pSrcCol->pDflt->op==TK_SPAN );
|
||||
if( (pDestCol->pDflt==0)!=(pSrcCol->pDflt==0)
|
||||
|| (pDestCol->pDflt && strcmp(pDestCol->pDflt->u.zToken,
|
||||
pSrcCol->pDflt->u.zToken)!=0)
|
||||
Expr *pDestExpr = sqlite3ColumnExpr(pDest, pDestCol);
|
||||
Expr *pSrcExpr = sqlite3ColumnExpr(pSrc, pSrcCol);
|
||||
assert( pDestExpr==0 || pDestExpr->op==TK_SPAN );
|
||||
assert( pDestExpr==0 || !ExprHasProperty(pDestExpr, EP_IntValue) );
|
||||
assert( pSrcExpr==0 || pSrcExpr->op==TK_SPAN );
|
||||
assert( pSrcExpr==0 || !ExprHasProperty(pSrcExpr, EP_IntValue) );
|
||||
if( (pDestExpr==0)!=(pSrcExpr==0)
|
||||
|| (pDestExpr!=0 && strcmp(pDestExpr->u.zToken,
|
||||
pSrcExpr->u.zToken)!=0)
|
||||
){
|
||||
return 0; /* Default values must be the same for all columns */
|
||||
}
|
||||
|
@ -2882,7 +2983,8 @@ static int xferOptimization(
|
|||
** the extra complication to make this rule less restrictive is probably
|
||||
** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
|
||||
*/
|
||||
if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){
|
||||
assert( IsOrdinaryTable(pDest) );
|
||||
if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->u.tab.pFKey!=0 ){
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
62
third_party/sqlite3/inttypes.inc
vendored
62
third_party/sqlite3/inttypes.inc
vendored
|
@ -1,62 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_THIRD_PARTY_SQLITE3_INTTYPES_H_
|
||||
#define COSMOPOLITAN_THIRD_PARTY_SQLITE3_INTTYPES_H_
|
||||
#include "third_party/sqlite3/sqlite3.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/*
|
||||
** Integers of known sizes. These typedefs might change for architectures
|
||||
** where the sizes very. Preprocessor macros are available so that the
|
||||
** types can be conveniently redefined at compile-type. Like this:
|
||||
**
|
||||
** cc '-DUINTPTR_TYPE=long long int' ...
|
||||
*/
|
||||
#ifndef UINT32_TYPE
|
||||
#ifdef HAVE_UINT32_T
|
||||
#define UINT32_TYPE uint32_t
|
||||
#else
|
||||
#define UINT32_TYPE unsigned int
|
||||
#endif
|
||||
#endif
|
||||
#ifndef UINT16_TYPE
|
||||
#ifdef HAVE_UINT16_T
|
||||
#define UINT16_TYPE uint16_t
|
||||
#else
|
||||
#define UINT16_TYPE unsigned short int
|
||||
#endif
|
||||
#endif
|
||||
#ifndef INT16_TYPE
|
||||
#ifdef HAVE_INT16_T
|
||||
#define INT16_TYPE int16_t
|
||||
#else
|
||||
#define INT16_TYPE short int
|
||||
#endif
|
||||
#endif
|
||||
#ifndef UINT8_TYPE
|
||||
#ifdef HAVE_UINT8_T
|
||||
#define UINT8_TYPE uint8_t
|
||||
#else
|
||||
#define UINT8_TYPE unsigned char
|
||||
#endif
|
||||
#endif
|
||||
#ifndef INT8_TYPE
|
||||
#ifdef HAVE_INT8_T
|
||||
#define INT8_TYPE int8_t
|
||||
#else
|
||||
#define INT8_TYPE signed char
|
||||
#endif
|
||||
#endif
|
||||
#ifndef LONGDOUBLE_TYPE
|
||||
#define LONGDOUBLE_TYPE long double
|
||||
#endif
|
||||
typedef sqlite_int64 i64; /* 8-byte signed integer */
|
||||
typedef sqlite_uint64 u64; /* 8-byte unsigned integer */
|
||||
typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
|
||||
typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
|
||||
typedef INT16_TYPE i16; /* 2-byte signed integer */
|
||||
typedef UINT8_TYPE u8; /* 1-byte unsigned integer */
|
||||
typedef INT8_TYPE i8; /* 1-byte signed integer */
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_THIRD_PARTY_SQLITE3_INTTYPES_H_ */
|
File diff suppressed because it is too large
Load diff
1
third_party/sqlite3/json.shell.c
vendored
Normal file
1
third_party/sqlite3/json.shell.c
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
#include "third_party/sqlite3/json.c"
|
1
third_party/sqlite3/json1.shell.c
vendored
1
third_party/sqlite3/json1.shell.c
vendored
|
@ -1 +0,0 @@
|
|||
#include "third_party/sqlite3/json1.c"
|
3
third_party/sqlite3/legacy.c
vendored
3
third_party/sqlite3/legacy.c
vendored
|
@ -14,9 +14,8 @@
|
|||
** other files are for internal use by SQLite and should not be
|
||||
** accessed by users of the library.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/*
|
||||
** Execute SQL code. Return one of the SQLITE_ success/failure
|
||||
|
|
72
third_party/sqlite3/loadext.c
vendored
72
third_party/sqlite3/loadext.c
vendored
|
@ -12,13 +12,12 @@
|
|||
** This file contains code used to dynamically load extensions into
|
||||
** the SQLite library.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
#ifndef SQLITE_CORE
|
||||
#define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */
|
||||
#endif
|
||||
#include "third_party/sqlite3/sqlite3ext.h"
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
||||
/*
|
||||
|
@ -481,6 +480,37 @@ static const sqlite3_api_routines sqlite3Apis = {
|
|||
sqlite3_database_file_object,
|
||||
/* Version 3.34.0 and later */
|
||||
sqlite3_txn_state,
|
||||
/* Version 3.36.1 and later */
|
||||
sqlite3_changes64,
|
||||
sqlite3_total_changes64,
|
||||
/* Version 3.37.0 and later */
|
||||
sqlite3_autovacuum_pages,
|
||||
/* Version 3.38.0 and later */
|
||||
sqlite3_error_offset,
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
sqlite3_vtab_rhs_value,
|
||||
sqlite3_vtab_distinct,
|
||||
sqlite3_vtab_in,
|
||||
sqlite3_vtab_in_first,
|
||||
sqlite3_vtab_in_next,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
#endif
|
||||
/* Version 3.39.0 and later */
|
||||
#ifndef SQLITE_OMIT_DESERIALIZE
|
||||
sqlite3_deserialize,
|
||||
sqlite3_serialize,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif
|
||||
sqlite3_db_name,
|
||||
/* Version 3.40.0 and later */
|
||||
sqlite3_value_type
|
||||
};
|
||||
|
||||
/* True if x is the directory separator character
|
||||
|
@ -516,7 +546,7 @@ static int sqlite3LoadExtension(
|
|||
const char *zEntry;
|
||||
char *zAltEntry = 0;
|
||||
void **aHandle;
|
||||
u64 nMsg = 300 + sqlite3Strlen30(zFile);
|
||||
u64 nMsg = strlen(zFile);
|
||||
int ii;
|
||||
int rc;
|
||||
|
||||
|
@ -550,6 +580,12 @@ static int sqlite3LoadExtension(
|
|||
|
||||
zEntry = zProc ? zProc : "sqlite3_extension_init";
|
||||
|
||||
/* tag-20210611-1. Some dlopen() implementations will segfault if given
|
||||
** an oversize filename. Most filesystems have a pathname limit of 4K,
|
||||
** so limit the extension filename length to about twice that.
|
||||
** https://sqlite.org/forum/forumpost/08a0d6d9bf */
|
||||
if( nMsg>SQLITE_MAX_PATHLEN ) goto extension_not_found;
|
||||
|
||||
handle = sqlite3OsDlOpen(pVfs, zFile);
|
||||
#if SQLITE_OS_UNIX || SQLITE_OS_WIN
|
||||
for(ii=0; ii<ArraySize(azEndings) && handle==0; ii++){
|
||||
|
@ -559,17 +595,7 @@ static int sqlite3LoadExtension(
|
|||
sqlite3_free(zAltFile);
|
||||
}
|
||||
#endif
|
||||
if( handle==0 ){
|
||||
if( pzErrMsg ){
|
||||
*pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg);
|
||||
if( zErrmsg ){
|
||||
sqlite3_snprintf(nMsg, zErrmsg,
|
||||
"unable to open shared library [%s]", zFile);
|
||||
sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
|
||||
}
|
||||
}
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
if( handle==0 ) goto extension_not_found;
|
||||
xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry);
|
||||
|
||||
/* If no entry point was specified and the default legacy
|
||||
|
@ -606,10 +632,11 @@ static int sqlite3LoadExtension(
|
|||
}
|
||||
if( xInit==0 ){
|
||||
if( pzErrMsg ){
|
||||
nMsg += sqlite3Strlen30(zEntry);
|
||||
nMsg += strlen(zEntry) + 300;
|
||||
*pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg);
|
||||
if( zErrmsg ){
|
||||
sqlite3_snprintf(nMsg, zErrmsg,
|
||||
assert( nMsg<0x7fffffff ); /* zErrmsg would be NULL if not so */
|
||||
sqlite3_snprintf((int)nMsg, zErrmsg,
|
||||
"no entry point [%s] in shared library [%s]", zEntry, zFile);
|
||||
sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
|
||||
}
|
||||
|
@ -643,6 +670,19 @@ static int sqlite3LoadExtension(
|
|||
|
||||
db->aExtension[db->nExtension++] = handle;
|
||||
return SQLITE_OK;
|
||||
|
||||
extension_not_found:
|
||||
if( pzErrMsg ){
|
||||
nMsg += 300;
|
||||
*pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg);
|
||||
if( zErrmsg ){
|
||||
assert( nMsg<0x7fffffff ); /* zErrmsg would be NULL if not so */
|
||||
sqlite3_snprintf((int)nMsg, zErrmsg,
|
||||
"unable to open shared library [%.*s]", SQLITE_MAX_PATHLEN, zFile);
|
||||
sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
|
||||
}
|
||||
}
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
int sqlite3_load_extension(
|
||||
sqlite3 *db, /* Load the extension into this database connection */
|
||||
|
|
372
third_party/sqlite3/main.c
vendored
372
third_party/sqlite3/main.c
vendored
|
@ -14,17 +14,16 @@
|
|||
** other files are for internal use by SQLite and should not be
|
||||
** accessed by users of the library.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
#ifdef SQLITE_ENABLE_FTS3
|
||||
#include "third_party/sqlite3/fts3.inc"
|
||||
# include "third_party/sqlite3/fts3.h"
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_RTREE
|
||||
#include "third_party/sqlite3/rtree.inc"
|
||||
# include "third_party/sqlite3/rtree.h"
|
||||
#endif
|
||||
#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS)
|
||||
#include "third_party/sqlite3/sqliteicu.inc"
|
||||
# include "third_party/sqlite3/sqliteicu.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -51,9 +50,6 @@ int sqlite3Fts2Init(sqlite3*);
|
|||
#ifdef SQLITE_ENABLE_FTS5
|
||||
int sqlite3Fts5Init(sqlite3*);
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_JSON1
|
||||
int sqlite3Json1Init(sqlite3*);
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_STMTVTAB
|
||||
int sqlite3StmtVtabInit(sqlite3*);
|
||||
#endif
|
||||
|
@ -88,8 +84,8 @@ static int (*const sqlite3BuiltinExtensions[])(sqlite3*) = {
|
|||
sqlite3DbstatRegister,
|
||||
#endif
|
||||
sqlite3TestExtInit,
|
||||
#ifdef SQLITE_ENABLE_JSON1
|
||||
sqlite3Json1Init,
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON)
|
||||
sqlite3JsonTableFunctions,
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_STMTVTAB
|
||||
sqlite3StmtVtabInit,
|
||||
|
@ -306,7 +302,7 @@ int sqlite3_initialize(void){
|
|||
sqlite3GlobalConfig.isPCacheInit = 1;
|
||||
rc = sqlite3OsInit();
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_DESERIALIZE
|
||||
#ifndef SQLITE_OMIT_DESERIALIZE
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3MemdbInit();
|
||||
}
|
||||
|
@ -721,12 +717,12 @@ int sqlite3_config(int op, ...){
|
|||
}
|
||||
#endif /* SQLITE_ENABLE_SORTER_REFERENCES */
|
||||
|
||||
#ifdef SQLITE_ENABLE_DESERIALIZE
|
||||
#ifndef SQLITE_OMIT_DESERIALIZE
|
||||
case SQLITE_CONFIG_MEMDB_MAXSIZE: {
|
||||
sqlite3GlobalConfig.mxMemdbSize = va_arg(ap, sqlite3_int64);
|
||||
break;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_DESERIALIZE */
|
||||
#endif /* SQLITE_OMIT_DESERIALIZE */
|
||||
|
||||
default: {
|
||||
rc = SQLITE_ERROR;
|
||||
|
@ -828,18 +824,19 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
|
|||
db->lookaside.bMalloced = pBuf==0 ?1:0;
|
||||
db->lookaside.nSlot = nBig+nSm;
|
||||
}else{
|
||||
db->lookaside.pStart = db;
|
||||
db->lookaside.pStart = 0;
|
||||
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
||||
db->lookaside.pSmallInit = 0;
|
||||
db->lookaside.pSmallFree = 0;
|
||||
db->lookaside.pMiddle = db;
|
||||
db->lookaside.pMiddle = 0;
|
||||
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
|
||||
db->lookaside.pEnd = db;
|
||||
db->lookaside.pEnd = 0;
|
||||
db->lookaside.bDisable = 1;
|
||||
db->lookaside.sz = 0;
|
||||
db->lookaside.bMalloced = 0;
|
||||
db->lookaside.nSlot = 0;
|
||||
}
|
||||
db->lookaside.pTrueEnd = db->lookaside.pEnd;
|
||||
assert( sqlite3LookasideUsed(db,0)==0 );
|
||||
#endif /* SQLITE_OMIT_LOOKASIDE */
|
||||
return SQLITE_OK;
|
||||
|
@ -918,6 +915,7 @@ int sqlite3_db_cacheflush(sqlite3 *db){
|
|||
int sqlite3_db_config(sqlite3 *db, int op, ...){
|
||||
va_list ap;
|
||||
int rc;
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
va_start(ap, op);
|
||||
switch( op ){
|
||||
case SQLITE_DBCONFIG_MAINDBNAME: {
|
||||
|
@ -983,6 +981,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
|
|||
}
|
||||
}
|
||||
va_end(ap);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1087,7 +1086,7 @@ void sqlite3_set_last_insert_rowid(sqlite3 *db, sqlite3_int64 iRowid){
|
|||
/*
|
||||
** Return the number of changes in the most recent call to sqlite3_exec().
|
||||
*/
|
||||
int sqlite3_changes(sqlite3 *db){
|
||||
sqlite3_int64 sqlite3_changes64(sqlite3 *db){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
|
@ -1096,11 +1095,14 @@ int sqlite3_changes(sqlite3 *db){
|
|||
#endif
|
||||
return db->nChange;
|
||||
}
|
||||
int sqlite3_changes(sqlite3 *db){
|
||||
return (int)sqlite3_changes64(db);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the number of changes since the database handle was opened.
|
||||
*/
|
||||
int sqlite3_total_changes(sqlite3 *db){
|
||||
sqlite3_int64 sqlite3_total_changes64(sqlite3 *db){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
|
@ -1109,6 +1111,9 @@ int sqlite3_total_changes(sqlite3 *db){
|
|||
#endif
|
||||
return db->nTotalChange;
|
||||
}
|
||||
int sqlite3_total_changes(sqlite3 *db){
|
||||
return (int)sqlite3_total_changes64(db);
|
||||
}
|
||||
|
||||
/*
|
||||
** Close all open savepoints. This function only manipulates fields of the
|
||||
|
@ -1133,7 +1138,9 @@ void sqlite3CloseSavepoints(sqlite3 *db){
|
|||
** with SQLITE_ANY as the encoding.
|
||||
*/
|
||||
static void functionDestroy(sqlite3 *db, FuncDef *p){
|
||||
FuncDestructor *pDestructor = p->u.pDestructor;
|
||||
FuncDestructor *pDestructor;
|
||||
assert( (p->funcFlags & SQLITE_FUNC_BUILTIN)==0 );
|
||||
pDestructor = p->u.pDestructor;
|
||||
if( pDestructor ){
|
||||
pDestructor->nRef--;
|
||||
if( pDestructor->nRef==0 ){
|
||||
|
@ -1237,7 +1244,7 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){
|
|||
|
||||
/* Convert the connection into a zombie and then close it.
|
||||
*/
|
||||
db->magic = SQLITE_MAGIC_ZOMBIE;
|
||||
db->eOpenState = SQLITE_STATE_ZOMBIE;
|
||||
sqlite3LeaveMutexAndCloseZombie(db);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
@ -1275,7 +1282,7 @@ int sqlite3_txn_state(sqlite3 *db, const char *zSchema){
|
|||
/*
|
||||
** Two variations on the public interface for closing a database
|
||||
** connection. The sqlite3_close() version returns SQLITE_BUSY and
|
||||
** leaves the connection option if there are unfinalized prepared
|
||||
** leaves the connection open if there are unfinalized prepared
|
||||
** statements or unfinished sqlite3_backups. The sqlite3_close_v2()
|
||||
** version forces the connection to become a zombie if there are
|
||||
** unclosed resources, and arranges for deallocation when the last
|
||||
|
@ -1301,7 +1308,7 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
|
|||
** or if the connection has not yet been closed by sqlite3_close_v2(),
|
||||
** then just leave the mutex and return.
|
||||
*/
|
||||
if( db->magic!=SQLITE_MAGIC_ZOMBIE || connectionIsBusy(db) ){
|
||||
if( db->eOpenState!=SQLITE_STATE_ZOMBIE || connectionIsBusy(db) ){
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return;
|
||||
}
|
||||
|
@ -1387,7 +1394,7 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
|
|||
sqlite3_free(db->auth.zAuthPW);
|
||||
#endif
|
||||
|
||||
db->magic = SQLITE_MAGIC_ERROR;
|
||||
db->eOpenState = SQLITE_STATE_ERROR;
|
||||
|
||||
/* The temp-database schema is allocated differently from the other schema
|
||||
** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
|
||||
|
@ -1396,8 +1403,11 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
|
|||
** structure?
|
||||
*/
|
||||
sqlite3DbFree(db, db->aDb[1].pSchema);
|
||||
if( db->xAutovacDestr ){
|
||||
db->xAutovacDestr(db->pAutovacPagesArg);
|
||||
}
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
db->magic = SQLITE_MAGIC_CLOSED;
|
||||
db->eOpenState = SQLITE_STATE_CLOSED;
|
||||
sqlite3_mutex_free(db->mutex);
|
||||
assert( sqlite3LookasideUsed(db,0)==0 );
|
||||
if( db->lookaside.bMalloced ){
|
||||
|
@ -1450,7 +1460,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
|
|||
/* Any deferred constraint violations have now been resolved. */
|
||||
db->nDeferredCons = 0;
|
||||
db->nDeferredImmCons = 0;
|
||||
db->flags &= ~(u64)SQLITE_DeferFKs;
|
||||
db->flags &= ~(u64)(SQLITE_DeferFKs|SQLITE_CorruptRdOnly);
|
||||
|
||||
/* If one has been configured, invoke the rollback-hook callback */
|
||||
if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
|
||||
|
@ -1785,7 +1795,7 @@ int sqlite3_busy_timeout(sqlite3 *db, int ms){
|
|||
*/
|
||||
void sqlite3_interrupt(sqlite3 *db){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) && (db==0 || db->magic!=SQLITE_MAGIC_ZOMBIE) ){
|
||||
if( !sqlite3SafetyCheckOk(db) && (db==0 || db->eOpenState!=SQLITE_STATE_ZOMBIE) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return;
|
||||
}
|
||||
|
@ -1814,7 +1824,6 @@ int sqlite3CreateFunc(
|
|||
FuncDestructor *pDestructor
|
||||
){
|
||||
FuncDef *p;
|
||||
int nName;
|
||||
int extraFlags;
|
||||
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
|
@ -1824,7 +1833,7 @@ int sqlite3CreateFunc(
|
|||
|| ((xFinal==0)!=(xStep==0)) /* Both or neither of xFinal and xStep */
|
||||
|| ((xValue==0)!=(xInverse==0)) /* Both or neither of xValue, xInverse */
|
||||
|| (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG)
|
||||
|| (255<(nName = sqlite3Strlen30( zFunctionName)))
|
||||
|| (255<sqlite3Strlen30(zFunctionName))
|
||||
){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
|
@ -1849,22 +1858,33 @@ int sqlite3CreateFunc(
|
|||
** If SQLITE_ANY is specified, add three versions of the function
|
||||
** to the hash table.
|
||||
*/
|
||||
if( enc==SQLITE_UTF16 ){
|
||||
enc = SQLITE_UTF16NATIVE;
|
||||
}else if( enc==SQLITE_ANY ){
|
||||
int rc;
|
||||
rc = sqlite3CreateFunc(db, zFunctionName, nArg,
|
||||
(SQLITE_UTF8|extraFlags)^SQLITE_FUNC_UNSAFE,
|
||||
pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
|
||||
if( rc==SQLITE_OK ){
|
||||
switch( enc ){
|
||||
case SQLITE_UTF16:
|
||||
enc = SQLITE_UTF16NATIVE;
|
||||
break;
|
||||
case SQLITE_ANY: {
|
||||
int rc;
|
||||
rc = sqlite3CreateFunc(db, zFunctionName, nArg,
|
||||
(SQLITE_UTF16LE|extraFlags)^SQLITE_FUNC_UNSAFE,
|
||||
(SQLITE_UTF8|extraFlags)^SQLITE_FUNC_UNSAFE,
|
||||
pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3CreateFunc(db, zFunctionName, nArg,
|
||||
(SQLITE_UTF16LE|extraFlags)^SQLITE_FUNC_UNSAFE,
|
||||
pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
enc = SQLITE_UTF16BE;
|
||||
break;
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
enc = SQLITE_UTF16BE;
|
||||
case SQLITE_UTF8:
|
||||
case SQLITE_UTF16LE:
|
||||
case SQLITE_UTF16BE:
|
||||
break;
|
||||
default:
|
||||
enc = SQLITE_UTF8;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
enc = SQLITE_UTF8;
|
||||
|
@ -1885,6 +1905,10 @@ int sqlite3CreateFunc(
|
|||
}else{
|
||||
sqlite3ExpirePreparedStatements(db, 0);
|
||||
}
|
||||
}else if( xSFunc==0 && xFinal==0 ){
|
||||
/* Trying to delete a function that does not exist. This is a no-op.
|
||||
** https://sqlite.org/forum/forumpost/726219164b */
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 1);
|
||||
|
@ -1957,7 +1981,7 @@ static int createFunctionApi(
|
|||
xSFunc, xStep, xFinal, xValue, xInverse, pArg
|
||||
);
|
||||
if( pArg && pArg->nRef==0 ){
|
||||
assert( rc!=SQLITE_OK );
|
||||
assert( rc!=SQLITE_OK || (xStep==0 && xFinal==0) );
|
||||
xDestroy(p);
|
||||
sqlite3_free(pArg);
|
||||
}
|
||||
|
@ -2283,6 +2307,34 @@ void *sqlite3_preupdate_hook(
|
|||
}
|
||||
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
|
||||
|
||||
/*
|
||||
** Register a function to be invoked prior to each autovacuum that
|
||||
** determines the number of pages to vacuum.
|
||||
*/
|
||||
int sqlite3_autovacuum_pages(
|
||||
sqlite3 *db, /* Attach the hook to this database */
|
||||
unsigned int (*xCallback)(void*,const char*,u32,u32,u32),
|
||||
void *pArg, /* Argument to the function */
|
||||
void (*xDestructor)(void*) /* Destructor for pArg */
|
||||
){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
if( xDestructor ) xDestructor(pArg);
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
if( db->xAutovacDestr ){
|
||||
db->xAutovacDestr(db->pAutovacPagesArg);
|
||||
}
|
||||
db->xAutovacPages = xCallback;
|
||||
db->pAutovacPagesArg = pArg;
|
||||
db->xAutovacDestr = xDestructor;
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
/*
|
||||
** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint().
|
||||
|
@ -2545,6 +2597,19 @@ const char *sqlite3_errmsg(sqlite3 *db){
|
|||
return z;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the byte offset of the most recent error
|
||||
*/
|
||||
int sqlite3_error_offset(sqlite3 *db){
|
||||
int iOffset = -1;
|
||||
if( db && sqlite3SafetyCheckSickOrOk(db) && db->errCode ){
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
iOffset = db->errByteOffset;
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
}
|
||||
return iOffset;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
/*
|
||||
** Return UTF-16 encoded English language explanation of the most recent
|
||||
|
@ -2805,6 +2870,8 @@ int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
|
|||
if( newLimit>=0 ){ /* IMP: R-52476-28732 */
|
||||
if( newLimit>aHardLimit[limitId] ){
|
||||
newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */
|
||||
}else if( newLimit<1 && limitId==SQLITE_LIMIT_LENGTH ){
|
||||
newLimit = 1;
|
||||
}
|
||||
db->aLimit[limitId] = newLimit;
|
||||
}
|
||||
|
@ -3076,7 +3143,7 @@ int sqlite3ParseUri(
|
|||
*/
|
||||
static const char *uriParameter(const char *zFilename, const char *zParam){
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
while( zFilename[0] ){
|
||||
while( ALWAYS(zFilename!=0) && zFilename[0] ){
|
||||
int x = strcmp(zFilename, zParam);
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
if( x==0 ) return zFilename;
|
||||
|
@ -3136,8 +3203,8 @@ static int openDatabase(
|
|||
** dealt with in the previous code block. Besides these, the only
|
||||
** valid input flags for sqlite3_open_v2() are SQLITE_OPEN_READONLY,
|
||||
** SQLITE_OPEN_READWRITE, SQLITE_OPEN_CREATE, SQLITE_OPEN_SHAREDCACHE,
|
||||
** SQLITE_OPEN_PRIVATECACHE, and some reserved bits. Silently mask
|
||||
** off all other flags.
|
||||
** SQLITE_OPEN_PRIVATECACHE, SQLITE_OPEN_EXRESCODE, and some reserved
|
||||
** bits. Silently mask off all other flags.
|
||||
*/
|
||||
flags &= ~( SQLITE_OPEN_DELETEONCLOSE |
|
||||
SQLITE_OPEN_EXCLUSIVE |
|
||||
|
@ -3172,9 +3239,9 @@ static int openDatabase(
|
|||
}
|
||||
}
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
db->errMask = 0xff;
|
||||
db->errMask = (flags & SQLITE_OPEN_EXRESCODE)!=0 ? 0xffffffff : 0xff;
|
||||
db->nDb = 2;
|
||||
db->magic = SQLITE_MAGIC_BUSY;
|
||||
db->eOpenState = SQLITE_STATE_BUSY;
|
||||
db->aDb = db->aDbStatic;
|
||||
db->lookaside.bDisable = 1;
|
||||
db->lookaside.sz = 0;
|
||||
|
@ -3186,7 +3253,15 @@ static int openDatabase(
|
|||
db->nextAutovac = -1;
|
||||
db->szMmap = sqlite3GlobalConfig.szMmap;
|
||||
db->nextPagesize = 0;
|
||||
db->init.azInit = sqlite3StdType; /* Any array of string ptrs will do */
|
||||
#ifdef SQLITE_ENABLE_SORTER_MMAP
|
||||
/* Beginning with version 3.37.0, using the VFS xFetch() API to memory-map
|
||||
** the temporary files used to do external sorts (see code in vdbesort.c)
|
||||
** is disabled. It can still be used either by defining
|
||||
** SQLITE_ENABLE_SORTER_MMAP at compile time or by using the
|
||||
** SQLITE_TESTCTRL_SORTER_MMAP test-control at runtime. */
|
||||
db->nMaxSorterMmap = 0x7FFFFFFF;
|
||||
#endif
|
||||
db->flags |= SQLITE_ShortColNames
|
||||
| SQLITE_EnableTrigger
|
||||
| SQLITE_EnableView
|
||||
|
@ -3277,6 +3352,19 @@ static int openDatabase(
|
|||
goto opendb_out;
|
||||
}
|
||||
|
||||
#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL)
|
||||
/* Process magic filenames ":localStorage:" and ":sessionStorage:" */
|
||||
if( zFilename && zFilename[0]==':' ){
|
||||
if( strcmp(zFilename, ":localStorage:")==0 ){
|
||||
zFilename = "file:local?vfs=kvvfs";
|
||||
flags |= SQLITE_OPEN_URI;
|
||||
}else if( strcmp(zFilename, ":sessionStorage:")==0 ){
|
||||
zFilename = "file:session?vfs=kvvfs";
|
||||
flags |= SQLITE_OPEN_URI;
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL) */
|
||||
|
||||
/* Parse the filename/URI argument
|
||||
**
|
||||
** Only allow sensible combinations of bits in the flags argument.
|
||||
|
@ -3307,6 +3395,12 @@ static int openDatabase(
|
|||
sqlite3_free(zErrMsg);
|
||||
goto opendb_out;
|
||||
}
|
||||
assert( db->pVfs!=0 );
|
||||
#if SQLITE_OS_KV || defined(SQLITE_OS_KV_OPTIONAL)
|
||||
if( sqlite3_stricmp(db->pVfs->zName, "kvvfs")==0 ){
|
||||
db->temp_store = 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Open the backend database driver */
|
||||
rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0,
|
||||
|
@ -3334,7 +3428,7 @@ static int openDatabase(
|
|||
db->aDb[1].zDbSName = "temp";
|
||||
db->aDb[1].safety_level = PAGER_SYNCHRONOUS_OFF;
|
||||
|
||||
db->magic = SQLITE_MAGIC_OPEN;
|
||||
db->eOpenState = SQLITE_STATE_OPEN;
|
||||
if( db->mallocFailed ){
|
||||
goto opendb_out;
|
||||
}
|
||||
|
@ -3396,12 +3490,12 @@ opendb_out:
|
|||
sqlite3_mutex_leave(db->mutex);
|
||||
}
|
||||
rc = sqlite3_errcode(db);
|
||||
assert( db!=0 || rc==SQLITE_NOMEM );
|
||||
if( rc==SQLITE_NOMEM ){
|
||||
assert( db!=0 || (rc&0xff)==SQLITE_NOMEM );
|
||||
if( (rc&0xff)==SQLITE_NOMEM ){
|
||||
sqlite3_close(db);
|
||||
db = 0;
|
||||
}else if( rc!=SQLITE_OK ){
|
||||
db->magic = SQLITE_MAGIC_SICK;
|
||||
db->eOpenState = SQLITE_STATE_SICK;
|
||||
}
|
||||
*ppDb = db;
|
||||
#ifdef SQLITE_ENABLE_SQLLOG
|
||||
|
@ -3412,7 +3506,7 @@ opendb_out:
|
|||
}
|
||||
#endif
|
||||
sqlite3_free_filename(zOpen);
|
||||
return rc & 0xff;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3712,7 +3806,7 @@ int sqlite3_table_column_metadata(
|
|||
|
||||
/* Locate the table in question */
|
||||
pTab = sqlite3FindTable(db, zTableName, zDbName);
|
||||
if( !pTab || pTab->pSelect ){
|
||||
if( !pTab || IsView(pTab) ){
|
||||
pTab = 0;
|
||||
goto error_out;
|
||||
}
|
||||
|
@ -3723,7 +3817,7 @@ int sqlite3_table_column_metadata(
|
|||
}else{
|
||||
for(iCol=0; iCol<pTab->nCol; iCol++){
|
||||
pCol = &pTab->aCol[iCol];
|
||||
if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){
|
||||
if( 0==sqlite3StrICmp(pCol->zCnName, zColumnName) ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -3750,7 +3844,7 @@ int sqlite3_table_column_metadata(
|
|||
*/
|
||||
if( pCol ){
|
||||
zDataType = sqlite3ColumnType(pCol,0);
|
||||
zCollSeq = pCol->zColl;
|
||||
zCollSeq = sqlite3ColumnColl(pCol);
|
||||
notnull = pCol->notNull!=0;
|
||||
primarykey = (pCol->colFlags & COLFLAG_PRIMKEY)!=0;
|
||||
autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0;
|
||||
|
@ -3957,12 +4051,16 @@ int sqlite3_test_control(int op, ...){
|
|||
** sqlite3_test_control().
|
||||
*/
|
||||
case SQLITE_TESTCTRL_FAULT_INSTALL: {
|
||||
/* MSVC is picky about pulling func ptrs from va lists.
|
||||
** http://support.microsoft.com/kb/47961
|
||||
/* A bug in MSVC prevents it from understanding pointers to functions
|
||||
** types in the second argument to va_arg(). Work around the problem
|
||||
** using a typedef.
|
||||
** http://support.microsoft.com/kb/47961 <-- dead hyperlink
|
||||
** Search at http://web.archive.org/ to find the 2015-03-16 archive
|
||||
** of the link above to see the original text.
|
||||
** sqlite3GlobalConfig.xTestCallback = va_arg(ap, int(*)(int));
|
||||
*/
|
||||
typedef int(*TESTCALLBACKFUNC_t)(int);
|
||||
sqlite3GlobalConfig.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t);
|
||||
typedef int(*sqlite3FaultFuncType)(int);
|
||||
sqlite3GlobalConfig.xTestCallback = va_arg(ap, sqlite3FaultFuncType);
|
||||
rc = sqlite3FaultSim(0);
|
||||
break;
|
||||
}
|
||||
|
@ -4021,6 +4119,28 @@ int sqlite3_test_control(int op, ...){
|
|||
volatile int x = 0;
|
||||
assert( /*side-effects-ok*/ (x = va_arg(ap,int))!=0 );
|
||||
rc = x;
|
||||
#if defined(SQLITE_DEBUG)
|
||||
/* Invoke these debugging routines so that the compiler does not
|
||||
** issue "defined but not used" warnings. */
|
||||
if( x==9999 ){
|
||||
sqlite3ShowExpr(0);
|
||||
sqlite3ShowExpr(0);
|
||||
sqlite3ShowExprList(0);
|
||||
sqlite3ShowIdList(0);
|
||||
sqlite3ShowSrcList(0);
|
||||
sqlite3ShowWith(0);
|
||||
sqlite3ShowUpsert(0);
|
||||
sqlite3ShowTriggerStep(0);
|
||||
sqlite3ShowTriggerStepList(0);
|
||||
sqlite3ShowTrigger(0);
|
||||
sqlite3ShowTriggerList(0);
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
sqlite3ShowWindow(0);
|
||||
sqlite3ShowWinFunc(0);
|
||||
#endif
|
||||
sqlite3ShowSelect(0);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -4089,13 +4209,27 @@ int sqlite3_test_control(int op, ...){
|
|||
break;
|
||||
}
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, onoff, xAlt);
|
||||
**
|
||||
** If parameter onoff is non-zero, subsequent calls to localtime()
|
||||
** and its variants fail. If onoff is zero, undo this setting.
|
||||
** If parameter onoff is 1, subsequent calls to localtime() fail.
|
||||
** If 2, then invoke xAlt() instead of localtime(). If 0, normal
|
||||
** processing.
|
||||
**
|
||||
** xAlt arguments are void pointers, but they really want to be:
|
||||
**
|
||||
** int xAlt(const time_t*, struct tm*);
|
||||
**
|
||||
** xAlt should write results in to struct tm object of its 2nd argument
|
||||
** and return zero on success, or return non-zero on failure.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
|
||||
sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int);
|
||||
if( sqlite3GlobalConfig.bLocaltimeFault==2 ){
|
||||
typedef int(*sqlite3LocaltimeType)(const void*,void*);
|
||||
sqlite3GlobalConfig.xAltLocaltime = va_arg(ap, sqlite3LocaltimeType);
|
||||
}else{
|
||||
sqlite3GlobalConfig.xAltLocaltime = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -4200,12 +4334,16 @@ int sqlite3_test_control(int op, ...){
|
|||
*/
|
||||
case SQLITE_TESTCTRL_IMPOSTER: {
|
||||
sqlite3 *db = va_arg(ap, sqlite3*);
|
||||
int iDb;
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
db->init.iDb = sqlite3FindDbName(db, va_arg(ap,const char*));
|
||||
db->init.busy = db->init.imposterTable = va_arg(ap,int);
|
||||
db->init.newTnum = va_arg(ap,int);
|
||||
if( db->init.busy==0 && db->init.newTnum>0 ){
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
iDb = sqlite3FindDbName(db, va_arg(ap,const char*));
|
||||
if( iDb>=0 ){
|
||||
db->init.iDb = iDb;
|
||||
db->init.busy = db->init.imposterTable = va_arg(ap,int);
|
||||
db->init.newTnum = va_arg(ap,int);
|
||||
if( db->init.busy==0 && db->init.newTnum>0 ){
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
}
|
||||
}
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
break;
|
||||
|
@ -4264,8 +4402,8 @@ int sqlite3_test_control(int op, ...){
|
|||
**
|
||||
** "ptr" is a pointer to a u32.
|
||||
**
|
||||
** op==0 Store the current sqlite3SelectTrace in *ptr
|
||||
** op==1 Set sqlite3SelectTrace to the value *ptr
|
||||
** op==0 Store the current sqlite3TreeTrace in *ptr
|
||||
** op==1 Set sqlite3TreeTrace to the value *ptr
|
||||
** op==3 Store the current sqlite3WhereTrace in *ptr
|
||||
** op==3 Set sqlite3WhereTrace to the value *ptr
|
||||
*/
|
||||
|
@ -4273,13 +4411,65 @@ int sqlite3_test_control(int op, ...){
|
|||
int opTrace = va_arg(ap, int);
|
||||
u32 *ptr = va_arg(ap, u32*);
|
||||
switch( opTrace ){
|
||||
case 0: *ptr = sqlite3SelectTrace; break;
|
||||
case 1: sqlite3SelectTrace = *ptr; break;
|
||||
case 2: *ptr = sqlite3WhereTrace; break;
|
||||
case 3: sqlite3WhereTrace = *ptr; break;
|
||||
case 0: *ptr = sqlite3TreeTrace; break;
|
||||
case 1: sqlite3TreeTrace = *ptr; break;
|
||||
case 2: *ptr = sqlite3WhereTrace; break;
|
||||
case 3: sqlite3WhereTrace = *ptr; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_LOGEST,
|
||||
** double fIn, // Input value
|
||||
** int *pLogEst, // sqlite3LogEstFromDouble(fIn)
|
||||
** u64 *pInt, // sqlite3LogEstToInt(*pLogEst)
|
||||
** int *pLogEst2 // sqlite3LogEst(*pInt)
|
||||
** );
|
||||
**
|
||||
** Test access for the LogEst conversion routines.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_LOGEST: {
|
||||
double rIn = va_arg(ap, double);
|
||||
LogEst rLogEst = sqlite3LogEstFromDouble(rIn);
|
||||
int *pI1 = va_arg(ap,int*);
|
||||
u64 *pU64 = va_arg(ap,u64*);
|
||||
int *pI2 = va_arg(ap,int*);
|
||||
*pI1 = rLogEst;
|
||||
*pU64 = sqlite3LogEstToInt(rLogEst);
|
||||
*pI2 = sqlite3LogEst(*pU64);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD)
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue)
|
||||
**
|
||||
** If "id" is an integer between 1 and SQLITE_NTUNE then set the value
|
||||
** of the id-th tuning parameter to *piValue. If "id" is between -1
|
||||
** and -SQLITE_NTUNE, then write the current value of the (-id)-th
|
||||
** tuning parameter into *piValue.
|
||||
**
|
||||
** Tuning parameters are for use during transient development builds,
|
||||
** to help find the best values for constants in the query planner.
|
||||
** Access tuning parameters using the Tuning(ID) macro. Set the
|
||||
** parameters in the CLI using ".testctrl tune ID VALUE".
|
||||
**
|
||||
** Transient use only. Tuning parameters should not be used in
|
||||
** checked-in code.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_TUNE: {
|
||||
int id = va_arg(ap, int);
|
||||
int *piValue = va_arg(ap, int*);
|
||||
if( id>0 && id<=SQLITE_NTUNE ){
|
||||
Tuning(id) = *piValue;
|
||||
}else if( id<0 && id>=-SQLITE_NTUNE ){
|
||||
*piValue = Tuning(-id);
|
||||
}else{
|
||||
rc = SQLITE_NOTFOUND;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
va_end(ap);
|
||||
#endif /* SQLITE_UNTESTABLE */
|
||||
|
@ -4320,7 +4510,7 @@ static char *appendText(char *p, const char *z){
|
|||
** Memory layout must be compatible with that generated by the pager
|
||||
** and expected by sqlite3_uri_parameter() and databaseName().
|
||||
*/
|
||||
char *sqlite3_create_filename(
|
||||
const char *sqlite3_create_filename(
|
||||
const char *zDatabase,
|
||||
const char *zJournal,
|
||||
const char *zWal,
|
||||
|
@ -4356,10 +4546,10 @@ char *sqlite3_create_filename(
|
|||
** error to call this routine with any parameter other than a pointer
|
||||
** previously obtained from sqlite3_create_filename() or a NULL pointer.
|
||||
*/
|
||||
void sqlite3_free_filename(char *p){
|
||||
void sqlite3_free_filename(const char *p){
|
||||
if( p==0 ) return;
|
||||
p = (char*)databaseName(p);
|
||||
sqlite3_free(p - 4);
|
||||
p = databaseName(p);
|
||||
sqlite3_free((char*)p - 4);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4387,7 +4577,7 @@ const char *sqlite3_uri_key(const char *zFilename, int N){
|
|||
if( zFilename==0 || N<0 ) return 0;
|
||||
zFilename = databaseName(zFilename);
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
while( zFilename[0] && (N--)>0 ){
|
||||
while( ALWAYS(zFilename) && zFilename[0] && (N--)>0 ){
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
}
|
||||
|
@ -4430,12 +4620,14 @@ sqlite3_int64 sqlite3_uri_int64(
|
|||
** corruption.
|
||||
*/
|
||||
const char *sqlite3_filename_database(const char *zFilename){
|
||||
if( zFilename==0 ) return 0;
|
||||
return databaseName(zFilename);
|
||||
}
|
||||
const char *sqlite3_filename_journal(const char *zFilename){
|
||||
if( zFilename==0 ) return 0;
|
||||
zFilename = databaseName(zFilename);
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
while( zFilename[0] ){
|
||||
while( ALWAYS(zFilename) && zFilename[0] ){
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
}
|
||||
|
@ -4446,7 +4638,7 @@ const char *sqlite3_filename_wal(const char *zFilename){
|
|||
return 0;
|
||||
#else
|
||||
zFilename = sqlite3_filename_journal(zFilename);
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
if( zFilename ) zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
return zFilename;
|
||||
#endif
|
||||
}
|
||||
|
@ -4459,6 +4651,24 @@ Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
|
|||
return iDb<0 ? 0 : db->aDb[iDb].pBt;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the name of the N-th database schema. Return NULL if N is out
|
||||
** of range.
|
||||
*/
|
||||
const char *sqlite3_db_name(sqlite3 *db, int N){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if( N<0 || N>=db->nDb ){
|
||||
return 0;
|
||||
}else{
|
||||
return db->aDb[N].zDbSName;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the filename of the database associated with a database
|
||||
** connection.
|
||||
|
@ -4590,8 +4800,8 @@ int sqlite3_snapshot_open(
|
|||
*/
|
||||
int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){
|
||||
int rc = SQLITE_ERROR;
|
||||
int iDb;
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
int iDb;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
|
|
129
third_party/sqlite3/malloc.c
vendored
129
third_party/sqlite3/malloc.c
vendored
|
@ -12,9 +12,7 @@
|
|||
**
|
||||
** Memory allocation functions used throughout sqlite.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/*
|
||||
** Attempt to release up to n bytes of non-essential memory currently
|
||||
|
@ -162,7 +160,6 @@ int sqlite3MallocInit(void){
|
|||
if( sqlite3GlobalConfig.m.xMalloc==0 ){
|
||||
sqlite3MemSetDefault();
|
||||
}
|
||||
memset(&mem0, 0, sizeof(mem0));
|
||||
mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
|
||||
if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512
|
||||
|| sqlite3GlobalConfig.nPage<=0 ){
|
||||
|
@ -272,18 +269,34 @@ static void mallocWithAlarm(int n, void **pp){
|
|||
*pp = p;
|
||||
}
|
||||
|
||||
/*
|
||||
** Maximum size of any single memory allocation.
|
||||
**
|
||||
** This is not a limit on the total amount of memory used. This is
|
||||
** a limit on the size parameter to sqlite3_malloc() and sqlite3_realloc().
|
||||
**
|
||||
** The upper bound is slightly less than 2GiB: 0x7ffffeff == 2,147,483,391
|
||||
** This provides a 256-byte safety margin for defense against 32-bit
|
||||
** signed integer overflow bugs when computing memory allocation sizes.
|
||||
** Parnoid applications might want to reduce the maximum allocation size
|
||||
** further for an even larger safety margin. 0x3fffffff or 0x0fffffff
|
||||
** or even smaller would be reasonable upper bounds on the size of a memory
|
||||
** allocations for most applications.
|
||||
*/
|
||||
#ifndef SQLITE_MAX_ALLOCATION_SIZE
|
||||
# define SQLITE_MAX_ALLOCATION_SIZE 2147483391
|
||||
#endif
|
||||
#if SQLITE_MAX_ALLOCATION_SIZE>2147483391
|
||||
# error Maximum size for SQLITE_MAX_ALLOCATION_SIZE is 2147483391
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Allocate memory. This routine is like sqlite3_malloc() except that it
|
||||
** assumes the memory subsystem has already been initialized.
|
||||
*/
|
||||
void *sqlite3Malloc(u64 n){
|
||||
void *p;
|
||||
if( n==0 || n>=0x7fffff00 ){
|
||||
/* A memory allocation of a number of bytes which is near the maximum
|
||||
** signed integer value might cause an integer overflow inside of the
|
||||
** xMalloc(). Hence we limit the maximum size to 0x7fffff00, giving
|
||||
** 255 bytes of overhead. SQLite itself will never use anything near
|
||||
** this amount. The only way to reach the limit is with sqlite3_malloc() */
|
||||
if( n==0 || n>SQLITE_MAX_ALLOCATION_SIZE ){
|
||||
p = 0;
|
||||
}else if( sqlite3GlobalConfig.bMemstat ){
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
|
@ -318,8 +331,8 @@ void *sqlite3_malloc64(sqlite3_uint64 n){
|
|||
** TRUE if p is a lookaside memory allocation from db
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_LOOKASIDE
|
||||
static int isLookaside(sqlite3 *db, void *p){
|
||||
return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pEnd);
|
||||
static int isLookaside(sqlite3 *db, const void *p){
|
||||
return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pTrueEnd);
|
||||
}
|
||||
#else
|
||||
#define isLookaside(A,B) 0
|
||||
|
@ -329,32 +342,30 @@ static int isLookaside(sqlite3 *db, void *p){
|
|||
** Return the size of a memory allocation previously obtained from
|
||||
** sqlite3Malloc() or sqlite3_malloc().
|
||||
*/
|
||||
int sqlite3MallocSize(void *p){
|
||||
int sqlite3MallocSize(const void *p){
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
||||
return sqlite3GlobalConfig.m.xSize(p);
|
||||
return sqlite3GlobalConfig.m.xSize((void*)p);
|
||||
}
|
||||
static int lookasideMallocSize(sqlite3 *db, void *p){
|
||||
static int lookasideMallocSize(sqlite3 *db, const void *p){
|
||||
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
||||
return p<db->lookaside.pMiddle ? db->lookaside.szTrue : LOOKASIDE_SMALL;
|
||||
#else
|
||||
return db->lookaside.szTrue;
|
||||
#endif
|
||||
}
|
||||
int sqlite3DbMallocSize(sqlite3 *db, void *p){
|
||||
int sqlite3DbMallocSize(sqlite3 *db, const void *p){
|
||||
assert( p!=0 );
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( db==0 || !isLookaside(db,p) ){
|
||||
if( db==0 ){
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
||||
}else{
|
||||
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
}
|
||||
if( db==0 ){
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
||||
}else if( !isLookaside(db,p) ){
|
||||
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
}
|
||||
#endif
|
||||
if( db ){
|
||||
if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
|
||||
if( ((uptr)p)<(uptr)(db->lookaside.pTrueEnd) ){
|
||||
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
||||
if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
|
@ -367,7 +378,7 @@ int sqlite3DbMallocSize(sqlite3 *db, void *p){
|
|||
}
|
||||
}
|
||||
}
|
||||
return sqlite3GlobalConfig.m.xSize(p);
|
||||
return sqlite3GlobalConfig.m.xSize((void*)p);
|
||||
}
|
||||
sqlite3_uint64 sqlite3_msize(void *p){
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
|
||||
|
@ -410,14 +421,11 @@ void sqlite3DbFreeNN(sqlite3 *db, void *p){
|
|||
assert( db==0 || sqlite3_mutex_held(db->mutex) );
|
||||
assert( p!=0 );
|
||||
if( db ){
|
||||
if( db->pnBytesFreed ){
|
||||
measureAllocationSize(db, p);
|
||||
return;
|
||||
}
|
||||
if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
|
||||
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
||||
if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
|
||||
LookasideSlot *pBuf = (LookasideSlot*)p;
|
||||
assert( db->pnBytesFreed==0 );
|
||||
#ifdef SQLITE_DEBUG
|
||||
memset(p, 0xaa, LOOKASIDE_SMALL); /* Trash freed content */
|
||||
#endif
|
||||
|
@ -428,6 +436,7 @@ void sqlite3DbFreeNN(sqlite3 *db, void *p){
|
|||
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
|
||||
if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){
|
||||
LookasideSlot *pBuf = (LookasideSlot*)p;
|
||||
assert( db->pnBytesFreed==0 );
|
||||
#ifdef SQLITE_DEBUG
|
||||
memset(p, 0xaa, db->lookaside.szTrue); /* Trash freed content */
|
||||
#endif
|
||||
|
@ -436,6 +445,10 @@ void sqlite3DbFreeNN(sqlite3 *db, void *p){
|
|||
return;
|
||||
}
|
||||
}
|
||||
if( db->pnBytesFreed ){
|
||||
measureAllocationSize(db, p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
|
@ -443,6 +456,43 @@ void sqlite3DbFreeNN(sqlite3 *db, void *p){
|
|||
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
void sqlite3DbNNFreeNN(sqlite3 *db, void *p){
|
||||
assert( db!=0 );
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
assert( p!=0 );
|
||||
if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
|
||||
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
||||
if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
|
||||
LookasideSlot *pBuf = (LookasideSlot*)p;
|
||||
assert( db->pnBytesFreed==0 );
|
||||
#ifdef SQLITE_DEBUG
|
||||
memset(p, 0xaa, LOOKASIDE_SMALL); /* Trash freed content */
|
||||
#endif
|
||||
pBuf->pNext = db->lookaside.pSmallFree;
|
||||
db->lookaside.pSmallFree = pBuf;
|
||||
return;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
|
||||
if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){
|
||||
LookasideSlot *pBuf = (LookasideSlot*)p;
|
||||
assert( db->pnBytesFreed==0 );
|
||||
#ifdef SQLITE_DEBUG
|
||||
memset(p, 0xaa, db->lookaside.szTrue); /* Trash freed content */
|
||||
#endif
|
||||
pBuf->pNext = db->lookaside.pFree;
|
||||
db->lookaside.pFree = pBuf;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if( db->pnBytesFreed ){
|
||||
measureAllocationSize(db, p);
|
||||
return;
|
||||
}
|
||||
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
void sqlite3DbFree(sqlite3 *db, void *p){
|
||||
assert( db==0 || sqlite3_mutex_held(db->mutex) );
|
||||
if( p ) sqlite3DbFreeNN(db, p);
|
||||
|
@ -752,8 +802,9 @@ char *sqlite3DbSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){
|
|||
** Free any prior content in *pz and replace it with a copy of zNew.
|
||||
*/
|
||||
void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){
|
||||
char *z = sqlite3DbStrDup(db, zNew);
|
||||
sqlite3DbFree(db, *pz);
|
||||
*pz = sqlite3DbStrDup(db, zNew);
|
||||
*pz = z;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -761,8 +812,15 @@ void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){
|
|||
** has happened. This routine will set db->mallocFailed, and also
|
||||
** temporarily disable the lookaside memory allocator and interrupt
|
||||
** any running VDBEs.
|
||||
**
|
||||
** Always return a NULL pointer so that this routine can be invoked using
|
||||
**
|
||||
** return sqlite3OomFault(db);
|
||||
**
|
||||
** and thereby avoid unnecessary stack frame allocations for the overwhelmingly
|
||||
** common case where no OOM occurs.
|
||||
*/
|
||||
void sqlite3OomFault(sqlite3 *db){
|
||||
void *sqlite3OomFault(sqlite3 *db){
|
||||
if( db->mallocFailed==0 && db->bBenignMalloc==0 ){
|
||||
db->mallocFailed = 1;
|
||||
if( db->nVdbeExec>0 ){
|
||||
|
@ -770,9 +828,16 @@ void sqlite3OomFault(sqlite3 *db){
|
|||
}
|
||||
DisableLookaside;
|
||||
if( db->pParse ){
|
||||
Parse *pParse;
|
||||
sqlite3ErrorMsg(db->pParse, "out of memory");
|
||||
db->pParse->rc = SQLITE_NOMEM_BKPT;
|
||||
for(pParse=db->pParse->pOuterParse; pParse; pParse = pParse->pOuterParse){
|
||||
pParse->nErr++;
|
||||
pParse->rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
3
third_party/sqlite3/mem0.c
vendored
3
third_party/sqlite3/mem0.c
vendored
|
@ -16,8 +16,7 @@
|
|||
** are merely placeholders. Real drivers must be substituted using
|
||||
** sqlite3_config() before SQLite will operate.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/*
|
||||
** This version of the memory allocator is the default. It is
|
||||
|
|
23
third_party/sqlite3/mem1.c
vendored
23
third_party/sqlite3/mem1.c
vendored
|
@ -41,8 +41,7 @@
|
|||
** be necessary when compiling for Delphi,
|
||||
** for example.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/*
|
||||
** This version of the memory allocator is the default. It is
|
||||
|
@ -104,16 +103,16 @@ static malloc_zone_t* _sqliteZone_;
|
|||
** the macro SQLITE_MALLOCSIZE to the desired function name.
|
||||
*/
|
||||
#if defined(SQLITE_USE_MALLOC_H)
|
||||
#include "libc/mem/mem.h"
|
||||
#if defined(SQLITE_USE_MALLOC_USABLE_SIZE)
|
||||
#if !defined(SQLITE_MALLOCSIZE)
|
||||
#define SQLITE_MALLOCSIZE(x) malloc_usable_size(x)
|
||||
#endif
|
||||
#elif defined(SQLITE_USE_MSIZE)
|
||||
#if !defined(SQLITE_MALLOCSIZE)
|
||||
#define SQLITE_MALLOCSIZE _msize
|
||||
#endif
|
||||
#endif
|
||||
# include <malloc.h>
|
||||
# if defined(SQLITE_USE_MALLOC_USABLE_SIZE)
|
||||
# if !defined(SQLITE_MALLOCSIZE)
|
||||
# define SQLITE_MALLOCSIZE(x) malloc_usable_size(x)
|
||||
# endif
|
||||
# elif defined(SQLITE_USE_MSIZE)
|
||||
# if !defined(SQLITE_MALLOCSIZE)
|
||||
# define SQLITE_MALLOCSIZE _msize
|
||||
# endif
|
||||
# endif
|
||||
#endif /* defined(SQLITE_USE_MALLOC_H) */
|
||||
|
||||
#endif /* __APPLE__ or not __APPLE__ */
|
||||
|
|
11
third_party/sqlite3/mem2.c
vendored
11
third_party/sqlite3/mem2.c
vendored
|
@ -19,8 +19,7 @@
|
|||
** This file contains implementations of the low-level memory allocation
|
||||
** routines specified in the sqlite3_mem_methods object.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/*
|
||||
** This version of the memory allocator is used only if the
|
||||
|
@ -38,7 +37,7 @@
|
|||
# define backtrace(A,B) 1
|
||||
# define backtrace_symbols_fd(A,B,C)
|
||||
#endif
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
** Each memory allocation looks like this:
|
||||
|
@ -150,7 +149,7 @@ static void adjustStats(int iSize, int increment){
|
|||
** This routine checks the guards at either end of the allocation and
|
||||
** if they are incorrect it asserts.
|
||||
*/
|
||||
static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){
|
||||
static struct MemBlockHdr *sqlite3MemsysGetHeader(const void *pAllocation){
|
||||
struct MemBlockHdr *p;
|
||||
int *pInt;
|
||||
u8 *pU8;
|
||||
|
@ -397,7 +396,7 @@ void sqlite3MemdebugSetType(void *p, u8 eType){
|
|||
**
|
||||
** assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
||||
*/
|
||||
int sqlite3MemdebugHasType(void *p, u8 eType){
|
||||
int sqlite3MemdebugHasType(const void *p, u8 eType){
|
||||
int rc = 1;
|
||||
if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
|
||||
struct MemBlockHdr *pHdr;
|
||||
|
@ -419,7 +418,7 @@ int sqlite3MemdebugHasType(void *p, u8 eType){
|
|||
**
|
||||
** assert( sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
|
||||
*/
|
||||
int sqlite3MemdebugNoType(void *p, u8 eType){
|
||||
int sqlite3MemdebugNoType(const void *p, u8 eType){
|
||||
int rc = 1;
|
||||
if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
|
||||
struct MemBlockHdr *pHdr;
|
||||
|
|
7
third_party/sqlite3/mem3.c
vendored
7
third_party/sqlite3/mem3.c
vendored
|
@ -10,12 +10,12 @@
|
|||
**
|
||||
*************************************************************************
|
||||
** This file contains the C functions that implement a memory
|
||||
** allocation subsystem for use by SQLite.
|
||||
** allocation subsystem for use by SQLite.
|
||||
**
|
||||
** This version of the memory allocation subsystem omits all
|
||||
** use of malloc(). The SQLite user supplies a block of memory
|
||||
** before calling sqlite3_initialize() from which allocations
|
||||
** are made and returned by the xMalloc() and xRealloc()
|
||||
** are made and returned by the xMalloc() and xRealloc()
|
||||
** implementations. Once sqlite3_initialize() has been called,
|
||||
** the amount of memory available to SQLite is fixed and cannot
|
||||
** be changed.
|
||||
|
@ -23,8 +23,7 @@
|
|||
** This version of the memory allocation subsystem is included
|
||||
** in the build only if SQLITE_ENABLE_MEMSYS3 is defined.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/*
|
||||
** This version of the memory allocator is only built into the library
|
||||
|
|
20
third_party/sqlite3/mem5.c
vendored
20
third_party/sqlite3/mem5.c
vendored
|
@ -10,12 +10,12 @@
|
|||
**
|
||||
*************************************************************************
|
||||
** This file contains the C functions that implement a memory
|
||||
** allocation subsystem for use by SQLite.
|
||||
** allocation subsystem for use by SQLite.
|
||||
**
|
||||
** This version of the memory allocation subsystem omits all
|
||||
** use of malloc(). The application gives SQLite a block of memory
|
||||
** before calling sqlite3_initialize() from which allocations
|
||||
** are made and returned by the xMalloc() and xRealloc()
|
||||
** are made and returned by the xMalloc() and xRealloc()
|
||||
** implementations. Once sqlite3_initialize() has been called,
|
||||
** the amount of memory available to SQLite is fixed and cannot
|
||||
** be changed.
|
||||
|
@ -35,12 +35,12 @@
|
|||
** This algorithm is described in: J. M. Robson. "Bounds for Some Functions
|
||||
** Concerning Dynamic Storage Allocation". Journal of the Association for
|
||||
** Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499.
|
||||
**
|
||||
**
|
||||
** Let n be the size of the largest allocation divided by the minimum
|
||||
** allocation size (after rounding all sizes up to a power of 2.) Let M
|
||||
** be the maximum amount of memory ever outstanding at one time. Let
|
||||
** N be the total amount of memory available for allocation. Robson
|
||||
** proved that this memory allocator will never breakdown due to
|
||||
** proved that this memory allocator will never breakdown due to
|
||||
** fragmentation as long as the following constraint holds:
|
||||
**
|
||||
** N >= M*(1 + log2(n)/2) - n + 1
|
||||
|
@ -48,8 +48,7 @@
|
|||
** The sqlite3_status() logic tracks the maximum values of n and M so
|
||||
** that an application can, at any time, verify this constraint.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/*
|
||||
** This version of the memory allocator is used only when
|
||||
|
@ -421,8 +420,13 @@ static void *memsys5Realloc(void *pPrior, int nBytes){
|
|||
*/
|
||||
static int memsys5Roundup(int n){
|
||||
int iFullSz;
|
||||
if( n > 0x40000000 ) return 0;
|
||||
for(iFullSz=mem5.szAtom; iFullSz<n; iFullSz *= 2);
|
||||
if( n<=mem5.szAtom*2 ){
|
||||
if( n<=mem5.szAtom ) return mem5.szAtom;
|
||||
return mem5.szAtom*2;
|
||||
}
|
||||
if( n>0x40000000 ) return 0;
|
||||
for(iFullSz=mem5.szAtom*8; iFullSz<n; iFullSz *= 4);
|
||||
if( (iFullSz/2)>=n ) return iFullSz/2;
|
||||
return iFullSz;
|
||||
}
|
||||
|
||||
|
|
368
third_party/sqlite3/memdb.c
vendored
368
third_party/sqlite3/memdb.c
vendored
|
@ -16,33 +16,89 @@
|
|||
** This file also implements interface sqlite3_serialize() and
|
||||
** sqlite3_deserialize().
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
#ifdef SQLITE_ENABLE_DESERIALIZE
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
#ifndef SQLITE_OMIT_DESERIALIZE
|
||||
|
||||
/*
|
||||
** Forward declaration of objects used by this utility
|
||||
*/
|
||||
typedef struct sqlite3_vfs MemVfs;
|
||||
typedef struct MemFile MemFile;
|
||||
typedef struct MemStore MemStore;
|
||||
|
||||
/* Access to a lower-level VFS that (might) implement dynamic loading,
|
||||
** access to randomness, etc.
|
||||
*/
|
||||
#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
|
||||
|
||||
/* An open file */
|
||||
struct MemFile {
|
||||
sqlite3_file base; /* IO methods */
|
||||
/* Storage for a memdb file.
|
||||
**
|
||||
** An memdb object can be shared or separate. Shared memdb objects can be
|
||||
** used by more than one database connection. Mutexes are used by shared
|
||||
** memdb objects to coordinate access. Separate memdb objects are only
|
||||
** connected to a single database connection and do not require additional
|
||||
** mutexes.
|
||||
**
|
||||
** Shared memdb objects have .zFName!=0 and .pMutex!=0. They are created
|
||||
** using "file:/name?vfs=memdb". The first character of the name must be
|
||||
** "/" or else the object will be a separate memdb object. All shared
|
||||
** memdb objects are stored in memdb_g.apMemStore[] in an arbitrary order.
|
||||
**
|
||||
** Separate memdb objects are created using a name that does not begin
|
||||
** with "/" or using sqlite3_deserialize().
|
||||
**
|
||||
** Access rules for shared MemStore objects:
|
||||
**
|
||||
** * .zFName is initialized when the object is created and afterwards
|
||||
** is unchanged until the object is destroyed. So it can be accessed
|
||||
** at any time as long as we know the object is not being destroyed,
|
||||
** which means while either the SQLITE_MUTEX_STATIC_VFS1 or
|
||||
** .pMutex is held or the object is not part of memdb_g.apMemStore[].
|
||||
**
|
||||
** * Can .pMutex can only be changed while holding the
|
||||
** SQLITE_MUTEX_STATIC_VFS1 mutex or while the object is not part
|
||||
** of memdb_g.apMemStore[].
|
||||
**
|
||||
** * Other fields can only be changed while holding the .pMutex mutex
|
||||
** or when the .nRef is less than zero and the object is not part of
|
||||
** memdb_g.apMemStore[].
|
||||
**
|
||||
** * The .aData pointer has the added requirement that it can can only
|
||||
** be changed (for resizing) when nMmap is zero.
|
||||
**
|
||||
*/
|
||||
struct MemStore {
|
||||
sqlite3_int64 sz; /* Size of the file */
|
||||
sqlite3_int64 szAlloc; /* Space allocated to aData */
|
||||
sqlite3_int64 szMax; /* Maximum allowed size of the file */
|
||||
unsigned char *aData; /* content of the file */
|
||||
sqlite3_mutex *pMutex; /* Used by shared stores only */
|
||||
int nMmap; /* Number of memory mapped pages */
|
||||
unsigned mFlags; /* Flags */
|
||||
int nRdLock; /* Number of readers */
|
||||
int nWrLock; /* Number of writers. (Always 0 or 1) */
|
||||
int nRef; /* Number of users of this MemStore */
|
||||
char *zFName; /* The filename for shared stores */
|
||||
};
|
||||
|
||||
/* An open file */
|
||||
struct MemFile {
|
||||
sqlite3_file base; /* IO methods */
|
||||
MemStore *pStore; /* The storage */
|
||||
int eLock; /* Most recent lock against this file */
|
||||
};
|
||||
|
||||
/*
|
||||
** File-scope variables for holding the memdb files that are accessible
|
||||
** to multiple database connections in separate threads.
|
||||
**
|
||||
** Must hold SQLITE_MUTEX_STATIC_VFS1 to access any part of this object.
|
||||
*/
|
||||
static struct MemFS {
|
||||
int nMemStore; /* Number of shared MemStore objects */
|
||||
MemStore **apMemStore; /* Array of all shared MemStore objects */
|
||||
} memdb_g;
|
||||
|
||||
/*
|
||||
** Methods for MemFile
|
||||
*/
|
||||
|
@ -96,7 +152,10 @@ static sqlite3_vfs memdb_vfs = {
|
|||
memdbSleep, /* xSleep */
|
||||
0, /* memdbCurrentTime, */ /* xCurrentTime */
|
||||
memdbGetLastError, /* xGetLastError */
|
||||
memdbCurrentTimeInt64 /* xCurrentTimeInt64 */
|
||||
memdbCurrentTimeInt64, /* xCurrentTimeInt64 */
|
||||
0, /* xSetSystemCall */
|
||||
0, /* xGetSystemCall */
|
||||
0, /* xNextSystemCall */
|
||||
};
|
||||
|
||||
static const sqlite3_io_methods memdb_io_methods = {
|
||||
|
@ -121,19 +180,67 @@ static const sqlite3_io_methods memdb_io_methods = {
|
|||
memdbUnfetch /* xUnfetch */
|
||||
};
|
||||
|
||||
/*
|
||||
** Enter/leave the mutex on a MemStore
|
||||
*/
|
||||
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
|
||||
static void memdbEnter(MemStore *p){
|
||||
UNUSED_PARAMETER(p);
|
||||
}
|
||||
static void memdbLeave(MemStore *p){
|
||||
UNUSED_PARAMETER(p);
|
||||
}
|
||||
#else
|
||||
static void memdbEnter(MemStore *p){
|
||||
sqlite3_mutex_enter(p->pMutex);
|
||||
}
|
||||
static void memdbLeave(MemStore *p){
|
||||
sqlite3_mutex_leave(p->pMutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Close an memdb-file.
|
||||
**
|
||||
** The pData pointer is owned by the application, so there is nothing
|
||||
** to free. Unless the SQLITE_DESERIALIZE_FREEONCLOSE flag is set,
|
||||
** in which case we own the pData pointer and need to free it.
|
||||
** Free the underlying MemStore object when its refcount drops to zero
|
||||
** or less.
|
||||
*/
|
||||
static int memdbClose(sqlite3_file *pFile){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
|
||||
sqlite3_free(p->aData);
|
||||
MemStore *p = ((MemFile*)pFile)->pStore;
|
||||
if( p->zFName ){
|
||||
int i;
|
||||
#ifndef SQLITE_MUTEX_OMIT
|
||||
sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
|
||||
#endif
|
||||
sqlite3_mutex_enter(pVfsMutex);
|
||||
for(i=0; ALWAYS(i<memdb_g.nMemStore); i++){
|
||||
if( memdb_g.apMemStore[i]==p ){
|
||||
memdbEnter(p);
|
||||
if( p->nRef==1 ){
|
||||
memdb_g.apMemStore[i] = memdb_g.apMemStore[--memdb_g.nMemStore];
|
||||
if( memdb_g.nMemStore==0 ){
|
||||
sqlite3_free(memdb_g.apMemStore);
|
||||
memdb_g.apMemStore = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
sqlite3_mutex_leave(pVfsMutex);
|
||||
}else{
|
||||
memdbEnter(p);
|
||||
}
|
||||
p->nRef--;
|
||||
if( p->nRef<=0 ){
|
||||
if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
|
||||
sqlite3_free(p->aData);
|
||||
}
|
||||
memdbLeave(p);
|
||||
sqlite3_mutex_free(p->pMutex);
|
||||
sqlite3_free(p);
|
||||
}else{
|
||||
memdbLeave(p);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
@ -147,22 +254,25 @@ static int memdbRead(
|
|||
int iAmt,
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
MemStore *p = ((MemFile*)pFile)->pStore;
|
||||
memdbEnter(p);
|
||||
if( iOfst+iAmt>p->sz ){
|
||||
memset(zBuf, 0, iAmt);
|
||||
if( iOfst<p->sz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);
|
||||
memdbLeave(p);
|
||||
return SQLITE_IOERR_SHORT_READ;
|
||||
}
|
||||
memcpy(zBuf, p->aData+iOfst, iAmt);
|
||||
memdbLeave(p);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Try to enlarge the memory allocation to hold at least sz bytes
|
||||
*/
|
||||
static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
|
||||
static int memdbEnlarge(MemStore *p, sqlite3_int64 newSz){
|
||||
unsigned char *pNew;
|
||||
if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){
|
||||
if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || NEVER(p->nMmap>0) ){
|
||||
return SQLITE_FULL;
|
||||
}
|
||||
if( newSz>p->szMax ){
|
||||
|
@ -171,7 +281,7 @@ static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
|
|||
newSz *= 2;
|
||||
if( newSz>p->szMax ) newSz = p->szMax;
|
||||
pNew = sqlite3Realloc(p->aData, newSz);
|
||||
if( pNew==0 ) return SQLITE_NOMEM;
|
||||
if( pNew==0 ) return SQLITE_IOERR_NOMEM;
|
||||
p->aData = pNew;
|
||||
p->szAlloc = newSz;
|
||||
return SQLITE_OK;
|
||||
|
@ -186,19 +296,27 @@ static int memdbWrite(
|
|||
int iAmt,
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ) return SQLITE_READONLY;
|
||||
MemStore *p = ((MemFile*)pFile)->pStore;
|
||||
memdbEnter(p);
|
||||
if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
|
||||
/* Can't happen: memdbLock() will return SQLITE_READONLY before
|
||||
** reaching this point */
|
||||
memdbLeave(p);
|
||||
return SQLITE_IOERR_WRITE;
|
||||
}
|
||||
if( iOfst+iAmt>p->sz ){
|
||||
int rc;
|
||||
if( iOfst+iAmt>p->szAlloc
|
||||
&& (rc = memdbEnlarge(p, iOfst+iAmt))!=SQLITE_OK
|
||||
){
|
||||
memdbLeave(p);
|
||||
return rc;
|
||||
}
|
||||
if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
|
||||
p->sz = iOfst+iAmt;
|
||||
}
|
||||
memcpy(p->aData+iOfst, z, iAmt);
|
||||
memdbLeave(p);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
@ -210,16 +328,25 @@ static int memdbWrite(
|
|||
** the size of a file, never to increase the size.
|
||||
*/
|
||||
static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
if( NEVER(size>p->sz) ) return SQLITE_FULL;
|
||||
p->sz = size;
|
||||
return SQLITE_OK;
|
||||
MemStore *p = ((MemFile*)pFile)->pStore;
|
||||
int rc = SQLITE_OK;
|
||||
memdbEnter(p);
|
||||
if( size>p->sz ){
|
||||
/* This can only happen with a corrupt wal mode db */
|
||||
rc = SQLITE_CORRUPT;
|
||||
}else{
|
||||
p->sz = size;
|
||||
}
|
||||
memdbLeave(p);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Sync an memdb-file.
|
||||
*/
|
||||
static int memdbSync(sqlite3_file *pFile, int flags){
|
||||
UNUSED_PARAMETER(pFile);
|
||||
UNUSED_PARAMETER(flags);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
@ -227,8 +354,10 @@ static int memdbSync(sqlite3_file *pFile, int flags){
|
|||
** Return the current file-size of an memdb-file.
|
||||
*/
|
||||
static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
MemStore *p = ((MemFile*)pFile)->pStore;
|
||||
memdbEnter(p);
|
||||
*pSize = p->sz;
|
||||
memdbLeave(p);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
@ -236,19 +365,48 @@ static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
|
|||
** Lock an memdb-file.
|
||||
*/
|
||||
static int memdbLock(sqlite3_file *pFile, int eLock){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
if( eLock>SQLITE_LOCK_SHARED
|
||||
&& (p->mFlags & SQLITE_DESERIALIZE_READONLY)!=0
|
||||
){
|
||||
return SQLITE_READONLY;
|
||||
MemFile *pThis = (MemFile*)pFile;
|
||||
MemStore *p = pThis->pStore;
|
||||
int rc = SQLITE_OK;
|
||||
if( eLock==pThis->eLock ) return SQLITE_OK;
|
||||
memdbEnter(p);
|
||||
if( eLock>SQLITE_LOCK_SHARED ){
|
||||
if( p->mFlags & SQLITE_DESERIALIZE_READONLY ){
|
||||
rc = SQLITE_READONLY;
|
||||
}else if( pThis->eLock<=SQLITE_LOCK_SHARED ){
|
||||
if( p->nWrLock ){
|
||||
rc = SQLITE_BUSY;
|
||||
}else{
|
||||
p->nWrLock = 1;
|
||||
}
|
||||
}
|
||||
}else if( eLock==SQLITE_LOCK_SHARED ){
|
||||
if( pThis->eLock > SQLITE_LOCK_SHARED ){
|
||||
assert( p->nWrLock==1 );
|
||||
p->nWrLock = 0;
|
||||
}else if( p->nWrLock ){
|
||||
rc = SQLITE_BUSY;
|
||||
}else{
|
||||
p->nRdLock++;
|
||||
}
|
||||
}else{
|
||||
assert( eLock==SQLITE_LOCK_NONE );
|
||||
if( pThis->eLock>SQLITE_LOCK_SHARED ){
|
||||
assert( p->nWrLock==1 );
|
||||
p->nWrLock = 0;
|
||||
}
|
||||
assert( p->nRdLock>0 );
|
||||
p->nRdLock--;
|
||||
}
|
||||
p->eLock = eLock;
|
||||
return SQLITE_OK;
|
||||
if( rc==SQLITE_OK ) pThis->eLock = eLock;
|
||||
memdbLeave(p);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if 0 /* Never used because memdbAccess() always returns false */
|
||||
#if 0
|
||||
/*
|
||||
** Check if another file-handle holds a RESERVED lock on an memdb-file.
|
||||
** This interface is only used for crash recovery, which does not
|
||||
** occur on an in-memory database.
|
||||
*/
|
||||
static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
||||
*pResOut = 0;
|
||||
|
@ -256,12 +414,14 @@ static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** File control method. For custom operations on an memdb-file.
|
||||
*/
|
||||
static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
MemStore *p = ((MemFile*)pFile)->pStore;
|
||||
int rc = SQLITE_NOTFOUND;
|
||||
memdbEnter(p);
|
||||
if( op==SQLITE_FCNTL_VFSNAME ){
|
||||
*(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
|
||||
rc = SQLITE_OK;
|
||||
|
@ -279,6 +439,7 @@ static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
|
|||
*(sqlite3_int64*)pArg = iLimit;
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
memdbLeave(p);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -295,6 +456,7 @@ static int memdbSectorSize(sqlite3_file *pFile){
|
|||
** Return the device characteristic flags supported by an memdb-file.
|
||||
*/
|
||||
static int memdbDeviceCharacteristics(sqlite3_file *pFile){
|
||||
UNUSED_PARAMETER(pFile);
|
||||
return SQLITE_IOCAP_ATOMIC |
|
||||
SQLITE_IOCAP_POWERSAFE_OVERWRITE |
|
||||
SQLITE_IOCAP_SAFE_APPEND |
|
||||
|
@ -308,20 +470,26 @@ static int memdbFetch(
|
|||
int iAmt,
|
||||
void **pp
|
||||
){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
if( iOfst+iAmt>p->sz ){
|
||||
MemStore *p = ((MemFile*)pFile)->pStore;
|
||||
memdbEnter(p);
|
||||
if( iOfst+iAmt>p->sz || (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)!=0 ){
|
||||
*pp = 0;
|
||||
}else{
|
||||
p->nMmap++;
|
||||
*pp = (void*)(p->aData + iOfst);
|
||||
}
|
||||
memdbLeave(p);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Release a memory-mapped page */
|
||||
static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
MemStore *p = ((MemFile*)pFile)->pStore;
|
||||
UNUSED_PARAMETER(iOfst);
|
||||
UNUSED_PARAMETER(pPage);
|
||||
memdbEnter(p);
|
||||
p->nMmap--;
|
||||
memdbLeave(p);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
@ -331,20 +499,79 @@ static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
|
|||
static int memdbOpen(
|
||||
sqlite3_vfs *pVfs,
|
||||
const char *zName,
|
||||
sqlite3_file *pFile,
|
||||
sqlite3_file *pFd,
|
||||
int flags,
|
||||
int *pOutFlags
|
||||
){
|
||||
MemFile *p = (MemFile*)pFile;
|
||||
if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
|
||||
return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags, pOutFlags);
|
||||
MemFile *pFile = (MemFile*)pFd;
|
||||
MemStore *p = 0;
|
||||
int szName;
|
||||
UNUSED_PARAMETER(pVfs);
|
||||
|
||||
memset(pFile, 0, sizeof(*pFile));
|
||||
szName = sqlite3Strlen30(zName);
|
||||
if( szName>1 && zName[0]=='/' ){
|
||||
int i;
|
||||
#ifndef SQLITE_MUTEX_OMIT
|
||||
sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
|
||||
#endif
|
||||
sqlite3_mutex_enter(pVfsMutex);
|
||||
for(i=0; i<memdb_g.nMemStore; i++){
|
||||
if( strcmp(memdb_g.apMemStore[i]->zFName,zName)==0 ){
|
||||
p = memdb_g.apMemStore[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( p==0 ){
|
||||
MemStore **apNew;
|
||||
p = sqlite3Malloc( sizeof(*p) + szName + 3 );
|
||||
if( p==0 ){
|
||||
sqlite3_mutex_leave(pVfsMutex);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
apNew = sqlite3Realloc(memdb_g.apMemStore,
|
||||
sizeof(apNew[0])*(memdb_g.nMemStore+1) );
|
||||
if( apNew==0 ){
|
||||
sqlite3_free(p);
|
||||
sqlite3_mutex_leave(pVfsMutex);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
apNew[memdb_g.nMemStore++] = p;
|
||||
memdb_g.apMemStore = apNew;
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE|SQLITE_DESERIALIZE_FREEONCLOSE;
|
||||
p->szMax = sqlite3GlobalConfig.mxMemdbSize;
|
||||
p->zFName = (char*)&p[1];
|
||||
memcpy(p->zFName, zName, szName+1);
|
||||
p->pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
||||
if( p->pMutex==0 ){
|
||||
memdb_g.nMemStore--;
|
||||
sqlite3_free(p);
|
||||
sqlite3_mutex_leave(pVfsMutex);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
p->nRef = 1;
|
||||
memdbEnter(p);
|
||||
}else{
|
||||
memdbEnter(p);
|
||||
p->nRef++;
|
||||
}
|
||||
sqlite3_mutex_leave(pVfsMutex);
|
||||
}else{
|
||||
p = sqlite3Malloc( sizeof(*p) );
|
||||
if( p==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
|
||||
p->szMax = sqlite3GlobalConfig.mxMemdbSize;
|
||||
}
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
|
||||
assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */
|
||||
*pOutFlags = flags | SQLITE_OPEN_MEMORY;
|
||||
pFile->pMethods = &memdb_io_methods;
|
||||
p->szMax = sqlite3GlobalConfig.mxMemdbSize;
|
||||
pFile->pStore = p;
|
||||
if( pOutFlags!=0 ){
|
||||
*pOutFlags = flags | SQLITE_OPEN_MEMORY;
|
||||
}
|
||||
pFd->pMethods = &memdb_io_methods;
|
||||
memdbLeave(p);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
@ -372,6 +599,9 @@ static int memdbAccess(
|
|||
int flags,
|
||||
int *pResOut
|
||||
){
|
||||
UNUSED_PARAMETER(pVfs);
|
||||
UNUSED_PARAMETER(zPath);
|
||||
UNUSED_PARAMETER(flags);
|
||||
*pResOut = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
@ -387,6 +617,7 @@ static int memdbFullPathname(
|
|||
int nOut,
|
||||
char *zOut
|
||||
){
|
||||
UNUSED_PARAMETER(pVfs);
|
||||
sqlite3_snprintf(nOut, zOut, "%s", zPath);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
@ -459,9 +690,14 @@ static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
|
|||
*/
|
||||
static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
|
||||
MemFile *p = 0;
|
||||
MemStore *pStore;
|
||||
int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
|
||||
if( rc ) return 0;
|
||||
if( p->base.pMethods!=&memdb_io_methods ) return 0;
|
||||
pStore = p->pStore;
|
||||
memdbEnter(pStore);
|
||||
if( pStore->zFName!=0 ) p = 0;
|
||||
memdbLeave(pStore);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -497,12 +733,14 @@ unsigned char *sqlite3_serialize(
|
|||
if( piSize ) *piSize = -1;
|
||||
if( iDb<0 ) return 0;
|
||||
if( p ){
|
||||
if( piSize ) *piSize = p->sz;
|
||||
MemStore *pStore = p->pStore;
|
||||
assert( pStore->pMutex==0 );
|
||||
if( piSize ) *piSize = pStore->sz;
|
||||
if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
|
||||
pOut = p->aData;
|
||||
pOut = pStore->aData;
|
||||
}else{
|
||||
pOut = sqlite3_malloc64( p->sz );
|
||||
if( pOut ) memcpy(pOut, p->aData, p->sz);
|
||||
pOut = sqlite3_malloc64( pStore->sz );
|
||||
if( pOut ) memcpy(pOut, pStore->aData, pStore->sz);
|
||||
}
|
||||
return pOut;
|
||||
}
|
||||
|
@ -572,10 +810,11 @@ int sqlite3_deserialize(
|
|||
sqlite3_mutex_enter(db->mutex);
|
||||
if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
|
||||
iDb = sqlite3FindDbName(db, zSchema);
|
||||
if( iDb<0 ){
|
||||
testcase( iDb==1 );
|
||||
if( iDb<2 && iDb!=0 ){
|
||||
rc = SQLITE_ERROR;
|
||||
goto end_deserialize;
|
||||
}
|
||||
}
|
||||
zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema);
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
|
@ -596,15 +835,16 @@ int sqlite3_deserialize(
|
|||
if( p==0 ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
p->aData = pData;
|
||||
MemStore *pStore = p->pStore;
|
||||
pStore->aData = pData;
|
||||
pData = 0;
|
||||
p->sz = szDb;
|
||||
p->szAlloc = szBuf;
|
||||
p->szMax = szBuf;
|
||||
if( p->szMax<sqlite3GlobalConfig.mxMemdbSize ){
|
||||
p->szMax = sqlite3GlobalConfig.mxMemdbSize;
|
||||
pStore->sz = szDb;
|
||||
pStore->szAlloc = szBuf;
|
||||
pStore->szMax = szBuf;
|
||||
if( pStore->szMax<sqlite3GlobalConfig.mxMemdbSize ){
|
||||
pStore->szMax = sqlite3GlobalConfig.mxMemdbSize;
|
||||
}
|
||||
p->mFlags = mFlags;
|
||||
pStore->mFlags = mFlags;
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
|
@ -623,7 +863,9 @@ end_deserialize:
|
|||
*/
|
||||
int sqlite3MemdbInit(void){
|
||||
sqlite3_vfs *pLower = sqlite3_vfs_find(0);
|
||||
int sz = pLower->szOsFile;
|
||||
unsigned int sz;
|
||||
if( NEVER(pLower==0) ) return SQLITE_ERROR;
|
||||
sz = pLower->szOsFile;
|
||||
memdb_vfs.pAppData = pLower;
|
||||
/* The following conditional can only be true when compiled for
|
||||
** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave
|
||||
|
@ -633,4 +875,4 @@ int sqlite3MemdbInit(void){
|
|||
memdb_vfs.szOsFile = sz;
|
||||
return sqlite3_vfs_register(&memdb_vfs, 0);
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_DESERIALIZE */
|
||||
#endif /* SQLITE_OMIT_DESERIALIZE */
|
||||
|
|
67
third_party/sqlite3/memjournal.c
vendored
67
third_party/sqlite3/memjournal.c
vendored
|
@ -23,8 +23,7 @@
|
|||
** in the common case, they are usually small and no file I/O needs to
|
||||
** occur.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/* Forward references to internal structures */
|
||||
typedef struct MemJournal MemJournal;
|
||||
|
@ -179,6 +178,9 @@ static int memjrnlCreateFile(MemJournal *p){
|
|||
}
|
||||
|
||||
|
||||
/* Forward reference */
|
||||
static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size);
|
||||
|
||||
/*
|
||||
** Write data to the file.
|
||||
*/
|
||||
|
@ -208,23 +210,21 @@ static int memjrnlWrite(
|
|||
** access writes are not required. The only exception to this is when
|
||||
** the in-memory journal is being used by a connection using the
|
||||
** atomic-write optimization. In this case the first 28 bytes of the
|
||||
** journal file may be written as part of committing the transaction. */
|
||||
assert( iOfst==p->endpoint.iOffset || iOfst==0 );
|
||||
#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
|
||||
|| defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
|
||||
** journal file may be written as part of committing the transaction. */
|
||||
assert( iOfst<=p->endpoint.iOffset );
|
||||
if( iOfst>0 && iOfst!=p->endpoint.iOffset ){
|
||||
memjrnlTruncate(pJfd, iOfst);
|
||||
}
|
||||
if( iOfst==0 && p->pFirst ){
|
||||
assert( p->nChunkSize>iAmt );
|
||||
memcpy((u8*)p->pFirst->zChunk, zBuf, iAmt);
|
||||
}else
|
||||
#else
|
||||
assert( iOfst>0 || p->pFirst==0 );
|
||||
#endif
|
||||
{
|
||||
}else{
|
||||
while( nWrite>0 ){
|
||||
FileChunk *pChunk = p->endpoint.pChunk;
|
||||
int iChunkOffset = (int)(p->endpoint.iOffset%p->nChunkSize);
|
||||
int iSpace = MIN(nWrite, p->nChunkSize - iChunkOffset);
|
||||
|
||||
assert( pChunk!=0 || iChunkOffset==0 );
|
||||
if( iChunkOffset==0 ){
|
||||
/* New chunk is required to extend the file. */
|
||||
FileChunk *pNew = sqlite3_malloc(fileChunkSize(p->nChunkSize));
|
||||
|
@ -239,10 +239,11 @@ static int memjrnlWrite(
|
|||
assert( !p->pFirst );
|
||||
p->pFirst = pNew;
|
||||
}
|
||||
p->endpoint.pChunk = pNew;
|
||||
pChunk = p->endpoint.pChunk = pNew;
|
||||
}
|
||||
|
||||
memcpy((u8*)p->endpoint.pChunk->zChunk + iChunkOffset, zWrite, iSpace);
|
||||
assert( pChunk!=0 );
|
||||
memcpy((u8*)pChunk->zChunk + iChunkOffset, zWrite, iSpace);
|
||||
zWrite += iSpace;
|
||||
nWrite -= iSpace;
|
||||
p->endpoint.iOffset += iSpace;
|
||||
|
@ -258,26 +259,28 @@ static int memjrnlWrite(
|
|||
*/
|
||||
static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
|
||||
MemJournal *p = (MemJournal *)pJfd;
|
||||
FileChunk *pIter = 0;
|
||||
assert( p->endpoint.pChunk==0 || p->endpoint.pChunk->pNext==0 );
|
||||
if( size<p->endpoint.iOffset ){
|
||||
FileChunk *pIter = 0;
|
||||
if( size==0 ){
|
||||
memjrnlFreeChunks(p->pFirst);
|
||||
p->pFirst = 0;
|
||||
}else{
|
||||
i64 iOff = p->nChunkSize;
|
||||
for(pIter=p->pFirst; ALWAYS(pIter) && iOff<size; pIter=pIter->pNext){
|
||||
iOff += p->nChunkSize;
|
||||
}
|
||||
if( ALWAYS(pIter) ){
|
||||
memjrnlFreeChunks(pIter->pNext);
|
||||
pIter->pNext = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( size==0 ){
|
||||
memjrnlFreeChunks(p->pFirst);
|
||||
p->pFirst = 0;
|
||||
}else{
|
||||
i64 iOff = p->nChunkSize;
|
||||
for(pIter=p->pFirst; ALWAYS(pIter) && iOff<=size; pIter=pIter->pNext){
|
||||
iOff += p->nChunkSize;
|
||||
}
|
||||
if( ALWAYS(pIter) ){
|
||||
memjrnlFreeChunks(pIter->pNext);
|
||||
pIter->pNext = 0;
|
||||
}
|
||||
p->endpoint.pChunk = pIter;
|
||||
p->endpoint.iOffset = size;
|
||||
p->readpoint.pChunk = 0;
|
||||
p->readpoint.iOffset = 0;
|
||||
}
|
||||
|
||||
p->endpoint.pChunk = pIter;
|
||||
p->endpoint.iOffset = size;
|
||||
p->readpoint.pChunk = 0;
|
||||
p->readpoint.iOffset = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
@ -356,6 +359,8 @@ int sqlite3JournalOpen(
|
|||
){
|
||||
MemJournal *p = (MemJournal*)pJfd;
|
||||
|
||||
assert( zName || nSpill<0 || (flags & SQLITE_OPEN_EXCLUSIVE) );
|
||||
|
||||
/* Zero the file-handle object. If nSpill was passed zero, initialize
|
||||
** it using the sqlite3OsOpen() function of the underlying VFS. In this
|
||||
** case none of the code in this module is executed as a result of calls
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
*/
|
||||
#ifndef SQLITE_MSVC_H
|
||||
#define SQLITE_MSVC_H
|
||||
/* clang-format off */
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable : 4054)
|
3
third_party/sqlite3/mutex.c
vendored
3
third_party/sqlite3/mutex.c
vendored
|
@ -13,8 +13,7 @@
|
|||
**
|
||||
** This file contains code that is common across all mutex implementations.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
#if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT)
|
||||
/*
|
||||
|
|
1
third_party/sqlite3/mutex.inc
vendored
1
third_party/sqlite3/mutex.inc
vendored
|
@ -19,7 +19,6 @@
|
|||
** Source files should #include the sqliteInt.h file and let that file
|
||||
** include this one indirectly.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
|
||||
/*
|
||||
|
|
3
third_party/sqlite3/mutex_noop.c
vendored
3
third_party/sqlite3/mutex_noop.c
vendored
|
@ -25,8 +25,7 @@
|
|||
** that does error checking on mutexes to make sure they are being
|
||||
** called correctly.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
#ifndef SQLITE_MUTEX_OMIT
|
||||
|
||||
|
|
6
third_party/sqlite3/mutex_unix.c
vendored
6
third_party/sqlite3/mutex_unix.c
vendored
|
@ -11,9 +11,7 @@
|
|||
*************************************************************************
|
||||
** This file contains the C functions that implement mutexes for pthreads
|
||||
*/
|
||||
#include "libc/thread/thread.h"
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/*
|
||||
** The code in this file is only used if we are compiling threadsafe
|
||||
|
@ -24,6 +22,8 @@
|
|||
*/
|
||||
#ifdef SQLITE_MUTEX_PTHREADS
|
||||
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
/*
|
||||
** The sqlite3_mutex.id, sqlite3_mutex.nRef, and sqlite3_mutex.owner fields
|
||||
** are necessary under two condidtions: (1) Debug builds and (2) using
|
||||
|
|
5
third_party/sqlite3/notify.c
vendored
5
third_party/sqlite3/notify.c
vendored
|
@ -13,9 +13,8 @@
|
|||
** This file contains the implementation of the sqlite3_unlock_notify()
|
||||
** API method and its associated functionality.
|
||||
*/
|
||||
#include "third_party/sqlite3/btreeInt.inc"
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
#include "third_party/sqlite3/btreeInt.h"
|
||||
|
||||
/* Omit this entire file if SQLITE_ENABLE_UNLOCK_NOTIFY is not defined. */
|
||||
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
|
|
319
third_party/sqlite3/opcodes.c
vendored
319
third_party/sqlite3/opcodes.c
vendored
|
@ -1,4 +1,3 @@
|
|||
/* clang-format off */
|
||||
/* Automatically generated. Do not edit */
|
||||
/* See the tool/mkopcodec.tcl script for details. */
|
||||
#if !defined(SQLITE_OMIT_EXPLAIN) \
|
||||
|
@ -14,53 +13,53 @@ const char *sqlite3OpcodeName(int i){
|
|||
/* 0 */ "Savepoint" OpHelp(""),
|
||||
/* 1 */ "AutoCommit" OpHelp(""),
|
||||
/* 2 */ "Transaction" OpHelp(""),
|
||||
/* 3 */ "SorterNext" OpHelp(""),
|
||||
/* 4 */ "Prev" OpHelp(""),
|
||||
/* 5 */ "Next" OpHelp(""),
|
||||
/* 6 */ "Checkpoint" OpHelp(""),
|
||||
/* 7 */ "JournalMode" OpHelp(""),
|
||||
/* 8 */ "Vacuum" OpHelp(""),
|
||||
/* 9 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"),
|
||||
/* 10 */ "VUpdate" OpHelp("data=r[P3@P2]"),
|
||||
/* 11 */ "Goto" OpHelp(""),
|
||||
/* 12 */ "Gosub" OpHelp(""),
|
||||
/* 13 */ "InitCoroutine" OpHelp(""),
|
||||
/* 14 */ "Yield" OpHelp(""),
|
||||
/* 15 */ "MustBeInt" OpHelp(""),
|
||||
/* 16 */ "Jump" OpHelp(""),
|
||||
/* 17 */ "Once" OpHelp(""),
|
||||
/* 18 */ "If" OpHelp(""),
|
||||
/* 3 */ "Checkpoint" OpHelp(""),
|
||||
/* 4 */ "JournalMode" OpHelp(""),
|
||||
/* 5 */ "Vacuum" OpHelp(""),
|
||||
/* 6 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"),
|
||||
/* 7 */ "VUpdate" OpHelp("data=r[P3@P2]"),
|
||||
/* 8 */ "Init" OpHelp("Start at P2"),
|
||||
/* 9 */ "Goto" OpHelp(""),
|
||||
/* 10 */ "Gosub" OpHelp(""),
|
||||
/* 11 */ "InitCoroutine" OpHelp(""),
|
||||
/* 12 */ "Yield" OpHelp(""),
|
||||
/* 13 */ "MustBeInt" OpHelp(""),
|
||||
/* 14 */ "Jump" OpHelp(""),
|
||||
/* 15 */ "Once" OpHelp(""),
|
||||
/* 16 */ "If" OpHelp(""),
|
||||
/* 17 */ "IfNot" OpHelp(""),
|
||||
/* 18 */ "IsType" OpHelp("if typeof(P1.P3) in P5 goto P2"),
|
||||
/* 19 */ "Not" OpHelp("r[P2]= !r[P1]"),
|
||||
/* 20 */ "IfNot" OpHelp(""),
|
||||
/* 21 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"),
|
||||
/* 22 */ "SeekLT" OpHelp("key=r[P3@P4]"),
|
||||
/* 23 */ "SeekLE" OpHelp("key=r[P3@P4]"),
|
||||
/* 24 */ "SeekGE" OpHelp("key=r[P3@P4]"),
|
||||
/* 25 */ "SeekGT" OpHelp("key=r[P3@P4]"),
|
||||
/* 26 */ "IfNotOpen" OpHelp("if( !csr[P1] ) goto P2"),
|
||||
/* 27 */ "IfNoHope" OpHelp("key=r[P3@P4]"),
|
||||
/* 28 */ "NoConflict" OpHelp("key=r[P3@P4]"),
|
||||
/* 29 */ "NotFound" OpHelp("key=r[P3@P4]"),
|
||||
/* 30 */ "Found" OpHelp("key=r[P3@P4]"),
|
||||
/* 31 */ "SeekRowid" OpHelp("intkey=r[P3]"),
|
||||
/* 32 */ "NotExists" OpHelp("intkey=r[P3]"),
|
||||
/* 33 */ "Last" OpHelp(""),
|
||||
/* 34 */ "IfSmaller" OpHelp(""),
|
||||
/* 35 */ "SorterSort" OpHelp(""),
|
||||
/* 36 */ "Sort" OpHelp(""),
|
||||
/* 37 */ "Rewind" OpHelp(""),
|
||||
/* 38 */ "IdxLE" OpHelp("key=r[P3@P4]"),
|
||||
/* 39 */ "IdxGT" OpHelp("key=r[P3@P4]"),
|
||||
/* 40 */ "IdxLT" OpHelp("key=r[P3@P4]"),
|
||||
/* 41 */ "IdxGE" OpHelp("key=r[P3@P4]"),
|
||||
/* 42 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
|
||||
/* 20 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"),
|
||||
/* 21 */ "SeekLT" OpHelp("key=r[P3@P4]"),
|
||||
/* 22 */ "SeekLE" OpHelp("key=r[P3@P4]"),
|
||||
/* 23 */ "SeekGE" OpHelp("key=r[P3@P4]"),
|
||||
/* 24 */ "SeekGT" OpHelp("key=r[P3@P4]"),
|
||||
/* 25 */ "IfNotOpen" OpHelp("if( !csr[P1] ) goto P2"),
|
||||
/* 26 */ "IfNoHope" OpHelp("key=r[P3@P4]"),
|
||||
/* 27 */ "NoConflict" OpHelp("key=r[P3@P4]"),
|
||||
/* 28 */ "NotFound" OpHelp("key=r[P3@P4]"),
|
||||
/* 29 */ "Found" OpHelp("key=r[P3@P4]"),
|
||||
/* 30 */ "SeekRowid" OpHelp("intkey=r[P3]"),
|
||||
/* 31 */ "NotExists" OpHelp("intkey=r[P3]"),
|
||||
/* 32 */ "Last" OpHelp(""),
|
||||
/* 33 */ "IfSmaller" OpHelp(""),
|
||||
/* 34 */ "SorterSort" OpHelp(""),
|
||||
/* 35 */ "Sort" OpHelp(""),
|
||||
/* 36 */ "Rewind" OpHelp(""),
|
||||
/* 37 */ "SorterNext" OpHelp(""),
|
||||
/* 38 */ "Prev" OpHelp(""),
|
||||
/* 39 */ "Next" OpHelp(""),
|
||||
/* 40 */ "IdxLE" OpHelp("key=r[P3@P4]"),
|
||||
/* 41 */ "IdxGT" OpHelp("key=r[P3@P4]"),
|
||||
/* 42 */ "IdxLT" OpHelp("key=r[P3@P4]"),
|
||||
/* 43 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
|
||||
/* 44 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
|
||||
/* 45 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
|
||||
/* 46 */ "Program" OpHelp(""),
|
||||
/* 47 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
|
||||
/* 48 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
|
||||
/* 49 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
|
||||
/* 45 */ "IdxGE" OpHelp("key=r[P3@P4]"),
|
||||
/* 46 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
|
||||
/* 47 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
|
||||
/* 48 */ "Program" OpHelp(""),
|
||||
/* 49 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
|
||||
/* 50 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
|
||||
/* 51 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
|
||||
/* 52 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
|
||||
|
@ -69,50 +68,50 @@ const char *sqlite3OpcodeName(int i){
|
|||
/* 55 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
|
||||
/* 56 */ "Lt" OpHelp("IF r[P3]<r[P1]"),
|
||||
/* 57 */ "Ge" OpHelp("IF r[P3]>=r[P1]"),
|
||||
/* 58 */ "ElseNotEq" OpHelp(""),
|
||||
/* 59 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
|
||||
/* 60 */ "IncrVacuum" OpHelp(""),
|
||||
/* 61 */ "VNext" OpHelp(""),
|
||||
/* 62 */ "Init" OpHelp("Start at P2"),
|
||||
/* 63 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"),
|
||||
/* 64 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"),
|
||||
/* 65 */ "Return" OpHelp(""),
|
||||
/* 66 */ "EndCoroutine" OpHelp(""),
|
||||
/* 67 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
|
||||
/* 68 */ "Halt" OpHelp(""),
|
||||
/* 69 */ "Integer" OpHelp("r[P2]=P1"),
|
||||
/* 70 */ "Int64" OpHelp("r[P2]=P4"),
|
||||
/* 71 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
|
||||
/* 72 */ "Null" OpHelp("r[P2..P3]=NULL"),
|
||||
/* 73 */ "SoftNull" OpHelp("r[P1]=NULL"),
|
||||
/* 74 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
|
||||
/* 75 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
|
||||
/* 76 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
|
||||
/* 77 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
|
||||
/* 78 */ "SCopy" OpHelp("r[P2]=r[P1]"),
|
||||
/* 79 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
|
||||
/* 80 */ "ChngCntRow" OpHelp("output=r[P1]"),
|
||||
/* 81 */ "ResultRow" OpHelp("output=r[P1@P2]"),
|
||||
/* 82 */ "CollSeq" OpHelp(""),
|
||||
/* 83 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
|
||||
/* 84 */ "RealAffinity" OpHelp(""),
|
||||
/* 85 */ "Cast" OpHelp("affinity(r[P1])"),
|
||||
/* 86 */ "Permutation" OpHelp(""),
|
||||
/* 87 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
|
||||
/* 88 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
|
||||
/* 89 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
|
||||
/* 90 */ "Column" OpHelp("r[P3]=PX"),
|
||||
/* 91 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
|
||||
/* 92 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
|
||||
/* 93 */ "Count" OpHelp("r[P2]=count()"),
|
||||
/* 94 */ "ReadCookie" OpHelp(""),
|
||||
/* 95 */ "SetCookie" OpHelp(""),
|
||||
/* 96 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
|
||||
/* 97 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
|
||||
/* 98 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
|
||||
/* 99 */ "OpenDup" OpHelp(""),
|
||||
/* 100 */ "OpenAutoindex" OpHelp("nColumn=P2"),
|
||||
/* 101 */ "OpenEphemeral" OpHelp("nColumn=P2"),
|
||||
/* 58 */ "ElseEq" OpHelp(""),
|
||||
/* 59 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
|
||||
/* 60 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
|
||||
/* 61 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
|
||||
/* 62 */ "IncrVacuum" OpHelp(""),
|
||||
/* 63 */ "VNext" OpHelp(""),
|
||||
/* 64 */ "Filter" OpHelp("if key(P3@P4) not in filter(P1) goto P2"),
|
||||
/* 65 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"),
|
||||
/* 66 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"),
|
||||
/* 67 */ "Return" OpHelp(""),
|
||||
/* 68 */ "EndCoroutine" OpHelp(""),
|
||||
/* 69 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
|
||||
/* 70 */ "Halt" OpHelp(""),
|
||||
/* 71 */ "Integer" OpHelp("r[P2]=P1"),
|
||||
/* 72 */ "Int64" OpHelp("r[P2]=P4"),
|
||||
/* 73 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
|
||||
/* 74 */ "BeginSubrtn" OpHelp("r[P2]=NULL"),
|
||||
/* 75 */ "Null" OpHelp("r[P2..P3]=NULL"),
|
||||
/* 76 */ "SoftNull" OpHelp("r[P1]=NULL"),
|
||||
/* 77 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
|
||||
/* 78 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
|
||||
/* 79 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
|
||||
/* 80 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
|
||||
/* 81 */ "SCopy" OpHelp("r[P2]=r[P1]"),
|
||||
/* 82 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
|
||||
/* 83 */ "FkCheck" OpHelp(""),
|
||||
/* 84 */ "ResultRow" OpHelp("output=r[P1@P2]"),
|
||||
/* 85 */ "CollSeq" OpHelp(""),
|
||||
/* 86 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
|
||||
/* 87 */ "RealAffinity" OpHelp(""),
|
||||
/* 88 */ "Cast" OpHelp("affinity(r[P1])"),
|
||||
/* 89 */ "Permutation" OpHelp(""),
|
||||
/* 90 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
|
||||
/* 91 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
|
||||
/* 92 */ "ZeroOrNull" OpHelp("r[P2] = 0 OR NULL"),
|
||||
/* 93 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
|
||||
/* 94 */ "Column" OpHelp("r[P3]=PX cursor P1 column P2"),
|
||||
/* 95 */ "TypeCheck" OpHelp("typecheck(r[P1@P2])"),
|
||||
/* 96 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
|
||||
/* 97 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
|
||||
/* 98 */ "Count" OpHelp("r[P2]=count()"),
|
||||
/* 99 */ "ReadCookie" OpHelp(""),
|
||||
/* 100 */ "SetCookie" OpHelp(""),
|
||||
/* 101 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
|
||||
/* 102 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
|
||||
/* 103 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
|
||||
/* 104 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
|
||||
|
@ -123,73 +122,81 @@ const char *sqlite3OpcodeName(int i){
|
|||
/* 109 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
|
||||
/* 110 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
|
||||
/* 111 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
|
||||
/* 112 */ "SorterOpen" OpHelp(""),
|
||||
/* 113 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
|
||||
/* 114 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
|
||||
/* 115 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
|
||||
/* 116 */ "String8" OpHelp("r[P2]='P4'"),
|
||||
/* 117 */ "Close" OpHelp(""),
|
||||
/* 118 */ "ColumnsUsed" OpHelp(""),
|
||||
/* 119 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"),
|
||||
/* 120 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"),
|
||||
/* 121 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
|
||||
/* 122 */ "NewRowid" OpHelp("r[P2]=rowid"),
|
||||
/* 123 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
|
||||
/* 124 */ "RowCell" OpHelp(""),
|
||||
/* 125 */ "Delete" OpHelp(""),
|
||||
/* 126 */ "ResetCount" OpHelp(""),
|
||||
/* 127 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
|
||||
/* 128 */ "SorterData" OpHelp("r[P2]=data"),
|
||||
/* 129 */ "RowData" OpHelp("r[P2]=data"),
|
||||
/* 130 */ "Rowid" OpHelp("r[P2]=rowid"),
|
||||
/* 131 */ "NullRow" OpHelp(""),
|
||||
/* 132 */ "SeekEnd" OpHelp(""),
|
||||
/* 133 */ "IdxInsert" OpHelp("key=r[P2]"),
|
||||
/* 134 */ "SorterInsert" OpHelp("key=r[P2]"),
|
||||
/* 135 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
|
||||
/* 136 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
|
||||
/* 137 */ "IdxRowid" OpHelp("r[P2]=rowid"),
|
||||
/* 138 */ "FinishSeek" OpHelp(""),
|
||||
/* 139 */ "Destroy" OpHelp(""),
|
||||
/* 140 */ "Clear" OpHelp(""),
|
||||
/* 141 */ "ResetSorter" OpHelp(""),
|
||||
/* 142 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
|
||||
/* 143 */ "SqlExec" OpHelp(""),
|
||||
/* 144 */ "ParseSchema" OpHelp(""),
|
||||
/* 145 */ "LoadAnalysis" OpHelp(""),
|
||||
/* 146 */ "DropTable" OpHelp(""),
|
||||
/* 147 */ "DropIndex" OpHelp(""),
|
||||
/* 148 */ "DropTrigger" OpHelp(""),
|
||||
/* 149 */ "IntegrityCk" OpHelp(""),
|
||||
/* 150 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
|
||||
/* 151 */ "Param" OpHelp(""),
|
||||
/* 152 */ "Real" OpHelp("r[P2]=P4"),
|
||||
/* 153 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
|
||||
/* 154 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
|
||||
/* 155 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
|
||||
/* 156 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
|
||||
/* 157 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
|
||||
/* 158 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
|
||||
/* 159 */ "AggValue" OpHelp("r[P3]=value N=P2"),
|
||||
/* 160 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
|
||||
/* 161 */ "Expire" OpHelp(""),
|
||||
/* 162 */ "CursorLock" OpHelp(""),
|
||||
/* 163 */ "CursorUnlock" OpHelp(""),
|
||||
/* 164 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
|
||||
/* 165 */ "VBegin" OpHelp(""),
|
||||
/* 166 */ "VCreate" OpHelp(""),
|
||||
/* 167 */ "VDestroy" OpHelp(""),
|
||||
/* 168 */ "VOpen" OpHelp(""),
|
||||
/* 169 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
|
||||
/* 170 */ "VRename" OpHelp(""),
|
||||
/* 171 */ "Pagecount" OpHelp(""),
|
||||
/* 172 */ "MaxPgcnt" OpHelp(""),
|
||||
/* 173 */ "Trace" OpHelp(""),
|
||||
/* 174 */ "CursorHint" OpHelp(""),
|
||||
/* 175 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
|
||||
/* 176 */ "Noop" OpHelp(""),
|
||||
/* 177 */ "Explain" OpHelp(""),
|
||||
/* 178 */ "Abortable" OpHelp(""),
|
||||
/* 112 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
|
||||
/* 113 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
|
||||
/* 114 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
|
||||
/* 115 */ "OpenDup" OpHelp(""),
|
||||
/* 116 */ "OpenAutoindex" OpHelp("nColumn=P2"),
|
||||
/* 117 */ "String8" OpHelp("r[P2]='P4'"),
|
||||
/* 118 */ "OpenEphemeral" OpHelp("nColumn=P2"),
|
||||
/* 119 */ "SorterOpen" OpHelp(""),
|
||||
/* 120 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
|
||||
/* 121 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
|
||||
/* 122 */ "Close" OpHelp(""),
|
||||
/* 123 */ "ColumnsUsed" OpHelp(""),
|
||||
/* 124 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"),
|
||||
/* 125 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"),
|
||||
/* 126 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
|
||||
/* 127 */ "NewRowid" OpHelp("r[P2]=rowid"),
|
||||
/* 128 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
|
||||
/* 129 */ "RowCell" OpHelp(""),
|
||||
/* 130 */ "Delete" OpHelp(""),
|
||||
/* 131 */ "ResetCount" OpHelp(""),
|
||||
/* 132 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
|
||||
/* 133 */ "SorterData" OpHelp("r[P2]=data"),
|
||||
/* 134 */ "RowData" OpHelp("r[P2]=data"),
|
||||
/* 135 */ "Rowid" OpHelp("r[P2]=PX rowid of P1"),
|
||||
/* 136 */ "NullRow" OpHelp(""),
|
||||
/* 137 */ "SeekEnd" OpHelp(""),
|
||||
/* 138 */ "IdxInsert" OpHelp("key=r[P2]"),
|
||||
/* 139 */ "SorterInsert" OpHelp("key=r[P2]"),
|
||||
/* 140 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
|
||||
/* 141 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
|
||||
/* 142 */ "IdxRowid" OpHelp("r[P2]=rowid"),
|
||||
/* 143 */ "FinishSeek" OpHelp(""),
|
||||
/* 144 */ "Destroy" OpHelp(""),
|
||||
/* 145 */ "Clear" OpHelp(""),
|
||||
/* 146 */ "ResetSorter" OpHelp(""),
|
||||
/* 147 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
|
||||
/* 148 */ "SqlExec" OpHelp(""),
|
||||
/* 149 */ "ParseSchema" OpHelp(""),
|
||||
/* 150 */ "LoadAnalysis" OpHelp(""),
|
||||
/* 151 */ "DropTable" OpHelp(""),
|
||||
/* 152 */ "DropIndex" OpHelp(""),
|
||||
/* 153 */ "Real" OpHelp("r[P2]=P4"),
|
||||
/* 154 */ "DropTrigger" OpHelp(""),
|
||||
/* 155 */ "IntegrityCk" OpHelp(""),
|
||||
/* 156 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
|
||||
/* 157 */ "Param" OpHelp(""),
|
||||
/* 158 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
|
||||
/* 159 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
|
||||
/* 160 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
|
||||
/* 161 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
|
||||
/* 162 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
|
||||
/* 163 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
|
||||
/* 164 */ "AggValue" OpHelp("r[P3]=value N=P2"),
|
||||
/* 165 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
|
||||
/* 166 */ "Expire" OpHelp(""),
|
||||
/* 167 */ "CursorLock" OpHelp(""),
|
||||
/* 168 */ "CursorUnlock" OpHelp(""),
|
||||
/* 169 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
|
||||
/* 170 */ "VBegin" OpHelp(""),
|
||||
/* 171 */ "VCreate" OpHelp(""),
|
||||
/* 172 */ "VDestroy" OpHelp(""),
|
||||
/* 173 */ "VOpen" OpHelp(""),
|
||||
/* 174 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"),
|
||||
/* 175 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
|
||||
/* 176 */ "VRename" OpHelp(""),
|
||||
/* 177 */ "Pagecount" OpHelp(""),
|
||||
/* 178 */ "MaxPgcnt" OpHelp(""),
|
||||
/* 179 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"),
|
||||
/* 180 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"),
|
||||
/* 181 */ "Trace" OpHelp(""),
|
||||
/* 182 */ "CursorHint" OpHelp(""),
|
||||
/* 183 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
|
||||
/* 184 */ "Noop" OpHelp(""),
|
||||
/* 185 */ "Explain" OpHelp(""),
|
||||
/* 186 */ "Abortable" OpHelp(""),
|
||||
};
|
||||
return azName[i];
|
||||
}
|
||||
|
|
233
third_party/sqlite3/opcodes.h
vendored
Normal file
233
third_party/sqlite3/opcodes.h
vendored
Normal file
|
@ -0,0 +1,233 @@
|
|||
/* Automatically generated. Do not edit */
|
||||
/* See the tool/mkopcodeh.tcl script for details */
|
||||
#define OP_Savepoint 0
|
||||
#define OP_AutoCommit 1
|
||||
#define OP_Transaction 2
|
||||
#define OP_Checkpoint 3
|
||||
#define OP_JournalMode 4
|
||||
#define OP_Vacuum 5
|
||||
#define OP_VFilter 6 /* jump, synopsis: iplan=r[P3] zplan='P4' */
|
||||
#define OP_VUpdate 7 /* synopsis: data=r[P3@P2] */
|
||||
#define OP_Init 8 /* jump, synopsis: Start at P2 */
|
||||
#define OP_Goto 9 /* jump */
|
||||
#define OP_Gosub 10 /* jump */
|
||||
#define OP_InitCoroutine 11 /* jump */
|
||||
#define OP_Yield 12 /* jump */
|
||||
#define OP_MustBeInt 13 /* jump */
|
||||
#define OP_Jump 14 /* jump */
|
||||
#define OP_Once 15 /* jump */
|
||||
#define OP_If 16 /* jump */
|
||||
#define OP_IfNot 17 /* jump */
|
||||
#define OP_IsType 18 /* jump, synopsis: if typeof(P1.P3) in P5 goto P2 */
|
||||
#define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */
|
||||
#define OP_IfNullRow 20 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */
|
||||
#define OP_SeekLT 21 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_SeekLE 22 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_SeekGE 23 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_SeekGT 24 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_IfNotOpen 25 /* jump, synopsis: if( !csr[P1] ) goto P2 */
|
||||
#define OP_IfNoHope 26 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_NoConflict 27 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_NotFound 28 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_Found 29 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_SeekRowid 30 /* jump, synopsis: intkey=r[P3] */
|
||||
#define OP_NotExists 31 /* jump, synopsis: intkey=r[P3] */
|
||||
#define OP_Last 32 /* jump */
|
||||
#define OP_IfSmaller 33 /* jump */
|
||||
#define OP_SorterSort 34 /* jump */
|
||||
#define OP_Sort 35 /* jump */
|
||||
#define OP_Rewind 36 /* jump */
|
||||
#define OP_SorterNext 37 /* jump */
|
||||
#define OP_Prev 38 /* jump */
|
||||
#define OP_Next 39 /* jump */
|
||||
#define OP_IdxLE 40 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_IdxGT 41 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_IdxLT 42 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_Or 43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
|
||||
#define OP_And 44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
|
||||
#define OP_IdxGE 45 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_RowSetRead 46 /* jump, synopsis: r[P3]=rowset(P1) */
|
||||
#define OP_RowSetTest 47 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
|
||||
#define OP_Program 48 /* jump */
|
||||
#define OP_FkIfZero 49 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
|
||||
#define OP_IsNull 50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
|
||||
#define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
|
||||
#define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
|
||||
#define OP_Eq 53 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
|
||||
#define OP_Gt 54 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
|
||||
#define OP_Le 55 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
|
||||
#define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
|
||||
#define OP_Ge 57 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
|
||||
#define OP_ElseEq 58 /* jump, same as TK_ESCAPE */
|
||||
#define OP_IfPos 59 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
|
||||
#define OP_IfNotZero 60 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
|
||||
#define OP_DecrJumpZero 61 /* jump, synopsis: if (--r[P1])==0 goto P2 */
|
||||
#define OP_IncrVacuum 62 /* jump */
|
||||
#define OP_VNext 63 /* jump */
|
||||
#define OP_Filter 64 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto P2 */
|
||||
#define OP_PureFunc 65 /* synopsis: r[P3]=func(r[P2@NP]) */
|
||||
#define OP_Function 66 /* synopsis: r[P3]=func(r[P2@NP]) */
|
||||
#define OP_Return 67
|
||||
#define OP_EndCoroutine 68
|
||||
#define OP_HaltIfNull 69 /* synopsis: if r[P3]=null halt */
|
||||
#define OP_Halt 70
|
||||
#define OP_Integer 71 /* synopsis: r[P2]=P1 */
|
||||
#define OP_Int64 72 /* synopsis: r[P2]=P4 */
|
||||
#define OP_String 73 /* synopsis: r[P2]='P4' (len=P1) */
|
||||
#define OP_BeginSubrtn 74 /* synopsis: r[P2]=NULL */
|
||||
#define OP_Null 75 /* synopsis: r[P2..P3]=NULL */
|
||||
#define OP_SoftNull 76 /* synopsis: r[P1]=NULL */
|
||||
#define OP_Blob 77 /* synopsis: r[P2]=P4 (len=P1) */
|
||||
#define OP_Variable 78 /* synopsis: r[P2]=parameter(P1,P4) */
|
||||
#define OP_Move 79 /* synopsis: r[P2@P3]=r[P1@P3] */
|
||||
#define OP_Copy 80 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
|
||||
#define OP_SCopy 81 /* synopsis: r[P2]=r[P1] */
|
||||
#define OP_IntCopy 82 /* synopsis: r[P2]=r[P1] */
|
||||
#define OP_FkCheck 83
|
||||
#define OP_ResultRow 84 /* synopsis: output=r[P1@P2] */
|
||||
#define OP_CollSeq 85
|
||||
#define OP_AddImm 86 /* synopsis: r[P1]=r[P1]+P2 */
|
||||
#define OP_RealAffinity 87
|
||||
#define OP_Cast 88 /* synopsis: affinity(r[P1]) */
|
||||
#define OP_Permutation 89
|
||||
#define OP_Compare 90 /* synopsis: r[P1@P3] <-> r[P2@P3] */
|
||||
#define OP_IsTrue 91 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
|
||||
#define OP_ZeroOrNull 92 /* synopsis: r[P2] = 0 OR NULL */
|
||||
#define OP_Offset 93 /* synopsis: r[P3] = sqlite_offset(P1) */
|
||||
#define OP_Column 94 /* synopsis: r[P3]=PX cursor P1 column P2 */
|
||||
#define OP_TypeCheck 95 /* synopsis: typecheck(r[P1@P2]) */
|
||||
#define OP_Affinity 96 /* synopsis: affinity(r[P1@P2]) */
|
||||
#define OP_MakeRecord 97 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
|
||||
#define OP_Count 98 /* synopsis: r[P2]=count() */
|
||||
#define OP_ReadCookie 99
|
||||
#define OP_SetCookie 100
|
||||
#define OP_ReopenIdx 101 /* synopsis: root=P2 iDb=P3 */
|
||||
#define OP_BitAnd 102 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
|
||||
#define OP_BitOr 103 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
|
||||
#define OP_ShiftLeft 104 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
|
||||
#define OP_ShiftRight 105 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
|
||||
#define OP_Add 106 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
|
||||
#define OP_Subtract 107 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
|
||||
#define OP_Multiply 108 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
|
||||
#define OP_Divide 109 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
|
||||
#define OP_Remainder 110 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
|
||||
#define OP_Concat 111 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
|
||||
#define OP_OpenRead 112 /* synopsis: root=P2 iDb=P3 */
|
||||
#define OP_OpenWrite 113 /* synopsis: root=P2 iDb=P3 */
|
||||
#define OP_BitNot 114 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
|
||||
#define OP_OpenDup 115
|
||||
#define OP_OpenAutoindex 116 /* synopsis: nColumn=P2 */
|
||||
#define OP_String8 117 /* same as TK_STRING, synopsis: r[P2]='P4' */
|
||||
#define OP_OpenEphemeral 118 /* synopsis: nColumn=P2 */
|
||||
#define OP_SorterOpen 119
|
||||
#define OP_SequenceTest 120 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
|
||||
#define OP_OpenPseudo 121 /* synopsis: P3 columns in r[P2] */
|
||||
#define OP_Close 122
|
||||
#define OP_ColumnsUsed 123
|
||||
#define OP_SeekScan 124 /* synopsis: Scan-ahead up to P1 rows */
|
||||
#define OP_SeekHit 125 /* synopsis: set P2<=seekHit<=P3 */
|
||||
#define OP_Sequence 126 /* synopsis: r[P2]=cursor[P1].ctr++ */
|
||||
#define OP_NewRowid 127 /* synopsis: r[P2]=rowid */
|
||||
#define OP_Insert 128 /* synopsis: intkey=r[P3] data=r[P2] */
|
||||
#define OP_RowCell 129
|
||||
#define OP_Delete 130
|
||||
#define OP_ResetCount 131
|
||||
#define OP_SorterCompare 132 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
|
||||
#define OP_SorterData 133 /* synopsis: r[P2]=data */
|
||||
#define OP_RowData 134 /* synopsis: r[P2]=data */
|
||||
#define OP_Rowid 135 /* synopsis: r[P2]=PX rowid of P1 */
|
||||
#define OP_NullRow 136
|
||||
#define OP_SeekEnd 137
|
||||
#define OP_IdxInsert 138 /* synopsis: key=r[P2] */
|
||||
#define OP_SorterInsert 139 /* synopsis: key=r[P2] */
|
||||
#define OP_IdxDelete 140 /* synopsis: key=r[P2@P3] */
|
||||
#define OP_DeferredSeek 141 /* synopsis: Move P3 to P1.rowid if needed */
|
||||
#define OP_IdxRowid 142 /* synopsis: r[P2]=rowid */
|
||||
#define OP_FinishSeek 143
|
||||
#define OP_Destroy 144
|
||||
#define OP_Clear 145
|
||||
#define OP_ResetSorter 146
|
||||
#define OP_CreateBtree 147 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
|
||||
#define OP_SqlExec 148
|
||||
#define OP_ParseSchema 149
|
||||
#define OP_LoadAnalysis 150
|
||||
#define OP_DropTable 151
|
||||
#define OP_DropIndex 152
|
||||
#define OP_Real 153 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
|
||||
#define OP_DropTrigger 154
|
||||
#define OP_IntegrityCk 155
|
||||
#define OP_RowSetAdd 156 /* synopsis: rowset(P1)=r[P2] */
|
||||
#define OP_Param 157
|
||||
#define OP_FkCounter 158 /* synopsis: fkctr[P1]+=P2 */
|
||||
#define OP_MemMax 159 /* synopsis: r[P1]=max(r[P1],r[P2]) */
|
||||
#define OP_OffsetLimit 160 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
|
||||
#define OP_AggInverse 161 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
|
||||
#define OP_AggStep 162 /* synopsis: accum=r[P3] step(r[P2@P5]) */
|
||||
#define OP_AggStep1 163 /* synopsis: accum=r[P3] step(r[P2@P5]) */
|
||||
#define OP_AggValue 164 /* synopsis: r[P3]=value N=P2 */
|
||||
#define OP_AggFinal 165 /* synopsis: accum=r[P1] N=P2 */
|
||||
#define OP_Expire 166
|
||||
#define OP_CursorLock 167
|
||||
#define OP_CursorUnlock 168
|
||||
#define OP_TableLock 169 /* synopsis: iDb=P1 root=P2 write=P3 */
|
||||
#define OP_VBegin 170
|
||||
#define OP_VCreate 171
|
||||
#define OP_VDestroy 172
|
||||
#define OP_VOpen 173
|
||||
#define OP_VInitIn 174 /* synopsis: r[P2]=ValueList(P1,P3) */
|
||||
#define OP_VColumn 175 /* synopsis: r[P3]=vcolumn(P2) */
|
||||
#define OP_VRename 176
|
||||
#define OP_Pagecount 177
|
||||
#define OP_MaxPgcnt 178
|
||||
#define OP_ClrSubtype 179 /* synopsis: r[P1].subtype = 0 */
|
||||
#define OP_FilterAdd 180 /* synopsis: filter(P1) += key(P3@P4) */
|
||||
#define OP_Trace 181
|
||||
#define OP_CursorHint 182
|
||||
#define OP_ReleaseReg 183 /* synopsis: release r[P1@P2] mask P3 */
|
||||
#define OP_Noop 184
|
||||
#define OP_Explain 185
|
||||
#define OP_Abortable 186
|
||||
|
||||
/* Properties such as "out2" or "jump" that are specified in
|
||||
** comments following the "case" for each opcode in the vdbe.c
|
||||
** are encoded into bitvectors as follows:
|
||||
*/
|
||||
#define OPFLG_JUMP 0x01 /* jump: P2 holds jmp target */
|
||||
#define OPFLG_IN1 0x02 /* in1: P1 is an input */
|
||||
#define OPFLG_IN2 0x04 /* in2: P2 is an input */
|
||||
#define OPFLG_IN3 0x08 /* in3: P3 is an input */
|
||||
#define OPFLG_OUT2 0x10 /* out2: P2 is an output */
|
||||
#define OPFLG_OUT3 0x20 /* out3: P3 is an output */
|
||||
#define OPFLG_INITIALIZER {\
|
||||
/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,\
|
||||
/* 8 */ 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01,\
|
||||
/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x09, 0x09, 0x09,\
|
||||
/* 24 */ 0x09, 0x01, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,\
|
||||
/* 32 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
|
||||
/* 40 */ 0x01, 0x01, 0x01, 0x26, 0x26, 0x01, 0x23, 0x0b,\
|
||||
/* 48 */ 0x01, 0x01, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
|
||||
/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x03, 0x01, 0x01,\
|
||||
/* 64 */ 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10,\
|
||||
/* 72 */ 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x00,\
|
||||
/* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02,\
|
||||
/* 88 */ 0x02, 0x00, 0x00, 0x12, 0x1e, 0x20, 0x00, 0x00,\
|
||||
/* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x26, 0x26,\
|
||||
/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\
|
||||
/* 112 */ 0x00, 0x00, 0x12, 0x00, 0x00, 0x10, 0x00, 0x00,\
|
||||
/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\
|
||||
/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\
|
||||
/* 136 */ 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10, 0x00,\
|
||||
/* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\
|
||||
/* 152 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\
|
||||
/* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
|
||||
/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,\
|
||||
/* 176 */ 0x00, 0x10, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00,\
|
||||
/* 184 */ 0x00, 0x00, 0x00,}
|
||||
|
||||
/* The resolve3P2Values() routine is able to run faster if it knows
|
||||
** the value of the largest JUMP opcode. The smaller the maximum
|
||||
** JUMP opcode the better, so the mkopcodeh.tcl script that
|
||||
** generated this include file strives to group all JUMP opcodes
|
||||
** together near the beginning of the list.
|
||||
*/
|
||||
#define SQLITE_MX_JUMP_OPCODE 64 /* Maximum JUMP opcode */
|
232
third_party/sqlite3/opcodes.inc
vendored
232
third_party/sqlite3/opcodes.inc
vendored
|
@ -1,232 +0,0 @@
|
|||
/* Automatically generated. Do not edit */
|
||||
/* See the tool/mkopcodeh.tcl script for details */
|
||||
#define OP_Savepoint 0
|
||||
#define OP_AutoCommit 1
|
||||
#define OP_Transaction 2
|
||||
#define OP_SorterNext 3 /* jump */
|
||||
#define OP_Prev 4 /* jump */
|
||||
#define OP_Next 5 /* jump */
|
||||
#define OP_Checkpoint 6
|
||||
#define OP_JournalMode 7
|
||||
#define OP_Vacuum 8
|
||||
#define OP_VFilter 9 /* jump, synopsis: iplan=r[P3] zplan='P4' */
|
||||
#define OP_VUpdate 10 /* synopsis: data=r[P3@P2] */
|
||||
#define OP_Goto 11 /* jump */
|
||||
#define OP_Gosub 12 /* jump */
|
||||
#define OP_InitCoroutine 13 /* jump */
|
||||
#define OP_Yield 14 /* jump */
|
||||
#define OP_MustBeInt 15 /* jump */
|
||||
#define OP_Jump 16 /* jump */
|
||||
#define OP_Once 17 /* jump */
|
||||
#define OP_If 18 /* jump */
|
||||
#define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */
|
||||
#define OP_IfNot 20 /* jump */
|
||||
#define OP_IfNullRow \
|
||||
21 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */
|
||||
#define OP_SeekLT 22 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_SeekLE 23 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_SeekGE 24 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_SeekGT 25 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_IfNotOpen 26 /* jump, synopsis: if( !csr[P1] ) goto P2 */
|
||||
#define OP_IfNoHope 27 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_NoConflict 28 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_NotFound 29 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_Found 30 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_SeekRowid 31 /* jump, synopsis: intkey=r[P3] */
|
||||
#define OP_NotExists 32 /* jump, synopsis: intkey=r[P3] */
|
||||
#define OP_Last 33 /* jump */
|
||||
#define OP_IfSmaller 34 /* jump */
|
||||
#define OP_SorterSort 35 /* jump */
|
||||
#define OP_Sort 36 /* jump */
|
||||
#define OP_Rewind 37 /* jump */
|
||||
#define OP_IdxLE 38 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_IdxGT 39 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_IdxLT 40 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_IdxGE 41 /* jump, synopsis: key=r[P3@P4] */
|
||||
#define OP_RowSetRead 42 /* jump, synopsis: r[P3]=rowset(P1) */
|
||||
#define OP_Or 43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
|
||||
#define OP_And 44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
|
||||
#define OP_RowSetTest 45 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
|
||||
#define OP_Program 46 /* jump */
|
||||
#define OP_FkIfZero 47 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
|
||||
#define OP_IfPos 48 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
|
||||
#define OP_IfNotZero 49 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 \
|
||||
*/
|
||||
#define OP_IsNull \
|
||||
50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
|
||||
#define OP_NotNull \
|
||||
51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
|
||||
#define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
|
||||
#define OP_Eq 53 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
|
||||
#define OP_Gt 54 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
|
||||
#define OP_Le 55 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
|
||||
#define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
|
||||
#define OP_Ge 57 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
|
||||
#define OP_ElseNotEq 58 /* jump, same as TK_ESCAPE */
|
||||
#define OP_DecrJumpZero 59 /* jump, synopsis: if (--r[P1])==0 goto P2 */
|
||||
#define OP_IncrVacuum 60 /* jump */
|
||||
#define OP_VNext 61 /* jump */
|
||||
#define OP_Init 62 /* jump, synopsis: Start at P2 */
|
||||
#define OP_PureFunc 63 /* synopsis: r[P3]=func(r[P2@NP]) */
|
||||
#define OP_Function 64 /* synopsis: r[P3]=func(r[P2@NP]) */
|
||||
#define OP_Return 65
|
||||
#define OP_EndCoroutine 66
|
||||
#define OP_HaltIfNull 67 /* synopsis: if r[P3]=null halt */
|
||||
#define OP_Halt 68
|
||||
#define OP_Integer 69 /* synopsis: r[P2]=P1 */
|
||||
#define OP_Int64 70 /* synopsis: r[P2]=P4 */
|
||||
#define OP_String 71 /* synopsis: r[P2]='P4' (len=P1) */
|
||||
#define OP_Null 72 /* synopsis: r[P2..P3]=NULL */
|
||||
#define OP_SoftNull 73 /* synopsis: r[P1]=NULL */
|
||||
#define OP_Blob 74 /* synopsis: r[P2]=P4 (len=P1) */
|
||||
#define OP_Variable 75 /* synopsis: r[P2]=parameter(P1,P4) */
|
||||
#define OP_Move 76 /* synopsis: r[P2@P3]=r[P1@P3] */
|
||||
#define OP_Copy 77 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
|
||||
#define OP_SCopy 78 /* synopsis: r[P2]=r[P1] */
|
||||
#define OP_IntCopy 79 /* synopsis: r[P2]=r[P1] */
|
||||
#define OP_ChngCntRow 80 /* synopsis: output=r[P1] */
|
||||
#define OP_ResultRow 81 /* synopsis: output=r[P1@P2] */
|
||||
#define OP_CollSeq 82
|
||||
#define OP_AddImm 83 /* synopsis: r[P1]=r[P1]+P2 */
|
||||
#define OP_RealAffinity 84
|
||||
#define OP_Cast 85 /* synopsis: affinity(r[P1]) */
|
||||
#define OP_Permutation 86
|
||||
#define OP_Compare 87 /* synopsis: r[P1@P3] <-> r[P2@P3] */
|
||||
#define OP_IsTrue 88 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
|
||||
#define OP_Offset 89 /* synopsis: r[P3] = sqlite_offset(P1) */
|
||||
#define OP_Column 90 /* synopsis: r[P3]=PX */
|
||||
#define OP_Affinity 91 /* synopsis: affinity(r[P1@P2]) */
|
||||
#define OP_MakeRecord 92 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
|
||||
#define OP_Count 93 /* synopsis: r[P2]=count() */
|
||||
#define OP_ReadCookie 94
|
||||
#define OP_SetCookie 95
|
||||
#define OP_ReopenIdx 96 /* synopsis: root=P2 iDb=P3 */
|
||||
#define OP_OpenRead 97 /* synopsis: root=P2 iDb=P3 */
|
||||
#define OP_OpenWrite 98 /* synopsis: root=P2 iDb=P3 */
|
||||
#define OP_OpenDup 99
|
||||
#define OP_OpenAutoindex 100 /* synopsis: nColumn=P2 */
|
||||
#define OP_OpenEphemeral 101 /* synopsis: nColumn=P2 */
|
||||
#define OP_BitAnd 102 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
|
||||
#define OP_BitOr 103 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
|
||||
#define OP_ShiftLeft 104 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
|
||||
#define OP_ShiftRight 105 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] \
|
||||
*/
|
||||
#define OP_Add 106 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
|
||||
#define OP_Subtract 107 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
|
||||
#define OP_Multiply 108 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
|
||||
#define OP_Divide 109 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
|
||||
#define OP_Remainder 110 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
|
||||
#define OP_Concat 111 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
|
||||
#define OP_SorterOpen 112
|
||||
#define OP_BitNot 113 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
|
||||
#define OP_SequenceTest 114 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
|
||||
#define OP_OpenPseudo 115 /* synopsis: P3 columns in r[P2] */
|
||||
#define OP_String8 116 /* same as TK_STRING, synopsis: r[P2]='P4' */
|
||||
#define OP_Close 117
|
||||
#define OP_ColumnsUsed 118
|
||||
#define OP_SeekScan 119 /* synopsis: Scan-ahead up to P1 rows */
|
||||
#define OP_SeekHit 120 /* synopsis: set P2<=seekHit<=P3 */
|
||||
#define OP_Sequence 121 /* synopsis: r[P2]=cursor[P1].ctr++ */
|
||||
#define OP_NewRowid 122 /* synopsis: r[P2]=rowid */
|
||||
#define OP_Insert 123 /* synopsis: intkey=r[P3] data=r[P2] */
|
||||
#define OP_RowCell 124
|
||||
#define OP_Delete 125
|
||||
#define OP_ResetCount 126
|
||||
#define OP_SorterCompare 127 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 \
|
||||
*/
|
||||
#define OP_SorterData 128 /* synopsis: r[P2]=data */
|
||||
#define OP_RowData 129 /* synopsis: r[P2]=data */
|
||||
#define OP_Rowid 130 /* synopsis: r[P2]=rowid */
|
||||
#define OP_NullRow 131
|
||||
#define OP_SeekEnd 132
|
||||
#define OP_IdxInsert 133 /* synopsis: key=r[P2] */
|
||||
#define OP_SorterInsert 134 /* synopsis: key=r[P2] */
|
||||
#define OP_IdxDelete 135 /* synopsis: key=r[P2@P3] */
|
||||
#define OP_DeferredSeek 136 /* synopsis: Move P3 to P1.rowid if needed */
|
||||
#define OP_IdxRowid 137 /* synopsis: r[P2]=rowid */
|
||||
#define OP_FinishSeek 138
|
||||
#define OP_Destroy 139
|
||||
#define OP_Clear 140
|
||||
#define OP_ResetSorter 141
|
||||
#define OP_CreateBtree 142 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
|
||||
#define OP_SqlExec 143
|
||||
#define OP_ParseSchema 144
|
||||
#define OP_LoadAnalysis 145
|
||||
#define OP_DropTable 146
|
||||
#define OP_DropIndex 147
|
||||
#define OP_DropTrigger 148
|
||||
#define OP_IntegrityCk 149
|
||||
#define OP_RowSetAdd 150 /* synopsis: rowset(P1)=r[P2] */
|
||||
#define OP_Param 151
|
||||
#define OP_Real 152 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
|
||||
#define OP_FkCounter 153 /* synopsis: fkctr[P1]+=P2 */
|
||||
#define OP_MemMax 154 /* synopsis: r[P1]=max(r[P1],r[P2]) */
|
||||
#define OP_OffsetLimit \
|
||||
155 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
|
||||
#define OP_AggInverse 156 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
|
||||
#define OP_AggStep 157 /* synopsis: accum=r[P3] step(r[P2@P5]) */
|
||||
#define OP_AggStep1 158 /* synopsis: accum=r[P3] step(r[P2@P5]) */
|
||||
#define OP_AggValue 159 /* synopsis: r[P3]=value N=P2 */
|
||||
#define OP_AggFinal 160 /* synopsis: accum=r[P1] N=P2 */
|
||||
#define OP_Expire 161
|
||||
#define OP_CursorLock 162
|
||||
#define OP_CursorUnlock 163
|
||||
#define OP_TableLock 164 /* synopsis: iDb=P1 root=P2 write=P3 */
|
||||
#define OP_VBegin 165
|
||||
#define OP_VCreate 166
|
||||
#define OP_VDestroy 167
|
||||
#define OP_VOpen 168
|
||||
#define OP_VColumn 169 /* synopsis: r[P3]=vcolumn(P2) */
|
||||
#define OP_VRename 170
|
||||
#define OP_Pagecount 171
|
||||
#define OP_MaxPgcnt 172
|
||||
#define OP_Trace 173
|
||||
#define OP_CursorHint 174
|
||||
#define OP_ReleaseReg 175 /* synopsis: release r[P1@P2] mask P3 */
|
||||
#define OP_Noop 176
|
||||
#define OP_Explain 177
|
||||
#define OP_Abortable 178
|
||||
/* clang-format off */
|
||||
|
||||
/* Properties such as "out2" or "jump" that are specified in
|
||||
** comments following the "case" for each opcode in the vdbe.c
|
||||
** are encoded into bitvectors as follows:
|
||||
*/
|
||||
#define OPFLG_JUMP 0x01 /* jump: P2 holds jmp target */
|
||||
#define OPFLG_IN1 0x02 /* in1: P1 is an input */
|
||||
#define OPFLG_IN2 0x04 /* in2: P2 is an input */
|
||||
#define OPFLG_IN3 0x08 /* in3: P3 is an input */
|
||||
#define OPFLG_OUT2 0x10 /* out2: P2 is an output */
|
||||
#define OPFLG_OUT3 0x20 /* out3: P3 is an output */
|
||||
#define OPFLG_INITIALIZER {\
|
||||
/* 0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x10,\
|
||||
/* 8 */ 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03,\
|
||||
/* 16 */ 0x01, 0x01, 0x03, 0x12, 0x03, 0x01, 0x09, 0x09,\
|
||||
/* 24 */ 0x09, 0x09, 0x01, 0x09, 0x09, 0x09, 0x09, 0x09,\
|
||||
/* 32 */ 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
|
||||
/* 40 */ 0x01, 0x01, 0x23, 0x26, 0x26, 0x0b, 0x01, 0x01,\
|
||||
/* 48 */ 0x03, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
|
||||
/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00,\
|
||||
/* 64 */ 0x00, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10, 0x10,\
|
||||
/* 72 */ 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10,\
|
||||
/* 80 */ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\
|
||||
/* 88 */ 0x12, 0x20, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,\
|
||||
/* 96 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x26,\
|
||||
/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\
|
||||
/* 112 */ 0x00, 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,\
|
||||
/* 120 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\
|
||||
/* 128 */ 0x00, 0x00, 0x10, 0x00, 0x00, 0x04, 0x04, 0x00,\
|
||||
/* 136 */ 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00,\
|
||||
/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10,\
|
||||
/* 152 */ 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00,\
|
||||
/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
|
||||
/* 168 */ 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00,\
|
||||
/* 176 */ 0x00, 0x00, 0x00,}
|
||||
|
||||
/* The sqlite3P2Values() routine is able to run faster if it knows
|
||||
** the value of the largest JUMP opcode. The smaller the maximum
|
||||
** JUMP opcode the better, so the mkopcodeh.tcl script that
|
||||
** generated this include file strives to group all JUMP opcodes
|
||||
** together near the beginning of the list.
|
||||
*/
|
||||
#define SQLITE_MX_JUMP_OPCODE 62 /* Maximum JUMP opcode */
|
14
third_party/sqlite3/os.c
vendored
14
third_party/sqlite3/os.c
vendored
|
@ -13,8 +13,7 @@
|
|||
** This file contains OS interface code that is common to all
|
||||
** architectures.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/*
|
||||
** If we compile with the SQLITE_TEST macro set, then the following block
|
||||
|
@ -107,9 +106,11 @@ int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
|
|||
}
|
||||
int sqlite3OsLock(sqlite3_file *id, int lockType){
|
||||
DO_OS_MALLOC_TEST(id);
|
||||
assert( lockType>=SQLITE_LOCK_SHARED && lockType<=SQLITE_LOCK_EXCLUSIVE );
|
||||
return id->pMethods->xLock(id, lockType);
|
||||
}
|
||||
int sqlite3OsUnlock(sqlite3_file *id, int lockType){
|
||||
assert( lockType==SQLITE_LOCK_NONE || lockType==SQLITE_LOCK_SHARED );
|
||||
return id->pMethods->xUnlock(id, lockType);
|
||||
}
|
||||
int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
|
||||
|
@ -162,6 +163,7 @@ int sqlite3OsSectorSize(sqlite3_file *id){
|
|||
return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
|
||||
}
|
||||
int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
|
||||
if( NEVER(id->pMethods==0) ) return 0;
|
||||
return id->pMethods->xDeviceCharacteristics(id);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
|
@ -223,6 +225,7 @@ int sqlite3OsOpen(
|
|||
** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
|
||||
** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
|
||||
** reaching the VFS. */
|
||||
assert( zPath || (flags & SQLITE_OPEN_EXCLUSIVE) );
|
||||
rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x1087f7f, pFlagsOut);
|
||||
assert( rc==SQLITE_OK || pFile->pMethods==0 );
|
||||
return rc;
|
||||
|
@ -230,7 +233,7 @@ int sqlite3OsOpen(
|
|||
int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
||||
DO_OS_MALLOC_TEST(0);
|
||||
assert( dirSync==0 || dirSync==1 );
|
||||
return pVfs->xDelete(pVfs, zPath, dirSync);
|
||||
return pVfs->xDelete!=0 ? pVfs->xDelete(pVfs, zPath, dirSync) : SQLITE_OK;
|
||||
}
|
||||
int sqlite3OsAccess(
|
||||
sqlite3_vfs *pVfs,
|
||||
|
@ -253,6 +256,8 @@ int sqlite3OsFullPathname(
|
|||
}
|
||||
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
||||
void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
|
||||
assert( zPath!=0 );
|
||||
assert( strlen(zPath)<=SQLITE_MAX_PATHLEN ); /* tag-20210611-1 */
|
||||
return pVfs->xDlOpen(pVfs, zPath);
|
||||
}
|
||||
void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
|
||||
|
@ -314,12 +319,15 @@ int sqlite3OsOpenMalloc(
|
|||
rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_free(pFile);
|
||||
*ppFile = 0;
|
||||
}else{
|
||||
*ppFile = pFile;
|
||||
}
|
||||
}else{
|
||||
*ppFile = 0;
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
assert( *ppFile!=0 || rc!=SQLITE_OK );
|
||||
return rc;
|
||||
}
|
||||
void sqlite3OsCloseFree(sqlite3_file *pFile){
|
||||
|
|
16
third_party/sqlite3/os.inc
vendored
16
third_party/sqlite3/os.inc
vendored
|
@ -19,13 +19,12 @@
|
|||
*/
|
||||
#ifndef _SQLITE_OS_H_
|
||||
#define _SQLITE_OS_H_
|
||||
/* clang-format off */
|
||||
|
||||
/*
|
||||
** Attempt to automatically detect the operating system and setup the
|
||||
** necessary pre-processor macros for it.
|
||||
*/
|
||||
#include "third_party/sqlite3/os_setup.inc"
|
||||
#include "third_party/sqlite3/os_setup.h"
|
||||
|
||||
/* If the SET_FULLSYNC macro is not defined above, then make it
|
||||
** a no-op
|
||||
|
@ -34,6 +33,19 @@
|
|||
# define SET_FULLSYNC(x,y)
|
||||
#endif
|
||||
|
||||
/* Maximum pathname length. Note: FILENAME_MAX defined by stdio.h
|
||||
*/
|
||||
#ifndef SQLITE_MAX_PATHLEN
|
||||
# define SQLITE_MAX_PATHLEN FILENAME_MAX
|
||||
#endif
|
||||
|
||||
/* Maximum number of symlinks that will be resolved while trying to
|
||||
** expand a filename in xFullPathname() in the VFS.
|
||||
*/
|
||||
#ifndef SQLITE_MAX_SYMLINK
|
||||
# define SQLITE_MAX_SYMLINK 200
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The default size of a disk sector
|
||||
*/
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*/
|
||||
#ifndef _OS_COMMON_H_
|
||||
#define _OS_COMMON_H_
|
||||
/* clang-format off */
|
||||
|
||||
/*
|
||||
** At least two bugs have slipped in because we changed the MEMORY_DEBUG
|
971
third_party/sqlite3/os_kv.c
vendored
Normal file
971
third_party/sqlite3/os_kv.c
vendored
Normal file
|
@ -0,0 +1,971 @@
|
|||
/*
|
||||
** 2022-09-06
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** This file contains an experimental VFS layer that operates on a
|
||||
** Key/Value storage engine where both keys and values must be pure
|
||||
** text.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
#if SQLITE_OS_KV || (SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL))
|
||||
|
||||
/*****************************************************************************
|
||||
** Debugging logic
|
||||
*/
|
||||
|
||||
/* SQLITE_KV_TRACE() is used for tracing calls to kvstorage routines. */
|
||||
#if 0
|
||||
#define SQLITE_KV_TRACE(X) printf X
|
||||
#else
|
||||
#define SQLITE_KV_TRACE(X)
|
||||
#endif
|
||||
|
||||
/* SQLITE_KV_LOG() is used for tracing calls to the VFS interface */
|
||||
#if 0
|
||||
#define SQLITE_KV_LOG(X) printf X
|
||||
#else
|
||||
#define SQLITE_KV_LOG(X)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Forward declaration of objects used by this VFS implementation
|
||||
*/
|
||||
typedef struct KVVfsFile KVVfsFile;
|
||||
|
||||
/* A single open file. There are only two files represented by this
|
||||
** VFS - the database and the rollback journal.
|
||||
*/
|
||||
struct KVVfsFile {
|
||||
sqlite3_file base; /* IO methods */
|
||||
const char *zClass; /* Storage class */
|
||||
int isJournal; /* True if this is a journal file */
|
||||
unsigned int nJrnl; /* Space allocated for aJrnl[] */
|
||||
char *aJrnl; /* Journal content */
|
||||
int szPage; /* Last known page size */
|
||||
sqlite3_int64 szDb; /* Database file size. -1 means unknown */
|
||||
};
|
||||
|
||||
/*
|
||||
** Methods for KVVfsFile
|
||||
*/
|
||||
static int kvvfsClose(sqlite3_file*);
|
||||
static int kvvfsReadDb(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
|
||||
static int kvvfsReadJrnl(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
|
||||
static int kvvfsWriteDb(sqlite3_file*,const void*,int iAmt, sqlite3_int64);
|
||||
static int kvvfsWriteJrnl(sqlite3_file*,const void*,int iAmt, sqlite3_int64);
|
||||
static int kvvfsTruncateDb(sqlite3_file*, sqlite3_int64 size);
|
||||
static int kvvfsTruncateJrnl(sqlite3_file*, sqlite3_int64 size);
|
||||
static int kvvfsSyncDb(sqlite3_file*, int flags);
|
||||
static int kvvfsSyncJrnl(sqlite3_file*, int flags);
|
||||
static int kvvfsFileSizeDb(sqlite3_file*, sqlite3_int64 *pSize);
|
||||
static int kvvfsFileSizeJrnl(sqlite3_file*, sqlite3_int64 *pSize);
|
||||
static int kvvfsLock(sqlite3_file*, int);
|
||||
static int kvvfsUnlock(sqlite3_file*, int);
|
||||
static int kvvfsCheckReservedLock(sqlite3_file*, int *pResOut);
|
||||
static int kvvfsFileControlDb(sqlite3_file*, int op, void *pArg);
|
||||
static int kvvfsFileControlJrnl(sqlite3_file*, int op, void *pArg);
|
||||
static int kvvfsSectorSize(sqlite3_file*);
|
||||
static int kvvfsDeviceCharacteristics(sqlite3_file*);
|
||||
|
||||
/*
|
||||
** Methods for sqlite3_vfs
|
||||
*/
|
||||
static int kvvfsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
|
||||
static int kvvfsDelete(sqlite3_vfs*, const char *zName, int syncDir);
|
||||
static int kvvfsAccess(sqlite3_vfs*, const char *zName, int flags, int *);
|
||||
static int kvvfsFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
|
||||
static void *kvvfsDlOpen(sqlite3_vfs*, const char *zFilename);
|
||||
static int kvvfsRandomness(sqlite3_vfs*, int nByte, char *zOut);
|
||||
static int kvvfsSleep(sqlite3_vfs*, int microseconds);
|
||||
static int kvvfsCurrentTime(sqlite3_vfs*, double*);
|
||||
static int kvvfsCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
|
||||
|
||||
static sqlite3_vfs sqlite3OsKvvfsObject = {
|
||||
1, /* iVersion */
|
||||
sizeof(KVVfsFile), /* szOsFile */
|
||||
1024, /* mxPathname */
|
||||
0, /* pNext */
|
||||
"kvvfs", /* zName */
|
||||
0, /* pAppData */
|
||||
kvvfsOpen, /* xOpen */
|
||||
kvvfsDelete, /* xDelete */
|
||||
kvvfsAccess, /* xAccess */
|
||||
kvvfsFullPathname, /* xFullPathname */
|
||||
kvvfsDlOpen, /* xDlOpen */
|
||||
0, /* xDlError */
|
||||
0, /* xDlSym */
|
||||
0, /* xDlClose */
|
||||
kvvfsRandomness, /* xRandomness */
|
||||
kvvfsSleep, /* xSleep */
|
||||
kvvfsCurrentTime, /* xCurrentTime */
|
||||
0, /* xGetLastError */
|
||||
kvvfsCurrentTimeInt64 /* xCurrentTimeInt64 */
|
||||
};
|
||||
|
||||
/* Methods for sqlite3_file objects referencing a database file
|
||||
*/
|
||||
static sqlite3_io_methods kvvfs_db_io_methods = {
|
||||
1, /* iVersion */
|
||||
kvvfsClose, /* xClose */
|
||||
kvvfsReadDb, /* xRead */
|
||||
kvvfsWriteDb, /* xWrite */
|
||||
kvvfsTruncateDb, /* xTruncate */
|
||||
kvvfsSyncDb, /* xSync */
|
||||
kvvfsFileSizeDb, /* xFileSize */
|
||||
kvvfsLock, /* xLock */
|
||||
kvvfsUnlock, /* xUnlock */
|
||||
kvvfsCheckReservedLock, /* xCheckReservedLock */
|
||||
kvvfsFileControlDb, /* xFileControl */
|
||||
kvvfsSectorSize, /* xSectorSize */
|
||||
kvvfsDeviceCharacteristics, /* xDeviceCharacteristics */
|
||||
0, /* xShmMap */
|
||||
0, /* xShmLock */
|
||||
0, /* xShmBarrier */
|
||||
0, /* xShmUnmap */
|
||||
0, /* xFetch */
|
||||
0 /* xUnfetch */
|
||||
};
|
||||
|
||||
/* Methods for sqlite3_file objects referencing a rollback journal
|
||||
*/
|
||||
static sqlite3_io_methods kvvfs_jrnl_io_methods = {
|
||||
1, /* iVersion */
|
||||
kvvfsClose, /* xClose */
|
||||
kvvfsReadJrnl, /* xRead */
|
||||
kvvfsWriteJrnl, /* xWrite */
|
||||
kvvfsTruncateJrnl, /* xTruncate */
|
||||
kvvfsSyncJrnl, /* xSync */
|
||||
kvvfsFileSizeJrnl, /* xFileSize */
|
||||
kvvfsLock, /* xLock */
|
||||
kvvfsUnlock, /* xUnlock */
|
||||
kvvfsCheckReservedLock, /* xCheckReservedLock */
|
||||
kvvfsFileControlJrnl, /* xFileControl */
|
||||
kvvfsSectorSize, /* xSectorSize */
|
||||
kvvfsDeviceCharacteristics, /* xDeviceCharacteristics */
|
||||
0, /* xShmMap */
|
||||
0, /* xShmLock */
|
||||
0, /* xShmBarrier */
|
||||
0, /* xShmUnmap */
|
||||
0, /* xFetch */
|
||||
0 /* xUnfetch */
|
||||
};
|
||||
|
||||
/****** Storage subsystem **************************************************/
|
||||
#include "libc/isystem/sys/types.h"
|
||||
#include "libc/isystem/sys/stat.h"
|
||||
|
||||
/* Forward declarations for the low-level storage engine
|
||||
*/
|
||||
static int kvstorageWrite(const char*, const char *zKey, const char *zData);
|
||||
static int kvstorageDelete(const char*, const char *zKey);
|
||||
static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf);
|
||||
#define KVSTORAGE_KEY_SZ 32
|
||||
|
||||
/* Expand the key name with an appropriate prefix and put the result
|
||||
** zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least
|
||||
** KVSTORAGE_KEY_SZ bytes.
|
||||
*/
|
||||
static void kvstorageMakeKey(
|
||||
const char *zClass,
|
||||
const char *zKeyIn,
|
||||
char *zKeyOut
|
||||
){
|
||||
sqlite3_snprintf(KVSTORAGE_KEY_SZ, zKeyOut, "kvvfs-%s-%s", zClass, zKeyIn);
|
||||
}
|
||||
|
||||
/* Write content into a key. zClass is the particular namespace of the
|
||||
** underlying key/value store to use - either "local" or "session".
|
||||
**
|
||||
** Both zKey and zData are zero-terminated pure text strings.
|
||||
**
|
||||
** Return the number of errors.
|
||||
*/
|
||||
static int kvstorageWrite(
|
||||
const char *zClass,
|
||||
const char *zKey,
|
||||
const char *zData
|
||||
){
|
||||
FILE *fd;
|
||||
char zXKey[KVSTORAGE_KEY_SZ];
|
||||
kvstorageMakeKey(zClass, zKey, zXKey);
|
||||
fd = fopen(zXKey, "wb");
|
||||
if( fd ){
|
||||
SQLITE_KV_TRACE(("KVVFS-WRITE %-15s (%d) %.50s%s\n", zXKey,
|
||||
(int)strlen(zData), zData,
|
||||
strlen(zData)>50 ? "..." : ""));
|
||||
fputs(zData, fd);
|
||||
fclose(fd);
|
||||
return 0;
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete a key (with its corresponding data) from the key/value
|
||||
** namespace given by zClass. If the key does not previously exist,
|
||||
** this routine is a no-op.
|
||||
*/
|
||||
static int kvstorageDelete(const char *zClass, const char *zKey){
|
||||
char zXKey[KVSTORAGE_KEY_SZ];
|
||||
kvstorageMakeKey(zClass, zKey, zXKey);
|
||||
unlink(zXKey);
|
||||
SQLITE_KV_TRACE(("KVVFS-DELETE %-15s\n", zXKey));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the value associated with a zKey from the key/value namespace given
|
||||
** by zClass and put the text data associated with that key in the first
|
||||
** nBuf bytes of zBuf[]. The value might be truncated if zBuf is not large
|
||||
** enough to hold it all. The value put into zBuf must always be zero
|
||||
** terminated, even if it gets truncated because nBuf is not large enough.
|
||||
**
|
||||
** Return the total number of bytes in the data, without truncation, and
|
||||
** not counting the final zero terminator. Return -1 if the key does
|
||||
** not exist.
|
||||
**
|
||||
** If nBuf<=0 then this routine simply returns the size of the data without
|
||||
** actually reading it.
|
||||
*/
|
||||
static int kvstorageRead(
|
||||
const char *zClass,
|
||||
const char *zKey,
|
||||
char *zBuf,
|
||||
int nBuf
|
||||
){
|
||||
FILE *fd;
|
||||
struct stat buf;
|
||||
char zXKey[KVSTORAGE_KEY_SZ];
|
||||
kvstorageMakeKey(zClass, zKey, zXKey);
|
||||
if( access(zXKey, R_OK)!=0
|
||||
|| stat(zXKey, &buf)!=0
|
||||
|| !S_ISREG(buf.st_mode)
|
||||
){
|
||||
SQLITE_KV_TRACE(("KVVFS-READ %-15s (-1)\n", zXKey));
|
||||
return -1;
|
||||
}
|
||||
if( nBuf<=0 ){
|
||||
return (int)buf.st_size;
|
||||
}else if( nBuf==1 ){
|
||||
zBuf[0] = 0;
|
||||
SQLITE_KV_TRACE(("KVVFS-READ %-15s (%d)\n", zXKey,
|
||||
(int)buf.st_size));
|
||||
return (int)buf.st_size;
|
||||
}
|
||||
if( nBuf > buf.st_size + 1 ){
|
||||
nBuf = buf.st_size + 1;
|
||||
}
|
||||
fd = fopen(zXKey, "rb");
|
||||
if( fd==0 ){
|
||||
SQLITE_KV_TRACE(("KVVFS-READ %-15s (-1)\n", zXKey));
|
||||
return -1;
|
||||
}else{
|
||||
sqlite3_int64 n = fread(zBuf, 1, nBuf-1, fd);
|
||||
fclose(fd);
|
||||
zBuf[n] = 0;
|
||||
SQLITE_KV_TRACE(("KVVFS-READ %-15s (%lld) %.50s%s\n", zXKey,
|
||||
n, zBuf, n>50 ? "..." : ""));
|
||||
return (int)n;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** An internal level of indirection which enables us to replace the
|
||||
** kvvfs i/o methods with JavaScript implementations in WASM builds.
|
||||
** Maintenance reminder: if this struct changes in any way, the JSON
|
||||
** rendering of its structure must be updated in
|
||||
** sqlite3_wasm_enum_json(). There are no binary compatibility
|
||||
** concerns, so it does not need an iVersion member. This file is
|
||||
** necessarily always compiled together with sqlite3_wasm_enum_json(),
|
||||
** and JS code dynamically creates the mapping of members based on
|
||||
** that JSON description.
|
||||
*/
|
||||
typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods;
|
||||
struct sqlite3_kvvfs_methods {
|
||||
int (*xRead)(const char *zClass, const char *zKey, char *zBuf, int nBuf);
|
||||
int (*xWrite)(const char *zClass, const char *zKey, const char *zData);
|
||||
int (*xDelete)(const char *zClass, const char *zKey);
|
||||
const int nKeySize;
|
||||
};
|
||||
|
||||
/*
|
||||
** This object holds the kvvfs I/O methods which may be swapped out
|
||||
** for JavaScript-side implementations in WASM builds. In such builds
|
||||
** it cannot be const, but in native builds it should be so that
|
||||
** the compiler can hopefully optimize this level of indirection out.
|
||||
** That said, kvvfs is intended primarily for use in WASM builds.
|
||||
**
|
||||
** Note that this is not explicitly flagged as static because the
|
||||
** amalgamation build will tag it with SQLITE_PRIVATE.
|
||||
*/
|
||||
#ifndef SQLITE_WASM
|
||||
const
|
||||
#endif
|
||||
sqlite3_kvvfs_methods sqlite3KvvfsMethods = {
|
||||
kvstorageRead,
|
||||
kvstorageWrite,
|
||||
kvstorageDelete,
|
||||
KVSTORAGE_KEY_SZ
|
||||
};
|
||||
|
||||
/****** Utility subroutines ************************************************/
|
||||
|
||||
/*
|
||||
** Encode binary into the text encoded used to persist on disk.
|
||||
** The output text is stored in aOut[], which must be at least
|
||||
** nData+1 bytes in length.
|
||||
**
|
||||
** Return the actual length of the encoded text, not counting the
|
||||
** zero terminator at the end.
|
||||
**
|
||||
** Encoding format
|
||||
** ---------------
|
||||
**
|
||||
** * Non-zero bytes are encoded as upper-case hexadecimal
|
||||
**
|
||||
** * A sequence of one or more zero-bytes that are not at the
|
||||
** beginning of the buffer are encoded as a little-endian
|
||||
** base-26 number using a..z. "a" means 0. "b" means 1,
|
||||
** "z" means 25. "ab" means 26. "ac" means 52. And so forth.
|
||||
**
|
||||
** * Because there is no overlap between the encoding characters
|
||||
** of hexadecimal and base-26 numbers, it is always clear where
|
||||
** one stops and the next begins.
|
||||
*/
|
||||
static int kvvfsEncode(const char *aData, int nData, char *aOut){
|
||||
int i, j;
|
||||
const unsigned char *a = (const unsigned char*)aData;
|
||||
for(i=j=0; i<nData; i++){
|
||||
unsigned char c = a[i];
|
||||
if( c!=0 ){
|
||||
aOut[j++] = "0123456789ABCDEF"[c>>4];
|
||||
aOut[j++] = "0123456789ABCDEF"[c&0xf];
|
||||
}else{
|
||||
/* A sequence of 1 or more zeros is stored as a little-endian
|
||||
** base-26 number using a..z as the digits. So one zero is "b".
|
||||
** Two zeros is "c". 25 zeros is "z", 26 zeros is "ab", 27 is "bb",
|
||||
** and so forth.
|
||||
*/
|
||||
int k;
|
||||
for(k=1; i+k<nData && a[i+k]==0; k++){}
|
||||
i += k-1;
|
||||
while( k>0 ){
|
||||
aOut[j++] = 'a'+(k%26);
|
||||
k /= 26;
|
||||
}
|
||||
}
|
||||
}
|
||||
aOut[j] = 0;
|
||||
return j;
|
||||
}
|
||||
|
||||
static const signed char kvvfsHexValue[256] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
|
||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
|
||||
};
|
||||
|
||||
/*
|
||||
** Decode the text encoding back to binary. The binary content is
|
||||
** written into pOut, which must be at least nOut bytes in length.
|
||||
**
|
||||
** The return value is the number of bytes actually written into aOut[].
|
||||
*/
|
||||
static int kvvfsDecode(const char *a, char *aOut, int nOut){
|
||||
int i, j;
|
||||
int c;
|
||||
const unsigned char *aIn = (const unsigned char*)a;
|
||||
i = 0;
|
||||
j = 0;
|
||||
while( 1 ){
|
||||
c = kvvfsHexValue[aIn[i]];
|
||||
if( c<0 ){
|
||||
int n = 0;
|
||||
int mult = 1;
|
||||
c = aIn[i];
|
||||
if( c==0 ) break;
|
||||
while( c>='a' && c<='z' ){
|
||||
n += (c - 'a')*mult;
|
||||
mult *= 26;
|
||||
c = aIn[++i];
|
||||
}
|
||||
if( j+n>nOut ) return -1;
|
||||
memset(&aOut[j], 0, n);
|
||||
j += n;
|
||||
c = aIn[i];
|
||||
if( c==0 ) break;
|
||||
}else{
|
||||
aOut[j] = c<<4;
|
||||
c = kvvfsHexValue[aIn[++i]];
|
||||
if( c<0 ) break;
|
||||
aOut[j++] += c;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
/*
|
||||
** Decode a complete journal file. Allocate space in pFile->aJrnl
|
||||
** and store the decoding there. Or leave pFile->aJrnl set to NULL
|
||||
** if an error is encountered.
|
||||
**
|
||||
** The first few characters of the text encoding will be a little-endian
|
||||
** base-26 number (digits a..z) that is the total number of bytes
|
||||
** in the decoded journal file image. This base-26 number is followed
|
||||
** by a single space, then the encoding of the journal. The space
|
||||
** separator is required to act as a terminator for the base-26 number.
|
||||
*/
|
||||
static void kvvfsDecodeJournal(
|
||||
KVVfsFile *pFile, /* Store decoding in pFile->aJrnl */
|
||||
const char *zTxt, /* Text encoding. Zero-terminated */
|
||||
int nTxt /* Bytes in zTxt, excluding zero terminator */
|
||||
){
|
||||
unsigned int n = 0;
|
||||
int c, i, mult;
|
||||
i = 0;
|
||||
mult = 1;
|
||||
while( (c = zTxt[i++])>='a' && c<='z' ){
|
||||
n += (zTxt[i] - 'a')*mult;
|
||||
mult *= 26;
|
||||
}
|
||||
sqlite3_free(pFile->aJrnl);
|
||||
pFile->aJrnl = sqlite3_malloc64( n );
|
||||
if( pFile->aJrnl==0 ){
|
||||
pFile->nJrnl = 0;
|
||||
return;
|
||||
}
|
||||
pFile->nJrnl = n;
|
||||
n = kvvfsDecode(zTxt+i, pFile->aJrnl, pFile->nJrnl);
|
||||
if( n<pFile->nJrnl ){
|
||||
sqlite3_free(pFile->aJrnl);
|
||||
pFile->aJrnl = 0;
|
||||
pFile->nJrnl = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Read or write the "sz" element, containing the database file size.
|
||||
*/
|
||||
static sqlite3_int64 kvvfsReadFileSize(KVVfsFile *pFile){
|
||||
char zData[50];
|
||||
zData[0] = 0;
|
||||
sqlite3KvvfsMethods.xRead(pFile->zClass, "sz", zData, sizeof(zData)-1);
|
||||
return strtoll(zData, 0, 0);
|
||||
}
|
||||
static int kvvfsWriteFileSize(KVVfsFile *pFile, sqlite3_int64 sz){
|
||||
char zData[50];
|
||||
sqlite3_snprintf(sizeof(zData), zData, "%lld", sz);
|
||||
return sqlite3KvvfsMethods.xWrite(pFile->zClass, "sz", zData);
|
||||
}
|
||||
|
||||
/****** sqlite3_io_methods methods ******************************************/
|
||||
|
||||
/*
|
||||
** Close an kvvfs-file.
|
||||
*/
|
||||
static int kvvfsClose(sqlite3_file *pProtoFile){
|
||||
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
||||
|
||||
SQLITE_KV_LOG(("xClose %s %s\n", pFile->zClass,
|
||||
pFile->isJournal ? "journal" : "db"));
|
||||
sqlite3_free(pFile->aJrnl);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Read from the -journal file.
|
||||
*/
|
||||
static int kvvfsReadJrnl(
|
||||
sqlite3_file *pProtoFile,
|
||||
void *zBuf,
|
||||
int iAmt,
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
|
||||
assert( pFile->isJournal );
|
||||
SQLITE_KV_LOG(("xRead('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
|
||||
if( pFile->aJrnl==0 ){
|
||||
int szTxt = kvstorageRead(pFile->zClass, "jrnl", 0, 0);
|
||||
char *aTxt;
|
||||
if( szTxt<=4 ){
|
||||
return SQLITE_IOERR;
|
||||
}
|
||||
aTxt = sqlite3_malloc64( szTxt+1 );
|
||||
if( aTxt==0 ) return SQLITE_NOMEM;
|
||||
kvstorageRead(pFile->zClass, "jrnl", aTxt, szTxt+1);
|
||||
kvvfsDecodeJournal(pFile, aTxt, szTxt);
|
||||
sqlite3_free(aTxt);
|
||||
if( pFile->aJrnl==0 ) return SQLITE_IOERR;
|
||||
}
|
||||
if( iOfst+iAmt>pFile->nJrnl ){
|
||||
return SQLITE_IOERR_SHORT_READ;
|
||||
}
|
||||
memcpy(zBuf, pFile->aJrnl+iOfst, iAmt);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Read from the database file.
|
||||
*/
|
||||
static int kvvfsReadDb(
|
||||
sqlite3_file *pProtoFile,
|
||||
void *zBuf,
|
||||
int iAmt,
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
|
||||
unsigned int pgno;
|
||||
int got, n;
|
||||
char zKey[30];
|
||||
char aData[133073];
|
||||
assert( iOfst>=0 );
|
||||
assert( iAmt>=0 );
|
||||
SQLITE_KV_LOG(("xRead('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
|
||||
if( iOfst+iAmt>=512 ){
|
||||
if( (iOfst % iAmt)!=0 ){
|
||||
return SQLITE_IOERR_READ;
|
||||
}
|
||||
if( (iAmt & (iAmt-1))!=0 || iAmt<512 || iAmt>65536 ){
|
||||
return SQLITE_IOERR_READ;
|
||||
}
|
||||
pFile->szPage = iAmt;
|
||||
pgno = 1 + iOfst/iAmt;
|
||||
}else{
|
||||
pgno = 1;
|
||||
}
|
||||
sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
|
||||
got = sqlite3KvvfsMethods.xRead(pFile->zClass, zKey, aData, sizeof(aData)-1);
|
||||
if( got<0 ){
|
||||
n = 0;
|
||||
}else{
|
||||
aData[got] = 0;
|
||||
if( iOfst+iAmt<512 ){
|
||||
int k = iOfst+iAmt;
|
||||
aData[k*2] = 0;
|
||||
n = kvvfsDecode(aData, &aData[2000], sizeof(aData)-2000);
|
||||
if( n>=iOfst+iAmt ){
|
||||
memcpy(zBuf, &aData[2000+iOfst], iAmt);
|
||||
n = iAmt;
|
||||
}else{
|
||||
n = 0;
|
||||
}
|
||||
}else{
|
||||
n = kvvfsDecode(aData, zBuf, iAmt);
|
||||
}
|
||||
}
|
||||
if( n<iAmt ){
|
||||
memset(zBuf+n, 0, iAmt-n);
|
||||
return SQLITE_IOERR_SHORT_READ;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Write into the -journal file.
|
||||
*/
|
||||
static int kvvfsWriteJrnl(
|
||||
sqlite3_file *pProtoFile,
|
||||
const void *zBuf,
|
||||
int iAmt,
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
|
||||
sqlite3_int64 iEnd = iOfst+iAmt;
|
||||
SQLITE_KV_LOG(("xWrite('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
|
||||
if( iEnd>=0x10000000 ) return SQLITE_FULL;
|
||||
if( pFile->aJrnl==0 || pFile->nJrnl<iEnd ){
|
||||
char *aNew = sqlite3_realloc(pFile->aJrnl, iEnd);
|
||||
if( aNew==0 ){
|
||||
return SQLITE_IOERR_NOMEM;
|
||||
}
|
||||
pFile->aJrnl = aNew;
|
||||
if( pFile->nJrnl<iOfst ){
|
||||
memset(pFile->aJrnl+pFile->nJrnl, 0, iOfst-pFile->nJrnl);
|
||||
}
|
||||
pFile->nJrnl = iEnd;
|
||||
}
|
||||
memcpy(pFile->aJrnl+iOfst, zBuf, iAmt);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Write into the database file.
|
||||
*/
|
||||
static int kvvfsWriteDb(
|
||||
sqlite3_file *pProtoFile,
|
||||
const void *zBuf,
|
||||
int iAmt,
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
|
||||
unsigned int pgno;
|
||||
char zKey[30];
|
||||
char aData[131073];
|
||||
SQLITE_KV_LOG(("xWrite('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
|
||||
assert( iAmt>=512 && iAmt<=65536 );
|
||||
assert( (iAmt & (iAmt-1))==0 );
|
||||
assert( pFile->szPage<0 || pFile->szPage==iAmt );
|
||||
pFile->szPage = iAmt;
|
||||
pgno = 1 + iOfst/iAmt;
|
||||
sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
|
||||
kvvfsEncode(zBuf, iAmt, aData);
|
||||
if( sqlite3KvvfsMethods.xWrite(pFile->zClass, zKey, aData) ){
|
||||
return SQLITE_IOERR;
|
||||
}
|
||||
if( iOfst+iAmt > pFile->szDb ){
|
||||
pFile->szDb = iOfst + iAmt;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Truncate an kvvfs-file.
|
||||
*/
|
||||
static int kvvfsTruncateJrnl(sqlite3_file *pProtoFile, sqlite_int64 size){
|
||||
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
||||
SQLITE_KV_LOG(("xTruncate('%s-journal',%lld)\n", pFile->zClass, size));
|
||||
assert( size==0 );
|
||||
sqlite3KvvfsMethods.xDelete(pFile->zClass, "jrnl");
|
||||
sqlite3_free(pFile->aJrnl);
|
||||
pFile->aJrnl = 0;
|
||||
pFile->nJrnl = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int kvvfsTruncateDb(sqlite3_file *pProtoFile, sqlite_int64 size){
|
||||
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
||||
if( pFile->szDb>size
|
||||
&& pFile->szPage>0
|
||||
&& (size % pFile->szPage)==0
|
||||
){
|
||||
char zKey[50];
|
||||
unsigned int pgno, pgnoMax;
|
||||
SQLITE_KV_LOG(("xTruncate('%s-db',%lld)\n", pFile->zClass, size));
|
||||
pgno = 1 + size/pFile->szPage;
|
||||
pgnoMax = 2 + pFile->szDb/pFile->szPage;
|
||||
while( pgno<=pgnoMax ){
|
||||
sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
|
||||
sqlite3KvvfsMethods.xDelete(pFile->zClass, zKey);
|
||||
pgno++;
|
||||
}
|
||||
pFile->szDb = size;
|
||||
return kvvfsWriteFileSize(pFile, size) ? SQLITE_IOERR : SQLITE_OK;
|
||||
}
|
||||
return SQLITE_IOERR;
|
||||
}
|
||||
|
||||
/*
|
||||
** Sync an kvvfs-file.
|
||||
*/
|
||||
static int kvvfsSyncJrnl(sqlite3_file *pProtoFile, int flags){
|
||||
int i, n;
|
||||
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
||||
char *zOut;
|
||||
SQLITE_KV_LOG(("xSync('%s-journal')\n", pFile->zClass));
|
||||
if( pFile->nJrnl<=0 ){
|
||||
return kvvfsTruncateJrnl(pProtoFile, 0);
|
||||
}
|
||||
zOut = sqlite3_malloc64( pFile->nJrnl*2 + 50 );
|
||||
if( zOut==0 ){
|
||||
return SQLITE_IOERR_NOMEM;
|
||||
}
|
||||
n = pFile->nJrnl;
|
||||
i = 0;
|
||||
do{
|
||||
zOut[i++] = 'a' + (n%26);
|
||||
n /= 26;
|
||||
}while( n>0 );
|
||||
zOut[i++] = ' ';
|
||||
kvvfsEncode(pFile->aJrnl, pFile->nJrnl, &zOut[i]);
|
||||
i = sqlite3KvvfsMethods.xWrite(pFile->zClass, "jrnl", zOut);
|
||||
sqlite3_free(zOut);
|
||||
return i ? SQLITE_IOERR : SQLITE_OK;
|
||||
}
|
||||
static int kvvfsSyncDb(sqlite3_file *pProtoFile, int flags){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the current file-size of an kvvfs-file.
|
||||
*/
|
||||
static int kvvfsFileSizeJrnl(sqlite3_file *pProtoFile, sqlite_int64 *pSize){
|
||||
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
||||
SQLITE_KV_LOG(("xFileSize('%s-journal')\n", pFile->zClass));
|
||||
*pSize = pFile->nJrnl;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int kvvfsFileSizeDb(sqlite3_file *pProtoFile, sqlite_int64 *pSize){
|
||||
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
||||
SQLITE_KV_LOG(("xFileSize('%s-db')\n", pFile->zClass));
|
||||
if( pFile->szDb>=0 ){
|
||||
*pSize = pFile->szDb;
|
||||
}else{
|
||||
*pSize = kvvfsReadFileSize(pFile);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Lock an kvvfs-file.
|
||||
*/
|
||||
static int kvvfsLock(sqlite3_file *pProtoFile, int eLock){
|
||||
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
||||
assert( !pFile->isJournal );
|
||||
SQLITE_KV_LOG(("xLock(%s,%d)\n", pFile->zClass, eLock));
|
||||
|
||||
if( eLock!=SQLITE_LOCK_NONE ){
|
||||
pFile->szDb = kvvfsReadFileSize(pFile);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Unlock an kvvfs-file.
|
||||
*/
|
||||
static int kvvfsUnlock(sqlite3_file *pProtoFile, int eLock){
|
||||
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
||||
assert( !pFile->isJournal );
|
||||
SQLITE_KV_LOG(("xUnlock(%s,%d)\n", pFile->zClass, eLock));
|
||||
if( eLock==SQLITE_LOCK_NONE ){
|
||||
pFile->szDb = -1;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check if another file-handle holds a RESERVED lock on an kvvfs-file.
|
||||
*/
|
||||
static int kvvfsCheckReservedLock(sqlite3_file *pProtoFile, int *pResOut){
|
||||
SQLITE_KV_LOG(("xCheckReservedLock\n"));
|
||||
*pResOut = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** File control method. For custom operations on an kvvfs-file.
|
||||
*/
|
||||
static int kvvfsFileControlJrnl(sqlite3_file *pProtoFile, int op, void *pArg){
|
||||
SQLITE_KV_LOG(("xFileControl(%d) on journal\n", op));
|
||||
return SQLITE_NOTFOUND;
|
||||
}
|
||||
static int kvvfsFileControlDb(sqlite3_file *pProtoFile, int op, void *pArg){
|
||||
SQLITE_KV_LOG(("xFileControl(%d) on database\n", op));
|
||||
if( op==SQLITE_FCNTL_SYNC ){
|
||||
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_KV_LOG(("xSync('%s-db')\n", pFile->zClass));
|
||||
if( pFile->szDb>0 && 0!=kvvfsWriteFileSize(pFile, pFile->szDb) ){
|
||||
rc = SQLITE_IOERR;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
return SQLITE_NOTFOUND;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the sector-size in bytes for an kvvfs-file.
|
||||
*/
|
||||
static int kvvfsSectorSize(sqlite3_file *pFile){
|
||||
return 512;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the device characteristic flags supported by an kvvfs-file.
|
||||
*/
|
||||
static int kvvfsDeviceCharacteristics(sqlite3_file *pProtoFile){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****** sqlite3_vfs methods *************************************************/
|
||||
|
||||
/*
|
||||
** Open an kvvfs file handle.
|
||||
*/
|
||||
static int kvvfsOpen(
|
||||
sqlite3_vfs *pProtoVfs,
|
||||
const char *zName,
|
||||
sqlite3_file *pProtoFile,
|
||||
int flags,
|
||||
int *pOutFlags
|
||||
){
|
||||
KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
|
||||
if( zName==0 ) zName = "";
|
||||
SQLITE_KV_LOG(("xOpen(\"%s\")\n", zName));
|
||||
if( strcmp(zName, "local")==0
|
||||
|| strcmp(zName, "session")==0
|
||||
){
|
||||
pFile->isJournal = 0;
|
||||
pFile->base.pMethods = &kvvfs_db_io_methods;
|
||||
}else
|
||||
if( strcmp(zName, "local-journal")==0
|
||||
|| strcmp(zName, "session-journal")==0
|
||||
){
|
||||
pFile->isJournal = 1;
|
||||
pFile->base.pMethods = &kvvfs_jrnl_io_methods;
|
||||
}else{
|
||||
return SQLITE_CANTOPEN;
|
||||
}
|
||||
if( zName[0]=='s' ){
|
||||
pFile->zClass = "session";
|
||||
}else{
|
||||
pFile->zClass = "local";
|
||||
}
|
||||
pFile->aJrnl = 0;
|
||||
pFile->nJrnl = 0;
|
||||
pFile->szPage = -1;
|
||||
pFile->szDb = -1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Delete the file located at zPath. If the dirSync argument is true,
|
||||
** ensure the file-system modifications are synced to disk before
|
||||
** returning.
|
||||
*/
|
||||
static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
||||
if( strcmp(zPath, "local-journal")==0 ){
|
||||
sqlite3KvvfsMethods.xDelete("local", "jrnl");
|
||||
}else
|
||||
if( strcmp(zPath, "session-journal")==0 ){
|
||||
sqlite3KvvfsMethods.xDelete("session", "jrnl");
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Test for access permissions. Return true if the requested permission
|
||||
** is available, or false otherwise.
|
||||
*/
|
||||
static int kvvfsAccess(
|
||||
sqlite3_vfs *pProtoVfs,
|
||||
const char *zPath,
|
||||
int flags,
|
||||
int *pResOut
|
||||
){
|
||||
SQLITE_KV_LOG(("xAccess(\"%s\")\n", zPath));
|
||||
if( strcmp(zPath, "local-journal")==0 ){
|
||||
*pResOut = sqlite3KvvfsMethods.xRead("local", "jrnl", 0, 0)>0;
|
||||
}else
|
||||
if( strcmp(zPath, "session-journal")==0 ){
|
||||
*pResOut = sqlite3KvvfsMethods.xRead("session", "jrnl", 0, 0)>0;
|
||||
}else
|
||||
if( strcmp(zPath, "local")==0 ){
|
||||
*pResOut = sqlite3KvvfsMethods.xRead("local", "sz", 0, 0)>0;
|
||||
}else
|
||||
if( strcmp(zPath, "session")==0 ){
|
||||
*pResOut = sqlite3KvvfsMethods.xRead("session", "sz", 0, 0)>0;
|
||||
}else
|
||||
{
|
||||
*pResOut = 0;
|
||||
}
|
||||
SQLITE_KV_LOG(("xAccess returns %d\n",*pResOut));
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Populate buffer zOut with the full canonical pathname corresponding
|
||||
** to the pathname in zPath. zOut is guaranteed to point to a buffer
|
||||
** of at least (INST_MAX_PATHNAME+1) bytes.
|
||||
*/
|
||||
static int kvvfsFullPathname(
|
||||
sqlite3_vfs *pVfs,
|
||||
const char *zPath,
|
||||
int nOut,
|
||||
char *zOut
|
||||
){
|
||||
size_t nPath;
|
||||
#ifdef SQLITE_OS_KV_ALWAYS_LOCAL
|
||||
zPath = "local";
|
||||
#endif
|
||||
nPath = strlen(zPath);
|
||||
SQLITE_KV_LOG(("xFullPathname(\"%s\")\n", zPath));
|
||||
if( nOut<nPath+1 ) nPath = nOut - 1;
|
||||
memcpy(zOut, zPath, nPath);
|
||||
zOut[nPath] = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Open the dynamic library located at zPath and return a handle.
|
||||
*/
|
||||
static void *kvvfsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Populate the buffer pointed to by zBufOut with nByte bytes of
|
||||
** random data.
|
||||
*/
|
||||
static int kvvfsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
|
||||
memset(zBufOut, 0, nByte);
|
||||
return nByte;
|
||||
}
|
||||
|
||||
/*
|
||||
** Sleep for nMicro microseconds. Return the number of microseconds
|
||||
** actually slept.
|
||||
*/
|
||||
static int kvvfsSleep(sqlite3_vfs *pVfs, int nMicro){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the current time as a Julian Day number in *pTimeOut.
|
||||
*/
|
||||
static int kvvfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
|
||||
sqlite3_int64 i = 0;
|
||||
int rc;
|
||||
rc = kvvfsCurrentTimeInt64(0, &i);
|
||||
*pTimeOut = i/86400000.0;
|
||||
return rc;
|
||||
}
|
||||
#include <sys/time.h>
|
||||
static int kvvfsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
|
||||
static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
|
||||
struct timeval sNow;
|
||||
(void)gettimeofday(&sNow, 0); /* Cannot fail given valid arguments */
|
||||
*pTimeOut = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#endif /* SQLITE_OS_KV || SQLITE_OS_UNIX */
|
||||
|
||||
#if SQLITE_OS_KV
|
||||
/*
|
||||
** This routine is called initialize the KV-vfs as the default VFS.
|
||||
*/
|
||||
int sqlite3_os_init(void){
|
||||
return sqlite3_vfs_register(&sqlite3OsKvvfsObject, 1);
|
||||
}
|
||||
int sqlite3_os_end(void){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#endif /* SQLITE_OS_KV */
|
||||
|
||||
#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL)
|
||||
int sqlite3KvvfsInit(void){
|
||||
return sqlite3_vfs_register(&sqlite3OsKvvfsObject, 0);
|
||||
}
|
||||
#endif
|
91
third_party/sqlite3/os_setup.h
vendored
Normal file
91
third_party/sqlite3/os_setup.h
vendored
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
** 2013 November 25
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** This file contains pre-processor directives related to operating system
|
||||
** detection and/or setup.
|
||||
*/
|
||||
#ifndef SQLITE_OS_SETUP_H
|
||||
#define SQLITE_OS_SETUP_H
|
||||
|
||||
/*
|
||||
** Figure out if we are dealing with Unix, Windows, or some other operating
|
||||
** system.
|
||||
**
|
||||
** After the following block of preprocess macros, all of
|
||||
**
|
||||
** SQLITE_OS_KV
|
||||
** SQLITE_OS_OTHER
|
||||
** SQLITE_OS_UNIX
|
||||
** SQLITE_OS_WIN
|
||||
**
|
||||
** will defined to either 1 or 0. One of them will be 1. The others will be 0.
|
||||
** If none of the macros are initially defined, then select either
|
||||
** SQLITE_OS_UNIX or SQLITE_OS_WIN depending on the target platform.
|
||||
**
|
||||
** If SQLITE_OS_OTHER=1 is specified at compile-time, then the application
|
||||
** must provide its own VFS implementation together with sqlite3_os_init()
|
||||
** and sqlite3_os_end() routines.
|
||||
*/
|
||||
#if !defined(SQLITE_OS_KV) && !defined(SQLITE_OS_OTHER) && \
|
||||
!defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_WIN)
|
||||
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
|
||||
defined(__MINGW32__) || defined(__BORLANDC__)
|
||||
# define SQLITE_OS_WIN 1
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# else
|
||||
# define SQLITE_OS_WIN 0
|
||||
# define SQLITE_OS_UNIX 1
|
||||
# endif
|
||||
#endif
|
||||
#if SQLITE_OS_OTHER+1>1
|
||||
# undef SQLITE_OS_KV
|
||||
# define SQLITE_OS_KV 0
|
||||
# undef SQLITE_OS_UNIX
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# undef SQLITE_OS_WIN
|
||||
# define SQLITE_OS_WIN 0
|
||||
#endif
|
||||
#if SQLITE_OS_KV+1>1
|
||||
# undef SQLITE_OS_OTHER
|
||||
# define SQLITE_OS_OTHER 0
|
||||
# undef SQLITE_OS_UNIX
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# undef SQLITE_OS_WIN
|
||||
# define SQLITE_OS_WIN 0
|
||||
# define SQLITE_OMIT_LOAD_EXTENSION 1
|
||||
# define SQLITE_OMIT_WAL 1
|
||||
# define SQLITE_OMIT_DEPRECATED 1
|
||||
# undef SQLITE_TEMP_STORE
|
||||
# define SQLITE_TEMP_STORE 3 /* Always use memory for temporary storage */
|
||||
# define SQLITE_DQS 0
|
||||
# define SQLITE_OMIT_SHARED_CACHE 1
|
||||
# define SQLITE_OMIT_AUTOINIT 1
|
||||
#endif
|
||||
#if SQLITE_OS_UNIX+1>1
|
||||
# undef SQLITE_OS_KV
|
||||
# define SQLITE_OS_KV 0
|
||||
# undef SQLITE_OS_OTHER
|
||||
# define SQLITE_OS_OTHER 0
|
||||
# undef SQLITE_OS_WIN
|
||||
# define SQLITE_OS_WIN 0
|
||||
#endif
|
||||
#if SQLITE_OS_WIN+1>1
|
||||
# undef SQLITE_OS_KV
|
||||
# define SQLITE_OS_KV 0
|
||||
# undef SQLITE_OS_OTHER
|
||||
# define SQLITE_OS_OTHER 0
|
||||
# undef SQLITE_OS_UNIX
|
||||
# define SQLITE_OS_UNIX 0
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* SQLITE_OS_SETUP_H */
|
58
third_party/sqlite3/os_setup.inc
vendored
58
third_party/sqlite3/os_setup.inc
vendored
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
** 2013 November 25
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** This file contains pre-processor directives related to operating system
|
||||
** detection and/or setup.
|
||||
*/
|
||||
#ifndef SQLITE_OS_SETUP_H
|
||||
#define SQLITE_OS_SETUP_H
|
||||
/* clang-format off */
|
||||
|
||||
/*
|
||||
** Figure out if we are dealing with Unix, Windows, or some other operating
|
||||
** system.
|
||||
**
|
||||
** After the following block of preprocess macros, all of SQLITE_OS_UNIX,
|
||||
** SQLITE_OS_WIN, and SQLITE_OS_OTHER will defined to either 1 or 0. One of
|
||||
** the three will be 1. The other two will be 0.
|
||||
*/
|
||||
#if defined(SQLITE_OS_OTHER)
|
||||
# if SQLITE_OS_OTHER==1
|
||||
# undef SQLITE_OS_UNIX
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# undef SQLITE_OS_WIN
|
||||
# define SQLITE_OS_WIN 0
|
||||
# else
|
||||
# undef SQLITE_OS_OTHER
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER)
|
||||
# define SQLITE_OS_OTHER 0
|
||||
# ifndef SQLITE_OS_WIN
|
||||
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
|
||||
defined(__MINGW32__) || defined(__BORLANDC__)
|
||||
# define SQLITE_OS_WIN 1
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# else
|
||||
# define SQLITE_OS_WIN 0
|
||||
# define SQLITE_OS_UNIX 1
|
||||
# endif
|
||||
# else
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# endif
|
||||
#else
|
||||
# ifndef SQLITE_OS_WIN
|
||||
# define SQLITE_OS_WIN 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* SQLITE_OS_SETUP_H */
|
493
third_party/sqlite3/os_unix.c
vendored
493
third_party/sqlite3/os_unix.c
vendored
|
@ -46,16 +46,9 @@
|
|||
*/
|
||||
#include "libc/stdio/rand.h"
|
||||
#include "libc/sysv/consts/lock.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "third_party/sqlite3/sqlite3.h"
|
||||
#include "third_party/sqlite3/mutex.internal.h"
|
||||
#include "third_party/sqlite3/mutex.internal.h"
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/dce.h"
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
#if SQLITE_OS_UNIX /* This file is used on unix only */
|
||||
|
||||
/*
|
||||
|
@ -101,10 +94,14 @@
|
|||
*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/flock.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/calls/weirdtypes.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/runtime/sysconf.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/mremap.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
@ -114,6 +111,16 @@
|
|||
#include "libc/time/time.h"
|
||||
#include "libc/mem/mem.h"
|
||||
|
||||
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
|
||||
#include "libc/isystem/sys/mman.h"
|
||||
#endif
|
||||
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE
|
||||
# include "libc/isystem/sys/ioctl.h"
|
||||
# include "libc/isystem/sys/file.h"
|
||||
# include "libc/isystem/sys/param.h"
|
||||
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
|
||||
|
||||
/*
|
||||
** Try to determine if gethostuuid() is available based on standard
|
||||
** macros. This might sometimes compute the wrong value for some
|
||||
|
@ -143,14 +150,13 @@
|
|||
|
||||
|
||||
#if OS_VXWORKS
|
||||
#include <semaphore.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "libc/limits.h"
|
||||
# include <sys/ioctl.h>
|
||||
# include <semaphore.h>
|
||||
# include "libc/limits.h"
|
||||
#endif /* OS_VXWORKS */
|
||||
|
||||
#ifdef HAVE_UTIME
|
||||
#include "libc/time/time.h"
|
||||
# include "libc/time/time.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -296,7 +302,7 @@ static pid_t randomnessPid = 0;
|
|||
/*
|
||||
** Include code that is common to all os_*.c files
|
||||
*/
|
||||
#include "third_party/sqlite3/os_common.inc"
|
||||
#include "os_common.h"
|
||||
|
||||
/*
|
||||
** Define various macros that are missing from some systems.
|
||||
|
@ -854,20 +860,20 @@ static int robust_ftruncate(int h, sqlite3_int64 sz){
|
|||
** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
|
||||
*/
|
||||
static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
|
||||
assert((sqliteIOErr == SQLITE_IOERR_LOCK) ||
|
||||
(sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
|
||||
(sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
|
||||
(sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK));
|
||||
assert( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
|
||||
(sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
|
||||
(sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
|
||||
(sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) );
|
||||
// changed switch to if-else
|
||||
if (posixError == EACCES || posixError == EAGAIN || posixError == ETIMEDOUT ||
|
||||
posixError == EBUSY || posixError == EINTR || posixError == ENOLCK)
|
||||
/* random NFS retry error, unless during file system support
|
||||
/* random NFS retry error, unless during file system support
|
||||
* introspection, in which it actually means what it says */
|
||||
return SQLITE_BUSY;
|
||||
|
||||
|
||||
else if (posixError == EPERM)
|
||||
return SQLITE_PERM;
|
||||
|
||||
|
||||
else
|
||||
return sqliteIOErr;
|
||||
}
|
||||
|
@ -3541,6 +3547,16 @@ int sqlite3_sync_count = 0;
|
|||
int sqlite3_fullsync_count = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** We do not trust systems to provide a working fdatasync(). Some do.
|
||||
** Others do no. To be safe, we will stick with the (slightly slower)
|
||||
** fsync(). If you know that your system does support fdatasync() correctly,
|
||||
** then simply compile with -Dfdatasync=fdatasync or -DHAVE_FDATASYNC
|
||||
*/
|
||||
#if !defined(fdatasync) && !HAVE_FDATASYNC
|
||||
# define fdatasync fsync
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not
|
||||
** the F_FULLFSYNC macro is defined. F_FULLFSYNC is currently
|
||||
|
@ -3936,6 +3952,9 @@ static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
|
|||
|
||||
/* Forward declaration */
|
||||
static int unixGetTempname(int nBuf, char *zBuf);
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
static int unixFcntlExternalReader(unixFile*, int*);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Information and control of an open file handle.
|
||||
|
@ -4052,6 +4071,15 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
|
|||
return proxyFileControl(id,op,pArg);
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
|
||||
|
||||
case SQLITE_FCNTL_EXTERNAL_READER: {
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
|
||||
#else
|
||||
*(int*)pArg = 0;
|
||||
return SQLITE_OK;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return SQLITE_NOTFOUND;
|
||||
}
|
||||
|
@ -4297,6 +4325,40 @@ struct unixShm {
|
|||
#define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
|
||||
#define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
|
||||
|
||||
/*
|
||||
** Use F_GETLK to check whether or not there are any readers with open
|
||||
** wal-mode transactions in other processes on database file pFile. If
|
||||
** no error occurs, return SQLITE_OK and set (*piOut) to 1 if there are
|
||||
** such transactions, or 0 otherwise. If an error occurs, return an
|
||||
** SQLite error code. The final value of *piOut is undefined in this
|
||||
** case.
|
||||
*/
|
||||
static int unixFcntlExternalReader(unixFile *pFile, int *piOut){
|
||||
int rc = SQLITE_OK;
|
||||
*piOut = 0;
|
||||
if( pFile->pShm){
|
||||
unixShmNode *pShmNode = pFile->pShm->pShmNode;
|
||||
struct flock f;
|
||||
|
||||
memset(&f, 0, sizeof(f));
|
||||
f.l_type = F_WRLCK;
|
||||
f.l_whence = SEEK_SET;
|
||||
f.l_start = UNIX_SHM_BASE + 3;
|
||||
f.l_len = SQLITE_SHM_NLOCK - 3;
|
||||
|
||||
sqlite3_mutex_enter(pShmNode->pShmMutex);
|
||||
if( osFcntl(pShmNode->hShm, F_GETLK, &f)<0 ){
|
||||
rc = SQLITE_IOERR_LOCK;
|
||||
}else{
|
||||
*piOut = (f.l_type!=F_UNLCK);
|
||||
}
|
||||
sqlite3_mutex_leave(pShmNode->pShmMutex);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
|
||||
**
|
||||
|
@ -4849,11 +4911,17 @@ static int unixShmLock(
|
|||
int flags /* What to do with the lock */
|
||||
){
|
||||
unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */
|
||||
unixShm *p = pDbFd->pShm; /* The shared memory being locked */
|
||||
unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */
|
||||
unixShm *p; /* The shared memory being locked */
|
||||
unixShmNode *pShmNode; /* The underlying file iNode */
|
||||
int rc = SQLITE_OK; /* Result code */
|
||||
u16 mask; /* Mask of locks to take or release */
|
||||
int *aLock = pShmNode->aLock;
|
||||
int *aLock;
|
||||
|
||||
p = pDbFd->pShm;
|
||||
if( p==0 ) return SQLITE_IOERR_SHMLOCK;
|
||||
pShmNode = p->pShmNode;
|
||||
if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK;
|
||||
aLock = pShmNode->aLock;
|
||||
|
||||
assert( pShmNode==pDbFd->pInode->pShmNode );
|
||||
assert( pShmNode->pInode==pDbFd->pInode );
|
||||
|
@ -5737,25 +5805,35 @@ static int fillInUnixFile(
|
|||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Directories to consider for temp files.
|
||||
*/
|
||||
static const char *azTempDirs[] = {
|
||||
0,
|
||||
0,
|
||||
"/var/tmp",
|
||||
"/usr/tmp",
|
||||
"/tmp",
|
||||
"."
|
||||
};
|
||||
|
||||
/*
|
||||
** Initialize first two members of azTempDirs[] array.
|
||||
*/
|
||||
static void unixTempFileInit(void){
|
||||
azTempDirs[0] = getenv("SQLITE_TMPDIR");
|
||||
azTempDirs[1] = getenv("TMPDIR");
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the name of a directory in which to put temporary files.
|
||||
** If no suitable temporary file directory can be found, return NULL.
|
||||
*/
|
||||
static const char *unixTempFileDir(void){
|
||||
static const char *azDirs[] = {
|
||||
0,
|
||||
0,
|
||||
"/var/tmp",
|
||||
"/usr/tmp",
|
||||
"/tmp",
|
||||
"."
|
||||
};
|
||||
unsigned int i = 0;
|
||||
struct stat buf;
|
||||
const char *zDir = sqlite3_temp_directory;
|
||||
|
||||
if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR");
|
||||
if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
|
||||
while(1){
|
||||
if( zDir!=0
|
||||
&& osStat(zDir, &buf)==0
|
||||
|
@ -5764,8 +5842,8 @@ static const char *unixTempFileDir(void){
|
|||
){
|
||||
return zDir;
|
||||
}
|
||||
if( i>=sizeof(azDirs)/sizeof(azDirs[0]) ) break;
|
||||
zDir = azDirs[i++];
|
||||
if( i>=sizeof(azTempDirs)/sizeof(azTempDirs[0]) ) break;
|
||||
zDir = azTempDirs[i++];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -5778,6 +5856,7 @@ static const char *unixTempFileDir(void){
|
|||
static int unixGetTempname(int nBuf, char *zBuf){
|
||||
const char *zDir;
|
||||
int iLimit = 0;
|
||||
int rc = SQLITE_OK;
|
||||
int e = errno; // [jart] don't pollute strace logs
|
||||
|
||||
/* It's odd to simulate an io-error here, but really this is just
|
||||
|
@ -5787,19 +5866,27 @@ static int unixGetTempname(int nBuf, char *zBuf){
|
|||
zBuf[0] = 0;
|
||||
SimulateIOError( return SQLITE_IOERR );
|
||||
|
||||
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
||||
zDir = unixTempFileDir();
|
||||
if( zDir==0 ) return SQLITE_IOERR_GETTEMPPATH;
|
||||
do{
|
||||
u64 r;
|
||||
sqlite3_randomness(sizeof(r), &r);
|
||||
assert( nBuf>2 );
|
||||
zBuf[nBuf-2] = 0;
|
||||
sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c",
|
||||
zDir, r, 0);
|
||||
if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ) return SQLITE_ERROR;
|
||||
}while( osAccess(zBuf,0)==0 );
|
||||
if( zDir==0 ){
|
||||
rc = SQLITE_IOERR_GETTEMPPATH;
|
||||
}else{
|
||||
do{
|
||||
u64 r;
|
||||
sqlite3_randomness(sizeof(r), &r);
|
||||
assert( nBuf>2 );
|
||||
zBuf[nBuf-2] = 0;
|
||||
sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c",
|
||||
zDir, r, 0);
|
||||
if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ){
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
}
|
||||
}while( osAccess(zBuf,0)==0 );
|
||||
}
|
||||
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
||||
errno = e; // [jart] don't pollute strace logs
|
||||
return SQLITE_OK;
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
|
||||
|
@ -5942,20 +6029,23 @@ static int findCreateFileMode(
|
|||
**
|
||||
** where NN is a decimal number. The NN naming schemes are
|
||||
** used by the test_multiplex.c module.
|
||||
**
|
||||
** In normal operation, the journal file name will always contain
|
||||
** a '-' character. However in 8+3 filename mode, or if a corrupt
|
||||
** rollback journal specifies a super-journal with a goofy name, then
|
||||
** the '-' might be missing or the '-' might be the first character in
|
||||
** the filename. In that case, just return SQLITE_OK with *pMode==0.
|
||||
*/
|
||||
nDb = sqlite3Strlen30(zPath) - 1;
|
||||
while( zPath[nDb]!='-' ){
|
||||
/* In normal operation, the journal file name will always contain
|
||||
** a '-' character. However in 8+3 filename mode, or if a corrupt
|
||||
** rollback journal specifies a super-journal with a goofy name, then
|
||||
** the '-' might be missing. */
|
||||
if( nDb==0 || zPath[nDb]=='.' ) return SQLITE_OK;
|
||||
nDb = sqlite3Strlen30(zPath) - 1;
|
||||
while( nDb>0 && zPath[nDb]!='.' ){
|
||||
if( zPath[nDb]=='-' ){
|
||||
memcpy(zDb, zPath, nDb);
|
||||
zDb[nDb] = '\0';
|
||||
rc = getFileMode(zDb, pMode, pUid, pGid);
|
||||
break;
|
||||
}
|
||||
nDb--;
|
||||
}
|
||||
memcpy(zDb, zPath, nDb);
|
||||
zDb[nDb] = '\0';
|
||||
|
||||
rc = getFileMode(zDb, pMode, pUid, pGid);
|
||||
}else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
|
||||
*pMode = 0600;
|
||||
}else if( flags & SQLITE_OPEN_URI ){
|
||||
|
@ -6073,6 +6163,11 @@ static int unixOpen(
|
|||
}
|
||||
bzero(p, sizeof(unixFile));
|
||||
|
||||
#ifdef SQLITE_ASSERT_NO_FILES
|
||||
/* Applications that never read or write a persistent disk files */
|
||||
assert( zName==0 );
|
||||
#endif
|
||||
|
||||
if( eType==SQLITE_OPEN_MAIN_DB ){
|
||||
UnixUnusedFd *pUnused;
|
||||
pUnused = findReusableFd(zName, flags);
|
||||
|
@ -6342,86 +6437,99 @@ static int unixAccess(
|
|||
}
|
||||
|
||||
/*
|
||||
** If the last component of the pathname in z[0]..z[j-1] is something
|
||||
** other than ".." then back it out and return true. If the last
|
||||
** component is empty or if it is ".." then return false.
|
||||
** A pathname under construction
|
||||
*/
|
||||
static int unixBackupDir(const char *z, int *pJ){
|
||||
int j = *pJ;
|
||||
int i;
|
||||
if( j<=0 ) return 0;
|
||||
for(i=j-1; i>0 && z[i-1]!='/'; i--){}
|
||||
if( i==0 ) return 0;
|
||||
if( z[i]=='.' && i==j-2 && z[i+1]=='.' ) return 0;
|
||||
*pJ = i-1;
|
||||
return 1;
|
||||
typedef struct DbPath DbPath;
|
||||
struct DbPath {
|
||||
int rc; /* Non-zero following any error */
|
||||
int nSymlink; /* Number of symlinks resolved */
|
||||
char *zOut; /* Write the pathname here */
|
||||
int nOut; /* Bytes of space available to zOut[] */
|
||||
int nUsed; /* Bytes of zOut[] currently being used */
|
||||
};
|
||||
|
||||
/* Forward reference */
|
||||
static void appendAllPathElements(DbPath*,const char*);
|
||||
|
||||
/*
|
||||
** Append a single path element to the DbPath under construction
|
||||
*/
|
||||
static void appendOnePathElement(
|
||||
DbPath *pPath, /* Path under construction, to which to append zName */
|
||||
const char *zName, /* Name to append to pPath. Not zero-terminated */
|
||||
int nName /* Number of significant bytes in zName */
|
||||
){
|
||||
assert( nName>0 );
|
||||
assert( zName!=0 );
|
||||
if( zName[0]=='.' ){
|
||||
if( nName==1 ) return;
|
||||
if( zName[1]=='.' && nName==2 ){
|
||||
if( pPath->nUsed<=1 ){
|
||||
pPath->rc = SQLITE_ERROR;
|
||||
return;
|
||||
}
|
||||
assert( pPath->zOut[0]=='/' );
|
||||
while( pPath->zOut[--pPath->nUsed]!='/' ){}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if( pPath->nUsed + nName + 2 >= pPath->nOut ){
|
||||
pPath->rc = SQLITE_ERROR;
|
||||
return;
|
||||
}
|
||||
pPath->zOut[pPath->nUsed++] = '/';
|
||||
memcpy(&pPath->zOut[pPath->nUsed], zName, nName);
|
||||
pPath->nUsed += nName;
|
||||
#if defined(HAVE_READLINK) && defined(HAVE_LSTAT)
|
||||
if( pPath->rc==SQLITE_OK ){
|
||||
const char *zIn;
|
||||
struct stat buf;
|
||||
pPath->zOut[pPath->nUsed] = 0;
|
||||
zIn = pPath->zOut;
|
||||
if( osLstat(zIn, &buf)!=0 ){
|
||||
if( errno!=ENOENT ){
|
||||
pPath->rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn);
|
||||
}
|
||||
}else if( S_ISLNK(buf.st_mode) ){
|
||||
ssize_t got;
|
||||
char zLnk[SQLITE_MAX_PATHLEN+2];
|
||||
if( pPath->nSymlink++ > SQLITE_MAX_SYMLINK ){
|
||||
pPath->rc = SQLITE_CANTOPEN_BKPT;
|
||||
return;
|
||||
}
|
||||
got = osReadlink(zIn, zLnk, sizeof(zLnk)-2);
|
||||
if( got<=0 || got>=(ssize_t)sizeof(zLnk)-2 ){
|
||||
pPath->rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn);
|
||||
return;
|
||||
}
|
||||
zLnk[got] = 0;
|
||||
if( zLnk[0]=='/' ){
|
||||
pPath->nUsed = 0;
|
||||
}else{
|
||||
pPath->nUsed -= nName + 1;
|
||||
}
|
||||
appendAllPathElements(pPath, zLnk);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Convert a relative pathname into a full pathname. Also
|
||||
** simplify the pathname as follows:
|
||||
**
|
||||
** Remove all instances of /./
|
||||
** Remove all isntances of /X/../ for any X
|
||||
** Append all path elements in zPath to the DbPath under construction.
|
||||
*/
|
||||
static int mkFullPathname(
|
||||
const char *zPath, /* Input path */
|
||||
char *zOut, /* Output buffer */
|
||||
int nOut /* Allocated size of buffer zOut */
|
||||
static void appendAllPathElements(
|
||||
DbPath *pPath, /* Path under construction, to which to append zName */
|
||||
const char *zPath /* Path to append to pPath. Is zero-terminated */
|
||||
){
|
||||
int nPath = sqlite3Strlen30(zPath);
|
||||
int iOff = 0;
|
||||
int i, j;
|
||||
if( zPath[0]!='/' ){
|
||||
if( osGetcwd(zOut, nOut-2)==0 ){
|
||||
return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
do{
|
||||
while( zPath[i] && zPath[i]!='/' ){ i++; }
|
||||
if( i>j ){
|
||||
appendOnePathElement(pPath, &zPath[j], i-j);
|
||||
}
|
||||
iOff = sqlite3Strlen30(zOut);
|
||||
zOut[iOff++] = '/';
|
||||
}
|
||||
if( (iOff+nPath+1)>nOut ){
|
||||
/* SQLite assumes that xFullPathname() nul-terminates the output buffer
|
||||
** even if it returns an error. */
|
||||
zOut[iOff] = '\0';
|
||||
return SQLITE_CANTOPEN_BKPT;
|
||||
}
|
||||
sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath);
|
||||
|
||||
/* Remove duplicate '/' characters. Except, two // at the beginning
|
||||
** of a pathname is allowed since this is important on windows. */
|
||||
for(i=j=1; zOut[i]; i++){
|
||||
zOut[j++] = zOut[i];
|
||||
while( zOut[i]=='/' && zOut[i+1]=='/' ) i++;
|
||||
}
|
||||
zOut[j] = 0;
|
||||
|
||||
assert( zOut[0]=='/' );
|
||||
for(i=j=0; zOut[i]; i++){
|
||||
if( zOut[i]=='/' ){
|
||||
/* Skip over internal "/." directory components */
|
||||
if( zOut[i+1]=='.' && zOut[i+2]=='/' ){
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If this is a "/.." directory component then back out the
|
||||
** previous term of the directory if it is something other than "..".
|
||||
*/
|
||||
if( zOut[i+1]=='.'
|
||||
&& zOut[i+2]=='.'
|
||||
&& zOut[i+3]=='/'
|
||||
&& unixBackupDir(zOut, &j)
|
||||
){
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( ALWAYS(j>=0) ) zOut[j] = zOut[i];
|
||||
j++;
|
||||
}
|
||||
if( NEVER(j==0) ) zOut[j++] = '/';
|
||||
zOut[j] = 0;
|
||||
return SQLITE_OK;
|
||||
j = i+1;
|
||||
}while( zPath[i++] );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -6439,86 +6547,27 @@ static int unixFullPathname(
|
|||
int nOut, /* Size of output buffer in bytes */
|
||||
char *zOut /* Output buffer */
|
||||
){
|
||||
#if !defined(HAVE_READLINK) || !defined(HAVE_LSTAT)
|
||||
return mkFullPathname(zPath, zOut, nOut);
|
||||
#else
|
||||
int rc = SQLITE_OK;
|
||||
int nByte;
|
||||
int nLink = 0; /* Number of symbolic links followed so far */
|
||||
const char *zIn = zPath; /* Input path for each iteration of loop */
|
||||
char *zDel = 0;
|
||||
|
||||
assert( pVfs->mxPathname==MAX_PATHNAME );
|
||||
DbPath path;
|
||||
UNUSED_PARAMETER(pVfs);
|
||||
|
||||
/* It's odd to simulate an io-error here, but really this is just
|
||||
** using the io-error infrastructure to test that SQLite handles this
|
||||
** function failing. This function could fail if, for example, the
|
||||
** current working directory has been unlinked.
|
||||
*/
|
||||
SimulateIOError( return SQLITE_ERROR );
|
||||
|
||||
do {
|
||||
|
||||
/* Call stat() on path zIn. Set bLink to true if the path is a symbolic
|
||||
** link, or false otherwise. */
|
||||
int bLink = 0;
|
||||
struct stat buf;
|
||||
if( osLstat(zIn, &buf)!=0 ){
|
||||
if( errno!=ENOENT ){
|
||||
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn);
|
||||
}
|
||||
}else{
|
||||
bLink = S_ISLNK(buf.st_mode);
|
||||
path.rc = 0;
|
||||
path.nUsed = 0;
|
||||
path.nSymlink = 0;
|
||||
path.nOut = nOut;
|
||||
path.zOut = zOut;
|
||||
if( zPath[0]!='/' ){
|
||||
char zPwd[SQLITE_MAX_PATHLEN+2];
|
||||
if( osGetcwd(zPwd, sizeof(zPwd)-2)==0 ){
|
||||
return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
|
||||
}
|
||||
|
||||
if( bLink ){
|
||||
nLink++;
|
||||
if( zDel==0 ){
|
||||
zDel = sqlite3_malloc(nOut);
|
||||
if( zDel==0 ) rc = SQLITE_NOMEM_BKPT;
|
||||
}else if( nLink>=SQLITE_MAX_SYMLINKS ){
|
||||
rc = SQLITE_CANTOPEN_BKPT;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
nByte = osReadlink(zIn, zDel, nOut-1);
|
||||
if( nByte<0 ){
|
||||
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn);
|
||||
}else{
|
||||
if( zDel[0]!='/' ){
|
||||
int n;
|
||||
for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--);
|
||||
if( nByte+n+1>nOut ){
|
||||
rc = SQLITE_CANTOPEN_BKPT;
|
||||
}else{
|
||||
memmove(&zDel[n], zDel, nByte+1);
|
||||
memcpy(zDel, zIn, n);
|
||||
nByte += n;
|
||||
}
|
||||
}
|
||||
zDel[nByte] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
zIn = zDel;
|
||||
}
|
||||
|
||||
assert( rc!=SQLITE_OK || zIn!=zOut || zIn[0]=='/' );
|
||||
if( rc==SQLITE_OK && zIn!=zOut ){
|
||||
rc = mkFullPathname(zIn, zOut, nOut);
|
||||
}
|
||||
if( bLink==0 ) break;
|
||||
zIn = zOut;
|
||||
}while( rc==SQLITE_OK );
|
||||
|
||||
sqlite3_free(zDel);
|
||||
if( rc==SQLITE_OK && nLink ) rc = SQLITE_OK_SYMLINK;
|
||||
return rc;
|
||||
#endif /* HAVE_READLINK && HAVE_LSTAT */
|
||||
appendAllPathElements(&path, zPwd);
|
||||
}
|
||||
appendAllPathElements(&path, zPath);
|
||||
zOut[path.nUsed] = 0;
|
||||
if( path.rc || path.nUsed<2 ) return SQLITE_CANTOPEN_BKPT;
|
||||
if( path.nSymlink ) return SQLITE_OK_SYMLINK;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
||||
/*
|
||||
** Interfaces for opening a shared library, finding entry points
|
||||
|
@ -7983,9 +8032,39 @@ int sqlite3_os_init(void){
|
|||
|
||||
/* Register all VFSes defined in the aVfs[] array */
|
||||
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
|
||||
#ifdef SQLITE_DEFAULT_UNIX_VFS
|
||||
sqlite3_vfs_register(&aVfs[i],
|
||||
0==strcmp(aVfs[i].zName,SQLITE_DEFAULT_UNIX_VFS));
|
||||
#else
|
||||
sqlite3_vfs_register(&aVfs[i], i==0);
|
||||
#endif
|
||||
}
|
||||
#ifdef SQLITE_OS_KV_OPTIONAL
|
||||
sqlite3KvvfsInit();
|
||||
#endif
|
||||
unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
|
||||
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
/* Validate lock assumptions */
|
||||
assert( SQLITE_SHM_NLOCK==8 ); /* Number of available locks */
|
||||
assert( UNIX_SHM_BASE==120 ); /* Start of locking area */
|
||||
/* Locks:
|
||||
** WRITE UNIX_SHM_BASE 120
|
||||
** CKPT UNIX_SHM_BASE+1 121
|
||||
** RECOVER UNIX_SHM_BASE+2 122
|
||||
** READ-0 UNIX_SHM_BASE+3 123
|
||||
** READ-1 UNIX_SHM_BASE+4 124
|
||||
** READ-2 UNIX_SHM_BASE+5 125
|
||||
** READ-3 UNIX_SHM_BASE+6 126
|
||||
** READ-4 UNIX_SHM_BASE+7 127
|
||||
** DMS UNIX_SHM_BASE+8 128
|
||||
*/
|
||||
assert( UNIX_SHM_DMS==128 ); /* Byte offset of the deadman-switch */
|
||||
#endif
|
||||
|
||||
/* Initialize temp file dir array. */
|
||||
unixTempFileInit();
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
|
6149
third_party/sqlite3/os_win.c
vendored
6149
third_party/sqlite3/os_win.c
vendored
File diff suppressed because it is too large
Load diff
1
third_party/sqlite3/os_win.shell.c
vendored
1
third_party/sqlite3/os_win.shell.c
vendored
|
@ -1 +0,0 @@
|
|||
#include "third_party/sqlite3/os_win.c"
|
103
third_party/sqlite3/pager.c
vendored
103
third_party/sqlite3/pager.c
vendored
|
@ -10,7 +10,7 @@
|
|||
**
|
||||
*************************************************************************
|
||||
** This is the implementation of the page cache subsystem or "pager".
|
||||
**
|
||||
**
|
||||
** The pager is used to access a database disk file. It implements
|
||||
** atomic commit and rollback through the use of a journal file that
|
||||
** is separate from the database file. The pager also implements file
|
||||
|
@ -19,9 +19,8 @@
|
|||
** another is writing.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_DISKIO
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
#include "third_party/sqlite3/wal.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
#include "third_party/sqlite3/wal.h"
|
||||
|
||||
|
||||
/******************* NOTES ON THE DESIGN OF THE PAGER ************************
|
||||
|
@ -631,6 +630,7 @@ struct Pager {
|
|||
u8 noLock; /* Do not lock (except in WAL mode) */
|
||||
u8 readOnly; /* True for a read-only database */
|
||||
u8 memDb; /* True to inhibit all file I/O */
|
||||
u8 memVfs; /* VFS-implemented memory database */
|
||||
|
||||
/**************************************************************************
|
||||
** The following block contains those class members that change during
|
||||
|
@ -680,8 +680,9 @@ struct Pager {
|
|||
i16 nReserve; /* Number of unused bytes at end of each page */
|
||||
u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */
|
||||
u32 sectorSize; /* Assumed sector size during rollback */
|
||||
int pageSize; /* Number of bytes in a page */
|
||||
Pgno mxPgno; /* Maximum allowed size of the database */
|
||||
Pgno lckPgno; /* Page number for the locking page */
|
||||
i64 pageSize; /* Number of bytes in a page */
|
||||
i64 journalSizeLimit; /* Size limit for persistent journal files */
|
||||
char *zFilename; /* Name of the database file */
|
||||
char *zJournal; /* Name of the journal file */
|
||||
|
@ -1667,7 +1668,7 @@ static int readJournalHdr(
|
|||
** journal file descriptor is advanced to the next sector boundary before
|
||||
** anything is written. The format is:
|
||||
**
|
||||
** + 4 bytes: PAGER_MJ_PGNO.
|
||||
** + 4 bytes: PAGER_SJ_PGNO.
|
||||
** + N bytes: super-journal filename in utf-8.
|
||||
** + 4 bytes: N (length of super-journal name in bytes, no nul-terminator).
|
||||
** + 4 bytes: super-journal name checksum.
|
||||
|
@ -1715,7 +1716,7 @@ static int writeSuperJournal(Pager *pPager, const char *zSuper){
|
|||
/* Write the super-journal data to the end of the journal file. If
|
||||
** an error occurs, return the error code to the caller.
|
||||
*/
|
||||
if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_MJ_PGNO(pPager))))
|
||||
if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_SJ_PGNO(pPager))))
|
||||
|| (0 != (rc = sqlite3OsWrite(pPager->jfd, zSuper, nSuper, iHdrOff+4)))
|
||||
|| (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper, nSuper)))
|
||||
|| (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper+4, cksum)))
|
||||
|
@ -2225,7 +2226,7 @@ static u32 pager_cksum(Pager *pPager, const u8 *aData){
|
|||
** corrupted, SQLITE_DONE is returned. Data is considered corrupted in
|
||||
** two circumstances:
|
||||
**
|
||||
** * If the record page-number is illegal (0 or PAGER_MJ_PGNO), or
|
||||
** * If the record page-number is illegal (0 or PAGER_SJ_PGNO), or
|
||||
** * If the record is being rolled back from the main journal file
|
||||
** and the checksum field does not match the record content.
|
||||
**
|
||||
|
@ -2285,7 +2286,7 @@ static int pager_playback_one_page(
|
|||
** it could cause invalid data to be written into the journal. We need to
|
||||
** detect this invalid data (with high probability) and ignore it.
|
||||
*/
|
||||
if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){
|
||||
if( pgno==0 || pgno==PAGER_SJ_PGNO(pPager) ){
|
||||
assert( !isSavepnt );
|
||||
return SQLITE_DONE;
|
||||
}
|
||||
|
@ -2622,6 +2623,7 @@ static int pager_truncate(Pager *pPager, Pgno nPage){
|
|||
memset(pTmp, 0, szPage);
|
||||
testcase( (newSize-szPage) == currentSize );
|
||||
testcase( (newSize-szPage) > currentSize );
|
||||
sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &newSize);
|
||||
rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
|
@ -2844,6 +2846,9 @@ static int pager_playback(Pager *pPager, int isHot){
|
|||
goto end_playback;
|
||||
}
|
||||
pPager->dbSize = mxPg;
|
||||
if( pPager->mxPgno<mxPg ){
|
||||
pPager->mxPgno = mxPg;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy original pages out of the journal and back into the
|
||||
|
@ -3025,6 +3030,7 @@ static int readDbPage(PgHdr *pPg){
|
|||
*/
|
||||
static void pager_write_changecounter(PgHdr *pPg){
|
||||
u32 change_counter;
|
||||
if( NEVER(pPg==0) ) return;
|
||||
|
||||
/* Increment the value just read and write it back to byte 24. */
|
||||
change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1;
|
||||
|
@ -3739,6 +3745,7 @@ int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){
|
|||
pPager->pTmpSpace = pNew;
|
||||
pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
|
||||
pPager->pageSize = pageSize;
|
||||
pPager->lckPgno = (Pgno)(PENDING_BYTE/pageSize) + 1;
|
||||
}else{
|
||||
sqlite3PageFree(pNew);
|
||||
}
|
||||
|
@ -3899,8 +3906,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
|
|||
** current database image, in pages, OR
|
||||
**
|
||||
** b) if the page content were written at this time, it would not
|
||||
** be necessary to write the current content out to the sub-journal
|
||||
** (as determined by function subjRequiresPage()).
|
||||
** be necessary to write the current content out to the sub-journal.
|
||||
**
|
||||
** If the condition asserted by this function were not true, and the
|
||||
** dirty page were to be discarded from the cache via the pagerStress()
|
||||
|
@ -3915,8 +3921,16 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
|
|||
*/
|
||||
#if defined(SQLITE_DEBUG)
|
||||
static void assertTruncateConstraintCb(PgHdr *pPg){
|
||||
Pager *pPager = pPg->pPager;
|
||||
assert( pPg->flags&PGHDR_DIRTY );
|
||||
assert( !subjRequiresPage(pPg) || pPg->pgno<=pPg->pPager->dbSize );
|
||||
if( pPg->pgno>pPager->dbSize ){ /* if (a) is false */
|
||||
Pgno pgno = pPg->pgno;
|
||||
int i;
|
||||
for(i=0; i<pPg->pPager->nSavepoint; i++){
|
||||
PagerSavepoint *p = &pPager->aSavepoint[i];
|
||||
assert( p->nOrig<pgno || sqlite3BitvecTestNotNull(p->pInSavepoint,pgno) );
|
||||
}
|
||||
}
|
||||
}
|
||||
static void assertTruncateConstraint(Pager *pPager){
|
||||
sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb);
|
||||
|
@ -3937,7 +3951,7 @@ static void assertTruncateConstraint(Pager *pPager){
|
|||
** then continue writing to the database.
|
||||
*/
|
||||
void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
|
||||
assert( pPager->dbSize>=nPage );
|
||||
assert( pPager->dbSize>=nPage || CORRUPT_DB );
|
||||
assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
|
||||
pPager->dbSize = nPage;
|
||||
|
||||
|
@ -4665,7 +4679,7 @@ int sqlite3PagerOpen(
|
|||
int rc = SQLITE_OK; /* Return code */
|
||||
int tempFile = 0; /* True for temp files (incl. in-memory files) */
|
||||
int memDb = 0; /* True if this is an in-memory file */
|
||||
#ifdef SQLITE_ENABLE_DESERIALIZE
|
||||
#ifndef SQLITE_OMIT_DESERIALIZE
|
||||
int memJM = 0; /* Memory journal mode */
|
||||
#else
|
||||
# define memJM 0
|
||||
|
@ -4858,6 +4872,7 @@ int sqlite3PagerOpen(
|
|||
pPager->zWal = 0;
|
||||
}
|
||||
#endif
|
||||
(void)pPtr; /* Suppress warning about unused pPtr value */
|
||||
|
||||
if( nPathname ) sqlite3DbFree(0, zPathname);
|
||||
pPager->pVfs = pVfs;
|
||||
|
@ -4869,8 +4884,8 @@ int sqlite3PagerOpen(
|
|||
int fout = 0; /* VFS flags returned by xOpen() */
|
||||
rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
|
||||
assert( !memDb );
|
||||
#ifdef SQLITE_ENABLE_DESERIALIZE
|
||||
memJM = (fout&SQLITE_OPEN_MEMORY)!=0;
|
||||
#ifndef SQLITE_OMIT_DESERIALIZE
|
||||
pPager->memVfs = memJM = (fout&SQLITE_OPEN_MEMORY)!=0;
|
||||
#endif
|
||||
readOnly = (fout&SQLITE_OPEN_READONLY)!=0;
|
||||
|
||||
|
@ -5255,7 +5270,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
|||
** may mean that the pager was in the error-state when this
|
||||
** function was called and the journal file does not exist.
|
||||
*/
|
||||
if( !isOpen(pPager->jfd) ){
|
||||
if( !isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
|
||||
sqlite3_vfs * const pVfs = pPager->pVfs;
|
||||
int bExists; /* True if journal file exists */
|
||||
rc = sqlite3OsAccess(
|
||||
|
@ -5500,7 +5515,7 @@ static int getPageNormal(
|
|||
if( pPg->pPager && !noContent ){
|
||||
/* In this case the pcache already contains an initialized copy of
|
||||
** the page. Return without further ado. */
|
||||
assert( pgno!=PAGER_MJ_PGNO(pPager) );
|
||||
assert( pgno!=PAGER_SJ_PGNO(pPager) );
|
||||
pPager->aStat[PAGER_STAT_HIT]++;
|
||||
return SQLITE_OK;
|
||||
|
||||
|
@ -5511,7 +5526,7 @@ static int getPageNormal(
|
|||
** (*) obsolete. Was: maximum page number is 2^31
|
||||
** (2) Never try to fetch the locking page
|
||||
*/
|
||||
if( pgno==PAGER_MJ_PGNO(pPager) ){
|
||||
if( pgno==PAGER_SJ_PGNO(pPager) ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto pager_acquire_err;
|
||||
}
|
||||
|
@ -5657,6 +5672,7 @@ int sqlite3PagerGet(
|
|||
DbPage **ppPage, /* Write a pointer to the page here */
|
||||
int flags /* PAGER_GET_XXX flags */
|
||||
){
|
||||
/* printf("PAGE %u\n", pgno); fflush(stdout); */
|
||||
return pPager->xGet(pPager, pgno, ppPage, flags);
|
||||
}
|
||||
|
||||
|
@ -5770,6 +5786,7 @@ static int pager_open_journal(Pager *pPager){
|
|||
|
||||
if( pPager->tempFile ){
|
||||
flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL);
|
||||
flags |= SQLITE_OPEN_EXCLUSIVE;
|
||||
nSpill = sqlite3Config.nStmtSpill;
|
||||
}else{
|
||||
flags |= SQLITE_OPEN_MAIN_JOURNAL;
|
||||
|
@ -5805,6 +5822,7 @@ static int pager_open_journal(Pager *pPager){
|
|||
if( rc!=SQLITE_OK ){
|
||||
sqlite3BitvecDestroy(pPager->pInJournal);
|
||||
pPager->pInJournal = 0;
|
||||
pPager->journalOff = 0;
|
||||
}else{
|
||||
assert( pPager->eState==PAGER_WRITER_LOCKED );
|
||||
pPager->eState = PAGER_WRITER_CACHEMOD;
|
||||
|
@ -5837,7 +5855,7 @@ int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
|
|||
assert( pPager->eState>=PAGER_READER && pPager->eState<PAGER_ERROR );
|
||||
pPager->subjInMemory = (u8)subjInMemory;
|
||||
|
||||
if( ALWAYS(pPager->eState==PAGER_READER) ){
|
||||
if( pPager->eState==PAGER_READER ){
|
||||
assert( pPager->pInJournal==0 );
|
||||
|
||||
if( pagerUseWal(pPager) ){
|
||||
|
@ -5909,7 +5927,7 @@ static SQLITE_NOINLINE int pagerAddPageToRollbackJournal(PgHdr *pPg){
|
|||
/* We should never write to the journal file the page that
|
||||
** contains the database locks. The following assert verifies
|
||||
** that we do not. */
|
||||
assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
|
||||
assert( pPg->pgno!=PAGER_SJ_PGNO(pPager) );
|
||||
|
||||
assert( pPager->journalHdr<=pPager->journalOff );
|
||||
pData2 = pPg->pData;
|
||||
|
@ -6088,7 +6106,7 @@ static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){
|
|||
Pgno pg = pg1+ii;
|
||||
PgHdr *pPage;
|
||||
if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){
|
||||
if( pg!=PAGER_MJ_PGNO(pPager) ){
|
||||
if( pg!=PAGER_SJ_PGNO(pPager) ){
|
||||
rc = sqlite3PagerGet(pPager, pg, &pPage, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pager_write(pPage);
|
||||
|
@ -6566,7 +6584,7 @@ int sqlite3PagerCommitPhaseOne(
|
|||
** last page is never written out to disk, leaving the database file
|
||||
** undersized. Fix this now if it is the case. */
|
||||
if( pPager->dbSize>pPager->dbFileSize ){
|
||||
Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager));
|
||||
Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_SJ_PGNO(pPager));
|
||||
assert( pPager->eState==PAGER_WRITER_DBMOD );
|
||||
rc = pager_truncate(pPager, nNew);
|
||||
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
|
||||
|
@ -6737,8 +6755,8 @@ int sqlite3PagerRefcount(Pager *pPager){
|
|||
** used by the pager and its associated cache.
|
||||
*/
|
||||
int sqlite3PagerMemUsed(Pager *pPager){
|
||||
int perPageSize = pPager->pageSize + pPager->nExtra + sizeof(PgHdr)
|
||||
+ 5*sizeof(void*);
|
||||
int perPageSize = pPager->pageSize + pPager->nExtra
|
||||
+ (int)(sizeof(PgHdr) + 5*sizeof(void*));
|
||||
return perPageSize*sqlite3PcachePagecount(pPager->pPCache)
|
||||
+ sqlite3MallocSize(pPager)
|
||||
+ pPager->pageSize;
|
||||
|
@ -6807,7 +6825,7 @@ void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
|
|||
** Return true if this is an in-memory or temp-file backed pager.
|
||||
*/
|
||||
int sqlite3PagerIsMemdb(Pager *pPager){
|
||||
return pPager->tempFile;
|
||||
return pPager->tempFile || pPager->memVfs;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -6932,14 +6950,14 @@ int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
|
|||
}
|
||||
pPager->nSavepoint = nNew;
|
||||
|
||||
/* If this is a release of the outermost savepoint, truncate
|
||||
** the sub-journal to zero bytes in size. */
|
||||
/* Truncate the sub-journal so that it only includes the parts
|
||||
** that are still in use. */
|
||||
if( op==SAVEPOINT_RELEASE ){
|
||||
PagerSavepoint *pRel = &pPager->aSavepoint[nNew];
|
||||
if( pRel->bTruncateOnRelease && isOpen(pPager->sjfd) ){
|
||||
/* Only truncate if it is an in-memory sub-journal. */
|
||||
if( sqlite3JournalIsInMemory(pPager->sjfd) ){
|
||||
i64 sz = (pPager->pageSize+4)*pRel->iSubRec;
|
||||
i64 sz = (pPager->pageSize+4)*(i64)pRel->iSubRec;
|
||||
rc = sqlite3OsTruncate(pPager->sjfd, sz);
|
||||
assert( rc==SQLITE_OK );
|
||||
}
|
||||
|
@ -7127,7 +7145,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
|||
pPgOld = sqlite3PagerLookup(pPager, pgno);
|
||||
assert( !pPgOld || pPgOld->nRef==1 || CORRUPT_DB );
|
||||
if( pPgOld ){
|
||||
if( pPgOld->nRef>1 ){
|
||||
if( NEVER(pPgOld->nRef>1) ){
|
||||
sqlite3PagerUnrefNotNull(pPgOld);
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
|
@ -7262,12 +7280,12 @@ int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
|
|||
u8 eOld = pPager->journalMode; /* Prior journalmode */
|
||||
|
||||
/* The eMode parameter is always valid */
|
||||
assert( eMode==PAGER_JOURNALMODE_DELETE
|
||||
|| eMode==PAGER_JOURNALMODE_TRUNCATE
|
||||
|| eMode==PAGER_JOURNALMODE_PERSIST
|
||||
|| eMode==PAGER_JOURNALMODE_OFF
|
||||
|| eMode==PAGER_JOURNALMODE_WAL
|
||||
|| eMode==PAGER_JOURNALMODE_MEMORY );
|
||||
assert( eMode==PAGER_JOURNALMODE_DELETE /* 0 */
|
||||
|| eMode==PAGER_JOURNALMODE_PERSIST /* 1 */
|
||||
|| eMode==PAGER_JOURNALMODE_OFF /* 2 */
|
||||
|| eMode==PAGER_JOURNALMODE_TRUNCATE /* 3 */
|
||||
|| eMode==PAGER_JOURNALMODE_MEMORY /* 4 */
|
||||
|| eMode==PAGER_JOURNALMODE_WAL /* 5 */ );
|
||||
|
||||
/* This routine is only called from the OP_JournalMode opcode, and
|
||||
** the logic there will never allow a temporary file to be changed
|
||||
|
@ -7304,7 +7322,6 @@ int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
|
|||
|
||||
assert( isOpen(pPager->fd) || pPager->exclusiveMode );
|
||||
if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){
|
||||
|
||||
/* In this case we would like to delete the journal file. If it is
|
||||
** not possible, then that is not a problem. Deleting the journal file
|
||||
** here is an optimization only.
|
||||
|
@ -7416,6 +7433,18 @@ int sqlite3PagerCheckpoint(
|
|||
int *pnCkpt /* OUT: Final number of checkpointed frames */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
if( pPager->pWal==0 && pPager->journalMode==PAGER_JOURNALMODE_WAL ){
|
||||
/* This only happens when a database file is zero bytes in size opened and
|
||||
** then "PRAGMA journal_mode=WAL" is run and then sqlite3_wal_checkpoint()
|
||||
** is invoked without any intervening transactions. We need to start
|
||||
** a transaction to initialize pWal. The PRAGMA table_list statement is
|
||||
** used for this since it starts transactions on every database file,
|
||||
** including all ATTACHed databases. This seems expensive for a single
|
||||
** sqlite3_wal_checkpoint() call, but it happens very rarely.
|
||||
** https://sqlite.org/forum/forumpost/fd0f19d229156939
|
||||
*/
|
||||
sqlite3_exec(db, "PRAGMA table_list",0,0,0);
|
||||
}
|
||||
if( pPager->pWal ){
|
||||
rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode,
|
||||
(eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
|
||||
|
|
6
third_party/sqlite3/pager.inc
vendored
6
third_party/sqlite3/pager.inc
vendored
|
@ -13,7 +13,6 @@
|
|||
** subsystem. The page cache subsystem reads and writes a file a page
|
||||
** at a time and provides a journal for rollback.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
#ifndef SQLITE_PAGER_H
|
||||
#define SQLITE_PAGER_H
|
||||
|
@ -44,14 +43,15 @@ typedef struct Pager Pager;
|
|||
typedef struct PgHdr DbPage;
|
||||
|
||||
/*
|
||||
** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is
|
||||
** Page number PAGER_SJ_PGNO is never used in an SQLite database (it is
|
||||
** reserved for working around a windows/posix incompatibility). It is
|
||||
** used in the journal to signify that the remainder of the journal file
|
||||
** is devoted to storing a super-journal name - there are no more pages to
|
||||
** roll back. See comments for function writeSuperJournal() in pager.c
|
||||
** for details.
|
||||
*/
|
||||
#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1))
|
||||
#define PAGER_SJ_PGNO_COMPUTED(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1))
|
||||
#define PAGER_SJ_PGNO(x) ((x)->lckPgno)
|
||||
|
||||
/*
|
||||
** Allowed values for the flags parameter to sqlite3PagerOpen().
|
||||
|
|
6681
third_party/sqlite3/parse.c
vendored
6681
third_party/sqlite3/parse.c
vendored
File diff suppressed because it is too large
Load diff
|
@ -22,8 +22,8 @@
|
|||
#define TK_LP 22
|
||||
#define TK_RP 23
|
||||
#define TK_AS 24
|
||||
#define TK_WITHOUT 25
|
||||
#define TK_COMMA 26
|
||||
#define TK_COMMA 25
|
||||
#define TK_WITHOUT 26
|
||||
#define TK_ABORT 27
|
||||
#define TK_ACTION 28
|
||||
#define TK_AFTER 29
|
||||
|
@ -109,74 +109,76 @@
|
|||
#define TK_SLASH 109
|
||||
#define TK_REM 110
|
||||
#define TK_CONCAT 111
|
||||
#define TK_COLLATE 112
|
||||
#define TK_BITNOT 113
|
||||
#define TK_ON 114
|
||||
#define TK_INDEXED 115
|
||||
#define TK_STRING 116
|
||||
#define TK_JOIN_KW 117
|
||||
#define TK_CONSTRAINT 118
|
||||
#define TK_DEFAULT 119
|
||||
#define TK_NULL 120
|
||||
#define TK_PRIMARY 121
|
||||
#define TK_UNIQUE 122
|
||||
#define TK_CHECK 123
|
||||
#define TK_REFERENCES 124
|
||||
#define TK_AUTOINCR 125
|
||||
#define TK_INSERT 126
|
||||
#define TK_DELETE 127
|
||||
#define TK_UPDATE 128
|
||||
#define TK_SET 129
|
||||
#define TK_DEFERRABLE 130
|
||||
#define TK_FOREIGN 131
|
||||
#define TK_DROP 132
|
||||
#define TK_UNION 133
|
||||
#define TK_ALL 134
|
||||
#define TK_EXCEPT 135
|
||||
#define TK_INTERSECT 136
|
||||
#define TK_SELECT 137
|
||||
#define TK_VALUES 138
|
||||
#define TK_DISTINCT 139
|
||||
#define TK_DOT 140
|
||||
#define TK_FROM 141
|
||||
#define TK_JOIN 142
|
||||
#define TK_USING 143
|
||||
#define TK_ORDER 144
|
||||
#define TK_GROUP 145
|
||||
#define TK_HAVING 146
|
||||
#define TK_LIMIT 147
|
||||
#define TK_WHERE 148
|
||||
#define TK_RETURNING 149
|
||||
#define TK_INTO 150
|
||||
#define TK_NOTHING 151
|
||||
#define TK_FLOAT 152
|
||||
#define TK_BLOB 153
|
||||
#define TK_INTEGER 154
|
||||
#define TK_VARIABLE 155
|
||||
#define TK_CASE 156
|
||||
#define TK_WHEN 157
|
||||
#define TK_THEN 158
|
||||
#define TK_ELSE 159
|
||||
#define TK_INDEX 160
|
||||
#define TK_ALTER 161
|
||||
#define TK_ADD 162
|
||||
#define TK_WINDOW 163
|
||||
#define TK_OVER 164
|
||||
#define TK_FILTER 165
|
||||
#define TK_COLUMN 166
|
||||
#define TK_AGG_FUNCTION 167
|
||||
#define TK_AGG_COLUMN 168
|
||||
#define TK_TRUEFALSE 169
|
||||
#define TK_ISNOT 170
|
||||
#define TK_FUNCTION 171
|
||||
#define TK_UMINUS 172
|
||||
#define TK_UPLUS 173
|
||||
#define TK_TRUTH 174
|
||||
#define TK_REGISTER 175
|
||||
#define TK_VECTOR 176
|
||||
#define TK_SELECT_COLUMN 177
|
||||
#define TK_IF_NULL_ROW 178
|
||||
#define TK_ASTERISK 179
|
||||
#define TK_SPAN 180
|
||||
#define TK_SPACE 181
|
||||
#define TK_ILLEGAL 182
|
||||
#define TK_PTR 112
|
||||
#define TK_COLLATE 113
|
||||
#define TK_BITNOT 114
|
||||
#define TK_ON 115
|
||||
#define TK_INDEXED 116
|
||||
#define TK_STRING 117
|
||||
#define TK_JOIN_KW 118
|
||||
#define TK_CONSTRAINT 119
|
||||
#define TK_DEFAULT 120
|
||||
#define TK_NULL 121
|
||||
#define TK_PRIMARY 122
|
||||
#define TK_UNIQUE 123
|
||||
#define TK_CHECK 124
|
||||
#define TK_REFERENCES 125
|
||||
#define TK_AUTOINCR 126
|
||||
#define TK_INSERT 127
|
||||
#define TK_DELETE 128
|
||||
#define TK_UPDATE 129
|
||||
#define TK_SET 130
|
||||
#define TK_DEFERRABLE 131
|
||||
#define TK_FOREIGN 132
|
||||
#define TK_DROP 133
|
||||
#define TK_UNION 134
|
||||
#define TK_ALL 135
|
||||
#define TK_EXCEPT 136
|
||||
#define TK_INTERSECT 137
|
||||
#define TK_SELECT 138
|
||||
#define TK_VALUES 139
|
||||
#define TK_DISTINCT 140
|
||||
#define TK_DOT 141
|
||||
#define TK_FROM 142
|
||||
#define TK_JOIN 143
|
||||
#define TK_USING 144
|
||||
#define TK_ORDER 145
|
||||
#define TK_GROUP 146
|
||||
#define TK_HAVING 147
|
||||
#define TK_LIMIT 148
|
||||
#define TK_WHERE 149
|
||||
#define TK_RETURNING 150
|
||||
#define TK_INTO 151
|
||||
#define TK_NOTHING 152
|
||||
#define TK_FLOAT 153
|
||||
#define TK_BLOB 154
|
||||
#define TK_INTEGER 155
|
||||
#define TK_VARIABLE 156
|
||||
#define TK_CASE 157
|
||||
#define TK_WHEN 158
|
||||
#define TK_THEN 159
|
||||
#define TK_ELSE 160
|
||||
#define TK_INDEX 161
|
||||
#define TK_ALTER 162
|
||||
#define TK_ADD 163
|
||||
#define TK_WINDOW 164
|
||||
#define TK_OVER 165
|
||||
#define TK_FILTER 166
|
||||
#define TK_COLUMN 167
|
||||
#define TK_AGG_FUNCTION 168
|
||||
#define TK_AGG_COLUMN 169
|
||||
#define TK_TRUEFALSE 170
|
||||
#define TK_ISNOT 171
|
||||
#define TK_FUNCTION 172
|
||||
#define TK_UMINUS 173
|
||||
#define TK_UPLUS 174
|
||||
#define TK_TRUTH 175
|
||||
#define TK_REGISTER 176
|
||||
#define TK_VECTOR 177
|
||||
#define TK_SELECT_COLUMN 178
|
||||
#define TK_IF_NULL_ROW 179
|
||||
#define TK_ASTERISK 180
|
||||
#define TK_SPAN 181
|
||||
#define TK_ERROR 182
|
||||
#define TK_SPACE 183
|
||||
#define TK_ILLEGAL 184
|
73
third_party/sqlite3/pcache.c
vendored
73
third_party/sqlite3/pcache.c
vendored
|
@ -11,8 +11,7 @@
|
|||
*************************************************************************
|
||||
** This file implements that page cache.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/*
|
||||
** A complete page cache is an instance of this structure. Every
|
||||
|
@ -67,12 +66,20 @@ struct PCache {
|
|||
int sqlite3PcacheTrace = 2; /* 0: off 1: simple 2: cache dumps */
|
||||
int sqlite3PcacheMxDump = 9999; /* Max cache entries for pcacheDump() */
|
||||
# define pcacheTrace(X) if(sqlite3PcacheTrace){sqlite3DebugPrintf X;}
|
||||
void pcacheDump(PCache *pCache){
|
||||
int N;
|
||||
int i, j;
|
||||
sqlite3_pcache_page *pLower;
|
||||
static void pcachePageTrace(int i, sqlite3_pcache_page *pLower){
|
||||
PgHdr *pPg;
|
||||
unsigned char *a;
|
||||
int j;
|
||||
pPg = (PgHdr*)pLower->pExtra;
|
||||
printf("%3d: nRef %2d flgs %02x data ", i, pPg->nRef, pPg->flags);
|
||||
a = (unsigned char *)pLower->pBuf;
|
||||
for(j=0; j<12; j++) printf("%02x", a[j]);
|
||||
printf(" ptr %p\n", pPg);
|
||||
}
|
||||
static void pcacheDump(PCache *pCache){
|
||||
int N;
|
||||
int i;
|
||||
sqlite3_pcache_page *pLower;
|
||||
|
||||
if( sqlite3PcacheTrace<2 ) return;
|
||||
if( pCache->pCache==0 ) return;
|
||||
|
@ -81,21 +88,32 @@ struct PCache {
|
|||
for(i=1; i<=N; i++){
|
||||
pLower = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, i, 0);
|
||||
if( pLower==0 ) continue;
|
||||
pPg = (PgHdr*)pLower->pExtra;
|
||||
printf("%3d: nRef %2d flgs %02x data ", i, pPg->nRef, pPg->flags);
|
||||
a = (unsigned char *)pLower->pBuf;
|
||||
for(j=0; j<12; j++) printf("%02x", a[j]);
|
||||
printf("\n");
|
||||
if( pPg->pPage==0 ){
|
||||
pcachePageTrace(i, pLower);
|
||||
if( ((PgHdr*)pLower)->pPage==0 ){
|
||||
sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, pLower, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#else
|
||||
# define pcacheTrace(X)
|
||||
# define pcachePageTrace(PGNO, X)
|
||||
# define pcacheDump(X)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return 1 if pPg is on the dirty list for pCache. Return 0 if not.
|
||||
** This routine runs inside of assert() statements only.
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
static int pageOnDirtyList(PCache *pCache, PgHdr *pPg){
|
||||
PgHdr *p;
|
||||
for(p=pCache->pDirty; p; p=p->pDirtyNext){
|
||||
if( p==pPg ) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Check invariants on a PgHdr entry. Return true if everything is OK.
|
||||
** Return false if any invariant is violated.
|
||||
|
@ -114,8 +132,13 @@ int sqlite3PcachePageSanity(PgHdr *pPg){
|
|||
assert( pCache!=0 ); /* Every page has an associated PCache */
|
||||
if( pPg->flags & PGHDR_CLEAN ){
|
||||
assert( (pPg->flags & PGHDR_DIRTY)==0 );/* Cannot be both CLEAN and DIRTY */
|
||||
assert( pCache->pDirty!=pPg ); /* CLEAN pages not on dirty list */
|
||||
assert( pCache->pDirtyTail!=pPg );
|
||||
assert( !pageOnDirtyList(pCache, pPg) );/* CLEAN pages not on dirty list */
|
||||
}else{
|
||||
assert( (pPg->flags & PGHDR_DIRTY)!=0 );/* If not CLEAN must be DIRTY */
|
||||
assert( pPg->pDirtyNext==0 || pPg->pDirtyNext->pDirtyPrev==pPg );
|
||||
assert( pPg->pDirtyPrev==0 || pPg->pDirtyPrev->pDirtyNext==pPg );
|
||||
assert( pPg->pDirtyPrev!=0 || pCache->pDirty==pPg );
|
||||
assert( pageOnDirtyList(pCache, pPg) );
|
||||
}
|
||||
/* WRITEABLE pages must also be DIRTY */
|
||||
if( pPg->flags & PGHDR_WRITEABLE ){
|
||||
|
@ -244,11 +267,14 @@ static int numberOfCachePages(PCache *p){
|
|||
** suggested cache size is set to N. */
|
||||
return p->szCache;
|
||||
}else{
|
||||
i64 n;
|
||||
/* IMPLEMANTATION-OF: R-59858-46238 If the argument N is negative, then the
|
||||
** number of cache pages is adjusted to be a number of pages that would
|
||||
** use approximately abs(N*1024) bytes of memory based on the current
|
||||
** page size. */
|
||||
return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
|
||||
n = ((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
|
||||
if( n>1000000000 ) n = 1000000000;
|
||||
return (int)n;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -386,8 +412,9 @@ sqlite3_pcache_page *sqlite3PcacheFetch(
|
|||
assert( createFlag==0 || pCache->eCreate==eCreate );
|
||||
assert( createFlag==0 || eCreate==1+(!pCache->bPurgeable||!pCache->pDirty) );
|
||||
pRes = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
|
||||
pcacheTrace(("%p.FETCH %d%s (result: %p)\n",pCache,pgno,
|
||||
pcacheTrace(("%p.FETCH %d%s (result: %p) ",pCache,pgno,
|
||||
createFlag?" create":"",pRes));
|
||||
pcachePageTrace(pgno, pRes);
|
||||
return pRes;
|
||||
}
|
||||
|
||||
|
@ -515,6 +542,7 @@ void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){
|
|||
pcacheUnpin(p);
|
||||
}else{
|
||||
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
|
||||
assert( sqlite3PcachePageSanity(p) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -558,6 +586,7 @@ void sqlite3PcacheMakeDirty(PgHdr *p){
|
|||
pcacheTrace(("%p.DIRTY %d\n",p->pCache,p->pgno));
|
||||
assert( (p->flags & (PGHDR_DIRTY|PGHDR_CLEAN))==PGHDR_DIRTY );
|
||||
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_ADD);
|
||||
assert( sqlite3PcachePageSanity(p) );
|
||||
}
|
||||
assert( sqlite3PcachePageSanity(p) );
|
||||
}
|
||||
|
@ -620,14 +649,24 @@ void sqlite3PcacheClearSyncFlags(PCache *pCache){
|
|||
*/
|
||||
void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
|
||||
PCache *pCache = p->pCache;
|
||||
sqlite3_pcache_page *pOther;
|
||||
assert( p->nRef>0 );
|
||||
assert( newPgno>0 );
|
||||
assert( sqlite3PcachePageSanity(p) );
|
||||
pcacheTrace(("%p.MOVE %d -> %d\n",pCache,p->pgno,newPgno));
|
||||
pOther = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, newPgno, 0);
|
||||
if( pOther ){
|
||||
PgHdr *pXPage = (PgHdr*)pOther->pExtra;
|
||||
assert( pXPage->nRef==0 );
|
||||
pXPage->nRef++;
|
||||
pCache->nRefSum++;
|
||||
sqlite3PcacheDrop(pXPage);
|
||||
}
|
||||
sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
|
||||
p->pgno = newPgno;
|
||||
if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
|
||||
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
|
||||
assert( sqlite3PcachePageSanity(p) );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
3
third_party/sqlite3/pcache.inc
vendored
3
third_party/sqlite3/pcache.inc
vendored
|
@ -10,9 +10,8 @@
|
|||
**
|
||||
*************************************************************************
|
||||
** This header file defines the interface that the sqlite page cache
|
||||
** subsystem.
|
||||
** subsystem.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
#ifndef _PCACHE_H_
|
||||
|
||||
|
|
102
third_party/sqlite3/pcache1.c
vendored
102
third_party/sqlite3/pcache1.c
vendored
|
@ -39,12 +39,13 @@
|
|||
** size can vary according to architecture, compile-time options, and
|
||||
** SQLite library version number.
|
||||
**
|
||||
** If SQLITE_PCACHE_SEPARATE_HEADER is defined, then the extension is obtained
|
||||
** using a separate memory allocation from the database page content. This
|
||||
** seeks to overcome the "clownshoe" problem (also called "internal
|
||||
** fragmentation" in academic literature) of allocating a few bytes more
|
||||
** than a power of two with the memory allocator rounding up to the next
|
||||
** power of two, and leaving the rounded-up space unused.
|
||||
** Historical note: It used to be that if the SQLITE_PCACHE_SEPARATE_HEADER
|
||||
** was defined, then the page content would be held in a separate memory
|
||||
** allocation from the PgHdr1. This was intended to avoid clownshoe memory
|
||||
** allocations. However, the btree layer needs a small (16-byte) overrun
|
||||
** area after the page content buffer. The header serves as that overrun
|
||||
** area. Therefore SQLITE_PCACHE_SEPARATE_HEADER was discontinued to avoid
|
||||
** any possibility of a memory error.
|
||||
**
|
||||
** This module tracks pointers to PgHdr1 objects. Only pcache.c communicates
|
||||
** with this module. Information is passed back and forth as PgHdr1 pointers.
|
||||
|
@ -63,7 +64,7 @@
|
|||
**
|
||||
** The third case is a chunk of heap memory (defaulting to 100 pages worth)
|
||||
** that is allocated when the page cache is created. The size of the local
|
||||
** bulk allocation can be adjusted using
|
||||
** bulk allocation can be adjusted using
|
||||
**
|
||||
** sqlite3_config(SQLITE_CONFIG_PAGECACHE, (void*)0, 0, N).
|
||||
**
|
||||
|
@ -82,7 +83,7 @@
|
|||
*/
|
||||
#include "libc/assert.h"
|
||||
#include "third_party/sqlite3/sqlite3.h"
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
/* clang-format off */
|
||||
|
||||
typedef struct PCache1 PCache1;
|
||||
|
@ -92,30 +93,40 @@ typedef struct PGroup PGroup;
|
|||
|
||||
/*
|
||||
** Each cache entry is represented by an instance of the following
|
||||
** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
|
||||
** PgHdr1.pCache->szPage bytes is allocated directly before this structure
|
||||
** in memory.
|
||||
** structure. A buffer of PgHdr1.pCache->szPage bytes is allocated
|
||||
** directly before this structure and is used to cache the page content.
|
||||
**
|
||||
** Note: Variables isBulkLocal and isAnchor were once type "u8". That works,
|
||||
** When reading a corrupt database file, it is possible that SQLite might
|
||||
** read a few bytes (no more than 16 bytes) past the end of the page buffer.
|
||||
** It will only read past the end of the page buffer, never write. This
|
||||
** object is positioned immediately after the page buffer to serve as an
|
||||
** overrun area, so that overreads are harmless.
|
||||
**
|
||||
** Variables isBulkLocal and isAnchor were once type "u8". That works,
|
||||
** but causes a 2-byte gap in the structure for most architectures (since
|
||||
** pointers must be either 4 or 8-byte aligned). As this structure is located
|
||||
** in memory directly after the associated page data, if the database is
|
||||
** corrupt, code at the b-tree layer may overread the page buffer and
|
||||
** read part of this structure before the corruption is detected. This
|
||||
** can cause a valgrind error if the unitialized gap is accessed. Using u16
|
||||
** ensures there is no such gap, and therefore no bytes of unitialized memory
|
||||
** in the structure.
|
||||
** ensures there is no such gap, and therefore no bytes of uninitialized
|
||||
** memory in the structure.
|
||||
**
|
||||
** The pLruNext and pLruPrev pointers form a double-linked circular list
|
||||
** of all pages that are unpinned. The PGroup.lru element (which should be
|
||||
** the only element on the list with PgHdr1.isAnchor set to 1) forms the
|
||||
** beginning and the end of the list.
|
||||
*/
|
||||
struct PgHdr1 {
|
||||
sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */
|
||||
unsigned int iKey; /* Key value (page number) */
|
||||
u16 isBulkLocal; /* This page from bulk local storage */
|
||||
u16 isAnchor; /* This is the PGroup.lru element */
|
||||
PgHdr1 *pNext; /* Next in hash table chain */
|
||||
PCache1 *pCache; /* Cache that currently owns this page */
|
||||
PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */
|
||||
PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
|
||||
/* NB: pLruPrev is only valid if pLruNext!=0 */
|
||||
sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */
|
||||
unsigned int iKey; /* Key value (page number) */
|
||||
u16 isBulkLocal; /* This page from bulk local storage */
|
||||
u16 isAnchor; /* This is the PGroup.lru element */
|
||||
PgHdr1 *pNext; /* Next in hash table chain */
|
||||
PCache1 *pCache; /* Cache that currently owns this page */
|
||||
PgHdr1 *pLruNext; /* Next in circular LRU list of unpinned pages */
|
||||
PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
|
||||
/* NB: pLruPrev is only valid if pLruNext!=0 */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -441,25 +452,13 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
|
|||
pcache1LeaveMutex(pCache->pGroup);
|
||||
#endif
|
||||
if( benignMalloc ){ sqlite3BeginBenignMalloc(); }
|
||||
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
|
||||
pPg = pcache1Alloc(pCache->szPage);
|
||||
p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
|
||||
if( !pPg || !p ){
|
||||
pcache1Free(pPg);
|
||||
sqlite3_free(p);
|
||||
pPg = 0;
|
||||
}
|
||||
#else
|
||||
pPg = pcache1Alloc(pCache->szAlloc);
|
||||
#endif
|
||||
if( benignMalloc ){ sqlite3EndBenignMalloc(); }
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
pcache1EnterMutex(pCache->pGroup);
|
||||
#endif
|
||||
if( pPg==0 ) return 0;
|
||||
#ifndef SQLITE_PCACHE_SEPARATE_HEADER
|
||||
p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
|
||||
#endif
|
||||
p->page.pBuf = pPg;
|
||||
p->page.pExtra = &p[1];
|
||||
p->isBulkLocal = 0;
|
||||
|
@ -483,9 +482,6 @@ static void pcache1FreePage(PgHdr1 *p){
|
|||
pCache->pFree = p;
|
||||
}else{
|
||||
pcache1Free(p->page.pBuf);
|
||||
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
|
||||
sqlite3_free(p);
|
||||
#endif
|
||||
}
|
||||
(*pCache->pnPurgeable)--;
|
||||
}
|
||||
|
@ -820,12 +816,18 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
|
|||
*/
|
||||
static void pcache1Cachesize(sqlite3_pcache *p, int nMax){
|
||||
PCache1 *pCache = (PCache1 *)p;
|
||||
u32 n;
|
||||
assert( nMax>=0 );
|
||||
if( pCache->bPurgeable ){
|
||||
PGroup *pGroup = pCache->pGroup;
|
||||
pcache1EnterMutex(pGroup);
|
||||
pGroup->nMaxPage += (nMax - pCache->nMax);
|
||||
n = (u32)nMax;
|
||||
if( n > 0x7fff0000 - pGroup->nMaxPage + pCache->nMax ){
|
||||
n = 0x7fff0000 - pGroup->nMaxPage + pCache->nMax;
|
||||
}
|
||||
pGroup->nMaxPage += (n - pCache->nMax);
|
||||
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
|
||||
pCache->nMax = nMax;
|
||||
pCache->nMax = n;
|
||||
pCache->n90pct = pCache->nMax*9/10;
|
||||
pcache1EnforceMaxPage(pCache);
|
||||
pcache1LeaveMutex(pGroup);
|
||||
|
@ -841,7 +843,7 @@ static void pcache1Shrink(sqlite3_pcache *p){
|
|||
PCache1 *pCache = (PCache1*)p;
|
||||
if( pCache->bPurgeable ){
|
||||
PGroup *pGroup = pCache->pGroup;
|
||||
int savedMaxPage;
|
||||
unsigned int savedMaxPage;
|
||||
pcache1EnterMutex(pGroup);
|
||||
savedMaxPage = pGroup->nMaxPage;
|
||||
pGroup->nMaxPage = 0;
|
||||
|
@ -1120,23 +1122,26 @@ static void pcache1Rekey(
|
|||
PCache1 *pCache = (PCache1 *)p;
|
||||
PgHdr1 *pPage = (PgHdr1 *)pPg;
|
||||
PgHdr1 **pp;
|
||||
unsigned int h;
|
||||
unsigned int hOld, hNew;
|
||||
assert( pPage->iKey==iOld );
|
||||
assert( pPage->pCache==pCache );
|
||||
assert( iOld!=iNew ); /* The page number really is changing */
|
||||
|
||||
pcache1EnterMutex(pCache->pGroup);
|
||||
|
||||
h = iOld%pCache->nHash;
|
||||
pp = &pCache->apHash[h];
|
||||
assert( pcache1FetchNoMutex(p, iOld, 0)==pPage ); /* pPg really is iOld */
|
||||
hOld = iOld%pCache->nHash;
|
||||
pp = &pCache->apHash[hOld];
|
||||
while( (*pp)!=pPage ){
|
||||
pp = &(*pp)->pNext;
|
||||
}
|
||||
*pp = pPage->pNext;
|
||||
|
||||
h = iNew%pCache->nHash;
|
||||
assert( pcache1FetchNoMutex(p, iNew, 0)==0 ); /* iNew not in cache */
|
||||
hNew = iNew%pCache->nHash;
|
||||
pPage->iKey = iNew;
|
||||
pPage->pNext = pCache->apHash[h];
|
||||
pCache->apHash[h] = pPage;
|
||||
pPage->pNext = pCache->apHash[hNew];
|
||||
pCache->apHash[hNew] = pPage;
|
||||
if( iNew>pCache->iMaxKey ){
|
||||
pCache->iMaxKey = iNew;
|
||||
}
|
||||
|
@ -1243,9 +1248,6 @@ int sqlite3PcacheReleaseMemory(int nReq){
|
|||
&& p->isAnchor==0
|
||||
){
|
||||
nFree += pcache1MemSize(p->page.pBuf);
|
||||
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
|
||||
nFree += sqlite3MemSize(p);
|
||||
#endif
|
||||
assert( PAGE_IS_UNPINNED(p) );
|
||||
pcache1PinPage(p);
|
||||
pcache1RemoveFromHash(p, 1);
|
||||
|
|
344
third_party/sqlite3/pragma.c
vendored
344
third_party/sqlite3/pragma.c
vendored
|
@ -11,8 +11,7 @@
|
|||
*************************************************************************
|
||||
** This file contains code used to implement the PRAGMA command.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
|
||||
# if defined(__APPLE__)
|
||||
|
@ -308,15 +307,16 @@ static void pragmaFunclistLine(
|
|||
int isBuiltin, /* True if this is a built-in function */
|
||||
int showInternFuncs /* True if showing internal functions */
|
||||
){
|
||||
u32 mask =
|
||||
SQLITE_DETERMINISTIC |
|
||||
SQLITE_DIRECTONLY |
|
||||
SQLITE_SUBTYPE |
|
||||
SQLITE_INNOCUOUS |
|
||||
SQLITE_FUNC_INTERNAL
|
||||
;
|
||||
if( showInternFuncs ) mask = 0xffffffff;
|
||||
for(; p; p=p->pNext){
|
||||
const char *zType;
|
||||
static const u32 mask =
|
||||
SQLITE_DETERMINISTIC |
|
||||
SQLITE_DIRECTONLY |
|
||||
SQLITE_SUBTYPE |
|
||||
SQLITE_INNOCUOUS |
|
||||
SQLITE_FUNC_INTERNAL
|
||||
;
|
||||
static const char *azEnc[] = { 0, "utf8", "utf16le", "utf16be" };
|
||||
|
||||
assert( SQLITE_FUNC_ENCMASK==0x3 );
|
||||
|
@ -468,7 +468,11 @@ void sqlite3Pragma(
|
|||
|
||||
/* Locate the pragma in the lookup table */
|
||||
pPragma = pragmaLocate(zLeft);
|
||||
if( pPragma==0 ) goto pragma_out;
|
||||
if( pPragma==0 ){
|
||||
/* IMP: R-43042-22504 No error messages are generated if an
|
||||
** unknown pragma is issued. */
|
||||
goto pragma_out;
|
||||
}
|
||||
|
||||
/* Make sure the database schema is loaded if the pragma requires that */
|
||||
if( (pPragma->mPragFlg & PragFlg_NeedSchema)!=0 ){
|
||||
|
@ -804,7 +808,7 @@ void sqlite3Pragma(
|
|||
*/
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
case PragTyp_INCREMENTAL_VACUUM: {
|
||||
int iLimit, addr;
|
||||
int iLimit = 0, addr;
|
||||
if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){
|
||||
iLimit = 0x7fffffff;
|
||||
}
|
||||
|
@ -961,6 +965,7 @@ void sqlite3Pragma(
|
|||
**
|
||||
*/
|
||||
case PragTyp_TEMP_STORE_DIRECTORY: {
|
||||
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
||||
if( !zRight ){
|
||||
returnSingleText(v, sqlite3_temp_directory);
|
||||
}else{
|
||||
|
@ -970,6 +975,7 @@ void sqlite3Pragma(
|
|||
rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
|
||||
if( rc!=SQLITE_OK || res==0 ){
|
||||
sqlite3ErrorMsg(pParse, "not a writable directory");
|
||||
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
||||
goto pragma_out;
|
||||
}
|
||||
}
|
||||
|
@ -987,6 +993,7 @@ void sqlite3Pragma(
|
|||
}
|
||||
#endif /* SQLITE_OMIT_WSD */
|
||||
}
|
||||
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1005,6 +1012,7 @@ void sqlite3Pragma(
|
|||
**
|
||||
*/
|
||||
case PragTyp_DATA_STORE_DIRECTORY: {
|
||||
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
||||
if( !zRight ){
|
||||
returnSingleText(v, sqlite3_data_directory);
|
||||
}else{
|
||||
|
@ -1014,6 +1022,7 @@ void sqlite3Pragma(
|
|||
rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
|
||||
if( rc!=SQLITE_OK || res==0 ){
|
||||
sqlite3ErrorMsg(pParse, "not a writable directory");
|
||||
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
||||
goto pragma_out;
|
||||
}
|
||||
}
|
||||
|
@ -1025,6 +1034,7 @@ void sqlite3Pragma(
|
|||
}
|
||||
#endif /* SQLITE_OMIT_WSD */
|
||||
}
|
||||
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
@ -1118,6 +1128,14 @@ void sqlite3Pragma(
|
|||
}else{
|
||||
db->flags &= ~mask;
|
||||
if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0;
|
||||
if( (mask & SQLITE_WriteSchema)!=0
|
||||
&& sqlite3_stricmp(zRight, "reset")==0
|
||||
){
|
||||
/* IMP: R-60817-01178 If the argument is "RESET" then schema
|
||||
** writing is disabled (as with "PRAGMA writable_schema=OFF") and,
|
||||
** in addition, the schema is reloaded. */
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
}
|
||||
}
|
||||
|
||||
/* Many of the flag-pragmas modify the code generated by the SQL
|
||||
|
@ -1158,6 +1176,7 @@ void sqlite3Pragma(
|
|||
sqlite3ViewGetColumnNames(pParse, pTab);
|
||||
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
|
||||
int isHidden = 0;
|
||||
const Expr *pColExpr;
|
||||
if( pCol->colFlags & COLFLAG_NOINSERT ){
|
||||
if( pPragma->iArg==0 ){
|
||||
nHidden++;
|
||||
|
@ -1178,13 +1197,16 @@ void sqlite3Pragma(
|
|||
}else{
|
||||
for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
|
||||
}
|
||||
assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN || isHidden>=2 );
|
||||
pColExpr = sqlite3ColumnExpr(pTab,pCol);
|
||||
assert( pColExpr==0 || pColExpr->op==TK_SPAN || isHidden>=2 );
|
||||
assert( pColExpr==0 || !ExprHasProperty(pColExpr, EP_IntValue)
|
||||
|| isHidden>=2 );
|
||||
sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi",
|
||||
i-nHidden,
|
||||
pCol->zName,
|
||||
pCol->zCnName,
|
||||
sqlite3ColumnType(pCol,""),
|
||||
pCol->notNull ? 1 : 0,
|
||||
pCol->pDflt && isHidden<2 ? pCol->pDflt->u.zToken : 0,
|
||||
(isHidden>=2 || pColExpr==0) ? 0 : pColExpr->u.zToken,
|
||||
k,
|
||||
isHidden);
|
||||
}
|
||||
|
@ -1192,6 +1214,85 @@ void sqlite3Pragma(
|
|||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
** PRAGMA table_list
|
||||
**
|
||||
** Return a single row for each table, virtual table, or view in the
|
||||
** entire schema.
|
||||
**
|
||||
** schema: Name of attached database hold this table
|
||||
** name: Name of the table itself
|
||||
** type: "table", "view", "virtual", "shadow"
|
||||
** ncol: Number of columns
|
||||
** wr: True for a WITHOUT ROWID table
|
||||
** strict: True for a STRICT table
|
||||
*/
|
||||
case PragTyp_TABLE_LIST: {
|
||||
int ii;
|
||||
pParse->nMem = 6;
|
||||
sqlite3CodeVerifyNamedSchema(pParse, zDb);
|
||||
for(ii=0; ii<db->nDb; ii++){
|
||||
HashElem *k;
|
||||
Hash *pHash;
|
||||
int initNCol;
|
||||
if( zDb && sqlite3_stricmp(zDb, db->aDb[ii].zDbSName)!=0 ) continue;
|
||||
|
||||
/* Ensure that the Table.nCol field is initialized for all views
|
||||
** and virtual tables. Each time we initialize a Table.nCol value
|
||||
** for a table, that can potentially disrupt the hash table, so restart
|
||||
** the initialization scan.
|
||||
*/
|
||||
pHash = &db->aDb[ii].pSchema->tblHash;
|
||||
initNCol = sqliteHashCount(pHash);
|
||||
while( initNCol-- ){
|
||||
for(k=sqliteHashFirst(pHash); 1; k=sqliteHashNext(k) ){
|
||||
Table *pTab;
|
||||
if( k==0 ){ initNCol = 0; break; }
|
||||
pTab = sqliteHashData(k);
|
||||
if( pTab->nCol==0 ){
|
||||
char *zSql = sqlite3MPrintf(db, "SELECT*FROM\"%w\"", pTab->zName);
|
||||
if( zSql ){
|
||||
sqlite3_stmt *pDummy = 0;
|
||||
(void)sqlite3_prepare(db, zSql, -1, &pDummy, 0);
|
||||
(void)sqlite3_finalize(pDummy);
|
||||
sqlite3DbFree(db, zSql);
|
||||
}
|
||||
if( db->mallocFailed ){
|
||||
sqlite3ErrorMsg(db->pParse, "out of memory");
|
||||
db->pParse->rc = SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
pHash = &db->aDb[ii].pSchema->tblHash;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(k=sqliteHashFirst(pHash); k; k=sqliteHashNext(k) ){
|
||||
Table *pTab = sqliteHashData(k);
|
||||
const char *zType;
|
||||
if( zRight && sqlite3_stricmp(zRight, pTab->zName)!=0 ) continue;
|
||||
if( IsView(pTab) ){
|
||||
zType = "view";
|
||||
}else if( IsVirtual(pTab) ){
|
||||
zType = "virtual";
|
||||
}else if( pTab->tabFlags & TF_Shadow ){
|
||||
zType = "shadow";
|
||||
}else{
|
||||
zType = "table";
|
||||
}
|
||||
sqlite3VdbeMultiLoad(v, 1, "sssiii",
|
||||
db->aDb[ii].zDbSName,
|
||||
sqlite3PreferredTableName(pTab->zName),
|
||||
zType,
|
||||
pTab->nCol,
|
||||
(pTab->tabFlags & TF_WithoutRowid)!=0,
|
||||
(pTab->tabFlags & TF_Strict)!=0
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
case PragTyp_STATS: {
|
||||
Index *pIdx;
|
||||
|
@ -1201,7 +1302,7 @@ void sqlite3Pragma(
|
|||
for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){
|
||||
Table *pTab = sqliteHashData(i);
|
||||
sqlite3VdbeMultiLoad(v, 1, "ssiii",
|
||||
pTab->zName,
|
||||
sqlite3PreferredTableName(pTab->zName),
|
||||
0,
|
||||
pTab->szTabRow,
|
||||
pTab->nRowLogEst,
|
||||
|
@ -1251,7 +1352,7 @@ void sqlite3Pragma(
|
|||
for(i=0; i<mx; i++){
|
||||
i16 cnum = pIdx->aiColumn[i];
|
||||
sqlite3VdbeMultiLoad(v, 1, "iisX", i, cnum,
|
||||
cnum<0 ? 0 : pTab->aCol[cnum].zName);
|
||||
cnum<0 ? 0 : pTab->aCol[cnum].zCnName);
|
||||
if( pPragma->iArg ){
|
||||
sqlite3VdbeMultiLoad(v, 4, "isiX",
|
||||
pIdx->aSortOrder[i],
|
||||
|
@ -1320,11 +1421,13 @@ void sqlite3Pragma(
|
|||
pParse->nMem = 6;
|
||||
for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
|
||||
for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){
|
||||
assert( p->funcFlags & SQLITE_FUNC_BUILTIN );
|
||||
pragmaFunclistLine(v, p, 1, showInternFunc);
|
||||
}
|
||||
}
|
||||
for(j=sqliteHashFirst(&db->aFunc); j; j=sqliteHashNext(j)){
|
||||
p = (FuncDef*)sqliteHashData(j);
|
||||
assert( (p->funcFlags & SQLITE_FUNC_BUILTIN)==0 );
|
||||
pragmaFunclistLine(v, p, 0, showInternFunc);
|
||||
}
|
||||
}
|
||||
|
@ -1358,8 +1461,8 @@ void sqlite3Pragma(
|
|||
FKey *pFK;
|
||||
Table *pTab;
|
||||
pTab = sqlite3FindTable(db, zRight, zDb);
|
||||
if( pTab ){
|
||||
pFK = pTab->pFKey;
|
||||
if( pTab && IsOrdinaryTable(pTab) ){
|
||||
pFK = pTab->u.tab.pFKey;
|
||||
if( pFK ){
|
||||
int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
int i = 0;
|
||||
|
@ -1372,7 +1475,7 @@ void sqlite3Pragma(
|
|||
i,
|
||||
j,
|
||||
pFK->zTo,
|
||||
pTab->aCol[pFK->aCol[j].iFrom].zName,
|
||||
pTab->aCol[pFK->aCol[j].iFrom].zCnName,
|
||||
pFK->aCol[j].zCol,
|
||||
actionName(pFK->aAction[1]), /* ON UPDATE */
|
||||
actionName(pFK->aAction[0]), /* ON DELETE */
|
||||
|
@ -1399,7 +1502,6 @@ void sqlite3Pragma(
|
|||
HashElem *k; /* Loop counter: Next table in schema */
|
||||
int x; /* result variable */
|
||||
int regResult; /* 3 registers to hold a result row */
|
||||
int regKey; /* Register to hold key for checking the FK */
|
||||
int regRow; /* Registers to hold a row from pTab */
|
||||
int addrTop; /* Top of a loop checking foreign keys */
|
||||
int addrOk; /* Jump here if the key is OK */
|
||||
|
@ -1407,7 +1509,6 @@ void sqlite3Pragma(
|
|||
|
||||
regResult = pParse->nMem+1;
|
||||
pParse->nMem += 4;
|
||||
regKey = ++pParse->nMem;
|
||||
regRow = ++pParse->nMem;
|
||||
k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
|
||||
while( k ){
|
||||
|
@ -1418,7 +1519,7 @@ void sqlite3Pragma(
|
|||
pTab = (Table*)sqliteHashData(k);
|
||||
k = sqliteHashNext(k);
|
||||
}
|
||||
if( pTab==0 || pTab->pFKey==0 ) continue;
|
||||
if( pTab==0 || !IsOrdinaryTable(pTab) || pTab->u.tab.pFKey==0 ) continue;
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
zDb = db->aDb[iDb].zDbSName;
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
|
@ -1426,7 +1527,8 @@ void sqlite3Pragma(
|
|||
if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
|
||||
sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
|
||||
sqlite3VdbeLoadString(v, regResult, pTab->zName);
|
||||
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
|
||||
assert( IsOrdinaryTable(pTab) );
|
||||
for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){
|
||||
pParent = sqlite3FindTable(db, pFK->zTo, zDb);
|
||||
if( pParent==0 ) continue;
|
||||
pIdx = 0;
|
||||
|
@ -1448,7 +1550,8 @@ void sqlite3Pragma(
|
|||
if( pFK ) break;
|
||||
if( pParse->nTab<i ) pParse->nTab = i;
|
||||
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v);
|
||||
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
|
||||
assert( IsOrdinaryTable(pTab) );
|
||||
for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){
|
||||
pParent = sqlite3FindTable(db, pFK->zTo, zDb);
|
||||
pIdx = 0;
|
||||
aiCols = 0;
|
||||
|
@ -1462,6 +1565,7 @@ void sqlite3Pragma(
|
|||
** regRow..regRow+n. If any of the child key values are NULL, this
|
||||
** row cannot cause an FK violation. Jump directly to addrOk in
|
||||
** this case. */
|
||||
if( regRow+pFK->nCol>pParse->nMem ) pParse->nMem = regRow+pFK->nCol;
|
||||
for(j=0; j<pFK->nCol; j++){
|
||||
int iCol = aiCols ? aiCols[j] : pFK->aCol[j].iFrom;
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, iCol, regRow+j);
|
||||
|
@ -1471,9 +1575,9 @@ void sqlite3Pragma(
|
|||
/* Generate code to query the parent index for a matching parent
|
||||
** key. If a match is found, jump to addrOk. */
|
||||
if( pIdx ){
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey,
|
||||
sqlite3VdbeAddOp4(v, OP_Affinity, regRow, pFK->nCol, 0,
|
||||
sqlite3IndexAffinityStr(db,pIdx), pFK->nCol);
|
||||
sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
|
||||
sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regRow, pFK->nCol);
|
||||
VdbeCoverage(v);
|
||||
}else if( pParent ){
|
||||
int jmp = sqlite3VdbeCurrentAddr(v)+2;
|
||||
|
@ -1644,14 +1748,24 @@ void sqlite3Pragma(
|
|||
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
|
||||
Table *pTab = sqliteHashData(x);
|
||||
Index *pIdx, *pPk;
|
||||
Index *pPrior = 0;
|
||||
Index *pPrior = 0; /* Previous index */
|
||||
int loopTop;
|
||||
int iDataCur, iIdxCur;
|
||||
int r1 = -1;
|
||||
int bStrict; /* True for a STRICT table */
|
||||
int r2; /* Previous key for WITHOUT ROWID tables */
|
||||
int mxCol; /* Maximum non-virtual column number */
|
||||
|
||||
if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */
|
||||
if( !IsOrdinaryTable(pTab) ) continue;
|
||||
if( pObjTab && pObjTab!=pTab ) continue;
|
||||
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
|
||||
if( isQuick || HasRowid(pTab) ){
|
||||
pPk = 0;
|
||||
r2 = 0;
|
||||
}else{
|
||||
pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
r2 = sqlite3GetTempRange(pParse, pPk->nKeyCol);
|
||||
sqlite3VdbeAddOp3(v, OP_Null, 1, r2, r2+pPk->nKeyCol-1);
|
||||
}
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
|
||||
1, 0, &iDataCur, &iIdxCur);
|
||||
/* reg[7] counts the number of entries in the table.
|
||||
|
@ -1665,27 +1779,157 @@ void sqlite3Pragma(
|
|||
assert( sqlite3NoTempsInRange(pParse,1,7+j) );
|
||||
sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v);
|
||||
loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
|
||||
if( !isQuick ){
|
||||
/* Sanity check on record header decoding */
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nNVCol-1,3);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
|
||||
|
||||
/* Fetch the right-most column from the table. This will cause
|
||||
** the entire record header to be parsed and sanity checked. It
|
||||
** will also prepopulate the cursor column cache that is used
|
||||
** by the OP_IsType code, so it is a required step.
|
||||
*/
|
||||
mxCol = pTab->nCol-1;
|
||||
while( mxCol>=0
|
||||
&& ((pTab->aCol[mxCol].colFlags & COLFLAG_VIRTUAL)!=0
|
||||
|| pTab->iPKey==mxCol) ) mxCol--;
|
||||
if( mxCol>=0 ){
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, mxCol, 3);
|
||||
sqlite3VdbeTypeofColumn(v, 3);
|
||||
}
|
||||
/* Verify that all NOT NULL columns really are NOT NULL */
|
||||
|
||||
if( !isQuick ){
|
||||
if( pPk ){
|
||||
/* Verify WITHOUT ROWID keys are in ascending order */
|
||||
int a1;
|
||||
char *zErr;
|
||||
a1 = sqlite3VdbeAddOp4Int(v, OP_IdxGT, iDataCur, 0,r2,pPk->nKeyCol);
|
||||
VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp1(v, OP_IsNull, r2); VdbeCoverage(v);
|
||||
zErr = sqlite3MPrintf(db,
|
||||
"row not in PRIMARY KEY order for %s",
|
||||
pTab->zName);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
|
||||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, a1);
|
||||
sqlite3VdbeJumpHere(v, a1+1);
|
||||
for(j=0; j<pPk->nKeyCol; j++){
|
||||
sqlite3ExprCodeLoadIndexColumn(pParse, pPk, iDataCur, j, r2+j);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Verify datatypes for all columns:
|
||||
**
|
||||
** (1) NOT NULL columns may not contain a NULL
|
||||
** (2) Datatype must be exact for non-ANY columns in STRICT tables
|
||||
** (3) Datatype for TEXT columns in non-STRICT tables must be
|
||||
** NULL, TEXT, or BLOB.
|
||||
** (4) Datatype for numeric columns in non-STRICT tables must not
|
||||
** be a TEXT value that can be losslessly converted to numeric.
|
||||
*/
|
||||
bStrict = (pTab->tabFlags & TF_Strict)!=0;
|
||||
for(j=0; j<pTab->nCol; j++){
|
||||
char *zErr;
|
||||
int jmp2;
|
||||
Column *pCol = pTab->aCol + j; /* The column to be checked */
|
||||
int labelError; /* Jump here to report an error */
|
||||
int labelOk; /* Jump here if all looks ok */
|
||||
int p1, p3, p4; /* Operands to the OP_IsType opcode */
|
||||
int doTypeCheck; /* Check datatypes (besides NOT NULL) */
|
||||
|
||||
if( j==pTab->iPKey ) continue;
|
||||
if( pTab->aCol[j].notNull==0 ) continue;
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
|
||||
if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
|
||||
if( bStrict ){
|
||||
doTypeCheck = pCol->eCType>COLTYPE_ANY;
|
||||
}else{
|
||||
doTypeCheck = pCol->affinity>SQLITE_AFF_BLOB;
|
||||
}
|
||||
jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
|
||||
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
|
||||
pTab->aCol[j].zName);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
|
||||
if( pCol->notNull==0 && !doTypeCheck ) continue;
|
||||
|
||||
/* Compute the operands that will be needed for OP_IsType */
|
||||
p4 = SQLITE_NULL;
|
||||
if( pCol->colFlags & COLFLAG_VIRTUAL ){
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
|
||||
p1 = -1;
|
||||
p3 = 3;
|
||||
}else{
|
||||
if( pCol->iDflt ){
|
||||
sqlite3_value *pDfltValue = 0;
|
||||
sqlite3ValueFromExpr(db, sqlite3ColumnExpr(pTab,pCol), ENC(db),
|
||||
pCol->affinity, &pDfltValue);
|
||||
if( pDfltValue ){
|
||||
p4 = sqlite3_value_type(pDfltValue);
|
||||
sqlite3ValueFree(pDfltValue);
|
||||
}
|
||||
}
|
||||
p1 = iDataCur;
|
||||
if( !HasRowid(pTab) ){
|
||||
testcase( j!=sqlite3TableColumnToStorage(pTab, j) );
|
||||
p3 = sqlite3TableColumnToIndex(sqlite3PrimaryKeyIndex(pTab), j);
|
||||
}else{
|
||||
p3 = sqlite3TableColumnToStorage(pTab,j);
|
||||
testcase( p3!=j);
|
||||
}
|
||||
}
|
||||
|
||||
labelError = sqlite3VdbeMakeLabel(pParse);
|
||||
labelOk = sqlite3VdbeMakeLabel(pParse);
|
||||
if( pCol->notNull ){
|
||||
/* (1) NOT NULL columns may not contain a NULL */
|
||||
int jmp2 = sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
|
||||
sqlite3VdbeChangeP5(v, 0x0f);
|
||||
VdbeCoverage(v);
|
||||
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
|
||||
pCol->zCnName);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
|
||||
if( doTypeCheck ){
|
||||
sqlite3VdbeGoto(v, labelError);
|
||||
sqlite3VdbeJumpHere(v, jmp2);
|
||||
}else{
|
||||
/* VDBE byte code will fall thru */
|
||||
}
|
||||
}
|
||||
if( bStrict && doTypeCheck ){
|
||||
/* (2) Datatype must be exact for non-ANY columns in STRICT tables*/
|
||||
static unsigned char aStdTypeMask[] = {
|
||||
0x1f, /* ANY */
|
||||
0x18, /* BLOB */
|
||||
0x11, /* INT */
|
||||
0x11, /* INTEGER */
|
||||
0x13, /* REAL */
|
||||
0x14 /* TEXT */
|
||||
};
|
||||
sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
|
||||
assert( pCol->eCType>=1 && pCol->eCType<=sizeof(aStdTypeMask) );
|
||||
sqlite3VdbeChangeP5(v, aStdTypeMask[pCol->eCType-1]);
|
||||
VdbeCoverage(v);
|
||||
zErr = sqlite3MPrintf(db, "non-%s value in %s.%s",
|
||||
sqlite3StdType[pCol->eCType-1],
|
||||
pTab->zName, pTab->aCol[j].zCnName);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
|
||||
}else if( !bStrict && pCol->affinity==SQLITE_AFF_TEXT ){
|
||||
/* (3) Datatype for TEXT columns in non-STRICT tables must be
|
||||
** NULL, TEXT, or BLOB. */
|
||||
sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
|
||||
sqlite3VdbeChangeP5(v, 0x1c); /* NULL, TEXT, or BLOB */
|
||||
VdbeCoverage(v);
|
||||
zErr = sqlite3MPrintf(db, "NUMERIC value in %s.%s",
|
||||
pTab->zName, pTab->aCol[j].zCnName);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
|
||||
}else if( !bStrict && pCol->affinity>=SQLITE_AFF_NUMERIC ){
|
||||
/* (4) Datatype for numeric columns in non-STRICT tables must not
|
||||
** be a TEXT value that can be converted to numeric. */
|
||||
sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
|
||||
sqlite3VdbeChangeP5(v, 0x1b); /* NULL, INT, FLOAT, or BLOB */
|
||||
VdbeCoverage(v);
|
||||
if( p1>=0 ){
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
|
||||
}
|
||||
sqlite3VdbeAddOp4(v, OP_Affinity, 3, 1, 0, "C", P4_STATIC);
|
||||
sqlite3VdbeAddOp4Int(v, OP_IsType, -1, labelOk, 3, p4);
|
||||
sqlite3VdbeChangeP5(v, 0x1c); /* NULL, TEXT, or BLOB */
|
||||
VdbeCoverage(v);
|
||||
zErr = sqlite3MPrintf(db, "TEXT value in %s.%s",
|
||||
pTab->zName, pTab->aCol[j].zCnName);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
|
||||
}
|
||||
sqlite3VdbeResolveLabel(v, labelError);
|
||||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, jmp2);
|
||||
sqlite3VdbeResolveLabel(v, labelOk);
|
||||
}
|
||||
/* Verify CHECK constraints */
|
||||
if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
|
||||
|
@ -1773,6 +2017,9 @@ void sqlite3Pragma(
|
|||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
}
|
||||
if( pPk ){
|
||||
sqlite3ReleaseTempRange(pParse, r2, pPk->nKeyCol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1923,6 +2170,11 @@ void sqlite3Pragma(
|
|||
aOp[1].p2 = iCookie;
|
||||
aOp[1].p3 = sqlite3Atoi(zRight);
|
||||
aOp[1].p5 = 1;
|
||||
if( iCookie==BTREE_SCHEMA_VERSION && (db->flags & SQLITE_Defensive)!=0 ){
|
||||
/* Do not allow the use of PRAGMA schema_version=VALUE in defensive
|
||||
** mode. Change the OP_SetCookie opcode into a no-op. */
|
||||
aOp[1].opcode = OP_Noop;
|
||||
}
|
||||
}else{
|
||||
/* Read the specified cookie value */
|
||||
static const VdbeOpList readCookie[] = {
|
||||
|
@ -2219,12 +2471,12 @@ void sqlite3Pragma(
|
|||
case PragTyp_ANALYSIS_LIMIT: {
|
||||
sqlite3_int64 N;
|
||||
if( zRight
|
||||
&& sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK
|
||||
&& sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK /* IMP: R-40975-20399 */
|
||||
&& N>=0
|
||||
){
|
||||
db->nAnalysisLimit = (int)(N&0x7fffffff);
|
||||
}
|
||||
returnSingleInt(v, db->nAnalysisLimit);
|
||||
returnSingleInt(v, db->nAnalysisLimit); /* IMP: R-57594-65522 */
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
135
third_party/sqlite3/pragma.inc
vendored
135
third_party/sqlite3/pragma.inc
vendored
|
@ -3,7 +3,6 @@
|
|||
** ../tool/mkpragmatab.tcl. To update the set of pragmas, edit
|
||||
** that script and rerun it.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
/* The various pragma types */
|
||||
#define PragTyp_ACTIVATE_EXTENSIONS 0
|
||||
|
@ -44,13 +43,14 @@
|
|||
#define PragTyp_SOFT_HEAP_LIMIT 35
|
||||
#define PragTyp_SYNCHRONOUS 36
|
||||
#define PragTyp_TABLE_INFO 37
|
||||
#define PragTyp_TEMP_STORE 38
|
||||
#define PragTyp_TEMP_STORE_DIRECTORY 39
|
||||
#define PragTyp_THREADS 40
|
||||
#define PragTyp_WAL_AUTOCHECKPOINT 41
|
||||
#define PragTyp_WAL_CHECKPOINT 42
|
||||
#define PragTyp_LOCK_STATUS 43
|
||||
#define PragTyp_STATS 44
|
||||
#define PragTyp_TABLE_LIST 38
|
||||
#define PragTyp_TEMP_STORE 39
|
||||
#define PragTyp_TEMP_STORE_DIRECTORY 40
|
||||
#define PragTyp_THREADS 41
|
||||
#define PragTyp_WAL_AUTOCHECKPOINT 42
|
||||
#define PragTyp_WAL_CHECKPOINT 43
|
||||
#define PragTyp_LOCK_STATUS 44
|
||||
#define PragTyp_STATS 45
|
||||
|
||||
/* Property flags associated with various pragma. */
|
||||
#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
|
||||
|
@ -83,45 +83,51 @@ static const char *const pragCName[] = {
|
|||
/* 13 */ "pk",
|
||||
/* 14 */ "hidden",
|
||||
/* table_info reuses 8 */
|
||||
/* 15 */ "seqno", /* Used by: index_xinfo */
|
||||
/* 16 */ "cid",
|
||||
/* 17 */ "name",
|
||||
/* 18 */ "desc",
|
||||
/* 19 */ "coll",
|
||||
/* 20 */ "key",
|
||||
/* 21 */ "name", /* Used by: function_list */
|
||||
/* 22 */ "builtin",
|
||||
/* 23 */ "type",
|
||||
/* 24 */ "enc",
|
||||
/* 25 */ "narg",
|
||||
/* 26 */ "flags",
|
||||
/* 27 */ "tbl", /* Used by: stats */
|
||||
/* 28 */ "idx",
|
||||
/* 29 */ "wdth",
|
||||
/* 30 */ "hght",
|
||||
/* 31 */ "flgs",
|
||||
/* 32 */ "seq", /* Used by: index_list */
|
||||
/* 33 */ "name",
|
||||
/* 34 */ "unique",
|
||||
/* 35 */ "origin",
|
||||
/* 36 */ "partial",
|
||||
/* 37 */ "table", /* Used by: foreign_key_check */
|
||||
/* 38 */ "rowid",
|
||||
/* 39 */ "parent",
|
||||
/* 40 */ "fkid",
|
||||
/* index_info reuses 15 */
|
||||
/* 41 */ "seq", /* Used by: database_list */
|
||||
/* 42 */ "name",
|
||||
/* 43 */ "file",
|
||||
/* 44 */ "busy", /* Used by: wal_checkpoint */
|
||||
/* 45 */ "log",
|
||||
/* 46 */ "checkpointed",
|
||||
/* collation_list reuses 32 */
|
||||
/* 47 */ "database", /* Used by: lock_status */
|
||||
/* 48 */ "status",
|
||||
/* 49 */ "cache_size", /* Used by: default_cache_size */
|
||||
/* 15 */ "schema", /* Used by: table_list */
|
||||
/* 16 */ "name",
|
||||
/* 17 */ "type",
|
||||
/* 18 */ "ncol",
|
||||
/* 19 */ "wr",
|
||||
/* 20 */ "strict",
|
||||
/* 21 */ "seqno", /* Used by: index_xinfo */
|
||||
/* 22 */ "cid",
|
||||
/* 23 */ "name",
|
||||
/* 24 */ "desc",
|
||||
/* 25 */ "coll",
|
||||
/* 26 */ "key",
|
||||
/* 27 */ "name", /* Used by: function_list */
|
||||
/* 28 */ "builtin",
|
||||
/* 29 */ "type",
|
||||
/* 30 */ "enc",
|
||||
/* 31 */ "narg",
|
||||
/* 32 */ "flags",
|
||||
/* 33 */ "tbl", /* Used by: stats */
|
||||
/* 34 */ "idx",
|
||||
/* 35 */ "wdth",
|
||||
/* 36 */ "hght",
|
||||
/* 37 */ "flgs",
|
||||
/* 38 */ "seq", /* Used by: index_list */
|
||||
/* 39 */ "name",
|
||||
/* 40 */ "unique",
|
||||
/* 41 */ "origin",
|
||||
/* 42 */ "partial",
|
||||
/* 43 */ "table", /* Used by: foreign_key_check */
|
||||
/* 44 */ "rowid",
|
||||
/* 45 */ "parent",
|
||||
/* 46 */ "fkid",
|
||||
/* index_info reuses 21 */
|
||||
/* 47 */ "seq", /* Used by: database_list */
|
||||
/* 48 */ "name",
|
||||
/* 49 */ "file",
|
||||
/* 50 */ "busy", /* Used by: wal_checkpoint */
|
||||
/* 51 */ "log",
|
||||
/* 52 */ "checkpointed",
|
||||
/* collation_list reuses 38 */
|
||||
/* 53 */ "database", /* Used by: lock_status */
|
||||
/* 54 */ "status",
|
||||
/* 55 */ "cache_size", /* Used by: default_cache_size */
|
||||
/* module_list pragma_list reuses 9 */
|
||||
/* 50 */ "timeout", /* Used by: busy_timeout */
|
||||
/* 56 */ "timeout", /* Used by: busy_timeout */
|
||||
};
|
||||
|
||||
/* Definitions of all built-in pragmas */
|
||||
|
@ -172,7 +178,7 @@ static const PragmaName aPragmaName[] = {
|
|||
{/* zName: */ "busy_timeout",
|
||||
/* ePragTyp: */ PragTyp_BUSY_TIMEOUT,
|
||||
/* ePragFlg: */ PragFlg_Result0,
|
||||
/* ColNames: */ 50, 1,
|
||||
/* ColNames: */ 56, 1,
|
||||
/* iArg: */ 0 },
|
||||
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
{/* zName: */ "cache_size",
|
||||
|
@ -211,7 +217,7 @@ static const PragmaName aPragmaName[] = {
|
|||
{/* zName: */ "collation_list",
|
||||
/* ePragTyp: */ PragTyp_COLLATION_LIST,
|
||||
/* ePragFlg: */ PragFlg_Result0,
|
||||
/* ColNames: */ 32, 2,
|
||||
/* ColNames: */ 38, 2,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
|
||||
|
@ -245,15 +251,15 @@ static const PragmaName aPragmaName[] = {
|
|||
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
|
||||
{/* zName: */ "database_list",
|
||||
/* ePragTyp: */ PragTyp_DATABASE_LIST,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
|
||||
/* ColNames: */ 41, 3,
|
||||
/* ePragFlg: */ PragFlg_Result0,
|
||||
/* ColNames: */ 47, 3,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
|
||||
{/* zName: */ "default_cache_size",
|
||||
/* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
|
||||
/* ColNames: */ 49, 1,
|
||||
/* ColNames: */ 55, 1,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
||||
|
@ -283,7 +289,7 @@ static const PragmaName aPragmaName[] = {
|
|||
{/* zName: */ "foreign_key_check",
|
||||
/* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt,
|
||||
/* ColNames: */ 37, 4,
|
||||
/* ColNames: */ 43, 4,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_FOREIGN_KEY)
|
||||
|
@ -326,7 +332,7 @@ static const PragmaName aPragmaName[] = {
|
|||
{/* zName: */ "function_list",
|
||||
/* ePragTyp: */ PragTyp_FUNCTION_LIST,
|
||||
/* ePragFlg: */ PragFlg_Result0,
|
||||
/* ColNames: */ 21, 6,
|
||||
/* ColNames: */ 27, 6,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#endif
|
||||
|
@ -355,23 +361,23 @@ static const PragmaName aPragmaName[] = {
|
|||
{/* zName: */ "index_info",
|
||||
/* ePragTyp: */ PragTyp_INDEX_INFO,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
|
||||
/* ColNames: */ 15, 3,
|
||||
/* ColNames: */ 21, 3,
|
||||
/* iArg: */ 0 },
|
||||
{/* zName: */ "index_list",
|
||||
/* ePragTyp: */ PragTyp_INDEX_LIST,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
|
||||
/* ColNames: */ 32, 5,
|
||||
/* ColNames: */ 38, 5,
|
||||
/* iArg: */ 0 },
|
||||
{/* zName: */ "index_xinfo",
|
||||
/* ePragTyp: */ PragTyp_INDEX_INFO,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
|
||||
/* ColNames: */ 15, 6,
|
||||
/* ColNames: */ 21, 6,
|
||||
/* iArg: */ 1 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
|
||||
{/* zName: */ "integrity_check",
|
||||
/* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt,
|
||||
/* ColNames: */ 0, 0,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
|
@ -405,7 +411,7 @@ static const PragmaName aPragmaName[] = {
|
|||
{/* zName: */ "lock_status",
|
||||
/* ePragTyp: */ PragTyp_LOCK_STATUS,
|
||||
/* ePragFlg: */ PragFlg_Result0,
|
||||
/* ColNames: */ 47, 2,
|
||||
/* ColNames: */ 53, 2,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
@ -479,7 +485,7 @@ static const PragmaName aPragmaName[] = {
|
|||
#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
|
||||
{/* zName: */ "quick_check",
|
||||
/* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt,
|
||||
/* ColNames: */ 0, 0,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
|
@ -544,7 +550,7 @@ static const PragmaName aPragmaName[] = {
|
|||
{/* zName: */ "stats",
|
||||
/* ePragTyp: */ PragTyp_STATS,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
|
||||
/* ColNames: */ 27, 5,
|
||||
/* ColNames: */ 33, 5,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
@ -560,6 +566,11 @@ static const PragmaName aPragmaName[] = {
|
|||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
|
||||
/* ColNames: */ 8, 6,
|
||||
/* iArg: */ 0 },
|
||||
{/* zName: */ "table_list",
|
||||
/* ePragTyp: */ PragTyp_TABLE_LIST,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1,
|
||||
/* ColNames: */ 15, 6,
|
||||
/* iArg: */ 0 },
|
||||
{/* zName: */ "table_xinfo",
|
||||
/* ePragTyp: */ PragTyp_TABLE_INFO,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
|
||||
|
@ -635,7 +646,7 @@ static const PragmaName aPragmaName[] = {
|
|||
{/* zName: */ "wal_checkpoint",
|
||||
/* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema,
|
||||
/* ColNames: */ 44, 3,
|
||||
/* ColNames: */ 50, 3,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
||||
|
@ -646,4 +657,4 @@ static const PragmaName aPragmaName[] = {
|
|||
/* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError },
|
||||
#endif
|
||||
};
|
||||
/* Number of pragmas: 67 on by default, 77 total. */
|
||||
/* Number of pragmas: 68 on by default, 78 total. */
|
||||
|
|
128
third_party/sqlite3/prepare.c
vendored
128
third_party/sqlite3/prepare.c
vendored
|
@ -13,8 +13,7 @@
|
|||
** interface, and routines that contribute to loading the database schema
|
||||
** from disk.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/*
|
||||
** Fill the InitData structure with an error message that indicates
|
||||
|
@ -30,10 +29,15 @@ static void corruptSchema(
|
|||
pData->rc = SQLITE_NOMEM_BKPT;
|
||||
}else if( pData->pzErrMsg[0]!=0 ){
|
||||
/* A error message has already been generated. Do not overwrite it */
|
||||
}else if( pData->mInitFlags & (INITFLAG_AlterRename|INITFLAG_AlterDrop) ){
|
||||
}else if( pData->mInitFlags & (INITFLAG_AlterMask) ){
|
||||
static const char *azAlterType[] = {
|
||||
"rename",
|
||||
"drop column",
|
||||
"add column"
|
||||
};
|
||||
*pData->pzErrMsg = sqlite3MPrintf(db,
|
||||
"error in %s %s after %s: %s", azObj[0], azObj[1],
|
||||
(pData->mInitFlags & INITFLAG_AlterRename) ? "rename" : "drop column",
|
||||
azAlterType[(pData->mInitFlags&INITFLAG_AlterMask)-1],
|
||||
zExtra
|
||||
);
|
||||
pData->rc = SQLITE_ERROR;
|
||||
|
@ -97,6 +101,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
|
|||
UNUSED_PARAMETER2(NotUsed, argc);
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
db->mDbFlags |= DBFLAG_EncodingFixed;
|
||||
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
|
||||
pData->nInitRow++;
|
||||
if( db->mallocFailed ){
|
||||
corruptSchema(pData, argv, 0);
|
||||
|
@ -104,7 +109,6 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
|
|||
}
|
||||
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
|
||||
if( argv[3]==0 ){
|
||||
corruptSchema(pData, argv, 0);
|
||||
}else if( argv[4]
|
||||
|
@ -135,7 +139,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
|
|||
}
|
||||
}
|
||||
db->init.orphanTrigger = 0;
|
||||
db->init.azInit = argv;
|
||||
db->init.azInit = (const char**)argv;
|
||||
pStmt = 0;
|
||||
TESTONLY(rcp = ) sqlite3Prepare(db, argv[4], -1, 0, 0, &pStmt, 0);
|
||||
rc = db->errCode;
|
||||
|
@ -154,6 +158,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
|
|||
}
|
||||
}
|
||||
}
|
||||
db->init.azInit = sqlite3StdType; /* Any array of string ptrs will do */
|
||||
sqlite3_finalize(pStmt);
|
||||
}else if( argv[1]==0 || (argv[4]!=0 && argv[4][0]!=0) ){
|
||||
corruptSchema(pData, argv, 0);
|
||||
|
@ -378,18 +383,22 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
|
|||
}
|
||||
#endif
|
||||
}
|
||||
assert( pDb == &(db->aDb[iDb]) );
|
||||
if( db->mallocFailed ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
}
|
||||
if( rc==SQLITE_OK || (db->flags&SQLITE_NoSchemaError)){
|
||||
/* Black magic: If the SQLITE_NoSchemaError flag is set, then consider
|
||||
** the schema loaded, even if errors occurred. In this situation the
|
||||
** current sqlite3_prepare() operation will fail, but the following one
|
||||
** will attempt to compile the supplied statement against whatever subset
|
||||
** of the schema was loaded before the error occurred. The primary
|
||||
** purpose of this is to allow access to the sqlite_schema table
|
||||
** even when its contents have been corrupted.
|
||||
pDb = &db->aDb[iDb];
|
||||
}else
|
||||
if( rc==SQLITE_OK || ((db->flags&SQLITE_NoSchemaError) && rc!=SQLITE_NOMEM)){
|
||||
/* Hack: If the SQLITE_NoSchemaError flag is set, then consider
|
||||
** the schema loaded, even if errors (other than OOM) occurred. In
|
||||
** this situation the current sqlite3_prepare() operation will fail,
|
||||
** but the following one will attempt to compile the supplied statement
|
||||
** against whatever subset of the schema was loaded before the error
|
||||
** occurred.
|
||||
**
|
||||
** The primary purpose of this is to allow access to the sqlite_schema
|
||||
** table even when its contents have been corrupted.
|
||||
*/
|
||||
DbSetProperty(db, iDb, DB_SchemaLoaded);
|
||||
rc = SQLITE_OK;
|
||||
|
@ -499,6 +508,7 @@ static void schemaIsValid(Parse *pParse){
|
|||
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
|
||||
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
|
||||
sqlite3OomFault(db);
|
||||
pParse->rc = SQLITE_NOMEM;
|
||||
}
|
||||
if( rc!=SQLITE_OK ) return;
|
||||
openedTransaction = 1;
|
||||
|
@ -558,23 +568,30 @@ int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
|
|||
/*
|
||||
** Free all memory allocations in the pParse object
|
||||
*/
|
||||
void sqlite3ParserReset(Parse *pParse){
|
||||
void sqlite3ParseObjectReset(Parse *pParse){
|
||||
sqlite3 *db = pParse->db;
|
||||
assert( db!=0 );
|
||||
assert( db->pParse==pParse );
|
||||
assert( pParse->nested==0 );
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
if( pParse->aTableLock ) sqlite3DbNNFreeNN(db, pParse->aTableLock);
|
||||
#endif
|
||||
while( pParse->pCleanup ){
|
||||
ParseCleanup *pCleanup = pParse->pCleanup;
|
||||
pParse->pCleanup = pCleanup->pNext;
|
||||
pCleanup->xCleanup(db, pCleanup->pPtr);
|
||||
sqlite3DbFreeNN(db, pCleanup);
|
||||
sqlite3DbNNFreeNN(db, pCleanup);
|
||||
}
|
||||
sqlite3DbFree(db, pParse->aLabel);
|
||||
if( pParse->aLabel ) sqlite3DbNNFreeNN(db, pParse->aLabel);
|
||||
if( pParse->pConstExpr ){
|
||||
sqlite3ExprListDelete(db, pParse->pConstExpr);
|
||||
}
|
||||
if( db ){
|
||||
assert( db->lookaside.bDisable >= pParse->disableLookaside );
|
||||
db->lookaside.bDisable -= pParse->disableLookaside;
|
||||
db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue;
|
||||
}
|
||||
assert( db->lookaside.bDisable >= pParse->disableLookaside );
|
||||
db->lookaside.bDisable -= pParse->disableLookaside;
|
||||
db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue;
|
||||
assert( pParse->db->pParse==pParse );
|
||||
db->pParse = pParse->pOuterParse;
|
||||
pParse->db = 0;
|
||||
pParse->disableLookaside = 0;
|
||||
}
|
||||
|
||||
|
@ -587,7 +604,7 @@ void sqlite3ParserReset(Parse *pParse){
|
|||
** cost for this mechansim (an extra malloc), so it should not be used
|
||||
** for common cleanups that happen on most calls. But for less
|
||||
** common cleanups, we save a single NULL-pointer comparison in
|
||||
** sqlite3ParserReset(), which reduces the total CPU cycle count.
|
||||
** sqlite3ParseObjectReset(), which reduces the total CPU cycle count.
|
||||
**
|
||||
** If a memory allocation error occurs, then the cleanup happens immediately.
|
||||
** When either SQLITE_DEBUG or SQLITE_COVERAGE_TEST are defined, the
|
||||
|
@ -627,6 +644,33 @@ void *sqlite3ParserAddCleanup(
|
|||
return pPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
** Turn bulk memory into a valid Parse object and link that Parse object
|
||||
** into database connection db.
|
||||
**
|
||||
** Call sqlite3ParseObjectReset() to undo this operation.
|
||||
**
|
||||
** Caution: Do not confuse this routine with sqlite3ParseObjectInit() which
|
||||
** is generated by Lemon.
|
||||
*/
|
||||
void sqlite3ParseObjectInit(Parse *pParse, sqlite3 *db){
|
||||
memset(PARSE_HDR(pParse), 0, PARSE_HDR_SZ);
|
||||
memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
|
||||
assert( db->pParse!=pParse );
|
||||
pParse->pOuterParse = db->pParse;
|
||||
db->pParse = pParse;
|
||||
pParse->db = db;
|
||||
if( db->mallocFailed ) sqlite3ErrorMsg(pParse, "out of memory");
|
||||
}
|
||||
|
||||
/*
|
||||
** Maximum number of times that we will try again to prepare a statement
|
||||
** that returns SQLITE_ERROR_RETRY.
|
||||
*/
|
||||
#ifndef SQLITE_MAX_PREPARE_RETRY
|
||||
# define SQLITE_MAX_PREPARE_RETRY 25
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
|
||||
*/
|
||||
|
@ -639,16 +683,19 @@ static int sqlite3Prepare(
|
|||
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
|
||||
const char **pzTail /* OUT: End of parsed string */
|
||||
){
|
||||
char *zErrMsg = 0; /* Error message */
|
||||
int rc = SQLITE_OK; /* Result code */
|
||||
int i; /* Loop counter */
|
||||
Parse sParse; /* Parsing context */
|
||||
|
||||
memset(&sParse, 0, PARSE_HDR_SZ);
|
||||
/* sqlite3ParseObjectInit(&sParse, db); // inlined for performance */
|
||||
memset(PARSE_HDR(&sParse), 0, PARSE_HDR_SZ);
|
||||
memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ);
|
||||
sParse.pOuterParse = db->pParse;
|
||||
db->pParse = &sParse;
|
||||
sParse.db = db;
|
||||
sParse.pReprepare = pReprepare;
|
||||
assert( ppStmt && *ppStmt==0 );
|
||||
/* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */
|
||||
if( db->mallocFailed ) sqlite3ErrorMsg(&sParse, "out of memory");
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
|
||||
/* For a long-term use prepared statement avoid the use of
|
||||
|
@ -658,7 +705,7 @@ static int sqlite3Prepare(
|
|||
sParse.disableLookaside++;
|
||||
DisableLookaside;
|
||||
}
|
||||
sParse.disableVtab = (prepFlags & SQLITE_PREPARE_NO_VTAB)!=0;
|
||||
sParse.prepFlags = prepFlags & 0xff;
|
||||
|
||||
/* Check to verify that it is possible to get a read lock on all
|
||||
** database schemas. The inability to get a read lock indicates that
|
||||
|
@ -699,9 +746,10 @@ static int sqlite3Prepare(
|
|||
}
|
||||
}
|
||||
|
||||
sqlite3VtabUnlockList(db);
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
if( db->pDisconnect ) sqlite3VtabUnlockList(db);
|
||||
#endif
|
||||
|
||||
sParse.db = db;
|
||||
if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
|
||||
char *zSqlCopy;
|
||||
int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
|
||||
|
@ -714,14 +762,14 @@ static int sqlite3Prepare(
|
|||
}
|
||||
zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes);
|
||||
if( zSqlCopy ){
|
||||
sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg);
|
||||
sqlite3RunParser(&sParse, zSqlCopy);
|
||||
sParse.zTail = &zSql[sParse.zTail-zSqlCopy];
|
||||
sqlite3DbFree(db, zSqlCopy);
|
||||
}else{
|
||||
sParse.zTail = &zSql[nBytes];
|
||||
}
|
||||
}else{
|
||||
sqlite3RunParser(&sParse, zSql, &zErrMsg);
|
||||
sqlite3RunParser(&sParse, zSql);
|
||||
}
|
||||
assert( 0==sParse.nQueryLoop );
|
||||
|
||||
|
@ -734,9 +782,10 @@ static int sqlite3Prepare(
|
|||
}
|
||||
if( db->mallocFailed ){
|
||||
sParse.rc = SQLITE_NOMEM_BKPT;
|
||||
sParse.checkSchema = 0;
|
||||
}
|
||||
if( sParse.rc!=SQLITE_OK && sParse.rc!=SQLITE_DONE ){
|
||||
if( sParse.checkSchema ){
|
||||
if( sParse.checkSchema && db->init.busy==0 ){
|
||||
schemaIsValid(&sParse);
|
||||
}
|
||||
if( sParse.pVdbe ){
|
||||
|
@ -744,14 +793,14 @@ static int sqlite3Prepare(
|
|||
}
|
||||
assert( 0==(*ppStmt) );
|
||||
rc = sParse.rc;
|
||||
if( zErrMsg ){
|
||||
sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg);
|
||||
sqlite3DbFree(db, zErrMsg);
|
||||
if( sParse.zErrMsg ){
|
||||
sqlite3ErrorWithMsg(db, rc, "%s", sParse.zErrMsg);
|
||||
sqlite3DbFree(db, sParse.zErrMsg);
|
||||
}else{
|
||||
sqlite3Error(db, rc);
|
||||
}
|
||||
}else{
|
||||
assert( zErrMsg==0 );
|
||||
assert( sParse.zErrMsg==0 );
|
||||
*ppStmt = (sqlite3_stmt*)sParse.pVdbe;
|
||||
rc = SQLITE_OK;
|
||||
sqlite3ErrorClear(db);
|
||||
|
@ -767,7 +816,7 @@ static int sqlite3Prepare(
|
|||
|
||||
end_prepare:
|
||||
|
||||
sqlite3ParserReset(&sParse);
|
||||
sqlite3ParseObjectReset(&sParse);
|
||||
return rc;
|
||||
}
|
||||
static int sqlite3LockAndPrepare(
|
||||
|
@ -797,7 +846,8 @@ static int sqlite3LockAndPrepare(
|
|||
** reset is considered a permanent error. */
|
||||
rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail);
|
||||
assert( rc==SQLITE_OK || *ppStmt==0 );
|
||||
}while( rc==SQLITE_ERROR_RETRY
|
||||
if( rc==SQLITE_OK || db->mallocFailed ) break;
|
||||
}while( (rc==SQLITE_ERROR_RETRY && (cnt++)<SQLITE_MAX_PREPARE_RETRY)
|
||||
|| (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) );
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
rc = sqlite3ApiExit(db, rc);
|
||||
|
|
140
third_party/sqlite3/printf.c
vendored
140
third_party/sqlite3/printf.c
vendored
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** The "printf" code that follows dates from the 1980's. It is in
|
||||
** the public domain.
|
||||
** the public domain.
|
||||
**
|
||||
**************************************************************************
|
||||
**
|
||||
|
@ -9,8 +9,7 @@
|
|||
** library, though the implementation here has enhancements to support
|
||||
** SQLite.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/*
|
||||
** Conversion types fall into various categories as defined by the
|
||||
|
@ -30,7 +29,7 @@
|
|||
#define etSQLESCAPE2 10 /* Strings with '\'' doubled and enclosed in '',
|
||||
NULL pointers replaced by SQL NULL. %Q */
|
||||
#define etTOKEN 11 /* a pointer to a Token structure */
|
||||
#define etSRCLIST 12 /* a pointer to a SrcList */
|
||||
#define etSRCITEM 12 /* a pointer to a SrcItem */
|
||||
#define etPOINTER 13 /* The %p conversion */
|
||||
#define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */
|
||||
#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
|
||||
|
@ -96,10 +95,16 @@ static const et_info fmtinfo[] = {
|
|||
|
||||
/* All the rest are undocumented and are for internal use only */
|
||||
{ 'T', 0, 0, etTOKEN, 0, 0 },
|
||||
{ 'S', 0, 0, etSRCLIST, 0, 0 },
|
||||
{ 'S', 0, 0, etSRCITEM, 0, 0 },
|
||||
{ 'r', 10, 1, etORDINAL, 0, 0 },
|
||||
};
|
||||
|
||||
/* Notes:
|
||||
**
|
||||
** %S Takes a pointer to SrcItem. Shows name or database.name
|
||||
** %!S Like %S but prefer the zName over the zAlias
|
||||
*/
|
||||
|
||||
/* Floating point constants used for rounding */
|
||||
static const double arRound[] = {
|
||||
5.0e-01, 5.0e-02, 5.0e-03, 5.0e-04, 5.0e-05,
|
||||
|
@ -140,7 +145,7 @@ static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
|
|||
/*
|
||||
** Set the StrAccum object to an error mode.
|
||||
*/
|
||||
static void setStrAccumError(StrAccum *p, u8 eError){
|
||||
void sqlite3StrAccumSetError(StrAccum *p, u8 eError){
|
||||
assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG );
|
||||
p->accError = eError;
|
||||
if( p->mxAlloc ) sqlite3_str_reset(p);
|
||||
|
@ -176,12 +181,12 @@ static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){
|
|||
char *z;
|
||||
if( pAccum->accError ) return 0;
|
||||
if( n>pAccum->nAlloc && n>pAccum->mxAlloc ){
|
||||
setStrAccumError(pAccum, SQLITE_TOOBIG);
|
||||
sqlite3StrAccumSetError(pAccum, SQLITE_TOOBIG);
|
||||
return 0;
|
||||
}
|
||||
z = sqlite3DbMallocRaw(pAccum->db, n);
|
||||
if( z==0 ){
|
||||
setStrAccumError(pAccum, SQLITE_NOMEM);
|
||||
sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM);
|
||||
}
|
||||
return z;
|
||||
}
|
||||
|
@ -798,8 +803,8 @@ void sqlite3_str_vappendf(
|
|||
case etSQLESCAPE: /* %q: Escape ' characters */
|
||||
case etSQLESCAPE2: /* %Q: Escape ' and enclose in '...' */
|
||||
case etSQLESCAPE3: { /* %w: Escape " characters */
|
||||
int i, j, k, n, isnull;
|
||||
int needQuote;
|
||||
i64 i, j, k, n;
|
||||
int needQuote, isnull;
|
||||
char ch;
|
||||
char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
|
||||
char *escarg;
|
||||
|
@ -844,31 +849,50 @@ void sqlite3_str_vappendf(
|
|||
goto adjust_width_for_utf8;
|
||||
}
|
||||
case etTOKEN: {
|
||||
Token *pToken;
|
||||
if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
|
||||
pToken = va_arg(ap, Token*);
|
||||
assert( bArgList==0 );
|
||||
if( pToken && pToken->n ){
|
||||
sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
|
||||
if( flag_alternateform ){
|
||||
/* %#T means an Expr pointer that uses Expr.u.zToken */
|
||||
Expr *pExpr = va_arg(ap,Expr*);
|
||||
if( ALWAYS(pExpr) && ALWAYS(!ExprHasProperty(pExpr,EP_IntValue)) ){
|
||||
sqlite3_str_appendall(pAccum, (const char*)pExpr->u.zToken);
|
||||
sqlite3RecordErrorOffsetOfExpr(pAccum->db, pExpr);
|
||||
}
|
||||
}else{
|
||||
/* %T means a Token pointer */
|
||||
Token *pToken = va_arg(ap, Token*);
|
||||
assert( bArgList==0 );
|
||||
if( pToken && pToken->n ){
|
||||
sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
|
||||
sqlite3RecordErrorByteOffset(pAccum->db, pToken->z);
|
||||
}
|
||||
}
|
||||
length = width = 0;
|
||||
break;
|
||||
}
|
||||
case etSRCLIST: {
|
||||
SrcList *pSrc;
|
||||
int k;
|
||||
case etSRCITEM: {
|
||||
SrcItem *pItem;
|
||||
if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
|
||||
pSrc = va_arg(ap, SrcList*);
|
||||
k = va_arg(ap, int);
|
||||
pItem = &pSrc->a[k];
|
||||
pItem = va_arg(ap, SrcItem*);
|
||||
assert( bArgList==0 );
|
||||
assert( k>=0 && k<pSrc->nSrc );
|
||||
if( pItem->zDatabase ){
|
||||
sqlite3_str_appendall(pAccum, pItem->zDatabase);
|
||||
sqlite3_str_append(pAccum, ".", 1);
|
||||
if( pItem->zAlias && !flag_altform2 ){
|
||||
sqlite3_str_appendall(pAccum, pItem->zAlias);
|
||||
}else if( pItem->zName ){
|
||||
if( pItem->zDatabase ){
|
||||
sqlite3_str_appendall(pAccum, pItem->zDatabase);
|
||||
sqlite3_str_append(pAccum, ".", 1);
|
||||
}
|
||||
sqlite3_str_appendall(pAccum, pItem->zName);
|
||||
}else if( pItem->zAlias ){
|
||||
sqlite3_str_appendall(pAccum, pItem->zAlias);
|
||||
}else{
|
||||
Select *pSel = pItem->pSelect;
|
||||
assert( pSel!=0 );
|
||||
if( pSel->selFlags & SF_NestedFrom ){
|
||||
sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);
|
||||
}else{
|
||||
sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId);
|
||||
}
|
||||
}
|
||||
sqlite3_str_appendall(pAccum, pItem->zName);
|
||||
length = width = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -901,6 +925,44 @@ void sqlite3_str_vappendf(
|
|||
}/* End for loop over the format string */
|
||||
} /* End of function */
|
||||
|
||||
|
||||
/*
|
||||
** The z string points to the first character of a token that is
|
||||
** associated with an error. If db does not already have an error
|
||||
** byte offset recorded, try to compute the error byte offset for
|
||||
** z and set the error byte offset in db.
|
||||
*/
|
||||
void sqlite3RecordErrorByteOffset(sqlite3 *db, const char *z){
|
||||
const Parse *pParse;
|
||||
const char *zText;
|
||||
const char *zEnd;
|
||||
assert( z!=0 );
|
||||
if( NEVER(db==0) ) return;
|
||||
if( db->errByteOffset!=(-2) ) return;
|
||||
pParse = db->pParse;
|
||||
if( NEVER(pParse==0) ) return;
|
||||
zText =pParse->zTail;
|
||||
if( NEVER(zText==0) ) return;
|
||||
zEnd = &zText[strlen(zText)];
|
||||
if( SQLITE_WITHIN(z,zText,zEnd) ){
|
||||
db->errByteOffset = (int)(z-zText);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** If pExpr has a byte offset for the start of a token, record that as
|
||||
** as the error offset.
|
||||
*/
|
||||
void sqlite3RecordErrorOffsetOfExpr(sqlite3 *db, const Expr *pExpr){
|
||||
while( pExpr
|
||||
&& (ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) || pExpr->w.iOfst<=0)
|
||||
){
|
||||
pExpr = pExpr->pLeft;
|
||||
}
|
||||
if( pExpr==0 ) return;
|
||||
db->errByteOffset = pExpr->w.iOfst;
|
||||
}
|
||||
|
||||
/*
|
||||
** Enlarge the memory allocation on a StrAccum object so that it is
|
||||
** able to accept at least N more bytes of text.
|
||||
|
@ -908,7 +970,7 @@ void sqlite3_str_vappendf(
|
|||
** Return the number of bytes of text that StrAccum is able to accept
|
||||
** after the attempted enlargement. The value returned might be zero.
|
||||
*/
|
||||
static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
char *zNew;
|
||||
assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */
|
||||
if( p->accError ){
|
||||
|
@ -917,7 +979,7 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
|||
return 0;
|
||||
}
|
||||
if( p->mxAlloc==0 ){
|
||||
setStrAccumError(p, SQLITE_TOOBIG);
|
||||
sqlite3StrAccumSetError(p, SQLITE_TOOBIG);
|
||||
return p->nAlloc - p->nChar - 1;
|
||||
}else{
|
||||
char *zOld = isMalloced(p) ? p->zText : 0;
|
||||
|
@ -930,7 +992,7 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
|||
}
|
||||
if( szNew > p->mxAlloc ){
|
||||
sqlite3_str_reset(p);
|
||||
setStrAccumError(p, SQLITE_TOOBIG);
|
||||
sqlite3StrAccumSetError(p, SQLITE_TOOBIG);
|
||||
return 0;
|
||||
}else{
|
||||
p->nAlloc = (int)szNew;
|
||||
|
@ -948,7 +1010,7 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
|||
p->printfFlags |= SQLITE_PRINTF_MALLOCED;
|
||||
}else{
|
||||
sqlite3_str_reset(p);
|
||||
setStrAccumError(p, SQLITE_NOMEM);
|
||||
sqlite3StrAccumSetError(p, SQLITE_NOMEM);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -1021,7 +1083,7 @@ static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){
|
|||
memcpy(zText, p->zText, p->nChar+1);
|
||||
p->printfFlags |= SQLITE_PRINTF_MALLOCED;
|
||||
}else{
|
||||
setStrAccumError(p, SQLITE_NOMEM);
|
||||
sqlite3StrAccumSetError(p, SQLITE_NOMEM);
|
||||
}
|
||||
p->zText = zText;
|
||||
return zText;
|
||||
|
@ -1036,6 +1098,22 @@ char *sqlite3StrAccumFinish(StrAccum *p){
|
|||
return p->zText;
|
||||
}
|
||||
|
||||
/*
|
||||
** Use the content of the StrAccum passed as the second argument
|
||||
** as the result of an SQL function.
|
||||
*/
|
||||
void sqlite3ResultStrAccum(sqlite3_context *pCtx, StrAccum *p){
|
||||
if( p->accError ){
|
||||
sqlite3_result_error_code(pCtx, p->accError);
|
||||
sqlite3_str_reset(p);
|
||||
}else if( isMalloced(p) ){
|
||||
sqlite3_result_text(pCtx, p->zText, p->nChar, SQLITE_DYNAMIC);
|
||||
}else{
|
||||
sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
|
||||
sqlite3_str_reset(p);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** This singleton is an sqlite3_str object that is returned if
|
||||
** sqlite3_malloc() fails to provide space for a real one. This
|
||||
|
|
98
third_party/sqlite3/random.c
vendored
98
third_party/sqlite3/random.c
vendored
|
@ -15,24 +15,48 @@
|
|||
** Random numbers are used by some of the database backends in order
|
||||
** to generate random integer keys for tables or random filenames.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
|
||||
/* All threads share a single random number generator.
|
||||
** This structure is the current state of the generator.
|
||||
*/
|
||||
static SQLITE_WSD struct sqlite3PrngType {
|
||||
unsigned char isInit; /* True if initialized */
|
||||
unsigned char i, j; /* State variables */
|
||||
unsigned char s[256]; /* State variables */
|
||||
u32 s[16]; /* 64 bytes of chacha20 state */
|
||||
u8 out[64]; /* Output bytes */
|
||||
u8 n; /* Output bytes remaining */
|
||||
} sqlite3Prng;
|
||||
|
||||
|
||||
/* The RFC-7539 ChaCha20 block function
|
||||
*/
|
||||
#define ROTL(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
|
||||
#define QR(a, b, c, d) ( \
|
||||
a += b, d ^= a, d = ROTL(d,16), \
|
||||
c += d, b ^= c, b = ROTL(b,12), \
|
||||
a += b, d ^= a, d = ROTL(d, 8), \
|
||||
c += d, b ^= c, b = ROTL(b, 7))
|
||||
static void chacha_block(u32 *out, const u32 *in){
|
||||
int i;
|
||||
u32 x[16];
|
||||
memcpy(x, in, 64);
|
||||
for(i=0; i<10; i++){
|
||||
QR(x[0], x[4], x[ 8], x[12]);
|
||||
QR(x[1], x[5], x[ 9], x[13]);
|
||||
QR(x[2], x[6], x[10], x[14]);
|
||||
QR(x[3], x[7], x[11], x[15]);
|
||||
QR(x[0], x[5], x[10], x[15]);
|
||||
QR(x[1], x[6], x[11], x[12]);
|
||||
QR(x[2], x[7], x[ 8], x[13]);
|
||||
QR(x[3], x[4], x[ 9], x[14]);
|
||||
}
|
||||
for(i=0; i<16; i++) out[i] = x[i]+in[i];
|
||||
}
|
||||
|
||||
/*
|
||||
** Return N random bytes.
|
||||
*/
|
||||
void sqlite3_randomness(int N, void *pBuf){
|
||||
unsigned char t;
|
||||
unsigned char *zBuf = pBuf;
|
||||
|
||||
/* The "wsdPrng" macro will resolve to the pseudo-random number generator
|
||||
|
@ -62,48 +86,46 @@ void sqlite3_randomness(int N, void *pBuf){
|
|||
|
||||
sqlite3_mutex_enter(mutex);
|
||||
if( N<=0 || pBuf==0 ){
|
||||
wsdPrng.isInit = 0;
|
||||
wsdPrng.s[0] = 0;
|
||||
sqlite3_mutex_leave(mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize the state of the random number generator once,
|
||||
** the first time this routine is called. The seed value does
|
||||
** not need to contain a lot of randomness since we are not
|
||||
** trying to do secure encryption or anything like that...
|
||||
**
|
||||
** Nothing in this file or anywhere else in SQLite does any kind of
|
||||
** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
|
||||
** number generator) not as an encryption device.
|
||||
** the first time this routine is called.
|
||||
*/
|
||||
if( !wsdPrng.isInit ){
|
||||
int i;
|
||||
char k[256];
|
||||
wsdPrng.j = 0;
|
||||
wsdPrng.i = 0;
|
||||
sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
|
||||
for(i=0; i<256; i++){
|
||||
wsdPrng.s[i] = (u8)i;
|
||||
if( wsdPrng.s[0]==0 ){
|
||||
sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
|
||||
static const u32 chacha20_init[] = {
|
||||
0x61707865, 0x3320646e, 0x79622d32, 0x6b206574
|
||||
};
|
||||
memcpy(&wsdPrng.s[0], chacha20_init, 16);
|
||||
if( NEVER(pVfs==0) ){
|
||||
memset(&wsdPrng.s[4], 0, 44);
|
||||
}else{
|
||||
sqlite3OsRandomness(pVfs, 44, (char*)&wsdPrng.s[4]);
|
||||
}
|
||||
for(i=0; i<256; i++){
|
||||
wsdPrng.j += wsdPrng.s[i] + k[i];
|
||||
t = wsdPrng.s[wsdPrng.j];
|
||||
wsdPrng.s[wsdPrng.j] = wsdPrng.s[i];
|
||||
wsdPrng.s[i] = t;
|
||||
}
|
||||
wsdPrng.isInit = 1;
|
||||
wsdPrng.s[15] = wsdPrng.s[12];
|
||||
wsdPrng.s[12] = 0;
|
||||
wsdPrng.n = 0;
|
||||
}
|
||||
|
||||
assert( N>0 );
|
||||
do{
|
||||
wsdPrng.i++;
|
||||
t = wsdPrng.s[wsdPrng.i];
|
||||
wsdPrng.j += t;
|
||||
wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
|
||||
wsdPrng.s[wsdPrng.j] = t;
|
||||
t += wsdPrng.s[wsdPrng.i];
|
||||
*(zBuf++) = wsdPrng.s[t];
|
||||
}while( --N );
|
||||
while( 1 /* exit by break */ ){
|
||||
if( N<=wsdPrng.n ){
|
||||
memcpy(zBuf, &wsdPrng.out[wsdPrng.n-N], N);
|
||||
wsdPrng.n -= N;
|
||||
break;
|
||||
}
|
||||
if( wsdPrng.n>0 ){
|
||||
memcpy(zBuf, wsdPrng.out, wsdPrng.n);
|
||||
N -= wsdPrng.n;
|
||||
zBuf += wsdPrng.n;
|
||||
}
|
||||
wsdPrng.s[12]++;
|
||||
chacha_block((u32*)wsdPrng.out, wsdPrng.s);
|
||||
wsdPrng.n = 64;
|
||||
}
|
||||
sqlite3_mutex_leave(mutex);
|
||||
}
|
||||
|
||||
|
|
512
third_party/sqlite3/resolve.c
vendored
512
third_party/sqlite3/resolve.c
vendored
File diff suppressed because it is too large
Load diff
5
third_party/sqlite3/rowset.c
vendored
5
third_party/sqlite3/rowset.c
vendored
|
@ -35,7 +35,7 @@
|
|||
** extracts the least value from the RowSet.
|
||||
**
|
||||
** The INSERT primitive might allocate additional memory. Memory is
|
||||
** allocated in chunks so most INSERTs do no allocation. There is an
|
||||
** allocated in chunks so most INSERTs do no allocation. There is an
|
||||
** upper bound on the size of allocated memory. No memory is freed
|
||||
** until DESTROY.
|
||||
**
|
||||
|
@ -61,8 +61,7 @@
|
|||
** be possible, but the feature was not used, so it was removed in order
|
||||
** to simplify the code.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
|
||||
/*
|
||||
|
|
171
third_party/sqlite3/rtree.c
vendored
171
third_party/sqlite3/rtree.c
vendored
|
@ -12,7 +12,6 @@
|
|||
** This file contains code for implementations of the r-tree and r*-tree
|
||||
** algorithms packaged as an SQLite virtual table module.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
/*
|
||||
** Database Format of R-Tree Tables
|
||||
|
@ -58,15 +57,19 @@
|
|||
|| (defined(SQLITE_ENABLE_RTREE) && !defined(SQLITE_OMIT_VIRTUALTABLE))
|
||||
|
||||
#ifndef SQLITE_CORE
|
||||
#include "third_party/sqlite3/sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include "third_party/sqlite3/sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#else
|
||||
#include "third_party/sqlite3/sqlite3.h"
|
||||
#include "third_party/sqlite3/sqlite3.h"
|
||||
#endif
|
||||
int sqlite3GetToken(const unsigned char*,int*); /* In the SQLite core */
|
||||
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
#include "third_party/sqlite3/sqlite3rtree.inc"
|
||||
/*
|
||||
** If building separately, we will need some setup that is normally
|
||||
** found in sqliteInt.h
|
||||
*/
|
||||
#if !defined(SQLITE_AMALGAMATION)
|
||||
#include "third_party/sqlite3/sqlite3rtree.h"
|
||||
typedef sqlite3_int64 i64;
|
||||
typedef sqlite3_uint64 u64;
|
||||
typedef unsigned char u8;
|
||||
|
@ -78,10 +81,22 @@ typedef unsigned int u32;
|
|||
#if defined(NDEBUG) && defined(SQLITE_DEBUG)
|
||||
# undef NDEBUG
|
||||
#endif
|
||||
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
|
||||
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
|
||||
#endif
|
||||
#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
|
||||
# define ALWAYS(X) (1)
|
||||
# define NEVER(X) (0)
|
||||
#elif !defined(NDEBUG)
|
||||
# define ALWAYS(X) ((X)?1:(assert(0),0))
|
||||
# define NEVER(X) ((X)?(assert(0),1):0)
|
||||
#else
|
||||
# define ALWAYS(X) (X)
|
||||
# define NEVER(X) (X)
|
||||
#endif
|
||||
#endif /* !defined(SQLITE_AMALGAMATION) */
|
||||
|
||||
#include "libc/assert.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
|
@ -136,7 +151,9 @@ struct Rtree {
|
|||
u8 nBytesPerCell; /* Bytes consumed per cell */
|
||||
u8 inWrTrans; /* True if inside write transaction */
|
||||
u8 nAux; /* # of auxiliary columns in %_rowid */
|
||||
#ifdef SQLITE_ENABLE_GEOPOLY
|
||||
u8 nAuxNotNull; /* Number of initial not-null aux columns */
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
u8 bCorrupt; /* Shadow table corruption detected */
|
||||
#endif
|
||||
|
@ -418,7 +435,12 @@ struct RtreeMatchArg {
|
|||
** it is not, make it a no-op.
|
||||
*/
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
# define testcase(X)
|
||||
# if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
|
||||
unsigned int sqlite3RtreeTestcase = 0;
|
||||
# define testcase(X) if( X ){ sqlite3RtreeTestcase += __LINE__; }
|
||||
# else
|
||||
# define testcase(X)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -667,18 +689,6 @@ static void nodeBlobReset(Rtree *pRtree){
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if pNode is the same as pParent or any of the parents
|
||||
** of pParent.
|
||||
*/
|
||||
static int nodeInParentChain(const RtreeNode *pNode, const RtreeNode *pParent){
|
||||
do{
|
||||
if( pNode==pParent ) return 1;
|
||||
pParent = pParent->pParent;
|
||||
}while( pParent );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Obtain a reference to an r-tree node.
|
||||
*/
|
||||
|
@ -695,14 +705,7 @@ static int nodeAcquire(
|
|||
** increase its reference count and return it.
|
||||
*/
|
||||
if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){
|
||||
if( pParent && !pNode->pParent ){
|
||||
if( nodeInParentChain(pNode, pParent) ){
|
||||
RTREE_IS_CORRUPT(pRtree);
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
pParent->nRef++;
|
||||
pNode->pParent = pParent;
|
||||
}else if( pParent && pNode->pParent && pParent!=pNode->pParent ){
|
||||
if( pParent && pParent!=pNode->pParent ){
|
||||
RTREE_IS_CORRUPT(pRtree);
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
|
@ -760,7 +763,7 @@ static int nodeAcquire(
|
|||
** are the leaves, and so on. If the depth as specified on the root node
|
||||
** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt.
|
||||
*/
|
||||
if( pNode && rc==SQLITE_OK && iNode==1 ){
|
||||
if( rc==SQLITE_OK && pNode && iNode==1 ){
|
||||
pRtree->iDepth = readInt16(pNode->zData);
|
||||
if( pRtree->iDepth>RTREE_MAX_DEPTH ){
|
||||
rc = SQLITE_CORRUPT_VTAB;
|
||||
|
@ -1283,20 +1286,29 @@ static void rtreeNonleafConstraint(
|
|||
switch( p->op ){
|
||||
case RTREE_TRUE: return; /* Always satisfied */
|
||||
case RTREE_FALSE: break; /* Never satisfied */
|
||||
case RTREE_LE:
|
||||
case RTREE_LT:
|
||||
case RTREE_EQ:
|
||||
RTREE_DECODE_COORD(eInt, pCellData, val);
|
||||
/* val now holds the lower bound of the coordinate pair */
|
||||
if( p->u.rValue>=val ){
|
||||
pCellData += 4;
|
||||
RTREE_DECODE_COORD(eInt, pCellData, val);
|
||||
/* val now holds the upper bound of the coordinate pair */
|
||||
if( p->u.rValue<=val ) return;
|
||||
}
|
||||
break;
|
||||
case RTREE_LE:
|
||||
case RTREE_LT:
|
||||
RTREE_DECODE_COORD(eInt, pCellData, val);
|
||||
/* val now holds the lower bound of the coordinate pair */
|
||||
if( p->u.rValue>=val ) return;
|
||||
if( p->op!=RTREE_EQ ) break; /* RTREE_LE and RTREE_LT end here */
|
||||
/* Fall through for the RTREE_EQ case */
|
||||
break;
|
||||
|
||||
default: /* RTREE_GT or RTREE_GE, or fallthrough of RTREE_EQ */
|
||||
default:
|
||||
pCellData += 4;
|
||||
RTREE_DECODE_COORD(eInt, pCellData, val);
|
||||
/* val now holds the upper bound of the coordinate pair */
|
||||
if( p->u.rValue<=val ) return;
|
||||
break;
|
||||
}
|
||||
*peWithin = NOT_WITHIN;
|
||||
}
|
||||
|
@ -1366,11 +1378,12 @@ static int nodeRowidIndex(
|
|||
*/
|
||||
static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode, int *piIndex){
|
||||
RtreeNode *pParent = pNode->pParent;
|
||||
if( pParent ){
|
||||
if( ALWAYS(pParent) ){
|
||||
return nodeRowidIndex(pRtree, pParent, pNode->iNode, piIndex);
|
||||
}else{
|
||||
*piIndex = -1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
*piIndex = -1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1493,7 +1506,8 @@ static RtreeSearchPoint *rtreeSearchPointNew(
|
|||
pNew = rtreeEnqueue(pCur, rScore, iLevel);
|
||||
if( pNew==0 ) return 0;
|
||||
ii = (int)(pNew - pCur->aPoint) + 1;
|
||||
if( ii<RTREE_CACHE_SZ ){
|
||||
assert( ii==1 );
|
||||
if( ALWAYS(ii<RTREE_CACHE_SZ) ){
|
||||
assert( pCur->aNode[ii]==0 );
|
||||
pCur->aNode[ii] = pCur->aNode[0];
|
||||
}else{
|
||||
|
@ -1554,7 +1568,7 @@ static void rtreeSearchPointPop(RtreeCursor *p){
|
|||
if( p->bPoint ){
|
||||
p->anQueue[p->sPoint.iLevel]--;
|
||||
p->bPoint = 0;
|
||||
}else if( p->nPoint ){
|
||||
}else if( ALWAYS(p->nPoint) ){
|
||||
p->anQueue[p->aPoint[0].iLevel]--;
|
||||
n = --p->nPoint;
|
||||
p->aPoint[0] = p->aPoint[n];
|
||||
|
@ -1695,7 +1709,7 @@ static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
|
|||
RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr);
|
||||
int rc = SQLITE_OK;
|
||||
RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
|
||||
if( rc==SQLITE_OK && p ){
|
||||
if( rc==SQLITE_OK && ALWAYS(p) ){
|
||||
*pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell);
|
||||
}
|
||||
return rc;
|
||||
|
@ -1713,7 +1727,7 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
|
|||
RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
|
||||
|
||||
if( rc ) return rc;
|
||||
if( p==0 ) return SQLITE_OK;
|
||||
if( NEVER(p==0) ) return SQLITE_OK;
|
||||
if( i==0 ){
|
||||
sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell));
|
||||
}else if( i<=pRtree->nDim2 ){
|
||||
|
@ -1912,8 +1926,11 @@ static int rtreeFilter(
|
|||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
RtreeSearchPoint *pNew;
|
||||
assert( pCsr->bPoint==0 ); /* Due to the resetCursor() call above */
|
||||
pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1));
|
||||
if( pNew==0 ) return SQLITE_NOMEM;
|
||||
if( NEVER(pNew==0) ){ /* Because pCsr->bPoint was FALSE */
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
pNew->id = 1;
|
||||
pNew->iCell = 0;
|
||||
pNew->eWithin = PARTLY_WITHIN;
|
||||
|
@ -1990,7 +2007,7 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
|||
struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii];
|
||||
|
||||
if( bMatch==0 && p->usable
|
||||
&& p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ
|
||||
&& p->iColumn<=0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ
|
||||
){
|
||||
/* We have an equality constraint on the rowid. Use strategy 1. */
|
||||
int jj;
|
||||
|
@ -2196,7 +2213,7 @@ static int ChooseLeaf(
|
|||
|
||||
int nCell = NCELL(pNode);
|
||||
RtreeCell cell;
|
||||
RtreeNode *pChild;
|
||||
RtreeNode *pChild = 0;
|
||||
|
||||
RtreeCell *aCell = 0;
|
||||
|
||||
|
@ -2243,12 +2260,19 @@ static int AdjustTree(
|
|||
){
|
||||
RtreeNode *p = pNode;
|
||||
int cnt = 0;
|
||||
int rc;
|
||||
while( p->pParent ){
|
||||
RtreeNode *pParent = p->pParent;
|
||||
RtreeCell cell;
|
||||
int iCell;
|
||||
|
||||
if( (++cnt)>1000 || nodeParentIndex(pRtree, p, &iCell) ){
|
||||
cnt++;
|
||||
if( NEVER(cnt>100) ){
|
||||
RTREE_IS_CORRUPT(pRtree);
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
rc = nodeParentIndex(pRtree, p, &iCell);
|
||||
if( NEVER(rc!=SQLITE_OK) ){
|
||||
RTREE_IS_CORRUPT(pRtree);
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
|
@ -2537,12 +2561,17 @@ static int updateMapping(
|
|||
xSetMapping = ((iHeight==0)?rowidWrite:parentWrite);
|
||||
if( iHeight>0 ){
|
||||
RtreeNode *pChild = nodeHashLookup(pRtree, iRowid);
|
||||
RtreeNode *p;
|
||||
for(p=pNode; p; p=p->pParent){
|
||||
if( p==pChild ) return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
if( pChild ){
|
||||
nodeRelease(pRtree, pChild->pParent);
|
||||
nodeReference(pNode);
|
||||
pChild->pParent = pNode;
|
||||
}
|
||||
}
|
||||
if( NEVER(pNode==0) ) return SQLITE_ERROR;
|
||||
return xSetMapping(pRtree, iRowid, pNode->iNode);
|
||||
}
|
||||
|
||||
|
@ -2632,11 +2661,12 @@ static int SplitNode(
|
|||
RtreeNode *pParent = pLeft->pParent;
|
||||
int iCell;
|
||||
rc = nodeParentIndex(pRtree, pLeft, &iCell);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( ALWAYS(rc==SQLITE_OK) ){
|
||||
nodeOverwriteCell(pRtree, pParent, &leftbbox, iCell);
|
||||
rc = AdjustTree(pRtree, pParent, &leftbbox);
|
||||
assert( rc==SQLITE_OK );
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( NEVER(rc!=SQLITE_OK) ){
|
||||
goto splitnode_out;
|
||||
}
|
||||
}
|
||||
|
@ -2711,7 +2741,7 @@ static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){
|
|||
*/
|
||||
iNode = sqlite3_column_int64(pRtree->pReadParent, 0);
|
||||
for(pTest=pLeaf; pTest && pTest->iNode!=iNode; pTest=pTest->pParent);
|
||||
if( !pTest ){
|
||||
if( pTest==0 ){
|
||||
rc2 = nodeAcquire(pRtree, iNode, 0, &pChild->pParent);
|
||||
}
|
||||
}
|
||||
|
@ -2742,6 +2772,7 @@ static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){
|
|||
pParent = pNode->pParent;
|
||||
pNode->pParent = 0;
|
||||
rc = deleteCell(pRtree, pParent, iCell, iHeight+1);
|
||||
testcase( rc!=SQLITE_OK );
|
||||
}
|
||||
rc2 = nodeRelease(pRtree, pParent);
|
||||
if( rc==SQLITE_OK ){
|
||||
|
@ -2964,7 +2995,7 @@ static int rtreeInsertCell(
|
|||
}
|
||||
}else{
|
||||
rc = AdjustTree(pRtree, pNode, pCell);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( ALWAYS(rc==SQLITE_OK) ){
|
||||
if( iHeight==0 ){
|
||||
rc = rowidWrite(pRtree, pCell->iRowid, pNode->iNode);
|
||||
}else{
|
||||
|
@ -3070,7 +3101,7 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
|
|||
int rc2;
|
||||
RtreeNode *pChild = 0;
|
||||
i64 iChild = nodeGetRowid(pRtree, pRoot, 0);
|
||||
rc = nodeAcquire(pRtree, iChild, pRoot, &pChild);
|
||||
rc = nodeAcquire(pRtree, iChild, pRoot, &pChild); /* tag-20210916a */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = removeNode(pRtree, pChild, pRtree->iDepth-1);
|
||||
}
|
||||
|
@ -3203,7 +3234,7 @@ static int rtreeUpdate(
|
|||
rtreeReference(pRtree);
|
||||
assert(nData>=1);
|
||||
|
||||
cell.iRowid = 0; /* Used only to suppress a compiler warning */
|
||||
memset(&cell, 0, sizeof(cell));
|
||||
|
||||
/* Constraint handling. A write operation on an r-tree table may return
|
||||
** SQLITE_CONSTRAINT for two reasons:
|
||||
|
@ -3405,7 +3436,7 @@ static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
|
|||
char *zSql;
|
||||
sqlite3_stmt *p;
|
||||
int rc;
|
||||
i64 nRow = 0;
|
||||
i64 nRow = RTREE_MIN_ROWEST;
|
||||
|
||||
rc = sqlite3_table_column_metadata(
|
||||
db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0
|
||||
|
@ -3422,20 +3453,10 @@ static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
|
|||
if( rc==SQLITE_OK ){
|
||||
if( sqlite3_step(p)==SQLITE_ROW ) nRow = sqlite3_column_int64(p, 0);
|
||||
rc = sqlite3_finalize(p);
|
||||
}else if( rc!=SQLITE_NOMEM ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
if( nRow==0 ){
|
||||
pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
|
||||
}else{
|
||||
pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST);
|
||||
}
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
|
||||
pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -3585,9 +3606,12 @@ static int rtreeSqlInit(
|
|||
sqlite3_str_appendf(p, "UPDATE \"%w\".\"%w_rowid\"SET ", zDb, zPrefix);
|
||||
for(ii=0; ii<pRtree->nAux; ii++){
|
||||
if( ii ) sqlite3_str_append(p, ",", 1);
|
||||
#ifdef SQLITE_ENABLE_GEOPOLY
|
||||
if( ii<pRtree->nAuxNotNull ){
|
||||
sqlite3_str_appendf(p,"a%d=coalesce(?%d,a%d)",ii,ii+2,ii);
|
||||
}else{
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
sqlite3_str_appendf(p,"a%d=?%d",ii,ii+2);
|
||||
}
|
||||
}
|
||||
|
@ -3852,6 +3876,7 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
|
|||
tree.nDim2 = tree.nDim*2;
|
||||
tree.nBytesPerCell = 8 + 8 * tree.nDim;
|
||||
node.zData = (u8 *)sqlite3_value_blob(apArg[1]);
|
||||
if( node.zData==0 ) return;
|
||||
nData = sqlite3_value_bytes(apArg[1]);
|
||||
if( nData<4 ) return;
|
||||
if( nData<NCELL(&node)*tree.nBytesPerCell ) return;
|
||||
|
@ -3891,11 +3916,16 @@ static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
|
|||
UNUSED_PARAMETER(nArg);
|
||||
if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB
|
||||
|| sqlite3_value_bytes(apArg[0])<2
|
||||
|
||||
){
|
||||
sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1);
|
||||
}else{
|
||||
u8 *zBlob = (u8 *)sqlite3_value_blob(apArg[0]);
|
||||
sqlite3_result_int(ctx, readInt16(zBlob));
|
||||
if( zBlob ){
|
||||
sqlite3_result_int(ctx, readInt16(zBlob));
|
||||
}else{
|
||||
sqlite3_result_error_nomem(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4261,8 +4291,10 @@ static int rtreeCheckTable(
|
|||
if( pStmt ){
|
||||
nAux = sqlite3_column_count(pStmt) - 2;
|
||||
sqlite3_finalize(pStmt);
|
||||
}else
|
||||
if( check.rc!=SQLITE_NOMEM ){
|
||||
check.rc = SQLITE_OK;
|
||||
}
|
||||
check.rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Find number of dimensions in the rtree table. */
|
||||
|
@ -4367,7 +4399,7 @@ static void rtreecheck(
|
|||
|
||||
/* Conditionally include the geopoly code */
|
||||
#ifdef SQLITE_ENABLE_GEOPOLY
|
||||
#include "third_party/sqlite3/geopoly.inc"
|
||||
# include "geopoly.inc"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -4519,7 +4551,10 @@ int sqlite3_rtree_query_callback(
|
|||
|
||||
/* Allocate and populate the context object. */
|
||||
pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback));
|
||||
if( !pGeomCtx ) return SQLITE_NOMEM;
|
||||
if( !pGeomCtx ){
|
||||
if( xDestructor ) xDestructor(pContext);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
pGeomCtx->xGeom = 0;
|
||||
pGeomCtx->xQueryFunc = xQueryFunc;
|
||||
pGeomCtx->xDestructor = xDestructor;
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
** RTREE library. All it does is declare the sqlite3RtreeInit() interface.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqlite3.h"
|
||||
/* clang-format off */
|
||||
|
||||
#ifdef SQLITE_OMIT_VIRTUALTABLE
|
||||
# undef SQLITE_ENABLE_RTREE
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue