diff options
author | Tom Lane | 2009-08-12 23:00:12 +0000 |
---|---|---|
committer | Tom Lane | 2009-08-12 23:00:12 +0000 |
commit | 5e4c6527f387130eb3bf8efc7189e3fe764df0fe (patch) | |
tree | 344c7731f791fb681f2beb4179626949e1ae808e | |
parent | 4b0e0eea12d7fc0c5beb74a0a8517396b9643ff3 (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.c | 39 |
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); |