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 enum CopyOnErrorChoice CopyOnErrorChoice
 
typedef enum CopyLogVerbosityChoice CopyLogVerbosityChoice
 
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 }
 
enum  CopyOnErrorChoice { COPY_ON_ERROR_STOP = 0 , COPY_ON_ERROR_IGNORE }
 
enum  CopyLogVerbosityChoice { COPY_LOG_VERBOSITY_DEFAULT = 0 , COPY_LOG_VERBOSITY_VERBOSE }
 

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)
 
char * CopyLimitPrintoutLength (const char *str)
 
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 94 of file copy.h.

◆ copy_data_source_cb

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

Definition at line 93 of file copy.h.

◆ CopyFormatOptions

◆ CopyFromState

Definition at line 90 of file copy.h.

◆ CopyHeaderChoice

◆ CopyLogVerbosityChoice

◆ CopyOnErrorChoice

◆ CopyToState

typedef struct CopyToStateData* CopyToState

Definition at line 91 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

◆ CopyLogVerbosityChoice

Enumerator
COPY_LOG_VERBOSITY_DEFAULT 
COPY_LOG_VERBOSITY_VERBOSE 

Definition at line 46 of file copy.h.

47 {
48  COPY_LOG_VERBOSITY_DEFAULT = 0, /* logs no additional messages, default */
49  COPY_LOG_VERBOSITY_VERBOSE, /* logs additional messages */
CopyLogVerbosityChoice
Definition: copy.h:47
@ COPY_LOG_VERBOSITY_VERBOSE
Definition: copy.h:49
@ COPY_LOG_VERBOSITY_DEFAULT
Definition: copy.h:48

◆ CopyOnErrorChoice

Enumerator
COPY_ON_ERROR_STOP 
COPY_ON_ERROR_IGNORE 

Definition at line 37 of file copy.h.

38 {
39  COPY_ON_ERROR_STOP = 0, /* immediately throw errors, default */
40  COPY_ON_ERROR_IGNORE, /* ignore errors */
CopyOnErrorChoice
Definition: copy.h:38
@ COPY_ON_ERROR_IGNORE
Definition: copy.h:40
@ COPY_ON_ERROR_STOP
Definition: copy.h:39

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 1380 of file copyfrom.c.

1388 {
1389  CopyFromState cstate;
1390  bool pipe = (filename == NULL);
1391  TupleDesc tupDesc;
1392  AttrNumber num_phys_attrs,
1393  num_defaults;
1394  FmgrInfo *in_functions;
1395  Oid *typioparams;
1396  Oid in_func_oid;
1397  int *defmap;
1398  ExprState **defexprs;
1399  MemoryContext oldcontext;
1400  bool volatile_defexprs;
1401  const int progress_cols[] = {
1405  };
1406  int64 progress_vals[] = {
1408  0,
1409  0
1410  };
1411 
1412  /* Allocate workspace and zero all fields */
1413  cstate = (CopyFromStateData *) palloc0(sizeof(CopyFromStateData));
1414 
1415  /*
1416  * We allocate everything used by a cstate in a new memory context. This
1417  * avoids memory leaks during repeated use of COPY in a query.
1418  */
1420  "COPY",
1422 
1423  oldcontext = MemoryContextSwitchTo(cstate->copycontext);
1424 
1425  /* Extract options from the statement node tree */
1426  ProcessCopyOptions(pstate, &cstate->opts, true /* is_from */ , options);
1427 
1428  /* Process the target relation */
1429  cstate->rel = rel;
1430 
1431  tupDesc = RelationGetDescr(cstate->rel);
1432 
1433  /* process common options or initialization */
1434 
1435  /* Generate or convert list of attributes to process */
1436  cstate->attnumlist = CopyGetAttnums(tupDesc, cstate->rel, attnamelist);
1437 
1438  num_phys_attrs = tupDesc->natts;
1439 
1440  /* Convert FORCE_NOT_NULL name list to per-column flags, check validity */
1441  cstate->opts.force_notnull_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1442  if (cstate->opts.force_notnull_all)
1443  MemSet(cstate->opts.force_notnull_flags, true, num_phys_attrs * sizeof(bool));
1444  else if (cstate->opts.force_notnull)
1445  {
1446  List *attnums;
1447  ListCell *cur;
1448 
1449  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_notnull);
1450 
1451  foreach(cur, attnums)
1452  {
1453  int attnum = lfirst_int(cur);
1454  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1455 
1456  if (!list_member_int(cstate->attnumlist, attnum))
1457  ereport(ERROR,
1458  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1459  /*- translator: first %s is the name of a COPY option, e.g. FORCE_NOT_NULL */
1460  errmsg("%s column \"%s\" not referenced by COPY",
1461  "FORCE_NOT_NULL", NameStr(attr->attname))));
1462  cstate->opts.force_notnull_flags[attnum - 1] = true;
1463  }
1464  }
1465 
1466  /* Set up soft error handler for ON_ERROR */
1467  if (cstate->opts.on_error != COPY_ON_ERROR_STOP)
1468  {
1469  cstate->escontext = makeNode(ErrorSaveContext);
1470  cstate->escontext->type = T_ErrorSaveContext;
1471  cstate->escontext->error_occurred = false;
1472 
1473  /*
1474  * Currently we only support COPY_ON_ERROR_IGNORE. We'll add other
1475  * options later
1476  */
1477  if (cstate->opts.on_error == COPY_ON_ERROR_IGNORE)
1478  cstate->escontext->details_wanted = false;
1479  }
1480  else
1481  cstate->escontext = NULL;
1482 
1483  /* Convert FORCE_NULL name list to per-column flags, check validity */
1484  cstate->opts.force_null_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1485  if (cstate->opts.force_null_all)
1486  MemSet(cstate->opts.force_null_flags, true, num_phys_attrs * sizeof(bool));
1487  else if (cstate->opts.force_null)
1488  {
1489  List *attnums;
1490  ListCell *cur;
1491 
1492  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_null);
1493 
1494  foreach(cur, attnums)
1495  {
1496  int attnum = lfirst_int(cur);
1497  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1498 
1499  if (!list_member_int(cstate->attnumlist, attnum))
1500  ereport(ERROR,
1501  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1502  /*- translator: first %s is the name of a COPY option, e.g. FORCE_NOT_NULL */
1503  errmsg("%s column \"%s\" not referenced by COPY",
1504  "FORCE_NULL", NameStr(attr->attname))));
1505  cstate->opts.force_null_flags[attnum - 1] = true;
1506  }
1507  }
1508 
1509  /* Convert convert_selectively name list to per-column flags */
1510  if (cstate->opts.convert_selectively)
1511  {
1512  List *attnums;
1513  ListCell *cur;
1514 
1515  cstate->convert_select_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1516 
1517  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.convert_select);
1518 
1519  foreach(cur, attnums)
1520  {
1521  int attnum = lfirst_int(cur);
1522  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1523 
1524  if (!list_member_int(cstate->attnumlist, attnum))
1525  ereport(ERROR,
1526  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1527  errmsg_internal("selected column \"%s\" not referenced by COPY",
1528  NameStr(attr->attname))));
1529  cstate->convert_select_flags[attnum - 1] = true;
1530  }
1531  }
1532 
1533  /* Use client encoding when ENCODING option is not specified. */
1534  if (cstate->opts.file_encoding < 0)
1536  else
1537  cstate->file_encoding = cstate->opts.file_encoding;
1538 
1539  /*
1540  * Look up encoding conversion function.
1541  */
1542  if (cstate->file_encoding == GetDatabaseEncoding() ||
1543  cstate->file_encoding == PG_SQL_ASCII ||
1545  {
1546  cstate->need_transcoding = false;
1547  }
1548  else
1549  {
1550  cstate->need_transcoding = true;
1553  if (!OidIsValid(cstate->conversion_proc))
1554  ereport(ERROR,
1555  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1556  errmsg("default conversion function for encoding \"%s\" to \"%s\" does not exist",
1559  }
1560 
1561  cstate->copy_src = COPY_FILE; /* default */
1562 
1563  cstate->whereClause = whereClause;
1564 
1565  /* Initialize state variables */
1566  cstate->eol_type = EOL_UNKNOWN;
1567  cstate->cur_relname = RelationGetRelationName(cstate->rel);
1568  cstate->cur_lineno = 0;
1569  cstate->cur_attname = NULL;
1570  cstate->cur_attval = NULL;
1571  cstate->relname_only = false;
1572 
1573  /*
1574  * Allocate buffers for the input pipeline.
1575  *
1576  * attribute_buf and raw_buf are used in both text and binary modes, but
1577  * input_buf and line_buf only in text mode.
1578  */
1579  cstate->raw_buf = palloc(RAW_BUF_SIZE + 1);
1580  cstate->raw_buf_index = cstate->raw_buf_len = 0;
1581  cstate->raw_reached_eof = false;
1582 
1583  if (!cstate->opts.binary)
1584  {
1585  /*
1586  * If encoding conversion is needed, we need another buffer to hold
1587  * the converted input data. Otherwise, we can just point input_buf
1588  * to the same buffer as raw_buf.
1589  */
1590  if (cstate->need_transcoding)
1591  {
1592  cstate->input_buf = (char *) palloc(INPUT_BUF_SIZE + 1);
1593  cstate->input_buf_index = cstate->input_buf_len = 0;
1594  }
1595  else
1596  cstate->input_buf = cstate->raw_buf;
1597  cstate->input_reached_eof = false;
1598 
1599  initStringInfo(&cstate->line_buf);
1600  }
1601 
1602  initStringInfo(&cstate->attribute_buf);
1603 
1604  /* Assign range table and rteperminfos, we'll need them in CopyFrom. */
1605  if (pstate)
1606  {
1607  cstate->range_table = pstate->p_rtable;
1608  cstate->rteperminfos = pstate->p_rteperminfos;
1609  }
1610 
1611  num_defaults = 0;
1612  volatile_defexprs = false;
1613 
1614  /*
1615  * Pick up the required catalog information for each attribute in the
1616  * relation, including the input function, the element type (to pass to
1617  * the input function), and info about defaults and constraints. (Which
1618  * input function we use depends on text/binary format choice.)
1619  */
1620  in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
1621  typioparams = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
1622  defmap = (int *) palloc(num_phys_attrs * sizeof(int));
1623  defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *));
1624 
1625  for (int attnum = 1; attnum <= num_phys_attrs; attnum++)
1626  {
1627  Form_pg_attribute att = TupleDescAttr(tupDesc, attnum - 1);
1628 
1629  /* We don't need info for dropped attributes */
1630  if (att->attisdropped)
1631  continue;
1632 
1633  /* Fetch the input function and typioparam info */
1634  if (cstate->opts.binary)
1635  getTypeBinaryInputInfo(att->atttypid,
1636  &in_func_oid, &typioparams[attnum - 1]);
1637  else
1638  getTypeInputInfo(att->atttypid,
1639  &in_func_oid, &typioparams[attnum - 1]);
1640  fmgr_info(in_func_oid, &in_functions[attnum - 1]);
1641 
1642  /* Get default info if available */
1643  defexprs[attnum - 1] = NULL;
1644 
1645  /*
1646  * We only need the default values for columns that do not appear in
1647  * the column list, unless the DEFAULT option was given. We never need
1648  * default values for generated columns.
1649  */
1650  if ((cstate->opts.default_print != NULL ||
1651  !list_member_int(cstate->attnumlist, attnum)) &&
1652  !att->attgenerated)
1653  {
1654  Expr *defexpr = (Expr *) build_column_default(cstate->rel,
1655  attnum);
1656 
1657  if (defexpr != NULL)
1658  {
1659  /* Run the expression through planner */
1660  defexpr = expression_planner(defexpr);
1661 
1662  /* Initialize executable expression in copycontext */
1663  defexprs[attnum - 1] = ExecInitExpr(defexpr, NULL);
1664 
1665  /* if NOT copied from input */
1666  /* use default value if one exists */
1667  if (!list_member_int(cstate->attnumlist, attnum))
1668  {
1669  defmap[num_defaults] = attnum - 1;
1670  num_defaults++;
1671  }
1672 
1673  /*
1674  * If a default expression looks at the table being loaded,
1675  * then it could give the wrong answer when using
1676  * multi-insert. Since database access can be dynamic this is
1677  * hard to test for exactly, so we use the much wider test of
1678  * whether the default expression is volatile. We allow for
1679  * the special case of when the default expression is the
1680  * nextval() of a sequence which in this specific case is
1681  * known to be safe for use with the multi-insert
1682  * optimization. Hence we use this special case function
1683  * checker rather than the standard check for
1684  * contain_volatile_functions(). Note also that we already
1685  * ran the expression through expression_planner().
1686  */
1687  if (!volatile_defexprs)
1688  volatile_defexprs = contain_volatile_functions_not_nextval((Node *) defexpr);
1689  }
1690  }
1691  }
1692 
1693  cstate->defaults = (bool *) palloc0(tupDesc->natts * sizeof(bool));
1694 
1695  /* initialize progress */
1697  cstate->rel ? RelationGetRelid(cstate->rel) : InvalidOid);
1698  cstate->bytes_processed = 0;
1699 
1700  /* We keep those variables in cstate. */
1701  cstate->in_functions = in_functions;
1702  cstate->typioparams = typioparams;
1703  cstate->defmap = defmap;
1704  cstate->defexprs = defexprs;
1705  cstate->volatile_defexprs = volatile_defexprs;
1706  cstate->num_defaults = num_defaults;
1707  cstate->is_program = is_program;
1708 
1709  if (data_source_cb)
1710  {
1711  progress_vals[1] = PROGRESS_COPY_TYPE_CALLBACK;
1712  cstate->copy_src = COPY_CALLBACK;
1713  cstate->data_source_cb = data_source_cb;
1714  }
1715  else if (pipe)
1716  {
1717  progress_vals[1] = PROGRESS_COPY_TYPE_PIPE;
1718  Assert(!is_program); /* the grammar does not allow this */
1720  ReceiveCopyBegin(cstate);
1721  else
1722  cstate->copy_file = stdin;
1723  }
1724  else
1725  {
1726  cstate->filename = pstrdup(filename);
1727 
1728  if (cstate->is_program)
1729  {
1730  progress_vals[1] = PROGRESS_COPY_TYPE_PROGRAM;
1731  cstate->copy_file = OpenPipeStream(cstate->filename, PG_BINARY_R);
1732  if (cstate->copy_file == NULL)
1733  ereport(ERROR,
1735  errmsg("could not execute command \"%s\": %m",
1736  cstate->filename)));
1737  }
1738  else
1739  {
1740  struct stat st;
1741 
1742  progress_vals[1] = PROGRESS_COPY_TYPE_FILE;
1743  cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_R);
1744  if (cstate->copy_file == NULL)
1745  {
1746  /* copy errno because ereport subfunctions might change it */
1747  int save_errno = errno;
1748 
1749  ereport(ERROR,
1751  errmsg("could not open file \"%s\" for reading: %m",
1752  cstate->filename),
1753  (save_errno == ENOENT || save_errno == EACCES) ?
1754  errhint("COPY FROM instructs the PostgreSQL server process to read a file. "
1755  "You may want a client-side facility such as psql's \\copy.") : 0));
1756  }
1757 
1758  if (fstat(fileno(cstate->copy_file), &st))
1759  ereport(ERROR,
1761  errmsg("could not stat file \"%s\": %m",
1762  cstate->filename)));
1763 
1764  if (S_ISDIR(st.st_mode))
1765  ereport(ERROR,
1766  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1767  errmsg("\"%s\" is a directory", cstate->filename)));
1768 
1769  progress_vals[2] = st.st_size;
1770  }
1771  }
1772 
1773  pgstat_progress_update_multi_param(3, progress_cols, progress_vals);
1774 
1775  if (cstate->opts.binary)
1776  {
1777  /* Read and verify binary header */
1778  ReceiveCopyBinaryHeader(cstate);
1779  }
1780 
1781  /* create workspace for CopyReadAttributes results */
1782  if (!cstate->opts.binary)
1783  {
1784  AttrNumber attr_count = list_length(cstate->attnumlist);
1785 
1786  cstate->max_fields = attr_count;
1787  cstate->raw_fields = (char **) palloc(attr_count * sizeof(char *));
1788  }
1789 
1790  MemoryContextSwitchTo(oldcontext);
1791 
1792  return cstate;
1793 }
int16 AttrNumber
Definition: attnum.h:21
List * CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
Definition: copy.c:892
void ProcessCopyOptions(ParseState *pstate, CopyFormatOptions *opts_out, bool is_from, List *options)
Definition: copy.c:463
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:746
#define PG_BINARY_R
Definition: c.h:1275
#define Assert(condition)
Definition: c.h:858
#define MemSet(start, val, len)
Definition: c.h:1020
#define OidIsValid(objectId)
Definition: c.h:775
bool contain_volatile_functions_not_nextval(Node *clause)
Definition: clauses.c:673
#define INPUT_BUF_SIZE
@ EOL_UNKNOWN
#define RAW_BUF_SIZE
void ReceiveCopyBinaryHeader(CopyFromState cstate)
void ReceiveCopyBegin(CopyFromState cstate)
@ COPY_FILE
Definition: copyto.c:45
@ COPY_CALLBACK
Definition: copyto.c:47
@ DestRemote
Definition: dest.h:89
struct cursor * cur
Definition: ecpg.c:28
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1157
int errcode_for_file_access(void)
Definition: elog.c:876
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:138
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2606
FILE * OpenPipeStream(const char *command, const char *mode)
Definition: fd.c:2709
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
bool list_member_int(const List *list, int datum)
Definition: list.c:702
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2874
void getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
Definition: lsyscache.c:2940
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
int pg_get_client_encoding(void)
Definition: mbutils.c:336
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void * palloc0(Size size)
Definition: mcxt.c:1347
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
void * palloc(Size size)
Definition: mcxt.c:1317
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
Oid FindDefaultConversionProc(int32 for_encoding, int32 to_encoding)
Definition: namespace.c:4065
#define makeNode(_type_)
Definition: nodes.h:155
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:119
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:226
#define pg_encoding_to_char
Definition: pg_wchar.h:630
Expr * expression_planner(Expr *expr)
Definition: planner.c:6586
CommandDest whereToSendOutput
Definition: postgres.c:91
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define PROGRESS_COPY_COMMAND
Definition: progress.h:144
#define PROGRESS_COPY_TYPE_FILE
Definition: progress.h:153
#define PROGRESS_COPY_COMMAND_FROM
Definition: progress.h:149
#define PROGRESS_COPY_TYPE
Definition: progress.h:145
#define PROGRESS_COPY_TYPE_PROGRAM
Definition: progress.h:154
#define PROGRESS_COPY_BYTES_TOTAL
Definition: progress.h:141
#define PROGRESS_COPY_TYPE_CALLBACK
Definition: progress.h:156
#define PROGRESS_COPY_TYPE_PIPE
Definition: progress.h:155
MemoryContextSwitchTo(old_ctx)
#define RelationGetRelid(relation)
Definition: rel.h:505
#define RelationGetDescr(relation)
Definition: rel.h:531
#define RelationGetRelationName(relation)
Definition: rel.h:539
Node * build_column_default(Relation rel, int attrno)
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
bool force_notnull_all
Definition: copy.h:78
bool binary
Definition: copy.h:62
bool convert_selectively
Definition: copy.h:83
CopyOnErrorChoice on_error
Definition: copy.h:84
List * force_null
Definition: copy.h:80
List * convert_select
Definition: copy.h:86
bool force_null_all
Definition: copy.h:81
bool * force_notnull_flags
Definition: copy.h:79
int file_encoding
Definition: copy.h:60
bool * force_null_flags
Definition: copy.h:82
char * default_print
Definition: copy.h:69
List * force_notnull
Definition: copy.h:77
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
ErrorSaveContext * escontext
bool details_wanted
Definition: miscnodes.h:47
bool error_occurred
Definition: miscnodes.h:46
NodeTag type
Definition: miscnodes.h:45
Definition: fmgr.h:57
Definition: pg_list.h:54
Definition: nodes.h:129
List * p_rteperminfos
Definition: parse_node.h:195
List * p_rtable
Definition: parse_node.h:194
#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, COPY_ON_ERROR_IGNORE, COPY_ON_ERROR_STOP, 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, ErrorSaveContext::details_wanted, CopyFromStateData::eol_type, EOL_UNKNOWN, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), errmsg_internal(), ERROR, ErrorSaveContext::error_occurred, CopyFromStateData::escontext, 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(), makeNode, CopyFromStateData::max_fields, MemoryContextSwitchTo(), MemSet, NameStr, TupleDescData::natts, CopyFromStateData::need_transcoding, CopyFromStateData::num_defaults, OidIsValid, CopyFormatOptions::on_error, 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, ErrorSaveContext::type, 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 350 of file copyto.c.

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

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

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(), COPY_ON_ERROR_IGNORE, COPY_ON_ERROR_STOP, CopyFromErrorCallback(), CopyMultiInsertInfoCleanup(), CopyMultiInsertInfoFlush(), CopyMultiInsertInfoInit(), CopyMultiInsertInfoIsEmpty(), CopyMultiInsertInfoIsFull(), CopyMultiInsertInfoNextFreeSlot(), CopyMultiInsertInfoSetupBuffer(), CopyMultiInsertInfoStore(), CreateExecutorState(), CopyFromStateData::cur_lineno, CurrentMemoryContext, ExprContext::ecxt_scantuple, FdwRoutine::EndForeignInsert, ereport, errcode(), errhint(), errmsg(), errmsg_plural(), ERROR, error_context_stack, ErrorSaveContext::error_occurred, EState::es_tupleTable, CopyFromStateData::escontext, 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, NOTICE, CopyFromStateData::num_errors, CopyFormatOptions::on_error, ModifyTableState::operation, CopyFromStateData::opts, pgstat_progress_update_param(), PlanState::plan, ErrorContextCallback::previous, PROGRESS_COPY_TUPLES_EXCLUDED, PROGRESS_COPY_TUPLES_PROCESSED, PROGRESS_COPY_TUPLES_SKIPPED, 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 115 of file copyfrom.c.

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

