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)
 
static CopyHeaderChoice defGetCopyHeaderChoice (DefElem *def, bool is_from)
 
static CopyOnErrorChoice defGetCopyOnErrorChoice (DefElem *def, ParseState *pstate, bool is_from)
 
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 841 of file copy.c.

842 {
843  List *attnums = NIL;
844 
845  if (attnamelist == NIL)
846  {
847  /* Generate default column list */
848  int attr_count = tupDesc->natts;
849  int i;
850 
851  for (i = 0; i < attr_count; i++)
852  {
853  if (TupleDescAttr(tupDesc, i)->attisdropped)
854  continue;
855  if (TupleDescAttr(tupDesc, i)->attgenerated)
856  continue;
857  attnums = lappend_int(attnums, i + 1);
858  }
859  }
860  else
861  {
862  /* Validate the user-supplied list and extract attnums */
863  ListCell *l;
864 
865  foreach(l, attnamelist)
866  {
867  char *name = strVal(lfirst(l));
868  int attnum;
869  int i;
870 
871  /* Lookup column name */
873  for (i = 0; i < tupDesc->natts; i++)
874  {
875  Form_pg_attribute att = TupleDescAttr(tupDesc, i);
876 
877  if (att->attisdropped)
878  continue;
879  if (namestrcmp(&(att->attname), name) == 0)
880  {
881  if (att->attgenerated)
882  ereport(ERROR,
883  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
884  errmsg("column \"%s\" is a generated column",
885  name),
886  errdetail("Generated columns cannot be used in COPY.")));
887  attnum = att->attnum;
888  break;
889  }
890  }
891  if (attnum == InvalidAttrNumber)
892  {
893  if (rel != NULL)
894  ereport(ERROR,
895  (errcode(ERRCODE_UNDEFINED_COLUMN),
896  errmsg("column \"%s\" of relation \"%s\" does not exist",
897  name, RelationGetRelationName(rel))));
898  else
899  ereport(ERROR,
900  (errcode(ERRCODE_UNDEFINED_COLUMN),
901  errmsg("column \"%s\" does not exist",
902  name)));
903  }
904  /* Check for duplicates */
905  if (list_member_int(attnums, attnum))
906  ereport(ERROR,
907  (errcode(ERRCODE_DUPLICATE_COLUMN),
908  errmsg("column \"%s\" specified more than once",
909  name)));
910  attnums = lappend_int(attnums, attnum);
911  }
912  }
913 
914  return attnums;
915 }
#define InvalidAttrNumber
Definition: attnum.h:23
int errdetail(const char *fmt,...)
Definition: elog.c:1208
int errcode(int sqlerrcode)
Definition: elog.c:860
int errmsg(const char *fmt,...)
Definition: elog.c:1075
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
int i
Definition: isn.c:73
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 namestrcmp(Name name, const char *str)
Definition: name.c:247
int16 attnum
Definition: pg_attribute.h:74
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
#define RelationGetRelationName(relation)
Definition: rel.h:538
Definition: pg_list.h:54
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define strVal(v)
Definition: value.h:82
const char * name

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().

◆ defGetCopyHeaderChoice()

static CopyHeaderChoice defGetCopyHeaderChoice ( DefElem def,
bool  is_from 
)
static

Definition at line 337 of file copy.c.

338 {
339  /*
340  * If no parameter value given, assume "true" is meant.
341  */
342  if (def->arg == NULL)
343  return COPY_HEADER_TRUE;
344 
345  /*
346  * Allow 0, 1, "true", "false", "on", "off", or "match".
347  */
348  switch (nodeTag(def->arg))
349  {
350  case T_Integer:
351  switch (intVal(def->arg))
352  {
353  case 0:
354  return COPY_HEADER_FALSE;
355  case 1:
356  return COPY_HEADER_TRUE;
357  default:
358  /* otherwise, error out below */
359  break;
360  }
361  break;
362  default:
363  {
364  char *sval = defGetString(def);
365 
366  /*
367  * The set of strings accepted here should match up with the
368  * grammar's opt_boolean_or_string production.
369  */
370  if (pg_strcasecmp(sval, "true") == 0)
371  return COPY_HEADER_TRUE;
372  if (pg_strcasecmp(sval, "false") == 0)
373  return COPY_HEADER_FALSE;
374  if (pg_strcasecmp(sval, "on") == 0)
375  return COPY_HEADER_TRUE;
376  if (pg_strcasecmp(sval, "off") == 0)
377  return COPY_HEADER_FALSE;
378  if (pg_strcasecmp(sval, "match") == 0)
379  {
380  if (!is_from)
381  ereport(ERROR,
382  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
383  errmsg("cannot use \"%s\" with HEADER in COPY TO",
384  sval)));
385  return COPY_HEADER_MATCH;
386  }
387  }
388  break;
389  }
390  ereport(ERROR,
391  (errcode(ERRCODE_SYNTAX_ERROR),
392  errmsg("%s requires a Boolean value or \"match\"",
393  def->defname)));
394  return COPY_HEADER_FALSE; /* keep compiler quiet */
395 }
char * defGetString(DefElem *def)
Definition: define.c:49
@ COPY_HEADER_TRUE
Definition: copy.h:29
@ COPY_HEADER_FALSE
Definition: copy.h:28
@ COPY_HEADER_MATCH
Definition: copy.h:30
#define nodeTag(nodeptr)
Definition: nodes.h:133
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
char * defname
Definition: parsenodes.h:802
Node * arg
Definition: parsenodes.h:803
#define intVal(v)
Definition: value.h:79

