From: drh <> Date: Fri, 12 Feb 2021 21:07:58 +0000 (+0000) Subject: Parsing of DML statements in a WITH clause. But at this point, it just X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fheads%2Fdml-in-cte;p=thirdparty%2Fsqlite.git Parsing of DML statements in a WITH clause. But at this point, it just generates an error about "not yet supported". FossilOrigin-Name: 964ff68d8fa4d72b1b4d510f1ec62a9674b75d4ebae4ba254bc2f99432857628 --- diff --git a/manifest b/manifest index b1b2a3bcbd..70814337f7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\slongstanding\sproblem\scausing\san\sRBU\svacuum\sto\somit\sreleasing\ssome\slocks\sbefore\sfinishing. -D 2021-02-10T20:00:40.512 +C Parsing\sof\sDML\sstatements\sin\sa\sWITH\sclause.\s\sBut\sat\sthis\spoint,\sit\sjust\ngenerates\san\serror\sabout\s"not\syet\ssupported". +D 2021-02-12T21:07:58.382 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -485,7 +485,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c 694020ad8a3af3d79b09f74c8f1421272a419cdea42a13401e3b0f7dea6e9c3e F src/btree.h 285f8377aa1353185a32bf455faafa9ff9a0d40d074d60509534d14990c7829e F src/btreeInt.h 7614cae30f95b6aed0c7cac7718276a55cfe2c77058cbfd8bef5b75329757331 -F src/build.c 1bae5588bfdf21bdf41e634f0a053d633fb1ae3a2896117b4eea76412b76c2e0 +F src/build.c 5687c1d14855af7c411de7e4316d3938d56aa6ab2c98c7f7bc31e9e8cf8bac17 F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 2a322b9a3d75771fb4d99e0702851f4f68dda982507a0f798eefb0712969a410 @@ -530,7 +530,7 @@ F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c c49952ac5e9cc536778eff528091d79d38b3e45cbeeed4695dc05e207dc6547d F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f -F src/parse.y 67ba503780de64b967ae195b7e14c33531329228e1bc0b83d63324beb733680b +F src/parse.y 75974e46f056c5a6aa18b9b894b784a0c3129fcb77a6d1b42c0356663ea1b179 F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache1.c 6596e10baf3d8f84cc1585d226cf1ab26564a5f5caf85a15757a281ff977d51a @@ -546,7 +546,7 @@ F src/shell.c.in 9ebc74e4f05cfbd0f4a36060fdaeff1da4e9af4458358722bc08c5a1ab9a087 F src/sqlite.h.in 8855a19f37ade8dad189a9e48233a2ebe1b46faf469c7eb0906a654e252dcc57 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e -F src/sqliteInt.h fc56cfde306778a431c133803676fdd1c962ee3e75b5f2483c20fa069cb056e4 +F src/sqliteInt.h c849d0f05d39733816966f4de2d16e4d86113c2cf2eea764aa603049ccc07179 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -1899,8 +1899,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P bd1e9e0a4c0e07901ef59fe3b7e6f7b9cc66ccfcd5192f576e1620820891de99 fb36ac4dc60ccc6c5fba3f23e13fcab985f27ebef0527c929806cda5f9d3660c -R f4fc3fdf82de1da25700d7b06c4d78f5 -T +closed fb36ac4dc60ccc6c5fba3f23e13fcab985f27ebef0527c929806cda5f9d3660c -U dan -Z e97f611a0a7197a91080c2d49e7edf82 +P 66c07a07b21e46529780eec3c82a84c494d586f8b7ed80b78d358e23b80458c7 +R 1961a25c73df65dd61d620956403440e +T *branch * dml-in-cte +T *sym-dml-in-cte * +T -sym-trunk * +U drh +Z ef9b268336156975e58d505fbf96353f diff --git a/manifest.uuid b/manifest.uuid index 8ca0b46774..fc1bb3a81c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -66c07a07b21e46529780eec3c82a84c494d586f8b7ed80b78d358e23b80458c7 \ No newline at end of file +964ff68d8fa4d72b1b4d510f1ec62a9674b75d4ebae4ba254bc2f99432857628 \ No newline at end of file diff --git a/src/build.c b/src/build.c index f5c796fac3..de3c417c8b 100644 --- a/src/build.c +++ b/src/build.c @@ -5204,6 +5204,45 @@ KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){ } #ifndef SQLITE_OMIT_CTE +/* +** Create a new CTE object +*/ +Cte *sqlite3CteNew( + Parse *pParse, /* Parsing context */ + Token *pName, /* Name of the common-table */ + ExprList *pArglist, /* Optional column name list for the table */ + Select *pQuery /* Query used to initialize the table */ +){ + Cte *pNew; + sqlite3 *db = pParse->db; + + pNew = sqlite3DbMallocZero(db, sizeof(*pNew)); + assert( pNew!=0 || db->mallocFailed ); + + if( db->mallocFailed ){ + sqlite3ExprListDelete(db, pArglist); + sqlite3SelectDelete(db, pQuery); + }else{ + pNew->pSelect = pQuery; + pNew->pCols = pArglist; + pNew->zName = sqlite3NameFromToken(pParse->db, pName); + pNew->zCteErr = 0; + } + return pNew; +} + +/* +** Free the contents of the CTE object passed as the second argument. +*/ +void sqlite3CteDelete(sqlite3 *db, Cte *pCte){ + if( pCte ){ + sqlite3ExprListDelete(db, pCte->pCols); + sqlite3SelectDelete(db, pCte->pSelect); + sqlite3DbFree(db, pCte->zName); + sqlite3DbFree(db, pCte); + } +} + /* ** This routine is invoked once per CTE by the parser while parsing a ** WITH clause. @@ -5211,17 +5250,20 @@ KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){ 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 */ - Select *pQuery /* Query used to initialize the table */ + Cte *pCte /* The CTE to add to the WITH clause */ ){ sqlite3 *db = pParse->db; With *pNew; char *zName; + + if( pCte==0 ){ + return pWith; + } + /* Check that the CTE name is unique within this WITH clause. If ** not, store an error in the Parse structure. */ - zName = sqlite3NameFromToken(pParse->db, pName); + zName = pCte->zName; if( zName && pWith ){ int i; for(i=0; inCte; i++){ @@ -5237,21 +5279,15 @@ With *sqlite3WithAdd( }else{ pNew = sqlite3DbMallocZero(db, sizeof(*pWith)); } - assert( (pNew!=0 && zName!=0) || db->mallocFailed ); if( db->mallocFailed ){ - sqlite3ExprListDelete(db, pArglist); - sqlite3SelectDelete(db, pQuery); - sqlite3DbFree(db, zName); + sqlite3CteDelete(db, pCte); pNew = pWith; }else{ - pNew->a[pNew->nCte].pSelect = pQuery; - pNew->a[pNew->nCte].pCols = pArglist; - pNew->a[pNew->nCte].zName = zName; - pNew->a[pNew->nCte].zCteErr = 0; + pNew->a[pNew->nCte] = *pCte; + sqlite3DbFree(db, pCte); pNew->nCte++; } - return pNew; } diff --git a/src/parse.y b/src/parse.y index 591cde3b9d..66e6f62493 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1658,17 +1658,36 @@ anylist ::= anylist ANY. //////////////////////// COMMON TABLE EXPRESSIONS //////////////////////////// %type wqlist {With*} %destructor wqlist {sqlite3WithDelete(pParse->db, $$);} +%type wqitem {Cte*} +%destructor wqitem {sqlite3CteDelete(pParse->db, $$);} with ::= . %ifndef SQLITE_OMIT_CTE with ::= WITH wqlist(W). { sqlite3WithPush(pParse, W, 1); } with ::= WITH RECURSIVE wqlist(W). { sqlite3WithPush(pParse, W, 1); } -wqlist(A) ::= nm(X) eidlist_opt(Y) AS LP select(Z) RP. { - A = sqlite3WithAdd(pParse, 0, &X, Y, Z); /*A-overwrites-X*/ +wqitem(A) ::= nm(X) eidlist_opt(Y) AS LP select(Z) RP. { + A = sqlite3CteNew(pParse, &X, Y, Z); /*A-overwrites-X*/ } -wqlist(A) ::= wqlist(A) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. { - A = sqlite3WithAdd(pParse, A, &X, Y, Z); +wqitem(A) ::= nm eidlist_opt AS LP DELETE FROM nm dbnm where_opt_ret RP. { + sqlite3ErrorMsg(pParse, "DELETE in WITH clauses not yet implemented"); + A = 0; +} +wqitem(A) ::= nm eidlist_opt AS LP + insert_cmd INTO nm dbnm idlist_opt select upsert RP. { + sqlite3ErrorMsg(pParse, "INSERT in WITH clauses not yet implemented"); + A = 0; +} +wqitem(A) ::= nm eidlist_opt AS LP + UPDATE orconf nm dbnm SET setlist from where_opt_ret RP. { + sqlite3ErrorMsg(pParse, "UPDATE in WITH clauses not yet implemented"); + A = 0; +} +wqlist(A) ::= wqitem(X). { + A = sqlite3WithAdd(pParse, 0, X); /*A-overwrites-X*/ +} +wqlist(A) ::= wqlist(A) COMMA wqitem(X). { + A = sqlite3WithAdd(pParse, A, X); } %endif SQLITE_OMIT_CTE diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 093ce76210..c0a11ef753 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1136,6 +1136,7 @@ typedef struct AutoincInfo AutoincInfo; typedef struct Bitvec Bitvec; typedef struct CollSeq CollSeq; typedef struct Column Column; +typedef struct Cte Cte; typedef struct Db Db; typedef struct DbFixer DbFixer; typedef struct Schema Schema; @@ -3870,15 +3871,16 @@ void sqlite3SelectWalkAssert2(Walker*, Select*); ** An instance of this structure represents a set of one or more CTEs ** (common table expressions) created by a single WITH clause. */ +struct Cte { + char *zName; /* Name of this CTE */ + ExprList *pCols; /* List of explicit column names, or NULL */ + Select *pSelect; /* The definition of this CTE */ + const char *zCteErr; /* Error message for circular references */ +}; struct With { - int nCte; /* Number of CTEs in the WITH clause */ - With *pOuter; /* Containing WITH clause, or NULL */ - struct Cte { /* For each CTE in the WITH clause.... */ - char *zName; /* Name of this CTE */ - ExprList *pCols; /* List of explicit column names, or NULL */ - Select *pSelect; /* The definition of this CTE */ - const char *zCteErr; /* Error message for circular references */ - } a[1]; + int nCte; /* Number of CTEs in the WITH clause */ + With *pOuter; /* Containing WITH clause, or NULL */ + Cte a[1]; /* The CTEs of this WITH clause */ }; #ifdef SQLITE_DEBUG @@ -4882,7 +4884,9 @@ const char *sqlite3JournalModename(int); int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int); #endif #ifndef SQLITE_OMIT_CTE - With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*); + Cte *sqlite3CteNew(Parse*,Token*,ExprList*,Select*); + With *sqlite3WithAdd(Parse*,With*,Cte*); + void sqlite3CteDelete(sqlite3*,Cte*); void sqlite3WithDelete(sqlite3*,With*); void sqlite3WithPush(Parse*, With*, u8); #else