References arg, CopyFormatOptions::binary, CopyLimitPrintoutLength(), CopyFromStateData::cur_attname, CopyFromStateData::cur_attval, CopyFromStateData::cur_lineno, CopyFromStateData::cur_relname, StringInfoData::data, errcontext, 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 892 of file copy.c.

893 {
894  List *attnums = NIL;
895 
896  if (attnamelist == NIL)
897  {
898  /* Generate default column list */
899  int attr_count = tupDesc->natts;
900  int i;
901 
902  for (i = 0; i < attr_count; i++)
903  {
904  if (TupleDescAttr(tupDesc, i)->attisdropped)
905  continue;
906  if (TupleDescAttr(tupDesc, i)->attgenerated)
907  continue;
908  attnums = lappend_int(attnums, i + 1);
909  }
910  }
911  else
912  {
913  /* Validate the user-supplied list and extract attnums */
914  ListCell *l;
915 
916  foreach(l, attnamelist)
917  {
918  char *name = strVal(lfirst(l));
919  int attnum;
920  int i;
921 
922  /* Lookup column name */
924  for (i = 0; i < tupDesc->natts; i++)
925  {
926  Form_pg_attribute att = TupleDescAttr(tupDesc, i);
927 
928  if (att->attisdropped)
929  continue;
930  if (namestrcmp(&(att->attname), name) == 0)
931  {
932  if (att->attgenerated)
933  ereport(ERROR,
934  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
935  errmsg("column \"%s\" is a generated column",
936  name),
937  errdetail("Generated columns cannot be used in COPY.")));
938  attnum = att->attnum;
939  break;
940  }
941  }
942  if (attnum == InvalidAttrNumber)
943  {
944  if (rel != NULL)
945  ereport(ERROR,
946  (errcode(ERRCODE_UNDEFINED_COLUMN),
947  errmsg("column \"%s\" of relation \"%s\" does not exist",
948  name, RelationGetRelationName(rel))));
949  else
950  ereport(ERROR,
951  (errcode(ERRCODE_UNDEFINED_COLUMN),
952  errmsg("column \"%s\" does not exist",
953  name)));
954  }
955  /* Check for duplicates */
956  if (list_member_int(attnums, attnum))
957  ereport(ERROR,
958  (errcode(ERRCODE_DUPLICATE_COLUMN),
959  errmsg("column \"%s\" specified more than once",
960  name)));
961  attnums = lappend_int(attnums, attnum);
962  }
963  }
964 
965  return attnums;
966 }
#define InvalidAttrNumber
Definition: attnum.h:23
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int i
Definition: isn.c:73
List * lappend_int(List *list, int datum)
Definition: list.c:357
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().

