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

Go to the source code of this file.

Data Structures

struct  CopyFormatOptions
 

Typedefs

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

Enumerations

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

Functions

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

Typedef Documentation

◆ copy_data_dest_cb

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

Definition at line 97 of file copy.h.

◆ copy_data_source_cb

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

Definition at line 96 of file copy.h.

◆ CopyFormatOptions

◆ CopyFromState

Definition at line 93 of file copy.h.

◆ CopyHeaderChoice

◆ CopyLogVerbosityChoice

◆ CopyOnErrorChoice

◆ CopyToState

typedef struct CopyToStateData* CopyToState

Definition at line 94 of file copy.h.

Enumeration Type Documentation

◆ CopyHeaderChoice

Enumerator
COPY_HEADER_FALSE 
COPY_HEADER_TRUE 
COPY_HEADER_MATCH 

Definition at line 26 of file copy.h.

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

◆ CopyLogVerbosityChoice

Enumerator
COPY_LOG_VERBOSITY_SILENT 
COPY_LOG_VERBOSITY_DEFAULT 
COPY_LOG_VERBOSITY_VERBOSE 

Definition at line 46 of file copy.h.

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

◆ CopyOnErrorChoice

Enumerator
COPY_ON_ERROR_STOP 
COPY_ON_ERROR_IGNORE 

Definition at line 37 of file copy.h.

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

Function Documentation

◆ BeginCopyFrom()

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

Definition at line 1529 of file copyfrom.c.

1537{
1538 CopyFromState cstate;
1539 bool pipe = (filename == NULL);
1540 TupleDesc tupDesc;
1541 AttrNumber num_phys_attrs,
1542 num_defaults;
1543 FmgrInfo *in_functions;
1544 Oid *typioparams;
1545 int *defmap;
1546 ExprState **defexprs;
1547 MemoryContext oldcontext;
1548 bool volatile_defexprs;
1549 const int progress_cols[] = {
1553 };
1554 int64 progress_vals[] = {
1556 0,
1557 0
1558 };
1559
1560 /* Allocate workspace and zero all fields */
1561 cstate = (CopyFromStateData *) palloc0(sizeof(CopyFromStateData));
1562
1563 /*
1564 * We allocate everything used by a cstate in a new memory context. This
1565 * avoids memory leaks during repeated use of COPY in a query.
1566 */
1568 "COPY",
1570
1571 oldcontext = MemoryContextSwitchTo(cstate->copycontext);
1572
1573 /* Extract options from the statement node tree */
1574 ProcessCopyOptions(pstate, &cstate->opts, true /* is_from */ , options);
1575
1576 /* Set the format routine */
1577 cstate->routine = CopyFromGetRoutine(&cstate->opts);
1578
1579 /* Process the target relation */
1580 cstate->rel = rel;
1581
1582 tupDesc = RelationGetDescr(cstate->rel);
1583
1584 /* process common options or initialization */
1585
1586 /* Generate or convert list of attributes to process */
1587 cstate->attnumlist = CopyGetAttnums(tupDesc, cstate->rel, attnamelist);
1588
1589 num_phys_attrs = tupDesc->natts;
1590
1591 /* Convert FORCE_NOT_NULL name list to per-column flags, check validity */
1592 cstate->opts.force_notnull_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1593 if (cstate->opts.force_notnull_all)
1594 MemSet(cstate->opts.force_notnull_flags, true, num_phys_attrs * sizeof(bool));
1595 else if (cstate->opts.force_notnull)
1596 {
1597 List *attnums;
1598 ListCell *cur;
1599
1600 attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_notnull);
1601
1602 foreach(cur, attnums)
1603 {
1604 int attnum = lfirst_int(cur);
1605 Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1606
1607 if (!list_member_int(cstate->attnumlist, attnum))
1608 ereport(ERROR,
1609 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1610 /*- translator: first %s is the name of a COPY option, e.g. FORCE_NOT_NULL */
1611 errmsg("%s column \"%s\" not referenced by COPY",
1612 "FORCE_NOT_NULL", NameStr(attr->attname))));
1613 cstate->opts.force_notnull_flags[attnum - 1] = true;
1614 }
1615 }
1616
1617 /* Set up soft error handler for ON_ERROR */
1618 if (cstate->opts.on_error != COPY_ON_ERROR_STOP)
1619 {
1621 cstate->escontext->type = T_ErrorSaveContext;
1622 cstate->escontext->error_occurred = false;
1623
1624 /*
1625 * Currently we only support COPY_ON_ERROR_IGNORE. We'll add other
1626 * options later
1627 */
1628 if (cstate->opts.on_error == COPY_ON_ERROR_IGNORE)
1629 cstate->escontext->details_wanted = false;
1630 }
1631 else
1632 cstate->escontext = NULL;
1633
1634 /* Convert FORCE_NULL name list to per-column flags, check validity */
1635 cstate->opts.force_null_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1636 if (cstate->opts.force_null_all)
1637 MemSet(cstate->opts.force_null_flags, true, num_phys_attrs * sizeof(bool));
1638 else if (cstate->opts.force_null)
1639 {
1640 List *attnums;
1641 ListCell *cur;
1642
1643 attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_null);
1644
1645 foreach(cur, attnums)
1646 {
1647 int attnum = lfirst_int(cur);
1648 Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1649
1650 if (!list_member_int(cstate->attnumlist, attnum))
1651 ereport(ERROR,
1652 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1653 /*- translator: first %s is the name of a COPY option, e.g. FORCE_NOT_NULL */
1654 errmsg("%s column \"%s\" not referenced by COPY",
1655 "FORCE_NULL", NameStr(attr->attname))));
1656 cstate->opts.force_null_flags[attnum - 1] = true;
1657 }
1658 }
1659
1660 /* Convert convert_selectively name list to per-column flags */
1661 if (cstate->opts.convert_selectively)
1662 {
1663 List *attnums;
1664 ListCell *cur;
1665
1666 cstate->convert_select_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1667
1668 attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.convert_select);
1669
1670 foreach(cur, attnums)
1671 {
1672 int attnum = lfirst_int(cur);
1673 Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1674
1675 if (!list_member_int(cstate->attnumlist, attnum))
1676 ereport(ERROR,
1677 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1678 errmsg_internal("selected column \"%s\" not referenced by COPY",
1679 NameStr(attr->attname))));
1680 cstate->convert_select_flags[attnum - 1] = true;
1681 }
1682 }
1683
1684 /* Use client encoding when ENCODING option is not specified. */
1685 if (cstate->opts.file_encoding < 0)
1687 else
1688 cstate->file_encoding = cstate->opts.file_encoding;
1689
1690 /*
1691 * Look up encoding conversion function.
1692 */
1693 if (cstate->file_encoding == GetDatabaseEncoding() ||
1694 cstate->file_encoding == PG_SQL_ASCII ||
1696 {
1697 cstate->need_transcoding = false;
1698 }
1699 else
1700 {
1701 cstate->need_transcoding = true;
1704 if (!OidIsValid(cstate->conversion_proc))
1705 ereport(ERROR,
1706 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1707 errmsg("default conversion function for encoding \"%s\" to \"%s\" does not exist",
1710 }
1711
1712 cstate->copy_src = COPY_FILE; /* default */
1713
1714 cstate->whereClause = whereClause;
1715
1716 /* Initialize state variables */
1717 cstate->eol_type = EOL_UNKNOWN;
1718 cstate->cur_relname = RelationGetRelationName(cstate->rel);
1719 cstate->cur_lineno = 0;
1720 cstate->cur_attname = NULL;
1721 cstate->cur_attval = NULL;
1722 cstate->relname_only = false;
1723
1724 /*
1725 * Allocate buffers for the input pipeline.
1726 *
1727 * attribute_buf and raw_buf are used in both text and binary modes, but
1728 * input_buf and line_buf only in text mode.
1729 */
1730 cstate->raw_buf = palloc(RAW_BUF_SIZE + 1);
1731 cstate->raw_buf_index = cstate->raw_buf_len = 0;
1732 cstate->raw_reached_eof = false;
1733
1734 initStringInfo(&cstate->attribute_buf);
1735
1736 /* Assign range table and rteperminfos, we'll need them in CopyFrom. */
1737 if (pstate)
1738 {
1739 cstate->range_table = pstate->p_rtable;
1740 cstate->rteperminfos = pstate->p_rteperminfos;
1741 }
1742
1743 num_defaults = 0;
1744 volatile_defexprs = false;
1745
1746 /*
1747 * Pick up the required catalog information for each attribute in the
1748 * relation, including the input function, the element type (to pass to
1749 * the input function), and info about defaults and constraints. (Which
1750 * input function we use depends on text/binary format choice.)
1751 */
1752 in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
1753 typioparams = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
1754 defmap = (int *) palloc(num_phys_attrs * sizeof(int));
1755 defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *));
1756
1757 for (int attnum = 1; attnum <= num_phys_attrs; attnum++)
1758 {
1759 Form_pg_attribute att = TupleDescAttr(tupDesc, attnum - 1);
1760
1761 /* We don't need info for dropped attributes */
1762 if (att->attisdropped)
1763 continue;
1764
1765 /* Fetch the input function and typioparam info */
1766 cstate->routine->CopyFromInFunc(cstate, att->atttypid,
1767 &in_functions[attnum - 1],
1768 &typioparams[attnum - 1]);
1769
1770 /* Get default info if available */
1771 defexprs[attnum - 1] = NULL;
1772
1773 /*
1774 * We only need the default values for columns that do not appear in
1775 * the column list, unless the DEFAULT option was given. We never need
1776 * default values for generated columns.
1777 */
1778 if ((cstate->opts.default_print != NULL ||
1779 !list_member_int(cstate->attnumlist, attnum)) &&
1780 !att->attgenerated)
1781 {
1782 Expr *defexpr = (Expr *) build_column_default(cstate->rel,
1783 attnum);
1784
1785 if (defexpr != NULL)
1786 {
1787 /* Run the expression through planner */
1788 defexpr = expression_planner(defexpr);
1789
1790 /* Initialize executable expression in copycontext */
1791 defexprs[attnum - 1] = ExecInitExpr(defexpr, NULL);
1792
1793 /* if NOT copied from input */
1794 /* use default value if one exists */
1795 if (!list_member_int(cstate->attnumlist, attnum))
1796 {
1797 defmap[num_defaults] = attnum - 1;
1798 num_defaults++;
1799 }
1800
1801 /*
1802 * If a default expression looks at the table being loaded,
1803 * then it could give the wrong answer when using
1804 * multi-insert. Since database access can be dynamic this is
1805 * hard to test for exactly, so we use the much wider test of
1806 * whether the default expression is volatile. We allow for
1807 * the special case of when the default expression is the
1808 * nextval() of a sequence which in this specific case is
1809 * known to be safe for use with the multi-insert
1810 * optimization. Hence we use this special case function
1811 * checker rather than the standard check for
1812 * contain_volatile_functions(). Note also that we already
1813 * ran the expression through expression_planner().
1814 */
1815 if (!volatile_defexprs)
1816 volatile_defexprs = contain_volatile_functions_not_nextval((Node *) defexpr);
1817 }
1818 }
1819 }
1820
1821 cstate->defaults = (bool *) palloc0(tupDesc->natts * sizeof(bool));
1822
1823 /* initialize progress */
1825 cstate->rel ? RelationGetRelid(cstate->rel) : InvalidOid);
1826 cstate->bytes_processed = 0;
1827
1828 /* We keep those variables in cstate. */
1829 cstate->in_functions = in_functions;
1830 cstate->typioparams = typioparams;
1831 cstate->defmap = defmap;
1832 cstate->defexprs = defexprs;
1833 cstate->volatile_defexprs = volatile_defexprs;
1834 cstate->num_defaults = num_defaults;
1835 cstate->is_program = is_program;
1836
1837 if (data_source_cb)
1838 {
1839 progress_vals[1] = PROGRESS_COPY_TYPE_CALLBACK;
1840 cstate->copy_src = COPY_CALLBACK;
1841 cstate->data_source_cb = data_source_cb;
1842 }
1843 else if (pipe)
1844 {
1845 progress_vals[1] = PROGRESS_COPY_TYPE_PIPE;
1846 Assert(!is_program); /* the grammar does not allow this */
1848 ReceiveCopyBegin(cstate);
1849 else
1850 cstate->copy_file = stdin;
1851 }
1852 else
1853 {
1854 cstate->filename = pstrdup(filename);
1855
1856 if (cstate->is_program)
1857 {
1858 progress_vals[1] = PROGRESS_COPY_TYPE_PROGRAM;
1859 cstate->copy_file = OpenPipeStream(cstate->filename, PG_BINARY_R);
1860 if (cstate->copy_file == NULL)
1861 ereport(ERROR,
1863 errmsg("could not execute command \"%s\": %m",
1864 cstate->filename)));
1865 }
1866 else
1867 {
1868 struct stat st;
1869
1870 progress_vals[1] = PROGRESS_COPY_TYPE_FILE;
1871 cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_R);
1872 if (cstate->copy_file == NULL)
1873 {
1874 /* copy errno because ereport subfunctions might change it */
1875 int save_errno = errno;
1876
1877 ereport(ERROR,
1879 errmsg("could not open file \"%s\" for reading: %m",
1880 cstate->filename),
1881 (save_errno == ENOENT || save_errno == EACCES) ?
1882 errhint("COPY FROM instructs the PostgreSQL server process to read a file. "
1883 "You may want a client-side facility such as psql's \\copy.") : 0));
1884 }
1885
1886 if (fstat(fileno(cstate->copy_file), &st))
1887 ereport(ERROR,
1889 errmsg("could not stat file \"%s\": %m",
1890 cstate->filename)));
1891
1892 if (S_ISDIR(st.st_mode))
1893 ereport(ERROR,
1894 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1895 errmsg("\"%s\" is a directory", cstate->filename)));
1896
1897 progress_vals[2] = st.st_size;
1898 }
1899 }
1900
1901 pgstat_progress_update_multi_param(3, progress_cols, progress_vals);
1902
1903 cstate->routine->CopyFromStart(cstate, tupDesc);
1904
1905 MemoryContextSwitchTo(oldcontext);
1906
1907 return cstate;
1908}
int16 AttrNumber
Definition: attnum.h:21
List * CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
Definition: copy.c:945
void ProcessCopyOptions(ParseState *pstate, CopyFormatOptions *opts_out, bool is_from, List *options)
Definition: copy.c:496
void pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid)
void pgstat_progress_update_multi_param(int nparam, const int *index, const int64 *val)
@ PROGRESS_COMMAND_COPY
#define NameStr(name)
Definition: c.h:717
#define PG_BINARY_R
Definition: c.h:1246
int64_t int64
Definition: c.h:499
#define MemSet(start, val, len)
Definition: c.h:991
#define OidIsValid(objectId)
Definition: c.h:746
bool contain_volatile_functions_not_nextval(Node *clause)
Definition: clauses.c:672
static const CopyFromRoutine * CopyFromGetRoutine(const CopyFormatOptions *opts)
Definition: copyfrom.c:156
@ EOL_UNKNOWN
#define RAW_BUF_SIZE
void ReceiveCopyBegin(CopyFromState cstate)
@ COPY_FILE
Definition: copyto.c:45
@ COPY_CALLBACK
Definition: copyto.c:47
@ DestRemote
Definition: dest.h:89
struct cursor * cur
Definition: ecpg.c:29
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1157
int errcode_for_file_access(void)
Definition: elog.c:876
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:143
FILE * OpenPipeStream(const char *command, const char *mode)
Definition: fd.c:2708
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2605
Assert(PointerIsAligned(start, uint64))
bool list_member_int(const List *list, int datum)
Definition: list.c:702
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
int pg_get_client_encoding(void)
Definition: mbutils.c:336
char * pstrdup(const char *in)
Definition: mcxt.c:1699
void * palloc0(Size size)
Definition: mcxt.c:1347
void * palloc(Size size)
Definition: mcxt.c:1317
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
Oid FindDefaultConversionProc(int32 for_encoding, int32 to_encoding)
Definition: namespace.c:4080
#define makeNode(_type_)
Definition: nodes.h:157
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
int16 attnum
Definition: pg_attribute.h:74
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
static char * filename
Definition: pg_dumpall.c:124
#define lfirst_int(lc)
Definition: pg_list.h:173
@ PG_SQL_ASCII
Definition: pg_wchar.h:226
#define pg_encoding_to_char
Definition: pg_wchar.h:630
Expr * expression_planner(Expr *expr)
Definition: planner.c:6641
CommandDest whereToSendOutput
Definition: postgres.c:91
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
#define PROGRESS_COPY_COMMAND
Definition: progress.h:146
#define PROGRESS_COPY_TYPE_FILE
Definition: progress.h:155
#define PROGRESS_COPY_COMMAND_FROM
Definition: progress.h:151
#define PROGRESS_COPY_TYPE
Definition: progress.h:147
#define PROGRESS_COPY_TYPE_PROGRAM
Definition: progress.h:156
#define PROGRESS_COPY_BYTES_TOTAL
Definition: progress.h:143
#define PROGRESS_COPY_TYPE_CALLBACK
Definition: progress.h:158
#define PROGRESS_COPY_TYPE_PIPE
Definition: progress.h:157
#define RelationGetRelid(relation)
Definition: rel.h:513
#define RelationGetDescr(relation)
Definition: rel.h:539
#define RelationGetRelationName(relation)
Definition: rel.h:547
Node * build_column_default(Relation rel, int attrno)
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
bool force_notnull_all
Definition: copy.h:80
bool convert_selectively
Definition: copy.h:85
CopyOnErrorChoice on_error
Definition: copy.h:86
List * force_null
Definition: copy.h:82
List * convert_select
Definition: copy.h:89
bool force_null_all
Definition: copy.h:83
bool * force_notnull_flags
Definition: copy.h:81
int file_encoding
Definition: copy.h:62
bool * force_null_flags
Definition: copy.h:84
char * default_print
Definition: copy.h:71
List * force_notnull
Definition: copy.h:79
void(* CopyFromInFunc)(CopyFromState cstate, Oid atttypid, FmgrInfo *finfo, Oid *typioparam)
Definition: copyapi.h:74
void(* CopyFromStart)(CopyFromState cstate, TupleDesc tupDesc)
Definition: copyapi.h:85
copy_data_source_cb data_source_cb
const struct CopyFromRoutine * routine
CopyFormatOptions opts
StringInfoData attribute_buf
MemoryContext copycontext
const char * cur_attval
const char * cur_attname
const char * cur_relname
ErrorSaveContext * escontext
bool details_wanted
Definition: miscnodes.h:48
bool error_occurred
Definition: miscnodes.h:47
NodeTag type
Definition: miscnodes.h:46
Definition: fmgr.h:57
Definition: pg_list.h:54
Definition: nodes.h:131
List * p_rteperminfos
Definition: parse_node.h:213
List * p_rtable
Definition: parse_node.h:212
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:154
#define S_ISDIR(m)
Definition: win32_port.h:315
#define fstat
Definition: win32_port.h:273

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

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