References DefElem::arg, COPY_HEADER_FALSE, COPY_HEADER_MATCH, COPY_HEADER_TRUE, defGetString(), DefElem::defname, ereport, errcode(), errmsg(), ERROR, intVal, nodeTag, and pg_strcasecmp().

Referenced by ProcessCopyOptions().

◆ defGetCopyOnErrorChoice()

static CopyOnErrorChoice defGetCopyOnErrorChoice ( DefElem def,
ParseState pstate,
bool  is_from 
)
static

Definition at line 401 of file copy.c.

402 {
403  char *sval;
404 
405  if (!is_from)
406  ereport(ERROR,
407  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
408  errmsg("COPY ON_ERROR cannot be used with COPY TO"),
409  parser_errposition(pstate, def->location)));
410 
411  /*
412  * If no parameter value given, assume the default value.
413  */
414  if (def->arg == NULL)
415  return COPY_ON_ERROR_STOP;
416 
417  /*
418  * Allow "stop", or "ignore" values.
419  */
420  sval = defGetString(def);
421  if (pg_strcasecmp(sval, "stop") == 0)
422  return COPY_ON_ERROR_STOP;
423  if (pg_strcasecmp(sval, "ignore") == 0)
424  return COPY_ON_ERROR_IGNORE;
425 
426  ereport(ERROR,
427  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
428  errmsg("COPY ON_ERROR \"%s\" not recognized", sval),
429  parser_errposition(pstate, def->location)));
430  return COPY_ON_ERROR_STOP; /* keep compiler quiet */
431 }
@ COPY_ON_ERROR_IGNORE
Definition: copy.h:40
@ COPY_ON_ERROR_STOP
Definition: copy.h:39
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
int location
Definition: parsenodes.h:806

References DefElem::arg, COPY_ON_ERROR_IGNORE, COPY_ON_ERROR_STOP, defGetString(), ereport, errcode(), errmsg(), ERROR, DefElem::location, parser_errposition(), and pg_strcasecmp().

Referenced by ProcessCopyOptions().

◆ DoCopy()

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

