Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * copy.c
4 : * Implements the COPY utility command
5 : *
6 : * Portions Copyright (c) 1996-2025, 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 11314 : DoCopy(ParseState *pstate, const CopyStmt *stmt,
63 : int stmt_location, int stmt_len,
64 : uint64 *processed)
65 : {
66 11314 : bool is_from = stmt->is_from;
67 11314 : bool pipe = (stmt->filename == NULL);
68 : Relation rel;
69 : Oid relid;
70 11314 : RawStmt *query = NULL;
71 11314 : Node *whereClause = NULL;
72 :
73 : /*
74 : * Disallow COPY to/from file or program except to users with the
75 : * appropriate role.
76 : */
77 11314 : if (!pipe)
78 : {
79 446 : 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 446 : 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 446 : 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 11314 : if (stmt->relation)
113 : {
114 10712 : 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 10712 : rel = table_openrv(stmt->relation, lockmode);
125 :
126 10710 : relid = RelationGetRelid(rel);
127 :
128 10710 : nsitem = addRangeTableEntryForRelation(pstate, rel, lockmode,
129 : NULL, false, false);
130 :
131 10710 : perminfo = nsitem->p_perminfo;
132 10710 : perminfo->requiredPerms = (is_from ? ACL_INSERT : ACL_SELECT);
133 :
134 10710 : if (stmt->whereClause)
135 : {
136 72 : Bitmapset *expr_attrs = NULL;
137 : int i;
138 :
139 : /* add nsitem to query namespace */
140 72 : addNSItemToQuery(pstate, nsitem, false, true, true);
141 :
142 : /* Transform the raw expression tree */
143 72 : whereClause = transformExpr(pstate, stmt->whereClause, EXPR_KIND_COPY_WHERE);
144 :
145 : /* Make sure it yields a boolean result. */
146 42 : whereClause = coerce_to_boolean(pstate, whereClause, "WHERE");
147 :
148 : /* we have to fix its collations too */
149 42 : assign_expr_collations(pstate, whereClause);
150 :
151 : /*
152 : * Examine all the columns in the WHERE clause expression. When
153 : * the whole-row reference is present, examine all the columns of
154 : * the table.
155 : */
156 42 : pull_varattnos(whereClause, 1, &expr_attrs);
157 42 : if (bms_is_member(0 - FirstLowInvalidHeapAttributeNumber, expr_attrs))
158 : {
159 24 : expr_attrs = bms_add_range(expr_attrs,
160 : 1 - FirstLowInvalidHeapAttributeNumber,
161 12 : RelationGetNumberOfAttributes(rel) - FirstLowInvalidHeapAttributeNumber);
162 12 : expr_attrs = bms_del_member(expr_attrs, 0 - FirstLowInvalidHeapAttributeNumber);
163 : }
164 :
165 42 : i = -1;
166 72 : while ((i = bms_next_member(expr_attrs, i)) >= 0)
167 : {
168 54 : AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber;
169 :
170 : Assert(attno != 0);
171 :
172 : /*
173 : * Prohibit generated columns in the WHERE clause. Stored
174 : * generated columns are not yet computed when the filtering
175 : * happens. Virtual generated columns could probably work (we
176 : * would need to expand them somewhere around here), but for
177 : * now we keep them consistent with the stored variant.
178 : */
179 54 : if (TupleDescAttr(RelationGetDescr(rel), attno - 1)->attgenerated)
180 24 : ereport(ERROR,
181 : errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
182 : errmsg("generated columns are not supported in COPY FROM WHERE conditions"),
183 : errdetail("Column \"%s\" is a generated column.",
184 : get_attname(RelationGetRelid(rel), attno, false)));
185 : }
186 :
187 18 : whereClause = eval_const_expressions(NULL, whereClause);
188 :
189 18 : whereClause = (Node *) canonicalize_qual((Expr *) whereClause, false);
190 18 : whereClause = (Node *) make_ands_implicit((Expr *) whereClause);
191 : }
192 :
193 10656 : tupDesc = RelationGetDescr(rel);
194 10656 : attnums = CopyGetAttnums(tupDesc, rel, stmt->attlist);
195 47170 : foreach(cur, attnums)
196 : {
197 : int attno;
198 : Bitmapset **bms;
199 :
200 36598 : attno = lfirst_int(cur) - FirstLowInvalidHeapAttributeNumber;
201 36598 : bms = is_from ? &perminfo->insertedCols : &perminfo->selectedCols;
202 :
203 36598 : *bms = bms_add_member(*bms, attno);
204 : }
205 10572 : ExecCheckPermissions(pstate->p_rtable, list_make1(perminfo), true);
206 :
207 : /*
208 : * Permission check for row security policies.
209 : *
210 : * check_enable_rls will ereport(ERROR) if the user has requested
211 : * something invalid and will otherwise indicate if we should enable
212 : * RLS (returns RLS_ENABLED) or not for this COPY statement.
213 : *
214 : * If the relation has a row security policy and we are to apply it
215 : * then perform a "query" copy and allow the normal query processing
216 : * to handle the policies.
217 : *
218 : * If RLS is not enabled for this, then just fall through to the
219 : * normal non-filtering relation handling.
220 : */
221 10488 : if (check_enable_rls(relid, InvalidOid, false) == RLS_ENABLED)
222 : {
223 : SelectStmt *select;
224 : ColumnRef *cr;
225 : ResTarget *target;
226 : RangeVar *from;
227 84 : List *targetList = NIL;
228 :
229 84 : if (is_from)
230 6 : ereport(ERROR,
231 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
232 : errmsg("COPY FROM not supported with row-level security"),
233 : errhint("Use INSERT statements instead.")));
234 :
235 : /*
236 : * Build target list
237 : *
238 : * If no columns are specified in the attribute list of the COPY
239 : * command, then the target list is 'all' columns. Therefore, '*'
240 : * should be used as the target list for the resulting SELECT
241 : * statement.
242 : *
243 : * In the case that columns are specified in the attribute list,
244 : * create a ColumnRef and ResTarget for each column and add them
245 : * to the target list for the resulting SELECT statement.
246 : */
247 78 : if (!stmt->attlist)
248 : {
249 42 : cr = makeNode(ColumnRef);
250 42 : cr->fields = list_make1(makeNode(A_Star));
251 42 : cr->location = -1;
252 :
253 42 : target = makeNode(ResTarget);
254 42 : target->name = NULL;
255 42 : target->indirection = NIL;
256 42 : target->val = (Node *) cr;
257 42 : target->location = -1;
258 :
259 42 : targetList = list_make1(target);
260 : }
261 : else
262 : {
263 : ListCell *lc;
264 :
265 102 : foreach(lc, stmt->attlist)
266 : {
267 : /*
268 : * Build the ColumnRef for each column. The ColumnRef
269 : * 'fields' property is a String node that corresponds to
270 : * the column name respectively.
271 : */
272 66 : cr = makeNode(ColumnRef);
273 66 : cr->fields = list_make1(lfirst(lc));
274 66 : cr->location = -1;
275 :
276 : /* Build the ResTarget and add the ColumnRef to it. */
277 66 : target = makeNode(ResTarget);
278 66 : target->name = NULL;
279 66 : target->indirection = NIL;
280 66 : target->val = (Node *) cr;
281 66 : target->location = -1;
282 :
283 : /* Add each column to the SELECT statement's target list */
284 66 : targetList = lappend(targetList, target);
285 : }
286 : }
287 :
288 : /*
289 : * Build RangeVar for from clause, fully qualified based on the
290 : * relation which we have opened and locked. Use "ONLY" so that
291 : * COPY retrieves rows from only the target table not any
292 : * inheritance children, the same as when RLS doesn't apply.
293 : *
294 : * However, when copying data from a partitioned table, we don't
295 : * use "ONLY", since we need to retrieve rows from its descendant
296 : * tables too.
297 : */
298 78 : from = makeRangeVar(get_namespace_name(RelationGetNamespace(rel)),
299 78 : pstrdup(RelationGetRelationName(rel)),
300 : -1);
301 78 : from->inh = (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
302 :
303 : /* Build query */
304 78 : select = makeNode(SelectStmt);
305 78 : select->targetList = targetList;
306 78 : select->fromClause = list_make1(from);
307 :
308 78 : query = makeNode(RawStmt);
309 78 : query->stmt = (Node *) select;
310 78 : query->stmt_location = stmt_location;
311 78 : query->stmt_len = stmt_len;
312 :
313 : /*
314 : * Close the relation for now, but keep the lock on it to prevent
315 : * changes between now and when we start the query-based COPY.
316 : *
317 : * We'll reopen it later as part of the query-based COPY.
318 : */
319 78 : table_close(rel, NoLock);
320 78 : rel = NULL;
321 : }
322 : }
323 : else
324 : {
325 : Assert(stmt->query);
326 :
327 602 : query = makeNode(RawStmt);
328 602 : query->stmt = stmt->query;
329 602 : query->stmt_location = stmt_location;
330 602 : query->stmt_len = stmt_len;
331 :
332 602 : relid = InvalidOid;
333 602 : rel = NULL;
334 : }
335 :
336 11066 : if (is_from)
337 : {
338 : CopyFromState cstate;
339 :
340 : Assert(rel);
341 :
342 : /* check read-only transaction and parallel mode */
343 1726 : if (XactReadOnly && !rel->rd_islocaltemp)
344 0 : PreventCommandIfReadOnly("COPY FROM");
345 :
346 1726 : cstate = BeginCopyFrom(pstate, rel, whereClause,
347 1726 : stmt->filename, stmt->is_program,
348 1726 : NULL, stmt->attlist, stmt->options);
349 1462 : *processed = CopyFrom(cstate); /* copy from file to database */
350 1224 : EndCopyFrom(cstate);
351 : }
352 : else
353 : {
354 : CopyToState cstate;
355 :
356 9340 : cstate = BeginCopyTo(pstate, rel, query, relid,
357 9340 : stmt->filename, stmt->is_program,
358 9340 : NULL, stmt->attlist, stmt->options);
359 9138 : *processed = DoCopyTo(cstate); /* copy from database to file */
360 9136 : EndCopyTo(cstate);
361 : }
362 :
363 10360 : if (rel != NULL)
364 9820 : table_close(rel, NoLock);
365 10360 : }
366 :
367 : /*
368 : * Extract the CopyFormatOptions.header_line value from a DefElem.
369 : *
370 : * Parses the HEADER option for COPY, which can be a boolean, a non-negative
371 : * integer (number of lines to skip), or the special value "match".
372 : */
373 : static int
374 228 : defGetCopyHeaderOption(DefElem *def, bool is_from)
375 : {
376 : /*
377 : * If no parameter value given, assume "true" is meant.
378 : */
379 228 : if (def->arg == NULL)
380 30 : return COPY_HEADER_TRUE;
381 :
382 : /*
383 : * Allow 0, 1, "true", "false", "on", "off", a non-negative integer, or
384 : * "match".
385 : */
386 198 : switch (nodeTag(def->arg))
387 : {
388 30 : case T_Integer:
389 : {
390 30 : int ival = intVal(def->arg);
391 :
392 30 : if (ival < 0)
393 6 : ereport(ERROR,
394 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
395 : errmsg("a negative integer value cannot be "
396 : "specified for %s", def->defname)));
397 :
398 24 : if (!is_from && ival > 1)
399 6 : ereport(ERROR,
400 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
401 : errmsg("cannot use multi-line header in COPY TO")));
402 :
403 18 : return ival;
404 : }
405 : break;
406 168 : default:
407 : {
408 168 : char *sval = defGetString(def);
409 :
410 : /*
411 : * The set of strings accepted here should match up with the
412 : * grammar's opt_boolean_or_string production.
413 : */
414 168 : if (pg_strcasecmp(sval, "true") == 0)
415 64 : return COPY_HEADER_TRUE;
416 104 : if (pg_strcasecmp(sval, "false") == 0)
417 0 : return COPY_HEADER_FALSE;
418 104 : if (pg_strcasecmp(sval, "on") == 0)
419 0 : return COPY_HEADER_TRUE;
420 104 : if (pg_strcasecmp(sval, "off") == 0)
421 6 : return COPY_HEADER_FALSE;
422 98 : if (pg_strcasecmp(sval, "match") == 0)
423 : {
424 86 : if (!is_from)
425 6 : ereport(ERROR,
426 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
427 : errmsg("cannot use \"%s\" with HEADER in COPY TO",
428 : sval)));
429 80 : return COPY_HEADER_MATCH;
430 : }
431 : }
432 12 : break;
433 : }
434 12 : ereport(ERROR,
435 : (errcode(ERRCODE_SYNTAX_ERROR),
436 : errmsg("%s requires a Boolean value, a non-negative integer, "
437 : "or the string \"match\"",
438 : def->defname)));
439 : return COPY_HEADER_FALSE; /* keep compiler quiet */
440 : }
441 :
442 : /*
443 : * Extract a CopyOnErrorChoice value from a DefElem.
444 : */
445 : static CopyOnErrorChoice
446 114 : defGetCopyOnErrorChoice(DefElem *def, ParseState *pstate, bool is_from)
447 : {
448 114 : char *sval = defGetString(def);
449 :
450 114 : if (!is_from)
451 6 : ereport(ERROR,
452 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
453 : /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
454 : second %s is a COPY with direction, e.g. COPY TO */
455 : errmsg("COPY %s cannot be used with %s", "ON_ERROR", "COPY TO"),
456 : parser_errposition(pstate, def->location)));
457 :
458 : /*
459 : * Allow "stop", or "ignore" values.
460 : */
461 108 : if (pg_strcasecmp(sval, "stop") == 0)
462 6 : return COPY_ON_ERROR_STOP;
463 102 : if (pg_strcasecmp(sval, "ignore") == 0)
464 94 : return COPY_ON_ERROR_IGNORE;
465 :
466 8 : ereport(ERROR,
467 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
468 : /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR */
469 : errmsg("COPY %s \"%s\" not recognized", "ON_ERROR", sval),
470 : parser_errposition(pstate, def->location)));
471 : return COPY_ON_ERROR_STOP; /* keep compiler quiet */
472 : }
473 :
474 : /*
475 : * Extract REJECT_LIMIT value from a DefElem.
476 : *
477 : * REJECT_LIMIT can be specified in two ways: as an int64 for the COPY command
478 : * option or as a single-quoted string for the foreign table option using
479 : * file_fdw. Therefore this function needs to handle both formats.
480 : */
481 : static int64
482 38 : defGetCopyRejectLimitOption(DefElem *def)
483 : {
484 : int64 reject_limit;
485 :
486 38 : if (def->arg == NULL)
487 0 : ereport(ERROR,
488 : (errcode(ERRCODE_SYNTAX_ERROR),
489 : errmsg("%s requires a numeric value",
490 : def->defname)));
491 38 : else if (nodeTag(def->arg) == T_String)
492 14 : reject_limit = pg_strtoint64(strVal(def->arg));
493 : else
494 24 : reject_limit = defGetInt64(def);
495 :
496 38 : if (reject_limit <= 0)
497 8 : ereport(ERROR,
498 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
499 : errmsg("REJECT_LIMIT (%" PRId64 ") must be greater than zero",
500 : reject_limit)));
501 :
502 30 : return reject_limit;
503 : }
504 :
505 : /*
506 : * Extract a CopyLogVerbosityChoice value from a DefElem.
507 : */
508 : static CopyLogVerbosityChoice
509 46 : defGetCopyLogVerbosityChoice(DefElem *def, ParseState *pstate)
510 : {
511 : char *sval;
512 :
513 : /*
514 : * Allow "silent", "default", or "verbose" values.
515 : */
516 46 : sval = defGetString(def);
517 46 : if (pg_strcasecmp(sval, "silent") == 0)
518 20 : return COPY_LOG_VERBOSITY_SILENT;
519 26 : if (pg_strcasecmp(sval, "default") == 0)
520 6 : return COPY_LOG_VERBOSITY_DEFAULT;
521 20 : if (pg_strcasecmp(sval, "verbose") == 0)
522 12 : return COPY_LOG_VERBOSITY_VERBOSE;
523 :
524 8 : ereport(ERROR,
525 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
526 : /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR */
527 : errmsg("COPY %s \"%s\" not recognized", "LOG_VERBOSITY", sval),
528 : parser_errposition(pstate, def->location)));
529 : return COPY_LOG_VERBOSITY_DEFAULT; /* keep compiler quiet */
530 : }
531 :
532 : /*
533 : * Process the statement option list for COPY.
534 : *
535 : * Scan the options list (a list of DefElem) and transpose the information
536 : * into *opts_out, applying appropriate error checking.
537 : *
538 : * If 'opts_out' is not NULL, it is assumed to be filled with zeroes initially.
539 : *
540 : * This is exported so that external users of the COPY API can sanity-check
541 : * a list of options. In that usage, 'opts_out' can be passed as NULL and
542 : * the collected data is just leaked until CurrentMemoryContext is reset.
543 : *
544 : * Note that additional checking, such as whether column names listed in FORCE
545 : * QUOTE actually exist, has to be applied later. This just checks for
546 : * self-consistency of the options list.
547 : */
548 : void
549 11608 : ProcessCopyOptions(ParseState *pstate,
550 : CopyFormatOptions *opts_out,
551 : bool is_from,
552 : List *options)
553 : {
554 11608 : bool format_specified = false;
555 11608 : bool freeze_specified = false;
556 11608 : bool header_specified = false;
557 11608 : bool on_error_specified = false;
558 11608 : bool log_verbosity_specified = false;
559 11608 : bool reject_limit_specified = false;
560 : ListCell *option;
561 :
562 : /* Support external use for option sanity checking */
563 11608 : if (opts_out == NULL)
564 104 : opts_out = (CopyFormatOptions *) palloc0(sizeof(CopyFormatOptions));
565 :
566 11608 : opts_out->file_encoding = -1;
567 :
568 : /* Extract options from the statement node tree */
569 13684 : foreach(option, options)
570 : {
571 2234 : DefElem *defel = lfirst_node(DefElem, option);
572 :
573 2234 : if (strcmp(defel->defname, "format") == 0)
574 : {
575 656 : char *fmt = defGetString(defel);
576 :
577 656 : if (format_specified)
578 6 : errorConflictingDefElem(defel, pstate);
579 650 : format_specified = true;
580 650 : if (strcmp(fmt, "text") == 0)
581 : /* default format */ ;
582 574 : else if (strcmp(fmt, "csv") == 0)
583 502 : opts_out->csv_mode = true;
584 72 : else if (strcmp(fmt, "binary") == 0)
585 70 : opts_out->binary = true;
586 : else
587 2 : ereport(ERROR,
588 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
589 : errmsg("COPY format \"%s\" not recognized", fmt),
590 : parser_errposition(pstate, defel->location)));
591 : }
592 1578 : else if (strcmp(defel->defname, "freeze") == 0)
593 : {
594 84 : if (freeze_specified)
595 6 : errorConflictingDefElem(defel, pstate);
596 78 : freeze_specified = true;
597 78 : opts_out->freeze = defGetBoolean(defel);
598 : }
599 1494 : else if (strcmp(defel->defname, "delimiter") == 0)
600 : {
601 302 : if (opts_out->delim)
602 6 : errorConflictingDefElem(defel, pstate);
603 296 : opts_out->delim = defGetString(defel);
604 : }
605 1192 : else if (strcmp(defel->defname, "null") == 0)
606 : {
607 144 : if (opts_out->null_print)
608 6 : errorConflictingDefElem(defel, pstate);
609 138 : opts_out->null_print = defGetString(defel);
610 : }
611 1048 : else if (strcmp(defel->defname, "default") == 0)
612 : {
613 90 : if (opts_out->default_print)
614 0 : errorConflictingDefElem(defel, pstate);
615 90 : opts_out->default_print = defGetString(defel);
616 : }
617 958 : else if (strcmp(defel->defname, "header") == 0)
618 : {
619 234 : if (header_specified)
620 6 : errorConflictingDefElem(defel, pstate);
621 228 : header_specified = true;
622 228 : opts_out->header_line = defGetCopyHeaderOption(defel, is_from);
623 : }
624 724 : else if (strcmp(defel->defname, "quote") == 0)
625 : {
626 102 : if (opts_out->quote)
627 6 : errorConflictingDefElem(defel, pstate);
628 96 : opts_out->quote = defGetString(defel);
629 : }
630 622 : else if (strcmp(defel->defname, "escape") == 0)
631 : {
632 94 : if (opts_out->escape)
633 6 : errorConflictingDefElem(defel, pstate);
634 88 : opts_out->escape = defGetString(defel);
635 : }
636 528 : else if (strcmp(defel->defname, "force_quote") == 0)
637 : {
638 78 : if (opts_out->force_quote || opts_out->force_quote_all)
639 6 : errorConflictingDefElem(defel, pstate);
640 72 : if (defel->arg && IsA(defel->arg, A_Star))
641 30 : opts_out->force_quote_all = true;
642 42 : else if (defel->arg && IsA(defel->arg, List))
643 42 : opts_out->force_quote = castNode(List, defel->arg);
644 : else
645 0 : ereport(ERROR,
646 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
647 : errmsg("argument to option \"%s\" must be a list of column names",
648 : defel->defname),
649 : parser_errposition(pstate, defel->location)));
650 : }
651 450 : else if (strcmp(defel->defname, "force_not_null") == 0)
652 : {
653 88 : if (opts_out->force_notnull || opts_out->force_notnull_all)
654 12 : errorConflictingDefElem(defel, pstate);
655 76 : if (defel->arg && IsA(defel->arg, A_Star))
656 30 : opts_out->force_notnull_all = true;
657 46 : else if (defel->arg && IsA(defel->arg, List))
658 46 : opts_out->force_notnull = castNode(List, defel->arg);
659 : else
660 0 : ereport(ERROR,
661 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
662 : errmsg("argument to option \"%s\" must be a list of column names",
663 : defel->defname),
664 : parser_errposition(pstate, defel->location)));
665 : }
666 362 : else if (strcmp(defel->defname, "force_null") == 0)
667 : {
668 88 : if (opts_out->force_null || opts_out->force_null_all)
669 12 : errorConflictingDefElem(defel, pstate);
670 76 : if (defel->arg && IsA(defel->arg, A_Star))
671 30 : opts_out->force_null_all = true;
672 46 : else if (defel->arg && IsA(defel->arg, List))
673 46 : opts_out->force_null = castNode(List, defel->arg);
674 : else
675 0 : ereport(ERROR,
676 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
677 : errmsg("argument to option \"%s\" must be a list of column names",
678 : defel->defname),
679 : parser_errposition(pstate, defel->location)));
680 : }
681 274 : else if (strcmp(defel->defname, "convert_selectively") == 0)
682 : {
683 : /*
684 : * Undocumented, not-accessible-from-SQL option: convert only the
685 : * named columns to binary form, storing the rest as NULLs. It's
686 : * allowed for the column list to be NIL.
687 : */
688 16 : if (opts_out->convert_selectively)
689 6 : errorConflictingDefElem(defel, pstate);
690 10 : opts_out->convert_selectively = true;
691 10 : if (defel->arg == NULL || IsA(defel->arg, List))
692 10 : opts_out->convert_select = castNode(List, defel->arg);
693 : else
694 0 : ereport(ERROR,
695 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
696 : errmsg("argument to option \"%s\" must be a list of column names",
697 : defel->defname),
698 : parser_errposition(pstate, defel->location)));
699 : }
700 258 : else if (strcmp(defel->defname, "encoding") == 0)
701 : {
702 48 : if (opts_out->file_encoding >= 0)
703 6 : errorConflictingDefElem(defel, pstate);
704 42 : opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
705 42 : if (opts_out->file_encoding < 0)
706 0 : ereport(ERROR,
707 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
708 : errmsg("argument to option \"%s\" must be a valid encoding name",
709 : defel->defname),
710 : parser_errposition(pstate, defel->location)));
711 : }
712 210 : else if (strcmp(defel->defname, "on_error") == 0)
713 : {
714 120 : if (on_error_specified)
715 6 : errorConflictingDefElem(defel, pstate);
716 114 : on_error_specified = true;
717 114 : opts_out->on_error = defGetCopyOnErrorChoice(defel, pstate, is_from);
718 : }
719 90 : else if (strcmp(defel->defname, "log_verbosity") == 0)
720 : {
721 52 : if (log_verbosity_specified)
722 6 : errorConflictingDefElem(defel, pstate);
723 46 : log_verbosity_specified = true;
724 46 : opts_out->log_verbosity = defGetCopyLogVerbosityChoice(defel, pstate);
725 : }
726 38 : else if (strcmp(defel->defname, "reject_limit") == 0)
727 : {
728 38 : if (reject_limit_specified)
729 0 : errorConflictingDefElem(defel, pstate);
730 38 : reject_limit_specified = true;
731 38 : opts_out->reject_limit = defGetCopyRejectLimitOption(defel);
732 : }
733 : else
734 0 : ereport(ERROR,
735 : (errcode(ERRCODE_SYNTAX_ERROR),
736 : errmsg("option \"%s\" not recognized",
737 : defel->defname),
738 : parser_errposition(pstate, defel->location)));
739 : }
740 :
741 : /*
742 : * Check for incompatible options (must do these three before inserting
743 : * defaults)
744 : */
745 11450 : if (opts_out->binary && opts_out->delim)
746 6 : ereport(ERROR,
747 : (errcode(ERRCODE_SYNTAX_ERROR),
748 : /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
749 : errmsg("cannot specify %s in BINARY mode", "DELIMITER")));
750 :
751 11444 : if (opts_out->binary && opts_out->null_print)
752 6 : ereport(ERROR,
753 : (errcode(ERRCODE_SYNTAX_ERROR),
754 : errmsg("cannot specify %s in BINARY mode", "NULL")));
755 :
756 11438 : if (opts_out->binary && opts_out->default_print)
757 6 : ereport(ERROR,
758 : (errcode(ERRCODE_SYNTAX_ERROR),
759 : errmsg("cannot specify %s in BINARY mode", "DEFAULT")));
760 :
761 : /* Set defaults for omitted options */
762 11432 : if (!opts_out->delim)
763 11148 : opts_out->delim = opts_out->csv_mode ? "," : "\t";
764 :
765 11432 : if (!opts_out->null_print)
766 11306 : opts_out->null_print = opts_out->csv_mode ? "" : "\\N";
767 11432 : opts_out->null_print_len = strlen(opts_out->null_print);
768 :
769 11432 : if (opts_out->csv_mode)
770 : {
771 484 : if (!opts_out->quote)
772 398 : opts_out->quote = "\"";
773 484 : if (!opts_out->escape)
774 408 : opts_out->escape = opts_out->quote;
775 : }
776 :
777 : /* Only single-byte delimiter strings are supported. */
778 11432 : if (strlen(opts_out->delim) != 1)
779 2 : ereport(ERROR,
780 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
781 : errmsg("COPY delimiter must be a single one-byte character")));
782 :
783 : /* Disallow end-of-line characters */
784 11430 : if (strchr(opts_out->delim, '\r') != NULL ||
785 11430 : strchr(opts_out->delim, '\n') != NULL)
786 2 : ereport(ERROR,
787 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
788 : errmsg("COPY delimiter cannot be newline or carriage return")));
789 :
790 11428 : if (strchr(opts_out->null_print, '\r') != NULL ||
791 11428 : strchr(opts_out->null_print, '\n') != NULL)
792 2 : ereport(ERROR,
793 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
794 : errmsg("COPY null representation cannot use newline or carriage return")));
795 :
796 11426 : if (opts_out->default_print)
797 : {
798 84 : opts_out->default_print_len = strlen(opts_out->default_print);
799 :
800 84 : if (strchr(opts_out->default_print, '\r') != NULL ||
801 78 : strchr(opts_out->default_print, '\n') != NULL)
802 12 : ereport(ERROR,
803 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
804 : errmsg("COPY default representation cannot use newline or carriage return")));
805 : }
806 :
807 : /*
808 : * Disallow unsafe delimiter characters in non-CSV mode. We can't allow
809 : * backslash because it would be ambiguous. We can't allow the other
810 : * cases because data characters matching the delimiter must be
811 : * backslashed, and certain backslash combinations are interpreted
812 : * non-literally by COPY IN. Disallowing all lower case ASCII letters is
813 : * more than strictly necessary, but seems best for consistency and
814 : * future-proofing. Likewise we disallow all digits though only octal
815 : * digits are actually dangerous.
816 : */
817 11414 : if (!opts_out->csv_mode &&
818 10936 : strchr("\\.abcdefghijklmnopqrstuvwxyz0123456789",
819 10936 : opts_out->delim[0]) != NULL)
820 10 : ereport(ERROR,
821 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
822 : errmsg("COPY delimiter cannot be \"%s\"", opts_out->delim)));
823 :
824 : /* Check header */
825 11404 : if (opts_out->binary && opts_out->header_line != COPY_HEADER_FALSE)
826 2 : ereport(ERROR,
827 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
828 : /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
829 : errmsg("cannot specify %s in BINARY mode", "HEADER")));
830 :
831 : /* Check quote */
832 11402 : if (!opts_out->csv_mode && opts_out->quote != NULL)
833 4 : ereport(ERROR,
834 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
835 : /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
836 : errmsg("COPY %s requires CSV mode", "QUOTE")));
837 :
838 11398 : if (opts_out->csv_mode && strlen(opts_out->quote) != 1)
839 2 : ereport(ERROR,
840 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
841 : errmsg("COPY quote must be a single one-byte character")));
842 :
843 11396 : if (opts_out->csv_mode && opts_out->delim[0] == opts_out->quote[0])
844 2 : ereport(ERROR,
845 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
846 : errmsg("COPY delimiter and quote must be different")));
847 :
848 : /* Check escape */
849 11394 : if (!opts_out->csv_mode && opts_out->escape != NULL)
850 6 : ereport(ERROR,
851 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
852 : /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
853 : errmsg("COPY %s requires CSV mode", "ESCAPE")));
854 :
855 11388 : if (opts_out->csv_mode && strlen(opts_out->escape) != 1)
856 2 : ereport(ERROR,
857 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
858 : errmsg("COPY escape must be a single one-byte character")));
859 :
860 : /* Check force_quote */
861 11386 : if (!opts_out->csv_mode && (opts_out->force_quote || opts_out->force_quote_all))
862 12 : ereport(ERROR,
863 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
864 : /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
865 : errmsg("COPY %s requires CSV mode", "FORCE_QUOTE")));
866 11374 : if ((opts_out->force_quote || opts_out->force_quote_all) && is_from)
867 12 : ereport(ERROR,
868 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
869 : /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
870 : second %s is a COPY with direction, e.g. COPY TO */
871 : errmsg("COPY %s cannot be used with %s", "FORCE_QUOTE",
872 : "COPY FROM")));
873 :
874 : /* Check force_notnull */
875 11362 : if (!opts_out->csv_mode && (opts_out->force_notnull != NIL ||
876 10894 : opts_out->force_notnull_all))
877 14 : ereport(ERROR,
878 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
879 : /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
880 : errmsg("COPY %s requires CSV mode", "FORCE_NOT_NULL")));
881 11348 : if ((opts_out->force_notnull != NIL || opts_out->force_notnull_all) &&
882 50 : !is_from)
883 12 : ereport(ERROR,
884 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
885 : /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
886 : second %s is a COPY with direction, e.g. COPY TO */
887 : errmsg("COPY %s cannot be used with %s", "FORCE_NOT_NULL",
888 : "COPY TO")));
889 :
890 : /* Check force_null */
891 11336 : if (!opts_out->csv_mode && (opts_out->force_null != NIL ||
892 10882 : opts_out->force_null_all))
893 12 : ereport(ERROR,
894 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
895 : /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
896 : errmsg("COPY %s requires CSV mode", "FORCE_NULL")));
897 :
898 11324 : if ((opts_out->force_null != NIL || opts_out->force_null_all) &&
899 50 : !is_from)
900 12 : ereport(ERROR,
901 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
902 : /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
903 : second %s is a COPY with direction, e.g. COPY TO */
904 : errmsg("COPY %s cannot be used with %s", "FORCE_NULL",
905 : "COPY TO")));
906 :
907 : /* Don't allow the delimiter to appear in the null string. */
908 11312 : if (strchr(opts_out->null_print, opts_out->delim[0]) != NULL)
909 2 : ereport(ERROR,
910 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
911 : /*- translator: %s is the name of a COPY option, e.g. NULL */
912 : errmsg("COPY delimiter character must not appear in the %s specification",
913 : "NULL")));
914 :
915 : /* Don't allow the CSV quote char to appear in the null string. */
916 11310 : if (opts_out->csv_mode &&
917 434 : strchr(opts_out->null_print, opts_out->quote[0]) != NULL)
918 2 : ereport(ERROR,
919 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
920 : /*- translator: %s is the name of a COPY option, e.g. NULL */
921 : errmsg("CSV quote character must not appear in the %s specification",
922 : "NULL")));
923 :
924 : /* Check freeze */
925 11308 : if (opts_out->freeze && !is_from)
926 0 : ereport(ERROR,
927 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
928 : /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
929 : second %s is a COPY with direction, e.g. COPY TO */
930 : errmsg("COPY %s cannot be used with %s", "FREEZE",
931 : "COPY TO")));
932 :
933 11308 : if (opts_out->default_print)
934 : {
935 72 : if (!is_from)
936 6 : ereport(ERROR,
937 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
938 : /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
939 : second %s is a COPY with direction, e.g. COPY TO */
940 : errmsg("COPY %s cannot be used with %s", "DEFAULT",
941 : "COPY TO")));
942 :
943 : /* Don't allow the delimiter to appear in the default string. */
944 66 : if (strchr(opts_out->default_print, opts_out->delim[0]) != NULL)
945 6 : ereport(ERROR,
946 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
947 : /*- translator: %s is the name of a COPY option, e.g. NULL */
948 : errmsg("COPY delimiter character must not appear in the %s specification",
949 : "DEFAULT")));
950 :
951 : /* Don't allow the CSV quote char to appear in the default string. */
952 60 : if (opts_out->csv_mode &&
953 30 : strchr(opts_out->default_print, opts_out->quote[0]) != NULL)
954 6 : ereport(ERROR,
955 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
956 : /*- translator: %s is the name of a COPY option, e.g. NULL */
957 : errmsg("CSV quote character must not appear in the %s specification",
958 : "DEFAULT")));
959 :
960 : /* Don't allow the NULL and DEFAULT string to be the same */
961 54 : if (opts_out->null_print_len == opts_out->default_print_len &&
962 24 : strncmp(opts_out->null_print, opts_out->default_print,
963 24 : opts_out->null_print_len) == 0)
964 6 : ereport(ERROR,
965 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
966 : errmsg("NULL specification and DEFAULT specification cannot be the same")));
967 : }
968 : /* Check on_error */
969 11284 : if (opts_out->binary && opts_out->on_error != COPY_ON_ERROR_STOP)
970 8 : ereport(ERROR,
971 : (errcode(ERRCODE_SYNTAX_ERROR),
972 : errmsg("only ON_ERROR STOP is allowed in BINARY mode")));
973 :
974 11276 : if (opts_out->reject_limit && !opts_out->on_error)
975 8 : ereport(ERROR,
976 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
977 : /*- translator: first and second %s are the names of COPY option, e.g.
978 : * ON_ERROR, third is the value of the COPY option, e.g. IGNORE */
979 : errmsg("COPY %s requires %s to be set to %s",
980 : "REJECT_LIMIT", "ON_ERROR", "IGNORE")));
981 11268 : }
982 :
983 : /*
984 : * CopyGetAttnums - build an integer list of attnums to be copied
985 : *
986 : * The input attnamelist is either the user-specified column list,
987 : * or NIL if there was none (in which case we want all the non-dropped
988 : * columns).
989 : *
990 : * We don't include generated columns in the generated full list and we don't
991 : * allow them to be specified explicitly. They don't make sense for COPY
992 : * FROM, but we could possibly allow them for COPY TO. But this way it's at
993 : * least ensured that whatever we copy out can be copied back in.
994 : *
995 : * rel can be NULL ... it's only used for error reports.
996 : */
997 : List *
998 21816 : CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
999 : {
1000 21816 : List *attnums = NIL;
1001 :
1002 21816 : if (attnamelist == NIL)
1003 : {
1004 : /* Generate default column list */
1005 3876 : int attr_count = tupDesc->natts;
1006 : int i;
1007 :
1008 13676 : for (i = 0; i < attr_count; i++)
1009 : {
1010 9800 : CompactAttribute *attr = TupleDescCompactAttr(tupDesc, i);
1011 :
1012 9800 : if (attr->attisdropped || attr->attgenerated)
1013 302 : continue;
1014 9498 : attnums = lappend_int(attnums, i + 1);
1015 : }
1016 : }
1017 : else
1018 : {
1019 : /* Validate the user-supplied list and extract attnums */
1020 : ListCell *l;
1021 :
1022 82250 : foreach(l, attnamelist)
1023 : {
1024 64394 : char *name = strVal(lfirst(l));
1025 : int attnum;
1026 : int i;
1027 :
1028 : /* Lookup column name */
1029 64394 : attnum = InvalidAttrNumber;
1030 9926834 : for (i = 0; i < tupDesc->natts; i++)
1031 : {
1032 9926804 : Form_pg_attribute att = TupleDescAttr(tupDesc, i);
1033 :
1034 9926804 : if (att->attisdropped)
1035 792 : continue;
1036 9926012 : if (namestrcmp(&(att->attname), name) == 0)
1037 : {
1038 64364 : if (att->attgenerated)
1039 48 : ereport(ERROR,
1040 : (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1041 : errmsg("column \"%s\" is a generated column",
1042 : name),
1043 : errdetail("Generated columns cannot be used in COPY.")));
1044 64316 : attnum = att->attnum;
1045 64316 : break;
1046 : }
1047 : }
1048 64346 : if (attnum == InvalidAttrNumber)
1049 : {
1050 30 : if (rel != NULL)
1051 30 : ereport(ERROR,
1052 : (errcode(ERRCODE_UNDEFINED_COLUMN),
1053 : errmsg("column \"%s\" of relation \"%s\" does not exist",
1054 : name, RelationGetRelationName(rel))));
1055 : else
1056 0 : ereport(ERROR,
1057 : (errcode(ERRCODE_UNDEFINED_COLUMN),
1058 : errmsg("column \"%s\" does not exist",
1059 : name)));
1060 : }
1061 : /* Check for duplicates */
1062 64316 : if (list_member_int(attnums, attnum))
1063 6 : ereport(ERROR,
1064 : (errcode(ERRCODE_DUPLICATE_COLUMN),
1065 : errmsg("column \"%s\" specified more than once",
1066 : name)));
1067 64310 : attnums = lappend_int(attnums, attnum);
1068 : }
1069 : }
1070 :
1071 21732 : return attnums;
1072 : }
|