]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Experimental API sqlite3_stmt_refresh() to force a prepared statement to sqlite3_stmt_refresh
authordrh <drh@noemail.net>
Thu, 20 Jul 2017 16:55:51 +0000 (16:55 +0000)
committerdrh <drh@noemail.net>
Thu, 20 Jul 2017 16:55:51 +0000 (16:55 +0000)
recompile if it needs to due to a schema change or other factor.

FossilOrigin-Name: 10556ee454edf60dd6542fdf9017f713c783b9ca1b86f25f45e3c17ffb184e24

manifest
manifest.uuid
src/sqlite.h.in
src/test1.c
src/vdbe.c
src/vdbeInt.h
src/vdbeapi.c
test/capi3d.test

index 4932481eb6242cc8cb5f73d4faac646020bc30ba..1de462db998fe0a737c7ce7e04719494f20a35b2 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Enhance\sthe\sbuilt-in\sdate/time\sfunctions\sso\sthat\sthey\scan\sbe\sused\sin\nCHECK\sconstraints,\sin\sthe\sWHERE\sclause\sor\spartial\sindexes,\sand\sindex\nexpressions,\sprovided\sthat\snone\sof\sthe\snon-deterministic\skeywords\n("now",\s"localtime",\s"utc")\sare\sused\sas\sarguments.
-D 2017-07-20T15:08:43.378
+C Experimental\sAPI\ssqlite3_stmt_refresh()\sto\sforce\sa\sprepared\sstatement\sto\nrecompile\sif\sit\sneeds\sto\sdue\sto\sa\sschema\schange\sor\sother\sfactor.
+D 2017-07-20T16:55:51.434
 F Makefile.in d9873c9925917cca9990ee24be17eb9613a668012c85a343aef7e5536ae266e8
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc 02b469e9dcd5b7ee63fc1fb05babc174260ee4cfa4e0ef2e48c3c6801567a016
@@ -455,7 +455,7 @@ F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
 F src/select.c c6bf96a7f9d7d68f929de84738c599a30d0a725ab0b54420e70545743cd5ee7b
 F src/shell.c bd6a37cbe8bf64ef6a6a74fdc50f067d3148149b4ce2b4d03154663e66ded55f
 F src/shell.c.in b5725acacba95ccefa57b6d068f710e29ba8239c3aa704628a1902a1f729c175
-F src/sqlite.h.in dad804d4e1979a2ddec33cc8da6aa50c04e6ba0dcb4058e7b3609588d010e041
+F src/sqlite.h.in d100c0942b5a6c20ec5c4a5a0b752be62530f80babd854544d1dbd2f23f91023
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 967154985ed2ae62f90d9029bb5b5071793d847f1696a2ebe9e8cc0b042ae60b
 F src/sqliteInt.h 96197a18f041b9ab99e6cee0db39dbf771ac7762d9f0f63d9e719285f0478664
@@ -463,7 +463,7 @@ F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6
 F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
 F src/tclsqlite.c 2c29b0b76e91edfd1b43bf135c32c8674710089197327682b6b7e6af88062c3d
-F src/test1.c cfb78b728b37ae3a2b14fe1b3a6c766e0da41370eda112594e698c94011b622e
+F src/test1.c 84f9472ca24c2c2aa2d76256f19db3ce0bb0224c0553db793f0fb2c0969c869e
 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
 F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b
 F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
@@ -520,10 +520,10 @@ F src/update.c c443935c652af9365e033f756550b5032d02e1b06eb2cb890ed7511ae0c051dc
 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
 F src/util.c fc081ec6f63448dcd80d3dfad35baecfa104823254a815b081a4d9fe76e1db23
 F src/vacuum.c 874c0f2f15ab2908748297d587d22d485ea96d55aaec91d4775dddb2e24d2ecf
-F src/vdbe.c 1e541ec7ff409bbabcc6b4f154957296fff5827c16c2ab0056348acae75685bf
+F src/vdbe.c 53f3f4d1ee9bd4985cc0b199bdf6a6c5e99c526eb15f100fed59653c79cf8fa6
 F src/vdbe.h d50cadf12bcf9fb99117ef392ce1ea283aa429270481426b6e8b0280c101fd97