◆ CopyLimitPrintoutLength()

char* CopyLimitPrintoutLength ( const char *  str)

Definition at line 194 of file copyfrom.c.

195 {
196 #define MAX_COPY_DATA_DISPLAY 100
197 
198  int slen = strlen(str);
199  int len;
200  char *res;
201 
202  /* Fast path if definitely okay */
203  if (slen <= MAX_COPY_DATA_DISPLAY)
204  return pstrdup(str);
205 
206  /* Apply encoding-dependent truncation */
208 
209  /*
210  * Truncate, and add "..." to show we truncated the input.
211  */
212  res = (char *) palloc(len + 4);
213  memcpy(res, str, len);
214  strcpy(res + len, "...");
215 
216  return res;
217 }
#define MAX_COPY_DATA_DISPLAY
const char * str
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:1083
const void size_t len

References len, MAX_COPY_DATA_DISPLAY, palloc(), pg_mbcliplen(), pstrdup(), res, and str.

Referenced by CopyFromErrorCallback(), and NextCopyFrom().

◆ CreateCopyDestReceiver()

DestReceiver* CreateCopyDestReceiver ( void  )

Definition at line 1269 of file copyto.c.

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

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 62 of file copy.c.

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

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, 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 743 of file copyto.c.

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

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, 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 1799 of file copyfrom.c.

