From 6178762fcf02f5f07099ff2277f8cdd82151cd0e Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 1 Jun 2006 00:15:36 +0000
Subject: [PATCH] Fix up hack to suppress escape_string_warning so that it
 actually works and there's only one place that's a kluge, ie,
 appendStringLiteralConn. Note that pg_dump itself doesn't use
 appendStringLiteralConn, so its behavior is not affected; only the other
 utility programs care.

---
 src/bin/pg_dump/dumputils.c  | 17 +++++++++-
 src/bin/psql/command.c       |  8 ++---
 src/bin/psql/common.h        |  8 +----
 src/bin/psql/copy.c          | 64 +++++++++++++++++++++---------------
 src/bin/psql/describe.c      |  6 +---
 src/bin/scripts/createdb.c   |  4 +--
 src/bin/scripts/createuser.c |  4 +--
 7 files changed, 61 insertions(+), 50 deletions(-)

diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c
index bad85e2bda5..8648c2f5590 100644
--- a/src/bin/pg_dump/dumputils.c
+++ b/src/bin/pg_dump/dumputils.c
@@ -7,7 +7,7 @@
  * 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.29 2006/05/28 21:13:54 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.30 2006/06/01 00:15:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -191,6 +191,21 @@ appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)
 {
 	size_t	length = strlen(str);
 
+	/*
+	 * XXX This is a kluge to silence escape_string_warning in our utility
+	 * programs.  It should go away someday.
+	 */
+	if (strchr(str, '\\') != NULL && PQserverVersion(conn) >= 80100)
+	{
+		/* ensure we are not adjacent to an identifier */
+		if (buf->len > 0 && buf->data[buf->len-1] != ' ')
+			appendPQExpBufferChar(buf, ' ');
+		appendPQExpBufferChar(buf, ESCAPE_STRING_SYNTAX);
+		appendStringLiteral(buf, str, PQclientEncoding(conn), false);
+		return;
+	}
+	/* XXX end kluge */
+
 	if (!enlargePQExpBuffer(buf, 2 * length + 2))
 		return;
 	appendPQExpBufferChar(buf, '\'');
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index a060e00abc7..63161edd457 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2006, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.167 2006/05/31 11:02:42 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.168 2006/06/01 00:15:36 tgl Exp $
  */
 #include "postgres_fe.h"
 #include "command.h"
@@ -681,9 +681,9 @@ exec_command(const char *cmd,
 				PGresult   *res;
 
 				initPQExpBuffer(&buf);
-				printfPQExpBuffer(&buf, "ALTER USER %s PASSWORD %c'%s';",
-								  fmtId(user), NEED_E_STR(encrypted_password),
-								  encrypted_password);
+				printfPQExpBuffer(&buf, "ALTER USER %s PASSWORD ",
+								  fmtId(user));
+				appendStringLiteralConn(&buf, encrypted_password, pset.db);
 				res = PSQLexec(buf.data, false);
 				termPQExpBuffer(&buf);
 				if (!res)
diff --git a/src/bin/psql/common.h b/src/bin/psql/common.h
index 0d0f7ad5ed5..4cf5da0bf35 100644
--- a/src/bin/psql/common.h
+++ b/src/bin/psql/common.h
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2006, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/common.h,v 1.48 2006/05/31 11:02:42 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/common.h,v 1.49 2006/06/01 00:15:36 tgl Exp $
  */
 #ifndef COMMON_H
 #define COMMON_H
@@ -22,12 +22,6 @@
 
 #define atooid(x)  ((Oid) strtoul((x), NULL, 10))
 
-/*
- *	We use this to prefix strings with E'' that we know are already safe,
- *	so we don't get an escape_string_warning.
- */
-#define	NEED_E_STR(str)		((strchr(str, '\\') && !standard_strings()) ? ESCAPE_STRING_SYNTAX : ' ')
-
 /*
  * Safer versions of some standard C library functions. If an
  * out-of-memory condition occurs, these functions will bail out
diff --git a/src/bin/psql/copy.c b/src/bin/psql/copy.c
index 15a3883cdda..ae4ad629e99 100644
--- a/src/bin/psql/copy.c
+++ b/src/bin/psql/copy.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2006, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.62 2006/05/31 11:02:42 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.63 2006/06/01 00:15:36 tgl Exp $
  */
 #include "postgres_fe.h"
 #include "copy.h"
@@ -19,6 +19,7 @@
 #include "libpq-fe.h"
 #include "pqexpbuffer.h"
 #include "pqsignal.h"
+#include "dumputils.h"
 
 #include "settings.h"
 #include "common.h"
@@ -113,6 +114,7 @@ parse_slash_copy(const char *args)
 	char	   *line;
 	char	   *token;
 	const char *whitespace = " \t\n\r";
+	char		nonstd_backslash = standard_strings() ? 0 : '\\';
 
 	if (args)
 		line = pg_strdup(args);
@@ -216,7 +218,7 @@ parse_slash_copy(const char *args)
 		goto error;
 
 	token = strtokx(NULL, whitespace, NULL, "'",
-					standard_strings() ? 0 : '\\', true, pset.encoding);
+					nonstd_backslash, true, pset.encoding);
 	if (!token)
 		goto error;
 
@@ -255,7 +257,7 @@ parse_slash_copy(const char *args)
 	if (token && pg_strcasecmp(token, "delimiters") == 0)
 	{
 		token = strtokx(NULL, whitespace, NULL, "'",
-						standard_strings() ? 0 : '\\', false, pset.encoding);
+						nonstd_backslash, false, pset.encoding);
 		if (!token)
 			goto error;
 		result->delim = pg_strdup(token);
@@ -290,10 +292,10 @@ parse_slash_copy(const char *args)
 			else if (pg_strcasecmp(token, "delimiter") == 0)
 			{
 				token = strtokx(NULL, whitespace, NULL, "'",
-								standard_strings() ? 0 : '\\', false, pset.encoding);
+								nonstd_backslash, false, pset.encoding);
 				if (token && pg_strcasecmp(token, "as") == 0)
 					token = strtokx(NULL, whitespace, NULL, "'",
-									standard_strings() ? 0 : '\\', false, pset.encoding);
+									nonstd_backslash, false, pset.encoding);
 				if (token)
 					result->delim = pg_strdup(token);
 				else
