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
This commit is contained in:
parent
5d3e2324a6
commit
b6bde524af
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.296 2009/08/07 15:27:56 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.297 2009/08/12 23:00:12 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -5117,6 +5117,7 @@ transformFkeyCheckAttrs(Relation pkrel,
|
||||||
{
|
{
|
||||||
Oid indexoid = InvalidOid;
|
Oid indexoid = InvalidOid;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
bool found_deferrable = false;
|
||||||
List *indexoidlist;
|
List *indexoidlist;
|
||||||
ListCell *indexoidscan;
|
ListCell *indexoidscan;
|
||||||
|
|
||||||
|
@ -5143,12 +5144,11 @@ transformFkeyCheckAttrs(Relation pkrel,
|
||||||
indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
|
indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Must have the right number of columns; must be unique (non
|
* Must have the right number of columns; must be unique and not a
|
||||||
* deferrable) and not a partial index; forget it if there are any
|
* partial index; forget it if there are any expressions, too
|
||||||
* expressions, too
|
|
||||||
*/
|
*/
|
||||||
if (indexStruct->indnatts == numattrs &&
|
if (indexStruct->indnatts == numattrs &&
|
||||||
indexStruct->indisunique && indexStruct->indimmediate &&
|
indexStruct->indisunique &&
|
||||||
heap_attisnull(indexTuple, Anum_pg_index_indpred) &&
|
heap_attisnull(indexTuple, Anum_pg_index_indpred) &&
|
||||||
heap_attisnull(indexTuple, Anum_pg_index_indexprs))
|
heap_attisnull(indexTuple, Anum_pg_index_indexprs))
|
||||||
{
|
{
|
||||||
|
@ -5198,6 +5198,21 @@ transformFkeyCheckAttrs(Relation pkrel,
|
||||||
break;
|
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);
|
ReleaseSysCache(indexTuple);
|
||||||
if (found)
|
if (found)
|
||||||
|
@ -5205,10 +5220,18 @@ transformFkeyCheckAttrs(Relation pkrel,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
|
{
|
||||||
|
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,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_FOREIGN_KEY),
|
(errcode(ERRCODE_INVALID_FOREIGN_KEY),
|
||||||
errmsg("there is no unique constraint matching given keys for referenced table \"%s\"",
|
errmsg("there is no unique constraint matching given keys for referenced table \"%s\"",
|
||||||
RelationGetRelationName(pkrel))));
|
RelationGetRelationName(pkrel))));
|
||||||
|
}
|
||||||
|
|
||||||
list_free(indexoidlist);
|
list_free(indexoidlist);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue