PostgreSQL Source Code  git master
copy.h File Reference
#include "nodes/execnodes.h"
#include "nodes/parsenodes.h"
#include "parser/parse_node.h"
#include "tcop/dest.h"
Include dependency graph for copy.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  CopyFormatOptions
 

Typedefs

typedef enum CopyHeaderChoice CopyHeaderChoice
 
typedef struct CopyFormatOptions CopyFormatOptions
 
typedef struct CopyFromStateDataCopyFromState
 
typedef struct CopyToStateDataCopyToState
 
typedef int(* copy_data_source_cb) (void *outbuf, int minread, int maxread)
 
typedef void(* copy_data_dest_cb) (void *data, int len)
 

Enumerations

enum  CopyHeaderChoice { COPY_HEADER_FALSE = 0 , COPY_HEADER_TRUE , COPY_HEADER_MATCH }
 

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)
 
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)
 
void EndCopyFrom (CopyFromState cstate)
 
bool NextCopyFrom (CopyFromState cstate, ExprContext *econtext, Datum *values, bool *nulls)
 
bool NextCopyFromRawFields (CopyFromState cstate, char ***fields, int *nfields)
 
void CopyFromErrorCallback (void *arg)
 
uint64 CopyFrom (CopyFromState cstate)
 
DestReceiverCreateCopyDestReceiver (void)
 
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)
 
void EndCopyTo (CopyToState cstate)
 
uint64 DoCopyTo (CopyToState cstate)
 
ListCopyGetAttnums (TupleDesc tupDesc, Relation rel, List *attnamelist)
 

Typedef Documentation

◆ copy_data_dest_cb

typedef void(* copy_data_dest_cb) (void *data, int len)

Definition at line 73 of file copy.h.

◆ copy_data_source_cb

typedef int(* copy_data_source_cb) (void *outbuf, int minread, int maxread)

Definition at line 72 of file copy.h.

◆ CopyFormatOptions

◆ CopyFromState

Definition at line 69 of file copy.h.

◆ CopyHeaderChoice

◆ CopyToState

typedef struct CopyToStateData* CopyToState

Definition at line 70 of file copy.h.

Enumeration Type Documentation

◆ CopyHeaderChoice

Enumerator
COPY_HEADER_FALSE 
COPY_HEADER_TRUE 
COPY_HEADER_MATCH 

Definition at line 26 of file copy.h.

27 {
CopyHeaderChoice
Definition: copy.h:27
@ COPY_HEADER_TRUE
Definition: copy.h:29
@ COPY_HEADER_FALSE
Definition: copy.h:28
@ COPY_HEADER_MATCH
Definition: copy.h:30

Function Documentation

◆ BeginCopyFrom()

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 at line 1337 of file copyfrom.c.

1345 {
1346  CopyFromState cstate;
1347  bool pipe = (filename == NULL);
1348  TupleDesc tupDesc;
1349  AttrNumber num_phys_attrs,
1350  num_defaults;
1351  FmgrInfo *in_functions;
1352  Oid *typioparams;
1353  Oid in_func_oid;
1354  int *defmap;
1355  ExprState **defexprs;
1356  MemoryContext oldcontext;
1357  bool volatile_defexprs;
1358  const int progress_cols[] = {
1362  };
1363  int64 progress_vals[] = {
1365  0,
1366  0
1367  };
1368 
1369  /* Allocate workspace and zero all fields */
1370  cstate = (CopyFromStateData *) palloc0(sizeof(CopyFromStateData));
1371 
1372  /*
1373  * We allocate everything used by a cstate in a new memory context. This
1374  * avoids memory leaks during repeated use of COPY in a query.
1375  */
1377  "COPY",
1379 
1380  oldcontext = MemoryContextSwitchTo(cstate->copycontext);
1381 
1382  /* Extract options from the statement node tree */
1383  ProcessCopyOptions(pstate, &cstate->opts, true /* is_from */ , options);
1384 
1385  /* Process the target relation */
1386  cstate->rel = rel;
1387 
1388  tupDesc = RelationGetDescr(cstate->rel);
1389 
1390  /* process common options or initialization */
1391 
1392  /* Generate or convert list of attributes to process */
1393  cstate->attnumlist = CopyGetAttnums(tupDesc, cstate->rel, attnamelist);
1394 
1395  num_phys_attrs = tupDesc->natts;
1396 
1397  /* Convert FORCE_NOT_NULL name list to per-column flags, check validity */
1398  cstate->opts.force_notnull_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1399  if (cstate->opts.force_notnull_all)
1400  MemSet(cstate->opts.force_notnull_flags, true, num_phys_attrs * sizeof(bool));
1401  else if (cstate->opts.force_notnull)
1402  {
1403  List *attnums;
1404  ListCell *cur;
1405 
1406  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_notnull);
1407 
1408  foreach(cur, attnums)
1409  {
1410  int attnum = lfirst_int(cur);
1411  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1412 
1413  if (!list_member_int(cstate->attnumlist, attnum))
1414  ereport(ERROR,
1415  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1416  errmsg("FORCE_NOT_NULL column \"%s\" not referenced by COPY",
1417  NameStr(attr->attname))));
1418  cstate->opts.force_notnull_flags[attnum - 1] = true;
1419  }
1420  }
1421 
1422  /* Convert FORCE_NULL name list to per-column flags, check validity */
1423  cstate->opts.force_null_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1424  if (cstate->opts.force_null_all)
1425  MemSet(cstate->opts.force_null_flags, true, num_phys_attrs * sizeof(bool));
1426  else if (cstate->opts.force_null)
1427  {
1428  List *attnums;
1429  ListCell *cur;
1430 
1431  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_null);
1432 
1433  foreach(cur, attnums)
1434  {
1435  int attnum = lfirst_int(cur);
1436  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1437 
1438  if (!list_member_int(cstate->attnumlist, attnum))
1439  ereport(ERROR,
1440  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1441  errmsg("FORCE_NULL column \"%s\" not referenced by COPY",
1442  NameStr(attr->attname))));
1443  cstate->opts.force_null_flags[attnum - 1] = true;
1444  }
1445  }
1446 
1447  /* Convert convert_selectively name list to per-column flags */
1448  if (cstate->opts.convert_selectively)
1449  {
1450  List *attnums;
1451  ListCell *cur;
1452 
1453  cstate->convert_select_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1454 
1455  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.convert_select);
1456 
1457  foreach(cur, attnums)
1458  {
1459  int attnum = lfirst_int(cur);
1460  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1461 
1462  if (!list_member_int(cstate->attnumlist, attnum))
1463  ereport(ERROR,
1464  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1465  errmsg_internal("selected column \"%s\" not referenced by COPY",
1466  NameStr(attr->attname))));
1467  cstate->convert_select_flags[attnum - 1] = true;
1468  }
1469  }
1470 
1471  /* Use client encoding when ENCODING option is not specified. */
1472  if (cstate->opts.file_encoding < 0)
1474  else
1475  cstate->file_encoding = cstate->opts.file_encoding;
1476 
1477  /*
1478  * Look up encoding conversion function.
1479  */
1480  if (cstate->file_encoding == GetDatabaseEncoding() ||
1481  cstate->file_encoding == PG_SQL_ASCII ||
1483  {
1484  cstate->need_transcoding = false;
1485  }
1486  else
1487  {
1488  cstate->need_transcoding = true;
1491  if (!OidIsValid(cstate->conversion_proc))
1492  ereport(ERROR,
1493  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1494  errmsg("default conversion function for encoding \"%s\" to \"%s\" does not exist",
1497  }
1498 
1499  cstate->copy_src = COPY_FILE; /* default */
1500 
1501  cstate->whereClause = whereClause;
1502 
1503  /* Initialize state variables */
1504  cstate->eol_type = EOL_UNKNOWN;
1505  cstate->cur_relname = RelationGetRelationName(cstate->rel);
1506  cstate->cur_lineno = 0;
1507  cstate->cur_attname = NULL;
1508  cstate->cur_attval = NULL;
1509  cstate->relname_only = false;
1510 
1511  /*
1512  * Allocate buffers for the input pipeline.
1513  *
1514  * attribute_buf and raw_buf are used in both text and binary modes, but
1515  * input_buf and line_buf only in text mode.
1516  */
1517  cstate->raw_buf = palloc(RAW_BUF_SIZE + 1);
1518  cstate->raw_buf_index = cstate->raw_buf_len = 0;
1519  cstate->raw_reached_eof = false;
1520 
1521  if (!cstate->opts.binary)
1522  {
1523  /*
1524  * If encoding conversion is needed, we need another buffer to hold
1525  * the converted input data. Otherwise, we can just point input_buf
1526  * to the same buffer as raw_buf.
1527  */
1528  if (cstate->need_transcoding)
1529  {
1530  cstate->input_buf = (char *) palloc(INPUT_BUF_SIZE + 1);
1531  cstate->input_buf_index = cstate->input_buf_len = 0;
1532  }
1533  else
1534  cstate->input_buf = cstate->raw_buf;
1535  cstate->input_reached_eof = false;
1536 
1537  initStringInfo(&cstate->line_buf);
1538  }
1539 
1540  initStringInfo(&cstate->attribute_buf);
1541 
1542  /* Assign range table and rteperminfos, we'll need them in CopyFrom. */
1543  if (pstate)
1544  {
1545  cstate->range_table = pstate->p_rtable;
1546  cstate->rteperminfos = pstate->p_rteperminfos;
1547  }
1548 
1549  num_defaults = 0;
1550  volatile_defexprs = false;
1551 
1552  /*
1553  * Pick up the required catalog information for each attribute in the
1554  * relation, including the input function, the element type (to pass to
1555  * the input function), and info about defaults and constraints. (Which
1556  * input function we use depends on text/binary format choice.)
1557  */
1558  in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
1559  typioparams = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
1560  defmap = (int *) palloc(num_phys_attrs * sizeof(int));
1561  defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *));
1562 
1563  for (int attnum = 1; attnum <= num_phys_attrs; attnum++)
1564  {
1565  Form_pg_attribute att = TupleDescAttr(tupDesc, attnum - 1);
1566 
1567  /* We don't need info for dropped attributes */
1568  if (att->attisdropped)
1569  continue;
1570 
1571  /* Fetch the input function and typioparam info */
1572  if (cstate->opts.binary)
1573  getTypeBinaryInputInfo(att->atttypid,
1574  &in_func_oid, &typioparams[attnum - 1]);
1575  else
1576  getTypeInputInfo(att->atttypid,
1577  &in_func_oid, &typioparams[attnum - 1]);
1578  fmgr_info(in_func_oid, &in_functions[attnum - 1]);
1579 
1580  /* Get default info if available */
1581  defexprs[attnum - 1] = NULL;
1582 
1583  /*
1584  * We only need the default values for columns that do not appear in
1585  * the column list, unless the DEFAULT option was given. We never need
1586  * default values for generated columns.
1587  */
1588  if ((cstate->opts.default_print != NULL ||
1589  !list_member_int(cstate->attnumlist, attnum)) &&
1590  !att->attgenerated)
1591  {
1592  Expr *defexpr = (Expr *) build_column_default(cstate->rel,
1593  attnum);
1594 
1595  if (defexpr != NULL)
1596  {
1597  /* Run the expression through planner */
1598  defexpr = expression_planner(defexpr);
1599 
1600  /* Initialize executable expression in copycontext */
1601  defexprs[attnum - 1] = ExecInitExpr(defexpr, NULL);
1602 
1603  /* if NOT copied from input */
1604  /* use default value if one exists */
1605  if (!list_member_int(cstate->attnumlist, attnum))
1606  {
1607  defmap[num_defaults] = attnum - 1;
1608  num_defaults++;
1609  }
1610 
1611  /*
1612  * If a default expression looks at the table being loaded,
1613  * then it could give the wrong answer when using
1614  * multi-insert. Since database access can be dynamic this is
1615  * hard to test for exactly, so we use the much wider test of
1616  * whether the default expression is volatile. We allow for
1617  * the special case of when the default expression is the
1618  * nextval() of a sequence which in this specific case is
1619  * known to be safe for use with the multi-insert
1620  * optimization. Hence we use this special case function
1621  * checker rather than the standard check for
1622  * contain_volatile_functions(). Note also that we already
1623  * ran the expression through expression_planner().
1624  */
1625  if (!volatile_defexprs)
1626  volatile_defexprs = contain_volatile_functions_not_nextval((Node *) defexpr);
1627  }
1628  }
1629  }
1630 
1631  cstate->defaults = (bool *) palloc0(tupDesc->natts * sizeof(bool));
1632 
1633  /* initialize progress */
1635  cstate->rel ? RelationGetRelid(cstate->rel) : InvalidOid);
1636  cstate->bytes_processed = 0;
1637 
1638  /* We keep those variables in cstate. */
1639  cstate->in_functions = in_functions;
1640  cstate->typioparams = typioparams;
1641  cstate->defmap = defmap;
1642  cstate->defexprs = defexprs;
1643  cstate->volatile_defexprs = volatile_defexprs;
1644  cstate->num_defaults = num_defaults;
1645  cstate->is_program = is_program;
1646 
1647  if (data_source_cb)
1648  {
1649  progress_vals[1] = PROGRESS_COPY_TYPE_CALLBACK;
1650  cstate->copy_src = COPY_CALLBACK;
1651  cstate->data_source_cb = data_source_cb;
1652  }
1653  else if (pipe)
1654  {
1655  progress_vals[1] = PROGRESS_COPY_TYPE_PIPE;
1656  Assert(!is_program); /* the grammar does not allow this */
1658  ReceiveCopyBegin(cstate);
1659  else
1660  cstate->copy_file = stdin;
1661  }
1662  else
1663  {
1664  cstate->filename = pstrdup(filename);
1665 
1666  if (cstate->is_program)
1667  {
1668  progress_vals[1] = PROGRESS_COPY_TYPE_PROGRAM;
1669  cstate->copy_file = OpenPipeStream(cstate->filename, PG_BINARY_R);
1670  if (cstate->copy_file == NULL)
1671  ereport(ERROR,
1673  errmsg("could not execute command \"%s\": %m",
1674  cstate->filename)));
1675  }
1676  else
1677  {
1678  struct stat st;
1679 
1680  progress_vals[1] = PROGRESS_COPY_TYPE_FILE;
1681  cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_R);
1682  if (cstate->copy_file == NULL)
1683  {
1684  /* copy errno because ereport subfunctions might change it */
1685  int save_errno = errno;
1686 
1687  ereport(ERROR,
1689  errmsg("could not open file \"%s\" for reading: %m",
1690  cstate->filename),
1691  (save_errno == ENOENT || save_errno == EACCES) ?
1692  errhint("COPY FROM instructs the PostgreSQL server process to read a file. "
1693  "You may want a client-side facility such as psql's \\copy.") : 0));
1694  }
1695 
1696  if (fstat(fileno(cstate->copy_file), &st))
1697  ereport(ERROR,
1699  errmsg("could not stat file \"%s\": %m",
1700  cstate->filename)));
1701 
1702  if (S_ISDIR(st.st_mode))
1703  ereport(ERROR,
1704  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1705  errmsg("\"%s\" is a directory", cstate->filename)));
1706 
1707  progress_vals[2] = st.st_size;
1708  }
1709  }
1710 
1711  pgstat_progress_update_multi_param(3, progress_cols, progress_vals);
1712 
1713  if (cstate->opts.binary)
1714  {
1715  /* Read and verify binary header */
1716  ReceiveCopyBinaryHeader(cstate);
1717  }
1718 
1719  /* create workspace for CopyReadAttributes results */
1720  if (!cstate->opts.binary)
1721  {
1722  AttrNumber attr_count = list_length(cstate->attnumlist);
1723 
1724  cstate->max_fields = attr_count;
1725  cstate->raw_fields = (char **) palloc(attr_count * sizeof(char *));
1726  }
1727 
1728  MemoryContextSwitchTo(oldcontext);
1729 
1730  return cstate;
1731 }
int16 AttrNumber
Definition: attnum.h:21
List * CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
Definition: copy.c:792
void ProcessCopyOptions(ParseState *pstate, CopyFormatOptions *opts_out, bool is_from, List *options)
Definition: copy.c:414
void pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid)
void pgstat_progress_update_multi_param(int nparam, const int *index, const int64 *val)
@ PROGRESS_COMMAND_COPY
#define NameStr(name)
Definition: c.h:735
#define PG_BINARY_R
Definition: c.h:1285
#define MemSet(start, val, len)
Definition: c.h:1009
#define OidIsValid(objectId)
Definition: c.h:764
bool contain_volatile_functions_not_nextval(Node *clause)
Definition: clauses.c:656
#define INPUT_BUF_SIZE
@ EOL_UNKNOWN
#define RAW_BUF_SIZE
void ReceiveCopyBinaryHeader(CopyFromState cstate)
void ReceiveCopyBegin(CopyFromState cstate)
@ COPY_FILE
Definition: copyto.c:52
@ COPY_CALLBACK
Definition: copyto.c:54
@ DestRemote
Definition: dest.h:89
struct cursor * cur
Definition: ecpg.c:28
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1156
int errcode_for_file_access(void)
Definition: elog.c:881
int errhint(const char *fmt,...)
Definition: elog.c:1316
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:128
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2553
FILE * OpenPipeStream(const char *command, const char *mode)
Definition: fd.c:2656
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
Assert(fmt[strlen(fmt) - 1] !='\n')
bool list_member_int(const List *list, int datum)
Definition: list.c:701
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2856
void getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
Definition: lsyscache.c:2922
int GetDatabaseEncoding(void)
Definition: mbutils.c:1268
int pg_get_client_encoding(void)
Definition: mbutils.c:337
char * pstrdup(const char *in)
Definition: mcxt.c:1644
void * palloc0(Size size)
Definition: mcxt.c:1257
MemoryContext CurrentMemoryContext
Definition: mcxt.c:135
void * palloc(Size size)
Definition: mcxt.c:1226
#define AllocSetContextCreate
Definition: memutils.h:126
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:150
Oid FindDefaultConversionProc(int32 for_encoding, int32 to_encoding)
Definition: namespace.c:4047
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:138
int16 attnum
Definition: pg_attribute.h:74
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
static char * filename
Definition: pg_dumpall.c:121
static int list_length(const List *l)
Definition: pg_list.h:152
#define lfirst_int(lc)
Definition: pg_list.h:173
@ PG_SQL_ASCII
Definition: pg_wchar.h:229
#define pg_encoding_to_char
Definition: pg_wchar.h:563
Expr * expression_planner(Expr *expr)
Definition: planner.c:6483
CommandDest whereToSendOutput
Definition: postgres.c:89
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define PROGRESS_COPY_COMMAND
Definition: progress.h:143
#define PROGRESS_COPY_TYPE_FILE
Definition: progress.h:151
#define PROGRESS_COPY_COMMAND_FROM
Definition: progress.h:147
#define PROGRESS_COPY_TYPE
Definition: progress.h:144
#define PROGRESS_COPY_TYPE_PROGRAM
Definition: progress.h:152
#define PROGRESS_COPY_BYTES_TOTAL
Definition: progress.h:140
#define PROGRESS_COPY_TYPE_CALLBACK
Definition: progress.h:154
#define PROGRESS_COPY_TYPE_PIPE
Definition: progress.h:153
#define RelationGetRelid(relation)
Definition: rel.h:504
#define RelationGetDescr(relation)
Definition: rel.h:530
#define RelationGetRelationName(relation)
Definition: rel.h:538
Node * build_column_default(Relation rel, int attrno)
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
bool force_notnull_all
Definition: copy.h:59
bool binary
Definition: copy.h:43
bool convert_selectively
Definition: copy.h:64
List * force_null
Definition: copy.h:61
List * convert_select
Definition: copy.h:65
bool force_null_all
Definition: copy.h:62
bool * force_notnull_flags
Definition: copy.h:60
int file_encoding
Definition: copy.h:41
bool * force_null_flags
Definition: copy.h:63
char * default_print
Definition: copy.h:50
List * force_notnull
Definition: copy.h:58
ExprState ** defexprs
copy_data_source_cb data_source_cb
StringInfoData line_buf
CopyFormatOptions opts
StringInfoData attribute_buf
MemoryContext copycontext
const char * cur_attval
const char * cur_attname
const char * cur_relname
Definition: fmgr.h:57
Definition: pg_list.h:54
Definition: nodes.h:129
List * p_rteperminfos
Definition: parse_node.h:194
List * p_rtable
Definition: parse_node.h:193
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define S_ISDIR(m)
Definition: win32_port.h:325
#define fstat
Definition: win32_port.h:283

