1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-14 18:42:34 +03:00

Support deferrable uniqueness constraints.

The current implementation fires an AFTER ROW trigger for each tuple that
looks like it might be non-unique according to the index contents at the
time of insertion.  This works well as long as there aren't many conflicts,
but won't scale to massive unique-key reassignments.  Improving that case
is a TODO item.

Dean Rasheed
This commit is contained in:
Tom Lane
2009-07-29 20:56:21 +00:00
parent 8504905793
commit 25d9bf2e3e
51 changed files with 1241 additions and 245 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.292 2009/07/28 02:56:30 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.293 2009/07/29 20:56:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -4391,6 +4391,8 @@ ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
stmt->unique,
stmt->primary,
stmt->isconstraint,
stmt->deferrable,
stmt->initdeferred,
true, /* is_alter_table */
check_rights,
skip_build,
@ -4955,6 +4957,17 @@ transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
if (indexStruct->indisprimary)
{
/*
* Refuse to use a deferrable primary key. This is per SQL spec,
* and there would be a lot of interesting semantic problems if
* we tried to allow it.
*/
if (!indexStruct->indimmediate)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("cannot use a deferrable primary key for referenced table \"%s\"",
RelationGetRelationName(pkrel))));
*indexOid = indexoid;
break;
}
@ -5040,11 +5053,12 @@ transformFkeyCheckAttrs(Relation pkrel,
indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
/*
* Must have the right number of columns; must be unique and not a
* partial index; forget it if there are any expressions, too
* 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
*/
if (indexStruct->indnatts == numattrs &&
indexStruct->indisunique &&
indexStruct->indisunique && indexStruct->indimmediate &&
heap_attisnull(indexTuple, Anum_pg_index_indpred) &&
heap_attisnull(indexTuple, Anum_pg_index_indexprs))
{
@ -5243,7 +5257,8 @@ CreateFKCheckTrigger(RangeVar *myRel, FkConstraint *fkconstraint,
fk_trigger->constrrel = fkconstraint->pktable;
fk_trigger->args = NIL;
(void) CreateTrigger(fk_trigger, constraintOid, indexOid, false);
(void) CreateTrigger(fk_trigger, constraintOid, indexOid,
"RI_ConstraintTrigger", false);
/* Make changes-so-far visible */
CommandCounterIncrement();
@ -5322,7 +5337,8 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
}
fk_trigger->args = NIL;
(void) CreateTrigger(fk_trigger, constraintOid, indexOid, false);
(void) CreateTrigger(fk_trigger, constraintOid, indexOid,
"RI_ConstraintTrigger", false);
/* Make changes-so-far visible */
CommandCounterIncrement();
@ -5373,7 +5389,8 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
}
fk_trigger->args = NIL;
(void) CreateTrigger(fk_trigger, constraintOid, indexOid, false);
(void) CreateTrigger(fk_trigger, constraintOid, indexOid,
"RI_ConstraintTrigger", false);
}
/*