]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add a test-control that allows setting a LIKE pattern for common table optbarrier-test-ctrl
authordrh <>
Sat, 13 Feb 2021 21:01:31 +0000 (21:01 +0000)
committerdrh <>
Sat, 13 Feb 2021 21:01:31 +0000 (21:01 +0000)
expression names such that CTEs with matching names become an
optimization barrier - They are not flattened and are implemented by
materialization.

FossilOrigin-Name: 15692ec02b401eb81a13b25099714cf49fe64c5bde8b1f4028aca18f8fdd7655

manifest
manifest.uuid
src/main.c
src/select.c
src/shell.c.in
src/sqlite.h.in
src/sqliteInt.h
src/test1.c

index 81d46eaf6d7643fb81ce1bb51004bbc57812f833..196213f253ebe6288e9b212e53d3be406f16450a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sincorrect\stest\sname\slabels\sin\sthe\sselect1.test\sscript.
-D 2021-02-13T18:14:15.205
+C Add\sa\stest-control\sthat\sallows\ssetting\sa\sLIKE\spattern\sfor\scommon\stable\nexpression\snames\ssuch\sthat\sCTEs\swith\smatching\snames\sbecome\san\noptimization\sbarrier\s-\sThey\sare\snot\sflattened\sand\sare\simplemented\sby\nmaterialization.
+D 2021-02-13T21:01:31.030
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -505,7 +505,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
 F src/insert.c 3d17e465c4cdb7e02e4b2a9d0a6cee08d23c478a01bd7eb5c5d4024fc70c5e5c
 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
 F src/loadext.c 8c9c8cd2bd8eecdb06d9b6e89de7e9e65bae45cc8fc33609cc74023a5c296067
-F src/main.c 1c5de7b3fabcdf05f4fe563aab5d81d175b89c67a8678a12ba86629356afa356
+F src/main.c cd31d12a11dc688bcdb74f798396f3f6999453d8542f5fb44d3017a54cfcf5c7
 F src/malloc.c c1af4ac5a463648cd2953fd4ac679b3ba9022ce5ec794a60806150ad69dfd33a
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -541,17 +541,17 @@ F src/printf.c 30e92b638fac71dcd85cdea1d12ecfae354c9adee2c71e8e1ae4727cde7c91ed
 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
 F src/resolve.c 89e4faf6171e179edf279905e8e45c4f9dd108777dc60716396729fbd7cb045e
 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
-F src/select.c 9b4c84fd2703ee3c8b5d4b189387482a84c26acf2c38ca4835db5b48c68a09d4
-F src/shell.c.in 9ebc74e4f05cfbd0f4a36060fdaeff1da4e9af4458358722bc08c5a1ab9a0879
-F src/sqlite.h.in 8855a19f37ade8dad189a9e48233a2ebe1b46faf469c7eb0906a654e252dcc57
+F src/select.c 9415f7aa051ce6130eb3cea4cf1df66cc014b40e1cc35684e35abb5b95ac2742
+F src/shell.c.in c51718e42071dc61773c438838a734b4b43b2a74f062293799cd79b7268da6cf
+F src/sqlite.h.in dfb3bc794602ecbc0e330347b8be22d44558eed2bf6d929980055e425cab1544
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
-F src/sqliteInt.h 4cb469678a0dbf814e4efbde4488a0161a5398e9a63141830d9f676b4e9fb0cc
+F src/sqliteInt.h e5de6401f539dc1fa7eda72f9d094ddc91cdbcb718a85c87045c9b470769ff95
 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
 F src/tclsqlite.c 986b6391f02cd9b53c1d688be55899f6ffddeb8e8014cd83c1b73ff912579a71
-F src/test1.c 2197966d2f7211ef9eefaa6c3c7dd2c7d786d1f33f2aadef2f08c8c79eceec26
+F src/test1.c 6a0c649bcde43b0817258809aabacc35f7513160ef1d1f27816658e062fac752
 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
 F src/test4.c 7c4420e01c577b5c4add2cb03119743b1a357543d347773b9e717195ea967159
@@ -1899,7 +1899,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 9692f510803c9b9725abb687d7c10fbc0d5ed784479ec6f3fcc55925a87fe16d
-R 0c64c86089d6aa467750f9eba3dbafff
+P 179c79ea0deb0f5adaa8d369cfcad06d959a9cc18a8a41e01ef013b2d90acd61
+R e0e6fb25237319b02038c6709b13c495
+T *branch * optbarrier-test-ctrl
+T *sym-optbarrier-test-ctrl *
+T -sym-trunk *
 U drh