◆ BeginCopyTo()

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

Definition at line 623 of file copyto.c.

632{
633 CopyToState cstate;
634 bool pipe = (filename == NULL && data_dest_cb == NULL);
635 TupleDesc tupDesc;
636 int num_phys_attrs;
637 MemoryContext oldcontext;
638 const int progress_cols[] = {
641 };
642 int64 progress_vals[] = {
644 0
645 };
646
647 if (rel != NULL && rel->rd_rel->relkind != RELKIND_RELATION)
648 {
649 if (rel->rd_rel->relkind == RELKIND_VIEW)
651 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
652 errmsg("cannot copy from view \"%s\"",
654 errhint("Try the COPY (SELECT ...) TO variant.")));
655 else if (rel->rd_rel->relkind == RELKIND_MATVIEW)
657 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
658 errmsg("cannot copy from materialized view \"%s\"",
660 errhint("Try the COPY (SELECT ...) TO variant.")));
661 else if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
663 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
664 errmsg("cannot copy from foreign table \"%s\"",
666 errhint("Try the COPY (SELECT ...) TO variant.")));
667 else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
669 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
670 errmsg("cannot copy from sequence \"%s\"",
672 else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
674 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
675 errmsg("cannot copy from partitioned table \"%s\"",
677 errhint("Try the COPY (SELECT ...) TO variant.")));
678 else
680 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
681 errmsg("cannot copy from non-table relation \"%s\"",
683 }
684
685
686 /* Allocate workspace and zero all fields */
687 cstate = (CopyToStateData *) palloc0(sizeof(CopyToStateData));
688
689 /*
690 * We allocate everything used by a cstate in a new memory context. This
691 * avoids memory leaks during repeated use of COPY in a query.
692 */
694 "COPY",
696
697 oldcontext = MemoryContextSwitchTo(cstate->copycontext);
698
699 /* Extract options from the statement node tree */
700 ProcessCopyOptions(pstate, &cstate->opts, false /* is_from */ , options);
701
702 /* Set format routine */
703 cstate->routine = CopyToGetRoutine(&cstate->opts);
704
705 /* Process the source/target relation or query */
706 if (rel)
707 {
708 Assert(!raw_query);
709
710 cstate->rel = rel;
711
712 tupDesc = RelationGetDescr(cstate->rel);
713 }
714 else
715 {
716 List *rewritten;
717 Query *query;
720
721 cstate->rel = NULL;
722
723 /*
724 * Run parse analysis and rewrite. Note this also acquires sufficient
725 * locks on the source table(s).
726 */
727 rewritten = pg_analyze_and_rewrite_fixedparams(raw_query,
728 pstate->p_sourcetext, NULL, 0,
729 NULL);
730
731 /* check that we got back something we can work with */
732 if (rewritten == NIL)
733 {
735 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
736 errmsg("DO INSTEAD NOTHING rules are not supported for COPY")));
737 }
738 else if (list_length(rewritten) > 1)
739 {
740 ListCell *lc;
741
742 /* examine queries to determine which error message to issue */
743 foreach(lc, rewritten)
744 {
745 Query *q = lfirst_node(Query, lc);
746
747 if (q->querySource == QSRC_QUAL_INSTEAD_RULE)
749 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
750 errmsg("conditional DO INSTEAD rules are not supported for COPY")));
751 if (q->querySource == QSRC_NON_INSTEAD_RULE)
753 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
754 errmsg("DO ALSO rules are not supported for COPY")));
755 }
756
758 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
759 errmsg("multi-statement DO INSTEAD rules are not supported for COPY")));
760 }
761
762 query = linitial_node(Query, rewritten);
763
764 /* The grammar allows SELECT INTO, but we don't support that */
765 if (query->utilityStmt != NULL &&
768 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
769 errmsg("COPY (SELECT INTO) is not supported")));
770
771 /* The only other utility command we could see is NOTIFY */
772 if (query->utilityStmt != NULL)
774 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
775 errmsg("COPY query must not be a utility command")));
776
777 /*
778 * Similarly the grammar doesn't enforce the presence of a RETURNING
779 * clause, but this is required here.
780 */
781 if (query->commandType != CMD_SELECT &&
782 query->returningList == NIL)
783 {
784 Assert(query->commandType == CMD_INSERT ||
785 query->commandType == CMD_UPDATE ||
786 query->commandType == CMD_DELETE ||
787 query->commandType == CMD_MERGE);
788
790 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
791 errmsg("COPY query must have a RETURNING clause")));
792 }
793
794 /* plan the query */
795 plan = pg_plan_query(query, pstate->p_sourcetext,
797
798 /*
799 * With row-level security and a user using "COPY relation TO", we
800 * have to convert the "COPY relation TO" to a query-based COPY (eg:
801 * "COPY (SELECT * FROM ONLY relation) TO"), to allow the rewriter to
802 * add in any RLS clauses.
803 *
804 * When this happens, we are passed in the relid of the originally
805 * found relation (which we have locked). As the planner will look up
806 * the relation again, we double-check here to make sure it found the
807 * same one that we have locked.
808 */
809 if (queryRelId != InvalidOid)
810 {
811 /*
812 * Note that with RLS involved there may be multiple relations,
813 * and while the one we need is almost certainly first, we don't
814 * make any guarantees of that in the planner, so check the whole
815 * list and make sure we find the original relation.
816 */
817 if (!list_member_oid(plan->relationOids, queryRelId))
819 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
820 errmsg("relation referenced by COPY statement has changed")));
821 }
822
823 /*
824 * Use a snapshot with an updated command ID to ensure this query sees
825 * results of any previously executed queries.
826 */
829
830 /* Create dest receiver for COPY OUT */
832 ((DR_copy *) dest)->cstate = cstate;
833
834 /* Create a QueryDesc requesting no output */
835 cstate->queryDesc = CreateQueryDesc(plan, NULL, pstate->p_sourcetext,
838 dest, NULL, NULL, 0);
839
840 /*
841 * Call ExecutorStart to prepare the plan for execution.
842 *
843 * ExecutorStart computes a result tupdesc for us
844 */
845 if (!ExecutorStart(cstate->queryDesc, 0))
846 elog(ERROR, "ExecutorStart() failed unexpectedly");
847
848 tupDesc = cstate->queryDesc->tupDesc;
849 }
850
851 /* Generate or convert list of attributes to process */
852 cstate->attnumlist = CopyGetAttnums(tupDesc, cstate->rel, attnamelist);
853
854 num_phys_attrs = tupDesc->natts;
855
856 /* Convert FORCE_QUOTE name list to per-column flags, check validity */
857 cstate->opts.force_quote_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
858 if (cstate->opts.force_quote_all)
859 {
860 MemSet(cstate->opts.force_quote_flags, true, num_phys_attrs * sizeof(bool));
861 }
862 else if (cstate->opts.force_quote)
863 {
864 List *attnums;
865 ListCell *cur;
866
867 attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_quote);
868
869 foreach(cur, attnums)
870 {
871 int attnum = lfirst_int(cur);
872 Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
873
874 if (!list_member_int(cstate->attnumlist, attnum))
876 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
877 /*- translator: %s is the name of a COPY option, e.g. FORCE_NOT_NULL */
878 errmsg("%s column \"%s\" not referenced by COPY",
879 "FORCE_QUOTE", NameStr(attr->attname))));
880 cstate->opts.force_quote_flags[attnum - 1] = true;
881 }
882 }
883
884 /* Use client encoding when ENCODING option is not specified. */
885 if (cstate->opts.file_encoding < 0)
887 else
888 cstate->file_encoding = cstate->opts.file_encoding;
889
890 /*
891 * Set up encoding conversion info if the file and server encodings differ
892 * (see also pg_server_to_any).
893 */
894 if (cstate->file_encoding == GetDatabaseEncoding() ||
895 cstate->file_encoding == PG_SQL_ASCII)
896 cstate->need_transcoding = false;
897 else
898 cstate->need_transcoding = true;
899
900 /* See Multibyte encoding comment above */
902
903 cstate->copy_dest = COPY_FILE; /* default */
904
905 if (data_dest_cb)
906 {
907 progress_vals[1] = PROGRESS_COPY_TYPE_CALLBACK;
908 cstate->copy_dest = COPY_CALLBACK;
909 cstate->data_dest_cb = data_dest_cb;
910 }
911 else if (pipe)
912 {
913 progress_vals[1] = PROGRESS_COPY_TYPE_PIPE;
914
915 Assert(!is_program); /* the grammar does not allow this */
917 cstate->copy_file = stdout;
918 }
919 else
920 {
921 cstate->filename = pstrdup(filename);
922 cstate->is_program = is_program;
923
924 if (is_program)
925 {
926 progress_vals[1] = PROGRESS_COPY_TYPE_PROGRAM;
927 cstate->copy_file = OpenPipeStream(cstate->filename, PG_BINARY_W);
928 if (cstate->copy_file == NULL)
931 errmsg("could not execute command \"%s\": %m",
932 cstate->filename)));
933 }
934 else
935 {
936 mode_t oumask; /* Pre-existing umask value */
937 struct stat st;
938
939 progress_vals[1] = PROGRESS_COPY_TYPE_FILE;
940
941 /*
942 * Prevent write to relative path ... too easy to shoot oneself in
943 * the foot by overwriting a database file ...
944 */
947 (errcode(ERRCODE_INVALID_NAME),
948 errmsg("relative path not allowed for COPY to file")));
949
950 oumask = umask(S_IWGRP | S_IWOTH);
951 PG_TRY();
952 {
953 cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_W);
954 }
955 PG_FINALLY();
956 {
957 umask(oumask);
958 }
959 PG_END_TRY();
960 if (cstate->copy_file == NULL)
961 {
962 /* copy errno because ereport subfunctions might change it */
963 int save_errno = errno;
964
967 errmsg("could not open file \"%s\" for writing: %m",
968 cstate->filename),
969 (save_errno == ENOENT || save_errno == EACCES) ?
970 errhint("COPY TO instructs the PostgreSQL server process to write a file. "
971 "You may want a client-side facility such as psql's \\copy.") : 0));
972 }
973
974 if (fstat(fileno(cstate->copy_file), &st))
977 errmsg("could not stat file \"%s\": %m",
978 cstate->filename)));
979
980 if (S_ISDIR(st.st_mode))
982 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
983 errmsg("\"%s\" is a directory", cstate->filename)));
984 }
985 }
986
987 /* initialize progress */
989 cstate->rel ? RelationGetRelid(cstate->rel) : InvalidOid);
990 pgstat_progress_update_multi_param(2, progress_cols, progress_vals);
991
992 cstate->bytes_processed = 0;
993
994 MemoryContextSwitchTo(oldcontext);
995
996 return cstate;
997}
#define PG_BINARY_W
Definition: c.h:1247
static const CopyToRoutine * CopyToGetRoutine(const CopyFormatOptions *opts)
Definition: copyto.c:177
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:113
@ DestCopyOut
Definition: dest.h:95
#define PG_TRY(...)
Definition: elog.h:371
#define PG_END_TRY(...)
Definition: elog.h:396
#define elog(elevel,...)
Definition: elog.h:225
#define PG_FINALLY(...)
Definition: elog.h:388
bool ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:125
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:722
#define IsA(nodeptr, _type_)
Definition: nodes.h:160
@ CMD_MERGE
Definition: nodes.h:271
@ CMD_INSERT
Definition: nodes.h:269
@ CMD_DELETE
Definition: nodes.h:270
@ CMD_UPDATE
Definition: nodes.h:268
@ CMD_SELECT
Definition: nodes.h:267
@ QSRC_NON_INSTEAD_RULE
Definition: parsenodes.h:40
@ QSRC_QUAL_INSTEAD_RULE
Definition: parsenodes.h:39
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:3378
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial_node(type, l)
Definition: pg_list.h:181
#define NIL
Definition: pg_list.h:68
#define plan(x)
Definition: pg_regress.c:161
#define PG_ENCODING_IS_CLIENT_ONLY(_enc)
Definition: pg_wchar.h:284
#define is_absolute_path(filename)
Definition: port.h:104
PlannedStmt * pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, ParamListInfo boundParams)
Definition: postgres.c:882
List * pg_analyze_and_rewrite_fixedparams(RawStmt *parsetree, const char *query_string, const Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
Definition: postgres.c:665
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, CachedPlan *cplan, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
Definition: pquery.c:72
#define PROGRESS_COPY_COMMAND_TO
Definition: progress.h:152
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:731
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:719
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:787
#define InvalidSnapshot
Definition: snapshot.h:119
bool force_quote_all
Definition: copy.h:77
List * force_quote
Definition: copy.h:76
bool * force_quote_flags
Definition: copy.h:78
MemoryContext copycontext
Definition: copyto.c:93
Relation rel
Definition: copyto.c:80
const CopyToRoutine * routine
Definition: copyto.c:68
copy_data_dest_cb data_dest_cb
Definition: copyto.c:85
bool encoding_embeds_ascii
Definition: copyto.c:77
CopyDest copy_dest
Definition: copyto.c:71
bool need_transcoding
Definition: copyto.c:76
bool is_program
Definition: copyto.c:84
FILE * copy_file
Definition: copyto.c:72
int file_encoding
Definition: copyto.c:75
CopyFormatOptions opts
Definition: copyto.c:87
uint64 bytes_processed
Definition: copyto.c:97
char * filename
Definition: copyto.c:83
List * attnumlist
Definition: copyto.c:82
QueryDesc * queryDesc
Definition: copyto.c:81
const char * p_sourcetext
Definition: parse_node.h:209
TupleDesc tupDesc
Definition: execdesc.h:48
List * returningList
Definition: parsenodes.h:209
CmdType commandType
Definition: parsenodes.h:121
Node * utilityStmt
Definition: parsenodes.h:136
Form_pg_class rd_rel
Definition: rel.h:111
#define S_IWOTH
Definition: win32_port.h:306
#define S_IWGRP
Definition: win32_port.h:294

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

Referenced by DoCopy(), and test_copy_to_callback().

◆ CopyFrom()

uint64 CopyFrom ( CopyFromState  cstate)

Definition at line 779 of file copyfrom.c.

780{
781 ResultRelInfo *resultRelInfo;
782 ResultRelInfo *target_resultRelInfo;
783 ResultRelInfo *prevResultRelInfo = NULL;
784 EState *estate = CreateExecutorState(); /* for ExecConstraints() */
785 ModifyTableState *mtstate;
786 ExprContext *econtext;
787 TupleTableSlot *singleslot = NULL;
789
790 PartitionTupleRouting *proute = NULL;
791 ErrorContextCallback errcallback;
792 CommandId mycid = GetCurrentCommandId(true);
793 int ti_options = 0; /* start with default options for insert */
794 BulkInsertState bistate = NULL;
795 CopyInsertMethod insertMethod;
796 CopyMultiInsertInfo multiInsertInfo = {0}; /* pacify compiler */
797 int64 processed = 0;
798 int64 excluded = 0;
799 bool has_before_insert_row_trig;
800 bool has_instead_insert_row_trig;
801 bool leafpart_use_multi_insert = false;
802
803 Assert(cstate->rel);
804 Assert(list_length(cstate->range_table) == 1);
805
806 if (cstate->opts.on_error != COPY_ON_ERROR_STOP)
807 Assert(cstate->escontext);
808
809 /*
810 * The target must be a plain, foreign, or partitioned relation, or have
811 * an INSTEAD OF INSERT row trigger. (Currently, such triggers are only
812 * allowed on views, so we only hint about them in the view case.)
813 */
814 if (cstate->rel->rd_rel->relkind != RELKIND_RELATION &&
815 cstate->rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
816 cstate->rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE &&
817 !(cstate->rel->trigdesc &&
819 {
820 if (cstate->rel->rd_rel->relkind == RELKIND_VIEW)
822 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
823 errmsg("cannot copy to view \"%s\"",
825 errhint("To enable copying to a view, provide an INSTEAD OF INSERT trigger.")));
826 else if (cstate->rel->rd_rel->relkind == RELKIND_MATVIEW)
828 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
829 errmsg("cannot copy to materialized view \"%s\"",
830 RelationGetRelationName(cstate->rel))));
831 else if (cstate->rel->rd_rel->relkind == RELKIND_SEQUENCE)
833 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
834 errmsg("cannot copy to sequence \"%s\"",
835 RelationGetRelationName(cstate->rel))));
836 else
838 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
839 errmsg("cannot copy to non-table relation \"%s\"",
840 RelationGetRelationName(cstate->rel))));
841 }
842
843 /*
844 * If the target file is new-in-transaction, we assume that checking FSM
845 * for free space is a waste of time. This could possibly be wrong, but
846 * it's unlikely.
847 */
848 if (RELKIND_HAS_STORAGE(cstate->rel->rd_rel->relkind) &&
851 ti_options |= TABLE_INSERT_SKIP_FSM;
852
853 /*
854 * Optimize if new relation storage was created in this subxact or one of
855 * its committed children and we won't see those rows later as part of an
856 * earlier scan or command. The subxact test ensures that if this subxact
857 * aborts then the frozen rows won't be visible after xact cleanup. Note
858 * that the stronger test of exactly which subtransaction created it is
859 * crucial for correctness of this optimization. The test for an earlier
860 * scan or command tolerates false negatives. FREEZE causes other sessions
861 * to see rows they would not see under MVCC, and a false negative merely
862 * spreads that anomaly to the current session.
863 */
864 if (cstate->opts.freeze)
865 {
866 /*
867 * We currently disallow COPY FREEZE on partitioned tables. The
868 * reason for this is that we've simply not yet opened the partitions
869 * to determine if the optimization can be applied to them. We could
870 * go and open them all here, but doing so may be quite a costly
871 * overhead for small copies. In any case, we may just end up routing
872 * tuples to a small number of partitions. It seems better just to
873 * raise an ERROR for partitioned tables.
874 */
875 if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
876 {
878 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
879 errmsg("cannot perform COPY FREEZE on a partitioned table")));
880 }
881
882 /* There's currently no support for COPY FREEZE on foreign tables. */
883 if (cstate->rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
885 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
886 errmsg("cannot perform COPY FREEZE on a foreign table")));
887
888 /*
889 * Tolerate one registration for the benefit of FirstXactSnapshot.
890 * Scan-bearing queries generally create at least two registrations,
891 * though relying on that is fragile, as is ignoring ActiveSnapshot.
892 * Clear CatalogSnapshot to avoid counting its registration. We'll
893 * still detect ongoing catalog scans, each of which separately
894 * registers the snapshot it uses.
895 */
899 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
900 errmsg("cannot perform COPY FREEZE because of prior transaction activity")));
901
905 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
906 errmsg("cannot perform COPY FREEZE because the table was not created or truncated in the current subtransaction")));
907
908 ti_options |= TABLE_INSERT_FROZEN;
909 }
910
911 /*
912 * We need a ResultRelInfo so we can use the regular executor's
913 * index-entry-making machinery. (There used to be a huge amount of code
914 * here that basically duplicated execUtils.c ...)
915 */
916 ExecInitRangeTable(estate, cstate->range_table, cstate->rteperminfos,
918 resultRelInfo = target_resultRelInfo = makeNode(ResultRelInfo);
919 ExecInitResultRelation(estate, resultRelInfo, 1);
920
921 /* Verify the named relation is a valid target for INSERT */
922 CheckValidResultRel(resultRelInfo, CMD_INSERT, NIL);
923
924 ExecOpenIndices(resultRelInfo, false);
925
926 /*
927 * Set up a ModifyTableState so we can let FDW(s) init themselves for
928 * foreign-table result relation(s).
929 */
930 mtstate = makeNode(ModifyTableState);
931 mtstate->ps.plan = NULL;
932 mtstate->ps.state = estate;
933 mtstate->operation = CMD_INSERT;
934 mtstate->mt_nrels = 1;
935 mtstate->resultRelInfo = resultRelInfo;
936 mtstate->rootResultRelInfo = resultRelInfo;
937
938 if (resultRelInfo->ri_FdwRoutine != NULL &&
939 resultRelInfo->ri_FdwRoutine->BeginForeignInsert != NULL)
940 resultRelInfo->ri_FdwRoutine->BeginForeignInsert(mtstate,
941 resultRelInfo);
942
943 /*
944 * Also, if the named relation is a foreign table, determine if the FDW
945 * supports batch insert and determine the batch size (a FDW may support
946 * batching, but it may be disabled for the server/table).
947 *
948 * If the FDW does not support batching, we set the batch size to 1.
949 */
950 if (resultRelInfo->ri_FdwRoutine != NULL &&
953 resultRelInfo->ri_BatchSize =
954 resultRelInfo->ri_FdwRoutine->GetForeignModifyBatchSize(resultRelInfo);
955 else
956 resultRelInfo->ri_BatchSize = 1;
957
958 Assert(resultRelInfo->ri_BatchSize >= 1);
959
960 /* Prepare to catch AFTER triggers. */
962
963 /*
964 * If there are any triggers with transition tables on the named relation,
965 * we need to be prepared to capture transition tuples.
966 *
967 * Because partition tuple routing would like to know about whether
968 * transition capture is active, we also set it in mtstate, which is
969 * passed to ExecFindPartition() below.
970 */
971 cstate->transition_capture = mtstate->mt_transition_capture =
973 RelationGetRelid(cstate->rel),
974 CMD_INSERT);
975
976 /*
977 * If the named relation is a partitioned table, initialize state for
978 * CopyFrom tuple routing.
979 */
980 if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
981 proute = ExecSetupPartitionTupleRouting(estate, cstate->rel);
982
983 if (cstate->whereClause)
984 cstate->qualexpr = ExecInitQual(castNode(List, cstate->whereClause),
985 &mtstate->ps);
986
987 /*
988 * It's generally more efficient to prepare a bunch of tuples for
989 * insertion, and insert them in one
990 * table_multi_insert()/ExecForeignBatchInsert() call, than call
991 * table_tuple_insert()/ExecForeignInsert() separately for every tuple.
992 * However, there are a number of reasons why we might not be able to do
993 * this. These are explained below.
994 */
995 if (resultRelInfo->ri_TrigDesc != NULL &&
996 (resultRelInfo->ri_TrigDesc->trig_insert_before_row ||
997 resultRelInfo->ri_TrigDesc->trig_insert_instead_row))
998 {
999 /*
1000 * Can't support multi-inserts when there are any BEFORE/INSTEAD OF
1001 * triggers on the table. Such triggers might query the table we're
1002 * inserting into and act differently if the tuples that have already
1003 * been processed and prepared for insertion are not there.
1004 */
1005 insertMethod = CIM_SINGLE;
1006 }
1007 else if (resultRelInfo->ri_FdwRoutine != NULL &&
1008 resultRelInfo->ri_BatchSize == 1)
1009 {
1010 /*
1011 * Can't support multi-inserts to a foreign table if the FDW does not
1012 * support batching, or it's disabled for the server or foreign table.
1013 */
1014 insertMethod = CIM_SINGLE;
1015 }
1016 else if (proute != NULL && resultRelInfo->ri_TrigDesc != NULL &&
1017 resultRelInfo->ri_TrigDesc->trig_insert_new_table)
1018 {
1019 /*
1020 * For partitioned tables we can't support multi-inserts when there
1021 * are any statement level insert triggers. It might be possible to
1022 * allow partitioned tables with such triggers in the future, but for
1023 * now, CopyMultiInsertInfoFlush expects that any after row insert and
1024 * statement level insert triggers are on the same relation.
1025 */
1026 insertMethod = CIM_SINGLE;
1027 }
1028 else if (cstate->volatile_defexprs)
1029 {
1030 /*
1031 * Can't support multi-inserts if there are any volatile default
1032 * expressions in the table. Similarly to the trigger case above,
1033 * such expressions may query the table we're inserting into.
1034 *
1035 * Note: It does not matter if any partitions have any volatile
1036 * default expressions as we use the defaults from the target of the
1037 * COPY command.
1038 */
1039 insertMethod = CIM_SINGLE;
1040 }
1041 else if (contain_volatile_functions(cstate->whereClause))
1042 {
1043 /*
1044 * Can't support multi-inserts if there are any volatile function
1045 * expressions in WHERE clause. Similarly to the trigger case above,
1046 * such expressions may query the table we're inserting into.
1047 *
1048 * Note: the whereClause was already preprocessed in DoCopy(), so it's
1049 * okay to use contain_volatile_functions() directly.
1050 */
1051 insertMethod = CIM_SINGLE;
1052 }
1053 else
1054 {
1055 /*
1056 * For partitioned tables, we may still be able to perform bulk
1057 * inserts. However, the possibility of this depends on which types
1058 * of triggers exist on the partition. We must disable bulk inserts
1059 * if the partition is a foreign table that can't use batching or it
1060 * has any before row insert or insert instead triggers (same as we
1061 * checked above for the parent table). Since the partition's
1062 * resultRelInfos are initialized only when we actually need to insert
1063 * the first tuple into them, we must have the intermediate insert
1064 * method of CIM_MULTI_CONDITIONAL to flag that we must later
1065 * determine if we can use bulk-inserts for the partition being
1066 * inserted into.
1067 */
1068 if (proute)
1069 insertMethod = CIM_MULTI_CONDITIONAL;
1070 else
1071 insertMethod = CIM_MULTI;
1072
1073 CopyMultiInsertInfoInit(&multiInsertInfo, resultRelInfo, cstate,
1074 estate, mycid, ti_options);
1075 }
1076
1077 /*
1078 * If not using batch mode (which allocates slots as needed) set up a
1079 * tuple slot too. When inserting into a partitioned table, we also need
1080 * one, even if we might batch insert, to read the tuple in the root
1081 * partition's form.
1082 */
1083 if (insertMethod == CIM_SINGLE || insertMethod == CIM_MULTI_CONDITIONAL)
1084 {
1085 singleslot = table_slot_create(resultRelInfo->ri_RelationDesc,
1086 &estate->es_tupleTable);
1087 bistate = GetBulkInsertState();
1088 }
1089
1090 has_before_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
1091 resultRelInfo->ri_TrigDesc->trig_insert_before_row);
1092
1093 has_instead_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
1094 resultRelInfo->ri_TrigDesc->trig_insert_instead_row);
1095
1096 /*
1097 * Check BEFORE STATEMENT insertion triggers. It's debatable whether we
1098 * should do this for COPY, since it's not really an "INSERT" statement as
1099 * such. However, executing these triggers maintains consistency with the
1100 * EACH ROW triggers that we already fire on COPY.
1101 */
1102 ExecBSInsertTriggers(estate, resultRelInfo);
1103
1104 econtext = GetPerTupleExprContext(estate);
1105
1106 /* Set up callback to identify error line number */
1107 errcallback.callback = CopyFromErrorCallback;
1108 errcallback.arg = cstate;
1109 errcallback.previous = error_context_stack;
1110 error_context_stack = &errcallback;
1111
1112 for (;;)
1113 {
1114 TupleTableSlot *myslot;
1115 bool skip_tuple;
1116
1118
1119 /*
1120 * Reset the per-tuple exprcontext. We do this after every tuple, to
1121 * clean-up after expression evaluations etc.
1122 */
1124
1125 /* select slot to (initially) load row into */
1126 if (insertMethod == CIM_SINGLE || proute)
1127 {
1128 myslot = singleslot;
1129 Assert(myslot != NULL);
1130 }
1131 else
1132 {
1133 Assert(resultRelInfo == target_resultRelInfo);
1134 Assert(insertMethod == CIM_MULTI);
1135
1136 myslot = CopyMultiInsertInfoNextFreeSlot(&multiInsertInfo,
1137 resultRelInfo);
1138 }
1139
1140 /*
1141 * Switch to per-tuple context before calling NextCopyFrom, which does
1142 * evaluate default expressions etc. and requires per-tuple context.
1143 */
1145
1146 ExecClearTuple(myslot);
1147
1148 /* Directly store the values/nulls array in the slot */
1149 if (!NextCopyFrom(cstate, econtext, myslot->tts_values, myslot->tts_isnull))
1150 break;
1151
1152 if (cstate->opts.on_error == COPY_ON_ERROR_IGNORE &&
1153 cstate->escontext->error_occurred)
1154 {
1155 /*
1156 * Soft error occurred, skip this tuple and just make
1157 * ErrorSaveContext ready for the next NextCopyFrom. Since we
1158 * don't set details_wanted and error_data is not to be filled,
1159 * just resetting error_occurred is enough.
1160 */
1161 cstate->escontext->error_occurred = false;
1162
1163 /* Report that this tuple was skipped by the ON_ERROR clause */
1165 cstate->num_errors);
1166
1167 if (cstate->opts.reject_limit > 0 &&
1168 cstate->num_errors > cstate->opts.reject_limit)
1169 ereport(ERROR,
1170 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1171 errmsg("skipped more than REJECT_LIMIT (%lld) rows due to data type incompatibility",
1172 (long long) cstate->opts.reject_limit)));
1173
1174 /* Repeat NextCopyFrom() until no soft error occurs */
1175 continue;
1176 }
1177
1178 ExecStoreVirtualTuple(myslot);
1179
1180 /*
1181 * Constraints and where clause might reference the tableoid column,
1182 * so (re-)initialize tts_tableOid before evaluating them.
1183 */
1184 myslot->tts_tableOid = RelationGetRelid(target_resultRelInfo->ri_RelationDesc);
1185
1186 /* Triggers and stuff need to be invoked in query context. */
1187 MemoryContextSwitchTo(oldcontext);
1188
1189 if (cstate->whereClause)
1190 {
1191 econtext->ecxt_scantuple = myslot;
1192 /* Skip items that don't match COPY's WHERE clause */
1193 if (!ExecQual(cstate->qualexpr, econtext))
1194 {
1195 /*
1196 * Report that this tuple was filtered out by the WHERE
1197 * clause.
1198 */
1200 ++excluded);
1201 continue;
1202 }
1203 }
1204
1205 /* Determine the partition to insert the tuple into */
1206 if (proute)
1207 {
1208 TupleConversionMap *map;
1209
1210 /*
1211 * Attempt to find a partition suitable for this tuple.
1212 * ExecFindPartition() will raise an error if none can be found or
1213 * if the found partition is not suitable for INSERTs.
1214 */
1215 resultRelInfo = ExecFindPartition(mtstate, target_resultRelInfo,
1216 proute, myslot, estate);
1217
1218 if (prevResultRelInfo != resultRelInfo)
1219 {
1220 /* Determine which triggers exist on this partition */
1221 has_before_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
1222 resultRelInfo->ri_TrigDesc->trig_insert_before_row);
1223
1224 has_instead_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
1225 resultRelInfo->ri_TrigDesc->trig_insert_instead_row);
1226
1227 /*
1228 * Disable multi-inserts when the partition has BEFORE/INSTEAD
1229 * OF triggers, or if the partition is a foreign table that
1230 * can't use batching.
1231 */
1232 leafpart_use_multi_insert = insertMethod == CIM_MULTI_CONDITIONAL &&
1233 !has_before_insert_row_trig &&
1234 !has_instead_insert_row_trig &&
1235 (resultRelInfo->ri_FdwRoutine == NULL ||
1236 resultRelInfo->ri_BatchSize > 1);
1237
1238 /* Set the multi-insert buffer to use for this partition. */
1239 if (leafpart_use_multi_insert)
1240 {
1241 if (resultRelInfo->ri_CopyMultiInsertBuffer == NULL)
1242 CopyMultiInsertInfoSetupBuffer(&multiInsertInfo,
1243 resultRelInfo);
1244 }
1245 else if (insertMethod == CIM_MULTI_CONDITIONAL &&
1246 !CopyMultiInsertInfoIsEmpty(&multiInsertInfo))
1247 {
1248 /*
1249 * Flush pending inserts if this partition can't use
1250 * batching, so rows are visible to triggers etc.
1251 */
1252 CopyMultiInsertInfoFlush(&multiInsertInfo,
1253 resultRelInfo,
1254 &processed);
1255 }
1256
1257 if (bistate != NULL)
1259 prevResultRelInfo = resultRelInfo;
1260 }
1261
1262 /*
1263 * If we're capturing transition tuples, we might need to convert
1264 * from the partition rowtype to root rowtype. But if there are no
1265 * BEFORE triggers on the partition that could change the tuple,
1266 * we can just remember the original unconverted tuple to avoid a
1267 * needless round trip conversion.
1268 */
1269 if (cstate->transition_capture != NULL)
1271 !has_before_insert_row_trig ? myslot : NULL;
1272
1273 /*
1274 * We might need to convert from the root rowtype to the partition
1275 * rowtype.
1276 */
1277 map = ExecGetRootToChildMap(resultRelInfo, estate);
1278 if (insertMethod == CIM_SINGLE || !leafpart_use_multi_insert)
1279 {
1280 /* non batch insert */
1281 if (map != NULL)
1282 {
1283 TupleTableSlot *new_slot;
1284
1285 new_slot = resultRelInfo->ri_PartitionTupleSlot;
1286 myslot = execute_attr_map_slot(map->attrMap, myslot, new_slot);
1287 }
1288 }
1289 else
1290 {
1291 /*
1292 * Prepare to queue up tuple for later batch insert into
1293 * current partition.
1294 */
1295 TupleTableSlot *batchslot;
1296
1297 /* no other path available for partitioned table */
1298 Assert(insertMethod == CIM_MULTI_CONDITIONAL);
1299
1300 batchslot = CopyMultiInsertInfoNextFreeSlot(&multiInsertInfo,
1301 resultRelInfo);
1302
1303 if (map != NULL)
1304 myslot = execute_attr_map_slot(map->attrMap, myslot,
1305 batchslot);
1306 else
1307 {
1308 /*
1309 * This looks more expensive than it is (Believe me, I
1310 * optimized it away. Twice.). The input is in virtual
1311 * form, and we'll materialize the slot below - for most
1312 * slot types the copy performs the work materialization
1313 * would later require anyway.
1314 */
1315 ExecCopySlot(batchslot, myslot);
1316 myslot = batchslot;
1317 }
1318 }
1319
1320 /* ensure that triggers etc see the right relation */
1321 myslot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
1322 }
1323
1324 skip_tuple = false;
1325
1326 /* BEFORE ROW INSERT Triggers */
1327 if (has_before_insert_row_trig)
1328 {
1329 if (!ExecBRInsertTriggers(estate, resultRelInfo, myslot))
1330 skip_tuple = true; /* "do nothing" */
1331 }
1332
1333 if (!skip_tuple)
1334 {
1335 /*
1336 * If there is an INSTEAD OF INSERT ROW trigger, let it handle the
1337 * tuple. Otherwise, proceed with inserting the tuple into the
1338 * table or foreign table.
1339 */
1340 if (has_instead_insert_row_trig)
1341 {
1342 ExecIRInsertTriggers(estate, resultRelInfo, myslot);
1343 }
1344 else
1345 {
1346 /* Compute stored generated columns */
1347 if (resultRelInfo->ri_RelationDesc->rd_att->constr &&
1349 ExecComputeStoredGenerated(resultRelInfo, estate, myslot,
1350 CMD_INSERT);
1351
1352 /*
1353 * If the target is a plain table, check the constraints of
1354 * the tuple.
1355 */
1356 if (resultRelInfo->ri_FdwRoutine == NULL &&
1357 resultRelInfo->ri_RelationDesc->rd_att->constr)
1358 ExecConstraints(resultRelInfo, myslot, estate);
1359
1360 /*
1361 * Also check the tuple against the partition constraint, if
1362 * there is one; except that if we got here via tuple-routing,
1363 * we don't need to if there's no BR trigger defined on the
1364 * partition.
1365 */
1366 if (resultRelInfo->ri_RelationDesc->rd_rel->relispartition &&
1367 (proute == NULL || has_before_insert_row_trig))
1368 ExecPartitionCheck(resultRelInfo, myslot, estate, true);
1369
1370 /* Store the slot in the multi-insert buffer, when enabled. */
1371 if (insertMethod == CIM_MULTI || leafpart_use_multi_insert)
1372 {
1373 /*
1374 * The slot previously might point into the per-tuple
1375 * context. For batching it needs to be longer lived.
1376 */
1377 ExecMaterializeSlot(myslot);
1378
1379 /* Add this tuple to the tuple buffer */
1380 CopyMultiInsertInfoStore(&multiInsertInfo,
1381 resultRelInfo, myslot,
1382 cstate->line_buf.len,
1383 cstate->cur_lineno);
1384
1385 /*
1386 * If enough inserts have queued up, then flush all
1387 * buffers out to their tables.
1388 */
1389 if (CopyMultiInsertInfoIsFull(&multiInsertInfo))
1390 CopyMultiInsertInfoFlush(&multiInsertInfo,
1391 resultRelInfo,
1392 &processed);
1393
1394 /*
1395 * We delay updating the row counter and progress of the
1396 * COPY command until after writing the tuples stored in
1397 * the buffer out to the table, as in single insert mode.
1398 * See CopyMultiInsertBufferFlush().
1399 */
1400 continue; /* next tuple please */
1401 }
1402 else
1403 {
1404 List *recheckIndexes = NIL;
1405
1406 /* OK, store the tuple */
1407 if (resultRelInfo->ri_FdwRoutine != NULL)
1408 {
1409 myslot = resultRelInfo->ri_FdwRoutine->ExecForeignInsert(estate,
1410 resultRelInfo,
1411 myslot,
1412 NULL);
1413
1414 if (myslot == NULL) /* "do nothing" */
1415 continue; /* next tuple please */
1416
1417 /*
1418 * AFTER ROW Triggers might reference the tableoid
1419 * column, so (re-)initialize tts_tableOid before
1420 * evaluating them.
1421 */
1422 myslot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
1423 }
1424 else
1425 {
1426 /* OK, store the tuple and create index entries for it */
1427 table_tuple_insert(resultRelInfo->ri_RelationDesc,
1428 myslot, mycid, ti_options, bistate);
1429
1430 if (resultRelInfo->ri_NumIndices > 0)
1431 recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
1432 myslot,
1433 estate,
1434 false,
1435 false,
1436 NULL,
1437 NIL,
1438 false);
1439 }
1440
1441 /* AFTER ROW INSERT Triggers */
1442 ExecARInsertTriggers(estate, resultRelInfo, myslot,
1443 recheckIndexes, cstate->transition_capture);
1444
1445 list_free(recheckIndexes);
1446 }
1447 }
1448
1449 /*
1450 * We count only tuples not suppressed by a BEFORE INSERT trigger
1451 * or FDW; this is the same definition used by nodeModifyTable.c
1452 * for counting tuples inserted by an INSERT command. Update
1453 * progress of the COPY command as well.
1454 */
1456 ++processed);
1457 }
1458 }
1459
1460 /* Flush any remaining buffered tuples */
1461 if (insertMethod != CIM_SINGLE)
1462 {
1463 if (!CopyMultiInsertInfoIsEmpty(&multiInsertInfo))
1464 CopyMultiInsertInfoFlush(&multiInsertInfo, NULL, &processed);
1465 }
1466
1467 /* Done, clean up */
1468 error_context_stack = errcallback.previous;
1469
1470 if (cstate->opts.on_error != COPY_ON_ERROR_STOP &&
1471 cstate->num_errors > 0 &&
1474 errmsg_plural("%llu row was skipped due to data type incompatibility",
1475 "%llu rows were skipped due to data type incompatibility",
1476 (unsigned long long) cstate->num_errors,
1477 (unsigned long long) cstate->num_errors));
1478
1479 if (bistate != NULL)
1480 FreeBulkInsertState(bistate);
1481
1482 MemoryContextSwitchTo(oldcontext);
1483
1484 /* Execute AFTER STATEMENT insertion triggers */
1485 ExecASInsertTriggers(estate, target_resultRelInfo, cstate->transition_capture);
1486
1487 /* Handle queued AFTER triggers */
1488 AfterTriggerEndQuery(estate);
1489
1490 ExecResetTupleTable(estate->es_tupleTable, false);
1491
1492 /* Allow the FDW to shut down */
1493 if (target_resultRelInfo->ri_FdwRoutine != NULL &&
1494 target_resultRelInfo->ri_FdwRoutine->EndForeignInsert != NULL)
1495 target_resultRelInfo->ri_FdwRoutine->EndForeignInsert(estate,
1496 target_resultRelInfo);
1497
1498 /* Tear down the multi-insert buffer data */
1499 if (insertMethod != CIM_SINGLE)
1500 CopyMultiInsertInfoCleanup(&multiInsertInfo);
1501
1502 /* Close all the partitioned tables, leaf partitions, and their indices */
1503 if (proute)
1504 ExecCleanupTupleRouting(mtstate, proute);
1505
1506 /* Close the result relations, including any trigger target relations */
1509
1510 FreeExecutorState(estate);
1511
1512 return processed;
1513}
void pgstat_progress_update_param(int index, int64 val)
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:216
#define InvalidSubTransactionId
Definition: c.h:629
uint32 CommandId
Definition: c.h:637
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:537
static void CopyMultiInsertInfoSetupBuffer(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri)
Definition: copyfrom.c:380
static TupleTableSlot * CopyMultiInsertInfoNextFreeSlot(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri)
Definition: copyfrom.c:735
static void CopyMultiInsertInfoInit(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri, CopyFromState cstate, EState *estate, CommandId mycid, int ti_options)
Definition: copyfrom.c:400
static void CopyMultiInsertInfoFlush(CopyMultiInsertInfo *miinfo, ResultRelInfo *curr_rri, int64 *processed)
Definition: copyfrom.c:662
static void CopyMultiInsertInfoStore(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri, TupleTableSlot *slot, int tuplen, uint64 lineno)
Definition: copyfrom.c:756
static void CopyMultiInsertInfoCleanup(CopyMultiInsertInfo *miinfo)
Definition: copyfrom.c:716
static bool CopyMultiInsertInfoIsFull(CopyMultiInsertInfo *miinfo)
Definition: copyfrom.c:425
static bool CopyMultiInsertInfoIsEmpty(CopyMultiInsertInfo *miinfo)
Definition: copyfrom.c:437
void CopyFromErrorCallback(void *arg)
Definition: copyfrom.c:254
CopyInsertMethod
@ CIM_SINGLE
@ CIM_MULTI_CONDITIONAL
@ CIM_MULTI
bool NextCopyFrom(CopyFromState cstate, ExprContext *econtext, Datum *values, bool *nulls)
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1180
ErrorContextCallback * error_context_stack
Definition: elog.c:94
#define NOTICE
Definition: elog.h:35
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:229
void ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative)
Definition: execIndexing.c:160
List * ExecInsertIndexTuples(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool update, bool noDupErr, bool *specConflict, List *arbiterIndexes, bool onlySummarizing)
Definition: execIndexing.c:310
void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation, List *mergeActions)
Definition: execMain.c:1149
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
Definition: execMain.c:1930
void ExecCloseResultRelations(EState *estate)
Definition: execMain.c:1647
void ExecCloseRangeTableRelations(EState *estate)
Definition: execMain.c:1707
void ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:2054
PartitionTupleRouting * ExecSetupPartitionTupleRouting(EState *estate, Relation rel)
ResultRelInfo * ExecFindPartition(ModifyTableState *mtstate, ResultRelInfo *rootResultRelInfo, PartitionTupleRouting *proute, TupleTableSlot *slot, EState *estate)
void ExecCleanupTupleRouting(ModifyTableState *mtstate, PartitionTupleRouting *proute)
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:1378
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1739
TupleConversionMap * ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate)
Definition: execUtils.c:1328
void ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos, Bitmapset *unpruned_relids)
Definition: execUtils.c:775
void ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo, Index rti)
Definition: execUtils.c:882
void FreeExecutorState(EState *estate)
Definition: execUtils.c:193
EState * CreateExecutorState(void)
Definition: execUtils.c:88
#define ResetPerTupleExprContext(estate)
Definition: executor.h:646
#define GetPerTupleExprContext(estate)
Definition: executor.h:637
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:642
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:500
void ReleaseBulkInsertStatePin(BulkInsertState bistate)
Definition: heapam.c:2051
BulkInsertState GetBulkInsertState(void)
Definition: heapam.c:2022
void FreeBulkInsertState(BulkInsertState bistate)
Definition: heapam.c:2039
void list_free(List *list)
Definition: list.c:1546
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
void ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo, EState *estate, TupleTableSlot *slot, CmdType cmdtype)
#define castNode(_type_, nodeptr)
Definition: nodes.h:178
bool ThereAreNoReadyPortals(void)
Definition: portalmem.c:1173
#define PROGRESS_COPY_TUPLES_PROCESSED
Definition: progress.h:144
#define PROGRESS_COPY_TUPLES_EXCLUDED
Definition: progress.h:145
#define PROGRESS_COPY_TUPLES_SKIPPED
Definition: progress.h:148
bool ThereAreNoPriorRegisteredSnapshots(void)
Definition: snapmgr.c:1613
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:443
bool freeze
Definition: copy.h:65
CopyLogVerbosityChoice log_verbosity
Definition: copy.h:87
int64 reject_limit
Definition: copy.h:88
StringInfoData line_buf
TransitionCaptureState * transition_capture
List * es_tupleTable
Definition: execnodes.h:704
struct ErrorContextCallback * previous
Definition: elog.h:296
void(* callback)(void *arg)
Definition: elog.h:297
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:268
EndForeignInsert_function EndForeignInsert
Definition: fdwapi.h:239
BeginForeignInsert_function BeginForeignInsert
Definition: fdwapi.h:238
ExecForeignInsert_function ExecForeignInsert
Definition: fdwapi.h:232
ExecForeignBatchInsert_function ExecForeignBatchInsert
Definition: fdwapi.h:233
GetForeignModifyBatchSize_function GetForeignModifyBatchSize
Definition: fdwapi.h:234
CmdType operation
Definition: execnodes.h:1392
ResultRelInfo * resultRelInfo
Definition: execnodes.h:1396
PlanState ps
Definition: execnodes.h:1391
ResultRelInfo * rootResultRelInfo
Definition: execnodes.h:1404
struct TransitionCaptureState * mt_transition_capture
Definition: execnodes.h:1430
Plan * plan
Definition: execnodes.h:1153
EState * state
Definition: execnodes.h:1155
SubTransactionId rd_firstRelfilelocatorSubid
Definition: rel.h:106
TriggerDesc * trigdesc
Definition: rel.h:117
TupleDesc rd_att
Definition: rel.h:112
SubTransactionId rd_newRelfilelocatorSubid
Definition: rel.h:104
SubTransactionId rd_createSubid
Definition: rel.h:103
TupleTableSlot * ri_PartitionTupleSlot
Definition: execnodes.h:610
int ri_NumIndices
Definition: execnodes.h:478
Relation ri_RelationDesc
Definition: execnodes.h:475
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition: execnodes.h:613
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:510
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:528
int ri_BatchSize
Definition: execnodes.h:539
TupleTableSlot * tcs_original_insert_tuple
Definition: trigger.h:76
bool trig_insert_instead_row
Definition: reltrigger.h:58
bool trig_insert_new_table
Definition: reltrigger.h:75
bool trig_insert_before_row
Definition: reltrigger.h:56
bool has_generated_stored
Definition: tupdesc.h:46
AttrMap * attrMap
Definition: tupconvert.h:28
TupleConstr * constr
Definition: tupdesc.h:135
Oid tts_tableOid
Definition: tuptable.h:130
bool * tts_isnull
Definition: tuptable.h:127
Datum * tts_values
Definition: tuptable.h:125
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition: tableam.c:92
#define TABLE_INSERT_FROZEN
Definition: tableam.h:261
#define TABLE_INSERT_SKIP_FSM
Definition: tableam.h:260
static void table_tuple_insert(Relation rel, TupleTableSlot *slot, CommandId cid, int options, struct BulkInsertStateData *bistate)
Definition: tableam.h:1372
TransitionCaptureState * MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType)
Definition: trigger.c:4917
void ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2399
bool ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2463
bool ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2558
void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot, List *recheckIndexes, TransitionCaptureState *transition_capture)
Definition: trigger.c:2541
void ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo, TransitionCaptureState *transition_capture)
Definition: trigger.c:2450
void AfterTriggerEndQuery(EState *estate)
Definition: trigger.c:5088
void AfterTriggerBeginQuery(void)
Definition: trigger.c:5053
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition: tupconvert.c:192
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:454
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: tuptable.h:509
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition: tuptable.h:472
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:791
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:829

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

