]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix to previous check-in: Make sure CHECK constraints involving the ROWID
authordrh <drh@noemail.net>
Wed, 10 Feb 2016 18:24:05 +0000 (18:24 +0000)
committerdrh <drh@noemail.net>
Wed, 10 Feb 2016 18:24:05 +0000 (18:24 +0000)
are not ignored when the ROWID changes.

FossilOrigin-Name: 7782cb1dd5914b867caf5ff2f0f837407abbfd7a

manifest
manifest.uuid
src/insert.c
test/check.test

index bff561c581bda0c7af1db15f75086b2756fe29ed..2a9e362c520c0233ae42581cbef5394b17a97781 100644 (file)
--- 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
index ad9bcac94d65170f93c517ff7a70cb014b1f8d11..18e52299534f016a7baa54948000dac51b2184b7 100644 (file)
@@ -1 +1 @@
-02fbdbc782dd98f080bf4482d820f36c0ef3d519
\ No newline at end of file
+7782cb1dd5914b867caf5ff2f0f837407abbfd7a
\ No newline at end of file
index a77d3e97d57dde4ef530331271c572fe51706c69..8cb26a54aea21610521e63262c0ad4cea742b448 100644 (file)
@@ -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; 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);
index 02b99f2ac9137c18a8507855d083f7393f8da49e..43e447f70d7ad9d5b8c285ccc2681b55fd5b180a 100644 (file)
@@ -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