-Z bef3ac59ff66799b655a50d5e67ecd31
+Z 1c66b6635d9f626e4ac88dfb239b3101
index 16c0579a8faf759a2312c8179e1a8d1ee3380c44..52d109ac46e577ff0149737201f9a013916312f9 100644 (file)
@@ -1 +1 @@
-179c79ea0deb0f5adaa8d369cfcad06d959a9cc18a8a41e01ef013b2d90acd61
\ No newline at end of file
+15692ec02b401eb81a13b25099714cf49fe64c5bde8b1f4028aca18f8fdd7655
\ No newline at end of file
index 0f3989d9df99d96705a13475b31848668a09f503..de2422ade9c5aaa1938815c92b67fdffad2f5e2a 100644 (file)
@@ -1395,6 +1395,7 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
   ** structure?
   */
   sqlite3DbFree(db, db->aDb[1].pSchema);
+  sqlite3DbFree(db, db->zOptBarrierLike);
   sqlite3_mutex_leave(db->mutex);
   db->magic = SQLITE_MAGIC_CLOSED;
   sqlite3_mutex_free(db->mutex);
@@ -4275,6 +4276,28 @@ int sqlite3_test_control(int op, ...){
        }
        break;
     }
+
+    /*  sqlite3_test_control(SQLITE_TESTCTRL_OPTBARRIER_LIKE, db, zPattern);
+    **
+    ** The zPattern argument is a LIKE pattern, or NULL.  After this call,
+    ** subqueries, common table expressions, and views whose names
+    ** match the LIKE pattern, assuming a \ escape character, are
+    ** treated as optimization barriers.  They are not flattened.
+    ** The are implemented by materialization.
+    **
+    ** Setting the LIKE pattern to NULL disables this setting.  The
+    ** default state is disabled.
+    **
+    ** This database connection makes its own copy of the pattern.  The
+    ** zPattern argument does not need to persist after this routine returns.
+    */
+    case SQLITE_TESTCTRL_OPTBARRIER_LIKE: {
+      sqlite3 *db = va_arg(ap, sqlite3*);
+      const char *zPattern = va_arg(ap, const char*);
+      sqlite3DbFree(db, db->zOptBarrierLike);
+      db->zOptBarrierLike = sqlite3DbStrDup(db, zPattern);
+      break;
+    }
   }
   va_end(ap);
 #endif /* SQLITE_UNTESTABLE */
