aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build.c2
-rw-r--r--src/pragma.c34
-rw-r--r--src/resolve.c2
-rw-r--r--src/shell.c58
-rw-r--r--src/sqlite.h.in9
-rw-r--r--src/vdbe.c10
-rw-r--r--src/where.c108
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