From: dan Date: Thu, 26 May 2022 19:10:11 +0000 (+0000) Subject: Fix issues with ALTER TABLE and triggers containing "UPDATE...FROM" statements. X-Git-Tag: version-3.39.0~91 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b8bbe3e2db8b0cd12a955de6c10a441301b60e55;p=thirdparty%2Fsqlite.git Fix issues with ALTER TABLE and triggers containing "UPDATE...FROM" statements. FossilOrigin-Name: 2fba0d41b781d226915fa2bf888a7bc640c046ce22670ceb53f62a09f3975259 --- diff --git a/manifest b/manifest index 2f209316a3..f83067ff4d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Correct\shandling\sof\souter\sjoins\sin\sthe\sFROM\sclause\sof\san\sUPDATE\sstatement\nthat\soccurs\sinside\sof\sa\strigger.\s\sFollow-on\sto\s[98b3816bbaf539ea]. -D 2022-05-26T17:33:42.057 +C Fix\sissues\swith\sALTER\sTABLE\sand\striggers\scontaining\s"UPDATE...FROM"\sstatements. +D 2022-05-26T19:10:11.700 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -500,7 +500,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c d8872f9d1863d8e31c37475e318de746e1b5ca57c0e477e35042a9ebbb6e0298 +F src/alter.c 379c644a32c64a18b592affac5ef173eb6024638b70ed4c593896e901702c78c F src/analyze.c aabdf3769c7fd9954a8ec508eb7041ae174b66f88d12c47199fabbea9a646467 F src/attach.c 4431f82f0247bf3aaf91589acafdff77d1882235c95407b36da1585c765fbbc8 F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf @@ -685,6 +685,7 @@ F test/alterqf.test ff6c6f881485c29ed699b8ef4774864ca1b0c01a6c08f5cdd624a008e4b4 F test/altertab.test 7273b8506eab46342be016af78028df49f3bd99037412f997a8f1011b37a6912 F test/altertab2.test 62597b6fd08feaba1b6bfe7d31dac6117c67e06dc9ce9c478a3abe75b5926de0 F test/altertab3.test 8af5c6eb4a7dd2fc73235b865b53561bf07428d1d6a9cd59a067abf51141891e +F test/altertrig.test f621cb3b209a2e72974e580840365b046537cd97b2df6b52088218a95dcbd58d F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f F test/analyze.test 547bb700f903107b38611b014ca645d6b5bb819f5210d7bf39c40802aafeb7d7 F test/analyze3.test 4440c4932247adb2b4e0c838f657c19dc7af4f56859255436dc4e855f39b9324 @@ -1969,8 +1970,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f22f41d2c8a676b9a339e7f00c29c163bbb7079b1a4a76ee1a6a96aaf7de5f9e -R 96c2f1a4243ab0b57b68e0f3b4978a15 -U drh -Z 723fac70f8b090aa70201f7f985c54bc +P 664a49fa813144b6fa5a7ae3f65af5412f150dd5def261c4d581d706b39f7846 +R 4d839461e9af3d0a5ea1b8ddf72bf796 +U dan +Z 14299f1b8c4a8b0632845b66e1aabf6a # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 04ae0302b2..07e5cbd3c4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -664a49fa813144b6fa5a7ae3f65af5412f150dd5def261c4d581d706b39f7846 \ No newline at end of file +2fba0d41b781d226915fa2bf888a7bc640c046ce22670ceb53f62a09f3975259 \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 538ba7d9f8..8e19c0acea 100644 --- a/src/alter.c +++ b/src/alter.c @@ -1318,6 +1318,8 @@ static int renameResolveTrigger(Parse *pParse){ SrcList *pSrc = sqlite3TriggerStepSrc(pParse, pStep); if( pSrc ){ int i; + assert( pSrc->nSrc==1 || pSrc->nSrc==2 ); + assert( pSrc->a[0].pSelect==0 ); for(i=0; inSrc && rc==SQLITE_OK; i++){ SrcItem *p = &pSrc->a[i]; p->iCursor = pParse->nTab++; @@ -1325,8 +1327,6 @@ static int renameResolveTrigger(Parse *pParse){ sqlite3SelectPrep(pParse, p->pSelect, 0); sqlite3ExpandSubquery(pParse, p); assert( i>0 ); - assert( pStep->pFrom->a[i-1].pSelect ); - sqlite3SelectPrep(pParse, pStep->pFrom->a[i-1].pSelect, 0); }else{ p->pTab = sqlite3LocateTableItem(pParse, 0, p); if( p->pTab==0 ){ @@ -1337,6 +1337,15 @@ static int renameResolveTrigger(Parse *pParse){ } } } + if( pStep->pFrom ){ + for(i=0; ipFrom->nSrc && rc==SQLITE_OK; i++){ + SrcItem *p = &pStep->pFrom->a[i]; + if( p->pSelect ){ + sqlite3SelectPrep(pParse, p->pSelect, 0); + } + } + } + if( rc==SQLITE_OK && db->mallocFailed ){ rc = SQLITE_NOMEM; } @@ -1789,6 +1798,15 @@ static void renameTableFunc( if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){ renameTokenFind(&sParse, &sCtx, pStep->zTarget); } + if( pStep->pFrom ){ + int i; + for(i=0; ipFrom->nSrc; i++){ + SrcItem *pItem = &pStep->pFrom->a[i]; + if( pItem->zName && 0==sqlite3_stricmp(pItem->zName, zOld) ){ + renameTokenFind(&sParse, &sCtx, pItem->zName); + } + } + } } } } diff --git a/test/altertrig.test b/test/altertrig.test new file mode 100644 index 0000000000..f418e58381 --- /dev/null +++ b/test/altertrig.test @@ -0,0 +1,130 @@ +# 2022 May 27 +# +# 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. +# +#************************************************************************* +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix altertrig + +# If SQLITE_OMIT_ALTERTABLE is defined, omit this file. +ifcapable !altertable { + finish_test + return +} + +proc collapse_whitespace {in} { + regsub -all {[ \t\n]+} [string trim $in] { } +} + +proc do_whitespace_sql_test {tn sql res} { + set got [execsql $sql] + set wgot [list] + set wres [list] + foreach g $got { lappend wgot [collapse_whitespace $g] } + foreach r $res { lappend wres [collapse_whitespace $r] } + + uplevel [list do_test $tn [list set {} $wgot] $wres] +} + +do_execsql_test 1.0 { + CREATE TABLE t1(x); + CREATE TABLE t2(y); + CREATE TABLE t3(z); + CREATE TABLE t4(a); + + CREATE TRIGGER r1 INSERT ON t1 BEGIN + UPDATE t1 SET d='xyz' FROM t2, t3; + END; +} + +do_whitespace_sql_test 1.1 { + ALTER TABLE t3 RENAME TO t5; + SELECT sql FROM sqlite_schema WHERE type='trigger'; +} {{ + CREATE TRIGGER r1 INSERT ON t1 BEGIN + UPDATE t1 SET d='xyz' FROM t2, "t5"; + END +}} + +do_execsql_test 1.2 { + DROP TRIGGER r1; + CREATE TRIGGER r1 INSERT ON t1 BEGIN + UPDATE t1 SET d='xyz' FROM t2, (SELECT * FROM t5); + END; +} + +do_whitespace_sql_test 1.3 { + ALTER TABLE t5 RENAME TO t3; + SELECT sql FROM sqlite_schema WHERE type='trigger'; +} {{ + CREATE TRIGGER r1 INSERT ON t1 BEGIN + UPDATE t1 SET d='xyz' FROM t2, (SELECT * FROM "t3"); + END +}} + +foreach {tn alter update final} { + 1 { + ALTER TABLE t3 RENAME TO t10 + } { + UPDATE t1 SET d='xyz' FROM t2, (SELECT * FROM t3) + } { + UPDATE t1 SET d='xyz' FROM t2, (SELECT * FROM "t10") + } + + 2 { + ALTER TABLE t3 RENAME TO t10 + } { + UPDATE t1 SET d='xyz' FROM t3, (SELECT * FROM (SELECT e FROM t3)) + } { + UPDATE t1 SET d='xyz' FROM "t10", (SELECT * FROM (SELECT e FROM "t10")) + } + + 3 { + ALTER TABLE t3 RENAME e TO abc + } { + UPDATE t1 SET d='xyz' FROM t3, (SELECT * FROM (SELECT e FROM t3)) + } { + UPDATE t1 SET d='xyz' FROM t3, (SELECT * FROM (SELECT abc FROM t3)) + } + + 4 { + ALTER TABLE t2 RENAME c TO abc + } { + UPDATE t1 SET d='xyz' FROM t3, (SELECT 1 FROM t2 WHERE c) + } { + UPDATE t1 SET d='xyz' FROM t3, (SELECT 1 FROM t2 WHERE abc) + } + +} { + reset_db + do_execsql_test 2.$tn.1 { + CREATE TABLE t1(a,b); + CREATE TABLE t2(c,d); + CREATE TABLE t3(e,f); + } + do_execsql_test 2.$tn.2 " + CREATE TRIGGER r1 INSERT ON t1 BEGIN + $update; + END + " + do_execsql_test 2.$tn.3 $alter + + do_whitespace_sql_test 2.$tn.4 { + SELECT sqL FROM sqlite_schema WHERE type='trigger' + } "{ + CREATE TRIGGER r1 INSERT ON t1 BEGIN + $final; + END + }" +} + +finish_test +