diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c
index 4023837408fd060d8de806d49dc6af46ed60c760..da9459f71e3f1fa46ed42b038e03d3f534f7cbd9 100644
--- a/src/bin/pg_dump/dumputils.c
+++ b/src/bin/pg_dump/dumputils.c
@@ -2,18 +2,20 @@
  *
  * Utility routines for SQL dumping
  *	Basically this is stuff that is useful in both pg_dump and pg_dumpall.
+ *	Lately it's also being used by psql and bin/scripts/ ...
  *
  *
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.32 2006/10/04 00:30:05 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.33 2006/10/09 23:30:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
-
 #include "postgres_fe.h"
 
+#include <ctype.h>
+
 #include "dumputils.h"
 
 #include "parser/keywords.h"
@@ -570,6 +572,8 @@ parseAclItem(const char *item, const char *type, const char *name,
 	char	   *pos;
 
 	buf = strdup(item);
+	if (!buf)
+		return false;
 
 	/* user or group name is string up to = */
 	eqpos = copyAclUserName(grantee, buf);
@@ -726,3 +730,200 @@ AddAcl(PQExpBuffer aclbuf, const char *keyword)
 		appendPQExpBufferChar(aclbuf, ',');
 	appendPQExpBuffer(aclbuf, "%s", keyword);
 }
