Index: src/backend/utils/adt/ri_triggers.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v
retrieving revision 1.115
diff -u -r1.115 ri_triggers.c
--- src/backend/utils/adt/ri_triggers.c	5 Nov 2009 04:38:29 -0000	1.115
+++ src/backend/utils/adt/ri_triggers.c	15 Nov 2009 06:51:20 -0000
@@ -31,6 +31,7 @@
 #include "postgres.h"
 
 #include "access/xact.h"
+#include "catalog/namespace.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_type.h"
@@ -237,6 +238,8 @@
 				   Relation pk_rel, Relation fk_rel,
 				   HeapTuple violator, TupleDesc tupdesc,
 				   bool spi_err);
+static bool searchPathContainsUnique(Relation rel);
+static char *getSchemaPrefix(Relation rel);
 
 
 /* ----------
@@ -257,6 +260,7 @@
 	Buffer		new_row_buf;
 	RI_QueryKey qkey;
 	SPIPlanPtr	qplan;
+	char		schema_prefix;
 	int			i;
 
 	/*
@@ -402,12 +406,15 @@
 					 * Not allowed - MATCH FULL says either all or none of the
 					 * attributes can be NULLs
 					 */
+					schema_prefix = getSchemaPrefix(trigdata->tg_relation);
 					ereport(ERROR,
 							(errcode(ERRCODE_FOREIGN_KEY_VIOLATION),
-							 errmsg("insert or update on table \"%s\" violates foreign key constraint \"%s\"",
+							 errmsg("insert or update on table \"%s%s\" violates foreign key constraint \"%s\"",
+								schema_prefix,
 							  RelationGetRelationName(trigdata->tg_relation),
 									NameStr(riinfo.conname)),
 							 errdetail("MATCH FULL does not allow mixing of null and nonnull key values.")));
+					pfree(schema_prefix);
 					heap_close(pk_rel, RowShareLock);
 					return PointerGetDatum(NULL);
 
@@ -2797,13 +2804,17 @@
 				if (isnull)
 					break;
 			}
-			if (isnull)
+			if (isnull) {
+				char *schema_prefix = getSchemaPrefix(fk_rel);
 				ereport(ERROR,
 						(errcode(ERRCODE_FOREIGN_KEY_VIOLATION),
-						 errmsg("insert or update on table \"%s\" violates foreign key constraint \"%s\"",
+						 errmsg("insert or update on table \"%s%s\" violates foreign key constraint \"%s\"",
+								schema_prefix,
 								RelationGetRelationName(fk_rel),
 								constrname),
 						 errdetail("MATCH FULL does not allow mixing of null and nonnull key values.")));
+				pfree(schema_prefix);
+			}
 		}
 
 		/*
@@ -3418,6 +3429,8 @@
 	bool		onfk;
 	int			idx,
 				key_idx;
+	char		*fk_schema_prefix;
+	char		*pk_schema_prefix;
 
 	if (spi_err)
 		ereport(ERROR,
@@ -3453,12 +3466,16 @@
 	 */
 	if (qkey->nkeypairs == 0)
 	{
+		fk_schema_prefix = getSchemaPrefix(fk_rel);
+		pk_schema_prefix = getSchemaPrefix(pk_rel);
 		ereport(ERROR,
 				(errcode(ERRCODE_FOREIGN_KEY_VIOLATION),
-				 errmsg("insert or update on table \"%s\" violates foreign key constraint \"%s\"",
-						RelationGetRelationName(fk_rel), constrname),
-				 errdetail("No rows were found in \"%s\".",
-						   RelationGetRelationName(pk_rel))));
+				 errmsg("insert or update on table \"%s%s\" violates foreign key constraint \"%s\"",
+						fk_schema_prefix, RelationGetRelationName(fk_rel), constrname),
+				 errdetail("No rows were found in \"%s%s\".",
+						   pk_schema_prefix, RelationGetRelationName(pk_rel))));
+		pfree(pk_schema_prefix);
+		pfree(fk_schema_prefix);
 	}
 
 	/* Get printable versions of the keys involved */
@@ -3484,23 +3501,27 @@
 		appendStringInfoString(&key_values, val);
 	}
 