Referenced by copy_table(), and DoCopy().

◆ CopyFromErrorCallback()

void CopyFromErrorCallback ( void *  arg)

Definition at line 254 of file copyfrom.c.

255{
257
258 if (cstate->relname_only)
259 {
260 errcontext("COPY %s",
261 cstate->cur_relname);
262 return;
263 }
264 if (cstate->opts.binary)
265 {
266 /* can't usefully display the data */
267 if (cstate->cur_attname)
268 errcontext("COPY %s, line %llu, column %s",
269 cstate->cur_relname,
270 (unsigned long long) cstate->cur_lineno,
271 cstate->cur_attname);
272 else
273 errcontext("COPY %s, line %llu",
274 cstate->cur_relname,
275 (unsigned long long) cstate->cur_lineno);
276 }
277 else
278 {
279 if (cstate->cur_attname && cstate->cur_attval)
280 {
281 /* error is relevant to a particular column */
282 char *attval;
283
284 attval = CopyLimitPrintoutLength(cstate->cur_attval);
285 errcontext("COPY %s, line %llu, column %s: \"%s\"",
286 cstate->cur_relname,
287 (unsigned long long) cstate->cur_lineno,
288 cstate->cur_attname,
289 attval);
290 pfree(attval);
291 }
292 else if (cstate->cur_attname)
293 {
294 /* error is relevant to a particular column, value is NULL */
295 errcontext("COPY %s, line %llu, column %s: null input",
296 cstate->cur_relname,
297 (unsigned long long) cstate->cur_lineno,
298 cstate->cur_attname);
299 }
300 else
301 {
302 /*
303 * Error is relevant to a particular line.
304 *
305 * If line_buf still contains the correct line, print it.
306 */
307 if (cstate->line_buf_valid)
308 {
309 char *lineval;
310
311 lineval = CopyLimitPrintoutLength(cstate->line_buf.data);
312 errcontext("COPY %s, line %llu: \"%s\"",
313 cstate->cur_relname,
314 (unsigned long long) cstate->cur_lineno, lineval);
315 pfree(lineval);
316 }
317 else
318 {
319 errcontext("COPY %s, line %llu",
320 cstate->cur_relname,
321 (unsigned long long) cstate->cur_lineno);
322 }
323 }
324 }
325}
char * CopyLimitPrintoutLength(const char *str)
Definition: copyfrom.c:333
#define errcontext
Definition: elog.h:196
struct CopyFromStateData * CopyFromState
Definition: copy.h:93
void pfree(void *pointer)
Definition: mcxt.c:1524
void * arg
bool binary
Definition: copy.h:64

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

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

