From 24bd9447acb1f64fb357ed3cec5623da51d67cc2 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 15 Aug 2005 21:50:15 +0000
Subject: [PATCH] Clean up recent patch for PL handler functions in pg_catalog:
 the patch caused PL languages and handlers to be dumped ALWAYS, even in the
 face of contrary --schema or --table switches.  Adopt a slightly saner
 definition.

---
 src/bin/pg_dump/pg_dump.c | 78 ++++++++++++++++++++++++++++-----------
 src/bin/pg_dump/pg_dump.h |  4 +-
 2 files changed, 59 insertions(+), 23 deletions(-)

diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 0f7d8b5543a..6e2a5f5493c 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -12,7 +12,7 @@
  *	by PostgreSQL
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.417 2005/08/15 02:36:29 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.418 2005/08/15 21:50:15 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2305,9 +2305,9 @@ getFuncs(int *numFuncs)
 	if (g_fout->remoteVersion >= 70300)
 	{
 		/*
-		 * We now collect info on pg_catalog resident functions, but
-		 * only if they are language call handlers or validators, and
-		 * only for non-default languages (i.e. not internal/C/SQL).
+		 * For 7.3 and up, we consider it's user-defined if it's not in
+		 * pg_catalog.  We also collect info on functions in pg_catalog, but
+		 * only if they are call handlers or validators for PL languages.
 		 */
 		appendPQExpBuffer(query,
 						  "SELECT tableoid, oid, proname, prolang, "
@@ -2316,10 +2316,10 @@ getFuncs(int *numFuncs)
 						  "(%s proowner) as rolname, "
 						  "CASE WHEN oid IN "
 						  "  (select lanplcallfoid from pg_language "
-						  "   where lanplcallfoid != 0) THEN true "
+						  "   where lanispl) THEN true "
 						  " WHEN oid IN "
 						  "  (select lanvalidator from pg_language "
-						  "   where lanplcallfoid != 0) THEN true "
+						  "   where lanispl) THEN true "
 						  " ELSE false END AS is_pl_handler "
 						  "FROM pg_proc "
 						  "WHERE NOT proisagg "
@@ -2328,10 +2328,10 @@ getFuncs(int *numFuncs)
 						  "     where nspname = 'pg_catalog')"
 						  "  OR oid IN "
 						  "    (select lanplcallfoid from pg_language "
-						  "     where lanplcallfoid != 0) "
+						  "     where lanispl) "
 						  "  OR oid IN "
 						  "    (select lanvalidator from pg_language "
-						  "     where lanplcallfoid != 0))",
+						  "     where lanispl))",
 						  username_subquery);
 	}
 	else if (g_fout->remoteVersion >= 70100)
@@ -2402,7 +2402,7 @@ getFuncs(int *numFuncs)
 		finfo[i].prorettype = atooid(PQgetvalue(res, i, i_prorettype));
 		finfo[i].proacl = strdup(PQgetvalue(res, i, i_proacl));
 		finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs));
-		finfo[i].isProlangFunc = 
+		finfo[i].islanghandler = 
 			strcmp(PQgetvalue(res, i, i_is_pl_handler), "t") == 0;
 		if (finfo[i].nargs == 0)
 			finfo[i].argtypes = NULL;
@@ -5095,6 +5095,29 @@ dumpCompositeType(Archive *fout, TypeInfo *tinfo)
 	destroyPQExpBuffer(query);
 }
 
+/*
+ * Determine whether we want to dump definitions for procedural languages.
+ * Since the languages themselves don't have schemas, we can't rely on
+ * the normal schema-based selection mechanism.  We choose to dump them
+ * whenever neither --schema nor --table was given.  (Before 8.1, we used
+ * the dump flag of the PL's call handler function, but in 8.1 this will
+ * probably always be false since call handlers are created in pg_catalog.)
+ *
+ * For some backwards compatibility with the older behavior, we forcibly
+ * dump a PL if its handler function (and validator if any) are in a
+ * dumpable namespace.  That case is not checked here.
+ */
+static bool
+shouldDumpProcLangs(void)
+{
+	if (selectTableName != NULL || selectSchemaName != NULL)
+		return false;
+	/* And they're schema not data */
+	if (dataOnly)
+		return false;
+	return true;
+}
+
 /*
  * dumpProcLang
  *		  writes out to fout the queries to recreate a user-defined
@@ -5113,28 +5136,33 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 		return;
 
 	/*
-	 * We dump PLs iff their underlying call handler functions have been
-	 * marked as language functions (or have a non-system OID in
-	 * pre-7.3 databases).	We treat the PL itself as being in
-	 * the underlying function's namespace, though it isn't really.  This
-	 * avoids searchpath problems for the HANDLER clause.
-	 *
+	 * Find the support functions, complaining if not there.
 	 */
-
 	funcInfo = findFuncByOid(plang->lanplcallfoid);
 	if (funcInfo == NULL)
+	{
+		write_msg(NULL, "WARNING: handler function for language \"%s\" not found\n",
+				  plang->dobj.name);
 		return;
-
-	if (!funcInfo->isProlangFunc && !funcInfo->dobj.namespace->dump)
-		return;
+	}
 
 	if (OidIsValid(plang->lanvalidator))
 	{
 		validatorInfo = findFuncByOid(plang->lanvalidator);
 		if (validatorInfo == NULL)
+		{
+			write_msg(NULL, "WARNING: validator function for language \"%s\" not found\n",
+					  plang->dobj.name);
 			return;
+		}
 	}
 
+	/* Dump if we should, or if both support functions are dumpable */
+	if (!shouldDumpProcLangs() &&
+		!(funcInfo->dobj.namespace->dump &&
+		  (validatorInfo == NULL || validatorInfo->dobj.namespace->dump)))
+		return;
+
 	defqry = createPQExpBuffer();
 	delqry = createPQExpBuffer();
 
@@ -5160,6 +5188,11 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 	}
 	appendPQExpBuffer(defqry, ";\n");
 
+	/*
+	 * We mark the PL's archive entry as being in the call handler's
+	 * namespace; this is what makes it OK to refer to the handler with
+	 * an unqualified name above.
+	 */
 	ArchiveEntry(fout, plang->dobj.catId, plang->dobj.dumpId,
 				 plang->dobj.name,
 				 funcInfo->dobj.namespace->dobj.name, NULL, "",
@@ -5323,10 +5356,13 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 	char	  **argmodes = NULL;
 	char	  **argnames = NULL;
 
-	/* Dump only funcs in dumpable namespaces, or needed language handlers */
-	if ((!finfo->isProlangFunc && !finfo->dobj.namespace->dump) || dataOnly)
+	if (dataOnly)
 		return;
 
+	/* Dump only funcs in dumpable namespaces, or needed language handlers */
+	if (!finfo->dobj.namespace->dump &&
+		(!finfo->islanghandler || !shouldDumpProcLangs()))
+		return;
 
 	query = createPQExpBuffer();
 	q = createPQExpBuffer();
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 2f53a8b67b2..4f4bb0c1982 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.118 2005/08/15 02:36:30 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.119 2005/08/15 21:50:15 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -132,7 +132,7 @@ typedef struct _funcInfo
 	Oid		   *argtypes;
 	Oid			prorettype;
 	char	   *proacl;
-	bool	isProlangFunc;
+	bool		islanghandler;
 } FuncInfo;
 
 /* AggInfo is a superset of FuncInfo */
-- 
GitLab