mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-06 15:49:35 +03:00
If a CHECK constraint is named, report that name on the error message when
the constraint fails. FossilOrigin-Name: 9a0f90d9deb335ac71044b8afa81538d85cc7ccf
This commit is contained in:
25
manifest
25
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
|
||||
|
||||
@@ -1 +1 @@
|
||||
b00ccda307caae597c143ab0586f90acb77f79cf
|
||||
9a0f90d9deb335ac71044b8afa81538d85cc7ccf
|
||||
17
src/build.c
17
src/build.c
@@ -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,10 +1492,13 @@ void sqlite3EndTable(
|
||||
sNC.pParse = pParse;
|
||||
sNC.pSrcList = &sSrc;
|
||||
sNC.isCheck = 1;
|
||||
if( sqlite3ResolveExprNames(&sNC, p->pCheck) ){
|
||||
pList = p->pCheck;
|
||||
for(i=0; i<pList->nExpr; i++){
|
||||
if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_CHECK) */
|
||||
|
||||
/* If the db->init.busy is 1 it means we are reading the SQL off the
|
||||
|
||||
30
src/insert.c
30
src/insert.c
@@ -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,19 +1216,29 @@ 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;
|
||||
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 */
|
||||
sqlite3HaltConstraint(pParse, onError, 0, 0);
|
||||
if( zConsName ){
|
||||
zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName);
|
||||
}else{
|
||||
zConsName = sqlite3MPrintf(db, "constraint failed");
|
||||
}
|
||||
sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
|
||||
}
|
||||
sqlite3VdbeResolveLabel(v, allOk);
|
||||
}
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_CHECK) */
|
||||
|
||||
/* If we have an INTEGER PRIMARY KEY, make sure the primary key
|
||||
@@ -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
|
||||
|
||||
@@ -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);}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user