Warning: This patch is only a work in work in progress.

Current Status:

This patch modifies postgres's current behavior by creating foreign-key 
triggers on not only the source and referenced tables, but also the children 
of the referenced table.  It modifies the source triggers, removing the ONLY 
keyword when looking up the referenced key.

Shortcomings:

The triggers are only created when the foreign key is created, so any new 
tables that inherit from the referenced table will not have the triggers.  
This can be fixed fairly easily.

When removing the ONLY clause on the foreign key checks, I also had to remove 
the FOR SHARE OF x part.  This was in the following functions: RI_FKey_check, 
ri_Check_Pk_Match, RI_FKey_noaction_del, RI_FKey_noaction_upd, 
RI_FKey_restrict_del. I don't really understand the significance of this.

There is no way to turn off the new behavior, which will likely cause 
breakages in existing applications.  If this behavior was made optional on a 
per foreign key basis, with the current syntax being backwards compatible, 
then this would not be an issue.

Inherited relations don't share primary key indexes, so there is the 
possibility of duplicates.  Can this be fixed by putting triggers on the 
inherited tables to ensure they aren't duplicating a primary key?

Can/should indexes, constraints, triggers be shared between inherited tables?  
Would this be a lot of work, and is it desired?  Does it need to be 
configurable per index, or per inheritance?

Matt Newell,
Blur Studio
? GNUmakefile
? config.log
? config.status
? inherit_fkey.diff
? pre_upgrade.sql
? src/Makefile.global
? src/backend/postgres
? src/backend/catalog/postgres.bki
? src/backend/catalog/postgres.description
? src/backend/utils/mb/conversion_procs/conversion_create.sql
? src/backend/utils/mb/conversion_procs/ascii_and_mic/libascii_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/cyrillic_and_mic/libcyrillic_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/euc_cn_and_mic/libeuc_cn_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/libeuc_jp_and_sjis.so.0.0
? src/backend/utils/mb/conversion_procs/euc_kr_and_mic/libeuc_kr_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/euc_tw_and_big5/libeuc_tw_and_big5.so.0.0
? src/backend/utils/mb/conversion_procs/latin2_and_win1250/liblatin2_and_win1250.so.0.0
? src/backend/utils/mb/conversion_procs/latin_and_mic/liblatin_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_ascii/libutf8_and_ascii.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_big5/libutf8_and_big5.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/libutf8_and_cyrillic.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/libutf8_and_euc_cn.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/libutf8_and_euc_jp.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/libutf8_and_euc_kr.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/libutf8_and_euc_tw.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_gb18030/libutf8_and_gb18030.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_gbk/libutf8_and_gbk.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_iso8859/libutf8_and_iso8859.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/libutf8_and_iso8859_1.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_johab/libutf8_and_johab.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_sjis/libutf8_and_sjis.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_uhc/libutf8_and_uhc.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_win1250/libutf8_and_win1250.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_win1252/libutf8_and_win1252.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_win1256/libutf8_and_win1256.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_win1258/libutf8_and_win1258.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_win874/libutf8_and_win874.so.0.0
? src/bin/initdb/initdb
? src/bin/ipcclean/ipcclean
? src/bin/pg_config/pg_config
? src/bin/pg_controldata/pg_controldata
? src/bin/pg_ctl/pg_ctl
? src/bin/pg_dump/pg_dump
? src/bin/pg_dump/pg_dumpall
? src/bin/pg_dump/pg_restore
? src/bin/pg_resetxlog/pg_resetxlog
? src/bin/psql/psql
? src/bin/scripts/clusterdb
? src/bin/scripts/createdb
? src/bin/scripts/createlang
? src/bin/scripts/createuser
? src/bin/scripts/dropdb
? src/bin/scripts/droplang
? src/bin/scripts/dropuser
? src/bin/scripts/reindexdb
? src/bin/scripts/vacuumdb
? src/include/pg_config.h
? src/include/stamp-h
? src/interfaces/ecpg/compatlib/libecpg_compat.so.2.1
? src/interfaces/ecpg/ecpglib/libecpg.so.5.1
? src/interfaces/ecpg/pgtypeslib/libpgtypes.so.2.1
? src/interfaces/ecpg/preproc/ecpg
? src/interfaces/libpq/libpq.so.4.1
? src/pl/plpgsql/src/libplpgsql.so.1.0
? src/port/pg_config_paths.h
? src/test/regress/libregress.so.0.0
? src/test/regress/log
? src/test/regress/pg_regress
? src/test/regress/regression.diffs
? src/test/regress/regression.out
? src/test/regress/results
? src/test/regress/testtablespace
? src/test/regress/tmp_check
? src/test/regress/expected/constraints.out
? src/test/regress/expected/copy.out
? src/test/regress/expected/create_function_1.out
? src/test/regress/expected/create_function_2.out
? src/test/regress/expected/misc.out
? src/test/regress/expected/tablespace.out
? src/test/regress/sql/constraints.sql
? src/test/regress/sql/copy.sql
? src/test/regress/sql/create_function_1.sql
? src/test/regress/sql/create_function_2.sql
? src/test/regress/sql/misc.sql
? src/test/regress/sql/tablespace.sql
? src/timezone/zic
Index: src/backend/commands/tablecmds.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/tablecmds.c,v
retrieving revision 1.174
diff -u -3 -p -u -r1.174 tablecmds.c
--- src/backend/commands/tablecmds.c	15 Oct 2005 02:49:15 -0000	1.174
+++ src/backend/commands/tablecmds.c	31 Oct 2005 01:09:24 -0000
@@ -4434,84 +4434,56 @@ CreateFKCheckTrigger(RangeVar *myRel, Fk
 }
 
 /*
- * Create the triggers that implement an FK constraint.
+ * This is a helper function for createForeignKeyTriggers.  It prepares a CreateTrigStmt
+ * object for calling CreateTrigger.
+ *   action_char must be either 'u' or 'd'
  */
