-C Allow\sexpressions\slike\s"<tbl>.rowid"\sto\srefer\sto\simplicit\srowid\scolumns\sof\stables\sin\snested\sFROM\sclauses.
-D 2023-09-15T18:36:51.501
+C Fix\sresolution\sof\sunqualified\s"rowid"\sidentifiers\sin\squeries\swith\snested\sjoins.
+D 2023-09-15T20:57:05.776
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F src/prepare.c 80548297dc0e1fb3139cdebffb5a1bcac3dfac66d791012dd74838e70445072d
F src/printf.c e3ba080e2f409f9bfcc8d34724e6fc160e9c718dc92d0548f6b71b8b6f860ce2
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
-F src/resolve.c f31aab54a4bcb1a3e592daa6b657b7d3a725e40bf764a652dc175006ed4eead2
+F src/resolve.c 1cbb3dacd41882dabe07209242d015f100d36cfb685235278b1d4e15711017b7
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 5e9ff0eb38e5341780a70e3a39ea1d447c237552d1f552416dc605c123bf2acd
F src/shell.c.in 62708bea44d4e43aa7b1270ed422d1d29e82297924d4e0f223c39336a3f582f8
F src/sqlite.h.in 931a58d119d5cf87110648f39fa0bb9f1738b0068cb68250d893304a471bd6c0
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 2f30b2671f4c03cd27a43f039e11251391066c97d11385f5f963bb40b03038ac
-F src/sqliteInt.h 6cac7a6d674ea44fa867d929786ddec86df9be64c24d59afbf15c7bac671067c
+F src/sqliteInt.h f2d713fac835f32b131d8a334595b0c471ede3796dab527c705d2b03c32d14e9
F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee1fb6
F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be28
F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
-F test/joinH.test 44c51631e487a55902b2ed05706cad19c3ecdd86b7e1c7c8aa84457cec564d11
+F test/joinH.test 832a33079ee8fba7e33fa5ac77c481b3fd8399ba16362d4524a0be22a060b9f2
F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
F test/journal3.test 7c3cf23ffc77db06601c1fcfc9743de8441cb77db9d1aa931863d94f5ffa140e
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P ce339046416e9ddeffe77f71a8bfb8c5b302160c3207f919aebd62902618ed59
-R bcfd521e8d34de98592bf4e489ebb783
-T *branch * nested-from-rowid-expansion
-T *sym-nested-from-rowid-expansion *
-T -sym-trunk *
+P 59a1bbc69f5dbb33418fa4b383393fb13a46bc1e531577da8ad54ae2fad5a10e
+R 790b7202228cf2f5b7a7a80533c697dd
U dan
-Z dee6d86baf948e05aa8b2bb5ee3449dc
+Z ce4b0349e1c5a42e7e7210175df9fc25
# Remove this line to create a well-formed Fossil manifest.
-59a1bbc69f5dbb33418fa4b383393fb13a46bc1e531577da8ad54ae2fad5a10e
\ No newline at end of file
+bbcbd3d537d6790373d97f59386b8ce7fa2177db572af0f1babe058a76e25cc3
\ No newline at end of file
** 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.
+** argument matches if zCol is a rowid alias. If it is not NULL, (*pbRowid)
+** is set to 1 if there is this kind of match.
*/
int sqlite3MatchEName(
const struct ExprList_item *pItem,
const char *zCol,
const char *zTab,
const char *zDb,
- int bRowidOk
+ int *pbRowid
){
int n;
const char *zSpan;
int eEName = pItem->fg.eEName;
- if( eEName!=ENAME_TAB && (eEName!=ENAME_ROWID || bRowidOk==0 || zTab==0) ){
+ if( eEName!=ENAME_TAB && (eEName!=ENAME_ROWID || pbRowid==0) ){
return 0;
}
+ assert( pbRowid==0 || *pbRowid==0 );
zSpan = pItem->zEName;
for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){
if( eEName==ENAME_TAB && sqlite3StrICmp(zSpan, zCol)!=0 ) return 0;
if( eEName==ENAME_ROWID && sqlite3IsRowid(zCol)==0 ) return 0;
}
+ if( eEName==ENAME_ROWID ) *pbRowid = 1;
return 1;
}
assert( pEList!=0 );
assert( pEList->nExpr==pTab->nCol );
for(j=0; j<pEList->nExpr; j++){
- if( !sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb, cnt==0) ){
+ int bRowid = 0; /* True if possible rowid match */
+ if( !sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb, &bRowid) ){
continue;
}
- if( cnt>0 ){
- if( pItem->fg.isUsing==0
- || sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0
- ){
- /* Two or more tables have the same column name which is
- ** not joined by USING. This is an error. Signal as much
- ** by clearing pFJMatch and letting cnt go above 1. */
- sqlite3ExprListDelete(db, pFJMatch);
- pFJMatch = 0;
- }else
- if( (pItem->fg.jointype & JT_RIGHT)==0 ){
- /* An INNER or LEFT JOIN. Use the left-most table */
- continue;
- }else
- if( (pItem->fg.jointype & JT_LEFT)==0 ){
- /* A RIGHT JOIN. Use the right-most table */
- cnt = 0;
- sqlite3ExprListDelete(db, pFJMatch);
- pFJMatch = 0;
- }else{
- /* For a FULL JOIN, we must construct a coalesce() func */
- extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn);
+ if( bRowid==0 ){
+ if( cnt>0 ){
+ if( pItem->fg.isUsing==0
+ || sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0
+ ){
+ /* Two or more tables have the same column name which is
+ ** not joined by USING. This is an error. Signal as much
+ ** by clearing pFJMatch and letting cnt go above 1. */
+ sqlite3ExprListDelete(db, pFJMatch);
+ pFJMatch = 0;
+ }else
+ if( (pItem->fg.jointype & JT_RIGHT)==0 ){
+ /* An INNER or LEFT JOIN. Use the left-most table */
+ continue;
+ }else
+ if( (pItem->fg.jointype & JT_LEFT)==0 ){
+ /* A RIGHT JOIN. Use the right-most table */
+ cnt = 0;
+ sqlite3ExprListDelete(db, pFJMatch);
+ pFJMatch = 0;
+ }else{
+ /* For a FULL JOIN, we must construct a coalesce() func */
+ extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn);
+ }
}
+ cnt++;
+ hit = 1;
+ }else if( cnt>0 ){
+ continue;
}
- cnt++;
- cntTab = 2;
+ cntTab++;
pMatch = pItem;
pExpr->iColumn = j;
pEList->a[j].fg.bUsed = 1;
- hit = 1;
if( pEList->a[j].fg.bUsingTerm ) break;
}
if( hit || zTab==0 ) continue;
&& pMatch
&& (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
&& sqlite3IsRowid(zCol)
- && ALWAYS(VisibleRowid(pMatch->pTab))
+ && ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom)
){
cnt = 1;
- pExpr->iColumn = -1;
+ if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1;
pExpr->affExpr = SQLITE_AFF_INTEGER;
}
const char*,
const char*,
const char*,
- int
+ int*
);
Bitmask sqlite3ExprColUsed(Expr*);
u8 sqlite3StrIHash(const char*);
SELECT x3.oid FROM x1 JOIN (x2 JOIN x3 ON c='c')
} 43
+breakpoint
do_execsql_test 8.2 {
SELECT x3.rowid FROM x1 JOIN (x2 JOIN x3 ON c='c')
} {hello}
CREATE TABLE wo1(a PRIMARY KEY, b) WITHOUT ROWID;
CREATE TABLE wo2(a PRIMARY KEY, rowid) WITHOUT ROWID;
+ CREATE TABLE wo3(a PRIMARY KEY, b) WITHOUT ROWID;
}
-# Should an error.
do_catchsql_test 9.1 {
- SELECT rowid FROM wo1 JOIN (x1 JOIN x2);
+ SELECT rowid FROM wo1, x1, x2;
} {1 {no such column: rowid}}
-
-# Should not be an error.
do_catchsql_test 9.2 {
+ SELECT rowid FROM wo1, (x1, x2);
+} {1 {no such column: rowid}}
+do_catchsql_test 9.3 {
+ SELECT rowid FROM wo1 JOIN (x1 JOIN x2);
+} {1 {no such column: rowid}}
+do_catchsql_test 9.4 {
+ SELECT a FROM wo1, x1, x2;
+} {1 {ambiguous column name: a}}
+do_catchsql_test 9.5 {
SELECT rowid FROM x1 JOIN (x2 JOIN wo2);
} {0 {}}
+do_catchsql_test 9.6 {
+ SELECT _rowid_ FROM wo1 JOIN (wo3 JOIN x3)
+} {0 {}}
+
+
+
finish_test