{
Oid indexoid = InvalidOid;
bool found = false;
+ bool found_deferrable = false;
List *indexoidlist;
ListCell *indexoidscan;
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))
{
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)
}
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);