-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
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
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
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
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.
-c1d42861778d65f7014c43fbaf09972a69ff0d81bfc2f4720160a989489cf2c8
\ No newline at end of file
+0da2232624571f4020c05d775ea518514d748fba8dacd4caba2e2e6ed1ae399f
\ No newline at end of file
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 ){
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) ...
** 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 ){
pMatch = pItem;
pExpr->iColumn = j;
hit = 1;
+ pEList->a[j].bUsed = 1;
+ pTab->aCol[j].colFlags &= ~COLFLAG_HIDDEN;
}
}
if( hit || zTab==0 ) continue;
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.
&& (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pTab->aCol[iCol])==0)
){
if( piTab ){
+ sqlite3SrcItemColumnUsed(&pSrc->a[i], iCol);
*piTab = i;
*piCol = iCol;
}
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
}
pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1);
pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol);
+ sqlite3SrcItemColumnUsed(pLeft, iLeftCol);
}
if( pFuncArgs ){
pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1);
}
}
pE2 = sqlite3CreateColumnExpr(db, pSrc, i+1, iRightCol);
+ sqlite3SrcItemColumnUsed(pRight, iRightCol);
pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2);
assert( pE2!=0 || pEq==0 );
if( pEq ){
}
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;
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;
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 */
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 {
#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
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);
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);