Fix the code generation for UPDATE and DELETE so that

BEFORE triggers that use RAISE(IGNORE) do not leave extra
values on the stack.  Ticket #2767 (CVS 4535)

FossilOrigin-Name: 3391f4139ccfe62cc27739a06567c422ddae9c69
This commit is contained in:
drh 2007-11-11 18:36:34 +00:00
parent bc674334e5
commit 95c0775484
5 changed files with 114 additions and 14 deletions

View File

@ -1,5 +1,5 @@
C Add\sasserts\son\ssqlite3_mutex_held()\sto\sthe\szero-malloc\smemory\sallocator,\nin\sorder\sto\sprove\sthat\sthe\smutex\sis\sheld\swhen\sit\sis\sneeded.\s(CVS\s4534)
D 2007-11-07T15:13:25
C Fix\sthe\scode\sgeneration\sfor\sUPDATE\sand\sDELETE\sso\sthat\nBEFORE\striggers\sthat\suse\sRAISE(IGNORE)\sdo\snot\sleave\sextra\nvalues\son\sthe\sstack.\s\sTicket\s#2767\s(CVS\s4535)
D 2007-11-11T18:36:34
F Makefile.in 30c7e3ba426ddb253b8ef037d1873425da6009a8
F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@ -88,7 +88,7 @@ F src/build.c d4ace66c2612d8973a17afdfe34b2a62f1a80178
F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
F src/delete.c 849846d06d29851dde0d9f424a5de5817eb140d1
F src/delete.c 034b87768c4135a22038a86a205f9d2d5f68a143
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
F src/expr.c 23fac3749024deeaaa6c25b6b5c521e8d140a2c5
F src/func.c 73b4974e5ff03cc71345cc3a33b0022f7b99974a
@ -161,7 +161,7 @@ F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59
F src/test_thread.c a98d69cae883e53d3686fc25889a5fa5f51439f8
F src/tokenize.c 67e42600ab34f976f2b1288c499ad6c98d652f0e
F src/trigger.c 724a77d54609a33bde90618934fbeddfcc729a10
F src/update.c e89b980b443d44b68bfc0b1746cdb6308e049ac9
F src/update.c 2add92a6159fa73128653706574afbcd8fd1dd80
F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624
F src/vacuum.c a5e51c77370c1a6445e86d42abfc43867cdd482d
@ -465,6 +465,7 @@ F test/tkt2450.test 77ed94863f2049c1420288ddfea2d41e5e0971d6
F test/tkt2640.test c513e7992a602a87ef3a2cc9ca1cba4146924e9b
F test/tkt2643.test 3f3ebb743da00d4fed4fcf6daed92a0e18e57813
F test/tkt2686.test 8815c3eeae7c8363bd7c2889349ec39e8bc8000d
F test/tkt2767.test 6b02308d553d194f329a469bf5c157fe724738d4
F test/trace.test 75ffc1b992c780d054748a656e3e7fd674f18567
F test/trans.test b73289992b46d38d9479ecc4fdc03d8edb2413dc
F test/trigger1.test 7c13f39ca36f529bf856e05c7d004fc0531d48b4
@ -584,7 +585,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
P c1fe27de7b6f0080466cc3f827979db9997e22a4
R 4d22767fe7548ed57a40b50ba1b3d0b1
P 31eb4abc89e9c0fd90fde5486d4008f9d09fdf4e
R a1f586a7644a244540f38fb9992343e8
U drh
Z 591ee87bae6e45cc97f6c36812f304cb
Z 9a344de272865e137595258a6a6021fd

View File

