diff options
author | drh <drh@noemail.net> | 2013-10-28 22:47:24 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2013-10-28 22:47:24 +0000 |
commit | d63d4b7bd7a5c84972dd16524610782fe301556c (patch) | |
tree | 541baea6988e77e4a7e0b40ee4aa0f102924b87b /src | |
parent | d82d4750a80e474a9be03a6c9abb7fde1dc44ce2 (diff) | |
parent | 7afc8b0c3f374e5b8f60a15dcc9bf9945f81cb78 (diff) | |
download | sqlite-d63d4b7bd7a5c84972dd16524610782fe301556c.tar.gz sqlite-d63d4b7bd7a5c84972dd16524610782fe301556c.zip |
Merge all trunk changes since 3.8.1 into the sessions branch.
FossilOrigin-Name: aa72ea8a004de7fe744fc13baef19d05aea607d5
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 2 | ||||
-rw-r--r-- | src/pragma.c | 34 | ||||
-rw-r--r-- | src/resolve.c | 2 | ||||
-rw-r--r-- | src/shell.c | 58 | ||||
-rw-r--r-- | src/sqlite.h.in | 9 | ||||
-rw-r--r-- | src/vdbe.c | 10 | ||||
-rw-r--r-- | src/where.c | 108 |
7 files changed, 178 insertions, 45 deletions
diff --git a/src/build.c b/src/build.c index 6868e60e0..38bdad859 100644 --- a/src/build.c +++ b/src/build.c @@ -1714,7 +1714,7 @@ void sqlite3EndTable( /* Reparse everything to update our internal data structures */ sqlite3VdbeAddParseSchemaOp(v, iDb, - sqlite3MPrintf(db, "tbl_name='%q'", p->zName)); + sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName)); } diff --git a/src/pragma.c b/src/pragma.c index a1f32c36d..b130ba461 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -94,12 +94,14 @@ static const struct sPragmaNames { /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if !defined(SQLITE_OMIT_AUTOMATIC_INDEX) { /* zName: */ "automatic_index", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_AutoIndex }, #endif +#endif { /* zName: */ "busy_timeout", /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, /* ePragFlag: */ 0, @@ -110,18 +112,22 @@ static const struct sPragmaNames { /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) { /* zName: */ "cache_spill", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_CacheSpill }, +#endif { /* zName: */ "case_sensitive_like", /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE, /* ePragFlag: */ 0, /* iArg: */ 0 }, +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) { /* zName: */ "checkpoint_fullfsync", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_CkptFullFSync }, +#endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) { /* zName: */ "collation_list", /* ePragTyp: */ PragTyp_COLLATION_LIST, @@ -134,10 +140,12 @@ static const struct sPragmaNames { /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) { /* zName: */ "count_changes", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_CountRows }, +#endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN { /* zName: */ "data_store_directory", /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY, @@ -156,16 +164,20 @@ static const struct sPragmaNames { /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) { /* zName: */ "defer_foreign_keys", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_DeferFKs }, #endif +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) { /* zName: */ "empty_result_callbacks", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_NullCallback }, +#endif #if !defined(SQLITE_OMIT_UTF16) { /* zName: */ "encoding", /* ePragTyp: */ PragTyp_ENCODING, @@ -184,18 +196,21 @@ static const struct sPragmaNames { /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) { /* zName: */ "foreign_keys", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_ForeignKeys }, #endif +#endif #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) { /* zName: */ "freelist_count", /* ePragTyp: */ PragTyp_HEADER_VALUE, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) { /* zName: */ "full_column_names", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, @@ -204,6 +219,7 @@ static const struct sPragmaNames { /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_FullFSync }, +#endif #if defined(SQLITE_HAS_CODEC) { /* zName: */ "hexkey", /* ePragTyp: */ PragTyp_HEXKEY, @@ -214,12 +230,14 @@ static const struct sPragmaNames { /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if !defined(SQLITE_OMIT_CHECK) { /* zName: */ "ignore_check_constraints", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_IgnoreChecks }, #endif +#endif #if !defined(SQLITE_OMIT_AUTOVACUUM) { /* zName: */ "incremental_vacuum", /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM, @@ -258,10 +276,12 @@ static const struct sPragmaNames { /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) { /* zName: */ "legacy_file_format", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_LegacyFileFmt }, +#endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE { /* zName: */ "lock_proxy_file", /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE, @@ -302,16 +322,19 @@ static const struct sPragmaNames { /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) { /* zName: */ "query_only", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_QueryOnly }, +#endif #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) { /* zName: */ "quick_check", /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) { /* zName: */ "read_uncommitted", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, @@ -320,16 +343,19 @@ static const struct sPragmaNames { /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_RecTriggers }, +#endif #if defined(SQLITE_HAS_CODEC) { /* zName: */ "rekey", /* ePragTyp: */ PragTyp_REKEY, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) { /* zName: */ "reverse_unordered_selects", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_ReverseOrder }, +#endif #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) { /* zName: */ "schema_version", /* ePragTyp: */ PragTyp_HEADER_VALUE, @@ -342,10 +368,12 @@ static const struct sPragmaNames { /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) { /* zName: */ "short_column_names", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_ShortColNames }, +#endif { /* zName: */ "shrink_memory", /* ePragTyp: */ PragTyp_SHRINK_MEMORY, /* ePragFlag: */ 0, @@ -354,12 +382,14 @@ static const struct sPragmaNames { /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT, /* ePragFlag: */ 0, /* iArg: */ 0 }, +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if defined(SQLITE_DEBUG) { /* zName: */ "sql_trace", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_SqlTrace }, #endif +#endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) { /* zName: */ "stats", /* ePragTyp: */ PragTyp_STATS, @@ -394,6 +424,7 @@ static const struct sPragmaNames { /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if defined(SQLITE_DEBUG) { /* zName: */ "vdbe_addoptrace", /* ePragTyp: */ PragTyp_FLAG, @@ -412,6 +443,7 @@ static const struct sPragmaNames { /* ePragFlag: */ 0, /* iArg: */ SQLITE_VdbeTrace }, #endif +#endif #if !defined(SQLITE_OMIT_WAL) { /* zName: */ "wal_autocheckpoint", /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT, @@ -422,10 +454,12 @@ static const struct sPragmaNames { /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) { /* zName: */ "writable_schema", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, +#endif }; /* Number of pragmas: 56 on by default, 68 total. */ /* End of the automatically generated pragma table. diff --git a/src/resolve.c b/src/resolve.c index dfe4b84c4..92fbaaf15 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -709,7 +709,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ }else{ /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to ** likelihood(X, 0.0625). - ** EVIDENCE-OF: R-35738-39582 The unlikely(X) fucntion is short-hand for + ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is short-hand for ** likelihood(X,0.0625). */ pExpr->iTable = 62; /* TUNING: Default 2nd arg to unlikely() is 0.0625 */ } diff --git a/src/shell.c b/src/shell.c index 41ea56492..26c38c59e 100644 --- a/src/shell.c +++ b/src/shell.c @@ -436,6 +436,7 @@ struct callback_data { ** .explain ON */ char outfile[FILENAME_MAX]; /* Filename for *out */ const char *zDbFilename; /* name of the database file */ + char *zFreeOnClose; /* Filename to free when closing */ const char *zVfs; /* Name of VFS to use */ sqlite3_stmt *pStmt; /* Current statement if any. */ FILE *pLog; /* Write log output here */ @@ -1437,6 +1438,7 @@ static char zHelp[] = " tabs Tab-separated values\n" " tcl TCL list elements\n" ".nullvalue STRING Use STRING in place of NULL values\n" + ".open ?FILENAME? Close existing database and reopen FILENAME\n" ".output FILENAME Send output to FILENAME\n" ".output stdout Send output to the screen\n" ".print STRING... Print literal STRING\n" @@ -1470,7 +1472,7 @@ static int process_input(struct callback_data *p, FILE *in); ** Make sure the database is open. If it is not, then open it. If ** the database fails to open, print an error message and exit. */ -static void open_db(struct callback_data *p){ +static void open_db(struct callback_data *p, int keepAlive){ if( p->db==0 ){ sqlite3_initialize(); sqlite3_open(p->zDbFilename, &p->db); @@ -1482,6 +1484,7 @@ static void open_db(struct callback_data *p){ if( db==0 || SQLITE_OK!=sqlite3_errcode(db) ){ fprintf(stderr,"Error: unable to open database \"%s\": %s\n", p->zDbFilename, sqlite3_errmsg(db)); + if( keepAlive ) return; exit(1); } #ifndef SQLITE_OMIT_LOAD_EXTENSION @@ -1834,7 +1837,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ sqlite3_close(pDest); return 1; } - open_db(p); + open_db(p, 0); pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb); if( pBackup==0 ){ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); @@ -1866,7 +1869,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 && nArg==1 ){ struct callback_data data; char *zErrMsg = 0; - open_db(p); + open_db(p, 0); memcpy(&data, p, sizeof(data)); data.showHeader = 1; data.mode = MODE_Column; @@ -1883,7 +1886,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ }else if( c=='d' && strncmp(azArg[0], "dump", n)==0 && nArg<3 ){ - open_db(p); + open_db(p, 0); /* When playing back a "dump", the content might appear in an order ** which causes immediate foreign key constraints to be violated. ** So disable foreign-key constraint enforcement to prevent problems. */ @@ -2002,7 +2005,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ seenInterrupt = 0; memset(&sCsv, 0, sizeof(sCsv)); - open_db(p); + open_db(p, 0); nSep = strlen30(p->separator); if( nSep==0 ){ fprintf(stderr, "Error: non-null separator required for import\n"); @@ -2140,7 +2143,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg<3 ){ struct callback_data data; char *zErrMsg = 0; - open_db(p); + open_db(p, 0); memcpy(&data, p, sizeof(data)); data.showHeader = 0; data.mode = MODE_List; @@ -2206,7 +2209,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ char *zErrMsg = 0; zFile = azArg[1]; zProc = nArg>=3 ? azArg[2] : 0; - open_db(p); + open_db(p, 0); rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg); if( rc!=SQLITE_OK ){ fprintf(stderr, "Error: %s\n", zErrMsg); @@ -2272,6 +2275,26 @@ static int do_meta_command(char *zLine, struct callback_data *p){ "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]); }else + if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){ + sqlite3 *savedDb = p->db; + const char *zSavedFilename = p->zDbFilename; + char *zNewFilename = 0; + p->db = 0; + if( nArg>=2 ){ + p->zDbFilename = zNewFilename = sqlite3_mprintf("%s", azArg[1]); + } + open_db(p, 1); + if( p->db!=0 ){ + sqlite3_close(savedDb); + sqlite3_free(p->zFreeOnClose); + p->zFreeOnClose = zNewFilename; + }else{ + sqlite3_free(zNewFilename); + p->db = savedDb; + p->zDbFilename = zSavedFilename; + } + }else + if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){ if( p->outfile[0]=='|' ){ pclose(p->out); @@ -2355,7 +2378,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ sqlite3_close(pSrc); return 1; } - open_db(p); + open_db(p, 0); pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main"); if( pBackup==0 ){ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); @@ -2385,7 +2408,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( c=='s' && strncmp(azArg[0], "schema", n)==0 && nArg<3 ){ struct callback_data data; char *zErrMsg = 0; - open_db(p); + open_db(p, 0); memcpy(&data, p, sizeof(data)); data.showHeader = 0; data.mode = MODE_Semi; @@ -2516,7 +2539,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ int nRow, nAlloc; char *zSql = 0; int ii; - open_db(p); + open_db(p, 0); rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); if( rc ) return rc; zSql = sqlite3_mprintf( @@ -2616,7 +2639,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ int testctrl = -1; int rc = 0; int i, n; - open_db(p); + open_db(p, 0); /* convert testctrl text option to value. allow any unique prefix ** of the option name, or a numerical value. */ @@ -2715,7 +2738,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ }else if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 && nArg==2 ){ - open_db(p); + open_db(p, 0); sqlite3_busy_timeout(p->db, (int)integerValue(azArg[1])); }else @@ -2726,7 +2749,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ }else if( c=='t' && strncmp(azArg[0], "trace", n)==0 && nArg>1 ){ - open_db(p); + open_db(p, 0); output_file_close(p->traceOut); p->traceOut = output_file_open(azArg[1]); #if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) @@ -2918,7 +2941,7 @@ static int process_input(struct callback_data *p, FILE *in){ if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) && sqlite3_complete(zSql) ){ p->cnt = 0; - open_db(p); + open_db(p, 0); BEGIN_TIMER; rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg); END_TIMER; @@ -3245,7 +3268,7 @@ int main(int argc, char **argv){ ** to the sqlite command-line tool. */ if( access(data.zDbFilename, 0)==0 ){ - open_db(&data); + open_db(&data, 0); } /* Process the initialization file if there is one. If no -init option @@ -3325,7 +3348,7 @@ int main(int argc, char **argv){ rc = do_meta_command(z, &data); if( rc && bail_on_error ) return rc==2 ? 0 : rc; }else{ - open_db(&data); + open_db(&data, 0); rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg); if( zErrMsg!=0 ){ fprintf(stderr,"Error: %s\n", zErrMsg); @@ -3349,7 +3372,7 @@ int main(int argc, char **argv){ rc = do_meta_command(zFirstCmd, &data); if( rc==2 ) rc = 0; }else{ - open_db(&data); + open_db(&data, 0); rc = shell_exec(data.db, zFirstCmd, shell_callback, &data, &zErrMsg); if( zErrMsg!=0 ){ fprintf(stderr,"Error: %s\n", zErrMsg); @@ -3396,5 +3419,6 @@ int main(int argc, char **argv){ if( data.db ){ sqlite3_close(data.db); } + sqlite3_free(data.zFreeOnClose); return rc; } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 461b09ad3..8b1c14bf8 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -907,6 +907,14 @@ struct sqlite3_io_methods { ** can be queried by passing in a pointer to a negative number. This ** file-control is used internally to implement [PRAGMA mmap_size]. ** +** <li>[[SQLITE_FCNTL_TRACE]] +** The [SQLITE_FCNTL_TRACE] file control provides advisory information +** to the VFS about what the higher layers of the SQLite stack are doing. +** This file control is used by some VFS activity tracing [shims]. +** The argument is a zero-terminated string. Higher layers in the +** SQLite stack may generate instances of this file control if +** the [SQLITE_USE_FCNTL_TRACE] compile-time option is enabled. +** ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 @@ -926,6 +934,7 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_BUSYHANDLER 15 #define SQLITE_FCNTL_TEMPFILENAME 16 #define SQLITE_FCNTL_MMAP_SIZE 18 +#define SQLITE_FCNTL_TRACE 19 /* ** CAPI3REF: Mutex Handle diff --git a/src/vdbe.c b/src/vdbe.c index 95e8c6e57..9b384b4c6 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -6190,6 +6190,16 @@ case OP_Trace: { db->xTrace(db->pTraceArg, z); sqlite3DbFree(db, z); } +#ifdef SQLITE_USE_FCNTL_TRACE + zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); + if( zTrace ){ + int i; + for(i=0; i<db->nDb; i++){ + if( ((1<<i) & p->btreeMask)==0 ) continue; + sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace); + } + } +#endif /* SQLITE_USE_FCNTL_TRACE */ #ifdef SQLITE_DEBUG if( (db->flags & SQLITE_SqlTrace)!=0 && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 diff --git a/src/where.c b/src/where.c index d89ce6513..304732db6 100644 --- a/src/where.c +++ b/src/where.c @@ -878,7 +878,10 @@ static WhereTerm *whereScanNext(WhereScan *pScan){ iColumn = pScan->aEquiv[pScan->iEquiv-1]; while( (pWC = pScan->pWC)!=0 ){ for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ - if( pTerm->leftCursor==iCur && pTerm->u.leftColumn==iColumn ){ + if( pTerm->leftCursor==iCur + && pTerm->u.leftColumn==iColumn + && (pScan->iEquiv<=2 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) + ){ if( (pTerm->eOperator & WO_EQUIV)!=0 && pScan->nEquiv<ArraySize(pScan->aEquiv) ){ @@ -2550,7 +2553,7 @@ static int whereRangeScanEst( nOut = nNew; } pLoop->nOut = (LogEst)nOut; - WHERETRACE(0x100, ("range scan regions: %u..%u est=%d\n", + WHERETRACE(0x10, ("range scan regions: %u..%u est=%d\n", (u32)iLower, (u32)iUpper, nOut)); return SQLITE_OK; } @@ -2636,7 +2639,7 @@ static int whereEqualScanEst( pBuilder->nRecValid = nEq; whereKeyStats(pParse, p, pRec, 0, a); - WHERETRACE(0x100,("equality scan regions: %d\n", (int)a[1])); + WHERETRACE(0x10,("equality scan regions: %d\n", (int)a[1])); *pnRow = a[1]; return rc; @@ -2684,7 +2687,7 @@ static int whereInScanEst( if( rc==SQLITE_OK ){ if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0]; *pnRow = nRowEst; - WHERETRACE(0x100,("IN row estimate: est=%g\n", nRowEst)); + WHERETRACE(0x10,("IN row estimate: est=%g\n", nRowEst)); } assert( pBuilder->nRecValid==nRecValid ); return rc; @@ -3889,22 +3892,38 @@ static Bitmask codeOneLoopStart( return pLevel->notReady; } +#if defined(WHERETRACE_ENABLED) && defined(SQLITE_ENABLE_TREE_EXPLAIN) +/* +** Generate "Explanation" text for a WhereTerm. +*/ +static void whereExplainTerm(Vdbe *v, WhereTerm *pTerm){ + char zType[4]; + memcpy(zType, "...", 4); + if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V'; + if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E'; + if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L'; + sqlite3ExplainPrintf(v, "%s ", zType); + sqlite3ExplainExpr(v, pTerm->pExpr); +} +#endif /* WHERETRACE_ENABLED && SQLITE_ENABLE_TREE_EXPLAIN */ + + #ifdef WHERETRACE_ENABLED /* ** Print a WhereLoop object for debugging purposes */ -static void whereLoopPrint(WhereLoop *p, SrcList *pTabList){ - int nb = 1+(pTabList->nSrc+7)/8; - struct SrcList_item *pItem = pTabList->a + p->iTab; +static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){ + WhereInfo *pWInfo = pWC->pWInfo; + int nb = 1+(pWInfo->pTabList->nSrc+7)/8; + struct SrcList_item *pItem = pWInfo->pTabList->a + p->iTab; Table *pTab = pItem->pTab; sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId, p->iTab, nb, p->maskSelf, nb, p->prereq); sqlite3DebugPrintf(" %12s", pItem->zAlias ? pItem->zAlias : pTab->zName); if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ - if( p->u.btree.pIndex ){ - const char *zName = p->u.btree.pIndex->zName; - if( zName==0 ) zName = "ipk"; + const char *zName; + if( p->u.btree.pIndex && (zName = p->u.btree.pIndex->zName)!=0 ){ if( strncmp(zName, "sqlite_autoindex_", 17)==0 ){ int i = sqlite3Strlen30(zName) - 1; while( zName[i]!='_' ) i--; @@ -3927,6 +3946,26 @@ static void whereLoopPrint(WhereLoop *p, SrcList *pTabList){ } sqlite3DebugPrintf(" f %04x N %d", p->wsFlags, p->nLTerm); sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut); +#ifdef SQLITE_ENABLE_TREE_EXPLAIN + /* If the 0x100 bit of wheretracing is set, then show all of the constraint + ** expressions in the WhereLoop.aLTerm[] array. + */ + if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){ /* WHERETRACE 0x100 */ + int i; + Vdbe *v = pWInfo->pParse->pVdbe; + sqlite3ExplainBegin(v); + for(i=0; i<p->nLTerm; i++){ + WhereTerm *pTerm = p->aLTerm[i]; + sqlite3ExplainPrintf(v, " (%d) #%-2d ", i+1, (int)(pTerm-pWC->a)); + sqlite3ExplainPush(v); + whereExplainTerm(v, pTerm); + sqlite3ExplainPop(v); + sqlite3ExplainNL(v); + } + sqlite3ExplainFinish(v); + sqlite3DebugPrintf("%s", sqlite3VdbeExplanation(v)); + } +#endif } #endif @@ -4066,10 +4105,10 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ #endif whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun, pTemplate->nOut); -#if WHERETRACE_ENABLED +#if WHERETRACE_ENABLED /* 0x8 */ if( sqlite3WhereTrace & 0x8 ){ sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n); - whereLoopPrint(pTemplate, pWInfo->pTabList); + whereLoopPrint(pTemplate, pBuilder->pWC); } #endif return SQLITE_OK; @@ -4139,14 +4178,14 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ ** with pTemplate[] if p[] exists, or if p==NULL then allocate a new ** WhereLoop and insert it. */ -#if WHERETRACE_ENABLED +#if WHERETRACE_ENABLED /* 0x8 */ if( sqlite3WhereTrace & 0x8 ){ if( p!=0 ){ sqlite3DebugPrintf("ins-del: "); - whereLoopPrint(p, pWInfo->pTabList); + whereLoopPrint(p, pBuilder->pWC); } sqlite3DebugPrintf("ins-new: "); - whereLoopPrint(pTemplate, pWInfo->pTabList); + whereLoopPrint(pTemplate, pBuilder->pWC); } #endif if( p==0 ){ @@ -4167,10 +4206,10 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ /* Jump here if the insert is a no-op */ whereLoopInsert_noop: -#if WHERETRACE_ENABLED +#if WHERETRACE_ENABLED /* 0x8 */ if( sqlite3WhereTrace & 0x8 ){ sqlite3DebugPrintf("ins-noop: "); - whereLoopPrint(pTemplate, pWInfo->pTabList); + whereLoopPrint(pTemplate, pBuilder->pWC); } #endif return SQLITE_OK; @@ -5328,7 +5367,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ } if( jj>=nTo ){ if( nTo>=mxChoice && rCost>=mxCost ){ -#ifdef WHERETRACE_ENABLED +#ifdef WHERETRACE_ENABLED /* 0x4 */ if( sqlite3WhereTrace&0x4 ){ sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n", wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, @@ -5346,7 +5385,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ jj = mxI; } pTo = &aTo[jj]; -#ifdef WHERETRACE_ENABLED +#ifdef WHERETRACE_ENABLED /* 0x4 */ if( sqlite3WhereTrace&0x4 ){ sqlite3DebugPrintf("New %s cost=%-3d,%3d order=%c\n", wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, @@ -5355,7 +5394,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ #endif }else{ if( pTo->rCost<=rCost && pTo->nRow<=nOut ){ -#ifdef WHERETRACE_ENABLED +#ifdef WHERETRACE_ENABLED /* 0x4 */ if( sqlite3WhereTrace&0x4 ){ sqlite3DebugPrintf( "Skip %s cost=%-3d,%3d order=%c", @@ -5371,7 +5410,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ } testcase( pTo->rCost==rCost+1 ); /* A new and better score for a previously created equivalent path */ -#ifdef WHERETRACE_ENABLED +#ifdef WHERETRACE_ENABLED /* 0x4 */ if( sqlite3WhereTrace&0x4 ){ sqlite3DebugPrintf( "Update %s cost=%-3d,%3d order=%c", @@ -5407,7 +5446,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ } } -#ifdef WHERETRACE_ENABLED +#ifdef WHERETRACE_ENABLED /* >=2 */ if( sqlite3WhereTrace>=2 ){ sqlite3DebugPrintf("---- after round %d ----\n", iLoop); for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){ @@ -5816,12 +5855,29 @@ WhereInfo *sqlite3WhereBegin( /* Construct the WhereLoop objects */ WHERETRACE(0xffff,("*** Optimizer Start ***\n")); + /* Display all terms of the WHERE clause */ +#if defined(WHERETRACE_ENABLED) && defined(SQLITE_ENABLE_TREE_EXPLAIN) + if( sqlite3WhereTrace & 0x100 ){ + int i; + Vdbe *v = pParse->pVdbe; + sqlite3ExplainBegin(v); + for(i=0; i<sWLB.pWC->nTerm; i++){ + sqlite3ExplainPrintf(v, "#%-2d ", i); + sqlite3ExplainPush(v); + whereExplainTerm(v, &sWLB.pWC->a[i]); + sqlite3ExplainPop(v); + sqlite3ExplainNL(v); + } + sqlite3ExplainFinish(v); + sqlite3DebugPrintf("%s", sqlite3VdbeExplanation(v)); + } +#endif if( nTabList!=1 || whereShortCut(&sWLB)==0 ){ rc = whereLoopAddAll(&sWLB); if( rc ) goto whereBeginError; /* Display all of the WhereLoop objects if wheretrace is enabled */ -#ifdef WHERETRACE_ENABLED +#ifdef WHERETRACE_ENABLED /* !=0 */ if( sqlite3WhereTrace ){ WhereLoop *p; int i; @@ -5829,7 +5885,7 @@ WhereInfo *sqlite3WhereBegin( "ABCDEFGHIJKLMNOPQRSTUVWYXZ"; for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){ p->cId = zLabel[i%sizeof(zLabel)]; - whereLoopPrint(p, pTabList); + whereLoopPrint(p, sWLB.pWC); } } #endif @@ -5847,7 +5903,7 @@ WhereInfo *sqlite3WhereBegin( if( pParse->nErr || NEVER(db->mallocFailed) ){ goto whereBeginError; } -#ifdef WHERETRACE_ENABLED +#ifdef WHERETRACE_ENABLED /* !=0 */ if( sqlite3WhereTrace ){ int ii; sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut); @@ -5870,7 +5926,7 @@ WhereInfo *sqlite3WhereBegin( } sqlite3DebugPrintf("\n"); for(ii=0; ii<pWInfo->nLevel; ii++){ - whereLoopPrint(pWInfo->a[ii].pWLoop, pTabList); + whereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC); } } #endif |