diff --git a/contrib/citext/expected/citext.out b/contrib/citext/expected/citext.out index 3694cb8b5b3..34ce3da3ee5 100644 --- a/contrib/citext/expected/citext.out +++ b/contrib/citext/expected/citext.out @@ -271,10 +271,13 @@ SELECT name, 'A' = name AS t FROM try where name = 'A'; -- expected failures on duplicate key INSERT INTO try (name) VALUES ('a'); ERROR: duplicate key value violates unique constraint "try_pkey" +DETAIL: Key (name)=(a) already exists. INSERT INTO try (name) VALUES ('A'); ERROR: duplicate key value violates unique constraint "try_pkey" +DETAIL: Key (name)=(A) already exists. INSERT INTO try (name) VALUES ('aB'); ERROR: duplicate key value violates unique constraint "try_pkey" +DETAIL: Key (name)=(aB) already exists. -- Make sure that citext_smaller() and citext_lager() work properly. SELECT citext_smaller( 'aa'::citext, 'ab'::citext ) = 'aa' AS t; t diff --git a/contrib/citext/expected/citext_1.out b/contrib/citext/expected/citext_1.out index 1a6bcdf0bcc..cc03e234ed2 100644 --- a/contrib/citext/expected/citext_1.out +++ b/contrib/citext/expected/citext_1.out @@ -271,10 +271,13 @@ SELECT name, 'A' = name AS t FROM try where name = 'A'; -- expected failures on duplicate key INSERT INTO try (name) VALUES ('a'); ERROR: duplicate key value violates unique constraint "try_pkey" +DETAIL: Key (name)=(a) already exists. INSERT INTO try (name) VALUES ('A'); ERROR: duplicate key value violates unique constraint "try_pkey" +DETAIL: Key (name)=(A) already exists. INSERT INTO try (name) VALUES ('aB'); ERROR: duplicate key value violates unique constraint "try_pkey" +DETAIL: Key (name)=(aB) already exists. -- Make sure that citext_smaller() and citext_lager() work properly. SELECT citext_smaller( 'aa'::citext, 'ab'::citext ) = 'aa' AS t; t diff --git a/src/backend/access/common/indextuple.c b/src/backend/access/common/indextuple.c index cd3b88654bd..a49ec34a040 100644 --- a/src/backend/access/common/indextuple.c +++ b/src/backend/access/common/indextuple.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/common/indextuple.c,v 1.88 2009/06/11 14:48:53 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/common/indextuple.c,v 1.89 2009/08/01 19:59:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -432,6 +432,27 @@ nocache_index_getattr(IndexTuple tup, return fetchatt(att[attnum], tp + off); } +/* + * Convert an index tuple into Datum/isnull arrays. + * + * The caller must allocate sufficient storage for the output arrays. + * (INDEX_MAX_KEYS entries should be enough.) + */ +void +index_deform_tuple(IndexTuple tup, TupleDesc tupleDescriptor, + Datum *values, bool *isnull) +{ + int i; + + /* Assert to protect callers who allocate fixed-size arrays */ + Assert(tupleDescriptor->natts <= INDEX_MAX_KEYS); + + for (i = 0; i < tupleDescriptor->natts; i++) + { + values[i] = index_getattr(tup, i + 1, tupleDescriptor, &isnull[i]); + } +} + /* * Create a palloc'd copy of an index tuple. */ diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c index a79c3920713..6482aaa6a70 100644 --- a/src/backend/access/index/genam.c +++ b/src/backend/access/index/genam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.74 2009/06/11 14:48:54 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.75 2009/08/01 19:59:41 tgl Exp $ * * NOTES * many of the old access method routines have been turned into @@ -24,6 +24,8 @@ #include "miscadmin.h" #include "pgstat.h" #include "storage/bufmgr.h" +#include "utils/builtins.h" +#include "utils/lsyscache.h" #include "utils/rel.h" #include "utils/tqual.h" @@ -130,6 +132,59 @@ IndexScanEnd(IndexScanDesc scan) pfree(scan); } +/* + * ReportUniqueViolation -- Report a unique-constraint violation. + * + * The index entry represented by values[]/isnull[] violates the unique + * constraint enforced by this index. Throw a suitable error. + */ +void +ReportUniqueViolation(Relation indexRelation, Datum *values, bool *isnull) +{ + /* + * XXX for the moment we use the index's tupdesc as a guide to the + * datatypes of the values. This is okay for btree indexes but is in + * fact the wrong thing in general. This will have to be fixed if we + * are ever to support non-btree unique indexes. + */ + TupleDesc tupdesc = RelationGetDescr(indexRelation); + char *key_names; + StringInfoData key_values; + int i; + + key_names = pg_get_indexdef_columns(RelationGetRelid(indexRelation), true); + + /* Get printable versions of the key values */ + initStringInfo(&key_values); + for (i = 0; i < tupdesc->natts; i++) + { + char *val; + + if (isnull[i]) + val = "null"; + else + { + Oid foutoid; + bool typisvarlena; + + getTypeOutputInfo(tupdesc->attrs[i]->atttypid, + &foutoid, &typisvarlena); + val = OidOutputFunctionCall(foutoid, values[i]); + } + + if (i > 0) + appendStringInfoString(&key_values, ", "); + appendStringInfoString(&key_values, val); + } + + ereport(ERROR, + (errcode(ERRCODE_UNIQUE_VIOLATION), + errmsg("duplicate key value violates unique constraint \"%s\"", + RelationGetRelationName(indexRelation)), + errdetail("Key (%s)=(%s) already exists.", + key_names, key_values.data))); +} + /* ---------------------------------------------------------------- * heap-or-index-scan access to system catalogs diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index f0137182249..ee3d89fd066 100644 --- a/src/backend/access/nbtree/nbtinsert.c +++ b/src/backend/access/nbtree/nbtinsert.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.171 2009/07/29 20:56:18 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.172 2009/08/01 19:59:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -362,12 +362,25 @@ _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel, } /* - * This is a definite conflict. + * This is a definite conflict. Break the tuple down + * into datums and report the error. But first, make + * sure we release the buffer locks we're holding --- + * the error reporting code could make catalog accesses, + * which in the worst case might touch this same index + * and cause deadlocks. */ - ereport(ERROR, - (errcode(ERRCODE_UNIQUE_VIOLATION), - errmsg("duplicate key value violates unique constraint \"%s\"", - RelationGetRelationName(rel)))); + if (nbuf != InvalidBuffer) + _bt_relbuf(rel, nbuf); + _bt_relbuf(rel, buf); + + { + Datum values[INDEX_MAX_KEYS]; + bool isnull[INDEX_MAX_KEYS]; + + index_deform_tuple(itup, RelationGetDescr(rel), + values, isnull); + ReportUniqueViolation(rel, values, isnull); + } } else if (all_dead) { diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index 5bcbd633043..c89553ce0c0 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -15,7 +15,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.113 2009/06/11 14:49:04 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.114 2009/08/01 19:59:41 tgl Exp $ * * ---------- */ @@ -3413,11 +3413,8 @@ ri_ReportViolation(RI_QueryKey *qkey, const char *constrname, HeapTuple violator, TupleDesc tupdesc, bool spi_err) { -#define BUFLENGTH 512 - char key_names[BUFLENGTH]; - char key_values[BUFLENGTH]; - char *name_ptr = key_names; - char *val_ptr = key_values; + StringInfoData key_names; + StringInfoData key_values; bool onfk; int idx, key_idx; @@ -3465,6 +3462,8 @@ ri_ReportViolation(RI_QueryKey *qkey, const char *constrname, } /* Get printable versions of the keys involved */ + initStringInfo(&key_names); + initStringInfo(&key_values); for (idx = 0; idx < qkey->nkeypairs; idx++) { int fnum = qkey->keypair[idx][key_idx]; @@ -3476,20 +3475,13 @@ ri_ReportViolation(RI_QueryKey *qkey, const char *constrname, if (!val) val = "null"; - /* - * Go to "..." if name or value doesn't fit in buffer. We reserve 5 - * bytes to ensure we can add comma, "...", null. - */ - if (strlen(name) >= (key_names + BUFLENGTH - 5) - name_ptr || - strlen(val) >= (key_values + BUFLENGTH - 5) - val_ptr) + if (idx > 0) { - sprintf(name_ptr, "..."); - sprintf(val_ptr, "..."); - break; + appendStringInfoString(&key_names, ", "); + appendStringInfoString(&key_values, ", "); } - - name_ptr += sprintf(name_ptr, "%s%s", idx > 0 ? "," : "", name); - val_ptr += sprintf(val_ptr, "%s%s", idx > 0 ? "," : "", val); + appendStringInfoString(&key_names, name); + appendStringInfoString(&key_values, val); } if (onfk) @@ -3498,7 +3490,7 @@ ri_ReportViolation(RI_QueryKey *qkey, const char *constrname, errmsg("insert or update on table \"%s\" violates foreign key constraint \"%s\"", RelationGetRelationName(fk_rel), constrname), errdetail("Key (%s)=(%s) is not present in table \"%s\".", - key_names, key_values, + key_names.data, key_values.data, RelationGetRelationName(pk_rel)))); else ereport(ERROR, @@ -3507,7 +3499,7 @@ ri_ReportViolation(RI_QueryKey *qkey, const char *constrname, RelationGetRelationName(pk_rel), constrname, RelationGetRelationName(fk_rel)), errdetail("Key (%s)=(%s) is still referenced from table \"%s\".", - key_names, key_values, + key_names.data, key_values.data, RelationGetRelationName(fk_rel)))); } diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 752e84dbfea..38057a0bfdc 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.305 2009/07/29 20:56:19 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.306 2009/08/01 19:59:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -142,7 +142,8 @@ static char *pg_get_viewdef_worker(Oid viewoid, int prettyFlags); static void decompile_column_index_array(Datum column_index_array, Oid relId, StringInfo buf); static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags); -static char *pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc, +static char *pg_get_indexdef_worker(Oid indexrelid, int colno, + bool attrsOnly, bool showTblSpc, int prettyFlags); static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, int prettyFlags); @@ -613,7 +614,7 @@ pg_get_indexdef(PG_FUNCTION_ARGS) Oid indexrelid = PG_GETARG_OID(0); PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0, - false, 0))); + false, false, 0))); } Datum @@ -626,18 +627,31 @@ pg_get_indexdef_ext(PG_FUNCTION_ARGS) prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0; PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno, - false, prettyFlags))); + colno != 0, + false, + prettyFlags))); } /* Internal version that returns a palloc'd C string */ char * pg_get_indexdef_string(Oid indexrelid) { - return pg_get_indexdef_worker(indexrelid, 0, true, 0); + return pg_get_indexdef_worker(indexrelid, 0, false, true, 0); +} + +/* Internal version that just reports the column definitions */ +char * +pg_get_indexdef_columns(Oid indexrelid, bool pretty) +{ + int prettyFlags; + + prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0; + return pg_get_indexdef_worker(indexrelid, 0, true, false, prettyFlags); } static char * -pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc, +pg_get_indexdef_worker(Oid indexrelid, int colno, + bool attrsOnly, bool showTblSpc, int prettyFlags) { HeapTuple ht_idx; @@ -736,7 +750,7 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc, */ initStringInfo(&buf); - if (!colno) + if (!attrsOnly) appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (", idxrec->indisunique ? "UNIQUE " : "", quote_identifier(NameStr(idxrelrec->relname)), @@ -790,8 +804,7 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc, keycoltype = exprType(indexkey); } - /* Provide decoration only in the colno=0 case */ - if (!colno) + if (!attrsOnly && (!colno || colno == keyno + 1)) { /* Add the operator class name, if not default */ get_opclass_name(indclass->values[keyno], keycoltype, &buf); @@ -816,7 +829,7 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc, } } - if (!colno) + if (!attrsOnly) { appendStringInfoChar(&buf, ')'); diff --git a/src/include/access/genam.h b/src/include/access/genam.h index a8c0e029296..19025265775 100644 --- a/src/include/access/genam.h +++ b/src/include/access/genam.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.79 2009/07/29 20:56:19 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.80 2009/08/01 19:59:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -164,6 +164,8 @@ extern FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum, extern IndexScanDesc RelationGetIndexScan(Relation indexRelation, int nkeys, ScanKey key); extern void IndexScanEnd(IndexScanDesc scan); +extern void ReportUniqueViolation(Relation indexRelation, + Datum *values, bool *isnull); /* * heap-or-index access to system catalogs (in genam.c) diff --git a/src/include/access/itup.h b/src/include/access/itup.h index 8527de65c90..ead628fec2b 100644 --- a/src/include/access/itup.h +++ b/src/include/access/itup.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/itup.h,v 1.51 2009/01/01 17:23:56 momjian Exp $ + * $PostgreSQL: pgsql/src/include/access/itup.h,v 1.52 2009/08/01 19:59:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -143,6 +143,8 @@ extern IndexTuple index_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull); extern Datum nocache_index_getattr(IndexTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull); +extern void index_deform_tuple(IndexTuple tup, TupleDesc tupleDescriptor, + Datum *values, bool *isnull); extern IndexTuple CopyIndexTuple(IndexTuple source); #endif /* ITUP_H */ diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 72b39f70685..481eacf9b9f 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.335 2009/07/29 20:56:21 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.336 2009/08/01 19:59:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -575,6 +575,7 @@ extern Datum pg_get_viewdef_name_ext(PG_FUNCTION_ARGS); extern Datum pg_get_indexdef(PG_FUNCTION_ARGS); extern Datum pg_get_indexdef_ext(PG_FUNCTION_ARGS); extern char *pg_get_indexdef_string(Oid indexrelid); +extern char *pg_get_indexdef_columns(Oid indexrelid, bool pretty); extern Datum pg_get_triggerdef(PG_FUNCTION_ARGS); extern Datum pg_get_constraintdef(PG_FUNCTION_ARGS); extern Datum pg_get_constraintdef_ext(PG_FUNCTION_ARGS); diff --git a/src/interfaces/ecpg/test/expected/compat_informix-test_informix.stderr b/src/interfaces/ecpg/test/expected/compat_informix-test_informix.stderr index c9322e57449..f57f88b4812 100644 --- a/src/interfaces/ecpg/test/expected/compat_informix-test_informix.stderr +++ b/src/interfaces/ecpg/test/expected/compat_informix-test_informix.stderr @@ -23,6 +23,7 @@ [NO_PID]: ecpg_execute on line 31: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_check_PQresult on line 31: ERROR: duplicate key value violates unique constraint "test_pkey" +DETAIL: Key (i)=(7) already exists. [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: raising sqlstate 23505 (sqlcode -239) on line 31: duplicate key value violates unique constraint "test_pkey" on line 31 [NO_PID]: sqlca: code: -239, state: 23505 diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index 031e59ca8f0..3c9bb6308ea 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -407,6 +407,7 @@ insert into atacc1 (test) values (2); -- should fail insert into atacc1 (test) values (2); ERROR: duplicate key value violates unique constraint "atacc_test1" +DETAIL: Key (test)=(2) already exists. -- should succeed insert into atacc1 (test) values (4); -- try adding a unique oid constraint @@ -442,6 +443,7 @@ insert into atacc1 (test,test2) values (4,4); -- should fail insert into atacc1 (test,test2) values (4,4); ERROR: duplicate key value violates unique constraint "atacc_test1" +DETAIL: Key (test, test2)=(4, 4) already exists. -- should all succeed insert into atacc1 (test,test2) values (4,5); insert into atacc1 (test,test2) values (5,4); @@ -456,6 +458,7 @@ NOTICE: ALTER TABLE / ADD UNIQUE will create implicit index "atacc1_test2_key" insert into atacc1 (test2, test) values (3, 3); insert into atacc1 (test2, test) values (2, 3); ERROR: duplicate key value violates unique constraint "atacc1_test_key" +DETAIL: Key (test)=(3) already exists. drop table atacc1; -- test primary key constraint adding create table atacc1 ( test int ) with oids; @@ -467,6 +470,7 @@ insert into atacc1 (test) values (2); -- should fail insert into atacc1 (test) values (2); ERROR: duplicate key value violates unique constraint "atacc_test1" +DETAIL: Key (test)=(2) already exists. -- should succeed insert into atacc1 (test) values (4); -- inserting NULL should fail @@ -534,6 +538,7 @@ insert into atacc1 (test,test2) values (4,4); -- should fail insert into atacc1 (test,test2) values (4,4); ERROR: duplicate key value violates unique constraint "atacc_test1" +DETAIL: Key (test, test2)=(4, 4) already exists. insert into atacc1 (test,test2) values (NULL,3); ERROR: null value in column "test" violates not-null constraint insert into atacc1 (test,test2) values (3, NULL); @@ -552,6 +557,7 @@ NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "atacc1_pkey" for insert into atacc1 (test2, test) values (3, 3); insert into atacc1 (test2, test) values (2, 3); ERROR: duplicate key value violates unique constraint "atacc1_pkey" +DETAIL: Key (test)=(3) already exists. insert into atacc1 (test2, test) values (1, NULL); ERROR: null value in column "test" violates not-null constraint drop table atacc1; diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out index 15f3f6082eb..7225d6e4429 100644 --- a/src/test/regress/expected/arrays.out +++ b/src/test/regress/expected/arrays.out @@ -713,6 +713,7 @@ insert into arr_tbl values ('{1,2}'); -- failure expected: insert into arr_tbl values ('{1,2,3}'); ERROR: duplicate key value violates unique constraint "arr_tbl_f1_key" +DETAIL: Key (f1)=({1,2,3}) already exists. insert into arr_tbl values ('{2,3,4}'); insert into arr_tbl values ('{1,5,3}'); insert into arr_tbl values ('{1,2,10}'); diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out index 6e06be5ed53..02f2474a052 100644 --- a/src/test/regress/expected/create_index.out +++ b/src/test/regress/expected/create_index.out @@ -641,6 +641,7 @@ INSERT INTO func_index_heap VALUES('QWE','RTY'); -- this should fail because of unique index: INSERT INTO func_index_heap VALUES('ABCD', 'EF'); ERROR: duplicate key value violates unique constraint "func_index_index" +DETAIL: Key (textcat(f1, f2))=(ABCDEF) already exists. -- but this shouldn't: INSERT INTO func_index_heap VALUES('QWERTY'); -- @@ -655,6 +656,7 @@ INSERT INTO func_index_heap VALUES('QWE','RTY'); -- this should fail because of unique index: INSERT INTO func_index_heap VALUES('ABCD', 'EF'); ERROR: duplicate key value violates unique constraint "func_index_index" +DETAIL: Key ((f1 || f2))=(ABCDEF) already exists. -- but this shouldn't: INSERT INTO func_index_heap VALUES('QWERTY'); -- @@ -679,6 +681,7 @@ CREATE UNIQUE INDEX CONCURRENTLY concur_index2 ON concur_heap(f1); -- check if constraint is set up properly to be enforced INSERT INTO concur_heap VALUES ('b','x'); ERROR: duplicate key value violates unique constraint "concur_index2" +DETAIL: Key (f1)=(b) already exists. -- check if constraint is enforced properly at build time CREATE UNIQUE INDEX CONCURRENTLY concur_index3 ON concur_heap(f2); ERROR: could not create unique index "concur_index3" diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out index 100edb35396..1b98ce94f1c 100644 --- a/src/test/regress/expected/inherit.out +++ b/src/test/regress/expected/inherit.out @@ -638,6 +638,7 @@ NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "inhg_pkey" for t INSERT INTO inhg VALUES (5, 10); INSERT INTO inhg VALUES (20, 10); -- should fail ERROR: duplicate key value violates unique constraint "inhg_pkey" +DETAIL: Key (xx)=(10) already exists. DROP TABLE inhg; /* Multiple primary keys creation should fail */ CREATE TABLE inhg (x text, LIKE inhx INCLUDING INDEXES, PRIMARY KEY(x)); /* fails */ @@ -653,6 +654,7 @@ INSERT INTO inhg (xx, yy, x) VALUES ('test', 5, 10); INSERT INTO inhg (xx, yy, x) VALUES ('test', 10, 15); INSERT INTO inhg (xx, yy, x) VALUES ('foo', 10, 15); -- should fail ERROR: duplicate key value violates unique constraint "inhg_x_key" +DETAIL: Key (x)=(15) already exists. DROP TABLE inhg; DROP TABLE inhz; -- Test changing the type of inherited columns diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out index 0446f5193cd..84a5943bbf1 100644 --- a/src/test/regress/expected/plpgsql.out +++ b/src/test/regress/expected/plpgsql.out @@ -1517,6 +1517,7 @@ select * from PField_v1 where pfname = 'PF0_2' order by slotname; -- insert into PField values ('PF1_1', 'should fail due to unique index'); ERROR: duplicate key value violates unique constraint "pfield_name" +DETAIL: Key (name)=(PF1_1) already exists. update PSlot set backlink = 'WS.not.there' where slotname = 'PS.base.a1'; ERROR: WS.not.there does not exist CONTEXT: PL/pgSQL function "tg_backlink_a" line 16 at assignment @@ -1531,6 +1532,7 @@ ERROR: illegal slotlink beginning with XX CONTEXT: PL/pgSQL function "tg_slotlink_a" line 16 at assignment insert into HSlot values ('HS', 'base.hub1', 1, ''); ERROR: duplicate key value violates unique constraint "hslot_name" +DETAIL: Key (slotname)=(HS.base.hub1.1 ) already exists. insert into HSlot values ('HS', 'base.hub1', 20, ''); ERROR: no manual manipulation of HSlot delete from HSlot; diff --git a/src/test/regress/expected/transactions.out b/src/test/regress/expected/transactions.out index 51bb3668f3b..fc98f0163a0 100644 --- a/src/test/regress/expected/transactions.out +++ b/src/test/regress/expected/transactions.out @@ -468,12 +468,14 @@ NOTICE: CREATE TABLE / UNIQUE will create implicit index "koju_a_key" for table INSERT INTO koju VALUES (1); INSERT INTO koju VALUES (1); ERROR: duplicate key value violates unique constraint "koju_a_key" +DETAIL: Key (a)=(1) already exists. rollback to x; CREATE TABLE koju (a INT UNIQUE); NOTICE: CREATE TABLE / UNIQUE will create implicit index "koju_a_key" for table "koju" INSERT INTO koju VALUES (1); INSERT INTO koju VALUES (1); ERROR: duplicate key value violates unique constraint "koju_a_key" +DETAIL: Key (a)=(1) already exists. ROLLBACK; DROP TABLE foo; DROP TABLE baz; diff --git a/src/test/regress/expected/uuid.out b/src/test/regress/expected/uuid.out index 03bd73bd0cf..da230fe2347 100644 --- a/src/test/regress/expected/uuid.out +++ b/src/test/regress/expected/uuid.out @@ -119,6 +119,7 @@ CREATE UNIQUE INDEX guid1_unique_BTREE ON guid1 USING BTREE (guid_field); -- should fail INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111'); ERROR: duplicate key value violates unique constraint "guid1_unique_btree" +DETAIL: Key (guid_field)=(11111111-1111-1111-1111-111111111111) already exists. -- check to see whether the new indexes are actually there SELECT count(*) FROM pg_class WHERE relkind='i' AND relname LIKE 'guid%'; count diff --git a/src/test/regress/output/constraints.source b/src/test/regress/output/constraints.source index e21aa6b7e16..56dbf7a0555 100644 --- a/src/test/regress/output/constraints.source +++ b/src/test/regress/output/constraints.source @@ -294,6 +294,7 @@ INSERT INTO PRIMARY_TBL VALUES (1, 'one'); INSERT INTO PRIMARY_TBL VALUES (2, 'two'); INSERT INTO PRIMARY_TBL VALUES (1, 'three'); ERROR: duplicate key value violates unique constraint "primary_tbl_pkey" +DETAIL: Key (i)=(1) already exists. INSERT INTO PRIMARY_TBL VALUES (4, 'three'); INSERT INTO PRIMARY_TBL VALUES (5, 'one'); INSERT INTO PRIMARY_TBL (t) VALUES ('six'); @@ -338,6 +339,7 @@ INSERT INTO UNIQUE_TBL VALUES (1, 'one'); INSERT INTO UNIQUE_TBL VALUES (2, 'two'); INSERT INTO UNIQUE_TBL VALUES (1, 'three'); ERROR: duplicate key value violates unique constraint "unique_tbl_i_key" +DETAIL: Key (i)=(1) already exists. INSERT INTO UNIQUE_TBL VALUES (4, 'four'); INSERT INTO UNIQUE_TBL VALUES (5, 'one'); INSERT INTO UNIQUE_TBL (t) VALUES ('six'); @@ -362,6 +364,7 @@ INSERT INTO UNIQUE_TBL VALUES (2, 'two'); INSERT INTO UNIQUE_TBL VALUES (1, 'three'); INSERT INTO UNIQUE_TBL VALUES (1, 'one'); ERROR: duplicate key value violates unique constraint "unique_tbl_i_key" +DETAIL: Key (i, t)=(1, one) already exists. INSERT INTO UNIQUE_TBL VALUES (5, 'one'); INSERT INTO UNIQUE_TBL (t) VALUES ('six'); SELECT '' AS five, * FROM UNIQUE_TBL; @@ -389,6 +392,7 @@ BEGIN; -- default is immediate so this should fail right away UPDATE unique_tbl SET i = 1 WHERE i = 0; ERROR: duplicate key value violates unique constraint "unique_tbl_i_key" +DETAIL: Key (i)=(1) already exists. ROLLBACK; -- check is done at end of statement, so this should succeed UPDATE unique_tbl SET i = i+1; @@ -446,11 +450,13 @@ BEGIN; INSERT INTO unique_tbl VALUES (3, 'Three'); -- should succeed for now COMMIT; -- should fail ERROR: duplicate key value violates unique constraint "unique_tbl_i_key" +DETAIL: Key (i)=(3) already exists. -- make constraint check immediate BEGIN; SET CONSTRAINTS ALL IMMEDIATE; INSERT INTO unique_tbl VALUES (3, 'Three'); -- should fail ERROR: duplicate key value violates unique constraint "unique_tbl_i_key" +DETAIL: Key (i)=(3) already exists. COMMIT; -- forced check when SET CONSTRAINTS is called BEGIN; @@ -458,6 +464,7 @@ SET CONSTRAINTS ALL DEFERRED; INSERT INTO unique_tbl VALUES (3, 'Three'); -- should succeed for now SET CONSTRAINTS ALL IMMEDIATE; -- should fail ERROR: duplicate key value violates unique constraint "unique_tbl_i_key" +DETAIL: Key (i)=(3) already exists. COMMIT; -- test a HOT update that invalidates the conflicting tuple. -- the trigger should still fire and catch the violation @@ -466,6 +473,7 @@ INSERT INTO unique_tbl VALUES (3, 'Three'); -- should succeed for now UPDATE unique_tbl SET t = 'THREE' WHERE i = 3 AND t = 'Three'; COMMIT; -- should fail ERROR: duplicate key value violates unique constraint "unique_tbl_i_key" +DETAIL: Key (i)=(3) already exists. SELECT * FROM unique_tbl; i | t ---+------- diff --git a/src/test/regress/output/tablespace.source b/src/test/regress/output/tablespace.source index 8065505be95..e57ad2b2174 100644 --- a/src/test/regress/output/tablespace.source +++ b/src/test/regress/output/tablespace.source @@ -49,6 +49,7 @@ ALTER INDEX testschema.anindex SET TABLESPACE testspace; INSERT INTO testschema.atable VALUES(3); -- ok INSERT INTO testschema.atable VALUES(1); -- fail (checks index) ERROR: duplicate key value violates unique constraint "anindex" +DETAIL: Key (column1)=(1) already exists. SELECT COUNT(*) FROM testschema.atable; -- checks heap count -------