References AllocateFile(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert(), attnum, CopyFromStateData::attnumlist, CopyFromStateData::attribute_buf, CopyFormatOptions::binary, build_column_default(), CopyFromStateData::bytes_processed, contain_volatile_functions_not_nextval(), CopyFromStateData::conversion_proc, CopyFormatOptions::convert_select, CopyFromStateData::convert_select_flags, CopyFormatOptions::convert_selectively, COPY_CALLBACK, COPY_FILE, CopyFromStateData::copy_file, CopyFromStateData::copy_src, CopyFromStateData::copycontext, CopyGetAttnums(), cur, CopyFromStateData::cur_attname, CopyFromStateData::cur_attval, CopyFromStateData::cur_lineno, CopyFromStateData::cur_relname, CurrentMemoryContext, CopyFromStateData::data_source_cb, CopyFormatOptions::default_print, CopyFromStateData::defaults, CopyFromStateData::defexprs, CopyFromStateData::defmap, DestRemote, CopyFromStateData::eol_type, EOL_UNKNOWN, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), errmsg_internal(), ERROR, ExecInitExpr(), expression_planner(), CopyFormatOptions::file_encoding, CopyFromStateData::file_encoding, filename, CopyFromStateData::filename, FindDefaultConversionProc(), fmgr_info(), CopyFormatOptions::force_notnull, CopyFormatOptions::force_notnull_all, CopyFormatOptions::force_notnull_flags, CopyFormatOptions::force_null, CopyFormatOptions::force_null_all, CopyFormatOptions::force_null_flags, fstat, GetDatabaseEncoding(), getTypeBinaryInputInfo(), getTypeInputInfo(), CopyFromStateData::in_functions, initStringInfo(), CopyFromStateData::input_buf, CopyFromStateData::input_buf_index, CopyFromStateData::input_buf_len, INPUT_BUF_SIZE, CopyFromStateData::input_reached_eof, InvalidOid, CopyFromStateData::is_program, lfirst_int, CopyFromStateData::line_buf, list_length(), list_member_int(), CopyFromStateData::max_fields, MemoryContextSwitchTo(), MemSet, NameStr, TupleDescData::natts, CopyFromStateData::need_transcoding, CopyFromStateData::num_defaults, OidIsValid, OpenPipeStream(), CopyFromStateData::opts, ParseState::p_rtable, ParseState::p_rteperminfos, palloc(), palloc0(), PG_BINARY_R, pg_encoding_to_char, pg_get_client_encoding(), PG_SQL_ASCII, pgstat_progress_start_command(), pgstat_progress_update_multi_param(), ProcessCopyOptions(), PROGRESS_COMMAND_COPY, PROGRESS_COPY_BYTES_TOTAL, PROGRESS_COPY_COMMAND, PROGRESS_COPY_COMMAND_FROM, PROGRESS_COPY_TYPE, PROGRESS_COPY_TYPE_CALLBACK, PROGRESS_COPY_TYPE_FILE, PROGRESS_COPY_TYPE_PIPE, PROGRESS_COPY_TYPE_PROGRAM, pstrdup(), CopyFromStateData::range_table, CopyFromStateData::raw_buf, CopyFromStateData::raw_buf_index, CopyFromStateData::raw_buf_len, RAW_BUF_SIZE, CopyFromStateData::raw_fields, CopyFromStateData::raw_reached_eof, ReceiveCopyBegin(), ReceiveCopyBinaryHeader(), CopyFromStateData::rel, RelationGetDescr, RelationGetRelationName, RelationGetRelid, CopyFromStateData::relname_only, CopyFromStateData::rteperminfos, S_ISDIR, stat::st_mode, stat::st_size, TupleDescAttr, CopyFromStateData::typioparams, CopyFromStateData::volatile_defexprs, CopyFromStateData::whereClause, and whereToSendOutput.

Referenced by copy_table(), DoCopy(), file_acquire_sample_rows(), fileBeginForeignScan(), and fileReScanForeignScan().

◆ BeginCopyTo()

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 at line 357 of file copyto.c.