+
+
+/*
+ * processSQLNamePattern
+ *
+ * Scan a wildcard-pattern string and generate appropriate WHERE clauses
+ * to limit the set of objects returned.  The WHERE clauses are appended
+ * to the already-partially-constructed query in buf.
+ *
+ * conn: connection query will be sent to (consulted for escaping rules).
+ * buf: output parameter.
+ * pattern: user-specified pattern option, or NULL if none ("*" is implied).
+ * have_where: true if caller already emitted "WHERE" (clauses will be ANDed
+ * onto the existing WHERE clause).
+ * force_escape: always quote regexp special characters, even outside
+ * double quotes (else they are quoted only between double quotes).
+ * schemavar: name of query variable to match against a schema-name pattern.
+ * Can be NULL if no schema.
+ * namevar: name of query variable to match against an object-name pattern.
+ * altnamevar: NULL, or name of an alternate variable to match against name.
+ * visibilityrule: clause to use if we want to restrict to visible objects
+ * (for example, "pg_catalog.pg_table_is_visible(p.oid)").	Can be NULL.
+ *
+ * Formatting note: the text already present in buf should end with a newline.
+ * The appended text, if any, will end with one too.
+ */
+void
+processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern,
+					  bool have_where, bool force_escape,
+					  const char *schemavar, const char *namevar,
+					  const char *altnamevar, const char *visibilityrule)
+{
+	PQExpBufferData schemabuf;
+	PQExpBufferData namebuf;
+	int			encoding = PQclientEncoding(conn);
+	bool		inquotes;
+	const char *cp;
+	int			i;
+
+#define WHEREAND() \
+	(appendPQExpBufferStr(buf, have_where ? "  AND " : "WHERE "), have_where = true)
+
+	if (pattern == NULL)
+	{
+		/* Default: select all visible objects */
+		if (visibilityrule)
+		{
+			WHEREAND();
+			appendPQExpBuffer(buf, "%s\n", visibilityrule);
+		}
+		return;
+	}
+
+	initPQExpBuffer(&schemabuf);
+	initPQExpBuffer(&namebuf);
+
+	/*
+	 * Parse the pattern, converting quotes and lower-casing unquoted letters.
+	 * Also, adjust shell-style wildcard characters into regexp notation.
+	 *
+	 * We surround the pattern with "^(...)$" to force it to match the whole
+	 * string, as per SQL practice.  We have to have parens in case the string
+	 * contains "|", else the "^" and "$" will be bound into the first and
+	 * last alternatives which is not what we want.
+	 *
+	 * Note: the result of this pass is the actual regexp pattern(s) we want to
+	 * execute.  Quoting/escaping into SQL literal format will be done below
+	 * using appendStringLiteralConn().
+	 */
+	appendPQExpBufferStr(&namebuf, "^(");
+
+	inquotes = false;
+	cp = pattern;
+
+	while (*cp)
+	{
+		char	ch = *cp;
+
+		if (ch == '"')
+		{
+			if (inquotes && cp[1] == '"')
+			{
+				/* emit one quote, stay in inquotes mode */
+				appendPQExpBufferChar(&namebuf, '"');
+				cp++;
+			}
+			else
+				inquotes = !inquotes;
+			cp++;
+		}
+		else if (!inquotes && isupper((unsigned char) ch))
+		{
+			appendPQExpBufferChar(&namebuf,
+								  pg_tolower((unsigned char) ch));
+			cp++;
+		}
+		else if (!inquotes && ch == '*')
+		{
+			appendPQExpBufferStr(&namebuf, ".*");
+			cp++;
+		}
+		else if (!inquotes && ch == '?')
+		{
+			appendPQExpBufferChar(&namebuf, '.');
+			cp++;
+		}
+		else if (!inquotes && ch == '.')
+		{
+			/* Found schema/name separator, move current pattern to schema */
+			resetPQExpBuffer(&schemabuf);
+			appendPQExpBufferStr(&schemabuf, namebuf.data);
+			resetPQExpBuffer(&namebuf);
+			appendPQExpBufferStr(&namebuf, "^(");
+			cp++;
+		}
+		else
+		{
+			/*
+			 * Ordinary data character, transfer to pattern
+			 *
+			 * Inside double quotes, or at all times if force_escape is true,
+			 * quote regexp special characters with a backslash to avoid
+			 * regexp errors.  Outside quotes, however, let them pass through
+			 * as-is; this lets knowledgeable users build regexp expressions
+			 * that are more powerful than shell-style patterns.
+			 */
+			if ((inquotes || force_escape) &&
+				strchr("|*+?()[]{}.^$\\", ch))
+				appendPQExpBufferChar(&namebuf, '\\');
+			i = PQmblen(cp, encoding);
+			while (i-- && *cp)
+			{
+				appendPQExpBufferChar(&namebuf, *cp);
+				cp++;
+			}
+		}
+	}
+
+	/*
+	 * Now decide what we need to emit.  Note there will be a leading "^("
+	 * in the patterns in any case.
+	 */
+	if (namebuf.len > 2)
+	{
+		/* We have a name pattern, so constrain the namevar(s) */
+
+		appendPQExpBufferStr(&namebuf, ")$");
+		/* Optimize away a "*" pattern */
+		if (strcmp(namebuf.data, "^(.*)$") != 0)
+		{
+			WHEREAND();
+			if (altnamevar)
+			{
+				appendPQExpBuffer(buf, "(%s ~ ", namevar);
+				appendStringLiteralConn(buf, namebuf.data, conn);
+				appendPQExpBuffer(buf, "\n        OR %s ~ ", altnamevar);
+				appendStringLiteralConn(buf, namebuf.data, conn);
+				appendPQExpBufferStr(buf, ")\n");
+			}
+			else
+			{
+				appendPQExpBuffer(buf, "%s ~ ", namevar);
+				appendStringLiteralConn(buf, namebuf.data, conn);
+				appendPQExpBufferChar(buf, '\n');
+			}
+		}
+	}
+
+	if (schemabuf.len > 2)
+	{
+		/* We have a schema pattern, so constrain the schemavar */
+
+		appendPQExpBufferStr(&schemabuf, ")$");
+		/* Optimize away a "*" pattern */
+		if (strcmp(schemabuf.data, "^(.*)$") != 0 && schemavar)
+		{
+			WHEREAND();
+			appendPQExpBuffer(buf, "%s ~ ", schemavar);
+			appendStringLiteralConn(buf, schemabuf.data, conn);
+			appendPQExpBufferChar(buf, '\n');
+		}
+	}
+	else
+	{
+		/* No schema pattern given, so select only visible objects */
+		if (visibilityrule)
+		{
+			WHEREAND();
+			appendPQExpBuffer(buf, "%s\n", visibilityrule);
+		}
+	}
+
+	termPQExpBuffer(&schemabuf);
+	termPQExpBuffer(&namebuf);
+
+#undef WHEREAND
+}
diff --git a/src/bin/pg_dump/dumputils.h b/src/bin/pg_dump/dumputils.h
index b177bb4bc82e65e61ccec4efd179ec8b9ab085e6..94beade21379aec03d1091fb3641475d9a06ec49 100644
--- a/src/bin/pg_dump/dumputils.h
+++ b/src/bin/pg_dump/dumputils.h
@@ -2,12 +2,13 @@
  *
  * Utility routines for SQL dumping
  *	Basically this is stuff that is useful in both pg_dump and pg_dumpall.