-F src/vdbeInt.h 19bd04a4211fe56c712ab35b48be77fd5a0579b851e9dea2cb8deade359b72b9
-F src/vdbeapi.c 52844a5a71712197be45f1c63d730c48a745c7457c959465cfb2b969af40a266
+F src/vdbeInt.h e202dc9f7b00722a85f609053610d40afa9b6a836a42810b2ef2d2a7b9e099ba
+F src/vdbeapi.c d83d30e1130c96d5bb1132275275402502b17cd7434065ea93b4cd1eccab8c65
 F src/vdbeaux.c 42e215cc6f69e91eebdd2b886ec1ff2b0d5e44331bd8b88a0a44e78bbeed7133
 F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9
 F src/vdbemem.c fe8fce1cdc258320b465934039fe4b1230d63f81d6b81b1eac775b6eec00af0d
@@ -632,7 +632,7 @@ F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738
 F test/capi3.test 986e57cea8ab423b3fc8c2e3b69330394252d3d2a4496122ff3749e258305695
 F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
 F test/capi3c.test 7ebed1d8fa2f3190149d556fe8cff5a006be62af437c5c4640db614470126098
-F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
+F test/capi3d.test 876b9dda41f003aed30df91f0b8653e576a956ab46efa00eadd35d6920cb94e2
 F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
 F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
 F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
@@ -1637,8 +1637,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 d14fc621e918915bbf8e04597eb238ea78dff3d9c5eb4402cb88692d00dbdfee b7f70c7fcabc10b8b3e62fe5ac68476cec23acaee037c7250ff70bca3f3ab541
-R 636bb2618e46215e27cfa1dc613ec36a
-T +closed b7f70c7fcabc10b8b3e62fe5ac68476cec23acaee037c7250ff70bca3f3ab541
+P a90c062d46c63a1e6f83064b1c5afb26a16e93b6ee8620ca46d169fdb325c488
+R 25671fe00f59e885629fa15763c01ca2
+T *branch * sqlite3_stmt_refresh
+T *sym-sqlite3_stmt_refresh *
+T -sym-trunk *
 U drh
-Z 8d21c041010891259262753e78bdd45f
+Z 3a35a5d7b215280c71ff1c56378d2e53
index 9f9976a1090f5717aeea19983e6995d5df6bb402..5897d5c6e58d98ab717916e22895981457ec3f7a 100644 (file)
@@ -1 +1 @@
-a90c062d46c63a1e6f83064b1c5afb26a16e93b6ee8620ca46d169fdb325c488
\ No newline at end of file
+10556ee454edf60dd6542fdf9017f713c783b9ca1b86f25f45e3c17ffb184e24
\ No newline at end of file
index 427b6f747e4dd62b5ecef23b19b2a6214a221b86..64fac3a1c4820a8b5e3731ef963b8451416484b7 100644 (file)
@@ -3742,6 +3742,17 @@ int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
 */
 int sqlite3_stmt_busy(sqlite3_stmt*);
 
