Update the parser so that sub-queries and CTEs may have WITH clauses.

FossilOrigin-Name: 704d3931b855562a619769955969d439c42ca406
This commit is contained in:
dan 2014-01-11 19:19:36 +00:00
parent 8b4718636c
commit 7d562dbe02
6 changed files with 98 additions and 32 deletions

View File

@ -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

View File

@ -1 +1 @@
da98b7205eb3d7ec2ddbf8a8e24eee0b2ff499a5
704d3931b855562a619769955969d439c42ca406

View File

@ -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) */

View File

@ -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

View File

@ -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
View 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