]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the experimental EXPLAIN QUERY PLAN diagnostic capability. (CVS 2685)
authordrh <drh@noemail.net>
Sat, 10 Sep 2005 16:46:12 +0000 (16:46 +0000)
committerdrh <drh@noemail.net>
Sat, 10 Sep 2005 16:46:12 +0000 (16:46 +0000)
FossilOrigin-Name: 986efb7b12643800805ad4b1f1e90e30fcf6d38a

manifest
manifest.uuid
src/parse.y
src/prepare.c
src/vdbe.c
src/vdbeaux.c
src/where.c
tool/mkkeywordhash.c

index 22502d5733fd4f1413d23c507c410823895dd66a..99d853d8d5a04550bc82141b644948c398662ee7 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Avoid\sa\smemory\sleak\sand/or\sassertion\sfailure\swhen\sparsing\sa\stable\r\ndeclaration\sthat\scontains\sa\sduplicate\scolumn\sname.\r\nTicket\s#1418.\s(CVS\s2684)
-D 2005-09-10T15:35:07
+C Add\sthe\sexperimental\sEXPLAIN\sQUERY\sPLAN\sdiagnostic\scapability.\s(CVS\s2685)
+D 2005-09-10T16:46:13
 F Makefile.in 12784cdce5ffc8dfb707300c34e4f1eb3b8a14f1
 F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -58,9 +58,9 @@ F src/os_win.c ed03a35b2894f9b99840415f941a9f8594dea756
 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
 F src/pager.c 2b48db1cc6073a6d2577100866db6ae039d20940
 F src/pager.h 17b13225abd93c1e9f470060f40a21b9edb5a164
-F src/parse.y 13c3d16e999184cb5fba39e44f133cdf01288e3e
+F src/parse.y c97d885c344579c55257e0bbaeaa1daa1659ef2d
 F src/pragma.c 69413fbdc0c6aaa493a776ea52c1b3e6cf35dfb2
-F src/prepare.c 86f0d8e744b8d956eff6bc40e29049efee017610
+F src/prepare.c fc098db25d2a121affb08686cf04833fd50452d4
 F src/printf.c c01e9ad473d79463fb1f483b1eca5c3cbed2a4e5
 F src/random.c 90adff4e73a3b249eb4f1fc2a6ff9cf78c7233a4
 F src/select.c a255ca7eddd14c68d966b6323234dd94fcc7a31f
@@ -80,14 +80,14 @@ F src/update.c c2716c2115533ffae3d08bf8853aaba4f970f37e
 F src/utf.c bda5eb85039ef16f2d17004c1e18c96e1ab0a80c
 F src/util.c 5650f6fe5ee30e0678985ad7b94da91e3f85752b
 F src/vacuum.c 829d9e1a6d7c094b80e0899686670932eafd768c
-F src/vdbe.c f722fbaf81890c342a1e1bf5a8a1600c5212ba47
+F src/vdbe.c 7b20b81b2643c0cc616c3fec6435f13c6e5fa6db
 F src/vdbe.h c8e105979fc7aaf5b8004e9621904e3bd096dfa2
 F src/vdbeInt.h 3dd2a29c7b0a55404c35f93caae81fb42f4cb70a
 F src/vdbeapi.c 72213ce0c1ab8b215b2ae0ed342511bf769c1e60
-F src/vdbeaux.c a0aaf135c39825027366b5129f85191226d8b333
+F src/vdbeaux.c 670264f8b8ddbc4277adf85ab945a59a3aaef871
 F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5
 F src/vdbemem.c fea0744936008831daa17cdc75056c3ca1469690
-F src/where.c d032cca1b983ad14fb0361f1f7a2706c5e7a9720
+F src/where.c 715e317eb37b89961ad7c5515a18f1e2eb1c7fd8
 F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
 F test/all.test 7f0988442ab811dfa41793b5b550f5828ce316f3
 F test/alter.test 9d6837a3d946b73df692b7cef2a7644d2e2f6bc6
@@ -243,7 +243,7 @@ F tool/lempar.c f0c30abcae762a7d1eb37cd88b2232ab8dd625fb
 F tool/memleak.awk 4e7690a51bf3ed757e611273d43fe3f65b510133
 F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
 F tool/memleak3.tcl 009da0ea82dc5893edca76cf1a21fb7260e9412e
-F tool/mkkeywordhash.c e0b7833fef924e3c75d5e5c28fdcdb879909bdfb
+F tool/mkkeywordhash.c 5263a654e5c9fd8d6e3238fb39c2d5c3126be32f
 F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
 F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
 F tool/report1.txt 9eae07f26a8fc53889b45fc833a66a33daa22816
