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 c904d401119fb210672cfd3bcdf372cb7c42eb4a..4aaa61899cbd426a0e0342872aff037162fa9c7a 100644 |
--- a/third_party/sqlite/src/src/main.c |
+++ b/third_party/sqlite/src/src/main.c |
@@ -26,15 +26,33 @@ |
# include "sqliteicu.h" |
#endif |
-/* |
-** The version of the library |
-*/ |
#ifndef SQLITE_AMALGAMATION |
+/* IMPLEMENTATION-OF: R-46656-45156 The sqlite3_version[] string constant |
+** contains the text of SQLITE_VERSION macro. |
+*/ |
const char sqlite3_version[] = SQLITE_VERSION; |
#endif |
+ |
+/* IMPLEMENTATION-OF: R-53536-42575 The sqlite3_libversion() function returns |
+** a pointer to the to the sqlite3_version[] string constant. |
+*/ |
const char *sqlite3_libversion(void){ return sqlite3_version; } |
+ |
+/* IMPLEMENTATION-OF: R-63124-39300 The sqlite3_sourceid() function returns a |
+** pointer to a string constant whose value is the same as the |
+** SQLITE_SOURCE_ID C preprocessor macro. |
+*/ |
const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } |
+ |
+/* IMPLEMENTATION-OF: R-35210-63508 The sqlite3_libversion_number() function |
+** returns an integer equal to SQLITE_VERSION_NUMBER. |
+*/ |
int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } |
+ |
+/* IMPLEMENTATION-OF: R-54823-41343 The sqlite3_threadsafe() function returns |
+** zero if and only if SQLite was compiled mutexing code omitted due to |
+** the SQLITE_THREADSAFE compile-time option being set to 0. |
+*/ |
int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } |
#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) |
@@ -155,6 +173,13 @@ int sqlite3_initialize(void){ |
** sqlite3_initialize(). The recursive calls normally come through |
** sqlite3_os_init() when it invokes sqlite3_vfs_register(), but other |
** recursive calls might also be possible. |
+ ** |
+ ** IMPLEMENTATION-OF: R-00140-37445 SQLite automatically serializes calls |
+ ** to the xInit method, so the xInit method need not be threadsafe. |
+ ** |
+ ** The following mutex is what serializes access to the appdef pcache xInit |
+ ** methods. The sqlite3_pcache_methods.xInit() all is embedded in the |
+ ** call to sqlite3PcacheInitialize(). |
*/ |
sqlite3_mutex_enter(sqlite3GlobalConfig.pInitMutex); |
if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){ |
@@ -257,7 +282,7 @@ int sqlite3_config(int op, ...){ |
/* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while |
** the SQLite library is in use. */ |
- if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE; |
+ if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE_BKPT; |
va_start(ap, op); |
switch( op ){ |
@@ -265,7 +290,7 @@ int sqlite3_config(int op, ...){ |
/* Mutex configuration options are only available in a threadsafe |
** compile. |
*/ |
-#if SQLITE_THREADSAFE |
+#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 |
case SQLITE_CONFIG_SINGLETHREAD: { |
/* Disable all mutexing */ |
sqlite3GlobalConfig.bCoreMutex = 0; |
@@ -350,6 +375,13 @@ int sqlite3_config(int op, ...){ |
sqlite3GlobalConfig.nHeap = va_arg(ap, int); |
sqlite3GlobalConfig.mnReq = va_arg(ap, int); |
+ if( sqlite3GlobalConfig.mnReq<1 ){ |
+ sqlite3GlobalConfig.mnReq = 1; |
+ }else if( sqlite3GlobalConfig.mnReq>(1<<12) ){ |
+ /* cap min request size at 2^12 */ |
+ sqlite3GlobalConfig.mnReq = (1<<12); |
+ } |
+ |
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 |
@@ -378,6 +410,21 @@ int sqlite3_config(int op, ...){ |
sqlite3GlobalConfig.nLookaside = va_arg(ap, int); |
break; |
} |
+ |
+ /* Record a pointer to the logger funcction and its first argument. |
+ ** The default is NULL. Logging is disabled if the function pointer is |
+ ** NULL. |
+ */ |
+ case SQLITE_CONFIG_LOG: { |
+ /* MSVC is picky about pulling func ptrs from va lists. |
+ ** http://support.microsoft.com/kb/47961 |
+ ** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*)); |
+ */ |
+ typedef void(*LOGFUNC_t)(void*,int,const char*); |
+ sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t); |
+ sqlite3GlobalConfig.pLogArg = va_arg(ap, void*); |
+ break; |
+ } |
default: { |
rc = SQLITE_ERROR; |
@@ -420,12 +467,12 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ |
sz = 0; |
pStart = 0; |
}else if( pBuf==0 ){ |
- sz = ROUND8(sz); |
+ sz = ROUNDDOWN8(sz); /* IMP: R-33038-09382 */ |
sqlite3BeginBenignMalloc(); |
- pStart = sqlite3Malloc( sz*cnt ); |
+ pStart = sqlite3Malloc( sz*cnt ); /* IMP: R-61949-35727 */ |
sqlite3EndBenignMalloc(); |
}else{ |
- sz = ROUNDDOWN8(sz); |
+ sz = ROUNDDOWN8(sz); /* IMP: R-33038-09382 */ |
pStart = pBuf; |
} |
db->lookaside.pStart = pStart; |
@@ -468,14 +515,42 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){ |
va_start(ap, op); |
switch( op ){ |
case SQLITE_DBCONFIG_LOOKASIDE: { |
- void *pBuf = va_arg(ap, void*); |
- int sz = va_arg(ap, int); |
- int cnt = va_arg(ap, int); |
+ void *pBuf = va_arg(ap, void*); /* IMP: R-26835-10964 */ |
+ int sz = va_arg(ap, int); /* IMP: R-47871-25994 */ |
+ int cnt = va_arg(ap, int); /* IMP: R-04460-53386 */ |
rc = setupLookaside(db, pBuf, sz, cnt); |
break; |
} |
default: { |
- rc = SQLITE_ERROR; |
+ static const struct { |
+ 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 }, |
+ }; |
+ unsigned int i; |
+ rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ |
+ for(i=0; i<ArraySize(aFlagOp); i++){ |
+ if( aFlagOp[i].op==op ){ |
+ int onoff = va_arg(ap, int); |
+ int *pRes = va_arg(ap, int*); |
+ int oldFlags = db->flags; |
+ if( onoff>0 ){ |
+ db->flags |= aFlagOp[i].mask; |
+ }else if( onoff==0 ){ |
+ db->flags &= ~aFlagOp[i].mask; |
+ } |
+ if( oldFlags!=db->flags ){ |
+ sqlite3ExpirePreparedStatements(db); |
+ } |
+ if( pRes ){ |
+ *pRes = (db->flags & aFlagOp[i].mask)!=0; |
+ } |
+ rc = SQLITE_OK; |
+ break; |
+ } |
+ } |
break; |
} |
} |
@@ -581,21 +656,39 @@ void sqlite3CloseSavepoints(sqlite3 *db){ |
} |
/* |
+** Invoke the destructor function associated with FuncDef p, if any. Except, |
+** if this is not the last copy of the function, do not invoke it. Multiple |
+** copies of a single function are created when create_function() is called |
+** with SQLITE_ANY as the encoding. |
+*/ |
+static void functionDestroy(sqlite3 *db, FuncDef *p){ |
+ FuncDestructor *pDestructor = p->pDestructor; |
+ if( pDestructor ){ |
+ pDestructor->nRef--; |
+ if( pDestructor->nRef==0 ){ |
+ pDestructor->xDestroy(pDestructor->pUserData); |
+ sqlite3DbFree(db, pDestructor); |
+ } |
+ } |
+} |
+ |
+/* |
** Close an existing SQLite database |
*/ |
int sqlite3_close(sqlite3 *db){ |
- HashElem *i; |
+ HashElem *i; /* Hash table iterator */ |
int j; |
if( !db ){ |
return SQLITE_OK; |
} |
if( !sqlite3SafetyCheckSickOrOk(db) ){ |
- return SQLITE_MISUSE; |
+ return SQLITE_MISUSE_BKPT; |
} |
sqlite3_mutex_enter(db->mutex); |
- sqlite3ResetInternalSchema(db, 0); |
+ /* Force xDestroy calls on all virtual tables */ |
+ sqlite3ResetInternalSchema(db, -1); |
/* If a transaction is open, the ResetInternalSchema() call above |
** will not have called the xDisconnect() method on any virtual |
@@ -638,7 +731,7 @@ int sqlite3_close(sqlite3 *db){ |
} |
} |
} |
- sqlite3ResetInternalSchema(db, 0); |
+ sqlite3ResetInternalSchema(db, -1); |
/* Tell the code in notify.c that the connection no longer holds any |
** locks and does not require any further unlock-notify callbacks. |
@@ -652,6 +745,7 @@ int sqlite3_close(sqlite3 *db){ |
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; |
@@ -728,9 +822,12 @@ void sqlite3RollbackAll(sqlite3 *db){ |
if( db->flags&SQLITE_InternChanges ){ |
sqlite3ExpirePreparedStatements(db); |
- sqlite3ResetInternalSchema(db, 0); |
+ sqlite3ResetInternalSchema(db, -1); |
} |
+ /* Any deferred constraint violations have now been resolved. */ |
+ db->nDeferredCons = 0; |
+ |
/* If one has been configured, invoke the rollback-hook callback */ |
if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ |
db->xRollbackCallback(db->pRollbackArg); |
@@ -755,10 +852,10 @@ const char *sqlite3ErrStr(int rc){ |
/* SQLITE_INTERRUPT */ "interrupted", |
/* SQLITE_IOERR */ "disk I/O error", |
/* SQLITE_CORRUPT */ "database disk image is malformed", |
- /* SQLITE_NOTFOUND */ 0, |
+ /* SQLITE_NOTFOUND */ "unknown operation", |
/* SQLITE_FULL */ "database or disk is full", |
/* SQLITE_CANTOPEN */ "unable to open database file", |
- /* SQLITE_PROTOCOL */ 0, |
+ /* SQLITE_PROTOCOL */ "locking protocol", |
/* SQLITE_EMPTY */ "table contains no data", |
/* SQLITE_SCHEMA */ "database schema has changed", |
/* SQLITE_TOOBIG */ "string or blob too big", |
@@ -794,7 +891,7 @@ static int sqliteDefaultBusyCallback( |
{ 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 }; |
static const u8 totals[] = |
{ 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 }; |
-# define NDELAY (sizeof(delays)/sizeof(delays[0])) |
+# define NDELAY ArraySize(delays) |
sqlite3 *db = (sqlite3 *)ptr; |
int timeout = db->busyTimeout; |
int delay, prior; |
@@ -923,7 +1020,8 @@ int sqlite3CreateFunc( |
void *pUserData, |
void (*xFunc)(sqlite3_context*,int,sqlite3_value **), |
void (*xStep)(sqlite3_context*,int,sqlite3_value **), |
- void (*xFinal)(sqlite3_context*) |
+ void (*xFinal)(sqlite3_context*), |
+ FuncDestructor *pDestructor |
){ |
FuncDef *p; |
int nName; |
@@ -935,7 +1033,7 @@ int sqlite3CreateFunc( |
(!xFunc && (!xFinal && xStep)) || |
(nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) || |
(255<(nName = sqlite3Strlen30( zFunctionName))) ){ |
- return SQLITE_MISUSE; |
+ return SQLITE_MISUSE_BKPT; |
} |
#ifndef SQLITE_OMIT_UTF16 |
@@ -951,10 +1049,10 @@ int sqlite3CreateFunc( |
}else if( enc==SQLITE_ANY ){ |
int rc; |
rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8, |
- pUserData, xFunc, xStep, xFinal); |
+ pUserData, xFunc, xStep, xFinal, pDestructor); |
if( rc==SQLITE_OK ){ |
rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE, |
- pUserData, xFunc, xStep, xFinal); |
+ pUserData, xFunc, xStep, xFinal, pDestructor); |
} |
if( rc!=SQLITE_OK ){ |
return rc; |
@@ -987,6 +1085,15 @@ int sqlite3CreateFunc( |
if( !p ){ |
return SQLITE_NOMEM; |
} |
+ |
+ /* If an older version of the function with a configured destructor is |
+ ** being replaced invoke the destructor function here. */ |
+ functionDestroy(db, p); |
+ |
+ if( pDestructor ){ |
+ pDestructor->nRef++; |
+ } |
+ p->pDestructor = pDestructor; |
p->flags = 0; |
p->xFunc = xFunc; |
p->xStep = xStep; |
@@ -1001,7 +1108,7 @@ int sqlite3CreateFunc( |
*/ |
int sqlite3_create_function( |
sqlite3 *db, |
- const char *zFunctionName, |
+ const char *zFunc, |
int nArg, |
int enc, |
void *p, |
@@ -1009,9 +1116,41 @@ int sqlite3_create_function( |
void (*xStep)(sqlite3_context*,int,sqlite3_value **), |
void (*xFinal)(sqlite3_context*) |
){ |
- int rc; |
+ return sqlite3_create_function_v2(db, zFunc, nArg, enc, p, xFunc, xStep, |
+ xFinal, 0); |
+} |
+ |
+int sqlite3_create_function_v2( |
+ sqlite3 *db, |
+ const char *zFunc, |
+ int nArg, |
+ int enc, |
+ void *p, |
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value **), |
+ void (*xStep)(sqlite3_context*,int,sqlite3_value **), |
+ void (*xFinal)(sqlite3_context*), |
+ void (*xDestroy)(void *) |
+){ |
+ int rc = SQLITE_ERROR; |
+ FuncDestructor *pArg = 0; |
sqlite3_mutex_enter(db->mutex); |
- rc = sqlite3CreateFunc(db, zFunctionName, nArg, enc, p, xFunc, xStep, xFinal); |
+ if( xDestroy ){ |
+ pArg = (FuncDestructor *)sqlite3DbMallocZero(db, sizeof(FuncDestructor)); |
+ if( !pArg ){ |
+ xDestroy(p); |
+ goto out; |
+ } |
+ pArg->xDestroy = xDestroy; |
+ pArg->pUserData = p; |
+ } |
+ rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, xFunc, xStep, xFinal, pArg); |
+ if( pArg && pArg->nRef==0 ){ |
+ assert( rc!=SQLITE_OK ); |
+ xDestroy(p); |
+ sqlite3DbFree(db, pArg); |
+ } |
+ |
+ out: |
rc = sqlite3ApiExit(db, rc); |
sqlite3_mutex_leave(db->mutex); |
return rc; |
@@ -1032,8 +1171,8 @@ int sqlite3_create_function16( |
char *zFunc8; |
sqlite3_mutex_enter(db->mutex); |
assert( !db->mallocFailed ); |
- zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1); |
- rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal); |
+ zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE); |
+ rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal,0); |
sqlite3DbFree(db, zFunc8); |
rc = sqlite3ApiExit(db, rc); |
sqlite3_mutex_leave(db->mutex); |
@@ -1064,7 +1203,7 @@ int sqlite3_overload_function( |
sqlite3_mutex_enter(db->mutex); |
if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){ |
sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8, |
- 0, sqlite3InvalidFunction, 0, 0); |
+ 0, sqlite3InvalidFunction, 0, 0, 0); |
} |
rc = sqlite3ApiExit(db, SQLITE_OK); |
sqlite3_mutex_leave(db->mutex); |
@@ -1168,6 +1307,174 @@ void *sqlite3_rollback_hook( |
return pRet; |
} |
+#ifndef SQLITE_OMIT_WAL |
+/* |
+** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint(). |
+** Invoke sqlite3_wal_checkpoint if the number of frames in the log file |
+** is greater than sqlite3.pWalArg cast to an integer (the value configured by |
+** wal_autocheckpoint()). |
+*/ |
+int sqlite3WalDefaultHook( |
+ void *pClientData, /* Argument */ |
+ sqlite3 *db, /* Connection */ |
+ const char *zDb, /* Database */ |
+ int nFrame /* Size of WAL */ |
+){ |
+ if( nFrame>=SQLITE_PTR_TO_INT(pClientData) ){ |
+ sqlite3BeginBenignMalloc(); |
+ sqlite3_wal_checkpoint(db, zDb); |
+ sqlite3EndBenignMalloc(); |
+ } |
+ return SQLITE_OK; |
+} |
+#endif /* SQLITE_OMIT_WAL */ |
+ |
+/* |
+** Configure an sqlite3_wal_hook() callback to automatically checkpoint |
+** a database after committing a transaction if there are nFrame or |
+** more frames in the log file. Passing zero or a negative value as the |
+** nFrame parameter disables automatic checkpoints entirely. |
+** |
+** The callback registered by this function replaces any existing callback |
+** registered using sqlite3_wal_hook(). Likewise, registering a callback |
+** using sqlite3_wal_hook() disables the automatic checkpoint mechanism |
+** configured by this function. |
+*/ |
+int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){ |
+#ifdef SQLITE_OMIT_WAL |
+ UNUSED_PARAMETER(db); |
+ UNUSED_PARAMETER(nFrame); |
+#else |
+ if( nFrame>0 ){ |
+ sqlite3_wal_hook(db, sqlite3WalDefaultHook, SQLITE_INT_TO_PTR(nFrame)); |
+ }else{ |
+ sqlite3_wal_hook(db, 0, 0); |
+ } |
+#endif |
+ return SQLITE_OK; |
+} |
+ |
+/* |
+** Register a callback to be invoked each time a transaction is written |
+** into the write-ahead-log by this database connection. |
+*/ |
+void *sqlite3_wal_hook( |
+ sqlite3 *db, /* Attach the hook to this db handle */ |
+ int(*xCallback)(void *, sqlite3*, const char*, int), |
+ void *pArg /* First argument passed to xCallback() */ |
+){ |
+#ifndef SQLITE_OMIT_WAL |
+ void *pRet; |
+ sqlite3_mutex_enter(db->mutex); |
+ pRet = db->pWalArg; |
+ db->xWalCallback = xCallback; |
+ db->pWalArg = pArg; |
+ sqlite3_mutex_leave(db->mutex); |
+ return pRet; |
+#else |
+ return 0; |
+#endif |
+} |
+ |
+/* |
+** Checkpoint database zDb. |
+*/ |
+int sqlite3_wal_checkpoint_v2( |
+ sqlite3 *db, /* Database handle */ |
+ const char *zDb, /* Name of attached database (or NULL) */ |
+ int eMode, /* SQLITE_CHECKPOINT_* value */ |
+ int *pnLog, /* OUT: Size of WAL log in frames */ |
+ int *pnCkpt /* OUT: Total number of frames checkpointed */ |
+){ |
+#ifdef SQLITE_OMIT_WAL |
+ return SQLITE_OK; |
+#else |
+ int rc; /* Return code */ |
+ int iDb = SQLITE_MAX_ATTACHED; /* sqlite3.aDb[] index of db to checkpoint */ |
+ |
+ /* 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 ){ |
+ return SQLITE_MISUSE; |
+ } |
+ |
+ sqlite3_mutex_enter(db->mutex); |
+ if( zDb && zDb[0] ){ |
+ iDb = sqlite3FindDbName(db, zDb); |
+ } |
+ if( iDb<0 ){ |
+ rc = SQLITE_ERROR; |
+ sqlite3Error(db, SQLITE_ERROR, "unknown database: %s", zDb); |
+ }else{ |
+ rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt); |
+ sqlite3Error(db, rc, 0); |
+ } |
+ rc = sqlite3ApiExit(db, rc); |
+ sqlite3_mutex_leave(db->mutex); |
+ return rc; |
+#endif |
+} |
+ |
+ |
+/* |
+** Checkpoint database zDb. If zDb is NULL, or if the buffer zDb points |
+** to contains a zero-length string, all attached databases are |
+** checkpointed. |
+*/ |
+int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ |
+ return sqlite3_wal_checkpoint_v2(db, zDb, SQLITE_CHECKPOINT_PASSIVE, 0, 0); |
+} |
+ |
+#ifndef SQLITE_OMIT_WAL |
+/* |
+** Run a checkpoint on database iDb. This is a no-op if database iDb is |
+** not currently open in WAL mode. |
+** |
+** If a transaction is open on the database being checkpointed, this |
+** function returns SQLITE_LOCKED and a checkpoint is not attempted. If |
+** an error occurs while running the checkpoint, an SQLite error code is |
+** returned (i.e. SQLITE_IOERR). Otherwise, SQLITE_OK. |
+** |
+** The mutex on database handle db should be held by the caller. The mutex |
+** associated with the specific b-tree being checkpointed is taken by |
+** this function while the checkpoint is running. |
+** |
+** If iDb is passed SQLITE_MAX_ATTACHED, then all attached databases are |
+** checkpointed. If an error is encountered it is returned immediately - |
+** no attempt is made to checkpoint any remaining databases. |
+** |
+** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. |
+*/ |
+int sqlite3Checkpoint(sqlite3 *db, int iDb, int eMode, int *pnLog, int *pnCkpt){ |
+ int rc = SQLITE_OK; /* Return code */ |
+ int i; /* Used to iterate through attached dbs */ |
+ int bBusy = 0; /* True if SQLITE_BUSY has been encountered */ |
+ |
+ assert( sqlite3_mutex_held(db->mutex) ); |
+ assert( !pnLog || *pnLog==-1 ); |
+ assert( !pnCkpt || *pnCkpt==-1 ); |
+ |
+ for(i=0; i<db->nDb && rc==SQLITE_OK; i++){ |
+ if( i==iDb || iDb==SQLITE_MAX_ATTACHED ){ |
+ rc = sqlite3BtreeCheckpoint(db->aDb[i].pBt, eMode, pnLog, pnCkpt); |
+ pnLog = 0; |
+ pnCkpt = 0; |
+ if( rc==SQLITE_BUSY ){ |
+ bBusy = 1; |
+ rc = SQLITE_OK; |
+ } |
+ } |
+ } |
+ |
+ return (rc==SQLITE_OK && bBusy) ? SQLITE_BUSY : rc; |
+} |
+#endif /* SQLITE_OMIT_WAL */ |
+ |
/* |
** This function returns true if main-memory should be used instead of |
** a temporary file for transient pager files and statement journals. |
@@ -1203,60 +1510,6 @@ int sqlite3TempInMemory(const sqlite3 *db){ |
} |
/* |
-** This routine is called to create a connection to a database BTree |
-** driver. If zFilename is the name of a file, then that file is |
-** opened and used. If zFilename is the magic name ":memory:" then |
-** the database is stored in memory (and is thus forgotten as soon as |
-** the connection is closed.) If zFilename is NULL then the database |
-** is a "virtual" database for transient use only and is deleted as |
-** soon as the connection is closed. |
-** |
-** A virtual database can be either a disk file (that is automatically |
-** deleted when the file is closed) or it an be held entirely in memory. |
-** The sqlite3TempInMemory() function is used to determine which. |
-*/ |
-int sqlite3BtreeFactory( |
- const sqlite3 *db, /* Main database when opening aux otherwise 0 */ |
- const char *zFilename, /* Name of the file containing the BTree database */ |
- int omitJournal, /* if TRUE then do not journal this file */ |
- int nCache, /* How many pages in the page cache */ |
- int vfsFlags, /* Flags passed through to vfsOpen */ |
- Btree **ppBtree /* Pointer to new Btree object written here */ |
-){ |
- int btFlags = 0; |
- int rc; |
- |
- assert( sqlite3_mutex_held(db->mutex) ); |
- assert( ppBtree != 0); |
- if( omitJournal ){ |
- btFlags |= BTREE_OMIT_JOURNAL; |
- } |
- if( db->flags & SQLITE_NoReadlock ){ |
- btFlags |= BTREE_NO_READLOCK; |
- } |
-#ifndef SQLITE_OMIT_MEMORYDB |
- if( zFilename==0 && sqlite3TempInMemory(db) ){ |
- zFilename = ":memory:"; |
- } |
-#endif |
- |
- if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (zFilename==0 || *zFilename==0) ){ |
- vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB; |
- } |
- rc = sqlite3BtreeOpen(zFilename, (sqlite3 *)db, ppBtree, btFlags, vfsFlags); |
- |
- /* If the B-Tree was successfully opened, set the pager-cache size to the |
- ** default value. Except, if the call to BtreeOpen() returned a handle |
- ** open on an existing shared pager-cache, do not change the pager-cache |
- ** size. |
- */ |
- if( rc==SQLITE_OK && 0==sqlite3BtreeSchema(*ppBtree, 0, 0) ){ |
- sqlite3BtreeSetCacheSize(*ppBtree, nCache); |
- } |
- return rc; |
-} |
- |
-/* |
** Return UTF-8 encoded English language explanation of the most recent |
** error. |
*/ |
@@ -1266,7 +1519,7 @@ const char *sqlite3_errmsg(sqlite3 *db){ |
return sqlite3ErrStr(SQLITE_NOMEM); |
} |
if( !sqlite3SafetyCheckSickOrOk(db) ){ |
- return sqlite3ErrStr(SQLITE_MISUSE); |
+ return sqlite3ErrStr(SQLITE_MISUSE_BKPT); |
} |
sqlite3_mutex_enter(db->mutex); |
if( db->mallocFailed ){ |
@@ -1335,7 +1588,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){ |
*/ |
int sqlite3_errcode(sqlite3 *db){ |
if( db && !sqlite3SafetyCheckSickOrOk(db) ){ |
- return SQLITE_MISUSE; |
+ return SQLITE_MISUSE_BKPT; |
} |
if( !db || db->mallocFailed ){ |
return SQLITE_NOMEM; |
@@ -1344,7 +1597,7 @@ int sqlite3_errcode(sqlite3 *db){ |
} |
int sqlite3_extended_errcode(sqlite3 *db){ |
if( db && !sqlite3SafetyCheckSickOrOk(db) ){ |
- return SQLITE_MISUSE; |
+ return SQLITE_MISUSE_BKPT; |
} |
if( !db || db->mallocFailed ){ |
return SQLITE_NOMEM; |
@@ -1382,7 +1635,7 @@ static int createCollation( |
enc2 = SQLITE_UTF16NATIVE; |
} |
if( enc2<SQLITE_UTF8 || enc2>SQLITE_UTF16BE ){ |
- return SQLITE_MISUSE; |
+ return SQLITE_MISUSE_BKPT; |
} |
/* Check if this call is removing or replacing an existing collation |
@@ -1420,13 +1673,12 @@ static int createCollation( |
} |
pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 1); |
- if( pColl ){ |
- pColl->xCmp = xCompare; |
- pColl->pUser = pCtx; |
- pColl->xDel = xDel; |
- pColl->enc = (u8)(enc2 | (enc & SQLITE_UTF16_ALIGNED)); |
- pColl->type = collType; |
- } |
+ if( pColl==0 ) return SQLITE_NOMEM; |
+ pColl->xCmp = xCompare; |
+ pColl->pUser = pCtx; |
+ pColl->xDel = xDel; |
+ pColl->enc = (u8)(enc2 | (enc & SQLITE_UTF16_ALIGNED)); |
+ pColl->type = collType; |
sqlite3Error(db, SQLITE_OK, 0); |
return SQLITE_OK; |
} |
@@ -1472,15 +1724,12 @@ static const int aHardLimit[] = { |
#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>1000 |
# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 1000 |
#endif |
-#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>30 |
-# error SQLITE_MAX_ATTACHED must be between 0 and 30 |
+#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>62 |
+# error SQLITE_MAX_ATTACHED must be between 0 and 62 |
#endif |
#if SQLITE_MAX_LIKE_PATTERN_LENGTH<1 |
# error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1 |
#endif |
-#if SQLITE_MAX_VARIABLE_NUMBER<1 |
-# error SQLITE_MAX_VARIABLE_NUMBER must be at least 1 |
-#endif |
#if SQLITE_MAX_COLUMN>32767 |
# error SQLITE_MAX_COLUMN must not exceed 32767 |
#endif |
@@ -1501,17 +1750,39 @@ static const int aHardLimit[] = { |
*/ |
int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ |
int oldLimit; |
+ |
+ |
+ /* 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 |
+ ** macro called SQLITE_MAX_NAME. (The "_LIMIT_" in the name is changed to |
+ ** "_MAX_".) |
+ */ |
+ assert( aHardLimit[SQLITE_LIMIT_LENGTH]==SQLITE_MAX_LENGTH ); |
+ assert( aHardLimit[SQLITE_LIMIT_SQL_LENGTH]==SQLITE_MAX_SQL_LENGTH ); |
+ assert( aHardLimit[SQLITE_LIMIT_COLUMN]==SQLITE_MAX_COLUMN ); |
+ assert( aHardLimit[SQLITE_LIMIT_EXPR_DEPTH]==SQLITE_MAX_EXPR_DEPTH ); |
+ assert( aHardLimit[SQLITE_LIMIT_COMPOUND_SELECT]==SQLITE_MAX_COMPOUND_SELECT); |
+ assert( aHardLimit[SQLITE_LIMIT_VDBE_OP]==SQLITE_MAX_VDBE_OP ); |
+ assert( aHardLimit[SQLITE_LIMIT_FUNCTION_ARG]==SQLITE_MAX_FUNCTION_ARG ); |
+ assert( aHardLimit[SQLITE_LIMIT_ATTACHED]==SQLITE_MAX_ATTACHED ); |
+ assert( aHardLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]== |
+ SQLITE_MAX_LIKE_PATTERN_LENGTH ); |
+ assert( aHardLimit[SQLITE_LIMIT_VARIABLE_NUMBER]==SQLITE_MAX_VARIABLE_NUMBER); |
+ assert( aHardLimit[SQLITE_LIMIT_TRIGGER_DEPTH]==SQLITE_MAX_TRIGGER_DEPTH ); |
+ assert( SQLITE_LIMIT_TRIGGER_DEPTH==(SQLITE_N_LIMIT-1) ); |
+ |
+ |
if( limitId<0 || limitId>=SQLITE_N_LIMIT ){ |
return -1; |
} |
oldLimit = db->aLimit[limitId]; |
- if( newLimit>=0 ){ |
+ if( newLimit>=0 ){ /* IMP: R-52476-28732 */ |
if( newLimit>aHardLimit[limitId] ){ |
- newLimit = aHardLimit[limitId]; |
+ newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */ |
} |
db->aLimit[limitId] = newLimit; |
} |
- return oldLimit; |
+ return oldLimit; /* IMP: R-53341-35419 */ |
} |
/* |
@@ -1535,6 +1806,24 @@ static int openDatabase( |
if( rc ) return rc; |
#endif |
+ /* Only allow sensible combinations of bits in the flags argument. |
+ ** Throw an error if any non-sense combination is used. If we |
+ ** do not block illegal combinations here, it could trigger |
+ ** assert() statements in deeper layers. Sensible combinations |
+ ** are: |
+ ** |
+ ** 1: SQLITE_OPEN_READONLY |
+ ** 2: SQLITE_OPEN_READWRITE |
+ ** 6: SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
+ */ |
+ assert( SQLITE_OPEN_READONLY == 0x01 ); |
+ assert( SQLITE_OPEN_READWRITE == 0x02 ); |
+ assert( SQLITE_OPEN_CREATE == 0x04 ); |
+ testcase( (1<<(flags&7))==0x02 ); /* READONLY */ |
+ testcase( (1<<(flags&7))==0x04 ); /* READWRITE */ |
+ testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */ |
+ if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE; |
+ |
if( sqlite3GlobalConfig.bCoreMutex==0 ){ |
isThreadsafe = 0; |
}else if( flags & SQLITE_OPEN_NOMUTEX ){ |
@@ -1555,7 +1844,8 @@ static int openDatabase( |
** The SQLITE_OPEN_NOMUTEX and SQLITE_OPEN_FULLMUTEX flags were |
** 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, and SQLITE_OPEN_CREATE. Silently mask |
+ ** SQLITE_OPEN_READWRITE, SQLITE_OPEN_CREATE, SQLITE_OPEN_SHAREDCACHE, |
+ ** SQLITE_OPEN_PRIVATECACHE, and some reserved bits. Silently mask |
** off all other flags. |
*/ |
flags &= ~( SQLITE_OPEN_DELETEONCLOSE | |
@@ -1568,7 +1858,8 @@ static int openDatabase( |
SQLITE_OPEN_SUBJOURNAL | |
SQLITE_OPEN_MASTER_JOURNAL | |
SQLITE_OPEN_NOMUTEX | |
- SQLITE_OPEN_FULLMUTEX |
+ SQLITE_OPEN_FULLMUTEX | |
+ SQLITE_OPEN_WAL |
); |
/* Allocate the sqlite data structure */ |
@@ -1593,7 +1884,7 @@ static int openDatabase( |
db->autoCommit = 1; |
db->nextAutovac = -1; |
db->nextPagesize = 0; |
- db->flags |= SQLITE_ShortColNames |
+ db->flags |= SQLITE_ShortColNames | SQLITE_AutoIndex | SQLITE_EnableTrigger |
#if SQLITE_DEFAULT_FILE_FORMAT<4 |
| SQLITE_LegacyFileFmt |
#endif |
@@ -1603,6 +1894,9 @@ static int openDatabase( |
#if SQLITE_DEFAULT_RECURSIVE_TRIGGERS |
| SQLITE_RecTriggers |
#endif |
+#if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS |
+ | SQLITE_ForeignKeys |
+#endif |
; |
sqlite3HashInit(&db->aCollSeq); |
#ifndef SQLITE_OMIT_VIRTUALTABLE |
@@ -1640,9 +1934,8 @@ static int openDatabase( |
/* Open the backend database driver */ |
db->openFlags = flags; |
- rc = sqlite3BtreeFactory(db, zFilename, 0, SQLITE_DEFAULT_CACHE_SIZE, |
- flags | SQLITE_OPEN_MAIN_DB, |
- &db->aDb[0].pBt); |
+ rc = sqlite3BtreeOpen(zFilename, db, &db->aDb[0].pBt, 0, |
+ flags | SQLITE_OPEN_MAIN_DB); |
if( rc!=SQLITE_OK ){ |
if( rc==SQLITE_IOERR_NOMEM ){ |
rc = SQLITE_NOMEM; |
@@ -1731,6 +2024,8 @@ static int openDatabase( |
setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside, |
sqlite3GlobalConfig.nLookaside); |
+ sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT); |
+ |
opendb_out: |
if( db ){ |
assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 ); |
@@ -1858,7 +2153,7 @@ int sqlite3_create_collation16( |
char *zName8; |
sqlite3_mutex_enter(db->mutex); |
assert( !db->mallocFailed ); |
- zName8 = sqlite3Utf16to8(db, zName, -1); |
+ zName8 = sqlite3Utf16to8(db, zName, -1, SQLITE_UTF16NATIVE); |
if( zName8 ){ |
rc = createCollation(db, zName8, (u8)enc, SQLITE_COLL_USER, pCtx, xCompare, 0); |
sqlite3DbFree(db, zName8); |
@@ -1905,7 +2200,6 @@ int sqlite3_collation_needed16( |
} |
#endif /* SQLITE_OMIT_UTF16 */ |
-#ifndef SQLITE_OMIT_GLOBALRECOVER |
#ifndef SQLITE_OMIT_DEPRECATED |
/* |
** This function is now an anachronism. It used to be used to recover from a |
@@ -1915,7 +2209,6 @@ int sqlite3_global_recover(void){ |
return SQLITE_OK; |
} |
#endif |
-#endif |
/* |
** Test to see whether or not the database connection is in autocommit |
@@ -1929,16 +2222,39 @@ int sqlite3_get_autocommit(sqlite3 *db){ |
return db->autoCommit; |
} |
-#ifdef SQLITE_DEBUG |
/* |
-** The following routine is subtituted for constant SQLITE_CORRUPT in |
-** debugging builds. This provides a way to set a breakpoint for when |
-** corruption is first detected. |
+** The following routines are subtitutes for constants SQLITE_CORRUPT, |
+** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_IOERR and possibly other error |
+** constants. They server two purposes: |
+** |
+** 1. Serve as a convenient place to set a breakpoint in a debugger |
+** to detect when version error conditions occurs. |
+** |
+** 2. Invoke sqlite3_log() to provide the source code location where |
+** a low-level error is first detected. |
*/ |
-int sqlite3Corrupt(void){ |
+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; |
} |
-#endif |
+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; |
+} |
+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; |
+} |
+ |
#ifndef SQLITE_OMIT_DEPRECATED |
/* |
@@ -1982,7 +2298,6 @@ int sqlite3_table_column_metadata( |
/* Ensure the database schema has been loaded */ |
sqlite3_mutex_enter(db->mutex); |
- (void)sqlite3SafetyOn(db); |
sqlite3BtreeEnterAll(db); |
rc = sqlite3Init(db, &zErrMsg); |
if( SQLITE_OK!=rc ){ |
@@ -2041,7 +2356,6 @@ int sqlite3_table_column_metadata( |
error_out: |
sqlite3BtreeLeaveAll(db); |
- (void)sqlite3SafetyOff(db); |
/* Whether the function call succeeded or failed, set the output parameters |
** to whatever their local counterparts contain. If an error did occur, |
@@ -2117,8 +2431,13 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ |
assert( pPager!=0 ); |
fd = sqlite3PagerFile(pPager); |
assert( fd!=0 ); |
- if( fd->pMethods ){ |
+ if( op==SQLITE_FCNTL_FILE_POINTER ){ |
+ *(sqlite3_file**)pArg = fd; |
+ rc = SQLITE_OK; |
+ }else if( fd->pMethods ){ |
rc = sqlite3OsFileControl(fd, op, pArg); |
+ }else{ |
+ rc = SQLITE_NOTFOUND; |
} |
sqlite3BtreeLeave(pBtree); |
} |
@@ -2209,9 +2528,13 @@ int sqlite3_test_control(int op, ...){ |
** dileterious behavior. |
*/ |
case SQLITE_TESTCTRL_PENDING_BYTE: { |
- unsigned int newVal = va_arg(ap, unsigned int); |
- rc = sqlite3PendingByte; |
- if( newVal ) sqlite3PendingByte = newVal; |
+ rc = PENDING_BYTE; |
+#ifndef SQLITE_OMIT_WSD |
+ { |
+ unsigned int newVal = va_arg(ap, unsigned int); |
+ if( newVal ) sqlite3PendingByte = newVal; |
+ } |
+#endif |
break; |
} |
@@ -2281,6 +2604,65 @@ int sqlite3_test_control(int op, ...){ |
break; |
} |
+ /* sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, sqlite3 *db, int N) |
+ ** |
+ ** Enable or disable various optimizations for testing purposes. The |
+ ** argument N is a bitmask of optimizations to be disabled. For normal |
+ ** operation N should be 0. The idea is that a test program (like the |
+ ** SQL Logic Test or SLT test module) can run the same SQL multiple times |
+ ** with various optimizations disabled to verify that the same answer |
+ ** is obtained in every case. |
+ */ |
+ case SQLITE_TESTCTRL_OPTIMIZATIONS: { |
+ sqlite3 *db = va_arg(ap, sqlite3*); |
+ int x = va_arg(ap,int); |
+ db->flags = (x & SQLITE_OptMask) | (db->flags & ~SQLITE_OptMask); |
+ break; |
+ } |
+ |
+#ifdef SQLITE_N_KEYWORD |
+ /* sqlite3_test_control(SQLITE_TESTCTRL_ISKEYWORD, const char *zWord) |
+ ** |
+ ** If zWord is a keyword recognized by the parser, then return the |
+ ** number of keywords. Or if zWord is not a keyword, return 0. |
+ ** |
+ ** This test feature is only available in the amalgamation since |
+ ** the SQLITE_N_KEYWORD macro is not defined in this file if SQLite |
+ ** is built using separate source files. |
+ */ |
+ case SQLITE_TESTCTRL_ISKEYWORD: { |
+ const char *zWord = va_arg(ap, const char*); |
+ int n = sqlite3Strlen30(zWord); |
+ rc = (sqlite3KeywordCode((u8*)zWord, n)!=TK_ID) ? SQLITE_N_KEYWORD : 0; |
+ break; |
+ } |
+#endif |
+ |
+ /* sqlite3_test_control(SQLITE_TESTCTRL_PGHDRSZ) |
+ ** |
+ ** Return the size of a pcache header in bytes. |
+ */ |
+ case SQLITE_TESTCTRL_PGHDRSZ: { |
+ rc = sizeof(PgHdr); |
+ break; |
+ } |
+ |
+ /* sqlite3_test_control(SQLITE_TESTCTRL_SCRATCHMALLOC, sz, &pNew, pFree); |
+ ** |
+ ** Pass pFree into sqlite3ScratchFree(). |
+ ** If sz>0 then allocate a scratch buffer into pNew. |
+ */ |
+ case SQLITE_TESTCTRL_SCRATCHMALLOC: { |
+ void *pFree, **ppNew; |
+ int sz; |
+ sz = va_arg(ap, int); |
+ ppNew = va_arg(ap, void**); |
+ pFree = va_arg(ap, void*); |
+ if( sz ) *ppNew = sqlite3ScratchMalloc(sz); |
+ sqlite3ScratchFree(pFree); |
+ break; |
+ } |
+ |
} |
va_end(ap); |
#endif /* SQLITE_OMIT_BUILTIN_TEST */ |