1800 {
1801  /* No COPY FROM related resources except memory. */
1802  if (cstate->is_program)
1803  {
1804  ClosePipeFromProgram(cstate);
1805  }
1806  else
1807  {
1808  if (cstate->filename != NULL && FreeFile(cstate->copy_file))
1809  ereport(ERROR,
1811  errmsg("could not close file \"%s\": %m",
1812  cstate->filename)));
1813  }
1814 
1816 
1818  pfree(cstate);
1819 }
void pgstat_progress_end_command(void)
static void ClosePipeFromProgram(CopyFromState cstate)
Definition: copyfrom.c:1825
int FreeFile(FILE *file)
Definition: fd.c:2804

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 722 of file copyto.c.

723 {
724  if (cstate->queryDesc != NULL)
725  {
726  /* Close down the query and free resources. */
727  ExecutorFinish(cstate->queryDesc);
728  ExecutorEnd(cstate->queryDesc);
729  FreeQueryDesc(cstate->queryDesc);
731  }
732 
733  /* Clean up storage */
734  EndCopy(cstate);
735 }
static void EndCopy(CopyToState cstate)
Definition: copyto.c:314
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:462
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:402
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:105
void PopActiveSnapshot(void)
Definition: snapmgr.c:743

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 
959  /*
960  * If ON_ERROR is specified with IGNORE, skip rows with soft
961  * errors
962  */
963  else if (!InputFunctionCallSafe(&in_functions[m],
964  string,
965  typioparams[m],
966  att->atttypmod,
967  (Node *) cstate->escontext,
968  &values[m]))
969  {
971 
972  cstate->num_errors++;
973 
975  {
976  /*
977  * Since we emit line number and column info in the below
978  * notice message, we suppress error context information
979  * other than the relation name.
980  */
981  Assert(!cstate->relname_only);
982  cstate->relname_only = true;
983 
984  if (cstate->cur_attval)
985  {
986  char *attval;
987 
988  attval = CopyLimitPrintoutLength(cstate->cur_attval);
989  ereport(NOTICE,
990  errmsg("skipping row due to data type incompatibility at line %llu for column \"%s\": \"%s\"",
991  (unsigned long long) cstate->cur_lineno,
992  cstate->cur_attname,
993  attval));
994  pfree(attval);
995  }
996  else
997  ereport(NOTICE,
998  errmsg("skipping row due to data type incompatibility at line %llu for column \"%s\": null input",
999  (unsigned long long) cstate->cur_lineno,
1000  cstate->cur_attname));
1001 
1002  /* reset relname_only */
1003  cstate->relname_only = false;
1004  }
1005 
1006  return true;
1007  }
1008 
1009  cstate->cur_attname = NULL;
1010  cstate->cur_attval = NULL;
1011  }
1012 
1013  Assert(fieldno == attr_count);
1014  }
1015  else
1016  {
1017  /* binary */
1018  int16 fld_count;
1019  ListCell *cur;
1020 
1021  cstate->cur_lineno++;
1022 
1023  if (!CopyGetInt16(cstate, &fld_count))
1024  {
1025  /* EOF detected (end of file, or protocol-level EOF) */
1026  return false;
1027  }
1028 
1029  if (fld_count == -1)
1030  {
1031  /*
1032  * Received EOF marker. Wait for the protocol-level EOF, and
1033  * complain if it doesn't come immediately. In COPY FROM STDIN,
1034  * this ensures that we correctly handle CopyFail, if client
1035  * chooses to send that now. When copying from file, we could
1036  * ignore the rest of the file like in text mode, but we choose to
1037  * be consistent with the COPY FROM STDIN case.
1038  */
1039  char dummy;
1040 
1041  if (CopyReadBinaryData(cstate, &dummy, 1) > 0)
1042  ereport(ERROR,
1043  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1044  errmsg("received copy data after EOF marker")));
1045  return false;
1046  }
1047 
1048  if (fld_count != attr_count)
1049  ereport(ERROR,
1050  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1051  errmsg("row field count is %d, expected %d",
1052  (int) fld_count, attr_count)));
1053 
1054  foreach(cur, cstate->attnumlist)
1055  {
1056  int attnum = lfirst_int(cur);
1057  int m = attnum - 1;
1058  Form_pg_attribute att = TupleDescAttr(tupDesc, m);
1059 
1060  cstate->cur_attname = NameStr(att->attname);
1061  values[m] = CopyReadBinaryAttribute(cstate,
1062  &in_functions[m],
1063  typioparams[m],
1064  att->atttypmod,
1065  &nulls[m]);
1066  cstate->cur_attname = NULL;
1067  }
1068  }
1069 
1070  /*
1071  * Now compute and insert any defaults available for the columns not
1072  * provided by the input data. Anything not processed here or above will
1073  * remain NULL.
1074  */
1075  for (i = 0; i < num_defaults; i++)
1076  {
1077  /*
1078  * The caller must supply econtext and have switched into the
1079  * per-tuple memory context in it.
1080  */
1081  Assert(econtext != NULL);
1083 
1084  values[defmap[i]] = ExecEvalExpr(defexprs[defmap[i]], econtext,
1085  &nulls[defmap[i]]);
1086  }
1087 
1088  return true;
1089 }
static Datum values[MAXATTR]
Definition: bootstrap.c:150
signed short int16
Definition: c.h:493
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:344
bool InputFunctionCallSafe(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod, fmNodePtr escontext, Datum *result)
Definition: fmgr.c:1585
uintptr_t Datum
Definition: postgres.h:64
char string[11]
Definition: preproc-type.c:52
CopyLogVerbosityChoice log_verbosity
Definition: copy.h:85
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:265

