Index: third_party/sqlite/src/src/main.c |
diff --git a/third_party/sqlite/src/src/main.c b/third_party/sqlite/src/src/main.c |
index 301808cdcec2cb8b50b64abecf74ab6b392d56d8..03e4f1b928457ba34dacc3ec5bdcae523e86f03d 100644 |
--- a/third_party/sqlite/src/src/main.c |
+++ b/third_party/sqlite/src/src/main.c |
@@ -187,7 +187,7 @@ int sqlite3_initialize(void){ |
sqlite3GlobalConfig.pInitMutex = |
sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); |
if( sqlite3GlobalConfig.bCoreMutex && !sqlite3GlobalConfig.pInitMutex ){ |
- rc = SQLITE_NOMEM; |
+ rc = SQLITE_NOMEM_BKPT; |
} |
} |
} |
@@ -218,7 +218,6 @@ int sqlite3_initialize(void){ |
*/ |
sqlite3_mutex_enter(sqlite3GlobalConfig.pInitMutex); |
if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){ |
- FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); |
sqlite3GlobalConfig.inProgress = 1; |
#ifdef SQLITE_ENABLE_SQLLOG |
{ |
@@ -226,8 +225,8 @@ int sqlite3_initialize(void){ |
sqlite3_init_sqllog(); |
} |
#endif |
- memset(pHash, 0, sizeof(sqlite3GlobalFunctions)); |
- sqlite3RegisterGlobalFunctions(); |
+ memset(&sqlite3BuiltinFunctions, 0, sizeof(sqlite3BuiltinFunctions)); |
+ sqlite3RegisterBuiltinFunctions(); |
if( sqlite3GlobalConfig.isPCacheInit==0 ){ |
rc = sqlite3PcacheInitialize(); |
} |
@@ -634,6 +633,11 @@ int sqlite3_config(int op, ...){ |
break; |
} |
+ case SQLITE_CONFIG_STMTJRNL_SPILL: { |
+ sqlite3GlobalConfig.nStmtSpill = va_arg(ap, int); |
+ break; |
+ } |
+ |
default: { |
rc = SQLITE_ERROR; |
break; |
@@ -698,12 +702,12 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ |
p = (LookasideSlot*)&((u8*)p)[sz]; |
} |
db->lookaside.pEnd = p; |
- db->lookaside.bEnabled = 1; |
+ db->lookaside.bDisable = 0; |
db->lookaside.bMalloced = pBuf==0 ?1:0; |
}else{ |
db->lookaside.pStart = db; |
db->lookaside.pEnd = db; |
- db->lookaside.bEnabled = 0; |
+ db->lookaside.bDisable = 1; |
db->lookaside.bMalloced = 0; |
} |
#endif /* SQLITE_OMIT_LOOKASIDE */ |
@@ -785,6 +789,11 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){ |
int rc; |
va_start(ap, op); |
switch( op ){ |
+ case SQLITE_DBCONFIG_MAINDBNAME: { |
+ db->aDb[0].zDbSName = va_arg(ap,char*); |
+ rc = SQLITE_OK; |
+ break; |
+ } |
case SQLITE_DBCONFIG_LOOKASIDE: { |
void *pBuf = va_arg(ap, void*); /* IMP: R-26835-10964 */ |
int sz = va_arg(ap, int); /* IMP: R-47871-25994 */ |
@@ -797,8 +806,11 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){ |
int op; /* The opcode */ |
u32 mask; /* Mask of the bit in sqlite3.flags to set/clear */ |
} aFlagOp[] = { |
- { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, |
- { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, |
+ { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, |
+ { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, |
+ { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, |
+ { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, |
+ { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose }, |
}; |
unsigned int i; |
rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ |
@@ -958,7 +970,7 @@ void sqlite3CloseSavepoints(sqlite3 *db){ |
** with SQLITE_ANY as the encoding. |
*/ |
static void functionDestroy(sqlite3 *db, FuncDef *p){ |
- FuncDestructor *pDestructor = p->pDestructor; |
+ FuncDestructor *pDestructor = p->u.pDestructor; |
if( pDestructor ){ |
pDestructor->nRef--; |
if( pDestructor->nRef==0 ){ |
@@ -1027,6 +1039,9 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){ |
return SQLITE_MISUSE_BKPT; |
} |
sqlite3_mutex_enter(db->mutex); |
+ if( db->mTrace & SQLITE_TRACE_CLOSE ){ |
+ db->xTrace(SQLITE_TRACE_CLOSE, db->pTraceArg, db, 0); |
+ } |
/* Force xDisconnect calls on all virtual tables */ |
disconnectAllVtab(db); |
@@ -1140,18 +1155,17 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ |
*/ |
sqlite3ConnectionClosed(db); |
- for(j=0; j<ArraySize(db->aFunc.a); j++){ |
- FuncDef *pNext, *pHash, *p; |
- for(p=db->aFunc.a[j]; p; p=pHash){ |
- pHash = p->pHash; |
- while( p ){ |
- functionDestroy(db, p); |
- pNext = p->pNext; |
- sqlite3DbFree(db, p); |
- p = pNext; |
- } |
- } |
- } |
+ for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){ |
+ FuncDef *pNext, *p; |
+ p = sqliteHashData(i); |
+ do{ |
+ functionDestroy(db, p); |
+ pNext = p->pNext; |
+ sqlite3DbFree(db, p); |
+ p = pNext; |
+ }while( p ); |
+ } |
+ sqlite3HashClear(&db->aFunc); |
for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){ |
CollSeq *pColl = (CollSeq *)sqliteHashData(i); |
/* Invoke any destructors registered for collation sequence user data. */ |
@@ -1554,7 +1568,7 @@ int sqlite3_busy_timeout(sqlite3 *db, int ms){ |
*/ |
void sqlite3_interrupt(sqlite3 *db){ |
#ifdef SQLITE_ENABLE_API_ARMOR |
- if( !sqlite3SafetyCheckOk(db) ){ |
+ if( !sqlite3SafetyCheckOk(db) && (db==0 || db->magic!=SQLITE_MAGIC_ZOMBIE) ){ |
(void)SQLITE_MISUSE_BKPT; |
return; |
} |
@@ -1575,7 +1589,7 @@ int sqlite3CreateFunc( |
int nArg, |
int enc, |
void *pUserData, |
- void (*xFunc)(sqlite3_context*,int,sqlite3_value **), |
+ void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), |
void (*xStep)(sqlite3_context*,int,sqlite3_value **), |
void (*xFinal)(sqlite3_context*), |
FuncDestructor *pDestructor |
@@ -1586,9 +1600,9 @@ int sqlite3CreateFunc( |
assert( sqlite3_mutex_held(db->mutex) ); |
if( zFunctionName==0 || |
- (xFunc && (xFinal || xStep)) || |
- (!xFunc && (xFinal && !xStep)) || |
- (!xFunc && (!xFinal && xStep)) || |
+ (xSFunc && (xFinal || xStep)) || |
+ (!xSFunc && (xFinal && !xStep)) || |
+ (!xSFunc && (!xFinal && xStep)) || |
(nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) || |
(255<(nName = sqlite3Strlen30( zFunctionName))) ){ |
return SQLITE_MISUSE_BKPT; |
@@ -1611,10 +1625,10 @@ int sqlite3CreateFunc( |
}else if( enc==SQLITE_ANY ){ |
int rc; |
rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8|extraFlags, |
- pUserData, xFunc, xStep, xFinal, pDestructor); |
+ pUserData, xSFunc, xStep, xFinal, pDestructor); |
if( rc==SQLITE_OK ){ |
rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE|extraFlags, |
- pUserData, xFunc, xStep, xFinal, pDestructor); |
+ pUserData, xSFunc, xStep, xFinal, pDestructor); |
} |
if( rc!=SQLITE_OK ){ |
return rc; |
@@ -1630,7 +1644,7 @@ int sqlite3CreateFunc( |
** is being overridden/deleted but there are no active VMs, allow the |
** operation to continue but invalidate all precompiled statements. |
*/ |
- p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 0); |
+ p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 0); |
if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==enc && p->nArg==nArg ){ |
if( db->nVdbeActive ){ |
sqlite3ErrorWithMsg(db, SQLITE_BUSY, |
@@ -1642,10 +1656,10 @@ int sqlite3CreateFunc( |
} |
} |
- p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 1); |
+ p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 1); |
assert(p || db->mallocFailed); |
if( !p ){ |
- return SQLITE_NOMEM; |
+ return SQLITE_NOMEM_BKPT; |
} |
/* If an older version of the function with a configured destructor is |
@@ -1655,11 +1669,10 @@ int sqlite3CreateFunc( |
if( pDestructor ){ |
pDestructor->nRef++; |
} |
- p->pDestructor = pDestructor; |
+ p->u.pDestructor = pDestructor; |
p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags; |
testcase( p->funcFlags & SQLITE_DETERMINISTIC ); |
- p->xFunc = xFunc; |
- p->xStep = xStep; |
+ p->xSFunc = xSFunc ? xSFunc : xStep; |
p->xFinalize = xFinal; |
p->pUserData = pUserData; |
p->nArg = (u16)nArg; |
@@ -1675,11 +1688,11 @@ int sqlite3_create_function( |
int nArg, |
int enc, |
void *p, |
- void (*xFunc)(sqlite3_context*,int,sqlite3_value **), |
+ void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), |
void (*xStep)(sqlite3_context*,int,sqlite3_value **), |
void (*xFinal)(sqlite3_context*) |
){ |
- return sqlite3_create_function_v2(db, zFunc, nArg, enc, p, xFunc, xStep, |
+ return sqlite3_create_function_v2(db, zFunc, nArg, enc, p, xSFunc, xStep, |
xFinal, 0); |
} |
@@ -1689,7 +1702,7 @@ int sqlite3_create_function_v2( |
int nArg, |
int enc, |
void *p, |
- void (*xFunc)(sqlite3_context*,int,sqlite3_value **), |
+ void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), |
void (*xStep)(sqlite3_context*,int,sqlite3_value **), |
void (*xFinal)(sqlite3_context*), |
void (*xDestroy)(void *) |
@@ -1712,7 +1725,7 @@ int sqlite3_create_function_v2( |
pArg->xDestroy = xDestroy; |
pArg->pUserData = p; |
} |
- rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, xFunc, xStep, xFinal, pArg); |
+ rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, xSFunc, xStep, xFinal, pArg); |
if( pArg && pArg->nRef==0 ){ |
assert( rc!=SQLITE_OK ); |
xDestroy(p); |
@@ -1732,7 +1745,7 @@ int sqlite3_create_function16( |
int nArg, |
int eTextRep, |
void *p, |
- void (*xFunc)(sqlite3_context*,int,sqlite3_value**), |
+ void (*xSFunc)(sqlite3_context*,int,sqlite3_value**), |
void (*xStep)(sqlite3_context*,int,sqlite3_value**), |
void (*xFinal)(sqlite3_context*) |
){ |
@@ -1745,7 +1758,7 @@ int sqlite3_create_function16( |
sqlite3_mutex_enter(db->mutex); |
assert( !db->mallocFailed ); |
zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE); |
- rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal,0); |
+ rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xSFunc,xStep,xFinal,0); |
sqlite3DbFree(db, zFunc8); |
rc = sqlite3ApiExit(db, rc); |
sqlite3_mutex_leave(db->mutex); |
@@ -1771,7 +1784,6 @@ int sqlite3_overload_function( |
const char *zName, |
int nArg |
){ |
- int nName = sqlite3Strlen30(zName); |
int rc = SQLITE_OK; |
#ifdef SQLITE_ENABLE_API_ARMOR |
@@ -1780,7 +1792,7 @@ int sqlite3_overload_function( |
} |
#endif |
sqlite3_mutex_enter(db->mutex); |
- if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){ |
+ if( sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)==0 ){ |
rc = sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8, |
0, sqlite3InvalidFunction, 0, 0, 0); |
} |
@@ -1798,7 +1810,8 @@ int sqlite3_overload_function( |
** trace is a pointer to a function that is invoked at the start of each |
** SQL statement. |
*/ |
-void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){ |
+#ifndef SQLITE_OMIT_DEPRECATED |
+void *sqlite3_trace(sqlite3 *db, void(*xTrace)(void*,const char*), void *pArg){ |
void *pOld; |
#ifdef SQLITE_ENABLE_API_ARMOR |
@@ -1809,11 +1822,38 @@ void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){ |
#endif |
sqlite3_mutex_enter(db->mutex); |
pOld = db->pTraceArg; |
- db->xTrace = xTrace; |
+ db->mTrace = xTrace ? SQLITE_TRACE_LEGACY : 0; |
+ db->xTrace = (int(*)(u32,void*,void*,void*))xTrace; |
db->pTraceArg = pArg; |
sqlite3_mutex_leave(db->mutex); |
return pOld; |
} |
+#endif /* SQLITE_OMIT_DEPRECATED */ |
+ |
+/* Register a trace callback using the version-2 interface. |
+*/ |
+int sqlite3_trace_v2( |
+ sqlite3 *db, /* Trace this connection */ |
+ unsigned mTrace, /* Mask of events to be traced */ |
+ int(*xTrace)(unsigned,void*,void*,void*), /* Callback to invoke */ |
+ void *pArg /* Context */ |
+){ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ return SQLITE_MISUSE_BKPT; |
+ } |
+#endif |
+ sqlite3_mutex_enter(db->mutex); |
+ if( mTrace==0 ) xTrace = 0; |
+ if( xTrace==0 ) mTrace = 0; |
+ db->mTrace = mTrace; |
+ db->xTrace = xTrace; |
+ db->pTraceArg = pArg; |
+ sqlite3_mutex_leave(db->mutex); |
+ return SQLITE_OK; |
+} |
+ |
+#ifndef SQLITE_OMIT_DEPRECATED |
/* |
** Register a profile function. The pArg from the previously registered |
** profile function is returned. |
@@ -1842,6 +1882,7 @@ void *sqlite3_profile( |
sqlite3_mutex_leave(db->mutex); |
return pOld; |
} |
+#endif /* SQLITE_OMIT_DEPRECATED */ |
#endif /* SQLITE_OMIT_TRACE */ |
/* |
@@ -1920,6 +1961,27 @@ void *sqlite3_rollback_hook( |
return pRet; |
} |
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
+/* |
+** Register a callback to be invoked each time a row is updated, |
+** inserted or deleted using this database connection. |
+*/ |
+void *sqlite3_preupdate_hook( |
+ sqlite3 *db, /* Attach the hook to this database */ |
+ void(*xCallback)( /* Callback function */ |
+ void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64), |
+ void *pArg /* First callback argument */ |
+){ |
+ void *pRet; |
+ sqlite3_mutex_enter(db->mutex); |
+ pRet = db->pPreUpdateArg; |
+ db->xPreUpdateCallback = xCallback; |
+ db->pPreUpdateArg = pArg; |
+ sqlite3_mutex_leave(db->mutex); |
+ return pRet; |
+} |
+#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ |
+ |
#ifndef SQLITE_OMIT_WAL |
/* |
** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint(). |
@@ -2045,6 +2107,13 @@ int sqlite3_wal_checkpoint_v2( |
sqlite3Error(db, rc); |
} |
rc = sqlite3ApiExit(db, rc); |
+ |
+ /* If there are no active statements, clear the interrupt flag at this |
+ ** point. */ |
+ if( db->nVdbeActive==0 ){ |
+ db->u1.isInterrupted = 0; |
+ } |
+ |
sqlite3_mutex_leave(db->mutex); |
return rc; |
#endif |
@@ -2150,14 +2219,14 @@ int sqlite3TempInMemory(const sqlite3 *db){ |
const char *sqlite3_errmsg(sqlite3 *db){ |
const char *z; |
if( !db ){ |
- return sqlite3ErrStr(SQLITE_NOMEM); |
+ return sqlite3ErrStr(SQLITE_NOMEM_BKPT); |
} |
if( !sqlite3SafetyCheckSickOrOk(db) ){ |
return sqlite3ErrStr(SQLITE_MISUSE_BKPT); |
} |
sqlite3_mutex_enter(db->mutex); |
if( db->mallocFailed ){ |
- z = sqlite3ErrStr(SQLITE_NOMEM); |
+ z = sqlite3ErrStr(SQLITE_NOMEM_BKPT); |
}else{ |
testcase( db->pErr==0 ); |
z = (char*)sqlite3_value_text(db->pErr); |
@@ -2209,7 +2278,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){ |
** be cleared before returning. Do this directly, instead of via |
** sqlite3ApiExit(), to avoid setting the database handle error message. |
*/ |
- db->mallocFailed = 0; |
+ sqlite3OomClear(db); |
} |
sqlite3_mutex_leave(db->mutex); |
return z; |
@@ -2225,7 +2294,7 @@ int sqlite3_errcode(sqlite3 *db){ |
return SQLITE_MISUSE_BKPT; |
} |
if( !db || db->mallocFailed ){ |
- return SQLITE_NOMEM; |
+ return SQLITE_NOMEM_BKPT; |
} |
return db->errCode & db->errMask; |
} |
@@ -2234,10 +2303,13 @@ int sqlite3_extended_errcode(sqlite3 *db){ |
return SQLITE_MISUSE_BKPT; |
} |
if( !db || db->mallocFailed ){ |
- return SQLITE_NOMEM; |
+ return SQLITE_NOMEM_BKPT; |
} |
return db->errCode; |
} |
+int sqlite3_system_errno(sqlite3 *db){ |
+ return db ? db->iSysErrno : 0; |
+} |
/* |
** Return a string that describes the kind of error specified in the |
@@ -2314,7 +2386,7 @@ static int createCollation( |
} |
pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 1); |
- if( pColl==0 ) return SQLITE_NOMEM; |
+ if( pColl==0 ) return SQLITE_NOMEM_BKPT; |
pColl->xCmp = xCompare; |
pColl->pUser = pCtx; |
pColl->xDel = xDel; |
@@ -2362,8 +2434,8 @@ static const int aHardLimit[] = { |
#if SQLITE_MAX_VDBE_OP<40 |
# error SQLITE_MAX_VDBE_OP must be at least 40 |
#endif |
-#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>1000 |
-# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 1000 |
+#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>127 |
+# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 127 |
#endif |
#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>125 |
# error SQLITE_MAX_ATTACHED must be between 0 and 125 |
@@ -2493,7 +2565,7 @@ int sqlite3ParseUri( |
for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&'); |
zFile = sqlite3_malloc64(nByte); |
- if( !zFile ) return SQLITE_NOMEM; |
+ if( !zFile ) return SQLITE_NOMEM_BKPT; |
iIn = 5; |
#ifdef SQLITE_ALLOW_URI_AUTHORITY |
@@ -2544,6 +2616,7 @@ int sqlite3ParseUri( |
assert( octet>=0 && octet<256 ); |
if( octet==0 ){ |
+#ifndef SQLITE_ENABLE_URI_00_ERROR |
/* This branch is taken when "%00" appears within the URI. In this |
** case we ignore all text in the remainder of the path, name or |
** value currently being parsed. So ignore the current character |
@@ -2556,6 +2629,12 @@ int sqlite3ParseUri( |
iIn++; |
} |
continue; |
+#else |
+ /* If ENABLE_URI_00_ERROR is defined, "%00" in a URI is an error. */ |
+ *pzErrMsg = sqlite3_mprintf("unexpected %%00 in uri"); |
+ rc = SQLITE_ERROR; |
+ goto parse_uri_out; |
+#endif |
} |
c = octet; |
}else if( eState==1 && (c=='&' || c=='=') ){ |
@@ -2659,8 +2738,10 @@ int sqlite3ParseUri( |
}else{ |
zFile = sqlite3_malloc64(nUri+2); |
- if( !zFile ) return SQLITE_NOMEM; |
- memcpy(zFile, zUri, nUri); |
+ if( !zFile ) return SQLITE_NOMEM_BKPT; |
+ if( nUri ){ |
+ memcpy(zFile, zUri, nUri); |
+ } |
zFile[nUri] = '\0'; |
zFile[nUri+1] = '\0'; |
flags &= ~SQLITE_OPEN_URI; |
@@ -2816,6 +2897,9 @@ static int openDatabase( |
#if defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK) |
| SQLITE_CellSizeCk |
#endif |
+#if defined(SQLITE_ENABLE_FTS3_TOKENIZER) |
+ | SQLITE_Fts3Tokenizer |
+#endif |
; |
sqlite3HashInit(&db->aCollSeq); |
#ifndef SQLITE_OMIT_VIRTUALTABLE |
@@ -2847,7 +2931,7 @@ static int openDatabase( |
db->openFlags = flags; |
rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg); |
if( rc!=SQLITE_OK ){ |
- if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; |
+ if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); |
sqlite3ErrorWithMsg(db, rc, zErrMsg ? "%s" : 0, zErrMsg); |
sqlite3_free(zErrMsg); |
goto opendb_out; |
@@ -2858,7 +2942,7 @@ static int openDatabase( |
flags | SQLITE_OPEN_MAIN_DB); |
if( rc!=SQLITE_OK ){ |
if( rc==SQLITE_IOERR_NOMEM ){ |
- rc = SQLITE_NOMEM; |
+ rc = SQLITE_NOMEM_BKPT; |
} |
sqlite3Error(db, rc); |
goto opendb_out; |
@@ -2869,13 +2953,13 @@ static int openDatabase( |
sqlite3BtreeLeave(db->aDb[0].pBt); |
db->aDb[1].pSchema = sqlite3SchemaGet(db, 0); |
- /* The default safety_level for the main database is 'full'; for the temp |
- ** database it is 'NONE'. This matches the pager layer defaults. |
+ /* The default safety_level for the main database is FULL; for the temp |
+ ** database it is OFF. This matches the pager layer defaults. |
*/ |
- db->aDb[0].zName = "main"; |
- db->aDb[0].safety_level = 3; |
- db->aDb[1].zName = "temp"; |
- db->aDb[1].safety_level = 1; |
+ db->aDb[0].zDbSName = "main"; |
+ db->aDb[0].safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; |
+ db->aDb[1].zDbSName = "temp"; |
+ db->aDb[1].safety_level = PAGER_SYNCHRONOUS_OFF; |
db->magic = SQLITE_MAGIC_OPEN; |
if( db->mallocFailed ){ |
@@ -2887,12 +2971,21 @@ static int openDatabase( |
** is accessed. |
*/ |
sqlite3Error(db, SQLITE_OK); |
- sqlite3RegisterBuiltinFunctions(db); |
+ sqlite3RegisterPerConnectionBuiltinFunctions(db); |
+ rc = sqlite3_errcode(db); |
+ |
+#ifdef SQLITE_ENABLE_FTS5 |
+ /* Register any built-in FTS5 module before loading the automatic |
+ ** extensions. This allows automatic extensions to register FTS5 |
+ ** tokenizers and auxiliary functions. */ |
+ if( !db->mallocFailed && rc==SQLITE_OK ){ |
+ rc = sqlite3Fts5Init(db); |
+ } |
+#endif |
/* Load automatic extensions - extensions that have been registered |
** using the sqlite3_automatic_extension() API. |
*/ |
- rc = sqlite3_errcode(db); |
if( rc==SQLITE_OK ){ |
sqlite3AutoLoadExtensions(db); |
rc = sqlite3_errcode(db); |
@@ -2921,12 +3014,6 @@ static int openDatabase( |
} |
#endif |
-#ifdef SQLITE_ENABLE_FTS5 |
- if( !db->mallocFailed && rc==SQLITE_OK ){ |
- rc = sqlite3Fts5Init(db); |
- } |
-#endif |
- |
#ifdef DEFAULT_ENABLE_RECOVER |
/* Initialize recover virtual table for testing. */ |
extern int recoverVtableInit(sqlite3 *db); |
@@ -3069,7 +3156,7 @@ int sqlite3_open16( |
SCHEMA_ENC(*ppDb) = ENC(*ppDb) = SQLITE_UTF16NATIVE; |
} |
}else{ |
- rc = SQLITE_NOMEM; |
+ rc = SQLITE_NOMEM_BKPT; |
} |
sqlite3ValueFree(pVal); |
@@ -3214,7 +3301,7 @@ int sqlite3_get_autocommit(sqlite3 *db){ |
/* |
** The following routines are substitutes for constants SQLITE_CORRUPT, |
-** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_IOERR and possibly other error |
+** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_NOMEM and possibly other error |
** constants. They serve two purposes: |
** |
** 1. Serve as a convenient place to set a breakpoint in a debugger |
@@ -3223,28 +3310,33 @@ int sqlite3_get_autocommit(sqlite3 *db){ |
** 2. Invoke sqlite3_log() to provide the source code location where |
** a low-level error is first detected. |
*/ |
+static int reportError(int iErr, int lineno, const char *zType){ |
+ sqlite3_log(iErr, "%s at line %d of [%.10s]", |
+ zType, lineno, 20+sqlite3_sourceid()); |
+ return iErr; |
+} |
int sqlite3CorruptError(int lineno){ |
testcase( sqlite3GlobalConfig.xLog!=0 ); |
- sqlite3_log(SQLITE_CORRUPT, |
- "database corruption at line %d of [%.10s]", |
- lineno, 20+sqlite3_sourceid()); |
- return SQLITE_CORRUPT; |
+ return reportError(SQLITE_CORRUPT, lineno, "database corruption"); |
} |
int sqlite3MisuseError(int lineno){ |
testcase( sqlite3GlobalConfig.xLog!=0 ); |
- sqlite3_log(SQLITE_MISUSE, |
- "misuse at line %d of [%.10s]", |
- lineno, 20+sqlite3_sourceid()); |
- return SQLITE_MISUSE; |
+ return reportError(SQLITE_MISUSE, lineno, "misuse"); |
} |
int sqlite3CantopenError(int lineno){ |
testcase( sqlite3GlobalConfig.xLog!=0 ); |
- sqlite3_log(SQLITE_CANTOPEN, |
- "cannot open file at line %d of [%.10s]", |
- lineno, 20+sqlite3_sourceid()); |
- return SQLITE_CANTOPEN; |
+ return reportError(SQLITE_CANTOPEN, lineno, "cannot open file"); |
} |
- |
+#ifdef SQLITE_DEBUG |
+int sqlite3NomemError(int lineno){ |
+ testcase( sqlite3GlobalConfig.xLog!=0 ); |
+ return reportError(SQLITE_NOMEM, lineno, "OOM"); |
+} |
+int sqlite3IoerrnomemError(int lineno){ |
+ testcase( sqlite3GlobalConfig.xLog!=0 ); |
+ return reportError(SQLITE_IOERR_NOMEM, lineno, "I/O OOM error"); |
+} |
+#endif |
#ifndef SQLITE_OMIT_DEPRECATED |
/* |
@@ -3338,7 +3430,7 @@ int sqlite3_table_column_metadata( |
** explicitly declared column. Copy meta information from *pCol. |
*/ |
if( pCol ){ |
- zDataType = pCol->zType; |
+ zDataType = sqlite3ColumnType(pCol,0); |
zCollSeq = pCol->zColl; |
notnull = pCol->notNull!=0; |
primarykey = (pCol->colFlags & COLFLAG_PRIMKEY)!=0; |
@@ -3451,7 +3543,7 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ |
*/ |
int sqlite3_test_control(int op, ...){ |
int rc = 0; |
-#ifdef SQLITE_OMIT_BUILTIN_TEST |
+#ifdef SQLITE_UNTESTABLE |
UNUSED_PARAMETER(op); |
#else |
va_list ap; |
@@ -3575,7 +3667,7 @@ int sqlite3_test_control(int op, ...){ |
*/ |
case SQLITE_TESTCTRL_ASSERT: { |
volatile int x = 0; |
- assert( (x = va_arg(ap,int))!=0 ); |
+ assert( /*side-effects-ok*/ (x = va_arg(ap,int))!=0 ); |
rc = x; |
break; |
} |
@@ -3717,6 +3809,15 @@ int sqlite3_test_control(int op, ...){ |
break; |
} |
+ /* Set the threshold at which OP_Once counters reset back to zero. |
+ ** By default this is 0x7ffffffe (over 2 billion), but that value is |
+ ** too big to test in a reasonable amount of time, so this control is |
+ ** provided to set a small and easily reachable reset value. |
+ */ |
+ case SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD: { |
+ sqlite3GlobalConfig.iOnceResetThreshold = va_arg(ap, int); |
+ break; |
+ } |
/* sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE, xCallback, ptr); |
** |
@@ -3779,7 +3880,7 @@ int sqlite3_test_control(int op, ...){ |
} |
} |
va_end(ap); |
-#endif /* SQLITE_OMIT_BUILTIN_TEST */ |
+#endif /* SQLITE_UNTESTABLE */ |
return rc; |
} |
@@ -3835,15 +3936,8 @@ sqlite3_int64 sqlite3_uri_int64( |
** Return the Btree pointer identified by zDbName. Return NULL if not found. |
*/ |
Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){ |
- int i; |
- for(i=0; i<db->nDb; i++){ |
- if( db->aDb[i].pBt |
- && (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zName)==0) |
- ){ |
- return db->aDb[i].pBt; |
- } |
- } |
- return 0; |
+ int iDb = zDbName ? sqlite3FindDbName(db, zDbName) : 0; |
+ return iDb<0 ? 0 : db->aDb[iDb].pBt; |
} |
/* |
@@ -3890,7 +3984,6 @@ int sqlite3_snapshot_get( |
){ |
int rc = SQLITE_ERROR; |
#ifndef SQLITE_OMIT_WAL |
- int iDb; |
#ifdef SQLITE_ENABLE_API_ARMOR |
if( !sqlite3SafetyCheckOk(db) ){ |
@@ -3899,13 +3992,15 @@ int sqlite3_snapshot_get( |
#endif |
sqlite3_mutex_enter(db->mutex); |
- iDb = sqlite3FindDbName(db, zDb); |
- if( iDb==0 || iDb>1 ){ |
- Btree *pBt = db->aDb[iDb].pBt; |
- if( 0==sqlite3BtreeIsInTrans(pBt) ){ |
- rc = sqlite3BtreeBeginTrans(pBt, 0); |
- if( rc==SQLITE_OK ){ |
- rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot); |
+ if( db->autoCommit==0 ){ |
+ int iDb = sqlite3FindDbName(db, zDb); |
+ if( iDb==0 || iDb>1 ){ |
+ Btree *pBt = db->aDb[iDb].pBt; |
+ if( 0==sqlite3BtreeIsInTrans(pBt) ){ |
+ rc = sqlite3BtreeBeginTrans(pBt, 0); |
+ if( rc==SQLITE_OK ){ |
+ rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot); |
+ } |
} |
} |
} |
@@ -3953,6 +4048,38 @@ int sqlite3_snapshot_open( |
} |
/* |
+** Recover as many snapshots as possible from the wal file associated with |
+** schema zDb of database db. |
+*/ |
+int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){ |
+ int rc = SQLITE_ERROR; |
+ int iDb; |
+#ifndef SQLITE_OMIT_WAL |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ return SQLITE_MISUSE_BKPT; |
+ } |
+#endif |
+ |
+ sqlite3_mutex_enter(db->mutex); |
+ iDb = sqlite3FindDbName(db, zDb); |
+ if( iDb==0 || iDb>1 ){ |
+ Btree *pBt = db->aDb[iDb].pBt; |
+ if( 0==sqlite3BtreeIsInReadTrans(pBt) ){ |
+ rc = sqlite3BtreeBeginTrans(pBt, 0); |
+ if( rc==SQLITE_OK ){ |
+ rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt)); |
+ sqlite3BtreeCommit(pBt); |
+ } |
+ } |
+ } |
+ sqlite3_mutex_leave(db->mutex); |
+#endif /* SQLITE_OMIT_WAL */ |
+ return rc; |
+} |
+ |
+/* |
** Free a snapshot handle obtained from sqlite3_snapshot_get(). |
*/ |
void sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){ |