7
7
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
8
8
* Portions Copyright (c) 1994, Regents of the University of California
9
9
*
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 $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -100,63 +100,102 @@ fmtId(const char *rawid)
100
100
101
101
/*
102
102
* 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.
104
105
*
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.
110
110
*/
111
111
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 )
114
114
{
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 ;
118
118
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' )
120
126
{
121
- ch = * p ;
127
+ char c = * source ;
128
+ int len ;
129
+ int i ;
122
130
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 ))
128
133
{
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 ;
132
141
}
133
- }
134
142
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 ++ )
140
148
{
141
- appendPQExpBufferChar (buf , ch );
142
- appendPQExpBufferChar (buf , ch );
149
+ if (* source == '\0' )
150
+ break ;
151
+ * target ++ = * source ++ ;
143
152
}
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 )
148
163
{
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 ;
156
173
}
157
- else
158
- appendPQExpBufferChar (buf , ch );
159
174
}
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 );
160
199
appendPQExpBufferChar (buf , '\'' );
161
200
}
162
201
@@ -167,7 +206,8 @@ appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll,
167
206
* dollar quote delimiter will begin with that (after the opening $).
168
207
*
169
208
* 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.
171
211
*/
172
212
void
173
213
appendStringLiteralDQ (PQExpBuffer buf , const char * str , const char * dqprefix )
@@ -204,21 +244,6 @@ appendStringLiteralDQ(PQExpBuffer buf, const char *str, const char *dqprefix)
204
244
}
205
245
206
246
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
-
222
247
/*
223
248
* Convert backend's version string into a number.
224
249
*/
0 commit comments