diff options
author | dan <dan@noemail.net> | 2014-01-11 19:19:36 +0000 |
---|---|---|
committer | dan <dan@noemail.net> | 2014-01-11 19:19:36 +0000 |
commit | 7d562dbe023a06bc8b7116c5415c5cb9b6a25cfc (patch) | |
tree | 18082c59340c1448d6aafb9567ce4fb01721601a /src | |
parent | 8b4718636ce00ad08d2d8cb41b6073ac02436e92 (diff) | |
download | sqlite-7d562dbe023a06bc8b7116c5415c5cb9b6a25cfc.tar.gz sqlite-7d562dbe023a06bc8b7116c5415c5cb9b6a25cfc.zip |
Update the parser so that sub-queries and CTEs may have WITH clauses.
FossilOrigin-Name: 704d3931b855562a619769955969d439c42ca406
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 18 | ||||
-rw-r--r-- | src/parse.y | 30 | ||||
-rw-r--r-- | src/sqliteInt.h | 18 |
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 |