]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Improved tracking of nested SELECT objects used to implement
authordrh <>
Wed, 20 Apr 2022 15:07:39 +0000 (15:07 +0000)
committerdrh <>
Wed, 20 Apr 2022 15:07:39 +0000 (15:07 +0000)
parenthensized FROM terms.

FossilOrigin-Name: 0da2232624571f4020c05d775ea518514d748fba8dacd4caba2e2e6ed1ae399f

manifest
manifest.uuid
src/build.c
src/resolve.c
src/select.c
src/sqliteInt.h
src/treeview.c

index a19f3d315dd371553c620dc24475f827a2716efa..432ff35dcf73ab0475a59d47fee415e87f824b60 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Also\sshow\sthe\sENAME_SPAN\svalue\sin\ssqlite3TreeViewExprList(),\sif\sthere\sis\sone.
-D 2022-04-20T12:15:51.225
+C Improved\stracking\sof\snested\sSELECT\sobjects\sused\sto\simplement\nparenthensized\sFROM\sterms.
+D 2022-04-20T15:07:39.807
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -495,7 +495,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
 F src/btree.c df695e953c2ce78ce4878ee5016751df9bc9a921dc0500a0f53ab3bb3196e505
 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
 F src/btreeInt.h 8ce1332edd89dfd2461d561ac10a0ab5601c8e06200cb5230596c3caaf54482e
-F src/build.c 7f4286d2b4c4ed013e8e064f958f10c277126085f7918c306e9f54c238b36393
+F src/build.c e1ecd83b3f9ff5079e63e5223ae02bbbd50335dbcf65b54405545de8988e6fae
 F src/callback.c 4c19af69835787bfe790ac560f3071a824eb629f34e41f97b52ce5235c77de1c
 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
 F src/ctime.c 026dbdcdbd8c3cde98a88483ee88310ff43150ab164ad768f12cc700a11495ad
@@ -550,14 +550,14 @@ F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
 F src/prepare.c fd940149c691684e7c1073c3787a7170e44852b02d1275d2e30a5b58e89cfcaf
 F src/printf.c 05d8dfd2018bc4fc3ddb8b37eb97ccef7abf985643fa1caebdcf2916ca90fa32
 F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
-F src/resolve.c a5ded9df5914fb1ff71e69e8d0c4aebfa04ad145e9ea8d9fbf185e409047e354
+F src/resolve.c 0d0bfa186b020909a26e776f34af1ddb060c653d99c0e80ec3de79efeada1093
 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
-F src/select.c 708edcf15749d1a91b8bc820f546772409b3a1a33d18ca70ff90f7253c470f5a
+F src/select.c df2bea1b4c6a5456f0f9892a633d59c2e2a3be0179ecd0c803bca75ddc1fd28d
 F src/shell.c.in ecff6f4ab0e8e25acd578b3eb27ac0bad4d48643c160259a277151d6e9d412e1
 F src/sqlite.h.in 2a35f62185eb5e7ecc64a2f68442b538ce9be74f80f28a00abc24837edcf1c17
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h f49e28c25bd941e79794db5415fdf7b202deb3bc072ed6f1ed273d578703684e
-F src/sqliteInt.h f1c2ad8969396460805c3334f55d623123f2ad2c79d468242b2332e9584453f3
+F src/sqliteInt.h 36b5d1cce15971fa71b53a950de3158197d85dbaf9b8b2f0bc6279347b09606a
 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
 F src/status.c 4a3da6d77eeb3531cb0dbdf7047772a2a1b99f98c69e90ce009c75fe6328b2c0
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -617,7 +617,7 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
 F src/tokenize.c a38f52058b517929e264094abd0b5fd1e8e145a1aa43bc6f6a72ae5218f96c98
-F src/treeview.c 26c904f27ac8b02ce3e2cd12caf451d48cdce2e0af89021629fb27800351e799
+F src/treeview.c f304faa8b595121da33f78f1f898af48a4db0caa7e310431aa27039ea5dbab36
 F src/trigger.c 372ada38f667c6823a3db15749eb668338e65c793394e55a37e56a489f2d1b55
 F src/update.c 2cfaded82ca80ff56afb8c3ae5e88284e0824bfd86119827cc22481959f96f92
 F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937
