diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 0f20f38c..34a1d58a 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -5954,7 +5954,22 @@ build_remattrmap(Relation relation, List *va_cols,
 
 		if (attrcnt > 0)
 			appendStringInfoString(column_list, ", ");
-		appendStringInfoString(column_list, quote_identifier(remote_attname));
+
+		/*
+		 * Use array-element quoting, not SQL identifier quoting.  The
+		 * column_list is interpolated into a text[] array literal, where
+		 * backslash is an escape character.  quote_identifier() does not
+		 * escape backslashes, so column names containing them would be
+		 * silently mangled by the array parser (e.g. "a\b" → "ab").
+		 */
+		appendStringInfoChar(column_list, '"');
+		for (const char *p = remote_attname; *p; p++)
+		{
+			if (*p == '"' || *p == '\\')
+				appendStringInfoChar(column_list, '\\');
+			appendStringInfoChar(column_list, *p);
+		}
+		appendStringInfoChar(column_list, '"');
 
 		remattrmap[attrcnt].local_attnum = attnum;
 		strncpy(remattrmap[attrcnt].local_attname, attname, NAMEDATALEN);
