Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit87e8014

Browse files
committed
Respond to Jeremy Drake's original gripe that \copy needs to recognize
E'...' syntax for strings in order to track the backend.
1 parent6178762 commit87e8014

File tree

3 files changed

+75
-78
lines changed

3 files changed

+75
-78
lines changed

‎src/bin/psql/copy.c

Lines changed: 52 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.63 2006/06/0100:15:36 tgl Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.64 2006/06/0101:28:00 tgl Exp $
77
*/
88
#include"postgres_fe.h"
99
#include"copy.h"
@@ -127,23 +127,23 @@ parse_slash_copy(const char *args)
127127
result=pg_calloc(1,sizeof(structcopy_options));
128128

129129
token=strtokx(line,whitespace,".,()","\"",
130-
0, false,pset.encoding);
130+
0, false,false,pset.encoding);
131131
if (!token)
132132
gotoerror;
133133

134134
if (pg_strcasecmp(token,"binary")==0)
135135
{
136136
result->binary= true;
137137
token=strtokx(NULL,whitespace,".,()","\"",
138-
0, false,pset.encoding);
138+
0, false,false,pset.encoding);
139139
if (!token)
140140
gotoerror;
141141
}
142142

143143
result->table=pg_strdup(token);
144144

145145
token=strtokx(NULL,whitespace,".,()","\"",
146-
0, false,pset.encoding);
146+
0, false,false,pset.encoding);
147147
if (!token)
148148
gotoerror;
149149

@@ -156,12 +156,12 @@ parse_slash_copy(const char *args)
156156
/* handle schema . table */
157157
xstrcat(&result->table,token);
158158
token=strtokx(NULL,whitespace,".,()","\"",
159-
0, false,pset.encoding);
159+
0, false,false,pset.encoding);
160160
if (!token)
161161
gotoerror;
162162
xstrcat(&result->table,token);
163163
token=strtokx(NULL,whitespace,".,()","\"",
164-
0, false,pset.encoding);
164+
0, false,false,pset.encoding);
165165
if (!token)
166166
gotoerror;
167167
}
@@ -173,12 +173,12 @@ parse_slash_copy(const char *args)
173173
for (;;)
174174
{
175175
token=strtokx(NULL,whitespace,".,()","\"",
176-
0, false,pset.encoding);
176+
0, false,false,pset.encoding);
177177
if (!token||strchr(".,()",token[0]))
178178
gotoerror;
179179
xstrcat(&result->column_list,token);
180180
token=strtokx(NULL,whitespace,".,()","\"",
181-
0, false,pset.encoding);
181+
0, false,false,pset.encoding);
182182
if (!token)
183183
gotoerror;
184184
xstrcat(&result->column_list,token);
@@ -188,7 +188,7 @@ parse_slash_copy(const char *args)
188188
gotoerror;
189189
}
190190
token=strtokx(NULL,whitespace,".,()","\"",
191-
0, false,pset.encoding);
191+
0, false,false,pset.encoding);
192192
if (!token)
193193
gotoerror;
194194
}
@@ -199,13 +199,13 @@ parse_slash_copy(const char *args)
199199
if (pg_strcasecmp(token,"with")==0)
200200
{
201201
token=strtokx(NULL,whitespace,NULL,NULL,
202-
0, false,pset.encoding);
202+
0, false,false,pset.encoding);
203203
if (!token||pg_strcasecmp(token,"oids")!=0)
204204
gotoerror;
205205
result->oids= true;
206206

207207
token=strtokx(NULL,whitespace,NULL,NULL,
208-
0, false,pset.encoding);
208+
0, false,false,pset.encoding);
209209
if (!token)
210210
gotoerror;
211211
}
@@ -218,7 +218,7 @@ parse_slash_copy(const char *args)
218218
gotoerror;
219219

220220
token=strtokx(NULL,whitespace,NULL,"'",
221-
nonstd_backslash, true,pset.encoding);
221+
0, false, true,pset.encoding);
222222
if (!token)
223223
gotoerror;
224224

@@ -242,27 +242,27 @@ parse_slash_copy(const char *args)
242242
}
243243

244244
token=strtokx(NULL,whitespace,NULL,NULL,
245-
0, false,pset.encoding);
245+
0, false,false,pset.encoding);
246246

