]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
If a CHECK constraint is named, report that name on the error message when named-check-constraints
authordrh <drh@noemail.net>
Wed, 7 Mar 2012 19:13:29 +0000 (19:13 +0000)
committerdrh <drh@noemail.net>
Wed, 7 Mar 2012 19:13:29 +0000 (19:13 +0000)
the constraint fails.

FossilOrigin-Name: 9a0f90d9deb335ac71044b8afa81538d85cc7ccf

manifest
manifest.uuid
src/build.c
src/insert.c
src/parse.y
src/sqliteInt.h
test/check.test

index 804df3f20bfecc51e8c0068b1f84cc5202bd7cdc..dc2ab319dbbe0b5c6aada8a3888d1be68ff571ee 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sproblem\scompiling\sthe\stest\scode\sin\sfts3_test.c\swhen\sSQLITE_ENABLE_FTS3\sis\snot\sdefined.
-D 2012-03-05T16:24:26.279
+C If\sa\sCHECK\sconstraint\sis\snamed,\sreport\sthat\sname\son\sthe\serror\smessage\swhen\nthe\sconstraint\sfails.
+D 2012-03-07T19:13:29.390
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 3f79a373e57c3b92dabf76f40b065e719d31ac34
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -128,7 +128,7 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
 F src/btree.c 253c3147a4ebbaee42cd329dbdc0856200bbbda7
 F src/btree.h 48a013f8964f12d944d90e4700df47b72dd6d923
 F src/btreeInt.h 26d8ca625b141927fe6620c1d2cf58eaf494ca0c
-F src/build.c c4d36e527f457f9992a6663365871dfa7c5094b8
+F src/build.c d58d314c5837737e15f94959cb55115347725182
 F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
 F src/ctime.c a9c26822515f81ec21588cbb482ca6724be02e33
@@ -142,7 +142,7 @@ F src/global.c 4cfdca5cb0edd33c4d021baec4ede958cb2c793b
 F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
 F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
-F src/insert.c d7c69718acbb92e10e4b121da7bed13903342962
+F src/insert.c 82b1bc7aaa54d0f058101a034a28d47fe6b70613
 F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
 F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
 F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416
@@ -170,7 +170,7 @@ F src/os_unix.c 0e3d2942d228d0366fb80a3640f35caf413b66d1
 F src/os_win.c 5ac061ae1326a71500cee578ed0fd9113b4f6a37
 F src/pager.c 3955b62cdb5bb64559607cb474dd12a6c8e1d4a5
 F src/pager.h ef1eaf8593e78f73885c1dfac27ad83bee23bdc5
-F src/parse.y 1ddd71ae55f4b7cbb2672526ea4de023de0f519e
+F src/parse.y 180976f414ba0473bffa7049b37aceab1e467175
 F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
 F src/pcache.h 1b5dcc3dc8103d03e625b177023ee67764fa6b7c
 F src/pcache1.c b30b1c35908346ecc43d8d9d17f2ddf6817f8f60
@@ -184,7 +184,7 @@ F src/select.c 44ccdcb5d2a1c48622c179b2d72167b716388581
 F src/shell.c aa28f117033ba3e44b5eaaf2ad572222bcdfd66e
 F src/sqlite.h.in f46e368d1a28b09d876e35444785674d170f2d62
 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
-F src/sqliteInt.h b013dab7d43fb67c3ca2f0253d7863abb37e233c
+F src/sqliteInt.h 306a6f0c6732c0d706dfebfc780a133a38507aee
 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
 F src/status.c 4568e72dfd36b6a5911f93457364deb072e0b03a
 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -320,7 +320,7 @@ F test/capi3c.test 1b5424d2ac57b7b443b5de5b9a287642c02279b6
 F test/capi3d.test 17b57ca28be3e37e14c2ba8f787d292d84b724a1
 F test/capi3e.test f7408dda65c92b9056199fdc180f893015f83dde
 F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
