aboutsummaryrefslogtreecommitdiff
path: root/src/bin/pg_dump/dumputils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/pg_dump/dumputils.c')
-rw-r--r--src/bin/pg_dump/dumputils.c143
1 files changed, 84 insertions, 59 deletions
diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c
index 795ce2b986d..bad85e2bda5 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.28 2006/05/26 23:48:54 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.29 2006/05/28 21:13:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -100,63 +100,102 @@ fmtId(const char *rawid)
/*
* Convert a string value to an SQL string literal and append it to
- * the given buffer.
+ * the given buffer. We assume the specified client_encoding and
+ * standard_conforming_strings settings.
*
- * Special characters are escaped. Quote mark ' goes to '' per SQL
- * standard, other stuff goes to \ sequences. If escapeAll is false,
- * whitespace characters are not escaped (tabs, newlines, etc.). This
- * is appropriate for dump file output. Using E'' strings for
- * backslashes is always safe for standard_conforming_strings on or off.
+ * This is essentially equivalent to libpq's PQescapeStringInternal,
+ * except for the output buffer structure. We need it in situations
+ * where we do not have a PGconn available. Where we do,
+ * appendStringLiteralConn is a better choice.
*/
void
-appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll,
- bool e_string_for_backslash)
+appendStringLiteral(PQExpBuffer buf, const char *str,
+ int encoding, bool std_strings)
{
- char ch;
- const char *p;
- bool is_e_string = false;
+ size_t length = strlen(str);
+ const char *source = str;
+ char *target;
- for (p = str; *p; p++)
+ if (!enlargePQExpBuffer(buf, 2 * length + 2))
+ return;
+
+ target = buf->data + buf->len;
+ *target++ = '\'';
+
+ while (*source != '\0')
{
- ch = *p;
+ char c = *source;
+ int len;
+ int i;
- if ((e_string_for_backslash && ch == '\\') ||
- ((unsigned char) ch < (unsigned char) ' ' &&
- (escapeAll ||
- (ch != '\t' && ch != '\n' && ch != '\v' &&
- ch != '\f' && ch != '\r'))))
+ /* Fast path for plain ASCII */
+ if (!IS_HIGHBIT_SET(c))
{
- appendPQExpBufferChar(buf, ESCAPE_STRING_SYNTAX);
- is_e_string = true;
- break;
+ /* Apply quoting if needed */
+ if (SQL_STR_DOUBLE(c, !std_strings))
+ *target++ = c;
+ /* Copy the character */
+ *target++ = c;
+ source++;
+ continue;
}
- }
- appendPQExpBufferChar(buf, '\'');
- for (p = str; *p; p++)
- {
- ch = *p;
- if (SQL_STR_DOUBLE(ch, is_e_string))
+ /* Slow path for possible multibyte characters */
+ len = PQmblen(source, encoding);
+
+ /* Copy the character */
+ for (i = 0; i < len; i++)
{
- appendPQExpBufferChar(buf, ch);
- appendPQExpBufferChar(buf, ch);
+ if (*source == '\0')
+ break;
+ *target++ = *source++;
}
- else if ((unsigned char) ch < (unsigned char) ' ' &&
- (escapeAll ||
- (ch != '\t' && ch != '\n' && ch != '\v' &&
- ch != '\f' && ch != '\r')))
+
+ /*
+ * If we hit premature end of string (ie, incomplete multibyte
+ * character), try to pad out to the correct length with spaces.
+ * We may not be able to pad completely, but we will always be able
+ * to insert at least one pad space (since we'd not have quoted a
+ * multibyte character). This should be enough to make a string that
+ * the server will error out on.
+ */
+ if (i < len)
{
- /*
- * generate octal escape for control chars other than whitespace
- */
- appendPQExpBufferChar(buf, '\\');
- appendPQExpBufferChar(buf, ((ch >> 6) & 3) + '0');
- appendPQExpBufferChar(buf, ((ch >> 3) & 7) + '0');
- appendPQExpBufferChar(buf, (ch & 7) + '0');
+ char *stop = buf->data + buf->maxlen - 2;
+
+ for (; i < len; i++)
+ {
+ if (target >= stop)
+ break;
+ *target++ = ' ';
+ }
+ break;
}
- else
- appendPQExpBufferChar(buf, ch);
}
+
+ /* Write the terminating quote and NUL character. */
+ *target++ = '\'';
+ *target = '\0';
+
+ buf->len = target - buf->data;
+}
+
+
+/*
+ * Convert a string value to an SQL string literal and append it to
+ * the given buffer. Encoding and string syntax rules are as indicated
+ * by current settings of the PGconn.
+ */
+void
+appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)
+{
+ size_t length = strlen(str);
+
+ if (!enlargePQExpBuffer(buf, 2 * length + 2))
+ return;
+ appendPQExpBufferChar(buf, '\'');
+ buf->len += PQescapeStringConn(conn, buf->data + buf->len,
+ str, length, NULL);
appendPQExpBufferChar(buf, '\'');
}
@@ -167,7 +206,8 @@ appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll,
* dollar quote delimiter will begin with that (after the opening $).
*
* No escaping is done at all on str, in compliance with the rules
- * for parsing dollar quoted strings.
+ * for parsing dollar quoted strings. Also, we need not worry about
+ * encoding issues.
*/
void
appendStringLiteralDQ(PQExpBuffer buf, const char *str, const char *dqprefix)
@@ -205,21 +245,6 @@ appendStringLiteralDQ(PQExpBuffer buf, const char *str, const char *dqprefix)
/*
- * Use dollar quoting if the string to be quoted contains ' or \,
- * otherwise use standard quoting.
- */
-void
-appendStringLiteralDQOpt(PQExpBuffer buf, const char *str,
- bool escapeAll, const char *dqprefix)
-{
- if (strchr(str, '\'') == NULL && strchr(str, '\\') == NULL)
- appendStringLiteral(buf, str, escapeAll, true);
- else
- appendStringLiteralDQ(buf, str, dqprefix);
-}
-
-
-/*
* Convert backend's version string into a number.
*/
int