Definition at line 64 of file copy.c.

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 (!has_privs_of_role(GetUserId(), ROLE_PG_EXECUTE_SERVER_PROGRAM))
84  ereport(ERROR,
85  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
86  errmsg("permission denied to COPY to or from an external program"),
87  errdetail("Only roles with privileges of the \"%s\" role may COPY to or from an external program.",
88  "pg_execute_server_program"),
89  errhint("Anyone can COPY to stdout or from stdin. "
90  "psql's \\copy command also works for anyone.")));
91  }
92  else
93  {
94  if (is_from && !has_privs_of_role(GetUserId(), ROLE_PG_READ_SERVER_FILES))
95  ereport(ERROR,
96  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
97  errmsg("permission denied to COPY from a file"),
98  errdetail("Only roles with privileges of the \"%s\" role may COPY from a file.",
99  "pg_read_server_files"),
100  errhint("Anyone can COPY to stdout or from stdin. "
101  "psql's \\copy command also works for anyone.")));
102 
103  if (!is_from && !has_privs_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES))
104  ereport(ERROR,
105  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
106  errmsg("permission denied to COPY to a file"),
107  errdetail("Only roles with privileges of the \"%s\" role may COPY to a file.",
108  "pg_write_server_files"),
109  errhint("Anyone can COPY to stdout or from stdin. "
110  "psql's \\copy command also works for anyone.")));
111  }
112  }
113 
114  if (stmt->relation)
115  {
116  LOCKMODE lockmode = is_from ? RowExclusiveLock : AccessShareLock;
117  ParseNamespaceItem *nsitem;
118  RTEPermissionInfo *perminfo;
119  TupleDesc tupDesc;
120  List *attnums;
121  ListCell *cur;
122 
123  Assert(!stmt->query);
124 
125  /* Open and lock the relation, using the appropriate lock type. */
126  rel = table_openrv(stmt->relation, lockmode);
127 
128  relid = RelationGetRelid(rel);
129 
130  nsitem = addRangeTableEntryForRelation(pstate, rel, lockmode,
131  NULL, false, false);
132 
133  perminfo = nsitem->p_perminfo;
134  perminfo->requiredPerms = (is_from ? ACL_INSERT : ACL_SELECT);
135 
136  if (stmt->whereClause)
137  {
138  /* add nsitem to query namespace */
139  addNSItemToQuery(pstate, nsitem, false, true, true);
140 
141  /* Transform the raw expression tree */
142  whereClause = transformExpr(pstate, stmt->whereClause, EXPR_KIND_COPY_WHERE);
143 
144  /* Make sure it yields a boolean result. */
145  whereClause = coerce_to_boolean(pstate, whereClause, "WHERE");
146 
147  /* we have to fix its collations too */
148  assign_expr_collations(pstate, whereClause);
149 
150  whereClause = eval_const_expressions(NULL, whereClause);
151 
152  whereClause = (Node *) canonicalize_qual((Expr *) whereClause, false);
153  whereClause = (Node *) make_ands_implicit((Expr *) whereClause);
154  }
155 
156  tupDesc = RelationGetDescr(rel);
157  attnums = CopyGetAttnums(tupDesc, rel, stmt->attlist);
158  foreach(cur, attnums)
159  {
160  int attno;
161  Bitmapset **bms;
162 
164  bms = is_from ? &perminfo->insertedCols : &perminfo->selectedCols;
165 
166  *bms = bms_add_member(*bms, attno);
167  }
168  ExecCheckPermissions(pstate->p_rtable, list_make1(perminfo), true);
169 
170  /*
171  * Permission check for row security policies.
172  *
173  * check_enable_rls will ereport(ERROR) if the user has requested
174  * something invalid and will otherwise indicate if we should enable
175  * RLS (returns RLS_ENABLED) or not for this COPY statement.
176  *
177  * If the relation has a row security policy and we are to apply it
178  * then perform a "query" copy and allow the normal query processing
179  * to handle the policies.
180  *
181  * If RLS is not enabled for this, then just fall through to the
182  * normal non-filtering relation handling.
183  */
184  if (check_enable_rls(relid, InvalidOid, false) == RLS_ENABLED)
185  {
187  ColumnRef *cr;
188  ResTarget *target;
189  RangeVar *from;
190  List *targetList = NIL;
191 
192  if (is_from)
193  ereport(ERROR,
194  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
195  errmsg("COPY FROM not supported with row-level security"),
196  errhint("Use INSERT statements instead.")));
197 
198  /*
199  * Build target list
200  *
201  * If no columns are specified in the attribute list of the COPY
202  * command, then the target list is 'all' columns. Therefore, '*'
203  * should be used as the target list for the resulting SELECT
204  * statement.
205  *
206  * In the case that columns are specified in the attribute list,
207  * create a ColumnRef and ResTarget for each column and add them
208  * to the target list for the resulting SELECT statement.
209  */
210  if (!stmt->attlist)
211  {
212  cr = makeNode(ColumnRef);
214  cr->location = -1;
215 
216  target = makeNode(ResTarget);
217  target->name = NULL;
218  target->indirection = NIL;
219  target->val = (Node *) cr;
220  target->location = -1;
221 
222  targetList = list_make1(target);
223  }
224  else
225  {
226  ListCell *lc;
227 
228  foreach(lc, stmt->attlist)
229  {
230  /*
231  * Build the ColumnRef for each column. The ColumnRef
232  * 'fields' property is a String node that corresponds to
233  * the column name respectively.
234  */
235  cr = makeNode(ColumnRef);
236  cr->fields = list_make1(lfirst(lc));
237  cr->location = -1;
238 
239  /* Build the ResTarget and add the ColumnRef to it. */
240  target = makeNode(ResTarget);
241  target->name = NULL;
242  target->indirection = NIL;
243  target->val = (Node *) cr;
244  target->location = -1;
245 
246  /* Add each column to the SELECT statement's target list */
247  targetList = lappend(targetList, target);
248  }
249  }
250 
251  /*
252  * Build RangeVar for from clause, fully qualified based on the
253  * relation which we have opened and locked. Use "ONLY" so that
254  * COPY retrieves rows from only the target table not any
255  * inheritance children, the same as when RLS doesn't apply.
256  */
259  -1);
260  from->inh = false; /* apply ONLY */
261 
262  /* Build query */
264  select->targetList = targetList;
265  select->fromClause = list_make1(from);
266 
267  query = makeNode(RawStmt);
268  query->stmt = (Node *) select;
269  query->stmt_location = stmt_location;
270  query->stmt_len = stmt_len;
271 
272  /*
273  * Close the relation for now, but keep the lock on it to prevent
274  * changes between now and when we start the query-based COPY.
275  *
276  * We'll reopen it later as part of the query-based COPY.
277  */
278  table_close(rel, NoLock);
279  rel = NULL;
280  }
281  }
282  else
283  {
284  Assert(stmt->query);
285 
286  /* MERGE is allowed by parser, but unimplemented. Reject for now */
287  if (IsA(stmt->query, MergeStmt))
288  ereport(ERROR,
289  errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
290  errmsg("MERGE not supported in COPY"));
291 
292  query = makeNode(RawStmt);
293  query->stmt = stmt->query;
294  query->stmt_location = stmt_location;
295  query->stmt_len = stmt_len;
296 
297  relid = InvalidOid;
298  rel = NULL;
299  }
300 
301  if (is_from)
302  {
303  CopyFromState cstate;
304 
305  Assert(rel);
306 
307  /* check read-only transaction and parallel mode */
308  if (XactReadOnly && !rel->rd_islocaltemp)
309  PreventCommandIfReadOnly("COPY FROM");
310 
311  cstate = BeginCopyFrom(pstate, rel, whereClause,
312  stmt->filename, stmt->is_program,
313  NULL, stmt->attlist, stmt->options);
314  *processed = CopyFrom(cstate); /* copy from file to database */
315  EndCopyFrom(cstate);
316  }
317  else
318  {
319  CopyToState cstate;
320 
321  cstate = BeginCopyTo(pstate, rel, query, relid,
322  stmt->filename, stmt->is_program,
323  NULL, stmt->attlist, stmt->options);
324  *processed = DoCopyTo(cstate); /* copy from database to file */
325  EndCopyTo(cstate);
326  }
327 
328  if (rel != NULL)
329  table_close(rel, NoLock);
330 }
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:5060
List * CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
Definition: copy.c:841
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:828
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2237
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:1373
uint64 CopyFrom(CopyFromState cstate)
Definition: copyfrom.c:633
void EndCopyFrom(CopyFromState cstate)
Definition: copyfrom.c:1790
uint64 DoCopyTo(CopyToState cstate)
Definition: copyto.c:748
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:357
void EndCopyTo(CopyToState cstate)
Definition: copyto.c:727
struct cursor * cur
Definition: ecpg.c:28
int errhint(const char *fmt,...)
Definition: elog.c:1322
bool ExecCheckPermissions(List *rangeTable, List *rteperminfos, bool ereport_on_violation)
Definition: execMain.c:581
#define stmt
Definition: indent_codes.h:59
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
Definition: list.c:339
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_namespace_name(Oid nspid)
Definition: lsyscache.c:3321
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:722
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:425
char * pstrdup(const char *in)
Definition: mcxt.c:1619
Oid GetUserId(void)
Definition: miscinit.c:511
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define makeNode(_type_)
Definition: nodes.h:155
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:110
@ EXPR_KIND_COPY_WHERE
Definition: parse_node.h:81
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
#define lfirst_int(lc)
Definition: pg_list.h:173
#define list_make1(x1)
Definition: pg_list.h:212
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
Expr * canonicalize_qual(Expr *qual, bool is_check)
Definition: prepqual.c:294
#define RelationGetRelid(relation)
Definition: rel.h:504
#define RelationGetDescr(relation)
Definition: rel.h:530
#define RelationGetNamespace(relation)
Definition: rel.h:545
int check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
Definition: rls.c:52
@ RLS_ENABLED
Definition: rls.h:45
int location
Definition: parsenodes.h:285
List * fields
Definition: parsenodes.h:284
Definition: nodes.h:129
RTEPermissionInfo * p_perminfo
Definition: parse_node.h:288
List * p_rtable
Definition: parse_node.h:193
Bitmapset * selectedCols
Definition: parsenodes.h:1240
AclMode requiredPerms
Definition: parsenodes.h:1238
Bitmapset * insertedCols
Definition: parsenodes.h:1241
bool inh
Definition: primnodes.h:85
int stmt_len
Definition: parsenodes.h:1863
Node * stmt
Definition: parsenodes.h:1861
int stmt_location
Definition: parsenodes.h:1862
bool rd_islocaltemp
Definition: rel.h:61
int location
Definition: parsenodes.h:510
Node * val
Definition: parsenodes.h:509
List * indirection
Definition: parsenodes.h:508
char * name
Definition: parsenodes.h:507
#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
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:411
#define select(n, r, w, e, timeout)
Definition: win32_port.h:495
bool XactReadOnly
Definition: xact.c:82