366 {
367  CopyToState cstate;
368  bool pipe = (filename == NULL && data_dest_cb == NULL);
369  TupleDesc tupDesc;
370  int num_phys_attrs;
371  MemoryContext oldcontext;
372  const int progress_cols[] = {
375  };
376  int64 progress_vals[] = {
378  0
379  };
380 
381  if (rel != NULL && rel->rd_rel->relkind != RELKIND_RELATION)
382  {
383  if (rel->rd_rel->relkind == RELKIND_VIEW)
384  ereport(ERROR,
385  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
386  errmsg("cannot copy from view \"%s\"",
388  errhint("Try the COPY (SELECT ...) TO variant.")));
389  else if (rel->rd_rel->relkind == RELKIND_MATVIEW)
390  ereport(ERROR,
391  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
392  errmsg("cannot copy from materialized view \"%s\"",
394  errhint("Try the COPY (SELECT ...) TO variant.")));
395  else if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
396  ereport(ERROR,
397  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
398  errmsg("cannot copy from foreign table \"%s\"",
400  errhint("Try the COPY (SELECT ...) TO variant.")));
401  else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
402  ereport(ERROR,
403  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
404  errmsg("cannot copy from sequence \"%s\"",
405  RelationGetRelationName(rel))));
406  else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
407  ereport(ERROR,
408  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
409  errmsg("cannot copy from partitioned table \"%s\"",
411  errhint("Try the COPY (SELECT ...) TO variant.")));
412  else
413  ereport(ERROR,
414  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
415  errmsg("cannot copy from non-table relation \"%s\"",
416  RelationGetRelationName(rel))));
417  }
418 
419 
420  /* Allocate workspace and zero all fields */
421  cstate = (CopyToStateData *) palloc0(sizeof(CopyToStateData));
422 
423  /*
424  * We allocate everything used by a cstate in a new memory context. This
425  * avoids memory leaks during repeated use of COPY in a query.
426  */
428  "COPY",
430 
431  oldcontext = MemoryContextSwitchTo(cstate->copycontext);
432 
433  /* Extract options from the statement node tree */
434  ProcessCopyOptions(pstate, &cstate->opts, false /* is_from */ , options);
435 
436  /* Process the source/target relation or query */
437  if (rel)
438  {
439  Assert(!raw_query);
440 
441  cstate->rel = rel;
442 
443  tupDesc = RelationGetDescr(cstate->rel);
444  }
445  else
446  {
447  List *rewritten;
448  Query *query;
449  PlannedStmt *plan;
451 
452  cstate->rel = NULL;
453 
454  /*
455  * Run parse analysis and rewrite. Note this also acquires sufficient
456  * locks on the source table(s).
457  */
458  rewritten = pg_analyze_and_rewrite_fixedparams(raw_query,
459  pstate->p_sourcetext, NULL, 0,
460  NULL);
461 
462  /* check that we got back something we can work with */
463  if (rewritten == NIL)
464  {
465  ereport(ERROR,
466  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
467  errmsg("DO INSTEAD NOTHING rules are not supported for COPY")));
468  }
469  else if (list_length(rewritten) > 1)
470  {
471  ListCell *lc;
472 
473  /* examine queries to determine which error message to issue */
474  foreach(lc, rewritten)
475  {
476  Query *q = lfirst_node(Query, lc);
477 
478  if (q->querySource == QSRC_QUAL_INSTEAD_RULE)
479  ereport(ERROR,
480  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
481  errmsg("conditional DO INSTEAD rules are not supported for COPY")));
482  if (q->querySource == QSRC_NON_INSTEAD_RULE)
483  ereport(ERROR,
484  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
485  errmsg("DO ALSO rules are not supported for the COPY")));
486  }
487 
488  ereport(ERROR,
489  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
490  errmsg("multi-statement DO INSTEAD rules are not supported for COPY")));
491  }
492 
493  query = linitial_node(Query, rewritten);
494 
495  /* The grammar allows SELECT INTO, but we don't support that */
496  if (query->utilityStmt != NULL &&
498  ereport(ERROR,
499  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
500  errmsg("COPY (SELECT INTO) is not supported")));
501 
502  Assert(query->utilityStmt == NULL);
503 
504  /*
505  * Similarly the grammar doesn't enforce the presence of a RETURNING
506  * clause, but this is required here.
507  */
508  if (query->commandType != CMD_SELECT &&
509  query->returningList == NIL)
510  {
511  Assert(query->commandType == CMD_INSERT ||
512  query->commandType == CMD_UPDATE ||
513  query->commandType == CMD_DELETE);
514 
515  ereport(ERROR,
516  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
517  errmsg("COPY query must have a RETURNING clause")));
518  }
519 
520  /* plan the query */
521  plan = pg_plan_query(query, pstate->p_sourcetext,
522  CURSOR_OPT_PARALLEL_OK, NULL);
523 
524  /*
525  * With row-level security and a user using "COPY relation TO", we
526  * have to convert the "COPY relation TO" to a query-based COPY (eg:
527  * "COPY (SELECT * FROM ONLY relation) TO"), to allow the rewriter to
528  * add in any RLS clauses.
529  *
530  * When this happens, we are passed in the relid of the originally
531  * found relation (which we have locked). As the planner will look up
532  * the relation again, we double-check here to make sure it found the
533  * same one that we have locked.
534  */
535  if (queryRelId != InvalidOid)
536  {
537  /*
538  * Note that with RLS involved there may be multiple relations,
539  * and while the one we need is almost certainly first, we don't
540  * make any guarantees of that in the planner, so check the whole
541  * list and make sure we find the original relation.
542  */
543  if (!list_member_oid(plan->relationOids, queryRelId))
544  ereport(ERROR,
545  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
546  errmsg("relation referenced by COPY statement has changed")));
547  }
548 
549  /*
550  * Use a snapshot with an updated command ID to ensure this query sees
551  * results of any previously executed queries.
552  */
555 
556  /* Create dest receiver for COPY OUT */
558  ((DR_copy *) dest)->cstate = cstate;
559 
560  /* Create a QueryDesc requesting no output */
561  cstate->queryDesc = CreateQueryDesc(plan, pstate->p_sourcetext,
564  dest, NULL, NULL, 0);
565 
566  /*
567  * Call ExecutorStart to prepare the plan for execution.
568  *
569  * ExecutorStart computes a result tupdesc for us
570  */
571  ExecutorStart(cstate->queryDesc, 0);
572 
573  tupDesc = cstate->queryDesc->tupDesc;
574  }
575 
576  /* Generate or convert list of attributes to process */
577  cstate->attnumlist = CopyGetAttnums(tupDesc, cstate->rel, attnamelist);
578 
579  num_phys_attrs = tupDesc->natts;
580 
581  /* Convert FORCE_QUOTE name list to per-column flags, check validity */
582  cstate->opts.force_quote_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
583  if (cstate->opts.force_quote_all)
584  {
585  MemSet(cstate->opts.force_quote_flags, true, num_phys_attrs * sizeof(bool));
586  }
587  else if (cstate->opts.force_quote)
588  {
589  List *attnums;
590  ListCell *cur;
591 
592  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_quote);
593 
594  foreach(cur, attnums)
595  {
596  int attnum = lfirst_int(cur);
597  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
598 
599  if (!list_member_int(cstate->attnumlist, attnum))
600  ereport(ERROR,
601  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
602  errmsg("FORCE_QUOTE column \"%s\" not referenced by COPY",
603  NameStr(attr->attname))));
604  cstate->opts.force_quote_flags[attnum - 1] = true;
605  }
606  }
607 
608  /* Use client encoding when ENCODING option is not specified. */
609  if (cstate->opts.file_encoding < 0)
611  else
612  cstate->file_encoding = cstate->opts.file_encoding;
613 
614  /*
615  * Set up encoding conversion info. Even if the file and server encodings
616  * are the same, we must apply pg_any_to_server() to validate data in
617  * multibyte encodings.
618  */
619  cstate->need_transcoding =
620  (cstate->file_encoding != GetDatabaseEncoding() ||
622  /* See Multibyte encoding comment above */
624 
625  cstate->copy_dest = COPY_FILE; /* default */
626 
627  if (data_dest_cb)
628  {
629  progress_vals[1] = PROGRESS_COPY_TYPE_CALLBACK;
630  cstate->copy_dest = COPY_CALLBACK;
631  cstate->data_dest_cb = data_dest_cb;
632  }
633  else if (pipe)
634  {
635  progress_vals[1] = PROGRESS_COPY_TYPE_PIPE;
636 
637  Assert(!is_program); /* the grammar does not allow this */
639  cstate->copy_file = stdout;
640  }
641  else
642  {
643  cstate->filename = pstrdup(filename);
644  cstate->is_program = is_program;
645 
646  if (is_program)
647  {
648  progress_vals[1] = PROGRESS_COPY_TYPE_PROGRAM;
649  cstate->copy_file = OpenPipeStream(cstate->filename, PG_BINARY_W);
650  if (cstate->copy_file == NULL)
651  ereport(ERROR,
653  errmsg("could not execute command \"%s\": %m",
654  cstate->filename)));
655  }
656  else
657  {
658  mode_t oumask; /* Pre-existing umask value */
659  struct stat st;
660 
661  progress_vals[1] = PROGRESS_COPY_TYPE_FILE;
662 
663  /*
664  * Prevent write to relative path ... too easy to shoot oneself in
665  * the foot by overwriting a database file ...
666  */
668  ereport(ERROR,
669  (errcode(ERRCODE_INVALID_NAME),
670  errmsg("relative path not allowed for COPY to file")));
671 
672  oumask = umask(S_IWGRP | S_IWOTH);
673  PG_TRY();
674  {
675  cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_W);
676  }
677  PG_FINALLY();
678  {
679  umask(oumask);
680  }
681  PG_END_TRY();
682  if (cstate->copy_file == NULL)
683  {
684  /* copy errno because ereport subfunctions might change it */
685  int save_errno = errno;
686 
687  ereport(ERROR,
689  errmsg("could not open file \"%s\" for writing: %m",
690  cstate->filename),
691  (save_errno == ENOENT || save_errno == EACCES) ?
692  errhint("COPY TO instructs the PostgreSQL server process to write a file. "
693  "You may want a client-side facility such as psql's \\copy.") : 0));
694  }
695 
696  if (fstat(fileno(cstate->copy_file), &st))
697  ereport(ERROR,
699  errmsg("could not stat file \"%s\": %m",
700  cstate->filename)));
701 
702  if (S_ISDIR(st.st_mode))
703  ereport(ERROR,
704  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
705  errmsg("\"%s\" is a directory", cstate->filename)));
706  }
707  }
708 
709  /* initialize progress */
711  cstate->rel ? RelationGetRelid(cstate->rel) : InvalidOid);
712  pgstat_progress_update_multi_param(2, progress_cols, progress_vals);
713 
714  cstate->bytes_processed = 0;
715 
716  MemoryContextSwitchTo(oldcontext);
717 
718  return cstate;
719 }
#define PG_BINARY_W
Definition: c.h:1286
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:113
@ DestCopyOut
Definition: dest.h:95
#define PG_TRY(...)
Definition: elog.h:370
#define PG_END_TRY(...)
Definition: elog.h:395
#define PG_FINALLY(...)
Definition: elog.h:387
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:132
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:721
int pg_database_encoding_max_length(void)
Definition: mbutils.c:1553
#define IsA(nodeptr, _type_)
Definition: nodes.h:179
@ CMD_INSERT
Definition: nodes.h:278
@ CMD_DELETE
Definition: nodes.h:279
@ CMD_UPDATE
Definition: nodes.h:277
@ CMD_SELECT
Definition: nodes.h:276
@ QSRC_NON_INSTEAD_RULE
Definition: parsenodes.h:40
@ QSRC_QUAL_INSTEAD_RULE
Definition: parsenodes.h:39
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:3141
#define lfirst_node(type, lc)
Definition: pg_list.h:176
#define linitial_node(type, l)
Definition: pg_list.h:181
#define NIL
Definition: pg_list.h:68
#define plan(x)
Definition: pg_regress.c:162
#define PG_ENCODING_IS_CLIENT_ONLY(_enc)
Definition: pg_wchar.h:287
#define is_absolute_path(filename)
Definition: port.h:103
List * pg_analyze_and_rewrite_fixedparams(RawStmt *parsetree, const char *query_string, const Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
Definition: postgres.c:670
PlannedStmt * pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, ParamListInfo boundParams)
Definition: postgres.c:885
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
Definition: pquery.c:67
#define PROGRESS_COPY_COMMAND_TO
Definition: progress.h:148
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:719
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:707
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:777
#define InvalidSnapshot
Definition: snapshot.h:123
bool force_quote_all
Definition: copy.h:56
List * force_quote
Definition: copy.h:55
bool * force_quote_flags
Definition: copy.h:57
MemoryContext copycontext
Definition: copyto.c:97
Relation rel
Definition: copyto.c:84
copy_data_dest_cb data_dest_cb
Definition: copyto.c:89
bool encoding_embeds_ascii
Definition: copyto.c:81
CopyDest copy_dest
Definition: copyto.c:75
bool need_transcoding
Definition: copyto.c:80
bool is_program
Definition: copyto.c:88
FILE * copy_file
Definition: copyto.c:76
int file_encoding
Definition: copyto.c:79
CopyFormatOptions opts
Definition: copyto.c:91
uint64 bytes_processed
Definition: copyto.c:101
char * filename
Definition: copyto.c:87
List * attnumlist
Definition: copyto.c:86
QueryDesc * queryDesc
Definition: copyto.c:85
const char * p_sourcetext
Definition: parse_node.h:192
TupleDesc tupDesc
Definition: execdesc.h:47
List * returningList
Definition: parsenodes.h:188
CmdType commandType
Definition: parsenodes.h:120
Node * utilityStmt
Definition: parsenodes.h:135
Form_pg_class rd_rel
Definition: rel.h:111
#define S_IWOTH
Definition: win32_port.h:316
#define S_IWGRP
Definition: win32_port.h:304

References AllocateFile(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert(), attnum, CopyToStateData::attnumlist, CopyToStateData::bytes_processed, CMD_DELETE, CMD_INSERT, CMD_SELECT, CMD_UPDATE, Query::commandType, COPY_CALLBACK, CopyToStateData::copy_dest, COPY_FILE, CopyToStateData::copy_file, CopyToStateData::copycontext, CopyGetAttnums(), CreateDestReceiver(), CreateQueryDesc(), cur, CurrentMemoryContext, CURSOR_OPT_PARALLEL_OK, CopyToStateData::data_dest_cb, generate_unaccent_rules::dest, DestCopyOut, DestRemote, CopyToStateData::encoding_embeds_ascii, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), ERROR, ExecutorStart(), CopyToStateData::file_encoding, CopyFormatOptions::file_encoding, CopyToStateData::filename, filename, CopyFormatOptions::force_quote, CopyFormatOptions::force_quote_all, CopyFormatOptions::force_quote_flags, fstat, GetActiveSnapshot(), GetDatabaseEncoding(), InvalidOid, InvalidSnapshot, is_absolute_path, CopyToStateData::is_program, IsA, lfirst_int, lfirst_node, linitial_node, list_length(), list_member_int(), list_member_oid(), MemoryContextSwitchTo(), MemSet, NameStr, TupleDescData::natts, CopyToStateData::need_transcoding, NIL, OpenPipeStream(), CopyToStateData::opts, ParseState::p_sourcetext, palloc0(), pg_analyze_and_rewrite_fixedparams(), PG_BINARY_W, pg_database_encoding_max_length(), PG_ENCODING_IS_CLIENT_ONLY, PG_END_TRY, PG_FINALLY, pg_get_client_encoding(), pg_plan_query(), PG_TRY, pgstat_progress_start_command(), pgstat_progress_update_multi_param(), plan, ProcessCopyOptions(), PROGRESS_COMMAND_COPY, PROGRESS_COPY_COMMAND, PROGRESS_COPY_COMMAND_TO, PROGRESS_COPY_TYPE, PROGRESS_COPY_TYPE_CALLBACK, PROGRESS_COPY_TYPE_FILE, PROGRESS_COPY_TYPE_PIPE, PROGRESS_COPY_TYPE_PROGRAM, pstrdup(), PushCopiedSnapshot(), QSRC_NON_INSTEAD_RULE, QSRC_QUAL_INSTEAD_RULE, CopyToStateData::queryDesc, RelationData::rd_rel, CopyToStateData::rel, RelationGetDescr, RelationGetRelationName, RelationGetRelid, Query::returningList, S_ISDIR, S_IWGRP, S_IWOTH, stat::st_mode, generate_unaccent_rules::stdout, QueryDesc::tupDesc, TupleDescAttr, UpdateActiveSnapshotCommandId(), Query::utilityStmt, and whereToSendOutput.

