diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/alter.c | 2 | ||||
-rw-r--r-- | src/attach.c | 31 | ||||
-rw-r--r-- | src/btree.c | 12 | ||||
-rw-r--r-- | src/build.c | 4 | ||||
-rw-r--r-- | src/ctime.c | 406 | ||||
-rw-r--r-- | src/fkey.c | 10 | ||||
-rw-r--r-- | src/legacy.c | 7 | ||||
-rw-r--r-- | src/main.c | 56 | ||||
-rw-r--r-- | src/parse.y | 3 | ||||
-rw-r--r-- | src/pragma.h | 10 | ||||
-rw-r--r-- | src/prepare.c | 8 | ||||
-rw-r--r-- | src/select.c | 11 | ||||
-rw-r--r-- | src/shell.c | 209 | ||||
-rw-r--r-- | src/sqlite.h.in | 12 | ||||
-rw-r--r-- | src/sqliteInt.h | 68 | ||||
-rw-r--r-- | src/tclsqlite.c | 51 | ||||
-rw-r--r-- | src/test1.c | 1 | ||||
-rw-r--r-- | src/vacuum.c | 2 | ||||
-rw-r--r-- | src/vdbe.c | 2 | ||||
-rw-r--r-- | src/vdbeaux.c | 2 | ||||
-rw-r--r-- | src/vdbemem.c | 11 | ||||
-rw-r--r-- | src/where.c | 58 | ||||
-rw-r--r-- | src/whereexpr.c | 5 |
23 files changed, 753 insertions, 228 deletions
diff --git a/src/alter.c b/src/alter.c index 067cbb896..8df06f064 100644 --- a/src/alter.c +++ b/src/alter.c @@ -375,7 +375,7 @@ static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){ ** Or, if zName is not a system table, zero is returned. */ static int isSystemTable(Parse *pParse, const char *zName){ - if( sqlite3Strlen30(zName)>6 && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ + if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ sqlite3ErrorMsg(pParse, "table %s may not be altered", zName); return 1; } diff --git a/src/attach.c b/src/attach.c index 393c46ccb..4a80008cb 100644 --- a/src/attach.c +++ b/src/attach.c @@ -69,7 +69,8 @@ static void attachFunc( char *zPath = 0; char *zErr = 0; unsigned int flags; - Db *aNew; + Db *aNew; /* New array of Db pointers */ + Db *pNew; /* Db object for the newly attached database */ char *zErrDyn = 0; sqlite3_vfs *pVfs; @@ -117,8 +118,8 @@ static void attachFunc( if( aNew==0 ) return; } db->aDb = aNew; - aNew = &db->aDb[db->nDb]; - memset(aNew, 0, sizeof(*aNew)); + pNew = &db->aDb[db->nDb]; + memset(pNew, 0, sizeof(*pNew)); /* Open the database file. If the btree is successfully opened, use ** it to obtain the database schema. At this point the schema may @@ -134,7 +135,7 @@ static void attachFunc( } assert( pVfs ); flags |= SQLITE_OPEN_MAIN_DB; - rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags); + rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags); sqlite3_free( zPath ); db->nDb++; db->skipBtreeMutex = 0; @@ -143,28 +144,28 @@ static void attachFunc( zErrDyn = sqlite3MPrintf(db, "database is already attached"); }else if( rc==SQLITE_OK ){ Pager *pPager; - aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt); - if( !aNew->pSchema ){ + pNew->pSchema = sqlite3SchemaGet(db, pNew->pBt); + if( !pNew->pSchema ){ rc = SQLITE_NOMEM_BKPT; - }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){ + }else if( pNew->pSchema->file_format && pNew->pSchema->enc!=ENC(db) ){ zErrDyn = sqlite3MPrintf(db, "attached databases must use the same text encoding as main database"); rc = SQLITE_ERROR; } - sqlite3BtreeEnter(aNew->pBt); - pPager = sqlite3BtreePager(aNew->pBt); + sqlite3BtreeEnter(pNew->pBt); + pPager = sqlite3BtreePager(pNew->pBt); sqlite3PagerLockingMode(pPager, db->dfltLockMode); - sqlite3BtreeSecureDelete(aNew->pBt, + sqlite3BtreeSecureDelete(pNew->pBt, sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); #ifndef SQLITE_OMIT_PAGER_PRAGMAS - sqlite3BtreeSetPagerFlags(aNew->pBt, + sqlite3BtreeSetPagerFlags(pNew->pBt, PAGER_SYNCHRONOUS_FULL | (db->flags & PAGER_FLAGS_MASK)); #endif - sqlite3BtreeLeave(aNew->pBt); + sqlite3BtreeLeave(pNew->pBt); } - aNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; - aNew->zDbSName = sqlite3DbStrDup(db, zName); - if( rc==SQLITE_OK && aNew->zDbSName==0 ){ + pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; + pNew->zDbSName = sqlite3DbStrDup(db, zName); + if( rc==SQLITE_OK && pNew->zDbSName==0 ){ rc = SQLITE_NOMEM_BKPT; } diff --git a/src/btree.c b/src/btree.c index c54433c8e..be6c0dd17 100644 --- a/src/btree.c +++ b/src/btree.c @@ -152,7 +152,7 @@ static int hasSharedCacheTableLock( ** Return true immediately. */ if( (pBtree->sharable==0) - || (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommitted)) + || (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommit)) ){ return 1; } @@ -229,7 +229,7 @@ static int hasReadConflicts(Btree *pBtree, Pgno iRoot){ for(p=pBtree->pBt->pCursor; p; p=p->pNext){ if( p->pgnoRoot==iRoot && p->pBtree!=pBtree - && 0==(p->pBtree->db->flags & SQLITE_ReadUncommitted) + && 0==(p->pBtree->db->flags & SQLITE_ReadUncommit) ){ return 1; } @@ -251,7 +251,7 @@ static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){ assert( sqlite3BtreeHoldsMutex(p) ); assert( eLock==READ_LOCK || eLock==WRITE_LOCK ); assert( p->db!=0 ); - assert( !(p->db->flags&SQLITE_ReadUncommitted)||eLock==WRITE_LOCK||iTab==1 ); + assert( !(p->db->flags&SQLITE_ReadUncommit)||eLock==WRITE_LOCK||iTab==1 ); /* If requesting a write-lock, then the Btree must have an open write ** transaction on this file. And, obviously, for this to be so there @@ -329,7 +329,7 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){ ** obtain a read-lock using this function. The only read-lock obtained ** by a connection in read-uncommitted mode is on the sqlite_master ** table, and that lock is obtained in BtreeBeginTrans(). */ - assert( 0==(p->db->flags&SQLITE_ReadUncommitted) || eLock==WRITE_LOCK ); + assert( 0==(p->db->flags&SQLITE_ReadUncommit) || eLock==WRITE_LOCK ); /* This function should only be called on a sharable b-tree after it ** has been determined that no other b-tree holds a conflicting lock. */ @@ -3021,7 +3021,7 @@ static int lockBtree(BtShared *pBt){ pageSize-usableSize); return rc; } - if( (pBt->db->flags & SQLITE_RecoveryMode)==0 && nPage>nPageFile ){ + if( (pBt->db->flags & SQLITE_WriteSchema)==0 && nPage>nPageFile ){ rc = SQLITE_CORRUPT_BKPT; goto page1_init_failed; } @@ -5716,7 +5716,7 @@ static int allocateBtreePage( } testcase( iTrunk==mxPage ); if( iTrunk>mxPage || nSearch++ > n ){ - rc = SQLITE_CORRUPT_PGNO(pPrevTrunk->pgno); + rc = SQLITE_CORRUPT_PGNO(pPrevTrunk ? pPrevTrunk->pgno : 1); }else{ rc = btreeGetUnusedPage(pBt, iTrunk, &pTrunk, 0); } diff --git a/src/build.c b/src/build.c index c4bb0300a..8a0624ea1 100644 --- a/src/build.c +++ b/src/build.c @@ -4185,7 +4185,9 @@ void sqlite3UniqueConstraint( assert( pIdx->aiColumn[j]>=0 ); zCol = pTab->aCol[pIdx->aiColumn[j]].zName; if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2); - sqlite3XPrintf(&errMsg, "%s.%s", pTab->zName, zCol); + sqlite3StrAccumAppendAll(&errMsg, pTab->zName); + sqlite3StrAccumAppend(&errMsg, ".", 1); + sqlite3StrAccumAppendAll(&errMsg, zCol); } } zErr = sqlite3StrAccumFinish(&errMsg); diff --git a/src/ctime.c b/src/ctime.c index 20e94edba..25df46c62 100644 --- a/src/ctime.c +++ b/src/ctime.c @@ -16,7 +16,19 @@ #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS -#include "sqliteInt.h" +/* +** Include the configuration header output by 'configure' if we're using the +** autoconf-based build +*/ +#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H) +#include "config.h" +#define SQLITECONFIG_H 1 +#endif + +/* These macros are provided to "stringify" the value of the define +** for those options in which the value is meaningful. */ +#define CTIMEOPT_VAL_(opt) #opt +#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) /* ** An array of names of all compile-time options. This array should @@ -26,19 +38,32 @@ ** only a handful of compile-time options, so most times this array is usually ** rather short and uses little memory space. */ -static const char * const azCompileOpt[] = { - -/* These macros are provided to "stringify" the value of the define -** for those options in which the value is meaningful. */ -#define CTIMEOPT_VAL_(opt) #opt -#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) +static const char * const sqlite3azCompileOpt[] = { +/* +** BEGIN CODE GENERATED BY tool/mkctime.tcl +*/ #if SQLITE_32BIT_ROWID "32BIT_ROWID", #endif #if SQLITE_4_BYTE_ALIGNED_MALLOC "4_BYTE_ALIGNED_MALLOC", #endif +#if SQLITE_64BIT_STATS + "64BIT_STATS", +#endif +#if SQLITE_ALLOW_COVERING_INDEX_SCAN + "ALLOW_COVERING_INDEX_SCAN", +#endif +#if SQLITE_ALLOW_URI_AUTHORITY + "ALLOW_URI_AUTHORITY", +#endif +#ifdef SQLITE_BITMASK_TYPE + "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE), +#endif +#if SQLITE_BUG_COMPATIBLE_20160819 + "BUG_COMPATIBLE_20160819", +#endif #if SQLITE_CASE_SENSITIVE_LIKE "CASE_SENSITIVE_LIKE", #endif @@ -57,31 +82,100 @@ static const char * const azCompileOpt[] = { #if SQLITE_COVERAGE_TEST "COVERAGE_TEST", #endif -#ifdef SQLITE_DEBUG +#if SQLITE_DEBUG "DEBUG", #endif -#if SQLITE_DEFAULT_LOCKING_MODE +#if SQLITE_DEFAULT_AUTOMATIC_INDEX + "DEFAULT_AUTOMATIC_INDEX", +#endif +#if SQLITE_DEFAULT_AUTOVACUUM + "DEFAULT_AUTOVACUUM", +#endif +#ifdef SQLITE_DEFAULT_CACHE_SIZE + "DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE), +#endif +#if SQLITE_DEFAULT_CKPTFULLFSYNC + "DEFAULT_CKPTFULLFSYNC", +#endif +#ifdef SQLITE_DEFAULT_FILE_FORMAT + "DEFAULT_FILE_FORMAT=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_FORMAT), +#endif +#ifdef SQLITE_DEFAULT_FILE_PERMISSIONS + "DEFAULT_FILE_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_PERMISSIONS), +#endif +#if SQLITE_DEFAULT_FOREIGN_KEYS + "DEFAULT_FOREIGN_KEYS", +#endif +#ifdef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT + "DEFAULT_JOURNAL_SIZE_LIMIT=" CTIMEOPT_VAL(SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT), +#endif +#ifdef SQLITE_DEFAULT_LOCKING_MODE "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), #endif -#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc) +#ifdef SQLITE_DEFAULT_LOOKASIDE + "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOOKASIDE), +#endif +#if SQLITE_DEFAULT_MEMSTATUS + "DEFAULT_MEMSTATUS", +#endif +#ifdef SQLITE_DEFAULT_MMAP_SIZE "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE), #endif -#if SQLITE_DEFAULT_SYNCHRONOUS +#ifdef SQLITE_DEFAULT_PAGE_SIZE + "DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE), +#endif +#ifdef SQLITE_DEFAULT_PCACHE_INITSZ + "DEFAULT_PCACHE_INITSZ=" CTIMEOPT_VAL(SQLITE_DEFAULT_PCACHE_INITSZ), +#endif +#ifdef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS + "DEFAULT_PROXYDIR_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_PROXYDIR_PERMISSIONS), +#endif +#if SQLITE_DEFAULT_RECURSIVE_TRIGGERS + "DEFAULT_RECURSIVE_TRIGGERS", +#endif +#ifdef SQLITE_DEFAULT_ROWEST + "DEFAULT_ROWEST=" CTIMEOPT_VAL(SQLITE_DEFAULT_ROWEST), +#endif +#ifdef SQLITE_DEFAULT_SECTOR_SIZE + "DEFAULT_SECTOR_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_SECTOR_SIZE), +#endif +#ifdef SQLITE_DEFAULT_SYNCHRONOUS "DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS), #endif -#if SQLITE_DEFAULT_WAL_SYNCHRONOUS +#ifdef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT + "DEFAULT_WAL_AUTOCHECKPOINT=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_AUTOCHECKPOINT), +#endif +#ifdef SQLITE_DEFAULT_WAL_SYNCHRONOUS "DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS), #endif +#ifdef SQLITE_DEFAULT_WORKER_THREADS + "DEFAULT_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WORKER_THREADS), +#endif #if SQLITE_DIRECT_OVERFLOW_READ "DIRECT_OVERFLOW_READ", #endif #if SQLITE_DISABLE_DIRSYNC "DISABLE_DIRSYNC", #endif +#if SQLITE_DISABLE_FTS3_UNICODE + "DISABLE_FTS3_UNICODE", +#endif +#if SQLITE_DISABLE_FTS4_DEFERRED + "DISABLE_FTS4_DEFERRED", +#endif +#if SQLITE_DISABLE_INTRINSIC + "DISABLE_INTRINSIC", +#endif #if SQLITE_DISABLE_LFS "DISABLE_LFS", #endif -#if SQLITE_ENABLE_8_3_NAMES +#if SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS + "DISABLE_PAGECACHE_OVERFLOW_STATS", +#endif +#if SQLITE_DISABLE_SKIPAHEAD_DISTINCT + "DISABLE_SKIPAHEAD_DISTINCT", +#endif +#ifdef SQLITE_ENABLE_8_3_NAMES "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES), #endif #if SQLITE_ENABLE_API_ARMOR @@ -96,6 +190,15 @@ static const char * const azCompileOpt[] = { #if SQLITE_ENABLE_COLUMN_METADATA "ENABLE_COLUMN_METADATA", #endif +#if SQLITE_ENABLE_COLUMN_USED_MASK + "ENABLE_COLUMN_USED_MASK", +#endif +#if SQLITE_ENABLE_COSTMULT + "ENABLE_COSTMULT", +#endif +#if SQLITE_ENABLE_CURSOR_HINTS + "ENABLE_CURSOR_HINTS", +#endif #if SQLITE_ENABLE_DBSTAT_VTAB "ENABLE_DBSTAT_VTAB", #endif @@ -114,12 +217,18 @@ static const char * const azCompileOpt[] = { #if SQLITE_ENABLE_FTS3_PARENTHESIS "ENABLE_FTS3_PARENTHESIS", #endif +#if SQLITE_ENABLE_FTS3_TOKENIZER + "ENABLE_FTS3_TOKENIZER", +#endif #if SQLITE_ENABLE_FTS4 "ENABLE_FTS4", #endif #if SQLITE_ENABLE_FTS5 "ENABLE_FTS5", #endif +#if SQLITE_ENABLE_HIDDEN_COLUMNS + "ENABLE_HIDDEN_COLUMNS", +#endif #if SQLITE_ENABLE_ICU "ENABLE_ICU", #endif @@ -132,7 +241,7 @@ static const char * const azCompileOpt[] = { #if SQLITE_ENABLE_LOAD_EXTENSION "ENABLE_LOAD_EXTENSION", #endif -#if SQLITE_ENABLE_LOCKING_STYLE +#ifdef SQLITE_ENABLE_LOCKING_STYLE "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE), #endif #if SQLITE_ENABLE_MEMORY_MANAGEMENT @@ -144,26 +253,86 @@ static const char * const azCompileOpt[] = { #if SQLITE_ENABLE_MEMSYS5 "ENABLE_MEMSYS5", #endif +#if SQLITE_ENABLE_MULTIPLEX + "ENABLE_MULTIPLEX", +#endif +#if SQLITE_ENABLE_NULL_TRIM + "ENABLE_NULL_TRIM", +#endif #if SQLITE_ENABLE_OVERSIZE_CELL_CHECK "ENABLE_OVERSIZE_CELL_CHECK", #endif +#if SQLITE_ENABLE_PREUPDATE_HOOK + "ENABLE_PREUPDATE_HOOK", +#endif +#if SQLITE_ENABLE_RBU + "ENABLE_RBU", +#endif #if SQLITE_ENABLE_RTREE "ENABLE_RTREE", #endif +#if SQLITE_ENABLE_SELECTTRACE + "ENABLE_SELECTTRACE", +#endif +#if SQLITE_ENABLE_SESSION + "ENABLE_SESSION", +#endif +#if SQLITE_ENABLE_SNAPSHOT + "ENABLE_SNAPSHOT", +#endif +#if SQLITE_ENABLE_SQLLOG + "ENABLE_SQLLOG", +#endif #if defined(SQLITE_ENABLE_STAT4) "ENABLE_STAT4", #elif defined(SQLITE_ENABLE_STAT3) "ENABLE_STAT3", #endif +#if SQLITE_ENABLE_STMT_SCANSTATUS + "ENABLE_STMT_SCANSTATUS", +#endif +#if SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION + "ENABLE_UNKNOWN_SQL_FUNCTION", +#endif #if SQLITE_ENABLE_UNLOCK_NOTIFY "ENABLE_UNLOCK_NOTIFY", #endif #if SQLITE_ENABLE_UPDATE_DELETE_LIMIT "ENABLE_UPDATE_DELETE_LIMIT", #endif -#if defined(SQLITE_ENABLE_URI_00_ERROR) +#if SQLITE_ENABLE_URI_00_ERROR "ENABLE_URI_00_ERROR", #endif +#if SQLITE_ENABLE_VFSTRACE + "ENABLE_VFSTRACE", +#endif +#if SQLITE_ENABLE_WHERETRACE + "ENABLE_WHERETRACE", +#endif +#if SQLITE_ENABLE_ZIPVFS + "ENABLE_ZIPVFS", +#endif +#if SQLITE_EXPLAIN_ESTIMATED_ROWS + "EXPLAIN_ESTIMATED_ROWS", +#endif +#if SQLITE_EXTRA_IFNULLROW + "EXTRA_IFNULLROW", +#endif +#ifdef SQLITE_EXTRA_INIT + "EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT), +#endif +#ifdef SQLITE_EXTRA_SHUTDOWN + "EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN), +#endif +#ifdef SQLITE_FTS3_MAX_EXPR_DEPTH + "FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH), +#endif +#if SQLITE_FTS5_ENABLE_TEST_MI + "FTS5_ENABLE_TEST_MI", +#endif +#if SQLITE_FTS5_NO_WITHOUT_ROWID + "FTS5_NO_WITHOUT_ROWID", +#endif #if SQLITE_HAS_CODEC "HAS_CODEC", #endif @@ -179,27 +348,114 @@ static const char * const azCompileOpt[] = { #if SQLITE_IGNORE_FLOCK_LOCK_ERRORS "IGNORE_FLOCK_LOCK_ERRORS", #endif -#ifdef SQLITE_INT64_TYPE +#if SQLITE_INLINE_MEMCPY + "INLINE_MEMCPY", +#endif +#if SQLITE_INT64_TYPE "INT64_TYPE", #endif -#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS +#ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX + "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX), +#endif +#if SQLITE_LIKE_DOESNT_MATCH_BLOBS "LIKE_DOESNT_MATCH_BLOBS", #endif #if SQLITE_LOCK_TRACE "LOCK_TRACE", #endif -#if defined(SQLITE_MAX_MMAP_SIZE) && !defined(SQLITE_MAX_MMAP_SIZE_xc) +#if SQLITE_LOG_CACHE_SPILL + "LOG_CACHE_SPILL", +#endif +#ifdef SQLITE_MALLOC_SOFT_LIMIT + "MALLOC_SOFT_LIMIT=" CTIMEOPT_VAL(SQLITE_MALLOC_SOFT_LIMIT), +#endif +#ifdef SQLITE_MAX_ATTACHED + "MAX_ATTACHED=" CTIMEOPT_VAL(SQLITE_MAX_ATTACHED), +#endif +#ifdef SQLITE_MAX_COLUMN + "MAX_COLUMN=" CTIMEOPT_VAL(SQLITE_MAX_COLUMN), +#endif +#ifdef SQLITE_MAX_COMPOUND_SELECT + "MAX_COMPOUND_SELECT=" CTIMEOPT_VAL(SQLITE_MAX_COMPOUND_SELECT), +#endif +#ifdef SQLITE_MAX_DEFAULT_PAGE_SIZE + "MAX_DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_DEFAULT_PAGE_SIZE), +#endif +#ifdef SQLITE_MAX_EXPR_DEPTH + "MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_EXPR_DEPTH), +#endif +#ifdef SQLITE_MAX_FUNCTION_ARG + "MAX_FUNCTION_ARG=" CTIMEOPT_VAL(SQLITE_MAX_FUNCTION_ARG), +#endif +#ifdef SQLITE_MAX_LENGTH + "MAX_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LENGTH), +#endif +#ifdef SQLITE_MAX_LIKE_PATTERN_LENGTH + "MAX_LIKE_PATTERN_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LIKE_PATTERN_LENGTH), +#endif +#ifdef SQLITE_MAX_MEMORY + "MAX_MEMORY=" CTIMEOPT_VAL(SQLITE_MAX_MEMORY), +#endif +#ifdef SQLITE_MAX_MMAP_SIZE "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE), #endif +#ifdef SQLITE_MAX_MMAP_SIZE_ + "MAX_MMAP_SIZE_=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE_), +#endif +#ifdef SQLITE_MAX_PAGE_COUNT + "MAX_PAGE_COUNT=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_COUNT), +#endif +#ifdef SQLITE_MAX_PAGE_SIZE + "MAX_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_SIZE), +#endif #ifdef SQLITE_MAX_SCHEMA_RETRY "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY), #endif +#ifdef SQLITE_MAX_SQL_LENGTH + "MAX_SQL_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_SQL_LENGTH), +#endif +#ifdef SQLITE_MAX_TRIGGER_DEPTH + "MAX_TRIGGER_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_TRIGGER_DEPTH), +#endif +#ifdef SQLITE_MAX_VARIABLE_NUMBER + "MAX_VARIABLE_NUMBER=" CTIMEOPT_VAL(SQLITE_MAX_VARIABLE_NUMBER), +#endif +#ifdef SQLITE_MAX_VDBE_OP + "MAX_VDBE_OP=" CTIMEOPT_VAL(SQLITE_MAX_VDBE_OP), +#endif +#ifdef SQLITE_MAX_WORKER_THREADS + "MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS), +#endif #if SQLITE_MEMDEBUG "MEMDEBUG", #endif #if SQLITE_MIXED_ENDIAN_64BIT_FLOAT "MIXED_ENDIAN_64BIT_FLOAT", #endif +#if SQLITE_MMAP_READWRITE + "MMAP_READWRITE", +#endif +#if SQLITE_MUTEX_NOOP + "MUTEX_NOOP", +#endif +#if SQLITE_MUTEX_NREF + "MUTEX_NREF", +#endif +#if SQLITE_MUTEX_OMIT + "MUTEX_OMIT", +#endif +#if SQLITE_MUTEX_PTHREADS + "MUTEX_PTHREADS", +#endif +#if SQLITE_MUTEX_W32 + "MUTEX_W32", +#endif +#if SQLITE_NEED_ERR_NAME + "NEED_ERR_NAME", +#endif +#if SQLITE_NOINLINE + "NOINLINE", +#endif #if SQLITE_NO_SYNC "NO_SYNC", #endif @@ -251,6 +507,9 @@ static const char * const azCompileOpt[] = { #if SQLITE_OMIT_COMPOUND_SELECT "OMIT_COMPOUND_SELECT", #endif +#if SQLITE_OMIT_CONFLICT_CLAUSE + "OMIT_CONFLICT_CLAUSE", +#endif #if SQLITE_OMIT_CTE "OMIT_CTE", #endif @@ -281,6 +540,9 @@ static const char * const azCompileOpt[] = { #if SQLITE_OMIT_GET_TABLE "OMIT_GET_TABLE", #endif +#if SQLITE_OMIT_HEX_INTEGER + "OMIT_HEX_INTEGER", +#endif #if SQLITE_OMIT_INCRBLOB "OMIT_INCRBLOB", #endif @@ -308,6 +570,12 @@ static const char * const azCompileOpt[] = { #if SQLITE_OMIT_PAGER_PRAGMAS "OMIT_PAGER_PRAGMAS", #endif +#if SQLITE_OMIT_PARSER_TRACE + "OMIT_PARSER_TRACE", +#endif +#if SQLITE_OMIT_POPEN + "OMIT_POPEN", +#endif #if SQLITE_OMIT_PRAGMA "OMIT_PRAGMA", #endif @@ -329,6 +597,9 @@ static const char * const azCompileOpt[] = { #if SQLITE_OMIT_SHARED_CACHE "OMIT_SHARED_CACHE", #endif +#if SQLITE_OMIT_SHUTDOWN_DIRECTORIES + "OMIT_SHUTDOWN_DIRECTORIES", +#endif #if SQLITE_OMIT_SUBQUERY "OMIT_SUBQUERY", #endif @@ -338,6 +609,9 @@ static const char * const azCompileOpt[] = { #if SQLITE_OMIT_TEMPDB "OMIT_TEMPDB", #endif +#if SQLITE_OMIT_TEST_CONTROL + "OMIT_TEST_CONTROL", +#endif #if SQLITE_OMIT_TRACE "OMIT_TRACE", #endif @@ -368,12 +642,24 @@ static const char * const azCompileOpt[] = { #if SQLITE_OMIT_XFER_OPT "OMIT_XFER_OPT", #endif +#if SQLITE_PCACHE_SEPARATE_HEADER + "PCACHE_SEPARATE_HEADER", +#endif #if SQLITE_PERFORMANCE_TRACE "PERFORMANCE_TRACE", #endif +#if SQLITE_POWERSAFE_OVERWRITE + "POWERSAFE_OVERWRITE", +#endif +#if SQLITE_PREFER_PROXY_LOCKING + "PREFER_PROXY_LOCKING", +#endif #if SQLITE_PROXY_DEBUG "PROXY_DEBUG", #endif +#if SQLITE_REVERSE_UNORDERED_SELECTS + "REVERSE_UNORDERED_SELECTS", +#endif #if SQLITE_RTREE_INT_ONLY "RTREE_INT_ONLY", #endif @@ -383,16 +669,28 @@ static const char * const azCompileOpt[] = { #if SQLITE_SMALL_STACK "SMALL_STACK", #endif +#ifdef SQLITE_SORTER_PMASZ + "SORTER_PMASZ=" CTIMEOPT_VAL(SQLITE_SORTER_PMASZ), +#endif #if SQLITE_SOUNDEX "SOUNDEX", #endif +#ifdef SQLITE_STAT4_SAMPLES + "STAT4_SAMPLES=" CTIMEOPT_VAL(SQLITE_STAT4_SAMPLES), +#endif +#ifdef SQLITE_STMTJRNL_SPILL + "STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL), +#endif +#if SQLITE_SUBSTR_COMPATIBILITY + "SUBSTR_COMPATIBILITY", +#endif #if SQLITE_SYSTEM_MALLOC "SYSTEM_MALLOC", #endif #if SQLITE_TCL "TCL", #endif -#if defined(SQLITE_TEMP_STORE) && !defined(SQLITE_TEMP_STORE_xc) +#ifdef SQLITE_TEMP_STORE "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE), #endif #if SQLITE_TEST @@ -400,64 +698,46 @@ static const char * const azCompileOpt[] = { #endif #if defined(SQLITE_THREADSAFE) "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE), +#elif defined(THREADSAFE) + "THREADSAFE=" CTIMEOPT_VAL(THREADSAFE), +#else + "THREADSAFE=1", +#endif +#if SQLITE_UNLINK_AFTER_CLOSE + "UNLINK_AFTER_CLOSE", #endif #if SQLITE_UNTESTABLE - "UNTESTABLE" + "UNTESTABLE", +#endif +#if SQLITE_USER_AUTHENTICATION + "USER_AUTHENTICATION", #endif #if SQLITE_USE_ALLOCA "USE_ALLOCA", #endif -#if SQLITE_USER_AUTHENTICATION - "USER_AUTHENTICATION", +#if SQLITE_USE_FCNTL_TRACE + "USE_FCNTL_TRACE", +#endif +#if SQLITE_USE_URI + "USE_URI", +#endif +#if SQLITE_VDBE_COVERAGE + "VDBE_COVERAGE", #endif #if SQLITE_WIN32_MALLOC "WIN32_MALLOC", #endif #if SQLITE_ZERO_MALLOC - "ZERO_MALLOC" + "ZERO_MALLOC", #endif -}; - -/* -** Given the name of a compile-time option, return true if that option -** was used and false if not. -** -** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix -** is not required for a match. +/* +** END CODE GENERATED BY tool/mkctime.tcl */ -int sqlite3_compileoption_used(const char *zOptName){ - int i, n; - -#if SQLITE_ENABLE_API_ARMOR - if( zOptName==0 ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7; - n = sqlite3Strlen30(zOptName); - - /* Since ArraySize(azCompileOpt) is normally in single digits, a - ** linear search is adequate. No need for a binary search. */ - for(i=0; i<ArraySize(azCompileOpt); i++){ - if( sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0 - && sqlite3IsIdChar((unsigned char)azCompileOpt[i][n])==0 - ){ - return 1; - } - } - return 0; -} +}; -/* -** Return the N-th compile-time option string. If N is out of range, -** return a NULL pointer. -*/ -const char *sqlite3_compileoption_get(int N){ - if( N>=0 && N<ArraySize(azCompileOpt) ){ - return azCompileOpt[N]; - } - return 0; +const char **sqlite3CompileOptions(int *pnOpt){ + *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]); + return (const char**)sqlite3azCompileOpt; } #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ diff --git a/src/fkey.c b/src/fkey.c index f91a6de54..0012768a3 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -633,10 +633,12 @@ static void fkScanChildren( /* Create VDBE to loop through the entries in pSrc that match the WHERE ** clause. For each row found, increment either the deferred or immediate ** foreign key constraint counter. */ - pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0); - sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); - if( pWInfo ){ - sqlite3WhereEnd(pWInfo); + if( pParse->nErr==0 ){ + pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0); + sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); + if( pWInfo ){ + sqlite3WhereEnd(pWInfo); + } } /* Clean up the WHERE clause constructed above. */ diff --git a/src/legacy.c b/src/legacy.c index df8e2780f..40959a854 100644 --- a/src/legacy.c +++ b/src/legacy.c @@ -127,11 +127,8 @@ exec_out: rc = sqlite3ApiExit(db, rc); if( rc!=SQLITE_OK && pzErrMsg ){ - int nErrMsg = 1 + sqlite3Strlen30(sqlite3_errmsg(db)); - *pzErrMsg = sqlite3Malloc(nErrMsg); - if( *pzErrMsg ){ - memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg); - }else{ + *pzErrMsg = sqlite3DbStrDup(0, sqlite3_errmsg(db)); + if( *pzErrMsg==0 ){ rc = SQLITE_NOMEM_BKPT; sqlite3Error(db, SQLITE_NOMEM); } diff --git a/src/main.c b/src/main.c index 44b7d5df8..f11942666 100644 --- a/src/main.c +++ b/src/main.c @@ -811,6 +811,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){ { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose }, + { SQLITE_DBCONFIG_ENABLE_QPSG, SQLITE_EnableQPSG }, }; unsigned int i; rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ @@ -2916,6 +2917,9 @@ static int openDatabase( #if defined(SQLITE_ENABLE_FTS3_TOKENIZER) | SQLITE_Fts3Tokenizer #endif +#if defined(SQLITE_ENABLE_QPSG) + | SQLITE_EnableQPSG +#endif ; sqlite3HashInit(&db->aCollSeq); #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -4102,3 +4106,55 @@ void sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){ sqlite3_free(pSnapshot); } #endif /* SQLITE_ENABLE_SNAPSHOT */ + +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS +/* +** Given the name of a compile-time option, return true if that option +** was used and false if not. +** +** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix +** is not required for a match. +*/ +int sqlite3_compileoption_used(const char *zOptName){ + int i, n; + int nOpt; + const char **azCompileOpt; + +#if SQLITE_ENABLE_API_ARMOR + if( zOptName==0 ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif + + azCompileOpt = sqlite3CompileOptions(&nOpt); + + if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7; + n = sqlite3Strlen30(zOptName); + + /* Since nOpt is normally in single digits, a linear search is + ** adequate. No need for a binary search. */ + for(i=0; i<nOpt; i++){ + if( sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0 + && sqlite3IsIdChar((unsigned char)azCompileOpt[i][n])==0 + ){ + return 1; + } + } + return 0; +} + +/* +** Return the N-th compile-time option string. If N is out of range, +** return a NULL pointer. +*/ +const char *sqlite3_compileoption_get(int N){ + int nOpt; + const char **azCompileOpt; + azCompileOpt = sqlite3CompileOptions(&nOpt); + if( N>=0 && N<nOpt ){ + return azCompileOpt[N]; + } + return 0; +} +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ diff --git a/src/parse.y b/src/parse.y index 522c80548..91e498214 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1375,8 +1375,7 @@ trigger_decl(A) ::= temp(T) TRIGGER ifnotexists(NOERR) nm(B) dbnm(Z) } %type trigger_time {int} -trigger_time(A) ::= BEFORE. { A = TK_BEFORE; } -trigger_time(A) ::= AFTER. { A = TK_AFTER; } +trigger_time(A) ::= BEFORE|AFTER(X). { A = @X; /*A-overwrites-X*/ } trigger_time(A) ::= INSTEAD OF. { A = TK_INSTEAD;} trigger_time(A) ::= . { A = TK_BEFORE; } diff --git a/src/pragma.h b/src/pragma.h index d05657c79..76e59cbc6 100644 --- a/src/pragma.h +++ b/src/pragma.h @@ -267,7 +267,7 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) {/* zName: */ "foreign_key_check", /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, - /* ePragFlg: */ PragFlg_NeedSchema, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, /* ColNames: */ 39, 4, /* iArg: */ 0 }, #endif @@ -354,7 +354,7 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) {/* zName: */ "integrity_check", /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, - /* ePragFlg: */ PragFlg_NeedSchema, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif @@ -449,7 +449,7 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) {/* zName: */ "quick_check", /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, - /* ePragFlg: */ PragFlg_NeedSchema, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif @@ -458,7 +458,7 @@ static const PragmaName aPragmaName[] = { /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_ReadUncommitted }, + /* iArg: */ SQLITE_ReadUncommit }, {/* zName: */ "recursive_triggers", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, @@ -610,7 +610,7 @@ static const PragmaName aPragmaName[] = { /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, + /* iArg: */ SQLITE_WriteSchema }, #endif }; /* Number of pragmas: 60 on by default, 74 total. */ diff --git a/src/prepare.c b/src/prepare.c index 8908007f8..fb885101d 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -25,7 +25,7 @@ static void corruptSchema( const char *zExtra /* Error information */ ){ sqlite3 *db = pData->db; - if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){ + if( !db->mallocFailed && (db->flags & SQLITE_WriteSchema)==0 ){ char *z; if( zObj==0 ) zObj = "?"; z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj); @@ -312,8 +312,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ rc = SQLITE_NOMEM_BKPT; sqlite3ResetAllSchemasOfConnection(db); } - if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){ - /* Black magic: If the SQLITE_RecoveryMode flag is set, then consider + if( rc==SQLITE_OK || (db->flags&SQLITE_WriteSchema)){ + /* Black magic: If the SQLITE_WriteSchema flag is set, then consider ** the schema loaded, even if errors occurred. In this situation the ** current sqlite3_prepare() operation will fail, but the following one ** will attempt to compile the supplied statement against whatever subset @@ -569,7 +569,7 @@ static int sqlite3Prepare( if( rc ){ const char *zDb = db->aDb[i].zDbSName; sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb); - testcase( db->flags & SQLITE_ReadUncommitted ); + testcase( db->flags & SQLITE_ReadUncommit ); goto end_prepare; } } diff --git a/src/select.c b/src/select.c index 51cd089a2..74747fadc 100644 --- a/src/select.c +++ b/src/select.c @@ -3205,9 +3205,12 @@ static Expr *substExpr( pCopy = &ifNullRow; } pNew = sqlite3ExprDup(db, pCopy, 0); - if( pNew && (pExpr->flags & EP_FromJoin) ){ + if( pNew && pSubst->isLeftJoin ){ + ExprSetProperty(pNew, EP_CanBeNull); + } + if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){ pNew->iRightJoinTable = pExpr->iRightJoinTable; - pNew->flags |= EP_FromJoin; + ExprSetProperty(pNew, EP_FromJoin); } sqlite3ExprDelete(db, pExpr); pExpr = pNew; @@ -3500,7 +3503,7 @@ static int flattenSubquery( ** ** If the subquery is the right operand of a LEFT JOIN, then the outer ** query cannot be an aggregate. This is an artifact of the way aggregates - ** are processed - there is not mechanism to determine if the LEFT JOIN + ** are processed - there is no mechanism to determine if the LEFT JOIN ** table should be all-NULL. ** ** See also tickets #306, #350, and #3300. @@ -5290,6 +5293,8 @@ int sqlite3Select( if( pPrior ){ sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor); explainSetInteger(pItem->iSelectId, pPrior->iSelectId); + assert( pPrior->pSelect!=0 ); + pSub->nSelectRow = pPrior->pSelect->nSelectRow; }else{ sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); diff --git a/src/shell.c b/src/shell.c index 36f6970d1..ec255a673 100644 --- a/src/shell.c +++ b/src/shell.c @@ -729,6 +729,61 @@ static char quoteChar(const char *zName){ return 0; } +/* +** SQL function: shell_add_schema(S,X) +** +** Add the schema name X to the CREATE statement in S and return the result. +** Examples: +** +** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x); +** +** Also works on +** +** CREATE INDEX +** CREATE UNIQUE INDEX +** CREATE VIEW +** CREATE TRIGGER +** CREATE VIRTUAL TABLE +** +** This UDF is used by the .schema command to insert the schema name of +** attached databases into the middle of the sqlite_master.sql field. +*/ +static void shellAddSchemaName( + sqlite3_context *pCtx, + int nVal, + sqlite3_value **apVal +){ + static const char *aPrefix[] = { + "TABLE", + "INDEX", + "UNIQUE INDEX", + "VIEW", + "TRIGGER", + "VIRTUAL TABLE" + }; + int i = 0; + const char *zIn = (const char*)sqlite3_value_text(apVal[0]); + const char *zSchema = (const char*)sqlite3_value_text(apVal[1]); + assert( nVal==2 ); + if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){ + for(i=0; i<sizeof(aPrefix)/sizeof(aPrefix[0]); i++){ + int n = strlen30(aPrefix[i]); + if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){ + char cQuote = quoteChar(zSchema); + char *z; + if( cQuote ){ + z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8); + }else{ + z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8); + } + sqlite3_result_text(pCtx, z, -1, sqlite3_free); + return; + } + } + } + sqlite3_result_value(pCtx, apVal[0]); +} + /****************************************************************************** ** SHA3 hash implementation copied from ../ext/misc/shathree.c */ @@ -2308,7 +2363,7 @@ static void set_table_name(ShellState *p, const char *zName){ if( zName==0 ) return; cQuote = quoteChar(zName); n = strlen30(zName); - if( cQuote ) n += 2; + if( cQuote ) n += n+2; z = p->zDestTable = malloc( n+1 ); if( z==0 ){ raw_printf(stderr,"Error: out of memory\n"); @@ -3536,6 +3591,9 @@ static void open_db(ShellState *p, int keepAlive){ sha3QueryFunc, 0, 0); sqlite3_create_function(p->db, "sha3_query", 2, SQLITE_UTF8, 0, sha3QueryFunc, 0, 0); + sqlite3_create_function(p->db, "shell_add_schema", 2, SQLITE_UTF8, 0, + shellAddSchemaName, 0, 0); + } } @@ -3764,6 +3822,7 @@ struct ImportCtx { int n; /* Number of bytes in z */ int nAlloc; /* Space allocated for z[] */ int nLine; /* Current line number */ + int bNotFirst; /* True if one or more bytes already read */ int cTerm; /* Character that terminated the most recent field */ int cColSep; /* The column separator character. (Usually ",") */ int cRowSep; /* The row separator character. (Usually "\n") */ @@ -3843,6 +3902,21 @@ static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){ pc = c; } }else{ + /* If this is the first field being parsed and it begins with the + ** UTF-8 BOM (0xEF BB BF) then skip the BOM */ + if( (c&0xff)==0xef && p->bNotFirst==0 ){ + import_append_char(p, c); + c = fgetc(p->in); + if( (c&0xff)==0xbb ){ + import_append_char(p, c); + c = fgetc(p->in); + if( (c&0xff)==0xbf ){ + p->bNotFirst = 1; + p->n = 0; + return csv_read_one_field(p); + } + } + } while( c!=EOF && c!=cSep && c!=rSep ){ import_append_char(p, c); c = fgetc(p->in); @@ -3854,6 +3928,7 @@ static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){ p->cTerm = c; } if( p->z ) p->z[p->n] = 0; + p->bNotFirst = 1; return p->z; } @@ -5689,12 +5764,17 @@ static int do_meta_command(char *zLine, ShellState *p){ }else if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ + ShellText sSelect; ShellState data; char *zErrMsg = 0; + const char *zDiv = 0; + int iSchema = 0; + open_db(p, 0); memcpy(&data, p, sizeof(data)); data.showHeader = 0; data.cMode = data.mode = MODE_Semi; + initText(&sSelect); if( nArg>=2 && optionMatch(azArg[1], "indent") ){ data.cMode = data.mode = MODE_Pretty; nArg--; @@ -5732,33 +5812,62 @@ static int do_meta_command(char *zLine, ShellState *p){ callback(&data, 1, new_argv, new_colv); rc = SQLITE_OK; }else{ - char *zSql; - zSql = sqlite3_mprintf( - "SELECT sql FROM " - " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" - " FROM sqlite_master UNION ALL" - " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " - "WHERE lower(tbl_name) LIKE %Q" - " AND type!='meta' AND sql NOTNULL " - "ORDER BY rowid", azArg[1]); - rc = sqlite3_exec(p->db, zSql, callback, &data, &zErrMsg); - sqlite3_free(zSql); + zDiv = "("; } }else if( nArg==1 ){ - rc = sqlite3_exec(p->db, - "SELECT sql FROM " - " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" - " FROM sqlite_master UNION ALL" - " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " - "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " - "ORDER BY rowid", - callback, &data, &zErrMsg - ); + zDiv = "("; }else{ raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n"); rc = 1; goto meta_command_exit; } + if( zDiv ){ + sqlite3_stmt *pStmt = 0; + sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list", + -1, &pStmt, 0); + appendText(&sSelect, "SELECT sql FROM", 0); + iSchema = 0; + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + const char *zDb = (const char*)sqlite3_column_text(pStmt, 0); + char zScNum[30]; + sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema); + appendText(&sSelect, zDiv, 0); + zDiv = " UNION ALL "; + if( strcmp(zDb, "main")!=0 ){ + appendText(&sSelect, "SELECT shell_add_schema(sql,", 0); + appendText(&sSelect, zDb, '"'); + appendText(&sSelect, ") AS sql, type, tbl_name, name, rowid,", 0); + appendText(&sSelect, zScNum, 0); + appendText(&sSelect, " AS snum, ", 0); + appendText(&sSelect, zDb, '\''); + appendText(&sSelect, " AS sname FROM ", 0); + appendText(&sSelect, zDb, '"'); + appendText(&sSelect, ".sqlite_master", 0); + }else{ + appendText(&sSelect, "SELECT sql, type, tbl_name, name, rowid, ", 0); + appendText(&sSelect, zScNum, 0); + appendText(&sSelect, " AS snum, 'main' AS sname FROM sqlite_master",0); + } + } + sqlite3_finalize(pStmt); + appendText(&sSelect, ") WHERE ", 0); + if( nArg>1 ){ + char *zQarg = sqlite3_mprintf("%Q", azArg[1]); + if( strchr(azArg[1], '.') ){ + appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0); + }else{ + appendText(&sSelect, "lower(tbl_name)", 0); + } + appendText(&sSelect, strchr(azArg[1], '*') ? " GLOB " : " LIKE ", 0); + appendText(&sSelect, zQarg, 0); + appendText(&sSelect, " AND ", 0); + sqlite3_free(zQarg); + } + appendText(&sSelect, "type!='meta' AND sql IS NOT NULL" + " ORDER BY snum, rowid", 0); + rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg); + freeText(&sSelect); + } if( zErrMsg ){ utf8_printf(stderr,"Error: %s\n", zErrMsg); sqlite3_free(zErrMsg); @@ -6307,59 +6416,47 @@ static int do_meta_command(char *zLine, ShellState *p){ sqlite3_stmt *pStmt; char **azResult; int nRow, nAlloc; - char *zSql = 0; int ii; + ShellText s; + initText(&s); open_db(p, 0); rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); if( rc ) return shellDatabaseError(p->db); - /* Create an SQL statement to query for the list of tables in the - ** main and all attached databases where the table name matches the - ** LIKE pattern bound to variable "?1". */ - if( c=='t' ){ - zSql = sqlite3_mprintf( - "SELECT name FROM sqlite_master" - " WHERE type IN ('table','view')" - " AND name NOT LIKE 'sqlite_%%'" - " AND name LIKE ?1"); - }else if( nArg>2 ){ + if( nArg>2 && c=='i' ){ /* It is an historical accident that the .indexes command shows an error ** when called with the wrong number of arguments whereas the .tables ** command does not. */ raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n"); rc = 1; goto meta_command_exit; - }else{ - zSql = sqlite3_mprintf( - "SELECT name FROM sqlite_master" - " WHERE type='index'" - " AND tbl_name LIKE ?1"); } - for(ii=0; zSql && sqlite3_step(pStmt)==SQLITE_ROW; ii++){ + for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){ const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1); - if( zDbName==0 || ii==0 ) continue; + if( zDbName==0 ) continue; + if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0); + if( sqlite3_stricmp(zDbName, "main")==0 ){ + appendText(&s, "SELECT name FROM ", 0); + }else{ + appendText(&s, "SELECT ", 0); + appendText(&s, zDbName, '\''); + appendText(&s, "||'.'||name FROM ", 0); + } + appendText(&s, zDbName, '"'); + appendText(&s, ".sqlite_master ", 0); if( c=='t' ){ - zSql = sqlite3_mprintf( - "%z UNION ALL " - "SELECT '%q.' || name FROM \"%w\".sqlite_master" - " WHERE type IN ('table','view')" - " AND name NOT LIKE 'sqlite_%%'" - " AND name LIKE ?1", zSql, zDbName, zDbName); + appendText(&s," WHERE type IN ('table','view')" + " AND name NOT LIKE 'sqlite_%'" + " AND name LIKE ?1", 0); }else{ - zSql = sqlite3_mprintf( - "%z UNION ALL " - "SELECT '%q.' || name FROM \"%w\".sqlite_master" - " WHERE type='index'" - " AND tbl_name LIKE ?1", zSql, zDbName, zDbName); + appendText(&s," WHERE type='index'" + " AND tbl_name LIKE ?1", 0); } } rc = sqlite3_finalize(pStmt); - if( zSql && rc==SQLITE_OK ){ - zSql = sqlite3_mprintf("%z ORDER BY 1", zSql); - if( zSql ) rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - } - sqlite3_free(zSql); - if( !zSql ) return shellNomemError(); + appendText(&s, " ORDER BY 1", 0); + rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0); + freeText(&s); if( rc ) return shellDatabaseError(p->db); /* Run the SQL statement prepared by the above block. Store the results diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 73d13a999..27f66a02a 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -2007,6 +2007,17 @@ struct sqlite3_mem_methods { ** have been disabled - 0 if they are not disabled, 1 if they are. ** </dd> ** +** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> +** <dd>The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates +** the [query planner stability guarantee] (QPSG). When the QPSG is active, +** a single SQL query statement will always use the same algorithm regardless +** of values of [bound parameters]. The QPSG disables some query optimizations +** that look at the values of bound parameters, which can make some queries +** slower. But the QPSG has the advantage of more predictable behavior. With +** the QPSG active, SQLite will always use the same query plan in the field as +** was used during testing in the lab. +** </dd> +** ** </dl> */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ @@ -2016,6 +2027,7 @@ struct sqlite3_mem_methods { #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ #define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ +#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */ /* diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 9252c352b..cc51197d6 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -178,8 +178,9 @@ ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build */ -#ifdef _HAVE_SQLITE_CONFIG_H +#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H) #include "config.h" +#define SQLITECONFIG_H 1 #endif #include "sqliteLimit.h" @@ -274,6 +275,11 @@ ** ** Older versions of SQLite used an optional THREADSAFE macro. ** We support that for legacy. +** +** To ensure that the correct value of "THREADSAFE" is reported when querying +** for compile-time options at runtime (e.g. "PRAGMA compile_options"), this +** logic is partially replicated in ctime.c. If it is updated here, it should +** also be updated there. */ #if !defined(SQLITE_THREADSAFE) # if defined(THREADSAFE) @@ -589,7 +595,6 @@ */ #ifndef SQLITE_TEMP_STORE # define SQLITE_TEMP_STORE 1 -# define SQLITE_TEMP_STORE_xc 1 /* Exclude from ctime.c */ #endif /* @@ -890,7 +895,6 @@ typedef INT16_TYPE LogEst; # else # define SQLITE_MAX_MMAP_SIZE 0 # endif -# define SQLITE_MAX_MMAP_SIZE_xc 1 /* exclude from ctime.c */ #endif /* @@ -900,7 +904,6 @@ typedef INT16_TYPE LogEst; */ #ifndef SQLITE_DEFAULT_MMAP_SIZE # define SQLITE_DEFAULT_MMAP_SIZE 0 -# define SQLITE_DEFAULT_MMAP_SIZE_xc 1 /* Exclude from ctime.c */ #endif #if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE # undef SQLITE_DEFAULT_MMAP_SIZE @@ -1447,8 +1450,8 @@ struct sqlite3 { ** SQLITE_CkptFullFSync == PAGER_CKPT_FULLFSYNC ** SQLITE_CacheSpill == PAGER_CACHE_SPILL */ -#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ -#define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */ +#define SQLITE_WriteSchema 0x00000001 /* OK to update SQLITE_MASTER */ +#define SQLITE_LegacyFileFmt 0x00000002 /* Create new databases in format 1 */ #define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */ #define SQLITE_FullFSync 0x00000008 /* Use full fsync on the backend */ #define SQLITE_CkptFullFSync 0x00000010 /* Use full fsync for checkpoint */ @@ -1459,29 +1462,34 @@ struct sqlite3 { /* the count using a callback. */ #define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */ /* result set is empty */ -#define SQLITE_SqlTrace 0x00000200 /* Debug print SQL as it executes */ -#define SQLITE_VdbeListing 0x00000400 /* Debug listings of VDBE programs */ -#define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */ -#define SQLITE_VdbeAddopTrace 0x00001000 /* Trace sqlite3VdbeAddOp() calls */ -#define SQLITE_IgnoreChecks 0x00002000 /* Do not enforce check constraints */ -#define SQLITE_ReadUncommitted 0x0004000 /* For shared-cache mode */ -#define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */ -#define SQLITE_RecoveryMode 0x00010000 /* Ignore schema errors */ -#define SQLITE_ReverseOrder 0x00020000 /* Reverse unordered SELECTs */ -#define SQLITE_RecTriggers 0x00040000 /* Enable recursive triggers */ -#define SQLITE_ForeignKeys 0x00080000 /* Enforce foreign key constraints */ -#define SQLITE_AutoIndex 0x00100000 /* Enable automatic indexes */ -#define SQLITE_PreferBuiltin 0x00200000 /* Preference to built-in funcs */ -#define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */ -#define SQLITE_LoadExtFunc 0x00800000 /* Enable load_extension() SQL func */ -#define SQLITE_EnableTrigger 0x01000000 /* True to enable triggers */ -#define SQLITE_DeferFKs 0x02000000 /* Defer all FK constraints */ -#define SQLITE_QueryOnly 0x04000000 /* Disable database changes */ -#define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */ -#define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */ -#define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */ -#define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */ -#define SQLITE_NoCkptOnClose 0x80000000 /* No checkpoint on close()/DETACH */ +#define SQLITE_IgnoreChecks 0x00000200 /* Do not enforce check constraints */ +#define SQLITE_ReadUncommit 0x00000400 /* READ UNCOMMITTED in shared-cache */ +#define SQLITE_NoCkptOnClose 0x00000800 /* No checkpoint on close()/DETACH */ +#define SQLITE_ReverseOrder 0x00001000 /* Reverse unordered SELECTs */ +#define SQLITE_RecTriggers 0x00002000 /* Enable recursive triggers */ +#define SQLITE_ForeignKeys 0x00004000 /* Enforce foreign key constraints */ +#define SQLITE_AutoIndex 0x00008000 /* Enable automatic indexes */ +#define SQLITE_LoadExtension 0x00010000 /* Enable load_extension */ +#define SQLITE_EnableTrigger 0x00020000 /* True to enable triggers */ +#define SQLITE_DeferFKs 0x00040000 /* Defer all FK constraints */ +#define SQLITE_QueryOnly 0x00080000 /* Disable database changes */ +#define SQLITE_CellSizeCk 0x00100000 /* Check btree cell sizes on load */ +#define SQLITE_Fts3Tokenizer 0x00200000 /* Enable fts3_tokenizer(2) */ +#define SQLITE_EnableQPSG 0x00400000 /* Query Planner Stability Guarantee */ +/* The next four values are not used by PRAGMAs or by sqlite3_dbconfig() and +** could be factored out into a separate bit vector of the sqlite3 object. */ +#define SQLITE_InternChanges 0x00800000 /* Uncommitted Hash table changes */ +#define SQLITE_LoadExtFunc 0x01000000 /* Enable load_extension() SQL func */ +#define SQLITE_PreferBuiltin 0x02000000 /* Preference to built-in funcs */ +#define SQLITE_Vacuum 0x04000000 /* Currently in a VACUUM */ +/* Flags used only if debugging */ +#ifdef SQLITE_DEBUG +#define SQLITE_SqlTrace 0x08000000 /* Debug print SQL as it executes */ +#define SQLITE_VdbeListing 0x10000000 /* Debug listings of VDBE programs */ +#define SQLITE_VdbeTrace 0x20000000 /* True to trace VDBE execution */ +#define SQLITE_VdbeAddopTrace 0x40000000 /* Trace sqlite3VdbeAddOp() calls */ +#define SQLITE_VdbeEQP 0x80000000 /* Debug EXPLAIN QUERY PLAN */ +#endif /* @@ -4370,4 +4378,6 @@ Expr *sqlite3VectorFieldSubexpr(Expr*, int); Expr *sqlite3ExprForVectorField(Parse*,Expr*,int); void sqlite3VectorErrorMsg(Parse*, Expr*); +const char **sqlite3CompileOptions(int *pnOpt); + #endif /* SQLITEINT_H */ diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 9fe2316bf..341d3f0dc 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -161,6 +161,7 @@ struct SqliteDb { int nStmt; /* Number of statements in stmtList */ IncrblobChannel *pIncrblob;/* Linked list of open incrblob channels */ int nStep, nSort, nIndex; /* Statistics for most recent operation */ + int nVMStep; /* Another statistic for most recent operation */ int nTransaction; /* Number of nested [transaction] methods */ int openFlags; /* Flags used to open. (SQLITE_OPEN_URI) */ #ifdef SQLITE_TEST @@ -1456,10 +1457,13 @@ struct DbEvalContext { const char *zSql; /* Remaining SQL to execute */ SqlPreparedStmt *pPreStmt; /* Current statement */ int nCol; /* Number of columns returned by pStmt */ + int evalFlags; /* Flags used */ Tcl_Obj *pArray; /* Name of array variable */ Tcl_Obj **apColName; /* Array of column names */ }; +#define SQLITE_EVAL_WITHOUTNULLS 0x00001 /* Unset array(*) for NULL */ + /* ** Release any cache of column names currently held as part of ** the DbEvalContext structure passed as the first argument. @@ -1492,7 +1496,8 @@ static void dbEvalInit( DbEvalContext *p, /* Pointer to structure to initialize */ SqliteDb *pDb, /* Database handle */ Tcl_Obj *pSql, /* Object containing SQL script */ - Tcl_Obj *pArray /* Name of Tcl array to set (*) element of */ + Tcl_Obj *pArray, /* Name of Tcl array to set (*) element of */ + int evalFlags /* Flags controlling evaluation */ ){ memset(p, 0, sizeof(DbEvalContext)); p->pDb = pDb; @@ -1503,6 +1508,7 @@ static void dbEvalInit( p->pArray = pArray; Tcl_IncrRefCount(pArray); } + p->evalFlags = evalFlags; } /* @@ -1594,6 +1600,7 @@ static int dbEvalStep(DbEvalContext *p){ pDb->nStep = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_FULLSCAN_STEP,1); pDb->nSort = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_SORT,1); pDb->nIndex = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_AUTOINDEX,1); + pDb->nVMStep = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_VM_STEP,1); dbReleaseColumnNames(p); p->pPreStmt = 0; @@ -1734,11 +1741,15 @@ static int SQLITE_TCLAPI DbEvalNextCmd( Tcl_Obj **apColName; dbEvalRowInfo(p, &nCol, &apColName); for(i=0; i<nCol; i++){ - Tcl_Obj *pVal = dbEvalColumnValue(p, i); if( pArray==0 ){ - Tcl_ObjSetVar2(interp, apColName[i], 0, pVal, 0); + Tcl_ObjSetVar2(interp, apColName[i], 0, dbEvalColumnValue(p,i), 0); + }else if( (p->evalFlags & SQLITE_EVAL_WITHOUTNULLS)!=0 + && sqlite3_column_type(p->pPreStmt->pStmt, i)==SQLITE_NULL + ){ + Tcl_UnsetVar2(interp, Tcl_GetString(pArray), + Tcl_GetString(apColName[i]), 0); }else{ - Tcl_ObjSetVar2(interp, pArray, apColName[i], pVal, 0); + Tcl_ObjSetVar2(interp, pArray, apColName[i], dbEvalColumnValue(p,i), 0); } } @@ -2451,7 +2462,7 @@ static int SQLITE_TCLAPI DbObjCmd( return TCL_ERROR; } - dbEvalInit(&sEval, pDb, objv[2], 0); + dbEvalInit(&sEval, pDb, objv[2], 0, 0); rc = dbEvalStep(&sEval); if( choice==DB_ONECOLUMN ){ if( rc==TCL_OK ){ @@ -2472,7 +2483,7 @@ static int SQLITE_TCLAPI DbObjCmd( } /* - ** $db eval $sql ?array? ?{ ...code... }? + ** $db eval ?options? $sql ?array? ?{ ...code... }? ** ** The SQL statement in $sql is evaluated. For each row, the values are ** placed in elements of the array named "array" and ...code... is executed. @@ -2481,8 +2492,22 @@ static int SQLITE_TCLAPI DbObjCmd( ** that have the same name as the fields extracted by the query. */ case DB_EVAL: { + int evalFlags = 0; + const char *zOpt; + while( objc>3 && (zOpt = Tcl_GetString(objv[2]))!=0 && zOpt[0]=='-' ){ + if( strcmp(zOpt, "-withoutnulls")==0 ){ + evalFlags |= SQLITE_EVAL_WITHOUTNULLS; + } + else{ + Tcl_AppendResult(interp, "unknown option: \"", zOpt, "\"", (void*)0); + return TCL_ERROR; + } + objc--; + objv++; + } if( objc<3 || objc>5 ){ - Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME? ?SCRIPT?"); + Tcl_WrongNumArgs(interp, 2, objv, + "?OPTIONS? SQL ?ARRAY-NAME? ?SCRIPT?"); return TCL_ERROR; } @@ -2490,7 +2515,7 @@ static int SQLITE_TCLAPI DbObjCmd( DbEvalContext sEval; Tcl_Obj *pRet = Tcl_NewObj(); Tcl_IncrRefCount(pRet); - dbEvalInit(&sEval, pDb, objv[2], 0); + dbEvalInit(&sEval, pDb, objv[2], 0, 0); while( TCL_OK==(rc = dbEvalStep(&sEval)) ){ int i; int nCol; @@ -2511,14 +2536,14 @@ static int SQLITE_TCLAPI DbObjCmd( Tcl_Obj *pArray = 0; Tcl_Obj *pScript; - if( objc==5 && *(char *)Tcl_GetString(objv[3]) ){ + if( objc>=5 && *(char *)Tcl_GetString(objv[3]) ){ pArray = objv[3]; } pScript = objv[objc-1]; Tcl_IncrRefCount(pScript); p = (DbEvalContext *)Tcl_Alloc(sizeof(DbEvalContext)); - dbEvalInit(p, pDb, objv[2], pArray); + dbEvalInit(p, pDb, objv[2], pArray, evalFlags); cd2[0] = (void *)p; cd2[1] = (void *)pScript; @@ -2861,7 +2886,7 @@ static int SQLITE_TCLAPI DbObjCmd( } /* - ** $db status (step|sort|autoindex) + ** $db status (step|sort|autoindex|vmstep) ** ** Display SQLITE_STMTSTATUS_FULLSCAN_STEP or ** SQLITE_STMTSTATUS_SORT for the most recent eval. @@ -2880,9 +2905,11 @@ static int SQLITE_TCLAPI DbObjCmd( v = pDb->nSort; }else if( strcmp(zOp, "autoindex")==0 ){ v = pDb->nIndex; + }else if( strcmp(zOp, "vmstep")==0 ){ + v = pDb->nVMStep; }else{ Tcl_AppendResult(interp, - "bad argument: should be autoindex, step, or sort", + "bad argument: should be autoindex, step, sort or vmstep", (char*)0); return TCL_ERROR; } diff --git a/src/test1.c b/src/test1.c index 87b255c9e..eaafd8775 100644 --- a/src/test1.c +++ b/src/test1.c @@ -7317,6 +7317,7 @@ static int SQLITE_TCLAPI test_sqlite3_db_config( { "FTS3_TOKENIZER", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, { "LOAD_EXTENSION", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, { "NO_CKPT_ON_CLOSE",SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, + { "QPSG", SQLITE_DBCONFIG_ENABLE_QPSG }, }; int i; int v; diff --git a/src/vacuum.c b/src/vacuum.c index 9e471b8d9..841aa5200 100644 --- a/src/vacuum.c +++ b/src/vacuum.c @@ -201,7 +201,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){ extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); int nKey; char *zKey; - sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); + sqlite3CodecGetKey(db, iDb, (void**)&zKey, &nKey); if( nKey ) db->nextPagesize = 0; } #endif diff --git a/src/vdbe.c b/src/vdbe.c index 4a412b4e5..ecdd92be9 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -6571,7 +6571,7 @@ case OP_Expire: { */ case OP_TableLock: { u8 isWriteLock = (u8)pOp->p3; - if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){ + if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommit) ){ int p1 = pOp->p1; assert( p1>=0 && p1<db->nDb ); assert( DbMaskTest(p->btreeMask, p1) ); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 2e81b0897..ce4a2f2de 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -4547,6 +4547,7 @@ sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){ assert( iVar>0 ); if( v ){ Mem *pMem = &v->aVar[iVar-1]; + assert( (v->db->flags & SQLITE_EnableQPSG)==0 ); if( 0==(pMem->flags & MEM_Null) ){ sqlite3_value *pRet = sqlite3ValueNew(v->db); if( pRet ){ @@ -4566,6 +4567,7 @@ sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){ */ void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){ assert( iVar>0 ); + assert( (v->db->flags & SQLITE_EnableQPSG)==0 ); if( iVar>=32 ){ v->expmask |= 0x80000000; }else{ diff --git a/src/vdbemem.c b/src/vdbemem.c index e95a8d1b9..41bb9b5c4 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -1325,7 +1325,7 @@ static int valueFromExpr( } }else if( op==TK_UMINUS ) { /* This branch happens for multiple negative signs. Ex: -(-5) */ - if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) + if( SQLITE_OK==valueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal,pCtx) && pVal!=0 ){ sqlite3VdbeMemNumerify(pVal); @@ -1482,14 +1482,13 @@ static int stat4ValueFromExpr( /* Skip over any TK_COLLATE nodes */ pExpr = sqlite3ExprSkipCollate(pExpr); + assert( pExpr==0 || pExpr->op!=TK_REGISTER || pExpr->op2!=TK_VARIABLE ); if( !pExpr ){ pVal = valueNew(db, pAlloc); if( pVal ){ sqlite3VdbeMemSetNull((Mem*)pVal); } - }else if( pExpr->op==TK_VARIABLE - || NEVER(pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE) - ){ + }else if( pExpr->op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){ Vdbe *v; int iBindVar = pExpr->iColumn; sqlite3VdbeSetVarmask(pParse->pVdbe, iBindVar); @@ -1497,9 +1496,7 @@ static int stat4ValueFromExpr( pVal = valueNew(db, pAlloc); if( pVal ){ rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iBindVar-1]); - if( rc==SQLITE_OK ){ - sqlite3ValueApplyAffinity(pVal, affinity, ENC(db)); - } + sqlite3ValueApplyAffinity(pVal, affinity, ENC(db)); pVal->db = pParse->db; } } diff --git a/src/where.c b/src/where.c index 89c4edeb8..41bcb3031 100644 --- a/src/where.c +++ b/src/where.c @@ -3972,6 +3972,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ rUnsorted, rCost)); }else{ rCost = rUnsorted; + rUnsorted -= 2; /* TUNING: Slight bias in favor of no-sort plans */ } /* Check to see if pWLoop should be added to the set of @@ -4295,6 +4296,31 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){ } /* +** Helper function for exprIsDeterministic(). +*/ +static int exprNodeIsDeterministic(Walker *pWalker, Expr *pExpr){ + if( pExpr->op==TK_FUNCTION && ExprHasProperty(pExpr, EP_ConstFunc)==0 ){ + pWalker->eCode = 0; + return WRC_Abort; + } + return WRC_Continue; +} + +/* +** Return true if the expression contains no non-deterministic SQL +** functions. Do not consider non-deterministic SQL functions that are +** part of sub-select statements. +*/ +static int exprIsDeterministic(Expr *p){ + Walker w; + memset(&w, 0, sizeof(w)); + w.eCode = 1; + w.xExprCallback = exprNodeIsDeterministic; + sqlite3WalkExpr(&w, p); + return w.eCode; +} + +/* ** Generate the beginning of the loop used for WHERE clause processing. ** The return value is a pointer to an opaque structure that contains ** information needed to terminate the loop. Later, the calling routine @@ -4492,17 +4518,6 @@ WhereInfo *sqlite3WhereBegin( sqlite3WhereClauseInit(&pWInfo->sWC, pWInfo); sqlite3WhereSplit(&pWInfo->sWC, pWhere, TK_AND); - /* Special case: a WHERE clause that is constant. Evaluate the - ** expression and either jump over all of the code or fall thru. - */ - for(ii=0; ii<sWLB.pWC->nTerm; ii++){ - if( nTabList==0 || sqlite3ExprIsConstantNotJoin(sWLB.pWC->a[ii].pExpr) ){ - sqlite3ExprIfFalse(pParse, sWLB.pWC->a[ii].pExpr, pWInfo->iBreak, - SQLITE_JUMPIFNULL); - sWLB.pWC->a[ii].wtFlags |= TERM_CODED; - } - } - /* Special case: No FROM clause */ if( nTabList==0 ){ @@ -4541,6 +4556,25 @@ WhereInfo *sqlite3WhereBegin( sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); if( db->mallocFailed ) goto whereBeginError; + /* Special case: WHERE terms that do not refer to any tables in the join + ** (constant expressions). Evaluate each such term, and jump over all the + ** generated code if the result is not true. + ** + ** Do not do this if the expression contains non-deterministic functions + ** that are not within a sub-select. This is not strictly required, but + ** preserves SQLite's legacy behaviour in the following two cases: + ** + ** FROM ... WHERE random()>0; -- eval random() once per row + ** FROM ... WHERE (SELECT random())>0; -- eval random() once overall + */ + for(ii=0; ii<sWLB.pWC->nTerm; ii++){ + WhereTerm *pT = &sWLB.pWC->a[ii]; + if( pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr)) ){ + sqlite3ExprIfFalse(pParse, pT->pExpr, pWInfo->iBreak, SQLITE_JUMPIFNULL); + pT->wtFlags |= TERM_CODED; + } + } + if( wctrlFlags & WHERE_WANT_DISTINCT ){ if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ /* The DISTINCT marking is pointless. Ignore it. */ @@ -4577,7 +4611,7 @@ WhereInfo *sqlite3WhereBegin( static const char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz" "ABCDEFGHIJKLMNOPQRSTUVWYXZ"; for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){ - p->cId = zLabel[i%sizeof(zLabel)]; + p->cId = zLabel[i%(sizeof(zLabel)-1)]; whereLoopPrint(p, sWLB.pWC); } } diff --git a/src/whereexpr.c b/src/whereexpr.c index 3625efa1e..76a091d52 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -216,7 +216,7 @@ static int isLikeOrGlob( pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr); op = pRight->op; - if( op==TK_VARIABLE ){ + if( op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){ Vdbe *pReprepare = pParse->pReprepare; int iCol = pRight->iColumn; pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_BLOB); @@ -1178,6 +1178,9 @@ static void exprAnalyze( Expr *pNewExpr; pNewExpr = sqlite3PExpr(pParse, TK_MATCH, 0, sqlite3ExprDup(db, pRight, 0)); + if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){ + ExprSetProperty(pNewExpr, EP_FromJoin); + } idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew==0 ); pNewTerm = &pWC->a[idxNew]; |