PostgreSQL Source Code  git master
copy.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <unistd.h>
#include <sys/stat.h>
#include "access/sysattr.h"
#include "access/table.h"
#include "access/xact.h"
#include "catalog/pg_authid.h"
#include "commands/copy.h"
#include "commands/defrem.h"
#include "executor/executor.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "optimizer/optimizer.h"
#include "parser/parse_coerce.h"
#include "parser/parse_collate.h"
#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
#include "rewrite/rewriteHandler.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/rls.h"
Include dependency graph for copy.c:

Go to the source code of this file.

Functions

void DoCopy (ParseState *pstate, const CopyStmt *stmt, int stmt_location, int stmt_len, uint64 *processed)
 
void ProcessCopyOptions (ParseState *pstate, CopyFormatOptions *opts_out, bool is_from, List *options)
 
ListCopyGetAttnums (TupleDesc tupDesc, Relation rel, List *attnamelist)
 

Function Documentation

◆ CopyGetAttnums()

List* CopyGetAttnums ( TupleDesc  tupDesc,
Relation  rel,
List attnamelist 
)

Definition at line 686 of file copy.c.

References attnum, ereport, errcode(), errdetail(), errmsg(), ERROR, i, InvalidAttrNumber, lappend_int(), lfirst, list_member_int(), name, namestrcmp(), TupleDescData::natts, NIL, RelationGetRelationName, strVal, and TupleDescAttr.

Referenced by BeginCopyFrom(), BeginCopyTo(), and DoCopy().

687 {
688  List *attnums = NIL;
689 
690  if (attnamelist == NIL)
691  {
692  /* Generate default column list */
693  int attr_count = tupDesc->natts;
694  int i;
695 
696  for (i = 0; i < attr_count; i++)
697  {
698  if (TupleDescAttr(tupDesc, i)->attisdropped)
699  continue;
700  if (TupleDescAttr(tupDesc, i)->attgenerated)
701  continue;
702  attnums = lappend_int(attnums, i + 1);
703  }
704  }
705  else
706  {
707  /* Validate the user-supplied list and extract attnums */
708  ListCell *l;
709 
710  foreach(l, attnamelist)
711  {
712  char *name = strVal(lfirst(l));
713  int attnum;
714  int i;
715 
716  /* Lookup column name */
717  attnum = InvalidAttrNumber;
718  for (i = 0; i < tupDesc->natts; i++)
719  {
720  Form_pg_attribute att = TupleDescAttr(tupDesc, i);
721 
722  if (att->attisdropped)
723  continue;
724  if (namestrcmp(&(att->attname), name) == 0)
725  {
726  if (att->attgenerated)
727  ereport(ERROR,
728  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
729  errmsg("column \"%s\" is a generated column",
730  name),
731  errdetail("Generated columns cannot be used in COPY.")));
732  attnum = att->attnum;
733  break;
734  }
735  }
736  if (attnum == InvalidAttrNumber)
737  {
738  if (rel != NULL)
739  ereport(ERROR,
740  (errcode(ERRCODE_UNDEFINED_COLUMN),
741  errmsg("column \"%s\" of relation \"%s\" does not exist",
742  name, RelationGetRelationName(rel))));
743  else
744  ereport(ERROR,
745  (errcode(ERRCODE_UNDEFINED_COLUMN),
746  errmsg("column \"%s\" does not exist",
747  name)));
748  }
749  /* Check for duplicates */
750  if (list_member_int(attnums, attnum))
751  ereport(ERROR,
752  (errcode(ERRCODE_DUPLICATE_COLUMN),
753  errmsg("column \"%s\" specified more than once",
754  name)));
755  attnums = lappend_int(attnums, attnum);
756  }
757  }
758 
759  return attnums;
760 }
#define NIL
Definition: pg_list.h:65
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:691
int namestrcmp(Name name, const char *str)
Definition: name.c:247
#define ERROR
Definition: elog.h:43
bool list_member_int(const List *list, int datum)
Definition: list.c:654
int errdetail(const char *fmt,...)
Definition: elog.c:1035
#define RelationGetRelationName(relation)
Definition: rel.h:491
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
List * lappend_int(List *list, int datum)
Definition: list.c:339
int16 attnum
Definition: pg_attribute.h:79
#define ereport(elevel,...)
Definition: elog.h:155
#define lfirst(lc)
Definition: pg_list.h:169
const char * name
Definition: encode.c:561
#define InvalidAttrNumber
Definition: attnum.h:23
int errmsg(const char *fmt,...)
Definition: elog.c:902
int i
Definition: pg_list.h:50

◆ DoCopy()

void DoCopy ( ParseState pstate,
const CopyStmt stmt,
int  stmt_location,
int  stmt_len,
uint64 *  processed 
)

Definition at line 64 of file copy.c.

References AccessShareLock, ACL_INSERT, ACL_SELECT, addNSItemToQuery(), addRangeTableEntryForRelation(), Assert, assign_expr_collations(), CopyStmt::attlist, BeginCopyFrom(), BeginCopyTo(), bms_add_member(), canonicalize_qual(), check_enable_rls(), coerce_to_boolean(), CopyFrom(), CopyGetAttnums(), cur, DoCopyTo(), EndCopyFrom(), EndCopyTo(), ereport, errcode(), errhint(), errmsg(), ERROR, eval_const_expressions(), ExecCheckRTPerms(), EXPR_KIND_COPY_WHERE, ColumnRef::fields, CopyStmt::filename, FirstLowInvalidHeapAttributeNumber, SelectStmt::fromClause, get_namespace_name(), GetUserId(), ResTarget::indirection, RangeTblEntry::insertedCols, InvalidOid, CopyStmt::is_from, is_member_of_role(), CopyStmt::is_program, lappend(), lfirst, lfirst_int, list_make1, ColumnRef::location, ResTarget::location, make_ands_implicit(), makeNode, makeRangeVar(), ResTarget::name, NIL, NoLock, CopyStmt::options, ParseState::p_rtable, ParseNamespaceItem::p_rte, PreventCommandIfReadOnly(), pstrdup(), CopyStmt::query, RelationData::rd_islocaltemp, CopyStmt::relation, RelationGetDescr, RelationGetNamespace, RelationGetRelationName, RelationGetRelid, RangeTblEntry::relid, RangeTblEntry::requiredPerms, RLS_ENABLED, RowExclusiveLock, select, RangeTblEntry::selectedCols, RawStmt::stmt, RawStmt::stmt_len, RawStmt::stmt_location, table_close(), table_openrv(), SelectStmt::targetList, transformExpr(), ResTarget::val, CopyStmt::whereClause, and XactReadOnly.

Referenced by standard_ProcessUtility().

