diff --git a/src/fe_utils/string_utils.c b/src/fe_utils/string_utils.c
index 3efee4e7ee..d4003247df 100644
--- a/src/fe_utils/string_utils.c
+++ b/src/fe_utils/string_utils.c
@@ -942,17 +942,14 @@ processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern,
  * unquoted letters, and adjusting shell-style wildcard characters into regexp
  * notation.
  *
- * If the dbnamebuf and schemabuf arguments are non-NULL, and the pattern
- * contains two or more dbname/schema/name separators, we parse the portions of
- * the pattern prior to the first and second separators into dbnamebuf and
- * schemabuf, and the rest into namebuf.  (Additional dots in the name portion
- * are not treated as special.)
+ * If the pattern contains dbname/schema/name separators, we interpret the
+ * final portion of the pattern as the name, the previous portion (if any) as
+ * the schema, and the portion previous to that (if any) as the database.  We
+ * ignore any additional portions prior to the database.
  *
- * If dbnamebuf is NULL and schemabuf is non-NULL, and the pattern contains at
- * least one separator, we parse the first portion into schemabuf and the rest
- * into namebuf.
- *
- * Otherwise, we parse all the pattern into namebuf.
+ * If the dbnamebuf, schemabuf, or namebuf are non-NULL, we store the
+ * corresponding portion of the pattern in them, otherwise that portion is
+ * discarded.
  *
  * We surround the regexps with "^(...)$" to force them to match whole strings,
  * as per SQL practice.  We have to have parens in case strings contain "|",
@@ -967,9 +964,9 @@ void
 patternToSQLRegex(int encoding, PQExpBuffer dbnamebuf, PQExpBuffer schemabuf,
 				  PQExpBuffer namebuf, const char *pattern, bool force_escape)
 {
-	PQExpBufferData buf[3];
-	PQExpBuffer curbuf;
-	PQExpBuffer maxbuf;
+	PQExpBuffer dbname = NULL;
+	PQExpBuffer schema = NULL;
+	PQExpBuffer relname = NULL;
 	int			i;
 	bool		inquotes;
 	const char *cp;
@@ -983,16 +980,8 @@ patternToSQLRegex(int encoding, PQExpBuffer dbnamebuf, PQExpBuffer schemabuf,
 	inquotes = false;
 	cp = pattern;
 
-	if (dbnamebuf != NULL)
-		maxbuf = &buf[2];
-	else if (schemabuf != NULL)
-		maxbuf = &buf[1];
-	else
-		maxbuf = &buf[0];
-
-	curbuf = &buf[0];
-	initPQExpBuffer(curbuf);
-	appendPQExpBufferStr(curbuf, "^(");
+	relname = createPQExpBuffer();
+	appendPQExpBufferStr(relname, "^(");
 	while (*cp)
 	{
 		char		ch = *cp;
@@ -1002,7 +991,7 @@ patternToSQLRegex(int encoding, PQExpBuffer dbnamebuf, PQExpBuffer schemabuf,
 			if (inquotes && cp[1] == '"')
 			{
 				/* emit one quote, stay in inquotes mode */
-				appendPQExpBufferChar(curbuf, '"');
+				appendPQExpBufferChar(relname, '"');
 				cp++;
 			}
 			else
@@ -1011,33 +1000,36 @@ patternToSQLRegex(int encoding, PQExpBuffer dbnamebuf, PQExpBuffer schemabuf,
 		}
 		else if (!inquotes && isupper((unsigned char) ch))
 		{
-			appendPQExpBufferChar(curbuf,
+			appendPQExpBufferChar(relname,
 								  pg_tolower((unsigned char) ch));
 			cp++;
 		}
 		else if (!inquotes && ch == '*')
 		{
-			appendPQExpBufferStr(curbuf, ".*");
+			appendPQExpBufferStr(relname, ".*");
 			cp++;
 		}
 		else if (!inquotes && ch == '?')
 		{
-			appendPQExpBufferChar(curbuf, '.');
+			appendPQExpBufferChar(relname, '.');
 			cp++;
 		}
 
-		/*
-		 * When we find a dbname/schema/name separator, we treat it specially
-		 * only if the caller requested more patterns to be parsed than we
-		 * have already parsed from the pattern.  Otherwise, dot characters
-		 * are not special.
-		 */
-		else if (!inquotes && ch == '.' && curbuf < maxbuf)
+		/* Handle dbname/schema/name separators */
+		else if (!inquotes && ch == '.')
 		{
-			appendPQExpBufferStr(curbuf, ")$");
-			curbuf++;
-			initPQExpBuffer(curbuf);
-			appendPQExpBufferStr(curbuf, "^(");
+			PQExpBuffer	tmp;
+
+			appendPQExpBufferStr(relname, ")$");
+			tmp = dbname;
+			dbname = schema;
+			schema = relname;
+			relname = tmp;
+			if (relname)
+				resetPQExpBuffer(relname);
+			else
+				relname = createPQExpBuffer();
+			appendPQExpBufferStr(relname, "^(");
 			cp++;
 		}
 		else if (ch == '$')
@@ -1049,7 +1041,7 @@ patternToSQLRegex(int encoding, PQExpBuffer dbnamebuf, PQExpBuffer schemabuf,
 			 * we anchor the pattern automatically there is no use-case for
 			 * having it possess its regexp meaning.
 			 */
-			appendPQExpBufferStr(curbuf, "\\$");
+			appendPQExpBufferStr(relname, "\\$");
 			cp++;
 		}
 		else
@@ -1069,30 +1061,28 @@ patternToSQLRegex(int encoding, PQExpBuffer dbnamebuf, PQExpBuffer schemabuf,
 			 */
 			if ((inquotes || force_escape) &&
 				strchr("|*+?()[]{}.^$\\", ch))
-				appendPQExpBufferChar(curbuf, '\\');
+				appendPQExpBufferChar(relname, '\\');
 			else if (ch == '[' && cp[1] == ']')
-				appendPQExpBufferChar(curbuf, '\\');
+				appendPQExpBufferChar(relname, '\\');
 			i = PQmblenBounded(cp, encoding);
 			while (i--)
-				appendPQExpBufferChar(curbuf, *cp++);
+				appendPQExpBufferChar(relname, *cp++);
 		}
 	}
-	appendPQExpBufferStr(curbuf, ")$");
+	appendPQExpBufferStr(relname, ")$");
 
-	appendPQExpBufferStr(namebuf, curbuf->data);
-	termPQExpBuffer(curbuf);
-
-	if (curbuf > buf)
+	appendPQExpBufferStr(namebuf, relname->data);
+	destroyPQExpBuffer(relname);
+	if (schema)
 	{
-		curbuf--;
-		appendPQExpBufferStr(schemabuf, curbuf->data);
-		termPQExpBuffer(curbuf);
-
-		if (curbuf > buf)
-		{
-			curbuf--;
-			appendPQExpBufferStr(dbnamebuf, curbuf->data);
-			termPQExpBuffer(curbuf);
-		}
+		if (schemabuf)
+			appendPQExpBufferStr(schemabuf, schema->data);
+		destroyPQExpBuffer(schema);
+	}
+	if (dbname)
+	{
+		if (dbnamebuf)
+			appendPQExpBufferStr(dbnamebuf, dbname->data);
+		destroyPQExpBuffer(dbname);
 	}
 }