Referenced by DoCopy(), and test_copy_to_callback().

◆ CopyFrom()

uint64 CopyFrom ( CopyFromState  cstate)

Definition at line 632 of file copyfrom.c.

633 {
634  ResultRelInfo *resultRelInfo;
635  ResultRelInfo *target_resultRelInfo;
636  ResultRelInfo *prevResultRelInfo = NULL;
637  EState *estate = CreateExecutorState(); /* for ExecConstraints() */
638  ModifyTableState *mtstate;
639  ExprContext *econtext;
640  TupleTableSlot *singleslot = NULL;
641  MemoryContext oldcontext = CurrentMemoryContext;
642 
643  PartitionTupleRouting *proute = NULL;
644  ErrorContextCallback errcallback;
645  CommandId mycid = GetCurrentCommandId(true);
646  int ti_options = 0; /* start with default options for insert */
647  BulkInsertState bistate = NULL;
648  CopyInsertMethod insertMethod;
649  CopyMultiInsertInfo multiInsertInfo = {0}; /* pacify compiler */
650  int64 processed = 0;
651  int64 excluded = 0;
652  bool has_before_insert_row_trig;
653  bool has_instead_insert_row_trig;
654  bool leafpart_use_multi_insert = false;
655 
656  Assert(cstate->rel);
657  Assert(list_length(cstate->range_table) == 1);
658 
659  /*
660  * The target must be a plain, foreign, or partitioned relation, or have
661  * an INSTEAD OF INSERT row trigger. (Currently, such triggers are only
662  * allowed on views, so we only hint about them in the view case.)
663  */
664  if (cstate->rel->rd_rel->relkind != RELKIND_RELATION &&
665  cstate->rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
666  cstate->rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE &&
667  !(cstate->rel->trigdesc &&
669  {
670  if (cstate->rel->rd_rel->relkind == RELKIND_VIEW)
671  ereport(ERROR,
672  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
673  errmsg("cannot copy to view \"%s\"",
674  RelationGetRelationName(cstate->rel)),
675  errhint("To enable copying to a view, provide an INSTEAD OF INSERT trigger.")));
676  else if (cstate->rel->rd_rel->relkind == RELKIND_MATVIEW)
677  ereport(ERROR,
678  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
679  errmsg("cannot copy to materialized view \"%s\"",
680  RelationGetRelationName(cstate->rel))));
681  else if (cstate->rel->rd_rel->relkind == RELKIND_SEQUENCE)
682  ereport(ERROR,
683  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
684  errmsg("cannot copy to sequence \"%s\"",
685  RelationGetRelationName(cstate->rel))));
686  else
687  ereport(ERROR,
688  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
689  errmsg("cannot copy to non-table relation \"%s\"",
690  RelationGetRelationName(cstate->rel))));
691  }
692 
693  /*
694  * If the target file is new-in-transaction, we assume that checking FSM
695  * for free space is a waste of time. This could possibly be wrong, but
696  * it's unlikely.
697  */
698  if (RELKIND_HAS_STORAGE(cstate->rel->rd_rel->relkind) &&
701  ti_options |= TABLE_INSERT_SKIP_FSM;
702 
703  /*
704  * Optimize if new relation storage was created in this subxact or one of
705  * its committed children and we won't see those rows later as part of an
706  * earlier scan or command. The subxact test ensures that if this subxact
707  * aborts then the frozen rows won't be visible after xact cleanup. Note
708  * that the stronger test of exactly which subtransaction created it is
709  * crucial for correctness of this optimization. The test for an earlier
710  * scan or command tolerates false negatives. FREEZE causes other sessions
711  * to see rows they would not see under MVCC, and a false negative merely
712  * spreads that anomaly to the current session.
713  */
714  if (cstate->opts.freeze)
715  {
716  /*
717  * We currently disallow COPY FREEZE on partitioned tables. The
718  * reason for this is that we've simply not yet opened the partitions
719  * to determine if the optimization can be applied to them. We could
720  * go and open them all here, but doing so may be quite a costly
721  * overhead for small copies. In any case, we may just end up routing
722  * tuples to a small number of partitions. It seems better just to
723  * raise an ERROR for partitioned tables.
724  */
725  if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
726  {
727  ereport(ERROR,
728  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
729  errmsg("cannot perform COPY FREEZE on a partitioned table")));
730  }
731 
732  /*
733  * Tolerate one registration for the benefit of FirstXactSnapshot.
734  * Scan-bearing queries generally create at least two registrations,
735  * though relying on that is fragile, as is ignoring ActiveSnapshot.
736  * Clear CatalogSnapshot to avoid counting its registration. We'll
737  * still detect ongoing catalog scans, each of which separately
738  * registers the snapshot it uses.
739  */
742  ereport(ERROR,
743  (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
744  errmsg("cannot perform COPY FREEZE because of prior transaction activity")));
745 
746  if (cstate->rel->rd_createSubid != GetCurrentSubTransactionId() &&
748  ereport(ERROR,
749  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
750  errmsg("cannot perform COPY FREEZE because the table was not created or truncated in the current subtransaction")));
751 
752  ti_options |= TABLE_INSERT_FROZEN;
753  }
754 
755  /*
756  * We need a ResultRelInfo so we can use the regular executor's
757  * index-entry-making machinery. (There used to be a huge amount of code
758  * here that basically duplicated execUtils.c ...)
759  */
760  ExecInitRangeTable(estate, cstate->range_table, cstate->rteperminfos);
761  resultRelInfo = target_resultRelInfo = makeNode(ResultRelInfo);
762  ExecInitResultRelation(estate, resultRelInfo, 1);
763 
764  /* Verify the named relation is a valid target for INSERT */
765  CheckValidResultRel(resultRelInfo, CMD_INSERT);
766 
767  ExecOpenIndices(resultRelInfo, false);
768 
769  /*
770  * Set up a ModifyTableState so we can let FDW(s) init themselves for
771  * foreign-table result relation(s).
772  */
773  mtstate = makeNode(ModifyTableState);
774  mtstate->ps.plan = NULL;
775  mtstate->ps.state = estate;
776  mtstate->operation = CMD_INSERT;
777  mtstate->mt_nrels = 1;
778  mtstate->resultRelInfo = resultRelInfo;
779  mtstate->rootResultRelInfo = resultRelInfo;
780 
781  if (resultRelInfo->ri_FdwRoutine != NULL &&
782  resultRelInfo->ri_FdwRoutine->BeginForeignInsert != NULL)
783  resultRelInfo->ri_FdwRoutine->BeginForeignInsert(mtstate,
784  resultRelInfo);
785 
786  /*
787  * Also, if the named relation is a foreign table, determine if the FDW
788  * supports batch insert and determine the batch size (a FDW may support
789  * batching, but it may be disabled for the server/table).
790  *
791  * If the FDW does not support batching, we set the batch size to 1.
792  */
793  if (resultRelInfo->ri_FdwRoutine != NULL &&
794  resultRelInfo->ri_FdwRoutine->GetForeignModifyBatchSize &&
795  resultRelInfo->ri_FdwRoutine->ExecForeignBatchInsert)
796  resultRelInfo->ri_BatchSize =
797  resultRelInfo->ri_FdwRoutine->GetForeignModifyBatchSize(resultRelInfo);
798  else
799  resultRelInfo->ri_BatchSize = 1;
800 
801  Assert(resultRelInfo->ri_BatchSize >= 1);
802 
803  /* Prepare to catch AFTER triggers. */
805 
806  /*
807  * If there are any triggers with transition tables on the named relation,
808  * we need to be prepared to capture transition tuples.
809  *
810  * Because partition tuple routing would like to know about whether
811  * transition capture is active, we also set it in mtstate, which is
812  * passed to ExecFindPartition() below.
813  */
814  cstate->transition_capture = mtstate->mt_transition_capture =
816  RelationGetRelid(cstate->rel),
817  CMD_INSERT);
818 
819  /*
820  * If the named relation is a partitioned table, initialize state for
821  * CopyFrom tuple routing.
822  */
823  if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
824  proute = ExecSetupPartitionTupleRouting(estate, cstate->rel);
825 
826  if (cstate->whereClause)
827  cstate->qualexpr = ExecInitQual(castNode(List, cstate->whereClause),
828  &mtstate->ps);
829 
830  /*
831  * It's generally more efficient to prepare a bunch of tuples for
832  * insertion, and insert them in one
833  * table_multi_insert()/ExecForeignBatchInsert() call, than call
834  * table_tuple_insert()/ExecForeignInsert() separately for every tuple.
835  * However, there are a number of reasons why we might not be able to do
836  * this. These are explained below.
837  */
838  if (resultRelInfo->ri_TrigDesc != NULL &&
839  (resultRelInfo->ri_TrigDesc->trig_insert_before_row ||
840  resultRelInfo->ri_TrigDesc->trig_insert_instead_row))
841  {
842  /*
843  * Can't support multi-inserts when there are any BEFORE/INSTEAD OF
844  * triggers on the table. Such triggers might query the table we're
845  * inserting into and act differently if the tuples that have already
846  * been processed and prepared for insertion are not there.
847  */
848  insertMethod = CIM_SINGLE;
849  }
850  else if (resultRelInfo->ri_FdwRoutine != NULL &&
851  resultRelInfo->ri_BatchSize == 1)
852  {
853  /*
854  * Can't support multi-inserts to a foreign table if the FDW does not
855  * support batching, or it's disabled for the server or foreign table.
856  */
857  insertMethod = CIM_SINGLE;
858  }
859  else if (proute != NULL && resultRelInfo->ri_TrigDesc != NULL &&
860  resultRelInfo->ri_TrigDesc->trig_insert_new_table)
861  {
862  /*
863  * For partitioned tables we can't support multi-inserts when there
864  * are any statement level insert triggers. It might be possible to
865  * allow partitioned tables with such triggers in the future, but for
866  * now, CopyMultiInsertInfoFlush expects that any after row insert and
867  * statement level insert triggers are on the same relation.
868  */
869  insertMethod = CIM_SINGLE;
870  }
871  else if (cstate->volatile_defexprs)
872  {
873  /*
874  * Can't support multi-inserts if there are any volatile default
875  * expressions in the table. Similarly to the trigger case above,
876  * such expressions may query the table we're inserting into.
877  *
878  * Note: It does not matter if any partitions have any volatile
879  * default expressions as we use the defaults from the target of the
880  * COPY command.
881  */
882  insertMethod = CIM_SINGLE;
883  }
884  else if (contain_volatile_functions(cstate->whereClause))
885  {
886  /*
887  * Can't support multi-inserts if there are any volatile function
888  * expressions in WHERE clause. Similarly to the trigger case above,
889  * such expressions may query the table we're inserting into.
890  *
891  * Note: the whereClause was already preprocessed in DoCopy(), so it's
892  * okay to use contain_volatile_functions() directly.
893  */
894  insertMethod = CIM_SINGLE;
895  }
896  else
897  {
898  /*
899  * For partitioned tables, we may still be able to perform bulk
900  * inserts. However, the possibility of this depends on which types
901  * of triggers exist on the partition. We must disable bulk inserts
902  * if the partition is a foreign table that can't use batching or it
903  * has any before row insert or insert instead triggers (same as we
904  * checked above for the parent table). Since the partition's
905  * resultRelInfos are initialized only when we actually need to insert
906  * the first tuple into them, we must have the intermediate insert
907  * method of CIM_MULTI_CONDITIONAL to flag that we must later
908  * determine if we can use bulk-inserts for the partition being
909  * inserted into.
910  */
911  if (proute)
912  insertMethod = CIM_MULTI_CONDITIONAL;
913  else
914  insertMethod = CIM_MULTI;
915 
916  CopyMultiInsertInfoInit(&multiInsertInfo, resultRelInfo, cstate,
917  estate, mycid, ti_options);
918  }
919 
920  /*
921  * If not using batch mode (which allocates slots as needed) set up a
922  * tuple slot too. When inserting into a partitioned table, we also need
923  * one, even if we might batch insert, to read the tuple in the root
924  * partition's form.
925  */
926  if (insertMethod == CIM_SINGLE || insertMethod == CIM_MULTI_CONDITIONAL)
927  {
928  singleslot = table_slot_create(resultRelInfo->ri_RelationDesc,
929  &estate->es_tupleTable);
930  bistate = GetBulkInsertState();
931  }
932 
933  has_before_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
934  resultRelInfo->ri_TrigDesc->trig_insert_before_row);
935 
936  has_instead_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
937  resultRelInfo->ri_TrigDesc->trig_insert_instead_row);
938 
939  /*
940  * Check BEFORE STATEMENT insertion triggers. It's debatable whether we
941  * should do this for COPY, since it's not really an "INSERT" statement as
942  * such. However, executing these triggers maintains consistency with the
943  * EACH ROW triggers that we already fire on COPY.
944  */
945  ExecBSInsertTriggers(estate, resultRelInfo);
946 
947  econtext = GetPerTupleExprContext(estate);
948 
949  /* Set up callback to identify error line number */
950  errcallback.callback = CopyFromErrorCallback;
951  errcallback.arg = (void *) cstate;
952  errcallback.previous = error_context_stack;
953  error_context_stack = &errcallback;
954 
955  for (;;)
956  {
957  TupleTableSlot *myslot;
958  bool skip_tuple;
959 
961 
962  /*
963  * Reset the per-tuple exprcontext. We do this after every tuple, to
964  * clean-up after expression evaluations etc.
965  */
966  ResetPerTupleExprContext(estate);
967 
968  /* select slot to (initially) load row into */
969  if (insertMethod == CIM_SINGLE || proute)
970  {
971  myslot = singleslot;
972  Assert(myslot != NULL);
973  }
974  else
975  {
976  Assert(resultRelInfo == target_resultRelInfo);
977  Assert(insertMethod == CIM_MULTI);
978 
979  myslot = CopyMultiInsertInfoNextFreeSlot(&multiInsertInfo,
980  resultRelInfo);
981  }
982 
983  /*
984  * Switch to per-tuple context before calling NextCopyFrom, which does
985  * evaluate default expressions etc. and requires per-tuple context.
986  */
988 
989  ExecClearTuple(myslot);
990 
991  /* Directly store the values/nulls array in the slot */
992  if (!NextCopyFrom(cstate, econtext, myslot->tts_values, myslot->tts_isnull))
993  break;
994 
995  ExecStoreVirtualTuple(myslot);
996 
997  /*
998  * Constraints and where clause might reference the tableoid column,
999  * so (re-)initialize tts_tableOid before evaluating them.
1000  */
1001  myslot->tts_tableOid = RelationGetRelid(target_resultRelInfo->ri_RelationDesc);
1002 
1003  /* Triggers and stuff need to be invoked in query context. */
1004  MemoryContextSwitchTo(oldcontext);
1005 
1006  if (cstate->whereClause)
1007  {
1008  econtext->ecxt_scantuple = myslot;
1009  /* Skip items that don't match COPY's WHERE clause */
1010  if (!ExecQual(cstate->qualexpr, econtext))
1011  {
1012  /*
1013  * Report that this tuple was filtered out by the WHERE
1014  * clause.
1015  */
1017  ++excluded);
1018  continue;
1019  }
1020  }
1021 
1022  /* Determine the partition to insert the tuple into */
1023  if (proute)
1024  {
1025  TupleConversionMap *map;
1026 
1027  /*
1028  * Attempt to find a partition suitable for this tuple.
1029  * ExecFindPartition() will raise an error if none can be found or
1030  * if the found partition is not suitable for INSERTs.
1031  */
1032  resultRelInfo = ExecFindPartition(mtstate, target_resultRelInfo,
1033  proute, myslot, estate);
1034 
1035  if (prevResultRelInfo != resultRelInfo)
1036  {
1037  /* Determine which triggers exist on this partition */
1038  has_before_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
1039  resultRelInfo->ri_TrigDesc->trig_insert_before_row);
1040 
1041  has_instead_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
1042  resultRelInfo->ri_TrigDesc->trig_insert_instead_row);
1043 
1044  /*
1045  * Disable multi-inserts when the partition has BEFORE/INSTEAD
1046  * OF triggers, or if the partition is a foreign table that
1047  * can't use batching.
1048  */
1049  leafpart_use_multi_insert = insertMethod == CIM_MULTI_CONDITIONAL &&
1050  !has_before_insert_row_trig &&
1051  !has_instead_insert_row_trig &&
1052  (resultRelInfo->ri_FdwRoutine == NULL ||
1053  resultRelInfo->ri_BatchSize > 1);
1054 
1055  /* Set the multi-insert buffer to use for this partition. */
1056  if (leafpart_use_multi_insert)
1057  {
1058  if (resultRelInfo->ri_CopyMultiInsertBuffer == NULL)
1059  CopyMultiInsertInfoSetupBuffer(&multiInsertInfo,
1060  resultRelInfo);
1061  }
1062  else if (insertMethod == CIM_MULTI_CONDITIONAL &&
1063  !CopyMultiInsertInfoIsEmpty(&multiInsertInfo))
1064  {
1065  /*
1066  * Flush pending inserts if this partition can't use
1067  * batching, so rows are visible to triggers etc.
1068  */
1069  CopyMultiInsertInfoFlush(&multiInsertInfo,
1070  resultRelInfo,
1071  &processed);
1072  }
1073 
1074  if (bistate != NULL)
1075  ReleaseBulkInsertStatePin(bistate);
1076  prevResultRelInfo = resultRelInfo;
1077  }
1078 
1079  /*
1080  * If we're capturing transition tuples, we might need to convert
1081  * from the partition rowtype to root rowtype. But if there are no
1082  * BEFORE triggers on the partition that could change the tuple,
1083  * we can just remember the original unconverted tuple to avoid a
1084  * needless round trip conversion.
1085  */
1086  if (cstate->transition_capture != NULL)
1088  !has_before_insert_row_trig ? myslot : NULL;
1089 
1090  /*
1091  * We might need to convert from the root rowtype to the partition
1092  * rowtype.
1093  */
1094  map = ExecGetRootToChildMap(resultRelInfo, estate);
1095  if (insertMethod == CIM_SINGLE || !leafpart_use_multi_insert)
1096  {
1097  /* non batch insert */
1098  if (map != NULL)
1099  {
1100  TupleTableSlot *new_slot;
1101 
1102  new_slot = resultRelInfo->ri_PartitionTupleSlot;
1103  myslot = execute_attr_map_slot(map->attrMap, myslot, new_slot);
1104  }
1105  }
1106  else
1107  {
1108  /*
1109  * Prepare to queue up tuple for later batch insert into
1110  * current partition.
1111  */
1112  TupleTableSlot *batchslot;
1113 
1114  /* no other path available for partitioned table */
1115  Assert(insertMethod == CIM_MULTI_CONDITIONAL);
1116 
1117  batchslot = CopyMultiInsertInfoNextFreeSlot(&multiInsertInfo,
1118  resultRelInfo);
1119 
1120  if (map != NULL)
1121  myslot = execute_attr_map_slot(map->attrMap, myslot,
1122  batchslot);
1123  else
1124  {
1125  /*
1126  * This looks more expensive than it is (Believe me, I
1127  * optimized it away. Twice.). The input is in virtual
1128  * form, and we'll materialize the slot below - for most
1129  * slot types the copy performs the work materialization
1130  * would later require anyway.
1131  */
1132  ExecCopySlot(batchslot, myslot);
1133  myslot = batchslot;
1134  }
1135  }
1136 
1137  /* ensure that triggers etc see the right relation */
1138  myslot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
1139  }
1140 
1141  skip_tuple = false;
1142 
1143  /* BEFORE ROW INSERT Triggers */
1144  if (has_before_insert_row_trig)
1145  {
1146  if (!ExecBRInsertTriggers(estate, resultRelInfo, myslot))
1147  skip_tuple = true; /* "do nothing" */
1148  }
1149 
1150  if (!skip_tuple)
1151  {
1152  /*
1153  * If there is an INSTEAD OF INSERT ROW trigger, let it handle the
1154  * tuple. Otherwise, proceed with inserting the tuple into the
1155  * table or foreign table.
1156  */
1157  if (has_instead_insert_row_trig)
1158  {
1159  ExecIRInsertTriggers(estate, resultRelInfo, myslot);
1160  }
1161  else
1162  {
1163  /* Compute stored generated columns */
1164  if (resultRelInfo->ri_RelationDesc->rd_att->constr &&
1166  ExecComputeStoredGenerated(resultRelInfo, estate, myslot,
1167  CMD_INSERT);
1168 
1169  /*
1170  * If the target is a plain table, check the constraints of
1171  * the tuple.
1172  */
1173  if (resultRelInfo->ri_FdwRoutine == NULL &&
1174  resultRelInfo->ri_RelationDesc->rd_att->constr)
1175  ExecConstraints(resultRelInfo, myslot, estate);
1176 
1177  /*
1178  * Also check the tuple against the partition constraint, if
1179  * there is one; except that if we got here via tuple-routing,
1180  * we don't need to if there's no BR trigger defined on the
1181  * partition.
1182  */
1183  if (resultRelInfo->ri_RelationDesc->rd_rel->relispartition &&
1184  (proute == NULL || has_before_insert_row_trig))
1185  ExecPartitionCheck(resultRelInfo, myslot, estate, true);
1186 
1187  /* Store the slot in the multi-insert buffer, when enabled. */
1188  if (insertMethod == CIM_MULTI || leafpart_use_multi_insert)
1189  {
1190  /*
1191  * The slot previously might point into the per-tuple
1192  * context. For batching it needs to be longer lived.
1193  */
1194  ExecMaterializeSlot(myslot);
1195 
1196  /* Add this tuple to the tuple buffer */
1197  CopyMultiInsertInfoStore(&multiInsertInfo,
1198  resultRelInfo, myslot,
1199  cstate->line_buf.len,
1200  cstate->cur_lineno);
1201 
1202  /*
1203  * If enough inserts have queued up, then flush all
1204  * buffers out to their tables.
1205  */
1206  if (CopyMultiInsertInfoIsFull(&multiInsertInfo))
1207  CopyMultiInsertInfoFlush(&multiInsertInfo,
1208  resultRelInfo,
1209  &processed);
1210 
1211  /*
1212  * We delay updating the row counter and progress of the
1213  * COPY command until after writing the tuples stored in
1214  * the buffer out to the table, as in single insert mode.
1215  * See CopyMultiInsertBufferFlush().
1216  */
1217  continue; /* next tuple please */
1218  }
1219  else
1220  {
1221  List *recheckIndexes = NIL;
1222 
1223  /* OK, store the tuple */
1224  if (resultRelInfo->ri_FdwRoutine != NULL)
1225  {
1226  myslot = resultRelInfo->ri_FdwRoutine->ExecForeignInsert(estate,
1227  resultRelInfo,
1228  myslot,
1229  NULL);
1230 
1231  if (myslot == NULL) /* "do nothing" */
1232  continue; /* next tuple please */
1233 
1234  /*
1235  * AFTER ROW Triggers might reference the tableoid
1236  * column, so (re-)initialize tts_tableOid before
1237  * evaluating them.
1238  */
1239  myslot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
1240  }
1241  else
1242  {
1243  /* OK, store the tuple and create index entries for it */
1244  table_tuple_insert(resultRelInfo->ri_RelationDesc,
1245  myslot, mycid, ti_options, bistate);
1246 
1247  if (resultRelInfo->ri_NumIndices > 0)
1248  recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
1249  myslot,
1250  estate,
1251  false,
1252  false,
1253  NULL,
1254  NIL,
1255  false);
1256  }
1257 
1258  /* AFTER ROW INSERT Triggers */
1259  ExecARInsertTriggers(estate, resultRelInfo, myslot,
1260  recheckIndexes, cstate->transition_capture);
1261 
1262  list_free(recheckIndexes);
1263  }
1264  }
1265 
1266  /*
1267  * We count only tuples not suppressed by a BEFORE INSERT trigger
1268  * or FDW; this is the same definition used by nodeModifyTable.c
1269  * for counting tuples inserted by an INSERT command. Update
1270  * progress of the COPY command as well.
1271  */
1273  ++processed);
1274  }
1275  }
1276 
1277  /* Flush any remaining buffered tuples */
1278  if (insertMethod != CIM_SINGLE)
1279  {
1280  if (!CopyMultiInsertInfoIsEmpty(&multiInsertInfo))
1281  CopyMultiInsertInfoFlush(&multiInsertInfo, NULL, &processed);
1282  }
1283 
1284  /* Done, clean up */
1285  error_context_stack = errcallback.previous;
1286 
1287  if (bistate != NULL)
1288  FreeBulkInsertState(bistate);
1289 
1290  MemoryContextSwitchTo(oldcontext);
1291 
1292  /* Execute AFTER STATEMENT insertion triggers */
1293  ExecASInsertTriggers(estate, target_resultRelInfo, cstate->transition_capture);
1294 
1295  /* Handle queued AFTER triggers */
1296  AfterTriggerEndQuery(estate);
1297 
1298  ExecResetTupleTable(estate->es_tupleTable, false);
1299 
1300  /* Allow the FDW to shut down */
1301  if (target_resultRelInfo->ri_FdwRoutine != NULL &&
1302  target_resultRelInfo->ri_FdwRoutine->EndForeignInsert != NULL)
1303  target_resultRelInfo->ri_FdwRoutine->EndForeignInsert(estate,
1304  target_resultRelInfo);
1305 
1306  /* Tear down the multi-insert buffer data */
1307  if (insertMethod != CIM_SINGLE)
1308  CopyMultiInsertInfoCleanup(&multiInsertInfo);
1309 
1310  /* Close all the partitioned tables, leaf partitions, and their indices */
1311  if (proute)
1312  ExecCleanupTupleRouting(mtstate, proute);
1313 
1314  /* Close the result relations, including any trigger target relations */
1315  ExecCloseResultRelations(estate);
1317 
1318  FreeExecutorState(estate);
1319 
1320  return processed;
1321 }
void pgstat_progress_update_param(int index, int64 val)
#define InvalidSubTransactionId
Definition: c.h:647
uint32 CommandId
Definition: c.h:655
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:521
static void CopyMultiInsertInfoSetupBuffer(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri)
Definition: copyfrom.c:242
static void CopyMultiInsertInfoInit(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri, CopyFromState cstate, EState *estate, CommandId mycid, int ti_options)
Definition: copyfrom.c:262
static void CopyMultiInsertInfoFlush(CopyMultiInsertInfo *miinfo, ResultRelInfo *curr_rri, int64 *processed)
Definition: copyfrom.c:524
static void CopyMultiInsertInfoStore(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri, TupleTableSlot *slot, int tuplen, uint64 lineno)
Definition: copyfrom.c:609
static void CopyMultiInsertInfoCleanup(CopyMultiInsertInfo *miinfo)
Definition: copyfrom.c:571
static bool CopyMultiInsertInfoIsFull(CopyMultiInsertInfo *miinfo)
Definition: copyfrom.c:287
static TupleTableSlot * CopyMultiInsertInfoNextFreeSlot(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri)
Definition: copyfrom.c:590
static bool CopyMultiInsertInfoIsEmpty(CopyMultiInsertInfo *miinfo)
Definition: copyfrom.c:299
void CopyFromErrorCallback(void *arg)
Definition: copyfrom.c:116
CopyInsertMethod
@ CIM_SINGLE
@ CIM_MULTI_CONDITIONAL
@ CIM_MULTI
bool NextCopyFrom(CopyFromState cstate, ExprContext *econtext, Datum *values, bool *nulls)
ErrorContextCallback * error_context_stack
Definition: elog.c:95
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:214
List * ExecInsertIndexTuples(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool update, bool noDupErr, bool *specConflict, List *arbiterIndexes, bool onlySummarizing)
Definition: execIndexing.c:298
void ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative)
Definition: execIndexing.c:156
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
Definition: execMain.c:1816
void ExecCloseResultRelations(EState *estate)
Definition: execMain.c:1541
void ExecCloseRangeTableRelations(EState *estate)
Definition: execMain.c:1601
void ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1940
void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation)
Definition: execMain.c:1024
ResultRelInfo * ExecFindPartition(ModifyTableState *mtstate, ResultRelInfo *rootResultRelInfo, PartitionTupleRouting *proute, TupleTableSlot *slot, EState *estate)
PartitionTupleRouting * ExecSetupPartitionTupleRouting(EState *estate, Relation rel)
void ExecCleanupTupleRouting(ModifyTableState *mtstate, PartitionTupleRouting *proute)
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:1190
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1551
void ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos)
Definition: execUtils.c:733
void ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo, Index rti)
Definition: execUtils.c:819
EState * CreateExecutorState(void)
Definition: execUtils.c:93
TupleConversionMap * ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate)
Definition: execUtils.c:1237
void FreeExecutorState(EState *estate)
Definition: execUtils.c:194
#define ResetPerTupleExprContext(estate)
Definition: executor.h:558
#define GetPerTupleExprContext(estate)
Definition: executor.h:549
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:554
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:412
void ReleaseBulkInsertStatePin(BulkInsertState bistate)
Definition: heapam.c:1790
BulkInsertState GetBulkInsertState(void)
Definition: heapam.c:1761
void FreeBulkInsertState(BulkInsertState bistate)
Definition: heapam.c:1778
void list_free(List *list)
Definition: list.c:1545
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
void ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo, EState *estate, TupleTableSlot *slot, CmdType cmdtype)
#define makeNode(_type_)
Definition: nodes.h:176
#define castNode(_type_, nodeptr)
Definition: nodes.h:197
bool ThereAreNoReadyPortals(void)
Definition: portalmem.c:1169
#define PROGRESS_COPY_TUPLES_PROCESSED
Definition: progress.h:141
#define PROGRESS_COPY_TUPLES_EXCLUDED
Definition: progress.h:142
bool ThereAreNoPriorRegisteredSnapshots(void)
Definition: snapmgr.c:1612
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:429
bool freeze
Definition: copy.h:44
TransitionCaptureState * transition_capture
List * es_tupleTable
Definition: execnodes.h:660
struct ErrorContextCallback * previous
Definition: elog.h:295
void(* callback)(void *arg)
Definition: elog.h:296
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:248
EndForeignInsert_function EndForeignInsert
Definition: fdwapi.h:239
BeginForeignInsert_function BeginForeignInsert
Definition: fdwapi.h:238
ExecForeignInsert_function ExecForeignInsert
Definition: fdwapi.h:232
ExecForeignBatchInsert_function ExecForeignBatchInsert
Definition: fdwapi.h:233
GetForeignModifyBatchSize_function GetForeignModifyBatchSize
Definition: fdwapi.h:234
CmdType operation
Definition: execnodes.h:1275
ResultRelInfo * resultRelInfo
Definition: execnodes.h:1279
PlanState ps
Definition: execnodes.h:1274
ResultRelInfo * rootResultRelInfo
Definition: execnodes.h:1287
struct TransitionCaptureState * mt_transition_capture
Definition: execnodes.h:1313
Plan * plan
Definition: execnodes.h:1036
EState * state
Definition: execnodes.h:1038
SubTransactionId rd_firstRelfilelocatorSubid
Definition: rel.h:106
TriggerDesc * trigdesc
Definition: rel.h:117
TupleDesc rd_att
Definition: rel.h:112
SubTransactionId rd_newRelfilelocatorSubid
Definition: rel.h:104
SubTransactionId rd_createSubid
Definition: rel.h:103
TupleTableSlot * ri_PartitionTupleSlot
Definition: execnodes.h:574
int ri_NumIndices
Definition: execnodes.h:452
Relation ri_RelationDesc
Definition: execnodes.h:449
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition: execnodes.h:577
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:479
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:496
int ri_BatchSize
Definition: execnodes.h:507
TupleTableSlot * tcs_original_insert_tuple
Definition: trigger.h:76
bool trig_insert_instead_row
Definition: reltrigger.h:58
bool trig_insert_new_table
Definition: reltrigger.h:75
bool trig_insert_before_row
Definition: reltrigger.h:56
bool has_generated_stored
Definition: tupdesc.h:45
AttrMap * attrMap
Definition: tupconvert.h:28
TupleConstr * constr
Definition: tupdesc.h:85
Oid tts_tableOid
Definition: tuptable.h:130
bool * tts_isnull
Definition: tuptable.h:127
Datum * tts_values
Definition: tuptable.h:125
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition: tableam.c:91
#define TABLE_INSERT_FROZEN
Definition: tableam.h:253
#define TABLE_INSERT_SKIP_FSM
Definition: tableam.h:252
static void table_tuple_insert(Relation rel, TupleTableSlot *slot, CommandId cid, int options, struct BulkInsertStateData *bistate)
Definition: tableam.h:1397
void ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2400
bool ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2464
bool ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2557
void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot, List *recheckIndexes, TransitionCaptureState *transition_capture)
Definition: trigger.c:2540
TransitionCaptureState * MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType)
Definition: trigger.c:4870
void ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo, TransitionCaptureState *transition_capture)
Definition: trigger.c:2451
void AfterTriggerEndQuery(EState *estate)
Definition: trigger.c:5026
void AfterTriggerBeginQuery(void)
Definition: trigger.c:5006
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition: tupconvert.c:192
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:433
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: tuptable.h:488
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition: tuptable.h:451
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:780
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:818

