mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Fixes so that SQLITE_OMIT_CTE builds work.
FossilOrigin-Name: 3908e2ea2e7e5f466cbbbffdc27e0fe8dc9751ac
This commit is contained in:
30
manifest
30
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Further\scomments\son\sWITH-clause\sprocessing\sroutines\sin\sselect.c.
|
C Fixes\sso\sthat\sSQLITE_OMIT_CTE\sbuilds\swork.
|
||||||
D 2014-01-15T18:35:52.482
|
D 2014-01-15T19:42:23.894
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
|
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -175,7 +175,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
|||||||
F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd
|
F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd
|
||||||
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
||||||
F src/delete.c 91e1321021db5dc266360531b8b6550009d771ff
|
F src/delete.c 91e1321021db5dc266360531b8b6550009d771ff
|
||||||
F src/expr.c fccff6c8cd170dc1df244fdd4befb2ec783b72b1
|
F src/expr.c 36c313049a716c3edcdd99d703f0f16ce96a4cc6
|
||||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||||
F src/fkey.c 2ab0f5384b70594468ef3ac5c7ed8ca24bfd17d5
|
F src/fkey.c 2ab0f5384b70594468ef3ac5c7ed8ca24bfd17d5
|
||||||
F src/func.c 6325ac2ec10833ccf4d5c36d323709221d37ea19
|
F src/func.c 6325ac2ec10833ccf4d5c36d323709221d37ea19
|
||||||
@@ -217,14 +217,14 @@ F src/pragma.c ed409ce4104cf4d9de6ead40ace70974f124853b
|
|||||||
F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337
|
F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337
|
||||||
F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269
|
F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269
|
||||||
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
|
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
|
||||||
F src/resolve.c 41d0cf644aa98131204e6243e108829797f038ab
|
F src/resolve.c ae278d8ce037883323f677e78c241f64289f12ec
|
||||||
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
||||||
F src/select.c 6bdb90db59e3e8277b8953e4cd3df01ccc253d70
|
F src/select.c b55e726c8dff607790038bf41e6d47925a832b14
|
||||||
F src/shell.c a3541193d5fce37e91dad8ef46a9505aa7c9b344
|
F src/shell.c a3541193d5fce37e91dad8ef46a9505aa7c9b344
|
||||||
F src/sqlite.h.in d94a8b89522f526ba711182ee161e06f8669bcc9
|
F src/sqlite.h.in d94a8b89522f526ba711182ee161e06f8669bcc9
|
||||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||||
F src/sqliteInt.h d91991457386b4a1414fa96f51a9a5bfd2b8606d
|
F src/sqliteInt.h 6db445ce172c249c29d8f532af64fd7051fe05dd
|
||||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||||
@@ -242,7 +242,7 @@ F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8
|
|||||||
F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
|
F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
|
||||||
F src/test_backup.c 3875e899222b651e18b662f86e0e50daa946344e
|
F src/test_backup.c 3875e899222b651e18b662f86e0e50daa946344e
|
||||||
F src/test_btree.c 5b89601dcb42a33ba8b820a6b763cc9cb48bac16
|
F src/test_btree.c 5b89601dcb42a33ba8b820a6b763cc9cb48bac16
|
||||||
F src/test_config.c 10d0e00dd6315879a6d9fac20bd063c7bbbfb8f8
|
F src/test_config.c 0336e0bdbe541b4af89d7e3dd0656e8e6b51e585
|
||||||
F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9
|
F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9
|
||||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||||
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
|
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
|
||||||
@@ -280,7 +280,7 @@ F src/update.c c2706a6eb232a96345c35b7e1e75a188e26812bb
|
|||||||
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
||||||
F src/util.c e71f19b272f05c8695cf747b4bac1732685f9e5c
|
F src/util.c e71f19b272f05c8695cf747b4bac1732685f9e5c
|
||||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||||
F src/vdbe.c 9b918126afb9a7b7ad232db7453680c7ef5821a4
|
F src/vdbe.c b06d79951a3f0da9cb41cb0aae5fdf5612f718a9
|
||||||
F src/vdbe.h e6c4c610fcabad4fa80ebb1efc6822a9367e2b26
|
F src/vdbe.h e6c4c610fcabad4fa80ebb1efc6822a9367e2b26
|
||||||
F src/vdbeInt.h 42db251e9f863401ff847b90d5fe1614c89a6a56
|
F src/vdbeInt.h 42db251e9f863401ff847b90d5fe1614c89a6a56
|
||||||
F src/vdbeapi.c ce4e68ea4842cc6081046f533d088dcf01d247ad
|
F src/vdbeapi.c ce4e68ea4842cc6081046f533d088dcf01d247ad
|
||||||
@@ -293,7 +293,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
|
|||||||
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
|
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
|
||||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||||
F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
|
F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
|
||||||
F src/where.c 9448a176c10020a4446a8d5e2cdaecf7526e593d
|
F src/where.c 27eb508c4184599a826e2ef3b4319cd28ba2c7af
|
||||||
F src/whereInt.h 96a75c61f1d2b9d4a8e4bb17d89deb0cf7cba358
|
F src/whereInt.h 96a75c61f1d2b9d4a8e4bb17d89deb0cf7cba358
|
||||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
@@ -1091,8 +1091,8 @@ F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
|
|||||||
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
|
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
|
||||||
F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361
|
F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361
|
||||||
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
||||||
F test/with1.test fcd45b0128292d57f4435df873b51b7261edc9ba
|
F test/with1.test 8ac68051fce8f2fe4a7bb6cb7ba62c0e941b1c84
|
||||||
F test/withM.test ac3ec7ee0b33a02d0fa15da91214d97ddea64e34
|
F test/withM.test 52448ce23e1c2ecba79d10e130ee49ce9f9a2a7a
|
||||||
F test/without_rowid1.test aaa26da19d543cd8d3d2d0e686dfa255556c15c8
|
F test/without_rowid1.test aaa26da19d543cd8d3d2d0e686dfa255556c15c8
|
||||||
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
|
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
|
||||||
F test/without_rowid3.test eac3d5c8a1924725b58503a368f2cbd24fd6c8a0
|
F test/without_rowid3.test eac3d5c8a1924725b58503a368f2cbd24fd6c8a0
|
||||||
@@ -1150,7 +1150,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||||
P d9ae0f5d9f8230ca7ca10ebed300e2f6635a0614
|
P c948384dfdd9f68a832d5a452af44f35337f66e7
|
||||||
R de20d9dcfc2fdd09cc5e9c05dc6deb70
|
R 366ade7d6e8c82851813f265ff0c51f5
|
||||||
U drh
|
U dan
|
||||||
Z 626093c1115d7d3f00c431f06f508aa1
|
Z a6417c60f97c097fa8d751079d1185b1
|
||||||
|
@@ -1 +1 @@
|
|||||||
c948384dfdd9f68a832d5a452af44f35337f66e7
|
3908e2ea2e7e5f466cbbbffdc27e0fe8dc9751ac
|
@@ -900,6 +900,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
|
|||||||
** argument. If an OOM condition is encountered, NULL is returned
|
** argument. If an OOM condition is encountered, NULL is returned
|
||||||
** and the db->mallocFailed flag set.
|
** and the db->mallocFailed flag set.
|
||||||
*/
|
*/
|
||||||
|
#ifndef SQLITE_OMIT_CTE
|
||||||
static With *withDup(sqlite3 *db, With *p){
|
static With *withDup(sqlite3 *db, With *p){
|
||||||
With *pRet = 0;
|
With *pRet = 0;
|
||||||
if( p ){
|
if( p ){
|
||||||
@@ -917,6 +918,9 @@ static With *withDup(sqlite3 *db, With *p){
|
|||||||
}
|
}
|
||||||
return pRet;
|
return pRet;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
# define withDup(x,y) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** The following group of routines make deep copies of expressions,
|
** The following group of routines make deep copies of expressions,
|
||||||
|
@@ -503,12 +503,14 @@ lookupname_end:
|
|||||||
sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
|
sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_CTE
|
||||||
/* If this expression reads a column value from a recursive CTE
|
/* If this expression reads a column value from a recursive CTE
|
||||||
** reference, then this is equivalent to reading from the outermost
|
** reference, then this is equivalent to reading from the outermost
|
||||||
** available name-context. */
|
** available name-context. */
|
||||||
if( pMatch && pMatch->isRecursive ){
|
if( pMatch && pMatch->isRecursive ){
|
||||||
while( pNC->pNext ) pNC = pNC->pNext;
|
while( pNC->pNext ) pNC = pNC->pNext;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Increment the nRef value on all name contexts from TopNC up to
|
/* Increment the nRef value on all name contexts from TopNC up to
|
||||||
** the point where the name matched. */
|
** the point where the name matched. */
|
||||||
|
119
src/select.c
119
src/select.c
@@ -1789,6 +1789,7 @@ static int multiSelect(
|
|||||||
goto multi_select_end;
|
goto multi_select_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_CTE
|
||||||
/* If this is a recursive query, check that there is no ORDER BY or
|
/* If this is a recursive query, check that there is no ORDER BY or
|
||||||
** LIMIT clause. Neither of these are supported. */
|
** LIMIT clause. Neither of these are supported. */
|
||||||
assert( p->pOffset==0 || p->pLimit );
|
assert( p->pOffset==0 || p->pLimit );
|
||||||
@@ -1799,13 +1800,6 @@ static int multiSelect(
|
|||||||
goto multi_select_end;
|
goto multi_select_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compound SELECTs that have an ORDER BY clause are handled separately.
|
|
||||||
*/
|
|
||||||
if( p->pOrderBy ){
|
|
||||||
return multiSelectOrderBy(pParse, p, pDest);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_CTE
|
|
||||||
if( p->pRecurse ){
|
if( p->pRecurse ){
|
||||||
int nCol = p->pEList->nExpr;
|
int nCol = p->pEList->nExpr;
|
||||||
int addrNext;
|
int addrNext;
|
||||||
@@ -1838,7 +1832,7 @@ static int multiSelect(
|
|||||||
rc = sqlite3Select(pParse, pPrior, &tmp2dest);
|
rc = sqlite3Select(pParse, pPrior, &tmp2dest);
|
||||||
if( rc ) goto multi_select_end;
|
if( rc ) goto multi_select_end;
|
||||||
|
|
||||||
/* Clear tmp1. Then switch the contents of tmp1 and tmp2. Then teturn
|
/* Clear tmp1. Then switch the contents of tmp1 and tmp2. Then return
|
||||||
** the contents of tmp1 to the caller. Or, if tmp1 is empty at this
|
** the contents of tmp1 to the caller. Or, if tmp1 is empty at this
|
||||||
** point, the recursive query has finished - jump to address iBreak. */
|
** point, the recursive query has finished - jump to address iBreak. */
|
||||||
addrSwap = sqlite3VdbeAddOp2(v, OP_SwapCursors, tmp1, tmp2);
|
addrSwap = sqlite3VdbeAddOp2(v, OP_SwapCursors, tmp1, tmp2);
|
||||||
@@ -1865,6 +1859,12 @@ static int multiSelect(
|
|||||||
}else
|
}else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Compound SELECTs that have an ORDER BY clause are handled separately.
|
||||||
|
*/
|
||||||
|
if( p->pOrderBy ){
|
||||||
|
return multiSelectOrderBy(pParse, p, pDest);
|
||||||
|
}else
|
||||||
|
|
||||||
/* Generate code for the left and right SELECT statements.
|
/* Generate code for the left and right SELECT statements.
|
||||||
*/
|
*/
|
||||||
switch( p->op ){
|
switch( p->op ){
|
||||||
@@ -3482,20 +3482,23 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
|
|||||||
return WRC_Continue;
|
return WRC_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the table identified by FROM clause element p is really
|
#ifndef SQLITE_OMIT_CTE
|
||||||
** a common-table-expression (CTE) then return a pointer to the
|
/*
|
||||||
** CTE definition for that table.
|
** Argument pWith (which may be NULL) points to a linked list of nested
|
||||||
|
** WITH contexts, from inner to outermost. If the table identified by
|
||||||
|
** FROM clause element pItem is really a common-table-expression (CTE)
|
||||||
|
** then return a pointer to the CTE definition for that table. Otherwise
|
||||||
|
** return NULL.
|
||||||
*/
|
*/
|
||||||
static struct Cte *searchWith(Parse *pParse, struct SrcList_item *p){
|
static struct Cte *searchWith(With *pWith, struct SrcList_item *pItem){
|
||||||
if( p->zDatabase==0 ){
|
if( pItem->zDatabase==0 ){
|
||||||
char *zName = p->zName;
|
const char *zName = pItem->zName;
|
||||||
With *pWith;
|
With *p;
|
||||||
|
for(p=pWith; p; p=p->pOuter){
|
||||||
for(pWith=pParse->pWith; pWith; pWith=pWith->pOuter){
|
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i<pWith->nCte; i++){
|
for(i=0; i<p->nCte; i++){
|
||||||
if( sqlite3StrICmp(zName, pWith->a[i].zName)==0 ){
|
if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){
|
||||||
return &pWith->a[i];
|
return &p->a[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3514,15 +3517,15 @@ void sqlite3WithPush(Parse *pParse, With *pWith){
|
|||||||
pParse->pWith = pWith;
|
pParse->pWith = pWith;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void withPop(Parse *pParse, With *pWith){
|
|
||||||
if( pWith ){
|
|
||||||
assert( pParse->pWith==pWith );
|
|
||||||
pParse->pWith = pWith->pOuter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Push or pull a CTE on the stack of all CTEs currently being
|
/*
|
||||||
** coded.
|
** If argument pCte is not NULL, check if it is already a part of the
|
||||||
|
** stack of CTEs stored by the parser. If so, this indicates an illegal
|
||||||
|
** recursive reference in a CTE, set of mutually recursive CTEs. Store
|
||||||
|
** an error in the parser and return SQLITE_ERROR if this is the case.
|
||||||
|
**
|
||||||
|
** Otherwise, if pCte is not already part of the stack of CTEs stored
|
||||||
|
** in the parser, push it onto the stop of that stack.
|
||||||
*/
|
*/
|
||||||
static int ctePush(Parse *pParse, struct Cte *pCte){
|
static int ctePush(Parse *pParse, struct Cte *pCte){
|
||||||
if( pCte ){
|
if( pCte ){
|
||||||
@@ -3541,6 +3544,11 @@ static int ctePush(Parse *pParse, struct Cte *pCte){
|
|||||||
}
|
}
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
** If argument pCte is not NULL, it must be a pointer to the CTE currently
|
||||||
|
** on top of the stack of CTEs stored in the parser. Remove it from that
|
||||||
|
** stack.
|
||||||
|
*/
|
||||||
static void ctePop(Parse *pParse, struct Cte *pCte){
|
static void ctePop(Parse *pParse, struct Cte *pCte){
|
||||||
if( pCte ){
|
if( pCte ){
|
||||||
assert( pParse->pCte==pCte );
|
assert( pParse->pCte==pCte );
|
||||||
@@ -3548,21 +3556,38 @@ static void ctePop(Parse *pParse, struct Cte *pCte){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** This function checks if argument pFrom refers to a CTE declared by
|
||||||
|
** a WITH clause on the stack currently maintained by the parser. And,
|
||||||
|
** if currently processing a CTE expression, if it is a recursive
|
||||||
|
** reference to the current CTE.
|
||||||
|
**
|
||||||
|
** If pFrom falls into either of the two categories above, pFrom->pTab
|
||||||
|
** and other fields are populated accordingly. The caller should check
|
||||||
|
** (pFrom->pTab!=0) to determine whether or not a successful match
|
||||||
|
** was found.
|
||||||
|
**
|
||||||
|
** Whether or not a match is found, SQLITE_OK is returned if no error
|
||||||
|
** occurs. If an error does occur, an error message is stored in the
|
||||||
|
** parser and some error code other than SQLITE_OK returned.
|
||||||
|
*/
|
||||||
static int withExpand(
|
static int withExpand(
|
||||||
Walker *pWalker,
|
Walker *pWalker,
|
||||||
struct SrcList_item *pFrom,
|
struct SrcList_item *pFrom
|
||||||
struct Cte *pCte
|
|
||||||
){
|
){
|
||||||
Table *pTab;
|
Table *pTab;
|
||||||
Parse *pParse = pWalker->pParse;
|
Parse *pParse = pWalker->pParse;
|
||||||
sqlite3 *db = pParse->db;
|
sqlite3 *db = pParse->db;
|
||||||
|
struct Cte *pCte;
|
||||||
|
|
||||||
assert( pFrom->pSelect==0 );
|
|
||||||
assert( pFrom->pTab==0 );
|
assert( pFrom->pTab==0 );
|
||||||
|
|
||||||
if( pCte==pParse->pCte && (pTab = pCte->pTab) ){
|
pCte = searchWith(pParse->pWith, pFrom);
|
||||||
|
if( pCte==0 ){
|
||||||
|
/* no-op */
|
||||||
|
}else if( pCte==pParse->pCte && (pTab = pCte->pTab) ){
|
||||||
/* This is the recursive part of a recursive CTE */
|
/* This is the recursive part of a recursive CTE */
|
||||||
assert( pFrom->pTab==0 && pFrom->isRecursive==0 );
|
assert( pFrom->pTab==0 && pFrom->isRecursive==0 && pFrom->pSelect==0 );
|
||||||
pFrom->pTab = pTab;
|
pFrom->pTab = pTab;
|
||||||
pFrom->isRecursive = 1;
|
pFrom->isRecursive = 1;
|
||||||
pTab->nRef++;
|
pTab->nRef++;
|
||||||
@@ -3623,6 +3648,7 @@ static int withExpand(
|
|||||||
|
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This routine is a Walker callback for "expanding" a SELECT statement.
|
** This routine is a Walker callback for "expanding" a SELECT statement.
|
||||||
@@ -3678,7 +3704,6 @@ static int selectExpander(Walker *pWalker, Select *p){
|
|||||||
** then create a transient table structure to describe the subquery.
|
** then create a transient table structure to describe the subquery.
|
||||||
*/
|
*/
|
||||||
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
|
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
|
||||||
struct Cte *pCte = 0;
|
|
||||||
Table *pTab;
|
Table *pTab;
|
||||||
if( pFrom->pTab!=0 ){
|
if( pFrom->pTab!=0 ){
|
||||||
/* This statement has already been prepared. There is no need
|
/* This statement has already been prepared. There is no need
|
||||||
@@ -3687,10 +3712,8 @@ static int selectExpander(Walker *pWalker, Select *p){
|
|||||||
return WRC_Prune;
|
return WRC_Prune;
|
||||||
}
|
}
|
||||||
#ifndef SQLITE_OMIT_CTE
|
#ifndef SQLITE_OMIT_CTE
|
||||||
pCte = searchWith(pParse, pFrom);
|
if( withExpand(pWalker, pFrom) ) return WRC_Abort;
|
||||||
if( pCte ){
|
if( pFrom->pTab ) {} else
|
||||||
if( withExpand(pWalker, pFrom, pCte) ) return WRC_Abort;
|
|
||||||
}else
|
|
||||||
#endif
|
#endif
|
||||||
if( pFrom->zName==0 ){
|
if( pFrom->zName==0 ){
|
||||||
#ifndef SQLITE_OMIT_SUBQUERY
|
#ifndef SQLITE_OMIT_SUBQUERY
|
||||||
@@ -3917,13 +3940,29 @@ static int selectExpander(Walker *pWalker, Select *p){
|
|||||||
return WRC_Continue;
|
return WRC_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Function (or macro) selectExpanderWith is used as the SELECT callback
|
||||||
|
** by sqlite3SelectExpand(). In builds that do not support CTEs, this
|
||||||
|
** is equivalent to the selectExpander() function. In CTE-enabled builds,
|
||||||
|
** any WITH clause associated with the SELECT statement needs to be
|
||||||
|
** pushed onto the stack before calling selectExpander(), and popped
|
||||||
|
** off again afterwards.
|
||||||
|
*/
|
||||||
|
#ifndef SQLITE_OMIT_CTE
|
||||||
static int selectExpanderWith(Walker *pWalker, Select *p){
|
static int selectExpanderWith(Walker *pWalker, Select *p){
|
||||||
|
Parse *pParse = pWalker->pParse;
|
||||||
int res;
|
int res;
|
||||||
sqlite3WithPush(pWalker->pParse, p->pWith);
|
sqlite3WithPush(pParse, p->pWith);
|
||||||
res = selectExpander(pWalker, p);
|
res = selectExpander(pWalker, p);
|
||||||
withPop(pWalker->pParse, p->pWith);
|
if( p->pWith ){
|
||||||
|
assert( pParse->pWith==p->pWith );
|
||||||
|
pParse->pWith = p->pWith->pOuter;
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#define selectExpanderWith selectExpander
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** No-op routine for the parse-tree walker.
|
** No-op routine for the parse-tree walker.
|
||||||
|
@@ -3359,6 +3359,7 @@ const char *sqlite3JournalModename(int);
|
|||||||
void sqlite3WithPush(Parse*, With*);
|
void sqlite3WithPush(Parse*, With*);
|
||||||
#else
|
#else
|
||||||
#define sqlite3WithPush(x,y)
|
#define sqlite3WithPush(x,y)
|
||||||
|
#define sqlite3WithDelete(x,y)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Declarations for functions in fkey.c. All of these are replaced by
|
/* Declarations for functions in fkey.c. All of these are replaced by
|
||||||
|
@@ -225,6 +225,12 @@ static void set_options(Tcl_Interp *interp){
|
|||||||
Tcl_SetVar2(interp, "sqlite_options", "check", "1", TCL_GLOBAL_ONLY);
|
Tcl_SetVar2(interp, "sqlite_options", "check", "1", TCL_GLOBAL_ONLY);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SQLITE_OMIT_CTE
|
||||||
|
Tcl_SetVar2(interp, "sqlite_options", "cte", "0", TCL_GLOBAL_ONLY);
|
||||||
|
#else
|
||||||
|
Tcl_SetVar2(interp, "sqlite_options", "cte", "1", TCL_GLOBAL_ONLY);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||||
Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "1", TCL_GLOBAL_ONLY);
|
Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "1", TCL_GLOBAL_ONLY);
|
||||||
#else
|
#else
|
||||||
|
@@ -3369,6 +3369,7 @@ case OP_OpenEphemeral: {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_CTE
|
||||||
/* Opcode: OpenEphreader P1 P2 * * *
|
/* Opcode: OpenEphreader P1 P2 * * *
|
||||||
**
|
**
|
||||||
** P2 is a cursor opened by the OpenEphemeral opcode. This opcode opens
|
** P2 is a cursor opened by the OpenEphemeral opcode. This opcode opens
|
||||||
@@ -3415,6 +3416,7 @@ case OP_SwapCursors: {
|
|||||||
rc = sqlite3BtreeClearTable(pTmp->pBt, MASTER_ROOT + !pTmp->isTable, 0);
|
rc = sqlite3BtreeClearTable(pTmp->pBt, MASTER_ROOT + !pTmp->isTable, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif /* ifndef SQLITE_OMIT_CTE */
|
||||||
|
|
||||||
/* Opcode: SorterOpen P1 * * P4 *
|
/* Opcode: SorterOpen P1 * * P4 *
|
||||||
**
|
**
|
||||||
|
@@ -5654,10 +5654,12 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||||
pLoop = pLevel->pWLoop;
|
pLoop = pLevel->pWLoop;
|
||||||
if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
|
if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
|
||||||
|
#ifndef SQLITE_OMIT_CTE
|
||||||
if( pTab->tabFlags & TF_Recursive ){
|
if( pTab->tabFlags & TF_Recursive ){
|
||||||
int iCur = pTabItem->iCursor;
|
int iCur = pTabItem->iCursor;
|
||||||
sqlite3VdbeAddOp2(v, OP_OpenEphreader, iCur, pTab->tnum);
|
sqlite3VdbeAddOp2(v, OP_OpenEphreader, iCur, pTab->tnum);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/* Otherwise do nothing */
|
/* Otherwise do nothing */
|
||||||
}else
|
}else
|
||||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||||
|
@@ -16,6 +16,11 @@ set testdir [file dirname $argv0]
|
|||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
set ::testprefix with1
|
set ::testprefix with1
|
||||||
|
|
||||||
|
ifcapable {!cte} {
|
||||||
|
finish_test
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
do_execsql_test 1.0 {
|
do_execsql_test 1.0 {
|
||||||
CREATE TABLE t1(x INTEGER, y INTEGER);
|
CREATE TABLE t1(x INTEGER, y INTEGER);
|
||||||
WITH x(a) AS ( SELECT * FROM t1) SELECT 10
|
WITH x(a) AS ( SELECT * FROM t1) SELECT 10
|
||||||
|
@@ -17,6 +17,11 @@ source $testdir/tester.tcl
|
|||||||
source $testdir/malloc_common.tcl
|
source $testdir/malloc_common.tcl
|
||||||
set ::testprefix withM
|
set ::testprefix withM
|
||||||
|
|
||||||
|
ifcapable {!cte} {
|
||||||
|
finish_test
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
do_execsql_test 1.0 {
|
do_execsql_test 1.0 {
|
||||||
CREATE TABLE t1(x INTEGER, y INTEGER);
|
CREATE TABLE t1(x INTEGER, y INTEGER);
|
||||||
INSERT INTO t1 VALUES(123, 456);
|
INSERT INTO t1 VALUES(123, 456);
|
||||||
|
Reference in New Issue
Block a user