@@ -306,7 +306,7 @@ F www/tclsqlite.tcl 3df553505b6efcad08f91e9b975deb2e6c9bb955
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
 F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P 415b8b24629aa12756d8285c094b5f85d8a8e532
-R 235cc9d948e051600520eade7dbee36c
+P f43427742b1c086f2621c900f4ede1a34a8b44ee
+R ab598fe85832474fa8020d661437e050
 U drh
-Z be7b5a2752d3ffcf1cf1e2330b39e495
+Z 6732d617323055d4bde842448e4c98ca
index ae88ac8ec8b3e42129994a0d4efc6c67c5c33a9f..fe81e8b687d14e26cb39ce0d9b812533060a2d83 100644 (file)
@@ -1 +1 @@
-f43427742b1c086f2621c900f4ede1a34a8b44ee
\ No newline at end of file
+986efb7b12643800805ad4b1f1e90e30fcf6d38a
\ No newline at end of file
index 20c2ef84e239aec3a73b8fb94b9e517bae11acff..e0e4199f4413e13e5a0af85ec438b972e7667c7d 100644 (file)
@@ -14,7 +14,7 @@
 ** the parser.  Lemon will also generate a header file containing
 ** numeric codes for all of the tokens.
 **
-** @(#) $Id: parse.y,v 1.177 2005/09/09 01:33:19 drh Exp $
+** @(#) $Id: parse.y,v 1.178 2005/09/10 16:46:13 drh Exp $
 */
 
 // All token codes are small integers with #defines that begin with "TK_"
@@ -104,7 +104,8 @@ ecmd ::= SEMI.
 ecmd ::= explain cmdx SEMI.
 explain ::= .           { sqlite3BeginParse(pParse, 0); }
 %ifndef SQLITE_OMIT_EXPLAIN
-explain ::= EXPLAIN.    { sqlite3BeginParse(pParse, 1); }
+explain ::= EXPLAIN.              { sqlite3BeginParse(pParse, 1); }
+explain ::= EXPLAIN QUERY PLAN.   { sqlite3BeginParse(pParse, 2); }
 %endif
 
 ///////////////////// Begin and end transactions. ////////////////////////////
@@ -172,7 +173,7 @@ id(A) ::= ID(X).         {A = X;}
 %fallback ID
   ABORT AFTER ANALYZE ASC ATTACH BEFORE BEGIN CASCADE CAST CONFLICT
   DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
-  IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH KEY
+  IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH PLAN QUERY KEY
   OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW STATEMENT
   TEMP TRIGGER VACUUM VIEW
 %ifdef SQLITE_OMIT_COMPOUND_SELECT
index 50d03e835671700f8012ae7ea64eb9558d8ffa0a..b3222a82f7b65270018248939b8636d4eb4ac0b5 100644 (file)
@@ -13,7 +13,7 @@
 ** interface, and routines that contribute to loading the database schema
 ** from disk.
 **
-** $Id: prepare.c,v 1.3 2005/08/19 00:14:42 drh Exp $
+** $Id: prepare.c,v 1.4 2005/09/10 16:46:13 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -458,12 +458,19 @@ int sqlite3_prepare(
 
 #ifndef SQLITE_OMIT_EXPLAIN
   if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
-    sqlite3VdbeSetNumCols(sParse.pVdbe, 5);
-    sqlite3VdbeSetColName(sParse.pVdbe, 0, "addr", P3_STATIC);
-    sqlite3VdbeSetColName(sParse.pVdbe, 1, "opcode", P3_STATIC);
-    sqlite3VdbeSetColName(sParse.pVdbe, 2, "p1", P3_STATIC);
-    sqlite3VdbeSetColName(sParse.pVdbe, 3, "p2", P3_STATIC);
-    sqlite3VdbeSetColName(sParse.pVdbe, 4, "p3", P3_STATIC);
+    if( sParse.explain==2 ){
+      sqlite3VdbeSetNumCols(sParse.pVdbe, 3);
+      sqlite3VdbeSetColName(sParse.pVdbe, 0, "order", P3_STATIC);
+      sqlite3VdbeSetColName(sParse.pVdbe, 1, "from", P3_STATIC);
+      sqlite3VdbeSetColName(sParse.pVdbe, 2, "detail", P3_STATIC);
+    }else{
+      sqlite3VdbeSetNumCols(sParse.pVdbe, 5);
+      sqlite3VdbeSetColName(sParse.pVdbe, 0, "addr", P3_STATIC);
+      sqlite3VdbeSetColName(sParse.pVdbe, 1, "opcode", P3_STATIC);
+      sqlite3VdbeSetColName(sParse.pVdbe, 2, "p1", P3_STATIC);
+      sqlite3VdbeSetColName(sParse.pVdbe, 3, "p2", P3_STATIC);
+      sqlite3VdbeSetColName(sParse.pVdbe, 4, "p3", P3_STATIC);
+    }
   } 
 #endif
 
index c327598781c922e1344f204ea6d7762fc1c41189..7b573bb0fe1a499436d7767f8f7840cbf1a84e49 100644 (file)
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.485 2005/09/08 14:17:20 drh Exp $
+** $Id: vdbe.c,v 1.486 2005/09/10 16:46:13 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -1645,6 +1645,13 @@ case OP_BitNot: {             /* same as TK_BITNOT, no-push */
 ** Do nothing.  This instruction is often useful as a jump
 ** destination.
 */
+/*
+** The magic Explain opcode are only inserted when explain==2 (which
+** is to say when the EXPLAIN QUERY PLAN syntax is used.)
+** This opcode records information from the optimizer.  It is the
+** the same as a no-op.  This opcodesnever appears in a real VM program.
+*/
+case OP_Explain:
 case OP_Noop: {            /* no-push */
   break;
 }
index c1ccd835965c67915a300803d1b475936807e4b1..1096077050b39160855e9e9b6100db72f14c88c5 100644 (file)
@@ -577,8 +577,9 @@ int sqlite3VdbeList(
   }
   p->resOnStack = 0;
 
-
-  i = p->pc++;
+  do{
+    i = p->pc++;
+  }while( i<p->nOp && p->explain==2 && p->aOp[i].opcode!=OP_Explain );
   if( i>=p->nOp ){
     p->rc = SQLITE_OK;
     rc = SQLITE_DONE;
@@ -617,7 +618,7 @@ int sqlite3VdbeList(
     pMem->type = SQLITE_TEXT;
     pMem->enc = SQLITE_UTF8;
 
-    p->nResColumn = 5;
+    p->nResColumn = 5 - 2*(p->explain-1);
     p->pTos = pMem;
     p->rc = SQLITE_OK;
     p->resOnStack = 1;
index 50ef5d6d9f306cc0559f157dda1c14eb5ed94cd1..1cb479c9ba7a757c696ef3cde279b0eaf53db815 100644 (file)
@@ -16,7 +16,7 @@
 ** so is applicable.  Because this module is responsible for selecting
 ** indices, you might also think of this module as the "query optimizer".
 **
-** $Id: where.c,v 1.170 2005/09/10 15:28:09 drh Exp $
+** $Id: where.c,v 1.171 2005/09/10 16:46:13 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -1499,6 +1499,20 @@ WhereInfo *sqlite3WhereBegin(
     Index *pIx;
     int iIdxCur = pLevel->iIdxCur;
 
+#ifndef SQLITE_OMIT_EXPLAIN
+    if( pParse->explain==2 ){
+      char *zMsg;
+      struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
+      zMsg = sqlite3MPrintf("TABLE %s", pItem->zName);
+      if( pItem->zAlias ){
+        zMsg = sqlite3MPrintf("%z AS %s", zMsg, pItem->zAlias);
+      }
+      if( (pIx = pLevel->pIdx)!=0 ){
+        zMsg = sqlite3MPrintf("%z WITH INDEX %s", zMsg, pIx->zName);
+      }
+      sqlite3VdbeOp3(v, OP_Explain, i, pLevel->iFrom, zMsg, P3_DYNAMIC);
+    }
+#endif /* SQLITE_OMIT_EXPLAIN */
     pTabItem = &pTabList->a[pLevel->iFrom];
     pTab = pTabItem->pTab;
     if( pTab->isTransient || pTab->pSelect ) continue;
index 58d4b9cb78a3c91f4e79041b570b5517f8b6b8b8..c43a767a30f0f2814fddcda218a552f66db2a9df 100644 (file)
@@ -193,8 +193,10 @@ static Keyword aKeywordTable[] = {
   { "OR",               "TK_OR",           ALWAYS                 },
   { "ORDER",            "TK_ORDER",        ALWAYS                 },
   { "OUTER",            "TK_JOIN_KW",      ALWAYS                 },
+  { "PLAN",             "TK_PLAN",         EXPLAIN                },
   { "PRAGMA",           "TK_PRAGMA",       PRAGMA                 },
   { "PRIMARY",          "TK_PRIMARY",      ALWAYS                 },
+  { "QUERY",            "TK_QUERY",        EXPLAIN                },
   { "RAISE",            "TK_RAISE",        TRIGGER                },
   { "REFERENCES",       "TK_REFERENCES",   FKEY                   },
   { "REGEXP",           "TK_LIKE_KW",      ALWAYS                 },