References AccessShareLock, ACL_INSERT, ACL_SELECT, addNSItemToQuery(), addRangeTableEntryForRelation(), Assert(), assign_expr_collations(), BeginCopyFrom(), BeginCopyTo(), bms_add_member(), canonicalize_qual(), check_enable_rls(), coerce_to_boolean(), CopyFrom(), CopyGetAttnums(), cur, DoCopyTo(), EndCopyFrom(), EndCopyTo(), ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, eval_const_expressions(), ExecCheckPermissions(), EXPR_KIND_COPY_WHERE, ColumnRef::fields, FirstLowInvalidHeapAttributeNumber, get_namespace_name(), GetUserId(), has_privs_of_role(), ResTarget::indirection, RangeVar::inh, RTEPermissionInfo::insertedCols, InvalidOid, IsA, lappend(), lfirst, lfirst_int, list_make1, ColumnRef::location, ResTarget::location, make_ands_implicit(), makeNode, makeRangeVar(), ResTarget::name, NIL, NoLock, ParseNamespaceItem::p_perminfo, ParseState::p_rtable, PreventCommandIfReadOnly(), pstrdup(), RelationData::rd_islocaltemp, RelationGetDescr, RelationGetNamespace, RelationGetRelationName, RelationGetRelid, RTEPermissionInfo::requiredPerms, RLS_ENABLED, RowExclusiveLock, select, RTEPermissionInfo::selectedCols, RawStmt::stmt, stmt, RawStmt::stmt_len, RawStmt::stmt_location, table_close(), table_openrv(), transformExpr(), ResTarget::val, and XactReadOnly.