@@ -302,10 +304,10 @@ parse_slash_copy(const char *args)
 			else if (pg_strcasecmp(token, "null") == 0)
 			{
 				token = strtokx(NULL, whitespace, NULL, "'",
-								standard_strings() ? 0 : '\\', false, pset.encoding);
+								nonstd_backslash, false, pset.encoding);
 				if (token && pg_strcasecmp(token, "as") == 0)
 					token = strtokx(NULL, whitespace, NULL, "'",
-									standard_strings() ? 0 : '\\', false, pset.encoding);
+									nonstd_backslash, false, pset.encoding);
 				if (token)
 					result->null = pg_strdup(token);
 				else
@@ -314,10 +316,10 @@ parse_slash_copy(const char *args)
 			else if (pg_strcasecmp(token, "quote") == 0)
 			{
 				token = strtokx(NULL, whitespace, NULL, "'",
-								standard_strings() ? 0 : '\\', false, pset.encoding);
+								nonstd_backslash, false, pset.encoding);
 				if (token && pg_strcasecmp(token, "as") == 0)
 					token = strtokx(NULL, whitespace, NULL, "'",
-									standard_strings() ? 0 : '\\', false, pset.encoding);
+									nonstd_backslash, false, pset.encoding);
 				if (token)
 					result->quote = pg_strdup(token);
 				else
@@ -326,10 +328,10 @@ parse_slash_copy(const char *args)
 			else if (pg_strcasecmp(token, "escape") == 0)
 			{
 				token = strtokx(NULL, whitespace, NULL, "'",
-								standard_strings() ? 0 : '\\', false, pset.encoding);
+								nonstd_backslash, false, pset.encoding);
 				if (token && pg_strcasecmp(token, "as") == 0)
 					token = strtokx(NULL, whitespace, NULL, "'",
-									standard_strings() ? 0 : '\\', false, pset.encoding);
+									nonstd_backslash, false, pset.encoding);
 				if (token)
 					result->escape = pg_strdup(token);
 				else
@@ -461,23 +463,27 @@ do_copy(const char *args)
 	/* Uses old COPY syntax for backward compatibility 2002-06-19 */
 	if (options->delim)
 	{
+		/* if user gave a quoted string, use it as-is */
 		if (options->delim[0] == '\'')
-			appendPQExpBuffer(&query, " USING DELIMITERS %c%s",
-							  NEED_E_STR(options->delim), options->delim);
+			appendPQExpBuffer(&query, " USING DELIMITERS %s", options->delim);
 		else
-			appendPQExpBuffer(&query, " USING DELIMITERS %c'%s'",
-							  NEED_E_STR(options->delim), options->delim);
+		{
+			appendPQExpBuffer(&query, " USING DELIMITERS ");
+			appendStringLiteralConn(&query, options->delim, pset.db);
+		}
 	}
 
 	/* There is no backward-compatible CSV syntax */
 	if (options->null)
 	{
+		/* if user gave a quoted string, use it as-is */
 		if (options->null[0] == '\'')
-			appendPQExpBuffer(&query, " WITH NULL AS %c%s",
-							  NEED_E_STR(options->null), options->null);
+			appendPQExpBuffer(&query, " WITH NULL AS %s", options->null);
 		else
-			appendPQExpBuffer(&query, " WITH NULL AS %c'%s'",
-							  NEED_E_STR(options->null), options->null);
+		{
+			appendPQExpBuffer(&query, " WITH NULL AS ");
+			appendStringLiteralConn(&query, options->null, pset.db);
+		}
 	}
 
 	if (options->csv_mode)
