Skip to content

Commit 527f0ae

Browse files
committed
Department of second thoughts: let's show the exact key during unique index
build failures, too. Refactor a bit more since that error message isn't spelled the same.
1 parent b680ae4 commit 527f0ae

File tree

6 files changed

+44
-30
lines changed

6 files changed

+44
-30
lines changed

src/backend/access/index/genam.c

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.75 2009/08/01 19:59:41 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.76 2009/08/01 20:59:17 tgl Exp $
1212
*
1313
* NOTES
1414
* many of the old access method routines have been turned into
@@ -133,13 +133,16 @@ IndexScanEnd(IndexScanDesc scan)
133133
}
134134

135135
/*
136-
* ReportUniqueViolation -- Report a unique-constraint violation.
136+
* BuildIndexValueDescription
137137
*
138-
* The index entry represented by values[]/isnull[] violates the unique
139-
* constraint enforced by this index. Throw a suitable error.
138+
* Construct a string describing the contents of an index entry, in the
139+
* form "(key_name, ...)=(key_value, ...)". This is currently used
140+
* only for building unique-constraint error messages, but we don't want
141+
* to hardwire the spelling of the messages here.
140142
*/
141-
void
142-
ReportUniqueViolation(Relation indexRelation, Datum *values, bool *isnull)
143+
char *
144+
BuildIndexValueDescription(Relation indexRelation,
145+
Datum *values, bool *isnull)
143146
{
144147
/*
145148
* XXX for the moment we use the index's tupdesc as a guide to the
@@ -148,14 +151,14 @@ ReportUniqueViolation(Relation indexRelation, Datum *values, bool *isnull)
148151
* are ever to support non-btree unique indexes.
149152
*/
150153
TupleDesc tupdesc = RelationGetDescr(indexRelation);
151-
char *key_names;
152-
StringInfoData key_values;
154+
StringInfoData buf;
153155
int i;
154156

155-
key_names = pg_get_indexdef_columns(RelationGetRelid(indexRelation), true);
157+
initStringInfo(&buf);
158+
appendStringInfo(&buf, "(%s)=(",
159+
pg_get_indexdef_columns(RelationGetRelid(indexRelation),
160+
true));
156161

157-
/* Get printable versions of the key values */
158-
initStringInfo(&key_values);
159162
for (i = 0; i < tupdesc->natts; i++)
160163
{
161164
char *val;
@@ -173,16 +176,13 @@ ReportUniqueViolation(Relation indexRelation, Datum *values, bool *isnull)
173176
}
174177

175178
if (i > 0)
176-
appendStringInfoString(&key_values, ", ");
177-
appendStringInfoString(&key_values, val);
179+
appendStringInfoString(&buf, ", ");
180+
appendStringInfoString(&buf, val);
178181
}
179182

180-
ereport(ERROR,
181-
(errcode(ERRCODE_UNIQUE_VIOLATION),
182-
errmsg("duplicate key value violates unique constraint \"%s\"",
183-
RelationGetRelationName(indexRelation)),
184-
errdetail("Key (%s)=(%s) already exists.",
185-
key_names, key_values.data)));
183+
appendStringInfoChar(&buf, ')');
184+
185+
return buf.data;
186186
}
187187

188188

src/backend/access/nbtree/nbtinsert.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.172 2009/08/01 19:59:41 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.173 2009/08/01 20:59:17 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -365,7 +365,7 @@ _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel,
365365
* This is a definite conflict. Break the tuple down
366366
* into datums and report the error. But first, make
367367
* sure we release the buffer locks we're holding ---
368-
* the error reporting code could make catalog accesses,
368+
* BuildIndexValueDescription could make catalog accesses,
369369
* which in the worst case might touch this same index
370370
* and cause deadlocks.
371371
*/
@@ -379,7 +379,13 @@ _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel,
379379

380380
index_deform_tuple(itup, RelationGetDescr(rel),
381381
values, isnull);
382-
ReportUniqueViolation(rel, values, isnull);
382+
ereport(ERROR,
383+
(errcode(ERRCODE_UNIQUE_VIOLATION),
384+
errmsg("duplicate key value violates unique constraint \"%s\"",
385+
RelationGetRelationName(rel)),
386+
errdetail("Key %s already exists.",
387+
BuildIndexValueDescription(rel,
388+
values, isnull))));
383389
}
384390
}
385391
else if (all_dead)

