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