67 {
68  bool is_from = stmt->is_from;
69  bool pipe = (stmt->filename == NULL);
70  Relation rel;
71  Oid relid;
72  RawStmt *query = NULL;
73  Node *whereClause = NULL;
74 
75  /*
76  * Disallow COPY to/from file or program except to users with the
77  * appropriate role.
78  */
79  if (!pipe)
80  {
81  if (stmt->is_program)
82  {
83  if (!is_member_of_role(GetUserId(), DEFAULT_ROLE_EXECUTE_SERVER_PROGRAM))
84  ereport(ERROR,
85  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
86  errmsg("must be superuser or a member of the pg_execute_server_program role to COPY to or from an external 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 && !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_SERVER_FILES))
93  ereport(ERROR,
94  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
95  errmsg("must be superuser or a member of the pg_read_server_files role to COPY from a file"),
96  errhint("Anyone can COPY to stdout or from stdin. "
97  "psql's \\copy command also works for anyone.")));
98 
99  if (!is_from && !is_member_of_role(GetUserId(), DEFAULT_ROLE_WRITE_SERVER_FILES))
100  ereport(ERROR,
101  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
102  errmsg("must be superuser or a member of the pg_write_server_files role to COPY to a file"),
103  errhint("Anyone can COPY to stdout or from stdin. "
104  "psql's \\copy command also works for anyone.")));
105  }
106  }
107 
108  if (stmt->relation)
109  {
110  LOCKMODE lockmode = is_from ? RowExclusiveLock : AccessShareLock;
111  ParseNamespaceItem *nsitem;
112  RangeTblEntry *rte;
113  TupleDesc tupDesc;
114  List *attnums;
115  ListCell *cur;
116 
117  Assert(!stmt->query);
118 
119  /* Open and lock the relation, using the appropriate lock type. */
120  rel = table_openrv(stmt->relation, lockmode);
121 
122  relid = RelationGetRelid(rel);
123 
124  nsitem = addRangeTableEntryForRelation(pstate, rel, lockmode,
125  NULL, false, false);
126  rte = nsitem->p_rte;
127  rte->requiredPerms = (is_from ? ACL_INSERT : ACL_SELECT);
128 
129  if (stmt->whereClause)
130  {
131  /* add nsitem to query namespace */
132  addNSItemToQuery(pstate, nsitem, false, true, true);
133 
134  /* Transform the raw expression tree */
135  whereClause = transformExpr(pstate, stmt->whereClause, EXPR_KIND_COPY_WHERE);
136 
137  /* Make sure it yields a boolean result. */
138  whereClause = coerce_to_boolean(pstate, whereClause, "WHERE");
139 
140  /* we have to fix its collations too */
141  assign_expr_collations(pstate, whereClause);
142 
143  whereClause = eval_const_expressions(NULL, whereClause);
144 
145  whereClause = (Node *) canonicalize_qual((Expr *) whereClause, false);
146  whereClause = (Node *) make_ands_implicit((Expr *) whereClause);
147  }
148 
149  tupDesc = RelationGetDescr(rel);
150  attnums = CopyGetAttnums(tupDesc, rel, stmt->attlist);
151  foreach(cur, attnums)
152  {
153  int attno = lfirst_int(cur) -
155 
156  if (is_from)
157  rte->insertedCols = bms_add_member(rte->insertedCols, attno);
158  else
159  rte->selectedCols = bms_add_member(rte->selectedCols, attno);
160  }
161  ExecCheckRTPerms(pstate->p_rtable, true);
162 
163  /*
164  * Permission check for row security policies.
165  *
166  * check_enable_rls will ereport(ERROR) if the user has requested
167  * something invalid and will otherwise indicate if we should enable
168  * RLS (returns RLS_ENABLED) or not for this COPY statement.
169  *
170  * If the relation has a row security policy and we are to apply it
171  * then perform a "query" copy and allow the normal query processing
172  * to handle the policies.
173  *
174  * If RLS is not enabled for this, then just fall through to the
175  * normal non-filtering relation handling.
176  */
177  if (check_enable_rls(rte->relid, InvalidOid, false) == RLS_ENABLED)
178  {
180  ColumnRef *cr;
181  ResTarget *target;
182  RangeVar *from;
183  List *targetList = NIL;
184 
185  if (is_from)
186  ereport(ERROR,
187  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
188  errmsg("COPY FROM not supported with row-level security"),
189  errhint("Use INSERT statements instead.")));
190 
191  /*
192  * Build target list
193  *
194  * If no columns are specified in the attribute list of the COPY
195  * command, then the target list is 'all' columns. Therefore, '*'
196  * should be used as the target list for the resulting SELECT
197  * statement.
198  *
199  * In the case that columns are specified in the attribute list,
200  * create a ColumnRef and ResTarget for each column and add them
201  * to the target list for the resulting SELECT statement.
202  */
203  if (!stmt->attlist)
204  {
205  cr = makeNode(ColumnRef);
207  cr->location = -1;
208 
209  target = makeNode(ResTarget);
210  target->name = NULL;
211  target->indirection = NIL;
212  target->val = (Node *) cr;
213  target->location = -1;
214 
215  targetList = list_make1(target);
216  }
217  else
218  {
219  ListCell *lc;
220 
221  foreach(lc, stmt->attlist)
222  {
223  /*
224  * Build the ColumnRef for each column. The ColumnRef
225  * 'fields' property is a String 'Value' node (see
226  * nodes/value.h) that corresponds to the column name
227  * respectively.
228  */
229  cr = makeNode(ColumnRef);
230  cr->fields = list_make1(lfirst(lc));
231  cr->location = -1;
232 
233  /* Build the ResTarget and add the ColumnRef to it. */
234  target = makeNode(ResTarget);
235  target->name = NULL;
236  target->indirection = NIL;
237  target->val = (Node *) cr;
238  target->location = -1;
239 
240  /* Add each column to the SELECT statement's target list */
241  targetList = lappend(targetList, target);
242  }
243  }
244 
245  /*
246  * Build RangeVar for from clause, fully qualified based on the
247  * relation which we have opened and locked.
248  */
251  -1);
252 
253  /* Build query */
254  select = makeNode(SelectStmt);
255  select->targetList = targetList;
256  select->fromClause = list_make1(from);
257 
258  query = makeNode(RawStmt);
259  query->stmt = (Node *) select;
260  query->stmt_location = stmt_location;
261  query->stmt_len = stmt_len;
262 
263  /*
264  * Close the relation for now, but keep the lock on it to prevent
265  * changes between now and when we start the query-based COPY.
266  *
267  * We'll reopen it later as part of the query-based COPY.
268  */
269  table_close(rel, NoLock);
270  rel = NULL;
271  }
272  }
273  else
274  {
275  Assert(stmt->query);
276 
277  query = makeNode(RawStmt);
278  query->stmt = stmt->query;
279  query->stmt_location = stmt_location;
280  query->stmt_len = stmt_len;
281 
282  relid = InvalidOid;
283  rel = NULL;
284  }
285 
286  if (is_from)
287  {
288  CopyFromState cstate;
289 
290  Assert(rel);
291 
292  /* check read-only transaction and parallel mode */
293  if (XactReadOnly && !rel->rd_islocaltemp)
294  PreventCommandIfReadOnly("COPY FROM");
295 
296  cstate = BeginCopyFrom(pstate, rel, whereClause,
297  stmt->filename, stmt->is_program,
298  NULL, stmt->attlist, stmt->options);
299  *processed = CopyFrom(cstate); /* copy from file to database */
300  EndCopyFrom(cstate);
301  }
302  else
303  {
304  CopyToState cstate;
305 
306  cstate = BeginCopyTo(pstate, rel, query, relid,
307  stmt->filename, stmt->is_program,
308  stmt->attlist, stmt->options);
309  *processed = DoCopyTo(cstate); /* copy from database to file */
310  EndCopyTo(cstate);
311  }
312 
313  if (rel != NULL)
314  table_close(rel, NoLock);
315 }
List * indirection
Definition: parsenodes.h:443
#define NIL
Definition: pg_list.h:65
Node * whereClause
Definition: parsenodes.h:2016
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Node * val
Definition: parsenodes.h:444
int errhint(const char *fmt,...)
Definition: elog.c:1149
List * attlist
Definition: parsenodes.h:2010
List * fromClause
Definition: parsenodes.h:1603
#define RelationGetDescr(relation)
Definition: rel.h:483
int LOCKMODE
Definition: lockdefs.h:26
char * name
Definition: parsenodes.h:442
Oid GetUserId(void)
Definition: miscinit.c:476
uint64 CopyFrom(CopyFromState cstate)
Definition: copyfrom.c:522
char * pstrdup(const char *in)
Definition: mcxt.c:1187
bool rd_islocaltemp
Definition: rel.h:60
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:144
#define AccessShareLock
Definition: lockdefs.h:36
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
Definition: nodes.h:527
struct cursor * cur
Definition: ecpg.c:28
int errcode(int sqlerrcode)
Definition: elog.c:691
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:1999
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
AclMode requiredPerms
Definition: parsenodes.h:1124
unsigned int Oid
Definition: postgres_ext.h:31
bool is_program
Definition: parsenodes.h:2013
void EndCopyTo(CopyToState cstate)
Definition: copyto.c:808
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
int location
Definition: parsenodes.h:237
int location
Definition: parsenodes.h:445
#define list_make1(x1)
Definition: pg_list.h:206
void assign_expr_collations(ParseState *pstate, Node *expr)
RangeTblEntry * p_rte
Definition: parse_node.h:257
Bitmapset * selectedCols
Definition: parsenodes.h:1126
#define ERROR
Definition: elog.h:43
#define lfirst_int(lc)
Definition: pg_list.h:170
RangeVar * relation
Definition: parsenodes.h:2007
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3196
Node * stmt
Definition: parsenodes.h:1513
#define NoLock
Definition: lockdefs.h:34
List * targetList
Definition: parsenodes.h:1602
#define RowExclusiveLock
Definition: lockdefs.h:38
Expr * canonicalize_qual(Expr *qual, bool is_check)
Definition: prepqual.c:292
List * options
Definition: parsenodes.h:2015
#define select(n, r, w, e, timeout)
Definition: win32_port.h:464
#define RelationGetRelationName(relation)
Definition: rel.h:491
List * lappend(List *list, void *datum)
Definition: list.c:321
#define ACL_SELECT
Definition: parsenodes.h:75
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:719
int stmt_len
Definition: parsenodes.h:1515
int stmt_location
Definition: parsenodes.h:1514
Relation table_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: table.c:102
#define InvalidOid
Definition: postgres_ext.h:36
CopyToState BeginCopyTo(ParseState *pstate, Relation rel, RawStmt *raw_query, Oid queryRelId, const char *filename, bool is_program, List *attnamelist, List *options)
Definition: copyto.c:374
#define ereport(elevel,...)
Definition: elog.h:155
bool XactReadOnly
Definition: xact.c:78
bool is_member_of_role(Oid member, Oid role)
Definition: acl.c:4916
int check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
Definition: rls.c:52
#define makeNode(_type_)
Definition: nodes.h:575
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:1176
#define Assert(condition)
Definition: c.h:800
#define lfirst(lc)
Definition: pg_list.h:169
#define ACL_INSERT
Definition: parsenodes.h:74
List * CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
Definition: copy.c:686
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:407
void EndCopyFrom(CopyFromState cstate)
Definition: copyfrom.c:1509
Node * query
Definition: parsenodes.h:2008
bool is_from
Definition: parsenodes.h:2012
int errmsg(const char *fmt,...)
Definition: elog.c:902
Bitmapset * insertedCols
Definition: parsenodes.h:1127
bool ExecCheckRTPerms(List *rangeTable, bool ereport_on_violation)
Definition: execMain.c:571
char * filename
Definition: parsenodes.h:2014
uint64 DoCopyTo(CopyToState cstate)
Definition: copyto.c:773
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:457
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:422
List * fields
Definition: parsenodes.h:236
#define RelationGetNamespace(relation)
Definition: rel.h:498
List * p_rtable
Definition: parse_node.h:180
Node * coerce_to_boolean(ParseState *pstate, Node *node, const char *constructName)

