Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 134b463

Browse files
committed
Fix up pg_dump to do string escaping fully correctly for client encoding
and standard_conforming_strings; likewise for the other client programs that need it. As per previous discussion, a pg_dump dump now conforms to the standard_conforming_strings setting of the source database. We don't use E'' syntax in the dump, thereby improving portability of the SQL. I added a SET escape_strings_warning = off command to keep the dumps from getting a lot of back-chatter from that.
1 parent 117d73a commit 134b463

File tree

15 files changed

+378
-304
lines changed

15 files changed

+378
-304
lines changed

src/backend/utils/adt/quote.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,13 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/utils/adt/quote.c,v 1.19 2006/05/26 23:48:54 momjian Exp $
10+
* $PostgreSQL: pgsql/src/backend/utils/adt/quote.c,v 1.20 2006/05/28 21:13:53 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
1414
#include "postgres.h"
1515

1616
#include "utils/builtins.h"
17-
#include "parser/gramparse.h"
1817

1918

2019
/*
@@ -49,6 +48,12 @@ quote_ident(PG_FUNCTION_ARGS)
4948
/*
5049
* quote_literal -
5150
* returns a properly quoted literal
51+
*
52+
* NOTE: think not to make this function's behavior change with
53+
* standard_conforming_strings. We don't know where the result
54+
* literal will be used, and so we must generate a result that
55+
* will work with either setting. Take a look at what dblink
56+
* uses this for before thinking you know better.
5257
*/
5358
Datum
5459
quote_literal(PG_FUNCTION_ARGS)
@@ -66,20 +71,22 @@ quote_literal(PG_FUNCTION_ARGS)
6671
cp1 = VARDATA(t);
6772
cp2 = VARDATA(result);
6873

69-
if (!standard_conforming_strings)
70-
for (; len-- > 0; cp1++)
71-
if (*cp1 == '\\')
72-
{
73-
*cp2++ = ESCAPE_STRING_SYNTAX;
74-
break;
75-
}
74+
for (; len-- > 0; cp1++)
75+
{
76+
if (*cp1 == '\\')
77+
{
78+
*cp2++ = ESCAPE_STRING_SYNTAX;
79+
break;
80+
}
81+
}
7682

7783
len = VARSIZE(t) - VARHDRSZ;
7884
cp1 = VARDATA(t);
85+
7986
*cp2++ = '\'';
8087
while (len-- > 0)
8188
{
82-
if (SQL_STR_DOUBLE(*cp1, !standard_conforming_strings))
89+
if (SQL_STR_DOUBLE(*cp1, true))
8390
*cp2++ = *cp1;
8491
*cp2++ = *cp1++;
8592
}

src/backend/utils/adt/ruleutils.c

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* ruleutils.c - Functions to convert stored expressions/querytrees
33
* back to source text
44
*
5-
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.222 2006/05/26 23:48:54 momjian Exp $
5+
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.223 2006/05/28 21:13:53 tgl Exp $
66
**********************************************************************/
77

88
#include "postgres.h"
@@ -534,18 +534,23 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
534534
{
535535
if (i > 0)
536536
appendStringInfo(&buf, ", ");
537-
if (!standard_conforming_strings && strchr(p, '\\') != NULL)
538-
appendStringInfoChar(&buf, ESCAPE_STRING_SYNTAX);
537+
/*
538+
* We form the string literal according to the prevailing setting
539+
* of standard_conforming_strings; we never use E''.
540+
* User is responsible for making sure result is used correctly.
541+
*/
539542
appendStringInfoChar(&buf, '\'');
540-
541543
while (*p)
542544
{
543-
if (SQL_STR_DOUBLE(*p, !standard_conforming_strings))
544-
appendStringInfoChar(&buf, *p);
545-
appendStringInfoChar(&buf, *p++);
545+
char ch = *p++;
546+
547+
if (SQL_STR_DOUBLE(ch, !standard_conforming_strings))
548+
appendStringInfoChar(&buf, ch);
549+
appendStringInfoChar(&buf, ch);
546550
}
547-
p++;
548551
appendStringInfoChar(&buf, '\'');
552+
/* advance p to next string embedded in tgargs */
553+
p++;
549554
}
550555
}
551556

