PostgreSQL Source Code  git master
copy.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <unistd.h>
#include <sys/stat.h>
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/sysattr.h"
#include "access/tableam.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/dependency.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_type.h"
#include "commands/copy.h"
#include "commands/defrem.h"
#include "commands/trigger.h"
#include "executor/execPartition.h"
#include "executor/executor.h"
#include "executor/nodeModifyTable.h"
#include "executor/tuptable.h"
#include "foreign/fdwapi.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "optimizer/optimizer.h"
#include "parser/parse_coerce.h"
#include "parser/parse_collate.h"
#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
#include "port/pg_bswap.h"
#include "rewrite/rewriteHandler.h"
#include "storage/fd.h"
#include "tcop/tcopprot.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/partcache.h"
#include "utils/portal.h"
#include "utils/rel.h"
#include "utils/rls.h"
#include "utils/snapmgr.h"
Include dependency graph for copy.c:

Go to the source code of this file.

Data Structures

struct  CopyStateData
 
struct  DR_copy
 
struct  CopyMultiInsertBuffer
 
struct  CopyMultiInsertInfo
 

Macros

#define ISOCTAL(c)   (((c) >= '0') && ((c) <= '7'))
 
#define OCTVALUE(c)   ((c) - '0')
 
#define RAW_BUF_SIZE   65536 /* we palloc RAW_BUF_SIZE+1 bytes */
 
#define MAX_BUFFERED_TUPLES   1000
 
#define MAX_BUFFERED_BYTES   65535
 
#define MAX_PARTITION_BUFFERS   32
 
#define IF_NEED_REFILL_AND_NOT_EOF_CONTINUE(extralen)
 
#define IF_NEED_REFILL_AND_EOF_BREAK(extralen)
 
#define REFILL_LINEBUF
 
#define NO_END_OF_COPY_GOTO
 
#define MAX_COPY_DATA_DISPLAY   100
 
#define DUMPSOFAR()
 

Typedefs

typedef enum CopyDest CopyDest
 
typedef enum EolType EolType
 
typedef enum CopyInsertMethod CopyInsertMethod
 
typedef struct CopyStateData CopyStateData
 
typedef struct CopyMultiInsertBuffer CopyMultiInsertBuffer
 
typedef struct CopyMultiInsertInfo CopyMultiInsertInfo
 

Enumerations

enum  CopyDest { COPY_FILE, COPY_OLD_FE, COPY_NEW_FE, COPY_CALLBACK }
 
enum  EolType { EOL_UNKNOWN, EOL_NL, EOL_CR, EOL_CRNL }
 
enum  CopyInsertMethod { CIM_SINGLE, CIM_MULTI, CIM_MULTI_CONDITIONAL }
 

Functions

static CopyState BeginCopy (ParseState *pstate, bool is_from, Relation rel, RawStmt *raw_query, Oid queryRelId, List *attnamelist, List *options)
 
static void EndCopy (CopyState cstate)
 
static void ClosePipeToProgram (CopyState cstate)
 
static CopyState BeginCopyTo (ParseState *pstate, Relation rel, RawStmt *query, Oid queryRelId, const char *filename, bool is_program, List *attnamelist, List *options)
 
static void EndCopyTo (CopyState cstate)
 
static uint64 DoCopyTo (CopyState cstate)
 
static uint64 CopyTo (CopyState cstate)
 
static void CopyOneRowTo (CopyState cstate, TupleTableSlot *slot)
 
static bool CopyReadLine (CopyState cstate)
 
static bool CopyReadLineText (CopyState cstate)
 
static int CopyReadAttributesText (CopyState cstate)
 
static int CopyReadAttributesCSV (CopyState cstate)
 
static Datum CopyReadBinaryAttribute (CopyState cstate, FmgrInfo *flinfo, Oid typioparam, int32 typmod, bool *isnull)
 
static void CopyAttributeOutText (CopyState cstate, char *string)
 
static void CopyAttributeOutCSV (CopyState cstate, char *string, bool use_quote, bool single_attr)
 
static ListCopyGetAttnums (TupleDesc tupDesc, Relation rel, List *attnamelist)
 
static char * limit_printout_length (const char *str)
 
static void SendCopyBegin (CopyState cstate)
 
static void ReceiveCopyBegin (CopyState cstate)
 
static void SendCopyEnd (CopyState cstate)
 
static void CopySendData (CopyState cstate, const void *databuf, int datasize)
 
static void CopySendString (CopyState cstate, const char *str)
 
static void CopySendChar (CopyState cstate, char c)
 
static void CopySendEndOfRow (CopyState cstate)
 
static int CopyGetData (CopyState cstate, void *databuf, int minread, int maxread)
 
static void CopySendInt32 (CopyState cstate, int32 val)
 
static bool CopyGetInt32 (CopyState cstate, int32 *val)
 
static void CopySendInt16 (CopyState cstate, int16 val)
 
static bool CopyGetInt16 (CopyState cstate, int16 *val)
 
static bool CopyLoadRawBuf (CopyState cstate)
 
void DoCopy (ParseState *pstate, const CopyStmt *stmt, int stmt_location, int stmt_len, uint64 *processed)
 
void ProcessCopyOptions (ParseState *pstate, CopyState cstate, bool is_from, List *options)
 
void CopyFromErrorCallback (void *arg)
 
static CopyMultiInsertBufferCopyMultiInsertBufferInit (ResultRelInfo *rri)
 
static void CopyMultiInsertInfoSetupBuffer (CopyMultiInsertInfo *miinfo, ResultRelInfo *rri)
 
static void CopyMultiInsertInfoInit (CopyMultiInsertInfo *miinfo, ResultRelInfo *rri, CopyState cstate, EState *estate, CommandId mycid, int ti_options)
 
static bool CopyMultiInsertInfoIsFull (CopyMultiInsertInfo *miinfo)
 
static bool CopyMultiInsertInfoIsEmpty (CopyMultiInsertInfo *miinfo)
 
static void CopyMultiInsertBufferFlush (CopyMultiInsertInfo *miinfo, CopyMultiInsertBuffer *buffer)
 
static void CopyMultiInsertBufferCleanup (CopyMultiInsertInfo *miinfo, CopyMultiInsertBuffer *buffer)
 
static void CopyMultiInsertInfoFlush (CopyMultiInsertInfo *miinfo, ResultRelInfo *curr_rri)
 
static void CopyMultiInsertInfoCleanup (CopyMultiInsertInfo *miinfo)
 
static TupleTableSlotCopyMultiInsertInfoNextFreeSlot (CopyMultiInsertInfo *miinfo, ResultRelInfo *rri)
 
static void CopyMultiInsertInfoStore (CopyMultiInsertInfo *miinfo, ResultRelInfo *rri, TupleTableSlot *slot, int tuplen, uint64 lineno)
 
uint64 CopyFrom (CopyState cstate)
 
CopyState BeginCopyFrom (ParseState *pstate, Relation rel, const char *filename, bool is_program, copy_data_source_cb data_source_cb, List *attnamelist, List *options)
 
bool NextCopyFromRawFields (CopyState cstate, char ***fields, int *nfields)
 
bool NextCopyFrom (CopyState cstate, ExprContext *econtext, Datum *values, bool *nulls)
 
void EndCopyFrom (CopyState cstate)
 
static int GetDecimalFromHex (char hex)
 
static void copy_dest_startup (DestReceiver *self, int operation, TupleDesc typeinfo)
 
static bool copy_dest_receive (TupleTableSlot *slot, DestReceiver *self)
 
static void copy_dest_shutdown (DestReceiver *self)
 
static void copy_dest_destroy (DestReceiver *self)
 
DestReceiverCreateCopyDestReceiver (void)
 

Variables

static const char BinarySignature [11] = "PGCOPY\n\377\r\n\0"
 

Macro Definition Documentation

◆ DUMPSOFAR

#define DUMPSOFAR ( )
Value:
do { \
if (ptr > start) \
CopySendData(cstate, start, ptr - start); \
} while (0)

Definition at line 4760 of file copy.c.

Referenced by CopyAttributeOutCSV(), and CopyAttributeOutText().

◆ IF_NEED_REFILL_AND_EOF_BREAK

#define IF_NEED_REFILL_AND_EOF_BREAK (   extralen)
Value:
if (1) \
{ \
if (raw_buf_ptr + (extralen) >= copy_buf_len && hit_eof) \
{ \
if (extralen) \
raw_buf_ptr = copy_buf_len; /* consume the partial character */ \
/* backslash just before EOF, treat as data char */ \
result = true; \
break; \
} \
} else ((void) 0)

Definition at line 313 of file copy.c.

Referenced by CopyReadLineText().

◆ IF_NEED_REFILL_AND_NOT_EOF_CONTINUE

#define IF_NEED_REFILL_AND_NOT_EOF_CONTINUE (   extralen)
Value:
if (1) \
{ \
if (raw_buf_ptr + (extralen) >= copy_buf_len && !hit_eof) \
{ \
raw_buf_ptr = prev_raw_ptr; /* undo fetch */ \
need_data = true; \
continue; \
} \
} else ((void) 0)

Definition at line 301 of file copy.c.

Referenced by CopyReadLineText().

◆ ISOCTAL

#define ISOCTAL (   c)    (((c) >= '0') && ((c) <= '7'))

Definition at line 62 of file copy.c.

Referenced by CopyReadAttributesText().

◆ MAX_BUFFERED_BYTES

#define MAX_BUFFERED_BYTES   65535

Definition at line 252 of file copy.c.

Referenced by CopyMultiInsertInfoIsFull().

◆ MAX_BUFFERED_TUPLES

#define MAX_BUFFERED_TUPLES   1000

◆ MAX_COPY_DATA_DISPLAY

#define MAX_COPY_DATA_DISPLAY   100

Referenced by limit_printout_length().

◆ MAX_PARTITION_BUFFERS

#define MAX_PARTITION_BUFFERS   32

Definition at line 255 of file copy.c.

Referenced by CopyMultiInsertInfoFlush().

◆ NO_END_OF_COPY_GOTO

#define NO_END_OF_COPY_GOTO
Value:
if (1) \
{ \
raw_buf_ptr = prev_raw_ptr + 1; \
goto not_end_of_copy; \
} else ((void) 0)

Definition at line 343 of file copy.c.

Referenced by CopyReadLineText().

◆ OCTVALUE

#define OCTVALUE (   c)    ((c) - '0')

Definition at line 63 of file copy.c.

Referenced by CopyReadAttributesText().

◆ RAW_BUF_SIZE

#define RAW_BUF_SIZE   65536 /* we palloc RAW_BUF_SIZE+1 bytes */

Definition at line 222 of file copy.c.

Referenced by BeginCopyFrom(), and CopyLoadRawBuf().

◆ REFILL_LINEBUF

#define REFILL_LINEBUF
Value:
if (1) \
{ \
if (raw_buf_ptr > cstate->raw_buf_index) \
{ \
appendBinaryStringInfo(&cstate->line_buf, \
cstate->raw_buf + cstate->raw_buf_index, \
raw_buf_ptr - cstate->raw_buf_index); \
cstate->raw_buf_index = raw_buf_ptr; \
} \
} else ((void) 0)

Definition at line 330 of file copy.c.

Referenced by CopyReadLineText().

Typedef Documentation

◆ CopyDest

typedef enum CopyDest CopyDest

◆ CopyInsertMethod

◆ CopyMultiInsertBuffer

◆ CopyMultiInsertInfo

◆ CopyStateData

typedef struct CopyStateData CopyStateData

◆ EolType

typedef enum EolType EolType

Enumeration Type Documentation

◆ CopyDest

enum CopyDest
Enumerator
COPY_FILE 
COPY_OLD_FE 
COPY_NEW_FE 
COPY_CALLBACK 

Definition at line 69 of file copy.c.

70 {
71  COPY_FILE, /* to/from file (or a piped program) */
72  COPY_OLD_FE, /* to/from frontend (2.0 protocol) */
73  COPY_NEW_FE, /* to/from frontend (3.0 protocol) */
74  COPY_CALLBACK /* to/from callback function */
75 } CopyDest;
Definition: copy.c:71
CopyDest
Definition: copy.c:69

◆ CopyInsertMethod

Enumerator
CIM_SINGLE 
CIM_MULTI 
CIM_MULTI_CONDITIONAL 

Definition at line 91 of file copy.c.

92 {
93  CIM_SINGLE, /* use table_tuple_insert or fdw routine */
94  CIM_MULTI, /* always use table_multi_insert */
95  CIM_MULTI_CONDITIONAL /* use table_multi_insert only if valid */
Definition: copy.c:94
CopyInsertMethod
Definition: copy.c:91

◆ EolType

enum EolType
Enumerator
EOL_UNKNOWN 
EOL_NL 
EOL_CR 
EOL_CRNL 

Definition at line 80 of file copy.c.

81 {
83  EOL_NL,
84  EOL_CR,
85  EOL_CRNL
86 } EolType;
Definition: copy.c:83
EolType
Definition: copy.c:80
Definition: copy.c:84
Definition: copy.c:85

Function Documentation

◆ BeginCopy()

static CopyState BeginCopy ( ParseState pstate,
bool  is_from,
Relation  rel,
RawStmt raw_query,
Oid  queryRelId,
List attnamelist,
List options 
)
static

Definition at line 1456 of file copy.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, attnum, CopyStateData::attnumlist, CMD_DELETE, CMD_INSERT, CMD_SELECT, CMD_UPDATE, Query::commandType, CopyStateData::convert_select, CopyStateData::convert_select_flags, CopyStateData::convert_selectively, CopyStateData::copy_dest, COPY_FILE, CopyStateData::copycontext, CopyGetAttnums(), copyObject, CreateDestReceiver(), CreateQueryDesc(), cur, CurrentMemoryContext, CURSOR_OPT_PARALLEL_OK, generate_unaccent_rules::dest, DestCopyOut, CopyStateData::encoding_embeds_ascii, ereport, errcode(), errmsg(), errmsg_internal(), ERROR, ExecutorStart(), CopyStateData::file_encoding, CopyStateData::force_notnull, CopyStateData::force_notnull_flags, CopyStateData::force_null, CopyStateData::force_null_flags, CopyStateData::force_quote, CopyStateData::force_quote_all, CopyStateData::force_quote_flags, GetActiveSnapshot(), GetDatabaseEncoding(), i, InvalidOid, InvalidSnapshot, IsA, lfirst_int, lfirst_node, linitial_node, list_length(), list_member_int(), list_member_oid(), MemoryContextSwitchTo(), NameStr, TupleDescData::natts, CopyStateData::need_transcoding, NIL, ParseState::p_sourcetext, palloc0(), pg_analyze_and_rewrite(), pg_database_encoding_max_length(), PG_ENCODING_IS_CLIENT_ONLY, pg_get_client_encoding(), pg_plan_query(), ProcessCopyOptions(), PushCopiedSnapshot(), QSRC_NON_INSTEAD_RULE, QSRC_QUAL_INSTEAD_RULE, CopyStateData::queryDesc, Query::querySource, CopyStateData::rel, RelationGetDescr, PlannedStmt::relationOids, Query::returningList, QueryDesc::tupDesc, TupleDescAttr, UpdateActiveSnapshotCommandId(), and Query::utilityStmt.

Referenced by BeginCopyFrom(), and BeginCopyTo().

1463 {
1464  CopyState cstate;
1465  TupleDesc tupDesc;
1466  int num_phys_attrs;
1467  MemoryContext oldcontext;
1468 
1469  /* Allocate workspace and zero all fields */
1470  cstate = (CopyStateData *) palloc0(sizeof(CopyStateData));
1471 
1472  /*
1473  * We allocate everything used by a cstate in a new memory context. This
1474  * avoids memory leaks during repeated use of COPY in a query.
1475  */
1477  "COPY",
1479 
1480  oldcontext = MemoryContextSwitchTo(cstate->copycontext);
1481 
1482  /* Extract options from the statement node tree */
1483  ProcessCopyOptions(pstate, cstate, is_from, options);
1484 
1485  /* Process the source/target relation or query */
1486  if (rel)
1487  {
1488  Assert(!raw_query);
1489 
1490  cstate->rel = rel;
1491 
1492  tupDesc = RelationGetDescr(cstate->rel);
1493  }
1494  else
1495  {
1496  List *rewritten;
1497  Query *query;
1498  PlannedStmt *plan;
1499  DestReceiver *dest;
1500 
1501  Assert(!is_from);
1502  cstate->rel = NULL;
1503 
1504  /*
1505  * Run parse analysis and rewrite. Note this also acquires sufficient
1506  * locks on the source table(s).
1507  *
1508  * Because the parser and planner tend to scribble on their input, we
1509  * make a preliminary copy of the source querytree. This prevents
1510  * problems in the case that the COPY is in a portal or plpgsql
1511  * function and is executed repeatedly. (See also the same hack in
1512  * DECLARE CURSOR and PREPARE.) XXX FIXME someday.
1513  */
1514  rewritten = pg_analyze_and_rewrite(copyObject(raw_query),
1515  pstate->p_sourcetext, NULL, 0,
1516  NULL);
1517 
1518  /* check that we got back something we can work with */
1519  if (rewritten == NIL)
1520  {
1521  ereport(ERROR,
1522  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1523  errmsg("DO INSTEAD NOTHING rules are not supported for COPY")));
1524  }
1525  else if (list_length(rewritten) > 1)
1526  {
1527  ListCell *lc;
1528 
1529  /* examine queries to determine which error message to issue */
1530  foreach(lc, rewritten)
1531  {
1532  Query *q = lfirst_node(Query, lc);
1533 
1535  ereport(ERROR,
1536  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1537  errmsg("conditional DO INSTEAD rules are not supported for COPY")));
1539  ereport(ERROR,
1540  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1541  errmsg("DO ALSO rules are not supported for the COPY")));
1542  }
1543 
1544  ereport(ERROR,
1545  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1546  errmsg("multi-statement DO INSTEAD rules are not supported for COPY")));
1547  }
1548 
1549  query = linitial_node(Query, rewritten);
1550 
1551  /* The grammar allows SELECT INTO, but we don't support that */
1552  if (query->utilityStmt != NULL &&
1554  ereport(ERROR,
1555  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1556  errmsg("COPY (SELECT INTO) is not supported")));
1557 
1558  Assert(query->utilityStmt == NULL);
1559 
1560  /*
1561  * Similarly the grammar doesn't enforce the presence of a RETURNING
1562  * clause, but this is required here.
1563  */
1564  if (query->commandType != CMD_SELECT &&
1565  query->returningList == NIL)
1566  {
1567  Assert(query->commandType == CMD_INSERT ||
1568  query->commandType == CMD_UPDATE ||
1569  query->commandType == CMD_DELETE);
1570 
1571  ereport(ERROR,
1572  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1573  errmsg("COPY query must have a RETURNING clause")));
1574  }
1575 
1576  /* plan the query */
1577  plan = pg_plan_query(query, pstate->p_sourcetext,
1578  CURSOR_OPT_PARALLEL_OK, NULL);
1579 
1580  /*
1581  * With row level security and a user using "COPY relation TO", we
1582  * have to convert the "COPY relation TO" to a query-based COPY (eg:
1583  * "COPY (SELECT * FROM relation) TO"), to allow the rewriter to add
1584  * in any RLS clauses.
1585  *
1586  * When this happens, we are passed in the relid of the originally
1587  * found relation (which we have locked). As the planner will look up
1588  * the relation again, we double-check here to make sure it found the
1589  * same one that we have locked.
1590  */
1591  if (queryRelId != InvalidOid)
1592  {
1593  /*
1594  * Note that with RLS involved there may be multiple relations,
1595  * and while the one we need is almost certainly first, we don't
1596  * make any guarantees of that in the planner, so check the whole
1597  * list and make sure we find the original relation.
1598  */
1599  if (!list_member_oid(plan->relationOids, queryRelId))
1600  ereport(ERROR,
1601  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1602  errmsg("relation referenced by COPY statement has changed")));
1603  }
1604 
1605  /*
1606  * Use a snapshot with an updated command ID to ensure this query sees
1607  * results of any previously executed queries.
1608  */
1611 
1612  /* Create dest receiver for COPY OUT */
1614  ((DR_copy *) dest)->cstate = cstate;
1615 
1616  /* Create a QueryDesc requesting no output */
1617  cstate->queryDesc = CreateQueryDesc(plan, pstate->p_sourcetext,
1620  dest, NULL, NULL, 0);
1621 
1622  /*
1623  * Call ExecutorStart to prepare the plan for execution.
1624  *
1625  * ExecutorStart computes a result tupdesc for us
1626  */
1627  ExecutorStart(cstate->queryDesc, 0);
1628 
1629  tupDesc = cstate->queryDesc->tupDesc;
1630  }
1631 
1632  /* Generate or convert list of attributes to process */
1633  cstate->attnumlist = CopyGetAttnums(tupDesc, cstate->rel, attnamelist);
1634 
1635  num_phys_attrs = tupDesc->natts;
1636 
1637  /* Convert FORCE_QUOTE name list to per-column flags, check validity */
1638  cstate->force_quote_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1639  if (cstate->force_quote_all)
1640  {
1641  int i;
1642 
1643  for (i = 0; i < num_phys_attrs; i++)
1644  cstate->force_quote_flags[i] = true;
1645  }
1646  else if (cstate->force_quote)
1647  {
1648  List *attnums;
1649  ListCell *cur;
1650 
1651  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->force_quote);
1652 
1653  foreach(cur, attnums)
1654  {
1655  int attnum = lfirst_int(cur);
1656  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1657 
1658  if (!list_member_int(cstate->attnumlist, attnum))
1659  ereport(ERROR,
1660  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1661  errmsg("FORCE_QUOTE column \"%s\" not referenced by COPY",
1662  NameStr(attr->attname))));
1663  cstate->force_quote_flags[attnum - 1] = true;
1664  }
1665  }
1666 
1667  /* Convert FORCE_NOT_NULL name list to per-column flags, check validity */
1668  cstate->force_notnull_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1669  if (cstate->force_notnull)
1670  {
1671  List *attnums;
1672  ListCell *cur;
1673 
1674  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->force_notnull);
1675 
1676  foreach(cur, attnums)
1677  {
1678  int attnum = lfirst_int(cur);
1679  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1680 
1681  if (!list_member_int(cstate->attnumlist, attnum))
1682  ereport(ERROR,
1683  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1684  errmsg("FORCE_NOT_NULL column \"%s\" not referenced by COPY",
1685  NameStr(attr->attname))));
1686  cstate->force_notnull_flags[attnum - 1] = true;
1687  }
1688  }
1689 
1690  /* Convert FORCE_NULL name list to per-column flags, check validity */
1691  cstate->force_null_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1692  if (cstate->force_null)
1693  {
1694  List *attnums;
1695  ListCell *cur;
1696 
1697  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->force_null);
1698 
1699  foreach(cur, attnums)
1700  {
1701  int attnum = lfirst_int(cur);
1702  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1703 
1704  if (!list_member_int(cstate->attnumlist, attnum))
1705  ereport(ERROR,
1706  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1707  errmsg("FORCE_NULL column \"%s\" not referenced by COPY",
1708  NameStr(attr->attname))));
1709  cstate->force_null_flags[attnum - 1] = true;
1710  }
1711  }
1712 
1713  /* Convert convert_selectively name list to per-column flags */
1714  if (cstate->convert_selectively)
1715  {
1716  List *attnums;
1717  ListCell *cur;
1718 
1719  cstate->convert_select_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1720 
1721  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->convert_select);
1722 
1723  foreach(cur, attnums)
1724  {
1725  int attnum = lfirst_int(cur);
1726  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1727 
1728  if (!list_member_int(cstate->attnumlist, attnum))
1729  ereport(ERROR,
1730  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1731  errmsg_internal("selected column \"%s\" not referenced by COPY",
1732  NameStr(attr->attname))));
1733  cstate->convert_select_flags[attnum - 1] = true;
1734  }
1735  }
1736 
1737  /* Use client encoding when ENCODING option is not specified. */
1738  if (cstate->file_encoding < 0)
1740 
1741  /*
1742  * Set up encoding conversion info. Even if the file and server encodings
1743  * are the same, we must apply pg_any_to_server() to validate data in
1744  * multibyte encodings.
1745  */
1746  cstate->need_transcoding =
1747  (cstate->file_encoding != GetDatabaseEncoding() ||
1749  /* See Multibyte encoding comment above */
1751 
1752  cstate->copy_dest = COPY_FILE; /* default */
1753 
1754  MemoryContextSwitchTo(oldcontext);
1755 
1756  return cstate;
1757 }
#define NIL
Definition: pg_list.h:65
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:783
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
#define AllocSetContextCreate
Definition: memutils.h:170
#define RelationGetDescr(relation)
Definition: rel.h:482
bool need_transcoding
Definition: copy.c:126
List * attnumlist
Definition: copy.c:132
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
List * relationOids
Definition: plannodes.h:86
Definition: copy.c:229
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:143
void ProcessCopyOptions(ParseState *pstate, CopyState cstate, bool is_from, List *options)
Definition: copy.c:1105
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:841
struct cursor * cur
Definition: ecpg.c:28
int errcode(int sqlerrcode)
Definition: elog.c:610
bool * force_quote_flags
Definition: copy.c:148
List * pg_analyze_and_rewrite(RawStmt *parsetree, const char *query_string, Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
Definition: postgres.c:676
Node * utilityStmt
Definition: parsenodes.h:120
#define linitial_node(type, l)
Definition: pg_list.h:198
bool * force_null_flags
Definition: copy.c:152
bool * convert_select_flags
Definition: copy.c:155
CopyDest copy_dest
Definition: copy.c:117
Definition: copy.c:71
Relation rel
Definition: copy.c:130
MemoryContext copycontext
Definition: copy.c:167
#define ERROR
Definition: elog.h:43
#define lfirst_int(lc)
Definition: pg_list.h:191
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:771
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 ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
#define lfirst_node(type, lc)
Definition: pg_list.h:193
QueryDesc * queryDesc
Definition: copy.c:131
bool list_member_int(const List *list, int datum)
Definition: list.c:654
bool encoding_embeds_ascii
Definition: copy.c:127
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:113
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
const char * p_sourcetext
Definition: parse_node.h:179
List * returningList
Definition: parsenodes.h:146
List * force_null
Definition: copy.c:151
int file_encoding
Definition: copy.c:125
static List * CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
Definition: copy.c:5016
TupleDesc tupDesc
Definition: execdesc.h:47
#define InvalidSnapshot
Definition: snapshot.h:123
void * palloc0(Size size)
Definition: mcxt.c:980
int GetDatabaseEncoding(void)
Definition: mbutils.c:1151
int pg_get_client_encoding(void)
Definition: mbutils.c:336
#define InvalidOid
Definition: postgres_ext.h:36
int16 attnum
Definition: pg_attribute.h:79
#define ereport(elevel,...)
Definition: elog.h:144
bool * force_notnull_flags
Definition: copy.c:150
CmdType commandType
Definition: parsenodes.h:112
List * force_notnull
Definition: copy.c:149
int errmsg_internal(const char *fmt,...)
Definition: elog.c:911
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:674
QuerySource querySource
Definition: parsenodes.h:114
#define Assert(condition)
Definition: c.h:738
List * convert_select
Definition: copy.c:154
static int list_length(const List *l)
Definition: pg_list.h:169
int pg_database_encoding_max_length(void)
Definition: mbutils.c:1436
bool force_quote_all
Definition: copy.c:147
#define PG_ENCODING_IS_CLIENT_ONLY(_enc)
Definition: pg_wchar.h:298
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2715
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
#define NameStr(name)
Definition: c.h:615
PlannedStmt * pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, ParamListInfo boundParams)
Definition: postgres.c:857
#define copyObject(obj)
Definition: nodes.h:645
Definition: pg_list.h:50
List * force_quote
Definition: copy.c:146
bool convert_selectively
Definition: copy.c:153