◆ CopyGetAttnums()

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

Definition at line 945 of file copy.c.

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

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

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

◆ CopyLimitPrintoutLength()

char * CopyLimitPrintoutLength ( const char *  str)

Definition at line 333 of file copyfrom.c.

334{
335#define MAX_COPY_DATA_DISPLAY 100
336
337 int slen = strlen(str);
338 int len;
339 char *res;
340
341 /* Fast path if definitely okay */
342 if (slen <= MAX_COPY_DATA_DISPLAY)
343 return pstrdup(str);
344
345 /* Apply encoding-dependent truncation */
347
348 /*
349 * Truncate, and add "..." to show we truncated the input.
350 */
351 res = (char *) palloc(len + 4);
352 memcpy(res, str, len);
353 strcpy(res + len, "...");
354
355 return res;
356}
#define MAX_COPY_DATA_DISPLAY
const char * str
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:1083
const void size_t len

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

Referenced by CopyFromErrorCallback(), and CopyFromTextLikeOneRow().

◆ CreateCopyDestReceiver()

DestReceiver * CreateCopyDestReceiver ( void  )

Definition at line 1433 of file copyto.c.

1434{
1435 DR_copy *self = (DR_copy *) palloc(sizeof(DR_copy));
1436
1441 self->pub.mydest = DestCopyOut;
1442
1443 self->cstate = NULL; /* will be set later */
1444 self->processed = 0;
1445
1446 return (DestReceiver *) self;
1447}
static bool copy_dest_receive(TupleTableSlot *slot, DestReceiver *self)
Definition: copyto.c:1396
static void copy_dest_destroy(DestReceiver *self)
Definition: copyto.c:1424
static void copy_dest_shutdown(DestReceiver *self)
Definition: copyto.c:1415
static void copy_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: copyto.c:1387
CopyToState cstate
Definition: copyto.c:104
DestReceiver pub
Definition: copyto.c:103
uint64 processed
Definition: copyto.c:105
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: dest.h:121
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:124
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:118
void(* rDestroy)(DestReceiver *self)
Definition: dest.h:126
CommandDest mydest
Definition: dest.h:128

