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_SILENT = -1 , 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 97 of file copy.h.

◆ copy_data_source_cb

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

Definition at line 96 of file copy.h.

◆ CopyFormatOptions

◆ CopyFromState

Definition at line 93 of file copy.h.

◆ CopyHeaderChoice

◆ CopyLogVerbosityChoice

◆ CopyOnErrorChoice

◆ CopyToState

typedef struct CopyToStateData* CopyToState

Definition at line 94 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_SILENT 
COPY_LOG_VERBOSITY_DEFAULT 
COPY_LOG_VERBOSITY_VERBOSE 

Definition at line 46 of file copy.h.

47 {
48  COPY_LOG_VERBOSITY_SILENT = -1, /* logs none */
49  COPY_LOG_VERBOSITY_DEFAULT = 0, /* logs no additional messages. As this is
50  * the default, assign 0 */
51  COPY_LOG_VERBOSITY_VERBOSE, /* logs additional messages */
CopyLogVerbosityChoice
Definition: copy.h:47
@ COPY_LOG_VERBOSITY_SILENT
Definition: copy.h:48
@ COPY_LOG_VERBOSITY_VERBOSE
Definition: copy.h:51
@ COPY_LOG_VERBOSITY_DEFAULT
Definition: copy.h:49

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

1391 {
1392  CopyFromState cstate;
1393  bool pipe = (filename == NULL);
1394  TupleDesc tupDesc;
1395  AttrNumber num_phys_attrs,
1396  num_defaults;
1397  FmgrInfo *in_functions;
1398  Oid *typioparams;
1399  Oid in_func_oid;
1400  int *defmap;
1401  ExprState **defexprs;
1402  MemoryContext oldcontext;
1403  bool volatile_defexprs;
1404  const int progress_cols[] = {
1408  };
1409  int64 progress_vals[] = {
1411  0,
1412  0
1413  };
1414 
1415  /* Allocate workspace and zero all fields */
1416  cstate = (CopyFromStateData *) palloc0(sizeof(CopyFromStateData));
1417 
1418  /*
1419  * We allocate everything used by a cstate in a new memory context. This
1420  * avoids memory leaks during repeated use of COPY in a query.
1421  */
1423  "COPY",
1425 
1426  oldcontext = MemoryContextSwitchTo(cstate->copycontext);
1427 
1428  /* Extract options from the statement node tree */
1429  ProcessCopyOptions(pstate, &cstate->opts, true /* is_from */ , options);
1430 
1431  /* Process the target relation */
1432  cstate->rel = rel;
1433 
1434  tupDesc = RelationGetDescr(cstate->rel);
1435 
1436  /* process common options or initialization */
1437 
1438  /* Generate or convert list of attributes to process */
1439  cstate->attnumlist = CopyGetAttnums(tupDesc, cstate->rel, attnamelist);
1440 
1441  num_phys_attrs = tupDesc->natts;
1442 
1443  /* Convert FORCE_NOT_NULL name list to per-column flags, check validity */
1444  cstate->opts.force_notnull_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1445  if (cstate->opts.force_notnull_all)
1446  MemSet(cstate->opts.force_notnull_flags, true, num_phys_attrs * sizeof(bool));
1447  else if (cstate->opts.force_notnull)
1448  {
1449  List *attnums;
1450  ListCell *cur;
1451 
1452  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_notnull);
1453 
1454  foreach(cur, attnums)
1455  {
1456  int attnum = lfirst_int(cur);
1457  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1458 
1459  if (!list_member_int(cstate->attnumlist, attnum))
1460  ereport(ERROR,
1461  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1462  /*- translator: first %s is the name of a COPY option, e.g. FORCE_NOT_NULL */
1463  errmsg("%s column \"%s\" not referenced by COPY",
1464  "FORCE_NOT_NULL", NameStr(attr->attname))));
1465  cstate->opts.force_notnull_flags[attnum - 1] = true;
1466  }
1467  }
1468 
1469  /* Set up soft error handler for ON_ERROR */
1470  if (cstate->opts.on_error != COPY_ON_ERROR_STOP)
1471  {
1472  cstate->escontext = makeNode(ErrorSaveContext);
1473  cstate->escontext->type = T_ErrorSaveContext;
1474  cstate->escontext->error_occurred = false;
1475 
1476  /*
1477  * Currently we only support COPY_ON_ERROR_IGNORE. We'll add other
1478  * options later
1479  */
1480  if (cstate->opts.on_error == COPY_ON_ERROR_IGNORE)
1481  cstate->escontext->details_wanted = false;
1482  }
1483  else
1484  cstate->escontext = NULL;
1485 
1486  /* Convert FORCE_NULL name list to per-column flags, check validity */
1487  cstate->opts.force_null_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1488  if (cstate->opts.force_null_all)
1489  MemSet(cstate->opts.force_null_flags, true, num_phys_attrs * sizeof(bool));
1490  else if (cstate->opts.force_null)
1491  {
1492  List *attnums;
1493  ListCell *cur;
1494 
1495  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_null);
1496 
1497  foreach(cur, attnums)
1498  {
1499  int attnum = lfirst_int(cur);
1500  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1501 
1502  if (!list_member_int(cstate->attnumlist, attnum))
1503  ereport(ERROR,
1504  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1505  /*- translator: first %s is the name of a COPY option, e.g. FORCE_NOT_NULL */
1506  errmsg("%s column \"%s\" not referenced by COPY",
1507  "FORCE_NULL", NameStr(attr->attname))));
1508  cstate->opts.force_null_flags[attnum - 1] = true;
1509  }
1510  }
1511 
1512  /* Convert convert_selectively name list to per-column flags */
1513  if (cstate->opts.convert_selectively)
1514  {
1515  List *attnums;
1516  ListCell *cur;
1517 
1518  cstate->convert_select_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1519 
1520  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.convert_select);
1521 
1522  foreach(cur, attnums)
1523  {
1524  int attnum = lfirst_int(cur);
1525  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1526 
1527  if (!list_member_int(cstate->attnumlist, attnum))
1528  ereport(ERROR,
1529  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1530  errmsg_internal("selected column \"%s\" not referenced by COPY",
1531  NameStr(attr->attname))));
1532  cstate->convert_select_flags[attnum - 1] = true;
1533  }
1534  }
1535 
1536  /* Use client encoding when ENCODING option is not specified. */
1537  if (cstate->opts.file_encoding < 0)
1539  else
1540  cstate->file_encoding = cstate->opts.file_encoding;
1541 
1542  /*
1543  * Look up encoding conversion function.
1544  */
1545  if (cstate->file_encoding == GetDatabaseEncoding() ||
1546  cstate->file_encoding == PG_SQL_ASCII ||
1548  {
1549  cstate->need_transcoding = false;
1550  }
1551  else
1552  {
1553  cstate->need_transcoding = true;
1556  if (!OidIsValid(cstate->conversion_proc))
1557  ereport(ERROR,
1558  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1559  errmsg("default conversion function for encoding \"%s\" to \"%s\" does not exist",
1562  }
1563 
1564  cstate->copy_src = COPY_FILE; /* default */
1565 
1566  cstate->whereClause = whereClause;
1567 
1568  /* Initialize state variables */
1569  cstate->eol_type = EOL_UNKNOWN;
1570  cstate->cur_relname = RelationGetRelationName(cstate->rel);
1571  cstate->cur_lineno = 0;
1572  cstate->cur_attname = NULL;
1573  cstate->cur_attval = NULL;
1574  cstate->relname_only = false;
1575 
1576  /*
1577  * Allocate buffers for the input pipeline.
1578  *
1579  * attribute_buf and raw_buf are used in both text and binary modes, but
1580  * input_buf and line_buf only in text mode.
1581  */
1582  cstate->raw_buf = palloc(RAW_BUF_SIZE + 1);
1583  cstate->raw_buf_index = cstate->raw_buf_len = 0;
1584  cstate->raw_reached_eof = false;
1585 
1586  if (!cstate->opts.binary)
1587  {
1588  /*
1589  * If encoding conversion is needed, we need another buffer to hold
1590  * the converted input data. Otherwise, we can just point input_buf
1591  * to the same buffer as raw_buf.
1592  */
1593  if (cstate->need_transcoding)
1594  {
1595  cstate->input_buf = (char *) palloc(INPUT_BUF_SIZE + 1);
1596  cstate->input_buf_index = cstate->input_buf_len = 0;
1597  }
1598  else
1599  cstate->input_buf = cstate->raw_buf;
1600  cstate->input_reached_eof = false;
1601 
1602  initStringInfo(&cstate->line_buf);
1603  }
1604 
1605  initStringInfo(&cstate->attribute_buf);
1606 
1607  /* Assign range table and rteperminfos, we'll need them in CopyFrom. */
1608  if (pstate)
1609  {
1610  cstate->range_table = pstate->p_rtable;
1611  cstate->rteperminfos = pstate->p_rteperminfos;
1612  }
1613 
1614  num_defaults = 0;
1615  volatile_defexprs = false;
1616 
1617  /*
1618  * Pick up the required catalog information for each attribute in the
1619  * relation, including the input function, the element type (to pass to
1620  * the input function), and info about defaults and constraints. (Which
1621  * input function we use depends on text/binary format choice.)
1622  */
1623  in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
1624  typioparams = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
1625  defmap = (int *) palloc(num_phys_attrs * sizeof(int));
1626  defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *));
1627 
1628  for (int attnum = 1; attnum <= num_phys_attrs; attnum++)
1629  {
1630  Form_pg_attribute att = TupleDescAttr(tupDesc, attnum - 1);
1631 
1632  /* We don't need info for dropped attributes */
1633  if (att->attisdropped)
1634  continue;
1635 
1636  /* Fetch the input function and typioparam info */
1637  if (cstate->opts.binary)
1638  getTypeBinaryInputInfo(att->atttypid,
1639  &in_func_oid, &typioparams[attnum - 1]);
1640  else
1641  getTypeInputInfo(att->atttypid,
1642  &in_func_oid, &typioparams[attnum - 1]);
1643  fmgr_info(in_func_oid, &in_functions[attnum - 1]);
1644 
1645  /* Get default info if available */
1646  defexprs[attnum - 1] = NULL;
1647 
1648  /*
1649  * We only need the default values for columns that do not appear in
1650  * the column list, unless the DEFAULT option was given. We never need
1651  * default values for generated columns.
1652  */
1653  if ((cstate->opts.default_print != NULL ||
1654  !list_member_int(cstate->attnumlist, attnum)) &&
1655  !att->attgenerated)
1656  {
1657  Expr *defexpr = (Expr *) build_column_default(cstate->rel,
1658  attnum);
1659 
1660  if (defexpr != NULL)
1661  {
1662  /* Run the expression through planner */
1663  defexpr = expression_planner(defexpr);
1664 
1665  /* Initialize executable expression in copycontext */
1666  defexprs[attnum - 1] = ExecInitExpr(defexpr, NULL);
1667 
1668  /* if NOT copied from input */
1669  /* use default value if one exists */
1670  if (!list_member_int(cstate->attnumlist, attnum))
1671  {
1672  defmap[num_defaults] = attnum - 1;
1673  num_defaults++;
1674  }
1675 
1676  /*
1677  * If a default expression looks at the table being loaded,
1678  * then it could give the wrong answer when using
1679  * multi-insert. Since database access can be dynamic this is
1680  * hard to test for exactly, so we use the much wider test of
1681  * whether the default expression is volatile. We allow for
1682  * the special case of when the default expression is the
1683  * nextval() of a sequence which in this specific case is
1684  * known to be safe for use with the multi-insert
1685  * optimization. Hence we use this special case function
1686  * checker rather than the standard check for
1687  * contain_volatile_functions(). Note also that we already
1688  * ran the expression through expression_planner().
1689  */
1690  if (!volatile_defexprs)
1691  volatile_defexprs = contain_volatile_functions_not_nextval((Node *) defexpr);
1692  }
1693  }
1694  }
1695 
1696  cstate->defaults = (bool *) palloc0(tupDesc->natts * sizeof(bool));
1697 
1698  /* initialize progress */
1700  cstate->rel ? RelationGetRelid(cstate->rel) : InvalidOid);
1701  cstate->bytes_processed = 0;
1702 
1703  /* We keep those variables in cstate. */
1704  cstate->in_functions = in_functions;
1705  cstate->typioparams = typioparams;
1706  cstate->defmap = defmap;
1707  cstate->defexprs = defexprs;
1708  cstate->volatile_defexprs = volatile_defexprs;
1709  cstate->num_defaults = num_defaults;
1710  cstate->is_program = is_program;
1711 
1712  if (data_source_cb)
1713  {
1714  progress_vals[1] = PROGRESS_COPY_TYPE_CALLBACK;
1715  cstate->copy_src = COPY_CALLBACK;
1716  cstate->data_source_cb = data_source_cb;
1717  }
1718  else if (pipe)
1719  {
1720  progress_vals[1] = PROGRESS_COPY_TYPE_PIPE;
1721  Assert(!is_program); /* the grammar does not allow this */
1723  ReceiveCopyBegin(cstate);
1724  else
1725  cstate->copy_file = stdin;
1726  }
1727  else
1728  {
1729  cstate->filename = pstrdup(filename);
1730 
1731  if (cstate->is_program)
1732  {
1733  progress_vals[1] = PROGRESS_COPY_TYPE_PROGRAM;
1734  cstate->copy_file = OpenPipeStream(cstate->filename, PG_BINARY_R);
1735  if (cstate->copy_file == NULL)
1736  ereport(ERROR,
1738  errmsg("could not execute command \"%s\": %m",
1739  cstate->filename)));
1740  }
1741  else
1742  {
1743  struct stat st;
1744 
1745  progress_vals[1] = PROGRESS_COPY_TYPE_FILE;
1746  cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_R);
1747  if (cstate->copy_file == NULL)
1748  {
1749  /* copy errno because ereport subfunctions might change it */
1750  int save_errno = errno;
1751 
1752  ereport(ERROR,
1754  errmsg("could not open file \"%s\" for reading: %m",
1755  cstate->filename),
1756  (save_errno == ENOENT || save_errno == EACCES) ?
1757  errhint("COPY FROM instructs the PostgreSQL server process to read a file. "
1758  "You may want a client-side facility such as psql's \\copy.") : 0));
1759  }
1760 
1761  if (fstat(fileno(cstate->copy_file), &st))
1762  ereport(ERROR,
1764  errmsg("could not stat file \"%s\": %m",
1765  cstate->filename)));
1766 
1767  if (S_ISDIR(st.st_mode))
1768  ereport(ERROR,
1769  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1770  errmsg("\"%s\" is a directory", cstate->filename)));
1771 
1772  progress_vals[2] = st.st_size;
1773  }
1774  }
1775 
1776  pgstat_progress_update_multi_param(3, progress_cols, progress_vals);
1777 
1778  if (cstate->opts.binary)
1779  {
1780  /* Read and verify binary header */
1781  ReceiveCopyBinaryHeader(cstate);
1782  }
1783 
1784  /* create workspace for CopyReadAttributes results */
1785  if (!cstate->opts.binary)
1786  {
1787  AttrNumber attr_count = list_length(cstate->attnumlist);
1788 
1789  cstate->max_fields = attr_count;
1790  cstate->raw_fields = (char **) palloc(attr_count * sizeof(char *));
1791  }
1792 
1793  MemoryContextSwitchTo(oldcontext);
1794 
1795  return cstate;
1796 }
int16 AttrNumber
Definition: attnum.h:21
List * CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
Definition: copy.c:945
void ProcessCopyOptions(ParseState *pstate, CopyFormatOptions *opts_out, bool is_from, List *options)
Definition: copy.c:496
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:700
#define PG_BINARY_R
Definition: c.h:1229
#define Assert(condition)
Definition: c.h:812
int64_t int64
Definition: c.h:482
#define MemSet(start, val, len)
Definition: c.h:974
#define OidIsValid(objectId)
Definition: c.h:729
bool contain_volatile_functions_not_nextval(Node *clause)
Definition: clauses.c:672
#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:29
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:2605
FILE * OpenPipeStream(const char *command, const char *mode)
Definition: fd.c:2708
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:4080
#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:6735
CommandDest whereToSendOutput
Definition: postgres.c:90
#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:56
bool force_notnull_all
Definition: copy.h:80
bool binary
Definition: copy.h:64
bool convert_selectively
Definition: copy.h:85
CopyOnErrorChoice on_error
Definition: copy.h:86
List * force_null
Definition: copy.h:82
List * convert_select
Definition: copy.h:89
bool force_null_all
Definition: copy.h:83
bool * force_notnull_flags
Definition: copy.h:81
int file_encoding
Definition: copy.h:62
bool * force_null_flags
Definition: copy.h:84
char * default_print
Definition: copy.h:71
List * force_notnull
Definition: copy.h:79
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:48
bool error_occurred
Definition: miscnodes.h:47
NodeTag type
Definition: miscnodes.h:46
Definition: fmgr.h:57
Definition: pg_list.h:54
Definition: nodes.h:129
List * p_rteperminfos
Definition: parse_node.h:213
List * p_rtable
Definition: parse_node.h:212
#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 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  /* The only other utility command we could see is NOTIFY */
496  if (query->utilityStmt != NULL)
497  ereport(ERROR,
498  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
499  errmsg("COPY query must not be a utility command")));
500 
501  /*
502  * Similarly the grammar doesn't enforce the presence of a RETURNING
503  * clause, but this is required here.
504  */
505  if (query->commandType != CMD_SELECT &&
506  query->returningList == NIL)
507  {
508  Assert(query->commandType == CMD_INSERT ||
509  query->commandType == CMD_UPDATE ||
510  query->commandType == CMD_DELETE ||
511  query->commandType == CMD_MERGE);
512 
513  ereport(ERROR,
514  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
515  errmsg("COPY query must have a RETURNING clause")));
516  }
517 
518  /* plan the query */
519  plan = pg_plan_query(query, pstate->p_sourcetext,
520  CURSOR_OPT_PARALLEL_OK, NULL);
521 
522  /*
523  * With row-level security and a user using "COPY relation TO", we
524  * have to convert the "COPY relation TO" to a query-based COPY (eg:
525  * "COPY (SELECT * FROM ONLY relation) TO"), to allow the rewriter to
526  * add in any RLS clauses.
527  *
528  * When this happens, we are passed in the relid of the originally
529  * found relation (which we have locked). As the planner will look up
530  * the relation again, we double-check here to make sure it found the
531  * same one that we have locked.
532  */
533  if (queryRelId != InvalidOid)
534  {
535  /*
536  * Note that with RLS involved there may be multiple relations,
537  * and while the one we need is almost certainly first, we don't
538  * make any guarantees of that in the planner, so check the whole
539  * list and make sure we find the original relation.
540  */
541  if (!list_member_oid(plan->relationOids, queryRelId))
542  ereport(ERROR,
543  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
544  errmsg("relation referenced by COPY statement has changed")));
545  }
546 
547  /*
548  * Use a snapshot with an updated command ID to ensure this query sees
549  * results of any previously executed queries.
550  */
553 
554  /* Create dest receiver for COPY OUT */
556  ((DR_copy *) dest)->cstate = cstate;
557 
558  /* Create a QueryDesc requesting no output */
559  cstate->queryDesc = CreateQueryDesc(plan, pstate->p_sourcetext,
562  dest, NULL, NULL, 0);
563 
564  /*
565  * Call ExecutorStart to prepare the plan for execution.
566  *
567  * ExecutorStart computes a result tupdesc for us
568  */
569  ExecutorStart(cstate->queryDesc, 0);
570 
571  tupDesc = cstate->queryDesc->tupDesc;
572  }
573 
574  /* Generate or convert list of attributes to process */
575  cstate->attnumlist = CopyGetAttnums(tupDesc, cstate->rel, attnamelist);
576 
577  num_phys_attrs = tupDesc->natts;
578 
579  /* Convert FORCE_QUOTE name list to per-column flags, check validity */
580  cstate->opts.force_quote_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
581  if (cstate->opts.force_quote_all)
582  {
583  MemSet(cstate->opts.force_quote_flags, true, num_phys_attrs * sizeof(bool));
584  }
585  else if (cstate->opts.force_quote)
586  {
587  List *attnums;
588  ListCell *cur;
589 
590  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_quote);
591 
592  foreach(cur, attnums)
593  {
594  int attnum = lfirst_int(cur);
595  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
596 
597  if (!list_member_int(cstate->attnumlist, attnum))
598  ereport(ERROR,
599  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
600  /*- translator: %s is the name of a COPY option, e.g. FORCE_NOT_NULL */
601  errmsg("%s column \"%s\" not referenced by COPY",
602  "FORCE_QUOTE", NameStr(attr->attname))));
603  cstate->opts.force_quote_flags[attnum - 1] = true;
604  }
605  }
606 
607  /* Use client encoding when ENCODING option is not specified. */
608  if (cstate->opts.file_encoding < 0)
610  else
611  cstate->file_encoding = cstate->opts.file_encoding;
612 
613  /*
614  * Set up encoding conversion info if the file and server encodings differ
615  * (see also pg_server_to_any).
616  */
617  if (cstate->file_encoding == GetDatabaseEncoding() ||
618  cstate->file_encoding == PG_SQL_ASCII)
619  cstate->need_transcoding = false;
620  else
621  cstate->need_transcoding = true;
622 
623  /* See Multibyte encoding comment above */
625 
626  cstate->copy_dest = COPY_FILE; /* default */
627 
628  if (data_dest_cb)
629  {
630  progress_vals[1] = PROGRESS_COPY_TYPE_CALLBACK;
631  cstate->copy_dest = COPY_CALLBACK;
632  cstate->data_dest_cb = data_dest_cb;
633  }
634  else if (pipe)
635  {
636  progress_vals[1] = PROGRESS_COPY_TYPE_PIPE;
637 
638  Assert(!is_program); /* the grammar does not allow this */
640  cstate->copy_file = stdout;
641  }
642  else
643  {
644  cstate->filename = pstrdup(filename);
645  cstate->is_program = is_program;
646 
647  if (is_program)
648  {
649  progress_vals[1] = PROGRESS_COPY_TYPE_PROGRAM;
650  cstate->copy_file = OpenPipeStream(cstate->filename, PG_BINARY_W);
651  if (cstate->copy_file == NULL)
652  ereport(ERROR,
654  errmsg("could not execute command \"%s\": %m",
655  cstate->filename)));
656  }
657  else
658  {
659  mode_t oumask; /* Pre-existing umask value */
660  struct stat st;
661 
662  progress_vals[1] = PROGRESS_COPY_TYPE_FILE;
663 
664  /*
665  * Prevent write to relative path ... too easy to shoot oneself in
666  * the foot by overwriting a database file ...
667  */
669  ereport(ERROR,
670  (errcode(ERRCODE_INVALID_NAME),
671  errmsg("relative path not allowed for COPY to file")));
672 
673  oumask = umask(S_IWGRP | S_IWOTH);
674  PG_TRY();
675  {
676  cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_W);
677  }
678  PG_FINALLY();
679  {
680  umask(oumask);
681  }
682  PG_END_TRY();
683  if (cstate->copy_file == NULL)
684  {
685  /* copy errno because ereport subfunctions might change it */
686  int save_errno = errno;
687 
688  ereport(ERROR,
690  errmsg("could not open file \"%s\" for writing: %m",
691  cstate->filename),
692  (save_errno == ENOENT || save_errno == EACCES) ?
693  errhint("COPY TO instructs the PostgreSQL server process to write a file. "
694  "You may want a client-side facility such as psql's \\copy.") : 0));
695  }
696 
697  if (fstat(fileno(cstate->copy_file), &st))
698  ereport(ERROR,
700  errmsg("could not stat file \"%s\": %m",
701  cstate->filename)));
702 
703  if (S_ISDIR(st.st_mode))
704  ereport(ERROR,
705  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
706  errmsg("\"%s\" is a directory", cstate->filename)));
707  }
708  }
709 
710  /* initialize progress */
712  cstate->rel ? RelationGetRelid(cstate->rel) : InvalidOid);
713  pgstat_progress_update_multi_param(2, progress_cols, progress_vals);
714 
715  cstate->bytes_processed = 0;
716 
717  MemoryContextSwitchTo(oldcontext);
718 
719  return cstate;
720 }
#define PG_BINARY_W
Definition: c.h:1230
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:121
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:3317
#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:161
#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:676
PlannedStmt * pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, ParamListInfo boundParams)
Definition: postgres.c:893
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:77
List * force_quote
Definition: copy.h:76
bool * force_quote_flags
Definition: copy.h:78
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:209
TupleDesc tupDesc
Definition: execdesc.h:47
List * returningList
Definition: parsenodes.h:200
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  bool has_before_insert_row_trig;
661  bool has_instead_insert_row_trig;
662  bool leafpart_use_multi_insert = false;
663 
664  Assert(cstate->rel);
665  Assert(list_length(cstate->range_table) == 1);
666 
667  if (cstate->opts.on_error != COPY_ON_ERROR_STOP)
668  Assert(cstate->escontext);
669 
670  /*
671  * The target must be a plain, foreign, or partitioned relation, or have
672  * an INSTEAD OF INSERT row trigger. (Currently, such triggers are only
673  * allowed on views, so we only hint about them in the view case.)
674  */
675  if (cstate->rel->rd_rel->relkind != RELKIND_RELATION &&
676  cstate->rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
677  cstate->rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE &&
678  !(cstate->rel->trigdesc &&
680  {
681  if (cstate->rel->rd_rel->relkind == RELKIND_VIEW)
682  ereport(ERROR,
683  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
684  errmsg("cannot copy to view \"%s\"",
685  RelationGetRelationName(cstate->rel)),
686  errhint("To enable copying to a view, provide an INSTEAD OF INSERT trigger.")));
687  else if (cstate->rel->rd_rel->relkind == RELKIND_MATVIEW)
688  ereport(ERROR,
689  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
690  errmsg("cannot copy to materialized view \"%s\"",
691  RelationGetRelationName(cstate->rel))));
692  else if (cstate->rel->rd_rel->relkind == RELKIND_SEQUENCE)
693  ereport(ERROR,
694  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
695  errmsg("cannot copy to sequence \"%s\"",
696  RelationGetRelationName(cstate->rel))));
697  else
698  ereport(ERROR,
699  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
700  errmsg("cannot copy to non-table relation \"%s\"",
701  RelationGetRelationName(cstate->rel))));
702  }
703 
704  /*
705  * If the target file is new-in-transaction, we assume that checking FSM
706  * for free space is a waste of time. This could possibly be wrong, but
707  * it's unlikely.
708  */
709  if (RELKIND_HAS_STORAGE(cstate->rel->rd_rel->relkind) &&
712  ti_options |= TABLE_INSERT_SKIP_FSM;
713 
714  /*
715  * Optimize if new relation storage was created in this subxact or one of
716  * its committed children and we won't see those rows later as part of an
717  * earlier scan or command. The subxact test ensures that if this subxact
718  * aborts then the frozen rows won't be visible after xact cleanup. Note
719  * that the stronger test of exactly which subtransaction created it is
720  * crucial for correctness of this optimization. The test for an earlier
721  * scan or command tolerates false negatives. FREEZE causes other sessions
722  * to see rows they would not see under MVCC, and a false negative merely
723  * spreads that anomaly to the current session.
724  */
725  if (cstate->opts.freeze)
726  {
727  /*
728  * We currently disallow COPY FREEZE on partitioned tables. The
729  * reason for this is that we've simply not yet opened the partitions
730  * to determine if the optimization can be applied to them. We could
731  * go and open them all here, but doing so may be quite a costly
732  * overhead for small copies. In any case, we may just end up routing
733  * tuples to a small number of partitions. It seems better just to
734  * raise an ERROR for partitioned tables.
735  */
736  if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
737  {
738  ereport(ERROR,
739  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
740  errmsg("cannot perform COPY FREEZE on a partitioned table")));
741  }
742 
743  /*
744  * Tolerate one registration for the benefit of FirstXactSnapshot.
745  * Scan-bearing queries generally create at least two registrations,
746  * though relying on that is fragile, as is ignoring ActiveSnapshot.
747  * Clear CatalogSnapshot to avoid counting its registration. We'll
748  * still detect ongoing catalog scans, each of which separately
749  * registers the snapshot it uses.
750  */
753  ereport(ERROR,
754  (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
755  errmsg("cannot perform COPY FREEZE because of prior transaction activity")));
756 
757  if (cstate->rel->rd_createSubid != GetCurrentSubTransactionId() &&
759  ereport(ERROR,
760  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
761  errmsg("cannot perform COPY FREEZE because the table was not created or truncated in the current subtransaction")));
762 
763  ti_options |= TABLE_INSERT_FROZEN;
764  }
765 
766  /*
767  * We need a ResultRelInfo so we can use the regular executor's
768  * index-entry-making machinery. (There used to be a huge amount of code
769  * here that basically duplicated execUtils.c ...)
770  */
771  ExecInitRangeTable(estate, cstate->range_table, cstate->rteperminfos);
772  resultRelInfo = target_resultRelInfo = makeNode(ResultRelInfo);
773  ExecInitResultRelation(estate, resultRelInfo, 1);
774 
775  /* Verify the named relation is a valid target for INSERT */
776  CheckValidResultRel(resultRelInfo, CMD_INSERT, NIL);
777 
778  ExecOpenIndices(resultRelInfo, false);
779 
780  /*
781  * Set up a ModifyTableState so we can let FDW(s) init themselves for
782  * foreign-table result relation(s).
783  */
784  mtstate = makeNode(ModifyTableState);
785  mtstate->ps.plan = NULL;
786  mtstate->ps.state = estate;
787  mtstate->operation = CMD_INSERT;
788  mtstate->mt_nrels = 1;
789  mtstate->resultRelInfo = resultRelInfo;
790  mtstate->rootResultRelInfo = resultRelInfo;
791 
792  if (resultRelInfo->ri_FdwRoutine != NULL &&
793  resultRelInfo->ri_FdwRoutine->BeginForeignInsert != NULL)
794  resultRelInfo->ri_FdwRoutine->BeginForeignInsert(mtstate,
795  resultRelInfo);
796 
797  /*
798  * Also, if the named relation is a foreign table, determine if the FDW
799  * supports batch insert and determine the batch size (a FDW may support
800  * batching, but it may be disabled for the server/table).
801  *
802  * If the FDW does not support batching, we set the batch size to 1.
803  */
804  if (resultRelInfo->ri_FdwRoutine != NULL &&
805  resultRelInfo->ri_FdwRoutine->GetForeignModifyBatchSize &&
806  resultRelInfo->ri_FdwRoutine->ExecForeignBatchInsert)
807  resultRelInfo->ri_BatchSize =
808  resultRelInfo->ri_FdwRoutine->GetForeignModifyBatchSize(resultRelInfo);
809  else
810  resultRelInfo->ri_BatchSize = 1;
811 
812  Assert(resultRelInfo->ri_BatchSize >= 1);
813 
814  /* Prepare to catch AFTER triggers. */
816 
817  /*
818  * If there are any triggers with transition tables on the named relation,
819  * we need to be prepared to capture transition tuples.
820  *
821  * Because partition tuple routing would like to know about whether
822  * transition capture is active, we also set it in mtstate, which is
823  * passed to ExecFindPartition() below.
824  */
825  cstate->transition_capture = mtstate->mt_transition_capture =
827  RelationGetRelid(cstate->rel),
828  CMD_INSERT);
829 
830  /*
831  * If the named relation is a partitioned table, initialize state for
832  * CopyFrom tuple routing.
833  */
834  if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
835  proute = ExecSetupPartitionTupleRouting(estate, cstate->rel);
836 
837  if (cstate->whereClause)
838  cstate->qualexpr = ExecInitQual(castNode(List, cstate->whereClause),
839  &mtstate->ps);
840 
841  /*
842  * It's generally more efficient to prepare a bunch of tuples for
843  * insertion, and insert them in one
844  * table_multi_insert()/ExecForeignBatchInsert() call, than call
845  * table_tuple_insert()/ExecForeignInsert() separately for every tuple.
846  * However, there are a number of reasons why we might not be able to do
847  * this. These are explained below.
848  */
849  if (resultRelInfo->ri_TrigDesc != NULL &&
850  (resultRelInfo->ri_TrigDesc->trig_insert_before_row ||
851  resultRelInfo->ri_TrigDesc->trig_insert_instead_row))
852  {
853  /*
854  * Can't support multi-inserts when there are any BEFORE/INSTEAD OF
855  * triggers on the table. Such triggers might query the table we're
856  * inserting into and act differently if the tuples that have already
857  * been processed and prepared for insertion are not there.
858  */
859  insertMethod = CIM_SINGLE;
860  }
861  else if (resultRelInfo->ri_FdwRoutine != NULL &&
862  resultRelInfo->ri_BatchSize == 1)
863  {
864  /*
865  * Can't support multi-inserts to a foreign table if the FDW does not
866  * support batching, or it's disabled for the server or foreign table.
867  */
868  insertMethod = CIM_SINGLE;
869  }
870  else if (proute != NULL && resultRelInfo->ri_TrigDesc != NULL &&
871  resultRelInfo->ri_TrigDesc->trig_insert_new_table)
872  {
873  /*
874  * For partitioned tables we can't support multi-inserts when there
875  * are any statement level insert triggers. It might be possible to
876  * allow partitioned tables with such triggers in the future, but for
877  * now, CopyMultiInsertInfoFlush expects that any after row insert and
878  * statement level insert triggers are on the same relation.
879  */
880  insertMethod = CIM_SINGLE;
881  }
882  else if (cstate->volatile_defexprs)
883  {
884  /*
885  * Can't support multi-inserts if there are any volatile default
886  * expressions in the table. Similarly to the trigger case above,
887  * such expressions may query the table we're inserting into.
888  *
889  * Note: It does not matter if any partitions have any volatile
890  * default expressions as we use the defaults from the target of the
891  * COPY command.
892  */
893  insertMethod = CIM_SINGLE;
894  }
895  else if (contain_volatile_functions(cstate->whereClause))
896  {
897  /*
898  * Can't support multi-inserts if there are any volatile function
899  * expressions in WHERE clause. Similarly to the trigger case above,
900  * such expressions may query the table we're inserting into.
901  *
902  * Note: the whereClause was already preprocessed in DoCopy(), so it's
903  * okay to use contain_volatile_functions() directly.
904  */
905  insertMethod = CIM_SINGLE;
906  }
907  else
908  {
909  /*
910  * For partitioned tables, we may still be able to perform bulk
911  * inserts. However, the possibility of this depends on which types
912  * of triggers exist on the partition. We must disable bulk inserts
913  * if the partition is a foreign table that can't use batching or it
914  * has any before row insert or insert instead triggers (same as we
915  * checked above for the parent table). Since the partition's
916  * resultRelInfos are initialized only when we actually need to insert
917  * the first tuple into them, we must have the intermediate insert
918  * method of CIM_MULTI_CONDITIONAL to flag that we must later
919  * determine if we can use bulk-inserts for the partition being
920  * inserted into.
921  */
922  if (proute)
923  insertMethod = CIM_MULTI_CONDITIONAL;
924  else
925  insertMethod = CIM_MULTI;
926 
927  CopyMultiInsertInfoInit(&multiInsertInfo, resultRelInfo, cstate,
928  estate, mycid, ti_options);
929  }
930 
931  /*
932  * If not using batch mode (which allocates slots as needed) set up a
933  * tuple slot too. When inserting into a partitioned table, we also need
934  * one, even if we might batch insert, to read the tuple in the root
935  * partition's form.
936  */
937  if (insertMethod == CIM_SINGLE || insertMethod == CIM_MULTI_CONDITIONAL)
938  {
939  singleslot = table_slot_create(resultRelInfo->ri_RelationDesc,
940  &estate->es_tupleTable);
941  bistate = GetBulkInsertState();
942  }
943 
944  has_before_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
945  resultRelInfo->ri_TrigDesc->trig_insert_before_row);
946 
947  has_instead_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
948  resultRelInfo->ri_TrigDesc->trig_insert_instead_row);
949 
950  /*
951  * Check BEFORE STATEMENT insertion triggers. It's debatable whether we
952  * should do this for COPY, since it's not really an "INSERT" statement as
953  * such. However, executing these triggers maintains consistency with the
954  * EACH ROW triggers that we already fire on COPY.
955  */
956  ExecBSInsertTriggers(estate, resultRelInfo);
957 
958  econtext = GetPerTupleExprContext(estate);
959 
960  /* Set up callback to identify error line number */
961  errcallback.callback = CopyFromErrorCallback;
962  errcallback.arg = cstate;
963  errcallback.previous = error_context_stack;
964  error_context_stack = &errcallback;
965 
966  for (;;)
967  {
968  TupleTableSlot *myslot;
969  bool skip_tuple;
970 
972 
973  /*
974  * Reset the per-tuple exprcontext. We do this after every tuple, to
975  * clean-up after expression evaluations etc.
976  */
977  ResetPerTupleExprContext(estate);
978 
979  /* select slot to (initially) load row into */
980  if (insertMethod == CIM_SINGLE || proute)
981  {
982  myslot = singleslot;
983  Assert(myslot != NULL);
984  }
985  else
986  {
987  Assert(resultRelInfo == target_resultRelInfo);
988  Assert(insertMethod == CIM_MULTI);
989 
990  myslot = CopyMultiInsertInfoNextFreeSlot(&multiInsertInfo,
991  resultRelInfo);
992  }
993 
994  /*
995  * Switch to per-tuple context before calling NextCopyFrom, which does
996  * evaluate default expressions etc. and requires per-tuple context.
997  */
999 
1000  ExecClearTuple(myslot);
1001 
1002  /* Directly store the values/nulls array in the slot */
1003  if (!NextCopyFrom(cstate, econtext, myslot->tts_values, myslot->tts_isnull))
1004  break;
1005 
1006  if (cstate->opts.on_error == COPY_ON_ERROR_IGNORE &&
1007  cstate->escontext->error_occurred)
1008  {
1009  /*
1010  * Soft error occurred, skip this tuple and just make
1011  * ErrorSaveContext ready for the next NextCopyFrom. Since we
1012  * don't set details_wanted and error_data is not to be filled,
1013  * just resetting error_occurred is enough.
1014  */
1015  cstate->escontext->error_occurred = false;
1016 
1017  /* Report that this tuple was skipped by the ON_ERROR clause */
1019  cstate->num_errors);
1020 
1021  if (cstate->opts.reject_limit > 0 &&
1022  cstate->num_errors > cstate->opts.reject_limit)
1023  ereport(ERROR,
1024  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1025  errmsg("skipped more than REJECT_LIMIT (%lld) rows due to data type incompatibility",
1026  (long long) cstate->opts.reject_limit)));
1027 
1028  /* Repeat NextCopyFrom() until no soft error occurs */
1029  continue;
1030  }
1031 
1032  ExecStoreVirtualTuple(myslot);
1033 
1034  /*
1035  * Constraints and where clause might reference the tableoid column,
1036  * so (re-)initialize tts_tableOid before evaluating them.
1037  */
1038  myslot->tts_tableOid = RelationGetRelid(target_resultRelInfo->ri_RelationDesc);
1039 
1040  /* Triggers and stuff need to be invoked in query context. */
1041  MemoryContextSwitchTo(oldcontext);
1042 
1043  if (cstate->whereClause)
1044  {
1045  econtext->ecxt_scantuple = myslot;
1046  /* Skip items that don't match COPY's WHERE clause */
1047  if (!ExecQual(cstate->qualexpr, econtext))
1048  {
1049  /*
1050  * Report that this tuple was filtered out by the WHERE
1051  * clause.
1052  */
1054  ++excluded);
1055  continue;
1056  }
1057  }
1058 
1059  /* Determine the partition to insert the tuple into */
1060  if (proute)
1061  {
1062  TupleConversionMap *map;
1063 
1064  /*
1065  * Attempt to find a partition suitable for this tuple.
1066  * ExecFindPartition() will raise an error if none can be found or
1067  * if the found partition is not suitable for INSERTs.
1068  */
1069  resultRelInfo = ExecFindPartition(mtstate, target_resultRelInfo,
1070  proute, myslot, estate);
1071 
1072  if (prevResultRelInfo != resultRelInfo)
1073  {
1074  /* Determine which triggers exist on this partition */
1075  has_before_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
1076  resultRelInfo->ri_TrigDesc->trig_insert_before_row);
1077 
1078  has_instead_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
1079  resultRelInfo->ri_TrigDesc->trig_insert_instead_row);
1080 
1081  /*
1082  * Disable multi-inserts when the partition has BEFORE/INSTEAD
1083  * OF triggers, or if the partition is a foreign table that
1084  * can't use batching.
1085  */
1086  leafpart_use_multi_insert = insertMethod == CIM_MULTI_CONDITIONAL &&
1087  !has_before_insert_row_trig &&
1088  !has_instead_insert_row_trig &&
1089  (resultRelInfo->ri_FdwRoutine == NULL ||
1090  resultRelInfo->ri_BatchSize > 1);
1091 
1092  /* Set the multi-insert buffer to use for this partition. */
1093  if (leafpart_use_multi_insert)
1094  {
1095  if (resultRelInfo->ri_CopyMultiInsertBuffer == NULL)
1096  CopyMultiInsertInfoSetupBuffer(&multiInsertInfo,
1097  resultRelInfo);
1098  }
1099  else if (insertMethod == CIM_MULTI_CONDITIONAL &&
1100  !CopyMultiInsertInfoIsEmpty(&multiInsertInfo))
1101  {
1102  /*
1103  * Flush pending inserts if this partition can't use
1104  * batching, so rows are visible to triggers etc.
1105  */
1106  CopyMultiInsertInfoFlush(&multiInsertInfo,
1107  resultRelInfo,
1108  &processed);
1109  }
1110 
1111  if (bistate != NULL)
1112  ReleaseBulkInsertStatePin(bistate);
1113  prevResultRelInfo = resultRelInfo;
1114  }
1115 
1116  /*
1117  * If we're capturing transition tuples, we might need to convert
1118  * from the partition rowtype to root rowtype. But if there are no
1119  * BEFORE triggers on the partition that could change the tuple,
1120  * we can just remember the original unconverted tuple to avoid a
1121  * needless round trip conversion.
1122  */
1123  if (cstate->transition_capture != NULL)
1125  !has_before_insert_row_trig ? myslot : NULL;
1126 
1127  /*
1128  * We might need to convert from the root rowtype to the partition
1129  * rowtype.
1130  */
1131  map = ExecGetRootToChildMap(resultRelInfo, estate);
1132  if (insertMethod == CIM_SINGLE || !leafpart_use_multi_insert)
1133  {
1134  /* non batch insert */
1135  if (map != NULL)
1136  {
1137  TupleTableSlot *new_slot;
1138 
1139  new_slot = resultRelInfo->ri_PartitionTupleSlot;
1140  myslot = execute_attr_map_slot(map->attrMap, myslot, new_slot);
1141  }
1142  }
1143  else
1144  {
1145  /*
1146  * Prepare to queue up tuple for later batch insert into
1147  * current partition.
1148  */
1149  TupleTableSlot *batchslot;
1150 
1151  /* no other path available for partitioned table */
1152  Assert(insertMethod == CIM_MULTI_CONDITIONAL);
1153 
1154  batchslot = CopyMultiInsertInfoNextFreeSlot(&multiInsertInfo,
1155  resultRelInfo);
1156 
1157  if (map != NULL)
1158  myslot = execute_attr_map_slot(map->attrMap, myslot,
1159  batchslot);
1160  else
1161  {
1162  /*
1163  * This looks more expensive than it is (Believe me, I
1164  * optimized it away. Twice.). The input is in virtual
1165  * form, and we'll materialize the slot below - for most
1166  * slot types the copy performs the work materialization
1167  * would later require anyway.
1168  */
1169  ExecCopySlot(batchslot, myslot);
1170  myslot = batchslot;
1171  }
1172  }
1173 
1174  /* ensure that triggers etc see the right relation */
1175  myslot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
1176  }
1177 
1178  skip_tuple = false;
1179 
1180  /* BEFORE ROW INSERT Triggers */
1181  if (has_before_insert_row_trig)
1182  {
1183  if (!ExecBRInsertTriggers(estate, resultRelInfo, myslot))
1184  skip_tuple = true; /* "do nothing" */
1185  }
1186 
1187  if (!skip_tuple)
1188  {
1189  /*
1190  * If there is an INSTEAD OF INSERT ROW trigger, let it handle the
1191  * tuple. Otherwise, proceed with inserting the tuple into the
1192  * table or foreign table.
1193  */
1194  if (has_instead_insert_row_trig)
1195  {
1196  ExecIRInsertTriggers(estate, resultRelInfo, myslot);
1197  }
1198  else
1199  {
1200  /* Compute stored generated columns */
1201  if (resultRelInfo->ri_RelationDesc->rd_att->constr &&
1203  ExecComputeStoredGenerated(resultRelInfo, estate, myslot,
1204  CMD_INSERT);
1205 
1206  /*
1207  * If the target is a plain table, check the constraints of
1208  * the tuple.
1209  */
1210  if (resultRelInfo->ri_FdwRoutine == NULL &&
1211  resultRelInfo->ri_RelationDesc->rd_att->constr)
1212  ExecConstraints(resultRelInfo, myslot, estate);
1213 
1214  /*
1215  * Also check the tuple against the partition constraint, if
1216  * there is one; except that if we got here via tuple-routing,
1217  * we don't need to if there's no BR trigger defined on the
1218  * partition.
1219  */
1220  if (resultRelInfo->ri_RelationDesc->rd_rel->relispartition &&
1221  (proute == NULL || has_before_insert_row_trig))
1222  ExecPartitionCheck(resultRelInfo, myslot, estate, true);
1223 
1224  /* Store the slot in the multi-insert buffer, when enabled. */
1225  if (insertMethod == CIM_MULTI || leafpart_use_multi_insert)
1226  {
1227  /*
1228  * The slot previously might point into the per-tuple
1229  * context. For batching it needs to be longer lived.
1230  */
1231  ExecMaterializeSlot(myslot);
1232 
1233  /* Add this tuple to the tuple buffer */
1234  CopyMultiInsertInfoStore(&multiInsertInfo,
1235  resultRelInfo, myslot,
1236  cstate->line_buf.len,
1237  cstate->cur_lineno);
1238 
1239  /*
1240  * If enough inserts have queued up, then flush all
1241  * buffers out to their tables.
1242  */
1243  if (CopyMultiInsertInfoIsFull(&multiInsertInfo))
1244  CopyMultiInsertInfoFlush(&multiInsertInfo,
1245  resultRelInfo,
1246  &processed);
1247 
1248  /*
1249  * We delay updating the row counter and progress of the
1250  * COPY command until after writing the tuples stored in
1251  * the buffer out to the table, as in single insert mode.
1252  * See CopyMultiInsertBufferFlush().
1253  */
1254  continue; /* next tuple please */
1255  }
1256  else
1257  {
1258  List *recheckIndexes = NIL;
1259 
1260  /* OK, store the tuple */
1261  if (resultRelInfo->ri_FdwRoutine != NULL)
1262  {
1263  myslot = resultRelInfo->ri_FdwRoutine->ExecForeignInsert(estate,
1264  resultRelInfo,
1265  myslot,
1266  NULL);
1267 
1268  if (myslot == NULL) /* "do nothing" */
1269  continue; /* next tuple please */
1270 
1271  /*
1272  * AFTER ROW Triggers might reference the tableoid
1273  * column, so (re-)initialize tts_tableOid before
1274  * evaluating them.
1275  */
1276  myslot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
1277  }
1278  else
1279  {
1280  /* OK, store the tuple and create index entries for it */
1281  table_tuple_insert(resultRelInfo->ri_RelationDesc,
1282  myslot, mycid, ti_options, bistate);
1283 
1284  if (resultRelInfo->ri_NumIndices > 0)
1285  recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
1286  myslot,
1287  estate,
1288  false,
1289  false,
1290  NULL,
1291  NIL,
1292  false);
1293  }
1294 
1295  /* AFTER ROW INSERT Triggers */
1296  ExecARInsertTriggers(estate, resultRelInfo, myslot,
1297  recheckIndexes, cstate->transition_capture);
1298 
1299  list_free(recheckIndexes);
1300  }
1301  }
1302 
1303  /*
1304  * We count only tuples not suppressed by a BEFORE INSERT trigger
1305  * or FDW; this is the same definition used by nodeModifyTable.c
1306  * for counting tuples inserted by an INSERT command. Update
1307  * progress of the COPY command as well.
1308  */
1310  ++processed);
1311  }
1312  }
1313 
1314  /* Flush any remaining buffered tuples */
1315  if (insertMethod != CIM_SINGLE)
1316  {
1317  if (!CopyMultiInsertInfoIsEmpty(&multiInsertInfo))
1318  CopyMultiInsertInfoFlush(&multiInsertInfo, NULL, &processed);
1319  }
1320 
1321  /* Done, clean up */
1322  error_context_stack = errcallback.previous;
1323 
1324  if (cstate->opts.on_error != COPY_ON_ERROR_STOP &&
1325  cstate->num_errors > 0 &&
1327  ereport(NOTICE,
1328  errmsg_plural("%llu row was skipped due to data type incompatibility",
1329  "%llu rows were skipped due to data type incompatibility",
1330  (unsigned long long) cstate->num_errors,
1331  (unsigned long long) cstate->num_errors));
1332 
1333  if (bistate != NULL)
1334  FreeBulkInsertState(bistate);
1335 
1336  MemoryContextSwitchTo(oldcontext);
1337 
1338  /* Execute AFTER STATEMENT insertion triggers */
1339  ExecASInsertTriggers(estate, target_resultRelInfo, cstate->transition_capture);
1340 
1341  /* Handle queued AFTER triggers */
1342  AfterTriggerEndQuery(estate);
1343 
1344  ExecResetTupleTable(estate->es_tupleTable, false);
1345 
1346  /* Allow the FDW to shut down */
1347  if (target_resultRelInfo->ri_FdwRoutine != NULL &&
1348  target_resultRelInfo->ri_FdwRoutine->EndForeignInsert != NULL)
1349  target_resultRelInfo->ri_FdwRoutine->EndForeignInsert(estate,
1350  target_resultRelInfo);
1351 
1352  /* Tear down the multi-insert buffer data */
1353  if (insertMethod != CIM_SINGLE)
1354  CopyMultiInsertInfoCleanup(&multiInsertInfo);
1355 
1356  /* Close all the partitioned tables, leaf partitions, and their indices */
1357  if (proute)
1358  ExecCleanupTupleRouting(mtstate, proute);
1359 
1360  /* Close the result relations, including any trigger target relations */
1361  ExecCloseResultRelations(estate);
1363 
1364  FreeExecutorState(estate);
1365 
1366  return processed;
1367 }
void pgstat_progress_update_param(int index, int64 val)
#define InvalidSubTransactionId
Definition: c.h:612
uint32 CommandId
Definition: c.h:620
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:537
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:303
void ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative)
Definition: execIndexing.c:160
void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation, List *mergeActions)
Definition: execMain.c:1029
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
Definition: execMain.c:1801
void ExecCloseResultRelations(EState *estate)
Definition: execMain.c:1526
void ExecCloseRangeTableRelations(EState *estate)
Definition: execMain.c:1586
void ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1925
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:730
void ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo, Index rti)
Definition: execUtils.c:816
EState * CreateExecutorState(void)
Definition: execUtils.c:88
TupleConversionMap * ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate)
Definition: execUtils.c:1234
void FreeExecutorState(EState *estate)
Definition: execUtils.c:191
#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:1947
BulkInsertState GetBulkInsertState(void)
Definition: heapam.c:1918
void FreeBulkInsertState(BulkInsertState bistate)
Definition: heapam.c:1935
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:1171
#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:65
CopyLogVerbosityChoice log_verbosity
Definition: copy.h:87
int64 reject_limit
Definition: copy.h:88
TransitionCaptureState * transition_capture
List * es_tupleTable
Definition: execnodes.h:677
struct ErrorContextCallback * previous
Definition: elog.h:296
void(* callback)(void *arg)
Definition: elog.h:297
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:258
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:1366
ResultRelInfo * resultRelInfo
Definition: execnodes.h:1370
PlanState ps
Definition: execnodes.h:1365
ResultRelInfo * rootResultRelInfo
Definition: execnodes.h:1378
struct TransitionCaptureState * mt_transition_capture
Definition: execnodes.h:1404
Plan * plan
Definition: execnodes.h:1127
EState * state
Definition: execnodes.h:1129
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:591
int ri_NumIndices
Definition: execnodes.h:462
Relation ri_RelationDesc
Definition: execnodes.h:459
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition: execnodes.h:594
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:492
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:509
int ri_BatchSize
Definition: execnodes.h:520
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:260
#define TABLE_INSERT_SKIP_FSM
Definition: tableam.h:259
static void table_tuple_insert(Relation rel, TupleTableSlot *slot, CommandId cid, int options, struct BulkInsertStateData *bistate)
Definition: tableam.h:1411
void ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2395
bool ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2459
bool ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2552
void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot, List *recheckIndexes, TransitionCaptureState *transition_capture)
Definition: trigger.c:2535
TransitionCaptureState * MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType)
Definition: trigger.c:4888
void ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo, TransitionCaptureState *transition_capture)
Definition: trigger.c:2446
void AfterTriggerEndQuery(EState *estate)
Definition: trigger.c:5044
void AfterTriggerBeginQuery(void)
Definition: trigger.c:5024
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_LOG_VERBOSITY_DEFAULT, 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(), CopyFormatOptions::log_verbosity, 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, CopyFormatOptions::reject_limit, 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:93
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 945 of file copy.c.

