aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build.c18
-rw-r--r--src/parse.y30
-rw-r--r--src/sqliteInt.h18
3 files changed, 47 insertions, 19 deletions
diff --git a/src/build.c b/src/build.c
index 4fb4b4efa..23628f73b 100644
--- a/src/build.c
+++ b/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) */
diff --git a/src/parse.y b/src/parse.y
index f4fa4b276..c3cb2d62a 100644
--- a/src/parse.y
+++ b/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
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index d517789da..8846ffb04 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -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
@@ -2632,6 +2633,19 @@ int sqlite3WalkSelectFrom(Walker*, Select*);
#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