]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Change sqlite3_prepare_v3() to require SQLITE_PREPARE_CACHE in order for a
authordrh <>
Wed, 24 Aug 2022 23:50:45 +0000 (23:50 +0000)
committerdrh <>
Wed, 24 Aug 2022 23:50:45 +0000 (23:50 +0000)
statement to be a cache candidate.  But any statement can pull from the cache.
Also add statement cache control to the CLI.

FossilOrigin-Name: c9dc536db9d13c0d66e5b84e564d6813c184ae26c889413a64b365781bf8ee50

manifest
manifest.uuid
src/main.c
src/prepare.c
src/shell.c.in
src/vdbeaux.c
test/speedtest1.c
tool/speed-check.sh

index 9c1bc75ff2d8dd10fe1ddb0de6ba68c75f664b4d..1125980cd07d941e3a737370c0a134ced945f773 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C First\sattempt\sat\sadding\sa\sbuilt-in\sprepared\sstatement\scache.\s\sThis\sis\nmostly\sworking,\sbut\sstill\shas\sa\sfew\sobscure\sfaults.
-D 2022-08-24T17:55:27.625
+C Change\ssqlite3_prepare_v3()\sto\srequire\sSQLITE_PREPARE_CACHE\sin\sorder\sfor\sa\nstatement\sto\sbe\sa\scache\scandidate.\s\sBut\sany\sstatement\scan\spull\sfrom\sthe\scache.\nAlso\sadd\sstatement\scache\scontrol\sto\sthe\sCLI.
+D 2022-08-24T23:50:45.133
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -552,7 +552,7 @@ F src/insert.c aea5361767817f917b0f0f647a1f0b1621bd858938ae6ae545c3b6b9814b798f
 F src/json.c 7749b98c62f691697c7ee536b570c744c0583cab4a89200fdd0fc2aa8cc8cbd6
 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
 F src/loadext.c 853385cc7a604157e137585097949252d5d0c731768e16b044608e5c95c3614b
-F src/main.c 5c82ba33d2032f099c90fbb2a7a05ed684164a0ddecb7aaeda4374d97f4055b5
+F src/main.c a9a6dbe70301a39a1d63b6460e329c4f9548a42b7a334d167fb077acdee9d275
 F src/malloc.c b7a3430cbe91d3e8e04fc10c2041b3a19794e63556ad2441a13d8dadd9b2bafc
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -583,13 +583,13 @@ F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
 F src/pcache1.c 0b4245cd4964e635f2630908c2533cd8e9da7af3ca592e23ae8730aa25ae5eb9
 F src/pragma.c b57a859a366472131194a9ad35cd76d5920577226b04c884b1b9085605faa280
 F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
-F src/prepare.c 54839876dd40924279004e98ba35e38a64aed728b9be5ba8641f10a9a5203496
+F src/prepare.c b0fb76a2c82587013410f0e27fcdb2ef5624f036d00179f7fd4f28a52acc0155
 F src/printf.c e99ee9741e79ae3873458146f59644276657340385ade4e76a5f5d1c25793764
 F src/random.c 546d6feb15ec69c1aafe9bb351a277cbb498fd5410e646add673acb805714960
 F src/resolve.c efea4e5fbecfd6d0a9071b0be0d952620991673391b6ffaaf4c277b0bb674633
 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
 F src/select.c ccce37e7fbe71089cf6aec91e7134c9c0c1d4840cff9f02587bbc71240d914a5
-F src/shell.c.in 269f682249c1bce2962883e5b99c8702b16a488a43b9ae186daa178713a93c5d
+F src/shell.c.in 6c18f7d3a42c590035f1c702265c73a8301fda79dda951a713bdae5ae185583b
 F src/sqlite.h.in f34d1ca4091c969e1b4b4744839f415c7963618bb10b34bbe1ef6a356ace0840
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h a988810c9b21c0dc36dc7a62735012339dc76fc7ab448fb0792721d30eacb69d
@@ -664,7 +664,7 @@ F src/vdbe.c 0150d16da21cb96b2b0f2880aad6acd80ddedf93a9f3eb2c5200aef864854fe6
 F src/vdbe.h c4c9defdf2ad9465f9c9c7f79c3b03555f47aa930ea2744f358d9b27269763c7
 F src/vdbeInt.h e332f7d165b2cb984772c425c45f67f1d57e3c032d8dbf74a9ef8f1cebfa4bb2
 F src/vdbeapi.c 8087dba84836f59d0d5340a6c554948cf4fef03ace62a8d7dd3c8f310107e3f4