References AfterTriggerBeginQuery(), AfterTriggerEndQuery(), ErrorContextCallback::arg, Assert(), TupleConversionMap::attrMap, FdwRoutine::BeginForeignInsert, ErrorContextCallback::callback, castNode, CHECK_FOR_INTERRUPTS, CheckValidResultRel(), CIM_MULTI, CIM_MULTI_CONDITIONAL, CIM_SINGLE, CMD_INSERT, TupleDescData::constr, contain_volatile_functions(), CopyFromErrorCallback(), CopyMultiInsertInfoCleanup(), CopyMultiInsertInfoFlush(), CopyMultiInsertInfoInit(), CopyMultiInsertInfoIsEmpty(), CopyMultiInsertInfoIsFull(), CopyMultiInsertInfoNextFreeSlot(), CopyMultiInsertInfoSetupBuffer(), CopyMultiInsertInfoStore(), CreateExecutorState(), CopyFromStateData::cur_lineno, CurrentMemoryContext, ExprContext::ecxt_scantuple, FdwRoutine::EndForeignInsert, ereport, errcode(), errhint(), errmsg(), ERROR, error_context_stack, EState::es_tupleTable, ExecARInsertTriggers(), ExecASInsertTriggers(), ExecBRInsertTriggers(), ExecBSInsertTriggers(), ExecCleanupTupleRouting(), ExecClearTuple(), ExecCloseRangeTableRelations(), ExecCloseResultRelations(), ExecComputeStoredGenerated(), ExecConstraints(), ExecCopySlot(), ExecFindPartition(), FdwRoutine::ExecForeignBatchInsert, FdwRoutine::ExecForeignInsert, ExecGetRootToChildMap(), ExecInitQual(), ExecInitRangeTable(), ExecInitResultRelation(), ExecInsertIndexTuples(), ExecIRInsertTriggers(), ExecMaterializeSlot(), ExecOpenIndices(), ExecPartitionCheck(), ExecQual(), ExecResetTupleTable(), ExecSetupPartitionTupleRouting(), ExecStoreVirtualTuple(), execute_attr_map_slot(), FreeBulkInsertState(), FreeExecutorState(), CopyFormatOptions::freeze, GetBulkInsertState(), GetCurrentCommandId(), GetCurrentSubTransactionId(), FdwRoutine::GetForeignModifyBatchSize, GetPerTupleExprContext, GetPerTupleMemoryContext, TupleConstr::has_generated_stored, InvalidateCatalogSnapshot(), InvalidSubTransactionId, StringInfoData::len, CopyFromStateData::line_buf, list_free(), list_length(), makeNode, MakeTransitionCaptureState(), MemoryContextSwitchTo(), ModifyTableState::mt_nrels, ModifyTableState::mt_transition_capture, NextCopyFrom(), NIL, ModifyTableState::operation, CopyFromStateData::opts, pgstat_progress_update_param(), PlanState::plan, ErrorContextCallback::previous, PROGRESS_COPY_TUPLES_EXCLUDED, PROGRESS_COPY_TUPLES_PROCESSED, ModifyTableState::ps, CopyFromStateData::qualexpr, CopyFromStateData::range_table, RelationData::rd_att, RelationData::rd_createSubid, RelationData::rd_firstRelfilelocatorSubid, RelationData::rd_newRelfilelocatorSubid, RelationData::rd_rel, CopyFromStateData::rel, RelationGetRelationName, RelationGetRelid, ReleaseBulkInsertStatePin(), ResetPerTupleExprContext, ModifyTableState::resultRelInfo, ResultRelInfo::ri_BatchSize, ResultRelInfo::ri_CopyMultiInsertBuffer, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_PartitionTupleSlot, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, ModifyTableState::rootResultRelInfo, CopyFromStateData::rteperminfos, PlanState::state, TABLE_INSERT_FROZEN, TABLE_INSERT_SKIP_FSM, table_slot_create(), table_tuple_insert(), TransitionCaptureState::tcs_original_insert_tuple, ThereAreNoPriorRegisteredSnapshots(), ThereAreNoReadyPortals(), CopyFromStateData::transition_capture, TriggerDesc::trig_insert_before_row, TriggerDesc::trig_insert_instead_row, TriggerDesc::trig_insert_new_table, RelationData::trigdesc, TupleTableSlot::tts_isnull, TupleTableSlot::tts_tableOid, TupleTableSlot::tts_values, CopyFromStateData::volatile_defexprs, and CopyFromStateData::whereClause.

