mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-03 16:53:36 +03:00
Import the "PRAGMA vdbe_eqp" enhancement and the enhanced EXPLAIN formatting
the shell from trunk. Fix a bug in skip-scan and add a test case to prevent a regression. FossilOrigin-Name: f668616a29686f3ce532731c534b168e536adbb5
This commit is contained in:
32
manifest
32
manifest
@@ -1,5 +1,5 @@
|
||||
C Add\sVDBE\scomments\sto\sthe\sbeginning\sand\send\sof\sskip-scan\sloops.
|
||||
D 2013-11-13T17:24:39.000
|
||||
C Import\sthe\s"PRAGMA\svdbe_eqp"\senhancement\sand\sthe\senhanced\sEXPLAIN\sformatting\nthe\sshell\sfrom\strunk.\s\sFix\sa\sbug\sin\sskip-scan\sand\sadd\sa\stest\scase\sto\sprevent\na\sregression.
|
||||
D 2013-11-13T19:01:41.390
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 8a07bebafbfda0eb67728f4bd15a36201662d1a1
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@@ -169,7 +169,7 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c 260dedc13119e6fb7930380bd3d294b98362bf5a
|
||||
F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf
|
||||
F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
|
||||
F src/build.c 4d740243144d9e5058a46df7d05d1243f449b4d7
|
||||
F src/build.c 2baeed38bdaa9f1199f101c63db41fdcc4b39ba5
|
||||
F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
|
||||
@@ -213,18 +213,18 @@ F src/parse.y 073a8294e1826f1b1656e84806b77e4199f4bb57
|
||||
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
|
||||
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
|
||||
F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63
|
||||
F src/pragma.c 3b7b766382ac679d3c1a7ba368aa008f9a756d59
|
||||
F src/pragma.c c8d70c47ec8d8ba93575d92e34d30ddff8e9b517
|
||||
F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f
|
||||
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
|
||||
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
|
||||
F src/resolve.c fc4673cc49b116e51e7f12de074c0acf8f2388f9
|
||||
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
||||
F src/select.c 7317406831ecced390edba972818f3c5f82238c0
|
||||
F src/shell.c 03d8d9b4052430343ff30d646334621f980f1202
|
||||
F src/shell.c 6ccc22b717afe4f6d7d3c8b6baa02e3b99a5fdf0
|
||||
F src/sqlite.h.in 4dedcab5b32358bf7a596badffe7363be1f1a82d
|
||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h 3da1940a2ba05a663e9016d57f1ea1f79ffcb03e
|
||||
F src/sqliteInt.h 2ec1d71220307fa5ee85a918a6240cf0b4635b0e
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
@@ -280,11 +280,11 @@ F src/update.c 3de7e657b98ac67338d775c114a4068faf732402
|
||||
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
||||
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
|
||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||
F src/vdbe.c fda0d2ba5a3a5ab588f0467782e7fd64930ddb22
|
||||
F src/vdbe.h 8d5a7351024d80374fc0acdbbe3cfe65c51ba8b6
|
||||
F src/vdbeInt.h f2fa3ceccceeb757773921fb08af7c6e9f3caa1c
|
||||
F src/vdbe.c 3d73013b4ef54061e768443fb35a36b3dd289663
|
||||
F src/vdbe.h c06f0813f853566457ce9cfb1a4a4bc39a5da644
|
||||
F src/vdbeInt.h 62eb680327011f3a4b0336642b0ca9d6ecc6eb91
|
||||
F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed
|
||||
F src/vdbeaux.c 75c5fee307004739d814a840699df5e853e02b79
|
||||
F src/vdbeaux.c dd0f6ab9dc159911facfc0a7a2164af44779bdda
|
||||
F src/vdbeblob.c ff60adf2953e0ffc1d59541b3101c9886b03a3de
|
||||
F src/vdbemem.c cc529bbf4f13e4e181bdb446bf6e6962ab030b4b
|
||||
F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147
|
||||
@@ -293,7 +293,7 @@ F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d
|
||||
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
|
||||
F src/where.c 1d19a1d49a608441fa697ae32627399073be8dcf
|
||||
F src/where.c 2eb88f96a73d77bd61d6afd50c33ec5d63c15dd5
|
||||
F src/whereInt.h 96a75c61f1d2b9d4a8e4bb17d89deb0cf7cba358
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
@@ -805,7 +805,7 @@ F test/shell5.test 46c8c18d62732415c4fe084816c13d559831705e
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
|
||||
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
|
||||
F test/skipscan1.test bc65ecb228eba396c404aa038f49798340f0677f
|
||||
F test/skipscan1.test 6bb4891c2cc5efd5690a9da9e7508e53d4a68e10
|
||||
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
|
||||
F test/softheap1.test 40562fe6cac6d9827b7b42b86d45aedf12c15e24
|
||||
F test/sort.test 0e4456e729e5a92a625907c63dcdedfbe72c5dc5
|
||||
@@ -1106,7 +1106,7 @@ F tool/logest.c 7ad625cac3d54012b27d468b7af6612f78b9ba75
|
||||
F tool/mkautoconfamal.sh f8d8dbf7d62f409ebed5134998bf5b51d7266383
|
||||
F tool/mkkeywordhash.c 189d76644e373c7d0864c628deb8ce7b4f403591
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkpragmatab.tcl 17d40faae6c4b865633bfc5763821402a1cbefc3
|
||||
F tool/mkpragmatab.tcl 78a77b2c554d534c6f2dc903130186ed15715460
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl 8bce31074e4cbe631bb7676526a048335f4c9f02
|
||||
F tool/mksqlite3c.tcl e2ba20d3f690990079d17f3e5a7417dfb7ada543
|
||||
@@ -1139,7 +1139,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||
P 5e75ab93881b85801cb4ebf70f2063ff7c51ac19
|
||||
R 324d2d53e7ac48858b72f1751f7e7610
|
||||
P 0c85d93b52311dee7980d977be6ed0dc70b060c1 e7d34ec6814ed4606a6d5d7f68c218ae4d25e666
|
||||
R 0f42dd23f60246e0b55a84d51974156a
|
||||
U drh
|
||||
Z 7cfb6326eedc7a21a0bd15f40c4f97e2
|
||||
Z 2c708550c85df0e56ea327d75809b287
|
||||
|
||||
@@ -1 +1 @@
|
||||
0c85d93b52311dee7980d977be6ed0dc70b060c1
|
||||
f668616a29686f3ce532731c534b168e536adbb5
|
||||
@@ -193,10 +193,6 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
/* Get the VDBE program ready for execution
|
||||
*/
|
||||
if( v && ALWAYS(pParse->nErr==0) && !db->mallocFailed ){
|
||||
#ifdef SQLITE_DEBUG
|
||||
FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
|
||||
sqlite3VdbeTrace(v, trace);
|
||||
#endif
|
||||
assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */
|
||||
/* A minimum of one cursor is required if autoincrement is used
|
||||
* See ticket [a696379c1f08866] */
|
||||
|
||||
@@ -434,6 +434,10 @@ static const struct sPragmaNames {
|
||||
/* ePragTyp: */ PragTyp_FLAG,
|
||||
/* ePragFlag: */ 0,
|
||||
/* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace },
|
||||
{ /* zName: */ "vdbe_eqp",
|
||||
/* ePragTyp: */ PragTyp_FLAG,
|
||||
/* ePragFlag: */ 0,
|
||||
/* iArg: */ SQLITE_VdbeEQP },
|
||||
{ /* zName: */ "vdbe_listing",
|
||||
/* ePragTyp: */ PragTyp_FLAG,
|
||||
/* ePragFlag: */ 0,
|
||||
@@ -461,7 +465,7 @@ static const struct sPragmaNames {
|
||||
/* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
|
||||
#endif
|
||||
};
|
||||
/* Number of pragmas: 56 on by default, 68 total. */
|
||||
/* Number of pragmas: 56 on by default, 69 total. */
|
||||
/* End of the automatically generated pragma table.
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
103
src/shell.c
103
src/shell.c
@@ -464,6 +464,8 @@ struct callback_data {
|
||||
const char *zVfs; /* Name of VFS to use */
|
||||
sqlite3_stmt *pStmt; /* Current statement if any. */
|
||||
FILE *pLog; /* Write log output here */
|
||||
int *aiIndent; /* Array of indents used in MODE_Explain */
|
||||
int nIndent; /* Size of array aiIndent[] */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -765,10 +767,15 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int
|
||||
}else{
|
||||
w = 10;
|
||||
}
|
||||
if( p->mode==MODE_Explain && azArg[i] &&
|
||||
strlen30(azArg[i])>w ){
|
||||
if( p->mode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){
|
||||
w = strlen30(azArg[i]);
|
||||
}
|
||||
if( i==1 && p->aiIndent && p->pStmt ){
|
||||
int iOp = sqlite3_column_int(p->pStmt, 0);
|
||||
if( iOp<p->nIndent ){
|
||||
fprintf(p->out, "%*.s", p->aiIndent[iOp], "");
|
||||
}
|
||||
}
|
||||
if( w<0 ){
|
||||
fprintf(p->out,"%*.*s%s",-w,-w,
|
||||
azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " ");
|
||||
@@ -1141,6 +1148,90 @@ static int display_stats(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Parameter azArray points to a zero-terminated array of strings. zStr
|
||||
** points to a single nul-terminated string. Return non-zero if zStr
|
||||
** is equal, according to strcmp(), to any of the strings in the array.
|
||||
** Otherwise, return zero.
|
||||
*/
|
||||
static int str_in_array(const char *zStr, const char **azArray){
|
||||
int i;
|
||||
for(i=0; azArray[i]; i++){
|
||||
if( 0==strcmp(zStr, azArray[i]) ) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** If compiled statement pSql appears to be an EXPLAIN statement, allocate
|
||||
** and populate the callback_data.aiIndent[] array with the number of
|
||||
** spaces each opcode should be indented before it is output.
|
||||
**
|
||||
** The indenting rules are:
|
||||
**
|
||||
** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
|
||||
** all opcodes that occur between the p2 jump destination and the opcode
|
||||
** itself by 2 spaces.
|
||||
**
|
||||
** * For each "Goto", if the jump destination is a "Yield", "SeekGt",
|
||||
** or "SeekLt" instruction that occurs earlier in the program than
|
||||
** the Goto itself, indent all opcodes between the earlier instruction
|
||||
** and "Goto" by 2 spaces.
|
||||
*/
|
||||
static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
|
||||
const char *zSql; /* The text of the SQL statement */
|
||||
const char *z; /* Used to check if this is an EXPLAIN */
|
||||
int *abYield = 0; /* True if op is an OP_Yield */
|
||||
int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
|
||||
int iOp;
|
||||
|
||||
const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", 0 };
|
||||
const char *azYield[] = { "Yield", "SeekLt", "SeekGt", 0 };
|
||||
const char *azGoto[] = { "Goto", 0 };
|
||||
|
||||
/* Try to figure out if this is really an EXPLAIN statement. If this
|
||||
** cannot be verified, return early. */
|
||||
zSql = sqlite3_sql(pSql);
|
||||
if( zSql==0 ) return;
|
||||
for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
|
||||
if( sqlite3_strnicmp(z, "explain", 7) ) return;
|
||||
|
||||
for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
|
||||
int i;
|
||||
const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
|
||||
int p2 = sqlite3_column_int(pSql, 3);
|
||||
|
||||
/* Grow the p->aiIndent array as required */
|
||||
if( iOp>=nAlloc ){
|
||||
nAlloc += 100;
|
||||
p->aiIndent = (int*)sqlite3_realloc(p->aiIndent, nAlloc*sizeof(int));
|
||||
abYield = (int*)sqlite3_realloc(abYield, nAlloc*sizeof(int));
|
||||
}
|
||||
abYield[iOp] = str_in_array(zOp, azYield);
|
||||
p->aiIndent[iOp] = 0;
|
||||
p->nIndent = iOp+1;
|
||||
|
||||
if( str_in_array(zOp, azNext) ){
|
||||
for(i=p2; i<iOp; i++) p->aiIndent[i] += 2;
|
||||
}
|
||||
if( str_in_array(zOp, azGoto) && p2<p->nIndent && abYield[p2] ){
|
||||
for(i=p2+1; i<iOp; i++) p->aiIndent[i] += 2;
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_free(abYield);
|
||||
sqlite3_reset(pSql);
|
||||
}
|
||||
|
||||
/*
|
||||
** Free the array allocated by explain_data_prepare().
|
||||
*/
|
||||
static void explain_data_delete(struct callback_data *p){
|
||||
sqlite3_free(p->aiIndent);
|
||||
p->aiIndent = 0;
|
||||
p->nIndent = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Execute a statement or set of statements. Print
|
||||
** any result rows/columns depending on the current mode
|
||||
@@ -1202,6 +1293,12 @@ static int shell_exec(
|
||||
}
|
||||
}
|
||||
|
||||
/* If the shell is currently in ".explain" mode, gather the extra
|
||||
** data required to add indents to the output.*/
|
||||
if( pArg->mode==MODE_Explain ){
|
||||
explain_data_prepare(pArg, pStmt);
|
||||
}
|
||||
|
||||
/* perform the first step. this will tell us if we
|
||||
** have a result set or not and how wide it is.
|
||||
*/
|
||||
@@ -1259,6 +1356,8 @@ static int shell_exec(
|
||||
}
|
||||
}
|
||||
|
||||
explain_data_delete(pArg);
|
||||
|
||||
/* print usage stats if stats on */
|
||||
if( pArg && pArg->statsOn ){
|
||||
display_stats(db, pArg, 0);
|
||||
|
||||
@@ -1043,6 +1043,7 @@ struct sqlite3 {
|
||||
#define SQLITE_EnableTrigger 0x00800000 /* True to enable triggers */
|
||||
#define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */
|
||||
#define SQLITE_QueryOnly 0x02000000 /* Disable database changes */
|
||||
#define SQLITE_VdbeEQP 0x04000000 /* Debug EXPLAIN QUERY PLAN */
|
||||
|
||||
|
||||
/*
|
||||
|
||||
66
src/vdbe.c
66
src/vdbe.c
@@ -417,37 +417,36 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
|
||||
/*
|
||||
** Print the value of a register for tracing purposes:
|
||||
*/
|
||||
static void memTracePrint(FILE *out, Mem *p){
|
||||
static void memTracePrint(Mem *p){
|
||||
if( p->flags & MEM_Invalid ){
|
||||
fprintf(out, " undefined");
|
||||
printf(" undefined");
|
||||
}else if( p->flags & MEM_Null ){
|
||||
fprintf(out, " NULL");
|
||||
printf(" NULL");
|
||||
}else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
|
||||
fprintf(out, " si:%lld", p->u.i);
|
||||
printf(" si:%lld", p->u.i);
|
||||
}else if( p->flags & MEM_Int ){
|
||||
fprintf(out, " i:%lld", p->u.i);
|
||||
printf(" i:%lld", p->u.i);
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
}else if( p->flags & MEM_Real ){
|
||||
fprintf(out, " r:%g", p->r);
|
||||
printf(" r:%g", p->r);
|
||||
#endif
|
||||
}else if( p->flags & MEM_RowSet ){
|
||||
fprintf(out, " (rowset)");
|
||||
printf(" (rowset)");
|
||||
}else{
|
||||
char zBuf[200];
|
||||
sqlite3VdbeMemPrettyPrint(p, zBuf);
|
||||
fprintf(out, " ");
|
||||
fprintf(out, "%s", zBuf);
|
||||
printf(" %s", zBuf);
|
||||
}
|
||||
}
|
||||
static void registerTrace(FILE *out, int iReg, Mem *p){
|
||||
fprintf(out, "REG[%d] = ", iReg);
|
||||
memTracePrint(out, p);
|
||||
fprintf(out, "\n");
|
||||
static void registerTrace(int iReg, Mem *p){
|
||||
printf("REG[%d] = ", iReg);
|
||||
memTracePrint(p);
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
# define REGISTER_TRACE(R,M) if(p->trace)registerTrace(p->trace,R,M)
|
||||
# define REGISTER_TRACE(R,M) if(db->flags&SQLITE_VdbeTrace)registerTrace(R,M)
|
||||
#else
|
||||
# define REGISTER_TRACE(R,M)
|
||||
#endif
|
||||
@@ -586,13 +585,28 @@ int sqlite3VdbeExec(
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
sqlite3BeginBenignMalloc();
|
||||
if( p->pc==0 && (p->db->flags & SQLITE_VdbeListing)!=0 ){
|
||||
if( p->pc==0
|
||||
&& (p->db->flags & (SQLITE_VdbeListing|SQLITE_VdbeEQP|SQLITE_VdbeTrace))!=0
|
||||
){
|
||||
int i;
|
||||
printf("VDBE Program Listing:\n");
|
||||
int once = 1;
|
||||
sqlite3VdbePrintSql(p);
|
||||
for(i=0; i<p->nOp; i++){
|
||||
sqlite3VdbePrintOp(stdout, i, &aOp[i]);
|
||||
if( p->db->flags & SQLITE_VdbeListing ){
|
||||
printf("VDBE Program Listing:\n");
|
||||
for(i=0; i<p->nOp; i++){
|
||||
sqlite3VdbePrintOp(stdout, i, &aOp[i]);
|
||||
}
|
||||
}
|
||||
if( p->db->flags & SQLITE_VdbeEQP ){
|
||||
for(i=0; i<p->nOp; i++){
|
||||
if( aOp[i].opcode==OP_Explain ){
|
||||
if( once ) printf("VDBE Query Plan:\n");
|
||||
printf("%s\n", aOp[i].p4.z);
|
||||
once = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( p->db->flags & SQLITE_VdbeTrace ) printf("VDBE Trace:\n");
|
||||
}
|
||||
sqlite3EndBenignMalloc();
|
||||
#endif
|
||||
@@ -609,12 +623,8 @@ int sqlite3VdbeExec(
|
||||
/* Only allow tracing if SQLITE_DEBUG is defined.
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( p->trace ){
|
||||
if( pc==0 ){
|
||||
printf("VDBE Execution Trace:\n");
|
||||
sqlite3VdbePrintSql(p);
|
||||
}
|
||||
sqlite3VdbePrintOp(p->trace, pc, pOp);
|
||||
if( db->flags & SQLITE_VdbeTrace ){
|
||||
sqlite3VdbePrintOp(stdout, pc, pOp);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6255,13 +6265,13 @@ default: { /* This is really OP_Noop and OP_Explain */
|
||||
assert( pc>=-1 && pc<p->nOp );
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( p->trace ){
|
||||
if( rc!=0 ) fprintf(p->trace,"rc=%d\n",rc);
|
||||
if( db->flags & SQLITE_VdbeTrace ){
|
||||
if( rc!=0 ) printf("rc=%d\n",rc);
|
||||
if( pOp->opflags & (OPFLG_OUT2_PRERELEASE|OPFLG_OUT2) ){
|
||||
registerTrace(p->trace, pOp->p2, &aMem[pOp->p2]);
|
||||
registerTrace(pOp->p2, &aMem[pOp->p2]);
|
||||
}
|
||||
if( pOp->opflags & OPFLG_OUT3 ){
|
||||
registerTrace(p->trace, pOp->p3, &aMem[pOp->p3]);
|
||||
registerTrace(pOp->p3, &aMem[pOp->p3]);
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
@@ -189,7 +189,6 @@ void sqlite3VdbeResolveLabel(Vdbe*, int);
|
||||
int sqlite3VdbeCurrentAddr(Vdbe*);
|
||||
#ifdef SQLITE_DEBUG
|
||||
int sqlite3VdbeAssertMayAbort(Vdbe *, int);
|
||||
void sqlite3VdbeTrace(Vdbe*,FILE*);
|
||||
#endif
|
||||
void sqlite3VdbeResetStepResult(Vdbe*);
|
||||
void sqlite3VdbeRewind(Vdbe*);
|
||||
|
||||
@@ -355,9 +355,6 @@ struct Vdbe {
|
||||
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
|
||||
char *zSql; /* Text of the SQL statement that generated this */
|
||||
void *pFree; /* Free this when deleting the vdbe */
|
||||
#ifdef SQLITE_DEBUG
|
||||
FILE *trace; /* Write an execution trace here, if not NULL */
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_TREE_EXPLAIN
|
||||
Explain *pExplain; /* The explainer */
|
||||
char *zExplain; /* Explanation of data structures */
|
||||
|
||||
@@ -78,15 +78,6 @@ void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
|
||||
pB->isPrepareV2 = pA->isPrepareV2;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Turn tracing on or off
|
||||
*/
|
||||
void sqlite3VdbeTrace(Vdbe *p, FILE *trace){
|
||||
p->trace = trace;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Resize the Vdbe.aOp array so that it is at least one op larger than
|
||||
** it was.
|
||||
@@ -1415,15 +1406,17 @@ int sqlite3VdbeList(
|
||||
** Print the SQL that was used to generate a VDBE program.
|
||||
*/
|
||||
void sqlite3VdbePrintSql(Vdbe *p){
|
||||
int nOp = p->nOp;
|
||||
VdbeOp *pOp;
|
||||
if( nOp<1 ) return;
|
||||
pOp = &p->aOp[0];
|
||||
if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){
|
||||
const char *z = pOp->p4.z;
|
||||
while( sqlite3Isspace(*z) ) z++;
|
||||
printf("SQL: [%s]\n", z);
|
||||
const char *z = 0;
|
||||
if( p->zSql ){
|
||||
z = p->zSql;
|
||||
}else if( p->nOp>=1 ){
|
||||
const VdbeOp *pOp = &p->aOp[0];
|
||||
if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){
|
||||
z = pOp->p4.z;
|
||||
while( sqlite3Isspace(*z) ) z++;
|
||||
}
|
||||
}
|
||||
if( z ) printf("SQL: [%s]\n", z);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -2650,7 +2650,10 @@ static void explainOneScan(
|
||||
int iFrom, /* Value for "from" column of output */
|
||||
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
|
||||
){
|
||||
if( pParse->explain==2 ){
|
||||
#ifndef SQLITE_DEBUG
|
||||
if( pParse->explain==2 )
|
||||
#endif
|
||||
{
|
||||
struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
|
||||
Vdbe *v = pParse->pVdbe; /* VM being constructed */
|
||||
sqlite3 *db = pParse->db; /* Database handle */
|
||||
@@ -3852,6 +3855,7 @@ static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop){
|
||||
if( (pTerm->prereqAll & notAllowed)!=0 ) continue;
|
||||
for(j=pLoop->nLTerm-1; j>=0; j--){
|
||||
pX = pLoop->aLTerm[j];
|
||||
if( pX==0 ) continue;
|
||||
if( pX==pTerm ) break;
|
||||
if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break;
|
||||
}
|
||||
|
||||
@@ -98,6 +98,21 @@ do_execsql_test skipscan1-1.6sort {
|
||||
SELECT a,b,c,d,'|' FROM t1 WHERE c BETWEEN 6 AND 7 ORDER BY a, b, c;
|
||||
} {~/*ORDER BY*/}
|
||||
|
||||
do_execsql_test skipscan1-1.7 {
|
||||
SELECT a,b,c,d,'|' FROM t1 WHERE b IN (234, 345) AND c BETWEEN 6 AND 7
|
||||
ORDER BY a, b;
|
||||
} {abc 234 6 7 | abc 345 7 8 |}
|
||||
do_execsql_test skipscan1-1.7eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a,b,c,d,'|' FROM t1 WHERE b IN (234, 345) AND c BETWEEN 6 AND 7
|
||||
ORDER BY a, b;
|
||||
} {/* USING INDEX t1abc (ANY(a) AND b=? AND c>? AND c<?)*/}
|
||||
do_execsql_test skipscan1-1.7sort {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a,b,c,d,'|' FROM t1 WHERE b IN (234, 345) AND c BETWEEN 6 AND 7
|
||||
ORDER BY a, b;
|
||||
} {~/*ORDER BY*/}
|
||||
|
||||
|
||||
# Joins
|
||||
#
|
||||
|
||||
@@ -97,6 +97,12 @@ set pragma_def {
|
||||
IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
||||
IF: defined(SQLITE_DEBUG)
|
||||
|
||||
NAME: vdbe_eqp
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_VdbeEQP
|
||||
IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
||||
IF: defined(SQLITE_DEBUG)
|
||||
|
||||
NAME: ignore_check_constraints
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_IgnoreChecks
|
||||
|
||||
Reference in New Issue
Block a user