Provide a more informative error message when a uniqueness constraint

fails.  Ticket #419. (CVS 1068)

FossilOrigin-Name: 086aa1c9922b7bf399b3ee8b73ba7353d126b119
This commit is contained in:
drh 2003-08-05 13:13:38 +00:00
parent 4305d10360
commit 37ed48ed2f
11 changed files with 107 additions and 54 deletions

View File

@ -1,5 +1,5 @@
C The\s{quote:\sSrcList}\sobject\swas\snot\sbeing\sexpanded\scorrectly\sby\sa\scall\sto\r\nsqliteSrcListAppend()\sif\sthe\s{quote:\sSrcList}\shad\spreviously\sbeen\sduplicated\sby\r\na\scall\sto\ssqliteSrcListDup().\s\sTicket\s#416.\sThis\scheck-in\sfixes\sthat\sproblem\r\nby\skeeping\sa\sseparate\snAlloc\sfield\son\s{quote:\sSrcList}.\s\sA\ssimilar\schange\sis\smade\r\nto\s{quote:\sIdList}\sand\s{quote:\sExprList}\sto\savoid\sfuture\sproblems.\s(CVS\s1067)
D 2003-07-30T12:34:12
C Provide\sa\smore\sinformative\serror\smessage\swhen\sa\suniqueness\sconstraint\nfails.\s\sTicket\s#419.\s(CVS\s1068)
D 2003-08-05T13:13:38
F Makefile.in 9ad23ed4ca97f9670c4496432e3fbd4b3760ebde
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@ -32,7 +32,7 @@ F src/expr.c 03c321ac66c1e998c2e0faf22184b5a808b559ca
F src/func.c 6b23578d48a8be98a664db145a635c2fa9ddb57b
F src/hash.c 058f077c1f36f266581aa16f907a3903abf64aa3
F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8
F src/insert.c fc4c26a0bb505fb802babfb9a7b7a1d4be2e3061
F src/insert.c dc200ae04a36bd36e575272a069e20c528b7fbdf
F src/main.c 2500392bad5629b6d70b06ac5a076958acb49b92
F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
F src/os.c b0ae51da6e2ec7dd9f48f92ac88985d5fde8c1d5
@ -74,9 +74,9 @@ F test/btree3.test e597fb59be2ac0ea69c62aaa2064e998e528b665
F test/btree3rb.test 127efcf5cdfcc352054e7db12622b01cdd8b36ac
F test/btree4.test fa955a3d7a8bc91d6084b7f494f9e5d1bdfb15b6
F test/btree4rb.test ae6f0438512edcb45cf483471cd6070a765963a9
F test/capi2.test 9634deaa27449e684f4b69ea2ccd8a77ee130bb8
F test/conflict.test 0a66a573b8b4f8b781b2ebb7d4f27dcfd9e87312
F test/copy.test c860847f1bd66175ef7cb724326a1700e0295820
F test/capi2.test ec96e0e235d87b53cbaef3d8e3e0f8ccf32c71ca
F test/conflict.test 0911bb2f079046914a6e9c3341b36658c4e2103e
F test/copy.test cfd2e9cd738081d9c0a3977acd9e4d0538afde84
F test/delete.test 92256384f1801760180ded129f7427884cf28886
F test/expr.test 48bc6400627532ec97e233809e33d336468bc84c
F test/fkey1.test d65c824459916249bee501532d6154ddab0b5db7
@ -93,10 +93,10 @@ F test/limit.test fa2a8b3fe377ebe60e0bc9a6a35af9ac4eb3d2b3
F test/lock.test 388a3a10962d2d571c0c1821cc35bf069ee73473
F test/main.test 6a851b5992c4881a725a3d9647e629199df8de9d
F test/malloc.test 7ba32a9ebd3aeed52ae4aaa6d42ca37e444536fd
F test/memdb.test cd4580f466f34c42354612a375c5adb90447e4c4
F test/memdb.test 6ece25c7c0e6500199d3662607a3edca081abb2a
F test/memleak.test a18e6810cae96d2f6f5136920267adbefc8e1e90
F test/minmax.test 6d9b6d6ee34f42e2a58dffece1f76d35f446b3af
F test/misc1.test c7dc2f2bd702d8283e885a64ec0714be26cfb051
F test/misc1.test 0b98d493b0cf55cb5f53e1f3df8107c166eecb5a
F test/misc2.test 6400032fe041360f717f501930585498853d79ae
F test/misuse.test a3aa2b18a97e4c409a1fcaff5151a4dd804a0162
F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0
@ -122,11 +122,11 @@ F test/temptable.test c82bd6f800f10e8cf96921af6315e5f1c21e2692
F test/tester.tcl 2671536d3650c29e7c105219f277568b0884cb58
F test/trans.test 75e7a171b5d2d94ee56766459113e2ad0e5f809d
F test/trigger1.test 6efd402da3b74e2d9e6a42b8a97413575fbf48f6
F test/trigger2.test b17223c35fe97bdca542a049774a2496afef0bb9
F test/trigger2.test 22aa0519ae18cf83568c7fba7b8cee893dd6b824
F test/trigger3.test a95ccace88291449f5eae7139ec438a42f90654d
F test/trigger4.test 542afce45774e8f8e1130b96b8675f414d6e4bd8
F test/unique.test 426580d01af47d44bea67aaf66007bd41a63e841
F test/update.test 3ddb0ece1f99ae4deeaa6e6798a0608e167f9444
F test/unique.test 0e38d4cc7affeef2527720d1dafd1f6870f02f2b
F test/update.test 2ef5a6655f2966f0aef733a9f4495b3fe8e16809
F test/vacuum.test 4d8c8af30338577af03e563bc815d7898ae65258
F test/version.test 605fd0d7e7d571370c32b12dbf395b58953de246
F test/view.test 1ee12c6f8f4791a2c0655120d5562a49400cfe53
@ -168,7 +168,7 @@ F www/speed.tcl 2f6b1155b99d39adb185f900456d1d592c4832b3
F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
P 09c10fe3c99cffc64ed02c2929f206d99c8e3309
R d2bc63b0694faef8c02f9403066fd889
P da6273255471673841fdcadc688aeac80722e130
R 1c0d64f5eac1f91d3d759569b9f6d88e
U drh
Z 6699c88f8cb611bb62eca292eb62c177
Z cf08853c7690373b766f29a37d61c34c