◆ BeginCopyFrom()

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

Definition at line 3329 of file copy.c.

References AllocateFile(), Assert, attnum, CopyStateData::attnumlist, CopyStateData::attribute_buf, BeginCopy(), CopyStateData::binary, BinarySignature, build_column_default(), contain_volatile_functions_not_nextval(), COPY_CALLBACK, CopyStateData::copy_dest, CopyStateData::copy_file, CopyStateData::copycontext, CopyGetData(), CopyGetInt32(), CopyStateData::cur_attname, CopyStateData::cur_attval, CopyStateData::cur_lineno, CopyStateData::cur_relname, CopyStateData::data_source_cb, CopyStateData::defexprs, CopyStateData::defmap, DestRemote, CopyStateData::eol_type, EOL_UNKNOWN, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), ERROR, ExecInitExpr(), expression_planner(), CopyStateData::filename, fmgr_info(), getTypeBinaryInputInfo(), getTypeInputInfo(), CopyStateData::in_functions, initStringInfo(), InvalidOid, CopyStateData::is_program, CopyStateData::line_buf, CopyStateData::line_buf_converted, list_length(), list_member_int(), CopyStateData::max_fields, MemoryContextSwitchTo(), TupleDescData::natts, CopyStateData::num_defaults, OpenPipeStream(), ParseState::p_rtable, palloc(), PG_BINARY_R, pstrdup(), CopyStateData::range_table, CopyStateData::raw_buf, CopyStateData::raw_buf_index, CopyStateData::raw_buf_len, RAW_BUF_SIZE, CopyStateData::raw_fields, CopyStateData::reached_eof, ReceiveCopyBegin(), CopyStateData::rel, RelationGetDescr, RelationGetRelationName, S_ISDIR, stat, TupleDescAttr, CopyStateData::typioparams, CopyStateData::volatile_defexprs, and whereToSendOutput.

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

3336 {
3337  CopyState cstate;
3338  bool pipe = (filename == NULL);
3339  TupleDesc tupDesc;
3340  AttrNumber num_phys_attrs,
3341  num_defaults;
3342  FmgrInfo *in_functions;
3343  Oid *typioparams;
3344  int attnum;
3345  Oid in_func_oid;
3346  int *defmap;
3347  ExprState **defexprs;
3348  MemoryContext oldcontext;
3349  bool volatile_defexprs;
3350 
3351  cstate = BeginCopy(pstate, true, rel, NULL, InvalidOid, attnamelist, options);
3352  oldcontext = MemoryContextSwitchTo(cstate->copycontext);
3353 
3354  /* Initialize state variables */
3355  cstate->reached_eof = false;
3356  cstate->eol_type = EOL_UNKNOWN;
3357  cstate->cur_relname = RelationGetRelationName(cstate->rel);
3358  cstate->cur_lineno = 0;
3359  cstate->cur_attname = NULL;
3360  cstate->cur_attval = NULL;
3361 
3362  /* Set up variables to avoid per-attribute overhead. */
3363  initStringInfo(&cstate->attribute_buf);
3364  initStringInfo(&cstate->line_buf);
3365  cstate->line_buf_converted = false;
3366  cstate->raw_buf = (char *) palloc(RAW_BUF_SIZE + 1);
3367  cstate->raw_buf_index = cstate->raw_buf_len = 0;
3368 
3369  /* Assign range table, we'll need it in CopyFrom. */
3370  if (pstate)
3371  cstate->range_table = pstate->p_rtable;
3372 
3373  tupDesc = RelationGetDescr(cstate->rel);
3374  num_phys_attrs = tupDesc->natts;
3375  num_defaults = 0;
3376  volatile_defexprs = false;
3377 
3378  /*
3379  * Pick up the required catalog information for each attribute in the
3380  * relation, including the input function, the element type (to pass to
3381  * the input function), and info about defaults and constraints. (Which
3382  * input function we use depends on text/binary format choice.)
3383  */
3384  in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
3385  typioparams = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
3386  defmap = (int *) palloc(num_phys_attrs * sizeof(int));
3387  defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *));
3388 
3389  for (attnum = 1; attnum <= num_phys_attrs; attnum++)
3390  {
3391  Form_pg_attribute att = TupleDescAttr(tupDesc, attnum - 1);
3392 
3393  /* We don't need info for dropped attributes */
3394  if (att->attisdropped)
3395  continue;
3396 
3397  /* Fetch the input function and typioparam info */
3398  if (cstate->binary)
3399  getTypeBinaryInputInfo(att->atttypid,
3400  &in_func_oid, &typioparams[attnum - 1]);
3401  else
3402  getTypeInputInfo(att->atttypid,
3403  &in_func_oid, &typioparams[attnum - 1]);
3404  fmgr_info(in_func_oid, &in_functions[attnum - 1]);
3405 
3406  /* Get default info if needed */
3407  if (!list_member_int(cstate->attnumlist, attnum) && !att->attgenerated)
3408  {
3409  /* attribute is NOT to be copied from input */
3410  /* use default value if one exists */
3411  Expr *defexpr = (Expr *) build_column_default(cstate->rel,
3412  attnum);
3413 
3414  if (defexpr != NULL)
3415  {
3416  /* Run the expression through planner */
3417  defexpr = expression_planner(defexpr);
3418 
3419  /* Initialize executable expression in copycontext */
3420  defexprs[num_defaults] = ExecInitExpr(defexpr, NULL);
3421  defmap[num_defaults] = attnum - 1;
3422  num_defaults++;
3423 
3424  /*
3425  * If a default expression looks at the table being loaded,
3426  * then it could give the wrong answer when using
3427  * multi-insert. Since database access can be dynamic this is
3428  * hard to test for exactly, so we use the much wider test of
3429  * whether the default expression is volatile. We allow for
3430  * the special case of when the default expression is the
3431  * nextval() of a sequence which in this specific case is
3432  * known to be safe for use with the multi-insert
3433  * optimization. Hence we use this special case function
3434  * checker rather than the standard check for
3435  * contain_volatile_functions().
3436  */
3437  if (!volatile_defexprs)
3438  volatile_defexprs = contain_volatile_functions_not_nextval((Node *) defexpr);
3439  }
3440  }
3441  }
3442 
3443  /* We keep those variables in cstate. */
3444  cstate->in_functions = in_functions;
3445  cstate->typioparams = typioparams;
3446  cstate->defmap = defmap;
3447  cstate->defexprs = defexprs;
3448  cstate->volatile_defexprs = volatile_defexprs;
3449  cstate->num_defaults = num_defaults;
3450  cstate->is_program = is_program;
3451 
3452  if (data_source_cb)
3453  {
3454  cstate->copy_dest = COPY_CALLBACK;
3455  cstate->data_source_cb = data_source_cb;
3456  }
3457  else if (pipe)
3458  {
3459  Assert(!is_program); /* the grammar does not allow this */
3461  ReceiveCopyBegin(cstate);
3462  else
3463  cstate->copy_file = stdin;
3464  }
3465  else
3466  {
3467  cstate->filename = pstrdup(filename);
3468 
3469  if (cstate->is_program)
3470  {
3471  cstate->copy_file = OpenPipeStream(cstate->filename, PG_BINARY_R);
3472  if (cstate->copy_file == NULL)
3473  ereport(ERROR,
3475  errmsg("could not execute command \"%s\": %m",
3476  cstate->filename)));
3477  }
3478  else
3479  {
3480  struct stat st;
3481 
3482  cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_R);
3483  if (cstate->copy_file == NULL)
3484  {
3485  /* copy errno because ereport subfunctions might change it */
3486  int save_errno = errno;
3487 
3488  ereport(ERROR,
3490  errmsg("could not open file \"%s\" for reading: %m",
3491  cstate->filename),
3492  (save_errno == ENOENT || save_errno == EACCES) ?
3493  errhint("COPY FROM instructs the PostgreSQL server process to read a file. "
3494  "You may want a client-side facility such as psql's \\copy.") : 0));
3495  }
3496 
3497  if (fstat(fileno(cstate->copy_file), &st))
3498  ereport(ERROR,
3500  errmsg("could not stat file \"%s\": %m",
3501  cstate->filename)));
3502 
3503  if (S_ISDIR(st.st_mode))
3504  ereport(ERROR,
3505  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3506  errmsg("\"%s\" is a directory", cstate->filename)));
3507  }
3508  }
3509 
3510  if (cstate->binary)
3511  {
3512  /* Read and verify binary header */
3513  char readSig[11];
3514  int32 tmp;
3515 
3516  /* Signature */
3517  if (CopyGetData(cstate, readSig, 11, 11) != 11 ||
3518  memcmp(readSig, BinarySignature, 11) != 0)
3519  ereport(ERROR,
3520  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
3521  errmsg("COPY file signature not recognized")));
3522  /* Flags field */
3523  if (!CopyGetInt32(cstate, &tmp))
3524  ereport(ERROR,
3525  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
3526  errmsg("invalid COPY file header (missing flags)")));
3527  if ((tmp & (1 << 16)) != 0)
3528  ereport(ERROR,
3529  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
3530  errmsg("invalid COPY file header (WITH OIDS)")));
3531  tmp &= ~(1 << 16);
3532  if ((tmp >> 16) != 0)
3533  ereport(ERROR,
3534  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
3535  errmsg("unrecognized critical flags in COPY file header")));
3536  /* Header extension length */
3537  if (!CopyGetInt32(cstate, &tmp) ||
3538  tmp < 0)
3539  ereport(ERROR,
3540  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
3541  errmsg("invalid COPY file header (missing length)")));
3542  /* Skip extension header, if present */
3543  while (tmp-- > 0)
3544  {
3545  if (CopyGetData(cstate, readSig, 1, 1) != 1)
3546  ereport(ERROR,
3547  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
3548  errmsg("invalid COPY file header (wrong length)")));
3549  }
3550  }
3551 
3552  /* create workspace for CopyReadAttributes results */
3553  if (!cstate->binary)
3554  {
3555  AttrNumber attr_count = list_length(cstate->attnumlist);
3556 
3557  cstate->max_fields = attr_count;
3558  cstate->raw_fields = (char **) palloc(attr_count * sizeof(char *));
3559  }
3560 
3561  MemoryContextSwitchTo(oldcontext);
3562 
3563  return cstate;
3564 }
Definition: fmgr.h:56
List * range_table
Definition: copy.c:184
static CopyState BeginCopy(ParseState *pstate, bool is_from, Relation rel, RawStmt *raw_query, Oid queryRelId, List *attnamelist, List *options)
Definition: copy.c:1456
bool contain_volatile_functions_not_nextval(Node *clause)
Definition: clauses.c:776
static bool CopyGetInt32(CopyState cstate, int32 *val)
Definition: copy.c:738
int errhint(const char *fmt,...)
Definition: elog.c:1071
char ** raw_fields
Definition: copy.c:202
bool binary
Definition: copy.c:136
#define RelationGetDescr(relation)
Definition: rel.h:482
AttrNumber num_defaults
Definition: copy.c:178
FmgrInfo * in_functions
Definition: copy.c:179
List * attnumlist
Definition: copy.c:132
char * filename
Definition: copy.c:133
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
char * pstrdup(const char *in)
Definition: mcxt.c:1186
static void ReceiveCopyBegin(CopyState cstate)
Definition: copy.c:434
Expr * expression_planner(Expr *expr)
Definition: planner.c:6156
StringInfoData line_buf
Definition: copy.c:211
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:529
int raw_buf_index
Definition: copy.c:224
int errcode(int sqlerrcode)
Definition: elog.c:610
unsigned int Oid
Definition: postgres_ext.h:31
bool volatile_defexprs
Definition: copy.c:183
#define PG_BINARY_R
Definition: c.h:1235
bool line_buf_converted
Definition: copy.c:212
signed int int32
Definition: c.h:355
CopyDest copy_dest
Definition: copy.c:117
uint64 cur_lineno
Definition: copy.c:160
const char * cur_attname
Definition: copy.c:161
Relation rel
Definition: copy.c:130
MemoryContext copycontext
Definition: copy.c:167
copy_data_source_cb data_source_cb
Definition: copy.c:135
#define ERROR
Definition: elog.h:43
static int CopyGetData(CopyState cstate, void *databuf, int minread, int maxread)
Definition: copy.c:610
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
bool list_member_int(const List *list, int datum)
Definition: list.c:654
char * raw_buf
Definition: copy.c:223
ExprState ** defexprs
Definition: copy.c:182
const char * cur_relname
Definition: copy.c:159
int errcode_for_file_access(void)
Definition: elog.c:633
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2320
#define RelationGetRelationName(relation)
Definition: rel.h:490
static const char BinarySignature[11]
Definition: copy.c:350
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
int raw_buf_len
Definition: copy.c:225
int max_fields
Definition: copy.c:201
FILE * OpenPipeStream(const char *command, const char *mode)
Definition: fd.c:2423
void getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
Definition: lsyscache.c:2817
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2751
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define stat(a, b)
Definition: win32_port.h:255
Oid * typioparams
Definition: copy.c:180
bool is_program
Definition: copy.c:134
Node * build_column_default(Relation rel, int attrno)
#define RAW_BUF_SIZE
Definition: copy.c:222
#define InvalidOid
Definition: postgres_ext.h:36
int16 attnum
Definition: pg_attribute.h:79
#define ereport(elevel,...)
Definition: elog.h:144
EolType eol_type
Definition: copy.c:124
#define Assert(condition)
Definition: c.h:738
bool reached_eof
Definition: copy.c:122
static int list_length(const List *l)
Definition: pg_list.h:169
#define S_ISDIR(m)
Definition: win32_port.h:296
static char * filename
Definition: pg_dumpall.c:90
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
FILE * copy_file
Definition: copy.c:118
StringInfoData attribute_buf
Definition: copy.c:197
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:123
const char * cur_attval
Definition: copy.c:162
CommandDest whereToSendOutput
Definition: postgres.c:91
int16 AttrNumber
Definition: attnum.h:21
int * defmap
Definition: copy.c:181
List * p_rtable
Definition: parse_node.h:180

◆ BeginCopyTo()

static CopyState BeginCopyTo ( ParseState pstate,
Relation  rel,
RawStmt query,
Oid  queryRelId,
const char *  filename,
bool  is_program,
List attnamelist,
List options 
)
static

Definition at line 1821 of file copy.c.

References AllocateFile(), Assert, BeginCopy(), CopyStateData::copy_file, CopyStateData::copycontext, DestRemote, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), ERROR, CopyStateData::filename, is_absolute_path, CopyStateData::is_program, MemoryContextSwitchTo(), OpenPipeStream(), PG_BINARY_W, PG_END_TRY, PG_FINALLY, PG_TRY, pstrdup(), RelationData::rd_rel, RelationGetRelationName, S_ISDIR, S_IWGRP, S_IWOTH, stat, generate_unaccent_rules::stdout, and whereToSendOutput.

Referenced by DoCopy().