-static void
-createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
-						 Oid constrOid)
+static CreateTrigStmt *
+prepareCreateTrigStmt(RangeVar * myRel, FkConstraint * fkconstraint, Oid constrOid, RangeVar * refRel, char action_char)
 {
-	RangeVar   *myRel;
 	CreateTrigStmt *fk_trigger;
 	ListCell   *fk_attr;
 	ListCell   *pk_attr;
-	ObjectAddress trigobj,
-				constrobj;
-
-	/*
-	 * Reconstruct a RangeVar for my relation (not passed in, unfortunately).
-	 */
-	myRel = makeRangeVar(get_namespace_name(RelationGetNamespace(rel)),
-						 pstrdup(RelationGetRelationName(rel)));
-
-	/*
-	 * Preset objectAddress fields
-	 */
-	constrobj.classId = ConstraintRelationId;
-	constrobj.objectId = constrOid;
-	constrobj.objectSubId = 0;
-	trigobj.classId = TriggerRelationId;
-	trigobj.objectSubId = 0;
 
-	/* Make changes-so-far visible */
-	CommandCounterIncrement();
+	Assert( (action_char=='u') || (action_char=='d') );
 
-	/*
-	 * Build and execute a CREATE CONSTRAINT TRIGGER statement for the CHECK
-	 * action for both INSERTs and UPDATEs on the referencing table.
-	 */
-	CreateFKCheckTrigger(myRel, fkconstraint, &constrobj, &trigobj, true);
-	CreateFKCheckTrigger(myRel, fkconstraint, &constrobj, &trigobj, false);
-
-	/*
-	 * Build and execute a CREATE CONSTRAINT TRIGGER statement for the ON
-	 * DELETE action on the referenced table.
-	 */
 	fk_trigger = makeNode(CreateTrigStmt);
 	fk_trigger->trigname = fkconstraint->constr_name;
-	fk_trigger->relation = fkconstraint->pktable;
+	fk_trigger->relation = refRel;
 	fk_trigger->before = false;
 	fk_trigger->row = true;
-	fk_trigger->actions[0] = 'd';
+	fk_trigger->actions[0] = action_char;
 	fk_trigger->actions[1] = '\0';
 
 	fk_trigger->isconstraint = true;
 	fk_trigger->constrrel = myRel;
-	switch (fkconstraint->fk_del_action)
+	char action = action_char == 'd' ? fkconstraint->fk_del_action : fkconstraint->fk_upd_action;
+	switch (action)
 	{
 		case FKCONSTR_ACTION_NOACTION:
 			fk_trigger->deferrable = fkconstraint->deferrable;
 			fk_trigger->initdeferred = fkconstraint->initdeferred;
-			fk_trigger->funcname = SystemFuncName("RI_FKey_noaction_del");
+			fk_trigger->funcname = SystemFuncName(action_char == 'd' ? "RI_FKey_noaction_del" : "RI_FKey_noaction_upd");
 			break;
 		case FKCONSTR_ACTION_RESTRICT:
 			fk_trigger->deferrable = false;
 			fk_trigger->initdeferred = false;
-			fk_trigger->funcname = SystemFuncName("RI_FKey_restrict_del");
+			fk_trigger->funcname = SystemFuncName(action_char == 'd' ? "RI_FKey_restrict_del" : "RI_FKey_restrict_upd");
 			break;
 		case FKCONSTR_ACTION_CASCADE:
 			fk_trigger->deferrable = false;
 			fk_trigger->initdeferred = false;
-			fk_trigger->funcname = SystemFuncName("RI_FKey_cascade_del");
+			fk_trigger->funcname = SystemFuncName(action_char == 'd' ? "RI_FKey_cascade_del" : "RI_FKey_cascade_upd");
 			break;
 		case FKCONSTR_ACTION_SETNULL:
 			fk_trigger->deferrable = false;
 			fk_trigger->initdeferred = false;
-			fk_trigger->funcname = SystemFuncName("RI_FKey_setnull_del");
+			fk_trigger->funcname = SystemFuncName(action_char == 'd' ? "RI_FKey_setnull_del" : "RI_FKey_setnull_upd");
 			break;
 		case FKCONSTR_ACTION_SETDEFAULT:
 			fk_trigger->deferrable = false;
 			fk_trigger->initdeferred = false;
-			fk_trigger->funcname = SystemFuncName("RI_FKey_setdefault_del");
+			fk_trigger->funcname = SystemFuncName(action_char == 'd' ? "RI_FKey_setdefault_del" : "RI_FKey_setdefault_upd");
 			break;
 		default:
 			elog(ERROR, "unrecognized FK action type: %d",
@@ -4525,7 +4497,7 @@ createForeignKeyTriggers(Relation rel, F
 	fk_trigger->args = lappend(fk_trigger->args,
 							   makeString(myRel->relname));
 	fk_trigger->args = lappend(fk_trigger->args,
-							   makeString(fkconstraint->pktable->relname));
+							   makeString(refRel->relname));
 	fk_trigger->args = lappend(fk_trigger->args,
 				makeString(fkMatchTypeToString(fkconstraint->fk_matchtype)));
 	forboth(fk_attr, fkconstraint->fk_attrs,
@@ -4534,6 +4506,56 @@ createForeignKeyTriggers(Relation rel, F
 		fk_trigger->args = lappend(fk_trigger->args, lfirst(fk_attr));
 		fk_trigger->args = lappend(fk_trigger->args, lfirst(pk_attr));
 	}
+	return fk_trigger;
+}
+
+/*
+ * Create the triggers that implement an FK constraint.
+ */
+static void
+createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
+						 Oid constrOid)
+{
+	RangeVar   *myRel;
+	CreateTrigStmt *fk_trigger;
+	ObjectAddress trigobj,
+				constrobj;
+	List	   *children;
+	ListCell   *child;
+
+	/* this routine is actually in the planner */
+	children = find_all_inheritors(RangeVarGetRelid(fkconstraint->pktable, false));
+
+	/*
+	 * Reconstruct a RangeVar for my relation (not passed in, unfortunately).
+	 */
+	myRel = makeRangeVar(get_namespace_name(RelationGetNamespace(rel)),
+						 pstrdup(RelationGetRelationName(rel)));
+
+	/*
+	 * Preset objectAddress fields
+	 */
+	constrobj.classId = ConstraintRelationId;
+	constrobj.objectId = constrOid;
+	constrobj.objectSubId = 0;
+	trigobj.classId = TriggerRelationId;
+	trigobj.objectSubId = 0;
+
+	/* Make changes-so-far visible */
+	CommandCounterIncrement();
+
+	/*
+	 * Build and execute a CREATE CONSTRAINT TRIGGER statement for the CHECK
+	 * action for both INSERTs and UPDATEs on the referencing table.
+	 */
+	CreateFKCheckTrigger(myRel, fkconstraint, &constrobj, &trigobj, true);
+	CreateFKCheckTrigger(myRel, fkconstraint, &constrobj, &trigobj, false);
+
+	/*
+	 * Build and execute a CREATE CONSTRAINT TRIGGER statement for the ON
+	 * DELETE action on the referenced table.
+	 */
+	fk_trigger = prepareCreateTrigStmt(myRel,fkconstraint,constrOid,fkconstraint->pktable,'d');
 
 	trigobj.objectId = CreateTrigger(fk_trigger, true);
 
@@ -4547,68 +4569,71 @@ createForeignKeyTriggers(Relation rel, F
 	 * Build and execute a CREATE CONSTRAINT TRIGGER statement for the ON
 	 * UPDATE action on the referenced table.
 	 */
-	fk_trigger = makeNode(CreateTrigStmt);
-	fk_trigger->trigname = fkconstraint->constr_name;
-	fk_trigger->relation = fkconstraint->pktable;
-	fk_trigger->before = false;
-	fk_trigger->row = true;
-	fk_trigger->actions[0] = 'u';
-	fk_trigger->actions[1] = '\0';
-	fk_trigger->isconstraint = true;
-	fk_trigger->constrrel = myRel;
-	switch (fkconstraint->fk_upd_action)
-	{
-		case FKCONSTR_ACTION_NOACTION:
-			fk_trigger->deferrable = fkconstraint->deferrable;
-			fk_trigger->initdeferred = fkconstraint->initdeferred;
-			fk_trigger->funcname = SystemFuncName("RI_FKey_noaction_upd");
-			break;
-		case FKCONSTR_ACTION_RESTRICT:
-			fk_trigger->deferrable = false;
-			fk_trigger->initdeferred = false;
-			fk_trigger->funcname = SystemFuncName("RI_FKey_restrict_upd");
-			break;
-		case FKCONSTR_ACTION_CASCADE:
-			fk_trigger->deferrable = false;
-			fk_trigger->initdeferred = false;
-			fk_trigger->funcname = SystemFuncName("RI_FKey_cascade_upd");
-			break;
-		case FKCONSTR_ACTION_SETNULL:
-			fk_trigger->deferrable = false;
-			fk_trigger->initdeferred = false;
-			fk_trigger->funcname = SystemFuncName("RI_FKey_setnull_upd");
-			break;
-		case FKCONSTR_ACTION_SETDEFAULT:
-			fk_trigger->deferrable = false;
-			fk_trigger->initdeferred = false;
-			fk_trigger->funcname = SystemFuncName("RI_FKey_setdefault_upd");
-			break;
-		default:
-			elog(ERROR, "unrecognized FK action type: %d",
-				 (int) fkconstraint->fk_upd_action);
-			break;
-	}
-
-	fk_trigger->args = NIL;
-	fk_trigger->args = lappend(fk_trigger->args,
-							   makeString(fkconstraint->constr_name));
-	fk_trigger->args = lappend(fk_trigger->args,
-							   makeString(myRel->relname));
-	fk_trigger->args = lappend(fk_trigger->args,
-							   makeString(fkconstraint->pktable->relname));
-	fk_trigger->args = lappend(fk_trigger->args,
-				makeString(fkMatchTypeToString(fkconstraint->fk_matchtype)));
-	forboth(fk_attr, fkconstraint->fk_attrs,
-			pk_attr, fkconstraint->pk_attrs)
-	{
-		fk_trigger->args = lappend(fk_trigger->args, lfirst(fk_attr));
-		fk_trigger->args = lappend(fk_trigger->args, lfirst(pk_attr));
-	}
+	fk_trigger = prepareCreateTrigStmt(myRel,fkconstraint,constrOid,fkconstraint->pktable,'u');
 
 	trigobj.objectId = CreateTrigger(fk_trigger, true);
 
 	/* Register dependency from trigger to constraint */
 	recordDependencyOn(&trigobj, &constrobj, DEPENDENCY_INTERNAL);
+
+	/* Make changes-so-far visible */
+	CommandCounterIncrement();
+
+	/*
+	* find_all_inheritors does the recursive search of the inheritance
+	* hierarchy, so all we have to do is process all of the relids in the
+	* list that it returns.
+	*/
+	foreach(child, children)
+	{
+		Oid childrelid;
+		Relation childrel;
+		RangeVar * childrv;
+		ObjectAddress childrelobj;
+
+		childrelid = lfirst_oid(child);
+		childrel = relation_open(childrelid, AccessExclusiveLock);
+
+		childrv = makeRangeVar(get_namespace_name(RelationGetNamespace(childrel)),
+							pstrdup(RelationGetRelationName(childrel)));
+
+		/*
+		 * First, add a dependancy between the table and the constraint
+		 * This is done for the original(opposed to children) table
+		 * in CreateConstraintEntry 
+		 */
+		childrelobj.classId = RelationRelationId;
+		childrelobj.objectId = childrelid;
+		childrelobj.objectSubId = 0;
+
+		recordDependencyOn(&constrobj, &childrelobj, DEPENDENCY_NORMAL);
+
+		/*
+		 * Create the update trigger
+		 */
+		fk_trigger = prepareCreateTrigStmt(myRel,fkconstraint,constrOid,childrv,'u');
+		trigobj.objectId = CreateTrigger(fk_trigger, true);
+
+		/* Register dependency from trigger to constraint */
+		recordDependencyOn(&trigobj, &constrobj, DEPENDENCY_INTERNAL);
+
+		/* Make changes-so-far visible */
+		CommandCounterIncrement();
+
+		/*
+		 * Create the delete trigger
+		 */
+		fk_trigger = prepareCreateTrigStmt(myRel,fkconstraint,constrOid,childrv,'d');
+		trigobj.objectId = CreateTrigger(fk_trigger, true);
+
+		/* Register dependency from trigger to constraint */
+		recordDependencyOn(&trigobj, &constrobj, DEPENDENCY_INTERNAL);
+
+		/* Make changes-so-far visible */
+		CommandCounterIncrement();
+
+		relation_close(childrel, AccessExclusiveLock);
+	}
 }
 
 /*
Index: src/backend/utils/adt/ri_triggers.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v
retrieving revision 1.81
diff -u -3 -p -u -r1.81 ri_triggers.c
--- src/backend/utils/adt/ri_triggers.c	15 Oct 2005 02:49:29 -0000	1.81
+++ src/backend/utils/adt/ri_triggers.c	31 Oct 2005 01:09:24 -0000
@@ -266,7 +266,7 @@ RI_FKey_check(PG_FUNCTION_ARGS)
 			 * ----------
 			 */
 			quoteRelationName(pkrelname, pk_rel);
-			snprintf(querystr, sizeof(querystr), "SELECT 1 FROM ONLY %s x FOR SHARE OF x",
+			snprintf(querystr, sizeof(querystr), "SELECT 1 FROM ONLY %s x",
 					 pkrelname);
 
 			/* Prepare and save the plan */
@@ -399,7 +399,7 @@ RI_FKey_check(PG_FUNCTION_ARGS)
 		 * ----------
 		 */
 		quoteRelationName(pkrelname, pk_rel);
-		snprintf(querystr, sizeof(querystr), "SELECT 1 FROM ONLY %s x", pkrelname);
+		snprintf(querystr, sizeof(querystr), "SELECT 1 FROM %s x", pkrelname);
 		querysep = "WHERE";
 		for (i = 0; i < qkey.nkeypairs; i++)
 		{
@@ -411,7 +411,6 @@ RI_FKey_check(PG_FUNCTION_ARGS)
 			queryoids[i] = SPI_gettypeid(fk_rel->rd_att,
 										 qkey.keypair[i][RI_KEYPAIR_FK_IDX]);
 		}
-		strcat(querystr, " FOR SHARE OF x");
 
 		/* Prepare and save the plan */
 		qplan = ri_PlanCheck(querystr, qkey.nkeypairs, queryoids,
@@ -560,7 +559,7 @@ ri_Check_Pk_Match(Relation pk_rel, Relat
 		 * ----------
 		 */
 		quoteRelationName(pkrelname, pk_rel);
-		snprintf(querystr, sizeof(querystr), "SELECT 1 FROM ONLY %s x", pkrelname);
+		snprintf(querystr, sizeof(querystr), "SELECT 1 FROM %s x", pkrelname);
 		querysep = "WHERE";
 		for (i = 0; i < qkey.nkeypairs; i++)
 		{
@@ -572,7 +571,6 @@ ri_Check_Pk_Match(Relation pk_rel, Relat
 			queryoids[i] = SPI_gettypeid(pk_rel->rd_att,
 										 qkey.keypair[i][RI_KEYPAIR_PK_IDX]);
 		}
-		strcat(querystr, " FOR SHARE OF x");
 
 		/* Prepare and save the plan */
 		qplan = ri_PlanCheck(querystr, qkey.nkeypairs, queryoids,
@@ -716,7 +714,7 @@ RI_FKey_noaction_del(PG_FUNCTION_ARGS)
 				 * ----------
 				 */
 				quoteRelationName(fkrelname, fk_rel);
-				snprintf(querystr, sizeof(querystr), "SELECT 1 FROM ONLY %s x", fkrelname);
+				snprintf(querystr, sizeof(querystr), "SELECT 1 FROM %s x", fkrelname);
 				querysep = "WHERE";
 				for (i = 0; i < qkey.nkeypairs; i++)
 				{
@@ -728,7 +726,6 @@ RI_FKey_noaction_del(PG_FUNCTION_ARGS)
 					queryoids[i] = SPI_gettypeid(pk_rel->rd_att,
 										 qkey.keypair[i][RI_KEYPAIR_PK_IDX]);
 				}
-				strcat(querystr, " FOR SHARE OF x");
 
 				/* Prepare and save the plan */
 				qplan = ri_PlanCheck(querystr, qkey.nkeypairs, queryoids,
@@ -905,7 +902,7 @@ RI_FKey_noaction_upd(PG_FUNCTION_ARGS)
 				 * ----------
 				 */
 				quoteRelationName(fkrelname, fk_rel);
-				snprintf(querystr, sizeof(querystr), "SELECT 1 FROM ONLY %s x", fkrelname);
+				snprintf(querystr, sizeof(querystr), "SELECT 1 FROM %s x", fkrelname);
 				querysep = "WHERE";
 				for (i = 0; i < qkey.nkeypairs; i++)
 				{
@@ -917,7 +914,6 @@ RI_FKey_noaction_upd(PG_FUNCTION_ARGS)
 					queryoids[i] = SPI_gettypeid(pk_rel->rd_att,
 										 qkey.keypair[i][RI_KEYPAIR_PK_IDX]);
 				}
-				strcat(querystr, " FOR SHARE OF x");
 
 				/* Prepare and save the plan */
 				qplan = ri_PlanCheck(querystr, qkey.nkeypairs, queryoids,
@@ -1063,7 +1059,7 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS)
 				 * ----------
 				 */
 				quoteRelationName(fkrelname, fk_rel);
-				snprintf(querystr, sizeof(querystr), "DELETE FROM ONLY %s", fkrelname);
+				snprintf(querystr, sizeof(querystr), "DELETE FROM %s", fkrelname);
 				querysep = "WHERE";
 				for (i = 0; i < qkey.nkeypairs; i++)
 				{
@@ -1239,7 +1235,7 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
 				 * ----------
 				 */
 				quoteRelationName(fkrelname, fk_rel);
-				snprintf(querystr, sizeof(querystr), "UPDATE ONLY %s SET", fkrelname);
+				snprintf(querystr, sizeof(querystr), "UPDATE %s SET", fkrelname);
 				qualstr[0] = '\0';
 				querysep = "";
 				qualsep = "WHERE";
@@ -1411,7 +1407,7 @@ RI_FKey_restrict_del(PG_FUNCTION_ARGS)
 				 * ----------
 				 */
 				quoteRelationName(fkrelname, fk_rel);
-				snprintf(querystr, sizeof(querystr), "SELECT 1 FROM ONLY %s x", fkrelname);
+				snprintf(querystr, sizeof(querystr), "SELECT 1 FROM %s x", fkrelname);
 				querysep = "WHERE";
 				for (i = 0; i < qkey.nkeypairs; i++)
 				{
@@ -1423,7 +1419,6 @@ RI_FKey_restrict_del(PG_FUNCTION_ARGS)
 					queryoids[i] = SPI_gettypeid(pk_rel->rd_att,
 										 qkey.keypair[i][RI_KEYPAIR_PK_IDX]);
 				}
-				strcat(querystr, " FOR SHARE OF x");
 
 				/* Prepare and save the plan */
 				qplan = ri_PlanCheck(querystr, qkey.nkeypairs, queryoids,
@@ -1590,7 +1585,7 @@ RI_FKey_restrict_upd(PG_FUNCTION_ARGS)
 				 * ----------
 				 */
 				quoteRelationName(fkrelname, fk_rel);
-				snprintf(querystr, sizeof(querystr), "SELECT 1 FROM ONLY %s x", fkrelname);
+				snprintf(querystr, sizeof(querystr), "SELECT 1 FROM %s x", fkrelname);
 				querysep = "WHERE";
 				for (i = 0; i < qkey.nkeypairs; i++)
 				{
@@ -1602,7 +1597,6 @@ RI_FKey_restrict_upd(PG_FUNCTION_ARGS)
 					queryoids[i] = SPI_gettypeid(pk_rel->rd_att,
 										 qkey.keypair[i][RI_KEYPAIR_PK_IDX]);
 				}
-				strcat(querystr, " FOR SHARE OF x");
 
 				/* Prepare and save the plan */
 				qplan = ri_PlanCheck(querystr, qkey.nkeypairs, queryoids,
@@ -1751,7 +1745,7 @@ RI_FKey_setnull_del(PG_FUNCTION_ARGS)
 				 * ----------
 				 */
 				quoteRelationName(fkrelname, fk_rel);
-				snprintf(querystr, sizeof(querystr), "UPDATE ONLY %s SET", fkrelname);
+				snprintf(querystr, sizeof(querystr), "UPDATE %s SET", fkrelname);
 				qualstr[0] = '\0';
 				querysep = "";
 				qualsep = "WHERE";
@@ -1951,7 +1945,7 @@ RI_FKey_setnull_upd(PG_FUNCTION_ARGS)
 				 * ----------
 				 */
 				quoteRelationName(fkrelname, fk_rel);
-				snprintf(querystr, sizeof(querystr), "UPDATE ONLY %s SET", fkrelname);
+				snprintf(querystr, sizeof(querystr), "UPDATE %s SET", fkrelname);
 				qualstr[0] = '\0';
 				querysep = "";
 				qualsep = "WHERE";
@@ -2132,7 +2126,7 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
 				 * ----------
 				 */
 				quoteRelationName(fkrelname, fk_rel);
-				snprintf(querystr, sizeof(querystr), "UPDATE ONLY %s SET", fkrelname);
+				snprintf(querystr, sizeof(querystr), "UPDATE %s SET", fkrelname);
 				qualstr[0] = '\0';
 				querysep = "";
 				qualsep = "WHERE";
@@ -2324,7 +2318,7 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
 				 * ----------
 				 */
 				quoteRelationName(fkrelname, fk_rel);
-				snprintf(querystr, sizeof(querystr), "UPDATE ONLY %s SET", fkrelname);
+				snprintf(querystr, sizeof(querystr), "UPDATE %s SET", fkrelname);
 				qualstr[0] = '\0';
 				querysep = "";
 				qualsep = "WHERE";
@@ -2622,7 +2616,7 @@ RI_Initial_Check(FkConstraint *fkconstra
 	quoteRelationName(pkrelname, pkrel);
 	quoteRelationName(relname, rel);
 	snprintf(querystr + strlen(querystr), sizeof(querystr) - strlen(querystr),
-			 " FROM ONLY %s fk LEFT OUTER JOIN ONLY %s pk ON (",
+			 " FROM %s fk LEFT OUTER JOIN ONLY %s pk ON (",
 			 relname, pkrelname);
 
 	sep = "";
---------------------------(end of broadcast)---------------------------
TIP 3: Have you checked our extensive FAQ?

               http://www.postgresql.org/docs/faq

Reply via email to