PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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:674
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:1158
int errcode_for_file_access(void)
Definition: elog.c:877
int errhint(const char *fmt,...)
Definition: elog.c:1318
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#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:2747
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2644
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:2325
void * palloc0(Size size)
Definition: mcxt.c:1973
void * palloc(Size size)
Definition: mcxt.c:1943
MemoryContext CurrentMemoryContext
Definition: mcxt.c:159
#define AllocSetContextCreate
Definition: memutils.h:149
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:180
Oid FindDefaultConversionProc(int32 for_encoding, int32 to_encoding)
Definition: namespace.c:4080
#define makeNode(_type_)
Definition: nodes.h:161
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:202
static char * filename
Definition: pg_dumpall.c:123
#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:6688
CommandDest whereToSendOutput
Definition: postgres.c:91
#define InvalidOid
Definition: postgres_ext.h:35
unsigned int Oid
Definition: postgres_ext.h:30
#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:516
#define RelationGetDescr(relation)
Definition: rel.h:542
#define RelationGetRelationName(relation)
Definition: rel.h:550
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:135
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:160
#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)
656 {
657 if (!RelationIsPopulated(rel))
659 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
660 errmsg("cannot copy from unpopulated materialized view \"%s\"",
662 errhint("Use the REFRESH MATERIALIZED VIEW command."));
663 }
664 else if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
666 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
667 errmsg("cannot copy from foreign table \"%s\"",
669 errhint("Try the COPY (SELECT ...) TO variant.")));
670 else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
672 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
673 errmsg("cannot copy from sequence \"%s\"",
675 else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
677 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
678 errmsg("cannot copy from partitioned table \"%s\"",
680 errhint("Try the COPY (SELECT ...) TO variant.")));
681 else
683 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
684 errmsg("cannot copy from non-table relation \"%s\"",
686 }
687
688
689 /* Allocate workspace and zero all fields */
690 cstate = (CopyToStateData *) palloc0(sizeof(CopyToStateData));
691
692 /*
693 * We allocate everything used by a cstate in a new memory context. This
694 * avoids memory leaks during repeated use of COPY in a query.
695 */
697 "COPY",
699
700 oldcontext = MemoryContextSwitchTo(cstate->copycontext);
701
702 /* Extract options from the statement node tree */
703 ProcessCopyOptions(pstate, &cstate->opts, false /* is_from */ , options);
704
705 /* Set format routine */
706 cstate->routine = CopyToGetRoutine(&cstate->opts);
707
708 /* Process the source/target relation or query */
709 if (rel)
710 {
711 Assert(!raw_query);
712
713 cstate->rel = rel;
714
715 tupDesc = RelationGetDescr(cstate->rel);
716 }
717 else
718 {
719 List *rewritten;
720 Query *query;
723
724 cstate->rel = NULL;
725
726 /*
727 * Run parse analysis and rewrite. Note this also acquires sufficient
728 * locks on the source table(s).
729 */
730 rewritten = pg_analyze_and_rewrite_fixedparams(raw_query,
731 pstate->p_sourcetext, NULL, 0,
732 NULL);
733
734 /* check that we got back something we can work with */
735 if (rewritten == NIL)
736 {
738 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
739 errmsg("DO INSTEAD NOTHING rules are not supported for COPY")));
740 }
741 else if (list_length(rewritten) > 1)
742 {
743 ListCell *lc;
744
745 /* examine queries to determine which error message to issue */
746 foreach(lc, rewritten)
747 {
748 Query *q = lfirst_node(Query, lc);
749
750 if (q->querySource == QSRC_QUAL_INSTEAD_RULE)
752 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
753 errmsg("conditional DO INSTEAD rules are not supported for COPY")));
754 if (q->querySource == QSRC_NON_INSTEAD_RULE)
756 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
757 errmsg("DO ALSO rules are not supported for COPY")));
758 }
759
761 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
762 errmsg("multi-statement DO INSTEAD rules are not supported for COPY")));
763 }
764
765 query = linitial_node(Query, rewritten);
766
767 /* The grammar allows SELECT INTO, but we don't support that */
768 if (query->utilityStmt != NULL &&
771 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
772 errmsg("COPY (SELECT INTO) is not supported")));
773
774 /* The only other utility command we could see is NOTIFY */
775 if (query->utilityStmt != NULL)
777 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
778 errmsg("COPY query must not be a utility command")));
779
780 /*
781 * Similarly the grammar doesn't enforce the presence of a RETURNING
782 * clause, but this is required here.
783 */
784 if (query->commandType != CMD_SELECT &&
785 query->returningList == NIL)
786 {
787 Assert(query->commandType == CMD_INSERT ||
788 query->commandType == CMD_UPDATE ||
789 query->commandType == CMD_DELETE ||
790 query->commandType == CMD_MERGE);
791
793 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
794 errmsg("COPY query must have a RETURNING clause")));
795 }
796
797 /* plan the query */
798 plan = pg_plan_query(query, pstate->p_sourcetext,
800
801 /*
802 * With row-level security and a user using "COPY relation TO", we
803 * have to convert the "COPY relation TO" to a query-based COPY (eg:
804 * "COPY (SELECT * FROM ONLY relation) TO"), to allow the rewriter to
805 * add in any RLS clauses.
806 *
807 * When this happens, we are passed in the relid of the originally
808 * found relation (which we have locked). As the planner will look up
809 * the relation again, we double-check here to make sure it found the
810 * same one that we have locked.
811 */
812 if (queryRelId != InvalidOid)
813 {
814 /*
815 * Note that with RLS involved there may be multiple relations,
816 * and while the one we need is almost certainly first, we don't
817 * make any guarantees of that in the planner, so check the whole
818 * list and make sure we find the original relation.
819 */
820 if (!list_member_oid(plan->relationOids, queryRelId))
822 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
823 errmsg("relation referenced by COPY statement has changed")));
824 }
825
826 /*
827 * Use a snapshot with an updated command ID to ensure this query sees
828 * results of any previously executed queries.
829 */
832
833 /* Create dest receiver for COPY OUT */
835 ((DR_copy *) dest)->cstate = cstate;
836
837 /* Create a QueryDesc requesting no output */
838 cstate->queryDesc = CreateQueryDesc(plan, NULL, pstate->p_sourcetext,
841 dest, NULL, NULL, 0);
842
843 /*
844 * Call ExecutorStart to prepare the plan for execution.
845 *
846 * ExecutorStart computes a result tupdesc for us
847 */
848 if (!ExecutorStart(cstate->queryDesc, 0))
849 elog(ERROR, "ExecutorStart() failed unexpectedly");
850
851 tupDesc = cstate->queryDesc->tupDesc;
852 }
853
854 /* Generate or convert list of attributes to process */
855 cstate->attnumlist = CopyGetAttnums(tupDesc, cstate->rel, attnamelist);
856
857 num_phys_attrs = tupDesc->natts;
858
859 /* Convert FORCE_QUOTE name list to per-column flags, check validity */
860 cstate->opts.force_quote_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
861 if (cstate->opts.force_quote_all)
862 {
863 MemSet(cstate->opts.force_quote_flags, true, num_phys_attrs * sizeof(bool));
864 }
865 else if (cstate->opts.force_quote)
866 {
867 List *attnums;
868 ListCell *cur;
869
870 attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_quote);
871
872 foreach(cur, attnums)
873 {
874 int attnum = lfirst_int(cur);
875 Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
876
877 if (!list_member_int(cstate->attnumlist, attnum))
879 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
880 /*- translator: %s is the name of a COPY option, e.g. FORCE_NOT_NULL */
881 errmsg("%s column \"%s\" not referenced by COPY",
882 "FORCE_QUOTE", NameStr(attr->attname))));
883 cstate->opts.force_quote_flags[attnum - 1] = true;
884 }
885 }
886
887 /* Use client encoding when ENCODING option is not specified. */
888 if (cstate->opts.file_encoding < 0)
890 else
891 cstate->file_encoding = cstate->opts.file_encoding;
892
893 /*
894 * Set up encoding conversion info if the file and server encodings differ
895 * (see also pg_server_to_any).
896 */
897 if (cstate->file_encoding == GetDatabaseEncoding() ||
898 cstate->file_encoding == PG_SQL_ASCII)
899 cstate->need_transcoding = false;
900 else
901 cstate->need_transcoding = true;
902
903 /* See Multibyte encoding comment above */
905
906 cstate->copy_dest = COPY_FILE; /* default */
907
908 if (data_dest_cb)
909 {
910 progress_vals[1] = PROGRESS_COPY_TYPE_CALLBACK;
911 cstate->copy_dest = COPY_CALLBACK;
912 cstate->data_dest_cb = data_dest_cb;
913 }
914 else if (pipe)
915 {
916 progress_vals[1] = PROGRESS_COPY_TYPE_PIPE;
917
918 Assert(!is_program); /* the grammar does not allow this */
920 cstate->copy_file = stdout;
921 }
922 else
923 {
924 cstate->filename = pstrdup(filename);
925 cstate->is_program = is_program;
926
927 if (is_program)
928 {
929 progress_vals[1] = PROGRESS_COPY_TYPE_PROGRAM;
930 cstate->copy_file = OpenPipeStream(cstate->filename, PG_BINARY_W);
931 if (cstate->copy_file == NULL)
934 errmsg("could not execute command \"%s\": %m",
935 cstate->filename)));
936 }
937 else
938 {
939 mode_t oumask; /* Pre-existing umask value */
940 struct stat st;
941
942 progress_vals[1] = PROGRESS_COPY_TYPE_FILE;
943
944 /*
945 * Prevent write to relative path ... too easy to shoot oneself in
946 * the foot by overwriting a database file ...
947 */
950 (errcode(ERRCODE_INVALID_NAME),
951 errmsg("relative path not allowed for COPY to file")));
952
953 oumask = umask(S_IWGRP | S_IWOTH);
954 PG_TRY();
955 {
956 cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_W);
957 }
958 PG_FINALLY();
959 {
960 umask(oumask);
961 }
962 PG_END_TRY();
963 if (cstate->copy_file == NULL)
964 {
965 /* copy errno because ereport subfunctions might change it */
966 int save_errno = errno;
967
970 errmsg("could not open file \"%s\" for writing: %m",
971 cstate->filename),
972 (save_errno == ENOENT || save_errno == EACCES) ?
973 errhint("COPY TO instructs the PostgreSQL server process to write a file. "
974 "You may want a client-side facility such as psql's \\copy.") : 0));
975 }
976
977 if (fstat(fileno(cstate->copy_file), &st))
980 errmsg("could not stat file \"%s\": %m",
981 cstate->filename)));
982
983 if (S_ISDIR(st.st_mode))
985 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
986 errmsg("\"%s\" is a directory", cstate->filename)));
987 }
988 }
989
990 /* initialize progress */
992 cstate->rel ? RelationGetRelid(cstate->rel) : InvalidOid);
993 pgstat_progress_update_multi_param(2, progress_cols, progress_vals);
994
995 cstate->bytes_processed = 0;
996
997 MemoryContextSwitchTo(oldcontext);
998
999 return cstate;
1000}
#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:128
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:722
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
@ CMD_MERGE
Definition: nodes.h:275
@ CMD_INSERT
Definition: nodes.h:273
@ CMD_DELETE
Definition: nodes.h:274
@ CMD_UPDATE
Definition: nodes.h:272
@ CMD_SELECT
Definition: nodes.h:271
@ QSRC_NON_INSTEAD_RULE
Definition: parsenodes.h:40
@ QSRC_QUAL_INSTEAD_RULE
Definition: parsenodes.h:39
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:3385
#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
#define RelationIsPopulated(relation)
Definition: rel.h:688
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, RelationIsPopulated, 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 (%" PRId64 ") rows due to data type incompatibility",
1172 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("%" PRIu64 " row was skipped due to data type incompatibility",
1475 "%" PRIu64 " rows were skipped due to data type incompatibility",
1476 cstate->num_errors,
1477 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:539
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:1181
ErrorContextCallback * error_context_stack
Definition: elog.c:95
#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:309
void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation, List *mergeActions)
Definition: execMain.c:1152
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
Definition: execMain.c:1932
void ExecCloseResultRelations(EState *estate)
Definition: execMain.c:1651
void ExecCloseRangeTableRelations(EState *estate)
Definition: execMain.c:1711
void ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:2056
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:1380
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1741
TupleConversionMap * ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate)
Definition: execUtils.c:1327
void ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos, Bitmapset *unpruned_relids)
Definition: execUtils.c:774
void ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo, Index rti)
Definition: execUtils.c:881
void FreeExecutorState(EState *estate)
Definition: execUtils.c:193
EState * CreateExecutorState(void)
Definition: execUtils.c:88
#define ResetPerTupleExprContext(estate)
Definition: executor.h:687
#define GetPerTupleExprContext(estate)
Definition: executor.h:678
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:683
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:541
void ReleaseBulkInsertStatePin(BulkInsertState bistate)
Definition: heapam.c:2018
BulkInsertState GetBulkInsertState(void)
Definition: heapam.c:1989
void FreeBulkInsertState(BulkInsertState bistate)
Definition: heapam.c:2006
void list_free(List *list)
Definition: list.c:1546
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:123
void ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo, EState *estate, TupleTableSlot *slot, CmdType cmdtype)
#define castNode(_type_, nodeptr)
Definition: nodes.h:182
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:710
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:1398
ResultRelInfo * resultRelInfo
Definition: execnodes.h:1402
PlanState ps
Definition: execnodes.h:1397
ResultRelInfo * rootResultRelInfo
Definition: execnodes.h:1410
struct TransitionCaptureState * mt_transition_capture
Definition: execnodes.h:1436
Plan * plan
Definition: execnodes.h:1159
EState * state
Definition: execnodes.h:1161
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:616
int ri_NumIndices
Definition: execnodes.h:478
Relation ri_RelationDesc
Definition: execnodes.h:475
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition: execnodes.h:619
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:141
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:254
#define TABLE_INSERT_SKIP_FSM
Definition: tableam.h:253
static void table_tuple_insert(Relation rel, TupleTableSlot *slot, CommandId cid, int options, struct BulkInsertStateData *bistate)
Definition: tableam.h:1362
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:458
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: tuptable.h:525
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition: tuptable.h:476
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 %" PRIu64 ", column %s",
269 cstate->cur_relname,
270 cstate->cur_lineno,
271 cstate->cur_attname);
272 else
273 errcontext("COPY %s, line %" PRIu64,
274 cstate->cur_relname,
275 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 %" PRIu64 ", column %s: \"%s\"",
286 cstate->cur_relname,
287 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 %" PRIu64 ", column %s: null input",
296 cstate->cur_relname,
297 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 %" PRIu64 ": \"%s\"",
313 cstate->cur_relname,
314 cstate->cur_lineno, lineval);
315 pfree(lineval);
316 }
317 else
318 {
319 errcontext("COPY %s, line %" PRIu64,
320 cstate->cur_relname,
321 cstate->cur_lineno);
322 }
323 }
324 }
325}
char * CopyLimitPrintoutLength(const char *str)
Definition: copyfrom.c:333
#define errcontext
Definition: elog.h:197
struct CopyFromStateData * CopyFromState
Definition: copy.h:93
void pfree(void *pointer)
Definition: mcxt.c:2150
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:1204
int i
Definition: isn.c:77
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:175
#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 1436 of file copyto.c.

