mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Fix a problem in SQLITE_ENABLE_HIDDEN_COLUMN builds occuring when an UPDATE...FROM fired an INSTEAD OF trigger.
FossilOrigin-Name: 5176cb7a6a4e8cfa1973aaae46fcd7d39baedb70ae20bfacc82d62ca39fb0aa3
This commit is contained in:
16
manifest
16
manifest
@ -1,25 +1,25 @@
|
|||||||
B 5ee3c27e20d12a126fb773b428bb864102b949a5b26a8d5c523753dcedf4be10
|
B 5ee3c27e20d12a126fb773b428bb864102b949a5b26a8d5c523753dcedf4be10
|
||||||
C Update\sthis\sbranch\swith\schanges\sfrom\strunk.
|
C Fix\sa\sproblem\sin\sSQLITE_ENABLE_HIDDEN_COLUMN\sbuilds\soccuring\swhen\san\sUPDATE...FROM\sfired\san\sINSTEAD\sOF\strigger.
|
||||||
D 2020-07-15T11:00:29.883
|
D 2020-07-15T15:32:59.655
|
||||||
F src/alter.c c63fb72ae0ca39175996fcf7008d44022a7ea99e03c0af3e1d968505ceff7120
|
F src/alter.c c63fb72ae0ca39175996fcf7008d44022a7ea99e03c0af3e1d968505ceff7120
|
||||||
F src/attach.c 0b11e00c166b622c84ec176773b1d691c61ad07d247809e3e1635d4e99e71d30
|
F src/attach.c 0b11e00c166b622c84ec176773b1d691c61ad07d247809e3e1635d4e99e71d30
|
||||||
F src/btree.c b8b0e80c8bbe4e1fb35ae559e9e9aa009799c20cf12f159ebb503b05be1fab9b
|
F src/btree.c b8b0e80c8bbe4e1fb35ae559e9e9aa009799c20cf12f159ebb503b05be1fab9b
|
||||||
F src/parse.y ecb9abdd79ec86c8dca7cb126bbdcf322c0e282f87a6d0d734ea5f2c57ced516
|
F src/parse.y ecb9abdd79ec86c8dca7cb126bbdcf322c0e282f87a6d0d734ea5f2c57ced516
|
||||||
F src/resolve.c 04f4710d3ab0070073b60b5b963158dadfbd049db55d10742d9fbd3f28a3f4b8
|
F src/resolve.c 04f4710d3ab0070073b60b5b963158dadfbd049db55d10742d9fbd3f28a3f4b8
|
||||||
F src/select.c a48570f614f777d02dd7f419789944225432a9231b2dbca863411ac19e5fb683
|
F src/select.c a48570f614f777d02dd7f419789944225432a9231b2dbca863411ac19e5fb683
|
||||||
F src/sqliteInt.h 9b73bd726b935568f081d2d77443102f663dbcef872eea4e7fbf56e697f3b53c
|
F src/sqliteInt.h e2684c4ba7ee9c0a0529ae2eb847cc5bf923e4104a9d0944bf3d9d151856b6ab
|
||||||
F src/trigger.c 6ff9c64a06e6354df8eba08ae18bc809e79931175d39dda32bf1101adee238e5
|
F src/trigger.c 6ff9c64a06e6354df8eba08ae18bc809e79931175d39dda32bf1101adee238e5
|
||||||
F src/update.c ab137d08171e2bb18a4c6af815bbd6dbe8bfb483ddd7a2b97dfbfb4d95906ee0
|
F src/update.c d9b7f86c8d694f5131152b4c216ba257844a8bf63ec4bfe71dbe511cad8a7600
|
||||||
F src/where.c 35cb38d45294118e484fd3a8011aaee8ebe96b28855a6913575a7fe3722d7af5
|
F src/where.c 35cb38d45294118e484fd3a8011aaee8ebe96b28855a6913575a7fe3722d7af5
|
||||||
F test/altertab3.test d0d51e652aaa11e37de1f1215181d88334fefcb185f3b9bd91e06e98260c4694
|
F test/altertab3.test d0d51e652aaa11e37de1f1215181d88334fefcb185f3b9bd91e06e98260c4694
|
||||||
F test/decimal.test fcf403fd5585f47342234e153c4a4338cd737b8e0884ac66fc484df47dbcf1a7
|
F test/decimal.test fcf403fd5585f47342234e153c4a4338cd737b8e0884ac66fc484df47dbcf1a7
|
||||||
F test/fts4upfrom.test 8df5acb6e10ad73f393d1add082b042ab1db72567888847d098152121e507b34
|
F test/fts4upfrom.test 8df5acb6e10ad73f393d1add082b042ab1db72567888847d098152121e507b34
|
||||||
F test/fuzzdata8.db 281cbc8166a8bc5843f4a913e803ba76e27905eb02fb9d5cfd581c2429f29855
|
F test/fuzzdata8.db 281cbc8166a8bc5843f4a913e803ba76e27905eb02fb9d5cfd581c2429f29855
|
||||||
F test/triggerupfrom.test 3645a325026619db117683ed1f9da63ec0b9313ff5857f097088c163b291d3fe
|
F test/triggerupfrom.test d25961fa70a99b6736193da7b49a36d8c1d28d56188f0be6406d4366315cd6e4
|
||||||
F test/upfrom1.tcl df984cb88010af1555812af55e9db44c4df50677395b45d1f30b69b1b6c07b73
|
F test/upfrom1.tcl df984cb88010af1555812af55e9db44c4df50677395b45d1f30b69b1b6c07b73
|
||||||
F test/upfrom1.test 2ba1ed45b4a2161fc79f234b9ce4300b0d3deba545e3f23b938fb3ebdbf8758d
|
F test/upfrom1.test 2ba1ed45b4a2161fc79f234b9ce4300b0d3deba545e3f23b938fb3ebdbf8758d
|
||||||
F test/upfrom3.test 2619374c4806913414cc39514630d85bb12489a5f09a5ebdf6fad0fb4df242e2
|
F test/upfrom3.test 2619374c4806913414cc39514630d85bb12489a5f09a5ebdf6fad0fb4df242e2
|
||||||
P 4f6d8d0ebf40029218a1d3b05ea657c0c5953b01c6f0b6a628465aa44c67e7f3 73d62f82f94347c60e026bc9cb859fec2d8b5f0c756df0c4941f11817234bff8
|
P 53b8b507a10364f5d580655d89c950a5f14c2a8114625fd8749d77f289413b22
|
||||||
R 6cb7af85326f5b68b9bed4397b12a467
|
R 50049e7505da24bcfa1309cf7e88265f
|
||||||
U dan
|
U dan
|
||||||
Z effbb38e785e7206fb837507bc0dcd3e
|
Z 6a5f095ea5bbd01f6db55318ec51bead
|
||||||
|
@ -1 +1 @@
|
|||||||
53b8b507a10364f5d580655d89c950a5f14c2a8114625fd8749d77f289413b22
|
5176cb7a6a4e8cfa1973aaae46fcd7d39baedb70ae20bfacc82d62ca39fb0aa3
|
@ -3190,6 +3190,14 @@ struct Select {
|
|||||||
** SRT_DistQueue Store results in priority queue pDest->iSDParm only if
|
** SRT_DistQueue Store results in priority queue pDest->iSDParm only if
|
||||||
** the same record has never been stored before. The
|
** the same record has never been stored before. The
|
||||||
** index at pDest->iSDParm+1 hold all prior stores.
|
** 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_Union 1 /* Store result as keys in an index */
|
||||||
#define SRT_Except 2 /* Remove result from a UNION index */
|
#define SRT_Except 2 /* Remove result from a UNION index */
|
||||||
|
21
src/update.c
21
src/update.c
@ -237,8 +237,8 @@ static void updatePopulateEphTable(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pSelect = sqlite3SelectNew(
|
pSelect = sqlite3SelectNew(pParse, pList,
|
||||||
pParse, pList, pSrc, pWhere2, pGroupBy, 0, pOrderBy2, 0, pLimit2
|
pSrc, pWhere2, pGroupBy, 0, pOrderBy2, SF_IncludeHidden, pLimit2
|
||||||
);
|
);
|
||||||
sqlite3SelectDestInit(&dest, eDest, iEph);
|
sqlite3SelectDestInit(&dest, eDest, iEph);
|
||||||
dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1);
|
dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1);
|
||||||
@ -249,9 +249,11 @@ static void updatePopulateEphTable(
|
|||||||
/*
|
/*
|
||||||
** Process an UPDATE statement.
|
** Process an UPDATE statement.
|
||||||
**
|
**
|
||||||
** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
|
** UPDATE OR IGNORE tbl SET a=b, c=d FROM tbl2... WHERE e<5 AND f NOT NULL;
|
||||||
** \_______/ \________/ \______/ \________________/
|
** \_______/ \_/ \______/ \_____/ \________________/
|
||||||
* onError pTabList pChanges pWhere
|
** onError | pChanges | pWhere
|
||||||
|
** \_______________________/
|
||||||
|
** pTabList
|
||||||
*/
|
*/
|
||||||
void sqlite3Update(
|
void sqlite3Update(
|
||||||
Parse *pParse, /* The parser context */
|
Parse *pParse, /* The parser context */
|
||||||
@ -285,7 +287,7 @@ void sqlite3Update(
|
|||||||
u8 chngRowid; /* Rowid changed in a normal table */
|
u8 chngRowid; /* Rowid changed in a normal table */
|
||||||
u8 chngKey; /* Either chngPk or chngRowid */
|
u8 chngKey; /* Either chngPk or chngRowid */
|
||||||
Expr *pRowidExpr = 0; /* Expression defining the new record number */
|
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 */
|
AuthContext sContext; /* The authorization context */
|
||||||
NameContext sNC; /* The name-context to resolve expressions in */
|
NameContext sNC; /* The name-context to resolve expressions in */
|
||||||
int iDb; /* Database containing the table being updated */
|
int iDb; /* Database containing the table being updated */
|
||||||
@ -309,7 +311,7 @@ void sqlite3Update(
|
|||||||
i16 nPk = 0; /* Number of components of the PRIMARY KEY */
|
i16 nPk = 0; /* Number of components of the PRIMARY KEY */
|
||||||
int bReplace = 0; /* True if REPLACE conflict resolution might happen */
|
int bReplace = 0; /* True if REPLACE conflict resolution might happen */
|
||||||
int bFinishSeek = 1; /* The OP_FinishSeek opcode is needed */
|
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 */
|
/* Register Allocations */
|
||||||
int regRowCount = 0; /* A count of rows changed */
|
int regRowCount = 0; /* A count of rows changed */
|
||||||
@ -348,6 +350,11 @@ void sqlite3Update(
|
|||||||
# undef isView
|
# undef isView
|
||||||
# define isView 0
|
# define isView 0
|
||||||
#endif
|
#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;
|
nChangeFrom = (pTabList->nSrc>1) ? pChanges->nExpr : 0;
|
||||||
assert( nChangeFrom==0 || pUpsert==0 );
|
assert( nChangeFrom==0 || pUpsert==0 );
|
||||||
|
|
||||||
|
@ -115,6 +115,60 @@ do_execsql_test 3.0 {
|
|||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
} {2 TWO}
|
} {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
|
finish_test
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user