◆ ProcessCopyOptions()

void ProcessCopyOptions ( ParseState pstate,
CopyFormatOptions opts_out,
bool  is_from,
List options 
)

Definition at line 334 of file copy.c.

References DefElem::arg, CopyFormatOptions::binary, castNode, CopyFormatOptions::convert_select, CopyFormatOptions::convert_selectively, CopyFormatOptions::csv_mode, defGetBoolean(), defGetString(), DefElem::defname, CopyFormatOptions::delim, ereport, errcode(), errmsg(), ERROR, CopyFormatOptions::escape, CopyFormatOptions::file_encoding, CopyFormatOptions::force_notnull, CopyFormatOptions::force_null, CopyFormatOptions::force_quote, CopyFormatOptions::force_quote_all, CopyFormatOptions::freeze, CopyFormatOptions::header_line, IsA, lfirst_node, DefElem::location, NIL, CopyFormatOptions::null_print, CopyFormatOptions::null_print_len, palloc0(), parser_errposition(), pg_char_to_encoding(), and CopyFormatOptions::quote.

Referenced by BeginCopyFrom(), BeginCopyTo(), and file_fdw_validator().

338 {
339  bool format_specified = false;
340  bool freeze_specified = false;
341  bool header_specified = false;
342  ListCell *option;
343 
344  /* Support external use for option sanity checking */
345  if (opts_out == NULL)
346  opts_out = (CopyFormatOptions *) palloc0(sizeof(CopyFormatOptions));
347 
348  opts_out->file_encoding = -1;
349 
350  /* Extract options from the statement node tree */
351  foreach(option, options)
352  {
353  DefElem *defel = lfirst_node(DefElem, option);
354 
355  if (strcmp(defel->defname, "format") == 0)
356  {
357  char *fmt = defGetString(defel);
358 
359  if (format_specified)
360  ereport(ERROR,
361  (errcode(ERRCODE_SYNTAX_ERROR),
362  errmsg("conflicting or redundant options"),
363  parser_errposition(pstate, defel->location)));
364  format_specified = true;
365  if (strcmp(fmt, "text") == 0)
366  /* default format */ ;
367  else if (strcmp(fmt, "csv") == 0)
368  opts_out->csv_mode = true;
369  else if (strcmp(fmt, "binary") == 0)
370  opts_out->binary = true;
371  else
372  ereport(ERROR,
373  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
374  errmsg("COPY format \"%s\" not recognized", fmt),
375  parser_errposition(pstate, defel->location)));
376  }
377  else if (strcmp(defel->defname, "freeze") == 0)
378  {
379  if (freeze_specified)
380  ereport(ERROR,
381  (errcode(ERRCODE_SYNTAX_ERROR),
382  errmsg("conflicting or redundant options"),
383  parser_errposition(pstate, defel->location)));
384  freeze_specified = true;
385  opts_out->freeze = defGetBoolean(defel);
386  }
387  else if (strcmp(defel->defname, "delimiter") == 0)
388  {
389  if (opts_out->delim)
390  ereport(ERROR,
391  (errcode(ERRCODE_SYNTAX_ERROR),
392  errmsg("conflicting or redundant options"),
393  parser_errposition(pstate, defel->location)));
394  opts_out->delim = defGetString(defel);
395  }
396  else if (strcmp(defel->defname, "null") == 0)
397  {
398  if (opts_out->null_print)
399  ereport(ERROR,
400  (errcode(ERRCODE_SYNTAX_ERROR),
401  errmsg("conflicting or redundant options"),
402  parser_errposition(pstate, defel->location)));
403  opts_out->null_print = defGetString(defel);
404  }
405  else if (strcmp(defel->defname, "header") == 0)
406  {
407  if (header_specified)
408  ereport(ERROR,
409  (errcode(ERRCODE_SYNTAX_ERROR),
410  errmsg("conflicting or redundant options"),
411  parser_errposition(pstate, defel->location)));
412  header_specified = true;
413  opts_out->header_line = defGetBoolean(defel);
414  }
415  else if (strcmp(defel->defname, "quote") == 0)
416  {
417  if (opts_out->quote)
418  ereport(ERROR,
419  (errcode(ERRCODE_SYNTAX_ERROR),
420  errmsg("conflicting or redundant options"),
421  parser_errposition(pstate, defel->location)));
422  opts_out->quote = defGetString(defel);
423  }
424  else if (strcmp(defel->defname, "escape") == 0)
425  {
426  if (opts_out->escape)
427  ereport(ERROR,
428  (errcode(ERRCODE_SYNTAX_ERROR),
429  errmsg("conflicting or redundant options"),
430  parser_errposition(pstate, defel->location)));
431  opts_out->escape = defGetString(defel);
432  }
433  else if (strcmp(defel->defname, "force_quote") == 0)
434  {
435  if (opts_out->force_quote || opts_out->force_quote_all)
436  ereport(ERROR,
437  (errcode(ERRCODE_SYNTAX_ERROR),
438  errmsg("conflicting or redundant options"),
439  parser_errposition(pstate, defel->location)));
440  if (defel->arg && IsA(defel->arg, A_Star))
441  opts_out->force_quote_all = true;
442  else if (defel->arg && IsA(defel->arg, List))
443  opts_out->force_quote = castNode(List, defel->arg);
444  else
445  ereport(ERROR,
446  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
447  errmsg("argument to option \"%s\" must be a list of column names",
448  defel->defname),
449  parser_errposition(pstate, defel->location)));
450  }
451  else if (strcmp(defel->defname, "force_not_null") == 0)
452  {
453  if (opts_out->force_notnull)
454  ereport(ERROR,
455  (errcode(ERRCODE_SYNTAX_ERROR),
456  errmsg("conflicting or redundant options"),
457  parser_errposition(pstate, defel->location)));
458  if (defel->arg && IsA(defel->arg, List))
459  opts_out->force_notnull = castNode(List, defel->arg);
460  else
461  ereport(ERROR,
462  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
463  errmsg("argument to option \"%s\" must be a list of column names",
464  defel->defname),
465  parser_errposition(pstate, defel->location)));
466  }
467  else if (strcmp(defel->defname, "force_null") == 0)
468  {
469  if (opts_out->force_null)
470  ereport(ERROR,
471  (errcode(ERRCODE_SYNTAX_ERROR),
472  errmsg("conflicting or redundant options")));
473  if (defel->arg && IsA(defel->arg, List))
474  opts_out->force_null = castNode(List, defel->arg);
475  else
476  ereport(ERROR,
477  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
478  errmsg("argument to option \"%s\" must be a list of column names",
479  defel->defname),
480  parser_errposition(pstate, defel->location)));
481  }
482  else if (strcmp(defel->defname, "convert_selectively") == 0)
483  {
484  /*
485  * Undocumented, not-accessible-from-SQL option: convert only the
486  * named columns to binary form, storing the rest as NULLs. It's
487  * allowed for the column list to be NIL.
488  */
489  if (opts_out->convert_selectively)
490  ereport(ERROR,
491  (errcode(ERRCODE_SYNTAX_ERROR),
492  errmsg("conflicting or redundant options"),
493  parser_errposition(pstate, defel->location)));
494  opts_out->convert_selectively = true;
495  if (defel->arg == NULL || IsA(defel->arg, List))
496  opts_out->convert_select = castNode(List, defel->arg);
497  else
498  ereport(ERROR,
499  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
500  errmsg("argument to option \"%s\" must be a list of column names",
501  defel->defname),
502  parser_errposition(pstate, defel->location)));
503  }
504  else if (strcmp(defel->defname, "encoding") == 0)
505  {
506  if (opts_out->file_encoding >= 0)
507  ereport(ERROR,
508  (errcode(ERRCODE_SYNTAX_ERROR),
509  errmsg("conflicting or redundant options"),
510  parser_errposition(pstate, defel->location)));
511  opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
512  if (opts_out->file_encoding < 0)
513  ereport(ERROR,
514  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
515  errmsg("argument to option \"%s\" must be a valid encoding name",
516  defel->defname),
517  parser_errposition(pstate, defel->location)));
518  }
519  else
520  ereport(ERROR,
521  (errcode(ERRCODE_SYNTAX_ERROR),
522  errmsg("option \"%s\" not recognized",
523  defel->defname),
524  parser_errposition(pstate, defel->location)));
525  }
526 
527  /*
528  * Check for incompatible options (must do these two before inserting
529  * defaults)
530  */
531  if (opts_out->binary && opts_out->delim)
532  ereport(ERROR,
533  (errcode(ERRCODE_SYNTAX_ERROR),
534  errmsg("cannot specify DELIMITER in BINARY mode")));
535 
536  if (opts_out->binary && opts_out->null_print)
537  ereport(ERROR,
538  (errcode(ERRCODE_SYNTAX_ERROR),
539  errmsg("cannot specify NULL in BINARY mode")));
540 
541  /* Set defaults for omitted options */
542  if (!opts_out->delim)
543  opts_out->delim = opts_out->csv_mode ? "," : "\t";
544 
545  if (!opts_out->null_print)
546  opts_out->null_print = opts_out->csv_mode ? "" : "\\N";
547  opts_out->null_print_len = strlen(opts_out->null_print);
548 
549  if (opts_out->csv_mode)
550  {
551  if (!opts_out->quote)
552  opts_out->quote = "\"";
553  if (!opts_out->escape)
554  opts_out->escape = opts_out->quote;
555  }
556 
557  /* Only single-byte delimiter strings are supported. */
558  if (strlen(opts_out->delim) != 1)
559  ereport(ERROR,
560  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
561  errmsg("COPY delimiter must be a single one-byte character")));
562 
563  /* Disallow end-of-line characters */
564  if (strchr(opts_out->delim, '\r') != NULL ||
565  strchr(opts_out->delim, '\n') != NULL)
566  ereport(ERROR,
567  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
568  errmsg("COPY delimiter cannot be newline or carriage return")));
569 
570  if (strchr(opts_out->null_print, '\r') != NULL ||
571  strchr(opts_out->null_print, '\n') != NULL)
572  ereport(ERROR,
573  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
574  errmsg("COPY null representation cannot use newline or carriage return")));
575 
576  /*
577  * Disallow unsafe delimiter characters in non-CSV mode. We can't allow
578  * backslash because it would be ambiguous. We can't allow the other
579  * cases because data characters matching the delimiter must be
580  * backslashed, and certain backslash combinations are interpreted
581  * non-literally by COPY IN. Disallowing all lower case ASCII letters is
582  * more than strictly necessary, but seems best for consistency and
583  * future-proofing. Likewise we disallow all digits though only octal
584  * digits are actually dangerous.
585  */
586  if (!opts_out->csv_mode &&
587  strchr("\\.abcdefghijklmnopqrstuvwxyz0123456789",
588  opts_out->delim[0]) != NULL)
589  ereport(ERROR,
590  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
591  errmsg("COPY delimiter cannot be \"%s\"", opts_out->delim)));
592 
593  /* Check header */
594  if (!opts_out->csv_mode && opts_out->header_line)
595  ereport(ERROR,
596  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
597  errmsg("COPY HEADER available only in CSV mode")));
598 
599  /* Check quote */
600  if (!opts_out->csv_mode && opts_out->quote != NULL)
601  ereport(ERROR,
602  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
603  errmsg("COPY quote available only in CSV mode")));
604 
605  if (opts_out->csv_mode && strlen(opts_out->quote) != 1)
606  ereport(ERROR,
607  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
608  errmsg("COPY quote must be a single one-byte character")));
609 
610  if (opts_out->csv_mode && opts_out->delim[0] == opts_out->quote[0])
611  ereport(ERROR,
612  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
613  errmsg("COPY delimiter and quote must be different")));
614 
615  /* Check escape */
616  if (!opts_out->csv_mode && opts_out->escape != NULL)
617  ereport(ERROR,
618  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
619  errmsg("COPY escape available only in CSV mode")));
620 
621  if (opts_out->csv_mode && strlen(opts_out->escape) != 1)
622  ereport(ERROR,
623  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
624  errmsg("COPY escape must be a single one-byte character")));
625 
626  /* Check force_quote */
627  if (!opts_out->csv_mode && (opts_out->force_quote || opts_out->force_quote_all))
628  ereport(ERROR,
629  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
630  errmsg("COPY force quote available only in CSV mode")));
631  if ((opts_out->force_quote || opts_out->force_quote_all) && is_from)
632  ereport(ERROR,
633  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
634  errmsg("COPY force quote only available using COPY TO")));
635 
636  /* Check force_notnull */
637  if (!opts_out->csv_mode && opts_out->force_notnull != NIL)
638  ereport(ERROR,
639  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
640  errmsg("COPY force not null available only in CSV mode")));
641  if (opts_out->force_notnull != NIL && !is_from)
642  ereport(ERROR,
643  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
644  errmsg("COPY force not null only available using COPY FROM")));
645 
646  /* Check force_null */
647  if (!opts_out->csv_mode && opts_out->force_null != NIL)
648  ereport(ERROR,
649  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
650  errmsg("COPY force null available only in CSV mode")));
651 
652  if (opts_out->force_null != NIL && !is_from)
653  ereport(ERROR,
654  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
655  errmsg("COPY force null only available using COPY FROM")));
656 
657  /* Don't allow the delimiter to appear in the null string. */
658  if (strchr(opts_out->null_print, opts_out->delim[0]) != NULL)
659  ereport(ERROR,
660  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
661  errmsg("COPY delimiter must not appear in the NULL specification")));
662 
663  /* Don't allow the CSV quote char to appear in the null string. */
664  if (opts_out->csv_mode &&
665  strchr(opts_out->null_print, opts_out->quote[0]) != NULL)
666  ereport(ERROR,
667  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
668  errmsg("CSV quote character must not appear in the NULL specification")));
669 }
#define NIL
Definition: pg_list.h:65
int null_print_len
Definition: copy.h:37
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
int pg_char_to_encoding(const char *name)
Definition: encnames.c:550
#define castNode(_type_, nodeptr)
Definition: nodes.h:596
int errcode(int sqlerrcode)
Definition: elog.c:691
List * force_notnull
Definition: copy.h:45
bool force_quote_all
Definition: copy.h:43
char * null_print
Definition: copy.h:36
char * quote
Definition: copy.h:40
bool defGetBoolean(DefElem *def)
Definition: define.c:111
#define ERROR
Definition: elog.h:43
char * defGetString(DefElem *def)
Definition: define.c:49
bool binary
Definition: copy.h:32
List * force_null
Definition: copy.h:47
#define lfirst_node(type, lc)
Definition: pg_list.h:172
bool csv_mode
Definition: copy.h:34
int location
Definition: parsenodes.h:736
bool header_line
Definition: copy.h:35
int file_encoding
Definition: copy.h:30
Node * arg
Definition: parsenodes.h:734
void * palloc0(Size size)
Definition: mcxt.c:981
List * force_quote
Definition: copy.h:42
char * delim
Definition: copy.h:39
List * convert_select
Definition: copy.h:50
#define ereport(elevel,...)
Definition: elog.h:155
bool convert_selectively
Definition: copy.h:49
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
char * escape
Definition: copy.h:41
bool freeze
Definition: copy.h:33
int errmsg(const char *fmt,...)
Definition: elog.c:902
char * defname
Definition: parsenodes.h:733
Definition: pg_list.h:50