]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
An experimental interface for retrieving the estimated cost and estimated
authordrh <drh@noemail.net>
Fri, 26 Apr 2019 17:20:33 +0000 (17:20 +0000)
committerdrh <drh@noemail.net>
Fri, 26 Apr 2019 17:20:33 +0000 (17:20 +0000)
number of output rows for a query.

FossilOrigin-Name: 1b25fa108ab2c4ada75935abf919de2b4c3b39553b2a0ab2a485645a02352e7e

manifest
manifest.uuid
src/shell.c.in
src/sqlite.h.in
src/vdbe.h
src/vdbeInt.h
src/vdbeapi.c
src/vdbeaux.c
src/where.c
src/whereInt.h

index 261ca06463f705dafa13a3f715f2c3f68004484c..f9983c512ad77dbbd40c9a9ac1906585ea85a832 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C New\stest\scases\sin\stest/fuzzdata8.db.
-D 2019-04-24T17:04:02.548
+C An\sexperimental\sinterface\sfor\sretrieving\sthe\sestimated\scost\sand\sestimated\nnumber\sof\soutput\srows\sfor\sa\squery.
+D 2019-04-26T17:20:33.254
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -519,8 +519,8 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
 F src/resolve.c 567888ee3faec14dae06519b4306201771058364a37560186a3e0e755ebc4cb8
 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
 F src/select.c b7304d2f491c11a03a7fbdf34bc218282ac54052377809d4dc3b4b1e7f4bfc93
-F src/shell.c.in bcfa17eb257bf8dc2359e99ba7e6bdfab7901705db013bc47a5be6d7fa7a037e
-F src/sqlite.h.in 38390767acc1914d58930e03149595ee4710afa4e3c43ab6c3a8aea3f1a6b8cd
+F src/shell.c.in 7544d68921f2c3919da2150c1f7b53a4942c212dd59e68b7926fd903101c3cab
+F src/sqlite.h.in 0c4ec0ea145005e2a458b892a8e6778d980efcd2ad36a68565b8774712eb79c1
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 9ecc93b8493bd20c0c07d52e2ac0ed8bab9b549c7f7955b59869597b650dd8b5
 F src/sqliteInt.h 866311ac436c0c2039fccc7ea976fbc79d40c1c2ea687161fa4ba64379b53ae6
@@ -591,10 +591,10 @@ F src/utf.c 2f0fac345c7660d5c5bd3df9e9d8d33d4c27f366bcfb09e07443064d751a0507
 F src/util.c 5061987401c2e8003177fa30d73196aa036727c8f04bf36a2df0c82b1904a236
 F src/vacuum.c 82dcec9e7b1afa980288718ad11bc499651c722d7b9f32933c4d694d91cb6ebf
 F src/vdbe.c 711ef421b3bb3db3b2476067b2dc3c71ef5844d9b1a723026578f89f6da621e8
-F src/vdbe.h 712bca562eaed1c25506b9faf9680bdc75fc42e2f4a1cd518d883fa79c7a4237
-F src/vdbeInt.h 2c12704db9740c8e899786ecfc7a5797a9d067563496eb1b6ed03c592d7b8d90
-F src/vdbeapi.c 2ddd60f4a351f15ee98d841e346af16111ad59dfa4d25d2dd4012e9875bf7d92
-F src/vdbeaux.c f873b5c2efcf8a4d6ecfc5b1a5b06fd810419198f3bd882175d371cc03801873
+F src/vdbe.h f99dbc42943d945f2aa61377dc67e571688310be51dbc9b3e4299bd0124fdd70
+F src/vdbeInt.h a9089cdf0d5f4a1f076d5b22e5690b6ee2f70b1db0a4814ae1a6397c497c838b
+F src/vdbeapi.c 69fae8eb6e1e762e04bfce308f8180294f98a95f7b346f6cb3a1364fd8095cdd
+F src/vdbeaux.c cf9159eaf4b2ac4d0c0daa61544055d9db924989d433c1f77e2af61ebdcb6a05
 F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
 F src/vdbemem.c dd2ee49255c4c5450f2b0887ef44cea8faa1cd7a46501b39a1a82b113ae418e3
 F src/vdbesort.c 66592d478dbb46f19aed0b42222325eadb84deb40a90eebe25c6e7c1d8468f47