References Assert, attnum, CopyFromStateData::attnumlist, CopyFormatOptions::binary, CopyFromStateData::convert_select_flags, COPY_LOG_VERBOSITY_VERBOSE, COPY_ON_ERROR_STOP, CopyGetInt16(), CopyLimitPrintoutLength(), 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, CopyFromStateData::escontext, ExecEvalExpr(), CopyFormatOptions::force_notnull_flags, CopyFormatOptions::force_null_flags, i, CopyFromStateData::in_functions, InputFunctionCallSafe(), lfirst_int, list_length(), CopyFormatOptions::log_verbosity, MemSet, NameStr, TupleDescData::natts, NextCopyFromRawFields(), NOTICE, CopyFormatOptions::null_print, CopyFromStateData::num_defaults, CopyFromStateData::num_errors, CopyFormatOptions::on_error, CopyFromStateData::opts, pfree(), CopyFromStateData::rel, RelationGetDescr, CopyFromStateData::relname_only, 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 463 of file copy.c.

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

References DefElem::arg, CopyFormatOptions::binary, castNode, CopyFormatOptions::convert_select, CopyFormatOptions::convert_selectively, COPY_ON_ERROR_STOP, CopyFormatOptions::csv_mode, CopyFormatOptions::default_print, CopyFormatOptions::default_print_len, defGetBoolean(), defGetCopyHeaderChoice(), defGetCopyLogVerbosityChoice(), defGetCopyOnErrorChoice(), defGetString(), DefElem::defname, CopyFormatOptions::delim, ereport, errcode(), errmsg(), ERROR, errorConflictingDefElem(), CopyFormatOptions::escape, CopyFormatOptions::file_encoding, fmt, CopyFormatOptions::force_notnull, CopyFormatOptions::force_notnull_all, CopyFormatOptions::force_null, CopyFormatOptions::force_null_all, CopyFormatOptions::force_quote, CopyFormatOptions::force_quote_all, CopyFormatOptions::freeze, CopyFormatOptions::header_line, IsA, lfirst_node, DefElem::location, CopyFormatOptions::log_verbosity, NIL, CopyFormatOptions::null_print, CopyFormatOptions::null_print_len, CopyFormatOptions::on_error, palloc0(), parser_errposition(), pg_char_to_encoding, and CopyFormatOptions::quote.

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