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

@ -14,17 +14,16 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
*/
#include "third_party/sqlite3/sqliteInt.inc"
/* clang-format off */
#include "third_party/sqlite3/sqliteInt.h"
#ifdef SQLITE_ENABLE_FTS3
#include "third_party/sqlite3/fts3.inc"
# include "third_party/sqlite3/fts3.h"
#endif
#ifdef SQLITE_ENABLE_RTREE
#include "third_party/sqlite3/rtree.inc"
# include "third_party/sqlite3/rtree.h"
#endif
#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS)
#include "third_party/sqlite3/sqliteicu.inc"
# include "third_party/sqlite3/sqliteicu.h"
#endif
/*
@ -51,9 +50,6 @@ int sqlite3Fts2Init(sqlite3*);
#ifdef SQLITE_ENABLE_FTS5
int sqlite3Fts5Init(sqlite3*);
#endif
#ifdef SQLITE_ENABLE_JSON1
int sqlite3Json1Init(sqlite3*);
#endif
#ifdef SQLITE_ENABLE_STMTVTAB
int sqlite3StmtVtabInit(sqlite3*);
#endif
@ -88,8 +84,8 @@ static int (*const sqlite3BuiltinExtensions[])(sqlite3*) = {
sqlite3DbstatRegister,
#endif
sqlite3TestExtInit,
#ifdef SQLITE_ENABLE_JSON1
sqlite3Json1Init,
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON)
sqlite3JsonTableFunctions,
#endif
#ifdef SQLITE_ENABLE_STMTVTAB
sqlite3StmtVtabInit,
@ -306,7 +302,7 @@ int sqlite3_initialize(void){
sqlite3GlobalConfig.isPCacheInit = 1;
rc = sqlite3OsInit();
}
#ifdef SQLITE_ENABLE_DESERIALIZE
#ifndef SQLITE_OMIT_DESERIALIZE
if( rc==SQLITE_OK ){
rc = sqlite3MemdbInit();
}
@ -721,12 +717,12 @@ int sqlite3_config(int op, ...){
}
#endif /* SQLITE_ENABLE_SORTER_REFERENCES */
#ifdef SQLITE_ENABLE_DESERIALIZE
#ifndef SQLITE_OMIT_DESERIALIZE
case SQLITE_CONFIG_MEMDB_MAXSIZE: {
sqlite3GlobalConfig.mxMemdbSize = va_arg(ap, sqlite3_int64);
break;
}
#endif /* SQLITE_ENABLE_DESERIALIZE */
#endif /* SQLITE_OMIT_DESERIALIZE */
default: {
rc = SQLITE_ERROR;
@ -828,18 +824,19 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
db->lookaside.bMalloced = pBuf==0 ?1:0;
db->lookaside.nSlot = nBig+nSm;
}else{
db->lookaside.pStart = db;
db->lookaside.pStart = 0;
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
db->lookaside.pSmallInit = 0;
db->lookaside.pSmallFree = 0;
db->lookaside.pMiddle = db;
db->lookaside.pMiddle = 0;
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
db->lookaside.pEnd = db;
db->lookaside.pEnd = 0;
db->lookaside.bDisable = 1;
db->lookaside.sz = 0;
db->lookaside.bMalloced = 0;
db->lookaside.nSlot = 0;
}
db->lookaside.pTrueEnd = db->lookaside.pEnd;
assert( sqlite3LookasideUsed(db,0)==0 );
#endif /* SQLITE_OMIT_LOOKASIDE */
return SQLITE_OK;
@ -918,6 +915,7 @@ int sqlite3_db_cacheflush(sqlite3 *db){
int sqlite3_db_config(sqlite3 *db, int op, ...){
va_list ap;
int rc;
sqlite3_mutex_enter(db->mutex);
va_start(ap, op);
switch( op ){
case SQLITE_DBCONFIG_MAINDBNAME: {
@ -983,6 +981,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
}
}
va_end(ap);
sqlite3_mutex_leave(db->mutex);
return rc;
}
@ -1087,7 +1086,7 @@ void sqlite3_set_last_insert_rowid(sqlite3 *db, sqlite3_int64 iRowid){
/*
** Return the number of changes in the most recent call to sqlite3_exec().
*/
int sqlite3_changes(sqlite3 *db){
sqlite3_int64 sqlite3_changes64(sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
@ -1096,11 +1095,14 @@ int sqlite3_changes(sqlite3 *db){
#endif
return db->nChange;
}
int sqlite3_changes(sqlite3 *db){
return (int)sqlite3_changes64(db);
}
/*
** Return the number of changes since the database handle was opened.
*/
int sqlite3_total_changes(sqlite3 *db){
sqlite3_int64 sqlite3_total_changes64(sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
@ -1109,6 +1111,9 @@ int sqlite3_total_changes(sqlite3 *db){
#endif
return db->nTotalChange;
}
int sqlite3_total_changes(sqlite3 *db){
return (int)sqlite3_total_changes64(db);
}
/*
** Close all open savepoints. This function only manipulates fields of the
@ -1133,7 +1138,9 @@ void sqlite3CloseSavepoints(sqlite3 *db){
** with SQLITE_ANY as the encoding.
*/
static void functionDestroy(sqlite3 *db, FuncDef *p){
FuncDestructor *pDestructor = p->u.pDestructor;
FuncDestructor *pDestructor;
assert( (p->funcFlags & SQLITE_FUNC_BUILTIN)==0 );
pDestructor = p->u.pDestructor;
if( pDestructor ){
pDestructor->nRef--;
if( pDestructor->nRef==0 ){
@ -1237,7 +1244,7 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){
/* Convert the connection into a zombie and then close it.
*/
db->magic = SQLITE_MAGIC_ZOMBIE;
db->eOpenState = SQLITE_STATE_ZOMBIE;
sqlite3LeaveMutexAndCloseZombie(db);
return SQLITE_OK;
}
@ -1275,7 +1282,7 @@ int sqlite3_txn_state(sqlite3 *db, const char *zSchema){
/*
** Two variations on the public interface for closing a database
** connection. The sqlite3_close() version returns SQLITE_BUSY and
** leaves the connection option if there are unfinalized prepared
** leaves the connection open if there are unfinalized prepared
** statements or unfinished sqlite3_backups. The sqlite3_close_v2()
** version forces the connection to become a zombie if there are
** unclosed resources, and arranges for deallocation when the last
@ -1301,7 +1308,7 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
** or if the connection has not yet been closed by sqlite3_close_v2(),
** then just leave the mutex and return.
*/
if( db->magic!=SQLITE_MAGIC_ZOMBIE || connectionIsBusy(db) ){
if( db->eOpenState!=SQLITE_STATE_ZOMBIE || connectionIsBusy(db) ){
sqlite3_mutex_leave(db->mutex);
return;
}
@ -1387,7 +1394,7 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
sqlite3_free(db->auth.zAuthPW);
#endif
db->magic = SQLITE_MAGIC_ERROR;
db->eOpenState = SQLITE_STATE_ERROR;
/* The temp-database schema is allocated differently from the other schema
** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
@ -1396,8 +1403,11 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
** structure?
*/
sqlite3DbFree(db, db->aDb[1].pSchema);
if( db->xAutovacDestr ){
db->xAutovacDestr(db->pAutovacPagesArg);
}
sqlite3_mutex_leave(db->mutex);
db->magic = SQLITE_MAGIC_CLOSED;
db->eOpenState = SQLITE_STATE_CLOSED;
sqlite3_mutex_free(db->mutex);
assert( sqlite3LookasideUsed(db,0)==0 );
if( db->lookaside.bMalloced ){
@ -1450,7 +1460,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
/* Any deferred constraint violations have now been resolved. */
db->nDeferredCons = 0;
db->nDeferredImmCons = 0;
db->flags &= ~(u64)SQLITE_DeferFKs;
db->flags &= ~(u64)(SQLITE_DeferFKs|SQLITE_CorruptRdOnly);
/* If one has been configured, invoke the rollback-hook callback */
if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
@ -1785,7 +1795,7 @@ int sqlite3_busy_timeout(sqlite3 *db, int ms){
*/
void sqlite3_interrupt(sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) && (db==0 || db->magic!=SQLITE_MAGIC_ZOMBIE) ){
if( !sqlite3SafetyCheckOk(db) && (db==0 || db->eOpenState!=SQLITE_STATE_ZOMBIE) ){
(void)SQLITE_MISUSE_BKPT;
return;
}
@ -1814,7 +1824,6 @@ int sqlite3CreateFunc(
FuncDestructor *pDestructor
){
FuncDef *p;
int nName;
int extraFlags;
assert( sqlite3_mutex_held(db->mutex) );
@ -1824,7 +1833,7 @@ int sqlite3CreateFunc(
|| ((xFinal==0)!=(xStep==0)) /* Both or neither of xFinal and xStep */
|| ((xValue==0)!=(xInverse==0)) /* Both or neither of xValue, xInverse */
|| (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG)
|| (255<(nName = sqlite3Strlen30( zFunctionName)))
|| (255<sqlite3Strlen30(zFunctionName))
){
return SQLITE_MISUSE_BKPT;
}
@ -1849,22 +1858,33 @@ int sqlite3CreateFunc(
** If SQLITE_ANY is specified, add three versions of the function
** to the hash table.
*/
if( enc==SQLITE_UTF16 ){
enc = SQLITE_UTF16NATIVE;
}else if( enc==SQLITE_ANY ){
int rc;
rc = sqlite3CreateFunc(db, zFunctionName, nArg,
(SQLITE_UTF8|extraFlags)^SQLITE_FUNC_UNSAFE,
pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
if( rc==SQLITE_OK ){
switch( enc ){
case SQLITE_UTF16:
enc = SQLITE_UTF16NATIVE;
break;
case SQLITE_ANY: {
int rc;
rc = sqlite3CreateFunc(db, zFunctionName, nArg,
(SQLITE_UTF16LE|extraFlags)^SQLITE_FUNC_UNSAFE,
(SQLITE_UTF8|extraFlags)^SQLITE_FUNC_UNSAFE,
pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
if( rc==SQLITE_OK ){
rc = sqlite3CreateFunc(db, zFunctionName, nArg,
(SQLITE_UTF16LE|extraFlags)^SQLITE_FUNC_UNSAFE,
pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
}
if( rc!=SQLITE_OK ){
return rc;
}
enc = SQLITE_UTF16BE;
break;
}
if( rc!=SQLITE_OK ){
return rc;
}
enc = SQLITE_UTF16BE;
case SQLITE_UTF8:
case SQLITE_UTF16LE:
case SQLITE_UTF16BE:
break;
default:
enc = SQLITE_UTF8;
break;
}
#else
enc = SQLITE_UTF8;
@ -1885,6 +1905,10 @@ int sqlite3CreateFunc(
}else{
sqlite3ExpirePreparedStatements(db, 0);
}
}else if( xSFunc==0 && xFinal==0 ){
/* Trying to delete a function that does not exist. This is a no-op.
** https://sqlite.org/forum/forumpost/726219164b */
return SQLITE_OK;
}
p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 1);
@ -1957,7 +1981,7 @@ static int createFunctionApi(
xSFunc, xStep, xFinal, xValue, xInverse, pArg
);
if( pArg && pArg->nRef==0 ){
assert( rc!=SQLITE_OK );
assert( rc!=SQLITE_OK || (xStep==0 && xFinal==0) );
xDestroy(p);
sqlite3_free(pArg);
}
@ -2283,6 +2307,34 @@ void *sqlite3_preupdate_hook(
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
/*
** Register a function to be invoked prior to each autovacuum that
** determines the number of pages to vacuum.
*/
int sqlite3_autovacuum_pages(
sqlite3 *db, /* Attach the hook to this database */
unsigned int (*xCallback)(void*,const char*,u32,u32,u32),
void *pArg, /* Argument to the function */
void (*xDestructor)(void*) /* Destructor for pArg */
){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
if( xDestructor ) xDestructor(pArg);
return SQLITE_MISUSE_BKPT;
}
#endif
sqlite3_mutex_enter(db->mutex);
if( db->xAutovacDestr ){
db->xAutovacDestr(db->pAutovacPagesArg);
}
db->xAutovacPages = xCallback;
db->pAutovacPagesArg = pArg;
db->xAutovacDestr = xDestructor;
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
#ifndef SQLITE_OMIT_WAL
/*
** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint().
@ -2545,6 +2597,19 @@ const char *sqlite3_errmsg(sqlite3 *db){
return z;
}
/*
** Return the byte offset of the most recent error
*/
int sqlite3_error_offset(sqlite3 *db){
int iOffset = -1;
if( db && sqlite3SafetyCheckSickOrOk(db) && db->errCode ){
sqlite3_mutex_enter(db->mutex);
iOffset = db->errByteOffset;
sqlite3_mutex_leave(db->mutex);
}
return iOffset;
}
#ifndef SQLITE_OMIT_UTF16
/*
** Return UTF-16 encoded English language explanation of the most recent
@ -2805,6 +2870,8 @@ int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
if( newLimit>=0 ){ /* IMP: R-52476-28732 */
if( newLimit>aHardLimit[limitId] ){
newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */
}else if( newLimit<1 && limitId==SQLITE_LIMIT_LENGTH ){
newLimit = 1;
}
db->aLimit[limitId] = newLimit;
}
@ -3076,7 +3143,7 @@ int sqlite3ParseUri(
*/
static const char *uriParameter(const char *zFilename, const char *zParam){
zFilename += sqlite3Strlen30(zFilename) + 1;
while( zFilename[0] ){
while( ALWAYS(zFilename!=0) && zFilename[0] ){
int x = strcmp(zFilename, zParam);
zFilename += sqlite3Strlen30(zFilename) + 1;
if( x==0 ) return zFilename;
@ -3136,8 +3203,8 @@ static int openDatabase(
** dealt with in the previous code block. Besides these, the only
** valid input flags for sqlite3_open_v2() are SQLITE_OPEN_READONLY,
** SQLITE_OPEN_READWRITE, SQLITE_OPEN_CREATE, SQLITE_OPEN_SHAREDCACHE,
** SQLITE_OPEN_PRIVATECACHE, and some reserved bits. Silently mask
** off all other flags.
** SQLITE_OPEN_PRIVATECACHE, SQLITE_OPEN_EXRESCODE, and some reserved
** bits. Silently mask off all other flags.
*/
flags &= ~( SQLITE_OPEN_DELETEONCLOSE |
SQLITE_OPEN_EXCLUSIVE |
@ -3172,9 +3239,9 @@ static int openDatabase(
}
}
sqlite3_mutex_enter(db->mutex);
db->errMask = 0xff;
db->errMask = (flags & SQLITE_OPEN_EXRESCODE)!=0 ? 0xffffffff : 0xff;
db->nDb = 2;
db->magic = SQLITE_MAGIC_BUSY;
db->eOpenState = SQLITE_STATE_BUSY;
db->aDb = db->aDbStatic;
db->lookaside.bDisable = 1;
db->lookaside.sz = 0;
@ -3186,7 +3253,15 @@ static int openDatabase(
db->nextAutovac = -1;
db->szMmap = sqlite3GlobalConfig.szMmap;
db->nextPagesize = 0;
db->init.azInit = sqlite3StdType; /* Any array of string ptrs will do */
#ifdef SQLITE_ENABLE_SORTER_MMAP
/* Beginning with version 3.37.0, using the VFS xFetch() API to memory-map
** the temporary files used to do external sorts (see code in vdbesort.c)
** is disabled. It can still be used either by defining
** SQLITE_ENABLE_SORTER_MMAP at compile time or by using the
** SQLITE_TESTCTRL_SORTER_MMAP test-control at runtime. */
db->nMaxSorterMmap = 0x7FFFFFFF;
#endif
db->flags |= SQLITE_ShortColNames
| SQLITE_EnableTrigger
| SQLITE_EnableView
@ -3277,6 +3352,19 @@ static int openDatabase(
goto opendb_out;
}
#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL)
/* Process magic filenames ":localStorage:" and ":sessionStorage:" */
if( zFilename && zFilename[0]==':' ){
if( strcmp(zFilename, ":localStorage:")==0 ){
zFilename = "file:local?vfs=kvvfs";
flags |= SQLITE_OPEN_URI;
}else if( strcmp(zFilename, ":sessionStorage:")==0 ){
zFilename = "file:session?vfs=kvvfs";
flags |= SQLITE_OPEN_URI;
}
}
#endif /* SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL) */
/* Parse the filename/URI argument
**
** Only allow sensible combinations of bits in the flags argument.
@ -3307,6 +3395,12 @@ static int openDatabase(
sqlite3_free(zErrMsg);
goto opendb_out;
}
assert( db->pVfs!=0 );
#if SQLITE_OS_KV || defined(SQLITE_OS_KV_OPTIONAL)
if( sqlite3_stricmp(db->pVfs->zName, "kvvfs")==0 ){
db->temp_store = 2;
}
#endif
/* Open the backend database driver */
rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0,
@ -3334,7 +3428,7 @@ static int openDatabase(
db->aDb[1].zDbSName = "temp";
db->aDb[1].safety_level = PAGER_SYNCHRONOUS_OFF;
db->magic = SQLITE_MAGIC_OPEN;
db->eOpenState = SQLITE_STATE_OPEN;
if( db->mallocFailed ){
goto opendb_out;
}
@ -3396,12 +3490,12 @@ opendb_out:
sqlite3_mutex_leave(db->mutex);
}
rc = sqlite3_errcode(db);
assert( db!=0 || rc==SQLITE_NOMEM );
if( rc==SQLITE_NOMEM ){
assert( db!=0 || (rc&0xff)==SQLITE_NOMEM );
if( (rc&0xff)==SQLITE_NOMEM ){
sqlite3_close(db);
db = 0;
}else if( rc!=SQLITE_OK ){
db->magic = SQLITE_MAGIC_SICK;
db->eOpenState = SQLITE_STATE_SICK;
}
*ppDb = db;
#ifdef SQLITE_ENABLE_SQLLOG
@ -3412,7 +3506,7 @@ opendb_out:
}
#endif
sqlite3_free_filename(zOpen);
return rc & 0xff;
return rc;
}
@ -3712,7 +3806,7 @@ int sqlite3_table_column_metadata(
/* Locate the table in question */
pTab = sqlite3FindTable(db, zTableName, zDbName);
if( !pTab || pTab->pSelect ){
if( !pTab || IsView(pTab) ){
pTab = 0;
goto error_out;
}
@ -3723,7 +3817,7 @@ int sqlite3_table_column_metadata(
}else{
for(iCol=0; iCol<pTab->nCol; iCol++){
pCol = &pTab->aCol[iCol];
if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){
if( 0==sqlite3StrICmp(pCol->zCnName, zColumnName) ){
break;
}
}
@ -3750,7 +3844,7 @@ int sqlite3_table_column_metadata(
*/
if( pCol ){
zDataType = sqlite3ColumnType(pCol,0);
zCollSeq = pCol->zColl;
zCollSeq = sqlite3ColumnColl(pCol);
notnull = pCol->notNull!=0;
primarykey = (pCol->colFlags & COLFLAG_PRIMKEY)!=0;
autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0;
@ -3957,12 +4051,16 @@ int sqlite3_test_control(int op, ...){
** sqlite3_test_control().
*/
case SQLITE_TESTCTRL_FAULT_INSTALL: {
/* MSVC is picky about pulling func ptrs from va lists.
** http://support.microsoft.com/kb/47961
/* A bug in MSVC prevents it from understanding pointers to functions
** types in the second argument to va_arg(). Work around the problem
** using a typedef.
** http://support.microsoft.com/kb/47961 <-- dead hyperlink
** Search at http://web.archive.org/ to find the 2015-03-16 archive
** of the link above to see the original text.
** sqlite3GlobalConfig.xTestCallback = va_arg(ap, int(*)(int));
*/
typedef int(*TESTCALLBACKFUNC_t)(int);
sqlite3GlobalConfig.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t);
typedef int(*sqlite3FaultFuncType)(int);
sqlite3GlobalConfig.xTestCallback = va_arg(ap, sqlite3FaultFuncType);
rc = sqlite3FaultSim(0);
break;
}
@ -4021,6 +4119,28 @@ int sqlite3_test_control(int op, ...){
volatile int x = 0;
assert( /*side-effects-ok*/ (x = va_arg(ap,int))!=0 );
rc = x;
#if defined(SQLITE_DEBUG)
/* Invoke these debugging routines so that the compiler does not
** issue "defined but not used" warnings. */
if( x==9999 ){
sqlite3ShowExpr(0);
sqlite3ShowExpr(0);
sqlite3ShowExprList(0);
sqlite3ShowIdList(0);
sqlite3ShowSrcList(0);
sqlite3ShowWith(0);
sqlite3ShowUpsert(0);
sqlite3ShowTriggerStep(0);
sqlite3ShowTriggerStepList(0);
sqlite3ShowTrigger(0);
sqlite3ShowTriggerList(0);
#ifndef SQLITE_OMIT_WINDOWFUNC
sqlite3ShowWindow(0);
sqlite3ShowWinFunc(0);
#endif
sqlite3ShowSelect(0);
}
#endif
break;
}
@ -4089,13 +4209,27 @@ int sqlite3_test_control(int op, ...){
break;
}
/* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
/* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, onoff, xAlt);
**
** If parameter onoff is non-zero, subsequent calls to localtime()
** and its variants fail. If onoff is zero, undo this setting.
** If parameter onoff is 1, subsequent calls to localtime() fail.
** If 2, then invoke xAlt() instead of localtime(). If 0, normal
** processing.
**
** xAlt arguments are void pointers, but they really want to be:
**
** int xAlt(const time_t*, struct tm*);
**
** xAlt should write results in to struct tm object of its 2nd argument
** and return zero on success, or return non-zero on failure.
*/
case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int);
if( sqlite3GlobalConfig.bLocaltimeFault==2 ){
typedef int(*sqlite3LocaltimeType)(const void*,void*);
sqlite3GlobalConfig.xAltLocaltime = va_arg(ap, sqlite3LocaltimeType);
}else{
sqlite3GlobalConfig.xAltLocaltime = 0;
}
break;
}
@ -4200,12 +4334,16 @@ int sqlite3_test_control(int op, ...){
*/
case SQLITE_TESTCTRL_IMPOSTER: {
sqlite3 *db = va_arg(ap, sqlite3*);
int iDb;
sqlite3_mutex_enter(db->mutex);
db->init.iDb = sqlite3FindDbName(db, va_arg(ap,const char*));
db->init.busy = db->init.imposterTable = va_arg(ap,int);
db->init.newTnum = va_arg(ap,int);
if( db->init.busy==0 && db->init.newTnum>0 ){
sqlite3ResetAllSchemasOfConnection(db);
iDb = sqlite3FindDbName(db, va_arg(ap,const char*));
if( iDb>=0 ){
db->init.iDb = iDb;
db->init.busy = db->init.imposterTable = va_arg(ap,int);
db->init.newTnum = va_arg(ap,int);
if( db->init.busy==0 && db->init.newTnum>0 ){
sqlite3ResetAllSchemasOfConnection(db);
}
}
sqlite3_mutex_leave(db->mutex);
break;
@ -4264,8 +4402,8 @@ int sqlite3_test_control(int op, ...){
**
** "ptr" is a pointer to a u32.
**
** op==0 Store the current sqlite3SelectTrace in *ptr
** op==1 Set sqlite3SelectTrace to the value *ptr
** op==0 Store the current sqlite3TreeTrace in *ptr
** op==1 Set sqlite3TreeTrace to the value *ptr
** op==3 Store the current sqlite3WhereTrace in *ptr
** op==3 Set sqlite3WhereTrace to the value *ptr
*/
@ -4273,13 +4411,65 @@ int sqlite3_test_control(int op, ...){
int opTrace = va_arg(ap, int);
u32 *ptr = va_arg(ap, u32*);
switch( opTrace ){
case 0: *ptr = sqlite3SelectTrace; break;
case 1: sqlite3SelectTrace = *ptr; break;
case 2: *ptr = sqlite3WhereTrace; break;
case 3: sqlite3WhereTrace = *ptr; break;
case 0: *ptr = sqlite3TreeTrace; break;
case 1: sqlite3TreeTrace = *ptr; break;
case 2: *ptr = sqlite3WhereTrace; break;
case 3: sqlite3WhereTrace = *ptr; break;
}
break;
}
/* sqlite3_test_control(SQLITE_TESTCTRL_LOGEST,
** double fIn, // Input value
** int *pLogEst, // sqlite3LogEstFromDouble(fIn)
** u64 *pInt, // sqlite3LogEstToInt(*pLogEst)
** int *pLogEst2 // sqlite3LogEst(*pInt)
** );
**
** Test access for the LogEst conversion routines.
*/
case SQLITE_TESTCTRL_LOGEST: {
double rIn = va_arg(ap, double);
LogEst rLogEst = sqlite3LogEstFromDouble(rIn);
int *pI1 = va_arg(ap,int*);
u64 *pU64 = va_arg(ap,u64*);
int *pI2 = va_arg(ap,int*);
*pI1 = rLogEst;
*pU64 = sqlite3LogEstToInt(rLogEst);
*pI2 = sqlite3LogEst(*pU64);
break;
}
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD)
/* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue)
**
** If "id" is an integer between 1 and SQLITE_NTUNE then set the value
** of the id-th tuning parameter to *piValue. If "id" is between -1
** and -SQLITE_NTUNE, then write the current value of the (-id)-th
** tuning parameter into *piValue.
**
** Tuning parameters are for use during transient development builds,
** to help find the best values for constants in the query planner.
** Access tuning parameters using the Tuning(ID) macro. Set the
** parameters in the CLI using ".testctrl tune ID VALUE".
**
** Transient use only. Tuning parameters should not be used in
** checked-in code.
*/
case SQLITE_TESTCTRL_TUNE: {
int id = va_arg(ap, int);
int *piValue = va_arg(ap, int*);
if( id>0 && id<=SQLITE_NTUNE ){
Tuning(id) = *piValue;
}else if( id<0 && id>=-SQLITE_NTUNE ){
*piValue = Tuning(-id);
}else{
rc = SQLITE_NOTFOUND;
}
break;
}
#endif
}
va_end(ap);
#endif /* SQLITE_UNTESTABLE */
@ -4320,7 +4510,7 @@ static char *appendText(char *p, const char *z){
** Memory layout must be compatible with that generated by the pager
** and expected by sqlite3_uri_parameter() and databaseName().
*/
char *sqlite3_create_filename(
const char *sqlite3_create_filename(
const char *zDatabase,
const char *zJournal,
const char *zWal,
@ -4356,10 +4546,10 @@ char *sqlite3_create_filename(
** error to call this routine with any parameter other than a pointer
** previously obtained from sqlite3_create_filename() or a NULL pointer.
*/
void sqlite3_free_filename(char *p){
void sqlite3_free_filename(const char *p){
if( p==0 ) return;
p = (char*)databaseName(p);
sqlite3_free(p - 4);
p = databaseName(p);
sqlite3_free((char*)p - 4);
}
@ -4387,7 +4577,7 @@ const char *sqlite3_uri_key(const char *zFilename, int N){
if( zFilename==0 || N<0 ) return 0;
zFilename = databaseName(zFilename);
zFilename += sqlite3Strlen30(zFilename) + 1;
while( zFilename[0] && (N--)>0 ){
while( ALWAYS(zFilename) && zFilename[0] && (N--)>0 ){
zFilename += sqlite3Strlen30(zFilename) + 1;
zFilename += sqlite3Strlen30(zFilename) + 1;
}
@ -4430,12 +4620,14 @@ sqlite3_int64 sqlite3_uri_int64(
** corruption.
*/
const char *sqlite3_filename_database(const char *zFilename){
if( zFilename==0 ) return 0;
return databaseName(zFilename);
}
const char *sqlite3_filename_journal(const char *zFilename){
if( zFilename==0 ) return 0;
zFilename = databaseName(zFilename);
zFilename += sqlite3Strlen30(zFilename) + 1;
while( zFilename[0] ){
while( ALWAYS(zFilename) && zFilename[0] ){
zFilename += sqlite3Strlen30(zFilename) + 1;
zFilename += sqlite3Strlen30(zFilename) + 1;
}
@ -4446,7 +4638,7 @@ const char *sqlite3_filename_wal(const char *zFilename){
return 0;
#else
zFilename = sqlite3_filename_journal(zFilename);
zFilename += sqlite3Strlen30(zFilename) + 1;
if( zFilename ) zFilename += sqlite3Strlen30(zFilename) + 1;
return zFilename;
#endif
}
@ -4459,6 +4651,24 @@ Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
return iDb<0 ? 0 : db->aDb[iDb].pBt;
}
/*
** Return the name of the N-th database schema. Return NULL if N is out
** of range.
*/
const char *sqlite3_db_name(sqlite3 *db, int N){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
if( N<0 || N>=db->nDb ){
return 0;
}else{
return db->aDb[N].zDbSName;
}
}
/*
** Return the filename of the database associated with a database
** connection.
@ -4590,8 +4800,8 @@ int sqlite3_snapshot_open(
*/
int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){
int rc = SQLITE_ERROR;
int iDb;
#ifndef SQLITE_OMIT_WAL
int iDb;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){