aboutsummaryrefslogtreecommitdiff
path: root/src/backend/catalog/index.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/catalog/index.c')
-rw-r--r--src/backend/catalog/index.c69
1 files changed, 64 insertions, 5 deletions
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 0199ca67303..73472d1568e 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.319 2009/07/28 02:56:29 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.320 2009/07/29 20:56:18 tgl Exp $
*
*
* INTERFACE ROUTINES
@@ -40,14 +40,18 @@
#include "catalog/pg_operator.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_tablespace.h"
+#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
#include "catalog/storage.h"
#include "commands/tablecmds.h"
+#include "commands/trigger.h"
#include "executor/executor.h"
#include "miscadmin.h"
+#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/var.h"
+#include "parser/parser.h"
#include "storage/bufmgr.h"
#include "storage/lmgr.h"
#include "storage/procarray.h"
@@ -87,6 +91,7 @@ static void UpdateIndexRelation(Oid indexoid, Oid heapoid,
Oid *classOids,
int16 *coloptions,
bool primary,
+ bool immediate,
bool isvalid);
static void index_update_stats(Relation rel, bool hasindex, bool isprimary,
Oid reltoastidxid, double reltuples);
@@ -372,6 +377,7 @@ UpdateIndexRelation(Oid indexoid,
Oid *classOids,
int16 *coloptions,
bool primary,
+ bool immediate,
bool isvalid)
{
int2vector *indkey;
@@ -439,6 +445,7 @@ UpdateIndexRelation(Oid indexoid,
values[Anum_pg_index_indnatts - 1] = Int16GetDatum(indexInfo->ii_NumIndexAttrs);
values[Anum_pg_index_indisunique - 1] = BoolGetDatum(indexInfo->ii_Unique);
values[Anum_pg_index_indisprimary - 1] = BoolGetDatum(primary);
+ values[Anum_pg_index_indimmediate - 1] = BoolGetDatum(immediate);
values[Anum_pg_index_indisclustered - 1] = BoolGetDatum(false);
values[Anum_pg_index_indisvalid - 1] = BoolGetDatum(isvalid);
values[Anum_pg_index_indcheckxmin - 1] = BoolGetDatum(false);
@@ -488,6 +495,8 @@ UpdateIndexRelation(Oid indexoid,
* reloptions: AM-specific options
* isprimary: index is a PRIMARY KEY
* isconstraint: index is owned by a PRIMARY KEY or UNIQUE constraint
+ * deferrable: constraint is DEFERRABLE
+ * initdeferred: constraint is INITIALLY DEFERRED
* allow_system_table_mods: allow table to be a system catalog
* skip_build: true to skip the index_build() step for the moment; caller
* must do it later (typically via reindex_index())
@@ -509,6 +518,8 @@ index_create(Oid heapRelationId,
Datum reloptions,
bool isprimary,
bool isconstraint,
+ bool deferrable,
+ bool initdeferred,
bool allow_system_table_mods,
bool skip_build,
bool concurrent)
@@ -679,7 +690,9 @@ index_create(Oid heapRelationId,
* ----------------
*/
UpdateIndexRelation(indexRelationId, heapRelationId, indexInfo,
- classObjectId, coloptions, isprimary, !concurrent);
+ classObjectId, coloptions, isprimary,
+ !deferrable,
+ !concurrent);
/*
* Register constraint and dependencies for the index.
@@ -726,8 +739,8 @@ index_create(Oid heapRelationId,
conOid = CreateConstraintEntry(indexRelationName,
namespaceId,
constraintType,
- false, /* isDeferrable */
- false, /* isDeferred */
+ deferrable,
+ initdeferred,
heapRelationId,
indexInfo->ii_KeyAttrNumbers,
indexInfo->ii_NumIndexAttrs,
@@ -753,6 +766,40 @@ index_create(Oid heapRelationId,
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
+
+ /*
+ * If the constraint is deferrable, create the deferred uniqueness
+ * checking trigger. (The trigger will be given an internal
+ * dependency on the constraint by CreateTrigger, so there's no
+ * need to do anything more here.)
+ */
+ if (deferrable)
+ {
+ RangeVar *heapRel;
+ CreateTrigStmt *trigger;
+
+ heapRel = makeRangeVar(get_namespace_name(namespaceId),
+ pstrdup(RelationGetRelationName(heapRelation)),
+ -1);
+
+ trigger = makeNode(CreateTrigStmt);
+ trigger->trigname = pstrdup(indexRelationName);
+ trigger->relation = heapRel;
+ trigger->funcname = SystemFuncName("unique_key_recheck");
+ trigger->args = NIL;
+ trigger->before = false;
+ trigger->row = true;
+ trigger->events = TRIGGER_TYPE_INSERT | TRIGGER_TYPE_UPDATE;
+ trigger->isconstraint = true;
+ trigger->deferrable = true;
+ trigger->initdeferred = initdeferred;
+ trigger->constrrel = NULL;
+
+ (void) CreateTrigger(trigger, conOid, indexRelationId,
+ isprimary ? "PK_ConstraintTrigger" :
+ "Unique_ConstraintTrigger",
+ false);
+ }
}
else
{
@@ -791,6 +838,10 @@ index_create(Oid heapRelationId,
recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
}
+
+ /* Non-constraint indexes can't be deferrable */
+ Assert(!deferrable);
+ Assert(!initdeferred);
}
/* Store dependency on operator classes */
@@ -823,6 +874,13 @@ index_create(Oid heapRelationId,
DEPENDENCY_AUTO);
}
}
+ else
+ {
+ /* Bootstrap mode - assert we weren't asked for constraint support */
+ Assert(!isconstraint);
+ Assert(!deferrable);
+ Assert(!initdeferred);
+ }
/*
* Advance the command counter so that we can see the newly-entered
@@ -2190,7 +2248,8 @@ validate_index_heapscan(Relation heapRelation,
isnull,
&rootTuple,
heapRelation,
- indexInfo->ii_Unique);
+ indexInfo->ii_Unique ?
+ UNIQUE_CHECK_YES : UNIQUE_CHECK_NO);
state->tups_inserted += 1;
}