946 {
947  List *attnums = NIL;
948 
949  if (attnamelist == NIL)
950  {
951  /* Generate default column list */
952  int attr_count = tupDesc->natts;
953  int i;
954 
955  for (i = 0; i < attr_count; i++)
956  {
957  if (TupleDescAttr(tupDesc, i)->attisdropped)
958  continue;
959  if (TupleDescAttr(tupDesc, i)->attgenerated)
960  continue;
961  attnums = lappend_int(attnums, i + 1);
962  }
963  }
964  else
965  {
966  /* Validate the user-supplied list and extract attnums */
967  ListCell *l;
968 
969  foreach(l, attnamelist)
970  {
971  char *name = strVal(lfirst(l));
972  int attnum;
973  int i;
974 
975  /* Lookup column name */
977  for (i = 0; i < tupDesc->natts; i++)
978  {
979  Form_pg_attribute att = TupleDescAttr(tupDesc, i);
980 
981  if (att->attisdropped)
982  continue;
983  if (namestrcmp(&(att->attname), name) == 0)
984  {
985  if (att->attgenerated)
986  ereport(ERROR,
987  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
988  errmsg("column \"%s\" is a generated column",
989  name),
990  errdetail("Generated columns cannot be used in COPY.")));
991  attnum = att->attnum;
992  break;
993  }
994  }
995  if (attnum == InvalidAttrNumber)
996  {
997  if (rel != NULL)
998  ereport(ERROR,
999  (errcode(ERRCODE_UNDEFINED_COLUMN),
1000  errmsg("column \"%s\" of relation \"%s\" does not exist",
1001  name, RelationGetRelationName(rel))));
1002  else
1003  ereport(ERROR,
1004  (errcode(ERRCODE_UNDEFINED_COLUMN),
1005  errmsg("column \"%s\" does not exist",
1006  name)));
1007  }
1008  /* Check for duplicates */
1009  if (list_member_int(attnums, attnum))
1010  ereport(ERROR,
1011  (errcode(ERRCODE_DUPLICATE_COLUMN),
1012  errmsg("column \"%s\" specified more than once",
1013  name)));
1014  attnums = lappend_int(attnums, attnum);
1015  }
1016  }
1017 
1018  return attnums;
1019 }
#define InvalidAttrNumber
Definition: attnum.h:23
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int i
Definition: isn.c:72
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 1276 of file copyto.c.

