From: drh Date: Wed, 10 Feb 2016 18:24:05 +0000 (+0000) Subject: Fix to previous check-in: Make sure CHECK constraints involving the ROWID X-Git-Tag: version-3.11.0~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=98bfa16db247c4887f4c090269413a0c2248b390;p=thirdparty%2Fsqlite.git Fix to previous check-in: Make sure CHECK constraints involving the ROWID are not ignored when the ROWID changes. FossilOrigin-Name: 7782cb1dd5914b867caf5ff2f0f837407abbfd7a --- diff --git a/manifest b/manifest index bff561c581..2a9e362c52 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Omit\sunnecessary\sCHECK\sconstraints\sin\sUPDATE\sstatements,\swhen\snone\sof\sthe\ncolumns\sreferenced\sin\sthe\sCHECK\sconstraint\sare\smodified. -D 2016-02-10T16:52:24.041 +C Fix\sto\sprevious\scheck-in:\sMake\ssure\sCHECK\sconstraints\sinvolving\sthe\sROWID\nare\snot\signored\swhen\sthe\sROWID\schanges. +D 2016-02-10T18:24:05.782 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 0fe3b22f8e29bcde0533ada7957a5f15835d797a @@ -309,7 +309,7 @@ F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 5b715b726f9705c512d3759c827f2db0f57b6de5 +F src/insert.c 6699f029049ea119b652b1464c92cae9f3813247 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c b1b0880fc474abfab89e737b0ecfde0bd7a60902 F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b @@ -522,7 +522,7 @@ F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82 F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3 F test/cffault.test aadc1f61f8811cb600e3e069acbf8796f472a096 -F test/check.test 5831ddb6f2c687782eaf2e1a07b6e17f24c4f763 +F test/check.test 85a84bfc4be0e83f668747211c7cd45a6721d485 F test/close.test 340bd24cc58b16c6bc01967402755027c37eb815 F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4 F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91 @@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 6a3aaedfb41735996470abbae6d3cd1be1f508b3 -R 5992825785c26c277f0bebde72670a95 +P 02fbdbc782dd98f080bf4482d820f36c0ef3d519 +R 52598be0e985900f7f9c7a3aa6a38f4a U drh -Z 18800c36980a344bd8e3c9fe7e30ed04 +Z c2e03029353f27985e4cc514e9bd561e diff --git a/manifest.uuid b/manifest.uuid index ad9bcac94d..18e5229953 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -02fbdbc782dd98f080bf4482d820f36c0ef3d519 \ No newline at end of file +7782cb1dd5914b867caf5ff2f0f837407abbfd7a \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index a77d3e97d5..8cb26a54ae 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1077,16 +1077,27 @@ insert_cleanup: #undef tmask #endif +/* +** Meanings of bits in of pWalker->eCode for checkConstraintUnchanged() +*/ +#define CKCNSTRNT_COLUMN 0x01 /* CHECK constraint uses a changing column */ +#define CKCNSTRNT_ROWID 0x02 /* CHECK constraint references the ROWID */ + /* This is the Walker callback from checkConstraintUnchanged(). Set +** bit 0x01 of pWalker->eCode if ** pWalker->eCode to 0 if this expression node references any of the ** columns that are being modifed by an UPDATE statement. */ static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_COLUMN - && pExpr->iColumn>=0 - && pWalker->u.aiCol[pExpr->iColumn]>=0 - ){ - pWalker->eCode = 0; + if( pExpr->op==TK_COLUMN ){ + assert( pExpr->iColumn>=0 || pExpr->iColumn==-1 ); + if( pExpr->iColumn>=0 ){ + if( pWalker->u.aiCol[pExpr->iColumn]>=0 ){ + pWalker->eCode |= CKCNSTRNT_COLUMN; + } + }else{ + pWalker->eCode |= CKCNSTRNT_ROWID; + } } return WRC_Continue; } @@ -1094,19 +1105,22 @@ static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){ /* ** pExpr is a CHECK constraint on a row that is being UPDATE-ed. The ** only columns that are modified by the UPDATE are those for which -** aiChng[i]>=0. Return true if CHECK constraint pExpr does not use -** any of the changing columns. In other words, return true if this -** CHECK constraint can be skipped when validating the new row in -** the UPDATE statement. +** aiChng[i]>=0, and also the ROWID is modified if chngRowid is true. +** +** Return true if CHECK constraint pExpr does not use any of the +** changing columns (or the rowid if it is changing). In other words, +** return true if this CHECK constraint can be skipped when validating +** the new row in the UPDATE statement. */ -static int checkConstraintUnchanged(Expr *pExpr, int *aiChng){ +static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){ Walker w; memset(&w, 0, sizeof(w)); - w.eCode = 1; + w.eCode = 0; w.xExprCallback = checkConstraintExprNode; w.u.aiCol = aiChng; sqlite3WalkExpr(&w, pExpr); - return w.eCode; + if( !chngRowid ) w.eCode &= ~CKCNSTRNT_ROWID; + return !w.eCode; } /* @@ -1308,7 +1322,7 @@ void sqlite3GenerateConstraintChecks( for(i=0; inExpr; i++){ int allOk = sqlite3VdbeMakeLabel(v); Expr *pExpr = pCheck->a[i].pExpr; - if( aiChng && checkConstraintUnchanged(pExpr, aiChng) ) continue; + if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue; sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL); if( onError==OE_Ignore ){ sqlite3VdbeGoto(v, ignoreDest); diff --git a/test/check.test b/test/check.test index 02b99f2ac9..43e447f70d 100644 --- a/test/check.test +++ b/test/check.test @@ -459,4 +459,24 @@ do_execsql_test 8.1 { CREATE TABLE t811(b, CHECK( xyzzy.t811.b BETWEEN 5 AND 10 )); } {} +# Make sure check constraints involving the ROWID are not ignored +# +do_execsql_test 9.1 { + CREATE TABLE t1( + a INTEGER PRIMARY KEY, + b INTEGER NOT NULL CONSTRAINT 'b-check' CHECK( b>a ), + c INTEGER NOT NULL CONSTRAINT 'c-check' CHECK( c>rowid*2 ), + d INTEGER NOT NULL CONSTRAINT 'd-check' CHECK( d BETWEEN b AND c ) + ); + INSERT INTO t1(a,b,c,d) VALUES(1,2,4,3),(2,4,6,5),(3,10,30,20); +} {} +do_catchsql_test 9.2 { + UPDATE t1 SET b=0 WHERE a=1; +} {1 {CHECK constraint failed: b-check}} +do_catchsql_test 9.3 { + UPDATE t1 SET c=a*2 WHERE a=1; +} {1 {CHECK constraint failed: c-check}} + + + finish_test