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

Go to the source code of this file.

Data Structures

struct  CopyFormatOptions
 

Typedefs

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

Enumerations

enum  CopyHeaderChoice { COPY_HEADER_FALSE = 0 , COPY_HEADER_TRUE , COPY_HEADER_MATCH }
 
enum  CopyOnErrorChoice { COPY_ON_ERROR_STOP = 0 , COPY_ON_ERROR_IGNORE }
 
enum  CopyLogVerbosityChoice { COPY_LOG_VERBOSITY_DEFAULT = 0 , COPY_LOG_VERBOSITY_VERBOSE }
 

Functions

void DoCopy (ParseState *pstate, const CopyStmt *stmt, int stmt_location, int stmt_len, uint64 *processed)
 
void ProcessCopyOptions (ParseState *pstate, CopyFormatOptions *opts_out, bool is_from, List *options)
 
CopyFromState BeginCopyFrom (ParseState *pstate, Relation rel, Node *whereClause, const char *filename, bool is_program, copy_data_source_cb data_source_cb, List *attnamelist, List *options)
 
void EndCopyFrom (CopyFromState cstate)
 
bool NextCopyFrom (CopyFromState cstate, ExprContext *econtext, Datum *values, bool *nulls)
 
bool NextCopyFromRawFields (CopyFromState cstate, char ***fields, int *nfields)
 
void CopyFromErrorCallback (void *arg)
 
char * CopyLimitPrintoutLength (const char *str)
 
uint64 CopyFrom (CopyFromState cstate)
 
DestReceiverCreateCopyDestReceiver (void)
 
CopyToState BeginCopyTo (ParseState *pstate, Relation rel, RawStmt *raw_query, Oid queryRelId, const char *filename, bool is_program, copy_data_dest_cb data_dest_cb, List *attnamelist, List *options)
 
void EndCopyTo (CopyToState cstate)
 
uint64 DoCopyTo (CopyToState cstate)
 
ListCopyGetAttnums (TupleDesc tupDesc, Relation rel, List *attnamelist)
 

Typedef Documentation

◆ copy_data_dest_cb

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

Definition at line 94 of file copy.h.

◆ copy_data_source_cb

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

Definition at line 93 of file copy.h.

◆ CopyFormatOptions

◆ CopyFromState

Definition at line 90 of file copy.h.

◆ CopyHeaderChoice

◆ CopyLogVerbosityChoice

◆ CopyOnErrorChoice

◆ CopyToState

typedef struct CopyToStateData* CopyToState

Definition at line 91 of file copy.h.

Enumeration Type Documentation

◆ CopyHeaderChoice

Enumerator
COPY_HEADER_FALSE 
COPY_HEADER_TRUE 
COPY_HEADER_MATCH 

Definition at line 26 of file copy.h.

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

◆ CopyLogVerbosityChoice

Enumerator
COPY_LOG_VERBOSITY_DEFAULT 
COPY_LOG_VERBOSITY_VERBOSE 

Definition at line 46 of file copy.h.

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

◆ CopyOnErrorChoice

Enumerator
COPY_ON_ERROR_STOP 
COPY_ON_ERROR_IGNORE 

Definition at line 37 of file copy.h.

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

Function Documentation

◆ BeginCopyFrom()

CopyFromState BeginCopyFrom ( ParseState pstate,
Relation  rel,
Node whereClause,
const char *  filename,
bool  is_program,
copy_data_source_cb  data_source_cb,
List attnamelist,
List options 
)

Definition at line 1368 of file copyfrom.c.

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

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

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

◆ BeginCopyTo()

CopyToState BeginCopyTo ( ParseState pstate,
Relation  rel,
RawStmt raw_query,
Oid  queryRelId,
const char *  filename,
bool  is_program,
copy_data_dest_cb  data_dest_cb,
List attnamelist,
List options 
)

Definition at line 350 of file copyto.c.

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

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