1437{
1438 DR_copy *self = (DR_copy *) palloc(sizeof(DR_copy));
1439
1444 self->pub.mydest = DestCopyOut;
1445
1446 self->cstate = NULL; /* will be set later */
1447 self->processed = 0;
1448
1449 return (DestReceiver *) self;
1450}
static bool copy_dest_receive(TupleTableSlot *slot, DestReceiver *self)
Definition: copyto.c:1399
static void copy_dest_destroy(DestReceiver *self)
Definition: copyto.c:1427
static void copy_dest_shutdown(DestReceiver *self)
Definition: copyto.c:1418
static void copy_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: copyto.c:1390
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:2256
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:1027
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:1006
bool ExecCheckPermissions(List *rangeTable, List *rteperminfos, bool ereport_on_violation)
Definition: execMain.c:661
#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:3506
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:557
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:1307
AclMode requiredPerms
Definition: parsenodes.h:1305
Bitmapset * insertedCols
Definition: parsenodes.h:1308
bool inh
Definition: primnodes.h:86
ParseLoc stmt_location
Definition: parsenodes.h:2072
ParseLoc stmt_len
Definition: parsenodes.h:2073
Node * stmt
Definition: parsenodes.h:2071
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 1027 of file copyto.c.

1028{
1029 bool pipe = (cstate->filename == NULL && cstate->data_dest_cb == NULL);
1030 bool fe_copy = (pipe && whereToSendOutput == DestRemote);
1031 TupleDesc tupDesc;
1032 int num_phys_attrs;
1033 ListCell *cur;
1034 uint64 processed;
1035
1036 if (fe_copy)
1037 SendCopyBegin(cstate);
1038
1039 if (cstate->rel)
1040 tupDesc = RelationGetDescr(cstate->rel);
1041 else
1042 tupDesc = cstate->queryDesc->tupDesc;
1043 num_phys_attrs = tupDesc->natts;
1044 cstate->opts.null_print_client = cstate->opts.null_print; /* default */
1045
1046 /* We use fe_msgbuf as a per-row buffer regardless of copy_dest */
1047 cstate->fe_msgbuf = makeStringInfo();
1048
1049 /* Get info about the columns we need to process. */
1050 cstate->out_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
1051 foreach(cur, cstate->attnumlist)
1052 {
1053 int attnum = lfirst_int(cur);
1054 Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1055
1056 cstate->routine->CopyToOutFunc(cstate, attr->atttypid,
1057 &cstate->out_functions[attnum - 1]);
1058 }
1059
1060 /*
1061 * Create a temporary memory context that we can reset once per row to
1062 * recover palloc'd memory. This avoids any problems with leaks inside
1063 * datatype output routines, and should be faster than retail pfree's
1064 * anyway. (We don't need a whole econtext as CopyFrom does.)
1065 */
1067 "COPY TO",
1069
1070 cstate->routine->CopyToStart(cstate, tupDesc);
1071
1072 if (cstate->rel)
1073 {
1074 TupleTableSlot *slot;
1075 TableScanDesc scandesc;
1076
1077 scandesc = table_beginscan(cstate->rel, GetActiveSnapshot(), 0, NULL);
1078 slot = table_slot_create(cstate->rel, NULL);
1079
1080 processed = 0;
1081 while (table_scan_getnextslot(scandesc, ForwardScanDirection, slot))
1082 {
1084
1085 /* Deconstruct the tuple ... */
1086 slot_getallattrs(slot);
1087
1088 /* Format and send the data */
1089 CopyOneRowTo(cstate, slot);
1090
1091 /*
1092 * Increment the number of processed tuples, and report the
1093 * progress.
1094 */
1096 ++processed);
1097 }
1098
1100 table_endscan(scandesc);
1101 }
1102 else
1103 {
1104 /* run the plan --- the dest receiver will send tuples */
1106 processed = ((DR_copy *) cstate->queryDesc->dest)->processed;
1107 }
1108
1109 cstate->routine->CopyToEnd(cstate);
1110
1112
1113 if (fe_copy)
1114 SendCopyEnd(cstate);
1115
1116 return processed;
1117}
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:1123
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition: execMain.c:365
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1443
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:485
@ 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:870
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:979
static bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
Definition: tableam.h:1015
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:372

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:2843
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 1006 of file copyto.c.

1007{
1008 if (cstate->queryDesc != NULL)
1009 {
1010 /* Close down the query and free resources. */
1011 ExecutorFinish(cstate->queryDesc);
1012 ExecutorEnd(cstate->queryDesc);
1013 FreeQueryDesc(cstate->queryDesc);
1015 }
1016
1017 /* Clean up storage */
1018 EndCopy(cstate);
1019}
static void EndCopy(CopyToState cstate)
Definition: copyto.c:587
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:538
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:475
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:415
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().