Referenced by copy_table(), and DoCopy().

◆ CopyFromErrorCallback()

void CopyFromErrorCallback ( void *  arg)

Definition at line 116 of file copyfrom.c.

117 {
118  CopyFromState cstate = (CopyFromState) arg;
119 
120  if (cstate->relname_only)
121  {
122  errcontext("COPY %s",
123  cstate->cur_relname);
124  return;
125  }
126  if (cstate->opts.binary)
127  {
128  /* can't usefully display the data */
129  if (cstate->cur_attname)
130  errcontext("COPY %s, line %llu, column %s",
131  cstate->cur_relname,
132  (unsigned long long) cstate->cur_lineno,
133  cstate->cur_attname);
134  else
135  errcontext("COPY %s, line %llu",
136  cstate->cur_relname,
137  (unsigned long long) cstate->cur_lineno);
138  }
139  else
140  {
141  if (cstate->cur_attname && cstate->cur_attval)
142  {
143  /* error is relevant to a particular column */
144  char *attval;
145 
146  attval = limit_printout_length(cstate->cur_attval);
147  errcontext("COPY %s, line %llu, column %s: \"%s\"",
148  cstate->cur_relname,
149  (unsigned long long) cstate->cur_lineno,
150  cstate->cur_attname,
151  attval);
152  pfree(attval);
153  }
154  else if (cstate->cur_attname)
155  {
156  /* error is relevant to a particular column, value is NULL */
157  errcontext("COPY %s, line %llu, column %s: null input",
158  cstate->cur_relname,
159  (unsigned long long) cstate->cur_lineno,
160  cstate->cur_attname);
161  }
162  else
163  {
164  /*
165  * Error is relevant to a particular line.
166  *
167  * If line_buf still contains the correct line, print it.
168  */
169  if (cstate->line_buf_valid)
170  {
171  char *lineval;
172 
173  lineval = limit_printout_length(cstate->line_buf.data);
174  errcontext("COPY %s, line %llu: \"%s\"",
175  cstate->cur_relname,
176  (unsigned long long) cstate->cur_lineno, lineval);
177  pfree(lineval);
178  }
179  else
180  {
181  errcontext("COPY %s, line %llu",
182  cstate->cur_relname,
183  (unsigned long long) cstate->cur_lineno);
184  }
185  }
186  }
187 }
static char * limit_printout_length(const char *str)
Definition: copyfrom.c:195
#define errcontext
Definition: elog.h:196
struct CopyFromStateData * CopyFromState
Definition: copy.h:69
void pfree(void *pointer)
Definition: mcxt.c:1456
void * arg

References arg, CopyFormatOptions::binary, CopyFromStateData::cur_attname, CopyFromStateData::cur_attval, CopyFromStateData::cur_lineno, CopyFromStateData::cur_relname, StringInfoData::data, errcontext, limit_printout_length(), CopyFromStateData::line_buf, CopyFromStateData::line_buf_valid, CopyFromStateData::opts, pfree(), and CopyFromStateData::relname_only.