1277 {
1278  DR_copy *self = (DR_copy *) palloc(sizeof(DR_copy));
1279 
1280  self->pub.receiveSlot = copy_dest_receive;
1281  self->pub.rStartup = copy_dest_startup;
1282  self->pub.rShutdown = copy_dest_shutdown;
1283  self->pub.rDestroy = copy_dest_destroy;
1284  self->pub.mydest = DestCopyOut;
1285 
1286  self->cstate = NULL; /* will be set later */
1287  self->processed = 0;
1288 
1289  return (DestReceiver *) self;
1290 }
static bool copy_dest_receive(TupleTableSlot *slot, DestReceiver *self)
Definition: copyto.c:1239
static void copy_dest_destroy(DestReceiver *self)
Definition: copyto.c:1267
static void copy_dest_shutdown(DestReceiver *self)
Definition: copyto.c:1258
static void copy_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: copyto.c:1230

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:5268
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2253
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:1383
uint64 CopyFrom(CopyFromState cstate)
Definition: copyfrom.c:640
void EndCopyFrom(CopyFromState cstate)
Definition: copyfrom.c:1802
uint64 DoCopyTo(CopyToState cstate)
Definition: copyto.c:747
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:726
bool ExecCheckPermissions(List *rangeTable, List *rteperminfos, bool ereport_on_violation)
Definition: execMain.c:582
#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:760
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:424
Oid GetUserId(void)
Definition: miscinit.c:524
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:118
@ 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:297
List * fields
Definition: parsenodes.h:296
RTEPermissionInfo * p_perminfo
Definition: parse_node.h:308
Bitmapset * selectedCols
Definition: parsenodes.h:1293
AclMode requiredPerms
Definition: parsenodes.h:1291
Bitmapset * insertedCols
Definition: parsenodes.h:1294
bool inh
Definition: primnodes.h:85
ParseLoc stmt_location
Definition: parsenodes.h:2023
ParseLoc stmt_len
Definition: parsenodes.h:2024
Node * stmt
Definition: parsenodes.h:2022
bool rd_islocaltemp
Definition: rel.h:61
Node * val
Definition: parsenodes.h:521
ParseLoc location
Definition: parsenodes.h:522
List * indirection
Definition: parsenodes.h:520
char * name
Definition: parsenodes.h:519
#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 747 of file copyto.c.

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

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

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

