Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * copy.c
4 : * Implements the COPY utility command
5 : *
6 : * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/commands/copy.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres.h"
16 :
17 : #include <ctype.h>
18 : #include <unistd.h>
19 : #include <sys/stat.h>
20 :
21 : #include "access/sysattr.h"
22 : #include "access/table.h"
23 : #include "access/xact.h"
24 : #include "catalog/pg_authid.h"
25 : #include "commands/copy.h"
26 : #include "commands/defrem.h"
27 : #include "executor/executor.h"
28 : #include "mb/pg_wchar.h"
29 : #include "miscadmin.h"
30 : #include "nodes/makefuncs.h"
31 : #include "optimizer/optimizer.h"
32 : #include "parser/parse_coerce.h"
33 : #include "parser/parse_collate.h"
34 : #include "parser/parse_expr.h"
35 : #include "parser/parse_relation.h"
36 : #include "utils/acl.h"
37 : #include "utils/builtins.h"
38 : #include "utils/lsyscache.h"
39 : #include "utils/rel.h"
40 : #include "utils/rls.h"
41 :
42 : /*
43 : * DoCopy executes the SQL COPY statement
44 : *
45 : * Either unload or reload contents of table <relation>, depending on <from>.
46 : * (<from> = true means we are inserting into the table.) In the "TO" case
47 : * we also support copying the output of an arbitrary SELECT, INSERT, UPDATE
48 : * or DELETE query.
49 : *
50 : * If <pipe> is false, transfer is between the table and the file named
51 : * <filename>. Otherwise, transfer is between the table and our regular
52 : * input/output stream. The latter could be either stdin/stdout or a
53 : * socket, depending on whether we're running under Postmaster control.
54 : *
55 : * Do not allow a Postgres user without the 'pg_read_server_files' or
56 : * 'pg_write_server_files' role to read from or write to a file.
57 : *
58 : * Do not allow the copy if user doesn't have proper permission to access
59 : * the table or the specifically requested columns.
60 : */
61 : void
62 9598 : DoCopy(ParseState *pstate, const CopyStmt *stmt,
63 : int stmt_location, int stmt_len,
64 : uint64 *processed)
65 : {
66 9598 : bool is_from = stmt->is_from;
67 9598 : bool pipe = (stmt->filename == NULL);
68 : Relation rel;
69 : Oid relid;
70 9598 : RawStmt *query = NULL;
71 9598 : Node *whereClause = NULL;
72 :
73 : /*
74 : * Disallow COPY to/from file or program except to users with the
75 : * appropriate role.
76 : */
77 9598 : if (!pipe)
78 : {
79 382 : if (stmt->is_program)
80 : {
81 0 : if (!has_privs_of_role(GetUserId(), ROLE_PG_EXECUTE_SERVER_PROGRAM))
82 0 : ereport(ERROR,
83 : (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
84 : errmsg("permission denied to COPY to or from an external program"),
85 : errdetail("Only roles with privileges of the \"%s\" role may COPY to or from an external program.",
86 : "pg_execute_server_program"),
87 : errhint("Anyone can COPY to stdout or from stdin. "
88 : "psql's \\copy command also works for anyone.")));
89 : }
90 : else
91 : {
92 382 : if (is_from && !has_privs_of_role(GetUserId(), ROLE_PG_READ_SERVER_FILES))
93 0 : ereport(ERROR,
94 : (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
95 : errmsg("permission denied to COPY from a file"),
96 : errdetail("Only roles with privileges of the \"%s\" role may COPY from a file.",
97 : "pg_read_server_files"),
98 : errhint("Anyone can COPY to stdout or from stdin. "
99 : "psql's \\copy command also works for anyone.")));
100 :
101 382 : if (!is_from && !has_privs_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES))
102 0 : ereport(ERROR,
103 : (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
104 : errmsg("permission denied to COPY to a file"),
105 : errdetail("Only roles with privileges of the \"%s\" role may COPY to a file.",
106 : "pg_write_server_files"),
107 : errhint("Anyone can COPY to stdout or from stdin. "
108 : "psql's \\copy command also works for anyone.")));
109 : }
110 : }
111 :
112 9598 : if (stmt->relation)
113 : {
114 9202 : LOCKMODE lockmode = is_from ? RowExclusiveLock : AccessShareLock;
115 : ParseNamespaceItem *nsitem;
116 : RTEPermissionInfo *perminfo;
117 : TupleDesc tupDesc;
118 : List *attnums;
119 : ListCell *cur;
120 :
121 : Assert(!stmt->query);
122 :
123 : /* Open and lock the relation, using the appropriate lock type. */
124 9202 : rel = table_openrv(stmt->relation, lockmode);
125 :
126 9200 : relid = RelationGetRelid(rel);
127 :
128 9200 : nsitem = addRangeTableEntryForRelation(pstate, rel, lockmode,
129 : NULL, false, false);
130 :
131 9200 : perminfo = nsitem->p_perminfo;
132 9200 : perminfo->requiredPerms = (is_from ? ACL_INSERT : ACL_SELECT);
133 :
134 9200 : if (stmt->whereClause)
135 : {
136 : /* add nsitem to query namespace */
137 48 : addNSItemToQuery(pstate, nsitem, false, true, true);
138 :
139 : /* Transform the raw expression tree */
140 48 : whereClause = transformExpr(pstate, stmt->whereClause, EXPR_KIND_COPY_WHERE);
141 :
142 : /* Make sure it yields a boolean result. */
143 18 : whereClause = coerce_to_boolean(pstate, whereClause, "WHERE");
144 :
145 : /* we have to fix its collations too */
146 18 : assign_expr_collations(pstate, whereClause);
147 :
148 18 : whereClause = eval_const_expressions(NULL, whereClause);
149 :
150 18 : whereClause = (Node *) canonicalize_qual((Expr *) whereClause, false);
151 18 : whereClause = (Node *) make_ands_implicit((Expr *) whereClause);
152 : }
153 :
154 9170 : tupDesc = RelationGetDescr(rel);
155 9170 : attnums = CopyGetAttnums(tupDesc, rel, stmt->attlist);
156 42750 : foreach(cur, attnums)
157 : {
158 : int attno;
159 : Bitmapset **bms;
160 :
161 33640 : attno = lfirst_int(cur) - FirstLowInvalidHeapAttributeNumber;
162 33640 : bms = is_from ? &perminfo->insertedCols : &perminfo->selectedCols;
163 :
164 33640 : *bms = bms_add_member(*bms, attno);
165 : }
166 9110 : ExecCheckPermissions(pstate->p_rtable, list_make1(perminfo), true);
167 :
168 : /*
169 : * Permission check for row security policies.
170 : *
171 : * check_enable_rls will ereport(ERROR) if the user has requested
172 : * something invalid and will otherwise indicate if we should enable
173 : * RLS (returns RLS_ENABLED) or not for this COPY statement.
174 : *
175 : * If the relation has a row security policy and we are to apply it
176 : * then perform a "query" copy and allow the normal query processing
177 : * to handle the policies.
178 : *
179 : * If RLS is not enabled for this, then just fall through to the
180 : * normal non-filtering relation handling.
181 : */
182 9026 : if (check_enable_rls(relid, InvalidOid, false) == RLS_ENABLED)
183 : {
184 : SelectStmt *select;
185 : ColumnRef *cr;
186 : ResTarget *target;
187 : RangeVar *from;
188 60 : List *targetList = NIL;
189 :
190 60 : if (is_from)
191 6 : ereport(ERROR,
192 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
193 : errmsg("COPY FROM not supported with row-level security"),
194 : errhint("Use INSERT statements instead.")));
195 :
196 : /*
197 : * Build target list
198 : *
199 : * If no columns are specified in the attribute list of the COPY
200 : * command, then the target list is 'all' columns. Therefore, '*'
201 : * should be used as the target list for the resulting SELECT
202 : * statement.
203 : *
204 : * In the case that columns are specified in the attribute list,
205 : * create a ColumnRef and ResTarget for each column and add them
206 : * to the target list for the resulting SELECT statement.
207 : */
208 54 : if (!stmt->attlist)
209 : {
210 18 : cr = makeNode(ColumnRef);
211 18 : cr->fields = list_make1(makeNode(A_Star));
212 18 : cr->location = -1;
213 :
214 18 : target = makeNode(ResTarget);
215 18 : target->name = NULL;
216 18 : target->indirection = NIL;
217 18 : target->val = (Node *) cr;
218 18 : target->location = -1;
219 :
220 18 : targetList = list_make1(target);
221 : }
222 : else
223 : {
224 : ListCell *lc;
225 :
226 102 : foreach(lc, stmt->attlist)
227 : {
228 : /*
229 : * Build the ColumnRef for each column. The ColumnRef
230 : * 'fields' property is a String node that corresponds to
231 : * the column name respectively.
232 : */
233 66 : cr = makeNode(ColumnRef);
234 66 : cr->fields = list_make1(lfirst(lc));
235 66 : cr->location = -1;
236 :
237 : /* Build the ResTarget and add the ColumnRef to it. */
238 66 : target = makeNode(ResTarget);
239 66 : target->name = NULL;
240 66 : target->indirection = NIL;
241 66 : target->val = (Node *) cr;
242 66 : target->location = -1;
243 :
244 : /* Add each column to the SELECT statement's target list */
245 66 : targetList = lappend(targetList, target);
246 : }
247 : }
248 :
249 : /*
250 : * Build RangeVar for from clause, fully qualified based on the
251 : * relation which we have opened and locked. Use "ONLY" so that
252 : * COPY retrieves rows from only the target table not any
253 : * inheritance children, the same as when RLS doesn't apply.
254 : */
255 54 : from = makeRangeVar(get_namespace_name(RelationGetNamespace(rel)),
256 54 : pstrdup(RelationGetRelationName(rel)),
257 : -1);
258 54 : from->inh = false; /* apply ONLY */
259 :
260 : /* Build query */
261 54 : select = makeNode(SelectStmt);
262 54 : select->targetList = targetList;
263 54 : select->fromClause = list_make1(from);
264 :
265 54 : query = makeNode(RawStmt);
266 54 : query->stmt = (Node *) select;
267 54 : query->stmt_location = stmt_location;
268 54 : query->stmt_len = stmt_len;
269 :
270 : /*
271 : * Close the relation for now, but keep the lock on it to prevent
272 : * changes between now and when we start the query-based COPY.
273 : *
274 : * We'll reopen it later as part of the query-based COPY.
275 : */
276 54 : table_close(rel, NoLock);
277 54 : rel = NULL;
278 : }
279 : }
280 : else
281 : {
282 : Assert(stmt->query);
283 :
284 396 : query = makeNode(RawStmt);
285 396 : query->stmt = stmt->query;
286 396 : query->stmt_location = stmt_location;
287 396 : query->stmt_len = stmt_len;
288 :
289 396 : relid = InvalidOid;
290 396 : rel = NULL;
291 : }
292 :
293 9398 : if (is_from)
294 : {
295 : CopyFromState cstate;
296 :
297 : Assert(rel);
298 :
299 : /* check read-only transaction and parallel mode */
300 1426 : if (XactReadOnly && !rel->rd_islocaltemp)
301 0 : PreventCommandIfReadOnly("COPY FROM");
302 :
303 1426 : cstate = BeginCopyFrom(pstate, rel, whereClause,
304 1426 : stmt->filename, stmt->is_program,
305 : NULL, stmt->attlist, stmt->options);
306 1246 : *processed = CopyFrom(cstate); /* copy from file to database */
307 1040 : EndCopyFrom(cstate);
308 : }
309 : else
310 : {
311 : CopyToState cstate;
312 :
313 7972 : cstate = BeginCopyTo(pstate, rel, query, relid,
314 7972 : stmt->filename, stmt->is_program,
315 : NULL, stmt->attlist, stmt->options);
316 7766 : *processed = DoCopyTo(cstate); /* copy from database to file */
317 7764 : EndCopyTo(cstate);
318 : }
319 :
320 8804 : if (rel != NULL)
321 8488 : table_close(rel, NoLock);
322 8804 : }
323 :
324 : /*
325 : * Extract a CopyHeaderChoice value from a DefElem. This is like
326 : * defGetBoolean() but also accepts the special value "match".
327 : */
328 : static CopyHeaderChoice
329 166 : defGetCopyHeaderChoice(DefElem *def, bool is_from)
330 : {
331 : /*
332 : * If no parameter value given, assume "true" is meant.
333 : */
334 166 : if (def->arg == NULL)
335 12 : return COPY_HEADER_TRUE;
336 :
337 : /*
338 : * Allow 0, 1, "true", "false", "on", "off", or "match".
339 : */
340 154 : switch (nodeTag(def->arg))
341 : {
342 0 : case T_Integer:
343 0 : switch (intVal(def->arg))
344 : {
345 0 : case 0:
346 0 : return COPY_HEADER_FALSE;
347 0 : case 1:
348 0 : return COPY_HEADER_TRUE;
349 0 : default:
350 : /* otherwise, error out below */
351 0 : break;
352 : }
353 0 : break;
354 154 : default:
355 : {
356 154 : char *sval = defGetString(def);
357 :
358 : /*
359 : * The set of strings accepted here should match up with the
360 : * grammar's opt_boolean_or_string production.
361 : */
362 154 : if (pg_strcasecmp(sval, "true") == 0)
363 56 : return COPY_HEADER_TRUE;
364 98 : if (pg_strcasecmp(sval, "false") == 0)
365 0 : return COPY_HEADER_FALSE;
366 98 : if (pg_strcasecmp(sval, "on") == 0)
367 0 : return COPY_HEADER_TRUE;
368 98 : if (pg_strcasecmp(sval, "off") == 0)
369 6 : return COPY_HEADER_FALSE;
370 92 : if (pg_strcasecmp(sval, "match") == 0)
371 : {
372 86 : if (!is_from)
373 6 : ereport(ERROR,
374 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
375 : errmsg("cannot use \"%s\" with HEADER in COPY TO",
376 : sval)));
377 80 : return COPY_HEADER_MATCH;
378 : }
379 : }
380 6 : break;
381 : }
382 6 : ereport(ERROR,
383 : (errcode(ERRCODE_SYNTAX_ERROR),
384 : errmsg("%s requires a Boolean value or \"match\"",
385 : def->defname)));
386 : return COPY_HEADER_FALSE; /* keep compiler quiet */
387 : }
388 :
389 : /*
390 : * Extract a CopyOnErrorChoice value from a DefElem.
391 : */
392 : static CopyOnErrorChoice
393 76 : defGetCopyOnErrorChoice(DefElem *def, ParseState *pstate, bool is_from)
394 : {
395 76 : char *sval = defGetString(def);
396 :
397 76 : if (!is_from)
398 6 : ereport(ERROR,
399 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
400 : /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
401 : second %s is a COPY with direction, e.g. COPY TO */
402 : errmsg("COPY %s cannot be used with %s", "ON_ERROR", "COPY TO"),
403 : parser_errposition(pstate, def->location)));
404 :
405 : /*
406 : * Allow "stop", or "ignore" values.
407 : */
408 70 : if (pg_strcasecmp(sval, "stop") == 0)
409 6 : return COPY_ON_ERROR_STOP;
410 64 : if (pg_strcasecmp(sval, "ignore") == 0)
411 58 : return COPY_ON_ERROR_IGNORE;
412 :
413 6 : ereport(ERROR,
414 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
415 : /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR */
416 : errmsg("COPY %s \"%s\" not recognized", "ON_ERROR", sval),
417 : parser_errposition(pstate, def->location)));
418 : return COPY_ON_ERROR_STOP; /* keep compiler quiet */
419 : }
420 :
421 : /*
422 : * Extract a CopyLogVerbosityChoice value from a DefElem.
423 : */
424 : static CopyLogVerbosityChoice
425 36 : defGetCopyLogVerbosityChoice(DefElem *def, ParseState *pstate)
426 : {
427 : char *sval;
428 :
429 : /*
430 : * Allow "silent", "default", or "verbose" values.
431 : */
432 36 : sval = defGetString(def);
433 36 : if (pg_strcasecmp(sval, "silent") == 0)
434 12 : return COPY_LOG_VERBOSITY_SILENT;
435 24 : if (pg_strcasecmp(sval, "default") == 0)
436 6 : return COPY_LOG_VERBOSITY_DEFAULT;
437 18 : if (pg_strcasecmp(sval, "verbose") == 0)
438 12 : return COPY_LOG_VERBOSITY_VERBOSE;
439 :
440 6 : ereport(ERROR,
441 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
442 : /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR */
443 : errmsg("COPY %s \"%s\" not recognized", "LOG_VERBOSITY", sval),
444 : parser_errposition(pstate, def->location)));
445 : return COPY_LOG_VERBOSITY_DEFAULT; /* keep compiler quiet */
446 : }
447 :
448 : /*
449 : * Process the statement option list for COPY.
450 : *
451 : * Scan the options list (a list of DefElem) and transpose the information
452 : * into *opts_out, applying appropriate error checking.
453 : *
454 : * If 'opts_out' is not NULL, it is assumed to be filled with zeroes initially.
455 : *
456 : * This is exported so that external users of the COPY API can sanity-check
457 : * a list of options. In that usage, 'opts_out' can be passed as NULL and
458 : * the collected data is just leaked until CurrentMemoryContext is reset.
459 : *
460 : * Note that additional checking, such as whether column names listed in FORCE
461 : * QUOTE actually exist, has to be applied later. This just checks for
462 : * self-consistency of the options list.
463 : */
464 : void
465 9886 : ProcessCopyOptions(ParseState *pstate,
466 : CopyFormatOptions *opts_out,
467 : bool is_from,
468 : List *options)
469 : {
470 9886 : bool format_specified = false;
471 9886 : bool freeze_specified = false;
472 9886 : bool header_specified = false;
473 9886 : bool on_error_specified = false;
474 9886 : bool log_verbosity_specified = false;
475 : ListCell *option;
476 :
477 : /* Support external use for option sanity checking */
478 9886 : if (opts_out == NULL)
479 90 : opts_out = (CopyFormatOptions *) palloc0(sizeof(CopyFormatOptions));
480 :
481 9886 : opts_out->file_encoding = -1;
482 :
483 : /* Extract options from the statement node tree */
484 11618 : foreach(option, options)
485 : {
486 1860 : DefElem *defel = lfirst_node(DefElem, option);
487 :
488 1860 : if (strcmp(defel->defname, "format") == 0)
489 : {
490 544 : char *fmt = defGetString(defel);
491 :
492 544 : if (format_specified)
493 6 : errorConflictingDefElem(defel, pstate);
494 538 : format_specified = true;
495 538 : if (strcmp(fmt, "text") == 0)
496 : /* default format */ ;
497 480 : else if (strcmp(fmt, "csv") == 0)
498 410 : opts_out->csv_mode = true;
499 70 : else if (strcmp(fmt, "binary") == 0)
500 68 : opts_out->binary = true;
501 : else
502 2 : ereport(ERROR,
503 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
504 : errmsg("COPY format \"%s\" not recognized", fmt),
505 : parser_errposition(pstate, defel->location)));
506 : }
507 1316 : else if (strcmp(defel->defname, "freeze") == 0)
508 : {
509 78 : if (freeze_specified)
510 6 : errorConflictingDefElem(defel, pstate);
511 72 : freeze_specified = true;
512 72 : opts_out->freeze = defGetBoolean(defel);
513 : }
514 1238 : else if (strcmp(defel->defname, "delimiter") == 0)
515 : {
516 278 : if (opts_out->delim)
517 6 : errorConflictingDefElem(defel, pstate);
518 272 : opts_out->delim = defGetString(defel);
519 : }
520 960 : else if (strcmp(defel->defname, "null") == 0)
521 : {
522 136 : if (opts_out->null_print)
523 6 : errorConflictingDefElem(defel, pstate);
524 130 : opts_out->null_print = defGetString(defel);
525 : }
526 824 : else if (strcmp(defel->defname, "default") == 0)
527 : {
528 90 : if (opts_out->default_print)
529 0 : errorConflictingDefElem(defel, pstate);
530 90 : opts_out->default_print = defGetString(defel);
531 : }
532 734 : else if (strcmp(defel->defname, "header") == 0)
533 : {
534 172 : if (header_specified)
535 6 : errorConflictingDefElem(defel, pstate);
536 166 : header_specified = true;
537 166 : opts_out->header_line = defGetCopyHeaderChoice(defel, is_from);
538 : }
539 562 : else if (strcmp(defel->defname, "quote") == 0)
540 : {
541 94 : if (opts_out->quote)
542 6 : errorConflictingDefElem(defel, pstate);
543 88 : opts_out->quote = defGetString(defel);
544 : }
545 468 : else if (strcmp(defel->defname, "escape") == 0)
546 : {
547 86 : if (opts_out->escape)
548 6 : errorConflictingDefElem(defel, pstate);
549 80 : opts_out->escape = defGetString(defel);
550 : }
551 382 : else if (strcmp(defel->defname, "force_quote") == 0)
552 : {
553 66 : if (opts_out->force_quote || opts_out->force_quote_all)
554 6 : errorConflictingDefElem(defel, pstate);
555 60 : if (defel->arg && IsA(defel->arg, A_Star))
556 18 : opts_out->force_quote_all = true;
557 42 : else if (defel->arg && IsA(defel->arg, List))
558 42 : opts_out->force_quote = castNode(List, defel->arg);
559 : else
560 0 : ereport(ERROR,
561 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
562 : errmsg("argument to option \"%s\" must be a list of column names",
563 : defel->defname),
564 : parser_errposition(pstate, defel->location)));
565 : }
566 316 : else if (strcmp(defel->defname, "force_not_null") == 0)
567 : {
568 76 : if (opts_out->force_notnull || opts_out->force_notnull_all)
569 12 : errorConflictingDefElem(defel, pstate);
570 64 : if (defel->arg && IsA(defel->arg, A_Star))
571 18 : opts_out->force_notnull_all = true;
572 46 : else if (defel->arg && IsA(defel->arg, List))
573 46 : opts_out->force_notnull = castNode(List, defel->arg);
574 : else
575 0 : ereport(ERROR,
576 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
577 : errmsg("argument to option \"%s\" must be a list of column names",
578 : defel->defname),
579 : parser_errposition(pstate, defel->location)));
580 : }
581 240 : else if (strcmp(defel->defname, "force_null") == 0)
582 : {
583 76 : if (opts_out->force_null || opts_out->force_null_all)
584 12 : errorConflictingDefElem(defel, pstate);
585 64 : if (defel->arg && IsA(defel->arg, A_Star))
586 18 : opts_out->force_null_all = true;
587 46 : else if (defel->arg && IsA(defel->arg, List))
588 46 : opts_out->force_null = castNode(List, defel->arg);
589 : else
590 0 : ereport(ERROR,
591 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
592 : errmsg("argument to option \"%s\" must be a list of column names",
593 : defel->defname),
594 : parser_errposition(pstate, defel->location)));
595 : }
596 164 : else if (strcmp(defel->defname, "convert_selectively") == 0)
597 : {
598 : /*
599 : * Undocumented, not-accessible-from-SQL option: convert only the
600 : * named columns to binary form, storing the rest as NULLs. It's
601 : * allowed for the column list to be NIL.
602 : */
603 16 : if (opts_out->convert_selectively)
604 6 : errorConflictingDefElem(defel, pstate);
605 10 : opts_out->convert_selectively = true;
606 10 : if (defel->arg == NULL || IsA(defel->arg, List))
607 10 : opts_out->convert_select = castNode(List, defel->arg);
608 : else
609 0 : ereport(ERROR,
610 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
611 : errmsg("argument to option \"%s\" must be a list of column names",
612 : defel->defname),
613 : parser_errposition(pstate, defel->location)));
614 : }
615 148 : else if (strcmp(defel->defname, "encoding") == 0)
616 : {
617 24 : if (opts_out->file_encoding >= 0)
618 6 : errorConflictingDefElem(defel, pstate);
619 18 : opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
620 18 : if (opts_out->file_encoding < 0)
621 0 : ereport(ERROR,
622 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
623 : errmsg("argument to option \"%s\" must be a valid encoding name",
624 : defel->defname),
625 : parser_errposition(pstate, defel->location)));
626 : }
627 124 : else if (strcmp(defel->defname, "on_error") == 0)
628 : {
629 82 : if (on_error_specified)
630 6 : errorConflictingDefElem(defel, pstate);
631 76 : on_error_specified = true;
632 76 : opts_out->on_error = defGetCopyOnErrorChoice(defel, pstate, is_from);
633 : }
634 42 : else if (strcmp(defel->defname, "log_verbosity") == 0)
635 : {
636 42 : if (log_verbosity_specified)
637 6 : errorConflictingDefElem(defel, pstate);
638 36 : log_verbosity_specified = true;
639 36 : opts_out->log_verbosity = defGetCopyLogVerbosityChoice(defel, pstate);
640 : }
641 : else
642 0 : ereport(ERROR,
643 : (errcode(ERRCODE_SYNTAX_ERROR),
644 : errmsg("option \"%s\" not recognized",
645 : defel->defname),
646 : parser_errposition(pstate, defel->location)));
647 : }
648 :
649 : /*
650 : * Check for incompatible options (must do these two before inserting
651 : * defaults)
652 : */
653 9758 : if (opts_out->binary && opts_out->delim)
654 6 : ereport(ERROR,
655 : (errcode(ERRCODE_SYNTAX_ERROR),
656 : /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
657 : errmsg("cannot specify %s in BINARY mode", "DELIMITER")));
658 :
659 9752 : if (opts_out->binary && opts_out->null_print)
660 6 : ereport(ERROR,
661 : (errcode(ERRCODE_SYNTAX_ERROR),
662 : errmsg("cannot specify %s in BINARY mode", "NULL")));
663 :
664 9746 : if (opts_out->binary && opts_out->default_print)
665 6 : ereport(ERROR,
666 : (errcode(ERRCODE_SYNTAX_ERROR),
667 : errmsg("cannot specify %s in BINARY mode", "DEFAULT")));
668 :
669 9740 : if (opts_out->binary && opts_out->on_error != COPY_ON_ERROR_STOP)
670 6 : ereport(ERROR,
671 : (errcode(ERRCODE_SYNTAX_ERROR),
672 : errmsg("only ON_ERROR STOP is allowed in BINARY mode")));
673 :
674 : /* Set defaults for omitted options */
675 9734 : if (!opts_out->delim)
676 9474 : opts_out->delim = opts_out->csv_mode ? "," : "\t";
677 :
678 9734 : if (!opts_out->null_print)
679 9616 : opts_out->null_print = opts_out->csv_mode ? "" : "\\N";
680 9734 : opts_out->null_print_len = strlen(opts_out->null_print);
681 :
682 9734 : if (opts_out->csv_mode)
683 : {
684 392 : if (!opts_out->quote)
685 314 : opts_out->quote = "\"";
686 392 : if (!opts_out->escape)
687 324 : opts_out->escape = opts_out->quote;
688 : }
689 :
690 : /* Only single-byte delimiter strings are supported. */
691 9734 : if (strlen(opts_out->delim) != 1)
692 2 : ereport(ERROR,
693 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
694 : errmsg("COPY delimiter must be a single one-byte character")));
695 :
696 : /* Disallow end-of-line characters */
697 9732 : if (strchr(opts_out->delim, '\r') != NULL ||
698 9732 : strchr(opts_out->delim, '\n') != NULL)
699 2 : ereport(ERROR,
700 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
701 : errmsg("COPY delimiter cannot be newline or carriage return")));
702 :
703 9730 : if (strchr(opts_out->null_print, '\r') != NULL ||
704 9730 : strchr(opts_out->null_print, '\n') != NULL)
705 2 : ereport(ERROR,
706 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
707 : errmsg("COPY null representation cannot use newline or carriage return")));
708 :
709 9728 : if (opts_out->default_print)
710 : {
711 84 : opts_out->default_print_len = strlen(opts_out->default_print);
712 :
713 84 : if (strchr(opts_out->default_print, '\r') != NULL ||
714 78 : strchr(opts_out->default_print, '\n') != NULL)
715 12 : ereport(ERROR,
716 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
717 : errmsg("COPY default representation cannot use newline or carriage return")));
718 : }
719 :
720 : /*
721 : * Disallow unsafe delimiter characters in non-CSV mode. We can't allow
722 : * backslash because it would be ambiguous. We can't allow the other
723 : * cases because data characters matching the delimiter must be
724 : * backslashed, and certain backslash combinations are interpreted
725 : * non-literally by COPY IN. Disallowing all lower case ASCII letters is
726 : * more than strictly necessary, but seems best for consistency and
727 : * future-proofing. Likewise we disallow all digits though only octal
728 : * digits are actually dangerous.
729 : */
730 9716 : if (!opts_out->csv_mode &&
731 9330 : strchr("\\.abcdefghijklmnopqrstuvwxyz0123456789",
732 9330 : opts_out->delim[0]) != NULL)
733 10 : ereport(ERROR,
734 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
735 : errmsg("COPY delimiter cannot be \"%s\"", opts_out->delim)));
736 :
737 : /* Check header */
738 9706 : if (opts_out->binary && opts_out->header_line)
739 2 : ereport(ERROR,
740 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
741 : /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
742 : errmsg("cannot specify %s in BINARY mode", "HEADER")));
743 :
744 : /* Check quote */
745 9704 : if (!opts_out->csv_mode && opts_out->quote != NULL)
746 4 : ereport(ERROR,
747 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
748 : /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
749 : errmsg("COPY %s requires CSV mode", "QUOTE")));
750 :
751 9700 : if (opts_out->csv_mode && strlen(opts_out->quote) != 1)
752 2 : ereport(ERROR,
753 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
754 : errmsg("COPY quote must be a single one-byte character")));
755 :
756 9698 : if (opts_out->csv_mode && opts_out->delim[0] == opts_out->quote[0])
757 2 : ereport(ERROR,
758 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
759 : errmsg("COPY delimiter and quote must be different")));
760 :
761 : /* Check escape */
762 9696 : if (!opts_out->csv_mode && opts_out->escape != NULL)
763 6 : ereport(ERROR,
764 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
765 : /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
766 : errmsg("COPY %s requires CSV mode", "ESCAPE")));
767 :
768 9690 : if (opts_out->csv_mode && strlen(opts_out->escape) != 1)
769 2 : ereport(ERROR,
770 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
771 : errmsg("COPY escape must be a single one-byte character")));
772 :
773 : /* Check force_quote */
774 9688 : if (!opts_out->csv_mode && (opts_out->force_quote || opts_out->force_quote_all))
775 6 : ereport(ERROR,
776 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
777 : /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
778 : errmsg("COPY %s requires CSV mode", "FORCE_QUOTE")));
779 9682 : if ((opts_out->force_quote || opts_out->force_quote_all) && is_from)
780 6 : ereport(ERROR,
781 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
782 : /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
783 : second %s is a COPY with direction, e.g. COPY TO */
784 : errmsg("COPY %s cannot be used with %s", "FORCE_QUOTE",
785 : "COPY FROM")));
786 :
787 : /* Check force_notnull */
788 9676 : if (!opts_out->csv_mode && opts_out->force_notnull != NIL)
789 8 : ereport(ERROR,
790 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
791 : /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
792 : errmsg("COPY %s requires CSV mode", "FORCE_NOT_NULL")));
793 9668 : if (opts_out->force_notnull != NIL && !is_from)
794 6 : ereport(ERROR,
795 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
796 : /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
797 : second %s is a COPY with direction, e.g. COPY TO */
798 : errmsg("COPY %s cannot be used with %s", "FORCE_NOT_NULL",
799 : "COPY TO")));
800 :
801 : /* Check force_null */
802 9662 : if (!opts_out->csv_mode && opts_out->force_null != NIL)
803 6 : ereport(ERROR,
804 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
805 : /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
806 : errmsg("COPY %s requires CSV mode", "FORCE_NULL")));
807 :
808 9656 : if (opts_out->force_null != NIL && !is_from)
809 6 : ereport(ERROR,
810 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
811 : /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
812 : second %s is a COPY with direction, e.g. COPY TO */
813 : errmsg("COPY %s cannot be used with %s", "FORCE_NULL",
814 : "COPY TO")));
815 :
816 : /* Don't allow the delimiter to appear in the null string. */
817 9650 : if (strchr(opts_out->null_print, opts_out->delim[0]) != NULL)
818 2 : ereport(ERROR,
819 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
820 : /*- translator: %s is the name of a COPY option, e.g. NULL */
821 : errmsg("COPY delimiter character must not appear in the %s specification",
822 : "NULL")));
823 :
824 : /* Don't allow the CSV quote char to appear in the null string. */
825 9648 : if (opts_out->csv_mode &&
826 360 : strchr(opts_out->null_print, opts_out->quote[0]) != NULL)
827 2 : ereport(ERROR,
828 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
829 : /*- translator: %s is the name of a COPY option, e.g. NULL */
830 : errmsg("CSV quote character must not appear in the %s specification",
831 : "NULL")));
832 :
833 : /* Check freeze */
834 9646 : if (opts_out->freeze && !is_from)
835 0 : ereport(ERROR,
836 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
837 : /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
838 : second %s is a COPY with direction, e.g. COPY TO */
839 : errmsg("COPY %s cannot be used with %s", "FREEZE",
840 : "COPY TO")));
841 :
842 9646 : if (opts_out->default_print)
843 : {
844 72 : if (!is_from)
845 6 : ereport(ERROR,
846 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
847 : /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
848 : second %s is a COPY with direction, e.g. COPY TO */
849 : errmsg("COPY %s cannot be used with %s", "DEFAULT",
850 : "COPY TO")));
851 :
852 : /* Don't allow the delimiter to appear in the default string. */
853 66 : if (strchr(opts_out->default_print, opts_out->delim[0]) != NULL)
854 6 : ereport(ERROR,
855 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
856 : /*- translator: %s is the name of a COPY option, e.g. NULL */
857 : errmsg("COPY delimiter character must not appear in the %s specification",
858 : "DEFAULT")));
859 :
860 : /* Don't allow the CSV quote char to appear in the default string. */
861 60 : if (opts_out->csv_mode &&
862 30 : strchr(opts_out->default_print, opts_out->quote[0]) != NULL)
863 6 : ereport(ERROR,
864 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
865 : /*- translator: %s is the name of a COPY option, e.g. NULL */
866 : errmsg("CSV quote character must not appear in the %s specification",
867 : "DEFAULT")));
868 :
869 : /* Don't allow the NULL and DEFAULT string to be the same */
870 54 : if (opts_out->null_print_len == opts_out->default_print_len &&
871 24 : strncmp(opts_out->null_print, opts_out->default_print,
872 24 : opts_out->null_print_len) == 0)
873 6 : ereport(ERROR,
874 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
875 : errmsg("NULL specification and DEFAULT specification cannot be the same")));
876 : }
877 9622 : }
878 :
879 : /*
880 : * CopyGetAttnums - build an integer list of attnums to be copied
881 : *
882 : * The input attnamelist is either the user-specified column list,
883 : * or NIL if there was none (in which case we want all the non-dropped
884 : * columns).
885 : *
886 : * We don't include generated columns in the generated full list and we don't
887 : * allow them to be specified explicitly. They don't make sense for COPY
888 : * FROM, but we could possibly allow them for COPY TO. But this way it's at
889 : * least ensured that whatever we copy out can be copied back in.
890 : *
891 : * rel can be NULL ... it's only used for error reports.
892 : */
893 : List *
894 18694 : CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
895 : {
896 18694 : List *attnums = NIL;
897 :
898 18694 : if (attnamelist == NIL)
899 : {
900 : /* Generate default column list */
901 3340 : int attr_count = tupDesc->natts;
902 : int i;
903 :
904 11428 : for (i = 0; i < attr_count; i++)
905 : {
906 8088 : if (TupleDescAttr(tupDesc, i)->attisdropped)
907 196 : continue;
908 7892 : if (TupleDescAttr(tupDesc, i)->attgenerated)
909 54 : continue;
910 7838 : attnums = lappend_int(attnums, i + 1);
911 : }
912 : }
913 : else
914 : {
915 : /* Validate the user-supplied list and extract attnums */
916 : ListCell *l;
917 :
918 74820 : foreach(l, attnamelist)
919 : {
920 59526 : char *name = strVal(lfirst(l));
921 : int attnum;
922 : int i;
923 :
924 : /* Lookup column name */
925 59526 : attnum = InvalidAttrNumber;
926 9914128 : for (i = 0; i < tupDesc->natts; i++)
927 : {
928 9914098 : Form_pg_attribute att = TupleDescAttr(tupDesc, i);
929 :
930 9914098 : if (att->attisdropped)
931 760 : continue;
932 9913338 : if (namestrcmp(&(att->attname), name) == 0)
933 : {
934 59496 : if (att->attgenerated)
935 24 : ereport(ERROR,
936 : (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
937 : errmsg("column \"%s\" is a generated column",
938 : name),
939 : errdetail("Generated columns cannot be used in COPY.")));
940 59472 : attnum = att->attnum;
941 59472 : break;
942 : }
943 : }
944 59502 : if (attnum == InvalidAttrNumber)
945 : {
946 30 : if (rel != NULL)
947 30 : ereport(ERROR,
948 : (errcode(ERRCODE_UNDEFINED_COLUMN),
949 : errmsg("column \"%s\" of relation \"%s\" does not exist",
950 : name, RelationGetRelationName(rel))));
951 : else
952 0 : ereport(ERROR,
953 : (errcode(ERRCODE_UNDEFINED_COLUMN),
954 : errmsg("column \"%s\" does not exist",
955 : name)));
956 : }
957 : /* Check for duplicates */
958 59472 : if (list_member_int(attnums, attnum))
959 6 : ereport(ERROR,
960 : (errcode(ERRCODE_DUPLICATE_COLUMN),
961 : errmsg("column \"%s\" specified more than once",
962 : name)));
963 59466 : attnums = lappend_int(attnums, attnum);
964 : }
965 : }
966 :
967 18634 : return attnums;
968 : }
|