Referenced by standard_ProcessUtility().

◆ ProcessCopyOptions()

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

Definition at line 450 of file copy.c.

454 {
455  bool format_specified = false;
456  bool freeze_specified = false;
457  bool header_specified = false;
458  bool on_error_specified = false;
459  ListCell *option;
460 
461  /* Support external use for option sanity checking */
462  if (opts_out == NULL)
463  opts_out = (CopyFormatOptions *) palloc0(sizeof(CopyFormatOptions));
464 
465  opts_out->file_encoding = -1;
466 
467  /* Extract options from the statement node tree */
468  foreach(option, options)
469  {
470  DefElem *defel = lfirst_node(DefElem, option);
471 
472  if (strcmp(defel->defname, "format") == 0)
473  {
474  char *fmt = defGetString(defel);
475 
476  if (format_specified)
477  errorConflictingDefElem(defel, pstate);
478  format_specified = true;
479  if (strcmp(fmt, "text") == 0)
480  /* default format */ ;
481  else if (strcmp(fmt, "csv") == 0)
482  opts_out->csv_mode = true;
483  else if (strcmp(fmt, "binary") == 0)
484  opts_out->binary = true;
485  else
486  ereport(ERROR,
487  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
488  errmsg("COPY format \"%s\" not recognized", fmt),
489  parser_errposition(pstate, defel->location)));
490  }
491  else if (strcmp(defel->defname, "freeze") == 0)
492  {
493  if (freeze_specified)
494  errorConflictingDefElem(defel, pstate);
495  freeze_specified = true;
496  opts_out->freeze = defGetBoolean(defel);
497  }
498  else if (strcmp(defel->defname, "delimiter") == 0)
499  {
500  if (opts_out->delim)
501  errorConflictingDefElem(defel, pstate);
502  opts_out->delim = defGetString(defel);
503  }
504  else if (strcmp(defel->defname, "null") == 0)
505  {
506  if (opts_out->null_print)
507  errorConflictingDefElem(defel, pstate);
508  opts_out->null_print = defGetString(defel);
509  }
510  else if (strcmp(defel->defname, "default") == 0)
511  {
512  if (opts_out->default_print)
513  errorConflictingDefElem(defel, pstate);
514  opts_out->default_print = defGetString(defel);
515  }
516  else if (strcmp(defel->defname, "header") == 0)
517  {
518  if (header_specified)
519  errorConflictingDefElem(defel, pstate);
520  header_specified = true;
521  opts_out->header_line = defGetCopyHeaderChoice(defel, is_from);
522  }
523  else if (strcmp(defel->defname, "quote") == 0)
524  {
525  if (opts_out->quote)
526  errorConflictingDefElem(defel, pstate);
527  opts_out->quote = defGetString(defel);
528  }
529  else if (strcmp(defel->defname, "escape") == 0)
530  {
531  if (opts_out->escape)
532  errorConflictingDefElem(defel, pstate);
533  opts_out->escape = defGetString(defel);
534  }
535  else if (strcmp(defel->defname, "force_quote") == 0)
536  {
537  if (opts_out->force_quote || opts_out->force_quote_all)
538  errorConflictingDefElem(defel, pstate);
539  if (defel->arg && IsA(defel->arg, A_Star))
540  opts_out->force_quote_all = true;
541  else if (defel->arg && IsA(defel->arg, List))
542  opts_out->force_quote = castNode(List, defel->arg);
543  else
544  ereport(ERROR,
545  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
546  errmsg("argument to option \"%s\" must be a list of column names",
547  defel->defname),
548  parser_errposition(pstate, defel->location)));
549  }
550  else if (strcmp(defel->defname, "force_not_null") == 0)
551  {
552  if (opts_out->force_notnull || opts_out->force_notnull_all)
553  errorConflictingDefElem(defel, pstate);
554  if (defel->arg && IsA(defel->arg, A_Star))
555  opts_out->force_notnull_all = true;
556  else if (defel->arg && IsA(defel->arg, List))
557  opts_out->force_notnull = castNode(List, defel->arg);
558  else
559  ereport(ERROR,
560  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
561  errmsg("argument to option \"%s\" must be a list of column names",
562  defel->defname),
563  parser_errposition(pstate, defel->location)));
564  }
565  else if (strcmp(defel->defname, "force_null") == 0)
566  {
567  if (opts_out->force_null || opts_out->force_null_all)
568  errorConflictingDefElem(defel, pstate);
569  if (defel->arg && IsA(defel->arg, A_Star))
570  opts_out->force_null_all = true;
571  else if (defel->arg && IsA(defel->arg, List))
572  opts_out->force_null = castNode(List, defel->arg);
573  else
574  ereport(ERROR,
575  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
576  errmsg("argument to option \"%s\" must be a list of column names",
577  defel->defname),
578  parser_errposition(pstate, defel->location)));
579  }
580  else if (strcmp(defel->defname, "convert_selectively") == 0)
581  {
582  /*
583  * Undocumented, not-accessible-from-SQL option: convert only the
584  * named columns to binary form, storing the rest as NULLs. It's
585  * allowed for the column list to be NIL.
586  */
587  if (opts_out->convert_selectively)
588  errorConflictingDefElem(defel, pstate);
589  opts_out->convert_selectively = true;
590  if (defel->arg == NULL || IsA(defel->arg, List))
591  opts_out->convert_select = castNode(List, defel->arg);
592  else
593  ereport(ERROR,
594  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
595  errmsg("argument to option \"%s\" must be a list of column names",
596  defel->defname),
597  parser_errposition(pstate, defel->location)));
598  }
599  else if (strcmp(defel->defname, "encoding") == 0)
600  {
601  if (opts_out->file_encoding >= 0)
602  errorConflictingDefElem(defel, pstate);
603  opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
604  if (opts_out->file_encoding < 0)
605  ereport(ERROR,
606  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
607  errmsg("argument to option \"%s\" must be a valid encoding name",
608  defel->defname),
609  parser_errposition(pstate, defel->location)));
610  }
611  else if (strcmp(defel->defname, "on_error") == 0)
612  {
613  if (on_error_specified)
614  errorConflictingDefElem(defel, pstate);
615  on_error_specified = true;
616  opts_out->on_error = defGetCopyOnErrorChoice(defel, pstate, is_from);
617  }
618  else
619  ereport(ERROR,
620  (errcode(ERRCODE_SYNTAX_ERROR),
621  errmsg("option \"%s\" not recognized",
622  defel->defname),
623  parser_errposition(pstate, defel->location)));
624  }
625 
626  /*
627  * Check for incompatible options (must do these two before inserting
628  * defaults)
629  */
630  if (opts_out->binary && opts_out->delim)
631  ereport(ERROR,
632  (errcode(ERRCODE_SYNTAX_ERROR),
633  errmsg("cannot specify DELIMITER in BINARY mode")));
634 
635  if (opts_out->binary && opts_out->null_print)
636  ereport(ERROR,
637  (errcode(ERRCODE_SYNTAX_ERROR),
638  errmsg("cannot specify NULL in BINARY mode")));
639 
640  if (opts_out->binary && opts_out->default_print)
641  ereport(ERROR,
642  (errcode(ERRCODE_SYNTAX_ERROR),
643  errmsg("cannot specify DEFAULT in BINARY mode")));
644 
645  if (opts_out->binary && opts_out->on_error != COPY_ON_ERROR_STOP)
646  ereport(ERROR,
647  (errcode(ERRCODE_SYNTAX_ERROR),
648  errmsg("only ON_ERROR STOP is allowed in BINARY mode")));
649 
650  /* Set defaults for omitted options */
651  if (!opts_out->delim)
652  opts_out->delim = opts_out->csv_mode ? "," : "\t";
653 
654  if (!opts_out->null_print)
655  opts_out->null_print = opts_out->csv_mode ? "" : "\\N";
656  opts_out->null_print_len = strlen(opts_out->null_print);
657 
658  if (opts_out->csv_mode)
659  {
660  if (!opts_out->quote)
661  opts_out->quote = "\"";
662  if (!opts_out->escape)
663  opts_out->escape = opts_out->quote;
664  }
665 
666  /* Only single-byte delimiter strings are supported. */
667  if (strlen(opts_out->delim) != 1)
668  ereport(ERROR,
669  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
670  errmsg("COPY delimiter must be a single one-byte character")));
671 
672  /* Disallow end-of-line characters */
673  if (strchr(opts_out->delim, '\r') != NULL ||
674  strchr(opts_out->delim, '\n') != NULL)
675  ereport(ERROR,
676  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
677  errmsg("COPY delimiter cannot be newline or carriage return")));
678 
679  if (strchr(opts_out->null_print, '\r') != NULL ||
680  strchr(opts_out->null_print, '\n') != NULL)
681  ereport(ERROR,
682  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
683  errmsg("COPY null representation cannot use newline or carriage return")));
684 
685  if (opts_out->default_print)
686  {
687  opts_out->default_print_len = strlen(opts_out->default_print);
688 
689  if (strchr(opts_out->default_print, '\r') != NULL ||
690  strchr(opts_out->default_print, '\n') != NULL)
691  ereport(ERROR,
692  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
693  errmsg("COPY default representation cannot use newline or carriage return")));
694  }
695 
696  /*
697  * Disallow unsafe delimiter characters in non-CSV mode. We can't allow
698  * backslash because it would be ambiguous. We can't allow the other
699  * cases because data characters matching the delimiter must be
700  * backslashed, and certain backslash combinations are interpreted
701  * non-literally by COPY IN. Disallowing all lower case ASCII letters is
702  * more than strictly necessary, but seems best for consistency and
703  * future-proofing. Likewise we disallow all digits though only octal
704  * digits are actually dangerous.
705  */
706  if (!opts_out->csv_mode &&
707  strchr("\\.abcdefghijklmnopqrstuvwxyz0123456789",
708  opts_out->delim[0]) != NULL)
709  ereport(ERROR,
710  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
711  errmsg("COPY delimiter cannot be \"%s\"", opts_out->delim)));
712 
713  /* Check header */
714  if (opts_out->binary && opts_out->header_line)
715  ereport(ERROR,
716  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
717  errmsg("cannot specify HEADER in BINARY mode")));
718 
719  /* Check quote */
720  if (!opts_out->csv_mode && opts_out->quote != NULL)
721  ereport(ERROR,
722  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
723  errmsg("COPY QUOTE requires CSV mode")));
724 
725  if (opts_out->csv_mode && strlen(opts_out->quote) != 1)
726  ereport(ERROR,
727  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
728  errmsg("COPY quote must be a single one-byte character")));
729 
730  if (opts_out->csv_mode && opts_out->delim[0] == opts_out->quote[0])
731  ereport(ERROR,
732  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
733  errmsg("COPY delimiter and quote must be different")));
734 
735  /* Check escape */
736  if (!opts_out->csv_mode && opts_out->escape != NULL)
737  ereport(ERROR,
738  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
739  errmsg("COPY ESCAPE requires CSV mode")));
740 
741  if (opts_out->csv_mode && strlen(opts_out->escape) != 1)
742  ereport(ERROR,
743  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
744  errmsg("COPY escape must be a single one-byte character")));
745 
746  /* Check force_quote */
747  if (!opts_out->csv_mode && (opts_out->force_quote || opts_out->force_quote_all))
748  ereport(ERROR,
749  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
750  errmsg("COPY FORCE_QUOTE requires CSV mode")));
751  if ((opts_out->force_quote || opts_out->force_quote_all) && is_from)
752  ereport(ERROR,
753  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
754  errmsg("COPY FORCE_QUOTE cannot be used with COPY FROM")));
755 
756  /* Check force_notnull */
757  if (!opts_out->csv_mode && opts_out->force_notnull != NIL)
758  ereport(ERROR,
759  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
760  errmsg("COPY FORCE_NOT_NULL requires CSV mode")));
761  if (opts_out->force_notnull != NIL && !is_from)
762  ereport(ERROR,
763  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
764  errmsg("COPY FORCE_NOT_NULL cannot be used with COPY TO")));
765 
766  /* Check force_null */
767  if (!opts_out->csv_mode && opts_out->force_null != NIL)
768  ereport(ERROR,
769  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
770  errmsg("COPY FORCE_NULL requires CSV mode")));
771 
772  if (opts_out->force_null != NIL && !is_from)
773  ereport(ERROR,
774  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
775  errmsg("COPY FORCE_NULL cannot be used with COPY TO")));
776 
777  /* Don't allow the delimiter to appear in the null string. */
778  if (strchr(opts_out->null_print, opts_out->delim[0]) != NULL)
779  ereport(ERROR,
780  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
781  errmsg("COPY delimiter character must not appear in the NULL specification")));
782 
783  /* Don't allow the CSV quote char to appear in the null string. */
784  if (opts_out->csv_mode &&
785  strchr(opts_out->null_print, opts_out->quote[0]) != NULL)
786  ereport(ERROR,
787  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
788  errmsg("CSV quote character must not appear in the NULL specification")));
789 
790  /* Check freeze */
791  if (opts_out->freeze && !is_from)
792  ereport(ERROR,
793  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
794  errmsg("COPY FREEZE cannot be used with COPY TO")));
795 
796  if (opts_out->default_print)
797  {
798  if (!is_from)
799  ereport(ERROR,
800  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
801  errmsg("COPY DEFAULT only available using COPY FROM")));
802 
803  /* Don't allow the delimiter to appear in the default string. */
804  if (strchr(opts_out->default_print, opts_out->delim[0]) != NULL)
805  ereport(ERROR,
806  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
807  errmsg("COPY delimiter must not appear in the DEFAULT specification")));
808 
809  /* Don't allow the CSV quote char to appear in the default string. */
810  if (opts_out->csv_mode &&
811  strchr(opts_out->default_print, opts_out->quote[0]) != NULL)
812  ereport(ERROR,
813  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
814  errmsg("CSV quote character must not appear in the DEFAULT specification")));
815 
816  /* Don't allow the NULL and DEFAULT string to be the same */
817  if (opts_out->null_print_len == opts_out->default_print_len &&
818  strncmp(opts_out->null_print, opts_out->default_print,
819  opts_out->null_print_len) == 0)
820  ereport(ERROR,
821  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
822  errmsg("NULL specification and DEFAULT specification cannot be the same")));
823  }
824 }
static CopyHeaderChoice defGetCopyHeaderChoice(DefElem *def, bool is_from)
Definition: copy.c:337
static CopyOnErrorChoice defGetCopyOnErrorChoice(DefElem *def, ParseState *pstate, bool is_from)
Definition: copy.c:401
bool defGetBoolean(DefElem *def)
Definition: define.c:108
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:385
static void const char * fmt
void * palloc0(Size size)
Definition: mcxt.c:1232
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
#define lfirst_node(type, lc)
Definition: pg_list.h:176
#define pg_char_to_encoding
Definition: pg_wchar.h:560
int default_print_len
Definition: copy.h:61
bool force_notnull_all
Definition: copy.h:69
bool force_quote_all
Definition: copy.h:66
bool freeze
Definition: copy.h:54
bool binary
Definition: copy.h:53
int null_print_len
Definition: copy.h:58
bool convert_selectively
Definition: copy.h:74
char * quote
Definition: copy.h:63
CopyOnErrorChoice on_error
Definition: copy.h:75
CopyHeaderChoice header_line
Definition: copy.h:56
List * force_quote
Definition: copy.h:65
char * escape
Definition: copy.h:64
char * null_print
Definition: copy.h:57
List * force_null
Definition: copy.h:71
char * delim
Definition: copy.h:62
List * convert_select
Definition: copy.h:76
bool force_null_all
Definition: copy.h:72
bool csv_mode
Definition: copy.h:55
int file_encoding
Definition: copy.h:51
char * default_print
Definition: copy.h:60
List * force_notnull
Definition: copy.h:68

References DefElem::arg, CopyFormatOptions::binary, castNode, CopyFormatOptions::convert_select, CopyFormatOptions::convert_selectively, COPY_ON_ERROR_STOP, CopyFormatOptions::csv_mode, CopyFormatOptions::default_print, CopyFormatOptions::default_print_len, defGetBoolean(), defGetCopyHeaderChoice(), defGetCopyOnErrorChoice(), defGetString(), DefElem::defname, CopyFormatOptions::delim, ereport, errcode(), errmsg(), ERROR, errorConflictingDefElem(), CopyFormatOptions::escape, CopyFormatOptions::file_encoding, fmt, CopyFormatOptions::force_notnull, CopyFormatOptions::force_notnull_all, CopyFormatOptions::force_null, CopyFormatOptions::force_null_all, 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, CopyFormatOptions::on_error, palloc0(), parser_errposition(), pg_char_to_encoding, and CopyFormatOptions::quote.

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