Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 532359e4e0 | |||
| ce365d6b7e |
@@ -31,4 +31,5 @@ END {
|
||||
printf "#define TK_%-29s %4d\n", "UMINUS", ++max
|
||||
printf "#define TK_%-29s %4d\n", "UPLUS", ++max
|
||||
printf "#define TK_%-29s %4d\n", "REGISTER", ++max
|
||||
printf "#define TK_%-29s %4d\n", "LEVEL", ++max
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
C In\swhere.c,\sdo\snot\sallocate\sspace\sin\ssqlite3_index_info\sstructures\sfor\sthe\sinternal\sWHERE\sclause\s"terms"\sgenerated\sto\srecord\scolumn\sequivalencies.
|
||||
D 2014-01-20T19:55:33.120
|
||||
C Fix\sa\scouple\scomment\stypos\sand\sone\soverly\slong\sline.\s\sNo\sfunctional\schanges.
|
||||
D 2014-01-21T01:13:45.746
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@@ -8,7 +8,7 @@ F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315
|
||||
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
|
||||
F VERSION 8ed548d87d0a27fd7d7620476f9e25f9fa742d73
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811
|
||||
F addopcodes.awk 9d87688069e97afd397035613fe5822408a0914e
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
|
||||
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
@@ -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 8c7e482bc8f7982333f046851a610ccdb8a1ba94
|
||||
F src/expr.c 1c954bc76bfefa7391bcd2ebe77b9c0fff0eccb8
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 2ab0f5384b70594468ef3ac5c7ed8ca24bfd17d5
|
||||
F src/func.c 6325ac2ec10833ccf4d5c36d323709221d37ea19
|
||||
@@ -217,14 +217,14 @@ F src/pragma.c ed409ce4104cf4d9de6ead40ace70974f124853b
|
||||
F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337
|
||||
F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269
|
||||
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
|
||||
F src/resolve.c 7eda9097b29fcf3d2b42fdc17d1de672134e09b6
|
||||
F src/resolve.c 3e22bf604677036d4aed6ddb91705c37938be4c5
|
||||
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
||||
F src/select.c a27ac21844df3123b7c1e89d79cd7034d4eb0e8e
|
||||
F src/select.c a2709e1b91731d65bc0839974ff95cdc58cd81bd
|
||||
F src/shell.c 9f3bc02a658b8f61d2cbe60cfc482f660c1c6c48
|
||||
F src/sqlite.h.in eed7f7d66a60daaa7b4a597dcd9bad87aad9611b
|
||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h 99fd628541e420b98fc52072635e8ba431706250
|
||||
F src/sqliteInt.h bd0ae72872841059d55f928c330c2c53efff509f
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
@@ -1094,6 +1094,7 @@ F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361
|
||||
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
||||
F test/with1.test cec63b56797a70842afa8929c241dfdb3d864283
|
||||
F test/with2.test 2fe78fcd8deef2a0f9cfc49bfc755911d0b3fd64
|
||||
F test/with3.test e302761b7bf3a9b5e66afa62f763f2719f8fe8ba
|
||||
F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
|
||||
F test/without_rowid1.test aaa26da19d543cd8d3d2d0e686dfa255556c15c8
|
||||
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
|
||||
@@ -1152,7 +1153,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 eba8a564e62f84a9620008beead80081fe90a1b7
|
||||
R c774305f58a7e7fff71d714265811a28
|
||||
U dan
|
||||
Z 8e05aa582afc8018a3754b6d40d97300
|
||||
P cc1cb3217800ff666a00bf4f544a5a477589bc1b
|
||||
R d7b88acbea11aa8a9631e3e1df1ea620
|
||||
U mistachkin
|
||||
Z 3b56f57b80b503ffdcf535e8f4844624
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
7d9e22187daaa3160b875a1df17b924969bf718e
|
||||
c57deced09c67085852eb17d4f6f881416daf24c
|
||||
@@ -2458,6 +2458,12 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
pExpr->op2);
|
||||
break;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_CTE
|
||||
case TK_LEVEL: {
|
||||
inReg = pParse->regLevel;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case TK_INTEGER: {
|
||||
codeInteger(pParse, pExpr, 0, target);
|
||||
break;
|
||||
@@ -3081,6 +3087,7 @@ int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
|
||||
pExpr = sqlite3ExprSkipCollate(pExpr);
|
||||
if( ConstFactorOk(pParse)
|
||||
&& pExpr->op!=TK_REGISTER
|
||||
&& pExpr->op!=TK_LEVEL
|
||||
&& sqlite3ExprIsConstantNotJoin(pExpr)
|
||||
){
|
||||
ExprList *p = pParse->pConstExpr;
|
||||
|
||||
+29
-4
@@ -226,7 +226,7 @@ static int lookupName(
|
||||
struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
|
||||
NameContext *pTopNC = pNC; /* First namecontext in the list */
|
||||
Schema *pSchema = 0; /* Schema of the expression */
|
||||
int isTrigger = 0; /* True if resolved to a trigger column */
|
||||
u8 newOp = TK_COLUMN; /* pExpr->op after resolving name */
|
||||
Table *pTab = 0; /* Table hold the row */
|
||||
Column *pCol; /* A column of pTab */
|
||||
|
||||
@@ -267,6 +267,26 @@ static int lookupName(
|
||||
ExprList *pEList;
|
||||
SrcList *pSrcList = pNC->pSrcList;
|
||||
|
||||
#ifndef SQLITE_OMIT_CTE
|
||||
/* The identifier "LEVEL", without a table or database qualifier and
|
||||
** within a recursive common table expression, resolves to the special
|
||||
** LEVEL pseudo-column. To access table names called "level", add a
|
||||
** table qualifier.
|
||||
*/
|
||||
if( (pNC->ncFlags&NC_Recursive)!=0
|
||||
&& zTab==0
|
||||
&& sqlite3_stricmp(zCol,"level")==0
|
||||
){
|
||||
assert( cnt==0 );
|
||||
cnt = 1;
|
||||
newOp = TK_LEVEL;
|
||||
pExpr->iColumn = -1;
|
||||
pExpr->affinity = SQLITE_AFF_INTEGER;
|
||||
pNC->ncFlags |= NC_UsesLevel;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( pSrcList ){
|
||||
for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
|
||||
pTab = pItem->pTab;
|
||||
@@ -371,7 +391,7 @@ static int lookupName(
|
||||
}
|
||||
pExpr->iColumn = (i16)iCol;
|
||||
pExpr->pTab = pTab;
|
||||
isTrigger = 1;
|
||||
newOp = TK_TRIGGER;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -495,11 +515,11 @@ static int lookupName(
|
||||
pExpr->pLeft = 0;
|
||||
sqlite3ExprDelete(db, pExpr->pRight);
|
||||
pExpr->pRight = 0;
|
||||
pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN);
|
||||
pExpr->op = newOp;
|
||||
lookupname_end:
|
||||
if( cnt==1 ){
|
||||
assert( pNC!=0 );
|
||||
if( pExpr->op!=TK_AS ){
|
||||
if( pExpr->op!=TK_AS && pExpr->op!=TK_LEVEL ){
|
||||
sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
|
||||
}
|
||||
/* Increment the nRef value on all name contexts from TopNC up to
|
||||
@@ -1196,6 +1216,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
** resolve the result-set expression list.
|
||||
*/
|
||||
sNC.ncFlags = NC_AllowAgg;
|
||||
if( p->selFlags & SF_Recursive ) sNC.ncFlags |= NC_Recursive;
|
||||
sNC.pSrcList = p->pSrc;
|
||||
sNC.pNext = pOuterNC;
|
||||
|
||||
@@ -1274,6 +1295,10 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
}
|
||||
}
|
||||
}
|
||||
if( sNC.ncFlags & NC_UsesLevel ){
|
||||
p->selFlags |= SF_UsesLevel;
|
||||
}
|
||||
sNC.ncFlags &= ~(NC_Recursive|NC_UsesLevel);
|
||||
|
||||
/* Advance to the next term of the compound
|
||||
*/
|
||||
|
||||
+17
-2
@@ -1792,8 +1792,8 @@ static int multiSelect(
|
||||
|
||||
#ifndef SQLITE_OMIT_CTE
|
||||
if( p->selFlags & SF_Recursive ){
|
||||
SrcList *pSrc = p->pSrc;
|
||||
int nCol = p->pEList->nExpr;
|
||||
SrcList *pSrc = p->pSrc; /* The FROM clause of the right-most SELECT */
|
||||
int nCol = p->pEList->nExpr; /* Number of columns in the result set */
|
||||
int addrNext;
|
||||
int addrSwap;
|
||||
int iCont, iBreak;
|
||||
@@ -1803,6 +1803,8 @@ static int multiSelect(
|
||||
int eDest = SRT_Table;
|
||||
SelectDest tmp2dest;
|
||||
int i;
|
||||
int regLevel = 0; /* Register for LEVEL value */
|
||||
int savedRegLevel; /* Saved value of pParse->regLevel */
|
||||
|
||||
/* Check that there is no ORDER BY or LIMIT clause. Neither of these
|
||||
** are supported on recursive queries. */
|
||||
@@ -1845,6 +1847,14 @@ static int multiSelect(
|
||||
rc = sqlite3Select(pParse, pPrior, &tmp2dest);
|
||||
if( rc ) goto multi_select_end;
|
||||
|
||||
/* Allocate and initialize a register to hold the LEVEL pseudo-column */
|
||||
savedRegLevel = pParse->regLevel;
|
||||
if( p->selFlags & SF_UsesLevel ){
|
||||
regLevel = pParse->regLevel = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, regLevel);
|
||||
VdbeComment((v, "level=0"));
|
||||
}
|
||||
|
||||
/* 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
|
||||
** point, the recursive query has finished - jump to address iBreak. */
|
||||
@@ -1855,6 +1865,10 @@ static int multiSelect(
|
||||
0, 0, &dest, iCont, iBreak);
|
||||
sqlite3VdbeResolveLabel(v, iCont);
|
||||
sqlite3VdbeAddOp2(v, OP_Next, tmp1, addrNext);
|
||||
if( regLevel ){
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, regLevel, 1);
|
||||
VdbeComment((v, "level++"));
|
||||
}
|
||||
|
||||
/* Execute the recursive SELECT. Store the results in tmp2. While this
|
||||
** SELECT is running, the contents of tmp1 are read by recursive
|
||||
@@ -1867,6 +1881,7 @@ static int multiSelect(
|
||||
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrSwap);
|
||||
sqlite3VdbeResolveLabel(v, iBreak);
|
||||
pParse->regLevel = savedRegLevel;
|
||||
}else
|
||||
#endif
|
||||
|
||||
|
||||
@@ -2107,6 +2107,8 @@ struct NameContext {
|
||||
#define NC_IsCheck 0x04 /* True if resolving names in a CHECK constraint */
|
||||
#define NC_InAggFunc 0x08 /* True if analyzing arguments to an agg func */
|
||||
#define NC_PartIdx 0x10 /* True if resolving a partial index WHERE */
|
||||
#define NC_Recursive 0x20 /* Resolving a recursive CTE definition */
|
||||
#define NC_UsesLevel 0x40 /* The LEVEL pseudo-column has been seen */
|
||||
|
||||
/*
|
||||
** An instance of the following structure contains all information
|
||||
@@ -2164,6 +2166,7 @@ struct Select {
|
||||
#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
|
||||
#define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */
|
||||
#define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */
|
||||
#define SF_UsesLevel 0x1000 /* Uses the LEVEL pseudo-column */
|
||||
|
||||
|
||||
/*
|
||||
@@ -2370,6 +2373,7 @@ struct Parse {
|
||||
Table *pZombieTab; /* List of Table objects to delete after code gen */
|
||||
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
|
||||
With *pWith; /* Current WITH clause, or NULL */
|
||||
int regLevel; /* Register holding the LEVEL variable */
|
||||
u8 bFreeWith; /* True if pWith should be freed with parser */
|
||||
};
|
||||
|
||||
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
# 2014 January 11
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the WITH clause and in particular the
|
||||
# LEVEL pseudo-column
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix with3
|
||||
|
||||
ifcapable {!cte} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
WITH RECURSIVE
|
||||
cnt(x) AS (VALUES(10) UNION SELECT x+1 FROM cnt WHERE level<10)
|
||||
SELECT * FROM cnt;
|
||||
} {10 11 12 13 14 15 16 17 18 19}
|
||||
do_execsql_test 1.1 {
|
||||
WITH RECURSIVE
|
||||
cnt(x,y) AS (VALUES(10,0) UNION SELECT x+1,level FROM cnt WHERE level<6)
|
||||
SELECT x, y, '|' FROM cnt;
|
||||
} {10 0 | 11 1 | 12 2 | 13 3 | 14 4 | 15 5 |}
|
||||
do_execsql_test 1.2 {
|
||||
WITH RECURSIVE
|
||||
cnt(x,level) AS (
|
||||
VALUES(10,99)
|
||||
UNION
|
||||
SELECT x+1, level FROM cnt WHERE level<6
|
||||
)
|
||||
SELECT x, level, '|' FROM cnt;
|
||||
} {10 99 | 11 1 | 12 2 | 13 3 | 14 4 | 15 5 |}
|
||||
do_execsql_test 1.3 {
|
||||
WITH RECURSIVE
|
||||
cnt(x,level) AS (
|
||||
VALUES(10,99)
|
||||
UNION
|
||||
SELECT x+1, cnt.level FROM cnt WHERE level<6
|
||||
)
|
||||
SELECT x, level, '|' FROM cnt;
|
||||
} {10 99 | 11 99 | 12 99 | 13 99 | 14 99 | 15 99 |}
|
||||
do_execsql_test 1.4 {
|
||||
WITH RECURSIVE
|
||||
cnt(x,level) AS (
|
||||
VALUES(10,0)
|
||||
UNION
|
||||
SELECT x+1, cnt.level+level FROM cnt WHERE level<6
|
||||
)
|
||||
SELECT x, level, '|' FROM cnt;
|
||||
} {10 0 | 11 1 | 12 3 | 13 6 | 14 10 | 15 15 |}
|
||||
do_execsql_test 1.5 {
|
||||
CREATE TABLE t1(level);
|
||||
WITH RECURSIVE
|
||||
cnt(x) AS (VALUES(10) UNION SELECT x*10 FROM cnt WHERE level<4)
|
||||
INSERT INTO t1 SELECT x FROM cnt;
|
||||
SELECT * FROM t1;
|
||||
} {10 100 1000 10000}
|
||||
do_execsql_test 1.6 {
|
||||
WITH RECURSIVE
|
||||
cnt(x, level) AS (
|
||||
VALUES(1,1)
|
||||
UNION
|
||||
SELECT x+1, level*t1.level FROM cnt, t1 WHERE level<3
|
||||
)
|
||||
SELECT x, level FROM cnt ORDER BY x, level;
|
||||
} {1 1 2 10 2 100 2 1000 2 10000 3 20 3 200 3 2000 3 20000}
|
||||
|
||||
do_execsql_test 1.11 {
|
||||
CREATE TEMP TABLE powersoftwo(a,b);
|
||||
WITH RECURSIVE
|
||||
tmp(a,b) AS (VALUES(0,1) UNION SELECT a+1, b*2 FROM tmp WHERE level<32)
|
||||
INSERT INTO powersoftwo SELECT a, b FROM tmp;
|
||||
WITH RECURSIVE
|
||||
cnt(x,y) AS (
|
||||
VALUES(0,0) UNION
|
||||
SELECT x+1, (x+1)*(SELECT b FROM powersoftwo WHERE a=level) FROM cnt
|
||||
WHERE level<5
|
||||
)
|
||||
SELECT * FROM cnt;
|
||||
} {0 0 1 2 2 8 3 24 4 64}
|
||||
|
||||
do_catchsql_test 2.1 {
|
||||
WITH RECURSIVE
|
||||
cnt(x) AS (VALUES(1) UNION SELECT x+1 FROM cnt WHERE level<10)
|
||||
SELECT x, level FROM cnt;
|
||||
} {1 {no such column: level}}
|
||||
do_catchsql_test 2.2 {
|
||||
WITH RECURSIVE
|
||||
cnt(x) AS (VALUES(level) UNION SELECT x+1 FROM cnt WHERE level<10)
|
||||
SELECT x FROM cnt;
|
||||
} {1 {no such column: level}}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
Reference in New Issue
Block a user