727 {
728  if (cstate->queryDesc != NULL)
729  {
730  /* Close down the query and free resources. */
731  ExecutorFinish(cstate->queryDesc);
732  ExecutorEnd(cstate->queryDesc);
733  FreeQueryDesc(cstate->queryDesc);
735  }
736 
737  /* Clean up storage */
738  EndCopy(cstate);
739 }
static void EndCopy(CopyToState cstate)
Definition: copyto.c:314
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:466
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:406
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 845 of file copyfromparse.c.

847 {
848  TupleDesc tupDesc;
849  AttrNumber num_phys_attrs,
850  attr_count,
851  num_defaults = cstate->num_defaults;
852  FmgrInfo *in_functions = cstate->in_functions;
853  Oid *typioparams = cstate->typioparams;
854  int i;
855  int *defmap = cstate->defmap;
856  ExprState **defexprs = cstate->defexprs;
857 
858  tupDesc = RelationGetDescr(cstate->rel);
859  num_phys_attrs = tupDesc->natts;
860  attr_count = list_length(cstate->attnumlist);
861 
862  /* Initialize all values for row to NULL */
863  MemSet(values, 0, num_phys_attrs * sizeof(Datum));
864  MemSet(nulls, true, num_phys_attrs * sizeof(bool));
865  MemSet(cstate->defaults, false, num_phys_attrs * sizeof(bool));
866 
867  if (!cstate->opts.binary)
868  {
869  char **field_strings;
870  ListCell *cur;
871  int fldct;
872  int fieldno;
873  char *string;
874 
875  /* read raw fields in the next line */
876  if (!NextCopyFromRawFields(cstate, &field_strings, &fldct))
877  return false;
878 
879  /* check for overflowing fields */
880  if (attr_count > 0 && fldct > attr_count)
881  ereport(ERROR,
882  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
883  errmsg("extra data after last expected column")));
884 
885  fieldno = 0;
886 
887  /* Loop to read the user attributes on the line. */
888  foreach(cur, cstate->attnumlist)
889  {
890  int attnum = lfirst_int(cur);
891  int m = attnum - 1;
892  Form_pg_attribute att = TupleDescAttr(tupDesc, m);
893 
894  if (fieldno >= fldct)
895  ereport(ERROR,
896  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
897  errmsg("missing data for column \"%s\"",
898  NameStr(att->attname))));
899  string = field_strings[fieldno++];
900 
901  if (cstate->convert_select_flags &&
902  !cstate->convert_select_flags[m])
903  {
904  /* ignore input field, leaving column as NULL */
905  continue;
906  }
907 
908  if (cstate->opts.csv_mode)
909  {
910  if (string == NULL &&
911  cstate->opts.force_notnull_flags[m])
912  {
913  /*
914  * FORCE_NOT_NULL option is set and column is NULL -
915  * convert it to the NULL string.
916  */
917  string = cstate->opts.null_print;
918  }
919  else if (string != NULL && cstate->opts.force_null_flags[m]
920  && strcmp(string, cstate->opts.null_print) == 0)
921  {
922  /*
923  * FORCE_NULL option is set and column matches the NULL
924  * string. It must have been quoted, or otherwise the
925  * string would already have been set to NULL. Convert it
926  * to NULL as specified.
927  */
928  string = NULL;
929  }
930  }
931 
932  cstate->cur_attname = NameStr(att->attname);
933  cstate->cur_attval = string;
934 
935  if (string != NULL)
936  nulls[m] = false;
937 
938  if (cstate->defaults[m])
939  {
940  /*
941  * The caller must supply econtext and have switched into the
942  * per-tuple memory context in it.
943  */
944  Assert(econtext != NULL);
946 
947  values[m] = ExecEvalExpr(defexprs[m], econtext, &nulls[m]);
948  }
949 
950  /*
951  * If ON_ERROR is specified with IGNORE, skip rows with soft
952  * errors
953  */
954  else if (!InputFunctionCallSafe(&in_functions[m],
955  string,
956  typioparams[m],
957  att->atttypmod,
958  (Node *) cstate->escontext,
959  &values[m]))
960  {
962 
963  cstate->num_errors++;
964 
966  {
967  /*
968  * Since we emit line number and column info in the below
969  * notice message, we suppress error context information
970  * other than the relation name.
971  */
972  Assert(!cstate->relname_only);
973  cstate->relname_only = true;
974 
975  if (cstate->cur_attval)
976  {
977  char *attval;
978 
979  attval = CopyLimitPrintoutLength(cstate->cur_attval);
980  ereport(NOTICE,
981  errmsg("skipping row due to data type incompatibility at line %llu for column \"%s\": \"%s\"",
982  (unsigned long long) cstate->cur_lineno,
983  cstate->cur_attname,
984  attval));
985  pfree(attval);
986  }
987  else
988  ereport(NOTICE,
989  errmsg("skipping row due to data type incompatibility at line %llu for column \"%s\": null input",
990  (unsigned long long) cstate->cur_lineno,
991  cstate->cur_attname));
992 
993  /* reset relname_only */
994  cstate->relname_only = false;
995  }
996 
997  return true;
998  }
999 
1000  cstate->cur_attname = NULL;
1001  cstate->cur_attval = NULL;
1002  }
1003 
1004  Assert(fieldno == attr_count);
1005  }
1006  else
1007  {
1008  /* binary */
1009  int16 fld_count;
1010  ListCell *cur;
1011 
1012  cstate->cur_lineno++;
1013 
1014  if (!CopyGetInt16(cstate, &fld_count))
1015  {
1016  /* EOF detected (end of file, or protocol-level EOF) */
1017  return false;
1018  }
1019 
1020  if (fld_count == -1)
1021  {
1022  /*
1023  * Received EOF marker. Wait for the protocol-level EOF, and
1024  * complain if it doesn't come immediately. In COPY FROM STDIN,
1025  * this ensures that we correctly handle CopyFail, if client
1026  * chooses to send that now. When copying from file, we could
1027  * ignore the rest of the file like in text mode, but we choose to
1028  * be consistent with the COPY FROM STDIN case.
1029  */
1030  char dummy;
1031 
1032  if (CopyReadBinaryData(cstate, &dummy, 1) > 0)
1033  ereport(ERROR,
1034  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1035  errmsg("received copy data after EOF marker")));
1036  return false;
1037  }
1038 
1039  if (fld_count != attr_count)
1040  ereport(ERROR,
1041  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1042  errmsg("row field count is %d, expected %d",
1043  (int) fld_count, attr_count)));
1044 
1045  foreach(cur, cstate->attnumlist)
1046  {
1047  int attnum = lfirst_int(cur);
1048  int m = attnum - 1;
1049  Form_pg_attribute att = TupleDescAttr(tupDesc, m);
1050 
1051  cstate->cur_attname = NameStr(att->attname);
1052  values[m] = CopyReadBinaryAttribute(cstate,
1053  &in_functions[m],
1054  typioparams[m],
1055  att->atttypmod,
1056  &nulls[m]);
1057  cstate->cur_attname = NULL;
1058  }
1059  }
1060 
1061  /*
1062  * Now compute and insert any defaults available for the columns not
1063  * provided by the input data. Anything not processed here or above will
1064  * remain NULL.
1065  */
1066  for (i = 0; i < num_defaults; i++)
1067  {
1068  /*
1069  * The caller must supply econtext and have switched into the
1070  * per-tuple memory context in it.
1071  */
1072  Assert(econtext != NULL);
1074 
1075  values[defmap[i]] = ExecEvalExpr(defexprs[defmap[i]], econtext,
1076  &nulls[defmap[i]]);
1077  }
1078 
1079  return true;
1080 }
static Datum values[MAXATTR]
Definition: bootstrap.c:151
int16_t int16
Definition: c.h:480
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
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:266

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 745 of file copyfromparse.c.

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

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

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(), defGetCopyRejectLimitOption(), 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, CopyFormatOptions::quote, and CopyFormatOptions::reject_limit.

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