Referenced by CopyFrom(), file_acquire_sample_rows(), and fileIterateForeignScan().

◆ CopyGetAttnums()

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

Definition at line 792 of file copy.c.

793 {
794  List *attnums = NIL;
795 
796  if (attnamelist == NIL)
797  {
798  /* Generate default column list */
799  int attr_count = tupDesc->natts;
800  int i;
801 
802  for (i = 0; i < attr_count; i++)
803  {
804  if (TupleDescAttr(tupDesc, i)->attisdropped)
805  continue;
806  if (TupleDescAttr(tupDesc, i)->attgenerated)
807  continue;
808  attnums = lappend_int(attnums, i + 1);
809  }
810  }
811  else
812  {
813  /* Validate the user-supplied list and extract attnums */
814  ListCell *l;
815 
816  foreach(l, attnamelist)
817  {
818  char *name = strVal(lfirst(l));
819  int attnum;
820  int i;
821 
822  /* Lookup column name */
824  for (i = 0; i < tupDesc->natts; i++)
825  {
826  Form_pg_attribute att = TupleDescAttr(tupDesc, i);
827 
828  if (att->attisdropped)
829  continue;
830  if (namestrcmp(&(att->attname), name) == 0)
831  {
832  if (att->attgenerated)
833  ereport(ERROR,
834  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
835  errmsg("column \"%s\" is a generated column",
836  name),
837  errdetail("Generated columns cannot be used in COPY.")));
838  attnum = att->attnum;
839  break;
840  }
841  }
842  if (attnum == InvalidAttrNumber)
843  {
844  if (rel != NULL)
845  ereport(ERROR,
846  (errcode(ERRCODE_UNDEFINED_COLUMN),
847  errmsg("column \"%s\" of relation \"%s\" does not exist",
848  name, RelationGetRelationName(rel))));
849  else
850  ereport(ERROR,
851  (errcode(ERRCODE_UNDEFINED_COLUMN),
852  errmsg("column \"%s\" does not exist",
853  name)));
854  }
855  /* Check for duplicates */
856  if (list_member_int(attnums, attnum))
857  ereport(ERROR,
858  (errcode(ERRCODE_DUPLICATE_COLUMN),
859  errmsg("column \"%s\" specified more than once",
860  name)));
861  attnums = lappend_int(attnums, attnum);
862  }
863  }
864 
865  return attnums;
866 }
#define InvalidAttrNumber
Definition: attnum.h:23
int errdetail(const char *fmt,...)
Definition: elog.c:1202
int i
Definition: isn.c:73
List * lappend_int(List *list, int datum)
Definition: list.c:356
int namestrcmp(Name name, const char *str)
Definition: name.c:247
#define lfirst(lc)
Definition: pg_list.h:172
#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().

◆ CreateCopyDestReceiver()

DestReceiver* CreateCopyDestReceiver ( void  )

Definition at line 1272 of file copyto.c.

1273 {
1274  DR_copy *self = (DR_copy *) palloc(sizeof(DR_copy));
1275 
1276  self->pub.receiveSlot = copy_dest_receive;
1277  self->pub.rStartup = copy_dest_startup;
1278  self->pub.rShutdown = copy_dest_shutdown;
1279  self->pub.rDestroy = copy_dest_destroy;
1280  self->pub.mydest = DestCopyOut;
1281 
1282  self->cstate = NULL; /* will be set later */
1283  self->processed = 0;
1284 
1285  return (DestReceiver *) self;
1286 }
static bool copy_dest_receive(TupleTableSlot *slot, DestReceiver *self)
Definition: copyto.c:1235
static void copy_dest_destroy(DestReceiver *self)
Definition: copyto.c:1263
static void copy_dest_shutdown(DestReceiver *self)
Definition: copyto.c:1254
static void copy_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: copyto.c:1226

References copy_dest_destroy(), copy_dest_receive(), copy_dest_shutdown(), copy_dest_startup(), DestCopyOut, and palloc().

Referenced by CreateDestReceiver().

◆ 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
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:753
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:1337
uint64 CopyFrom(CopyFromState cstate)
Definition: copyfrom.c:632
void EndCopyFrom(CopyFromState cstate)
Definition: copyfrom.c:1737
uint64 DoCopyTo(CopyToState cstate)
Definition: copyto.c:746
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:725
bool ExecCheckPermissions(List *rangeTable, List *rteperminfos, bool ereport_on_violation)
Definition: execMain.c:581
#define stmt
Definition: indent_codes.h:59
List * lappend(List *list, void *datum)
Definition: list.c:338
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:3348
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:722
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:425
Oid GetUserId(void)
Definition: miscinit.c:508
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 list_make1(x1)
Definition: pg_list.h:212
Expr * canonicalize_qual(Expr *qual, bool is_check)
Definition: prepqual.c:294
#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
RTEPermissionInfo * p_perminfo
Definition: parse_node.h:288
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().

◆ DoCopyTo()

uint64 DoCopyTo ( CopyToState  cstate)

Definition at line 746 of file copyto.c.

747 {
748  bool pipe = (cstate->filename == NULL && cstate->data_dest_cb == NULL);
749  bool fe_copy = (pipe && whereToSendOutput == DestRemote);
750  TupleDesc tupDesc;
751  int num_phys_attrs;
752  ListCell *cur;
753  uint64 processed;
754 
755  if (fe_copy)
756  SendCopyBegin(cstate);
757 
758  if (cstate->rel)
759  tupDesc = RelationGetDescr(cstate->rel);
760  else
761  tupDesc = cstate->queryDesc->tupDesc;
762  num_phys_attrs = tupDesc->natts;
763  cstate->opts.null_print_client = cstate->opts.null_print; /* default */
764 
765  /* We use fe_msgbuf as a per-row buffer regardless of copy_dest */
766  cstate->fe_msgbuf = makeStringInfo();
767 
768  /* Get info about the columns we need to process. */
769  cstate->out_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
770  foreach(cur, cstate->attnumlist)
771  {
772  int attnum = lfirst_int(cur);
773  Oid out_func_oid;
774  bool isvarlena;
775  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
776 
777  if (cstate->opts.binary)
778  getTypeBinaryOutputInfo(attr->atttypid,
779  &out_func_oid,
780  &isvarlena);
781  else
782  getTypeOutputInfo(attr->atttypid,
783  &out_func_oid,
784  &isvarlena);
785  fmgr_info(out_func_oid, &cstate->out_functions[attnum - 1]);
786  }
787 
788  /*
789  * Create a temporary memory context that we can reset once per row to
790  * recover palloc'd memory. This avoids any problems with leaks inside
791  * datatype output routines, and should be faster than retail pfree's
792  * anyway. (We don't need a whole econtext as CopyFrom does.)
793  */
795  "COPY TO",
797 
798  if (cstate->opts.binary)
799  {
800  /* Generate header for a binary copy */
801  int32 tmp;
802 
803  /* Signature */
804  CopySendData(cstate, BinarySignature, 11);
805  /* Flags field */
806  tmp = 0;
807  CopySendInt32(cstate, tmp);
808  /* No header extension */
809  tmp = 0;
810  CopySendInt32(cstate, tmp);
811  }
812  else
813  {
814  /*
815  * For non-binary copy, we need to convert null_print to file
816  * encoding, because it will be sent directly with CopySendString.
817  */
818  if (cstate->need_transcoding)
820  cstate->opts.null_print_len,
821  cstate->file_encoding);
822 
823  /* if a header has been requested send the line */
824  if (cstate->opts.header_line)
825  {
826  bool hdr_delim = false;
827 
828  foreach(cur, cstate->attnumlist)
829  {
830  int attnum = lfirst_int(cur);
831  char *colname;
832 
833  if (hdr_delim)
834  CopySendChar(cstate, cstate->opts.delim[0]);
835  hdr_delim = true;
836 
837  colname = NameStr(TupleDescAttr(tupDesc, attnum - 1)->attname);
838 
839  if (cstate->opts.csv_mode)
840  CopyAttributeOutCSV(cstate, colname, false,
841  list_length(cstate->attnumlist) == 1);
842  else
843  CopyAttributeOutText(cstate, colname);
844  }
845 
846  CopySendEndOfRow(cstate);
847  }
848  }
849 
850  if (cstate->rel)
851  {
852  TupleTableSlot *slot;
853  TableScanDesc scandesc;
854 
855  scandesc = table_beginscan(cstate->rel, GetActiveSnapshot(), 0, NULL);
856  slot = table_slot_create(cstate->rel, NULL);
857 
858  processed = 0;
859  while (table_scan_getnextslot(scandesc, ForwardScanDirection, slot))
860  {
862 
863  /* Deconstruct the tuple ... */
864  slot_getallattrs(slot);
865 
866  /* Format and send the data */
867  CopyOneRowTo(cstate, slot);
868 
869  /*
870  * Increment the number of processed tuples, and report the
871  * progress.
872  */
874  ++processed);
875  }
876 
878  table_endscan(scandesc);
879  }
880  else
881  {
882  /* run the plan --- the dest receiver will send tuples */
883  ExecutorRun(cstate->queryDesc, ForwardScanDirection, 0, true);
884  processed = ((DR_copy *) cstate->queryDesc->dest)->processed;
885  }
886 
887  if (cstate->opts.binary)
888  {
889  /* Generate trailer for a binary copy */
890  CopySendInt16(cstate, -1);
891  /* Need to flush out the trailer */
892  CopySendEndOfRow(cstate);
893  }
894 
896 
897  if (fe_copy)
898  SendCopyEnd(cstate);
899 
900  return processed;
901 }
signed int int32
Definition: c.h:483
static void CopySendInt32(CopyToState cstate, int32 val)
Definition: copyto.c:272
static void CopyAttributeOutText(CopyToState cstate, const char *string)
Definition: copyto.c:988
static void CopySendInt16(CopyToState cstate, int16 val)
Definition: copyto.c:284
static void CopySendData(CopyToState cstate, const void *databuf, int datasize)
Definition: copyto.c:176
static void CopySendChar(CopyToState cstate, char c)
Definition: copyto.c:188
static void CopyAttributeOutCSV(CopyToState cstate, const char *string, bool use_quote, bool single_attr)
Definition: copyto.c:1141
static void SendCopyBegin(CopyToState cstate)
Definition: copyto.c:140
static void SendCopyEnd(CopyToState cstate)
Definition: copyto.c:157
static void CopySendEndOfRow(CopyToState cstate)
Definition: copyto.c:194
static void CopyOneRowTo(CopyToState cstate, TupleTableSlot *slot)
Definition: copyto.c:907
static const char BinarySignature[11]
Definition: copyto.c:113
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:302
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1253
void getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
Definition: lsyscache.c:2955
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2889
char * pg_server_to_any(const char *s, int len, int encoding)
Definition: mbutils.c:750
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:403
NameData attname
Definition: pg_attribute.h:41
@ ForwardScanDirection
Definition: sdir.h:28
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
int null_print_len
Definition: copy.h:48
CopyHeaderChoice header_line
Definition: copy.h:46
char * null_print
Definition: copy.h:47
char * delim
Definition: copy.h:52
char * null_print_client
Definition: copy.h:49
bool csv_mode
Definition: copy.h:45
FmgrInfo * out_functions
Definition: copyto.c:99
MemoryContext rowcontext
Definition: copyto.c:100
StringInfo fe_msgbuf
Definition: copyto.c:77
DestReceiver * dest
Definition: execdesc.h:41
static TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key)
Definition: tableam.h:901
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:1009
static bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
Definition: tableam.h:1050
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:362

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, attname, attnum, CopyToStateData::attnumlist, CopyFormatOptions::binary, BinarySignature, CHECK_FOR_INTERRUPTS, CopyAttributeOutCSV(), CopyAttributeOutText(), CopyOneRowTo(), CopySendChar(), CopySendData(), CopySendEndOfRow(), CopySendInt16(), CopySendInt32(), CopyFormatOptions::csv_mode, cur, CurrentMemoryContext, CopyToStateData::data_dest_cb, CopyFormatOptions::delim, QueryDesc::dest, DestRemote, ExecDropSingleTupleTableSlot(), ExecutorRun(), CopyToStateData::fe_msgbuf, CopyToStateData::file_encoding, CopyToStateData::filename, fmgr_info(), ForwardScanDirection, GetActiveSnapshot(), getTypeBinaryOutputInfo(), getTypeOutputInfo(), CopyFormatOptions::header_line, lfirst_int, list_length(), makeStringInfo(), MemoryContextDelete(), NameStr, TupleDescData::natts, CopyToStateData::need_transcoding, CopyFormatOptions::null_print, CopyFormatOptions::null_print_client, CopyFormatOptions::null_print_len, CopyToStateData::opts, CopyToStateData::out_functions, palloc(), pg_server_to_any(), pgstat_progress_update_param(), PROGRESS_COPY_TUPLES_PROCESSED, CopyToStateData::queryDesc, CopyToStateData::rel, RelationGetDescr, CopyToStateData::rowcontext, SendCopyBegin(), SendCopyEnd(), slot_getallattrs(), table_beginscan(), table_endscan(), table_scan_getnextslot(), table_slot_create(), QueryDesc::tupDesc, TupleDescAttr, and whereToSendOutput.

Referenced by DoCopy(), and test_copy_to_callback().

◆ EndCopyFrom()

void EndCopyFrom ( CopyFromState  cstate)

Definition at line 1737 of file copyfrom.c.