+ *	Lately it's also being used by psql and bin/scripts/ ...
  *
  *
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.h,v 1.18 2006/10/04 00:30:05 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.h,v 1.19 2006/10/09 23:30:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,5 +32,10 @@ extern bool buildACLCommands(const char *name, const char *type,
 				 const char *acls, const char *owner,
 				 int remoteVersion,
 				 PQExpBuffer sql);
+extern void processSQLNamePattern(PGconn *conn, PQExpBuffer buf,
+					  const char *pattern,
+					  bool have_where, bool force_escape,
+					  const char *schemavar, const char *namevar,
+					  const char *altnamevar, const char *visibilityrule);
 
 #endif   /* DUMPUTILS_H */
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index d83a6aa45eec8585f7bc1153efafb5446496f9ae..bab0e24f957912a73dc653329502b5eaab599c71 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2006, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.146 2006/10/07 22:21:38 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.147 2006/10/09 23:30:33 tgl Exp $
  */
 #include "postgres_fe.h"
 #include "describe.h"
@@ -31,11 +31,6 @@ static bool describeOneTableDetails(const char *schemaname,
 						const char *relationname,
 						const char *oid,
 						bool verbose);
-static void processNamePattern(PQExpBuffer buf, const char *pattern,
-				   bool have_where, bool force_escape,
-				   const char *schemavar, const char *namevar,
-				   const char *altnamevar, const char *visibilityrule);
-
 static bool add_tablespace_footer(char relkind, Oid tablespace, char **footers,
 					  int *count, PQExpBufferData buf, bool newline);
 
@@ -84,9 +79,9 @@ describeAggregates(const char *pattern, bool verbose)
 					  _("Schema"), _("Name"),
 					  _("Argument data types"), _("Description"));
 
-	processNamePattern(&buf, pattern, true, false,
-					   "n.nspname", "p.proname", NULL,
-					   "pg_catalog.pg_function_is_visible(p.oid)");
+	processSQLNamePattern(pset.db, &buf, pattern, true, false,
+						  "n.nspname", "p.proname", NULL,
+						  "pg_catalog.pg_function_is_visible(p.oid)");
 
 	appendPQExpBuffer(&buf, "ORDER BY 1, 2, 3;");
 
@@ -138,9 +133,9 @@ describeTablespaces(const char *pattern, bool verbose)
 	appendPQExpBuffer(&buf,
 					  "\nFROM pg_catalog.pg_tablespace\n");
 
-	processNamePattern(&buf, pattern, false, false,
-					   NULL, "spcname", NULL,
-					   NULL);
+	processSQLNamePattern(pset.db, &buf, pattern, false, false,
+						  NULL, "spcname", NULL,
+						  NULL);
 
 	appendPQExpBuffer(&buf, "ORDER BY 1;");
 
@@ -236,9 +231,9 @@ describeFunctions(const char *pattern, bool verbose)
 					  "      OR   p.proargtypes[0] <> 'pg_catalog.cstring'::pg_catalog.regtype)\n"
 					  "      AND NOT p.proisagg\n");
 
-	processNamePattern(&buf, pattern, true, false,
-					   "n.nspname", "p.proname", NULL,
-					   "pg_catalog.pg_function_is_visible(p.oid)");
+	processSQLNamePattern(pset.db, &buf, pattern, true, false,
+						  "n.nspname", "p.proname", NULL,
+						  "pg_catalog.pg_function_is_visible(p.oid)");
 
 	appendPQExpBuffer(&buf, "ORDER BY 1, 2, 3, 4;");
 
@@ -302,10 +297,10 @@ describeTypes(const char *pattern, bool verbose)
 	appendPQExpBuffer(&buf, "AND t.typname !~ '^_'\n");
 
 	/* Match name pattern against either internal or external name */
-	processNamePattern(&buf, pattern, true, false,
-					   "n.nspname", "t.typname",
-					   "pg_catalog.format_type(t.oid, NULL)",
-					   "pg_catalog.pg_type_is_visible(t.oid)");
+	processSQLNamePattern(pset.db, &buf, pattern, true, false,
+						  "n.nspname", "t.typname",
+						  "pg_catalog.format_type(t.oid, NULL)",
+						  "pg_catalog.pg_type_is_visible(t.oid)");
 
 	appendPQExpBuffer(&buf, "ORDER BY 1, 2;");
 
