aboutsummaryrefslogtreecommitdiff
path: root/src/resolve.c
diff options
context:
space:
mode:
authordan <Dan Kennedy>2023-09-15 18:36:51 +0000
committerdan <Dan Kennedy>2023-09-15 18:36:51 +0000
commit81b70d97eb3ccf25d8fec5544009e6ebe9225b4a (patch)
treefce9a903cbc8d9ac0d341dd697e20af9f7931da3 /src/resolve.c
parent581b22936297aa4cc19f2ee1920804ce96d5459d (diff)
downloadsqlite-81b70d97eb3ccf25d8fec5544009e6ebe9225b4a.tar.gz
sqlite-81b70d97eb3ccf25d8fec5544009e6ebe9225b4a.zip
Allow expressions like "<tbl>.rowid" to refer to implicit rowid columns of tables in nested FROM clauses.
FossilOrigin-Name: 59a1bbc69f5dbb33418fa4b383393fb13a46bc1e531577da8ad54ae2fad5a10e
Diffstat (limited to 'src/resolve.c')
-rw-r--r--src/resolve.c35
1 files changed, 25 insertions, 10 deletions
diff --git a/src/resolve.c b/src/resolve.c
index 7fc0151ad..20bce29a2 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -104,21 +104,35 @@ static void resolveAlias(
}
/*
-** Subqueries stores the original database, table and column names for their
-** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN".
-** Check to see if the zSpan given to this routine matches the zDb, zTab,
-** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will
-** match anything.
+** Subqueries store the original database, table and column names for their
+** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN",
+** and mark the expression-list item by setting ExprList.a[].fg.eEName
+** to ENAME_TAB.
+**
+** Check to see if the zSpan/eEName of the expression-list item passed to this
+** routine matches the zDb, zTab, and zCol. If any of zDb, zTab, and zCol are
+** NULL then those fields will match anything. Return true if there is a match,
+** or false otherwise.
+**
+** SF_NestedFrom subqueries also store an entry for the implicit rowid (or
+** _rowid_, or oid) column by setting ExprList.a[].fg.eEName to ENAME_ROWID,
+** and setting zSpan to "DATABASE.TABLE.<rowid-alias>". This type of pItem
+** argument matches if bRowidOk is true, zTab is not NULL, zCol is a rowid
+** alias, and zDb matches as for the usual case.
*/
int sqlite3MatchEName(
const struct ExprList_item *pItem,
const char *zCol,
const char *zTab,
- const char *zDb
+ const char *zDb,
+ int bRowidOk
){
int n;
const char *zSpan;
- if( pItem->fg.eEName!=ENAME_TAB ) return 0;
+ int eEName = pItem->fg.eEName;
+ if( eEName!=ENAME_TAB && (eEName!=ENAME_ROWID || bRowidOk==0 || zTab==0) ){
+ return 0;
+ }
zSpan = pItem->zEName;
for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){
@@ -130,8 +144,9 @@ int sqlite3MatchEName(
return 0;
}
zSpan += n+1;
- if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){
- return 0;
+ if( zCol ){
+ if( eEName==ENAME_TAB && sqlite3StrICmp(zSpan, zCol)!=0 ) return 0;
+ if( eEName==ENAME_ROWID && sqlite3IsRowid(zCol)==0 ) return 0;
}
return 1;
}
@@ -342,7 +357,7 @@ static int lookupName(
assert( pEList!=0 );
assert( pEList->nExpr==pTab->nCol );
for(j=0; j<pEList->nExpr; j++){
- if( !sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb) ){
+ if( !sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb, cnt==0) ){
continue;
}
if( cnt>0 ){