Update the parser so that sub-queries and CTEs may have WITH clauses.
FossilOrigin-Name: 704d3931b855562a619769955969d439c42ca406
This commit is contained in:
parent
8b4718636c
commit
7d562dbe02
22
manifest
22
manifest
@ -1,5 +1,5 @@
|
||||
C Parse\scommon\stable\sexpressions.\s\sBut\sdo\snot\sdo\sanything\swith\sthem\s(yet).
|
||||
D 2014-01-11T13:22:17.016
|
||||
C Update\sthe\sparser\sso\sthat\ssub-queries\sand\sCTEs\smay\shave\sWITH\sclauses.
|
||||
D 2014-01-11T19:19:36.147
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -169,7 +169,7 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c 11e29ef8cf16a42925fde036bcffbeffd9cc82df
|
||||
F src/btree.h a61ddebc78c66795a2b93181321a116746302cc9
|
||||
F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
|
||||
F src/build.c 198670a78fe748b6e60d6345a8aa1db57794511a
|
||||
F src/build.c 1da29e4e93d9774599f1f791d011ba46d841000c
|
||||
F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd
|
||||
@ -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 0ccd364dd3670ad5763a5e94dd11196ddc10927a
|
||||
F src/parse.y 1e3fd22fc82930d0cce01f2ab90616100c59ee0c
|
||||
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
|
||||
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
|
||||
F src/pcache1.c 57fee9a9a617218f5037afbbe49b09da65bde56b
|
||||
@ -224,7 +224,7 @@ F src/shell.c a3541193d5fce37e91dad8ef46a9505aa7c9b344
|
||||
F src/sqlite.h.in d94a8b89522f526ba711182ee161e06f8669bcc9
|
||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h bb093076ba1eb956330cca0ca2a206c91facab4b
|
||||
F src/sqliteInt.h 2710b3a6c66edda9f193453268f6fe878ff5a0ca
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
@ -1091,6 +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 e8146198319c3627bb21ef085c58a827f35686a7
|
||||
F test/without_rowid1.test aaa26da19d543cd8d3d2d0e686dfa255556c15c8
|
||||
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
|
||||
F test/without_rowid3.test eac3d5c8a1924725b58503a368f2cbd24fd6c8a0
|
||||
@ -1148,10 +1149,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 29ba458d849ad8864711cbe59fb10447a947e06a
|
||||
R b8f42a0591e43b680c1e09056e8afd6e
|
||||
T *branch * common-table-expr
|
||||
T *sym-common-table-expr *
|
||||
T -sym-trunk *
|
||||
U drh
|
||||
Z 9a38087dfe69ad33926bbf7c01c0b22a
|
||||
P da98b7205eb3d7ec2ddbf8a8e24eee0b2ff499a5
|
||||
R bbb9d541af414d7b8bb3f418deb50875
|
||||
U dan
|
||||
Z a973a84816d55810384771a899b1092b
|
||||
|
@ -1 +1 @@
|
||||
da98b7205eb3d7ec2ddbf8a8e24eee0b2ff499a5
|
||||
704d3931b855562a619769955969d439c42ca406
|
18
src/build.c
18
src/build.c
@ -4200,22 +4200,26 @@ KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_CTE
|
||||
/* This routine is invoked when a single with_query of a
|
||||
** common-table-expression has been parsed. Record the query.
|
||||
/*
|
||||
** This routine is invoked once per CTE by the parser while parsing a
|
||||
** WITH clause.
|
||||
*/
|
||||
void sqlite3CteAdd(
|
||||
With *sqlite3WithAdd(
|
||||
Parse *pParse, /* Parsing context */
|
||||
With *pWith, /* Existing WITH clause, or NULL */
|
||||
Token *pName, /* Name of the common-table */
|
||||
ExprList *pArgList, /* Optional column name list for the table */
|
||||
IdList *pArglist, /* Optional column name list for the table */
|
||||
Select *pQuery /* Query used to initialize the table */
|
||||
){
|
||||
sqlite3ExprListDelete(pParse->db, pArgList);
|
||||
sqlite3IdListDelete(pParse->db, pArglist);
|
||||
sqlite3SelectDelete(pParse->db, pQuery);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This routine is invoked at the end of the entire WITH clause.
|
||||
/*
|
||||
** Free the contents of the With object passed as the second argument.
|
||||
*/
|
||||
void sqlite3CteFinish(Parse *pParse, int isRecursive){
|
||||
void sqlite3WithDelete(sqlite3 *db, With *pWith){
|
||||
/* TBD */
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_CTE) */
|
||||
|
30
src/parse.y
30
src/parse.y
@ -396,7 +396,7 @@ cmd ::= DROP VIEW ifexists(E) fullname(X). {
|
||||
|
||||
//////////////////////// The SELECT statement /////////////////////////////////
|
||||
//
|
||||
cmd ::= with select(X). {
|
||||
cmd ::= select(X). {
|
||||
SelectDest dest = {SRT_Output, 0, 0, 0, 0};
|
||||
sqlite3Select(pParse, X, &dest);
|
||||
sqlite3ExplainBegin(pParse->pVdbe);
|
||||
@ -407,12 +407,16 @@ cmd ::= with select(X). {
|
||||
|
||||
%type select {Select*}
|
||||
%destructor select {sqlite3SelectDelete(pParse->db, $$);}
|
||||
%type selectnowith {Select*}
|
||||
%destructor selectnowith {sqlite3SelectDelete(pParse->db, $$);}
|
||||
%type oneselect {Select*}
|
||||
%destructor oneselect {sqlite3SelectDelete(pParse->db, $$);}
|
||||
|
||||
select(A) ::= oneselect(X). {A = X;}
|
||||
select(A) ::= with selectnowith(X). {A = X;}
|
||||
|
||||
selectnowith(A) ::= oneselect(X). {A = X;}
|
||||
%ifndef SQLITE_OMIT_COMPOUND_SELECT
|
||||
select(A) ::= select(X) multiselect_op(Y) oneselect(Z). {
|
||||
selectnowith(A) ::= selectnowith(X) multiselect_op(Y) oneselect(Z). {
|
||||
if( Z ){
|
||||
Z->op = (u8)Y;
|
||||
Z->pPrior = X;
|
||||
@ -1365,13 +1369,19 @@ anylist ::= anylist ANY.
|
||||
|
||||
|
||||
//////////////////////// COMMON TABLE EXPRESSIONS ////////////////////////////
|
||||
with ::= .
|
||||
%type with {With*}
|
||||
%type wqlist {With*}
|
||||
%destructor with {sqlite3WithDelete(pParse->db, $$);}
|
||||
|
||||
with(A) ::= . {A = 0;}
|
||||
%ifndef SQLITE_OMIT_CTE
|
||||
with ::= WITH wqlist. {sqlite3CteFinish(pParse, 0);}
|
||||
with ::= WITH RECURSIVE wqlist. {sqlite3CteFinish(pParse, 1);}
|
||||
wqlist ::= with_query.
|
||||
wqlist ::= wqlist COMMA with_query.
|
||||
with_query ::= nm(X) idxlist_opt(Y) AS LP select(Z) RP. {
|
||||
sqlite3CteAdd(pParse, &X, Y, Z);
|
||||
with(A) ::= WITH wqlist(W). { A = W; }
|
||||
with(A) ::= WITH RECURSIVE wqlist(W). { A = W; }
|
||||
|
||||
wqlist(A) ::= nm(X) inscollist_opt(Y) AS LP select(Z) RP. {
|
||||
A = sqlite3WithAdd(pParse, 0, &X, Y, Z);
|
||||
}
|
||||
wqlist(A) ::= wqlist(W) COMMA nm(X) inscollist_opt(Y) AS LP select(Z) RP. {
|
||||
A = sqlite3WithAdd(pParse, W, &X, Y, Z);
|
||||
}
|
||||
%endif SQLITE_OMIT_CTE
|
||||
|
@ -760,6 +760,7 @@ typedef struct VTable VTable;
|
||||
typedef struct VtabCtx VtabCtx;
|
||||
typedef struct Walker Walker;
|
||||
typedef struct WhereInfo WhereInfo;
|
||||
typedef struct With With;
|
||||
|
||||
/*
|
||||
** Defer sourcing vdbe.h and btree.h until after the "u8" and
|
||||
@ -2631,6 +2632,19 @@ int sqlite3WalkSelectFrom(Walker*, Select*);
|
||||
#define WRC_Prune 1 /* Omit children but continue walking siblings */
|
||||
#define WRC_Abort 2 /* Abandon the tree walk */
|
||||
|
||||
/*
|
||||
** An instance of this structure represents a set of CTEs (common table
|
||||
** expressions) created by a single WITH clause.
|
||||
*/
|
||||
struct With {
|
||||
int nCte; /* Number of CTEs */
|
||||
struct Cte {
|
||||
const char *zName; /* Name of this CTE */
|
||||
IdList *pCol; /* List of explicit column names, or NULL */
|
||||
Select *pSelect; /* The contents of the CTE */
|
||||
} a[1];
|
||||
};
|
||||
|
||||
/*
|
||||
** Assuming zIn points to the first byte of a UTF-8 character,
|
||||
** advance zIn to point to the first byte of the next UTF-8 character.
|
||||
@ -3330,8 +3344,8 @@ const char *sqlite3JournalModename(int);
|
||||
int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_CTE
|
||||
void sqlite3CteAdd(Parse*,Token*,ExprList*,Select*);
|
||||
void sqlite3CteFinish(Parse*,int);
|
||||
With *sqlite3WithAdd(Parse*,With*,Token*,IdList*,Select*);
|
||||
void sqlite3WithDelete(sqlite3*,With*);
|
||||
#endif
|
||||
|
||||
/* Declarations for functions in fkey.c. All of these are replaced by
|
||||
|
40
test/with1.test
Normal file
40
test/with1.test
Normal file
@ -0,0 +1,40 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix with1
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(x INTEGER, y INTEGER);
|
||||
WITH x(a) AS ( SELECT * FROM t1) SELECT 10
|
||||
} {10}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
SELECT * FROM ( WITH x AS ( SELECT * FROM t1) SELECT 10 );
|
||||
} {10}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
WITH x(a) AS ( SELECT * FROM t1) INSERT INTO t1 VALUES(1,2);
|
||||
} {}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
WITH x(a) AS ( SELECT * FROM t1) DELETE FROM t1;
|
||||
} {}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
WITH x(a) AS ( SELECT * FROM t1) UPDATE t1 SET x = y;
|
||||
} {}
|
||||
|
||||
finish_test
|
Loading…
x
Reference in New Issue
Block a user