From: dan Date: Fri, 11 Jun 2021 11:14:24 +0000 (+0000) Subject: Fix problems with ALTER TABLE and schemas that contain views with some recursive... X-Git-Tag: version-3.36.0~26 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=26d61e5adfbc9e1a3955d1fb04a5f5f06ebfdb13;p=thirdparty%2Fsqlite.git Fix problems with ALTER TABLE and schemas that contain views with some recursive CTEs, or CTEs that reference other CTEs. FossilOrigin-Name: 8b1f9a51e962cd9a5593a1ecf4da6c86e34c4f9ff96ffcea0fb421880c8836cb --- diff --git a/manifest b/manifest index 5e3b293dd7..b9d1b407de 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\srobustness\sfollowing\sOOM\sin\sthe\sconstant\spropagation\soptimization.\ndbsqlfuzz\s001a20255c0df7495c21df62a20ea5b51e22c390. -D 2021-06-10T14:36:23.869 +C Fix\sproblems\swith\sALTER\sTABLE\sand\sschemas\sthat\scontain\sviews\swith\ssome\srecursive\sCTEs,\sor\sCTEs\sthat\sreference\sother\sCTEs. +D 2021-06-11T11:14:24.212 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -478,7 +478,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c 2cb4a3d15cfee6a8a631bbf35943421312addaee36ed171aafe1a88de8ada060 +F src/alter.c 3de695d859627b1a80f673c16155260a12af310b5853012da411f81e6f4442a4 F src/analyze.c 01c6c6765cb4d40b473b71d85535093730770bb186f2f473abac25f07fcdee5c F src/attach.c a514e81758ba7b3a3a0501faf70af6cfc509de8810235db726cfc9f25165e929 F src/auth.c 08954fdc4cc2da5264ba5b75cfd90b67a6fc7d1710a02ccf917c38eadec77853 @@ -496,7 +496,7 @@ F src/date.c e0632f335952b32401482d099321bbf12716b29d6e72836b53ae49683ebae4bf F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbstat.c 3aa79fc3aed7ce906e4ea6c10e85d657299e304f6049861fe300053ac57de36c F src/delete.c 930e63df768dcb197242b1efa0ed9fcdcc9a7b7556c236ee01a9959b61cf527b -F src/expr.c 57534c739e1280de1cef333a4dc4c42ac1f8524acb71b715ae21406bf4363f57 +F src/expr.c 30a2abf526531ce6bd45fbc85bfec0fc3f6e5a0fb490cd2350855f2fc34dd789 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c e9063648396c58778f77583a678342fe4a9bc82436bf23c5f9f444f2df0fdaa4 F src/func.c 88fd711754a7241cb9f8eb1391370fd0c0cea756b3358efa274c5d1efd59af93 @@ -549,7 +549,7 @@ F src/shell.c.in a4bc0e2ba9be798e293790f354dcc0099c6370127eec18cf49cb161b9dae2fb F src/sqlite.h.in f450394634eac00bc680c0e91582b818359c6ad61149f49f90fb6ecbd526b51f F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e -F src/sqliteInt.h 61f717ac4242af975c6d8abc11a3ada6153ad5bfb7ce08ef8a443c01e13c8031 +F src/sqliteInt.h c33a2734081287541a8356d2f2e6764c1b9f9c9d1635e8233084205ea7f11f65 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -658,7 +658,7 @@ F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74 F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b F test/altermalloc3.test 059841a3de6b6780efd9f0b30bf1d9b4443c555f68d39975cbcac2583167b239 F test/alterqf.test 67568ad152db8c1187b15633b801242cf960f1beafc51261a3d1725d910baeb2 -F test/altertab.test a96e2169bbb2c5a754b0ddac8a396e15b4ad6f34a5fbf6fbfad76bdfb339479f +F test/altertab.test 4120b9b2baa96ef2b0aaf4dd46b1858171503edf5e346b5ce939c73b4d314fa6 F test/altertab2.test b0d62f323ca5dab42b0bc028c52e310ebdd13e655e8fac070fe622bad7852c2b F test/altertab3.test 2b82fa2236a3a91553d53ae5555d8e723c7eec174c41f1fa62ff497355398479 F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f @@ -1918,7 +1918,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 56ff58c0b8905aa10c85f1418da8d6089d23fd9a220c5cb17027d46affe05002 -R 18566ccb2436921d616b19510604cebd -U drh -Z c0637a6bda27d46672c1c58f8de8002f +P 8658a64d414db6900b55281f5e67180ea74b82627199b927634a727ed28030c2 +R 3e7137855bcb4cdf964662c585c92d6f +U dan +Z 5e06bfe97c02741d63caecdb97ff3417 diff --git a/manifest.uuid b/manifest.uuid index 8d2cf0705d..dd936d5176 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8658a64d414db6900b55281f5e67180ea74b82627199b927634a727ed28030c2 \ No newline at end of file +8b1f9a51e962cd9a5593a1ecf4da6c86e34c4f9ff96ffcea0fb421880c8836cb \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 744b75ea8b..de0dd4e4d4 100644 --- a/src/alter.c +++ b/src/alter.c @@ -800,15 +800,30 @@ static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){ static void renameWalkWith(Walker *pWalker, Select *pSelect){ With *pWith = pSelect->pWith; if( pWith ){ + Parse *pParse = pWalker->pParse; int i; + With *pCopy = 0; + assert( pWith->nCte>0 ); + if( (pWith->a[0].pSelect->selFlags & SF_Expanded)==0 ){ + /* Push a copy of the With object onto the with-stack. We use a copy + ** here as the original will be expanded and resolved (flags SF_Expanded + ** and SF_Resolved) below. And the parser code that uses the with-stack + ** fails if the Select objects on it have already been expanded and + ** resolved. */ + pCopy = sqlite3WithDup(pParse->db, pWith); + sqlite3WithPush(pParse, pCopy, 1); + } for(i=0; inCte; i++){ Select *p = pWith->a[i].pSelect; NameContext sNC; memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pWalker->pParse; - sqlite3SelectPrep(sNC.pParse, p, &sNC); + sNC.pParse = pParse; + if( pCopy ) sqlite3SelectPrep(sNC.pParse, p, &sNC); sqlite3WalkSelect(pWalker, p); - sqlite3RenameExprlistUnmap(pWalker->pParse, pWith->a[i].pCols); + sqlite3RenameExprlistUnmap(pParse, pWith->a[i].pCols); + } + if( pCopy && pParse->pWith==pCopy ){ + pParse->pWith = pCopy->pOuter; } } } diff --git a/src/expr.c b/src/expr.c index 0a57d745e1..b751f51a6d 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1413,7 +1413,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){ ** and the db->mallocFailed flag set. */ #ifndef SQLITE_OMIT_CTE -static With *withDup(sqlite3 *db, With *p){ +With *sqlite3WithDup(sqlite3 *db, With *p){ With *pRet = 0; if( p ){ sqlite3_int64 nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1); @@ -1431,7 +1431,7 @@ static With *withDup(sqlite3 *db, With *p){ return pRet; } #else -# define withDup(x,y) 0 +# define sqlite3WithDup(x,y) 0 #endif #ifndef SQLITE_OMIT_WINDOWFUNC @@ -1635,7 +1635,7 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){ pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; pNew->nSelectRow = p->nSelectRow; - pNew->pWith = withDup(db, p->pWith); + pNew->pWith = sqlite3WithDup(db, p->pWith); #ifndef SQLITE_OMIT_WINDOWFUNC pNew->pWin = 0; pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 806a1a3395..ad857ab03b 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4576,6 +4576,7 @@ void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*); int sqlite3SafetyCheckOk(sqlite3*); int sqlite3SafetyCheckSickOrOk(sqlite3*); void sqlite3ChangeCookie(Parse*, int); +With *sqlite3WithDup(sqlite3 *db, With *p); #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int); diff --git a/test/altertab.test b/test/altertab.test index dacc5ab0e7..8742c1769a 100644 --- a/test/altertab.test +++ b/test/altertab.test @@ -793,20 +793,80 @@ do_execsql_test 27.2 { alter table t_sa rename column c_muyat to c_dg; } +#------------------------------------------------------------------------- +reset_db +do_execsql_test 29.1 { + CREATE TABLE t1(a, b, c); + INSERT INTO t1 VALUES('a', 'b', 'c'); + + CREATE VIEW v0 AS + WITH p AS ( SELECT 1 FROM t1 ), + g AS ( SELECT 1 FROM p, t1 ) + SELECT 1 FROM g; +} + +do_execsql_test 29.2 { + SELECT * FROM v0 +} 1 + +do_execsql_test 29.2 { + ALTER TABLE t1 RENAME TO t2 +} + +do_execsql_test 29.3 { + SELECT sql FROM sqlite_schema WHERE name='v0' +} {{CREATE VIEW v0 AS + WITH p AS ( SELECT 1 FROM "t2" ), + g AS ( SELECT 1 FROM p, "t2" ) + SELECT 1 FROM g}} + +do_execsql_test 29.4 { + CREATE VIEW v2 AS + WITH p AS ( SELECT 1 FROM t2 ), + g AS ( SELECT 1 FROM ( + WITH i AS (SELECT 1 FROM p, t2) + SELECT * FROM i + ) + ) + SELECT 1 FROM g; +} + +do_execsql_test 29.4 { + SELECT * FROM v2; +} 1 + +do_execsql_test 29.5 { + ALTER TABLE t2 RENAME TO t3; +} + +do_execsql_test 29.5 { + SELECT sql FROM sqlite_schema WHERE name='v2' +} {{CREATE VIEW v2 AS + WITH p AS ( SELECT 1 FROM "t3" ), + g AS ( SELECT 1 FROM ( + WITH i AS (SELECT 1 FROM p, "t3") + SELECT * FROM i + ) + ) + SELECT 1 FROM g}} + + #------------------------------------------------------------------------- reset_db do_execsql_test 28.1 { CREATE TABLE t1(a); CREATE TABLE t2(b,c); + CREATE TABLE t4(b,c); INSERT INTO t2 VALUES(1,2),(1,3),(2,5); + INSERT INTO t4 VALUES(1,2),(1,3),(2,5); + CREATE VIEW v3 AS WITH RECURSIVE t3(x,y,z) AS ( - SELECT b,c,NULL FROM t2 + SELECT b,c,NULL FROM t4 UNION - SELECT x,y,NULL FROM t3, t2 WHERE b=x - ORDER BY y + SELECT x,y,NULL FROM t3, t2 ) - SELECT * FROM t3; + SELECT * FROM t3 AS xyz; } do_execsql_test 28.2 { @@ -819,4 +879,74 @@ do_execsql_test 28.3 { ALTER TABLE t1 RENAME a TO a2; -- fails in v3 } +do_execsql_test 28.4 { + ALTER TABLE t2 RENAME TO t5; +} + +do_execsql_test 28.5 { + SELECT sql FROM sqlite_schema WHERE name='v3' +} {{CREATE VIEW v3 AS + WITH RECURSIVE t3(x,y,z) AS ( + SELECT b,c,NULL FROM t4 + UNION + SELECT x,y,NULL FROM t3, "t5" + ) + SELECT * FROM t3 AS xyz}} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 30.0 { + CREATE TABLE t1(a,b,c,d,e,f); + CREATE TABLE t2(a,b,c); + CREATE INDEX t1abc ON t1(a,b,c+d+e); + CREATE VIEW v1(x,y) AS + SELECT t1.b,t2.b FROM t1,t2 WHERE t1.a=t2.a + GROUP BY 1 HAVING t2.c NOT NULL LIMIT 10; + CREATE TRIGGER r1 AFTER INSERT ON t1 WHEN 'no' NOT NULL BEGIN + INSERT INTO t2(a,a,b,c) VALUES(new.b,new.a,new.c-7); + WITH c1(x) AS ( + VALUES(0) + UNION ALL + SELECT current_time+x FROM c1 WHERE x + UNION ALL + SELECT 1+x FROM c1 WHERE x<1 + ), c2(x) AS (VALUES(0),(1)) + SELECT * FROM c1 AS x1, c2 AS x2, ( + SELECT x+1 FROM c1 WHERE x IS NOT TRUE + UNION ALL + SELECT 1+x FROM c1 WHERE 1