mirror of
https://github.com/postgres/postgres.git
synced 2025-06-16 06:01:02 +03:00
Improve unique-constraint-violation error messages to include the exact
values being complained of. In passing, also remove the arbitrary length limitation in the similar error detail message for foreign key violations. Itagaki Takahiro
This commit is contained in:
@ -271,10 +271,13 @@ SELECT name, 'A' = name AS t FROM try where name = 'A';
|
|||||||
-- expected failures on duplicate key
|
-- expected failures on duplicate key
|
||||||
INSERT INTO try (name) VALUES ('a');
|
INSERT INTO try (name) VALUES ('a');
|
||||||
ERROR: duplicate key value violates unique constraint "try_pkey"
|
ERROR: duplicate key value violates unique constraint "try_pkey"
|
||||||
|
DETAIL: Key (name)=(a) already exists.
|
||||||
INSERT INTO try (name) VALUES ('A');
|
INSERT INTO try (name) VALUES ('A');
|
||||||
ERROR: duplicate key value violates unique constraint "try_pkey"
|
ERROR: duplicate key value violates unique constraint "try_pkey"
|
||||||
|
DETAIL: Key (name)=(A) already exists.
|
||||||
INSERT INTO try (name) VALUES ('aB');
|
INSERT INTO try (name) VALUES ('aB');
|
||||||
ERROR: duplicate key value violates unique constraint "try_pkey"
|
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.
|
-- Make sure that citext_smaller() and citext_lager() work properly.
|
||||||
SELECT citext_smaller( 'aa'::citext, 'ab'::citext ) = 'aa' AS t;
|
SELECT citext_smaller( 'aa'::citext, 'ab'::citext ) = 'aa' AS t;
|
||||||
t
|
t
|
||||||
|
@ -271,10 +271,13 @@ SELECT name, 'A' = name AS t FROM try where name = 'A';
|
|||||||
-- expected failures on duplicate key
|
-- expected failures on duplicate key
|
||||||
INSERT INTO try (name) VALUES ('a');
|
INSERT INTO try (name) VALUES ('a');
|
||||||
ERROR: duplicate key value violates unique constraint "try_pkey"
|
ERROR: duplicate key value violates unique constraint "try_pkey"
|
||||||
|
DETAIL: Key (name)=(a) already exists.
|
||||||
INSERT INTO try (name) VALUES ('A');
|
INSERT INTO try (name) VALUES ('A');
|
||||||
ERROR: duplicate key value violates unique constraint "try_pkey"
|
ERROR: duplicate key value violates unique constraint "try_pkey"
|
||||||
|
DETAIL: Key (name)=(A) already exists.
|
||||||
INSERT INTO try (name) VALUES ('aB');
|
INSERT INTO try (name) VALUES ('aB');
|
||||||
ERROR: duplicate key value violates unique constraint "try_pkey"
|
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.
|
-- Make sure that citext_smaller() and citext_lager() work properly.
|
||||||
SELECT citext_smaller( 'aa'::citext, 'ab'::citext ) = 'aa' AS t;
|
SELECT citext_smaller( 'aa'::citext, 'ab'::citext ) = 'aa' AS t;
|
||||||
t
|
t
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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);
|
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.
|
* Create a palloc'd copy of an index tuple.
|
||||||
*/
|
*/
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* many of the old access method routines have been turned into
|
* many of the old access method routines have been turned into
|
||||||
@ -24,6 +24,8 @@
|
|||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "pgstat.h"
|
#include "pgstat.h"
|
||||||
#include "storage/bufmgr.h"
|
#include "storage/bufmgr.h"
|
||||||
|
#include "utils/builtins.h"
|
||||||
|
#include "utils/lsyscache.h"
|
||||||
#include "utils/rel.h"
|
#include "utils/rel.h"
|
||||||
#include "utils/tqual.h"
|
#include "utils/tqual.h"
|
||||||
|
|
||||||
@ -130,6 +132,59 @@ IndexScanEnd(IndexScanDesc scan)
|
|||||||
pfree(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
|
* heap-or-index-scan access to system catalogs
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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,
|
if (nbuf != InvalidBuffer)
|
||||||
(errcode(ERRCODE_UNIQUE_VIOLATION),
|
_bt_relbuf(rel, nbuf);
|
||||||
errmsg("duplicate key value violates unique constraint \"%s\"",
|
_bt_relbuf(rel, buf);
|
||||||
RelationGetRelationName(rel))));
|
|
||||||
|
{
|
||||||
|
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)
|
else if (all_dead)
|
||||||
{
|
{
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
* 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,
|
HeapTuple violator, TupleDesc tupdesc,
|
||||||
bool spi_err)
|
bool spi_err)
|
||||||
{
|
{
|
||||||
#define BUFLENGTH 512
|
StringInfoData key_names;
|
||||||
char key_names[BUFLENGTH];
|
StringInfoData key_values;
|
||||||
char key_values[BUFLENGTH];
|
|
||||||
char *name_ptr = key_names;
|
|
||||||
char *val_ptr = key_values;
|
|
||||||
bool onfk;
|
bool onfk;
|
||||||
int idx,
|
int idx,
|
||||||
key_idx;
|
key_idx;
|
||||||
@ -3465,6 +3462,8 @@ ri_ReportViolation(RI_QueryKey *qkey, const char *constrname,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get printable versions of the keys involved */
|
/* Get printable versions of the keys involved */
|
||||||
|
initStringInfo(&key_names);
|
||||||
|
initStringInfo(&key_values);
|
||||||
for (idx = 0; idx < qkey->nkeypairs; idx++)
|
for (idx = 0; idx < qkey->nkeypairs; idx++)
|
||||||
{
|
{
|
||||||
int fnum = qkey->keypair[idx][key_idx];
|
int fnum = qkey->keypair[idx][key_idx];
|
||||||
@ -3476,20 +3475,13 @@ ri_ReportViolation(RI_QueryKey *qkey, const char *constrname,
|
|||||||
if (!val)
|
if (!val)
|
||||||
val = "null";
|
val = "null";
|
||||||
|
|
||||||
/*
|
if (idx > 0)
|
||||||
* 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)
|
|
||||||
{
|
{
|
||||||
sprintf(name_ptr, "...");
|
appendStringInfoString(&key_names, ", ");
|
||||||
sprintf(val_ptr, "...");
|
appendStringInfoString(&key_values, ", ");
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
appendStringInfoString(&key_names, name);
|
||||||
name_ptr += sprintf(name_ptr, "%s%s", idx > 0 ? "," : "", name);
|
appendStringInfoString(&key_values, val);
|
||||||
val_ptr += sprintf(val_ptr, "%s%s", idx > 0 ? "," : "", val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onfk)
|
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\"",
|
errmsg("insert or update on table \"%s\" violates foreign key constraint \"%s\"",
|
||||||
RelationGetRelationName(fk_rel), constrname),
|
RelationGetRelationName(fk_rel), constrname),
|
||||||
errdetail("Key (%s)=(%s) is not present in table \"%s\".",
|
errdetail("Key (%s)=(%s) is not present in table \"%s\".",
|
||||||
key_names, key_values,
|
key_names.data, key_values.data,
|
||||||
RelationGetRelationName(pk_rel))));
|
RelationGetRelationName(pk_rel))));
|
||||||
else
|
else
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
@ -3507,7 +3499,7 @@ ri_ReportViolation(RI_QueryKey *qkey, const char *constrname,
|
|||||||
RelationGetRelationName(pk_rel),
|
RelationGetRelationName(pk_rel),
|
||||||
constrname, RelationGetRelationName(fk_rel)),
|
constrname, RelationGetRelationName(fk_rel)),
|
||||||
errdetail("Key (%s)=(%s) is still referenced from table \"%s\".",
|
errdetail("Key (%s)=(%s) is still referenced from table \"%s\".",
|
||||||
key_names, key_values,
|
key_names.data, key_values.data,
|
||||||
RelationGetRelationName(fk_rel))));
|
RelationGetRelationName(fk_rel))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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,
|
static void decompile_column_index_array(Datum column_index_array, Oid relId,
|
||||||
StringInfo buf);
|
StringInfo buf);
|
||||||
static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
|
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);
|
int prettyFlags);
|
||||||
static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
|
static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
|
||||||
int prettyFlags);
|
int prettyFlags);
|
||||||
@ -613,7 +614,7 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
|
|||||||
Oid indexrelid = PG_GETARG_OID(0);
|
Oid indexrelid = PG_GETARG_OID(0);
|
||||||
|
|
||||||
PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0,
|
PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0,
|
||||||
false, 0)));
|
false, false, 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
@ -626,18 +627,31 @@ pg_get_indexdef_ext(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
|
prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
|
||||||
PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno,
|
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 */
|
/* Internal version that returns a palloc'd C string */
|
||||||
char *
|
char *
|
||||||
pg_get_indexdef_string(Oid indexrelid)
|
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 *
|
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)
|
int prettyFlags)
|
||||||
{
|
{
|
||||||
HeapTuple ht_idx;
|
HeapTuple ht_idx;
|
||||||
@ -736,7 +750,7 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc,
|
|||||||
*/
|
*/
|
||||||
initStringInfo(&buf);
|
initStringInfo(&buf);
|
||||||
|
|
||||||
if (!colno)
|
if (!attrsOnly)
|
||||||
appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (",
|
appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (",
|
||||||
idxrec->indisunique ? "UNIQUE " : "",
|
idxrec->indisunique ? "UNIQUE " : "",
|
||||||
quote_identifier(NameStr(idxrelrec->relname)),
|
quote_identifier(NameStr(idxrelrec->relname)),
|
||||||
@ -790,8 +804,7 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc,
|
|||||||
keycoltype = exprType(indexkey);
|
keycoltype = exprType(indexkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Provide decoration only in the colno=0 case */
|
if (!attrsOnly && (!colno || colno == keyno + 1))
|
||||||
if (!colno)
|
|
||||||
{
|
{
|
||||||
/* Add the operator class name, if not default */
|
/* Add the operator class name, if not default */
|
||||||
get_opclass_name(indclass->values[keyno], keycoltype, &buf);
|
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, ')');
|
appendStringInfoChar(&buf, ')');
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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,
|
extern IndexScanDesc RelationGetIndexScan(Relation indexRelation,
|
||||||
int nkeys, ScanKey key);
|
int nkeys, ScanKey key);
|
||||||
extern void IndexScanEnd(IndexScanDesc scan);
|
extern void IndexScanEnd(IndexScanDesc scan);
|
||||||
|
extern void ReportUniqueViolation(Relation indexRelation,
|
||||||
|
Datum *values, bool *isnull);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* heap-or-index access to system catalogs (in genam.c)
|
* heap-or-index access to system catalogs (in genam.c)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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);
|
Datum *values, bool *isnull);
|
||||||
extern Datum nocache_index_getattr(IndexTuple tup, int attnum,
|
extern Datum nocache_index_getattr(IndexTuple tup, int attnum,
|
||||||
TupleDesc tupleDesc, bool *isnull);
|
TupleDesc tupleDesc, bool *isnull);
|
||||||
|
extern void index_deform_tuple(IndexTuple tup, TupleDesc tupleDescriptor,
|
||||||
|
Datum *values, bool *isnull);
|
||||||
extern IndexTuple CopyIndexTuple(IndexTuple source);
|
extern IndexTuple CopyIndexTuple(IndexTuple source);
|
||||||
|
|
||||||
#endif /* ITUP_H */
|
#endif /* ITUP_H */
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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(PG_FUNCTION_ARGS);
|
||||||
extern Datum pg_get_indexdef_ext(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_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_triggerdef(PG_FUNCTION_ARGS);
|
||||||
extern Datum pg_get_constraintdef(PG_FUNCTION_ARGS);
|
extern Datum pg_get_constraintdef(PG_FUNCTION_ARGS);
|
||||||
extern Datum pg_get_constraintdef_ext(PG_FUNCTION_ARGS);
|
extern Datum pg_get_constraintdef_ext(PG_FUNCTION_ARGS);
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
[NO_PID]: ecpg_execute on line 31: using PQexec
|
[NO_PID]: ecpg_execute on line 31: using PQexec
|
||||||
[NO_PID]: sqlca: code: 0, state: 00000
|
[NO_PID]: sqlca: code: 0, state: 00000
|
||||||
[NO_PID]: ecpg_check_PQresult on line 31: ERROR: duplicate key value violates unique constraint "test_pkey"
|
[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]: 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]: 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
|
[NO_PID]: sqlca: code: -239, state: 23505
|
||||||
|
@ -407,6 +407,7 @@ insert into atacc1 (test) values (2);
|
|||||||
-- should fail
|
-- should fail
|
||||||
insert into atacc1 (test) values (2);
|
insert into atacc1 (test) values (2);
|
||||||
ERROR: duplicate key value violates unique constraint "atacc_test1"
|
ERROR: duplicate key value violates unique constraint "atacc_test1"
|
||||||
|
DETAIL: Key (test)=(2) already exists.
|
||||||
-- should succeed
|
-- should succeed
|
||||||
insert into atacc1 (test) values (4);
|
insert into atacc1 (test) values (4);
|
||||||
-- try adding a unique oid constraint
|
-- try adding a unique oid constraint
|
||||||
@ -442,6 +443,7 @@ insert into atacc1 (test,test2) values (4,4);
|
|||||||
-- should fail
|
-- should fail
|
||||||
insert into atacc1 (test,test2) values (4,4);
|
insert into atacc1 (test,test2) values (4,4);
|
||||||
ERROR: duplicate key value violates unique constraint "atacc_test1"
|
ERROR: duplicate key value violates unique constraint "atacc_test1"
|
||||||
|
DETAIL: Key (test, test2)=(4, 4) already exists.
|
||||||
-- should all succeed
|
-- should all succeed
|
||||||
insert into atacc1 (test,test2) values (4,5);
|
insert into atacc1 (test,test2) values (4,5);
|
||||||
insert into atacc1 (test,test2) values (5,4);
|
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 (3, 3);
|
||||||
insert into atacc1 (test2, test) values (2, 3);
|
insert into atacc1 (test2, test) values (2, 3);
|
||||||
ERROR: duplicate key value violates unique constraint "atacc1_test_key"
|
ERROR: duplicate key value violates unique constraint "atacc1_test_key"
|
||||||
|
DETAIL: Key (test)=(3) already exists.
|
||||||
drop table atacc1;
|
drop table atacc1;
|
||||||
-- test primary key constraint adding
|
-- test primary key constraint adding
|
||||||
create table atacc1 ( test int ) with oids;
|
create table atacc1 ( test int ) with oids;
|
||||||
@ -467,6 +470,7 @@ insert into atacc1 (test) values (2);
|
|||||||
-- should fail
|
-- should fail
|
||||||
insert into atacc1 (test) values (2);
|
insert into atacc1 (test) values (2);
|
||||||
ERROR: duplicate key value violates unique constraint "atacc_test1"
|
ERROR: duplicate key value violates unique constraint "atacc_test1"
|
||||||
|
DETAIL: Key (test)=(2) already exists.
|
||||||
-- should succeed
|
-- should succeed
|
||||||
insert into atacc1 (test) values (4);
|
insert into atacc1 (test) values (4);
|
||||||
-- inserting NULL should fail
|
-- inserting NULL should fail
|
||||||
@ -534,6 +538,7 @@ insert into atacc1 (test,test2) values (4,4);
|
|||||||
-- should fail
|
-- should fail
|
||||||
insert into atacc1 (test,test2) values (4,4);
|
insert into atacc1 (test,test2) values (4,4);
|
||||||
ERROR: duplicate key value violates unique constraint "atacc_test1"
|
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);
|
insert into atacc1 (test,test2) values (NULL,3);
|
||||||
ERROR: null value in column "test" violates not-null constraint
|
ERROR: null value in column "test" violates not-null constraint
|
||||||
insert into atacc1 (test,test2) values (3, NULL);
|
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 (3, 3);
|
||||||
insert into atacc1 (test2, test) values (2, 3);
|
insert into atacc1 (test2, test) values (2, 3);
|
||||||
ERROR: duplicate key value violates unique constraint "atacc1_pkey"
|
ERROR: duplicate key value violates unique constraint "atacc1_pkey"
|
||||||
|
DETAIL: Key (test)=(3) already exists.
|
||||||
insert into atacc1 (test2, test) values (1, NULL);
|
insert into atacc1 (test2, test) values (1, NULL);
|
||||||
ERROR: null value in column "test" violates not-null constraint
|
ERROR: null value in column "test" violates not-null constraint
|
||||||
drop table atacc1;
|
drop table atacc1;
|
||||||
|
@ -713,6 +713,7 @@ insert into arr_tbl values ('{1,2}');
|
|||||||
-- failure expected:
|
-- failure expected:
|
||||||
insert into arr_tbl values ('{1,2,3}');
|
insert into arr_tbl values ('{1,2,3}');
|
||||||
ERROR: duplicate key value violates unique constraint "arr_tbl_f1_key"
|
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 ('{2,3,4}');
|
||||||
insert into arr_tbl values ('{1,5,3}');
|
insert into arr_tbl values ('{1,5,3}');
|
||||||
insert into arr_tbl values ('{1,2,10}');
|
insert into arr_tbl values ('{1,2,10}');
|
||||||
|
@ -641,6 +641,7 @@ INSERT INTO func_index_heap VALUES('QWE','RTY');
|
|||||||
-- this should fail because of unique index:
|
-- this should fail because of unique index:
|
||||||
INSERT INTO func_index_heap VALUES('ABCD', 'EF');
|
INSERT INTO func_index_heap VALUES('ABCD', 'EF');
|
||||||
ERROR: duplicate key value violates unique constraint "func_index_index"
|
ERROR: duplicate key value violates unique constraint "func_index_index"
|
||||||
|
DETAIL: Key (textcat(f1, f2))=(ABCDEF) already exists.
|
||||||
-- but this shouldn't:
|
-- but this shouldn't:
|
||||||
INSERT INTO func_index_heap VALUES('QWERTY');
|
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:
|
-- this should fail because of unique index:
|
||||||
INSERT INTO func_index_heap VALUES('ABCD', 'EF');
|
INSERT INTO func_index_heap VALUES('ABCD', 'EF');
|
||||||
ERROR: duplicate key value violates unique constraint "func_index_index"
|
ERROR: duplicate key value violates unique constraint "func_index_index"
|
||||||
|
DETAIL: Key ((f1 || f2))=(ABCDEF) already exists.
|
||||||
-- but this shouldn't:
|
-- but this shouldn't:
|
||||||
INSERT INTO func_index_heap VALUES('QWERTY');
|
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
|
-- check if constraint is set up properly to be enforced
|
||||||
INSERT INTO concur_heap VALUES ('b','x');
|
INSERT INTO concur_heap VALUES ('b','x');
|
||||||
ERROR: duplicate key value violates unique constraint "concur_index2"
|
ERROR: duplicate key value violates unique constraint "concur_index2"
|
||||||
|
DETAIL: Key (f1)=(b) already exists.
|
||||||
-- check if constraint is enforced properly at build time
|
-- check if constraint is enforced properly at build time
|
||||||
CREATE UNIQUE INDEX CONCURRENTLY concur_index3 ON concur_heap(f2);
|
CREATE UNIQUE INDEX CONCURRENTLY concur_index3 ON concur_heap(f2);
|
||||||
ERROR: could not create unique index "concur_index3"
|
ERROR: could not create unique index "concur_index3"
|
||||||
|
@ -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 (5, 10);
|
||||||
INSERT INTO inhg VALUES (20, 10); -- should fail
|
INSERT INTO inhg VALUES (20, 10); -- should fail
|
||||||
ERROR: duplicate key value violates unique constraint "inhg_pkey"
|
ERROR: duplicate key value violates unique constraint "inhg_pkey"
|
||||||
|
DETAIL: Key (xx)=(10) already exists.
|
||||||
DROP TABLE inhg;
|
DROP TABLE inhg;
|
||||||
/* Multiple primary keys creation should fail */
|
/* Multiple primary keys creation should fail */
|
||||||
CREATE TABLE inhg (x text, LIKE inhx INCLUDING INDEXES, PRIMARY KEY(x)); /* fails */
|
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 ('test', 10, 15);
|
||||||
INSERT INTO inhg (xx, yy, x) VALUES ('foo', 10, 15); -- should fail
|
INSERT INTO inhg (xx, yy, x) VALUES ('foo', 10, 15); -- should fail
|
||||||
ERROR: duplicate key value violates unique constraint "inhg_x_key"
|
ERROR: duplicate key value violates unique constraint "inhg_x_key"
|
||||||
|
DETAIL: Key (x)=(15) already exists.
|
||||||
DROP TABLE inhg;
|
DROP TABLE inhg;
|
||||||
DROP TABLE inhz;
|
DROP TABLE inhz;
|
||||||
-- Test changing the type of inherited columns
|
-- Test changing the type of inherited columns
|
||||||
|
@ -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');
|
insert into PField values ('PF1_1', 'should fail due to unique index');
|
||||||
ERROR: duplicate key value violates unique constraint "pfield_name"
|
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';
|
update PSlot set backlink = 'WS.not.there' where slotname = 'PS.base.a1';
|
||||||
ERROR: WS.not.there does not exist
|
ERROR: WS.not.there does not exist
|
||||||
CONTEXT: PL/pgSQL function "tg_backlink_a" line 16 at assignment
|
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
|
CONTEXT: PL/pgSQL function "tg_slotlink_a" line 16 at assignment
|
||||||
insert into HSlot values ('HS', 'base.hub1', 1, '');
|
insert into HSlot values ('HS', 'base.hub1', 1, '');
|
||||||
ERROR: duplicate key value violates unique constraint "hslot_name"
|
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, '');
|
insert into HSlot values ('HS', 'base.hub1', 20, '');
|
||||||
ERROR: no manual manipulation of HSlot
|
ERROR: no manual manipulation of HSlot
|
||||||
delete from HSlot;
|
delete from HSlot;
|
||||||
|
@ -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);
|
||||||
INSERT INTO koju VALUES (1);
|
INSERT INTO koju VALUES (1);
|
||||||
ERROR: duplicate key value violates unique constraint "koju_a_key"
|
ERROR: duplicate key value violates unique constraint "koju_a_key"
|
||||||
|
DETAIL: Key (a)=(1) already exists.
|
||||||
rollback to x;
|
rollback to x;
|
||||||
CREATE TABLE koju (a INT UNIQUE);
|
CREATE TABLE koju (a INT UNIQUE);
|
||||||
NOTICE: CREATE TABLE / UNIQUE will create implicit index "koju_a_key" for table "koju"
|
NOTICE: CREATE TABLE / UNIQUE will create implicit index "koju_a_key" for table "koju"
|
||||||
INSERT INTO koju VALUES (1);
|
INSERT INTO koju VALUES (1);
|
||||||
INSERT INTO koju VALUES (1);
|
INSERT INTO koju VALUES (1);
|
||||||
ERROR: duplicate key value violates unique constraint "koju_a_key"
|
ERROR: duplicate key value violates unique constraint "koju_a_key"
|
||||||
|
DETAIL: Key (a)=(1) already exists.
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
DROP TABLE foo;
|
DROP TABLE foo;
|
||||||
DROP TABLE baz;
|
DROP TABLE baz;
|
||||||
|
@ -119,6 +119,7 @@ CREATE UNIQUE INDEX guid1_unique_BTREE ON guid1 USING BTREE (guid_field);
|
|||||||
-- should fail
|
-- should fail
|
||||||
INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111');
|
INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111');
|
||||||
ERROR: duplicate key value violates unique constraint "guid1_unique_btree"
|
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
|
-- check to see whether the new indexes are actually there
|
||||||
SELECT count(*) FROM pg_class WHERE relkind='i' AND relname LIKE 'guid%';
|
SELECT count(*) FROM pg_class WHERE relkind='i' AND relname LIKE 'guid%';
|
||||||
count
|
count
|
||||||
|
@ -294,6 +294,7 @@ INSERT INTO PRIMARY_TBL VALUES (1, 'one');
|
|||||||
INSERT INTO PRIMARY_TBL VALUES (2, 'two');
|
INSERT INTO PRIMARY_TBL VALUES (2, 'two');
|
||||||
INSERT INTO PRIMARY_TBL VALUES (1, 'three');
|
INSERT INTO PRIMARY_TBL VALUES (1, 'three');
|
||||||
ERROR: duplicate key value violates unique constraint "primary_tbl_pkey"
|
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 (4, 'three');
|
||||||
INSERT INTO PRIMARY_TBL VALUES (5, 'one');
|
INSERT INTO PRIMARY_TBL VALUES (5, 'one');
|
||||||
INSERT INTO PRIMARY_TBL (t) VALUES ('six');
|
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 (2, 'two');
|
||||||
INSERT INTO UNIQUE_TBL VALUES (1, 'three');
|
INSERT INTO UNIQUE_TBL VALUES (1, 'three');
|
||||||
ERROR: duplicate key value violates unique constraint "unique_tbl_i_key"
|
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 (4, 'four');
|
||||||
INSERT INTO UNIQUE_TBL VALUES (5, 'one');
|
INSERT INTO UNIQUE_TBL VALUES (5, 'one');
|
||||||
INSERT INTO UNIQUE_TBL (t) VALUES ('six');
|
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, 'three');
|
||||||
INSERT INTO UNIQUE_TBL VALUES (1, 'one');
|
INSERT INTO UNIQUE_TBL VALUES (1, 'one');
|
||||||
ERROR: duplicate key value violates unique constraint "unique_tbl_i_key"
|
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 VALUES (5, 'one');
|
||||||
INSERT INTO UNIQUE_TBL (t) VALUES ('six');
|
INSERT INTO UNIQUE_TBL (t) VALUES ('six');
|
||||||
SELECT '' AS five, * FROM UNIQUE_TBL;
|
SELECT '' AS five, * FROM UNIQUE_TBL;
|
||||||
@ -389,6 +392,7 @@ BEGIN;
|
|||||||
-- default is immediate so this should fail right away
|
-- default is immediate so this should fail right away
|
||||||
UPDATE unique_tbl SET i = 1 WHERE i = 0;
|
UPDATE unique_tbl SET i = 1 WHERE i = 0;
|
||||||
ERROR: duplicate key value violates unique constraint "unique_tbl_i_key"
|
ERROR: duplicate key value violates unique constraint "unique_tbl_i_key"
|
||||||
|
DETAIL: Key (i)=(1) already exists.
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
-- check is done at end of statement, so this should succeed
|
-- check is done at end of statement, so this should succeed
|
||||||
UPDATE unique_tbl SET i = i+1;
|
UPDATE unique_tbl SET i = i+1;
|
||||||
@ -446,11 +450,13 @@ BEGIN;
|
|||||||
INSERT INTO unique_tbl VALUES (3, 'Three'); -- should succeed for now
|
INSERT INTO unique_tbl VALUES (3, 'Three'); -- should succeed for now
|
||||||
COMMIT; -- should fail
|
COMMIT; -- should fail
|
||||||
ERROR: duplicate key value violates unique constraint "unique_tbl_i_key"
|
ERROR: duplicate key value violates unique constraint "unique_tbl_i_key"
|
||||||
|
DETAIL: Key (i)=(3) already exists.
|
||||||
-- make constraint check immediate
|
-- make constraint check immediate
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SET CONSTRAINTS ALL IMMEDIATE;
|
SET CONSTRAINTS ALL IMMEDIATE;
|
||||||
INSERT INTO unique_tbl VALUES (3, 'Three'); -- should fail
|
INSERT INTO unique_tbl VALUES (3, 'Three'); -- should fail
|
||||||
ERROR: duplicate key value violates unique constraint "unique_tbl_i_key"
|
ERROR: duplicate key value violates unique constraint "unique_tbl_i_key"
|
||||||
|
DETAIL: Key (i)=(3) already exists.
|
||||||
COMMIT;
|
COMMIT;
|
||||||
-- forced check when SET CONSTRAINTS is called
|
-- forced check when SET CONSTRAINTS is called
|
||||||
BEGIN;
|
BEGIN;
|
||||||
@ -458,6 +464,7 @@ SET CONSTRAINTS ALL DEFERRED;
|
|||||||
INSERT INTO unique_tbl VALUES (3, 'Three'); -- should succeed for now
|
INSERT INTO unique_tbl VALUES (3, 'Three'); -- should succeed for now
|
||||||
SET CONSTRAINTS ALL IMMEDIATE; -- should fail
|
SET CONSTRAINTS ALL IMMEDIATE; -- should fail
|
||||||
ERROR: duplicate key value violates unique constraint "unique_tbl_i_key"
|
ERROR: duplicate key value violates unique constraint "unique_tbl_i_key"
|
||||||
|
DETAIL: Key (i)=(3) already exists.
|
||||||
COMMIT;
|
COMMIT;
|
||||||
-- test a HOT update that invalidates the conflicting tuple.
|
-- test a HOT update that invalidates the conflicting tuple.
|
||||||
-- the trigger should still fire and catch the violation
|
-- 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';
|
UPDATE unique_tbl SET t = 'THREE' WHERE i = 3 AND t = 'Three';
|
||||||
COMMIT; -- should fail
|
COMMIT; -- should fail
|
||||||
ERROR: duplicate key value violates unique constraint "unique_tbl_i_key"
|
ERROR: duplicate key value violates unique constraint "unique_tbl_i_key"
|
||||||
|
DETAIL: Key (i)=(3) already exists.
|
||||||
SELECT * FROM unique_tbl;
|
SELECT * FROM unique_tbl;
|
||||||
i | t
|
i | t
|
||||||
---+-------
|
---+-------
|
||||||
|
@ -49,6 +49,7 @@ ALTER INDEX testschema.anindex SET TABLESPACE testspace;
|
|||||||
INSERT INTO testschema.atable VALUES(3); -- ok
|
INSERT INTO testschema.atable VALUES(3); -- ok
|
||||||
INSERT INTO testschema.atable VALUES(1); -- fail (checks index)
|
INSERT INTO testschema.atable VALUES(1); -- fail (checks index)
|
||||||
ERROR: duplicate key value violates unique constraint "anindex"
|
ERROR: duplicate key value violates unique constraint "anindex"
|
||||||
|
DETAIL: Key (column1)=(1) already exists.
|
||||||
SELECT COUNT(*) FROM testschema.atable; -- checks heap
|
SELECT COUNT(*) FROM testschema.atable; -- checks heap
|
||||||
count
|
count
|
||||||
-------
|
-------
|
||||||
|
Reference in New Issue
Block a user