1829 {
1830  CopyState cstate;
1831  bool pipe = (filename == NULL);
1832  MemoryContext oldcontext;
1833 
1834  if (rel != NULL && rel->rd_rel->relkind != RELKIND_RELATION)
1835  {
1836  if (rel->rd_rel->relkind == RELKIND_VIEW)
1837  ereport(ERROR,
1838  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1839  errmsg("cannot copy from view \"%s\"",
1841  errhint("Try the COPY (SELECT ...) TO variant.")));
1842  else if (rel->rd_rel->relkind == RELKIND_MATVIEW)
1843  ereport(ERROR,
1844  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1845  errmsg("cannot copy from materialized view \"%s\"",
1847  errhint("Try the COPY (SELECT ...) TO variant.")));
1848  else if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1849  ereport(ERROR,
1850  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1851  errmsg("cannot copy from foreign table \"%s\"",
1853  errhint("Try the COPY (SELECT ...) TO variant.")));
1854  else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
1855  ereport(ERROR,
1856  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1857  errmsg("cannot copy from sequence \"%s\"",
1858  RelationGetRelationName(rel))));
1859  else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1860  ereport(ERROR,
1861  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1862  errmsg("cannot copy from partitioned table \"%s\"",
1864  errhint("Try the COPY (SELECT ...) TO variant.")));
1865  else
1866  ereport(ERROR,
1867  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1868  errmsg("cannot copy from non-table relation \"%s\"",
1869  RelationGetRelationName(rel))));
1870  }
1871 
1872  cstate = BeginCopy(pstate, false, rel, query, queryRelId, attnamelist,
1873  options);
1874  oldcontext = MemoryContextSwitchTo(cstate->copycontext);
1875 
1876  if (pipe)
1877  {
1878  Assert(!is_program); /* the grammar does not allow this */
1880  cstate->copy_file = stdout;
1881  }
1882  else
1883  {
1884  cstate->filename = pstrdup(filename);
1885  cstate->is_program = is_program;
1886 
1887  if (is_program)
1888  {
1889  cstate->copy_file = OpenPipeStream(cstate->filename, PG_BINARY_W);
1890  if (cstate->copy_file == NULL)
1891  ereport(ERROR,
1893  errmsg("could not execute command \"%s\": %m",
1894  cstate->filename)));
1895  }
1896  else
1897  {
1898  mode_t oumask; /* Pre-existing umask value */
1899  struct stat st;
1900 
1901  /*
1902  * Prevent write to relative path ... too easy to shoot oneself in
1903  * the foot by overwriting a database file ...
1904  */
1905  if (!is_absolute_path(filename))
1906  ereport(ERROR,
1907  (errcode(ERRCODE_INVALID_NAME),
1908  errmsg("relative path not allowed for COPY to file")));
1909 
1910  oumask = umask(S_IWGRP | S_IWOTH);
1911  PG_TRY();
1912  {
1913  cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_W);
1914  }
1915  PG_FINALLY();
1916  {
1917  umask(oumask);
1918  }
1919  PG_END_TRY();
1920  if (cstate->copy_file == NULL)
1921  {
1922  /* copy errno because ereport subfunctions might change it */
1923  int save_errno = errno;
1924 
1925  ereport(ERROR,
1927  errmsg("could not open file \"%s\" for writing: %m",
1928  cstate->filename),
1929  (save_errno == ENOENT || save_errno == EACCES) ?
1930  errhint("COPY TO instructs the PostgreSQL server process to write a file. "
1931  "You may want a client-side facility such as psql's \\copy.") : 0));
1932  }
1933 
1934  if (fstat(fileno(cstate->copy_file), &st))
1935  ereport(ERROR,
1937  errmsg("could not stat file \"%s\": %m",
1938  cstate->filename)));
1939 
1940  if (S_ISDIR(st.st_mode))
1941  ereport(ERROR,
1942  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1943  errmsg("\"%s\" is a directory", cstate->filename)));
1944  }
1945  }
1946 
1947  MemoryContextSwitchTo(oldcontext);
1948 
1949  return cstate;
1950 }
static CopyState BeginCopy(ParseState *pstate, bool is_from, Relation rel, RawStmt *raw_query, Oid queryRelId, List *attnamelist, List *options)
Definition: copy.c:1456
int errhint(const char *fmt,...)
Definition: elog.c:1071
char * filename
Definition: copy.c:133
char * pstrdup(const char *in)
Definition: mcxt.c:1186
#define S_IWOTH
Definition: win32_port.h:287
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:610
#define PG_BINARY_W
Definition: c.h:1236
Form_pg_class rd_rel
Definition: rel.h:109
MemoryContext copycontext
Definition: copy.c:167
#define ERROR
Definition: elog.h:43
int errcode_for_file_access(void)
Definition: elog.c:633
#define is_absolute_path(filename)
Definition: port.h:86
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2320
#define RelationGetRelationName(relation)
Definition: rel.h:490
#define S_IWGRP
Definition: win32_port.h:275
FILE * OpenPipeStream(const char *command, const char *mode)
Definition: fd.c:2423
#define stat(a, b)
Definition: win32_port.h:255
bool is_program
Definition: copy.c:134
#define PG_FINALLY()
Definition: elog.h:312
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
#define S_ISDIR(m)
Definition: win32_port.h:296
static char * filename
Definition: pg_dumpall.c:90
int errmsg(const char *fmt,...)
Definition: elog.c:824
FILE * copy_file
Definition: copy.c:118
CommandDest whereToSendOutput
Definition: postgres.c:91
#define PG_TRY()
Definition: elog.h:295
#define PG_END_TRY()
Definition: elog.h:320

◆ ClosePipeToProgram()

static void ClosePipeToProgram ( CopyState  cstate)
static

Definition at line 1763 of file copy.c.

References Assert, ClosePipeStream(), CopyStateData::copy_file, ereport, errcode(), errcode_for_file_access(), errdetail_internal(), errmsg(), ERROR, CopyStateData::filename, CopyStateData::is_copy_from, CopyStateData::is_program, CopyStateData::reached_eof, SIGPIPE, wait_result_is_signal(), and wait_result_to_str().

Referenced by CopySendEndOfRow(), and EndCopy().

1764 {
1765  int pclose_rc;
1766 
1767  Assert(cstate->is_program);
1768 
1769  pclose_rc = ClosePipeStream(cstate->copy_file);
1770  if (pclose_rc == -1)
1771  ereport(ERROR,
1773  errmsg("could not close pipe to external command: %m")));
1774  else if (pclose_rc != 0)
1775  {
1776  /*
1777  * If we ended a COPY FROM PROGRAM before reaching EOF, then it's
1778  * expectable for the called program to fail with SIGPIPE, and we
1779  * should not report that as an error. Otherwise, SIGPIPE indicates a
1780  * problem.
1781  */
1782  if (cstate->is_copy_from && !cstate->reached_eof &&
1783  wait_result_is_signal(pclose_rc, SIGPIPE))
1784  return;
1785 
1786  ereport(ERROR,
1787  (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
1788  errmsg("program \"%s\" failed",
1789  cstate->filename),
1790  errdetail_internal("%s", wait_result_to_str(pclose_rc))));
1791  }
1792 }
char * filename
Definition: copy.c:133
int errcode(int sqlerrcode)
Definition: elog.c:610
#define SIGPIPE
Definition: win32_port.h:158
char * wait_result_to_str(int exitstatus)
Definition: wait_error.c:32
int ClosePipeStream(FILE *file)
Definition: fd.c:2729
int errdetail_internal(const char *fmt,...)
Definition: elog.c:984
bool wait_result_is_signal(int exit_status, int signum)
Definition: wait_error.c:92
#define ERROR
Definition: elog.h:43
int errcode_for_file_access(void)
Definition: elog.c:633
bool is_copy_from
Definition: copy.c:121
bool is_program
Definition: copy.c:134
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
bool reached_eof
Definition: copy.c:122
int errmsg(const char *fmt,...)
Definition: elog.c:824
FILE * copy_file
Definition: copy.c:118

◆ copy_dest_destroy()

static void copy_dest_destroy ( DestReceiver self)
static

Definition at line 5131 of file copy.c.

References pfree().

Referenced by CreateCopyDestReceiver().

5132 {
5133  pfree(self);
5134 }
void pfree(void *pointer)
Definition: mcxt.c:1056

◆ copy_dest_receive()

static bool copy_dest_receive ( TupleTableSlot slot,
DestReceiver self 
)
static

Definition at line 5106 of file copy.c.

References CopyOneRowTo(), DR_copy::cstate, and DR_copy::processed.

Referenced by CreateCopyDestReceiver().

5107 {
5108  DR_copy *myState = (DR_copy *) self;
5109  CopyState cstate = myState->cstate;
5110 
5111  /* Send the data */
5112  CopyOneRowTo(cstate, slot);
5113  myState->processed++;
5114 
5115  return true;
5116 }
Definition: copy.c:229
CopyState cstate
Definition: copy.c:232
static void CopyOneRowTo(CopyState cstate, TupleTableSlot *slot)
Definition: copy.c:2155
uint64 processed
Definition: copy.c:233

◆ copy_dest_shutdown()

static void copy_dest_shutdown ( DestReceiver self)
static

Definition at line 5122 of file copy.c.

Referenced by CreateCopyDestReceiver().

5123 {
5124  /* no-op */
5125 }

◆ copy_dest_startup()

static void copy_dest_startup ( DestReceiver self,
int  operation,
TupleDesc  typeinfo 
)
static

Definition at line 5097 of file copy.c.

Referenced by CreateCopyDestReceiver().

5098 {
5099  /* no-op */
5100 }

◆ CopyAttributeOutCSV()

static void CopyAttributeOutCSV ( CopyState  cstate,
char *  string,
bool  use_quote,
bool  single_attr 
)
static

Definition at line 4920 of file copy.c.

References CopySendChar(), CopySendString(), CopyStateData::delim, DUMPSOFAR, CopyStateData::encoding_embeds_ascii, CopyStateData::escape, CopyStateData::file_encoding, IS_HIGHBIT_SET, CopyStateData::need_transcoding, CopyStateData::null_print, pg_encoding_mblen(), pg_server_to_any(), and CopyStateData::quote.

Referenced by CopyOneRowTo(), and CopyTo().

4922 {
4923  char *ptr;
4924  char *start;
4925  char c;
4926  char delimc = cstate->delim[0];
4927  char quotec = cstate->quote[0];
4928  char escapec = cstate->escape[0];
4929 
4930  /* force quoting if it matches null_print (before conversion!) */
4931  if (!use_quote && strcmp(string, cstate->null_print) == 0)
4932  use_quote = true;
4933 
4934  if (cstate->need_transcoding)
4935  ptr = pg_server_to_any(string, strlen(string), cstate->file_encoding);
4936  else
4937  ptr = string;
4938 
4939  /*
4940  * Make a preliminary pass to discover if it needs quoting
4941  */
4942  if (!use_quote)
4943  {
4944  /*
4945  * Because '\.' can be a data value, quote it if it appears alone on a
4946  * line so it is not interpreted as the end-of-data marker.
4947  */
4948  if (single_attr && strcmp(ptr, "\\.") == 0)
4949  use_quote = true;
4950  else
4951  {
4952  char *tptr = ptr;
4953 
4954  while ((c = *tptr) != '\0')
4955  {
4956  if (c == delimc || c == quotec || c == '\n' || c == '\r')
4957  {
4958  use_quote = true;
4959  break;
4960  }
4961  if (IS_HIGHBIT_SET(c) && cstate->encoding_embeds_ascii)
4962  tptr += pg_encoding_mblen(cstate->file_encoding, tptr);
4963  else
4964  tptr++;
4965  }
4966  }
4967  }
4968 
4969  if (use_quote)
4970  {
4971  CopySendChar(cstate, quotec);
4972 
4973  /*
4974  * We adopt the same optimization strategy as in CopyAttributeOutText
4975  */
4976  start = ptr;
4977  while ((c = *ptr) != '\0')
4978  {
4979  if (c == quotec || c == escapec)
4980  {
4981  DUMPSOFAR();
4982  CopySendChar(cstate, escapec);
4983  start = ptr; /* we include char in next run */
4984  }
4985  if (IS_HIGHBIT_SET(c) && cstate->encoding_embeds_ascii)
4986  ptr += pg_encoding_mblen(cstate->file_encoding, ptr);
4987  else
4988  ptr++;
4989  }
4990  DUMPSOFAR();
4991 
4992  CopySendChar(cstate, quotec);
4993  }
4994  else
4995  {
4996  /* If it doesn't need quoting, we can just dump it as-is */
4997  CopySendString(cstate, ptr);
4998  }
4999 }
bool need_transcoding
Definition: copy.c:126
char * delim
Definition: copy.c:143
char * pg_server_to_any(const char *s, int len, int encoding)
Definition: mbutils.c:692
static void CopySendChar(CopyState cstate, char c)
Definition: copy.c:511
char * null_print
Definition: copy.c:140
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1119
bool encoding_embeds_ascii
Definition: copy.c:127
char * c
char * quote
Definition: copy.c:144
int pg_encoding_mblen(int encoding, const char *mbstr)
Definition: wchar.c:1554
char string[11]
Definition: preproc-type.c:46
char * escape
Definition: copy.c:145
int file_encoding
Definition: copy.c:125
static void CopySendString(CopyState cstate, const char *str)
Definition: copy.c:505
#define DUMPSOFAR()
Definition: copy.c:4760

◆ CopyAttributeOutText()

static void CopyAttributeOutText ( CopyState  cstate,
char *  string 
)
static

Definition at line 4767 of file copy.c.

References CopySendChar(), CopyStateData::delim, DUMPSOFAR, CopyStateData::encoding_embeds_ascii, CopyStateData::file_encoding, IS_HIGHBIT_SET, CopyStateData::need_transcoding, pg_encoding_mblen(), and pg_server_to_any().

Referenced by CopyOneRowTo().

4768 {
4769  char *ptr;
4770  char *start;
4771  char c;
4772  char delimc = cstate->delim[0];
4773 
4774  if (cstate->need_transcoding)
4775  ptr = pg_server_to_any(string, strlen(string), cstate->file_encoding);
4776  else
4777  ptr = string;
4778 
4779  /*
4780  * We have to grovel through the string searching for control characters
4781  * and instances of the delimiter character. In most cases, though, these
4782  * are infrequent. To avoid overhead from calling CopySendData once per
4783  * character, we dump out all characters between escaped characters in a
4784  * single call. The loop invariant is that the data from "start" to "ptr"
4785  * can be sent literally, but hasn't yet been.
4786  *
4787  * We can skip pg_encoding_mblen() overhead when encoding is safe, because
4788  * in valid backend encodings, extra bytes of a multibyte character never
4789  * look like ASCII. This loop is sufficiently performance-critical that
4790  * it's worth making two copies of it to get the IS_HIGHBIT_SET() test out
4791  * of the normal safe-encoding path.
4792  */
4793  if (cstate->encoding_embeds_ascii)
4794  {
4795  start = ptr;
4796  while ((c = *ptr) != '\0')
4797  {
4798  if ((unsigned char) c < (unsigned char) 0x20)
4799  {
4800  /*
4801  * \r and \n must be escaped, the others are traditional. We
4802  * prefer to dump these using the C-like notation, rather than
4803  * a backslash and the literal character, because it makes the
4804  * dump file a bit more proof against Microsoftish data
4805  * mangling.
4806  */
4807  switch (c)
4808  {
4809  case '\b':
4810  c = 'b';
4811  break;
4812  case '\f':
4813  c = 'f';
4814  break;
4815  case '\n':
4816  c = 'n';
4817  break;
4818  case '\r':
4819  c = 'r';
4820  break;
4821  case '\t':
4822  c = 't';
4823  break;
4824  case '\v':
4825  c = 'v';
4826  break;
4827  default:
4828  /* If it's the delimiter, must backslash it */
4829  if (c == delimc)
4830  break;
4831  /* All ASCII control chars are length 1 */
4832  ptr++;
4833  continue; /* fall to end of loop */
4834  }
4835  /* if we get here, we need to convert the control char */
4836  DUMPSOFAR();
4837  CopySendChar(cstate, '\\');
4838  CopySendChar(cstate, c);
4839  start = ++ptr; /* do not include char in next run */
4840  }
4841  else if (c == '\\' || c == delimc)
4842  {
4843  DUMPSOFAR();
4844  CopySendChar(cstate, '\\');
4845  start = ptr++; /* we include char in next run */
4846  }
4847  else if (IS_HIGHBIT_SET(c))
4848  ptr += pg_encoding_mblen(cstate->file_encoding, ptr);
4849  else
4850  ptr++;
4851  }
4852  }
4853  else
4854  {
4855  start = ptr;
4856  while ((c = *ptr) != '\0')
4857  {
4858  if ((unsigned char) c < (unsigned char) 0x20)
4859  {
4860  /*
4861  * \r and \n must be escaped, the others are traditional. We
4862  * prefer to dump these using the C-like notation, rather than
4863  * a backslash and the literal character, because it makes the
4864  * dump file a bit more proof against Microsoftish data
4865  * mangling.
4866  */
4867  switch (c)
4868  {
4869  case '\b':
4870  c = 'b';
4871  break;
4872  case '\f':
4873  c = 'f';
4874  break;
4875  case '\n':
4876  c = 'n';
4877  break;
4878  case '\r':
4879  c = 'r';
4880  break;
4881  case '\t':
4882  c = 't';
4883  break;
4884  case '\v':
4885  c = 'v';
4886  break;
4887  default:
4888  /* If it's the delimiter, must backslash it */
4889  if (c == delimc)
4890  break;
4891  /* All ASCII control chars are length 1 */
4892  ptr++;
4893  continue; /* fall to end of loop */
4894  }
4895  /* if we get here, we need to convert the control char */
4896  DUMPSOFAR();
4897  CopySendChar(cstate, '\\');
4898  CopySendChar(cstate, c);
4899  start = ++ptr; /* do not include char in next run */
4900  }
4901  else if (c == '\\' || c == delimc)
4902  {
4903  DUMPSOFAR();
4904  CopySendChar(cstate, '\\');
4905  start = ptr++; /* we include char in next run */
4906  }
4907  else
4908  ptr++;
4909  }
4910  }
4911 
4912  DUMPSOFAR();
4913 }
bool need_transcoding
Definition: copy.c:126
char * delim
Definition: copy.c:143
char * pg_server_to_any(const char *s, int len, int encoding)
Definition: mbutils.c:692
static void CopySendChar(CopyState cstate, char c)
Definition: copy.c:511
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1119
bool encoding_embeds_ascii
Definition: copy.c:127
char * c
int pg_encoding_mblen(int encoding, const char *mbstr)
Definition: wchar.c:1554
char string[11]
Definition: preproc-type.c:46
int file_encoding
Definition: copy.c:125
#define DUMPSOFAR()
Definition: copy.c:4760

◆ CopyFrom()

uint64 CopyFrom ( CopyState  cstate)

Definition at line 2648 of file copy.c.

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(), CopyStateData::copy_dest, COPY_OLD_FE, CopyFromErrorCallback(), CopyMultiInsertInfoCleanup(), CopyMultiInsertInfoFlush(), CopyMultiInsertInfoInit(), CopyMultiInsertInfoIsEmpty(), CopyMultiInsertInfoIsFull(), CopyMultiInsertInfoNextFreeSlot(), CopyMultiInsertInfoSetupBuffer(), CopyMultiInsertInfoStore(), CreateExecutorState(), CopyStateData::cur_lineno, CurrentMemoryContext, ExprContext::ecxt_scantuple, FdwRoutine::EndForeignInsert, ereport, errcode(), errhint(), errmsg(), ERROR, error_context_stack, EState::es_num_result_relations, EState::es_result_relation_info, EState::es_result_relations, EState::es_tupleTable, ExecARInsertTriggers(), ExecASInsertTriggers(), ExecBRInsertTriggers(), ExecBSInsertTriggers(), ExecCleanUpTriggerState(), ExecCleanupTupleRouting(), ExecClearTuple(), ExecCloseIndices(), ExecComputeStoredGenerated(), ExecConstraints(), ExecCopySlot(), ExecFindPartition(), FdwRoutine::ExecForeignInsert, ExecInitQual(), ExecInitRangeTable(), ExecInsertIndexTuples(), ExecIRInsertTriggers(), ExecMaterializeSlot(), ExecOpenIndices(), ExecPartitionCheck(), ExecQual(), ExecResetTupleTable(), ExecSetupPartitionTupleRouting(), ExecStoreVirtualTuple(), execute_attr_map_slot(), FreeBulkInsertState(), FreeExecutorState(), CopyStateData::freeze, GetBulkInsertState(), GetCurrentCommandId(), GetCurrentSubTransactionId(), GetPerTupleExprContext, GetPerTupleMemoryContext, TupleConstr::has_generated_stored, InitResultRelInfo(), InvalidateCatalogSnapshot(), InvalidSubTransactionId, StringInfoData::len, CopyStateData::line_buf, list_free(), makeNode, MakeTransitionCaptureState(), MemoryContextSwitchTo(), ModifyTableState::mt_transition_capture, NextCopyFrom(), NIL, ModifyTableState::operation, PartitionRoutingInfo::pi_PartitionToRootMap, PartitionRoutingInfo::pi_PartitionTupleSlot, PartitionRoutingInfo::pi_RootToPartitionMap, PlanState::plan, pq_endmsgread(), ErrorContextCallback::previous, ModifyTableState::ps, CopyStateData::qualexpr, CopyStateData::range_table, RelationData::rd_att, RelationData::rd_createSubid, RelationData::rd_firstRelfilenodeSubid, RelationData::rd_newRelfilenodeSubid, RelationData::rd_rel, CopyStateData::rel, RelationGetRelationName, RelationGetRelid, ReleaseBulkInsertStatePin(), ResetPerTupleExprContext, ModifyTableState::resultRelInfo, ResultRelInfo::ri_CopyMultiInsertBuffer, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_PartitionCheck, ResultRelInfo::ri_PartitionInfo, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, PlanState::state, TABLE_INSERT_FROZEN, TABLE_INSERT_SKIP_FSM, table_slot_create(), table_tuple_insert(), TransitionCaptureState::tcs_map, TransitionCaptureState::tcs_original_insert_tuple, ThereAreNoPriorRegisteredSnapshots(), ThereAreNoReadyPortals(), CopyStateData::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, CopyStateData::volatile_defexprs, and CopyStateData::whereClause.

Referenced by copy_table(), and DoCopy().

