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 d15ab9bba11209516be4110a6fd542906939c3bc..301808cdcec2cb8b50b64abecf74ab6b392d56d8 100644 |
--- a/third_party/sqlite/src/src/main.c |
+++ b/third_party/sqlite/src/src/main.c |
@@ -25,6 +25,12 @@ |
#ifdef SQLITE_ENABLE_ICU |
# include "sqliteicu.h" |
#endif |
+#ifdef SQLITE_ENABLE_JSON1 |
+int sqlite3Json1Init(sqlite3*); |
+#endif |
+#ifdef SQLITE_ENABLE_FTS5 |
+int sqlite3Fts5Init(sqlite3*); |
+#endif |
#ifndef SQLITE_AMALGAMATION |
/* IMPLEMENTATION-OF: R-46656-45156 The sqlite3_version[] string constant |
@@ -55,6 +61,18 @@ int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } |
*/ |
int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } |
+/* |
+** When compiling the test fixture or with debugging enabled (on Win32), |
+** this variable being set to non-zero will cause OSTRACE macros to emit |
+** extra diagnostic information. |
+*/ |
+#ifdef SQLITE_HAVE_OS_TRACE |
+# ifndef SQLITE_DEBUG_OS_TRACE |
+# define SQLITE_DEBUG_OS_TRACE 0 |
+# endif |
+ int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE; |
+#endif |
+ |
#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) |
/* |
** If the following function pointer is not NULL and if |
@@ -62,7 +80,7 @@ int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } |
** I/O active are written using this function. These messages |
** are intended for debugging activity only. |
*/ |
-void (*sqlite3IoTrace)(const char*, ...) = 0; |
+SQLITE_API void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...) = 0; |
#endif |
/* |
@@ -128,6 +146,11 @@ int sqlite3_initialize(void){ |
} |
#endif |
+ /* If the following assert() fails on some obscure processor/compiler |
+ ** combination, the work-around is to set the correct pointer |
+ ** size at compile-time using -DSQLITE_PTRSIZE=n compile-time option */ |
+ assert( SQLITE_PTRSIZE==sizeof(char*) ); |
+ |
/* If SQLite is already completely initialized, then this call |
** to sqlite3_initialize() should be a no-op. But the initialization |
** must be complete. So isInit must not be set until the very end |
@@ -197,6 +220,12 @@ int sqlite3_initialize(void){ |
if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){ |
FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); |
sqlite3GlobalConfig.inProgress = 1; |
+#ifdef SQLITE_ENABLE_SQLLOG |
+ { |
+ extern void sqlite3_init_sqllog(void); |
+ sqlite3_init_sqllog(); |
+ } |
+#endif |
memset(pHash, 0, sizeof(sqlite3GlobalFunctions)); |
sqlite3RegisterGlobalFunctions(); |
if( sqlite3GlobalConfig.isPCacheInit==0 ){ |
@@ -271,6 +300,13 @@ int sqlite3_initialize(void){ |
** when this routine is invoked, then this routine is a harmless no-op. |
*/ |
int sqlite3_shutdown(void){ |
+#ifdef SQLITE_OMIT_WSD |
+ int rc = sqlite3_wsd_init(4096, 24); |
+ if( rc!=SQLITE_OK ){ |
+ return rc; |
+ } |
+#endif |
+ |
if( sqlite3GlobalConfig.isInit ){ |
#ifdef SQLITE_EXTRA_SHUTDOWN |
void SQLITE_EXTRA_SHUTDOWN(void); |
@@ -329,33 +365,43 @@ int sqlite3_config(int op, ...){ |
switch( op ){ |
/* Mutex configuration options are only available in a threadsafe |
- ** compile. |
+ ** compile. |
*/ |
-#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 |
+#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-54466-46756 */ |
case SQLITE_CONFIG_SINGLETHREAD: { |
- /* Disable all mutexing */ |
- sqlite3GlobalConfig.bCoreMutex = 0; |
- sqlite3GlobalConfig.bFullMutex = 0; |
+ /* EVIDENCE-OF: R-02748-19096 This option sets the threading mode to |
+ ** Single-thread. */ |
+ sqlite3GlobalConfig.bCoreMutex = 0; /* Disable mutex on core */ |
+ sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */ |
break; |
} |
+#endif |
+#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-20520-54086 */ |
case SQLITE_CONFIG_MULTITHREAD: { |
- /* Disable mutexing of database connections */ |
- /* Enable mutexing of core data structures */ |
- sqlite3GlobalConfig.bCoreMutex = 1; |
- sqlite3GlobalConfig.bFullMutex = 0; |
+ /* EVIDENCE-OF: R-14374-42468 This option sets the threading mode to |
+ ** Multi-thread. */ |
+ sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */ |
+ sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */ |
break; |
} |
+#endif |
+#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-59593-21810 */ |
case SQLITE_CONFIG_SERIALIZED: { |
- /* Enable all mutexing */ |
- sqlite3GlobalConfig.bCoreMutex = 1; |
- sqlite3GlobalConfig.bFullMutex = 1; |
+ /* EVIDENCE-OF: R-41220-51800 This option sets the threading mode to |
+ ** Serialized. */ |
+ sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */ |
+ sqlite3GlobalConfig.bFullMutex = 1; /* Enable mutex on connections */ |
break; |
} |
+#endif |
+#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-63666-48755 */ |
case SQLITE_CONFIG_MUTEX: { |
/* Specify an alternative mutex implementation */ |
sqlite3GlobalConfig.mutex = *va_arg(ap, sqlite3_mutex_methods*); |
break; |
} |
+#endif |
+#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-14450-37597 */ |
case SQLITE_CONFIG_GETMUTEX: { |
/* Retrieve the current mutex implementation */ |
*va_arg(ap, sqlite3_mutex_methods*) = sqlite3GlobalConfig.mutex; |
@@ -363,37 +409,62 @@ int sqlite3_config(int op, ...){ |
} |
#endif |
- |
case SQLITE_CONFIG_MALLOC: { |
- /* Specify an alternative malloc implementation */ |
+ /* EVIDENCE-OF: R-55594-21030 The SQLITE_CONFIG_MALLOC option takes a |
+ ** single argument which is a pointer to an instance of the |
+ ** sqlite3_mem_methods structure. The argument specifies alternative |
+ ** low-level memory allocation routines to be used in place of the memory |
+ ** allocation routines built into SQLite. */ |
sqlite3GlobalConfig.m = *va_arg(ap, sqlite3_mem_methods*); |
break; |
} |
case SQLITE_CONFIG_GETMALLOC: { |
- /* Retrieve the current malloc() implementation */ |
+ /* EVIDENCE-OF: R-51213-46414 The SQLITE_CONFIG_GETMALLOC option takes a |
+ ** single argument which is a pointer to an instance of the |
+ ** sqlite3_mem_methods structure. The sqlite3_mem_methods structure is |
+ ** filled with the currently defined memory allocation routines. */ |
if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault(); |
*va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m; |
break; |
} |
case SQLITE_CONFIG_MEMSTATUS: { |
- /* Enable or disable the malloc status collection */ |
+ /* EVIDENCE-OF: R-61275-35157 The SQLITE_CONFIG_MEMSTATUS option takes |
+ ** single argument of type int, interpreted as a boolean, which enables |
+ ** or disables the collection of memory allocation statistics. */ |
sqlite3GlobalConfig.bMemstat = va_arg(ap, int); |
break; |
} |
case SQLITE_CONFIG_SCRATCH: { |
- /* Designate a buffer for scratch memory space */ |
+ /* EVIDENCE-OF: R-08404-60887 There are three arguments to |
+ ** SQLITE_CONFIG_SCRATCH: A pointer an 8-byte aligned memory buffer from |
+ ** which the scratch allocations will be drawn, the size of each scratch |
+ ** allocation (sz), and the maximum number of scratch allocations (N). */ |
sqlite3GlobalConfig.pScratch = va_arg(ap, void*); |
sqlite3GlobalConfig.szScratch = va_arg(ap, int); |
sqlite3GlobalConfig.nScratch = va_arg(ap, int); |
break; |
} |
case SQLITE_CONFIG_PAGECACHE: { |
- /* Designate a buffer for page cache memory space */ |
+ /* EVIDENCE-OF: R-18761-36601 There are three arguments to |
+ ** SQLITE_CONFIG_PAGECACHE: A pointer to 8-byte aligned memory (pMem), |
+ ** the size of each page cache line (sz), and the number of cache lines |
+ ** (N). */ |
sqlite3GlobalConfig.pPage = va_arg(ap, void*); |
sqlite3GlobalConfig.szPage = va_arg(ap, int); |
sqlite3GlobalConfig.nPage = va_arg(ap, int); |
break; |
} |
+ case SQLITE_CONFIG_PCACHE_HDRSZ: { |
+ /* EVIDENCE-OF: R-39100-27317 The SQLITE_CONFIG_PCACHE_HDRSZ option takes |
+ ** a single parameter which is a pointer to an integer and writes into |
+ ** that integer the number of extra bytes per page required for each page |
+ ** in SQLITE_CONFIG_PAGECACHE. */ |
+ *va_arg(ap, int*) = |
+ sqlite3HeaderSizeBtree() + |
+ sqlite3HeaderSizePcache() + |
+ sqlite3HeaderSizePcache1(); |
+ break; |
+ } |
case SQLITE_CONFIG_PCACHE: { |
/* no-op */ |
@@ -406,11 +477,18 @@ int sqlite3_config(int op, ...){ |
} |
case SQLITE_CONFIG_PCACHE2: { |
- /* Specify an alternative page cache implementation */ |
+ /* EVIDENCE-OF: R-63325-48378 The SQLITE_CONFIG_PCACHE2 option takes a |
+ ** single argument which is a pointer to an sqlite3_pcache_methods2 |
+ ** object. This object specifies the interface to a custom page cache |
+ ** implementation. */ |
sqlite3GlobalConfig.pcache2 = *va_arg(ap, sqlite3_pcache_methods2*); |
break; |
} |
case SQLITE_CONFIG_GETPCACHE2: { |
+ /* EVIDENCE-OF: R-22035-46182 The SQLITE_CONFIG_GETPCACHE2 option takes a |
+ ** single argument which is a pointer to an sqlite3_pcache_methods2 |
+ ** object. SQLite copies of the current page cache implementation into |
+ ** that object. */ |
if( sqlite3GlobalConfig.pcache2.xInit==0 ){ |
sqlite3PCacheSetDefault(); |
} |
@@ -418,9 +496,15 @@ int sqlite3_config(int op, ...){ |
break; |
} |
+/* EVIDENCE-OF: R-06626-12911 The SQLITE_CONFIG_HEAP option is only |
+** available if SQLite is compiled with either SQLITE_ENABLE_MEMSYS3 or |
+** SQLITE_ENABLE_MEMSYS5 and returns SQLITE_ERROR if invoked otherwise. */ |
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) |
case SQLITE_CONFIG_HEAP: { |
- /* Designate a buffer for heap memory space */ |
+ /* EVIDENCE-OF: R-19854-42126 There are three arguments to |
+ ** SQLITE_CONFIG_HEAP: An 8-byte aligned pointer to the memory, the |
+ ** number of bytes in the memory buffer, and the minimum allocation size. |
+ */ |
sqlite3GlobalConfig.pHeap = va_arg(ap, void*); |
sqlite3GlobalConfig.nHeap = va_arg(ap, int); |
sqlite3GlobalConfig.mnReq = va_arg(ap, int); |
@@ -433,17 +517,19 @@ int sqlite3_config(int op, ...){ |
} |
if( sqlite3GlobalConfig.pHeap==0 ){ |
- /* If the heap pointer is NULL, then restore the malloc implementation |
- ** back to NULL pointers too. This will cause the malloc to go |
- ** back to its default implementation when sqlite3_initialize() is |
- ** run. |
+ /* EVIDENCE-OF: R-49920-60189 If the first pointer (the memory pointer) |
+ ** is NULL, then SQLite reverts to using its default memory allocator |
+ ** (the system malloc() implementation), undoing any prior invocation of |
+ ** SQLITE_CONFIG_MALLOC. |
+ ** |
+ ** Setting sqlite3GlobalConfig.m to all zeros will cause malloc to |
+ ** revert to its default implementation when sqlite3_initialize() is run |
*/ |
memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m)); |
}else{ |
- /* The heap pointer is not NULL, then install one of the |
- ** mem5.c/mem3.c methods. The enclosing #if guarantees at |
- ** least one of these methods is currently enabled. |
- */ |
+ /* EVIDENCE-OF: R-61006-08918 If the memory pointer is not NULL then the |
+ ** alternative memory allocator is engaged to handle all of SQLites |
+ ** memory allocation needs. */ |
#ifdef SQLITE_ENABLE_MEMSYS3 |
sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3(); |
#endif |
@@ -482,11 +568,19 @@ int sqlite3_config(int op, ...){ |
** sqlite3_config(SQLITE_CONFIG_URI,0) configuration calls. |
*/ |
case SQLITE_CONFIG_URI: { |
+ /* EVIDENCE-OF: R-25451-61125 The SQLITE_CONFIG_URI option takes a single |
+ ** argument of type int. If non-zero, then URI handling is globally |
+ ** enabled. If the parameter is zero, then URI handling is globally |
+ ** disabled. */ |
sqlite3GlobalConfig.bOpenUri = va_arg(ap, int); |
break; |
} |
case SQLITE_CONFIG_COVERING_INDEX_SCAN: { |
+ /* EVIDENCE-OF: R-36592-02772 The SQLITE_CONFIG_COVERING_INDEX_SCAN |
+ ** option takes a single integer argument which is interpreted as a |
+ ** boolean in order to enable or disable the use of covering indices for |
+ ** full table scans in the query optimizer. */ |
sqlite3GlobalConfig.bUseCis = va_arg(ap, int); |
break; |
} |
@@ -501,25 +595,45 @@ int sqlite3_config(int op, ...){ |
#endif |
case SQLITE_CONFIG_MMAP_SIZE: { |
+ /* EVIDENCE-OF: R-58063-38258 SQLITE_CONFIG_MMAP_SIZE takes two 64-bit |
+ ** integer (sqlite3_int64) values that are the default mmap size limit |
+ ** (the default setting for PRAGMA mmap_size) and the maximum allowed |
+ ** mmap size limit. */ |
sqlite3_int64 szMmap = va_arg(ap, sqlite3_int64); |
sqlite3_int64 mxMmap = va_arg(ap, sqlite3_int64); |
+ /* EVIDENCE-OF: R-53367-43190 If either argument to this option is |
+ ** negative, then that argument is changed to its compile-time default. |
+ ** |
+ ** EVIDENCE-OF: R-34993-45031 The maximum allowed mmap size will be |
+ ** silently truncated if necessary so that it does not exceed the |
+ ** compile-time maximum mmap size set by the SQLITE_MAX_MMAP_SIZE |
+ ** compile-time option. |
+ */ |
if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ){ |
mxMmap = SQLITE_MAX_MMAP_SIZE; |
} |
- sqlite3GlobalConfig.mxMmap = mxMmap; |
if( szMmap<0 ) szMmap = SQLITE_DEFAULT_MMAP_SIZE; |
if( szMmap>mxMmap) szMmap = mxMmap; |
+ sqlite3GlobalConfig.mxMmap = mxMmap; |
sqlite3GlobalConfig.szMmap = szMmap; |
break; |
} |
-#if SQLITE_OS_WIN && defined(SQLITE_WIN32_MALLOC) |
+#if SQLITE_OS_WIN && defined(SQLITE_WIN32_MALLOC) /* IMP: R-04780-55815 */ |
case SQLITE_CONFIG_WIN32_HEAPSIZE: { |
+ /* EVIDENCE-OF: R-34926-03360 SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit |
+ ** unsigned integer value that specifies the maximum size of the created |
+ ** heap. */ |
sqlite3GlobalConfig.nHeap = va_arg(ap, int); |
break; |
} |
#endif |
+ case SQLITE_CONFIG_PMASZ: { |
+ sqlite3GlobalConfig.szPma = va_arg(ap, unsigned int); |
+ break; |
+ } |
+ |
default: { |
rc = SQLITE_ERROR; |
break; |
@@ -541,6 +655,7 @@ int sqlite3_config(int op, ...){ |
** the lookaside memory. |
*/ |
static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ |
+#ifndef SQLITE_OMIT_LOOKASIDE |
void *pStart; |
if( db->lookaside.nOut ){ |
return SQLITE_BUSY; |
@@ -591,6 +706,7 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ |
db->lookaside.bEnabled = 0; |
db->lookaside.bMalloced = 0; |
} |
+#endif /* SQLITE_OMIT_LOOKASIDE */ |
return SQLITE_OK; |
} |
@@ -598,6 +714,12 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ |
** Return the mutex associated with a database connection. |
*/ |
sqlite3_mutex *sqlite3_db_mutex(sqlite3 *db){ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return 0; |
+ } |
+#endif |
return db->mutex; |
} |
@@ -607,6 +729,10 @@ sqlite3_mutex *sqlite3_db_mutex(sqlite3 *db){ |
*/ |
int sqlite3_db_release_memory(sqlite3 *db){ |
int i; |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
+#endif |
sqlite3_mutex_enter(db->mutex); |
sqlite3BtreeEnterAll(db); |
for(i=0; i<db->nDb; i++){ |
@@ -622,6 +748,36 @@ int sqlite3_db_release_memory(sqlite3 *db){ |
} |
/* |
+** Flush any dirty pages in the pager-cache for any attached database |
+** to disk. |
+*/ |
+int sqlite3_db_cacheflush(sqlite3 *db){ |
+ int i; |
+ int rc = SQLITE_OK; |
+ int bSeenBusy = 0; |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
+#endif |
+ sqlite3_mutex_enter(db->mutex); |
+ sqlite3BtreeEnterAll(db); |
+ for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ |
+ Btree *pBt = db->aDb[i].pBt; |
+ if( pBt && sqlite3BtreeIsInTrans(pBt) ){ |
+ Pager *pPager = sqlite3BtreePager(pBt); |
+ rc = sqlite3PagerFlush(pPager); |
+ if( rc==SQLITE_BUSY ){ |
+ bSeenBusy = 1; |
+ rc = SQLITE_OK; |
+ } |
+ } |
+ } |
+ sqlite3BtreeLeaveAll(db); |
+ sqlite3_mutex_leave(db->mutex); |
+ return ((rc==SQLITE_OK && bSeenBusy) ? SQLITE_BUSY : rc); |
+} |
+ |
+/* |
** Configuration settings for an individual database connection |
*/ |
int sqlite3_db_config(sqlite3 *db, int op, ...){ |
@@ -696,13 +852,20 @@ static int binCollFunc( |
){ |
int rc, n; |
n = nKey1<nKey2 ? nKey1 : nKey2; |
+ /* EVIDENCE-OF: R-65033-28449 The built-in BINARY collation compares |
+ ** strings byte by byte using the memcmp() function from the standard C |
+ ** library. */ |
rc = memcmp(pKey1, pKey2, n); |
if( rc==0 ){ |
if( padFlag |
&& allSpaces(((char*)pKey1)+n, nKey1-n) |
&& allSpaces(((char*)pKey2)+n, nKey2-n) |
){ |
- /* Leave rc unchanged at 0 */ |
+ /* EVIDENCE-OF: R-31624-24737 RTRIM is like BINARY except that extra |
+ ** spaces at the end of either string do not change the result. In other |
+ ** words, strings will compare equal to one another as long as they |
+ ** differ only in the number of spaces at the end. |
+ */ |
}else{ |
rc = nKey1 - nKey2; |
} |
@@ -737,6 +900,12 @@ static int nocaseCollatingFunc( |
** Return the ROWID of the most recent insert |
*/ |
sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return 0; |
+ } |
+#endif |
return db->lastRowid; |
} |
@@ -744,6 +913,12 @@ sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){ |
** Return the number of changes in the most recent call to sqlite3_exec(). |
*/ |
int sqlite3_changes(sqlite3 *db){ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return 0; |
+ } |
+#endif |
return db->nChange; |
} |
@@ -751,6 +926,12 @@ int sqlite3_changes(sqlite3 *db){ |
** Return the number of changes since the database handle was opened. |
*/ |
int sqlite3_total_changes(sqlite3 *db){ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return 0; |
+ } |
+#endif |
return db->nTotalChange; |
} |
@@ -794,17 +975,23 @@ static void functionDestroy(sqlite3 *db, FuncDef *p){ |
static void disconnectAllVtab(sqlite3 *db){ |
#ifndef SQLITE_OMIT_VIRTUALTABLE |
int i; |
+ HashElem *p; |
sqlite3BtreeEnterAll(db); |
for(i=0; i<db->nDb; i++){ |
Schema *pSchema = db->aDb[i].pSchema; |
if( db->aDb[i].pSchema ){ |
- HashElem *p; |
for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){ |
Table *pTab = (Table *)sqliteHashData(p); |
if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab); |
} |
} |
} |
+ for(p=sqliteHashFirst(&db->aModule); p; p=sqliteHashNext(p)){ |
+ Module *pMod = (Module *)sqliteHashData(p); |
+ if( pMod->pEpoTab ){ |
+ sqlite3VtabDisconnect(db, pMod->pEpoTab); |
+ } |
+ } |
sqlite3VtabUnlockList(db); |
sqlite3BtreeLeaveAll(db); |
#else |
@@ -930,16 +1117,6 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ |
for(j=0; j<db->nDb; j++){ |
struct Db *pDb = &db->aDb[j]; |
if( pDb->pBt ){ |
- if( pDb->pSchema ){ |
- /* Must clear the KeyInfo cache. See ticket [e4a18565a36884b00edf] */ |
- sqlite3BtreeEnter(pDb->pBt); |
- for(i=sqliteHashFirst(&pDb->pSchema->idxHash); i; i=sqliteHashNext(i)){ |
- Index *pIdx = sqliteHashData(i); |
- sqlite3KeyInfoUnref(pIdx->pKeyInfo); |
- pIdx->pKeyInfo = 0; |
- } |
- sqlite3BtreeLeave(pDb->pBt); |
- } |
sqlite3BtreeClose(pDb->pBt); |
pDb->pBt = 0; |
if( j!=1 ){ |
@@ -992,6 +1169,7 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ |
if( pMod->xDestroy ){ |
pMod->xDestroy(pMod->pAux); |
} |
+ sqlite3VtabEponymousTableClear(db, pMod); |
sqlite3DbFree(db, pMod); |
} |
sqlite3HashClear(&db->aModule); |
@@ -1080,7 +1258,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){ |
** Return a static string containing the name corresponding to the error code |
** specified in the argument. |
*/ |
-#if (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) || defined(SQLITE_TEST) |
+#if defined(SQLITE_NEED_ERR_NAME) |
const char *sqlite3ErrName(int rc){ |
const char *zName = 0; |
int i, origRc = rc; |
@@ -1246,7 +1424,7 @@ static int sqliteDefaultBusyCallback( |
void *ptr, /* Database connection */ |
int count /* Number of times table has been busy */ |
){ |
-#if SQLITE_OS_WIN || (defined(HAVE_USLEEP) && HAVE_USLEEP) |
+#if SQLITE_OS_WIN || HAVE_USLEEP |
static const u8 delays[] = |
{ 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 }; |
static const u8 totals[] = |
@@ -1309,6 +1487,9 @@ int sqlite3_busy_handler( |
int (*xBusy)(void*,int), |
void *pArg |
){ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
+#endif |
sqlite3_mutex_enter(db->mutex); |
db->busyHandler.xFunc = xBusy; |
db->busyHandler.pArg = pArg; |
@@ -1330,6 +1511,12 @@ void sqlite3_progress_handler( |
int (*xProgress)(void*), |
void *pArg |
){ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return; |
+ } |
+#endif |
sqlite3_mutex_enter(db->mutex); |
if( nOps>0 ){ |
db->xProgress = xProgress; |
@@ -1350,6 +1537,9 @@ void sqlite3_progress_handler( |
** specified number of milliseconds before returning 0. |
*/ |
int sqlite3_busy_timeout(sqlite3 *db, int ms){ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
+#endif |
if( ms>0 ){ |
sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db); |
db->busyTimeout = ms; |
@@ -1363,6 +1553,12 @@ int sqlite3_busy_timeout(sqlite3 *db, int ms){ |
** Cause any pending operation to stop at its earliest opportunity. |
*/ |
void sqlite3_interrupt(sqlite3 *db){ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return; |
+ } |
+#endif |
db->u1.isInterrupted = 1; |
} |
@@ -1500,6 +1696,12 @@ int sqlite3_create_function_v2( |
){ |
int rc = SQLITE_ERROR; |
FuncDestructor *pArg = 0; |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ return SQLITE_MISUSE_BKPT; |
+ } |
+#endif |
sqlite3_mutex_enter(db->mutex); |
if( xDestroy ){ |
pArg = (FuncDestructor *)sqlite3DbMallocZero(db, sizeof(FuncDestructor)); |
@@ -1536,6 +1738,10 @@ int sqlite3_create_function16( |
){ |
int rc; |
char *zFunc8; |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) || zFunctionName==0 ) return SQLITE_MISUSE_BKPT; |
+#endif |
sqlite3_mutex_enter(db->mutex); |
assert( !db->mallocFailed ); |
zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE); |
@@ -1567,6 +1773,12 @@ int sqlite3_overload_function( |
){ |
int nName = sqlite3Strlen30(zName); |
int rc = SQLITE_OK; |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) || zName==0 || nArg<-2 ){ |
+ return SQLITE_MISUSE_BKPT; |
+ } |
+#endif |
sqlite3_mutex_enter(db->mutex); |
if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){ |
rc = sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8, |
@@ -1588,6 +1800,13 @@ int sqlite3_overload_function( |
*/ |
void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){ |
void *pOld; |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return 0; |
+ } |
+#endif |
sqlite3_mutex_enter(db->mutex); |
pOld = db->pTraceArg; |
db->xTrace = xTrace; |
@@ -1609,6 +1828,13 @@ void *sqlite3_profile( |
void *pArg |
){ |
void *pOld; |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return 0; |
+ } |
+#endif |
sqlite3_mutex_enter(db->mutex); |
pOld = db->pProfileArg; |
db->xProfile = xProfile; |
@@ -1629,6 +1855,13 @@ void *sqlite3_commit_hook( |
void *pArg /* Argument to the function */ |
){ |
void *pOld; |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return 0; |
+ } |
+#endif |
sqlite3_mutex_enter(db->mutex); |
pOld = db->pCommitArg; |
db->xCommitCallback = xCallback; |
@@ -1647,6 +1880,13 @@ void *sqlite3_update_hook( |
void *pArg /* Argument to the function */ |
){ |
void *pRet; |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return 0; |
+ } |
+#endif |
sqlite3_mutex_enter(db->mutex); |
pRet = db->pUpdateArg; |
db->xUpdateCallback = xCallback; |
@@ -1665,6 +1905,13 @@ void *sqlite3_rollback_hook( |
void *pArg /* Argument to the function */ |
){ |
void *pRet; |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return 0; |
+ } |
+#endif |
sqlite3_mutex_enter(db->mutex); |
pRet = db->pRollbackArg; |
db->xRollbackCallback = xCallback; |
@@ -1711,6 +1958,9 @@ int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){ |
UNUSED_PARAMETER(db); |
UNUSED_PARAMETER(nFrame); |
#else |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
+#endif |
if( nFrame>0 ){ |
sqlite3_wal_hook(db, sqlite3WalDefaultHook, SQLITE_INT_TO_PTR(nFrame)); |
}else{ |
@@ -1731,6 +1981,12 @@ void *sqlite3_wal_hook( |
){ |
#ifndef SQLITE_OMIT_WAL |
void *pRet; |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return 0; |
+ } |
+#endif |
sqlite3_mutex_enter(db->mutex); |
pRet = db->pWalArg; |
db->xWalCallback = xCallback; |
@@ -1758,14 +2014,21 @@ int sqlite3_wal_checkpoint_v2( |
int rc; /* Return code */ |
int iDb = SQLITE_MAX_ATTACHED; /* sqlite3.aDb[] index of db to checkpoint */ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
+#endif |
+ |
/* Initialize the output variables to -1 in case an error occurs. */ |
if( pnLog ) *pnLog = -1; |
if( pnCkpt ) *pnCkpt = -1; |
- assert( SQLITE_CHECKPOINT_FULL>SQLITE_CHECKPOINT_PASSIVE ); |
- assert( SQLITE_CHECKPOINT_FULL<SQLITE_CHECKPOINT_RESTART ); |
- assert( SQLITE_CHECKPOINT_PASSIVE+2==SQLITE_CHECKPOINT_RESTART ); |
- if( eMode<SQLITE_CHECKPOINT_PASSIVE || eMode>SQLITE_CHECKPOINT_RESTART ){ |
+ assert( SQLITE_CHECKPOINT_PASSIVE==0 ); |
+ assert( SQLITE_CHECKPOINT_FULL==1 ); |
+ assert( SQLITE_CHECKPOINT_RESTART==2 ); |
+ assert( SQLITE_CHECKPOINT_TRUNCATE==3 ); |
+ if( eMode<SQLITE_CHECKPOINT_PASSIVE || eMode>SQLITE_CHECKPOINT_TRUNCATE ){ |
+ /* EVIDENCE-OF: R-03996-12088 The M parameter must be a valid checkpoint |
+ ** mode: */ |
return SQLITE_MISUSE; |
} |
@@ -1777,6 +2040,7 @@ int sqlite3_wal_checkpoint_v2( |
rc = SQLITE_ERROR; |
sqlite3ErrorWithMsg(db, SQLITE_ERROR, "unknown database: %s", zDb); |
}else{ |
+ db->busyHandler.nBusy = 0; |
rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt); |
sqlite3Error(db, rc); |
} |
@@ -1793,7 +2057,9 @@ int sqlite3_wal_checkpoint_v2( |
** checkpointed. |
*/ |
int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ |
- return sqlite3_wal_checkpoint_v2(db, zDb, SQLITE_CHECKPOINT_PASSIVE, 0, 0); |
+ /* EVIDENCE-OF: R-41613-20553 The sqlite3_wal_checkpoint(D,X) is equivalent to |
+ ** sqlite3_wal_checkpoint_v2(D,X,SQLITE_CHECKPOINT_PASSIVE,0,0). */ |
+ return sqlite3_wal_checkpoint_v2(db,zDb,SQLITE_CHECKPOINT_PASSIVE,0,0); |
} |
#ifndef SQLITE_OMIT_WAL |
@@ -1868,9 +2134,11 @@ int sqlite3TempInMemory(const sqlite3 *db){ |
return ( db->temp_store!=1 ); |
#endif |
#if SQLITE_TEMP_STORE==3 |
+ UNUSED_PARAMETER(db); |
return 1; |
#endif |
#if SQLITE_TEMP_STORE<1 || SQLITE_TEMP_STORE>3 |
+ UNUSED_PARAMETER(db); |
return 0; |
#endif |
} |
@@ -1981,32 +2249,6 @@ const char *sqlite3_errstr(int rc){ |
} |
/* |
-** Invalidate all cached KeyInfo objects for database connection "db" |
-*/ |
-static void invalidateCachedKeyInfo(sqlite3 *db){ |
- Db *pDb; /* A single database */ |
- int iDb; /* The database index number */ |
- HashElem *k; /* For looping over tables in pDb */ |
- Table *pTab; /* A table in the database */ |
- Index *pIdx; /* Each index */ |
- |
- for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){ |
- if( pDb->pBt==0 ) continue; |
- sqlite3BtreeEnter(pDb->pBt); |
- for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ |
- pTab = (Table*)sqliteHashData(k); |
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
- if( pIdx->pKeyInfo && pIdx->pKeyInfo->db==db ){ |
- sqlite3KeyInfoUnref(pIdx->pKeyInfo); |
- pIdx->pKeyInfo = 0; |
- } |
- } |
- } |
- sqlite3BtreeLeave(pDb->pBt); |
- } |
-} |
- |
-/* |
** Create a new collating function for database "db". The name is zName |
** and the encoding is enc. |
*/ |
@@ -2049,7 +2291,6 @@ static int createCollation( |
return SQLITE_BUSY; |
} |
sqlite3ExpirePreparedStatements(db); |
- invalidateCachedKeyInfo(db); |
/* If collation sequence pColl was created directly by a call to |
** sqlite3_create_collation, and not generated by synthCollSeq(), |
@@ -2154,6 +2395,12 @@ static const int aHardLimit[] = { |
int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ |
int oldLimit; |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return -1; |
+ } |
+#endif |
/* EVIDENCE-OF: R-30189-54097 For each limit category SQLITE_LIMIT_NAME |
** there is a hard upper bound set at compile-time by a C preprocessor |
@@ -2230,25 +2477,38 @@ int sqlite3ParseUri( |
assert( *pzErrMsg==0 ); |
- if( ((flags & SQLITE_OPEN_URI) || sqlite3GlobalConfig.bOpenUri) |
+ if( ((flags & SQLITE_OPEN_URI) /* IMP: R-48725-32206 */ |
+ || sqlite3GlobalConfig.bOpenUri) /* IMP: R-51689-46548 */ |
&& nUri>=5 && memcmp(zUri, "file:", 5)==0 /* IMP: R-57884-37496 */ |
){ |
char *zOpt; |
int eState; /* Parser state when parsing URI */ |
int iIn; /* Input character index */ |
int iOut = 0; /* Output character index */ |
- int nByte = nUri+2; /* Bytes of space to allocate */ |
+ u64 nByte = nUri+2; /* Bytes of space to allocate */ |
/* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen |
** method that there may be extra parameters following the file-name. */ |
flags |= SQLITE_OPEN_URI; |
for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&'); |
- zFile = sqlite3_malloc(nByte); |
+ zFile = sqlite3_malloc64(nByte); |
if( !zFile ) return SQLITE_NOMEM; |
iIn = 5; |
-#ifndef SQLITE_ALLOW_URI_AUTHORITY |
+#ifdef SQLITE_ALLOW_URI_AUTHORITY |
+ if( strncmp(zUri+5, "///", 3)==0 ){ |
+ iIn = 7; |
+ /* The following condition causes URIs with five leading / characters |
+ ** like file://///host/path to be converted into UNCs like //host/path. |
+ ** The correct URI for that UNC has only two or four leading / characters |
+ ** file://host/path or file:////host/path. But 5 leading slashes is a |
+ ** common error, we are told, so we handle it as a special case. */ |
+ if( strncmp(zUri+7, "///", 3)==0 ){ iIn++; } |
+ }else if( strncmp(zUri+5, "//localhost/", 12)==0 ){ |
+ iIn = 16; |
+ } |
+#else |
/* Discard the scheme and authority segments of the URI. */ |
if( zUri[5]=='/' && zUri[6]=='/' ){ |
iIn = 7; |
@@ -2398,7 +2658,7 @@ int sqlite3ParseUri( |
} |
}else{ |
- zFile = sqlite3_malloc(nUri+2); |
+ zFile = sqlite3_malloc64(nUri+2); |
if( !zFile ) return SQLITE_NOMEM; |
memcpy(zFile, zUri, nUri); |
zFile[nUri] = '\0'; |
@@ -2439,6 +2699,9 @@ static int openDatabase( |
char *zOpen = 0; /* Filename argument to pass to BtreeOpen() */ |
char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( ppDb==0 ) return SQLITE_MISUSE_BKPT; |
+#endif |
*ppDb = 0; |
#ifndef SQLITE_OMIT_AUTOINIT |
rc = sqlite3_initialize(); |
@@ -2532,6 +2795,9 @@ static int openDatabase( |
#if !defined(SQLITE_DEFAULT_AUTOMATIC_INDEX) || SQLITE_DEFAULT_AUTOMATIC_INDEX |
| SQLITE_AutoIndex |
#endif |
+#if SQLITE_DEFAULT_CKPTFULLFSYNC |
+ | SQLITE_CkptFullFSync |
+#endif |
#if SQLITE_DEFAULT_FILE_FORMAT<4 |
| SQLITE_LegacyFileFmt |
#endif |
@@ -2544,6 +2810,12 @@ static int openDatabase( |
#if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS |
| SQLITE_ForeignKeys |
#endif |
+#if defined(SQLITE_REVERSE_UNORDERED_SELECTS) |
+ | SQLITE_ReverseOrder |
+#endif |
+#if defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK) |
+ | SQLITE_CellSizeCk |
+#endif |
; |
sqlite3HashInit(&db->aCollSeq); |
#ifndef SQLITE_OMIT_VIRTUALTABLE |
@@ -2553,20 +2825,24 @@ static int openDatabase( |
/* Add the default collation sequence BINARY. BINARY works for both UTF-8 |
** and UTF-16, so add a version for each to avoid any unnecessary |
** conversions. The only error that can occur here is a malloc() failure. |
+ ** |
+ ** EVIDENCE-OF: R-52786-44878 SQLite defines three built-in collating |
+ ** functions: |
*/ |
- createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc, 0); |
- createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc, 0); |
- createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0); |
+ createCollation(db, sqlite3StrBINARY, SQLITE_UTF8, 0, binCollFunc, 0); |
+ createCollation(db, sqlite3StrBINARY, SQLITE_UTF16BE, 0, binCollFunc, 0); |
+ createCollation(db, sqlite3StrBINARY, SQLITE_UTF16LE, 0, binCollFunc, 0); |
+ createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0); |
createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0); |
if( db->mallocFailed ){ |
goto opendb_out; |
} |
- db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0); |
+ /* EVIDENCE-OF: R-08308-17224 The default collating function for all |
+ ** strings is BINARY. |
+ */ |
+ db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, sqlite3StrBINARY, 0); |
assert( db->pDfltColl!=0 ); |
- /* Also add a UTF-8 case-insensitive collation sequence. */ |
- createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0); |
- |
/* Parse the filename/URI argument. */ |
db->openFlags = flags; |
rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg); |
@@ -2589,6 +2865,7 @@ static int openDatabase( |
} |
sqlite3BtreeEnter(db->aDb[0].pBt); |
db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt); |
+ if( !db->mallocFailed ) ENC(db) = SCHEMA_ENC(db); |
sqlite3BtreeLeave(db->aDb[0].pBt); |
db->aDb[1].pSchema = sqlite3SchemaGet(db, 0); |
@@ -2638,12 +2915,18 @@ static int openDatabase( |
} |
#endif |
-#ifdef SQLITE_ENABLE_FTS3 |
+#ifdef SQLITE_ENABLE_FTS3 /* automatically defined by SQLITE_ENABLE_FTS4 */ |
if( !db->mallocFailed && rc==SQLITE_OK ){ |
rc = sqlite3Fts3Init(db); |
} |
#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); |
@@ -2664,6 +2947,18 @@ static int openDatabase( |
} |
#endif |
+#ifdef SQLITE_ENABLE_DBSTAT_VTAB |
+ if( !db->mallocFailed && rc==SQLITE_OK){ |
+ rc = sqlite3DbstatRegister(db); |
+ } |
+#endif |
+ |
+#ifdef SQLITE_ENABLE_JSON1 |
+ if( !db->mallocFailed && rc==SQLITE_OK){ |
+ rc = sqlite3Json1Init(db); |
+ } |
+#endif |
+ |
/* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking |
** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking |
** mode. Doing nothing at all also makes NORMAL the default. |
@@ -2683,9 +2978,9 @@ static int openDatabase( |
sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT); |
opendb_out: |
- sqlite3_free(zOpen); |
if( db ){ |
- assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 ); |
+ assert( db->mutex!=0 || isThreadsafe==0 |
+ || sqlite3GlobalConfig.bFullMutex==0 ); |
sqlite3_mutex_leave(db->mutex); |
} |
rc = sqlite3_errcode(db); |
@@ -2704,7 +2999,23 @@ opendb_out: |
sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0); |
} |
#endif |
- return sqlite3ApiExit(0, rc); |
+#if defined(SQLITE_HAS_CODEC) |
+ if( rc==SQLITE_OK ){ |
+ const char *zHexKey = sqlite3_uri_parameter(zOpen, "hexkey"); |
+ if( zHexKey && zHexKey[0] ){ |
+ u8 iByte; |
+ int i; |
+ char zKey[40]; |
+ for(i=0, iByte=0; i<sizeof(zKey)*2 && sqlite3Isxdigit(zHexKey[i]); i++){ |
+ iByte = (iByte<<4) + sqlite3HexToInt(zHexKey[i]); |
+ if( (i&1)!=0 ) zKey[i/2] = iByte; |
+ } |
+ sqlite3_key_v2(db, 0, zKey, i/2); |
+ } |
+ } |
+#endif |
+ sqlite3_free(zOpen); |
+ return rc & 0xff; |
} |
/* |
@@ -2738,13 +3049,15 @@ int sqlite3_open16( |
sqlite3_value *pVal; |
int rc; |
- assert( zFilename ); |
- assert( ppDb ); |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( ppDb==0 ) return SQLITE_MISUSE_BKPT; |
+#endif |
*ppDb = 0; |
#ifndef SQLITE_OMIT_AUTOINIT |
rc = sqlite3_initialize(); |
if( rc ) return rc; |
#endif |
+ if( zFilename==0 ) zFilename = "\000\000"; |
pVal = sqlite3ValueNew(0); |
sqlite3ValueSetStr(pVal, -1, zFilename, SQLITE_UTF16NATIVE, SQLITE_STATIC); |
zFilename8 = sqlite3ValueText(pVal, SQLITE_UTF8); |
@@ -2753,14 +3066,14 @@ int sqlite3_open16( |
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); |
assert( *ppDb || rc==SQLITE_NOMEM ); |
if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){ |
- ENC(*ppDb) = SQLITE_UTF16NATIVE; |
+ SCHEMA_ENC(*ppDb) = ENC(*ppDb) = SQLITE_UTF16NATIVE; |
} |
}else{ |
rc = SQLITE_NOMEM; |
} |
sqlite3ValueFree(pVal); |
- return sqlite3ApiExit(0, rc); |
+ return rc & 0xff; |
} |
#endif /* SQLITE_OMIT_UTF16 */ |
@@ -2774,13 +3087,7 @@ int sqlite3_create_collation( |
void* pCtx, |
int(*xCompare)(void*,int,const void*,int,const void*) |
){ |
- int rc; |
- sqlite3_mutex_enter(db->mutex); |
- assert( !db->mallocFailed ); |
- rc = createCollation(db, zName, (u8)enc, pCtx, xCompare, 0); |
- rc = sqlite3ApiExit(db, rc); |
- sqlite3_mutex_leave(db->mutex); |
- return rc; |
+ return sqlite3_create_collation_v2(db, zName, enc, pCtx, xCompare, 0); |
} |
/* |
@@ -2795,6 +3102,10 @@ int sqlite3_create_collation_v2( |
void(*xDel)(void*) |
){ |
int rc; |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT; |
+#endif |
sqlite3_mutex_enter(db->mutex); |
assert( !db->mallocFailed ); |
rc = createCollation(db, zName, (u8)enc, pCtx, xCompare, xDel); |
@@ -2816,6 +3127,10 @@ int sqlite3_create_collation16( |
){ |
int rc = SQLITE_OK; |
char *zName8; |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT; |
+#endif |
sqlite3_mutex_enter(db->mutex); |
assert( !db->mallocFailed ); |
zName8 = sqlite3Utf16to8(db, zName, -1, SQLITE_UTF16NATIVE); |
@@ -2838,6 +3153,9 @@ int sqlite3_collation_needed( |
void *pCollNeededArg, |
void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*) |
){ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
+#endif |
sqlite3_mutex_enter(db->mutex); |
db->xCollNeeded = xCollNeeded; |
db->xCollNeeded16 = 0; |
@@ -2856,6 +3174,9 @@ int sqlite3_collation_needed16( |
void *pCollNeededArg, |
void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*) |
){ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
+#endif |
sqlite3_mutex_enter(db->mutex); |
db->xCollNeeded = 0; |
db->xCollNeeded16 = xCollNeeded16; |
@@ -2882,6 +3203,12 @@ int sqlite3_global_recover(void){ |
** by the next COMMIT or ROLLBACK. |
*/ |
int sqlite3_get_autocommit(sqlite3 *db){ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return 0; |
+ } |
+#endif |
return db->autoCommit; |
} |
@@ -2935,7 +3262,6 @@ void sqlite3_thread_cleanup(void){ |
** Return meta information about a specific column of a database table. |
** See comment in sqlite3.h (sqlite.h.in) for details. |
*/ |
-#ifdef SQLITE_ENABLE_COLUMN_METADATA |
int sqlite3_table_column_metadata( |
sqlite3 *db, /* Connection handle */ |
const char *zDbName, /* Database name or NULL */ |
@@ -2951,14 +3277,20 @@ int sqlite3_table_column_metadata( |
char *zErrMsg = 0; |
Table *pTab = 0; |
Column *pCol = 0; |
- int iCol; |
- |
+ int iCol = 0; |
char const *zDataType = 0; |
char const *zCollSeq = 0; |
int notnull = 0; |
int primarykey = 0; |
int autoinc = 0; |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) || zTableName==0 ){ |
+ return SQLITE_MISUSE_BKPT; |
+ } |
+#endif |
+ |
/* Ensure the database schema has been loaded */ |
sqlite3_mutex_enter(db->mutex); |
sqlite3BtreeEnterAll(db); |
@@ -2975,11 +3307,8 @@ int sqlite3_table_column_metadata( |
} |
/* Find the column for which info is requested */ |
- if( sqlite3IsRowid(zColumnName) ){ |
- iCol = pTab->iPKey; |
- if( iCol>=0 ){ |
- pCol = &pTab->aCol[iCol]; |
- } |
+ if( zColumnName==0 ){ |
+ /* Query for existance of table only */ |
}else{ |
for(iCol=0; iCol<pTab->nCol; iCol++){ |
pCol = &pTab->aCol[iCol]; |
@@ -2988,8 +3317,13 @@ int sqlite3_table_column_metadata( |
} |
} |
if( iCol==pTab->nCol ){ |
- pTab = 0; |
- goto error_out; |
+ if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){ |
+ iCol = pTab->iPKey; |
+ pCol = iCol>=0 ? &pTab->aCol[iCol] : 0; |
+ }else{ |
+ pTab = 0; |
+ goto error_out; |
+ } |
} |
} |
@@ -3014,7 +3348,7 @@ int sqlite3_table_column_metadata( |
primarykey = 1; |
} |
if( !zCollSeq ){ |
- zCollSeq = "BINARY"; |
+ zCollSeq = sqlite3StrBINARY; |
} |
error_out: |
@@ -3042,7 +3376,6 @@ error_out: |
sqlite3_mutex_leave(db->mutex); |
return rc; |
} |
-#endif |
/* |
** Sleep for a little while. Return the amount of time slept. |
@@ -3064,6 +3397,9 @@ int sqlite3_sleep(int ms){ |
** Enable or disable the extended result codes. |
*/ |
int sqlite3_extended_result_codes(sqlite3 *db, int onoff){ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
+#endif |
sqlite3_mutex_enter(db->mutex); |
db->errMask = onoff ? 0xffffffff : 0xff; |
sqlite3_mutex_leave(db->mutex); |
@@ -3077,6 +3413,9 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ |
int rc = SQLITE_ERROR; |
Btree *pBtree; |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
+#endif |
sqlite3_mutex_enter(db->mutex); |
pBtree = sqlite3DbNameToBtree(db, zDbName); |
if( pBtree ){ |
@@ -3090,6 +3429,12 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ |
if( op==SQLITE_FCNTL_FILE_POINTER ){ |
*(sqlite3_file**)pArg = fd; |
rc = SQLITE_OK; |
+ }else if( op==SQLITE_FCNTL_VFS_POINTER ){ |
+ *(sqlite3_vfs**)pArg = sqlite3PagerVfs(pPager); |
+ rc = SQLITE_OK; |
+ }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){ |
+ *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager); |
+ rc = SQLITE_OK; |
}else if( fd->pMethods ){ |
rc = sqlite3OsFileControl(fd, op, pArg); |
}else{ |
@@ -3098,7 +3443,7 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ |
sqlite3BtreeLeave(pBtree); |
} |
sqlite3_mutex_leave(db->mutex); |
- return rc; |
+ return rc; |
} |
/* |
@@ -3106,7 +3451,9 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ |
*/ |
int sqlite3_test_control(int op, ...){ |
int rc = 0; |
-#ifndef SQLITE_OMIT_BUILTIN_TEST |
+#ifdef SQLITE_OMIT_BUILTIN_TEST |
+ UNUSED_PARAMETER(op); |
+#else |
va_list ap; |
va_start(ap, op); |
switch( op ){ |
@@ -3401,6 +3748,35 @@ int sqlite3_test_control(int op, ...){ |
if( sqlite3GlobalConfig.isInit==0 ) rc = SQLITE_ERROR; |
break; |
} |
+ |
+ /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum); |
+ ** |
+ ** This test control is used to create imposter tables. "db" is a pointer |
+ ** to the database connection. dbName is the database name (ex: "main" or |
+ ** "temp") which will receive the imposter. "onOff" turns imposter mode on |
+ ** or off. "tnum" is the root page of the b-tree to which the imposter |
+ ** table should connect. |
+ ** |
+ ** Enable imposter mode only when the schema has already been parsed. Then |
+ ** run a single CREATE TABLE statement to construct the imposter table in |
+ ** the parsed schema. Then turn imposter mode back off again. |
+ ** |
+ ** If onOff==0 and tnum>0 then reset the schema for all databases, causing |
+ ** the schema to be reparsed the next time it is needed. This has the |
+ ** effect of erasing all imposter tables. |
+ */ |
+ case SQLITE_TESTCTRL_IMPOSTER: { |
+ sqlite3 *db = va_arg(ap, sqlite3*); |
+ 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); |
+ } |
+ sqlite3_mutex_leave(db->mutex); |
+ break; |
+ } |
} |
va_end(ap); |
#endif /* SQLITE_OMIT_BUILTIN_TEST */ |
@@ -3419,7 +3795,7 @@ int sqlite3_test_control(int op, ...){ |
** returns a NULL pointer. |
*/ |
const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){ |
- if( zFilename==0 ) return 0; |
+ if( zFilename==0 || zParam==0 ) return 0; |
zFilename += sqlite3Strlen30(zFilename) + 1; |
while( zFilename[0] ){ |
int x = strcmp(zFilename, zParam); |
@@ -3475,7 +3851,14 @@ Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){ |
** connection. |
*/ |
const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ |
- Btree *pBt = sqlite3DbNameToBtree(db, zDbName); |
+ Btree *pBt; |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return 0; |
+ } |
+#endif |
+ pBt = sqlite3DbNameToBtree(db, zDbName); |
return pBt ? sqlite3BtreeGetFilename(pBt) : 0; |
} |
@@ -3484,6 +3867,95 @@ const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ |
** no such database exists. |
*/ |
int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ |
- Btree *pBt = sqlite3DbNameToBtree(db, zDbName); |
+ Btree *pBt; |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return -1; |
+ } |
+#endif |
+ pBt = sqlite3DbNameToBtree(db, zDbName); |
return pBt ? sqlite3BtreeIsReadonly(pBt) : -1; |
} |
+ |
+#ifdef SQLITE_ENABLE_SNAPSHOT |
+/* |
+** Obtain a snapshot handle for the snapshot of database zDb currently |
+** being read by handle db. |
+*/ |
+int sqlite3_snapshot_get( |
+ sqlite3 *db, |
+ const char *zDb, |
+ sqlite3_snapshot **ppSnapshot |
+){ |
+ int rc = SQLITE_ERROR; |
+#ifndef SQLITE_OMIT_WAL |
+ int iDb; |
+ |
+#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==sqlite3BtreeIsInTrans(pBt) ){ |
+ rc = sqlite3BtreeBeginTrans(pBt, 0); |
+ if( rc==SQLITE_OK ){ |
+ rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot); |
+ } |
+ } |
+ } |
+ |
+ sqlite3_mutex_leave(db->mutex); |
+#endif /* SQLITE_OMIT_WAL */ |
+ return rc; |
+} |
+ |
+/* |
+** Open a read-transaction on the snapshot idendified by pSnapshot. |
+*/ |
+int sqlite3_snapshot_open( |
+ sqlite3 *db, |
+ const char *zDb, |
+ sqlite3_snapshot *pSnapshot |
+){ |
+ int rc = SQLITE_ERROR; |
+#ifndef SQLITE_OMIT_WAL |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ){ |
+ return SQLITE_MISUSE_BKPT; |
+ } |
+#endif |
+ sqlite3_mutex_enter(db->mutex); |
+ if( db->autoCommit==0 ){ |
+ int iDb; |
+ iDb = sqlite3FindDbName(db, zDb); |
+ if( iDb==0 || iDb>1 ){ |
+ Btree *pBt = db->aDb[iDb].pBt; |
+ if( 0==sqlite3BtreeIsInReadTrans(pBt) ){ |
+ rc = sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), pSnapshot); |
+ if( rc==SQLITE_OK ){ |
+ rc = sqlite3BtreeBeginTrans(pBt, 0); |
+ sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), 0); |
+ } |
+ } |
+ } |
+ } |
+ |
+ 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){ |
+ sqlite3_free(pSnapshot); |
+} |
+#endif /* SQLITE_ENABLE_SNAPSHOT */ |