-F test/check.test db2b29d557544347d28e25b8406f5d5ecc3d1bc3
+F test/check.test 06795c188bf1776673fd2ac0787aa1c7238970d8
 F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
 F test/collate1.test e3eaa48c21e150814be1a7b852d2a8af24458d04
 F test/collate2.test 04cebe4a033be319d6ddbb3bbc69464e01700b49
@@ -992,7 +992,10 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
-P 99a9073b5e411ce94f38ce49608baaa15de8b850
-R d0dc4635c0ac977f7342c0a0dac9e48b
-U dan
-Z d6573fd4e75425ab6ee13bee3b518e09
+P b00ccda307caae597c143ab0586f90acb77f79cf
+R 5242d5c6432e029c0fd352c1dbfa159a
+T *branch * named-check-constraints
+T *sym-named-check-constraints *
+T -sym-trunk *
+U drh
+Z 198934e577031b93f87585ac1616330d
index dda6c5d4144f7aa95e27b4eb7b00807dd9bffbf6..65912e34e8a9cb33f3aed787410867515dc0265f 100644 (file)
@@ -1 +1 @@
-b00ccda307caae597c143ab0586f90acb77f79cf
\ No newline at end of file
+9a0f90d9deb335ac71044b8afa81538d85cc7ccf
\ No newline at end of file
index daa5430406027b69aaf1dc38f16f6b8ac935e100..16a9978fcfca576e6f13d01b3f9fd2521b5e3793 100644 (file)
@@ -537,7 +537,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
   sqlite3DbFree(db, pTable->zColAff);
   sqlite3SelectDelete(db, pTable->pSelect);
 #ifndef SQLITE_OMIT_CHECK
-  sqlite3ExprDelete(db, pTable->pCheck);
+  sqlite3ExprListDelete(db, pTable->pCheck);
 #endif
 #ifndef SQLITE_OMIT_VIRTUALTABLE
   sqlite3VtabClear(db, pTable);
@@ -1200,15 +1200,17 @@ void sqlite3AddCheckConstraint(
   Parse *pParse,    /* Parsing context */
   Expr *pCheckExpr  /* The check expression */
 ){
-  sqlite3 *db = pParse->db;
 #ifndef SQLITE_OMIT_CHECK
   Table *pTab = pParse->pNewTable;
   if( pTab && !IN_DECLARE_VTAB ){
-    pTab->pCheck = sqlite3ExprAnd(db, pTab->pCheck, pCheckExpr);
+    pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr);
+    if( pParse->constraintName.n ){
+      sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1);
+    }
   }else
 #endif
   {
-    sqlite3ExprDelete(db, pCheckExpr);
+    sqlite3ExprDelete(pParse->db, pCheckExpr);
   }
 }
 
@@ -1478,6 +1480,8 @@ void sqlite3EndTable(
   if( p->pCheck ){
     SrcList sSrc;                   /* Fake SrcList for pParse->pNewTable */
     NameContext sNC;                /* Name context for pParse->pNewTable */
+    ExprList *pList;                /* List of all CHECK constraints */
+    int i;                          /* Loop counter */
 
     memset(&sNC, 0, sizeof(sNC));
     memset(&sSrc, 0, sizeof(sSrc));
@@ -1488,8 +1492,11 @@ void sqlite3EndTable(
     sNC.pParse = pParse;
     sNC.pSrcList = &sSrc;
     sNC.isCheck = 1;
-    if( sqlite3ResolveExprNames(&sNC, p->pCheck) ){
-      return;
+    pList = p->pCheck;
+    for(i=0; i<pList->nExpr; i++){
+      if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
+        return;
+      }
     }
   }
 #endif /* !defined(SQLITE_OMIT_CHECK) */
index 6b31e24f2c03eed0b3436fc13b32a1bcb3abee72..18ed8cfcf38fa4079a80cf2a96504d09dc5769f5 100644 (file)
@@ -1157,9 +1157,11 @@ void sqlite3GenerateConstraintChecks(
   int regData;        /* Register containing first data column */
   int iCur;           /* Table cursor number */
   Index *pIdx;         /* Pointer to one of the indices */
+  sqlite3 *db;         /* Database connection */
   int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
   int regOldRowid = (rowidChng && isUpdate) ? rowidChng : regRowid;
 
+  db = pParse->db;
   v = sqlite3GetVdbe(pParse);
   assert( v!=0 );
   assert( pTab->pSelect==0 );  /* This table is not a VIEW */
@@ -1192,7 +1194,7 @@ void sqlite3GenerateConstraintChecks(
         char *zMsg;
         sqlite3VdbeAddOp3(v, OP_HaltIfNull,
                                   SQLITE_CONSTRAINT, onError, regData+i);
-        zMsg = sqlite3MPrintf(pParse->db, "%s.%s may not be NULL",
+        zMsg = sqlite3MPrintf(db, "%s.%s may not be NULL",
                               pTab->zName, pTab->aCol[i].zName);
         sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC);
         break;
@@ -1214,18 +1216,28 @@ void sqlite3GenerateConstraintChecks(
   /* Test all CHECK constraints
   */
 #ifndef SQLITE_OMIT_CHECK
-  if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){
-    int allOk = sqlite3VdbeMakeLabel(v);
+  if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
+    ExprList *pCheck = pTab->pCheck;
+    int i;
     pParse->ckBase = regData;
-    sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, SQLITE_JUMPIFNULL);
     onError = overrideError!=OE_Default ? overrideError : OE_Abort;
-    if( onError==OE_Ignore ){
-      sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
-    }else{
-      if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
-      sqlite3HaltConstraint(pParse, onError, 0, 0);
+    for(i=0; i<pCheck->nExpr; i++){
+      int allOk = sqlite3VdbeMakeLabel(v);
+      sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL);
+      if( onError==OE_Ignore ){
+        sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
+      }else{
+        char *zConsName = pCheck->a[i].zName;
+        if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
+        if( zConsName ){
+          zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName);
+        }else{
+          zConsName = sqlite3MPrintf(db, "constraint failed");
+        }
+        sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
+      }
+      sqlite3VdbeResolveLabel(v, allOk);
     }
-    sqlite3VdbeResolveLabel(v, allOk);
   }
 #endif /* !defined(SQLITE_OMIT_CHECK) */
 
@@ -1281,7 +1293,7 @@ void sqlite3GenerateConstraintChecks(
         ** table.
         */
         Trigger *pTrigger = 0;
-        if( pParse->db->flags&SQLITE_RecTriggers ){
+        if( db->flags&SQLITE_RecTriggers ){
           pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
         }
         if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
@@ -1370,7 +1382,7 @@ void sqlite3GenerateConstraintChecks(
         char *zErr;
 
         sqlite3StrAccumInit(&errMsg, 0, 0, 200);
-        errMsg.db = pParse->db;
+        errMsg.db = db;
         zSep = pIdx->nColumn>1 ? "columns " : "column ";
         for(j=0; j<pIdx->nColumn; j++){
           char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
@@ -1394,7 +1406,7 @@ void sqlite3GenerateConstraintChecks(
         Trigger *pTrigger = 0;
         assert( onError==OE_Replace );
         sqlite3MultiWrite(pParse);
-        if( pParse->db->flags&SQLITE_RecTriggers ){
+        if( db->flags&SQLITE_RecTriggers ){
           pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
         }
         sqlite3GenerateRowDelete(
@@ -1724,7 +1736,7 @@ static int xferOptimization(
     }
   }
 #ifndef SQLITE_OMIT_CHECK
-  if( pDest->pCheck && sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
+  if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck, pDest->pCheck) ){
     return 0;   /* Tables have different CHECK constraints.  Ticket #2252 */
   }
 #endif
index ed18e7f973744a1485a042742c5360f55e9097cb..29b58a43df4b924504b92ac2bef4b0ff54835085 100644 (file)
@@ -273,10 +273,10 @@ signed ::= minus_num.
 // "carglist" is a list of additional constraints that come after the
 // column name and column type in a CREATE TABLE statement.
 //
-carglist ::= carglist carg.
+carglist ::= carglist cname ccons.
 carglist ::= .
-carg ::= CONSTRAINT nm ccons.
-carg ::= ccons.
+cname ::= CONSTRAINT nm(X).           {pParse->constraintName = X;}
+cname ::= .                           {pParse->constraintName.n = 0;}
 ccons ::= DEFAULT term(X).            {sqlite3AddDefaultValue(pParse,&X);}
 ccons ::= DEFAULT LP expr(X) RP.      {sqlite3AddDefaultValue(pParse,&X);}
 ccons ::= DEFAULT PLUS term(X).       {sqlite3AddDefaultValue(pParse,&X);}
index cfe8fd64fb8634270d9803947a2714d42e0d2498..dcc2ecec9a325e6d79ad2ec2df7c43e40750047b 100644 (file)
@@ -1274,7 +1274,7 @@ struct Table {
   FKey *pFKey;         /* Linked list of all foreign keys in this table */
   char *zColAff;       /* String defining the affinity of each column */
 #ifndef SQLITE_OMIT_CHECK
-  Expr *pCheck;        /* The AND of all CHECK constraints */
+  ExprList *pCheck;    /* All CHECK constraints */
 #endif
 #ifndef SQLITE_OMIT_ALTERTABLE
   int addColOffset;    /* Offset in CREATE TABLE stmt to add a new column */
@@ -2208,6 +2208,7 @@ struct Parse {
   int regRowid;        /* Register holding rowid of CREATE TABLE entry */
   int regRoot;         /* Register holding root page number for new objects */
   int nMaxArg;         /* Max args passed to user function by sub-program */
+  Token constraintName;/* Name of the constraint currently being parsed */
 #ifndef SQLITE_OMIT_SHARED_CACHE
   int nTableLock;        /* Number of locks in aTableLock */
   TableLock *aTableLock; /* Required table locks for shared-cache mode */
index d2867a096ebc588dc63cba3572682e1eae658822..4d1a44117d78de79c02b1e28abdb37e1e1b55764 100644 (file)
@@ -117,9 +117,9 @@ do_test check-1.17 {
 do_test check-2.1 {
   execsql {
     CREATE TABLE t2(
-      x INTEGER CHECK( typeof(coalesce(x,0))=="integer" ),
-      y REAL CHECK( typeof(coalesce(y,0.1))=='real' ),
-      z TEXT CHECK( typeof(coalesce(z,''))=='text' )
+      x INTEGER CONSTRAINT one CHECK( typeof(coalesce(x,0))=="integer" ),
+      y REAL CONSTRAINT two CHECK( typeof(coalesce(y,0.1))=='real' ),
+      z TEXT CONSTRAINT three CHECK( typeof(coalesce(z,''))=='text' )
     );
   }
 } {}
@@ -141,17 +141,17 @@ do_test check-2.4 {
   catchsql {
     INSERT INTO t2 VALUES(1.1, NULL, NULL);
   }
-} {1 {constraint failed}}
+} {1 {constraint one failed}}
 do_test check-2.5 {
   catchsql {
     INSERT INTO t2 VALUES(NULL, 5, NULL);
   }
-} {1 {constraint failed}}
+} {1 {constraint two failed}}
 do_test check-2.6 {
   catchsql {
     INSERT INTO t2 VALUES(NULL, NULL, 3.14159);
   }
-} {1 {constraint failed}}
+} {1 {constraint three failed}}
 
 ifcapable subquery {
   do_test check-3.1 {