@@ -1950,8 +1950,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 eb3f883b45f1bf3f388823360f4aec2d4b8776bfd96185b4fb44b7bc95c62318
-R e8d9048ff74b7a71cf59494018285469
+P c1d42861778d65f7014c43fbaf09972a69ff0d81bfc2f4720160a989489cf2c8
+R 29bf9f13e64da641ea2eb344ef47fe0b
 U drh
-Z 087ab6d881fce9542bec295d73873a1e
+Z 1cabab88f048c2ecc5e840f82512e328
 # Remove this line to create a well-formed Fossil manifest.
index c6a7b1c525768c4d9336016117c1f3cfdbff5814..76b90cdf5f4b471c05315fedf387048b1c554d46 100644 (file)
@@ -1 +1 @@
-c1d42861778d65f7014c43fbaf09972a69ff0d81bfc2f4720160a989489cf2c8
\ No newline at end of file
+0da2232624571f4020c05d775ea518514d748fba8dacd4caba2e2e6ed1ae399f
\ No newline at end of file
index 1c632c94ed43f4fadeffde7436543f07b19c8a33..e1051ab9f38c5155ed3e36e1c013b1be531ebdde 100644 (file)
@@ -4970,7 +4970,12 @@ SrcList *sqlite3SrcListAppendFromTerm(
   if( pAlias->n ){
     pItem->zAlias = sqlite3NameFromToken(db, pAlias);
   }
-  pItem->pSelect = pSubquery;
+  if( pSubquery ){
+    pItem->pSelect = pSubquery;
+    if( pSubquery->selFlags & SF_NestedFrom ){
+      pItem->fg.isNestedFrom = 1;
+    }
+  }
   assert( pOnUsing==0 || pOnUsing->pOn==0 || pOnUsing->pUsing==0 );
   assert( pItem->fg.isUsing==0 );
   if( pOnUsing==0 ){
index c1a2a790ca91e889c0ead03c3577f5eb761f278a..ed764a5b1fd99e26bce5ed83baf33ce09b1620e6 100644 (file)
@@ -313,7 +313,8 @@ static int lookupName(
         pTab = pItem->pTab;
         assert( pTab!=0 && pTab->zName!=0 );
         assert( pTab->nCol>0 || pParse->nErr );
-        if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){
+        assert( pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
+        if( pItem->fg.isNestedFrom ){
           /* In this case, pItem is a subquery that has been formed from a
           ** parenthesized subset of the FROM clause terms.  Example:
           **   .... FROM t1 LEFT JOIN (t2 RIGHT JOIN t3 USING(x)) USING(y) ...
@@ -321,7 +322,10 @@ static int lookupName(
           **             This pItem -------------^
           */
           int hit = 0;
+          assert( pItem->pSelect!=0 );
           pEList = pItem->pSelect->pEList;
+          assert( pEList!=0 );
+          assert( pEList->nExpr==pTab->nCol );
           for(j=0; j<pEList->nExpr; j++){
             if( sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb) ){
               if( cnt>0 ){
@@ -353,6 +357,8 @@ static int lookupName(
               pMatch = pItem;
               pExpr->iColumn = j;
               hit = 1;
+              pEList->a[j].bUsed = 1;
+              pTab->aCol[j].colFlags &= ~COLFLAG_HIDDEN;
             }
           }
           if( hit || zTab==0 ) continue;
index 65ca283b3e61b1c247e2680f55bb0e90a091b641..3f754915df1aa177c2507f493546a043b2eeb298 100644 (file)
@@ -319,6 +319,22 @@ int sqlite3ColumnIndex(Table *pTab, const char *zCol){
   return -1;
 }
 
+/*
+** Mark a subquery result column as having been used.
+*/
+void sqlite3SrcItemColumnUsed(SrcItem *pItem, int iCol){
+  assert( pItem!=0 );
+  assert( pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
+  if( pItem->fg.isNestedFrom ){
+    ExprList *pResults;
+    assert( pItem->pSelect!=0 );
+    pResults = pItem->pSelect->pEList;
+    assert( pResults!=0 );
+    assert( iCol>=0 && iCol<pResults->nExpr );
+    pResults->a[iCol].bUsed = 1;
+  }
+}
+
 /*
 ** Search the tables iStart..iEnd (inclusive) in pSrc, looking for a
 ** table that has a column named zCol.  The search is left-to-right.
@@ -351,6 +367,7 @@ static int tableAndColumnIndex(
      && (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pTab->aCol[iCol])==0)
     ){
       if( piTab ){
+        sqlite3SrcItemColumnUsed(&pSrc->a[i], iCol);
         *piTab = i;
         *piCol = iCol;
       }
@@ -530,6 +547,7 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
           return 1;
         }
         pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol);
+        sqlite3SrcItemColumnUsed(pLeft, iLeftCol);
         if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
           /* This branch runs if the query contains one or more RIGHT or FULL
           ** JOINs.  If only a single table on the left side of this join
@@ -557,6 +575,7 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
             }
             pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1);
             pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol);
+            sqlite3SrcItemColumnUsed(pLeft, iLeftCol);
           }
           if( pFuncArgs ){
             pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1);
@@ -564,6 +583,7 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
           }
         }
         pE2 = sqlite3CreateColumnExpr(db, pSrc, i+1, iRightCol);
+        sqlite3SrcItemColumnUsed(pRight, iRightCol);
         pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2);
         assert( pE2!=0 || pEq==0 );
         if( pEq ){
@@ -5777,7 +5797,7 @@ static int selectExpander(Walker *pWalker, Select *p){
         }
         for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
           Table *pTab = pFrom->pTab;
-          Select *pSub = pFrom->pSelect;
+          Select *pSub;
           char *zTabName = pFrom->zAlias;
           const char *zSchemaName = 0;
           int iDb;
@@ -5785,7 +5805,12 @@ static int selectExpander(Walker *pWalker, Select *p){
             zTabName = pTab->zName;
           }
           if( db->mallocFailed ) break;
-          if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){
+          assert( pFrom->fg.isNestedFrom == IsNestedFrom(pFrom->pSelect) );
+          if( pFrom->fg.isNestedFrom ){
+            pSub = pFrom->pSelect;
+            assert( pSub->pEList!=0 );
+            assert( pSub->pEList->nExpr==pTab->nCol );
+          }else{
             pSub = 0;
             if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
               continue;
index 56b885906e3f8971d358ebce36759f9153cf49ca..ec465cdb335707426e50751d84fad6b599663570 100644 (file)
@@ -3004,6 +3004,7 @@ struct ExprList {
     unsigned reusable :1;   /* Constant expression is reusable */
     unsigned bSorterRef :1; /* Defer evaluation until after sorting */
     unsigned bNulls: 1;     /* True if explicit "NULLS FIRST/LAST" */
+    unsigned bUsed: 1;      /* This column used in a SF_NestedFrom subquery */
     union {
       struct {             /* Used by any ExprList other than Parse.pConsExpr */
         u16 iOrderByCol;      /* For ORDER BY, column number in result set */
@@ -3091,6 +3092,7 @@ struct SrcItem {
     unsigned notCte :1;        /* This item may not match a CTE */
     unsigned isUsing :1;       /* u3.pUsing is valid */
     unsigned isSynthUsing :1;  /* u3.pUsing is synthensized from NATURAL */
+    unsigned isNestedFrom :1;  /* pSelect is a SF_NestedFrom subquery */
   } fg;
   int iCursor;      /* The VDBE cursor number used to access this table */
   union {
@@ -3372,6 +3374,9 @@ struct Select {
 #define SF_CopyCte       0x4000000 /* SELECT statement is a copy of a CTE */
 #define SF_OrderByReqd   0x8000000 /* The ORDER BY clause may not be omitted */
 
+/* True if S exists and has SF_NestedFrom */
+#define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0)
+
 /*
 ** The results of a SELECT can be distributed in several ways, as defined
 ** by one of the following macros.  The "SRT" prefix means "SELECT Result
@@ -4843,6 +4848,7 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
 
 int sqlite3JoinType(Parse*, Token*, Token*, Token*);
 int sqlite3ColumnIndex(Table *pTab, const char *zCol);
+void sqlite3SrcItemColumnUsed(SrcItem*,int);
 void sqlite3SetJoinExpr(Expr*,int,u32);
 void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
 void sqlite3DeferForeignKey(Parse*, int);
index 6b77d41338fc375f9403ad6862f4ad04b0d71281..95c14448fd4ff32513aab7f5eb7a435eb9c3c347 100644 (file)
@@ -805,6 +805,7 @@ void sqlite3TreeViewBareExprList(
               break;
             case ENAME_TAB:
               fprintf(stdout, "TABLE-ALIAS-NAME(\"%s\") ", zName);
+              if( pList->a[i].bUsed==0 ) fprintf(stdout, "(unused) ");
               break;
             case ENAME_SPAN:
               fprintf(stdout, "SPAN(\"%s\") ", zName);