diff --git a/manifest b/manifest index 3d4a6ad897..1f819eb388 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Use\sthe\suser-supplied\stable\sname\sin\sWITH\sRECURSIVE\stables\sas\sthe\sinternal\nname\sof\sthe\stable\sand\sthe\sname\sof\sthe\stable\sin\sVDBE\scomments. -D 2014-01-15T02:40:11.688 +C Disable\sthe\sflattening\soptimization\sif\sthe\ssub-query\sis\sa\srecursive\sCTE. +D 2014-01-15T14:17:31.048 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -175,7 +175,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 F src/delete.c 91e1321021db5dc266360531b8b6550009d771ff -F src/expr.c fee4b54fdcf5a979e6f5012da3dfb084ac5d3aac +F src/expr.c 2277282d8938b8eab782e4f5111ca0cd492529b3 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 2ab0f5384b70594468ef3ac5c7ed8ca24bfd17d5 F src/func.c 6325ac2ec10833ccf4d5c36d323709221d37ea19 @@ -209,7 +209,7 @@ F src/os_unix.c 3a4dcb554d3c915075766162f28c3fd4cdb75968 F src/os_win.c 16eac0961603182ffc10c02b39fe830126538e07 F src/pager.c efa923693e958696eee69b205a20bfbc402c8480 F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428 -F src/parse.y e5c4a23f445cde4b30d50948df8f21bc586dd7a4 +F src/parse.y 824eeb752c026b551bda2b66163889d7664b42e4 F src/pcache.c f8043b433a57aba85384a531e3937a804432a346 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c 57fee9a9a617218f5037afbbe49b09da65bde56b @@ -219,7 +219,7 @@ F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c 7eda9097b29fcf3d2b42fdc17d1de672134e09b6 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 -F src/select.c 3d93e3b4736a95507540b708106c1db6d01c41a8 +F src/select.c 51c74176eb949d1ff5797735acedd6c08d19450a F src/shell.c a3541193d5fce37e91dad8ef46a9505aa7c9b344 F src/sqlite.h.in d94a8b89522f526ba711182ee161e06f8669bcc9 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e @@ -1091,7 +1091,7 @@ F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361 F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d -F test/with1.test 12a6661eabcc9ae299020f7b4197a75a9c084748 +F test/with1.test 77739a9e5e88873e7655634297d9dc4360334f9a F test/withM.test ac3ec7ee0b33a02d0fa15da91214d97ddea64e34 F test/without_rowid1.test aaa26da19d543cd8d3d2d0e686dfa255556c15c8 F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99 @@ -1150,7 +1150,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P a5c2a54a07d35166911abc792008c05dea897742 -R cc1fc541222b981017b72fc3aee14bde -U drh -Z dcce44e449a071e984cc874f0c8e1e54 +P a29330238be6366444269a0b1b328475b2d01ae2 +R baaf1d38169072daf03c7e43cc689f3b +U dan +Z e4d26324d0deafbbb1cfbafb0f22db9f diff --git a/manifest.uuid b/manifest.uuid index 1be3de1308..493b55e692 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a29330238be6366444269a0b1b328475b2d01ae2 \ No newline at end of file +9472f6d820a7fb233936d9b8f7a39c9d4c4d6d73 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index e271e46796..4da9d6263c 100644 --- a/src/expr.c +++ b/src/expr.c @@ -895,7 +895,12 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ return pNew; } -With *withDup(sqlite3 *db, With *p){ +/* +** Create and return a deep copy of the object passed as the second +** argument. If an OOM condition is encountered, NULL is returned +** and the db->mallocFailed flag set. +*/ +static With *withDup(sqlite3 *db, With *p){ With *pRet = 0; if( p ){ int nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1); @@ -1055,7 +1060,8 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ pNew->addrOpenEphm[1] = -1; pNew->addrOpenEphm[2] = -1; pNew->pWith = withDup(db, p->pWith); - pNew->pRecurse = p->pRecurse; + assert( p->pRecurse==0 ); + pNew->pRecurse = 0; return pNew; } #else diff --git a/src/parse.y b/src/parse.y index b1992f2415..937669eb5c 100644 --- a/src/parse.y +++ b/src/parse.y @@ -684,8 +684,9 @@ where_opt(A) ::= WHERE expr(X). {A = X.pExpr;} ////////////////////////// The UPDATE command //////////////////////////////// // %ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT -cmd ::= with UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y) +cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y) where_opt(W) orderby_opt(O) limit_opt(L). { + sqlite3WithPush(pParse, C); sqlite3SrcListIndexedBy(pParse, X, &I); sqlite3ExprListCheckLength(pParse,Y,"set list"); W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "UPDATE"); diff --git a/src/select.c b/src/select.c index 22eaf1b1cb..35edcbb03c 100644 --- a/src/select.c +++ b/src/select.c @@ -2844,6 +2844,8 @@ static void substSelect( ** ** Flattening is only attempted if all of the following are true: ** +** (0) The subquery is not a recursive CTE. +** ** (1) The subquery and the outer query do not both use aggregates. ** ** (2) The subquery is not an aggregate or the outer query is not a join. @@ -2968,6 +2970,7 @@ static int flattenSubquery( iParent = pSubitem->iCursor; pSub = pSubitem->pSelect; assert( pSub!=0 ); + if( pSub->pRecurse ) return 0; /* Restriction (0) */ if( isAgg && subqueryIsAgg ) return 0; /* Restriction (1) */ if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; /* Restriction (2) */ pSubSrc = pSub->pSrc; diff --git a/test/with1.test b/test/with1.test index 3dd8c47ea2..480afa8074 100644 --- a/test/with1.test +++ b/test/with1.test @@ -164,6 +164,50 @@ do_execsql_test 5.5 { SELECT x FROM i LIMIT 20; } {1 2 3 4 5 6 7 8 9 0} +#------------------------------------------------------------------------- +# +do_execsql_test 6.1 { + CREATE TABLE f( + id INTEGER PRIMARY KEY, parentid REFERENCES f, name TEXT + ); + + INSERT INTO f VALUES(0, NULL, ''); + INSERT INTO f VALUES(1, 0, 'bin'); + INSERT INTO f VALUES(2, 1, 'true'); + INSERT INTO f VALUES(3, 1, 'false'); + INSERT INTO f VALUES(4, 1, 'ls'); + INSERT INTO f VALUES(5, 1, 'grep'); + INSERT INTO f VALUES(6, 0, 'etc'); + INSERT INTO f VALUES(7, 6, 'rc.d'); + INSERT INTO f VALUES(8, 7, 'rc.apache'); + INSERT INTO f VALUES(9, 7, 'rc.samba'); + INSERT INTO f VALUES(10, 0, 'home'); + INSERT INTO f VALUES(11, 10, 'dan'); + INSERT INTO f VALUES(12, 11, 'public_html'); + INSERT INTO f VALUES(13, 12, 'index.html'); + INSERT INTO f VALUES(14, 13, 'logo.gif'); +} + +do_execsql_test 6.2 { + WITH flat(fid, fpath) AS ( + SELECT id, '' FROM f WHERE parentid IS NULL + UNION ALL + SELECT id, fpath || '/' || name FROM f, flat WHERE +parentid=+fid + ) + SELECT fpath FROM flat WHERE fpath!='' ORDER BY 1; +} { + /bin + /bin/false /bin/grep /bin/ls /bin/true + /etc + /etc/rc.d + /etc/rc.d/rc.apache /etc/rc.d/rc.samba + /home + /home/dan + /home/dan/public_html + /home/dan/public_html/index.html + /home/dan/public_html/index.html/logo.gif +} + finish_test