@@ -604,8 +604,8 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
 F src/wal.c b09a2a9cab50efa08451a8c81d47052120ad5da174048c6d0b08d405384abdf2
 F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a
 F src/walker.c 7607f1a68130c028255d8d56094ea602fc402c79e1e35a46e6282849d90d5fe4
-F src/where.c 99c7b718ef846ac952016083aaf4e22ede2290beceaf4730a2df55c023251369
-F src/whereInt.h 5f14db426ca46a83eabab1ae9aa6d4b8f27504ad35b64c290916289b1ddb2e88
+F src/where.c 3e9689df25c0410dc60ee28d81ca21ea4dcdbdd925bff764afea95ef6c105975
+F src/whereInt.h 50e1ddaae281e056eb71d8209ffc194e730745fb521fa8f22d0867cc34e9f3d7
 F src/wherecode.c 0e76672930bea322eb3606d891a4744be55c09bcd3a995bfd501af62a46e0625
 F src/whereexpr.c 90859652920f153d2c03f075488744be2926625ebd36911bcbcb17d0d29c891c
 F src/window.c 038c248267e74ff70a2bb9b1884d40fd145c5183b017823ecb6cbb14bc781478
@@ -1818,7 +1818,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P e1724f1d618cfbcfd1e495d8965a395656cfc1114e1bffd4bc3be0bd5cdb6550
-R 3e1175ca2cd3d699a0989ce182ed2c32
+P 7be6222c9ec44596e4eddd906c831eb1272b90fbdf68641d791f216264feb7cf
+R f445bfaab7875d7e9d6792f1def24978
+T *branch * cost-est
+T *sym-cost-est *
+T -sym-trunk *
 U drh
