summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2009-08-12 23:00:12 +0000
committerTom Lane2009-08-12 23:00:12 +0000
commit5e4c6527f387130eb3bf8efc7189e3fe764df0fe (patch)
tree344c7731f791fb681f2beb4179626949e1ae808e
parent4b0e0eea12d7fc0c5beb74a0a8517396b9643ff3 (diff)
Improve error message for the case where a requested foreign key constraint
does match some unique index on the referenced table, but that index is only deferrably unique. We were doing this nicely for the default-to-primary-key case, but were being lazy for the other case. Dean Rasheed
-rw-r--r--src/backend/commands/tablecmds.c39
1 files changed, 31 insertions, 8 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 30a5c8b454..7029c3c1e8 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -5117,6 +5117,7 @@ transformFkeyCheckAttrs(Relation pkrel,
{
Oid indexoid = InvalidOid;
bool found = false;
+ bool found_deferrable = false;
List *indexoidlist;
ListCell *indexoidscan;
@@ -5143,12 +5144,11 @@ transformFkeyCheckAttrs(Relation pkrel,
indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
/*
- * Must have the right number of columns; must be unique (non
- * deferrable) and not a partial index; forget it if there are any
- * expressions, too
+ * Must have the right number of columns; must be unique and not a
+ * partial index; forget it if there are any expressions, too
*/
if (indexStruct->indnatts == numattrs &&
- indexStruct->indisunique && indexStruct->indimmediate &&
+ indexStruct->indisunique &&
heap_attisnull(indexTuple, Anum_pg_index_indpred) &&
heap_attisnull(indexTuple, Anum_pg_index_indexprs))
{
@@ -5198,6 +5198,21 @@ transformFkeyCheckAttrs(Relation pkrel,
break;
}
}
+
+ /*
+ * Refuse to use a deferrable unique/primary key. This is per
+ * SQL spec, and there would be a lot of interesting semantic
+ * problems if we tried to allow it.
+ */
+ if (found && !indexStruct->indimmediate)
+ {
+ /*
+ * Remember that we found an otherwise matching index, so
+ * that we can generate a more appropriate error message.
+ */
+ found_deferrable = true;
+ found = false;
+ }
}
ReleaseSysCache(indexTuple);
if (found)
@@ -5205,10 +5220,18 @@ transformFkeyCheckAttrs(Relation pkrel,
}
if (!found)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_FOREIGN_KEY),
- errmsg("there is no unique constraint matching given keys for referenced table \"%s\"",
- RelationGetRelationName(pkrel))));
+ {
+ if (found_deferrable)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("cannot use a deferrable unique constraint for referenced table \"%s\"",
+ RelationGetRelationName(pkrel))));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FOREIGN_KEY),
+ errmsg("there is no unique constraint matching given keys for referenced table \"%s\"",
+ RelationGetRelationName(pkrel))));
+ }
list_free(indexoidlist);