@@ -350,9 +345,9 @@ describeOperators(const char *pattern)
 					  _("Left arg type"), _("Right arg type"),
 					  _("Result type"), _("Description"));
 
-	processNamePattern(&buf, pattern, false, true,
-					   "n.nspname", "o.oprname", NULL,
-					   "pg_catalog.pg_operator_is_visible(o.oid)");
+	processSQLNamePattern(pset.db, &buf, pattern, false, true,
+						  "n.nspname", "o.oprname", NULL,
+						  "pg_catalog.pg_operator_is_visible(o.oid)");
 
 	appendPQExpBuffer(&buf, "ORDER BY 1, 2, 3, 4;");
 
@@ -455,8 +450,8 @@ permissionsList(const char *pattern)
 	 * point of view.  You can see 'em by explicit request though, eg with \z
 	 * pg_catalog.*
 	 */
-	processNamePattern(&buf, pattern, true, false,
-					   "n.nspname", "c.relname", NULL,
+	processSQLNamePattern(pset.db, &buf, pattern, true, false,
+						  "n.nspname", "c.relname", NULL,
 			"n.nspname !~ '^pg_' AND pg_catalog.pg_table_is_visible(c.oid)");
 
 	appendPQExpBuffer(&buf, "ORDER BY 1, 2;");
@@ -513,9 +508,9 @@ objectDescription(const char *pattern)
 	 "       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n"
 					  "  WHERE p.proisagg\n",
 					  _("aggregate"));
-	processNamePattern(&buf, pattern, true, false,
-					   "n.nspname", "p.proname", NULL,
-					   "pg_catalog.pg_function_is_visible(p.oid)");
+	processSQLNamePattern(pset.db, &buf, pattern, true, false,
+						  "n.nspname", "p.proname", NULL,
+						  "pg_catalog.pg_function_is_visible(p.oid)");
 
 	/* Function descriptions (except in/outs for datatypes) */
 	appendPQExpBuffer(&buf,
@@ -532,9 +527,9 @@ objectDescription(const char *pattern)
 					  "      OR   p.proargtypes[0] <> 'pg_catalog.cstring'::pg_catalog.regtype)\n"
 					  "      AND NOT p.proisagg\n",
 					  _("function"));
-	processNamePattern(&buf, pattern, true, false,
-					   "n.nspname", "p.proname", NULL,
-					   "pg_catalog.pg_function_is_visible(p.oid)");
+	processSQLNamePattern(pset.db, &buf, pattern, true, false,
+						  "n.nspname", "p.proname", NULL,
+						  "pg_catalog.pg_function_is_visible(p.oid)");
 
 	/* Operator descriptions (only if operator has its own comment) */
 	appendPQExpBuffer(&buf,
@@ -546,9 +541,9 @@ objectDescription(const char *pattern)
 					  "  FROM pg_catalog.pg_operator o\n"
 	"       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = o.oprnamespace\n",
 					  _("operator"));
-	processNamePattern(&buf, pattern, false, false,
-					   "n.nspname", "o.oprname", NULL,
-					   "pg_catalog.pg_operator_is_visible(o.oid)");
+	processSQLNamePattern(pset.db, &buf, pattern, false, false,
+						  "n.nspname", "o.oprname", NULL,
+						  "pg_catalog.pg_operator_is_visible(o.oid)");
 
 	/* Type description */
 	appendPQExpBuffer(&buf,
@@ -560,9 +555,10 @@ objectDescription(const char *pattern)
 					  "  FROM pg_catalog.pg_type t\n"
 	"       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n",
 					  _("data type"));
-	processNamePattern(&buf, pattern, false, false,
-					"n.nspname", "pg_catalog.format_type(t.oid, NULL)", NULL,
-					   "pg_catalog.pg_type_is_visible(t.oid)");
+	processSQLNamePattern(pset.db, &buf, pattern, false, false,
+						  "n.nspname", "pg_catalog.format_type(t.oid, NULL)",
+						  NULL,
+						  "pg_catalog.pg_type_is_visible(t.oid)");
 
 	/* Relation (tables, views, indexes, sequences) descriptions */
 	appendPQExpBuffer(&buf,
@@ -577,9 +573,9 @@ objectDescription(const char *pattern)
 	 "       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"
 					  "  WHERE c.relkind IN ('r', 'v', 'i', 'S')\n",
 					  _("table"), _("view"), _("index"), _("sequence"));
