1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Fix issues with ALTER TABLE and triggers containing "UPDATE...FROM" statements.

FossilOrigin-Name: 2fba0d41b781d226915fa2bf888a7bc640c046ce22670ceb53f62a09f3975259
This commit is contained in:
dan
2022-05-26 19:10:11 +00:00
parent 26c4df0fb0
commit b8bbe3e2db
4 changed files with 159 additions and 10 deletions

View File

@ -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]. C Fix\sissues\swith\sALTER\sTABLE\sand\striggers\scontaining\s"UPDATE...FROM"\sstatements.
D 2022-05-26T17:33:42.057 D 2022-05-26T19:10:11.700
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -500,7 +500,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c d8872f9d1863d8e31c37475e318de746e1b5ca57c0e477e35042a9ebbb6e0298 F src/alter.c 379c644a32c64a18b592affac5ef173eb6024638b70ed4c593896e901702c78c
F src/analyze.c aabdf3769c7fd9954a8ec508eb7041ae174b66f88d12c47199fabbea9a646467 F src/analyze.c aabdf3769c7fd9954a8ec508eb7041ae174b66f88d12c47199fabbea9a646467
F src/attach.c 4431f82f0247bf3aaf91589acafdff77d1882235c95407b36da1585c765fbbc8 F src/attach.c 4431f82f0247bf3aaf91589acafdff77d1882235c95407b36da1585c765fbbc8
F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
@ -685,6 +685,7 @@ F test/alterqf.test ff6c6f881485c29ed699b8ef4774864ca1b0c01a6c08f5cdd624a008e4b4
F test/altertab.test 7273b8506eab46342be016af78028df49f3bd99037412f997a8f1011b37a6912 F test/altertab.test 7273b8506eab46342be016af78028df49f3bd99037412f997a8f1011b37a6912
F test/altertab2.test 62597b6fd08feaba1b6bfe7d31dac6117c67e06dc9ce9c478a3abe75b5926de0 F test/altertab2.test 62597b6fd08feaba1b6bfe7d31dac6117c67e06dc9ce9c478a3abe75b5926de0
F test/altertab3.test 8af5c6eb4a7dd2fc73235b865b53561bf07428d1d6a9cd59a067abf51141891e F test/altertab3.test 8af5c6eb4a7dd2fc73235b865b53561bf07428d1d6a9cd59a067abf51141891e
F test/altertrig.test f621cb3b209a2e72974e580840365b046537cd97b2df6b52088218a95dcbd58d
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
F test/analyze.test 547bb700f903107b38611b014ca645d6b5bb819f5210d7bf39c40802aafeb7d7 F test/analyze.test 547bb700f903107b38611b014ca645d6b5bb819f5210d7bf39c40802aafeb7d7
F test/analyze3.test 4440c4932247adb2b4e0c838f657c19dc7af4f56859255436dc4e855f39b9324 F test/analyze3.test 4440c4932247adb2b4e0c838f657c19dc7af4f56859255436dc4e855f39b9324
@ -1969,8 +1970,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P f22f41d2c8a676b9a339e7f00c29c163bbb7079b1a4a76ee1a6a96aaf7de5f9e P 664a49fa813144b6fa5a7ae3f65af5412f150dd5def261c4d581d706b39f7846
R 96c2f1a4243ab0b57b68e0f3b4978a15 R 4d839461e9af3d0a5ea1b8ddf72bf796
U drh U dan
Z 723fac70f8b090aa70201f7f985c54bc Z 14299f1b8c4a8b0632845b66e1aabf6a
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
664a49fa813144b6fa5a7ae3f65af5412f150dd5def261c4d581d706b39f7846 2fba0d41b781d226915fa2bf888a7bc640c046ce22670ceb53f62a09f3975259

View File

@ -1318,6 +1318,8 @@ static int renameResolveTrigger(Parse *pParse){
SrcList *pSrc = sqlite3TriggerStepSrc(pParse, pStep); SrcList *pSrc = sqlite3TriggerStepSrc(pParse, pStep);
if( pSrc ){ if( pSrc ){
int i; int i;
assert( pSrc->nSrc==1 || pSrc->nSrc==2 );
assert( pSrc->a[0].pSelect==0 );
for(i=0; i<pSrc->nSrc && rc==SQLITE_OK; i++){ for(i=0; i<pSrc->nSrc && rc==SQLITE_OK; i++){
SrcItem *p = &pSrc->a[i]; SrcItem *p = &pSrc->a[i];
p->iCursor = pParse->nTab++; p->iCursor = pParse->nTab++;
@ -1325,8 +1327,6 @@ static int renameResolveTrigger(Parse *pParse){
sqlite3SelectPrep(pParse, p->pSelect, 0); sqlite3SelectPrep(pParse, p->pSelect, 0);
sqlite3ExpandSubquery(pParse, p); sqlite3ExpandSubquery(pParse, p);
assert( i>0 ); assert( i>0 );
assert( pStep->pFrom->a[i-1].pSelect );
sqlite3SelectPrep(pParse, pStep->pFrom->a[i-1].pSelect, 0);
}else{ }else{
p->pTab = sqlite3LocateTableItem(pParse, 0, p); p->pTab = sqlite3LocateTableItem(pParse, 0, p);
if( p->pTab==0 ){ if( p->pTab==0 ){
@ -1337,6 +1337,15 @@ static int renameResolveTrigger(Parse *pParse){
} }
} }
} }
if( pStep->pFrom ){
for(i=0; i<pStep->pFrom->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 ){ if( rc==SQLITE_OK && db->mallocFailed ){
rc = SQLITE_NOMEM; rc = SQLITE_NOMEM;
} }
@ -1789,6 +1798,15 @@ static void renameTableFunc(
if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){ if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){
renameTokenFind(&sParse, &sCtx, pStep->zTarget); renameTokenFind(&sParse, &sCtx, pStep->zTarget);
} }
if( pStep->pFrom ){
int i;
for(i=0; i<pStep->pFrom->nSrc; i++){
SrcItem *pItem = &pStep->pFrom->a[i];
if( pItem->zName && 0==sqlite3_stricmp(pItem->zName, zOld) ){
renameTokenFind(&sParse, &sCtx, pItem->zName);
}
}
}
} }
} }
} }

130
test/altertrig.test Normal file
View File

@ -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