1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-12-13 22:42:20 +03:00

Fix resolution of unqualified "rowid" identifiers in queries with nested joins.

FossilOrigin-Name: bbcbd3d537d6790373d97f59386b8ce7fa2177db572af0f1babe058a76e25cc3
This commit is contained in:
dan
2023-09-15 20:57:05 +00:00
parent 81b70d97eb
commit 63702bccaa
5 changed files with 67 additions and 49 deletions

View File

@@ -1,5 +1,5 @@
C Allow\sexpressions\slike\s"<tbl>.rowid"\sto\srefer\sto\simplicit\srowid\scolumns\sof\stables\sin\snested\sFROM\sclauses. C Fix\sresolution\sof\sunqualified\s"rowid"\sidentifiers\sin\squeries\swith\snested\sjoins.
D 2023-09-15T18:36:51.501 D 2023-09-15T20:57:05.776
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -708,14 +708,14 @@ F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
F src/prepare.c 80548297dc0e1fb3139cdebffb5a1bcac3dfac66d791012dd74838e70445072d F src/prepare.c 80548297dc0e1fb3139cdebffb5a1bcac3dfac66d791012dd74838e70445072d
F src/printf.c e3ba080e2f409f9bfcc8d34724e6fc160e9c718dc92d0548f6b71b8b6f860ce2 F src/printf.c e3ba080e2f409f9bfcc8d34724e6fc160e9c718dc92d0548f6b71b8b6f860ce2
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c f31aab54a4bcb1a3e592daa6b657b7d3a725e40bf764a652dc175006ed4eead2 F src/resolve.c 1cbb3dacd41882dabe07209242d015f100d36cfb685235278b1d4e15711017b7
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 5e9ff0eb38e5341780a70e3a39ea1d447c237552d1f552416dc605c123bf2acd F src/select.c 5e9ff0eb38e5341780a70e3a39ea1d447c237552d1f552416dc605c123bf2acd
F src/shell.c.in 62708bea44d4e43aa7b1270ed422d1d29e82297924d4e0f223c39336a3f582f8 F src/shell.c.in 62708bea44d4e43aa7b1270ed422d1d29e82297924d4e0f223c39336a3f582f8
F src/sqlite.h.in 931a58d119d5cf87110648f39fa0bb9f1738b0068cb68250d893304a471bd6c0 F src/sqlite.h.in 931a58d119d5cf87110648f39fa0bb9f1738b0068cb68250d893304a471bd6c0
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 2f30b2671f4c03cd27a43f039e11251391066c97d11385f5f963bb40b03038ac F src/sqlite3ext.h 2f30b2671f4c03cd27a43f039e11251391066c97d11385f5f963bb40b03038ac
F src/sqliteInt.h 6cac7a6d674ea44fa867d929786ddec86df9be64c24d59afbf15c7bac671067c F src/sqliteInt.h f2d713fac835f32b131d8a334595b0c471ede3796dab527c705d2b03c32d14e9
F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee1fb6 F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee1fb6
F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749 F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -1290,7 +1290,7 @@ F test/joinC.test 1f1a602c2127f55f136e2cbd3bf2d26546614bf8cffe5902ec1ac9c07f87f2
F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be28 F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be28
F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127 F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
F test/joinH.test 44c51631e487a55902b2ed05706cad19c3ecdd86b7e1c7c8aa84457cec564d11 F test/joinH.test 832a33079ee8fba7e33fa5ac77c481b3fd8399ba16362d4524a0be22a060b9f2
F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497 F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4 F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
F test/journal3.test 7c3cf23ffc77db06601c1fcfc9743de8441cb77db9d1aa931863d94f5ffa140e F test/journal3.test 7c3cf23ffc77db06601c1fcfc9743de8441cb77db9d1aa931863d94f5ffa140e
@@ -2121,11 +2121,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P ce339046416e9ddeffe77f71a8bfb8c5b302160c3207f919aebd62902618ed59 P 59a1bbc69f5dbb33418fa4b383393fb13a46bc1e531577da8ad54ae2fad5a10e
R bcfd521e8d34de98592bf4e489ebb783 R 790b7202228cf2f5b7a7a80533c697dd
T *branch * nested-from-rowid-expansion
T *sym-nested-from-rowid-expansion *
T -sym-trunk *
U dan U dan
Z dee6d86baf948e05aa8b2bb5ee3449dc Z ce4b0349e1c5a42e7e7210175df9fc25
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
59a1bbc69f5dbb33418fa4b383393fb13a46bc1e531577da8ad54ae2fad5a10e bbcbd3d537d6790373d97f59386b8ce7fa2177db572af0f1babe058a76e25cc3

View File