References copy_dest_destroy(), copy_dest_receive(), copy_dest_shutdown(), copy_dest_startup(), DR_copy::cstate, DestCopyOut, _DestReceiver::mydest, palloc(), DR_copy::processed, DR_copy::pub, _DestReceiver::rDestroy, _DestReceiver::receiveSlot, _DestReceiver::rShutdown, and _DestReceiver::rStartup.

Referenced by CreateDestReceiver().

◆ DoCopy()

void DoCopy ( ParseState pstate,
const CopyStmt stmt,
int  stmt_location,
int  stmt_len,
uint64 processed 
)

Definition at line 62 of file copy.c.

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

References AccessShareLock, ACL_INSERT, ACL_SELECT, addNSItemToQuery(), addRangeTableEntryForRelation(), Assert(), assign_expr_collations(), BeginCopyFrom(), BeginCopyTo(), bms_add_member(), canonicalize_qual(), check_enable_rls(), coerce_to_boolean(), CopyFrom(), CopyGetAttnums(), cur, DoCopyTo(), EndCopyFrom(), EndCopyTo(), ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, eval_const_expressions(), ExecCheckPermissions(), EXPR_KIND_COPY_WHERE, ColumnRef::fields, FirstLowInvalidHeapAttributeNumber, get_namespace_name(), GetUserId(), has_privs_of_role(), ResTarget::indirection, RangeVar::inh, RTEPermissionInfo::insertedCols, InvalidOid, lappend(), lfirst, lfirst_int, list_make1, ColumnRef::location, ResTarget::location, make_ands_implicit(), makeNode, makeRangeVar(), ResTarget::name, NIL, NoLock, ParseNamespaceItem::p_perminfo, ParseState::p_rtable, PreventCommandIfReadOnly(), pstrdup(), RelationData::rd_islocaltemp, RelationGetDescr, RelationGetNamespace, RelationGetRelationName, RelationGetRelid, RTEPermissionInfo::requiredPerms, RLS_ENABLED, RowExclusiveLock, select, RTEPermissionInfo::selectedCols, RawStmt::stmt, stmt, RawStmt::stmt_len, RawStmt::stmt_location, table_close(), table_openrv(), transformExpr(), ResTarget::val, and XactReadOnly.