-F src/vdbeaux.c fdbf1df03cfcf4d11c49178be30b23d2b750082edd4d7b6aa663479e7dc65f7c
+F src/vdbeaux.c 7e682b9cae69e3801d2c04fefe2c80b40e5fcca470a4e11aa53342e2218aa1ab
 F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd
 F src/vdbemem.c c3ce80af15e2ff5c2824a8db881681cbf511376f13613da020bac6d320c535b1
 F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35
@@ -1480,7 +1480,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
 F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
 F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
 F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
-F test/speedtest1.c d37467faf7a43711b134f05e9cde7abfd1504bf8f16f6220f67d8db1bc0fc51f
+F test/speedtest1.c ace4f2f7053d01237d41ab3a9baaf785eab1f22457bdc0113a41d573a506d2c5
 F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
 F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
 F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
@@ -1957,7 +1957,7 @@ F tool/showstat4.c 0682ebea7abf4d3657f53c4a243f2e7eab48eab344ed36a94bb75dcd19a5c
 F tool/showwal.c 0253c187ae16fdae9cde89e63e1dfcd3bb35e5416d066415f99e2f8cac6ab03d
 F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
 F tool/spaceanal.tcl 1b5be34c6223cb1af06da2a10fb77863eb869b1962d055820b0a11cf2336ab45
-F tool/speed-check.sh fc224ee49062fedf3bbef87779197bb5103f6f796603e4255ea558633360e8ba
+F tool/speed-check.sh 13f8e07dbfe25f3aecda33fb6068894665af61ca1360a7b654be0ad0c3f3ae0b
 F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
 F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
@@ -1999,11 +1999,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 34b8ea31877ae8b40729d37b3f51ae7e15f38be841881ea4a37c9c8f0a52896d
-R 08d11f60d527a9ebc32a98574ca5f0f9
-T *branch * stmt-cache
-T *sym-stmt-cache *
-T -sym-trunk *
+P c217b763b148e8bece9d1f72525fd5026d3f710b337c010ffd0306fde4f9add8
+R 46f3adc34868ee6f9be56f487a4c1aae
 U drh
-Z c8d2ef694a3736c7eee4ba211f6abfcb
+Z 42a77517994ced9f374a6cd335be1880
 # Remove this line to create a well-formed Fossil manifest.
index 9e6622d10d3c7a1c6fb365c7fb82c2206e9d704e..e5c4112044d8224fdd3c78574e3e20646ce88ffb 100644 (file)
@@ -1 +1 @@
-c217b763b148e8bece9d1f72525fd5026d3f710b337c010ffd0306fde4f9add8
\ No newline at end of file
+c9dc536db9d13c0d66e5b84e564d6813c184ae26c889413a64b365781bf8ee50
\ No newline at end of file
index ac09341eb8a56bae99155030f0884aa7594e9b2a..8f33c7790b4be1e790a3882608126b0379d282c3 100644 (file)
@@ -923,7 +923,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
       if( szDesired>=0 ){
         sqlite3VdbeChangeStmtCacheSize(db, szDesired);
       }
-      *pszNew = (int)db->mxCache;
+      if( pszNew ) *pszNew = (int)db->mxCache;
       rc = SQLITE_OK;
       break;
     }