247247
/*
248248
* Allows old COPY syntax for backward compatibility 2002-06-19
249249
*/
250250
if (token&&pg_strcasecmp(token,"using")==0)
251251
{
252252
token=strtokx(NULL,whitespace,NULL,NULL,
253-
0, false,pset.encoding);
253+
0, false,false,pset.encoding);
254254
if (!(token&&pg_strcasecmp(token,"delimiters")==0))
255255
gotoerror;
256256
}
257257
if (token&&pg_strcasecmp(token,"delimiters")==0)
258258
{
259259
token=strtokx(NULL,whitespace,NULL,"'",
260-
nonstd_backslash, false,pset.encoding);
260+
nonstd_backslash,true,false,pset.encoding);
261261
if (!token)
262262
gotoerror;
263263
result->delim=pg_strdup(token);
264264
token=strtokx(NULL,whitespace,NULL,NULL,
265-
0, false,pset.encoding);
265+
0, false,false,pset.encoding);
266266
}
267267

268268
if (token)
@@ -273,7 +273,7 @@ parse_slash_copy(const char *args)
273273
*/
274274
if (pg_strcasecmp(token,"with")==0)
275275
token=strtokx(NULL,whitespace,NULL,NULL,
276-
0, false,pset.encoding);
276+
0, false,false,pset.encoding);
277277

278278
while (token)
279279
{
@@ -292,10 +292,10 @@ parse_slash_copy(const char *args)
292292
elseif (pg_strcasecmp(token,"delimiter")==0)
293293
{
294294
token=strtokx(NULL,whitespace,NULL,"'",
295-
nonstd_backslash, false,pset.encoding);
295+
nonstd_backslash,true,false,pset.encoding);
296296
if (token&&pg_strcasecmp(token,"as")==0)
297297
token=strtokx(NULL,whitespace,NULL,"'",
298-
nonstd_backslash, false,pset.encoding);
298+
nonstd_backslash,true,false,pset.encoding);
299299
if (token)
300300
result->delim=pg_strdup(token);
301301
else
@@ -304,10 +304,10 @@ parse_slash_copy(const char *args)
304304
elseif (pg_strcasecmp(token,"null")==0)
305305
{
306306
token=strtokx(NULL,whitespace,NULL,"'",
307-
nonstd_backslash, false,pset.encoding);
307+
nonstd_backslash,true,false,pset.encoding);
308308
if (token&&pg_strcasecmp(token,"as")==0)
309309
token=strtokx(NULL,whitespace,NULL,"'",
310-
nonstd_backslash, false,pset.encoding);
310+
nonstd_backslash,true,false,pset.encoding);
311311
if (token)
312312
result->null=pg_strdup(token);
313313
else
@@ -316,10 +316,10 @@ parse_slash_copy(const char *args)
316316
elseif (pg_strcasecmp(token,"quote")==0)
317317
{
318318
token=strtokx(NULL,whitespace,NULL,"'",
319-
nonstd_backslash, false,pset.encoding);
319+
nonstd_backslash,true,false,pset.encoding);
320320
if (token&&pg_strcasecmp(token,"as")==0)
321321
token=strtokx(NULL,whitespace,NULL,"'",
322-
nonstd_backslash, false,pset.encoding);
322+
nonstd_backslash,true,false,pset.encoding);
323323
if (token)
324324
result->quote=pg_strdup(token);
325325
else
@@ -328,10 +328,10 @@ parse_slash_copy(const char *args)
328328
elseif (pg_strcasecmp(token,"escape")==0)
329329
{
330330
token=strtokx(NULL,whitespace,NULL,"'",
331-
nonstd_backslash, false,pset.encoding);
331+
nonstd_backslash,true,false,pset.encoding);
332332
if (token&&pg_strcasecmp(token,"as")==0)
333333
token=strtokx(NULL,whitespace,NULL,"'",
334-
nonstd_backslash, false,pset.encoding);
334+
nonstd_backslash,true,false,pset.encoding);
335335
if (token)
336336
result->escape=pg_strdup(token);
337337
else
@@ -340,23 +340,23 @@ parse_slash_copy(const char *args)
340340
elseif (pg_strcasecmp(token,"force")==0)
341341
{
342342
token=strtokx(NULL,whitespace,",","\"",
343-
0, false,pset.encoding);
343+
0, false,false,pset.encoding);
344344
if (pg_strcasecmp(token,"quote")==0)
345345
{
346346
/* handle column list */
347347
fetch_next= false;
348348
for (;;)
349349
{
350350
token=strtokx(NULL,whitespace,",","\"",
351-
0, false,pset.encoding);
351+
0, false,false,pset.encoding);
352352
if (!token||strchr(",",token[0]))
353353
gotoerror;
354354
if (!result->force_quote_list)
355355
result->force_quote_list=pg_strdup(token);
356356
else
357357
xstrcat(&result->force_quote_list,token);
358358
token=strtokx(NULL,whitespace,",","\"",
359-
0, false,pset.encoding);
359+
0, false,false,pset.encoding);
360360
if (!token||token[0]!=',')
361361
break;
362362
xstrcat(&result->force_quote_list,token);
@@ -365,23 +365,23 @@ parse_slash_copy(const char *args)
365365
elseif (pg_strcasecmp(token,"not")==0)
366366
{
367367
token=strtokx(NULL,whitespace,",","\"",
368-
0, false,pset.encoding);
368+
0, false,false,pset.encoding);
369369
if (pg_strcasecmp(token,"null")!=0)
370370
gotoerror;
371371
/* handle column list */
372372
fetch_next= false;
373373
for (;;)
374374
{
375375
token=strtokx(NULL,whitespace,",","\"",
376-
0, false,pset.encoding);
376+
0, false,false,pset.encoding);
377377
if (!token||strchr(",",token[0]))
378378
gotoerror;
379379
if (!result->force_notnull_list)
380380
result->force_notnull_list=pg_strdup(token);
381381
else
382382
xstrcat(&result->force_notnull_list,token);
383383
token=strtokx(NULL,whitespace,",","\"",
384-
0, false,pset.encoding);
384+
0, false,false,pset.encoding);
385385
if (!token||token[0]!=',')
386386
break;
387387
xstrcat(&result->force_notnull_list,token);
@@ -395,7 +395,7 @@ parse_slash_copy(const char *args)
395395