@@ -488,22 +494,26 @@ do_copy(const char *args)
 
 	if (options->quote)
 	{
+		/* if user gave a quoted string, use it as-is */
 		if (options->quote[0] == '\'')
-			appendPQExpBuffer(&query, " QUOTE AS %c%s",
-							  NEED_E_STR(options->quote), options->quote);
+			appendPQExpBuffer(&query, " QUOTE AS %s", options->quote);
 		else
-			appendPQExpBuffer(&query, " QUOTE AS %c'%s'",
-							  NEED_E_STR(options->quote), options->quote);
+		{
+			appendPQExpBuffer(&query, " QUOTE AS ");
+			appendStringLiteralConn(&query, options->quote, pset.db);
+		}
 	}
 
 	if (options->escape)
 	{
+		/* if user gave a quoted string, use it as-is */
 		if (options->escape[0] == '\'')
-			appendPQExpBuffer(&query, " ESCAPE AS %c%s",
-							  NEED_E_STR(options->escape), options->escape);
+			appendPQExpBuffer(&query, " ESCAPE AS %s", options->escape);
 		else
-			appendPQExpBuffer(&query, " ESCAPE AS %c'%s'",
-							  NEED_E_STR(options->escape), options->escape);
+		{
+			appendPQExpBuffer(&query, " ESCAPE AS ");
+			appendStringLiteralConn(&query, options->escape, pset.db);
+		}
 	}
 
 	if (options->force_quote_list)
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index b6a462c3c91..9c9f6094079 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.138 2006/05/31 11:02:42 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.139 2006/06/01 00:15:36 tgl Exp $
  */
 #include "postgres_fe.h"
 #include "describe.h"
@@ -1907,17 +1907,14 @@ processNamePattern(PQExpBuffer buf, const char *pattern,
 			if (altnamevar)
 			{
 				appendPQExpBuffer(buf, "(%s ~ ", namevar);
-				appendPQExpBufferChar(buf, NEED_E_STR(namebuf.data));
 				appendStringLiteralConn(buf, namebuf.data, pset.db);
 				appendPQExpBuffer(buf, "\n        OR %s ~ ", altnamevar);
-				appendPQExpBufferChar(buf, NEED_E_STR(namebuf.data));
 				appendStringLiteralConn(buf, namebuf.data, pset.db);
 				appendPQExpBuffer(buf, ")\n");
 			}
 			else
 			{
 				appendPQExpBuffer(buf, "%s ~ ", namevar);
-				appendPQExpBufferChar(buf, NEED_E_STR(namebuf.data));
 				appendStringLiteralConn(buf, namebuf.data, pset.db);
 				appendPQExpBufferChar(buf, '\n');
 			}
@@ -1941,7 +1938,6 @@ processNamePattern(PQExpBuffer buf, const char *pattern,
 		{
 			WHEREAND();
 			appendPQExpBuffer(buf, "%s ~ ", schemavar);
-			appendPQExpBufferChar(buf, NEED_E_STR(schemabuf.data));
 			appendStringLiteralConn(buf, schemabuf.data, pset.db);
 			appendPQExpBufferChar(buf, '\n');
 		}
diff --git a/src/bin/scripts/createdb.c b/src/bin/scripts/createdb.c
index c023a12bd9d..4998c798dec 100644
--- a/src/bin/scripts/createdb.c
+++ b/src/bin/scripts/createdb.c
@@ -5,7 +5,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/bin/scripts/createdb.c,v 1.20 2006/05/31 11:02:42 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/scripts/createdb.c,v 1.21 2006/06/01 00:15:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -185,8 +185,6 @@ main(int argc, char *argv[])
 	{
 		conn = connectDatabase(dbname, host, port, username, password, progname);
 
-		executeCommand(conn, "SET escape_string_warning TO 'off'", progname, false);
-
 		printfPQExpBuffer(&sql, "COMMENT ON DATABASE %s IS ", fmtId(dbname));
 		appendStringLiteralConn(&sql, comment, conn);
 		appendPQExpBuffer(&sql, ";\n");
diff --git a/src/bin/scripts/createuser.c b/src/bin/scripts/createuser.c
index 17b3407a3a3..e671298fda2 100644
--- a/src/bin/scripts/createuser.c
+++ b/src/bin/scripts/createuser.c
@@ -5,7 +5,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/bin/scripts/createuser.c,v 1.31 2006/05/31 11:02:42 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/scripts/createuser.c,v 1.32 2006/06/01 00:15:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -243,8 +243,6 @@ main(int argc, char *argv[])
 	printfPQExpBuffer(&sql, "CREATE ROLE %s", fmtId(newuser));
 	if (newpassword)
 	{
-		executeCommand(conn, "SET escape_string_warning TO 'off'", progname, false);
-
 		if (encrypted == TRI_YES)
 			appendPQExpBuffer(&sql, " ENCRYPTED");
 		if (encrypted == TRI_NO)
-- 
GitLab