-	processNamePattern(&buf, pattern, true, false,
-					   "n.nspname", "c.relname", NULL,
-					   "pg_catalog.pg_table_is_visible(c.oid)");
+	processSQLNamePattern(pset.db, &buf, pattern, true, false,
+						  "n.nspname", "c.relname", NULL,
+						  "pg_catalog.pg_table_is_visible(c.oid)");
 
 	/* Rule description (ignore rules for views) */
 	appendPQExpBuffer(&buf,
@@ -594,9 +590,9 @@ objectDescription(const char *pattern)
 					  "  WHERE r.rulename != '_RETURN'\n",
 					  _("rule"));
 	/* XXX not sure what to do about visibility rule here? */
-	processNamePattern(&buf, pattern, true, false,
-					   "n.nspname", "r.rulename", NULL,
-					   "pg_catalog.pg_table_is_visible(c.oid)");
+	processSQLNamePattern(pset.db, &buf, pattern, true, false,
+						  "n.nspname", "r.rulename", NULL,
+						  "pg_catalog.pg_table_is_visible(c.oid)");
 
 	/* Trigger description */
 	appendPQExpBuffer(&buf,
@@ -610,9 +606,9 @@ objectDescription(const char *pattern)
 	"       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n",
 					  _("trigger"));
 	/* XXX not sure what to do about visibility rule here? */
-	processNamePattern(&buf, pattern, false, false,
-					   "n.nspname", "t.tgname", NULL,
-					   "pg_catalog.pg_table_is_visible(c.oid)");
+	processSQLNamePattern(pset.db, &buf, pattern, false, false,
+						  "n.nspname", "t.tgname", NULL,
+						  "pg_catalog.pg_table_is_visible(c.oid)");
 
 	appendPQExpBuffer(&buf,
 					  ") AS tt\n"
@@ -660,9 +656,9 @@ describeTableDetails(const char *pattern, bool verbose)
 					  "FROM pg_catalog.pg_class c\n"
 	 "     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n");
 
-	processNamePattern(&buf, pattern, false, false,
-					   "n.nspname", "c.relname", NULL,
-					   "pg_catalog.pg_table_is_visible(c.oid)");
+	processSQLNamePattern(pset.db, &buf, pattern, false, false,
+						  "n.nspname", "c.relname", NULL,
+						  "pg_catalog.pg_table_is_visible(c.oid)");
 
 	appendPQExpBuffer(&buf, "ORDER BY 2, 3;");
 
@@ -1464,8 +1460,8 @@ describeRoles(const char *pattern, bool verbose)
 
 	appendPQExpBuffer(&buf, "\nFROM pg_catalog.pg_roles r\n");
 
-	processNamePattern(&buf, pattern, false, false,
-					   NULL, "r.rolname", NULL, NULL);
+	processSQLNamePattern(pset.db, &buf, pattern, false, false,
+						  NULL, "r.rolname", NULL, NULL);
 
 	appendPQExpBuffer(&buf, "ORDER BY 1;");
 
@@ -1571,9 +1567,9 @@ listTables(const char *tabtypes, const char *pattern, bool verbose)
 	else
 		appendPQExpBuffer(&buf, "      AND n.nspname NOT IN ('pg_catalog', 'pg_toast')\n");
 
-	processNamePattern(&buf, pattern, true, false,
-					   "n.nspname", "c.relname", NULL,
-					   "pg_catalog.pg_table_is_visible(c.oid)");
+	processSQLNamePattern(pset.db, &buf, pattern, true, false,
+						  "n.nspname", "c.relname", NULL,
+						  "pg_catalog.pg_table_is_visible(c.oid)");
 
 	appendPQExpBuffer(&buf, "ORDER BY 1,2;");
 
@@ -1636,9 +1632,9 @@ listDomains(const char *pattern)
 					  _("Modifier"),
 					  _("Check"));
 
-	processNamePattern(&buf, pattern, true, false,
-					   "n.nspname", "t.typname", NULL,
-					   "pg_catalog.pg_type_is_visible(t.oid)");
+	processSQLNamePattern(pset.db, &buf, pattern, true, false,
+						  "n.nspname", "t.typname", NULL,
+						  "pg_catalog.pg_type_is_visible(t.oid)");
 
 	appendPQExpBuffer(&buf, "ORDER BY 1, 2;");
 
@@ -1687,9 +1683,9 @@ listConversions(const char *pattern)
 					  _("no"),
 					  _("Default?"));
 
-	processNamePattern(&buf, pattern, true, false,
-					   "n.nspname", "c.conname", NULL,
-					   "pg_catalog.pg_conversion_is_visible(c.oid)");
+	processSQLNamePattern(pset.db, &buf, pattern, true, false,
+						  "n.nspname", "c.conname", NULL,
+						  "pg_catalog.pg_conversion_is_visible(c.oid)");
 
 	appendPQExpBuffer(&buf, "ORDER BY 1, 2;");
 
@@ -1787,9 +1783,9 @@ listSchemas(const char *pattern, bool verbose)
 					  "WHERE	(n.nspname !~ '^pg_temp_' OR\n"
 		   "		 n.nspname = (pg_catalog.current_schemas(true))[1])\n");		/* temp schema is first */
 
-	processNamePattern(&buf, pattern, true, false,
-					   NULL, "n.nspname", NULL,
-					   NULL);
+	processSQLNamePattern(pset.db, &buf, pattern, true, false,
+						  NULL, "n.nspname", NULL,
+						  NULL);
 
 	appendPQExpBuffer(&buf, "ORDER BY 1;");
 
@@ -1806,201 +1802,3 @@ listSchemas(const char *pattern, bool verbose)
 	PQclear(res);
 	return true;
 }
