From: dan Date: Mon, 5 Jul 2021 11:27:13 +0000 (+0000) Subject: Allow sub-queries in the FROM clause of an UPDATE...FROM statement to access the... X-Git-Tag: version-3.37.0~360 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5daf69e5f4277085ed44c76930f777cf415edff3;p=thirdparty%2Fsqlite.git Allow sub-queries in the FROM clause of an UPDATE...FROM statement to access the object being updated without using an alias, as is required in the parent query. FossilOrigin-Name: 740cb43025449b7d7b47a97ad00885e54b7701cbcb14f4a50c7523022e3936d5 --- diff --git a/manifest b/manifest index fff16cfa52..66e4413327 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\srebustness\sin\ssqlite3ExprListDup()\swhen\sit\scontains\sa\svector\sassignment\nfrom\san\sUPDATE\swhere\sthe\sinitial\sterm\sis\somitted.\s\sThis\scan\shappen\sduring\sa\nUNION\sALL\squery\sflattening\swhile\sprocessing\sa\svirtual\stable\supdate\sin\swhich\nthe\sfirst\sterm\sof\sthe\svector\sis\srepeated.\n[forum:/forumpost/16ca0e9f32|Forum\spost\s16ca0e9f32]. -D 2021-07-05T02:40:29.435 +C Allow\ssub-queries\sin\sthe\sFROM\sclause\sof\san\sUPDATE...FROM\sstatement\sto\saccess\sthe\sobject\sbeing\supdated\swithout\susing\san\salias,\sas\sis\srequired\sin\sthe\sparent\squery. +D 2021-07-05T11:27:13.620 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -544,12 +544,12 @@ F src/printf.c 78fabb49b9ac9a12dd1c89d744abdc9b67fd3205e62967e158f78b965a29ec4b F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c b379c5ffe3b692e9c64fa37817cc0efa204b7c9468a818309dde85fd132d9d81 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 -F src/select.c 4fa607bab6bcc580f12dbaf9c800b2250a1e408f10321a1d3bcb1dd30c447e62 +F src/select.c 1c1230aaa4e5979edd3c5a9f7a90ab856a302cca4962e8a7d08f42dd2e7e1a49 F src/shell.c.in 699910739eb7296fd47be19db71f6e5d15d0760f4352c62639d4d6cc7bd8d4cc F src/sqlite.h.in ecf5aa981da30c33da3e9f353bf3ebf055d3c380c80d6a4f954e58d18ccd6df1 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510 -F src/sqliteInt.h 6cfa7b73801657c89155a02e748ba538b8bb12fe6f4e8143c74f055d55e1190d +F src/sqliteInt.h bb5868a443be017a2701bff26a7eb934b5390adef6322ff36ae4e41d3d036b81 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -611,7 +611,7 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c bae853ad129d1129c063de8630a3e99e306283bc40146f359b1bb91be2c08f1e F src/treeview.c ce7a3da38caba094c78d888d2366f749ea33dc8cbafb04218b57768fb8669a6c F src/trigger.c 7d16aa09e63226b6d8b3f0fc60b21cbfa596fc406288b2ebcf4266633d1ba222 -F src/update.c 56fa0458b1ffc1042629f926443e8ed44203983df3ab2b0db2ba556e6ceed68c +F src/update.c ff10c7ca6dc9007cdebb3eee6630e87639ef9f949ccb574c34f9d34c52c32fb9 F src/upsert.c df8f1727d62b5987c4fd302cd4d7c0c84ae57cd65683c5a34a740dfe24039235 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 41c7a72da1df47864faa378a1c720b38adb288c6838cb6be5594511b6287a048 @@ -1660,7 +1660,7 @@ F test/update.test e906ca7cb1dc6f52af1ea243e08f727edfa79f924c2691f2f9e72481f8473 F test/update2.test 67455bc61fcbcf96923c45b3bc4f87bc72be7d67575ad35f134906148c7b06d3 F test/upfrom1.tcl 8859d9d437f03b44174c4524a7a734a391fd4526fcff65be08285dafc9dc9041 F test/upfrom1.test 8cb06689e99cd707d884faa16da0e8eb26ff658bb01c47ddf72fadade666e6e1 -F test/upfrom2.test f92e47bfc35e9410d3e8716ee626384e89ad026c55fd6148508ca9d707521673 +F test/upfrom2.test 88d39cb755db5789541e645d4e2764abc697a56958f28a3f8451a0e9342bbd6b F test/upfrom3.test 6130f24ebf97f5ea865e5d2a14a2d543fe5428a62e87cc60f62d875e45c1f5f0 F test/upfromfault.test 3a10075a0043f0c4fad6614b2c371f88a8ba5a4acab68b907438413865d6a8d6 F test/upsert1.test 88f9e258c6a0eeeb85937b08831e8daad440ba41f125af48439e9d33f266fb18 @@ -1685,7 +1685,7 @@ F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 F test/view.test ea88361d5e9bc8eabf9f573185a16aea73a885be9b6c6a95ae84908913416a80 F test/view2.test db32c8138b5b556f610b35dfddd38c5a58a292f07fda5281eedb0851b2672679 -F test/vtab1.test e5760911437a97f5887f41ed37d6b124b2c4d8f7dc6ab4e08be8c0dff75b34e8 +F test/vtab1.test 772c94825d455dffc5da34dcf4b648d8a23887616185fa024a472bf745e56df8 F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082 F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3 @@ -1919,7 +1919,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 026f08d4cff19a95e0f38f2ef431cacd65c7c77ed92e30d7f2ded84651f47150 -R 370a07f45c8536f9b9e4e0469f767d7e -U drh -Z 4f1da44a75ffa77140a4f27e7fbced11 +P 2547cfe38f8fb35109b3fc5bdfada387fe4b2b8a304156b704ab7f03f1f71198 +R 3e8d3cb17bf6ee799e7e5bba55fb6114 +U dan +Z 5d47dc2f76359fb6048332e2e7229d64 diff --git a/manifest.uuid b/manifest.uuid index 3ecd262408..68cfb10ea1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2547cfe38f8fb35109b3fc5bdfada387fe4b2b8a304156b704ab7f03f1f71198 \ No newline at end of file +740cb43025449b7d7b47a97ad00885e54b7701cbcb14f4a50c7523022e3936d5 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 7d8fd5939d..d36839264d 100644 --- a/src/select.c +++ b/src/select.c @@ -6286,11 +6286,16 @@ int sqlite3Select( } #endif - /* If the SF_UpdateFrom flag is set, then this function is being called + /* If the SF_UFSrcCheck flag is set, then this function is being called ** as part of populating the temp table for an UPDATE...FROM statement. ** In this case, it is an error if the target object (pSrc->a[0]) name - ** or alias is duplicated within FROM clause (pSrc->a[1..n]). */ - if( p->selFlags & SF_UpdateFrom ){ + ** or alias is duplicated within FROM clause (pSrc->a[1..n]). + ** + ** Postgres disallows this case too. The reason is that some other + ** systems handle this case differently, and not all the same way, + ** which is just confusing. To avoid this, we follow PG's lead and + ** disallow it altogether. */ + if( p->selFlags & SF_UFSrcCheck ){ SrcItem *p0 = &p->pSrc->a[0]; for(i=1; ipSrc->nSrc; i++){ SrcItem *p1 = &p->pSrc->a[i]; @@ -6302,6 +6307,12 @@ int sqlite3Select( goto select_end; } } + + /* Clear the SF_UFSrcCheck flag. The check has already been performed, + ** and leaving this flag set can cause errors if a compound sub-query + ** in p->pSrc is flattened into this query and this function called + ** again as part of compound SELECT processing. */ + p->selFlags &= ~SF_UFSrcCheck; } if( pDest->eDest==SRT_Output ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index fea5ddd3a0..b5fbff6454 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3210,7 +3210,7 @@ struct Select { #define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */ #define SF_View 0x0200000 /* SELECT statement is a view */ #define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */ -#define SF_UpdateFrom 0x0800000 /* Statement is an UPDATE...FROM */ +#define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */ #define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */ #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */ #define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */ diff --git a/src/update.c b/src/update.c index 132232724a..45f332bf37 100644 --- a/src/update.c +++ b/src/update.c @@ -259,7 +259,7 @@ static void updateFromSelect( } } pSelect = sqlite3SelectNew(pParse, pList, - pSrc, pWhere2, pGrp, 0, pOrderBy2, SF_UpdateFrom|SF_IncludeHidden, pLimit2 + pSrc, pWhere2, pGrp, 0, pOrderBy2, SF_UFSrcCheck|SF_IncludeHidden, pLimit2 ); sqlite3SelectDestInit(&dest, eDest, iEph); dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1); diff --git a/test/upfrom2.test b/test/upfrom2.test index 81c847a604..a1f00953e6 100644 --- a/test/upfrom2.test +++ b/test/upfrom2.test @@ -365,5 +365,21 @@ foreach {tn update nm} { "1 {target object/alias may not appear in FROM clause: $nm}" } +#-------------------------------------------------------------------------- +reset_db +do_execsql_test 6.0 { + CREATE TABLE t1(a); +} + +do_execsql_test 6.1 { + UPDATE t1 SET a = 1 FROM ( + SELECT * FROM t1 + ) +} {} +do_execsql_test 6.2 { + UPDATE t1 SET a = 1 FROM ( + SELECT * FROM t1 UNION ALL SELECT * FROM t1 + ) +} {} finish_test diff --git a/test/vtab1.test b/test/vtab1.test index 0934ef502a..7a55703089 100644 --- a/test/vtab1.test +++ b/test/vtab1.test @@ -1570,6 +1570,6 @@ do_catchsql_test 25.0 { CREATE VIRTUAL TABLE t1 USING echo(t0); WITH t3(a) AS (SELECT * FROM t1 UNION ALL SELECT * FROM t1) UPDATE t1 SET (a,a) = (SELECT 1, 0) FROM t3; -} {1 {target object/alias may not appear in FROM clause: t1}} +} {0 {}} finish_test