PostgreSQL Source Code git master
copy.c
Go to the documentation of this file.
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"
34#include "parser/parse_expr.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 */
61void
63 int stmt_location, int stmt_len,
64 uint64 *processed)
65{
66 bool is_from = stmt->is_from;
67 bool pipe = (stmt->filename == NULL);
68 Relation rel;
69 Oid relid;
70 RawStmt *query = NULL;
71 Node *whereClause = NULL;
72
73 /*
74 * Disallow COPY to/from file or program except to users with the
75 * appropriate role.
76 */
77 if (!pipe)
78 {
79 if (stmt->is_program)
80 {
81 if (!has_privs_of_role(GetUserId(), ROLE_PG_EXECUTE_SERVER_PROGRAM))
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 if (is_from && !has_privs_of_role(GetUserId(), ROLE_PG_READ_SERVER_FILES))
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 if (!is_from && !has_privs_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES))
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 if (stmt->relation)
113 {
114 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 rel = table_openrv(stmt->relation, lockmode);
125
126 relid = RelationGetRelid(rel);
127
128 nsitem = addRangeTableEntryForRelation(pstate, rel, lockmode,
129 NULL, false, false);
130
131 perminfo = nsitem->p_perminfo;
132 perminfo->requiredPerms = (is_from ? ACL_INSERT : ACL_SELECT);
133
134 if (stmt->whereClause)
135 {
136 Bitmapset *expr_attrs = NULL;
137 int i;
138
139 /* add nsitem to query namespace */
140 addNSItemToQuery(pstate, nsitem, false, true, true);
141
142 /* Transform the raw expression tree */
143 whereClause = transformExpr(pstate, stmt->whereClause, EXPR_KIND_COPY_WHERE);
144
145 /* Make sure it yields a boolean result. */
146 whereClause = coerce_to_boolean(pstate, whereClause, "WHERE");
147
148 /* we have to fix its collations too */
149 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 pull_varattnos(whereClause, 1, &expr_attrs);
158 {
159 expr_attrs = bms_add_range(expr_attrs,
162 expr_attrs = bms_del_member(expr_attrs, 0 - FirstLowInvalidHeapAttributeNumber);
163 }
164
165 i = -1;
166 while ((i = bms_next_member(expr_attrs, i)) >= 0)
167 {
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 if (TupleDescAttr(RelationGetDescr(rel), attno - 1)->attgenerated)
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 whereClause = eval_const_expressions(NULL, whereClause);
188
189 whereClause = (Node *) canonicalize_qual((Expr *) whereClause, false);
190 whereClause = (Node *) make_ands_implicit((Expr *) whereClause);
191 }
192
193 tupDesc = RelationGetDescr(rel);
194 attnums = CopyGetAttnums(tupDesc, rel, stmt->attlist);
195 foreach(cur, attnums)
196 {
197 int attno;
198 Bitmapset **bms;
199
201 bms = is_from ? &perminfo->insertedCols : &perminfo->selectedCols;
202
203 *bms = bms_add_member(*bms, attno);
204 }
205 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 if (check_enable_rls(relid, InvalidOid, false) == RLS_ENABLED)
222 {
224 ColumnRef *cr;
225 ResTarget *target;
226 RangeVar *from;
227 List *targetList = NIL;
228
229 if (is_from)
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 if (!stmt->attlist)
248 {
249 cr = makeNode(ColumnRef);
251 cr->location = -1;
252
253 target = makeNode(ResTarget);
254 target->name = NULL;
255 target->indirection = NIL;
256 target->val = (Node *) cr;
257 target->location = -1;
258
259 targetList = list_make1(target);
260 }
261 else
262 {
263 ListCell *lc;
264
265 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 cr = makeNode(ColumnRef);
273 cr->fields = list_make1(lfirst(lc));
274 cr->location = -1;
275
276 /* Build the ResTarget and add the ColumnRef to it. */
277 target = makeNode(ResTarget);
278 target->name = NULL;
279 target->indirection = NIL;
280 target->val = (Node *) cr;
281 target->location = -1;
282
283 /* Add each column to the SELECT statement's target list */
284 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 */
300 -1);
301 from->inh = (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
302
303 /* Build query */
305 select->targetList = targetList;
306 select->fromClause = list_make1(from);
307
308 query = makeNode(RawStmt);
309 query->stmt = (Node *) select;
310 query->stmt_location = stmt_location;
311 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 table_close(rel, NoLock);
320 rel = NULL;
321 }
322 }
323 else
324 {
325 Assert(stmt->query);
326
327 query = makeNode(RawStmt);
328 query->stmt = stmt->query;
329 query->stmt_location = stmt_location;
330 query->stmt_len = stmt_len;
331
332 relid = InvalidOid;
333 rel = NULL;
334 }
335
336 if (is_from)
337 {
338 CopyFromState cstate;
339
340 Assert(rel);
341
342 /* check read-only transaction and parallel mode */
343 if (XactReadOnly && !rel->rd_islocaltemp)
344 PreventCommandIfReadOnly("COPY FROM");
345
346 cstate = BeginCopyFrom(pstate, rel, whereClause,
347 stmt->filename, stmt->is_program,
348 NULL, stmt->attlist, stmt->options);
349 *processed = CopyFrom(cstate); /* copy from file to database */
350 EndCopyFrom(cstate);
351 }
352 else
353 {
354 CopyToState cstate;
355
356 cstate = BeginCopyTo(pstate, rel, query, relid,
357 stmt->filename, stmt->is_program,
358 NULL, stmt->attlist, stmt->options);
359 *processed = DoCopyTo(cstate); /* copy from database to file */
360 EndCopyTo(cstate);
361 }
362
363 if (rel != NULL)
364 table_close(rel, NoLock);
365}
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 */
373static int
375{
376 /*
377 * If no parameter value given, assume "true" is meant.
378 */
379 if (def->arg == NULL)
380 return COPY_HEADER_TRUE;
381
382 /*
383 * Allow 0, 1, "true", "false", "on", "off", a non-negative integer, or
384 * "match".
385 */
386 switch (nodeTag(def->arg))
387 {
388 case T_Integer:
389 {
390 int ival = intVal(def->arg);
391
392 if (ival < 0)
394 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
395 errmsg("a negative integer value cannot be "
396 "specified for %s", def->defname)));
397
398 if (!is_from && ival > 1)
400 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
401 errmsg("cannot use multi-line header in COPY TO")));
402
403 return ival;
404 }
405 break;
406 default:
407 {
408 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 if (pg_strcasecmp(sval, "true") == 0)
415 return COPY_HEADER_TRUE;
416 if (pg_strcasecmp(sval, "false") == 0)
417 return COPY_HEADER_FALSE;
418 if (pg_strcasecmp(sval, "on") == 0)
419 return COPY_HEADER_TRUE;
420 if (pg_strcasecmp(sval, "off") == 0)
421 return COPY_HEADER_FALSE;
422 if (pg_strcasecmp(sval, "match") == 0)
423 {
424 if (!is_from)
426 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
427 errmsg("cannot use \"%s\" with HEADER in COPY TO",
428 sval)));
429 return COPY_HEADER_MATCH;
430 }
431 }
432 break;
433 }
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 */
446defGetCopyOnErrorChoice(DefElem *def, ParseState *pstate, bool is_from)
447{
448 char *sval = defGetString(def);
449
450 if (!is_from)
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 if (pg_strcasecmp(sval, "stop") == 0)
462 return COPY_ON_ERROR_STOP;
463 if (pg_strcasecmp(sval, "ignore") == 0)
465
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 */
481static int64
483{
484 int64 reject_limit;
485
486 if (def->arg == NULL)
488 (errcode(ERRCODE_SYNTAX_ERROR),
489 errmsg("%s requires a numeric value",
490 def->defname)));
491 else if (nodeTag(def->arg) == T_String)
492 reject_limit = pg_strtoint64(strVal(def->arg));
493 else
494 reject_limit = defGetInt64(def);
495
496 if (reject_limit <= 0)
498 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
499 errmsg("REJECT_LIMIT (%" PRId64 ") must be greater than zero",
500 reject_limit)));
501
502 return reject_limit;
503}
504
505/*
506 * Extract a CopyLogVerbosityChoice value from a DefElem.
507 */
510{
511 char *sval;
512
513 /*
514 * Allow "silent", "default", or "verbose" values.
515 */
516 sval = defGetString(def);
517 if (pg_strcasecmp(sval, "silent") == 0)
519 if (pg_strcasecmp(sval, "default") == 0)
521 if (pg_strcasecmp(sval, "verbose") == 0)
523
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 */
548void
550 CopyFormatOptions *opts_out,
551 bool is_from,
552 List *options)
553{
554 bool format_specified = false;
555 bool freeze_specified = false;
556 bool header_specified = false;
557 bool on_error_specified = false;
558 bool log_verbosity_specified = false;
559 bool reject_limit_specified = false;
561
562 /* Support external use for option sanity checking */
563 if (opts_out == NULL)
564 opts_out = (CopyFormatOptions *) palloc0(sizeof(CopyFormatOptions));
565
566 opts_out->file_encoding = -1;
567
568 /* Extract options from the statement node tree */
569 foreach(option, options)
570 {
572
573 if (strcmp(defel->defname, "format") == 0)
574 {
575 char *fmt = defGetString(defel);
576
577 if (format_specified)
578 errorConflictingDefElem(defel, pstate);
579 format_specified = true;
580 if (strcmp(fmt, "text") == 0)
581 /* default format */ ;
582 else if (strcmp(fmt, "csv") == 0)
583 opts_out->csv_mode = true;
584 else if (strcmp(fmt, "binary") == 0)
585 opts_out->binary = true;
586 else
588 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
589 errmsg("COPY format \"%s\" not recognized", fmt),
590 parser_errposition(pstate, defel->location)));
591 }
592 else if (strcmp(defel->defname, "freeze") == 0)
593 {
594 if (freeze_specified)
595 errorConflictingDefElem(defel, pstate);
596 freeze_specified = true;
597 opts_out->freeze = defGetBoolean(defel);
598 }
599 else if (strcmp(defel->defname, "delimiter") == 0)
600 {
601 if (opts_out->delim)
602 errorConflictingDefElem(defel, pstate);
603 opts_out->delim = defGetString(defel);
604 }
605 else if (strcmp(defel->defname, "null") == 0)
606 {
607 if (opts_out->null_print)
608 errorConflictingDefElem(defel, pstate);
609 opts_out->null_print = defGetString(defel);
610 }
611 else if (strcmp(defel->defname, "default") == 0)
612 {
613 if (opts_out->default_print)
614 errorConflictingDefElem(defel, pstate);
615 opts_out->default_print = defGetString(defel);
616 }
617 else if (strcmp(defel->defname, "header") == 0)
618 {
619 if (header_specified)
620 errorConflictingDefElem(defel, pstate);
621 header_specified = true;
622 opts_out->header_line = defGetCopyHeaderOption(defel, is_from);
623 }
624 else if (strcmp(defel->defname, "quote") == 0)
625 {
626 if (opts_out->quote)
627 errorConflictingDefElem(defel, pstate);
628 opts_out->quote = defGetString(defel);
629 }
630 else if (strcmp(defel->defname, "escape") == 0)
631 {
632 if (opts_out->escape)
633 errorConflictingDefElem(defel, pstate);
634 opts_out->escape = defGetString(defel);
635 }
636 else if (strcmp(defel->defname, "force_quote") == 0)
637 {
638 if (opts_out->force_quote || opts_out->force_quote_all)
639 errorConflictingDefElem(defel, pstate);
640 if (defel->arg && IsA(defel->arg, A_Star))
641 opts_out->force_quote_all = true;
642 else if (defel->arg && IsA(defel->arg, List))
643 opts_out->force_quote = castNode(List, defel->arg);
644 else
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 else if (strcmp(defel->defname, "force_not_null") == 0)
652 {
653 if (opts_out->force_notnull || opts_out->force_notnull_all)
654 errorConflictingDefElem(defel, pstate);
655 if (defel->arg && IsA(defel->arg, A_Star))
656 opts_out->force_notnull_all = true;
657 else if (defel->arg && IsA(defel->arg, List))
658 opts_out->force_notnull = castNode(List, defel->arg);
659 else
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 else if (strcmp(defel->defname, "force_null") == 0)
667 {
668 if (opts_out->force_null || opts_out->force_null_all)
669 errorConflictingDefElem(defel, pstate);
670 if (defel->arg && IsA(defel->arg, A_Star))
671 opts_out->force_null_all = true;
672 else if (defel->arg && IsA(defel->arg, List))
673 opts_out->force_null = castNode(List, defel->arg);
674 else
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 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 if (opts_out->convert_selectively)
689 errorConflictingDefElem(defel, pstate);
690 opts_out->convert_selectively = true;
691 if (defel->arg == NULL || IsA(defel->arg, List))
692 opts_out->convert_select = castNode(List, defel->arg);
693 else
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 else if (strcmp(defel->defname, "encoding") == 0)
701 {
702 if (opts_out->file_encoding >= 0)
703 errorConflictingDefElem(defel, pstate);
705 if (opts_out->file_encoding < 0)
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 else if (strcmp(defel->defname, "on_error") == 0)
713 {
714 if (on_error_specified)
715 errorConflictingDefElem(defel, pstate);
716 on_error_specified = true;
717 opts_out->on_error = defGetCopyOnErrorChoice(defel, pstate, is_from);
718 }
719 else if (strcmp(defel->defname, "log_verbosity") == 0)
720 {
721 if (log_verbosity_specified)
722 errorConflictingDefElem(defel, pstate);
723 log_verbosity_specified = true;
724 opts_out->log_verbosity = defGetCopyLogVerbosityChoice(defel, pstate);
725 }
726 else if (strcmp(defel->defname, "reject_limit") == 0)
727 {
728 if (reject_limit_specified)
729 errorConflictingDefElem(defel, pstate);
730 reject_limit_specified = true;
731 opts_out->reject_limit = defGetCopyRejectLimitOption(defel);
732 }
733 else
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 if (opts_out->binary && opts_out->delim)
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 if (opts_out->binary && opts_out->null_print)
753 (errcode(ERRCODE_SYNTAX_ERROR),
754 errmsg("cannot specify %s in BINARY mode", "NULL")));
755
756 if (opts_out->binary && opts_out->default_print)
758 (errcode(ERRCODE_SYNTAX_ERROR),
759 errmsg("cannot specify %s in BINARY mode", "DEFAULT")));
760
761 /* Set defaults for omitted options */
762 if (!opts_out->delim)
763 opts_out->delim = opts_out->csv_mode ? "," : "\t";
764
765 if (!opts_out->null_print)
766 opts_out->null_print = opts_out->csv_mode ? "" : "\\N";
767 opts_out->null_print_len = strlen(opts_out->null_print);
768
769 if (opts_out->csv_mode)
770 {
771 if (!opts_out->quote)
772 opts_out->quote = "\"";
773 if (!opts_out->escape)
774 opts_out->escape = opts_out->quote;
775 }
776
777 /* Only single-byte delimiter strings are supported. */
778 if (strlen(opts_out->delim) != 1)
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 if (strchr(opts_out->delim, '\r') != NULL ||
785 strchr(opts_out->delim, '\n') != NULL)
787 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
788 errmsg("COPY delimiter cannot be newline or carriage return")));
789
790 if (strchr(opts_out->null_print, '\r') != NULL ||
791 strchr(opts_out->null_print, '\n') != NULL)
793 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
794 errmsg("COPY null representation cannot use newline or carriage return")));
795
796 if (opts_out->default_print)
797 {
798 opts_out->default_print_len = strlen(opts_out->default_print);
799
800 if (strchr(opts_out->default_print, '\r') != NULL ||
801 strchr(opts_out->default_print, '\n') != NULL)
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 if (!opts_out->csv_mode &&
818 strchr("\\.abcdefghijklmnopqrstuvwxyz0123456789",
819 opts_out->delim[0]) != NULL)
821 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
822 errmsg("COPY delimiter cannot be \"%s\"", opts_out->delim)));
823
824 /* Check header */
825 if (opts_out->binary && opts_out->header_line != COPY_HEADER_FALSE)
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 if (!opts_out->csv_mode && opts_out->quote != NULL)
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 if (opts_out->csv_mode && strlen(opts_out->quote) != 1)
840 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
841 errmsg("COPY quote must be a single one-byte character")));
842
843 if (opts_out->csv_mode && opts_out->delim[0] == opts_out->quote[0])
845 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
846 errmsg("COPY delimiter and quote must be different")));
847
848 /* Check escape */
849 if (!opts_out->csv_mode && opts_out->escape != NULL)
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 if (opts_out->csv_mode && strlen(opts_out->escape) != 1)
857 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
858 errmsg("COPY escape must be a single one-byte character")));
859
860 /* Check force_quote */
861 if (!opts_out->csv_mode && (opts_out->force_quote || opts_out->force_quote_all))
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 if ((opts_out->force_quote || opts_out->force_quote_all) && is_from)
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 if (!opts_out->csv_mode && (opts_out->force_notnull != NIL ||
876 opts_out->force_notnull_all))
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 if ((opts_out->force_notnull != NIL || opts_out->force_notnull_all) &&
882 !is_from)
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 if (!opts_out->csv_mode && (opts_out->force_null != NIL ||
892 opts_out->force_null_all))
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 if ((opts_out->force_null != NIL || opts_out->force_null_all) &&
899 !is_from)
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 if (strchr(opts_out->null_print, opts_out->delim[0]) != NULL)
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 if (opts_out->csv_mode &&
917 strchr(opts_out->null_print, opts_out->quote[0]) != NULL)
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 if (opts_out->freeze && !is_from)
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 if (opts_out->default_print)
934 {
935 if (!is_from)
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 if (strchr(opts_out->default_print, opts_out->delim[0]) != NULL)
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 if (opts_out->csv_mode &&
953 strchr(opts_out->default_print, opts_out->quote[0]) != NULL)
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 if (opts_out->null_print_len == opts_out->default_print_len &&
962 strncmp(opts_out->null_print, opts_out->default_print,
963 opts_out->null_print_len) == 0)
965 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
966 errmsg("NULL specification and DEFAULT specification cannot be the same")));
967 }
968 /* Check on_error */
969 if (opts_out->binary && opts_out->on_error != COPY_ON_ERROR_STOP)
971 (errcode(ERRCODE_SYNTAX_ERROR),
972 errmsg("only ON_ERROR STOP is allowed in BINARY mode")));
973
974 if (opts_out->reject_limit && !opts_out->on_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}
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 */
997List *
998CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
999{
1000 List *attnums = NIL;
1001
1002 if (attnamelist == NIL)
1003 {
1004 /* Generate default column list */
1005 int attr_count = tupDesc->natts;
1006 int i;
1007
1008 for (i = 0; i < attr_count; i++)
1009 {
1010 CompactAttribute *attr = TupleDescCompactAttr(tupDesc, i);
1011
1012 if (attr->attisdropped || attr->attgenerated)
1013 continue;
1014 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 foreach(l, attnamelist)
1023 {
1024 char *name = strVal(lfirst(l));
1025 int attnum;
1026 int i;
1027
1028 /* Lookup column name */
1030 for (i = 0; i < tupDesc->natts; i++)
1031 {
1032 Form_pg_attribute att = TupleDescAttr(tupDesc, i);
1033
1034 if (att->attisdropped)
1035 continue;
1036 if (namestrcmp(&(att->attname), name) == 0)
1037 {
1038 if (att->attgenerated)
1039 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 attnum = att->attnum;
1045 break;
1046 }
1047 }
1049 {
1050 if (rel != NULL)
1051 ereport(ERROR,
1052 (errcode(ERRCODE_UNDEFINED_COLUMN),
1053 errmsg("column \"%s\" of relation \"%s\" does not exist",
1055 else
1056 ereport(ERROR,
1057 (errcode(ERRCODE_UNDEFINED_COLUMN),
1058 errmsg("column \"%s\" does not exist",
1059 name)));
1060 }
1061 /* Check for duplicates */
1062 if (list_member_int(attnums, attnum))
1063 ereport(ERROR,
1064 (errcode(ERRCODE_DUPLICATE_COLUMN),
1065 errmsg("column \"%s\" specified more than once",
1066 name)));
1067 attnums = lappend_int(attnums, attnum);
1068 }
1069 }
1070
1071 return attnums;
1072}
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:5284
int16 AttrNumber
Definition: attnum.h:21
#define InvalidAttrNumber
Definition: attnum.h:23
void DoCopy(ParseState *pstate, const CopyStmt *stmt, int stmt_location, int stmt_len, uint64 *processed)
Definition: copy.c:62
static int defGetCopyHeaderOption(DefElem *def, bool is_from)
Definition: copy.c:374
static int64 defGetCopyRejectLimitOption(DefElem *def)
Definition: copy.c:482
List * CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
Definition: copy.c:998
static CopyOnErrorChoice defGetCopyOnErrorChoice(DefElem *def, ParseState *pstate, bool is_from)
Definition: copy.c:446
void ProcessCopyOptions(ParseState *pstate, CopyFormatOptions *opts_out, bool is_from, List *options)
Definition: copy.c:549
static CopyLogVerbosityChoice defGetCopyLogVerbosityChoice(DefElem *def, ParseState *pstate)
Definition: copy.c:509
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1306
Bitmapset * bms_add_range(Bitmapset *a, int lower, int upper)
Definition: bitmapset.c:1019
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition: bitmapset.c:868
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
int64_t int64
Definition: c.h:540
uint64_t uint64
Definition: c.h:544
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2262
CopyFromState BeginCopyFrom(ParseState *pstate, Relation rel, Node *whereClause, const char *filename, bool is_program, copy_data_source_cb data_source_cb, List *attnamelist, List *options)
Definition: copyfrom.c:1529
uint64 CopyFrom(CopyFromState cstate)
Definition: copyfrom.c:779
void EndCopyFrom(CopyFromState cstate)
Definition: copyfrom.c:1914
uint64 DoCopyTo(CopyToState cstate)
Definition: copyto.c:1061
CopyToState BeginCopyTo(ParseState *pstate, Relation rel, RawStmt *raw_query, Oid queryRelId, const char *filename, bool is_program, copy_data_dest_cb data_dest_cb, List *attnamelist, List *options)
Definition: copyto.c:632
void EndCopyTo(CopyToState cstate)
Definition: copyto.c:1040
char * defGetString(DefElem *def)
Definition: define.c:35
bool defGetBoolean(DefElem *def)
Definition: define.c:94
int64 defGetInt64(DefElem *def)
Definition: define.c:173
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:371
struct cursor * cur
Definition: ecpg.c:29
int errdetail(const char *fmt,...)
Definition: elog.c:1216
int errhint(const char *fmt,...)
Definition: elog.c:1330
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:150
bool ExecCheckPermissions(List *rangeTable, List *rteperminfos, bool ereport_on_violation)
Definition: execMain.c:582
Assert(PointerIsAligned(start, uint64))
CopyOnErrorChoice
Definition: copy.h:35
@ COPY_ON_ERROR_IGNORE
Definition: copy.h:37
@ COPY_ON_ERROR_STOP
Definition: copy.h:36
CopyLogVerbosityChoice
Definition: copy.h:44
@ COPY_LOG_VERBOSITY_SILENT
Definition: copy.h:45
@ COPY_LOG_VERBOSITY_VERBOSE
Definition: copy.h:48
@ COPY_LOG_VERBOSITY_DEFAULT
Definition: copy.h:46
#define COPY_HEADER_MATCH
Definition: copy.h:26
#define COPY_HEADER_FALSE
Definition: copy.h:27
#define COPY_HEADER_TRUE
Definition: copy.h:28
#define stmt
Definition: indent_codes.h:59
int i
Definition: isn.c:77
List * lappend(List *list, void *datum)
Definition: list.c:339
List * lappend_int(List *list, int datum)
Definition: list.c:357
bool list_member_int(const List *list, int datum)
Definition: list.c:702
int LOCKMODE
Definition: lockdefs.h:26
#define NoLock
Definition: lockdefs.h:34
#define AccessShareLock
Definition: lockdefs.h:36
#define RowExclusiveLock
Definition: lockdefs.h:38
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:920
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3533
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:473
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:810
char * pstrdup(const char *in)
Definition: mcxt.c:1759
void * palloc0(Size size)
Definition: mcxt.c:1395
Oid GetUserId(void)
Definition: miscinit.c:469
int namestrcmp(Name name, const char *str)
Definition: name.c:247
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
#define nodeTag(nodeptr)
Definition: nodes.h:139
#define makeNode(_type_)
Definition: nodes.h:161
#define castNode(_type_, nodeptr)
Definition: nodes.h:182
int64 pg_strtoint64(const char *s)
Definition: numutils.c:644
Node * coerce_to_boolean(ParseState *pstate, Node *node, const char *constructName)
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:119
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
@ EXPR_KIND_COPY_WHERE
Definition: parse_node.h:82
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
#define ACL_INSERT
Definition: parsenodes.h:76
#define ACL_SELECT
Definition: parsenodes.h:77
int16 attnum
Definition: pg_attribute.h:74
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:202
#define lfirst(lc)
Definition: pg_list.h:172
#define lfirst_node(type, lc)
Definition: pg_list.h:176
#define NIL
Definition: pg_list.h:68
#define lfirst_int(lc)
Definition: pg_list.h:173
#define list_make1(x1)
Definition: pg_list.h:212
#define pg_char_to_encoding
Definition: pg_wchar.h:629
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
Expr * canonicalize_qual(Expr *qual, bool is_check)
Definition: prepqual.c:293
#define RelationGetRelid(relation)
Definition: rel.h:515
#define RelationGetDescr(relation)
Definition: rel.h:541
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:521
#define RelationGetRelationName(relation)
Definition: rel.h:549
#define RelationGetNamespace(relation)
Definition: rel.h:556
int check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
Definition: rls.c:52
@ RLS_ENABLED
Definition: rls.h:45
ParseLoc location
Definition: parsenodes.h:312
List * fields
Definition: parsenodes.h:311
bool attgenerated
Definition: tupdesc.h:78
bool attisdropped
Definition: tupdesc.h:77
int header_line
Definition: copy.h:64
int default_print_len
Definition: copy.h:70
bool force_notnull_all
Definition: copy.h:78
bool force_quote_all
Definition: copy.h:75
bool freeze
Definition: copy.h:62
bool binary
Definition: copy.h:61
int null_print_len
Definition: copy.h:67
bool convert_selectively
Definition: copy.h:83
CopyLogVerbosityChoice log_verbosity
Definition: copy.h:85
char * quote
Definition: copy.h:72
CopyOnErrorChoice on_error
Definition: copy.h:84
List * force_quote
Definition: copy.h:74
char * escape
Definition: copy.h:73
char * null_print
Definition: copy.h:66
List * force_null
Definition: copy.h:80
char * delim
Definition: copy.h:71
int64 reject_limit
Definition: copy.h:86
List * convert_select
Definition: copy.h:87
bool force_null_all
Definition: copy.h:81
bool csv_mode
Definition: copy.h:63
int file_encoding
Definition: copy.h:59
char * default_print
Definition: copy.h:69
List * force_notnull
Definition: copy.h:77
char * defname
Definition: parsenodes.h:843
ParseLoc location
Definition: parsenodes.h:847
Node * arg
Definition: parsenodes.h:844
Definition: pg_list.h:54
Definition: nodes.h:135
RTEPermissionInfo * p_perminfo
Definition: parse_node.h:297
List * p_rtable
Definition: parse_node.h:196
Bitmapset * selectedCols
Definition: parsenodes.h:1324
AclMode requiredPerms
Definition: parsenodes.h:1322
Bitmapset * insertedCols
Definition: parsenodes.h:1325
bool inh
Definition: primnodes.h:86
ParseLoc stmt_location
Definition: parsenodes.h:2089
ParseLoc stmt_len
Definition: parsenodes.h:2090
Node * stmt
Definition: parsenodes.h:2088
bool rd_islocaltemp
Definition: rel.h:61
Form_pg_class rd_rel
Definition: rel.h:111
Node * val
Definition: parsenodes.h:547
ParseLoc location
Definition: parsenodes.h:548
List * indirection
Definition: parsenodes.h:546
char * name
Definition: parsenodes.h:545
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: table.c:83
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:160
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:175
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:406
#define intVal(v)
Definition: value.h:79
#define strVal(v)
Definition: value.h:82
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:296
const char * name
#define select(n, r, w, e, timeout)
Definition: win32_port.h:503
bool XactReadOnly
Definition: xact.c:83