src/backend/utils/sort/tuplesort.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@
9191
* Portions Copyright (c) 1994, Regents of the University of California
9292
*
9393
* IDENTIFICATION
94-
* $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.91 2009/06/11 14:49:06 momjian Exp $
94+
* $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.92 2009/08/01 20:59:17 tgl Exp $
9595
*
9696
*-------------------------------------------------------------------------
9797
*/
@@ -2801,11 +2801,19 @@ comparetup_index_btree(const SortTuple *a, const SortTuple *b,
28012801
* error in that case.
28022802
*/
28032803
if (state->enforceUnique && !equal_hasnull && tuple1 != tuple2)
2804+
{
2805+
Datum values[INDEX_MAX_KEYS];
2806+
bool isnull[INDEX_MAX_KEYS];
2807+
2808+
index_deform_tuple(tuple1, tupDes, values, isnull);
28042809
ereport(ERROR,
28052810
(errcode(ERRCODE_UNIQUE_VIOLATION),
28062811
errmsg("could not create unique index \"%s\"",
28072812
RelationGetRelationName(state->indexRel)),
2808-
errdetail("Table contains duplicated values.")));
2813+
errdetail("Key %s is duplicated.",
2814+
BuildIndexValueDescription(state->indexRel,
2815+
values, isnull))));
2816+
}
28092817

28102818
/*
28112819
* If key values are equal, we sort on ItemPointer. This does not affect

src/include/access/genam.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/access/genam.h,v 1.80 2009/08/01 19:59:41 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/access/genam.h,v 1.81 2009/08/01 20:59:17 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -164,8 +164,8 @@ extern FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum,
164164
extern IndexScanDesc RelationGetIndexScan(Relation indexRelation,
165165
int nkeys, ScanKey key);
166166
extern void IndexScanEnd(IndexScanDesc scan);
167-
extern void ReportUniqueViolation(Relation indexRelation,
168-
Datum *values, bool *isnull);
167+
extern char *BuildIndexValueDescription(Relation indexRelation,
168+
Datum *values, bool *isnull);
169169

170170
/*
171171
* heap-or-index access to system catalogs (in genam.c)

src/test/regress/expected/alter_table.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ insert into atacc1 (test) values (2);
423423
alter table atacc1 add constraint atacc_test1 unique (test);
424424
NOTICE: ALTER TABLE / ADD UNIQUE will create implicit index "atacc_test1" for table "atacc1"
425425
ERROR: could not create unique index "atacc_test1"
426-
DETAIL: Table contains duplicated values.
426+
DETAIL: Key (test)=(2) is duplicated.
427427
insert into atacc1 (test) values (3);
428428
drop table atacc1;
429429
-- let's do one where the unique constraint fails
@@ -494,7 +494,7 @@ insert into atacc1 (test) values (2);
494494
alter table atacc1 add constraint atacc_test1 primary key (test);
495495
NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "atacc_test1" for table "atacc1"
496496
ERROR: could not create unique index "atacc_test1"
497-
DETAIL: Table contains duplicated values.
497+
DETAIL: Key (test)=(2) is duplicated.
498498
insert into atacc1 (test) values (3);
499499
drop table atacc1;
500500
-- let's do another one where the primary key constraint fails when added

src/test/regress/expected/create_index.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,7 @@ DETAIL: Key (f1)=(b) already exists.
685685
-- check if constraint is enforced properly at build time
686686
CREATE UNIQUE INDEX CONCURRENTLY concur_index3 ON concur_heap(f2);
687687
ERROR: could not create unique index "concur_index3"
688-
DETAIL: Table contains duplicated values.
688+
DETAIL: Key (f2)=(b) is duplicated.
689689
-- test that expression indexes and partial indexes work concurrently
690690
CREATE INDEX CONCURRENTLY concur_index4 on concur_heap(f2) WHERE f1='a';
691691
CREATE INDEX CONCURRENTLY concur_index5 on concur_heap(f2) WHERE f1='x';

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy