]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Handle the case where a virtual table xBestIndex method called while coding a trigger...
authordan <Dan Kennedy>
Thu, 26 Oct 2023 16:05:57 +0000 (16:05 +0000)
committerdan <Dan Kennedy>
Thu, 26 Oct 2023 16:05:57 +0000 (16:05 +0000)
FossilOrigin-Name: ec6bffa3b0fbf7cdee852cb0208de1f5869dafd88e2ee64c23cec89634219adc

manifest
manifest.uuid
src/build.c
src/sqliteInt.h
test/bestindexB.test [new file with mode: 0644]

index 009e49e106bf182d709c79d29b91d67779d2048c..70aeaa22c579f2349661aeb96c18da9c3fec8fff 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Deal\swith\sthe\scase\sof\sa\sreentrant\sINSERT\son\sa\svirtual\stable\swhere\sthe\nouter\sINSERT\shas\sa\sRETURNING\sclause\sbut\sthe\sinner\sdoes\snot.\ndbsqlfuzz\s3ac9a1e33f676254e02c0f297263b0a7aeb0c1a5.
-D 2023-10-26T12:59:41.136
+C Handle\sthe\scase\swhere\sa\svirtual\stable\sxBestIndex\smethod\scalled\swhile\scoding\sa\strigger\sfired\sby\sa\stop-level\sstatement\swith\sa\sRETURNING\sclause\sprepares\sa\sstatement\sthat\salso\scontains\sa\sRETURNING\sclause.
+D 2023-10-26T16:05:57.832
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -663,7 +663,7 @@ F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
 F src/btree.c f6c8512a0db0851877683e41936aac0f8927bc31630cbb1bc87ccccf79c06944
 F src/btree.h 03e3356f5208bcab8eed4e094240fdac4a7f9f5ddf5e91045ce589f67d47c240
 F src/btreeInt.h ef12a72b708677e48d6bc8dcd66fed25434740568b89e2cfa368093cfc5b9d15
-F src/build.c 1a9061ab67987cfa9c7f9d52ccc862a31d37ad2b05faaf0d72eeb4b4b5ee37cf
+F src/build.c 189e4517d67f09f0a3e0d8e1faa6e2ef0c2e95f6ac82e33c912cb7efa2a359cc
 F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
 F src/ctime.c 23331529e654be40ca97d171cbbffe9b3d4c71cc53b78fe5501230675952da8b
@@ -726,7 +726,7 @@ F src/shell.c.in acc452c414fddd10289d165be3c89a7a2c36c919def04c93fb7dd11ac022e6e
 F src/sqlite.h.in 428948ef39b3ef7b675ec12bd4853619bad77279b5fa38e3a51c5b9656ae16ff
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 2f30b2671f4c03cd27a43f039e11251391066c97d11385f5f963bb40b03038ac
-F src/sqliteInt.h cf6646e8694a63749096e1f086767a2c1920dca9848ec2dbe9f7bfb961d322ef
+F src/sqliteInt.h 567e317f8631883897b7d3da43fce778b7c30dd0dd7f714558c9725fc1c1196c
 F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee1fb6
 F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -905,6 +905,7 @@ F test/bestindex7.test f094c669a6400777f4d2ddc3ed28e39169f1adb5be3d59b55f22ccf8c
 F test/bestindex8.test 333ad8c6a554b885a49b68c019166eda92b05f493a92b36b0acdf7f766d04dad
 F test/bestindex9.test 1a4b93db117fd8abe74ae9be982f86aa72f01e60cd4ac541e6ede39673a451a0
 F test/bestindexA.test e1b5def6b190797cacf008e6815ffb78fb30261999030d60a728d572eef44c7f
+F test/bestindexB.test 328b97b69cd1a20928d5997f9ecb04d2e00f1d18e19ab27f9e9adb44d7bc51ce
 F test/between.test b9a65fb065391980119e8a781a7409d3fcf059d89968279c750e190a9a1d5263
 F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
 F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
@@ -2138,8 +2139,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 cc8efe0494b8fe0df18aa67b1675779bf704d1ac53647fe1f7f55d8048041680
-R 9ba44fb9dc03b38d8120c04401aaff8f
-U drh
-Z ab6f9f2ea52a3134056d677d31c255aa
+P 8aba78e4dbf5c196aa50a28579f4bcd7c96103661c5968d62b2fded075bc73e4
+R 3f971dd192c77b68556855589625c95d
+U dan
+Z ef9839d8477bc114052377f752ca4da6
 # Remove this line to create a well-formed Fossil manifest.
index 15e01cccdbd8e9ba1bf66928e1382d8a2cbc2f00..edc06300fdb7bb3ffdccc6b762f35868919bc9c2 100644 (file)
@@ -1 +1 @@
-8aba78e4dbf5c196aa50a28579f4bcd7c96103661c5968d62b2fded075bc73e4
\ No newline at end of file
+ec6bffa3b0fbf7cdee852cb0208de1f5869dafd88e2ee64c23cec89634219adc
\ No newline at end of file
index 24f5d3f96a0c31f97d72e0fbb7506ee2cd2781db..3d0679235866f421222f500efd28a5375136a3b9 100644 (file)
@@ -1407,20 +1407,13 @@ void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){
 }
 #endif
 