2649 {
2650  ResultRelInfo *resultRelInfo;
2651  ResultRelInfo *target_resultRelInfo;
2652  ResultRelInfo *prevResultRelInfo = NULL;
2653  EState *estate = CreateExecutorState(); /* for ExecConstraints() */
2654  ModifyTableState *mtstate;
2655  ExprContext *econtext;
2656  TupleTableSlot *singleslot = NULL;
2657  MemoryContext oldcontext = CurrentMemoryContext;
2658 
2659  PartitionTupleRouting *proute = NULL;
2660  ErrorContextCallback errcallback;
2661  CommandId mycid = GetCurrentCommandId(true);
2662  int ti_options = 0; /* start with default options for insert */
2663  BulkInsertState bistate = NULL;
2664  CopyInsertMethod insertMethod;
2665  CopyMultiInsertInfo multiInsertInfo = {0}; /* pacify compiler */
2666  uint64 processed = 0;
2667  bool has_before_insert_row_trig;
2668  bool has_instead_insert_row_trig;
2669  bool leafpart_use_multi_insert = false;
2670 
2671  Assert(cstate->rel);
2672 
2673  /*
2674  * The target must be a plain, foreign, or partitioned relation, or have
2675  * an INSTEAD OF INSERT row trigger. (Currently, such triggers are only
2676  * allowed on views, so we only hint about them in the view case.)
2677  */
2678  if (cstate->rel->rd_rel->relkind != RELKIND_RELATION &&
2679  cstate->rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
2680  cstate->rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE &&
2681  !(cstate->rel->trigdesc &&
2683  {
2684  if (cstate->rel->rd_rel->relkind == RELKIND_VIEW)
2685  ereport(ERROR,
2686  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2687  errmsg("cannot copy to view \"%s\"",
2688  RelationGetRelationName(cstate->rel)),
2689  errhint("To enable copying to a view, provide an INSTEAD OF INSERT trigger.")));
2690  else if (cstate->rel->rd_rel->relkind == RELKIND_MATVIEW)
2691  ereport(ERROR,
2692  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2693  errmsg("cannot copy to materialized view \"%s\"",
2694  RelationGetRelationName(cstate->rel))));
2695  else if (cstate->rel->rd_rel->relkind == RELKIND_SEQUENCE)
2696  ereport(ERROR,
2697  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2698  errmsg("cannot copy to sequence \"%s\"",
2699  RelationGetRelationName(cstate->rel))));
2700  else
2701  ereport(ERROR,
2702  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2703  errmsg("cannot copy to non-table relation \"%s\"",
2704  RelationGetRelationName(cstate->rel))));
2705  }
2706 
2707  /*
2708  * If the target file is new-in-transaction, we assume that checking FSM
2709  * for free space is a waste of time. This could possibly be wrong, but
2710  * it's unlikely.
2711  */
2712  if (RELKIND_HAS_STORAGE(cstate->rel->rd_rel->relkind) &&
2715  ti_options |= TABLE_INSERT_SKIP_FSM;
2716 
2717  /*
2718  * Optimize if new relfilenode was created in this subxact or one of its
2719  * committed children and we won't see those rows later as part of an
2720  * earlier scan or command. The subxact test ensures that if this subxact
2721  * aborts then the frozen rows won't be visible after xact cleanup. Note
2722  * that the stronger test of exactly which subtransaction created it is
2723  * crucial for correctness of this optimization. The test for an earlier
2724  * scan or command tolerates false negatives. FREEZE causes other sessions
2725  * to see rows they would not see under MVCC, and a false negative merely
2726  * spreads that anomaly to the current session.
2727  */
2728  if (cstate->freeze)
2729  {
2730  /*
2731  * We currently disallow COPY FREEZE on partitioned tables. The
2732  * reason for this is that we've simply not yet opened the partitions
2733  * to determine if the optimization can be applied to them. We could
2734  * go and open them all here, but doing so may be quite a costly
2735  * overhead for small copies. In any case, we may just end up routing
2736  * tuples to a small number of partitions. It seems better just to
2737  * raise an ERROR for partitioned tables.
2738  */
2739  if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
2740  {
2741  ereport(ERROR,
2742  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2743  errmsg("cannot perform COPY FREEZE on a partitioned table")));
2744  }
2745 
2746  /*
2747  * Tolerate one registration for the benefit of FirstXactSnapshot.
2748  * Scan-bearing queries generally create at least two registrations,
2749  * though relying on that is fragile, as is ignoring ActiveSnapshot.
2750  * Clear CatalogSnapshot to avoid counting its registration. We'll
2751  * still detect ongoing catalog scans, each of which separately
2752  * registers the snapshot it uses.
2753  */
2756  ereport(ERROR,
2757  (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
2758  errmsg("cannot perform COPY FREEZE because of prior transaction activity")));
2759 
2760  if (cstate->rel->rd_createSubid != GetCurrentSubTransactionId() &&
2762  ereport(ERROR,
2763  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2764  errmsg("cannot perform COPY FREEZE because the table was not created or truncated in the current subtransaction")));
2765 
2766  ti_options |= TABLE_INSERT_FROZEN;
2767  }
2768 
2769  /*
2770  * We need a ResultRelInfo so we can use the regular executor's
2771  * index-entry-making machinery. (There used to be a huge amount of code
2772  * here that basically duplicated execUtils.c ...)
2773  */
2774  resultRelInfo = makeNode(ResultRelInfo);
2775  InitResultRelInfo(resultRelInfo,
2776  cstate->rel,
2777  1, /* must match rel's position in range_table */
2778  NULL,
2779  0);
2780  target_resultRelInfo = resultRelInfo;
2781 
2782  /* Verify the named relation is a valid target for INSERT */
2783  CheckValidResultRel(resultRelInfo, CMD_INSERT);
2784 
2785  ExecOpenIndices(resultRelInfo, false);
2786 
2787  estate->es_result_relations = resultRelInfo;
2788  estate->es_num_result_relations = 1;
2789  estate->es_result_relation_info = resultRelInfo;
2790 
2791  ExecInitRangeTable(estate, cstate->range_table);
2792 
2793  /*
2794  * Set up a ModifyTableState so we can let FDW(s) init themselves for
2795  * foreign-table result relation(s).
2796  */
2797  mtstate = makeNode(ModifyTableState);
2798  mtstate->ps.plan = NULL;
2799  mtstate->ps.state = estate;
2800  mtstate->operation = CMD_INSERT;
2801  mtstate->resultRelInfo = estate->es_result_relations;
2802 
2803  if (resultRelInfo->ri_FdwRoutine != NULL &&
2804  resultRelInfo->ri_FdwRoutine->BeginForeignInsert != NULL)
2805  resultRelInfo->ri_FdwRoutine->BeginForeignInsert(mtstate,
2806  resultRelInfo);
2807 
2808  /* Prepare to catch AFTER triggers. */
2810 
2811  /*
2812  * If there are any triggers with transition tables on the named relation,
2813  * we need to be prepared to capture transition tuples.
2814  *
2815  * Because partition tuple routing would like to know about whether
2816  * transition capture is active, we also set it in mtstate, which is
2817  * passed to ExecFindPartition() below.
2818  */
2819  cstate->transition_capture = mtstate->mt_transition_capture =
2821  RelationGetRelid(cstate->rel),
2822  CMD_INSERT);
2823 
2824  /*
2825  * If the named relation is a partitioned table, initialize state for
2826  * CopyFrom tuple routing.
2827  */
2828  if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
2829  proute = ExecSetupPartitionTupleRouting(estate, NULL, cstate->rel);
2830 
2831  if (cstate->whereClause)
2832  cstate->qualexpr = ExecInitQual(castNode(List, cstate->whereClause),
2833  &mtstate->ps);
2834 
2835  /*
2836  * It's generally more efficient to prepare a bunch of tuples for
2837  * insertion, and insert them in one table_multi_insert() call, than call
2838  * table_tuple_insert() separately for every tuple. However, there are a
2839  * number of reasons why we might not be able to do this. These are
2840  * explained below.
2841  */
2842  if (resultRelInfo->ri_TrigDesc != NULL &&
2843  (resultRelInfo->ri_TrigDesc->trig_insert_before_row ||
2844  resultRelInfo->ri_TrigDesc->trig_insert_instead_row))
2845  {
2846  /*
2847  * Can't support multi-inserts when there are any BEFORE/INSTEAD OF
2848  * triggers on the table. Such triggers might query the table we're
2849  * inserting into and act differently if the tuples that have already
2850  * been processed and prepared for insertion are not there.
2851  */
2852  insertMethod = CIM_SINGLE;
2853  }
2854  else if (proute != NULL && resultRelInfo->ri_TrigDesc != NULL &&
2855  resultRelInfo->ri_TrigDesc->trig_insert_new_table)
2856  {
2857  /*
2858  * For partitioned tables we can't support multi-inserts when there
2859  * are any statement level insert triggers. It might be possible to
2860  * allow partitioned tables with such triggers in the future, but for
2861  * now, CopyMultiInsertInfoFlush expects that any before row insert
2862  * and statement level insert triggers are on the same relation.
2863  */
2864  insertMethod = CIM_SINGLE;
2865  }
2866  else if (resultRelInfo->ri_FdwRoutine != NULL ||
2867  cstate->volatile_defexprs)
2868  {
2869  /*
2870  * Can't support multi-inserts to foreign tables or if there are any
2871  * volatile default expressions in the table. Similarly to the
2872  * trigger case above, such expressions may query the table we're
2873  * inserting into.
2874  *
2875  * Note: It does not matter if any partitions have any volatile
2876  * default expressions as we use the defaults from the target of the
2877  * COPY command.
2878  */
2879  insertMethod = CIM_SINGLE;
2880  }
2881  else if (contain_volatile_functions(cstate->whereClause))
2882  {
2883  /*
2884  * Can't support multi-inserts if there are any volatile function
2885  * expressions in WHERE clause. Similarly to the trigger case above,
2886  * such expressions may query the table we're inserting into.
2887  */
2888  insertMethod = CIM_SINGLE;
2889  }
2890  else
2891  {
2892  /*
2893  * For partitioned tables, we may still be able to perform bulk
2894  * inserts. However, the possibility of this depends on which types
2895  * of triggers exist on the partition. We must disable bulk inserts
2896  * if the partition is a foreign table or it has any before row insert
2897  * or insert instead triggers (same as we checked above for the parent
2898  * table). Since the partition's resultRelInfos are initialized only
2899  * when we actually need to insert the first tuple into them, we must
2900  * have the intermediate insert method of CIM_MULTI_CONDITIONAL to
2901  * flag that we must later determine if we can use bulk-inserts for
2902  * the partition being inserted into.
2903  */
2904  if (proute)
2905  insertMethod = CIM_MULTI_CONDITIONAL;
2906  else
2907  insertMethod = CIM_MULTI;
2908 
2909  CopyMultiInsertInfoInit(&multiInsertInfo, resultRelInfo, cstate,
2910  estate, mycid, ti_options);
2911  }
2912 
2913  /*
2914  * If not using batch mode (which allocates slots as needed) set up a
2915  * tuple slot too. When inserting into a partitioned table, we also need
2916  * one, even if we might batch insert, to read the tuple in the root
2917  * partition's form.
2918  */
2919  if (insertMethod == CIM_SINGLE || insertMethod == CIM_MULTI_CONDITIONAL)
2920  {
2921  singleslot = table_slot_create(resultRelInfo->ri_RelationDesc,
2922  &estate->es_tupleTable);
2923  bistate = GetBulkInsertState();
2924  }
2925 
2926  has_before_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
2927  resultRelInfo->ri_TrigDesc->trig_insert_before_row);
2928 
2929  has_instead_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
2930  resultRelInfo->ri_TrigDesc->trig_insert_instead_row);
2931 
2932  /*
2933  * Check BEFORE STATEMENT insertion triggers. It's debatable whether we
2934  * should do this for COPY, since it's not really an "INSERT" statement as
2935  * such. However, executing these triggers maintains consistency with the
2936  * EACH ROW triggers that we already fire on COPY.
2937  */
2938  ExecBSInsertTriggers(estate, resultRelInfo);
2939 
2940  econtext = GetPerTupleExprContext(estate);
2941 
2942  /* Set up callback to identify error line number */
2943  errcallback.callback = CopyFromErrorCallback;
2944  errcallback.arg = (void *) cstate;
2945  errcallback.previous = error_context_stack;
2946  error_context_stack = &errcallback;
2947 
2948  for (;;)
2949  {
2950  TupleTableSlot *myslot;
2951  bool skip_tuple;
2952 
2954 
2955  /*
2956  * Reset the per-tuple exprcontext. We do this after every tuple, to
2957  * clean-up after expression evaluations etc.
2958  */
2959  ResetPerTupleExprContext(estate);
2960 
2961  /* select slot to (initially) load row into */
2962  if (insertMethod == CIM_SINGLE || proute)
2963  {
2964  myslot = singleslot;
2965  Assert(myslot != NULL);
2966  }
2967  else
2968  {
2969  Assert(resultRelInfo == target_resultRelInfo);
2970  Assert(insertMethod == CIM_MULTI);
2971 
2972  myslot = CopyMultiInsertInfoNextFreeSlot(&multiInsertInfo,
2973  resultRelInfo);
2974  }
2975 
2976  /*
2977  * Switch to per-tuple context before calling NextCopyFrom, which does
2978  * evaluate default expressions etc. and requires per-tuple context.
2979  */
2981 
2982  ExecClearTuple(myslot);
2983 
2984  /* Directly store the values/nulls array in the slot */
2985  if (!NextCopyFrom(cstate, econtext, myslot->tts_values, myslot->tts_isnull))
2986  break;
2987 
2988  ExecStoreVirtualTuple(myslot);
2989 
2990  /*
2991  * Constraints and where clause might reference the tableoid column,
2992  * so (re-)initialize tts_tableOid before evaluating them.
2993  */
2994  myslot->tts_tableOid = RelationGetRelid(target_resultRelInfo->ri_RelationDesc);
2995 
2996  /* Triggers and stuff need to be invoked in query context. */
2997  MemoryContextSwitchTo(oldcontext);
2998 
2999  if (cstate->whereClause)
3000  {
3001  econtext->ecxt_scantuple = myslot;
3002  /* Skip items that don't match COPY's WHERE clause */
3003  if (!ExecQual(cstate->qualexpr, econtext))
3004  continue;
3005  }
3006 
3007  /* Determine the partition to insert the tuple into */
3008  if (proute)
3009  {
3010  TupleConversionMap *map;
3011 
3012  /*
3013  * Attempt to find a partition suitable for this tuple.
3014  * ExecFindPartition() will raise an error if none can be found or
3015  * if the found partition is not suitable for INSERTs.
3016  */
3017  resultRelInfo = ExecFindPartition(mtstate, target_resultRelInfo,
3018  proute, myslot, estate);
3019 
3020  if (prevResultRelInfo != resultRelInfo)
3021  {
3022  /* Determine which triggers exist on this partition */
3023  has_before_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
3024  resultRelInfo->ri_TrigDesc->trig_insert_before_row);
3025 
3026  has_instead_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
3027  resultRelInfo->ri_TrigDesc->trig_insert_instead_row);
3028 
3029  /*
3030  * Disable multi-inserts when the partition has BEFORE/INSTEAD
3031  * OF triggers, or if the partition is a foreign partition.
3032  */
3033  leafpart_use_multi_insert = insertMethod == CIM_MULTI_CONDITIONAL &&
3034  !has_before_insert_row_trig &&
3035  !has_instead_insert_row_trig &&
3036  resultRelInfo->ri_FdwRoutine == NULL;
3037 
3038  /* Set the multi-insert buffer to use for this partition. */
3039  if (leafpart_use_multi_insert)
3040  {
3041  if (resultRelInfo->ri_CopyMultiInsertBuffer == NULL)
3042  CopyMultiInsertInfoSetupBuffer(&multiInsertInfo,
3043  resultRelInfo);
3044  }
3045  else if (insertMethod == CIM_MULTI_CONDITIONAL &&
3046  !CopyMultiInsertInfoIsEmpty(&multiInsertInfo))
3047  {
3048  /*
3049  * Flush pending inserts if this partition can't use
3050  * batching, so rows are visible to triggers etc.
3051  */
3052  CopyMultiInsertInfoFlush(&multiInsertInfo, resultRelInfo);
3053  }
3054 
3055  if (bistate != NULL)
3056  ReleaseBulkInsertStatePin(bistate);
3057  prevResultRelInfo = resultRelInfo;
3058  }
3059 
3060  /*
3061  * For ExecInsertIndexTuples() to work on the partition's indexes
3062  */
3063  estate->es_result_relation_info = resultRelInfo;
3064 
3065  /*
3066  * If we're capturing transition tuples, we might need to convert
3067  * from the partition rowtype to root rowtype.
3068  */
3069  if (cstate->transition_capture != NULL)
3070  {
3071  if (has_before_insert_row_trig)
3072  {
3073  /*
3074  * If there are any BEFORE triggers on the partition,
3075  * we'll have to be ready to convert their result back to
3076  * tuplestore format.
3077  */
3079  cstate->transition_capture->tcs_map =
3080  resultRelInfo->ri_PartitionInfo->pi_PartitionToRootMap;
3081  }
3082  else
3083  {
3084  /*
3085  * Otherwise, just remember the original unconverted
3086  * tuple, to avoid a needless round trip conversion.
3087  */
3089  cstate->transition_capture->tcs_map = NULL;
3090  }
3091  }
3092 
3093  /*
3094  * We might need to convert from the root rowtype to the partition
3095  * rowtype.
3096  */
3097  map = resultRelInfo->ri_PartitionInfo->pi_RootToPartitionMap;
3098  if (insertMethod == CIM_SINGLE || !leafpart_use_multi_insert)
3099  {
3100  /* non batch insert */
3101  if (map != NULL)
3102  {
3103  TupleTableSlot *new_slot;
3104 
3105  new_slot = resultRelInfo->ri_PartitionInfo->pi_PartitionTupleSlot;
3106  myslot = execute_attr_map_slot(map->attrMap, myslot, new_slot);
3107  }
3108  }
3109  else
3110  {
3111  /*
3112  * Prepare to queue up tuple for later batch insert into
3113  * current partition.
3114  */
3115  TupleTableSlot *batchslot;
3116 
3117  /* no other path available for partitioned table */
3118  Assert(insertMethod == CIM_MULTI_CONDITIONAL);
3119 
3120  batchslot = CopyMultiInsertInfoNextFreeSlot(&multiInsertInfo,
3121  resultRelInfo);
3122 
3123  if (map != NULL)
3124  myslot = execute_attr_map_slot(map->attrMap, myslot,
3125  batchslot);
3126  else
3127  {
3128  /*
3129  * This looks more expensive than it is (Believe me, I
3130  * optimized it away. Twice.). The input is in virtual
3131  * form, and we'll materialize the slot below - for most
3132  * slot types the copy performs the work materialization
3133  * would later require anyway.
3134  */
3135  ExecCopySlot(batchslot, myslot);
3136  myslot = batchslot;
3137  }
3138  }
3139 
3140  /* ensure that triggers etc see the right relation */
3141  myslot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
3142  }
3143 
3144  skip_tuple = false;
3145 
3146  /* BEFORE ROW INSERT Triggers */
3147  if (has_before_insert_row_trig)
3148  {
3149  if (!ExecBRInsertTriggers(estate, resultRelInfo, myslot))
3150  skip_tuple = true; /* "do nothing" */
3151  }
3152 
3153  if (!skip_tuple)
3154  {
3155  /*
3156  * If there is an INSTEAD OF INSERT ROW trigger, let it handle the
3157  * tuple. Otherwise, proceed with inserting the tuple into the
3158  * table or foreign table.
3159  */
3160  if (has_instead_insert_row_trig)
3161  {
3162  ExecIRInsertTriggers(estate, resultRelInfo, myslot);
3163  }
3164  else
3165  {
3166  /* Compute stored generated columns */
3167  if (resultRelInfo->ri_RelationDesc->rd_att->constr &&
3169  ExecComputeStoredGenerated(estate, myslot, CMD_INSERT);
3170 
3171  /*
3172  * If the target is a plain table, check the constraints of
3173  * the tuple.
3174  */
3175  if (resultRelInfo->ri_FdwRoutine == NULL &&
3176  resultRelInfo->ri_RelationDesc->rd_att->constr)
3177  ExecConstraints(resultRelInfo, myslot, estate);
3178 
3179  /*
3180  * Also check the tuple against the partition constraint, if
3181  * there is one; except that if we got here via tuple-routing,
3182  * we don't need to if there's no BR trigger defined on the
3183  * partition.
3184  */
3185  if (resultRelInfo->ri_PartitionCheck &&
3186  (proute == NULL || has_before_insert_row_trig))
3187  ExecPartitionCheck(resultRelInfo, myslot, estate, true);
3188 
3189  /* Store the slot in the multi-insert buffer, when enabled. */
3190  if (insertMethod == CIM_MULTI || leafpart_use_multi_insert)
3191  {
3192  /*
3193  * The slot previously might point into the per-tuple
3194  * context. For batching it needs to be longer lived.
3195  */
3196  ExecMaterializeSlot(myslot);
3197 
3198  /* Add this tuple to the tuple buffer */
3199  CopyMultiInsertInfoStore(&multiInsertInfo,
3200  resultRelInfo, myslot,
3201  cstate->line_buf.len,
3202  cstate->cur_lineno);
3203 
3204  /*
3205  * If enough inserts have queued up, then flush all
3206  * buffers out to their tables.
3207  */
3208  if (CopyMultiInsertInfoIsFull(&multiInsertInfo))
3209  CopyMultiInsertInfoFlush(&multiInsertInfo, resultRelInfo);
3210  }
3211  else
3212  {
3213  List *recheckIndexes = NIL;
3214 
3215  /* OK, store the tuple */
3216  if (resultRelInfo->ri_FdwRoutine != NULL)
3217  {
3218  myslot = resultRelInfo->ri_FdwRoutine->ExecForeignInsert(estate,
3219  resultRelInfo,
3220  myslot,
3221  NULL);
3222 
3223  if (myslot == NULL) /* "do nothing" */
3224  continue; /* next tuple please */
3225 
3226  /*
3227  * AFTER ROW Triggers might reference the tableoid
3228  * column, so (re-)initialize tts_tableOid before
3229  * evaluating them.
3230  */
3231  myslot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
3232  }
3233  else
3234  {
3235  /* OK, store the tuple and create index entries for it */
3236  table_tuple_insert(resultRelInfo->ri_RelationDesc,
3237  myslot, mycid, ti_options, bistate);
3238 
3239  if (resultRelInfo->ri_NumIndices > 0)
3240  recheckIndexes = ExecInsertIndexTuples(myslot,
3241  estate,
3242  false,
3243  NULL,
3244  NIL);
3245  }
3246 
3247  /* AFTER ROW INSERT Triggers */
3248  ExecARInsertTriggers(estate, resultRelInfo, myslot,
3249  recheckIndexes, cstate->transition_capture);
3250 
3251  list_free(recheckIndexes);
3252  }
3253  }
3254 
3255  /*
3256  * We count only tuples not suppressed by a BEFORE INSERT trigger
3257  * or FDW; this is the same definition used by nodeModifyTable.c
3258  * for counting tuples inserted by an INSERT command.
3259  */
3260  processed++;
3261  }
3262  }
3263 
3264  /* Flush any remaining buffered tuples */
3265  if (insertMethod != CIM_SINGLE)
3266  {
3267  if (!CopyMultiInsertInfoIsEmpty(&multiInsertInfo))
3268  CopyMultiInsertInfoFlush(&multiInsertInfo, NULL);
3269  }
3270 
3271  /* Done, clean up */
3272  error_context_stack = errcallback.previous;
3273 
3274  if (bistate != NULL)
3275  FreeBulkInsertState(bistate);
3276 
3277  MemoryContextSwitchTo(oldcontext);
3278 
3279  /*
3280  * In the old protocol, tell pqcomm that we can process normal protocol
3281  * messages again.
3282  */
3283  if (cstate->copy_dest == COPY_OLD_FE)
3284  pq_endmsgread();
3285 
3286  /* Execute AFTER STATEMENT insertion triggers */
3287  ExecASInsertTriggers(estate, target_resultRelInfo, cstate->transition_capture);
3288 
3289  /* Handle queued AFTER triggers */
3290  AfterTriggerEndQuery(estate);
3291 
3292  ExecResetTupleTable(estate->es_tupleTable, false);
3293 
3294  /* Allow the FDW to shut down */
3295  if (target_resultRelInfo->ri_FdwRoutine != NULL &&
3296  target_resultRelInfo->ri_FdwRoutine->EndForeignInsert != NULL)
3297  target_resultRelInfo->ri_FdwRoutine->EndForeignInsert(estate,
3298  target_resultRelInfo);
3299 
3300  /* Tear down the multi-insert buffer data */
3301  if (insertMethod != CIM_SINGLE)
3302  CopyMultiInsertInfoCleanup(&multiInsertInfo);
3303 
3304  ExecCloseIndices(target_resultRelInfo);
3305 
3306  /* Close all the partitioned tables, leaf partitions, and their indices */
3307  if (proute)
3308  ExecCleanupTupleRouting(mtstate, proute);
3309 
3310  /* Close any trigger target relations */
3311  ExecCleanUpTriggerState(estate);
3312 
3313  FreeExecutorState(estate);
3314 
3315  return processed;
3316 }
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition: tableam.c:77
int ri_NumIndices
Definition: execnodes.h:416
Node * whereClause
Definition: copy.c:156
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: tuptable.h:475
#define NIL
Definition: pg_list.h:65
Oid tts_tableOid
Definition: tuptable.h:131
uint32 CommandId
Definition: c.h:527
void ExecInitRangeTable(EState *estate, List *rangeTable)
Definition: execUtils.c:765
void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, Relation partition_root, int instrument_options)
Definition: execMain.c:1277
Relation ri_RelationDesc
Definition: execnodes.h:413
List * range_table
Definition: copy.c:184
static void CopyMultiInsertInfoStore(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri, TupleTableSlot *slot, int tuplen, uint64 lineno)
Definition: copy.c:2625
int errhint(const char *fmt,...)
Definition: elog.c:1071
void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot, List *recheckIndexes, TransitionCaptureState *transition_capture)
Definition: trigger.c:2268
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition: execnodes.h:493
void CopyFromErrorCallback(void *arg)
Definition: copy.c:2233
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
#define ResetPerTupleExprContext(estate)
Definition: executor.h:516
#define TABLE_INSERT_FROZEN
Definition: tableam.h:133
#define castNode(_type_, nodeptr)
Definition: nodes.h:598
BeginForeignInsert_function BeginForeignInsert
Definition: fdwapi.h:215
ResultRelInfo * resultRelInfo
Definition: execnodes.h:1174
ExecForeignInsert_function ExecForeignInsert
Definition: fdwapi.h:211
struct PartitionRoutingInfo * ri_PartitionInfo
Definition: execnodes.h:490
void ExecComputeStoredGenerated(EState *estate, TupleTableSlot *slot, CmdType cmdtype)
static void CopyMultiInsertInfoSetupBuffer(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri)
Definition: copy.c:2356
void ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1897
StringInfoData line_buf
Definition: copy.c:211
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool ThereAreNoPriorRegisteredSnapshots(void)
Definition: snapmgr.c:1689
int errcode(int sqlerrcode)
Definition: elog.c:610
CmdType operation
Definition: execnodes.h:1166
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:103
Datum * tts_values
Definition: tuptable.h:126
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:726
EState * state
Definition: execnodes.h:947
Form_pg_class rd_rel
Definition: rel.h:109
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:370
bool volatile_defexprs
Definition: copy.c:183
void(* callback)(void *arg)
Definition: elog.h:229
struct ErrorContextCallback * previous
Definition: elog.h:228
static void CopyMultiInsertInfoInit(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri, CopyState cstate, EState *estate, CommandId mycid, int ti_options)
Definition: copy.c:2376
static void table_tuple_insert(Relation rel, TupleTableSlot *slot, CommandId cid, int options, struct BulkInsertStateData *bistate)
Definition: tableam.h:1152
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:209
void ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative)
Definition: execIndexing.c:151
CopyDest copy_dest
Definition: copy.c:117
ErrorContextCallback * error_context_stack
Definition: elog.c:92
uint64 cur_lineno
Definition: copy.c:160
bool trig_insert_instead_row
Definition: reltrigger.h:58
void FreeExecutorState(EState *estate)
Definition: execUtils.c:191
Relation rel
Definition: copy.c:130
#define GetPerTupleExprContext(estate)
Definition: executor.h:507
BulkInsertState GetBulkInsertState(void)
Definition: heapam.c:1778
bool trig_insert_new_table
Definition: reltrigger.h:75
bool has_generated_stored
Definition: tupdesc.h:45
TupleConversionMap * pi_RootToPartitionMap
Definition: execPartition.h:37
bool ThereAreNoReadyPortals(void)
Definition: portalmem.c:1209
#define ERROR
Definition: elog.h:43
PlanState ps
Definition: execnodes.h:1165
void ExecCleanupTupleRouting(ModifyTableState *mtstate, PartitionTupleRouting *proute)
bool ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2192
static bool CopyMultiInsertInfoIsFull(CopyMultiInsertInfo *miinfo)
Definition: copy.c:2401
TupleConversionMap * tcs_map
Definition: trigger.h:74
static bool CopyMultiInsertInfoIsEmpty(CopyMultiInsertInfo *miinfo)
Definition: copy.c:2413
List * ExecInsertIndexTuples(TupleTableSlot *slot, EState *estate, bool noDupErr, bool *specConflict, List *arbiterIndexes)
Definition: execIndexing.c:273
TriggerDesc * trigdesc
Definition: rel.h:115
void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation)
Definition: execMain.c:1076
void ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2130
struct TransitionCaptureState * mt_transition_capture
Definition: execnodes.h:1191
bool * tts_isnull
Definition: tuptable.h:128
static void CopyMultiInsertInfoFlush(CopyMultiInsertInfo *miinfo, ResultRelInfo *curr_rri)
Definition: copy.c:2544
TupleConstr * constr
Definition: tupdesc.h:85
ResultRelInfo * es_result_relations
Definition: execnodes.h:525
#define RelationGetRelationName(relation)
Definition: rel.h:490
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:442
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
PartitionTupleRouting * ExecSetupPartitionTupleRouting(EState *estate, ModifyTableState *mtstate, Relation rel)
AttrMap * attrMap
Definition: tupconvert.h:27
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:512
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:425
EState * CreateExecutorState(void)
Definition: execUtils.c:89
SubTransactionId rd_createSubid
Definition: rel.h:102
Definition: copy.c:94
bool trig_insert_before_row
Definition: reltrigger.h:56
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
List * es_tupleTable
Definition: execnodes.h:557
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:1161
void ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo, TransitionCaptureState *transition_capture)
Definition: trigger.c:2181
TransitionCaptureState * MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType)
Definition: trigger.c:4310
int es_num_result_relations
Definition: execnodes.h:526
#define TABLE_INSERT_SKIP_FSM
Definition: tableam.h:132
TupleConversionMap * pi_PartitionToRootMap
Definition: execPartition.h:43
List * ri_PartitionCheck
Definition: execnodes.h:481
TupleDesc rd_att
Definition: rel.h:110
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition: tuptable.h:443
bool freeze
Definition: copy.c:137
Plan * plan
Definition: execnodes.h:945
void pq_endmsgread(void)
Definition: pqcomm.c:1221
#define ereport(elevel,...)
Definition: elog.h:144
void AfterTriggerBeginQuery(void)
Definition: trigger.c:4432
#define makeNode(_type_)
Definition: nodes.h:577
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition: tupconvert.c:177
#define Assert(condition)
Definition: c.h:738
void FreeBulkInsertState(BulkInsertState bistate)
Definition: heapam.c:1792
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:708
bool ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2283
CopyInsertMethod
Definition: copy.c:91
bool NextCopyFrom(CopyState cstate, ExprContext *econtext, Datum *values, bool *nulls)
Definition: copy.c:3630
static TupleTableSlot * CopyMultiInsertInfoNextFreeSlot(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri)
Definition: copy.c:2606
static void CopyMultiInsertInfoCleanup(CopyMultiInsertInfo *miinfo)
Definition: copy.c:2590
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:226
#define InvalidSubTransactionId
Definition: c.h:519
void ReleaseBulkInsertStatePin(BulkInsertState bistate)
Definition: heapam.c:1804
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:512
void ExecCleanUpTriggerState(EState *estate)
Definition: execMain.c:1454
void AfterTriggerEndQuery(EState *estate)
Definition: trigger.c:4452
int errmsg(const char *fmt,...)
Definition: elog.c:824
void list_free(List *list)
Definition: list.c:1376
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
Definition: execMain.c:1783
TransitionCaptureState * transition_capture
Definition: copy.c:187
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:746
ResultRelInfo * ExecFindPartition(ModifyTableState *mtstate, ResultRelInfo *rootResultRelInfo, PartitionTupleRouting *proute, TupleTableSlot *slot, EState *estate)
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:456
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Definition: execIndexing.c:226
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1522
EndForeignInsert_function EndForeignInsert
Definition: fdwapi.h:216
TupleTableSlot * pi_PartitionTupleSlot
Definition: execPartition.h:49
TupleTableSlot * tcs_original_insert_tuple
Definition: trigger.h:83
ExprState * qualexpr
Definition: copy.c:185
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:527