@@ -3883,8 +3888,7 @@ get_const_expr(Const *constval, deparse_context *context)
38833888
char *valptr;
38843889
bool isfloat = false;
38853890
bool needlabel;
3886-
bool is_e_string = false;
3887-
3891+
38883892
if (constval->constisnull)
38893893
{
38903894
/*
@@ -3946,32 +3950,18 @@ get_const_expr(Const *constval, deparse_context *context)
39463950
default:
39473951

39483952
/*
3949-
* We must quote any funny characters in the constant's
3950-
* representation. XXX Any MULTIBYTE considerations here?
3953+
* We form the string literal according to the prevailing setting
3954+
* of standard_conforming_strings; we never use E''.
3955+
* User is responsible for making sure result is used correctly.
39513956
*/
3952-
for (valptr = extval; *valptr; valptr++)
3953-
if ((!standard_conforming_strings && *valptr == '\\') ||
3954-
(unsigned char) *valptr < (unsigned char) ' ')
3955-
{
3956-
appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX);
3957-
is_e_string = true;
3958-
break;
3959-
}
3960-
39613957
appendStringInfoChar(buf, '\'');
39623958
for (valptr = extval; *valptr; valptr++)
39633959
{
39643960
char ch = *valptr;
39653961

3966-
if (SQL_STR_DOUBLE(ch, is_e_string))
3967-
{
3968-
appendStringInfoChar(buf, ch);
3969-
appendStringInfoChar(buf, ch);
3970-
}
3971-
else if ((unsigned char) ch < (unsigned char) ' ')
3972-
appendStringInfo(buf, "\\%03o", (int) ch);
3973-
else
3962+
if (SQL_STR_DOUBLE(ch, !standard_conforming_strings))
39743963
appendStringInfoChar(buf, ch);
3964+
appendStringInfoChar(buf, ch);
39753965
}
39763966
appendStringInfoChar(buf, '\'');
39773967
break;

src/bin/pg_dump/dumputils.c

Lines changed: 84 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.28 2006/05/26 23:48:54 momjian Exp $
10+
* $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.29 2006/05/28 21:13:54 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -100,63 +100,102 @@ fmtId(const char *rawid)
100100

101101
/*
102102
* Convert a string value to an SQL string literal and append it to
103-
* the given buffer.
103+
* the given buffer. We assume the specified client_encoding and
104+
* standard_conforming_strings settings.
104105
*
105-
* Special characters are escaped. Quote mark ' goes to '' per SQL
106-
* standard, other stuff goes to \ sequences. If escapeAll is false,
107-
* whitespace characters are not escaped (tabs, newlines, etc.). This
108-
* is appropriate for dump file output. Using E'' strings for
109-
* backslashes is always safe for standard_conforming_strings on or off.
106+
* This is essentially equivalent to libpq's PQescapeStringInternal,
107+
* except for the output buffer structure. We need it in situations
108+
* where we do not have a PGconn available. Where we do,
109+
* appendStringLiteralConn is a better choice.
110110
*/
111111
void
112-
appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll,
113-
bool e_string_for_backslash)
112+
appendStringLiteral(PQExpBuffer buf, const char *str,
113+
int encoding, bool std_strings)
114114
{
115-
char ch;
116-
const char *p;
117-
bool is_e_string = false;
115+
size_t length = strlen(str);
116+
const char *source = str;
117+
char *target;
118118

119-
for (p = str; *p; p++)
119+
if (!enlargePQExpBuffer(buf, 2 * length + 2))
120+
return;
121+
122+
target = buf->data + buf->len;
123+
*target++ = '\'';
124+
125+
while (*source != '\0')
120126
{
121-
ch = *p;
127+
char c = *source;
128+
int len;
129+
int i;
122130

123-
if ((e_string_for_backslash && ch == '\\') ||
124-
((unsigned char) ch < (unsigned char) ' ' &&
125-
(escapeAll ||
126-
(ch != '\t' && ch != '\n' && ch != '\v' &&
127-
ch != '\f' && ch != '\r'))))
131+
/* Fast path for plain ASCII */
132+
if (!IS_HIGHBIT_SET(c))
128133
{
129-
appendPQExpBufferChar(buf, ESCAPE_STRING_SYNTAX);
130-
is_e_string = true;
131-
break;
134+
/* Apply quoting if needed */
135+
if (SQL_STR_DOUBLE(c, !std_strings))
136+
*target++ = c;
137+
/* Copy the character */
138+
*target++ = c;
139+
source++;
140+
continue;
132141
}
133-
}
134142

135-
appendPQExpBufferChar(buf, '\'');
136-
for (p = str; *p; p++)
137-
{
138-
ch = *p;
139-
if (SQL_STR_DOUBLE(ch, is_e_string))
143+
/* Slow path for possible multibyte characters */
144+
len = PQmblen(source, encoding);
145+
146+
/* Copy the character */
147+
for (i = 0; i < len; i++)
140148
{
141-
appendPQExpBufferChar(buf, ch);
142-
appendPQExpBufferChar(buf, ch);
149+
if (*source == '\0')
150+
break;
151+
*target++ = *source++;
143152
}
144-
else if ((unsigned char) ch < (unsigned char) ' ' &&
145-
(escapeAll ||
146-
(ch != '\t' && ch != '\n' && ch != '\v' &&
147-
ch != '\f' && ch != '\r')))
153+
154+
/*
155+
* If we hit premature end of string (ie, incomplete multibyte
156+
* character), try to pad out to the correct length with spaces.
157+
* We may not be able to pad completely, but we will always be able
158+
* to insert at least one pad space (since we'd not have quoted a
159+
* multibyte character). This should be enough to make a string that
160+
* the server will error out on.
161+
*/
162+
if (i < len)
148163
{
149-
/*
150-
* generate octal escape for control chars other than whitespace
151-
*/
152-
appendPQExpBufferChar(buf, '\\');
153-
appendPQExpBufferChar(buf, ((ch >> 6) & 3) + '0');
154-
appendPQExpBufferChar(buf, ((ch >> 3) & 7) + '0');
155-
appendPQExpBufferChar(buf, (ch & 7) + '0');
164+
char *stop = buf->data + buf->maxlen - 2;
165+
166+
for (; i < len; i++)
167+
{
168+
if (target >= stop)
169+
break;
170+
*target++ = ' ';
171+
}
172+
break;
156173
}
157-
else
158-
appendPQExpBufferChar(buf, ch);
159174
}
175+
176+
/* Write the terminating quote and NUL character. */
177+
*target++ = '\'';
178+
*target = '\0';
179+
180+
buf->len = target - buf->data;
181+
}
182+
183+
184+
/*
185+
* Convert a string value to an SQL string literal and append it to
186+
* the given buffer. Encoding and string syntax rules are as indicated
187+
* by current settings of the PGconn.
188+
*/
189+
void
190+
appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)
191+
{
192+
size_t length = strlen(str);
193+
194+
if (!enlargePQExpBuffer(buf, 2 * length + 2))
195+
return;
196+
appendPQExpBufferChar(buf, '\'');
197+
buf->len += PQescapeStringConn(conn, buf->data + buf->len,
198+
str, length, NULL);
160199
appendPQExpBufferChar(buf, '\'');
161200
}
162201