index 1ab2ec367ed31155c453b9b6d7bcd3f46782ed9f..aa8df03ee16c9c73d1c62a3e193a03f602c03067 100644 (file)
@@ -4938,6 +4938,11 @@ static int withExpand(
     pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
     if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
     assert( pFrom->pSelect );
+    if( db->zOptBarrierLike
+     && sqlite3_strlike(db->zOptBarrierLike, pTab->zName, '\\')==0
+    ){
+      pFrom->pSelect->selFlags |= SF_OptBarrier;
+    }
 
     /* Check if this is a recursive CTE. */
     pRecTerm = pSel = pFrom->pSelect;
@@ -6070,6 +6075,9 @@ int sqlite3Select(
       continue;
     }
 
+    /* Do not flatten if the subquery is an optimization barrier */
+    if( pSub->selFlags & SF_OptBarrier ) continue;
+
     if( flattenSubquery(pParse, p, i, isAgg) ){
       if( pParse->nErr ) goto select_end;
       /* This subquery can be absorbed into its parent. */
@@ -6214,16 +6222,18 @@ int sqlite3Select(
 
     /* Generate code to implement the subquery
     **
-    ** The subquery is implemented as a co-routine if the subquery is
+    ** The subquery is implemented as a co-routine if (1) the subquery is
     ** guaranteed to be the outer loop (so that it does not need to be
-    ** computed more than once)
+    ** computed more than once) and if (2) the subquery is not an
+    ** optimization barrier.
     **
-    ** TODO: Are there other reasons beside (1) to use a co-routine
+    ** TODO: Are there other reasons beside (1) and (2) to use a co-routine
     ** implementation?
     */
     if( i==0
      && (pTabList->nSrc==1
             || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0)  /* (1) */
+     && (pSub->selFlags & SF_OptBarrier)==0                         /* (2) */
     ){
       /* Implement a co-routine that will return a single row of the result
       ** set on each invocation.
index bfb9648128aa2f6eacb332dc424c0ba335c5fe8d..9d4a22f5db1885d0c0a0706d71515fbf727d6a57 100644 (file)
@@ -9942,6 +9942,7 @@ static int do_meta_command(char *zLine, ShellState *p){
       { "prng_save",          SQLITE_TESTCTRL_PRNG_SAVE,     ""               },
       { "prng_seed",          SQLITE_TESTCTRL_PRNG_SEED,     "SEED ?db?"      },
       { "seek_count",         SQLITE_TESTCTRL_SEEK_COUNT,    ""               },
+      { "optbarrier_like",    SQLITE_TESTCTRL_OPTBARRIER_LIKE, "?PATTERN?"    },
     };
     int testctrl = -1;
     int iCtrl = -1;
@@ -10085,6 +10086,16 @@ static int do_meta_command(char *zLine, ShellState *p){
           break;
         }
 
+        case SQLITE_TESTCTRL_OPTBARRIER_LIKE: {
+          if( nArg>=3 ){
+            rc2 = sqlite3_test_control(testctrl, p->db, azArg[2]);
+          }else{
+            rc2 = sqlite3_test_control(testctrl, p->db, 0);
+          }
+          isOk = 3;
+          break;
+        }
+
 #ifdef YYCOVERAGE
         case SQLITE_TESTCTRL_PARSER_COVERAGE:
           if( nArg==2 ){
index 8a9470f01b2c838cfd5c566452a980f8f482a48d..59a6ba8ae25c0e7fada3bcbf4925fc2bb09c2c9a 100644 (file)
@@ -7756,6 +7756,7 @@ int sqlite3_test_control(int op, ...);
 #define SQLITE_TESTCTRL_RESERVE                 14  /* NOT USED */
 #define SQLITE_TESTCTRL_OPTIMIZATIONS           15
 #define SQLITE_TESTCTRL_ISKEYWORD               16  /* NOT USED */
+#define SQLITE_TESTCTRL_OPTBARRIER_LIKE         16
 #define SQLITE_TESTCTRL_SCRATCHMALLOC           17  /* NOT USED */
 #define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS      17
 #define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
index 17b1cb415d24960061f6660d9e1da10bb41bc02b..04c317edce3f19bbfce95dbacfbf7af9c6b2c3b7 100644 (file)
@@ -1598,6 +1598,7 @@ struct sqlite3 {
   i64 nDeferredCons;            /* Net deferred constraints this transaction. */
   i64 nDeferredImmCons;         /* Net deferred immediate constraints */
   int *pnBytesFreed;            /* If not NULL, increment this in DbFree() */
+  char *zOptBarrierLike;        /* LIKE pattern for SF_OptBarrier SELECTs */
 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
   /* The following variables are all protected by the STATIC_MAIN
   ** mutex, not by sqlite3.mutex. They are used by code in notify.c.
@@ -3185,6 +3186,7 @@ struct Select {
 #define SF_NoopOrderBy   0x0400000 /* ORDER BY is ignored for this query */
 #define SF_UpdateFrom    0x0800000 /* Statement is an UPDATE...FROM */
 #define SF_PushDown      0x1000000 /* SELECT has be modified by push-down opt */
+#define SF_OptBarrier    0x2000000 /* This SELECT is an optimization barrier */
 
 /*
 ** The results of a SELECT can be distributed in several ways, as defined
index 1eb30514bffe14595aab2816c4cc82789e57d55c..f06044cad0749ab0ff04e186da0f963ccf1de02a 100644 (file)
@@ -6656,6 +6656,36 @@ static int SQLITE_TCLAPI prng_seed(
   return TCL_OK;
 }
 
+/*
+** tclcmd:  optimization_barrier_like_pattern PATTERN ?DB?
+**
+** Use the SQLITE_TESTCTRL_OPTBARRIER_LIKE test-control to set a LIKE
+** pattern that creates optimization barriers on views, common table
+** expressions, and subqueries.  An empty-string pattern disables this
+** feature.
+*/
+static int SQLITE_TCLAPI optbarrier_like(
+  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
+  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
+  int objc,              /* Number of arguments */
+  Tcl_Obj *CONST objv[]  /* Command arguments */
+){
+  int i = 0;
+  sqlite3 *db = 0;
+  const char *zPattern;
+  if( objc!=2 && objc!=3 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "PATTERN ?DB?");
+    return TCL_ERROR;
+  }
+  zPattern = Tcl_GetString(objv[1]);
+  if( zPattern && zPattern[0]==0 ) zPattern = 0;
+  if( objc==3 && getDbPointer(interp, Tcl_GetString(objv[2]), &db) ){
+    return TCL_ERROR;
+  }
+  sqlite3_test_control(SQLITE_TESTCTRL_OPTBARRIER_LIKE, db, zPattern);
+  return TCL_OK;
+}
+
 /*
 ** tclcmd:  extra_schema_checks BOOLEAN
 **
@@ -8354,6 +8384,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
      { "restore_prng_state",            restore_prng_state, 0 },
      { "reset_prng_state",              reset_prng_state,   0 },
      { "prng_seed",                     prng_seed,          0 },
+     { "optimization_barrier_like_pattern",
+                                        optbarrier_like,        0},
      { "extra_schema_checks",           extra_schema_checks,    0},
      { "database_never_corrupt",        database_never_corrupt, 0},
      { "database_may_be_corrupt",       database_may_be_corrupt, 0},