OSDN Git Service

Department of second thoughts: let's show the exact key during unique index
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 1 Aug 2009 20:59:17 +0000 (20:59 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 1 Aug 2009 20:59:17 +0000 (20:59 +0000)
build failures, too.  Refactor a bit more since that error message isn't
spelled the same.

src/backend/access/index/genam.c
src/backend/access/nbtree/nbtinsert.c
src/backend/utils/sort/tuplesort.c
src/include/access/genam.h
src/test/regress/expected/alter_table.out
src/test/regress/expected/create_index.out

index 6482aaa..860e576 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.75 2009/08/01 19:59:41 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.76 2009/08/01 20:59:17 tgl Exp $
  *
  * NOTES
  *       many of the old access method routines have been turned into
@@ -133,13 +133,16 @@ IndexScanEnd(IndexScanDesc scan)
 }
 
 /*
- * ReportUniqueViolation -- Report a unique-constraint violation.
+ * BuildIndexValueDescription
  *
- * The index entry represented by values[]/isnull[] violates the unique
- * constraint enforced by this index.  Throw a suitable error.
+ * Construct a string describing the contents of an index entry, in the
+ * form "(key_name, ...)=(key_value, ...)".  This is currently used
+ * only for building unique-constraint error messages, but we don't want
+ * to hardwire the spelling of the messages here.
  */
-void
-ReportUniqueViolation(Relation indexRelation, Datum *values, bool *isnull)
+char *
+BuildIndexValueDescription(Relation indexRelation,
+                                                  Datum *values, bool *isnull)
 {
        /*
         * 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)
         * are ever to support non-btree unique indexes.
         */
        TupleDesc       tupdesc = RelationGetDescr(indexRelation);
-       char       *key_names;
-       StringInfoData key_values;
+       StringInfoData buf;
        int                     i;
 
-       key_names = pg_get_indexdef_columns(RelationGetRelid(indexRelation), true);
+       initStringInfo(&buf);
+       appendStringInfo(&buf, "(%s)=(",
+                                        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;
@@ -173,16 +176,13 @@ ReportUniqueViolation(Relation indexRelation, Datum *values, bool *isnull)
                }
 
                if (i > 0)
-                       appendStringInfoString(&key_values, ", ");
-               appendStringInfoString(&key_values, val);
+                       appendStringInfoString(&buf, ", ");
+               appendStringInfoString(&buf, 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)));
+       appendStringInfoChar(&buf, ')');
+
+       return buf.data;
 }
 
 
index ee3d89f..dd3736a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.172 2009/08/01 19:59:41 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.173 2009/08/01 20:59:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -365,7 +365,7 @@ _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel,
                                         * 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,
+                                        * BuildIndexValueDescription could make catalog accesses,
                                         * which in the worst case might touch this same index
                                         * and cause deadlocks.
                                         */
@@ -379,7 +379,13 @@ _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel,
 
                                                index_deform_tuple(itup, RelationGetDescr(rel),
                                                                                   values, isnull);
-                                               ReportUniqueViolation(rel, values, isnull);
+                                               ereport(ERROR,
+                                                               (errcode(ERRCODE_UNIQUE_VIOLATION),
+                                                                errmsg("duplicate key value violates unique constraint \"%s\"",
+                                                                               RelationGetRelationName(rel)),
+                                                                errdetail("Key %s already exists.",
+                                                                                  BuildIndexValueDescription(rel,
+                                                                                                                       values, isnull))));
                                        }
                                }
                                else if (all_dead)
index 6d07296..cb89f65 100644 (file)
@@ -91,7 +91,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.91 2009/06/11 14:49:06 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.92 2009/08/01 20:59:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2801,11 +2801,19 @@ comparetup_index_btree(const SortTuple *a, const SortTuple *b,
         * error in that case.
         */
        if (state->enforceUnique && !equal_hasnull && tuple1 != tuple2)
+       {
+               Datum   values[INDEX_MAX_KEYS];
+               bool    isnull[INDEX_MAX_KEYS];
+
+               index_deform_tuple(tuple1, tupDes, values, isnull);
                ereport(ERROR,
                                (errcode(ERRCODE_UNIQUE_VIOLATION),
                                 errmsg("could not create unique index \"%s\"",
                                                RelationGetRelationName(state->indexRel)),
-                                errdetail("Table contains duplicated values.")));
+                                errdetail("Key %s is duplicated.",
+                                                  BuildIndexValueDescription(state->indexRel,
+                                                                                                         values, isnull))));
+       }
 
        /*
         * If key values are equal, we sort on ItemPointer.  This does not affect
index 1902526..068d964 100644 (file)
@@ -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.80 2009/08/01 19:59:41 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.81 2009/08/01 20:59:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -164,8 +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);
+extern char *BuildIndexValueDescription(Relation indexRelation,
+                                                  Datum *values, bool *isnull);
 
 /*
  * heap-or-index access to system catalogs (in genam.c)
index 3c9bb63..20bf3de 100644 (file)
@@ -423,7 +423,7 @@ insert into atacc1 (test) values (2);
 alter table atacc1 add constraint atacc_test1 unique (test);
 NOTICE:  ALTER TABLE / ADD UNIQUE will create implicit index "atacc_test1" for table "atacc1"
 ERROR:  could not create unique index "atacc_test1"
-DETAIL:  Table contains duplicated values.
+DETAIL:  Key (test)=(2) is duplicated.
 insert into atacc1 (test) values (3);
 drop table atacc1;
 -- let's do one where the unique constraint fails
@@ -494,7 +494,7 @@ insert into atacc1 (test) values (2);
 alter table atacc1 add constraint atacc_test1 primary key (test);
 NOTICE:  ALTER TABLE / ADD PRIMARY KEY will create implicit index "atacc_test1" for table "atacc1"
 ERROR:  could not create unique index "atacc_test1"
-DETAIL:  Table contains duplicated values.
+DETAIL:  Key (test)=(2) is duplicated.
 insert into atacc1 (test) values (3);
 drop table atacc1;
 -- let's do another one where the primary key constraint fails when added
index 02f2474..079a640 100644 (file)
@@ -685,7 +685,7 @@ 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"
-DETAIL:  Table contains duplicated values.
+DETAIL:  Key (f2)=(b) is duplicated.
 -- test that expression indexes and partial indexes work concurrently
 CREATE INDEX CONCURRENTLY concur_index4 on concur_heap(f2) WHERE f1='a';
 CREATE INDEX CONCURRENTLY concur_index5 on concur_heap(f2) WHERE f1='x';