Upgrade SQLite to 3.40 (#699)

This commit is contained in:
Paul Kulchenko 2022-11-28 12:54:48 -08:00 committed by GitHub
parent bcae817215
commit 0dc0758574
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
151 changed files with 27917 additions and 22169 deletions

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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;
sqlite3StrAccumInit(&sStat, 0, 0, 0, p->nCol*100);
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);
}
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 ){

View file

@ -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,7 +465,8 @@ 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) ){
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);
@ -473,11 +474,17 @@ static int fixSelectCb(Walker *p, Select *pSelect){
}
sqlite3DbFree(db, pItem->zDatabase);
pItem->zDatabase = 0;
pItem->fg.notCte = 1;
}
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,8 +581,9 @@ int sqlite3FixTriggerStep(
return 1;
}
#ifndef SQLITE_OMIT_UPSERT
if( pStep->pUpsert ){
Upsert *pUp = pStep->pUpsert;
{
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)
@ -584,6 +592,7 @@ int sqlite3FixTriggerStep(
return 1;
}
}
}
#endif
pStep = pStep->pNext;
}

View file

@ -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";
}

View file

@ -12,9 +12,8 @@
** 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;
}

View file

@ -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:

View file

@ -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;

File diff suppressed because it is too large Load diff

View file

@ -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);

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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);

View file

@ -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
/*

View file

@ -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]);

View file

@ -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(
static int toLocaltime(
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 */
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;
}
x.tz = 0;
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);
}
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,82 +1148,40 @@ 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{
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_snprintf(3, &z[j],"%02d",x.D); j+=2; break;
case 'd': {
sqlite3_str_appendf(&sRes, "%02d", x.D);
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]);
sqlite3_str_appendf(&sRes, "%06.3f", s);
break;
}
case 'H': {
sqlite3_str_appendf(&sRes, "%02d", x.h);
break;
}
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 */
@ -1101,43 +1194,54 @@ static void strftimeFunc(
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;
sqlite3_str_appendf(&sRes,"%02d",(nDay+7-wd)/7);
}else{
sqlite3_snprintf(4, &z[j],"%03d",nDay+1);
j += 3;
sqlite3_str_appendf(&sRes,"%03d",nDay+1);
}
break;
}
case 'J': {
sqlite3_snprintf(20, &z[j],"%.16g",x.iJD/86400000.0);
j+=sqlite3Strlen30(&z[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 '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]);
sqlite3_str_appendf(&sRes,"%lld",iS);
break;
}
case 'S': {
sqlite3_str_appendf(&sRes,"%02d",(int)x.s);
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';
sqlite3_str_appendchar(&sRes, 1,
(char)(((x.iJD+129600000)/86400000) % 7) + '0');
break;
}
case 'Y': {
sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=sqlite3Strlen30(&z[j]);
sqlite3_str_appendf(&sRes,"%04d",x.Y);
break;
}
default: z[j++] = '%'; 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 ),

View file

@ -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;
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);
}
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;
}

View file

@ -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 ){
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;

View file

@ -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,8 +473,12 @@ void sqlite3DeleteFrom(
}
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
assert( pIdx->pSchema==pTab->pSchema );
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,14 +987,16 @@ int sqlite3GenerateIndexKey(
continue;
}
sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iDataCur, j, regBase+j);
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 */
** 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);
}

View file

@ -43,7 +43,7 @@ hash
icu
ieee754
insert
json1
json
legacy
loadext
main

File diff suppressed because it is too large Load diff

View file

@ -23,9 +23,8 @@
** 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

View file

@ -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

View file

@ -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);
@ -430,11 +429,10 @@ 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{

View file

@ -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"
#include "third_party/sqlite3/fts3.h"
#ifndef SQLITE_CORE
#include "third_party/sqlite3/sqlite3ext.h"
SQLITE_EXTENSION_INIT1
# 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);
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 ){

View file

@ -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)
#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(SQLITE_DEBUG)
# define ALWAYS(x) sqlite3Fts3Always((x)!=0)
# define NEVER(x) sqlite3Fts3Never((x)!=0)
int sqlite3Fts3Always(int b);
int sqlite3Fts3Never(int b);
#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

View file

@ -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;

View file

@ -15,9 +15,8 @@
** syntax is relatively simple, the whole tokenizer/parser system is
** 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

View file

@ -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

View file

@ -16,7 +16,6 @@
*/
#ifndef _FTS3_HASH_H_
#define _FTS3_HASH_H_
/* clang-format off */
/* Forward declarations of structures. */
typedef struct Fts3Hash Fts3Hash;

View file

@ -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;

View file

@ -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;
}

View file

@ -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.

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -10,7 +10,6 @@
**
******************************************************************************
*/
/* clang-format off */
/*
** DO NOT EDIT THIS MACHINE GENERATED FILE.

View file

@ -16,14 +16,13 @@
** 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);
}
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;
}

File diff suppressed because it is too large Load diff

View file

@ -16,7 +16,6 @@
** * custom tokenizers, and
** * custom auxiliary functions.
*/
/* clang-format off */
#ifndef _FTS5_H

View file

@ -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){
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){
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);
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_snprintf(sizeof(zBuf), zBuf, "%!.20e", r1);
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];
int firstTerm = pGCC->str.mxAlloc==0;
pGCC->str.mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
if( argc==1 ){
if( !firstTerm ){
if( argc==2 ){
sqlite3_str_appendchar(&pGCC->str, 1, ',');
}
#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{
zSep = ",";
nSep = 1;
pnsl = (int*)sqlite3_realloc64(pnsl, pGCC->nAccum * sizeof(int));
}
if( zSep ) sqlite3_str_append(pAccum, zSep, nSep);
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]);
}else{
n++;
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));
}
if( n>=(int)pAccum->nChar ){
pAccum->nChar = 0;
}else{
pAccum->nChar -= n;
memmove(pAccum->zText, &pAccum->zText[n], pAccum->nChar);
/* If removing single accumulated string, harmlessly over-do. */
nVS += pGCC->nFirstSepLength;
}
if( nVS>=(int)pGCC->str.nChar ){
pGCC->str.nChar = 0;
}else{
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
#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");

View file

@ -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]);
}

View file

@ -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"
};

View file

@ -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.

View file

@ -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 */

View file

@ -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.

View file

@ -27,20 +27,20 @@
** * 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;
}

View file

@ -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){
char *sqlite3TableAffinityStr(sqlite3 *db, const Table *pTab){
char *zColAff;
zColAff = (char *)sqlite3DbMallocRaw(db, pTab->nCol+1);
if( zColAff ){
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;
}
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,9 +294,9 @@ 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
){
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. */
@ -260,6 +313,12 @@ void sqlite3ComputeGeneratedColumns(
}
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;
}
}
/* Because there can be multiple generated columns that refer to one another,
@ -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
);
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]);
@ -2165,6 +2263,7 @@ 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. */
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

View file

@ -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
View file

@ -0,0 +1 @@
#include "third_party/sqlite3/json.c"

View file

@ -1 +0,0 @@
#include "third_party/sqlite3/json1.c"

View file

@ -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

View file

@ -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 */

View file

@ -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,9 +1858,11 @@ int sqlite3CreateFunc(
** If SQLITE_ANY is specified, add three versions of the function
** to the hash table.
*/
if( enc==SQLITE_UTF16 ){
switch( enc ){
case SQLITE_UTF16:
enc = SQLITE_UTF16NATIVE;
}else if( enc==SQLITE_ANY ){
break;
case SQLITE_ANY: {
int rc;
rc = sqlite3CreateFunc(db, zFunctionName, nArg,
(SQLITE_UTF8|extraFlags)^SQLITE_FUNC_UNSAFE,
@ -1865,6 +1876,15 @@ int sqlite3CreateFunc(
return rc;
}
enc = SQLITE_UTF16BE;
break;
}
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,13 +4334,17 @@ 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*));
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 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) ){

View file

@ -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{
}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;
}
/*

View file

@ -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

View file

@ -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__ */

View file

@ -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;

View file

@ -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

View file

@ -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;
}

View file

@ -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,20 +180,68 @@ 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;
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;
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;
return SQLITE_OK;
}
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;
}
p->eLock = eLock;
return SQLITE_OK;
}
}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--;
}
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;
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,7 +810,8 @@ 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;
}
@ -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 */

View file