Referenced by standard_ProcessUtility().

◆ DoCopyTo()

uint64 DoCopyTo ( CopyToState  cstate)

Definition at line 1024 of file copyto.c.

1025{
1026 bool pipe = (cstate->filename == NULL && cstate->data_dest_cb == NULL);
1027 bool fe_copy = (pipe && whereToSendOutput == DestRemote);
1028 TupleDesc tupDesc;
1029 int num_phys_attrs;
1030 ListCell *cur;
1031 uint64 processed;
1032
1033 if (fe_copy)
1034 SendCopyBegin(cstate);
1035
1036 if (cstate->rel)
1037 tupDesc = RelationGetDescr(cstate->rel);
1038 else
1039 tupDesc = cstate->queryDesc->tupDesc;
1040 num_phys_attrs = tupDesc->natts;
1041 cstate->opts.null_print_client = cstate->opts.null_print; /* default */
1042
1043 /* We use fe_msgbuf as a per-row buffer regardless of copy_dest */
1044 cstate->fe_msgbuf = makeStringInfo();
1045
1046 /* Get info about the columns we need to process. */
1047 cstate->out_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
1048 foreach(cur, cstate->attnumlist)
1049 {
1050 int attnum = lfirst_int(cur);
1051 Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1052
1053 cstate->routine->CopyToOutFunc(cstate, attr->atttypid,
1054 &cstate->out_functions[attnum - 1]);
1055 }
1056
1057 /*
1058 * Create a temporary memory context that we can reset once per row to
1059 * recover palloc'd memory. This avoids any problems with leaks inside
1060 * datatype output routines, and should be faster than retail pfree's
1061 * anyway. (We don't need a whole econtext as CopyFrom does.)
1062 */
1064 "COPY TO",
1066
1067 cstate->routine->CopyToStart(cstate, tupDesc);
1068
1069 if (cstate->rel)
1070 {
1071 TupleTableSlot *slot;
1072 TableScanDesc scandesc;
1073
1074 scandesc = table_beginscan(cstate->rel, GetActiveSnapshot(), 0, NULL);
1075 slot = table_slot_create(cstate->rel, NULL);
1076
1077 processed = 0;
1078 while (table_scan_getnextslot(scandesc, ForwardScanDirection, slot))
1079 {
1081
1082 /* Deconstruct the tuple ... */
1083 slot_getallattrs(slot);
1084
1085 /* Format and send the data */
1086 CopyOneRowTo(cstate, slot);
1087
1088 /*
1089 * Increment the number of processed tuples, and report the
1090 * progress.
1091 */
1093 ++processed);
1094 }
1095
1097 table_endscan(scandesc);
1098 }
1099 else
1100 {
1101 /* run the plan --- the dest receiver will send tuples */
1103 processed = ((DR_copy *) cstate->queryDesc->dest)->processed;
1104 }
1105
1106 cstate->routine->CopyToEnd(cstate);
1107
1109
1110 if (fe_copy)
1111 SendCopyEnd(cstate);
1112
1113 return processed;
1114}
uint64_t uint64
Definition: c.h:503
static void SendCopyBegin(CopyToState cstate)
Definition: copyto.c:391
static void SendCopyEnd(CopyToState cstate)
Definition: copyto.c:408
static void CopyOneRowTo(CopyToState cstate, TupleTableSlot *slot)
Definition: copyto.c:1120
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition: execMain.c:362
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1441
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
@ ForwardScanDirection
Definition: sdir.h:28
StringInfo makeStringInfo(void)
Definition: stringinfo.c:72
char * null_print
Definition: copy.h:68
char * null_print_client
Definition: copy.h:70
void(* CopyToOutFunc)(CopyToState cstate, Oid atttypid, FmgrInfo *finfo)
Definition: copyapi.h:34
void(* CopyToEnd)(CopyToState cstate)
Definition: copyapi.h:54
void(* CopyToStart)(CopyToState cstate, TupleDesc tupDesc)
Definition: copyapi.h:44
FmgrInfo * out_functions
Definition: copyto.c:95
MemoryContext rowcontext
Definition: copyto.c:96
StringInfo fe_msgbuf
Definition: copyto.c:73
DestReceiver * dest
Definition: execdesc.h:42
static TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key)
Definition: tableam.h:877
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:989
static bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
Definition: tableam.h:1025
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:368

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, attnum, CopyToStateData::attnumlist, CHECK_FOR_INTERRUPTS, CopyOneRowTo(), CopyToRoutine::CopyToEnd, CopyToRoutine::CopyToOutFunc, CopyToRoutine::CopyToStart, cur, CurrentMemoryContext, CopyToStateData::data_dest_cb, QueryDesc::dest, DestRemote, ExecDropSingleTupleTableSlot(), ExecutorRun(), CopyToStateData::fe_msgbuf, CopyToStateData::filename, ForwardScanDirection, GetActiveSnapshot(), lfirst_int, makeStringInfo(), MemoryContextDelete(), TupleDescData::natts, CopyFormatOptions::null_print, CopyFormatOptions::null_print_client, CopyToStateData::opts, CopyToStateData::out_functions, palloc(), pgstat_progress_update_param(), PROGRESS_COPY_TUPLES_PROCESSED, CopyToStateData::queryDesc, CopyToStateData::rel, RelationGetDescr, CopyToStateData::routine, CopyToStateData::rowcontext, SendCopyBegin(), SendCopyEnd(), slot_getallattrs(), table_beginscan(), table_endscan(), table_scan_getnextslot(), table_slot_create(), QueryDesc::tupDesc, TupleDescAttr(), and whereToSendOutput.