@@ -117,22 +117,23 @@ static void resolveAlias(
** SF_NestedFrom subqueries also store an entry for the implicit rowid (or ** 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, ** _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 ** 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 ** argument matches if zCol is a rowid alias. If it is not NULL, (*pbRowid)
** alias, and zDb matches as for the usual case. ** is set to 1 if there is this kind of match.
*/ */
int sqlite3MatchEName( int sqlite3MatchEName(
const struct ExprList_item *pItem, const struct ExprList_item *pItem,
const char *zCol, const char *zCol,
const char *zTab, const char *zTab,
const char *zDb, const char *zDb,
int bRowidOk int *pbRowid
){ ){
int n; int n;
const char *zSpan; const char *zSpan;
int eEName = pItem->fg.eEName; 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; return 0;
} }
assert( pbRowid==0 || *pbRowid==0 );
zSpan = pItem->zEName; zSpan = pItem->zEName;
for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){ if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){
@@ -148,6 +149,7 @@ int sqlite3MatchEName(
if( eEName==ENAME_TAB && sqlite3StrICmp(zSpan, zCol)!=0 ) return 0; if( eEName==ENAME_TAB && sqlite3StrICmp(zSpan, zCol)!=0 ) return 0;
if( eEName==ENAME_ROWID && sqlite3IsRowid(zCol)==0 ) return 0; if( eEName==ENAME_ROWID && sqlite3IsRowid(zCol)==0 ) return 0;
} }
if( eEName==ENAME_ROWID ) *pbRowid = 1;
return 1; return 1;
} }
@@ -357,9 +359,11 @@ static int lookupName(
assert( pEList!=0 ); assert( pEList!=0 );
assert( pEList->nExpr==pTab->nCol ); assert( pEList->nExpr==pTab->nCol );
for(j=0; j<pEList->nExpr; j++){ 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; continue;
} }
if( bRowid==0 ){
if( cnt>0 ){ if( cnt>0 ){
if( pItem->fg.isUsing==0 if( pItem->fg.isUsing==0
|| sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0 || sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0
@@ -385,11 +389,14 @@ static int lookupName(
} }
} }
cnt++; cnt++;
cntTab = 2; hit = 1;
}else if( cnt>0 ){
continue;
}
cntTab++;
pMatch = pItem; pMatch = pItem;
pExpr->iColumn = j; pExpr->iColumn = j;
pEList->a[j].fg.bUsed = 1; pEList->a[j].fg.bUsed = 1;
hit = 1;
if( pEList->a[j].fg.bUsingTerm ) break; if( pEList->a[j].fg.bUsingTerm ) break;
} }
if( hit || zTab==0 ) continue; if( hit || zTab==0 ) continue;
@@ -584,10 +591,10 @@ static int lookupName(
&& pMatch && pMatch
&& (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0 && (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
&& sqlite3IsRowid(zCol) && sqlite3IsRowid(zCol)
&& ALWAYS(VisibleRowid(pMatch->pTab)) && ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom)
){ ){
cnt = 1; cnt = 1;
pExpr->iColumn = -1; if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1;
pExpr->affExpr = SQLITE_AFF_INTEGER; pExpr->affExpr = SQLITE_AFF_INTEGER;
} }

View File

@@ -5284,7 +5284,7 @@ int sqlite3MatchEName(
const char*, const char*,
const char*, const char*,
const char*, const char*,
int int*
); );
Bitmask sqlite3ExprColUsed(Expr*); Bitmask sqlite3ExprColUsed(Expr*);
u8 sqlite3StrIHash(const char*); u8 sqlite3StrIHash(const char*);

View File

@@ -176,6 +176,7 @@ do_execsql_test 8.1 {
SELECT x3.oid FROM x1 JOIN (x2 JOIN x3 ON c='c') SELECT x3.oid FROM x1 JOIN (x2 JOIN x3 ON c='c')
} 43 } 43
breakpoint
do_execsql_test 8.2 { do_execsql_test 8.2 {
SELECT x3.rowid FROM x1 JOIN (x2 JOIN x3 ON c='c') SELECT x3.rowid FROM x1 JOIN (x2 JOIN x3 ON c='c')
} {hello} } {hello}
@@ -195,18 +196,31 @@ do_execsql_test 9.0 {
CREATE TABLE wo1(a PRIMARY KEY, b) WITHOUT ROWID; CREATE TABLE wo1(a PRIMARY KEY, b) WITHOUT ROWID;
CREATE TABLE wo2(a PRIMARY KEY, rowid) 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 { do_catchsql_test 9.1 {
SELECT rowid FROM wo1, x1, x2;
} {1 {no such column: rowid}}
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); SELECT rowid FROM wo1 JOIN (x1 JOIN x2);
} {1 {no such column: rowid}} } {1 {no such column: rowid}}
do_catchsql_test 9.4 {
# Should not be an error. SELECT a FROM wo1, x1, x2;
do_catchsql_test 9.2 { } {1 {ambiguous column name: a}}
do_catchsql_test 9.5 {
SELECT rowid FROM x1 JOIN (x2 JOIN wo2); SELECT rowid FROM x1 JOIN (x2 JOIN wo2);
} {0 {}} } {0 {}}
do_catchsql_test 9.6 {
SELECT _rowid_ FROM wo1 JOIN (wo3 JOIN x3)
} {0 {}}
finish_test finish_test