+/*
+** CAPI3REF: Recompile A Prepared Statement If Needed
+** METHOD: sqlite3_stmt
+**
+** ^The sqlite3_stmt_refresh(S) examines the [prepared statement] S
+** and attempts to recompile it if it has expired, for example due
+** to a schema change.  ^If the prepared statement S is up-to-date and
+** ready for use, then sqlite3_stmt_refresh(S) is a no-op.
+*/
+int sqlite3_stmt_refresh(sqlite3_stmt*);
+
 /*
 ** CAPI3REF: Dynamically Typed Value Object
 ** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value}
index df7685f244d698a788aec0c3aff26abf5892afc4..a75d6f8de132b88c0fc2415fa25e44876eafe5ba 100644 (file)
@@ -2638,6 +2638,32 @@ static int SQLITE_TCLAPI test_stmt_busy(
   return TCL_OK;
 }
 
+/*
+** Usage:  sqlite3_stmt_refresh  STMT
+**
+** Recompile the STMT prepared statement if it needs to be recompiled.
+*/
+static int SQLITE_TCLAPI test_stmt_refresh(
+  void * clientData,
+  Tcl_Interp *interp,
+  int objc,
+  Tcl_Obj *CONST objv[]
+){
+  sqlite3_stmt *pStmt;
+  int rc;
+
+  if( objc!=2 ){
+    Tcl_AppendResult(interp, "wrong # args: should be \"",
+        Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
+    return TCL_ERROR;
+  }
+
+  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
+  rc = sqlite3_stmt_refresh(pStmt);
+  Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
+  return TCL_OK;
+}
+
 /*
 ** Usage:  uses_stmt_journal  STMT
 **
@@ -7491,6 +7517,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
      { "sqlite3_next_stmt",             test_next_stmt     ,0 },
      { "sqlite3_stmt_readonly",         test_stmt_readonly ,0 },
      { "sqlite3_stmt_busy",             test_stmt_busy     ,0 },
+     { "sqlite3_stmt_refresh",          test_stmt_refresh  ,0 },
      { "uses_stmt_journal",             uses_stmt_journal ,0 },
 
      { "sqlite3_release_memory",        test_release_memory,     0},
index 3e6231e0d886ef922b8af3827dc011cfae098b87..76a0bb2419c0ebbb9dae9cdb5347eeca5ec7e4c1 100644 (file)
@@ -3191,6 +3191,9 @@ case OP_Transaction: {
     rc = SQLITE_SCHEMA;
   }
   if( rc ) goto abort_due_to_error;
+  if( p->stopAfterInit && pOp[1].opcode!=OP_Transaction ){
+    goto vdbe_return;
+  }
   break;
 }
 
index 599fe704145688ff298fcafc762ace3b9faa8321..be288e1e47035dcdbb562bcd1c2e6cf4eece5934 100644 (file)
@@ -392,6 +392,7 @@ 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 */
+  bft stopAfterInit:1;    /* Halt after running the last OP_Transaction */
   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 35b194fffeff52dde9b47c5da5e588ea4abad7b1..df2b4cbf152a88b3c644906379654b72ef1d70f1 100644 (file)
@@ -1608,6 +1608,28 @@ int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
   return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0;
 }
 
+/*
+** Recompile the prepared statement if it has expired
+*/
+int sqlite3_stmt_refresh(sqlite3_stmt *pStmt){
+  int rc = SQLITE_OK;
+  if( !sqlite3_stmt_busy(pStmt) ){
+    VdbeOp *aOp;
+    Vdbe *v = (Vdbe*)pStmt;
+    sqlite3_mutex_enter(v->db->mutex);
+    aOp = v->aOp;
+    assert( aOp[0].opcode==OP_Init );
+    if( aOp[aOp[0].p2].opcode==OP_Transaction ){
+      v->stopAfterInit = 1;
+      rc = sqlite3_step(pStmt);
+      v->stopAfterInit = 0;
+      sqlite3_reset(pStmt);
+    }
+    sqlite3_mutex_leave(v->db->mutex);
+  }
+  return rc;
+}
+
 /*
 ** Return a pointer to the next prepared statement after pStmt associated
 ** with database connection pDb.  If pStmt is NULL, return the first
index 3b9b8375d180a5c5e1009b8f48192583132b2ab7..ead409eba73b86ec6e0abb486673a32f6ca4b166 100644 (file)
@@ -179,5 +179,30 @@ do_test capi3d-4.2.6 {
   sqlite3_finalize $::s1
 } {SQLITE_OK}
 
+# Tests for the sqlite3_stmt_refresh() interface
+#
+do_execsql_test capi3d-5.1 {
+  DROP TABLE IF EXISTS t5;
+  CREATE TABLE t5(a,b);
+  INSERT INTO t5 VALUES(1,2),(3,4);
+}
+do_test capi3d-5.2 {
+  set ::s1 [sqlite3_prepare_v2 db "SELECT * FROM t5" -1 notused]
+  sqlite3 db2 test.db
+  db2 eval {SELECT * FROM t5 ORDER BY a}
+} {1 2 3 4}
+do_test capi3d-5.3 {
+  sqlite3_column_count $::s1
+} 2
+do_test capi3d-5.4 {
+  db2 eval {ALTER TABLE t5 ADD COLUMN c DEFAULT 9}
+  sqlite3_column_count $::s1
+} 2
+do_test capi3d-5.5 {
+  sqlite3_stmt_refresh $::s1
+  sqlite3_column_count $::s1
+} 3
+sqlite3_finalize $::s1
+db2 close
 
 finish_test