Referenced by DoCopy(), and test_copy_to_callback().

◆ CopyFrom()

uint64 CopyFrom ( CopyFromState  cstate)

Definition at line 628 of file copyfrom.c.

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

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

Referenced by copy_table(), and DoCopy().

◆ CopyFromErrorCallback()

void CopyFromErrorCallback ( void *  arg)

Definition at line 112 of file copyfrom.c.

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

859 {
860  List *attnums = NIL;
861 
862  if (attnamelist == NIL)
863  {
864  /* Generate default column list */
865  int attr_count = tupDesc->natts;
866  int i;
867 
868  for (i = 0; i < attr_count; i++)
869  {
870  if (TupleDescAttr(tupDesc, i)->attisdropped)
871  continue;
872  if (TupleDescAttr(tupDesc, i)->attgenerated)
873  continue;
874  attnums = lappend_int(attnums, i + 1);
875  }
876  }
877  else
878  {
879  /* Validate the user-supplied list and extract attnums */
880  ListCell *l;
881 
882  foreach(l, attnamelist)
883  {
884  char *name = strVal(lfirst(l));
885  int attnum;
886  int i;
887 
888  /* Lookup column name */
890  for (i = 0; i < tupDesc->natts; i++)
891  {
892  Form_pg_attribute att = TupleDescAttr(tupDesc, i);
893 
894  if (att->attisdropped)
895  continue;
896  if (namestrcmp(&(att->attname), name) == 0)
897  {
898  if (att->attgenerated)
899  ereport(ERROR,
900  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
901  errmsg("column \"%s\" is a generated column",
902  name),
903  errdetail("Generated columns cannot be used in COPY.")));
904  attnum = att->attnum;
905  break;
906  }
907  }
908  if (attnum == InvalidAttrNumber)
909  {
910  if (rel != NULL)
911  ereport(ERROR,
912  (errcode(ERRCODE_UNDEFINED_COLUMN),
913  errmsg("column \"%s\" of relation \"%s\" does not exist",
914  name, RelationGetRelationName(rel))));
915  else
916  ereport(ERROR,
917  (errcode(ERRCODE_UNDEFINED_COLUMN),
918  errmsg("column \"%s\" does not exist",
919  name)));
920  }
921  /* Check for duplicates */
922  if (list_member_int(attnums, attnum))
923  ereport(ERROR,
924  (errcode(ERRCODE_DUPLICATE_COLUMN),
925  errmsg("column \"%s\" specified more than once",
926  name)));
927  attnums = lappend_int(attnums, attnum);
928  }
929  }
930 
931  return attnums;
932 }
#define InvalidAttrNumber
Definition: attnum.h:23
int errdetail(const char *fmt,...)
Definition: elog.c:1205
int i
Definition: isn.c:73
List * lappend_int(List *list, int datum)
Definition: list.c:357
int namestrcmp(Name name, const char *str)
Definition: name.c:247
#define lfirst(lc)
Definition: pg_list.h:172
#define strVal(v)
Definition: value.h:82
const char * name

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

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

◆ CopyLimitPrintoutLength()

char* CopyLimitPrintoutLength ( const char *  str)

Definition at line 191 of file copyfrom.c.