◆ CopyFromErrorCallback()

void CopyFromErrorCallback ( void *  arg)

Definition at line 2233 of file copy.c.

References CopyStateData::binary, CopyStateData::cur_attname, CopyStateData::cur_attval, CopyStateData::cur_lineno, CopyStateData::cur_relname, StringInfoData::data, errcontext, limit_printout_length(), CopyStateData::line_buf, CopyStateData::line_buf_converted, CopyStateData::line_buf_valid, CopyStateData::need_transcoding, pfree(), snprintf, and UINT64_FORMAT.

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

2234 {
2235  CopyState cstate = (CopyState) arg;
2236  char curlineno_str[32];
2237 
2238  snprintf(curlineno_str, sizeof(curlineno_str), UINT64_FORMAT,
2239  cstate->cur_lineno);
2240 
2241  if (cstate->binary)
2242  {
2243  /* can't usefully display the data */
2244  if (cstate->cur_attname)
2245  errcontext("COPY %s, line %s, column %s",
2246  cstate->cur_relname, curlineno_str,
2247  cstate->cur_attname);
2248  else
2249  errcontext("COPY %s, line %s",
2250  cstate->cur_relname, curlineno_str);
2251  }
2252  else
2253  {
2254  if (cstate->cur_attname && cstate->cur_attval)
2255  {
2256  /* error is relevant to a particular column */
2257  char *attval;
2258 
2259  attval = limit_printout_length(cstate->cur_attval);
2260  errcontext("COPY %s, line %s, column %s: \"%s\"",
2261  cstate->cur_relname, curlineno_str,
2262  cstate->cur_attname, attval);
2263  pfree(attval);
2264  }
2265  else if (cstate->cur_attname)
2266  {
2267  /* error is relevant to a particular column, value is NULL */
2268  errcontext("COPY %s, line %s, column %s: null input",
2269  cstate->cur_relname, curlineno_str,
2270  cstate->cur_attname);
2271  }
2272  else
2273  {
2274  /*
2275  * Error is relevant to a particular line.
2276  *
2277  * If line_buf still contains the correct line, and it's already
2278  * transcoded, print it. If it's still in a foreign encoding, it's
2279  * quite likely that the error is precisely a failure to do
2280  * encoding conversion (ie, bad data). We dare not try to convert
2281  * it, and at present there's no way to regurgitate it without
2282  * conversion. So we have to punt and just report the line number.
2283  */
2284  if (cstate->line_buf_valid &&
2285  (cstate->line_buf_converted || !cstate->need_transcoding))
2286  {
2287  char *lineval;
2288 
2289  lineval = limit_printout_length(cstate->line_buf.data);
2290  errcontext("COPY %s, line %s: \"%s\"",
2291  cstate->cur_relname, curlineno_str, lineval);
2292  pfree(lineval);
2293  }
2294  else
2295  {
2296  errcontext("COPY %s, line %s",
2297  cstate->cur_relname, curlineno_str);
2298  }
2299  }
2300  }
2301 }
bool binary
Definition: copy.c:136
bool need_transcoding
Definition: copy.c:126
StringInfoData line_buf
Definition: copy.c:211
bool line_buf_valid
Definition: copy.c:213
bool line_buf_converted
Definition: copy.c:212
uint64 cur_lineno
Definition: copy.c:160
const char * cur_attname
Definition: copy.c:161
void pfree(void *pointer)
Definition: mcxt.c:1056
static char * limit_printout_length(const char *str)
Definition: copy.c:2309
const char * cur_relname
Definition: copy.c:159
#define errcontext
Definition: elog.h:185
struct CopyStateData * CopyState
Definition: copy.h:23
void * arg
const char * cur_attval
Definition: copy.c:162
#define snprintf
Definition: port.h:193
#define UINT64_FORMAT
Definition: c.h:410

◆ CopyGetAttnums()

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

Definition at line 5016 of file copy.c.

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 BeginCopy(), and DoCopy().

5017 {
5018  List *attnums = NIL;
5019 
5020  if (attnamelist == NIL)
5021  {
5022  /* Generate default column list */
5023  int attr_count = tupDesc->natts;
5024  int i;
5025 
5026  for (i = 0; i < attr_count; i++)
5027  {
5028  if (TupleDescAttr(tupDesc, i)->attisdropped)
5029  continue;
5030  if (TupleDescAttr(tupDesc, i)->attgenerated)
5031  continue;
5032  attnums = lappend_int(attnums, i + 1);
5033  }
5034  }
5035  else
5036  {
5037  /* Validate the user-supplied list and extract attnums */
5038  ListCell *l;
5039 
5040  foreach(l, attnamelist)
5041  {
5042  char *name = strVal(lfirst(l));
5043  int attnum;
5044  int i;
5045 
5046  /* Lookup column name */
5047  attnum = InvalidAttrNumber;
5048  for (i = 0; i < tupDesc->natts; i++)
5049  {
5050  Form_pg_attribute att = TupleDescAttr(tupDesc, i);
5051 
5052  if (att->attisdropped)
5053  continue;
5054  if (namestrcmp(&(att->attname), name) == 0)
5055  {
5056  if (att->attgenerated)
5057  ereport(ERROR,
5058  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
5059  errmsg("column \"%s\" is a generated column",
5060  name),
5061  errdetail("Generated columns cannot be used in COPY.")));
5062  attnum = att->attnum;
5063  break;
5064  }
5065  }
5066  if (attnum == InvalidAttrNumber)
5067  {
5068  if (rel != NULL)
5069  ereport(ERROR,
5070  (errcode(ERRCODE_UNDEFINED_COLUMN),
5071  errmsg("column \"%s\" of relation \"%s\" does not exist",
5072  name, RelationGetRelationName(rel))));
5073  else
5074  ereport(ERROR,
5075  (errcode(ERRCODE_UNDEFINED_COLUMN),
5076  errmsg("column \"%s\" does not exist",
5077  name)));
5078  }
5079  /* Check for duplicates */
5080  if (list_member_int(attnums, attnum))
5081  ereport(ERROR,
5082  (errcode(ERRCODE_DUPLICATE_COLUMN),
5083  errmsg("column \"%s\" specified more than once",
5084  name)));
5085  attnums = lappend_int(attnums, attnum);
5086  }
5087  }
5088 
5089  return attnums;
5090 }
#define NIL
Definition: pg_list.h:65
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:610
int namestrcmp(Name name, const char *str)
Definition: name.c:287
#define ERROR
Definition: elog.h:43
bool list_member_int(const List *list, int datum)
Definition: list.c:654
int errdetail(const char *fmt,...)
Definition: elog.c:957
#define RelationGetRelationName(relation)
Definition: rel.h:490
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
List * lappend_int(List *list, int datum)
Definition: list.c:339
int16 attnum
Definition: pg_attribute.h:79
#define ereport(elevel,...)
Definition: elog.h:144
#define lfirst(lc)
Definition: pg_list.h:190
const char * name
Definition: encode.c:561
#define InvalidAttrNumber
Definition: attnum.h:23
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
Definition: pg_list.h:50

◆ CopyGetData()

static int CopyGetData ( CopyState  cstate,
void *  databuf,
int  minread,
int  maxread 
)
static

Definition at line 610 of file copy.c.

References COPY_CALLBACK, CopyStateData::copy_dest, COPY_FILE, CopyStateData::copy_file, COPY_NEW_FE, COPY_OLD_FE, StringInfoData::cursor, CopyStateData::data_source_cb, ereport, errcode(), errcode_for_file_access(), errmsg(), ERROR, CopyStateData::fe_msgbuf, HOLD_CANCEL_INTERRUPTS, StringInfoData::len, pq_copymsgbytes(), pq_getbyte(), pq_getbytes(), pq_getmessage(), pq_getmsgstring(), pq_startmsgread(), CopyStateData::reached_eof, and RESUME_CANCEL_INTERRUPTS.

Referenced by BeginCopyFrom(), CopyGetInt16(), CopyGetInt32(), CopyLoadRawBuf(), CopyReadBinaryAttribute(), and NextCopyFrom().

611 {
612  int bytesread = 0;
613 
614  switch (cstate->copy_dest)
615  {
616  case COPY_FILE:
617  bytesread = fread(databuf, 1, maxread, cstate->copy_file);
618  if (ferror(cstate->copy_file))
619  ereport(ERROR,
621  errmsg("could not read from COPY file: %m")));
622  if (bytesread == 0)
623  cstate->reached_eof = true;
624  break;
625  case COPY_OLD_FE:
626 
627  /*
628  * We cannot read more than minread bytes (which in practice is 1)
629  * because old protocol doesn't have any clear way of separating
630  * the COPY stream from following data. This is slow, but not any
631  * slower than the code path was originally, and we don't care
632  * much anymore about the performance of old protocol.
633  */
634  if (pq_getbytes((char *) databuf, minread))
635  {
636  /* Only a \. terminator is legal EOF in old protocol */
637  ereport(ERROR,
638  (errcode(ERRCODE_CONNECTION_FAILURE),
639  errmsg("unexpected EOF on client connection with an open transaction")));
640  }
641  bytesread = minread;
642  break;
643  case COPY_NEW_FE:
644  while (maxread > 0 && bytesread < minread && !cstate->reached_eof)
645  {
646  int avail;
647 
648  while (cstate->fe_msgbuf->cursor >= cstate->fe_msgbuf->len)
649  {
650  /* Try to receive another message */
651  int mtype;
652 
653  readmessage:
655  pq_startmsgread();
656  mtype = pq_getbyte();
657  if (mtype == EOF)
658  ereport(ERROR,
659  (errcode(ERRCODE_CONNECTION_FAILURE),
660  errmsg("unexpected EOF on client connection with an open transaction")));
661  if (pq_getmessage(cstate->fe_msgbuf, 0))
662  ereport(ERROR,
663  (errcode(ERRCODE_CONNECTION_FAILURE),
664  errmsg("unexpected EOF on client connection with an open transaction")));
666  switch (mtype)
667  {
668  case 'd': /* CopyData */
669  break;
670  case 'c': /* CopyDone */
671  /* COPY IN correctly terminated by frontend */
672  cstate->reached_eof = true;
673  return bytesread;
674  case 'f': /* CopyFail */
675  ereport(ERROR,
676  (errcode(ERRCODE_QUERY_CANCELED),
677  errmsg("COPY from stdin failed: %s",
678  pq_getmsgstring(cstate->fe_msgbuf))));
679  break;
680  case 'H': /* Flush */
681  case 'S': /* Sync */
682 
683  /*
684  * Ignore Flush/Sync for the convenience of client
685  * libraries (such as libpq) that may send those
686  * without noticing that the command they just
687  * sent was COPY.
688  */
689  goto readmessage;
690  default:
691  ereport(ERROR,
692  (errcode(ERRCODE_PROTOCOL_VIOLATION),
693  errmsg("unexpected message type 0x%02X during COPY from stdin",
694  mtype)));
695  break;
696  }
697  }
698  avail = cstate->fe_msgbuf->len - cstate->fe_msgbuf->cursor;
699  if (avail > maxread)
700  avail = maxread;
701  pq_copymsgbytes(cstate->fe_msgbuf, databuf, avail);
702  databuf = (void *) ((char *) databuf + avail);
703  maxread -= avail;
704  bytesread += avail;
705  }
706  break;
707  case COPY_CALLBACK:
708  bytesread = cstate->data_source_cb(databuf, minread, maxread);
709  break;
710  }
711 
712  return bytesread;
713 }
#define HOLD_CANCEL_INTERRUPTS()
Definition: miscadmin.h:124
const char * pq_getmsgstring(StringInfo msg)
Definition: pqformat.c:581
int errcode(int sqlerrcode)
Definition: elog.c:610
CopyDest copy_dest
Definition: copy.c:117
Definition: copy.c:71
copy_data_source_cb data_source_cb
Definition: copy.c:135
#define ERROR
Definition: elog.h:43
void pq_startmsgread(void)
Definition: pqcomm.c:1197
int pq_getbytes(char *s, size_t len)
Definition: pqcomm.c:1081
int errcode_for_file_access(void)
Definition: elog.c:633
int pq_getmessage(StringInfo s, int maxlen)
Definition: pqcomm.c:1259
int pq_getbyte(void)
Definition: pqcomm.c:987
#define ereport(elevel,...)
Definition: elog.h:144
StringInfo fe_msgbuf
Definition: copy.c:119
bool reached_eof
Definition: copy.c:122
void pq_copymsgbytes(StringInfo msg, char *buf, int datalen)
Definition: pqformat.c:530
int errmsg(const char *fmt,...)
Definition: elog.c:824
FILE * copy_file
Definition: copy.c:118
#define RESUME_CANCEL_INTERRUPTS()
Definition: miscadmin.h:126

◆ CopyGetInt16()

static bool CopyGetInt16 ( CopyState  cstate,
int16 val 
)
static

Definition at line 767 of file copy.c.

References buf, CopyGetData(), and pg_ntoh16.

Referenced by NextCopyFrom().

768 {
769  uint16 buf;
770 
771  if (CopyGetData(cstate, &buf, sizeof(buf), sizeof(buf)) != sizeof(buf))
772  {
773  *val = 0; /* suppress compiler warning */
774  return false;
775  }
776  *val = (int16) pg_ntoh16(buf);
777  return true;
778 }
signed short int16
Definition: c.h:354
#define pg_ntoh16(x)
Definition: pg_bswap.h:124
unsigned short uint16
Definition: c.h:366
static int CopyGetData(CopyState cstate, void *databuf, int minread, int maxread)
Definition: copy.c:610
static char * buf
Definition: pg_test_fsync.c:67
long val
Definition: informix.c:664

◆ CopyGetInt32()

static bool CopyGetInt32 ( CopyState  cstate,
int32 val 
)
static

Definition at line 738 of file copy.c.

References buf, CopyGetData(), and pg_ntoh32.

Referenced by BeginCopyFrom(), and CopyReadBinaryAttribute().