-Z b7a4bb53a6677ebeb4f1be668326c373
+Z b1b37fe7015f8bb5921c7a5e02cfd8b8
index 7b9871a25bcaeba56c3882525e8e3cc8270d16ca..575253ef18e0629279f420ef8098e6f89b984d3e 100644 (file)
@@ -1 +1 @@
-7be6222c9ec44596e4eddd906c831eb1272b90fbdf68641d791f216264feb7cf
\ No newline at end of file
+1b25fa108ab2c4ada75935abf919de2b4c3b39553b2a0ab2a485645a02352e7e
\ No newline at end of file
index 1f57d1ec3d209446a451bfc82a606aa5daabe6bf..adce32512ce69af1e3c165e0da1f90cba0544656 100644 (file)
@@ -1772,7 +1772,7 @@ static void eqp_render_level(ShellState *p, int iEqpId){
 /*
 ** Display and reset the EXPLAIN QUERY PLAN data
 */
-static void eqp_render(ShellState *p){
+static void eqp_render(ShellState *p, sqlite3_stmt *pStmt){
   EQPGraphRow *pRow = p->sGraph.pRow;
   if( pRow ){
     if( pRow->zText[0]=='-' ){
@@ -1784,7 +1784,10 @@ static void eqp_render(ShellState *p){
       p->sGraph.pRow = pRow->pNext;
       sqlite3_free(pRow);
     }else{
-      utf8_printf(p->out, "QUERY PLAN\n");
+      int iCost, nRow;
+      iCost = sqlite3_stmt_status(pStmt, SQLITE_STMTSTATUS_EST_COST, 0);
+      nRow = sqlite3_stmt_status(pStmt, SQLITE_STMTSTATUS_EST_ROWS, 0);
+      utf8_printf(p->out, "QUERY PLAN (log est cost=%d rows=%d)\n", iCost, nRow);
     }
     p->sGraph.zPrefix[0] = 0;
     eqp_render_level(p, 0);
@@ -3075,10 +3078,10 @@ static int shell_exec(
             const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
             int iEqpId = sqlite3_column_int(pExplain, 0);
             int iParentId = sqlite3_column_int(pExplain, 1);
-            if( zEQPLine[0]=='-' ) eqp_render(pArg);
+            if( zEQPLine[0]=='-' ) eqp_render(pArg, pExplain);
             eqp_append(pArg, iEqpId, iParentId, zEQPLine);
           }
-          eqp_render(pArg);
+          eqp_render(pArg, pExplain);
         }
         sqlite3_finalize(pExplain);
         sqlite3_free(zEQP);
@@ -3126,7 +3129,7 @@ static int shell_exec(
       bind_prepared_stmt(pArg, pStmt);
       exec_prepared_stmt(pArg, pStmt);
       explain_data_delete(pArg);
-      eqp_render(pArg);
+      eqp_render(pArg, pStmt);
 
       /* print usage stats if stats on */
       if( pArg && pArg->statsOn ){
index cf390ac372ac5b5de6c1931c3e011cfd2e905586..105bc8a2015f1f9d5fb74ecac3de6a0b8383e2e7 100644 (file)
@@ -7847,6 +7847,15 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
 ** used to store the prepared statement.  ^This value is not actually
 ** a counter, and so the resetFlg parameter to sqlite3_stmt_status()
 ** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED.
+**
+** [[SQLITE_STMTSTATUS_EST_ROWS]] <dt>SQLITE_STMTSTATUS_EST_ROWS</dt>
+** <dd>^A return value of X indicates that the query planner estimated
+** that the query will return pow(2,X/10.0) rows.
+**
+** [[SQLITE_STMTSTATUS_EST_COST]] <dt>SQLITE_STMTSTATUS_EST_COST</dt>
+** <dd>^A return value of X indicates that the query planner estimated
+** the relative cost of running this statement to completion is
+** pow(2,X/10.0).
 ** </dd>
 ** </dl>
 */
@@ -7857,6 +7866,8 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
 #define SQLITE_STMTSTATUS_REPREPARE         5
 #define SQLITE_STMTSTATUS_RUN               6
 #define SQLITE_STMTSTATUS_MEMUSED           99
+#define SQLITE_STMTSTATUS_EST_ROWS          100
+#define SQLITE_STMTSTATUS_EST_COST          101
 
 /*
 ** CAPI3REF: Custom Page Cache Object
index 041a91c51fe93e2dbbfd73d69a9bd9b3c9930806..639f3e1e544c0f7706c55819ceca58550d08416f 100644 (file)
@@ -264,6 +264,7 @@ void sqlite3VdbeSwap(Vdbe*,Vdbe*);
 VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
 sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
 void sqlite3VdbeSetVarmask(Vdbe*, int);
+void sqlite3VdbeUpdateCostEstimates(Parse*, LogEst, LogEst);
 #ifndef SQLITE_OMIT_TRACE
   char *sqlite3VdbeExpandSql(Vdbe*, const char*);
 #endif
index 15a371d5508fc0c014880bac1b4cd3f659b0e78b..a19ae1187a9e3763104629e0ba5955190faca4bb 100644 (file)
@@ -425,6 +425,8 @@ struct Vdbe {
   bft usesStmtJournal:1;  /* True if uses a statement journal */
   bft readOnly:1;         /* True for statements that do not write */
   bft bIsReader:1;        /* True for statements that read */
+  LogEst nRowEst;         /* Query planner of estimated number of output rows */
+  LogEst iCostEst;        /* Query planner cost estimate */
   yDbMask btreeMask;      /* Bitmask of db->aDb[] entries referenced */
   yDbMask lockMask;       /* Subset of btreeMask that requires a lock */
   u32 aCounter[7];        /* Counters used by sqlite3_stmt_status() */
index 00eea75a457bdaaa25259a466c6e17470e26e094..eba342b74c52893bc672ee83a5149c7734670026 100644 (file)
@@ -1658,27 +1658,39 @@ sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){
 */
 int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
   Vdbe *pVdbe = (Vdbe*)pStmt;
-  u32 v;
-#ifdef SQLITE_ENABLE_API_ARMOR
-  if( !pStmt 
-   || (op!=SQLITE_STMTSTATUS_MEMUSED && (op<0||op>=ArraySize(pVdbe->aCounter)))
-  ){
+  u32 v = 0;
+  if( !pStmt ){
     (void)SQLITE_MISUSE_BKPT;
     return 0;
   }
-#endif
-  if( op==SQLITE_STMTSTATUS_MEMUSED ){
-    sqlite3 *db = pVdbe->db;
-    sqlite3_mutex_enter(db->mutex);
-    v = 0;
-    db->pnBytesFreed = (int*)&v;
-    sqlite3VdbeClearObject(db, pVdbe);
-    sqlite3DbFree(db, pVdbe);
-    db->pnBytesFreed = 0;
-    sqlite3_mutex_leave(db->mutex);
-  }else{
-    v = pVdbe->aCounter[op];
-    if( resetFlag ) pVdbe->aCounter[op] = 0;
+  switch( op ){
+    case SQLITE_STMTSTATUS_MEMUSED: {
+      sqlite3 *db = pVdbe->db;
+      sqlite3_mutex_enter(db->mutex);
+      v = 0;
+      db->pnBytesFreed = (int*)&v;
+      sqlite3VdbeClearObject(db, pVdbe);
+      sqlite3DbFree(db, pVdbe);
+      db->pnBytesFreed = 0;
+      sqlite3_mutex_leave(db->mutex);
+      break;
+    }
+    case SQLITE_STMTSTATUS_EST_ROWS: {
+      v = pVdbe->nRowEst;
+      break;
+    }
+    case SQLITE_STMTSTATUS_EST_COST: {
+      v = pVdbe->iCostEst;
+      break;
+    }
+    default: {
+      if( op>=0 && op<ArraySize(pVdbe->aCounter) ){
+        v = pVdbe->aCounter[op];
+        if( resetFlag ) pVdbe->aCounter[op] = 0;
+      }else{
+        (void)SQLITE_MISUSE_BKPT;
+      }
+    }
   }
   return (int)v;
 }
index 822c6fe60c95647a42cbdf5f7e85a24ffc78dd12..d2b58aec8af872caf20497468f8b3d4d93a180de 100644 (file)
@@ -4848,6 +4848,20 @@ void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
   }
 }
 
+/*
+** Update the estimated cost fields
+*/
+void sqlite3VdbeUpdateCostEstimates(Parse *pParse, LogEst iCost, LogEst nRow){
+  Vdbe *v = pParse->pVdbe;
+  if( v->iCostEst ){
+    v->iCostEst = sqlite3LogEstAdd(v->iCostEst, iCost+pParse->nQueryLoop) + 1;
+    if( nRow > v->nRowEst ) v->nRowEst = nRow;
+  }else{
+    v->nRowEst = nRow;
+    v->iCostEst = iCost + 1;
+  }
+}
+
 /*
 ** Cause a function to throw an error if it was call from OP_PureFunc
 ** rather than OP_Function.
index b421e4ae93d5a523978bec86c813139f54db7687..81fc9158ae041dc9a2f6bd56d3e07d1079e97d44 100644 (file)
@@ -4363,6 +4363,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
 
 
   pWInfo->nRowOut = pFrom->nRow;
+  pWInfo->iTotalCost = pFrom->rCost;
 
   /* Free temporary memory and return success */
   sqlite3DbFreeNN(db, pSpace);
@@ -5145,6 +5146,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
 
   /* Generate loop termination code.
   */
+  sqlite3VdbeUpdateCostEstimates(pParse, pWInfo->iTotalCost, pWInfo->nRowOut);
   VdbeModuleComment((v, "End WHERE-core"));
   for(i=pWInfo->nLevel-1; i>=0; i--){
     int addr;
index 07876f435311ccb3ead29e7b9b38b05969aa0105..6728732c201fffb8e6158cb7fa90f2a3e6d4375a 100644 (file)
@@ -462,6 +462,7 @@ struct WhereInfo {
   WhereLoop *pLoops;        /* List of all WhereLoop objects */
   Bitmask revMask;          /* Mask of ORDER BY terms that need reversing */
   LogEst nRowOut;           /* Estimated number of output rows */
+  LogEst iTotalCost;        /* Cost estimate for the whole plan */
   WhereClause sWC;          /* Decomposition of the WHERE clause */
   WhereMaskSet sMaskSet;    /* Map cursor numbers to bitmasks */
   WhereLevel a[1];          /* Information about each nest loop in WHERE */