192 {
193 #define MAX_COPY_DATA_DISPLAY 100
194 
195  int slen = strlen(str);
196  int len;
197  char *res;
198 
199  /* Fast path if definitely okay */
200  if (slen <= MAX_COPY_DATA_DISPLAY)
201  return pstrdup(str);
202 
203  /* Apply encoding-dependent truncation */
205 
206  /*
207  * Truncate, and add "..." to show we truncated the input.
208  */
209  res = (char *) palloc(len + 4);
210  memcpy(res, str, len);
211  strcpy(res + len, "...");
212 
213  return res;
214 }
#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 1267 of file copyto.c.

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

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:5128
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2254
CopyFromState BeginCopyFrom(ParseState *pstate, Relation rel, Node *whereClause, const char *filename, bool is_program, copy_data_source_cb data_source_cb, List *attnamelist, List *options)
Definition: copyfrom.c:1368
uint64 CopyFrom(CopyFromState cstate)
Definition: copyfrom.c:628
void EndCopyFrom(CopyFromState cstate)
Definition: copyfrom.c:1785
uint64 DoCopyTo(CopyToState cstate)
Definition: copyto.c:742
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:721
bool ExecCheckPermissions(List *rangeTable, List *rteperminfos, bool ereport_on_violation)
Definition: execMain.c:579
#define stmt
Definition: indent_codes.h:59
List * lappend(List *list, void *datum)
Definition: list.c:339
int LOCKMODE
Definition: lockdefs.h:26
#define NoLock
Definition: lockdefs.h:34
#define AccessShareLock
Definition: lockdefs.h:36
#define RowExclusiveLock
Definition: lockdefs.h:38
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3366
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:737
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:424
Oid GetUserId(void)
Definition: miscinit.c:514
Node * coerce_to_boolean(ParseState *pstate, Node *node, const char *constructName)
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:121
@ EXPR_KIND_COPY_WHERE
Definition: parse_node.h:82
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
#define ACL_INSERT
Definition: parsenodes.h:76
#define ACL_SELECT
Definition: parsenodes.h:77
#define list_make1(x1)
Definition: pg_list.h:212
Expr * canonicalize_qual(Expr *qual, bool is_check)
Definition: prepqual.c:293
#define RelationGetNamespace(relation)
Definition: rel.h:546
int check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
Definition: rls.c:52
@ RLS_ENABLED
Definition: rls.h:45
ParseLoc location
Definition: parsenodes.h:295
List * fields
Definition: parsenodes.h:294
RTEPermissionInfo * p_perminfo
Definition: parse_node.h:289
Bitmapset * selectedCols
Definition: parsenodes.h:1297
AclMode requiredPerms
Definition: parsenodes.h:1295
Bitmapset * insertedCols
Definition: parsenodes.h:1298
bool inh
Definition: primnodes.h:85
ParseLoc stmt_location
Definition: parsenodes.h:2028
ParseLoc stmt_len
Definition: parsenodes.h:2029
Node * stmt
Definition: parsenodes.h:2027
bool rd_islocaltemp
Definition: rel.h:61
Node * val
Definition: parsenodes.h:519
ParseLoc location
Definition: parsenodes.h:520
List * indirection
Definition: parsenodes.h:518
char * name
Definition: parsenodes.h:517
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: table.c:83
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:404
#define select(n, r, w, e, timeout)
Definition: win32_port.h:495
bool XactReadOnly
Definition: xact.c:80

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

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

1786 {
1787  /* No COPY FROM related resources except memory. */
1788  if (cstate->is_program)
1789  {
1790  ClosePipeFromProgram(cstate);
1791  }
1792  else
1793  {
1794  if (cstate->filename != NULL && FreeFile(cstate->copy_file))
1795  ereport(ERROR,
1797  errmsg("could not close file \"%s\": %m",
1798  cstate->filename)));
1799  }
1800 
1802 
1804  pfree(cstate);
1805 }
void pgstat_progress_end_command(void)
static void ClosePipeFromProgram(CopyFromState cstate)
Definition: copyfrom.c:1811
int FreeFile(FILE *file)
Definition: fd.c:2781

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

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

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

Referenced by DoCopy(), and test_copy_to_callback().

◆ NextCopyFrom()

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

Definition at line 854 of file copyfromparse.c.

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

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

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

◆ NextCopyFromRawFields()

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

Definition at line 754 of file copyfromparse.c.

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

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

Referenced by NextCopyFrom().

◆ ProcessCopyOptions()

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

Definition at line 459 of file copy.c.

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

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

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