View File

@ -1 +1 @@
da6273255471673841fdcadc688aeac80722e130
086aa1c9922b7bf399b3ee8b73ba7353d126b119

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.88 2003/06/04 16:24:39 drh Exp $
** $Id: insert.c,v 1.89 2003/08/05 13:13:38 drh Exp $
*/
#include "sqliteInt.h"
@ -817,8 +817,30 @@ void sqliteGenerateConstraintChecks(
case OE_Rollback:
case OE_Abort:
case OE_Fail: {
int j, n1, n2;
char zErrMsg[200];
strcpy(zErrMsg, pIdx->nColumn>1 ? "columns " : "column ");
n1 = strlen(zErrMsg);
for(j=0; j<pIdx->nColumn && n1<sizeof(zErrMsg)-30; j++){
char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
n2 = strlen(zCol);
if( j>0 ){
strcpy(&zErrMsg[n1], ", ");
n1 += 2;
}
if( n1+n2>sizeof(zErrMsg)-30 ){
strcpy(&zErrMsg[n1], "...");
n1 += 3;
break;
}else{
strcpy(&zErrMsg[n1], zCol);
n1 += n2;
}
}
strcpy(&zErrMsg[n1],
pIdx->nColumn>1 ? " are not unique" : " is not unique");
sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError);
sqliteVdbeChangeP3(v, -1, "uniqueness constraint failed", P3_STATIC);
sqliteVdbeChangeP3(v, -1, sqliteStrDup(zErrMsg), P3_DYNAMIC);
break;
}
case OE_Ignore: {

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this script testing the callback-free C/C++ API.
#
# $Id: capi2.test,v 1.9 2003/07/09 00:28:15 drh Exp $
# $Id: capi2.test,v 1.10 2003/08/05 13:13:38 drh Exp $
#
set testdir [file dirname $argv0]
@ -178,7 +178,7 @@ do_test capi2-3.13 {
do_test capi2-3.13b {db changes} {0}
do_test capi2-3.14 {
list [catch {sqlite_finalize $VM} msg] [set msg]
} {1 {(19) uniqueness constraint failed}}
} {1 {(19) column a is not unique}}
do_test capi2-3.15 {
set VM [sqlite_compile $DB {CREATE TABLE t2(a NOT NULL, b)} TAIL]
set TAIL
@ -386,7 +386,7 @@ do_test capi2-6.27 {
INSERT INTO t1 VALUES(2,4,5);
SELECT * FROM t1;
}
} {1 {uniqueness constraint failed}}
} {1 {column a is not unique}}
do_test capi2-6.28 {
list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
} {SQLITE_ROW 1 13 {x counter}}

View File

@ -13,7 +13,7 @@
# This file implements tests for the conflict resolution extension
# to SQLite.
#
# $Id: conflict.test,v 1.18 2003/06/15 23:42:25 drh Exp $
# $Id: conflict.test,v 1.19 2003/08/05 13:13:39 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -363,7 +363,7 @@ foreach {i conf1 conf2 cmd t0 t1 t2} {
25 IGNORE ABORT UPDATE 1 {1 2 3 4} 1
26 REPLACE ROLLBACK UPDATE 1 {1 2 3 4} 0
} {
if {$t0} {set t1 {uniqueness constraint failed}}
if {$t0} {set t1 {column a is not unique}}
do_test conflict-6.$i {
if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"}
if {$conf2!=""} {set conf2 "ON CONFLICT $conf2"}
@ -539,13 +539,13 @@ do_test conflict-9.5 {
INSERT INTO t2 VALUES(3,1,3,3,3);
SELECT * FROM t2;
}
} {1 {uniqueness constraint failed}}
} {1 {column b is not unique}}
do_test conflict-9.6 {
catchsql {
UPDATE t2 SET b=b+1 WHERE b=1;
SELECT * FROM t2;
}
} {1 {uniqueness constraint failed}}
} {1 {column b is not unique}}
do_test conflict-9.7 {
catchsql {
BEGIN;
@ -553,7 +553,7 @@ do_test conflict-9.7 {
INSERT INTO t2 VALUES(3,1,3,3,3);
SELECT * FROM t2;
}
} {1 {uniqueness constraint failed}}
} {1 {column b is not unique}}
do_test conflict-9.8 {
execsql {COMMIT}
execsql {SELECT * FROM t3}
@ -565,7 +565,7 @@ do_test conflict-9.9 {
UPDATE t2 SET b=b+1 WHERE b=1;
SELECT * FROM t2;
}
} {1 {uniqueness constraint failed}}
} {1 {column b is not unique}}
do_test conflict-9.10 {
execsql {COMMIT}
execsql {SELECT * FROM t3}
@ -575,13 +575,13 @@ do_test conflict-9.11 {
INSERT INTO t2 VALUES(3,3,3,1,3);
SELECT * FROM t2;
}
} {1 {uniqueness constraint failed}}
} {1 {column d is not unique}}
do_test conflict-9.12 {
catchsql {
UPDATE t2 SET d=d+1 WHERE d=1;
SELECT * FROM t2;
}
} {1 {uniqueness constraint failed}}
} {1 {column d is not unique}}
do_test conflict-9.13 {
catchsql {
BEGIN;
@ -589,7 +589,7 @@ do_test conflict-9.13 {
INSERT INTO t2 VALUES(3,3,3,1,3);
SELECT * FROM t2;
}
} {1 {uniqueness constraint failed}}
} {1 {column d is not unique}}
do_test conflict-9.14 {
execsql {COMMIT}
execsql {SELECT * FROM t3}
@ -601,7 +601,7 @@ do_test conflict-9.15 {
UPDATE t2 SET d=d+1 WHERE d=1;
SELECT * FROM t2;
}
} {1 {uniqueness constraint failed}}
} {1 {column d is not unique}}
do_test conflict-9.16 {
execsql {COMMIT}
execsql {SELECT * FROM t3}
@ -611,13 +611,13 @@ do_test conflict-9.17 {
INSERT INTO t2 VALUES(3,3,3,3,1);
SELECT * FROM t2;
}
} {1 {uniqueness constraint failed}}
} {1 {column e is not unique}}
do_test conflict-9.18 {
catchsql {
UPDATE t2 SET e=e+1 WHERE e=1;
SELECT * FROM t2;
}
} {1 {uniqueness constraint failed}}
} {1 {column e is not unique}}
do_test conflict-9.19 {
catchsql {
BEGIN;
@ -625,7 +625,7 @@ do_test conflict-9.19 {
INSERT INTO t2 VALUES(3,3,3,3,1);
SELECT * FROM t2;
}
} {1 {uniqueness constraint failed}}
} {1 {column e is not unique}}
do_test conflict-9.20 {
catch {execsql {COMMIT}}
execsql {SELECT * FROM t3}
@ -637,7 +637,7 @@ do_test conflict-9.21 {
UPDATE t2 SET e=e+1 WHERE e=1;
SELECT * FROM t2;
}
} {1 {uniqueness constraint failed}}
} {1 {column e is not unique}}
do_test conflict-9.22 {
catch {execsql {COMMIT}}
execsql {SELECT * FROM t3}

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing the COPY statement.
#
# $Id: copy.test,v 1.14 2003/06/02 22:50:27 drh Exp $
# $Id: copy.test,v 1.15 2003/08/05 13:13:39 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -196,7 +196,7 @@ do_test copy-5.2 {
COPY t1 FROM 'data6.txt' USING DELIMITERS '|';
SELECT * FROM t1;
}
} {1 {uniqueness constraint failed}}
} {1 {column b is not unique}}
do_test copy-5.3 {
set fd [open data6.txt w]
puts $fd "33|22|44"

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this script is in-memory database backend.
#
# $Id: memdb.test,v 1.5 2003/06/15 23:42:25 drh Exp $
# $Id: memdb.test,v 1.6 2003/08/05 13:13:39 drh Exp $
set testdir [file dirname $argv0]
@ -253,7 +253,7 @@ foreach {i conf1 conf2 cmd t0 t1 t2} {
25 IGNORE ABORT UPDATE 1 {1 2 3 4} 1
26 REPLACE ROLLBACK UPDATE 1 {1 2 3 4} 0
} {
if {$t0} {set t1 {uniqueness constraint failed}}
if {$t0} {set t1 {column a is not unique}}
do_test memdb-5.$i {
if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"}
if {$conf2!=""} {set conf2 "ON CONFLICT $conf2"}

View File

@ -13,7 +13,7 @@
# This file implements tests for miscellanous features that were
# left out of other test files.
#
# $Id: misc1.test,v 1.22 2003/06/03 01:47:12 drh Exp $
# $Id: misc1.test,v 1.23 2003/08/05 13:13:39 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -222,7 +222,7 @@ do_test misc1-7.4 {
catchsql {
INSERT INTO t5 VALUES(1,2,4);
}
} {1 {uniqueness constraint failed}}
} {1 {columns a, b are not unique}}
do_test misc1-7.5 {
catchsql {
INSERT INTO t5 VALUES(0,2,4);

View File

@ -472,7 +472,7 @@ do_test trigger2-6.1b {
catchsql {
INSERT OR ABORT INTO tbl values (2, 2, 3);
}
} {1 {uniqueness constraint failed}}
} {1 {column a is not unique}}
do_test trigger2-6.1c {
execsql {
SELECT * from tbl;
@ -482,7 +482,7 @@ do_test trigger2-6.1d {
catchsql {
INSERT OR FAIL INTO tbl values (2, 2, 3);
}
} {1 {uniqueness constraint failed}}
} {1 {column a is not unique}}
do_test trigger2-6.1e {
execsql {
SELECT * from tbl;
@ -498,7 +498,7 @@ do_test trigger2-6.1g {
catchsql {
INSERT OR ROLLBACK INTO tbl values (3, 2, 3);
}
} {1 {uniqueness constraint failed}}
} {1 {column a is not unique}}
do_test trigger2-6.1h {
execsql {
SELECT * from tbl;
@ -526,7 +526,7 @@ do_test trigger2-6.2b {
catchsql {
UPDATE OR ABORT tbl SET a = 4 WHERE a = 1;
}
} {1 {uniqueness constraint failed}}
} {1 {column a is not unique}}
do_test trigger2-6.2c {
execsql {
SELECT * from tbl;
@ -536,7 +536,7 @@ do_test trigger2-6.2d {
catchsql {
UPDATE OR FAIL tbl SET a = 4 WHERE a = 1;
}
} {1 {uniqueness constraint failed}}
} {1 {column a is not unique}}
do_test trigger2-6.2e {
execsql {
SELECT * from tbl;
@ -558,7 +558,7 @@ do_test trigger2-6.2g {
catchsql {
UPDATE OR ROLLBACK tbl SET a = 4 WHERE a = 1;
}
} {1 {uniqueness constraint failed}}
} {1 {column a is not unique}}
do_test trigger2-6.2h {
execsql {
SELECT * from tbl;

View File

@ -12,7 +12,7 @@
# focus of this file is testing the CREATE UNIQUE INDEX statement,
# and primary keys, and the UNIQUE constraint on table columns
#
# $Id: unique.test,v 1.6 2003/06/15 23:42:25 drh Exp $
# $Id: unique.test,v 1.7 2003/08/05 13:13:39 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -47,7 +47,7 @@ do_test unique-1.3 {
catchsql {
INSERT INTO t1(a,b,c) VALUES(1,3,4)
}
} {1 {uniqueness constraint failed}}
} {1 {column a is not unique}}
do_test unique-1.4 {
execsql {
SELECT * FROM t1 ORDER BY a;
@ -57,7 +57,7 @@ do_test unique-1.5 {
catchsql {
INSERT INTO t1(a,b,c) VALUES(3,2,4)
}
} {1 {uniqueness constraint failed}}
} {1 {column b is not unique}}
do_test unique-1.6 {
execsql {
SELECT * FROM t1 ORDER BY a;
@ -98,7 +98,7 @@ do_test unique-2.3 {
catchsql {
INSERT INTO t2 VALUES(1,5);
}
} {1 {uniqueness constraint failed}}
} {1 {column a is not unique}}
do_test unique-2.4 {
catchsql {
SELECT * FROM t2 ORDER BY a
@ -162,7 +162,7 @@ do_test unique-3.4 {
INSERT INTO t3(a,b,c,d) VALUES(1,4,3,5);
SELECT * FROM t3 ORDER BY a,b,c,d;
}
} {1 {uniqueness constraint failed}}
} {1 {columns a, c, d are not unique}}
integrity_check unique-3.5
# Make sure NULLs are distinct as far as the UNIQUE tests are
@ -198,4 +198,35 @@ do_test unique-4.5 {
} {1 2 3 {} 2 {} {} 3 4 2 2 {}}
integrity_check unique-4.6
# Test the error message generation logic. In particular, make sure we
# do not overflow the static buffer used to generate the error message.
#
do_test unique-5.1 {
execsql {
CREATE TABLE t5(
first_column_with_long_name,
second_column_with_long_name,
third_column_with_long_name,
fourth_column_with_long_name,
fifth_column_with_long_name,
sixth_column_with_long_name,
UNIQUE(
first_column_with_long_name,
second_column_with_long_name,
third_column_with_long_name,
fourth_column_with_long_name,
fifth_column_with_long_name,
sixth_column_with_long_name
)
);
INSERT INTO t5 VALUES(1,2,3,4,5,6);
SELECT * FROM t5;
}
} {1 2 3 4 5 6}
do_test unique-5.2 {
catchsql {
INSERT INTO t5 VALUES(1,2,3,4,5,6);
}
} {1 {columns first_column_with_long_name, second_column_with_long_name, third_column_with_long_name, fourth_column_with_long_name, fifth_column_with_long_name, ... are not unique}}
finish_test

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing the UPDATE statement.
#
# $Id: update.test,v 1.13 2003/06/15 23:42:25 drh Exp $
# $Id: update.test,v 1.14 2003/08/05 13:13:39 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -457,7 +457,7 @@ do_test update-10.6 {
UPDATE t1 SET b=2, e=12 WHERE f=7;
SELECT * FROM t1;
}
} {1 {uniqueness constraint failed}}
} {1 {column b is not unique}}
do_test update-10.7 {
catchsql {
SELECT * FROM t1;
@ -474,7 +474,7 @@ do_test update-10.9 {
UPDATE t1 SET c=3, d=4, e=14 WHERE f=7;
SELECT * FROM t1;
}
} {1 {uniqueness constraint failed}}
} {1 {columns c, d are not unique}}
do_test update-10.10 {
catchsql {
SELECT * FROM t1;