-
-
-/*
- * processNamePattern
- *
- * Scan a wildcard-pattern option and generate appropriate WHERE clauses
- * to limit the set of objects returned.  The WHERE clauses are appended
- * to buf.
- *
- * pattern: user-specified pattern option to a \d command, or NULL if none.
- * have_where: true if caller already emitted WHERE.
- * force_escape: always quote regexp special characters, even outside quotes.
- * schemavar: name of WHERE variable to match against a schema-name pattern.
- * Can be NULL if no schema.
- * namevar: name of WHERE variable to match against an object-name pattern.
- * altnamevar: NULL, or name of an alternate variable to match against name.
- * visibilityrule: clause to use if we want to restrict to visible objects
- * (for example, "pg_catalog.pg_table_is_visible(p.oid)").	Can be NULL.
- */
-static void
-processNamePattern(PQExpBuffer buf, const char *pattern,
-				   bool have_where, bool force_escape,
-				   const char *schemavar, const char *namevar,
-				   const char *altnamevar, const char *visibilityrule)
-{
-	PQExpBufferData schemabuf;
-	PQExpBufferData namebuf;
-	bool		inquotes;
-	const char *cp;
-	int			i;
-
-#define WHEREAND() \
-	(appendPQExpBuffer(buf, have_where ? "      AND " : "WHERE "), have_where = true)
-
-	if (pattern == NULL)
-	{
-		/* Default: select all visible objects */
-		if (visibilityrule)
-		{
-			WHEREAND();
-			appendPQExpBuffer(buf, "%s\n", visibilityrule);
-		}
-		return;
-	}
-
-	initPQExpBuffer(&schemabuf);
-	initPQExpBuffer(&namebuf);
-
-	/*
-	 * Parse the pattern, converting quotes and lower-casing unquoted letters;
-	 * we assume this was NOT done by scan_option.	Also, adjust shell-style
-	 * wildcard characters into regexp notation.
-	 *
-	 * Note: the result of this pass is the actual regexp pattern we want to
-	 * execute.  Quoting/escaping it into a SQL literal will be done below.
-	 */
-	appendPQExpBufferChar(&namebuf, '^');
-
-	inquotes = false;
-	cp = pattern;
-
-	while (*cp)
-	{
-		char	ch = *cp;
-
-		if (ch == '"')
-		{
-			if (inquotes && cp[1] == '"')
-			{
-				/* emit one quote, stay in inquotes mode */
-				appendPQExpBufferChar(&namebuf, '"');
-				cp++;
-			}
-			else
-				inquotes = !inquotes;
-			cp++;
-		}
-		else if (!inquotes && isupper((unsigned char) ch))
-		{
-			appendPQExpBufferChar(&namebuf,
-								  pg_tolower((unsigned char) ch));
-			cp++;
-		}
-		else if (!inquotes && ch == '*')
-		{
-			appendPQExpBuffer(&namebuf, ".*");
-			cp++;
-		}
-		else if (!inquotes && ch == '?')
-		{
-			appendPQExpBufferChar(&namebuf, '.');
-			cp++;
-		}
-		else if (!inquotes && ch == '.')
-		{
-			/* Found schema/name separator, move current pattern to schema */
-			resetPQExpBuffer(&schemabuf);
-			appendPQExpBufferStr(&schemabuf, namebuf.data);
-			resetPQExpBuffer(&namebuf);
-			appendPQExpBufferChar(&namebuf, '^');
-			cp++;
-		}
-		else
-		{
-			/*
-			 * Ordinary data character, transfer to pattern
-			 *
-			 * Inside double quotes, or at all times if parsing an operator
-			 * name, quote regexp special characters with a backslash to avoid
-			 * regexp errors.  Outside quotes, however, let them pass through
-			 * as-is; this lets knowledgeable users build regexp expressions
-			 * that are more powerful than shell-style patterns.
-			 */
-			if ((inquotes || force_escape) &&
-				strchr("|*+?()[]{}.^$\\", ch))
-				appendPQExpBufferChar(&namebuf, '\\');
-			i = PQmblen(cp, pset.encoding);
-			while (i-- && *cp)
-			{
-				appendPQExpBufferChar(&namebuf, *cp);
-				cp++;
-			}
-		}
-	}
-
-	/*
-	 * Now decide what we need to emit.  Note there will be a leading '^' in
-	 * the patterns in any case.
-	 */
-	if (namebuf.len > 1)
-	{
-		/* We have a name pattern, so constrain the namevar(s) */
-
-		appendPQExpBufferChar(&namebuf, '$');
-		/* Optimize away ".*$", and possibly the whole pattern */
-		if (namebuf.len >= 4 &&
-			strcmp(namebuf.data + (namebuf.len - 3), ".*$") == 0)
-		{
-			namebuf.len -= 3;
-			namebuf.data[namebuf.len] = '\0';
-		}
-
-		if (namebuf.len > 1)
-		{
-			WHEREAND();
-			if (altnamevar)
-			{
-				appendPQExpBuffer(buf, "(%s ~ ", namevar);
-				appendStringLiteralConn(buf, namebuf.data, pset.db);
-				appendPQExpBuffer(buf, "\n        OR %s ~ ", altnamevar);
-				appendStringLiteralConn(buf, namebuf.data, pset.db);
-				appendPQExpBuffer(buf, ")\n");
-			}
-			else
-			{
-				appendPQExpBuffer(buf, "%s ~ ", namevar);
-				appendStringLiteralConn(buf, namebuf.data, pset.db);
-				appendPQExpBufferChar(buf, '\n');
-			}
-		}
-	}
-
-	if (schemabuf.len > 1)
-	{
-		/* We have a schema pattern, so constrain the schemavar */
-
-		appendPQExpBufferChar(&schemabuf, '$');
-		/* Optimize away ".*$", and possibly the whole pattern */
-		if (schemabuf.len >= 4 &&
-			strcmp(schemabuf.data + (schemabuf.len - 3), ".*$") == 0)
-		{
-			schemabuf.len -= 3;
-			schemabuf.data[schemabuf.len] = '\0';
-		}
-
-		if (schemabuf.len > 1 && schemavar)
-		{
-			WHEREAND();
-			appendPQExpBuffer(buf, "%s ~ ", schemavar);
-			appendStringLiteralConn(buf, schemabuf.data, pset.db);
-			appendPQExpBufferChar(buf, '\n');
-		}
-	}
-	else
-	{
-		/* No schema pattern given, so select only visible objects */
-		if (visibilityrule)
-		{
-			WHEREAND();
-			appendPQExpBuffer(buf, "%s\n", visibilityrule);
-		}
-	}
-
-	termPQExpBuffer(&schemabuf);
-	termPQExpBuffer(&namebuf);
-
-#undef WHEREAND
-}