@ -1 +1 @@
31eb4abc89e9c0fd90fde5486d4008f9d09fdf4e
3391f4139ccfe62cc27739a06567c422ddae9c69

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
** $Id: delete.c,v 1.130 2007/08/16 04:30:40 drh Exp $
** $Id: delete.c,v 1.131 2007/11/11 18:36:34 drh Exp $
*/
#include "sqliteInt.h"
@ -277,9 +277,10 @@ void sqlite3DeleteFrom(
** row triggers.
*/
if( triggers_exist ){
int mem1 = pParse->nMem++;
addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end);
sqlite3VdbeAddOp(v, OP_MemStore, mem1, 0);
if( !isView ){
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
}
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
@ -293,6 +294,9 @@ void sqlite3DeleteFrom(
(void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_BEFORE, pTab,
-1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
addr);
if( !isView ){
sqlite3VdbeAddOp(v, OP_MemLoad, mem1, 0);
}
}
if( !isView ){

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.140 2007/08/16 10:09:03 danielk1977 Exp $
** $Id: update.c,v 1.141 2007/11/11 18:36:34 drh Exp $
*/
#include "sqliteInt.h"
@ -318,6 +318,8 @@ void sqlite3Update(
}
if( triggers_exist ){
int mem1; /* Memory address storing the rowid for next row to update */
/* Create pseudo-tables for NEW and OLD
*/
sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
@ -328,10 +330,10 @@ void sqlite3Update(
/* The top of the update loop for when there are triggers.
*/
addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
mem1 = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_MemStore, mem1, 0);
if( !isView ){
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
/* Open a cursor and make it point to the record that is
** being updated.
*/
@ -381,6 +383,11 @@ void sqlite3Update(
newIdx, oldIdx, onError, addr) ){
goto update_cleanup;
}
if( !isView ){
sqlite3VdbeAddOp(v, OP_MemLoad, mem1, 0);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
}
}
if( !isView && !IsVirtual(pTab) ){

88
test/tkt2767.test Normal file
View File

@ -0,0 +1,88 @@
# 2007 Oct 3
#
# 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.
#
#***********************************************************************
#
# This file is to test that ticket #2767 has been fixed.
# Ticket #2767 is for a VDBE stack overflow on BEFORE
# triggers that run RAISE(IGNORE).
#
# $Id: tkt2767.test,v 1.1 2007/11/11 18:36:35 drh Exp $
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_test tkt2767-1.1 {
execsql {
-- Construct a table with many rows of data
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(1);
INSERT INTO t1 VALUES(2);
INSERT INTO t1 SELECT x+2 FROM t1;
INSERT INTO t1 SELECT x+4 FROM t1;
INSERT INTO t1 SELECT x+8 FROM t1;
INSERT INTO t1 SELECT x+16 FROM t1;
-- BEFORE triggers that invoke raise(ignore). The effect of
-- these triggers should be to make INSERTs, UPDATEs, and DELETEs
-- into no-ops.
CREATE TRIGGER r1 BEFORE UPDATE ON t1 BEGIN
SELECT raise(ignore);
END;
CREATE TRIGGER r2 BEFORE DELETE ON t1 BEGIN
SELECT raise(ignore);
END;
CREATE TRIGGER r3 BEFORE INSERT ON t1 BEGIN
SELECT raise(ignore);
END;
-- Verify the table content
SELECT count(*), sum(x) FROM t1;
}
} {32 528}
# Try to delete all elements of the table. This will invoke the
# DELETE trigger 32 times, which should overflow the VDBE stack if
# the problem of #2767 is not fixed. If the problem is fixed, all
# the deletes should be no-ops so the table should remain unchanged.
#
do_test tkt2767-1.2 {
execsql {
DELETE FROM t1 WHERE x>0;
SELECT count(*), sum(x) FROM t1;
}
} {32 528}
# Try to update all elements of the table. This will invoke the
# UPDATE trigger 32 times, which should overflow the VDBE stack if
# the problem of #2767 is not fixed. If the problem is fixed, all
# the updates should be no-ops so the table should remain unchanged.
#
do_test tkt2767-1.3 {
execsql {
UPDATE t1 SET x=x+1;
SELECT count(*), sum(x) FROM t1;
}
} {32 528}
# Invoke the insert trigger. The insert trigger was working
# even prior to the fix of #2767. But it seems good to go ahead
# and verify that it works.
#
do_test tkt2767-1.4 {
execsql {
INSERT INTO t1 SELECT x+32 FROM t1;
SELECT count(*), sum(x) FROM t1;
}
} {32 528}
finish_test