Referenced by DoCopy(), and test_copy_to_callback().

◆ EndCopyFrom()

void EndCopyFrom ( CopyFromState  cstate)

Definition at line 1914 of file copyfrom.c.

1915{
1916 /* Invoke the end callback */
1917 cstate->routine->CopyFromEnd(cstate);
1918
1919 /* No COPY FROM related resources except memory. */
1920 if (cstate->is_program)
1921 {
1922 ClosePipeFromProgram(cstate);
1923 }
1924 else
1925 {
1926 if (cstate->filename != NULL && FreeFile(cstate->copy_file))
1927 ereport(ERROR,
1929 errmsg("could not close file \"%s\": %m",
1930 cstate->filename)));
1931 }
1932
1934
1936 pfree(cstate);
1937}
void pgstat_progress_end_command(void)
static void ClosePipeFromProgram(CopyFromState cstate)
Definition: copyfrom.c:1943
int FreeFile(FILE *file)
Definition: fd.c:2803
void(* CopyFromEnd)(CopyFromState cstate)
Definition: copyapi.h:102

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

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

◆ EndCopyTo()

void EndCopyTo ( CopyToState  cstate)

Definition at line 1003 of file copyto.c.

1004{
1005 if (cstate->queryDesc != NULL)
1006 {
1007 /* Close down the query and free resources. */
1008 ExecutorFinish(cstate->queryDesc);
1009 ExecutorEnd(cstate->queryDesc);
1010 FreeQueryDesc(cstate->queryDesc);
1012 }
1013
1014 /* Clean up storage */
1015 EndCopy(cstate);
1016}
static void EndCopy(CopyToState cstate)
Definition: copyto.c:587
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:535
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:472
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:112
void PopActiveSnapshot(void)
Definition: snapmgr.c:762

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

