From: Tom Lane Date: Wed, 12 Aug 2009 23:00:12 +0000 (+0000) Subject: Improve error message for the case where a requested foreign key constraint X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=5e4c6527f387130eb3bf8efc7189e3fe764df0fe;p=users%2Fsimon%2Fpostgres.git 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 --- 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);