739 {
740  uint32 buf;
741 
742  if (CopyGetData(cstate, &buf, sizeof(buf), sizeof(buf)) != sizeof(buf))
743  {
744  *val = 0; /* suppress compiler warning */
745  return false;
746  }
747  *val = (int32) pg_ntoh32(buf);
748  return true;
749 }
signed int int32
Definition: c.h:355
#define pg_ntoh32(x)
Definition: pg_bswap.h:125
static int CopyGetData(CopyState cstate, void *databuf, int minread, int maxread)
Definition: copy.c:610
static char * buf
Definition: pg_test_fsync.c:67
unsigned int uint32
Definition: c.h:367
long val
Definition: informix.c:664

◆ CopyLoadRawBuf()

static bool CopyLoadRawBuf ( CopyState  cstate)
static

Definition at line 792 of file copy.c.

References CopyGetData(), CopyStateData::raw_buf, CopyStateData::raw_buf_index, CopyStateData::raw_buf_len, and RAW_BUF_SIZE.

Referenced by CopyReadLine(), and CopyReadLineText().

793 {
794  int nbytes;
795  int inbytes;
796 
797  if (cstate->raw_buf_index < cstate->raw_buf_len)
798  {
799  /* Copy down the unprocessed data */
800  nbytes = cstate->raw_buf_len - cstate->raw_buf_index;
801  memmove(cstate->raw_buf, cstate->raw_buf + cstate->raw_buf_index,
802  nbytes);
803  }
804  else
805  nbytes = 0; /* no data need be saved */
806 
807  inbytes = CopyGetData(cstate, cstate->raw_buf + nbytes,
808  1, RAW_BUF_SIZE - nbytes);
809  nbytes += inbytes;
810  cstate->raw_buf[nbytes] = '\0';
811  cstate->raw_buf_index = 0;
812  cstate->raw_buf_len = nbytes;
813  return (inbytes > 0);
814 }
int raw_buf_index
Definition: copy.c:224
static int CopyGetData(CopyState cstate, void *databuf, int minread, int maxread)
Definition: copy.c:610
char * raw_buf
Definition: copy.c:223
int raw_buf_len
Definition: copy.c:225
#define RAW_BUF_SIZE
Definition: copy.c:222

◆ CopyMultiInsertBufferCleanup()

static void CopyMultiInsertBufferCleanup ( CopyMultiInsertInfo miinfo,
CopyMultiInsertBuffer buffer 
)
inlinestatic

Definition at line 2510 of file copy.c.

References Assert, CopyMultiInsertBuffer::bistate, ExecDropSingleTupleTableSlot(), FreeBulkInsertState(), i, MAX_BUFFERED_TUPLES, CopyMultiInsertBuffer::nused, pfree(), CopyMultiInsertBuffer::resultRelInfo, ResultRelInfo::ri_CopyMultiInsertBuffer, ResultRelInfo::ri_RelationDesc, CopyMultiInsertBuffer::slots, table_finish_bulk_insert(), and CopyMultiInsertInfo::ti_options.

Referenced by CopyMultiInsertInfoCleanup(), and CopyMultiInsertInfoFlush().

2512 {
2513  int i;
2514 
2515  /* Ensure buffer was flushed */
2516  Assert(buffer->nused == 0);
2517 
2518  /* Remove back-link to ourself */
2519  buffer->resultRelInfo->ri_CopyMultiInsertBuffer = NULL;
2520 
2521  FreeBulkInsertState(buffer->bistate);
2522 
2523  /* Since we only create slots on demand, just drop the non-null ones. */
2524  for (i = 0; i < MAX_BUFFERED_TUPLES && buffer->slots[i] != NULL; i++)
2525  ExecDropSingleTupleTableSlot(buffer->slots[i]);
2526 
2528  miinfo->ti_options);
2529 
2530  pfree(buffer);
2531 }
Relation ri_RelationDesc
Definition: execnodes.h:413
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition: execnodes.h:493
#define MAX_BUFFERED_TUPLES
Definition: copy.c:246
static void table_finish_bulk_insert(Relation rel, int options)
Definition: tableam.h:1345
ResultRelInfo * resultRelInfo
Definition: copy.c:261
void pfree(void *pointer)
Definition: mcxt.c:1056
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1224
BulkInsertState bistate
Definition: copy.c:262
#define Assert(condition)
Definition: c.h:738
void FreeBulkInsertState(BulkInsertState bistate)
Definition: heapam.c:1792
TupleTableSlot * slots[MAX_BUFFERED_TUPLES]
Definition: copy.c:260
int i

◆ CopyMultiInsertBufferFlush()

static void CopyMultiInsertBufferFlush ( CopyMultiInsertInfo miinfo,
CopyMultiInsertBuffer buffer 
)
inlinestatic

Definition at line 2422 of file copy.c.

References CopyMultiInsertBuffer::bistate, CopyMultiInsertInfo::cstate, CopyStateData::cur_lineno, EState::es_result_relation_info, CopyMultiInsertInfo::estate, ExecARInsertTriggers(), ExecClearTuple(), ExecInsertIndexTuples(), GetPerTupleMemoryContext, i, CopyStateData::line_buf_valid, CopyMultiInsertBuffer::linenos, list_free(), MemoryContextSwitchTo(), CopyMultiInsertInfo::mycid, NIL, CopyMultiInsertBuffer::nused, CopyMultiInsertBuffer::resultRelInfo, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, CopyMultiInsertBuffer::slots, table_multi_insert(), CopyMultiInsertInfo::ti_options, CopyStateData::transition_capture, TriggerDesc::trig_insert_after_row, and TriggerDesc::trig_insert_new_table.

Referenced by CopyMultiInsertInfoFlush().

2424 {
2425  MemoryContext oldcontext;
2426  int i;
2427  uint64 save_cur_lineno;
2428  CopyState cstate = miinfo->cstate;
2429  EState *estate = miinfo->estate;
2430  CommandId mycid = miinfo->mycid;
2431  int ti_options = miinfo->ti_options;
2432  bool line_buf_valid = cstate->line_buf_valid;
2433  int nused = buffer->nused;
2434  ResultRelInfo *resultRelInfo = buffer->resultRelInfo;
2435  TupleTableSlot **slots = buffer->slots;
2436 
2437  /* Set es_result_relation_info to the ResultRelInfo we're flushing. */
2438  estate->es_result_relation_info = resultRelInfo;
2439 
2440  /*
2441  * Print error context information correctly, if one of the operations
2442  * below fail.
2443  */
2444  cstate->line_buf_valid = false;
2445  save_cur_lineno = cstate->cur_lineno;
2446 
2447  /*
2448  * table_multi_insert may leak memory, so switch to short-lived memory
2449  * context before calling it.
2450  */
2451  oldcontext = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
2452  table_multi_insert(resultRelInfo->ri_RelationDesc,
2453  slots,
2454  nused,
2455  mycid,
2456  ti_options,
2457  buffer->bistate);
2458  MemoryContextSwitchTo(oldcontext);
2459 
2460  for (i = 0; i < nused; i++)
2461  {
2462  /*
2463  * If there are any indexes, update them for all the inserted tuples,
2464  * and run AFTER ROW INSERT triggers.
2465  */
2466  if (resultRelInfo->ri_NumIndices > 0)
2467  {
2468  List *recheckIndexes;
2469 
2470  cstate->cur_lineno = buffer->linenos[i];
2471  recheckIndexes =
2472  ExecInsertIndexTuples(buffer->slots[i], estate, false, NULL,
2473  NIL);
2474  ExecARInsertTriggers(estate, resultRelInfo,
2475  slots[i], recheckIndexes,
2476  cstate->transition_capture);
2477  list_free(recheckIndexes);
2478  }
2479 
2480  /*
2481  * There's no indexes, but see if we need to run AFTER ROW INSERT
2482  * triggers anyway.
2483  */
2484  else if (resultRelInfo->ri_TrigDesc != NULL &&
2485  (resultRelInfo->ri_TrigDesc->trig_insert_after_row ||
2486  resultRelInfo->ri_TrigDesc->trig_insert_new_table))
2487  {
2488  cstate->cur_lineno = buffer->linenos[i];
2489  ExecARInsertTriggers(estate, resultRelInfo,
2490  slots[i], NIL, cstate->transition_capture);
2491  }
2492 
2493  ExecClearTuple(slots[i]);
2494  }
2495 
2496  /* Mark that all slots are free */
2497  buffer->nused = 0;
2498 
2499  /* reset cur_lineno and line_buf_valid to what they were */
2500  cstate->line_buf_valid = line_buf_valid;
2501  cstate->cur_lineno = save_cur_lineno;
2502 }
int ri_NumIndices
Definition: execnodes.h:416
#define NIL
Definition: pg_list.h:65
uint32 CommandId
Definition: c.h:527
Relation ri_RelationDesc
Definition: execnodes.h:413
void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot, List *recheckIndexes, TransitionCaptureState *transition_capture)
Definition: trigger.c:2268
EState * estate
Definition: copy.c:279
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
CommandId mycid
Definition: copy.c:280
uint64 linenos[MAX_BUFFERED_TUPLES]
Definition: copy.c:264
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool line_buf_valid
Definition: copy.c:213
ResultRelInfo * resultRelInfo
Definition: copy.c:261
uint64 cur_lineno
Definition: copy.c:160
bool trig_insert_new_table
Definition: reltrigger.h:75
List * ExecInsertIndexTuples(TupleTableSlot *slot, EState *estate, bool noDupErr, bool *specConflict, List *arbiterIndexes)
Definition: execIndexing.c:273
bool trig_insert_after_row
Definition: reltrigger.h:57
static void table_multi_insert(Relation rel, TupleTableSlot **slots, int nslots, CommandId cid, int options, struct BulkInsertStateData *bistate)
Definition: tableam.h:1207
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:425
BulkInsertState bistate
Definition: copy.c:262
TupleTableSlot * slots[MAX_BUFFERED_TUPLES]
Definition: copy.c:260
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:512
CopyState cstate
Definition: copy.c:278
void list_free(List *list)
Definition: list.c:1376
int i
TransitionCaptureState * transition_capture
Definition: copy.c:187
Definition: pg_list.h:50
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:527

◆ CopyMultiInsertBufferInit()

static CopyMultiInsertBuffer* CopyMultiInsertBufferInit ( ResultRelInfo rri)
static

Definition at line 2339 of file copy.c.

References CopyMultiInsertBuffer::bistate, GetBulkInsertState(), MAX_BUFFERED_TUPLES, CopyMultiInsertBuffer::nused, palloc(), CopyMultiInsertBuffer::resultRelInfo, and CopyMultiInsertBuffer::slots.

Referenced by CopyMultiInsertInfoSetupBuffer().

2340 {
2341  CopyMultiInsertBuffer *buffer;
2342 
2343  buffer = (CopyMultiInsertBuffer *) palloc(sizeof(CopyMultiInsertBuffer));
2344  memset(buffer->slots, 0, sizeof(TupleTableSlot *) * MAX_BUFFERED_TUPLES);
2345  buffer->resultRelInfo = rri;
2346  buffer->bistate = GetBulkInsertState();
2347  buffer->nused = 0;
2348 
2349  return buffer;
2350 }
#define MAX_BUFFERED_TUPLES
Definition: copy.c:246
ResultRelInfo * resultRelInfo
Definition: copy.c:261
BulkInsertState GetBulkInsertState(void)
Definition: heapam.c:1778
BulkInsertState bistate
Definition: copy.c:262
TupleTableSlot * slots[MAX_BUFFERED_TUPLES]
Definition: copy.c:260
void * palloc(Size size)
Definition: mcxt.c:949

◆ CopyMultiInsertInfoCleanup()

static void CopyMultiInsertInfoCleanup ( CopyMultiInsertInfo miinfo)
inlinestatic

Definition at line 2590 of file copy.c.

References CopyMultiInsertBufferCleanup(), lfirst, list_free(), and CopyMultiInsertInfo::multiInsertBuffers.

Referenced by CopyFrom().

2591 {
2592  ListCell *lc;
2593 
2594  foreach(lc, miinfo->multiInsertBuffers)
2595  CopyMultiInsertBufferCleanup(miinfo, lfirst(lc));
2596 
2597  list_free(miinfo->multiInsertBuffers);
2598 }
#define lfirst(lc)
Definition: pg_list.h:190
static void CopyMultiInsertBufferCleanup(CopyMultiInsertInfo *miinfo, CopyMultiInsertBuffer *buffer)
Definition: copy.c:2510
void list_free(List *list)
Definition: list.c:1376
List * multiInsertBuffers
Definition: copy.c:275

◆ CopyMultiInsertInfoFlush()

static void CopyMultiInsertInfoFlush ( CopyMultiInsertInfo miinfo,
ResultRelInfo curr_rri 
)
inlinestatic

Definition at line 2544 of file copy.c.

References CopyMultiInsertInfo::bufferedBytes, CopyMultiInsertInfo::bufferedTuples, CopyMultiInsertBufferCleanup(), CopyMultiInsertBufferFlush(), lappend(), lfirst, linitial, list_delete_first(), list_length(), MAX_PARTITION_BUFFERS, CopyMultiInsertInfo::multiInsertBuffers, and CopyMultiInsertBuffer::resultRelInfo.

Referenced by CopyFrom().

2545 {
2546  ListCell *lc;
2547 
2548  foreach(lc, miinfo->multiInsertBuffers)
2549  {
2551 
2552  CopyMultiInsertBufferFlush(miinfo, buffer);
2553  }
2554 
2555  miinfo->bufferedTuples = 0;
2556  miinfo->bufferedBytes = 0;
2557 
2558  /*
2559  * Trim the list of tracked buffers down if it exceeds the limit. Here we
2560  * remove buffers starting with the ones we created first. It seems more
2561  * likely that these older ones are less likely to be needed than ones
2562  * that were just created.
2563  */
2565  {
2566  CopyMultiInsertBuffer *buffer;
2567 
2568  buffer = (CopyMultiInsertBuffer *) linitial(miinfo->multiInsertBuffers);
2569 
2570  /*
2571  * We never want to remove the buffer that's currently being used, so
2572  * if we happen to find that then move it to the end of the list.
2573  */
2574  if (buffer->resultRelInfo == curr_rri)
2575  {
2577  miinfo->multiInsertBuffers = lappend(miinfo->multiInsertBuffers, buffer);
2578  buffer = (CopyMultiInsertBuffer *) linitial(miinfo->multiInsertBuffers);
2579  }
2580 
2581  CopyMultiInsertBufferCleanup(miinfo, buffer);
2583  }
2584 }
ResultRelInfo * resultRelInfo
Definition: copy.c:261
#define linitial(l)
Definition: pg_list.h:195
static void CopyMultiInsertBufferFlush(CopyMultiInsertInfo *miinfo, CopyMultiInsertBuffer *buffer)
Definition: copy.c:2422
List * lappend(List *list, void *datum)
Definition: list.c:321
int bufferedTuples
Definition: copy.c:276
#define MAX_PARTITION_BUFFERS
Definition: copy.c:255
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
static void CopyMultiInsertBufferCleanup(CopyMultiInsertInfo *miinfo, CopyMultiInsertBuffer *buffer)
Definition: copy.c:2510
List * multiInsertBuffers
Definition: copy.c:275
List * list_delete_first(List *list)
Definition: list.c:860

◆ CopyMultiInsertInfoInit()

static void CopyMultiInsertInfoInit ( CopyMultiInsertInfo miinfo,
ResultRelInfo rri,
CopyState  cstate,
EState estate,
CommandId  mycid,
int  ti_options 
)
static

Definition at line 2376 of file copy.c.

References CopyMultiInsertInfo::bufferedBytes, CopyMultiInsertInfo::bufferedTuples, CopyMultiInsertInfoSetupBuffer(), CopyMultiInsertInfo::cstate, CopyMultiInsertInfo::estate, CopyMultiInsertInfo::multiInsertBuffers, CopyMultiInsertInfo::mycid, NIL, RelationData::rd_rel, ResultRelInfo::ri_RelationDesc, and CopyMultiInsertInfo::ti_options.

Referenced by CopyFrom().

