-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
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
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
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
-02fbdbc782dd98f080bf4482d820f36c0ef3d519
\ No newline at end of file
+7782cb1dd5914b867caf5ff2f0f837407abbfd7a
\ No newline at end of file
#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;
}
/*
** 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;
}
/*
for(i=0; i<pCheck->nExpr; 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);
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