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:
parent
bc674334e5
commit
95c0775484
15
manifest
15
manifest
@ -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
|
||||
|
@ -1 +1 @@
|
||||
31eb4abc89e9c0fd90fde5486d4008f9d09fdf4e
|
||||
3391f4139ccfe62cc27739a06567c422ddae9c69
|
@ -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 ){
|
||||
|
15
src/update.c
15
src/update.c
@ -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
88
test/tkt2767.test
Normal 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
|
Loading…
Reference in New Issue
Block a user