2379 {
2380  miinfo->multiInsertBuffers = NIL;
2381  miinfo->bufferedTuples = 0;
2382  miinfo->bufferedBytes = 0;
2383  miinfo->cstate = cstate;
2384  miinfo->estate = estate;
2385  miinfo->mycid = mycid;
2386  miinfo->ti_options = ti_options;
2387 
2388  /*
2389  * Only setup the buffer when not dealing with a partitioned table.
2390  * Buffers for partitioned tables will just be setup when we need to send
2391  * tuples their way for the first time.
2392  */
2393  if (rri->ri_RelationDesc->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
2394  CopyMultiInsertInfoSetupBuffer(miinfo, rri);
2395 }
#define NIL
Definition: pg_list.h:65
Relation ri_RelationDesc
Definition: execnodes.h:413
EState * estate
Definition: copy.c:279
static void CopyMultiInsertInfoSetupBuffer(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri)
Definition: copy.c:2356
CommandId mycid
Definition: copy.c:280
Form_pg_class rd_rel
Definition: rel.h:109
int bufferedTuples
Definition: copy.c:276
CopyState cstate
Definition: copy.c:278
List * multiInsertBuffers
Definition: copy.c:275

◆ CopyMultiInsertInfoIsEmpty()

static bool CopyMultiInsertInfoIsEmpty ( CopyMultiInsertInfo miinfo)
inlinestatic

Definition at line 2413 of file copy.c.

References CopyMultiInsertInfo::bufferedTuples.

Referenced by CopyFrom().

2414 {
2415  return miinfo->bufferedTuples == 0;
2416 }
int bufferedTuples
Definition: copy.c:276

◆ CopyMultiInsertInfoIsFull()

static bool CopyMultiInsertInfoIsFull ( CopyMultiInsertInfo miinfo)
inlinestatic

Definition at line 2401 of file copy.c.

References CopyMultiInsertInfo::bufferedBytes, CopyMultiInsertInfo::bufferedTuples, MAX_BUFFERED_BYTES, and MAX_BUFFERED_TUPLES.

Referenced by CopyFrom().

2402 {
2403  if (miinfo->bufferedTuples >= MAX_BUFFERED_TUPLES ||
2404  miinfo->bufferedBytes >= MAX_BUFFERED_BYTES)
2405  return true;
2406  return false;
2407 }
#define MAX_BUFFERED_TUPLES
Definition: copy.c:246
#define MAX_BUFFERED_BYTES
Definition: copy.c:252
int bufferedTuples
Definition: copy.c:276

◆ CopyMultiInsertInfoNextFreeSlot()

static TupleTableSlot* CopyMultiInsertInfoNextFreeSlot ( CopyMultiInsertInfo miinfo,
ResultRelInfo rri 
)
inlinestatic

Definition at line 2606 of file copy.c.

References Assert, MAX_BUFFERED_TUPLES, CopyMultiInsertBuffer::nused, ResultRelInfo::ri_CopyMultiInsertBuffer, ResultRelInfo::ri_RelationDesc, CopyMultiInsertBuffer::slots, and table_slot_create().

Referenced by CopyFrom().

2608 {
2610  int nused = buffer->nused;
2611 
2612  Assert(buffer != NULL);
2613  Assert(nused < MAX_BUFFERED_TUPLES);
2614 
2615  if (buffer->slots[nused] == NULL)
2616  buffer->slots[nused] = table_slot_create(rri->ri_RelationDesc, NULL);
2617  return buffer->slots[nused];
2618 }
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition: tableam.c:77
Relation ri_RelationDesc
Definition: execnodes.h:413
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition: execnodes.h:493
#define MAX_BUFFERED_TUPLES
Definition: copy.c:246
#define Assert(condition)
Definition: c.h:738
TupleTableSlot * slots[MAX_BUFFERED_TUPLES]
Definition: copy.c:260

◆ CopyMultiInsertInfoSetupBuffer()

static void CopyMultiInsertInfoSetupBuffer ( CopyMultiInsertInfo miinfo,
ResultRelInfo rri 
)
inlinestatic

Definition at line 2356 of file copy.c.

References CopyMultiInsertBufferInit(), lappend(), CopyMultiInsertInfo::multiInsertBuffers, and ResultRelInfo::ri_CopyMultiInsertBuffer.

Referenced by CopyFrom(), and CopyMultiInsertInfoInit().

2358 {
2359  CopyMultiInsertBuffer *buffer;
2360 
2361  buffer = CopyMultiInsertBufferInit(rri);
2362 
2363  /* Setup back-link so we can easily find this buffer again */
2364  rri->ri_CopyMultiInsertBuffer = buffer;
2365  /* Record that we're tracking this buffer */
2366  miinfo->multiInsertBuffers = lappend(miinfo->multiInsertBuffers, buffer);
2367 }
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition: execnodes.h:493
List * lappend(List *list, void *datum)
Definition: list.c:321
static CopyMultiInsertBuffer * CopyMultiInsertBufferInit(ResultRelInfo *rri)
Definition: copy.c:2339
List * multiInsertBuffers
Definition: copy.c:275

◆ CopyMultiInsertInfoStore()

static void CopyMultiInsertInfoStore ( CopyMultiInsertInfo miinfo,
ResultRelInfo rri,
TupleTableSlot slot,
int  tuplen,
uint64  lineno 
)
inlinestatic

Definition at line 2625 of file copy.c.

References Assert, CopyMultiInsertInfo::bufferedBytes, CopyMultiInsertInfo::bufferedTuples, CopyMultiInsertBuffer::linenos, CopyMultiInsertBuffer::nused, ResultRelInfo::ri_CopyMultiInsertBuffer, and CopyMultiInsertBuffer::slots.

Referenced by CopyFrom().

2627 {
2629 
2630  Assert(buffer != NULL);
2631  Assert(slot == buffer->slots[buffer->nused]);
2632 
2633  /* Store the line number so we can properly report any errors later */
2634  buffer->linenos[buffer->nused] = lineno;
2635 
2636  /* Record this slot as being used */
2637  buffer->nused++;
2638 
2639  /* Update how many tuples are stored and their size */
2640  miinfo->bufferedTuples++;
2641  miinfo->bufferedBytes += tuplen;
2642 }
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition: execnodes.h:493
uint64 linenos[MAX_BUFFERED_TUPLES]
Definition: copy.c:264
int bufferedTuples
Definition: copy.c:276
#define Assert(condition)
Definition: c.h:738
TupleTableSlot * slots[MAX_BUFFERED_TUPLES]
Definition: copy.c:260

◆ CopyOneRowTo()

static void CopyOneRowTo ( CopyState  cstate,
TupleTableSlot slot 
)
static

Definition at line 2155 of file copy.c.

References attnum, CopyStateData::attnumlist, CopyStateData::binary, CopyAttributeOutCSV(), CopyAttributeOutText(), CopySendChar(), CopySendData(), CopySendEndOfRow(), CopySendInt16(), CopySendInt32(), CopySendString(), CopyStateData::csv_mode, cur, CopyStateData::delim, CopyStateData::force_quote_flags, lfirst_int, list_length(), MemoryContextReset(), MemoryContextSwitchTo(), CopyStateData::null_print_client, CopyStateData::out_functions, OutputFunctionCall(), CopyStateData::rowcontext, SendFunctionCall(), slot_getallattrs(), TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, value, VARDATA, VARHDRSZ, and VARSIZE.

Referenced by copy_dest_receive(), and CopyTo().

2156 {
2157  bool need_delim = false;
2158  FmgrInfo *out_functions = cstate->out_functions;
2159  MemoryContext oldcontext;
2160  ListCell *cur;
2161  char *string;
2162 
2163  MemoryContextReset(cstate->rowcontext);
2164  oldcontext = MemoryContextSwitchTo(cstate->rowcontext);
2165 
2166  if (cstate->binary)
2167  {
2168  /* Binary per-tuple header */
2169  CopySendInt16(cstate, list_length(cstate->attnumlist));
2170  }
2171 
2172  /* Make sure the tuple is fully deconstructed */
2173  slot_getallattrs(slot);
2174 
2175  foreach(cur, cstate->attnumlist)
2176  {
2177  int attnum = lfirst_int(cur);
2178  Datum value = slot->tts_values[attnum - 1];
2179  bool isnull = slot->tts_isnull[attnum - 1];
2180 
2181  if (!cstate->binary)
2182  {
2183  if (need_delim)
2184  CopySendChar(cstate, cstate->delim[0]);
2185  need_delim = true;
2186  }
2187 
2188  if (isnull)
2189  {
2190  if (!cstate->binary)
2191  CopySendString(cstate, cstate->null_print_client);
2192  else
2193  CopySendInt32(cstate, -1);
2194  }
2195  else
2196  {
2197  if (!cstate->binary)
2198  {
2199  string = OutputFunctionCall(&out_functions[attnum - 1],
2200  value);
2201  if (cstate->csv_mode)
2202  CopyAttributeOutCSV(cstate, string,
2203  cstate->force_quote_flags[attnum - 1],
2204  list_length(cstate->attnumlist) == 1);
2205  else
2206  CopyAttributeOutText(cstate, string);
2207  }
2208  else
2209  {
2210  bytea *outputbytes;
2211 
2212  outputbytes = SendFunctionCall(&out_functions[attnum - 1],
2213  value);
2214  CopySendInt32(cstate, VARSIZE(outputbytes) - VARHDRSZ);
2215  CopySendData(cstate, VARDATA(outputbytes),
2216  VARSIZE(outputbytes) - VARHDRSZ);
2217  }
2218  }
2219  }
2220 
2221  CopySendEndOfRow(cstate);
2222 
2223  MemoryContextSwitchTo(oldcontext);
2224 }
Definition: fmgr.h:56
bool csv_mode
Definition: copy.c:138
#define VARDATA(PTR)
Definition: postgres.h:302
bool binary
Definition: copy.c:136
List * attnumlist
Definition: copy.c:132
#define VARSIZE(PTR)
Definition: postgres.h:303
#define VARHDRSZ
Definition: c.h:561
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
struct cursor * cur
Definition: ecpg.c:28
static void CopyAttributeOutText(CopyState cstate, char *string)
Definition: copy.c:4767
Datum * tts_values
Definition: tuptable.h:126
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:136
bool * force_quote_flags
Definition: copy.c:148
char * delim
Definition: copy.c:143
MemoryContext rowcontext
Definition: copy.c:173
static void CopySendChar(CopyState cstate, char c)
Definition: copy.c:511
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1577
static void CopySendInt16(CopyState cstate, int16 val)
Definition: copy.c:755
#define lfirst_int(lc)
Definition: pg_list.h:191
static void CopyAttributeOutCSV(CopyState cstate, char *string, bool use_quote, bool single_attr)
Definition: copy.c:4920
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:354
bool * tts_isnull
Definition: tuptable.h:128
char string[11]
Definition: preproc-type.c:46
bytea * SendFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1638
uintptr_t Datum
Definition: postgres.h:367
int16 attnum
Definition: pg_attribute.h:79
static struct @143 value
static void CopySendData(CopyState cstate, const void *databuf, int datasize)
Definition: copy.c:499
static void CopySendString(CopyState cstate, const char *str)
Definition: copy.c:505
static int list_length(const List *l)
Definition: pg_list.h:169
static void CopySendInt32(CopyState cstate, int32 val)
Definition: copy.c:724
FmgrInfo * out_functions
Definition: copy.c:172
static void CopySendEndOfRow(CopyState cstate)
Definition: copy.c:517
Definition: c.h:555
char * null_print_client
Definition: copy.c:142

◆ CopyReadAttributesCSV()

static int CopyReadAttributesCSV ( CopyState  cstate)
static

Definition at line 4540 of file copy.c.

References Assert, CopyStateData::attribute_buf, StringInfoData::data, CopyStateData::delim, enlargeStringInfo(), ereport, errcode(), errmsg(), ERROR, CopyStateData::escape, StringInfoData::len, CopyStateData::line_buf, CopyStateData::max_fields, StringInfoData::maxlen, CopyStateData::null_print, CopyStateData::null_print_len, CopyStateData::quote, CopyStateData::raw_fields, repalloc(), and resetStringInfo().

Referenced by NextCopyFromRawFields().

4541 {
4542  char delimc = cstate->delim[0];
4543  char quotec = cstate->quote[0];
4544  char escapec = cstate->escape[0];
4545  int fieldno;
4546  char *output_ptr;
4547  char *cur_ptr;
4548  char *line_end_ptr;
4549 
4550  /*
4551  * We need a special case for zero-column tables: check that the input
4552  * line is empty, and return.
4553  */
4554  if (cstate->max_fields <= 0)
4555  {
4556  if (cstate->line_buf.len != 0)
4557  ereport(ERROR,
4558  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
4559  errmsg("extra data after last expected column")));
4560  return 0;
4561  }
4562 
4563  resetStringInfo(&cstate->attribute_buf);
4564 
4565  /*
4566  * The de-escaped attributes will certainly not be longer than the input
4567  * data line, so we can just force attribute_buf to be large enough and
4568  * then transfer data without any checks for enough space. We need to do
4569  * it this way because enlarging attribute_buf mid-stream would invalidate
4570  * pointers already stored into cstate->raw_fields[].
4571  */
4572  if (cstate->attribute_buf.maxlen <= cstate->line_buf.len)
4573  enlargeStringInfo(&cstate->attribute_buf, cstate->line_buf.len);
4574  output_ptr = cstate->attribute_buf.data;
4575 
4576  /* set pointer variables for loop */
4577  cur_ptr = cstate->line_buf.data;
4578  line_end_ptr = cstate->line_buf.data + cstate->line_buf.len;
4579 
4580  /* Outer loop iterates over fields */
4581  fieldno = 0;
4582  for (;;)
4583  {
4584  bool found_delim = false;
4585  bool saw_quote = false;
4586  char *start_ptr;
4587  char *end_ptr;
4588  int input_len;
4589 
4590  /* Make sure there is enough space for the next value */
4591  if (fieldno >= cstate->max_fields)
4592  {
4593  cstate->max_fields *= 2;
4594  cstate->raw_fields =
4595  repalloc(cstate->raw_fields, cstate->max_fields * sizeof(char *));
4596  }
4597 
4598  /* Remember start of field on both input and output sides */
4599  start_ptr = cur_ptr;
4600  cstate->raw_fields[fieldno] = output_ptr;
4601 
4602  /*
4603  * Scan data for field,
4604  *
4605  * The loop starts in "not quote" mode and then toggles between that
4606  * and "in quote" mode. The loop exits normally if it is in "not
4607  * quote" mode and a delimiter or line end is seen.
4608  */
4609  for (;;)
4610  {
4611  char c;
4612 
4613  /* Not in quote */
4614  for (;;)
4615  {
4616  end_ptr = cur_ptr;
4617  if (cur_ptr >= line_end_ptr)
4618  goto endfield;
4619  c = *cur_ptr++;
4620  /* unquoted field delimiter */
4621  if (c == delimc)
4622  {
4623  found_delim = true;
4624  goto endfield;
4625  }
4626  /* start of quoted field (or part of field) */
4627  if (c == quotec)
4628  {
4629  saw_quote = true;
4630  break;
4631  }
4632  /* Add c to output string */
4633  *output_ptr++ = c;
4634  }
4635 
4636  /* In quote */
4637  for (;;)
4638  {
4639  end_ptr = cur_ptr;
4640  if (cur_ptr >= line_end_ptr)
4641  ereport(ERROR,
4642  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
4643  errmsg("unterminated CSV quoted field")));
4644 
4645  c = *cur_ptr++;
4646 
4647  /* escape within a quoted field */
4648  if (c == escapec)
4649  {
4650  /*
4651  * peek at the next char if available, and escape it if it
4652  * is an escape char or a quote char
4653  */
4654  if (cur_ptr < line_end_ptr)
4655  {
4656  char nextc = *cur_ptr;
4657 
4658  if (nextc == escapec || nextc == quotec)
4659  {
4660  *output_ptr++ = nextc;
4661  cur_ptr++;
4662  continue;
4663  }
4664  }
4665  }
4666 
4667  /*
4668  * end of quoted field. Must do this test after testing for
4669  * escape in case quote char and escape char are the same
4670  * (which is the common case).
4671  */
4672  if (c == quotec)
4673  break;
4674 
4675  /* Add c to output string */
4676  *output_ptr++ = c;
4677  }
4678  }
4679 endfield:
4680 
4681  /* Terminate attribute value in output area */
4682  *output_ptr++ = '\0';
4683 
4684  /* Check whether raw input matched null marker */
4685  input_len = end_ptr - start_ptr;
4686  if (!saw_quote && input_len == cstate->null_print_len &&
4687  strncmp(start_ptr, cstate->null_print, input_len) == 0)
4688  cstate->raw_fields[fieldno] = NULL;
4689 
4690  fieldno++;
4691  /* Done if we hit EOL instead of a delim */
4692  if (!found_delim)
4693  break;
4694  }
4695 
4696  /* Clean up state of attribute_buf */
4697  output_ptr--;
4698  Assert(*output_ptr == '\0');
4699  cstate->attribute_buf.len = (output_ptr - cstate->attribute_buf.data);
4700 
4701  return fieldno;
4702 }
char ** raw_fields
Definition: copy.c:202
StringInfoData line_buf
Definition: copy.c:211
int errcode(int sqlerrcode)
Definition: elog.c:610
char * delim
Definition: copy.c:143
char * null_print
Definition: copy.c:140
#define ERROR
Definition: elog.h:43
char * c
char * quote
Definition: copy.c:144
void enlargeStringInfo(StringInfo str, int needed)
Definition: stringinfo.c:283
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:75
int max_fields
Definition: copy.c:201
char * escape
Definition: copy.c:145
int null_print_len
Definition: copy.c:141
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
int errmsg(const char *fmt,...)
Definition: elog.c:824
StringInfoData attribute_buf
Definition: copy.c:197

◆ CopyReadAttributesText()

static int CopyReadAttributesText ( CopyState  cstate)
static

Definition at line 4312 of file copy.c.

References Assert, CopyStateData::attribute_buf, StringInfoData::data, CopyStateData::delim, enlargeStringInfo(), ereport, errcode(), errmsg(), ERROR, GetDecimalFromHex(), IS_HIGHBIT_SET, ISOCTAL, StringInfoData::len, CopyStateData::line_buf, CopyStateData::max_fields, StringInfoData::maxlen, CopyStateData::null_print, CopyStateData::null_print_len, OCTVALUE, pg_verifymbstr(), CopyStateData::raw_fields, repalloc(), resetStringInfo(), and val.

Referenced by NextCopyFromRawFields().

4313 {
4314  char delimc = cstate->delim[0];
4315  int fieldno;
4316  char *output_ptr;
4317  char *cur_ptr;
4318  char *line_end_ptr;
4319 
4320  /*
4321  * We need a special case for zero-column tables: check that the input
4322  * line is empty, and return.
4323  */
4324  if (cstate->max_fields <= 0)
4325  {
4326  if (cstate->line_buf.len != 0)
4327  ereport(ERROR,
4328  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
4329  errmsg("extra data after last expected column")));
4330  return 0;
4331  }
4332 
4333  resetStringInfo(&cstate->attribute_buf);
4334 
4335  /*
4336  * The de-escaped attributes will certainly not be longer than the input
4337  * data line, so we can just force attribute_buf to be large enough and
4338  * then transfer data without any checks for enough space. We need to do
4339  * it this way because enlarging attribute_buf mid-stream would invalidate
4340  * pointers already stored into cstate->raw_fields[].
4341  */
4342  if (cstate->attribute_buf.maxlen <= cstate->line_buf.len)
4343  enlargeStringInfo(&cstate->attribute_buf, cstate->line_buf.len);
4344  output_ptr = cstate->attribute_buf.data;
4345 
4346  /* set pointer variables for loop */
4347  cur_ptr = cstate->line_buf.data;
4348  line_end_ptr = cstate->line_buf.data + cstate->line_buf.len;
4349 
4350  /* Outer loop iterates over fields */
4351  fieldno = 0;
4352  for (;;)
4353  {
4354  bool found_delim = false;
4355  char *start_ptr;
4356  char *end_ptr;
4357  int input_len;
4358  bool saw_non_ascii = false;
4359 
4360  /* Make sure there is enough space for the next value */
4361  if (fieldno >= cstate->max_fields)
4362  {
4363  cstate->max_fields *= 2;
4364  cstate->raw_fields =
4365  repalloc(cstate->raw_fields, cstate->max_fields * sizeof(char *));
4366  }
4367 
4368  /* Remember start of field on both input and output sides */
4369  start_ptr = cur_ptr;
4370  cstate->raw_fields[fieldno] = output_ptr;
4371 
4372  /*
4373  * Scan data for field.
4374  *
4375  * Note that in this loop, we are scanning to locate the end of field
4376  * and also speculatively performing de-escaping. Once we find the
4377  * end-of-field, we can match the raw field contents against the null
4378  * marker string. Only after that comparison fails do we know that
4379  * de-escaping is actually the right thing to do; therefore we *must
4380  * not* throw any syntax errors before we've done the null-marker
4381  * check.
4382  */
4383  for (;;)
4384  {
4385  char c;
4386 
4387  end_ptr = cur_ptr;
4388  if (cur_ptr >= line_end_ptr)
4389  break;
4390  c = *cur_ptr++;
4391  if (c == delimc)
4392  {
4393  found_delim = true;
4394  break;
4395  }
4396  if (c == '\\')
4397  {
4398  if (cur_ptr >= line_end_ptr)
4399  break;
4400  c = *cur_ptr++;
4401  switch (c)
4402  {
4403  case '0':
4404  case '1':
4405  case '2':
4406  case '3':
4407  case '4':
4408  case '5':
4409  case '6':
4410  case '7':
4411  {
4412  /* handle \013 */
4413  int val;
4414 
4415  val = OCTVALUE(c);
4416  if (cur_ptr < line_end_ptr)
4417  {
4418  c = *cur_ptr;
4419  if (ISOCTAL(c))
4420  {
4421  cur_ptr++;
4422  val = (val << 3) + OCTVALUE(c);
4423  if (cur_ptr < line_end_ptr)
4424  {
4425  c = *cur_ptr;
4426  if (ISOCTAL(c))
4427  {
4428  cur_ptr++;
4429  val = (val << 3) + OCTVALUE(c);
4430  }
4431  }
4432  }
4433  }
4434  c = val & 0377;
4435  if (c == '\0' || IS_HIGHBIT_SET(c))
4436  saw_non_ascii = true;
4437  }
4438  break;
4439  case 'x':
4440  /* Handle \x3F */
4441  if (cur_ptr < line_end_ptr)
4442  {
4443  char hexchar = *cur_ptr;
4444 
4445  if (isxdigit((unsigned char) hexchar))
4446  {
4447  int val = GetDecimalFromHex(hexchar);
4448 
4449  cur_ptr++;
4450  if (cur_ptr < line_end_ptr)
4451  {
4452  hexchar = *cur_ptr;
4453  if (isxdigit((unsigned char) hexchar))
4454  {
4455  cur_ptr++;
4456  val = (val << 4) + GetDecimalFromHex(hexchar);
4457  }
4458  }
4459  c = val & 0xff;
4460  if (c == '\0' || IS_HIGHBIT_SET(c))
4461  saw_non_ascii = true;
4462  }
4463  }
4464  break;
4465  case 'b':
4466  c = '\b';
4467  break;
4468  case 'f':
4469  c = '\f';
4470  break;
4471  case 'n':
4472  c = '\n';
4473  break;
4474  case 'r':
4475  c = '\r';
4476  break;
4477  case 't':
4478  c = '\t';
4479  break;
4480  case 'v':
4481  c = '\v';
4482  break;
4483 
4484  /*
4485  * in all other cases, take the char after '\'
4486  * literally
4487  */
4488  }
4489  }
4490 
4491  /* Add c to output string */
4492  *output_ptr++ = c;
4493  }
4494 
4495  /* Check whether raw input matched null marker */
4496  input_len = end_ptr - start_ptr;
4497  if (input_len == cstate->null_print_len &&
4498  strncmp(start_ptr, cstate->null_print, input_len) == 0)
4499  cstate->raw_fields[fieldno] = NULL;
4500  else
4501  {
4502  /*
4503  * At this point we know the field is supposed to contain data.
4504  *
4505  * If we de-escaped any non-7-bit-ASCII chars, make sure the
4506  * resulting string is valid data for the db encoding.
4507  */
4508  if (saw_non_ascii)
4509  {
4510  char *fld = cstate->raw_fields[fieldno];
4511 
4512  pg_verifymbstr(fld, output_ptr - fld, false);
4513  }
4514  }
4515 
4516  /* Terminate attribute value in output area */
4517  *output_ptr++ = '\0';
4518 
4519  fieldno++;
4520  /* Done if we hit EOL instead of a delim */
4521  if (!found_delim)
4522  break;
4523  }
4524 
4525  /* Clean up state of attribute_buf */
4526  output_ptr--;
4527  Assert(*output_ptr == '\0');
4528  cstate->attribute_buf.len = (output_ptr - cstate->attribute_buf.data);
4529 
4530  return fieldno;
4531 }
static int GetDecimalFromHex(char hex)
Definition: copy.c:4284
char ** raw_fields
Definition: copy.c:202
#define ISOCTAL(c)
Definition: copy.c:62
#define OCTVALUE(c)
Definition: copy.c:63
StringInfoData line_buf
Definition: copy.c:211
int errcode(int sqlerrcode)
Definition: elog.c:610
char * delim
Definition: copy.c:143
char * null_print
Definition: copy.c:140
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1119
#define ERROR
Definition: elog.h:43
char * c
void enlargeStringInfo(StringInfo str, int needed)
Definition: stringinfo.c:283
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:75
int max_fields
Definition: copy.c:201
int null_print_len
Definition: copy.c:141
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: mbutils.c:1446
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
int errmsg(const char *fmt,...)
Definition: elog.c:824
StringInfoData attribute_buf
Definition: copy.c:197
long val
Definition: informix.c:664

◆ CopyReadBinaryAttribute()

static Datum CopyReadBinaryAttribute ( CopyState  cstate,
FmgrInfo flinfo,
Oid  typioparam,
int32  typmod,
bool isnull 
)
static

Definition at line 4709 of file copy.c.

References CopyStateData::attribute_buf, CopyGetData(), CopyGetInt32(), StringInfoData::cursor, StringInfoData::data, enlargeStringInfo(), ereport, errcode(), errmsg(), ERROR, StringInfoData::len, ReceiveFunctionCall(), and resetStringInfo().

Referenced by NextCopyFrom().

4712 {
4713  int32 fld_size;
4714  Datum result;
4715 
4716  if (!CopyGetInt32(cstate, &fld_size))
4717  ereport(ERROR,
4718  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
4719  errmsg("unexpected EOF in COPY data")));
4720  if (fld_size == -1)
4721  {
4722  *isnull = true;
4723  return ReceiveFunctionCall(flinfo, NULL, typioparam, typmod);
4724  }
4725  if (fld_size < 0)
4726  ereport(ERROR,
4727  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
4728  errmsg("invalid field size")));
4729 
4730  /* reset attribute_buf to empty, and load raw data in it */
4731  resetStringInfo(&cstate->attribute_buf);
4732 
4733  enlargeStringInfo(&cstate->attribute_buf, fld_size);
4734  if (CopyGetData(cstate, cstate->attribute_buf.data,
4735  fld_size, fld_size) != fld_size)
4736  ereport(ERROR,
4737  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
4738  errmsg("unexpected EOF in COPY data")));
4739 
4740  cstate->attribute_buf.len = fld_size;
4741  cstate->attribute_buf.data[fld_size] = '\0';
4742 
4743  /* Call the column type's binary input converter */
4744  result = ReceiveFunctionCall(flinfo, &cstate->attribute_buf,
4745  typioparam, typmod);
4746 
4747  /* Trouble if it didn't eat the whole buffer */
4748  if (cstate->attribute_buf.cursor != cstate->attribute_buf.len)
4749  ereport(ERROR,
4750  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
4751  errmsg("incorrect binary data format")));
4752 
4753  *isnull = false;
4754  return result;
4755 }
static bool CopyGetInt32(CopyState cstate, int32 *val)
Definition: copy.c:738
int errcode(int sqlerrcode)
Definition: elog.c:610
signed int int32
Definition: c.h:355
#define ERROR
Definition: elog.h:43
static int CopyGetData(CopyState cstate, void *databuf, int minread, int maxread)
Definition: copy.c:610
Datum ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf, Oid typioparam, int32 typmod)
Definition: fmgr.c:1591
void enlargeStringInfo(StringInfo str, int needed)
Definition: stringinfo.c:283
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:75
uintptr_t Datum
Definition: postgres.h:367
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:824
StringInfoData attribute_buf
Definition: copy.c:197

◆ CopyReadLine()

static bool CopyReadLine ( CopyState  cstate)
static

Definition at line 3831 of file copy.c.

References appendBinaryStringInfo(), Assert, CopyStateData::copy_dest, COPY_NEW_FE, CopyLoadRawBuf(), CopyReadLineText(), StringInfoData::data, EOL_CR, EOL_CRNL, EOL_NL, CopyStateData::eol_type, EOL_UNKNOWN, CopyStateData::file_encoding, StringInfoData::len, CopyStateData::line_buf, CopyStateData::line_buf_converted, CopyStateData::line_buf_valid, CopyStateData::need_transcoding, pfree(), pg_any_to_server(), CopyStateData::raw_buf_index, CopyStateData::raw_buf_len, and resetStringInfo().