+	fk_schema_prefix = getSchemaPrefix(fk_rel);
+	pk_schema_prefix = getSchemaPrefix(pk_rel);
 	if (onfk)
 		ereport(ERROR,
 				(errcode(ERRCODE_FOREIGN_KEY_VIOLATION),
-				 errmsg("insert or update on table \"%s\" violates foreign key constraint \"%s\"",
-						RelationGetRelationName(fk_rel), constrname),
-				 errdetail("Key (%s)=(%s) is not present in table \"%s\".",
+				 errmsg("insert or update on table \"%s%s\" violates foreign key constraint \"%s\"",
+						fk_schema_prefix, RelationGetRelationName(fk_rel), constrname),
+				 errdetail("Key (%s)=(%s) is not present in table \"%s%s\".",
 						   key_names.data, key_values.data,
-						   RelationGetRelationName(pk_rel))));
+						   pk_schema_prefix, RelationGetRelationName(pk_rel))));
 	else
 		ereport(ERROR,
 				(errcode(ERRCODE_FOREIGN_KEY_VIOLATION),
-				 errmsg("update or delete on table \"%s\" violates foreign key constraint \"%s\" on table \"%s\"",
-						RelationGetRelationName(pk_rel),
-						constrname, RelationGetRelationName(fk_rel)),
-			errdetail("Key (%s)=(%s) is still referenced from table \"%s\".",
+				 errmsg("update or delete on table \"%s%s\" violates foreign key constraint \"%s\" on table \"%s%s\"",
+						pk_schema_prefix, RelationGetRelationName(pk_rel),
+						constrname, fk_schema_prefix, RelationGetRelationName(fk_rel)),
+			errdetail("Key (%s)=(%s) is still referenced from table \"%s%s\".",
 					  key_names.data, key_values.data,
-					  RelationGetRelationName(fk_rel))));
+					  pk_schema_prefix, RelationGetRelationName(fk_rel))));
+	pfree(pk_schema_prefix);
+	pfree(fk_schema_prefix);
 }
 
 /* ----------
@@ -4014,3 +4035,57 @@
 
 	return RI_TRIGGER_NONE;
 }
+
+static bool
+searchPathContainsUnique(Relation rel)
+{
+	ListCell *l;
+	List *searchPath = fetch_search_path(true);
+	char *relname = RelationGetRelationName(rel);
+	int count = 0;
+
+	if (searchPath == NIL)
+		return false;
+	foreach(l, searchPath)
+	{
+		Oid			namespaceId = lfirst_oid(l);
+
+		if (OidIsValid(get_relname_relid(relname, namespaceId)))
+			count++;
+
+		if( count >= 2 )
+			break;
+	}
+
+	list_free(searchPath);
+
+	return count == 1;
+}
+
+/*
+ * Given a relation OID, return a palloc'd string which contains a
+ * schema prefix if the relation is absent or non-unique within the search path
+ */
+static char *
+getSchemaPrefix(Relation rel)
+{
+	if (!searchPathContainsUnique(rel)) {
+		int len;
+		char *schema_prefix;
+		char *schemaname = get_namespace_name(RelationGetNamespace(rel));
+
+		if (schemaname == NULL)
+			return pstrdup("");
+
+		len = strlen(schemaname);
+
+		schema_prefix = palloc(len + 2);
+		strcpy(schema_prefix, schemaname);
+		strcpy(&schema_prefix[len], ".");
+		pfree(schemaname);
+
+		return schema_prefix;
+	}
+
+	return pstrdup("");
+}
Index: src/test/regress/expected/foreign_key.out
===================================================================
RCS file: /projects/cvsroot/pgsql/src/test/regress/expected/foreign_key.out,v
retrieving revision 1.48
diff -u -r1.48 foreign_key.out
--- src/test/regress/expected/foreign_key.out	14 Jun 2008 18:04:34 -0000	1.48
+++ src/test/regress/expected/foreign_key.out	15 Nov 2009 06:51:22 -0000
@@ -1287,3 +1287,25 @@
 (3 rows)
 
 COMMIT;
+-- test foreign key namespace printing
+CREATE TABLE fknssrc (
+  id INT PRIMARY KEY
+);
+NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "fknssrc_pkey" for table "fknssrc"
+CREATE SCHEMA non_searched_schema;
+CREATE TABLE non_searched_schema.fknsref ( 
+  fknssrc_id INT REFERENCES fknssrc ON UPDATE CASCADE ON DELETE SET NULL
+);
+INSERT INTO non_searched_schema.fknsref VALUES (1000);
+ERROR:  insert or update on table "non_searched_schema.fknsref" violates foreign key constraint "fknsref_fknssrc_id_fkey"
+DETAIL:  Key (fknssrc_id)=(1000) is not present in table "fknssrc".
+SET search_path TO public, non_searched_schema;
+-- make the original table non-unique
+CREATE TABLE non_searched_schema.fknssrc (
+  id INT PRIMARY KEY
+);
+NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "fknssrc_pkey" for table "fknssrc"
+-- and note the addition of the public schema
+INSERT INTO non_searched_schema.fknsref VALUES (1000);
+ERROR:  insert or update on table "fknsref" violates foreign key constraint "fknsref_fknssrc_id_fkey"
+DETAIL:  Key (fknssrc_id)=(1000) is not present in table "public.fknssrc".
Index: src/test/regress/sql/foreign_key.sql
===================================================================
RCS file: /projects/cvsroot/pgsql/src/test/regress/sql/foreign_key.sql,v
retrieving revision 1.22
diff -u -r1.22 foreign_key.sql
--- src/test/regress/sql/foreign_key.sql	14 Jun 2008 18:04:34 -0000	1.22
+++ src/test/regress/sql/foreign_key.sql	15 Nov 2009 06:51:22 -0000
@@ -921,3 +921,26 @@
 DELETE FROM users WHERE id = 2;
 SELECT * FROM tasks;
 COMMIT;
+
+-- test foreign key namespace printing
+CREATE TABLE fknssrc (
+  id INT PRIMARY KEY
+);
+
+CREATE SCHEMA non_searched_schema;
+
+CREATE TABLE non_searched_schema.fknsref ( 
+  fknssrc_id INT REFERENCES fknssrc ON UPDATE CASCADE ON DELETE SET NULL
+);
+
+INSERT INTO non_searched_schema.fknsref VALUES (1000);
+
+SET search_path TO public, non_searched_schema;
+
+-- make the original table non-unique
+CREATE TABLE non_searched_schema.fknssrc (
+  id INT PRIMARY KEY
+);
+
+-- and note the addition of the public schema
+INSERT INTO non_searched_schema.fknsref VALUES (1000);
