When materializing a view for an UPDATE or DELETE make use of the WHERE
clause to limit the number of rows materialized. Ticket #2938. (CVS 4782) FossilOrigin-Name: 5ab71c3a79cac04cb2c576f83a62218d05571006
This commit is contained in:
parent
8e5b5f8e54
commit
0f35a6b529
19
manifest
19
manifest
@ -1,5 +1,5 @@
|
||||
C ALTER\sTABLE\suses\sdouble-quotes\sfor\squoting\stable\snames.\s(CVS\s4781)
|
||||
D 2008-02-09T14:30:30
|
||||
C When\smaterializing\sa\sview\sfor\san\sUPDATE\sor\sDELETE\smake\suse\sof\sthe\sWHERE\nclause\sto\slimit\sthe\snumber\sof\srows\smaterialized.\s\sTicket\s#2938.\s(CVS\s4782)
|
||||
D 2008-02-12T16:52:14
|
||||
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
||||
F Makefile.in bc2b5df3e3d0d4b801b824b7ef6dec43812b049b
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -90,7 +90,7 @@ F src/build.c 7d93ee565b5676746d014acdc638adee87cfd27e
|
||||
F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
|
||||
F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
|
||||
F src/date.c 8ce763c68143b1e8fb6f79dcfc8b801853c97017
|
||||
F src/delete.c 220570cc99f1461b00a8e1b417d9254ec3588f94
|
||||
F src/delete.c fa13c296262e89c32d28949f15be275e52d7f524
|
||||
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
|
||||
F src/expr.c e6fb42c6e55fd9526174b1cb8296b69a60a6688a
|
||||
F src/fault.c 049b88b8ba0a1db3240aeaf9695cd08b9a3ba9e1
|
||||
@ -137,7 +137,7 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
||||
F src/shell.c ca06cb687c40a8bff6307b5fad41a0e86a0f8558
|
||||
F src/sqlite.h.in 690736613958e0f462e08ae2a9136fa335214edc
|
||||
F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
|
||||
F src/sqliteInt.h 9dabb5a68e1952a556b78558c87e26af2fdb5ddb
|
||||
F src/sqliteInt.h e4ca11fff0cdac38551b75a2a278edb8ad9e1f00
|
||||
F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e
|
||||
F src/table.c 46ccf9b7892a86f57420ae7bac69ecd5e72d26b5
|
||||
F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf
|
||||
@ -166,7 +166,7 @@ F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59
|
||||
F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
|
||||
F src/tokenize.c c4b79fd48ddb709b2b8522b7d93a5a3d98168ca4
|
||||
F src/trigger.c 9bd3b6fa0beff4a02d262c96466f752ec15a7fc3
|
||||
F src/update.c 31edd9c9764e80753930bd5f9b43e0edb404636f
|
||||
F src/update.c 9b3be169cd2a0b065717164aa0f90aa48f34aed1
|
||||
F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
|
||||
F src/util.c c56e41ed4769c1f2b8af9ffde4757a7b4fb08ed1
|
||||
F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
|
||||
@ -195,7 +195,7 @@ F test/attach.test 4ab582932e3c815689f61afcdb9bce245f0bac53
|
||||
F test/attach2.test a295d2d7061adcee5884ef4a93c7c96a82765437
|
||||
F test/attach3.test 7b92dc8e40c1ebca9732ca6f2d3fefbd46f196df
|
||||
F test/attachmalloc.test 56c5e55563dba6d64641ef2f70ce06900df16912
|
||||
F test/auth.test be181f70ced0c84ecb5e2515d9b620f89f6a7b87
|
||||
F test/auth.test d5896499f901eeda88c9f441b13aaccf22d5ceee
|
||||
F test/auth2.test 65ac294b8d52cbdd463f61e77ad0165268373126
|
||||
F test/autoinc.test 0555aa5c789520f16d86a39c6c49b87998e01bea
|
||||
F test/autovacuum.test 4339e66003b9cf813dd667a83aed2dee27c4c36d
|
||||
@ -507,6 +507,7 @@ F test/trigger6.test 0e411654f122552da6590f0b4e6f781048a4a9b9
|
||||
F test/trigger7.test 0afa870be2ce1b132cdb85b17a4a4ef45aa8cece
|
||||
F test/trigger8.test 3a09275aa2214fdff56f731b1e775d8dfee4408a
|
||||
F test/trigger9.test b42703c378916d52a5e240ba98b25b155d3927a3
|
||||
F test/triggerA.test 8dbf5bffa3190bd513785a24a573a166a885fc1b
|
||||
F test/types.test 98e7a631bddf0806204358b452b02d0e319318a6
|
||||
F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84
|
||||
F test/types3.test b730a7db03ef69f0fdb85b2addc20d1a0a04039b
|
||||
@ -616,7 +617,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||
P 63915b54cfb41c2361c387636aa904145b166411
|
||||
R 4cb42b2925ae8f45e9151c56cf51f1f9
|
||||
P 607247c27b80520b8c25c489757288b8ea186f9e
|
||||
R 6e7459c99c887be282a1c6ce2d461da7
|
||||
U drh
|
||||
Z 3b52650fd58593f0d3eb3e17a3cd9c37
|
||||
Z 584629669827c756e74626290b2a5564
|
||||
|
@ -1 +1 @@
|
||||
607247c27b80520b8c25c489757288b8ea186f9e
|
||||
5ab71c3a79cac04cb2c576f83a62218d05571006
|
59
src/delete.c
59
src/delete.c
@ -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.160 2008/01/25 15:04:50 drh Exp $
|
||||
** $Id: delete.c,v 1.161 2008/02/12 16:52:14 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -81,6 +81,39 @@ void sqlite3OpenTable(
|
||||
}
|
||||
|
||||
|
||||
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
|
||||
/*
|
||||
** Evaluate a view and store its result in an ephemeral table. The
|
||||
** pWhere argument is an optional WHERE clause that restricts the
|
||||
** set of rows in the view that are to be added to the ephemeral table.
|
||||
*/
|
||||
void sqlite3MaterializeView(
|
||||
Parse *pParse, /* Parsing context */
|
||||
Select *pView, /* View definition */
|
||||
Expr *pWhere, /* Optional WHERE clause to be added */
|
||||
u32 col_mask, /* Render only the columns in this mask. */
|
||||
int iCur /* Cursor number for ephemerial table */
|
||||
){
|
||||
SelectDest dest;
|
||||
Select *pDup;
|
||||
sqlite3 *db = pParse->db;
|
||||
|
||||
pDup = sqlite3SelectDup(db, pView);
|
||||
if( pWhere ){
|
||||
SrcList *pFrom;
|
||||
|
||||
pWhere = sqlite3ExprDup(db, pWhere);
|
||||
pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, 0, pDup, 0, 0);
|
||||
pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
sqlite3SelectMask(pParse, pDup, col_mask);
|
||||
sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
|
||||
sqlite3Select(pParse, pDup, &dest, 0, 0, 0, 0);
|
||||
sqlite3SelectDelete(pDup);
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */
|
||||
|
||||
|
||||
/*
|
||||
** Generate code for a DELETE FROM statement.
|
||||
**
|
||||
@ -170,19 +203,13 @@ void sqlite3DeleteFrom(
|
||||
oldIdx = pParse->nTab++;
|
||||
}
|
||||
|
||||
/* Resolve the column names in the WHERE clause.
|
||||
/* Assign cursor number to the table and all its indices.
|
||||
*/
|
||||
assert( pTabList->nSrc==1 );
|
||||
iCur = pTabList->a[0].iCursor = pParse->nTab++;
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
pParse->nTab++;
|
||||
}
|
||||
memset(&sNC, 0, sizeof(sNC));
|
||||
sNC.pParse = pParse;
|
||||
sNC.pSrcList = pTabList;
|
||||
if( sqlite3ExprResolveNames(&sNC, pWhere) ){
|
||||
goto delete_from_cleanup;
|
||||
}
|
||||
|
||||
/* Start the view context
|
||||
*/
|
||||
@ -221,14 +248,16 @@ void sqlite3DeleteFrom(
|
||||
** a ephemeral table.
|
||||
*/
|
||||
if( isView ){
|
||||
SelectDest dest;
|
||||
Select *pView;
|
||||
sqlite3MaterializeView(pParse, pTab->pSelect, pWhere, old_col_mask, iCur);
|
||||
}
|
||||
|
||||
pView = sqlite3SelectDup(db, pTab->pSelect);
|
||||
sqlite3SelectMask(pParse, pView, old_col_mask);
|
||||
sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
|
||||
sqlite3Select(pParse, pView, &dest, 0, 0, 0, 0);
|
||||
sqlite3SelectDelete(pView);
|
||||
/* Resolve the column names in the WHERE clause.
|
||||
*/
|
||||
memset(&sNC, 0, sizeof(sNC));
|
||||
sNC.pParse = pParse;
|
||||
sNC.pSrcList = pTabList;
|
||||
if( sqlite3ExprResolveNames(&sNC, pWhere) ){
|
||||
goto delete_from_cleanup;
|
||||
}
|
||||
|
||||
/* Initialize the counter of the number of rows deleted, if
|
||||
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.659 2008/02/02 04:47:09 danielk1977 Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.660 2008/02/12 16:52:14 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
@ -1826,6 +1826,7 @@ void sqlite3RegisterDateTimeFunctions(sqlite3*);
|
||||
int sqlite3SafetyCheckOk(sqlite3*);
|
||||
int sqlite3SafetyCheckSickOrOk(sqlite3*);
|
||||
void sqlite3ChangeCookie(Parse*, int);
|
||||
void sqlite3MaterializeView(Parse*, Select*, Expr*, u32, int);
|
||||
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
|
||||
|
24
src/update.c
24
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.170 2008/01/19 03:35:59 drh Exp $
|
||||
** $Id: update.c,v 1.171 2008/02/12 16:52:14 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -289,13 +289,6 @@ void sqlite3Update(
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Resolve the column names in all the expressions in the
|
||||
** WHERE clause.
|
||||
*/
|
||||
if( sqlite3ExprResolveNames(&sNC, pWhere) ){
|
||||
goto update_cleanup;
|
||||
}
|
||||
|
||||
/* Start the view context
|
||||
*/
|
||||
if( isView ){
|
||||
@ -335,14 +328,15 @@ void sqlite3Update(
|
||||
** a ephemeral table.
|
||||
*/
|
||||
if( isView ){
|
||||
Select *pView;
|
||||
SelectDest dest;
|
||||
sqlite3MaterializeView(pParse, pTab->pSelect, pWhere,
|
||||
old_col_mask|new_col_mask, iCur);
|
||||
}
|
||||
|
||||
pView = sqlite3SelectDup(db, pTab->pSelect);
|
||||
sqlite3SelectMask(pParse, pView, old_col_mask|new_col_mask);
|
||||
sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
|
||||
sqlite3Select(pParse, pView, &dest, 0, 0, 0, 0);
|
||||
sqlite3SelectDelete(pView);
|
||||
/* Resolve the column names in all the expressions in the
|
||||
** WHERE clause.
|
||||
*/
|
||||
if( sqlite3ExprResolveNames(&sNC, pWhere) ){
|
||||
goto update_cleanup;
|
||||
}
|
||||
|
||||
/* Begin the database scan
|
||||
|
@ -12,7 +12,7 @@
|
||||
# focus of this script is testing the sqlite3_set_authorizer() API
|
||||
# and related functionality.
|
||||
#
|
||||
# $Id: auth.test,v 1.40 2008/01/01 19:02:09 danielk1977 Exp $
|
||||
# $Id: auth.test,v 1.41 2008/02/12 16:52:14 drh Exp $
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
@ -2245,13 +2245,15 @@ do_test auth-4.3 {
|
||||
set authargs
|
||||
} [list \
|
||||
SQLITE_UPDATE v1 x main {} \
|
||||
SQLITE_READ v1 x main {} \
|
||||
SQLITE_INSERT v1chng {} main r2 \
|
||||
SQLITE_READ v1 x main r2 \
|
||||
SQLITE_READ v1 x main r2 \
|
||||
SQLITE_READ t2 a main v1 \
|
||||
SQLITE_READ t2 b main v1 \
|
||||
SQLITE_SELECT {} {} {} v1]
|
||||
SQLITE_SELECT {} {} {} v1 \
|
||||
SQLITE_SELECT {} {} {} v1 \
|
||||
SQLITE_READ v1 x main v1 \
|
||||
]
|
||||
do_test auth-4.4 {
|
||||
execsql {
|
||||
CREATE TRIGGER r3 INSTEAD OF DELETE ON v1 BEGIN
|
||||
@ -2268,12 +2270,14 @@ do_test auth-4.5 {
|
||||
set authargs
|
||||
} [list \
|
||||
SQLITE_DELETE v1 {} main {} \
|
||||
SQLITE_READ v1 x main {} \
|
||||
SQLITE_INSERT v1chng {} main r3 \
|
||||
SQLITE_READ v1 x main r3 \
|
||||
SQLITE_READ t2 a main v1 \
|
||||
SQLITE_READ t2 b main v1 \
|
||||
SQLITE_SELECT {} {} {} v1]
|
||||
SQLITE_SELECT {} {} {} v1 \
|
||||
SQLITE_SELECT {} {} {} v1 \
|
||||
SQLITE_READ v1 x main v1 \
|
||||
]
|
||||
|
||||
} ;# ifcapable view && trigger
|
||||
|
||||
|
230
test/triggerA.test
Normal file
230
test/triggerA.test
Normal file
@ -0,0 +1,230 @@
|
||||
# 2008 February 12
|
||||
#
|
||||
# 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 implements regression tests for SQLite library. Specifically,
|
||||
# it tests issues relating to firing an INSTEAD OF trigger on a VIEW
|
||||
# when one tries to UPDATE or DELETE from the view. Does the WHERE
|
||||
# clause of the UPDATE or DELETE statement get passed down correctly
|
||||
# into the query that manifests the view?
|
||||
#
|
||||
# Ticket #2938
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable {!trigger} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# Create two table containing some sample data
|
||||
#
|
||||
do_test triggerA-1.1 {
|
||||
db eval {
|
||||
CREATE TABLE t1(x INTEGER PRIMARY KEY, y TEXT UNIQUE);
|
||||
CREATE TABLE t2(a INTEGER PRIMARY KEY, b INTEGER UNIQUE, c TEXT);
|
||||
}
|
||||
set i 1
|
||||
foreach word {one two three four five six seven eight nine ten} {
|
||||
set j [expr {$i*100 + [string length $word]}]
|
||||
db eval {
|
||||
INSERT INTO t1 VALUES($i,$word);
|
||||
INSERT INTO t2 VALUES(20-$i,$j,$word);
|
||||
}
|
||||
incr i
|
||||
}
|
||||
db eval {
|
||||
SELECT count(*) FROM t1 UNION ALL SELECT count(*) FROM t2;
|
||||
}
|
||||
} {10 10}
|
||||
|
||||
# Create views of various forms against one or both of the two tables.
|
||||
#
|
||||
do_test triggerA-1.2 {
|
||||
db eval {
|
||||
CREATE VIEW v1 AS SELECT y, x FROM t1;
|
||||
SELECT * FROM v1 ORDER BY 1;
|
||||
}
|
||||
} {eight 8 five 5 four 4 nine 9 one 1 seven 7 six 6 ten 10 three 3 two 2}
|
||||
do_test triggerA-1.3 {
|
||||
db eval {
|
||||
CREATE VIEW v2 AS SELECT x, y FROM t1 WHERE y GLOB '*e*';
|
||||
SELECT * FROM v2 ORDER BY 1;
|
||||
}
|
||||
} {1 one 3 three 5 five 7 seven 8 eight 9 nine 10 ten}
|
||||
do_test triggerA-1.4 {
|
||||
db eval {
|
||||
CREATE VIEW v3 AS
|
||||
SELECT CAST(x AS TEXT) AS c1 FROM t1 UNION SELECT y FROM t1;
|
||||
SELECT * FROM v3 ORDER BY c1;
|
||||
}
|
||||
} {1 10 2 3 4 5 6 7 8 9 eight five four nine one seven six ten three two}
|
||||
do_test triggerA-1.5 {
|
||||
db eval {
|
||||
CREATE VIEW v4 AS
|
||||
SELECT CAST(x AS TEXT) AS c1 FROM t1
|
||||
UNION SELECT y FROM t1 WHERE x BETWEEN 3 and 5;
|
||||
SELECT * FROM v4 ORDER BY 1;
|
||||
}
|
||||
} {1 10 2 3 4 5 6 7 8 9 five four three}
|
||||
do_test triggerA-1.6 {
|
||||
db eval {
|
||||
CREATE VIEW v5 AS SELECT x, b FROM t1, t2 WHERE y=c;
|
||||
SELECT * FROM v5;
|
||||
}
|
||||
} {1 103 2 203 3 305 4 404 5 504 6 603 7 705 8 805 9 904 10 1003}
|
||||
|
||||
# Create INSTEAD OF triggers on the views. Run UPDATE and DELETE statements
|
||||
# using those triggers. Verify correct operation.
|
||||
#
|
||||
do_test triggerA-2.1 {
|
||||
db eval {
|
||||
CREATE TABLE result2(a,b);
|
||||
CREATE TRIGGER r1d INSTEAD OF DELETE ON v1 BEGIN
|
||||
INSERT INTO result2(a,b) VALUES(old.y, old.x);
|
||||
END;
|
||||
DELETE FROM v1 WHERE x=5;
|
||||
SELECT * FROM result2;
|
||||
}
|
||||
} {five 5}
|
||||
do_test triggerA-2.2 {
|
||||
db eval {
|
||||
CREATE TABLE result4(a,b,c,d);
|
||||
CREATE TRIGGER r1u INSTEAD OF UPDATE ON v1 BEGIN
|
||||
INSERT INTO result4(a,b,c,d) VALUES(old.y, old.x, new.y, new.x);
|
||||
END;
|
||||
UPDATE v1 SET y=y||'-extra' WHERE x BETWEEN 3 AND 5;
|
||||
SELECT * FROM result4 ORDER BY a;
|
||||
}
|
||||
} {five 5 five-extra 5 four 4 four-extra 4 three 3 three-extra 3}
|
||||
|
||||
|
||||
do_test triggerA-2.3 {
|
||||
db eval {
|
||||
DELETE FROM result2;
|
||||
CREATE TRIGGER r2d INSTEAD OF DELETE ON v2 BEGIN
|
||||
INSERT INTO result2(a,b) VALUES(old.y, old.x);
|
||||
END;
|
||||
DELETE FROM v2 WHERE x=5;
|
||||
SELECT * FROM result2;
|
||||
}
|
||||
} {five 5}
|
||||
do_test triggerA-2.4 {
|
||||
db eval {
|
||||
DELETE FROM result4;
|
||||
CREATE TRIGGER r2u INSTEAD OF UPDATE ON v2 BEGIN
|
||||
INSERT INTO result4(a,b,c,d) VALUES(old.y, old.x, new.y, new.x);
|
||||
END;
|
||||
UPDATE v2 SET y=y||'-extra' WHERE x BETWEEN 3 AND 5;
|
||||
SELECT * FROM result4 ORDER BY a;
|
||||
}
|
||||
} {five 5 five-extra 5 three 3 three-extra 3}
|
||||
|
||||
|
||||
do_test triggerA-2.5 {
|
||||
db eval {
|
||||
CREATE TABLE result1(a);
|
||||
CREATE TRIGGER r3d INSTEAD OF DELETE ON v3 BEGIN
|
||||
INSERT INTO result1(a) VALUES(old.c1);
|
||||
END;
|
||||
DELETE FROM v3 WHERE c1 BETWEEN '8' AND 'eight';
|
||||
SELECT * FROM result1 ORDER BY a;
|
||||
}
|
||||
} {8 9 eight}
|
||||
do_test triggerA-2.6 {
|
||||
db eval {
|
||||
DELETE FROM result2;
|
||||
CREATE TRIGGER r3u INSTEAD OF UPDATE ON v3 BEGIN
|
||||
INSERT INTO result2(a,b) VALUES(old.c1, new.c1);
|
||||
END;
|
||||
UPDATE v3 SET c1 = c1 || '-extra' WHERE c1 BETWEEN '8' and 'eight';
|
||||
SELECT * FROM result2 ORDER BY a;
|
||||
}
|
||||
} {8 8-extra 9 9-extra eight eight-extra}
|
||||
|
||||
|
||||
do_test triggerA-2.7 {
|
||||
db eval {
|
||||
DELETE FROM result1;
|
||||
CREATE TRIGGER r4d INSTEAD OF DELETE ON v4 BEGIN
|
||||
INSERT INTO result1(a) VALUES(old.c1);
|
||||
END;
|
||||
DELETE FROM v4 WHERE c1 BETWEEN '8' AND 'eight';
|
||||
SELECT * FROM result1 ORDER BY a;
|
||||
}
|
||||
} {8 9}
|
||||
do_test triggerA-2.8 {
|
||||
db eval {
|
||||
DELETE FROM result2;
|
||||
CREATE TRIGGER r4u INSTEAD OF UPDATE ON v4 BEGIN
|
||||
INSERT INTO result2(a,b) VALUES(old.c1, new.c1);
|
||||
END;
|
||||
UPDATE v4 SET c1 = c1 || '-extra' WHERE c1 BETWEEN '8' and 'eight';
|
||||
SELECT * FROM result2 ORDER BY a;
|
||||
}
|
||||
} {8 8-extra 9 9-extra}
|
||||
|
||||
|
||||
do_test triggerA-2.9 {
|
||||
db eval {
|
||||
DELETE FROM result2;
|
||||
CREATE TRIGGER r5d INSTEAD OF DELETE ON v5 BEGIN
|
||||
INSERT INTO result2(a,b) VALUES(old.x, old.b);
|
||||
END;
|
||||
DELETE FROM v5 WHERE x=5;
|
||||
SELECT * FROM result2;
|
||||
}
|
||||
} {5 504}
|
||||
do_test triggerA-2.10 {
|
||||
db eval {
|
||||
DELETE FROM result4;
|
||||
CREATE TRIGGER r5u INSTEAD OF UPDATE ON v5 BEGIN
|
||||
INSERT INTO result4(a,b,c,d) VALUES(old.x, old.b, new.x, new.b);
|
||||
END;
|
||||
UPDATE v5 SET b = b+9900000 WHERE x BETWEEN 3 AND 5;
|
||||
SELECT * FROM result4 ORDER BY a;
|
||||
}
|
||||
} {3 305 3 9900305 4 404 4 9900404 5 504 5 9900504}
|
||||
|
||||
# Only run the reamining tests if memory debugging is turned on.
|
||||
#
|
||||
ifcapable !memdebug {
|
||||
puts "Skipping triggerA malloc tests: not compiled with -DSQLITE_MEMDEBUG..."
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
source $testdir/malloc_common.tcl
|
||||
|
||||
# Save a copy of the current database configuration.
|
||||
#
|
||||
db close
|
||||
file delete -force test.db-triggerA
|
||||
file copy test.db test.db-triggerA
|
||||
sqlite3 db test.db
|
||||
|
||||
# Run malloc tests on the INSTEAD OF trigger firing.
|
||||
#
|
||||
do_malloc_test triggerA-3 -tclprep {
|
||||
db close
|
||||
file delete -force test.db test.db-journal
|
||||
file copy -force test.db-triggerA test.db
|
||||
sqlite3 db test.db
|
||||
sqlite3_extended_result_codes db 1
|
||||
db eval {SELECT * FROM v5; -- warm up the cache}
|
||||
} -sqlbody {
|
||||
DELETE FROM v5 WHERE x=5;
|
||||
UPDATE v5 SET b=b+9900000 WHERE x BETWEEN 3 AND 5;
|
||||
}
|
||||
|
||||
# Clean up the saved database copy.
|
||||
#
|
||||
file delete -force test.db-triggerA
|
||||
|
||||
finish_test
|
Loading…
x
Reference in New Issue
Block a user