Referenced by NextCopyFromRawFields().

3832 {
3833  bool result;
3834 
3835  resetStringInfo(&cstate->line_buf);
3836  cstate->line_buf_valid = true;
3837 
3838  /* Mark that encoding conversion hasn't occurred yet */
3839  cstate->line_buf_converted = false;
3840 
3841  /* Parse data and transfer into line_buf */
3842  result = CopyReadLineText(cstate);
3843 
3844  if (result)
3845  {
3846  /*
3847  * Reached EOF. In protocol version 3, we should ignore anything
3848  * after \. up to the protocol end of copy data. (XXX maybe better
3849  * not to treat \. as special?)
3850  */
3851  if (cstate->copy_dest == COPY_NEW_FE)
3852  {
3853  do
3854  {
3855  cstate->raw_buf_index = cstate->raw_buf_len;
3856  } while (CopyLoadRawBuf(cstate));
3857  }
3858  }
3859  else
3860  {
3861  /*
3862  * If we didn't hit EOF, then we must have transferred the EOL marker
3863  * to line_buf along with the data. Get rid of it.
3864  */
3865  switch (cstate->eol_type)
3866  {
3867  case EOL_NL:
3868  Assert(cstate->line_buf.len >= 1);
3869  Assert(cstate->line_buf.data[cstate->line_buf.len - 1] == '\n');
3870  cstate->line_buf.len--;
3871  cstate->line_buf.data[cstate->line_buf.len] = '\0';
3872  break;
3873  case EOL_CR:
3874  Assert(cstate->line_buf.len >= 1);
3875  Assert(cstate->line_buf.data[cstate->line_buf.len - 1] == '\r');
3876  cstate->line_buf.len--;
3877  cstate->line_buf.data[cstate->line_buf.len] = '\0';
3878  break;
3879  case EOL_CRNL:
3880  Assert(cstate->line_buf.len >= 2);
3881  Assert(cstate->line_buf.data[cstate->line_buf.len - 2] == '\r');
3882  Assert(cstate->line_buf.data[cstate->line_buf.len - 1] == '\n');
3883  cstate->line_buf.len -= 2;
3884  cstate->line_buf.data[cstate->line_buf.len] = '\0';
3885  break;
3886  case EOL_UNKNOWN:
3887  /* shouldn't get here */
3888  Assert(false);
3889  break;
3890  }
3891  }
3892 
3893  /* Done reading the line. Convert it to server encoding. */
3894  if (cstate->need_transcoding)
3895  {
3896  char *cvt;
3897 
3898  cvt = pg_any_to_server(cstate->line_buf.data,
3899  cstate->line_buf.len,
3900  cstate->file_encoding);
3901  if (cvt != cstate->line_buf.data)
3902  {
3903  /* transfer converted data back to line_buf */
3904  resetStringInfo(&cstate->line_buf);
3905  appendBinaryStringInfo(&cstate->line_buf, cvt, strlen(cvt));
3906  pfree(cvt);
3907  }
3908  }
3909 
3910  /* Now it's safe to use the buffer in error messages */
3911  cstate->line_buf_converted = true;
3912 
3913  return result;
3914 }
static bool CopyReadLineText(CopyState cstate)
Definition: copy.c:3920
Definition: copy.c:83
bool need_transcoding
Definition: copy.c:126
StringInfoData line_buf
Definition: copy.c:211
int raw_buf_index
Definition: copy.c:224
bool line_buf_valid
Definition: copy.c:213
bool line_buf_converted
Definition: copy.c:212
CopyDest copy_dest
Definition: copy.c:117
void pfree(void *pointer)
Definition: mcxt.c:1056
static bool CopyLoadRawBuf(CopyState cstate)
Definition: copy.c:792
Definition: copy.c:84
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:75
int raw_buf_len
Definition: copy.c:225
Definition: copy.c:85
int file_encoding
Definition: copy.c:125
EolType eol_type
Definition: copy.c:124
#define Assert(condition)
Definition: c.h:738
char * pg_any_to_server(const char *s, int len, int encoding)
Definition: mbutils.c:619
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227

◆ CopyReadLineText()

static bool CopyReadLineText ( CopyState  cstate)
static

Definition at line 3920 of file copy.c.

References appendBinaryStringInfo(), CopyLoadRawBuf(), CopyStateData::csv_mode, CopyStateData::cur_lineno, CopyStateData::encoding_embeds_ascii, EOL_CR, EOL_CRNL, EOL_NL, CopyStateData::eol_type, EOL_UNKNOWN, ereport, errcode(), errhint(), errmsg(), ERROR, CopyStateData::escape, CopyStateData::file_encoding, IF_NEED_REFILL_AND_EOF_BREAK, IF_NEED_REFILL_AND_NOT_EOF_CONTINUE, IS_HIGHBIT_SET, CopyStateData::line_buf, NO_END_OF_COPY_GOTO, pg_encoding_mblen(), CopyStateData::quote, CopyStateData::raw_buf, CopyStateData::raw_buf_index, CopyStateData::raw_buf_len, and REFILL_LINEBUF.

Referenced by CopyReadLine().

3921 {
3922  char *copy_raw_buf;
3923  int raw_buf_ptr;
3924  int copy_buf_len;
3925  bool need_data = false;
3926  bool hit_eof = false;
3927  bool result = false;
3928  char mblen_str[2];
3929 
3930  /* CSV variables */
3931  bool first_char_in_line = true;
3932  bool in_quote = false,
3933  last_was_esc = false;
3934  char quotec = '\0';
3935  char escapec = '\0';
3936 
3937  if (cstate->csv_mode)
3938  {
3939  quotec = cstate->quote[0];
3940  escapec = cstate->escape[0];
3941  /* ignore special escape processing if it's the same as quotec */
3942  if (quotec == escapec)
3943  escapec = '\0';
3944  }
3945 
3946  mblen_str[1] = '\0';
3947 
3948  /*
3949  * The objective of this loop is to transfer the entire next input line
3950  * into line_buf. Hence, we only care for detecting newlines (\r and/or
3951  * \n) and the end-of-copy marker (\.).
3952  *
3953  * In CSV mode, \r and \n inside a quoted field are just part of the data
3954  * value and are put in line_buf. We keep just enough state to know if we
3955  * are currently in a quoted field or not.
3956  *
3957  * These four characters, and the CSV escape and quote characters, are
3958  * assumed the same in frontend and backend encodings.
3959  *
3960  * For speed, we try to move data from raw_buf to line_buf in chunks
3961  * rather than one character at a time. raw_buf_ptr points to the next
3962  * character to examine; any characters from raw_buf_index to raw_buf_ptr
3963  * have been determined to be part of the line, but not yet transferred to
3964  * line_buf.
3965  *
3966  * For a little extra speed within the loop, we copy raw_buf and
3967  * raw_buf_len into local variables.
3968  */
3969  copy_raw_buf = cstate->raw_buf;
3970  raw_buf_ptr = cstate->raw_buf_index;
3971  copy_buf_len = cstate->raw_buf_len;
3972 
3973  for (;;)
3974  {
3975  int prev_raw_ptr;
3976  char c;
3977 
3978  /*
3979  * Load more data if needed. Ideally we would just force four bytes
3980  * of read-ahead and avoid the many calls to
3981  * IF_NEED_REFILL_AND_NOT_EOF_CONTINUE(), but the COPY_OLD_FE protocol
3982  * does not allow us to read too far ahead or we might read into the
3983  * next data, so we read-ahead only as far we know we can. One
3984  * optimization would be to read-ahead four byte here if
3985  * cstate->copy_dest != COPY_OLD_FE, but it hardly seems worth it,
3986  * considering the size of the buffer.
3987  */
3988  if (raw_buf_ptr >= copy_buf_len || need_data)
3989  {
3991 
3992  /*
3993  * Try to read some more data. This will certainly reset
3994  * raw_buf_index to zero, and raw_buf_ptr must go with it.
3995  */
3996  if (!CopyLoadRawBuf(cstate))
3997  hit_eof = true;
3998  raw_buf_ptr = 0;
3999  copy_buf_len = cstate->raw_buf_len;
4000 
4001  /*
4002  * If we are completely out of data, break out of the loop,
4003  * reporting EOF.
4004  */
4005  if (copy_buf_len <= 0)
4006  {
4007  result = true;
4008  break;
4009  }
4010  need_data = false;
4011  }
4012 
4013  /* OK to fetch a character */
4014  prev_raw_ptr = raw_buf_ptr;
4015  c = copy_raw_buf[raw_buf_ptr++];
4016 
4017  if (cstate->csv_mode)
4018  {
4019  /*
4020  * If character is '\\' or '\r', we may need to look ahead below.
4021  * Force fetch of the next character if we don't already have it.
4022  * We need to do this before changing CSV state, in case one of
4023  * these characters is also the quote or escape character.
4024  *
4025  * Note: old-protocol does not like forced prefetch, but it's OK
4026  * here since we cannot validly be at EOF.
4027  */
4028  if (c == '\\' || c == '\r')
4029  {
4031  }
4032 
4033  /*
4034  * Dealing with quotes and escapes here is mildly tricky. If the
4035  * quote char is also the escape char, there's no problem - we
4036  * just use the char as a toggle. If they are different, we need
4037  * to ensure that we only take account of an escape inside a
4038  * quoted field and immediately preceding a quote char, and not
4039  * the second in an escape-escape sequence.
4040  */
4041  if (in_quote && c == escapec)
4042  last_was_esc = !last_was_esc;
4043  if (c == quotec && !last_was_esc)
4044  in_quote = !in_quote;
4045  if (c != escapec)
4046  last_was_esc = false;
4047 
4048  /*
4049  * Updating the line count for embedded CR and/or LF chars is
4050  * necessarily a little fragile - this test is probably about the
4051  * best we can do. (XXX it's arguable whether we should do this
4052  * at all --- is cur_lineno a physical or logical count?)
4053  */
4054  if (in_quote && c == (cstate->eol_type == EOL_NL ? '\n' : '\r'))
4055  cstate->cur_lineno++;
4056  }
4057 
4058  /* Process \r */
4059  if (c == '\r' && (!cstate->csv_mode || !in_quote))
4060  {
4061  /* Check for \r\n on first line, _and_ handle \r\n. */
4062  if (cstate->eol_type == EOL_UNKNOWN ||
4063  cstate->eol_type == EOL_CRNL)
4064  {
4065  /*
4066  * If need more data, go back to loop top to load it.
4067  *
4068  * Note that if we are at EOF, c will wind up as '\0' because
4069  * of the guaranteed pad of raw_buf.
4070  */
4072 
4073  /* get next char */
4074  c = copy_raw_buf[raw_buf_ptr];
4075 
4076  if (c == '\n')
4077  {
4078  raw_buf_ptr++; /* eat newline */
4079  cstate->eol_type = EOL_CRNL; /* in case not set yet */
4080  }
4081  else
4082  {
4083  /* found \r, but no \n */
4084  if (cstate->eol_type == EOL_CRNL)
4085  ereport(ERROR,
4086  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
4087  !cstate->csv_mode ?
4088  errmsg("literal carriage return found in data") :
4089  errmsg("unquoted carriage return found in data"),
4090  !cstate->csv_mode ?
4091  errhint("Use \"\\r\" to represent carriage return.") :
4092  errhint("Use quoted CSV field to represent carriage return.")));
4093 
4094  /*
4095  * if we got here, it is the first line and we didn't find
4096  * \n, so don't consume the peeked character
4097  */
4098  cstate->eol_type = EOL_CR;
4099  }
4100  }
4101  else if (cstate->eol_type == EOL_NL)
4102  ereport(ERROR,
4103  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
4104  !cstate->csv_mode ?
4105  errmsg("literal carriage return found in data") :
4106  errmsg("unquoted carriage return found in data"),
4107  !cstate->csv_mode ?
4108  errhint("Use \"\\r\" to represent carriage return.") :
4109  errhint("Use quoted CSV field to represent carriage return.")));
4110  /* If reach here, we have found the line terminator */
4111  break;
4112  }
4113 
4114  /* Process \n */
4115  if (c == '\n' && (!cstate->csv_mode || !in_quote))
4116  {
4117  if (cstate->eol_type == EOL_CR || cstate->eol_type == EOL_CRNL)
4118  ereport(ERROR,
4119  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
4120  !cstate->csv_mode ?
4121  errmsg("literal newline found in data") :
4122  errmsg("unquoted newline found in data"),
4123  !cstate->csv_mode ?
4124  errhint("Use \"\\n\" to represent newline.") :
4125  errhint("Use quoted CSV field to represent newline.")));
4126  cstate->eol_type = EOL_NL; /* in case not set yet */
4127  /* If reach here, we have found the line terminator */
4128  break;
4129  }
4130 
4131  /*
4132  * In CSV mode, we only recognize \. alone on a line. This is because
4133  * \. is a valid CSV data value.
4134  */
4135  if (c == '\\' && (!cstate->csv_mode || first_char_in_line))
4136  {
4137  char c2;
4138 
4141 
4142  /* -----
4143  * get next character
4144  * Note: we do not change c so if it isn't \., we can fall
4145  * through and continue processing for file encoding.
4146  * -----
4147  */
4148  c2 = copy_raw_buf[raw_buf_ptr];
4149 
4150  if (c2 == '.')
4151  {
4152  raw_buf_ptr++; /* consume the '.' */
4153 
4154  /*
4155  * Note: if we loop back for more data here, it does not
4156  * matter that the CSV state change checks are re-executed; we
4157  * will come back here with no important state changed.
4158  */
4159  if (cstate->eol_type == EOL_CRNL)
4160  {
4161  /* Get the next character */
4163  /* if hit_eof, c2 will become '\0' */
4164  c2 = copy_raw_buf[raw_buf_ptr++];
4165 
4166  if (c2 == '\n')
4167  {
4168  if (!cstate->csv_mode)
4169  ereport(ERROR,
4170  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
4171  errmsg("end-of-copy marker does not match previous newline style")));
4172  else
4174  }
4175  else if (c2 != '\r')
4176  {
4177  if (!cstate->csv_mode)
4178  ereport(ERROR,
4179  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
4180  errmsg("end-of-copy marker corrupt")));
4181  else
4183  }
4184  }
4185 
4186  /* Get the next character */
4188  /* if hit_eof, c2 will become '\0' */
4189  c2 = copy_raw_buf[raw_buf_ptr++];
4190 
4191  if (c2 != '\r' && c2 != '\n')
4192  {
4193  if (!cstate->csv_mode)
4194  ereport(ERROR,
4195  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
4196  errmsg("end-of-copy marker corrupt")));
4197  else
4199  }
4200 
4201  if ((cstate->eol_type == EOL_NL && c2 != '\n') ||
4202  (cstate->eol_type == EOL_CRNL && c2 != '\n') ||
4203  (cstate->eol_type == EOL_CR && c2 != '\r'))
4204  {
4205  ereport(ERROR,
4206  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
4207  errmsg("end-of-copy marker does not match previous newline style")));
4208  }
4209 
4210  /*
4211  * Transfer only the data before the \. into line_buf, then
4212  * discard the data and the \. sequence.
4213  */
4214  if (prev_raw_ptr > cstate->raw_buf_index)
4216  cstate->raw_buf + cstate->raw_buf_index,
4217  prev_raw_ptr - cstate->raw_buf_index);
4218  cstate->raw_buf_index = raw_buf_ptr;
4219  result = true; /* report EOF */
4220  break;
4221  }
4222  else if (!cstate->csv_mode)
4223 
4224  /*
4225  * If we are here, it means we found a backslash followed by
4226  * something other than a period. In non-CSV mode, anything
4227  * after a backslash is special, so we skip over that second
4228  * character too. If we didn't do that \\. would be
4229  * considered an eof-of copy, while in non-CSV mode it is a
4230  * literal backslash followed by a period. In CSV mode,
4231  * backslashes are not special, so we want to process the
4232  * character after the backslash just like a normal character,
4233  * so we don't increment in those cases.
4234  */
4235  raw_buf_ptr++;
4236  }
4237 
4238  /*
4239  * This label is for CSV cases where \. appears at the start of a
4240  * line, but there is more text after it, meaning it was a data value.
4241  * We are more strict for \. in CSV mode because \. could be a data
4242  * value, while in non-CSV mode, \. cannot be a data value.
4243  */
4244 not_end_of_copy:
4245 
4246  /*
4247  * Process all bytes of a multi-byte character as a group.
4248  *
4249  * We only support multi-byte sequences where the first byte has the
4250  * high-bit set, so as an optimization we can avoid this block
4251  * entirely if it is not set.
4252  */
4253  if (cstate->encoding_embeds_ascii && IS_HIGHBIT_SET(c))
4254  {
4255  int mblen;
4256 
4257  /*
4258  * It is enough to look at the first byte in all our encodings, to
4259  * get the length. (GB18030 is a bit special, but still works for
4260  * our purposes; see comment in pg_gb18030_mblen())
4261  */
4262  mblen_str[0] = c;
4263  mblen = pg_encoding_mblen(cstate->file_encoding, mblen_str);
4264 
4266  IF_NEED_REFILL_AND_EOF_BREAK(mblen - 1);
4267  raw_buf_ptr += mblen - 1;
4268  }
4269  first_char_in_line = false;
4270  } /* end of outer loop */
4271 
4272  /*
4273  * Transfer any still-uncopied data to line_buf.
4274  */
4276 
4277  return result;
4278 }
bool csv_mode
Definition: copy.c:138
int errhint(const char *fmt,...)
Definition: elog.c:1071
Definition: copy.c:83
StringInfoData line_buf
Definition: copy.c:211
#define IF_NEED_REFILL_AND_EOF_BREAK(extralen)
Definition: copy.c:313
int raw_buf_index
Definition: copy.c:224
int errcode(int sqlerrcode)
Definition: elog.c:610
#define REFILL_LINEBUF
Definition: copy.c:330
uint64 cur_lineno
Definition: copy.c:160
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1119
#define ERROR
Definition: elog.h:43
bool encoding_embeds_ascii
Definition: copy.c:127
char * c
char * raw_buf
Definition: copy.c:223
static bool CopyLoadRawBuf(CopyState cstate)
Definition: copy.c:792
char * quote
Definition: copy.c:144
int pg_encoding_mblen(int encoding, const char *mbstr)
Definition: wchar.c:1554
Definition: copy.c:84
int raw_buf_len
Definition: copy.c:225
char * escape
Definition: copy.c:145
Definition: copy.c:85
int file_encoding
Definition: copy.c:125
#define IF_NEED_REFILL_AND_NOT_EOF_CONTINUE(extralen)
Definition: copy.c:301
#define ereport(elevel,...)
Definition: elog.h:144
EolType eol_type
Definition: copy.c:124
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define NO_END_OF_COPY_GOTO
Definition: copy.c:343
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227

◆ CopySendChar()

static void CopySendChar ( CopyState  cstate,
char  c 
)
static

Definition at line 511 of file copy.c.

References appendStringInfoCharMacro, and CopyStateData::fe_msgbuf.

Referenced by CopyAttributeOutCSV(), CopyAttributeOutText(), CopyOneRowTo(), CopySendEndOfRow(), and CopyTo().

512 {
514 }
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:128
char * c
StringInfo fe_msgbuf
Definition: copy.c:119

◆ CopySendData()

static void CopySendData ( CopyState  cstate,
const void *  databuf,
int  datasize 
)
static

Definition at line 499 of file copy.c.

References appendBinaryStringInfo(), and CopyStateData::fe_msgbuf.

Referenced by CopyOneRowTo(), CopySendInt16(), CopySendInt32(), CopyTo(), and SendCopyEnd().

500 {
501  appendBinaryStringInfo(cstate->fe_msgbuf, databuf, datasize);
502 }
StringInfo fe_msgbuf
Definition: copy.c:119
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227

◆ CopySendEndOfRow()

static void CopySendEndOfRow ( CopyState  cstate)
static

Definition at line 517 of file copy.c.

References Assert, CopyStateData::binary, ClosePipeToProgram(), COPY_CALLBACK, CopyStateData::copy_dest, COPY_FILE, CopyStateData::copy_file, COPY_NEW_FE, COPY_OLD_FE, CopySendChar(), CopySendString(), StringInfoData::data, ereport, errcode(), errcode_for_file_access(), errmsg(), ERROR, FATAL, CopyStateData::fe_msgbuf, CopyStateData::is_program, StringInfoData::len, pq_putbytes(), pq_putmessage, and resetStringInfo().

Referenced by CopyOneRowTo(), CopyTo(), and SendCopyEnd().

518 {
519  StringInfo fe_msgbuf = cstate->fe_msgbuf;
520 
521  switch (cstate->copy_dest)
522  {
523  case COPY_FILE:
524  if (!cstate->binary)
525  {
526  /* Default line termination depends on platform */
527 #ifndef WIN32
528  CopySendChar(cstate, '\n');
529 #else
530  CopySendString(cstate, "\r\n");
531 #endif
532  }
533 
534  if (fwrite(fe_msgbuf->data, fe_msgbuf->len, 1,
535  cstate->copy_file) != 1 ||
536  ferror(cstate->copy_file))
537  {
538  if (cstate->is_program)
539  {
540  if (errno == EPIPE)
541  {
542  /*
543  * The pipe will be closed automatically on error at
544  * the end of transaction, but we might get a better
545  * error message from the subprocess' exit code than
546  * just "Broken Pipe"
547  */
548  ClosePipeToProgram(cstate);
549 
550  /*
551  * If ClosePipeToProgram() didn't throw an error, the
552  * program terminated normally, but closed the pipe
553  * first. Restore errno, and throw an error.
554  */
555  errno = EPIPE;
556  }
557  ereport(ERROR,
559  errmsg("could not write to COPY program: %m")));
560  }
561  else
562  ereport(ERROR,
564  errmsg("could not write to COPY file: %m")));
565  }
566  break;
567  case COPY_OLD_FE:
568  /* The FE/BE protocol uses \n as newline for all platforms */
569  if (!cstate->binary)
570  CopySendChar(cstate, '\n');
571 
572  if (pq_putbytes(fe_msgbuf->data, fe_msgbuf->len))
573  {
574  /* no hope of recovering connection sync, so FATAL */
575  ereport(FATAL,
576  (errcode(ERRCODE_CONNECTION_FAILURE),
577  errmsg("connection lost during COPY to stdout")));
578  }
579  break;
580  case COPY_NEW_FE:
<