@ -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.
*/
@ -209,22 +211,20 @@ static int memjrnlWrite(
** 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)
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,14 +259,15 @@ static int memjrnlWrite(
*/
static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
MemJournal *p = (MemJournal *)pJfd;
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){
for(pIter=p->pFirst; ALWAYS(pIter) && iOff<size; pIter=pIter->pNext){
iOff += p->nChunkSize;
}
if( ALWAYS(pIter) ){
@ -278,6 +280,7 @@ static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
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

View file

@ -14,7 +14,6 @@
*/
#ifndef SQLITE_MSVC_H
#define SQLITE_MSVC_H
/* clang-format off */
#if defined(_MSC_VER)
#pragma warning(disable : 4054)

View file

@ -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)
/*

View file

@ -19,7 +19,6 @@
** Source files should #include the sqliteInt.h file and let that file
** include this one indirectly.
*/
/* clang-format off */
/*

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
View 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 */

View file

@ -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 */

View file

@ -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){

View file

@ -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
*/

View file

@ -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
View 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
View 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 */

View file

@ -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 */

View file

@ -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,10 +860,10 @@ 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) ||
assert( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
(sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
(sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
(sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK));
(sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) );
// changed switch to if-else
if (posixError == EACCES || posixError == EAGAIN || posixError == ETIMEDOUT ||
posixError == EBUSY || posixError == EINTR || posixError == ENOLCK)
@ -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 );
@ -5738,24 +5806,34 @@ static int fillInUnixFile(
}
/*
** Return the name of a directory in which to put temporary files.
** If no suitable temporary file directory can be found, return NULL.
** Directories to consider for temp files.
*/
static const char *unixTempFileDir(void){
static const char *azDirs[] = {
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){
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,8 +5866,11 @@ 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;
if( zDir==0 ){
rc = SQLITE_IOERR_GETTEMPPATH;
}else{
do{
u64 r;
sqlite3_randomness(sizeof(r), &r);
@ -5796,10 +5878,15 @@ static int unixGetTempname(int nBuf, char *zBuf){
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;
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.
*/
nDb = sqlite3Strlen30(zPath) - 1;
while( zPath[nDb]!='-' ){
/* In normal operation, the journal file name will always contain
**
** 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--;
}
** 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( nDb>0 && zPath[nDb]!='.' ){
if( zPath[nDb]=='-' ){
memcpy(zDb, zPath, nDb);
zDb[nDb] = '\0';
rc = getFileMode(zDb, pMode, pUid, pGid);
break;
}
nDb--;
}
}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);
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);
}
}else{
bLink = S_ISLNK(buf.st_mode);
appendAllPathElements(&path, zPwd);
}
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, 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;
}

File diff suppressed because it is too large Load diff

View file

@ -1 +0,0 @@
#include "third_party/sqlite3/os_win.c"

View 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),

View file

@ -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().

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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) );
}
}

View file

@ -12,7 +12,6 @@
** This header file defines the interface that the sqlite page cache
** subsystem.
*/
/* clang-format off */
#ifndef _PCACHE_H_

View file

@ -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.
@ -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,19 +93,29 @@ 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 */
@ -113,7 +124,7 @@ struct PgHdr1 {
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 *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);

View file

@ -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 */
){
for(; p; p=p->pNext){
const char *zType;
static const u32 mask =
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 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);
/* 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);
}
if( !isQuick ){
/* Sanity check on record header decoding */
sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nNVCol-1,3);
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
}
/* Verify that all NOT NULL columns really are NOT NULL */
for(j=0; j<pTab->nCol; j++){
if( pPk ){
/* Verify WITHOUT ROWID keys are in ascending order */
int a1;
char *zErr;
int jmp2;
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);
}
jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
pTab->aCol[j].zName);
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;
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( bStrict ){
doTypeCheck = pCol->eCType>COLTYPE_ANY;
}else{
doTypeCheck = pCol->affinity>SQLITE_AFF_BLOB;
}
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);
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;
}

View file

@ -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. */

View file

@ -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( 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);

View file

@ -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*);
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->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);
}
}
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

View file

@ -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);
}

File diff suppressed because it is too large Load diff

View file

@ -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"
/*

View file

@ -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
# 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,21 +1286,30 @@ 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 ) return;
if( p->op!=RTREE_EQ ) break; /* RTREE_LE and RTREE_LT end here */
/* Fall through for the RTREE_EQ case */
default: /* RTREE_GT or RTREE_GE, or fallthrough of RTREE_EQ */
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;
break;
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;
}
}
/*
@ -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]);
if( zBlob ){
sqlite3_result_int(ctx, readInt16(zBlob));
}else{
sqlite3_result_error_nomem(ctx);
}
}
}
@ -4261,9 +4291,11 @@ static int rtreeCheckTable(
if( pStmt ){
nAux = sqlite3_column_count(pStmt) - 2;
sqlite3_finalize(pStmt);
}
}else
if( check.rc!=SQLITE_NOMEM ){
check.rc = SQLITE_OK;
}
}
/* Find number of dimensions in the rtree table. */
pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.%Q", zDb, zTab);
@ -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;

View file

@ -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