Referenced by DoCopy(), and test_copy_to_callback().

◆ NextCopyFrom()

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

Definition at line 871 of file copyfromparse.c.

873{
874 TupleDesc tupDesc;
875 AttrNumber num_phys_attrs,
876 num_defaults = cstate->num_defaults;
877 int i;
878 int *defmap = cstate->defmap;
879 ExprState **defexprs = cstate->defexprs;
880
881 tupDesc = RelationGetDescr(cstate->rel);
882 num_phys_attrs = tupDesc->natts;
883
884 /* Initialize all values for row to NULL */
885 MemSet(values, 0, num_phys_attrs * sizeof(Datum));
886 MemSet(nulls, true, num_phys_attrs * sizeof(bool));
887 MemSet(cstate->defaults, false, num_phys_attrs * sizeof(bool));
888
889 /* Get one row from source */
890 if (!cstate->routine->CopyFromOneRow(cstate, econtext, values, nulls))
891 return false;
892
893 /*
894 * Now compute and insert any defaults available for the columns not
895 * provided by the input data. Anything not processed here or above will
896 * remain NULL.
897 */
898 for (i = 0; i < num_defaults; i++)
899 {
900 /*
901 * The caller must supply econtext and have switched into the
902 * per-tuple memory context in it.
903 */
904 Assert(econtext != NULL);
906
907 values[defmap[i]] = ExecEvalExpr(defexprs[defmap[i]], econtext,
908 &nulls[defmap[i]]);
909 }
910
911 return true;
912}
static Datum values[MAXATTR]
Definition: bootstrap.c:151
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:374
uintptr_t Datum
Definition: postgres.h:69
bool(* CopyFromOneRow)(CopyFromState cstate, ExprContext *econtext, Datum *values, bool *nulls)
Definition: copyapi.h:96
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:276

References Assert(), CopyFromRoutine::CopyFromOneRow, CurrentMemoryContext, CopyFromStateData::defaults, CopyFromStateData::defexprs, CopyFromStateData::defmap, ExprContext::ecxt_per_tuple_memory, ExecEvalExpr(), i, MemSet, TupleDescData::natts, CopyFromStateData::num_defaults, CopyFromStateData::rel, RelationGetDescr, CopyFromStateData::routine, and values.

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

◆ NextCopyFromRawFields()

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

Definition at line 747 of file copyfromparse.c.

748{
749 return NextCopyFromRawFieldsInternal(cstate, fields, nfields,
750 cstate->opts.csv_mode);
751}
static pg_attribute_always_inline bool NextCopyFromRawFieldsInternal(CopyFromState cstate, char ***fields, int *nfields, bool is_csv)
bool csv_mode
Definition: copy.h:66

References CopyFormatOptions::csv_mode, NextCopyFromRawFieldsInternal(), and CopyFromStateData::opts.

◆ ProcessCopyOptions()

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

Definition at line 496 of file copy.c.

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

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

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