@@ -167,7 +206,8 @@ appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll,
167206
* dollar quote delimiter will begin with that (after the opening $).
168207
*
169208
* No escaping is done at all on str, in compliance with the rules
170-
* for parsing dollar quoted strings.
209+
* for parsing dollar quoted strings. Also, we need not worry about
210+
* encoding issues.
171211
*/
172212
void
173213
appendStringLiteralDQ(PQExpBuffer buf, const char *str, const char *dqprefix)
@@ -204,21 +244,6 @@ appendStringLiteralDQ(PQExpBuffer buf, const char *str, const char *dqprefix)
204244
}
205245

206246

207-
/*
208-
* Use dollar quoting if the string to be quoted contains ' or \,
209-
* otherwise use standard quoting.
210-
*/
211-
void
212-
appendStringLiteralDQOpt(PQExpBuffer buf, const char *str,
213-
bool escapeAll, const char *dqprefix)
214-
{
215-
if (strchr(str, '\'') == NULL && strchr(str, '\\') == NULL)
216-
appendStringLiteral(buf, str, escapeAll, true);
217-
else
218-
appendStringLiteralDQ(buf, str, dqprefix);
219-
}
220-
221-
222247
/*
223248
* Convert backend's version string into a number.
224249
*/

src/bin/pg_dump/dumputils.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,24 @@
77
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.h,v 1.16 2006/05/26 23:48:54 momjian Exp $
10+
* $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.h,v 1.17 2006/05/28 21:13:54 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
1414

1515
#ifndef DUMPUTILS_H
1616
#define DUMPUTILS_H
1717

18+
#include "libpq-fe.h"
1819
#include "pqexpbuffer.h"
1920

2021
extern const char *fmtId(const char *identifier);
2122
extern void appendStringLiteral(PQExpBuffer buf, const char *str,
22-
bool escapeAll, bool e_string_for_backslash);
23+
int encoding, bool std_strings);
24+
extern void appendStringLiteralConn(PQExpBuffer buf, const char *str,
25+
PGconn *conn);
2326
extern void appendStringLiteralDQ(PQExpBuffer buf, const char *str,
2427
const char *dqprefix);
25-
extern void appendStringLiteralDQOpt(PQExpBuffer buf, const char *str,
26-
bool escapeAll, const char *dqprefix);
2728
extern int parse_version(const char *versionString);
2829
extern bool parsePGArray(const char *atext, char ***itemarray, int *nitems);
2930
extern bool buildACLCommands(const char *name, const char *type,

src/bin/pg_dump/pg_backup.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup.h,v 1.38 2006/02/12 04:04:32 momjian Exp $
18+
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup.h,v 1.39 2006/05/28 21:13:54 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -60,6 +60,10 @@ typedef struct _Archive
6060
int minRemoteVersion; /* allowable range */
6161
int maxRemoteVersion;
6262

63+
/* info needed for string escaping */
64+
int encoding; /* libpq code for client_encoding */
65+
bool std_strings; /* standard_conforming_strings */
66+
6367
/* error handling */
6468
bool exit_on_error; /* whether to exit on SQL errors... */
6569
int n_errors; /* number of errors (if no die) */
@@ -182,4 +186,7 @@ archprintf(Archive *AH, const char *fmt,...)
182186
/* This extension allows gcc to check the format string */
183187
__attribute__((format(printf, 2, 3)));
184188

189+
#define appendStringLiteralAH(buf,str,AH) \
190+
appendStringLiteral(buf, str, (AH)->encoding, (AH)->std_strings)
191+
185192
#endif /* PG_BACKUP_H */

0 commit comments

Comments
 (0)