1738 {
1739  /* No COPY FROM related resources except memory. */
1740  if (cstate->is_program)
1741  {
1742  ClosePipeFromProgram(cstate);
1743  }
1744  else
1745  {
1746  if (cstate->filename != NULL && FreeFile(cstate->copy_file))
1747  ereport(ERROR,
1749  errmsg("could not close file \"%s\": %m",
1750  cstate->filename)));
1751  }
1752 
1754 
1756  pfree(cstate);
1757 }
void pgstat_progress_end_command(void)
static void ClosePipeFromProgram(CopyFromState cstate)
Definition: copyfrom.c:1763
int FreeFile(FILE *file)
Definition: fd.c:2751

References ClosePipeFromProgram(), CopyFromStateData::copy_file, CopyFromStateData::copycontext, ereport, errcode_for_file_access(), errmsg(), ERROR, CopyFromStateData::filename, FreeFile(), CopyFromStateData::is_program, MemoryContextDelete(), pfree(), and pgstat_progress_end_command().

Referenced by DoCopy(), file_acquire_sample_rows(), fileEndForeignScan(), and fileReScanForeignScan().

◆ EndCopyTo()

void EndCopyTo ( CopyToState  cstate)

Definition at line 725 of file copyto.c.

726 {
727  if (cstate->queryDesc != NULL)
728  {
729  /* Close down the query and free resources. */
730  ExecutorFinish(cstate->queryDesc);
731  ExecutorEnd(cstate->queryDesc);
732  FreeQueryDesc(cstate->queryDesc);
734  }
735 
736  /* Clean up storage */
737  EndCopy(cstate);
738 }
static void EndCopy(CopyToState cstate)
Definition: copyto.c:321
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:469
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:409
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:105
void PopActiveSnapshot(void)
Definition: snapmgr.c:750

References EndCopy(), ExecutorEnd(), ExecutorFinish(), FreeQueryDesc(), PopActiveSnapshot(), and CopyToStateData::queryDesc.

Referenced by DoCopy(), and test_copy_to_callback().

◆ NextCopyFrom()

bool NextCopyFrom ( CopyFromState  cstate,
ExprContext econtext,
Datum values,
bool nulls 
)

Definition at line 854 of file copyfromparse.c.

856 {
857  TupleDesc tupDesc;
858  AttrNumber num_phys_attrs,
859  attr_count,
860  num_defaults = cstate->num_defaults;
861  FmgrInfo *in_functions = cstate->in_functions;
862  Oid *typioparams = cstate->typioparams;
863  int i;
864  int *defmap = cstate->defmap;
865  ExprState **defexprs = cstate->defexprs;
866 
867  tupDesc = RelationGetDescr(cstate->rel);
868  num_phys_attrs = tupDesc->natts;
869  attr_count = list_length(cstate->attnumlist);
870 
871  /* Initialize all values for row to NULL */
872  MemSet(values, 0, num_phys_attrs * sizeof(Datum));
873  MemSet(nulls, true, num_phys_attrs * sizeof(bool));
874  MemSet(cstate->defaults, false, num_phys_attrs * sizeof(bool));
875 
876  if (!cstate->opts.binary)
877  {
878  char **field_strings;
879  ListCell *cur;
880  int fldct;
881  int fieldno;
882  char *string;
883 
884  /* read raw fields in the next line */
885  if (!NextCopyFromRawFields(cstate, &field_strings, &fldct))
886  return false;
887 
888  /* check for overflowing fields */
889  if (attr_count > 0 && fldct > attr_count)
890  ereport(ERROR,
891  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
892  errmsg("extra data after last expected column")));
893 
894  fieldno = 0;
895 
896  /* Loop to read the user attributes on the line. */
897  foreach(cur, cstate->attnumlist)
898  {
899  int attnum = lfirst_int(cur);
900  int m = attnum - 1;
901  Form_pg_attribute att = TupleDescAttr(tupDesc, m);
902 
903  if (fieldno >= fldct)
904  ereport(ERROR,
905  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
906  errmsg("missing data for column \"%s\"",
907  NameStr(att->attname))));
908  string = field_strings[fieldno++];
909 
910  if (cstate->convert_select_flags &&
911  !cstate->convert_select_flags[m])
912  {
913  /* ignore input field, leaving column as NULL */
914  continue;
915  }
916 
917  if (cstate->opts.csv_mode)
918  {
919  if (string == NULL &&
920  cstate->opts.force_notnull_flags[m])
921  {
922  /*
923  * FORCE_NOT_NULL option is set and column is NULL -
924  * convert it to the NULL string.
925  */
926  string = cstate->opts.null_print;
927  }
928  else if (string != NULL && cstate->opts.force_null_flags[m]
929  && strcmp(string, cstate->opts.null_print) == 0)
930  {
931  /*
932  * FORCE_NULL option is set and column matches the NULL
933  * string. It must have been quoted, or otherwise the
934  * string would already have been set to NULL. Convert it
935  * to NULL as specified.
936  */
937  string = NULL;
938  }
939  }
940 
941  cstate->cur_attname = NameStr(att->attname);
942  cstate->cur_attval = string;
943 
944  if (string != NULL)
945  nulls[m] = false;
946 
947  if (cstate->defaults[m])
948  {
949  /*
950  * The caller must supply econtext and have switched into the
951  * per-tuple memory context in it.
952  */
953  Assert(econtext != NULL);
955 
956  values[m] = ExecEvalExpr(defexprs[m], econtext, &nulls[m]);
957  }
958  else
959  values[m] = InputFunctionCall(&in_functions[m],
960  string,
961  typioparams[m],
962  att->atttypmod);
963 
964  cstate->cur_attname = NULL;
965  cstate->cur_attval = NULL;
966  }
967 
968  Assert(fieldno == attr_count);
969  }
970  else
971  {
972  /* binary */
973  int16 fld_count;
974  ListCell *cur;
975 
976  cstate->cur_lineno++;
977 
978  if (!CopyGetInt16(cstate, &fld_count))
979  {
980  /* EOF detected (end of file, or protocol-level EOF) */
981  return false;
982  }
983 
984  if (fld_count == -1)
985  {
986  /*
987  * Received EOF marker. Wait for the protocol-level EOF, and
988  * complain if it doesn't come immediately. In COPY FROM STDIN,
989  * this ensures that we correctly handle CopyFail, if client
990  * chooses to send that now. When copying from file, we could
991  * ignore the rest of the file like in text mode, but we choose to
992  * be consistent with the COPY FROM STDIN case.
993  */
994  char dummy;
995 
996  if (CopyReadBinaryData(cstate, &dummy, 1) > 0)
997  ereport(ERROR,
998  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
999  errmsg("received copy data after EOF marker")));
1000  return false;
1001  }
1002 
1003  if (fld_count != attr_count)
1004  ereport(ERROR,
1005  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1006  errmsg("row field count is %d, expected %d",
1007  (int) fld_count, attr_count)));
1008 
1009  foreach(cur, cstate->attnumlist)
1010  {
1011  int attnum = lfirst_int(cur);
1012  int m = attnum - 1;
1013  Form_pg_attribute att = TupleDescAttr(tupDesc, m);
1014 
1015  cstate->cur_attname = NameStr(att->attname);
1016  values[m] = CopyReadBinaryAttribute(cstate,
1017  &in_functions[m],
1018  typioparams[m],
1019  att->atttypmod,
1020  &nulls[m]);
1021  cstate->cur_attname = NULL;
1022  }
1023  }
1024 
1025  /*
1026  * Now compute and insert any defaults available for the columns not
1027  * provided by the input data. Anything not processed here or above will
1028  * remain NULL.
1029  */
1030  for (i = 0; i < num_defaults; i++)
1031  {
1032  /*
1033  * The caller must supply econtext and have switched into the
1034  * per-tuple memory context in it.
1035  */
1036  Assert(econtext != NULL);
1038 
1039  values[defmap[i]] = ExecEvalExpr(defexprs[defmap[i]], econtext,
1040  &nulls[defmap[i]]);
1041  }
1042 
1043  return true;
1044 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
signed short int16
Definition: c.h:482
static bool CopyGetInt16(CopyFromState cstate, int16 *val)
static Datum CopyReadBinaryAttribute(CopyFromState cstate, FmgrInfo *flinfo, Oid typioparam, int32 typmod, bool *isnull)
static int CopyReadBinaryData(CopyFromState cstate, char *dest, int nbytes)
bool NextCopyFromRawFields(CopyFromState cstate, char ***fields, int *nfields)
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:332
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1530
uintptr_t Datum
Definition: postgres.h:64
char string[11]
Definition: preproc-type.c:52
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:256

References Assert(), attnum, CopyFromStateData::attnumlist, CopyFormatOptions::binary, CopyFromStateData::convert_select_flags, CopyGetInt16(), CopyReadBinaryAttribute(), CopyReadBinaryData(), CopyFormatOptions::csv_mode, cur, CopyFromStateData::cur_attname, CopyFromStateData::cur_attval, CopyFromStateData::cur_lineno, CurrentMemoryContext, CopyFromStateData::defaults, CopyFromStateData::defexprs, CopyFromStateData::defmap, ExprContext::ecxt_per_tuple_memory, ereport, errcode(), errmsg(), ERROR, ExecEvalExpr(), CopyFormatOptions::force_notnull_flags, CopyFormatOptions::force_null_flags, i, CopyFromStateData::in_functions, InputFunctionCall(), lfirst_int, list_length(), MemSet, NameStr, TupleDescData::natts, NextCopyFromRawFields(), CopyFormatOptions::null_print, CopyFromStateData::num_defaults, CopyFromStateData::opts, CopyFromStateData::rel, RelationGetDescr, TupleDescAttr, CopyFromStateData::typioparams, and values.

Referenced by CopyFrom(), file_acquire_sample_rows(), and fileIterateForeignScan().

◆ NextCopyFromRawFields()

bool NextCopyFromRawFields ( CopyFromState  cstate,
char ***  fields,
int *  nfields 
)

Definition at line 754 of file copyfromparse.c.

755 {
756  int fldct;
757  bool done;
758 
759  /* only available for text or csv input */
760  Assert(!cstate->opts.binary);
761 
762  /* on input check that the header line is correct if needed */
763  if (cstate->cur_lineno == 0 && cstate->opts.header_line)
764  {
765  ListCell *cur;
766  TupleDesc tupDesc;
767 
768  tupDesc = RelationGetDescr(cstate->rel);
769 
770  cstate->cur_lineno++;
771  done = CopyReadLine(cstate);
772 
773  if (cstate->opts.header_line == COPY_HEADER_MATCH)
774  {
775  int fldnum;
776 
777  if (cstate->opts.csv_mode)
778  fldct = CopyReadAttributesCSV(cstate);
779  else
780  fldct = CopyReadAttributesText(cstate);
781 
782  if (fldct != list_length(cstate->attnumlist))
783  ereport(ERROR,
784  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
785  errmsg("wrong number of fields in header line: got %d, expected %d",
786  fldct, list_length(cstate->attnumlist))));
787 
788  fldnum = 0;
789  foreach(cur, cstate->attnumlist)
790  {
791  int attnum = lfirst_int(cur);
792  char *colName;
793  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
794 
795  Assert(fldnum < cstate->max_fields);
796 
797  colName = cstate->raw_fields[fldnum++];
798  if (colName == NULL)
799  ereport(ERROR,
800  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
801  errmsg("column name mismatch in header line field %d: got null value (\"%s\"), expected \"%s\"",
802  fldnum, cstate->opts.null_print, NameStr(attr->attname))));
803 
804  if (namestrcmp(&attr->attname, colName) != 0)
805  {
806  ereport(ERROR,
807  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
808  errmsg("column name mismatch in header line field %d: got \"%s\", expected \"%s\"",
809  fldnum, colName, NameStr(attr->attname))));
810  }
811  }
812  }
813 
814  if (done)
815  return false;
816  }
817 
818  cstate->cur_lineno++;
819 
820  /* Actually read the line into memory here */
821  done = CopyReadLine(cstate);
822 
823  /*
824  * EOF at start of line means we're done. If we see EOF after some
825  * characters, we act as though it was newline followed by EOF, ie,
826  * process the line and then exit loop on next iteration.
827  */
828  if (done && cstate->line_buf.len == 0)
829  return false;
830 
831  /* Parse the line into de-escaped field values */
832  if (cstate->opts.csv_mode)
833  fldct = CopyReadAttributesCSV(cstate);
834  else
835  fldct = CopyReadAttributesText(cstate);
836 
837  *fields = cstate->raw_fields;
838  *nfields = fldct;
839  return true;
840 }
static int CopyReadAttributesCSV(CopyFromState cstate)
static int CopyReadAttributesText(CopyFromState cstate)
static bool CopyReadLine(CopyFromState cstate)

References Assert(), attnum, CopyFromStateData::attnumlist, CopyFormatOptions::binary, COPY_HEADER_MATCH, CopyReadAttributesCSV(), CopyReadAttributesText(), CopyReadLine(), CopyFormatOptions::csv_mode, cur, CopyFromStateData::cur_lineno, ereport, errcode(), errmsg(), ERROR, CopyFormatOptions::header_line, StringInfoData::len, lfirst_int, CopyFromStateData::line_buf, list_length(), NameStr, namestrcmp(), CopyFormatOptions::null_print, CopyFromStateData::opts, CopyFromStateData::raw_fields, CopyFromStateData::rel, RelationGetDescr, and TupleDescAttr.

Referenced by NextCopyFrom().

◆ ProcessCopyOptions()

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

Definition at line 414 of file copy.c.

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

References DefElem::arg, CopyFormatOptions::binary, castNode, CopyFormatOptions::convert_select, CopyFormatOptions::convert_selectively, CopyFormatOptions::csv_mode, CopyFormatOptions::default_print, CopyFormatOptions::default_print_len, defGetBoolean(), defGetCopyHeaderChoice(), 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, palloc0(), parser_errposition(), pg_char_to_encoding, and CopyFormatOptions::quote.

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