index 0ac4c8d97be163a814b4192871f5f17e72e863fa..355703e2afe5512925a7346f89a75225d5a691e4 100644 (file)
@@ -699,24 +699,25 @@ static int sqlite3Prepare(
   if( db->mallocFailed ) sqlite3ErrorMsg(&sParse, "out of memory");
   assert( sqlite3_mutex_held(db->mutex) );
 
-  if( prepFlags & SQLITE_PREPARE_PERSISTENT ){
-    /* Check to see if the prepared statement can be resolved from cache. */
-    if( db->mxCache>0 ){
-      Vdbe *pCache;
-      if( nBytes<0 ) nBytes = sqlite3Strlen30(zSql);
-      pCache = sqlite3VdbeFindInStmtCache(db, zSql, nBytes, &hSql);
-      if( pCache ){
-        *ppStmt = (sqlite3_stmt*)pCache;
-        if( pzTail ){
-          *pzTail = &zSql[nBytes];
-        }
-        goto end_prepare;
+  if( db->nCache>0 ){
+    Vdbe *pCache;
+    if( nBytes<0 ) nBytes = sqlite3Strlen30(zSql);
+    pCache = sqlite3VdbeFindInStmtCache(db, zSql, nBytes, &hSql);
+    if( pCache ){
+      *ppStmt = (sqlite3_stmt*)pCache;
+      if( pzTail ){
+        *pzTail = &zSql[nBytes];
       }
+      goto end_prepare;
     }
+  }
 
-    /* For a long-term use prepared statement should avoid the use of
-    ** lookaside memory.
-    */
+  /* For a long-term use prepared statement should avoid the use of
+  ** lookaside memory.
+  */
+  if( prepFlags & (SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_CACHE) ){
+    testcase( prepFlags & SQLITE_PREPARE_PERSISTENT );
+    testcase( prepFlags & SQLITE_PREPARE_CACHE );
     sParse.disableLookaside++;
     DisableLookaside;
   }
index 5feadd7bf0631356d22055883f51c68b6a4c48f2..92079d598bbbbd81b0a1cc3827c1521c24efa636 100644 (file)
@@ -1112,6 +1112,7 @@ struct ShellState {
   int cnt;               /* Number of records displayed so far */
   int lineno;            /* Line number of last line read from in */
   int openFlags;         /* Additional flags to open.  (SQLITE_OPEN_NOFOLLOW) */
+  int prepFlags;         /* Flags for sqlite3_prepare_v3() */
   FILE *in;              /* Read commands from this stream */
   FILE *out;             /* Write results here */
   FILE *traceOut;        /* Output for sqlite3_trace() */
@@ -2649,7 +2650,7 @@ static int run_table_dump_query(
   int nResult;
   int i;
   const char *z;
-  rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
+  rc = sqlite3_prepare_v3(p->db, zSelect, -1, p->prepFlags, &pSelect, 0);
   if( rc!=SQLITE_OK || !pSelect ){
     char *zContext = shell_error_context(zSelect, p->db);
     utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n%s", rc,
@@ -3845,7 +3846,7 @@ static int shell_exec(
 
   while( zSql[0] && (SQLITE_OK == rc) ){
     static const char *zStmtSql;
-    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
+    rc = sqlite3_prepare_v3(db, zSql, -1, pArg->prepFlags, &pStmt, &zLeftover);
     if( SQLITE_OK != rc ){
       if( pzErrMsg ){
         *pzErrMsg = save_err_msg(db, "in prepare", rc, zSql);
@@ -3911,7 +3912,7 @@ static int shell_exec(
           sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
           /* Reprepare pStmt before reactiving trace modes */
           sqlite3_finalize(pStmt);
-          sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
+          sqlite3_prepare_v3(db, zSql, -1, pArg->prepFlags, &pStmt, 0);
           if( pArg ) pArg->pStmt = pStmt;
         }
         restore_debug_trace_modes();
@@ -4010,7 +4011,7 @@ static char **tableColumnList(ShellState *p, const char *zTab){
 
   zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
   shell_check_oom(zSql);
-  rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
+  rc = sqlite3_prepare_v3(p->db, zSql, -1, p->prepFlags, &pStmt, 0);
   sqlite3_free(zSql);
   if( rc ) return 0;
   while( sqlite3_step(pStmt)==SQLITE_ROW ){
@@ -4055,7 +4056,7 @@ static char **tableColumnList(ShellState *p, const char *zTab){
     zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
                            " WHERE origin='pk'", zTab);
     shell_check_oom(zSql);
-    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
+    rc = sqlite3_prepare_v3(p->db, zSql, -1, p->prepFlags, &pStmt, 0);
     sqlite3_free(zSql);
     if( rc ){
       freeColumnList(azCol);
@@ -8307,8 +8308,10 @@ static int do_meta_command(char *zLine, ShellState *p){
     }
   }else
 
-  /* The undocumented ".breakpoint" command causes a call to the no-op
-  ** routine named test_breakpoint().
+  /* UNDOCUMENTED COMMAND:    .breakpoint
+  **
+  ** Causes a call to the no-op routine named test_breakpoint().  This provides
+  ** a convenient function on which to set a breakpoint.
   */
   if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
     test_breakpoint();
@@ -8487,6 +8490,7 @@ static int do_meta_command(char *zLine, ShellState *p){
         { "load_extension",     SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
         { "no_ckpt_on_close",   SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE      },
         { "reset_database",     SQLITE_DBCONFIG_RESET_DATABASE        },
+        { "stmtcache_size",     SQLITE_DBCONFIG_STMTCACHE_SIZE        },
         { "trigger_eqp",        SQLITE_DBCONFIG_TRIGGER_EQP           },
         { "trusted_schema",     SQLITE_DBCONFIG_TRUSTED_SCHEMA        },
         { "writable_schema",    SQLITE_DBCONFIG_WRITABLE_SCHEMA       },
@@ -8494,12 +8498,22 @@ static int do_meta_command(char *zLine, ShellState *p){
     int ii, v;
     open_db(p, 0);
     for(ii=0; ii<ArraySize(aDbConfig); ii++){
+      int op;
       if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
+      op = aDbConfig[ii].op;
       if( nArg>=3 ){
-        sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
+        if( op==SQLITE_DBCONFIG_STMTCACHE_SIZE ){
+          sqlite3_db_config(p->db, op, (int)integerValue(azArg[2]), 0);
+        }else{
+          sqlite3_db_config(p->db, op, booleanValue(azArg[2]), 0);
+        }
+      }
+      sqlite3_db_config(p->db, op, -1, &v);
+      if( op==SQLITE_DBCONFIG_STMTCACHE_SIZE ){
+        utf8_printf(p->out, "%19s %d\n", aDbConfig[ii].zName, v);
+      }else{
+        utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
       }
-      sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
-      utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
       if( nArg>1 ) break;
     }
     if( nArg>1 && ii==ArraySize(aDbConfig) ){
@@ -9913,6 +9927,47 @@ static int do_meta_command(char *zLine, ShellState *p){
     showHelp(p->out, "parameter");
   }else
 
+  /* UNDOCUMENTED COMMAND:    .prepflags  (+|-)FLAG ...
+  **
+  ** For SQLite core debugging use only.
+  **
+  ** Change the value of ShellState.prepFlags which becomes the flags
+  ** parameter to sqlite3_prepare_v3() in some calls in this application.
+  */
+  if( c=='p' && n>=3 && strncmp(azArg[0], "prepflags", n)==0 ){
+    int i;
+    for(i=1; i<nArg; i++){
+      int op = 0;
+      if( azArg[i][0]!='-' && azArg[i][0]!='+' ){
+        utf8_printf(p->out, "unknown option: \"%s\"\n", azArg[i]);
+        rc = 1;
+        goto meta_command_exit;
+      }
+      if( strcmp(azArg[i]+1, "persist")==0 ){
+        op = SQLITE_PREPARE_PERSISTENT;
+      }else if( strcmp(azArg[i]+1, "no-vtab")==0 ){
+        op = SQLITE_PREPARE_NO_VTAB;
+      }else if( strcmp(azArg[i]+1, "cache")==0 ){
+        op = SQLITE_PREPARE_CACHE;
+      }else{
+        utf8_printf(p->out, "option \"%s\" should be one of: \"%cpersist\""
+                            "\"%cno-vtab\" \"%ccache\"\n",
+          azArg[i], azArg[i][0],azArg[i][0],azArg[i][0]);
+        rc = 1;
+        goto meta_command_exit;
+      }
+      if( azArg[i][0]=='+' ){
+        p->prepFlags |= op;
+      }else{
+        p->prepFlags &= ~op;
+      }
+    }
+    utf8_printf(p->out, "  prepflags:");
+    utf8_printf(p->out, " %cpersist", (p->prepFlags & SQLITE_PREPARE_PERSISTENT)?'+':'-');
+    utf8_printf(p->out, " %cno-vtab", (p->prepFlags & SQLITE_PREPARE_NO_VTAB)?'+':'-');
+    utf8_printf(p->out, " %ccache\n", (p->prepFlags & SQLITE_PREPARE_CACHE)?'+':'-');
+  }else
+
   if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
     int i;
     for(i=1; i<nArg; i++){
@@ -10229,6 +10284,13 @@ static int do_meta_command(char *zLine, ShellState *p){
     }
   }else
 
+  /* UNDOCUMENTED COMMAND:    .treetrace N
+  **
+  ** For SQLite core debugging use only.
+  **
+  ** Set the treetrace mask to N.  Also called ".selectrace" for historical
+  ** compatibility.
+  */
   if( (c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0)
    || (c=='t' && n==9  && strncmp(azArg[0], "treetrace", n)==0)
   ){
@@ -10730,6 +10792,9 @@ static int do_meta_command(char *zLine, ShellState *p){
       rc = 1;
       goto meta_command_exit;
     }
+    utf8_printf(p->out,"%12.12s: ", "colseparator");
+      output_c_string(p->out, p->colSeparator);
+      raw_printf(p->out, "\n");
     utf8_printf(p->out, "%12.12s: %s\n","echo",
                 azBool[ShellHasFlag(p, SHFLG_Echo)]);
     utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
@@ -10752,9 +10817,10 @@ static int do_meta_command(char *zLine, ShellState *p){
       raw_printf(p->out, "\n");
     utf8_printf(p->out,"%12.12s: %s\n","output",
             strlen30(p->outfile) ? p->outfile : "stdout");
-    utf8_printf(p->out,"%12.12s: ", "colseparator");
-      output_c_string(p->out, p->colSeparator);
-      raw_printf(p->out, "\n");
+    utf8_printf(p->out,"%12.12s:", "prepflags");
+      utf8_printf(p->out," %cpersist",(p->prepFlags&SQLITE_PREPARE_PERSISTENT)?'+':'-');
+      utf8_printf(p->out," %cno-vtab",(p->prepFlags&SQLITE_PREPARE_NO_VTAB)?'+':'-');
+      utf8_printf(p->out," %ccache\n",(p->prepFlags&SQLITE_PREPARE_CACHE)?'+':'-');
     utf8_printf(p->out,"%12.12s: ", "rowseparator");
       output_c_string(p->out, p->rowSeparator);
       raw_printf(p->out, "\n");
@@ -11368,6 +11434,12 @@ static int do_meta_command(char *zLine, ShellState *p){
     }
   }else
 
+  /* UNDOCUMENTED COMMMAND:  .wheretrace NUMBER
+  **
+  ** For SQLite core debugging use only.
+  **
+  ** See the wheretrace mask to NUMBER.
+  */
   if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
     unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
     sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
index 916b2277e3ef4c2c7c9544635e0cf2f7e57bd285..e60158978d58300ca87833ce525a2cf9ecc6caed 100644 (file)
@@ -64,6 +64,19 @@ void sqlite3VdbeError(Vdbe *p, const char *zFormat, ...){
   va_end(ap);
 }
 
+/*
+** Compute a hash on the SQL used to generate a prepared statement.
+*/
+static u32 sqlHash(const char *zSql, int nSql){
+  u32 hSql = 0;
+  int i;
+  for(i=0; i<nSql; i++){
+    hSql = (hSql + zSql[i]) * 0x9e3779b1;
+  }
+  hSql |= 1;
+  return hSql;
+}
+
 /*
 ** Remember the SQL string for a prepared statement.
 */
@@ -82,7 +95,12 @@ void sqlite3VdbeSetSql(
   assert( p->zSql==0 );
   p->zSql = sqlite3DbStrNDup(p->db, z, n);
   p->nSql = n;
-  p->hSql = hSql;
+  if( prepFlags & SQLITE_PREPARE_CACHE ){
+    if( hSql==0 ) hSql = sqlHash(z, n);
+    p->hSql = hSql;
+  }else{
+    p->hSql = 0;
+  }
 }
 
 /*
@@ -94,19 +112,11 @@ Vdbe *sqlite3VdbeFindInStmtCache(
   int nSql,             /* Size of zSql[] in bytes */
   u32 *phSql            /* Write the hash value here if not found */
 ){
-  int i;                /* Loop counter */
   Vdbe *pCache;         /* Candidate statement */
-  u32 c;                /* One character of SQL input */
   u32 hSql;             /* A hash of the SQL input */
-  int n;                /* Number of SQL input characters to be hashed */
 
-  hSql = 0;
-  n = nSql;
-  if( n>100 ) n = 100;
-  for(i=0; i<n && (c = ((u8*)zSql)[i])!=';'; i++){
-    hSql = (hSql + c) * 0x9e3779b1;
-  }
-  hSql |= 1;
+  assert( nSql>=0 );
+  hSql = sqlHash(zSql, nSql);
   if( db->nCache ){
     for(pCache = db->pVdbe; pCache; pCache=pCache->pVNext){
       if( pCache->hSql==hSql
index e782e7313c6588439c29015d80506d51379a7198..2f87809f2228b8ede513a34bb44871a739647686 100644 (file)
@@ -37,6 +37,7 @@ static const char zHelp[] =
   "  --size N            Relative test size.  Default=100\n"
   "  --strict            Use STRICT table where appropriate\n"
   "  --stats             Show statistics at the end\n"
+  "  --stmtcache N       Use a statement cache of size N\n"
   "  --temp N            N from 0 to 9.  0: no temp table. 9: all temp tables\n"
   "  --testset T         Run test-set T (main, cte, rtree, orm, fp, debug)\n"
   "  --trace             Turn on SQL tracing\n"
@@ -98,6 +99,7 @@ static struct Global {
   int nRepeat;               /* Repeat selects this many times */
   int doCheckpoint;          /* Run PRAGMA wal_checkpoint after each trans */
   int nReserve;              /* Reserve bytes */
+  int szStmtCache;           /* Size of the statement cache */
   const char *zWR;           /* Might be WITHOUT ROWID */
   const char *zNN;           /* Might be NOT NULL */
   const char *zPK;           /* Might be UNIQUE or PRIMARY KEY */
@@ -588,7 +590,7 @@ void speedtest1_run(void){
 #if SQLITE_VERSION_NUMBER>=3006001
   if( g.bReprepare ){
     sqlite3_stmt *pNew;
-    if( g.mPrepFlags & SQLITE_PREPARE_PERSISTENT ){
+    if( g.mPrepFlags & SQLITE_PREPARE_CACHE ){
       char zBuf[1000];
       strncpy(zBuf, sqlite3_sql(g.pStmt), sizeof(zBuf));
       zBuf[sizeof(zBuf)-1] = 0;
@@ -2300,6 +2302,10 @@ int main(int argc, char **argv){
       }else if( strcmp(z,"size")==0 ){
         if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
         g.szTest = integerValue(argv[++i]);
+      }else if( strcmp(z,"stmtcache")==0 ){
+        if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
+        g.szStmtCache = integerValue(argv[++i]);
+        g.mPrepFlags |= SQLITE_PREPARE_CACHE;
       }else if( strcmp(z,"stats")==0 ){
         showStats = 1;
       }else if( strcmp(z,"temp")==0 ){
@@ -2394,6 +2400,14 @@ int main(int argc, char **argv){
     if( rc ) fatal_error("lookaside configuration failed: %d\n", rc);
   }
 #endif
+#ifdef SQLITE_DBCONFIG_STMTCACHE_SIZE
+  if( g.mPrepFlags & SQLITE_PREPARE_CACHE ){
+    int nCache = 0;
+    rc = sqlite3_db_config(g.db, SQLITE_DBCONFIG_STMTCACHE_SIZE,
+                           g.szStmtCache, &nCache);
+    if( rc ) fatal_error("statement cache configuration failed: %d\n", rc);
+  }
+#endif /* SQLITE_DBCONFIG_STMTCACHE_SIZE */
   if( g.nReserve>0 ){
     sqlite3_file_control(g.db, 0, SQLITE_FCNTL_RESERVE_BYTES, &g.nReserve);
   }
index 6d69ea032060c0453737090c5457bee204c8b6de..879ffa9562b70d618d3a204e27ab08c29e36ff65 100644 (file)
@@ -96,6 +96,9 @@ while test "$1" != ""; do
     --cachesize)
         shift; SPEEDTEST_OPTS="$SPEEDTEST_OPTS --cachesize $1"
         ;;
+    --stmtcache)
+        shift; SPEEDTEST_OPTS="$SPEEDTEST_OPTS --stmtcache $1"
+        ;;
     --checkpoint)
         SPEEDTEST_OPTS="$SPEEDTEST_OPTS --checkpoint"
         ;;