396396
if (fetch_next)
397397
token=strtokx(NULL,whitespace,NULL,NULL,
398-
0, false,pset.encoding);
398+
0, false,false,pset.encoding);
399399
}
400400
}
401401

@@ -415,6 +415,22 @@ parse_slash_copy(const char *args)
415415
}
416416

417417

418+
/*
419+
* Handle one of the "string" options of COPY. If the user gave a quoted
420+
* string, pass it to the backend as-is; if it wasn't quoted then quote
421+
* and escape it.
422+
*/
423+
staticvoid
424+
emit_copy_option(PQExpBufferquery,constchar*keyword,constchar*option)
425+
{
426+
appendPQExpBufferStr(query,keyword);
427+
if (option[0]=='\''||
428+
((option[0]=='E'||option[0]=='e')&&option[1]=='\''))
429+
appendPQExpBufferStr(query,option);
430+
else
431+
appendStringLiteralConn(query,option,pset.db);
432+
}
433+
418434

419435
/*
420436
* Execute a \copy command (frontend copy). We have to open a file, then
@@ -462,29 +478,11 @@ do_copy(const char *args)
462478

463479
/* Uses old COPY syntax for backward compatibility 2002-06-19 */
464480
if (options->delim)
465-
{
466-
/* if user gave a quoted string, use it as-is */
467-
if (options->delim[0]=='\'')
468-
appendPQExpBuffer(&query," USING DELIMITERS %s",options->delim);
469-
else
470-
{
471-
appendPQExpBuffer(&query," USING DELIMITERS ");
472-
appendStringLiteralConn(&query,options->delim,pset.db);
473-
}
474-
}
481+
emit_copy_option(&query," USING DELIMITERS ",options->delim);
475482

476483
/* There is no backward-compatible CSV syntax */
477484
if (options->null)
478-
{
479-
/* if user gave a quoted string, use it as-is */
480-
if (options->null[0]=='\'')
481-
appendPQExpBuffer(&query," WITH NULL AS %s",options->null);
482-
else
483-
{
484-
appendPQExpBuffer(&query," WITH NULL AS ");
485-
appendStringLiteralConn(&query,options->null,pset.db);
486-
}
487-
}
485+
emit_copy_option(&query," WITH NULL AS ",options->null);
488486

489487
if (options->csv_mode)
490488
appendPQExpBuffer(&query," CSV");
@@ -493,28 +491,10 @@ do_copy(const char *args)
493491
appendPQExpBuffer(&query," HEADER");
494492

495493
if (options->quote)
496-
{
497-
/* if user gave a quoted string, use it as-is */
498-
if (options->quote[0]=='\'')
499-
appendPQExpBuffer(&query," QUOTE AS %s",options->quote);
500-
else
501-
{
502-
appendPQExpBuffer(&query," QUOTE AS ");
503-
appendStringLiteralConn(&query,options->quote,pset.db);
504-
}
505-
}
494+
emit_copy_option(&query," QUOTE AS ",options->quote);
506495

507496
if (options->escape)
508-
{
509-
/* if user gave a quoted string, use it as-is */
510-
if (options->escape[0]=='\'')
511-
appendPQExpBuffer(&query," ESCAPE AS %s",options->escape);
512-
else
513-
{
514-
appendPQExpBuffer(&query," ESCAPE AS ");
515-
appendStringLiteralConn(&query,options->escape,pset.db);
516-
}
517-
}
497+
emit_copy_option(&query," ESCAPE AS ",options->escape);
518498

519499
if (options->force_quote_list)
520500
appendPQExpBuffer(&query," FORCE QUOTE %s",options->force_quote_list);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp