From: dan Date: Wed, 15 Jul 2020 15:32:59 +0000 (+0000) Subject: Fix a problem in SQLITE_ENABLE_HIDDEN_COLUMN builds occuring when an UPDATE...FROM... X-Git-Tag: version-3.33.0~53^2~9^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=243210b79b1467a727a75c175f0cb6673c28d3f8;p=thirdparty%2Fsqlite.git Fix a problem in SQLITE_ENABLE_HIDDEN_COLUMN builds occuring when an UPDATE...FROM fired an INSTEAD OF trigger. FossilOrigin-Name: 5176cb7a6a4e8cfa1973aaae46fcd7d39baedb70ae20bfacc82d62ca39fb0aa3 --- diff --git a/manifest b/manifest index c18fafc64d..872b6d5db8 100644 --- a/manifest +++ b/manifest @@ -1,25 +1,25 @@ B 5ee3c27e20d12a126fb773b428bb864102b949a5b26a8d5c523753dcedf4be10 -C Update\sthis\sbranch\swith\schanges\sfrom\strunk. -D 2020-07-15T11:00:29.883 +C Fix\sa\sproblem\sin\sSQLITE_ENABLE_HIDDEN_COLUMN\sbuilds\soccuring\swhen\san\sUPDATE...FROM\sfired\san\sINSTEAD\sOF\strigger. +D 2020-07-15T15:32:59.655 F src/alter.c c63fb72ae0ca39175996fcf7008d44022a7ea99e03c0af3e1d968505ceff7120 F src/attach.c 0b11e00c166b622c84ec176773b1d691c61ad07d247809e3e1635d4e99e71d30 F src/btree.c b8b0e80c8bbe4e1fb35ae559e9e9aa009799c20cf12f159ebb503b05be1fab9b F src/parse.y ecb9abdd79ec86c8dca7cb126bbdcf322c0e282f87a6d0d734ea5f2c57ced516 F src/resolve.c 04f4710d3ab0070073b60b5b963158dadfbd049db55d10742d9fbd3f28a3f4b8 F src/select.c a48570f614f777d02dd7f419789944225432a9231b2dbca863411ac19e5fb683 -F src/sqliteInt.h 9b73bd726b935568f081d2d77443102f663dbcef872eea4e7fbf56e697f3b53c +F src/sqliteInt.h e2684c4ba7ee9c0a0529ae2eb847cc5bf923e4104a9d0944bf3d9d151856b6ab F src/trigger.c 6ff9c64a06e6354df8eba08ae18bc809e79931175d39dda32bf1101adee238e5 -F src/update.c ab137d08171e2bb18a4c6af815bbd6dbe8bfb483ddd7a2b97dfbfb4d95906ee0 +F src/update.c d9b7f86c8d694f5131152b4c216ba257844a8bf63ec4bfe71dbe511cad8a7600 F src/where.c 35cb38d45294118e484fd3a8011aaee8ebe96b28855a6913575a7fe3722d7af5 F test/altertab3.test d0d51e652aaa11e37de1f1215181d88334fefcb185f3b9bd91e06e98260c4694 F test/decimal.test fcf403fd5585f47342234e153c4a4338cd737b8e0884ac66fc484df47dbcf1a7 F test/fts4upfrom.test 8df5acb6e10ad73f393d1add082b042ab1db72567888847d098152121e507b34 F test/fuzzdata8.db 281cbc8166a8bc5843f4a913e803ba76e27905eb02fb9d5cfd581c2429f29855 -F test/triggerupfrom.test 3645a325026619db117683ed1f9da63ec0b9313ff5857f097088c163b291d3fe +F test/triggerupfrom.test d25961fa70a99b6736193da7b49a36d8c1d28d56188f0be6406d4366315cd6e4 F test/upfrom1.tcl df984cb88010af1555812af55e9db44c4df50677395b45d1f30b69b1b6c07b73 F test/upfrom1.test 2ba1ed45b4a2161fc79f234b9ce4300b0d3deba545e3f23b938fb3ebdbf8758d F test/upfrom3.test 2619374c4806913414cc39514630d85bb12489a5f09a5ebdf6fad0fb4df242e2 -P 4f6d8d0ebf40029218a1d3b05ea657c0c5953b01c6f0b6a628465aa44c67e7f3 73d62f82f94347c60e026bc9cb859fec2d8b5f0c756df0c4941f11817234bff8 -R 6cb7af85326f5b68b9bed4397b12a467 +P 53b8b507a10364f5d580655d89c950a5f14c2a8114625fd8749d77f289413b22 +R 50049e7505da24bcfa1309cf7e88265f U dan -Z effbb38e785e7206fb837507bc0dcd3e +Z 6a5f095ea5bbd01f6db55318ec51bead diff --git a/manifest.uuid b/manifest.uuid index 72d2eb8c10..b024410586 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -53b8b507a10364f5d580655d89c950a5f14c2a8114625fd8749d77f289413b22 \ No newline at end of file +5176cb7a6a4e8cfa1973aaae46fcd7d39baedb70ae20bfacc82d62ca39fb0aa3 \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 0240294299..da1a3386cd 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3190,6 +3190,14 @@ struct Select { ** SRT_DistQueue Store results in priority queue pDest->iSDParm only if ** the same record has never been stored before. The ** index at pDest->iSDParm+1 hold all prior stores. +** +** SRT_Upfrom Store results in the temporary table already opened by +** pDest->iSDParm. If (pDest->iSDParm<0), then the temp +** table is an intkey table - in this case the first +** column returned by the SELECT is used as the integer +** key. If (pDest->iSDParm>0), then the table is an index +** table. (pDest->iSDParm) is the number of key columns in +** each index record in this case. */ #define SRT_Union 1 /* Store result as keys in an index */ #define SRT_Except 2 /* Remove result from a UNION index */ diff --git a/src/update.c b/src/update.c index 799caf6abd..c321edce8e 100644 --- a/src/update.c +++ b/src/update.c @@ -237,8 +237,8 @@ static void updatePopulateEphTable( ); } } - pSelect = sqlite3SelectNew( - pParse, pList, pSrc, pWhere2, pGroupBy, 0, pOrderBy2, 0, pLimit2 + pSelect = sqlite3SelectNew(pParse, pList, + pSrc, pWhere2, pGroupBy, 0, pOrderBy2, SF_IncludeHidden, pLimit2 ); sqlite3SelectDestInit(&dest, eDest, iEph); dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1); @@ -249,9 +249,11 @@ static void updatePopulateEphTable( /* ** Process an UPDATE statement. ** -** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL; -** \_______/ \________/ \______/ \________________/ -* onError pTabList pChanges pWhere +** UPDATE OR IGNORE tbl SET a=b, c=d FROM tbl2... WHERE e<5 AND f NOT NULL; +** \_______/ \_/ \______/ \_____/ \________________/ +** onError | pChanges | pWhere +** \_______________________/ +** pTabList */ void sqlite3Update( Parse *pParse, /* The parser context */ @@ -285,7 +287,7 @@ void sqlite3Update( u8 chngRowid; /* Rowid changed in a normal table */ u8 chngKey; /* Either chngPk or chngRowid */ Expr *pRowidExpr = 0; /* Expression defining the new record number */ - int iRowidExpr = -1; + int iRowidExpr = -1; /* Index of "rowid=" (or IPK) assignment in pChanges */ AuthContext sContext; /* The authorization context */ NameContext sNC; /* The name-context to resolve expressions in */ int iDb; /* Database containing the table being updated */ @@ -309,7 +311,7 @@ void sqlite3Update( i16 nPk = 0; /* Number of components of the PRIMARY KEY */ int bReplace = 0; /* True if REPLACE conflict resolution might happen */ int bFinishSeek = 1; /* The OP_FinishSeek opcode is needed */ - int nChangeFrom = 0; + int nChangeFrom = 0; /* If there is a FROM, pChanges->nExpr, else 0 */ /* Register Allocations */ int regRowCount = 0; /* A count of rows changed */ @@ -348,6 +350,11 @@ void sqlite3Update( # undef isView # define isView 0 #endif + + /* If there was a FROM clause, set nChangeFrom to the number of expressions + ** in the change-list. Otherwise, set it to 0. There cannot be a FROM + ** clause if this function is being called to generate code for part of + ** an UPSERT statement. */ nChangeFrom = (pTabList->nSrc>1) ? pChanges->nExpr : 0; assert( nChangeFrom==0 || pUpsert==0 ); diff --git a/test/triggerupfrom.test b/test/triggerupfrom.test index 41f4a1481a..9bfacb8430 100644 --- a/test/triggerupfrom.test +++ b/test/triggerupfrom.test @@ -115,6 +115,60 @@ do_execsql_test 3.0 { SELECT * FROM t1; } {2 TWO} +#------------------------------------------------------------------------- +# Test that INSTEAD OF UPDATE triggers on views work with UPDATE...FROM +# statements. Including, if the library is built with ENABLE_HIDDEN_COLUMNS, +# that they work correctly on views with hidden columns. +# +reset_db +do_execsql_test 4.0 { + CREATE TABLE t1(k, a, b); + INSERT INTO t1 VALUES('a', 1, 'one'); + INSERT INTO t1 VALUES('b', 2, 'two'); + INSERT INTO t1 VALUES('c', 3, 'three'); + INSERT INTO t1 VALUES('d', 4, 'four'); + + CREATE TABLE log(x); + CREATE VIEW v1 AS SELECT k, a, b AS __hidden__b FROM t1; + CREATE TRIGGER tr1 INSTEAD OF UPDATE ON v1 BEGIN + INSERT INTO log VALUES( + '('||old.a||','||old.__hidden__b||')->('||new.a||','||new.__hidden__b||')' + ); + END; +} + +ifcapable hiddencolumns { + do_execsql_test 4.1-hc-enabled { + SELECT * FROM v1 + } {a 1 b 2 c 3 d 4} +} else { + do_execsql_test 4.1-hc-disabled { + SELECT * FROM v1 + } {a 1 one b 2 two c 3 three d 4 four} +} + +do_execsql_test 4.2 { + UPDATE v1 SET a='xyz' WHERE k IN ('a', 'c'); + SELECT * FROM log; + DELETE FROM log; +} { + (1,one)->(xyz,one) + (3,three)->(xyz,three) +} + +do_execsql_test 4.3 { + CREATE TABLE map(k, v); + INSERT INTO map VALUES('b', 'twelve'); + INSERT INTO map VALUES('d', 'fourteen'); + UPDATE v1 SET a=map.v FROM map WHERE v1.k=map.k; + SELECT * FROM log; + DELETE FROM log; +} { + (2,two)->(twelve,two) + (4,four)->(fourteen,four) +} + + finish_test