-/*
-** Name of the special TEMP trigger used to implement RETURNING.  The
-** name begins with "sqlite_" so that it is guaranteed not to collide
-** with any application-generated triggers.
-*/
-#define RETURNING_TRIGGER_NAME  "sqlite_returning"
-
 /*
 ** Clean up the data structures associated with the RETURNING clause.
 */
 static void sqlite3DeleteReturning(sqlite3 *db, Returning *pRet){
   Hash *pHash;
   pHash = &(db->aDb[1].pSchema->trigHash);
-  sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, 0);
+  sqlite3HashInsert(pHash, pRet->zName, 0);
   sqlite3ExprListDelete(db, pRet->pReturnEL);
   sqlite3DbFree(db, pRet);
 }
@@ -1463,7 +1456,9 @@ void sqlite3AddReturning(Parse *pParse, ExprList *pList){
      (void(*)(sqlite3*,void*))sqlite3DeleteReturning, pRet);
   testcase( pParse->earlyCleanup );
   if( db->mallocFailed ) return;
-  pRet->retTrig.zName = RETURNING_TRIGGER_NAME;
+  sqlite3_snprintf(sizeof(pRet->zName), pRet->zName,
+                   "sqlite_returning_%p", pParse);
+  pRet->retTrig.zName = pRet->zName;
   pRet->retTrig.op = TK_RETURNING;
   pRet->retTrig.tr_tm = TRIGGER_AFTER;
   pRet->retTrig.bReturning = 1;
@@ -1474,9 +1469,9 @@ void sqlite3AddReturning(Parse *pParse, ExprList *pList){
   pRet->retTStep.pTrig = &pRet->retTrig;
   pRet->retTStep.pExprList = pList;
   pHash = &(db->aDb[1].pSchema->trigHash);
-  assert( sqlite3HashFind(pHash, RETURNING_TRIGGER_NAME)==0
+  assert( sqlite3HashFind(pHash, pRet->zName)==0
           || pParse->nErr  || pParse->ifNotExists );
-  if( sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, &pRet->retTrig)
+  if( sqlite3HashInsert(pHash, pRet->zName, &pRet->retTrig)
           ==&pRet->retTrig ){
     sqlite3OomFault(db);
   }
index b6cc81fba1e5eb62289ca384a69b28f68e9c9a99..dbf01dd139089bcc6cd1f4047bc505eb9d01f064 100644 (file)
@@ -4077,6 +4077,7 @@ struct Returning {
   int iRetCur;          /* Transient table holding RETURNING results */
   int nRetCol;          /* Number of in pReturnEL after expansion */
   int iRetReg;          /* Register array for holding a row of RETURNING */
+  char zName[40];       /* Name of trigger: "sqlite_returning_%p" */
 };
 
 /*
diff --git a/test/bestindexB.test b/test/bestindexB.test
new file mode 100644 (file)
index 0000000..b50e74f
--- /dev/null
@@ -0,0 +1,87 @@
+# 2023-10-26
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# 
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix bestindexB
+
+ifcapable !vtab {
+  finish_test
+  return
+}
+
+register_tcl_module db
+
+proc vtab_command {method args} {
+  switch -- $method {
+    xConnect {
+      return "CREATE TABLE t1(a, b, c)"
+    }
+
+    xBestIndex {
+      set hdl [lindex $args 0]
+      set clist [$hdl constraints]
+      set orderby [$hdl orderby]
+
+      if {[info exists ::xbestindex_sql]} { 
+        explain_i $::xbestindex_sql 
+        set ::xbestindex_res [ execsql $::xbestindex_sql ]
+      }
+
+      return "cost 1000000 rows 1000000 idxnum 0 idxstr hello"
+    }
+
+    xFilter {
+      return "sql {SELECT 0, 1, 2, 3}"
+    }
+  }
+
+  return {}
+}
+
+do_execsql_test 1.0 {
+  CREATE VIRTUAL TABLE x1 USING tcl(vtab_command);
+  CREATE TABLE y1(a, b);
+  CREATE TABLE y2(a, b);
+} {}
+
+do_execsql_test 1.1 {
+  SELECT * FROM x1
+} {1 2 3}
+
+do_execsql_test 1.2 {
+  INSERT INTO y1 VALUES(1, 2) RETURNING rowid;
+} {1}
+
+do_execsql_test 1.3 {
+  CREATE TRIGGER y1tr BEFORE INSERT ON y1 BEGIN
+    SELECT * FROM x1;
+  END;
+  INSERT INTO y1 VALUES(3, 4) RETURNING rowid;
+} {2}
+
+
+# This time, rig the xBestIndex() method of the vtab to invoke an SQL
+# statement that uses RETURNING.
+set ::xbestindex_sql {
+  INSERT INTO y2 VALUES(NULL, NULL) RETURNING rowid;
+}
+do_execsql_test 1.4 {
+  INSERT INTO y1 VALUES(5, 6) RETURNING rowid;
+} {3}
+
+do_test 1.5 {
+  set ::xbestindex_res
+} {1}
+
+finish_test