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

Go to the source code of this file.

Data Structures

struct  CopyFormatOptions
 

Macros

#define COPY_HEADER_MATCH   -1
 
#define COPY_HEADER_FALSE   0
 
#define COPY_HEADER_TRUE   1
 

Typedefs

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  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)
 

Macro Definition Documentation

◆ COPY_HEADER_FALSE

#define COPY_HEADER_FALSE   0

Definition at line 27 of file copy.h.

◆ COPY_HEADER_MATCH

#define COPY_HEADER_MATCH   -1

Definition at line 26 of file copy.h.

◆ COPY_HEADER_TRUE

#define COPY_HEADER_TRUE   1

Definition at line 28 of file copy.h.

Typedef Documentation

◆ copy_data_dest_cb

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

Definition at line 95 of file copy.h.

◆ copy_data_source_cb

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

Definition at line 94 of file copy.h.

◆ CopyFormatOptions

◆ CopyFromState

Definition at line 91 of file copy.h.

◆ CopyLogVerbosityChoice

◆ CopyOnErrorChoice

◆ CopyToState

typedef struct CopyToStateData* CopyToState

Definition at line 92 of file copy.h.

Enumeration Type Documentation

◆ CopyLogVerbosityChoice

Enumerator
COPY_LOG_VERBOSITY_SILENT 
COPY_LOG_VERBOSITY_DEFAULT 
COPY_LOG_VERBOSITY_VERBOSE 

Definition at line 43 of file copy.h.

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

◆ CopyOnErrorChoice

Enumerator
COPY_ON_ERROR_STOP 
COPY_ON_ERROR_IGNORE 

Definition at line 34 of file copy.h.

35{
36 COPY_ON_ERROR_STOP = 0, /* immediately throw errors, default */
37 COPY_ON_ERROR_IGNORE, /* ignore errors */
CopyOnErrorChoice
Definition: copy.h:35
@ COPY_ON_ERROR_IGNORE
Definition: copy.h:37
@ COPY_ON_ERROR_STOP
Definition: copy.h:36

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:998
void ProcessCopyOptions(ParseState *pstate, CopyFormatOptions *opts_out, bool is_from, List *options)
Definition: copy.c:549
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:754
#define PG_BINARY_R
Definition: c.h:1263
int64_t int64
Definition: c.h:538
#define MemSet(start, val, len)
Definition: c.h:1022
#define OidIsValid(objectId)
Definition: c.h:777
bool contain_volatile_functions_not_nextval(Node *clause)
Definition: clauses.c:685
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:47
@ COPY_CALLBACK
Definition: copyto.c:49
@ DestRemote
Definition: dest.h:89
struct cursor * cur
Definition: ecpg.c:29
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1170
int errcode_for_file_access(void)
Definition: elog.c:886
int errhint(const char *fmt,...)
Definition: elog.c:1330
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:150
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:143
FILE * OpenPipeStream(const char *command, const char *mode)
Definition: fd.c:2744
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2641
Assert(PointerIsAligned(start, uint64))
bool list_member_int(const List *list, int datum)
Definition: list.c:702
int GetDatabaseEncoding(void)
Definition: mbutils.c:1262
int pg_get_client_encoding(void)
Definition: mbutils.c:337
char * pstrdup(const char *in)
Definition: mcxt.c:1759
void * palloc0(Size size)
Definition: mcxt.c:1395
void * palloc(Size size)
Definition: mcxt.c:1365
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
Oid FindDefaultConversionProc(int32 for_encoding, int32 to_encoding)
Definition: namespace.c:4150
#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:120
#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:6763
CommandDest whereToSendOutput
Definition: postgres.c:92
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
#define PROGRESS_COPY_COMMAND
Definition: progress.h:151
#define PROGRESS_COPY_TYPE_FILE
Definition: progress.h:160
#define PROGRESS_COPY_COMMAND_FROM
Definition: progress.h:156
#define PROGRESS_COPY_TYPE
Definition: progress.h:152
#define PROGRESS_COPY_TYPE_PROGRAM
Definition: progress.h:161
#define PROGRESS_COPY_BYTES_TOTAL
Definition: progress.h:148
#define PROGRESS_COPY_TYPE_CALLBACK
Definition: progress.h:163
#define PROGRESS_COPY_TYPE_PIPE
Definition: progress.h:162
#define RelationGetRelid(relation)
Definition: rel.h:515
#define RelationGetDescr(relation)
Definition: rel.h:541
#define RelationGetRelationName(relation)
Definition: rel.h:549
Node * build_column_default(Relation rel, int attrno)
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
bool force_notnull_all
Definition: copy.h:78
bool convert_selectively
Definition: copy.h:83
CopyOnErrorChoice on_error
Definition: copy.h:84
List * force_null
Definition: copy.h:80
List * convert_select
Definition: copy.h:87
bool force_null_all
Definition: copy.h:81
bool * force_notnull_flags
Definition: copy.h:79
int file_encoding
Definition: copy.h:59
bool * force_null_flags
Definition: copy.h:82
char * default_print
Definition: copy.h:69
List * force_notnull
Definition: copy.h:77
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:197
List * p_rtable
Definition: parse_node.h:196
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 632 of file copyto.c.

641{
642 CopyToState cstate;
643 bool pipe = (filename == NULL && data_dest_cb == NULL);
644 TupleDesc tupDesc;
645 int num_phys_attrs;
646 MemoryContext oldcontext;
647 const int progress_cols[] = {
650 };
651 int64 progress_vals[] = {
653 0
654 };
655 List *children = NIL;
656
657 if (rel != NULL && rel->rd_rel->relkind != RELKIND_RELATION)
658 {
659 if (rel->rd_rel->relkind == RELKIND_VIEW)
661 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
662 errmsg("cannot copy from view \"%s\"",
664 errhint("Try the COPY (SELECT ...) TO variant.")));
665 else if (rel->rd_rel->relkind == RELKIND_MATVIEW)
666 {
667 if (!RelationIsPopulated(rel))
669 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
670 errmsg("cannot copy from unpopulated materialized view \"%s\"",
672 errhint("Use the REFRESH MATERIALIZED VIEW command."));
673 }
674 else if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
676 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
677 errmsg("cannot copy from foreign table \"%s\"",
679 errhint("Try the COPY (SELECT ...) TO variant.")));
680 else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
682 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
683 errmsg("cannot copy from sequence \"%s\"",
685 else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
686 {
687 /*
688 * Collect OIDs of relation containing data, so that later
689 * DoCopyTo can copy the data from them.
690 */
692
693 foreach_oid(child, children)
694 {
695 char relkind = get_rel_relkind(child);
696
697 if (relkind == RELKIND_FOREIGN_TABLE)
698 {
699 char *relation_name = get_rel_name(child);
700
702 errcode(ERRCODE_WRONG_OBJECT_TYPE),
703 errmsg("cannot copy from foreign table \"%s\"", relation_name),
704 errdetail("Partition \"%s\" is a foreign table in partitioned table \"%s\"",
705 relation_name, RelationGetRelationName(rel)),
706 errhint("Try the COPY (SELECT ...) TO variant."));
707 }
708
709 /* Exclude tables with no data */
710 if (RELKIND_HAS_PARTITIONS(relkind))
711 children = foreach_delete_current(children, child);
712 }
713 }
714 else
716 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
717 errmsg("cannot copy from non-table relation \"%s\"",
719 }
720
721
722 /* Allocate workspace and zero all fields */
723 cstate = (CopyToStateData *) palloc0(sizeof(CopyToStateData));
724
725 /*
726 * We allocate everything used by a cstate in a new memory context. This
727 * avoids memory leaks during repeated use of COPY in a query.
728 */
730 "COPY",
732
733 oldcontext = MemoryContextSwitchTo(cstate->copycontext);
734
735 /* Extract options from the statement node tree */
736 ProcessCopyOptions(pstate, &cstate->opts, false /* is_from */ , options);
737
738 /* Set format routine */
739 cstate->routine = CopyToGetRoutine(&cstate->opts);
740
741 /* Process the source/target relation or query */
742 if (rel)
743 {
744 Assert(!raw_query);
745
746 cstate->rel = rel;
747
748 tupDesc = RelationGetDescr(cstate->rel);
749 cstate->partitions = children;
750 }
751 else
752 {
753 List *rewritten;
754 Query *query;
757
758 cstate->rel = NULL;
759 cstate->partitions = NIL;
760
761 /*
762 * Run parse analysis and rewrite. Note this also acquires sufficient
763 * locks on the source table(s).
764 */
765 rewritten = pg_analyze_and_rewrite_fixedparams(raw_query,
766 pstate->p_sourcetext, NULL, 0,
767 NULL);
768
769 /* check that we got back something we can work with */
770 if (rewritten == NIL)
771 {
773 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
774 errmsg("DO INSTEAD NOTHING rules are not supported for COPY")));
775 }
776 else if (list_length(rewritten) > 1)
777 {
778 ListCell *lc;
779
780 /* examine queries to determine which error message to issue */
781 foreach(lc, rewritten)
782 {
783 Query *q = lfirst_node(Query, lc);
784
785 if (q->querySource == QSRC_QUAL_INSTEAD_RULE)
787 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
788 errmsg("conditional DO INSTEAD rules are not supported for COPY")));
789 if (q->querySource == QSRC_NON_INSTEAD_RULE)
791 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
792 errmsg("DO ALSO rules are not supported for COPY")));
793 }
794
796 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
797 errmsg("multi-statement DO INSTEAD rules are not supported for COPY")));
798 }
799
800 query = linitial_node(Query, rewritten);
801
802 /* The grammar allows SELECT INTO, but we don't support that */
803 if (query->utilityStmt != NULL &&
806 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
807 errmsg("COPY (SELECT INTO) is not supported")));
808
809 /* The only other utility command we could see is NOTIFY */
810 if (query->utilityStmt != NULL)
812 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
813 errmsg("COPY query must not be a utility command")));
814
815 /*
816 * Similarly the grammar doesn't enforce the presence of a RETURNING
817 * clause, but this is required here.
818 */
819 if (query->commandType != CMD_SELECT &&
820 query->returningList == NIL)
821 {
822 Assert(query->commandType == CMD_INSERT ||
823 query->commandType == CMD_UPDATE ||
824 query->commandType == CMD_DELETE ||
825 query->commandType == CMD_MERGE);
826
828 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
829 errmsg("COPY query must have a RETURNING clause")));
830 }
831
832 /* plan the query */
833 plan = pg_plan_query(query, pstate->p_sourcetext,
834 CURSOR_OPT_PARALLEL_OK, NULL, NULL);
835
836 /*
837 * With row-level security and a user using "COPY relation TO", we
838 * have to convert the "COPY relation TO" to a query-based COPY (eg:
839 * "COPY (SELECT * FROM ONLY relation) TO"), to allow the rewriter to
840 * add in any RLS clauses.
841 *
842 * When this happens, we are passed in the relid of the originally
843 * found relation (which we have locked). As the planner will look up
844 * the relation again, we double-check here to make sure it found the
845 * same one that we have locked.
846 */
847 if (queryRelId != InvalidOid)
848 {
849 /*
850 * Note that with RLS involved there may be multiple relations,
851 * and while the one we need is almost certainly first, we don't
852 * make any guarantees of that in the planner, so check the whole
853 * list and make sure we find the original relation.
854 */
855 if (!list_member_oid(plan->relationOids, queryRelId))
857 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
858 errmsg("relation referenced by COPY statement has changed")));
859 }
860
861 /*
862 * Use a snapshot with an updated command ID to ensure this query sees
863 * results of any previously executed queries.
864 */
867
868 /* Create dest receiver for COPY OUT */
870 ((DR_copy *) dest)->cstate = cstate;
871
872 /* Create a QueryDesc requesting no output */
873 cstate->queryDesc = CreateQueryDesc(plan, pstate->p_sourcetext,
876 dest, NULL, NULL, 0);
877
878 /*
879 * Call ExecutorStart to prepare the plan for execution.
880 *
881 * ExecutorStart computes a result tupdesc for us
882 */
883 ExecutorStart(cstate->queryDesc, 0);
884
885 tupDesc = cstate->queryDesc->tupDesc;
886 }
887
888 /* Generate or convert list of attributes to process */
889 cstate->attnumlist = CopyGetAttnums(tupDesc, cstate->rel, attnamelist);
890
891 num_phys_attrs = tupDesc->natts;
892
893 /* Convert FORCE_QUOTE name list to per-column flags, check validity */
894 cstate->opts.force_quote_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
895 if (cstate->opts.force_quote_all)
896 {
897 MemSet(cstate->opts.force_quote_flags, true, num_phys_attrs * sizeof(bool));
898 }
899 else if (cstate->opts.force_quote)
900 {
901 List *attnums;
902 ListCell *cur;
903
904 attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_quote);
905
906 foreach(cur, attnums)
907 {
908 int attnum = lfirst_int(cur);
909 Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
910
911 if (!list_member_int(cstate->attnumlist, attnum))
913 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
914 /*- translator: %s is the name of a COPY option, e.g. FORCE_NOT_NULL */
915 errmsg("%s column \"%s\" not referenced by COPY",
916 "FORCE_QUOTE", NameStr(attr->attname))));
917 cstate->opts.force_quote_flags[attnum - 1] = true;
918 }
919 }
920
921 /* Use client encoding when ENCODING option is not specified. */
922 if (cstate->opts.file_encoding < 0)
924 else
925 cstate->file_encoding = cstate->opts.file_encoding;
926
927 /*
928 * Set up encoding conversion info if the file and server encodings differ
929 * (see also pg_server_to_any).
930 */
931 if (cstate->file_encoding == GetDatabaseEncoding() ||
932 cstate->file_encoding == PG_SQL_ASCII)
933 cstate->need_transcoding = false;
934 else
935 cstate->need_transcoding = true;
936
937 /* See Multibyte encoding comment above */
939
940 cstate->copy_dest = COPY_FILE; /* default */
941
942 if (data_dest_cb)
943 {
944 progress_vals[1] = PROGRESS_COPY_TYPE_CALLBACK;
945 cstate->copy_dest = COPY_CALLBACK;
946 cstate->data_dest_cb = data_dest_cb;
947 }
948 else if (pipe)
949 {
950 progress_vals[1] = PROGRESS_COPY_TYPE_PIPE;
951
952 Assert(!is_program); /* the grammar does not allow this */
954 cstate->copy_file = stdout;
955 }
956 else
957 {
958 cstate->filename = pstrdup(filename);
959 cstate->is_program = is_program;
960
961 if (is_program)
962 {
963 progress_vals[1] = PROGRESS_COPY_TYPE_PROGRAM;
964 cstate->copy_file = OpenPipeStream(cstate->filename, PG_BINARY_W);
965 if (cstate->copy_file == NULL)
968 errmsg("could not execute command \"%s\": %m",
969 cstate->filename)));
970 }
971 else
972 {
973 mode_t oumask; /* Pre-existing umask value */
974 struct stat st;
975
976 progress_vals[1] = PROGRESS_COPY_TYPE_FILE;
977
978 /*
979 * Prevent write to relative path ... too easy to shoot oneself in
980 * the foot by overwriting a database file ...
981 */
984 (errcode(ERRCODE_INVALID_NAME),
985 errmsg("relative path not allowed for COPY to file")));
986
987 oumask = umask(S_IWGRP | S_IWOTH);
988 PG_TRY();
989 {
990 cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_W);
991 }
992 PG_FINALLY();
993 {
994 umask(oumask);
995 }
996 PG_END_TRY();
997 if (cstate->copy_file == NULL)
998 {
999 /* copy errno because ereport subfunctions might change it */
1000 int save_errno = errno;
1001
1002 ereport(ERROR,
1004 errmsg("could not open file \"%s\" for writing: %m",
1005 cstate->filename),
1006 (save_errno == ENOENT || save_errno == EACCES) ?
1007 errhint("COPY TO instructs the PostgreSQL server process to write a file. "
1008 "You may want a client-side facility such as psql's \\copy.") : 0));
1009 }
1010
1011 if (fstat(fileno(cstate->copy_file), &st))
1012 ereport(ERROR,
1014 errmsg("could not stat file \"%s\": %m",
1015 cstate->filename)));
1016
1017 if (S_ISDIR(st.st_mode))
1018 ereport(ERROR,
1019 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1020 errmsg("\"%s\" is a directory", cstate->filename)));
1021 }
1022 }
1023
1024 /* initialize progress */
1026 cstate->rel ? RelationGetRelid(cstate->rel) : InvalidOid);
1027 pgstat_progress_update_multi_param(2, progress_cols, progress_vals);
1028
1029 cstate->bytes_processed = 0;
1030
1031 MemoryContextSwitchTo(oldcontext);
1032
1033 return cstate;
1034}
#define PG_BINARY_W
Definition: c.h:1264
static const CopyToRoutine * CopyToGetRoutine(const CopyFormatOptions *opts)
Definition: copyto.c:182
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:113
@ DestCopyOut
Definition: dest.h:95
int errdetail(const char *fmt,...)
Definition: elog.c:1216
#define PG_TRY(...)
Definition: elog.h:372
#define PG_END_TRY(...)
Definition: elog.h:397
#define PG_FINALLY(...)
Definition: elog.h:389
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:122
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:722
#define AccessShareLock
Definition: lockdefs.h:36
char * get_rel_name(Oid relid)
Definition: lsyscache.c:2095
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:2170
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
@ CMD_MERGE
Definition: nodes.h:279
@ CMD_INSERT
Definition: nodes.h:277
@ CMD_DELETE
Definition: nodes.h:278
@ CMD_UPDATE
Definition: nodes.h:276
@ CMD_SELECT
Definition: nodes.h:275
@ QSRC_NON_INSTEAD_RULE
Definition: parsenodes.h:40
@ QSRC_QUAL_INSTEAD_RULE
Definition: parsenodes.h:39
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:3396
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
Definition: pg_inherits.c:255
#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 foreach_delete_current(lst, var_or_cell)
Definition: pg_list.h:391
#define foreach_oid(var, lst)
Definition: pg_list.h:471
#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, ExplainState *es)
Definition: postgres.c:887
List * pg_analyze_and_rewrite_fixedparams(RawStmt *parsetree, const char *query_string, const Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
Definition: postgres.c:670
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
Definition: pquery.c:68
#define PROGRESS_COPY_COMMAND_TO
Definition: progress.h:157
#define RelationIsPopulated(relation)
Definition: rel.h:687
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:744
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:732
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:800
#define InvalidSnapshot
Definition: snapshot.h:119
bool force_quote_all
Definition: copy.h:75
List * force_quote
Definition: copy.h:74
bool * force_quote_flags
Definition: copy.h:76
MemoryContext copycontext
Definition: copyto.c:96
Relation rel
Definition: copyto.c:82
const CopyToRoutine * routine
Definition: copyto.c:70
copy_data_dest_cb data_dest_cb
Definition: copyto.c:87
bool encoding_embeds_ascii
Definition: copyto.c:79
CopyDest copy_dest
Definition: copyto.c:73
bool need_transcoding
Definition: copyto.c:78
bool is_program
Definition: copyto.c:86
FILE * copy_file
Definition: copyto.c:74
int file_encoding
Definition: copyto.c:77
CopyFormatOptions opts
Definition: copyto.c:89
uint64 bytes_processed
Definition: copyto.c:100
char * filename
Definition: copyto.c:85
List * attnumlist
Definition: copyto.c:84
QueryDesc * queryDesc
Definition: copyto.c:83
List * partitions
Definition: copyto.c:91
const char * p_sourcetext
Definition: parse_node.h:195
TupleDesc tupDesc
Definition: execdesc.h:47
List * returningList
Definition: parsenodes.h:214
CmdType commandType
Definition: parsenodes.h:121
Node * utilityStmt
Definition: parsenodes.h:141
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 AccessShareLock, 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, CopyToStateData::encoding_embeds_ascii, ereport, errcode(), errcode_for_file_access(), errdetail(), errhint(), errmsg(), ERROR, ExecutorStart(), CopyToStateData::file_encoding, CopyFormatOptions::file_encoding, CopyToStateData::filename, filename, find_all_inheritors(), CopyFormatOptions::force_quote, CopyFormatOptions::force_quote_all, CopyFormatOptions::force_quote_flags, foreach_delete_current, foreach_oid, fstat, get_rel_name(), get_rel_relkind(), 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(), CopyToStateData::partitions, 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 */
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:666
uint32 CommandId
Definition: c.h:674
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:550
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:1193
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:161
List * ExecInsertIndexTuples(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool update, bool noDupErr, bool *specConflict, List *arbiterIndexes, bool onlySummarizing)
Definition: execIndexing.c:310
void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation, OnConflictAction onConflictAction, List *mergeActions)
Definition: execMain.c:1050
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
Definition: execMain.c:1856
void ExecCloseResultRelations(EState *estate)
Definition: execMain.c:1575
void ExecCloseRangeTableRelations(EState *estate)
Definition: execMain.c:1635
void ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1980
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:1326
void ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos, Bitmapset *unpruned_relids)
Definition: execUtils.c:773
void ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo, Index rti)
Definition: execUtils.c:880
void FreeExecutorState(EState *estate)
Definition: execUtils.c:192
EState * CreateExecutorState(void)
Definition: execUtils.c:88
#define ResetPerTupleExprContext(estate)
Definition: executor.h:665
#define GetPerTupleExprContext(estate)
Definition: executor.h:656
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:661
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:519
void ReleaseBulkInsertStatePin(BulkInsertState bistate)
Definition: heapam.c:2065
BulkInsertState GetBulkInsertState(void)
Definition: heapam.c:2036
void FreeBulkInsertState(BulkInsertState bistate)
Definition: heapam.c:2053
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)
@ ONCONFLICT_NONE
Definition: nodes.h:428
#define castNode(_type_, nodeptr)
Definition: nodes.h:182
bool ThereAreNoReadyPortals(void)
Definition: portalmem.c:1171
#define PROGRESS_COPY_TUPLES_PROCESSED
Definition: progress.h:149
#define PROGRESS_COPY_TUPLES_EXCLUDED
Definition: progress.h:150
#define PROGRESS_COPY_TUPLES_SKIPPED
Definition: progress.h:153
bool ThereAreNoPriorRegisteredSnapshots(void)
Definition: snapmgr.c:1626
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:455
bool freeze
Definition: copy.h:62
CopyLogVerbosityChoice log_verbosity
Definition: copy.h:85
int64 reject_limit
Definition: copy.h:86
StringInfoData line_buf
TransitionCaptureState * transition_capture
List * es_tupleTable
Definition: execnodes.h:712
struct ErrorContextCallback * previous
Definition: elog.h:297
void(* callback)(void *arg)
Definition: elog.h:298
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:273
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:1404
ResultRelInfo * resultRelInfo
Definition: execnodes.h:1408
PlanState ps
Definition: execnodes.h:1403
ResultRelInfo * rootResultRelInfo
Definition: execnodes.h:1416
struct TransitionCaptureState * mt_transition_capture
Definition: execnodes.h:1442
Plan * plan
Definition: execnodes.h:1165
EState * state
Definition: execnodes.h:1167
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:619
int ri_NumIndices
Definition: execnodes.h:483
Relation ri_RelationDesc
Definition: execnodes.h:480
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition: execnodes.h:622
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:515
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:533
int ri_BatchSize
Definition: execnodes.h:544
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:129
bool * tts_isnull
Definition: tuptable.h:126
Datum * tts_values
Definition: tuptable.h:124
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition: tableam.c:92
#define TABLE_INSERT_FROZEN
Definition: tableam.h:260
#define TABLE_INSERT_SKIP_FSM
Definition: tableam.h:259
static void table_tuple_insert(Relation rel, TupleTableSlot *slot, CommandId cid, int options, BulkInsertStateData *bistate)
Definition: tableam.h:1377
TransitionCaptureState * MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType)
Definition: trigger.c:4968
void ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2401
bool ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2465
bool ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2569
void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot, List *recheckIndexes, TransitionCaptureState *transition_capture)
Definition: trigger.c:2543
void ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo, TransitionCaptureState *transition_capture)
Definition: trigger.c:2452
void AfterTriggerEndQuery(EState *estate)
Definition: trigger.c:5124
void AfterTriggerBeginQuery(void)
Definition: trigger.c:5104
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition: tupconvert.c:193
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:457
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: tuptable.h:524
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition: tuptable.h:475
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:792
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:830

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, ONCONFLICT_NONE, 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:198
struct CopyFromStateData * CopyFromState
Definition: copy.h:91
void pfree(void *pointer)
Definition: mcxt.c:1594
void * arg
bool binary
Definition: copy.h:61

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 998 of file copy.c.

999{
1000 List *attnums = NIL;
1001
1002 if (attnamelist == NIL)
1003 {
1004 /* Generate default column list */
1005 int attr_count = tupDesc->natts;
1006 int i;
1007
1008 for (i = 0; i < attr_count; i++)
1009 {
1010 CompactAttribute *attr = TupleDescCompactAttr(tupDesc, i);
1011
1012 if (attr->attisdropped || attr->attgenerated)
1013 continue;
1014 attnums = lappend_int(attnums, i + 1);
1015 }
1016 }
1017 else
1018 {
1019 /* Validate the user-supplied list and extract attnums */
1020 ListCell *l;
1021
1022 foreach(l, attnamelist)
1023 {
1024 char *name = strVal(lfirst(l));
1025 int attnum;
1026 int i;
1027
1028 /* Lookup column name */
1030 for (i = 0; i < tupDesc->natts; i++)
1031 {
1032 Form_pg_attribute att = TupleDescAttr(tupDesc, i);
1033
1034 if (att->attisdropped)
1035 continue;
1036 if (namestrcmp(&(att->attname), name) == 0)
1037 {
1038 if (att->attgenerated)
1039 ereport(ERROR,
1040 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1041 errmsg("column \"%s\" is a generated column",
1042 name),
1043 errdetail("Generated columns cannot be used in COPY.")));
1044 attnum = att->attnum;
1045 break;
1046 }
1047 }
1049 {
1050 if (rel != NULL)
1051 ereport(ERROR,
1052 (errcode(ERRCODE_UNDEFINED_COLUMN),
1053 errmsg("column \"%s\" of relation \"%s\" does not exist",
1055 else
1056 ereport(ERROR,
1057 (errcode(ERRCODE_UNDEFINED_COLUMN),
1058 errmsg("column \"%s\" does not exist",
1059 name)));
1060 }
1061 /* Check for duplicates */
1062 if (list_member_int(attnums, attnum))
1063 ereport(ERROR,
1064 (errcode(ERRCODE_DUPLICATE_COLUMN),
1065 errmsg("column \"%s\" specified more than once",
1066 name)));
1067 attnums = lappend_int(attnums, attnum);
1068 }
1069 }
1070
1071 return attnums;
1072}
#define InvalidAttrNumber
Definition: attnum.h:23
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:1084
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 1528 of file copyto.c.

1529{
1530 DR_copy *self = (DR_copy *) palloc(sizeof(DR_copy));
1531
1536 self->pub.mydest = DestCopyOut;
1537
1538 self->cstate = NULL; /* will be set later */
1539 self->processed = 0;
1540
1541 return (DestReceiver *) self;
1542}
static bool copy_dest_receive(TupleTableSlot *slot, DestReceiver *self)
Definition: copyto.c:1491
static void copy_dest_destroy(DestReceiver *self)
Definition: copyto.c:1519
static void copy_dest_shutdown(DestReceiver *self)
Definition: copyto.c:1510
static void copy_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: copyto.c:1482
CopyToState cstate
Definition: copyto.c:107
DestReceiver pub
Definition: copyto.c:106
uint64 processed
Definition: copyto.c:108
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 Bitmapset *expr_attrs = NULL;
137 int i;
138
139 /* add nsitem to query namespace */
140 addNSItemToQuery(pstate, nsitem, false, true, true);
141
142 /* Transform the raw expression tree */
143 whereClause = transformExpr(pstate, stmt->whereClause, EXPR_KIND_COPY_WHERE);
144
145 /* Make sure it yields a boolean result. */
146 whereClause = coerce_to_boolean(pstate, whereClause, "WHERE");
147
148 /* we have to fix its collations too */
149 assign_expr_collations(pstate, whereClause);
150
151 /*
152 * Examine all the columns in the WHERE clause expression. When
153 * the whole-row reference is present, examine all the columns of
154 * the table.
155 */
156 pull_varattnos(whereClause, 1, &expr_attrs);
158 {
159 expr_attrs = bms_add_range(expr_attrs,
162 expr_attrs = bms_del_member(expr_attrs, 0 - FirstLowInvalidHeapAttributeNumber);
163 }
164
165 i = -1;
166 while ((i = bms_next_member(expr_attrs, i)) >= 0)
167 {
169
170 Assert(attno != 0);
171
172 /*
173 * Prohibit generated columns in the WHERE clause. Stored
174 * generated columns are not yet computed when the filtering
175 * happens. Virtual generated columns could probably work (we
176 * would need to expand them somewhere around here), but for
177 * now we keep them consistent with the stored variant.
178 */
179 if (TupleDescAttr(RelationGetDescr(rel), attno - 1)->attgenerated)
181 errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
182 errmsg("generated columns are not supported in COPY FROM WHERE conditions"),
183 errdetail("Column \"%s\" is a generated column.",
184 get_attname(RelationGetRelid(rel), attno, false)));
185 }
186
187 whereClause = eval_const_expressions(NULL, whereClause);
188
189 whereClause = (Node *) canonicalize_qual((Expr *) whereClause, false);
190 whereClause = (Node *) make_ands_implicit((Expr *) whereClause);
191 }
192
193 tupDesc = RelationGetDescr(rel);
194 attnums = CopyGetAttnums(tupDesc, rel, stmt->attlist);
195 foreach(cur, attnums)
196 {
197 int attno;
198 Bitmapset **bms;
199
201 bms = is_from ? &perminfo->insertedCols : &perminfo->selectedCols;
202
203 *bms = bms_add_member(*bms, attno);
204 }
205 ExecCheckPermissions(pstate->p_rtable, list_make1(perminfo), true);
206
207 /*
208 * Permission check for row security policies.
209 *
210 * check_enable_rls will ereport(ERROR) if the user has requested
211 * something invalid and will otherwise indicate if we should enable
212 * RLS (returns RLS_ENABLED) or not for this COPY statement.
213 *
214 * If the relation has a row security policy and we are to apply it
215 * then perform a "query" copy and allow the normal query processing
216 * to handle the policies.
217 *
218 * If RLS is not enabled for this, then just fall through to the
219 * normal non-filtering relation handling.
220 */
221 if (check_enable_rls(relid, InvalidOid, false) == RLS_ENABLED)
222 {
224 ColumnRef *cr;
225 ResTarget *target;
226 RangeVar *from;
227 List *targetList = NIL;
228
229 if (is_from)
231 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
232 errmsg("COPY FROM not supported with row-level security"),
233 errhint("Use INSERT statements instead.")));
234
235 /*
236 * Build target list
237 *
238 * If no columns are specified in the attribute list of the COPY
239 * command, then the target list is 'all' columns. Therefore, '*'
240 * should be used as the target list for the resulting SELECT
241 * statement.
242 *
243 * In the case that columns are specified in the attribute list,
244 * create a ColumnRef and ResTarget for each column and add them
245 * to the target list for the resulting SELECT statement.
246 */
247 if (!stmt->attlist)
248 {
249 cr = makeNode(ColumnRef);
251 cr->location = -1;
252
253 target = makeNode(ResTarget);
254 target->name = NULL;
255 target->indirection = NIL;
256 target->val = (Node *) cr;
257 target->location = -1;
258
259 targetList = list_make1(target);
260 }
261 else
262 {
263 ListCell *lc;
264
265 foreach(lc, stmt->attlist)
266 {
267 /*
268 * Build the ColumnRef for each column. The ColumnRef
269 * 'fields' property is a String node that corresponds to
270 * the column name respectively.
271 */
272 cr = makeNode(ColumnRef);
273 cr->fields = list_make1(lfirst(lc));
274 cr->location = -1;
275
276 /* Build the ResTarget and add the ColumnRef to it. */
277 target = makeNode(ResTarget);
278 target->name = NULL;
279 target->indirection = NIL;
280 target->val = (Node *) cr;
281 target->location = -1;
282
283 /* Add each column to the SELECT statement's target list */
284 targetList = lappend(targetList, target);
285 }
286 }
287
288 /*
289 * Build RangeVar for from clause, fully qualified based on the
290 * relation which we have opened and locked. Use "ONLY" so that
291 * COPY retrieves rows from only the target table not any
292 * inheritance children, the same as when RLS doesn't apply.
293 *
294 * However, when copying data from a partitioned table, we don't
295 * use "ONLY", since we need to retrieve rows from its descendant
296 * tables too.
297 */
300 -1);
301 from->inh = (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
302
303 /* Build query */
305 select->targetList = targetList;
306 select->fromClause = list_make1(from);
307
308 query = makeNode(RawStmt);
309 query->stmt = (Node *) select;
310 query->stmt_location = stmt_location;
311 query->stmt_len = stmt_len;
312
313 /*
314 * Close the relation for now, but keep the lock on it to prevent
315 * changes between now and when we start the query-based COPY.
316 *
317 * We'll reopen it later as part of the query-based COPY.
318 */
319 table_close(rel, NoLock);
320 rel = NULL;
321 }
322 }
323 else
324 {
325 Assert(stmt->query);
326
327 query = makeNode(RawStmt);
328 query->stmt = stmt->query;
329 query->stmt_location = stmt_location;
330 query->stmt_len = stmt_len;
331
332 relid = InvalidOid;
333 rel = NULL;
334 }
335
336 if (is_from)
337 {
338 CopyFromState cstate;
339
340 Assert(rel);
341
342 /* check read-only transaction and parallel mode */
343 if (XactReadOnly && !rel->rd_islocaltemp)
344 PreventCommandIfReadOnly("COPY FROM");
345
346 cstate = BeginCopyFrom(pstate, rel, whereClause,
347 stmt->filename, stmt->is_program,
348 NULL, stmt->attlist, stmt->options);
349 *processed = CopyFrom(cstate); /* copy from file to database */
350 EndCopyFrom(cstate);
351 }
352 else
353 {
354 CopyToState cstate;
355
356 cstate = BeginCopyTo(pstate, rel, query, relid,
357 stmt->filename, stmt->is_program,
358 NULL, stmt->attlist, stmt->options);
359 *processed = DoCopyTo(cstate); /* copy from database to file */
360 EndCopyTo(cstate);
361 }
362
363 if (rel != NULL)
364 table_close(rel, NoLock);
365}
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:5284
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1305
Bitmapset * bms_add_range(Bitmapset *a, int lower, int upper)
Definition: bitmapset.c:1018
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition: bitmapset.c:867
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:814
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2270
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:1061
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:632
void EndCopyTo(CopyToState cstate)
Definition: copyto.c:1040
bool ExecCheckPermissions(List *rangeTable, List *rteperminfos, bool ereport_on_violation)
Definition: execMain.c:582
#define stmt
Definition: indent_codes.h:59
List * lappend(List *list, void *datum)
Definition: list.c:339
int LOCKMODE
Definition: lockdefs.h:26
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:920
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3533
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:469
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:119
@ 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 RelationGetNumberOfAttributes(relation)
Definition: rel.h:521
#define RelationGetNamespace(relation)
Definition: rel.h:556
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:312
List * fields
Definition: parsenodes.h:311
RTEPermissionInfo * p_perminfo
Definition: parse_node.h:297
Bitmapset * selectedCols
Definition: parsenodes.h:1324
AclMode requiredPerms
Definition: parsenodes.h:1322
Bitmapset * insertedCols
Definition: parsenodes.h:1325
bool inh
Definition: primnodes.h:86
ParseLoc stmt_location
Definition: parsenodes.h:2089
ParseLoc stmt_len
Definition: parsenodes.h:2090
Node * stmt
Definition: parsenodes.h:2088
bool rd_islocaltemp
Definition: rel.h:61
Node * val
Definition: parsenodes.h:547
ParseLoc location
Definition: parsenodes.h:548
List * indirection
Definition: parsenodes.h:546
char * name
Definition: parsenodes.h:545
#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:406
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:296
#define select(n, r, w, e, timeout)
Definition: win32_port.h:503
bool XactReadOnly
Definition: xact.c:83

References AccessShareLock, ACL_INSERT, ACL_SELECT, addNSItemToQuery(), addRangeTableEntryForRelation(), Assert(), assign_expr_collations(), BeginCopyFrom(), BeginCopyTo(), bms_add_member(), bms_add_range(), bms_del_member(), bms_is_member(), bms_next_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_attname(), get_namespace_name(), GetUserId(), has_privs_of_role(), i, 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(), pull_varattnos(), RelationData::rd_islocaltemp, RelationData::rd_rel, RelationGetDescr, RelationGetNamespace, RelationGetNumberOfAttributes, RelationGetRelationName, RelationGetRelid, RTEPermissionInfo::requiredPerms, RLS_ENABLED, RowExclusiveLock, select, RTEPermissionInfo::selectedCols, RawStmt::stmt, stmt, RawStmt::stmt_len, RawStmt::stmt_location, table_close(), table_openrv(), transformExpr(), TupleDescAttr(), ResTarget::val, and XactReadOnly.

Referenced by standard_ProcessUtility().

◆ DoCopyTo()

uint64 DoCopyTo ( CopyToState  cstate)

Definition at line 1061 of file copyto.c.

1062{
1063 bool pipe = (cstate->filename == NULL && cstate->data_dest_cb == NULL);
1064 bool fe_copy = (pipe && whereToSendOutput == DestRemote);
1065 TupleDesc tupDesc;
1066 int num_phys_attrs;
1067 ListCell *cur;
1068 uint64 processed = 0;
1069
1070 if (fe_copy)
1071 SendCopyBegin(cstate);
1072
1073 if (cstate->rel)
1074 tupDesc = RelationGetDescr(cstate->rel);
1075 else
1076 tupDesc = cstate->queryDesc->tupDesc;
1077 num_phys_attrs = tupDesc->natts;
1078 cstate->opts.null_print_client = cstate->opts.null_print; /* default */
1079
1080 /* We use fe_msgbuf as a per-row buffer regardless of copy_dest */
1081 cstate->fe_msgbuf = makeStringInfo();
1082
1083 /* Get info about the columns we need to process. */
1084 cstate->out_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
1085 foreach(cur, cstate->attnumlist)
1086 {
1087 int attnum = lfirst_int(cur);
1088 Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1089
1090 cstate->routine->CopyToOutFunc(cstate, attr->atttypid,
1091 &cstate->out_functions[attnum - 1]);
1092 }
1093
1094 /*
1095 * Create a temporary memory context that we can reset once per row to
1096 * recover palloc'd memory. This avoids any problems with leaks inside
1097 * datatype output routines, and should be faster than retail pfree's
1098 * anyway. (We don't need a whole econtext as CopyFrom does.)
1099 */
1101 "COPY TO",
1103
1104 cstate->routine->CopyToStart(cstate, tupDesc);
1105
1106 if (cstate->rel)
1107 {
1108 /*
1109 * If COPY TO source table is a partitioned table, then open each
1110 * partition and process each individual partition.
1111 */
1112 if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1113 {
1114 foreach_oid(child, cstate->partitions)
1115 {
1116 Relation scan_rel;
1117
1118 /* We already got the lock in BeginCopyTo */
1119 scan_rel = table_open(child, NoLock);
1120 CopyRelationTo(cstate, scan_rel, cstate->rel, &processed);
1121 table_close(scan_rel, NoLock);
1122 }
1123 }
1124 else
1125 CopyRelationTo(cstate, cstate->rel, NULL, &processed);
1126 }
1127 else
1128 {
1129 /* run the plan --- the dest receiver will send tuples */
1131 processed = ((DR_copy *) cstate->queryDesc->dest)->processed;
1132 }
1133
1134 cstate->routine->CopyToEnd(cstate);
1135
1137
1138 if (fe_copy)
1139 SendCopyEnd(cstate);
1140
1141 return processed;
1142}
uint64_t uint64
Definition: c.h:542
static void CopyRelationTo(CopyToState cstate, Relation rel, Relation root_rel, uint64 *processed)
Definition: copyto.c:1152
static void SendCopyBegin(CopyToState cstate)
Definition: copyto.c:396
static void SendCopyEnd(CopyToState cstate)
Definition: copyto.c:413
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition: execMain.c:297
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:469
@ ForwardScanDirection
Definition: sdir.h:28
StringInfo makeStringInfo(void)
Definition: stringinfo.c:72
char * null_print
Definition: copy.h:66
char * null_print_client
Definition: copy.h:68
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:98
MemoryContext rowcontext
Definition: copyto.c:99
StringInfo fe_msgbuf
Definition: copyto.c:75
DestReceiver * dest
Definition: execdesc.h:41
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, attnum, CopyToStateData::attnumlist, CopyRelationTo(), CopyToRoutine::CopyToEnd, CopyToRoutine::CopyToOutFunc, CopyToRoutine::CopyToStart, cur, CurrentMemoryContext, CopyToStateData::data_dest_cb, QueryDesc::dest, DestRemote, ExecutorRun(), CopyToStateData::fe_msgbuf, CopyToStateData::filename, foreach_oid, ForwardScanDirection, lfirst_int, makeStringInfo(), MemoryContextDelete(), TupleDescData::natts, NoLock, CopyFormatOptions::null_print, CopyFormatOptions::null_print_client, CopyToStateData::opts, CopyToStateData::out_functions, palloc(), CopyToStateData::partitions, CopyToStateData::queryDesc, RelationData::rd_rel, CopyToStateData::rel, RelationGetDescr, CopyToStateData::routine, CopyToStateData::rowcontext, SendCopyBegin(), SendCopyEnd(), table_close(), table_open(), 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:2840
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 1040 of file copyto.c.

1041{
1042 if (cstate->queryDesc != NULL)
1043 {
1044 /* Close down the query and free resources. */
1045 ExecutorFinish(cstate->queryDesc);
1046 ExecutorEnd(cstate->queryDesc);
1047 FreeQueryDesc(cstate->queryDesc);
1049 }
1050
1051 /* Clean up storage */
1052 EndCopy(cstate);
1053}
static void EndCopy(CopyToState cstate)
Definition: copyto.c:592
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:466
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:406
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:106
void PopActiveSnapshot(void)
Definition: snapmgr.c:775

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

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

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:63

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

◆ ProcessCopyOptions()

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

Definition at line 549 of file copy.c.

553{
554 bool format_specified = false;
555 bool freeze_specified = false;
556 bool header_specified = false;
557 bool on_error_specified = false;
558 bool log_verbosity_specified = false;
559 bool reject_limit_specified = false;
561
562 /* Support external use for option sanity checking */
563 if (opts_out == NULL)
564 opts_out = (CopyFormatOptions *) palloc0(sizeof(CopyFormatOptions));
565
566 opts_out->file_encoding = -1;
567
568 /* Extract options from the statement node tree */
569 foreach(option, options)
570 {
572
573 if (strcmp(defel->defname, "format") == 0)
574 {
575 char *fmt = defGetString(defel);
576
577 if (format_specified)
578 errorConflictingDefElem(defel, pstate);
579 format_specified = true;
580 if (strcmp(fmt, "text") == 0)
581 /* default format */ ;
582 else if (strcmp(fmt, "csv") == 0)
583 opts_out->csv_mode = true;
584 else if (strcmp(fmt, "binary") == 0)
585 opts_out->binary = true;
586 else
588 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
589 errmsg("COPY format \"%s\" not recognized", fmt),
590 parser_errposition(pstate, defel->location)));
591 }
592 else if (strcmp(defel->defname, "freeze") == 0)
593 {
594 if (freeze_specified)
595 errorConflictingDefElem(defel, pstate);
596 freeze_specified = true;
597 opts_out->freeze = defGetBoolean(defel);
598 }
599 else if (strcmp(defel->defname, "delimiter") == 0)
600 {
601 if (opts_out->delim)
602 errorConflictingDefElem(defel, pstate);
603 opts_out->delim = defGetString(defel);
604 }
605 else if (strcmp(defel->defname, "null") == 0)
606 {
607 if (opts_out->null_print)
608 errorConflictingDefElem(defel, pstate);
609 opts_out->null_print = defGetString(defel);
610 }
611 else if (strcmp(defel->defname, "default") == 0)
612 {
613 if (opts_out->default_print)
614 errorConflictingDefElem(defel, pstate);
615 opts_out->default_print = defGetString(defel);
616 }
617 else if (strcmp(defel->defname, "header") == 0)
618 {
619 if (header_specified)
620 errorConflictingDefElem(defel, pstate);
621 header_specified = true;
622 opts_out->header_line = defGetCopyHeaderOption(defel, is_from);
623 }
624 else if (strcmp(defel->defname, "quote") == 0)
625 {
626 if (opts_out->quote)
627 errorConflictingDefElem(defel, pstate);
628 opts_out->quote = defGetString(defel);
629 }
630 else if (strcmp(defel->defname, "escape") == 0)
631 {
632 if (opts_out->escape)
633 errorConflictingDefElem(defel, pstate);
634 opts_out->escape = defGetString(defel);
635 }
636 else if (strcmp(defel->defname, "force_quote") == 0)
637 {
638 if (opts_out->force_quote || opts_out->force_quote_all)
639 errorConflictingDefElem(defel, pstate);
640 if (defel->arg && IsA(defel->arg, A_Star))
641 opts_out->force_quote_all = true;
642 else if (defel->arg && IsA(defel->arg, List))
643 opts_out->force_quote = castNode(List, defel->arg);
644 else
646 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
647 errmsg("argument to option \"%s\" must be a list of column names",
648 defel->defname),
649 parser_errposition(pstate, defel->location)));
650 }
651 else if (strcmp(defel->defname, "force_not_null") == 0)
652 {
653 if (opts_out->force_notnull || opts_out->force_notnull_all)
654 errorConflictingDefElem(defel, pstate);
655 if (defel->arg && IsA(defel->arg, A_Star))
656 opts_out->force_notnull_all = true;
657 else if (defel->arg && IsA(defel->arg, List))
658 opts_out->force_notnull = castNode(List, defel->arg);
659 else
661 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
662 errmsg("argument to option \"%s\" must be a list of column names",
663 defel->defname),
664 parser_errposition(pstate, defel->location)));
665 }
666 else if (strcmp(defel->defname, "force_null") == 0)
667 {
668 if (opts_out->force_null || opts_out->force_null_all)
669 errorConflictingDefElem(defel, pstate);
670 if (defel->arg && IsA(defel->arg, A_Star))
671 opts_out->force_null_all = true;
672 else if (defel->arg && IsA(defel->arg, List))
673 opts_out->force_null = castNode(List, defel->arg);
674 else
676 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
677 errmsg("argument to option \"%s\" must be a list of column names",
678 defel->defname),
679 parser_errposition(pstate, defel->location)));
680 }
681 else if (strcmp(defel->defname, "convert_selectively") == 0)
682 {
683 /*
684 * Undocumented, not-accessible-from-SQL option: convert only the
685 * named columns to binary form, storing the rest as NULLs. It's
686 * allowed for the column list to be NIL.
687 */
688 if (opts_out->convert_selectively)
689 errorConflictingDefElem(defel, pstate);
690 opts_out->convert_selectively = true;
691 if (defel->arg == NULL || IsA(defel->arg, List))
692 opts_out->convert_select = castNode(List, defel->arg);
693 else
695 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
696 errmsg("argument to option \"%s\" must be a list of column names",
697 defel->defname),
698 parser_errposition(pstate, defel->location)));
699 }
700 else if (strcmp(defel->defname, "encoding") == 0)
701 {
702 if (opts_out->file_encoding >= 0)
703 errorConflictingDefElem(defel, pstate);
705 if (opts_out->file_encoding < 0)
707 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
708 errmsg("argument to option \"%s\" must be a valid encoding name",
709 defel->defname),
710 parser_errposition(pstate, defel->location)));
711 }
712 else if (strcmp(defel->defname, "on_error") == 0)
713 {
714 if (on_error_specified)
715 errorConflictingDefElem(defel, pstate);
716 on_error_specified = true;
717 opts_out->on_error = defGetCopyOnErrorChoice(defel, pstate, is_from);
718 }
719 else if (strcmp(defel->defname, "log_verbosity") == 0)
720 {
721 if (log_verbosity_specified)
722 errorConflictingDefElem(defel, pstate);
723 log_verbosity_specified = true;
724 opts_out->log_verbosity = defGetCopyLogVerbosityChoice(defel, pstate);
725 }
726 else if (strcmp(defel->defname, "reject_limit") == 0)
727 {
728 if (reject_limit_specified)
729 errorConflictingDefElem(defel, pstate);
730 reject_limit_specified = true;
731 opts_out->reject_limit = defGetCopyRejectLimitOption(defel);
732 }
733 else
735 (errcode(ERRCODE_SYNTAX_ERROR),
736 errmsg("option \"%s\" not recognized",
737 defel->defname),
738 parser_errposition(pstate, defel->location)));
739 }
740
741 /*
742 * Check for incompatible options (must do these three before inserting
743 * defaults)
744 */
745 if (opts_out->binary && opts_out->delim)
747 (errcode(ERRCODE_SYNTAX_ERROR),
748 /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
749 errmsg("cannot specify %s in BINARY mode", "DELIMITER")));
750
751 if (opts_out->binary && opts_out->null_print)
753 (errcode(ERRCODE_SYNTAX_ERROR),
754 errmsg("cannot specify %s in BINARY mode", "NULL")));
755
756 if (opts_out->binary && opts_out->default_print)
758 (errcode(ERRCODE_SYNTAX_ERROR),
759 errmsg("cannot specify %s in BINARY mode", "DEFAULT")));
760
761 /* Set defaults for omitted options */
762 if (!opts_out->delim)
763 opts_out->delim = opts_out->csv_mode ? "," : "\t";
764
765 if (!opts_out->null_print)
766 opts_out->null_print = opts_out->csv_mode ? "" : "\\N";
767 opts_out->null_print_len = strlen(opts_out->null_print);
768
769 if (opts_out->csv_mode)
770 {
771 if (!opts_out->quote)
772 opts_out->quote = "\"";
773 if (!opts_out->escape)
774 opts_out->escape = opts_out->quote;
775 }
776
777 /* Only single-byte delimiter strings are supported. */
778 if (strlen(opts_out->delim) != 1)
780 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
781 errmsg("COPY delimiter must be a single one-byte character")));
782
783 /* Disallow end-of-line characters */
784 if (strchr(opts_out->delim, '\r') != NULL ||
785 strchr(opts_out->delim, '\n') != NULL)
787 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
788 errmsg("COPY delimiter cannot be newline or carriage return")));
789
790 if (strchr(opts_out->null_print, '\r') != NULL ||
791 strchr(opts_out->null_print, '\n') != NULL)
793 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
794 errmsg("COPY null representation cannot use newline or carriage return")));
795
796 if (opts_out->default_print)
797 {
798 opts_out->default_print_len = strlen(opts_out->default_print);
799
800 if (strchr(opts_out->default_print, '\r') != NULL ||
801 strchr(opts_out->default_print, '\n') != NULL)
803 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
804 errmsg("COPY default representation cannot use newline or carriage return")));
805 }
806
807 /*
808 * Disallow unsafe delimiter characters in non-CSV mode. We can't allow
809 * backslash because it would be ambiguous. We can't allow the other
810 * cases because data characters matching the delimiter must be
811 * backslashed, and certain backslash combinations are interpreted
812 * non-literally by COPY IN. Disallowing all lower case ASCII letters is
813 * more than strictly necessary, but seems best for consistency and
814 * future-proofing. Likewise we disallow all digits though only octal
815 * digits are actually dangerous.
816 */
817 if (!opts_out->csv_mode &&
818 strchr("\\.abcdefghijklmnopqrstuvwxyz0123456789",
819 opts_out->delim[0]) != NULL)
821 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
822 errmsg("COPY delimiter cannot be \"%s\"", opts_out->delim)));
823
824 /* Check header */
825 if (opts_out->binary && opts_out->header_line != COPY_HEADER_FALSE)
827 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
828 /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
829 errmsg("cannot specify %s in BINARY mode", "HEADER")));
830
831 /* Check quote */
832 if (!opts_out->csv_mode && opts_out->quote != NULL)
834 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
835 /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
836 errmsg("COPY %s requires CSV mode", "QUOTE")));
837
838 if (opts_out->csv_mode && strlen(opts_out->quote) != 1)
840 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
841 errmsg("COPY quote must be a single one-byte character")));
842
843 if (opts_out->csv_mode && opts_out->delim[0] == opts_out->quote[0])
845 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
846 errmsg("COPY delimiter and quote must be different")));
847
848 /* Check escape */
849 if (!opts_out->csv_mode && opts_out->escape != NULL)
851 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
852 /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
853 errmsg("COPY %s requires CSV mode", "ESCAPE")));
854
855 if (opts_out->csv_mode && strlen(opts_out->escape) != 1)
857 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
858 errmsg("COPY escape must be a single one-byte character")));
859
860 /* Check force_quote */
861 if (!opts_out->csv_mode && (opts_out->force_quote || opts_out->force_quote_all))
863 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
864 /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
865 errmsg("COPY %s requires CSV mode", "FORCE_QUOTE")));
866 if ((opts_out->force_quote || opts_out->force_quote_all) && is_from)
868 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
869 /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
870 second %s is a COPY with direction, e.g. COPY TO */
871 errmsg("COPY %s cannot be used with %s", "FORCE_QUOTE",
872 "COPY FROM")));
873
874 /* Check force_notnull */
875 if (!opts_out->csv_mode && (opts_out->force_notnull != NIL ||
876 opts_out->force_notnull_all))
878 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
879 /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
880 errmsg("COPY %s requires CSV mode", "FORCE_NOT_NULL")));
881 if ((opts_out->force_notnull != NIL || opts_out->force_notnull_all) &&
882 !is_from)
884 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
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", "FORCE_NOT_NULL",
888 "COPY TO")));
889
890 /* Check force_null */
891 if (!opts_out->csv_mode && (opts_out->force_null != NIL ||
892 opts_out->force_null_all))
894 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
895 /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
896 errmsg("COPY %s requires CSV mode", "FORCE_NULL")));
897
898 if ((opts_out->force_null != NIL || opts_out->force_null_all) &&
899 !is_from)
901 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
902 /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
903 second %s is a COPY with direction, e.g. COPY TO */
904 errmsg("COPY %s cannot be used with %s", "FORCE_NULL",
905 "COPY TO")));
906
907 /* Don't allow the delimiter to appear in the null string. */
908 if (strchr(opts_out->null_print, opts_out->delim[0]) != NULL)
910 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
911 /*- translator: %s is the name of a COPY option, e.g. NULL */
912 errmsg("COPY delimiter character must not appear in the %s specification",
913 "NULL")));
914
915 /* Don't allow the CSV quote char to appear in the null string. */
916 if (opts_out->csv_mode &&
917 strchr(opts_out->null_print, opts_out->quote[0]) != NULL)
919 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
920 /*- translator: %s is the name of a COPY option, e.g. NULL */
921 errmsg("CSV quote character must not appear in the %s specification",
922 "NULL")));
923
924 /* Check freeze */
925 if (opts_out->freeze && !is_from)
927 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
928 /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
929 second %s is a COPY with direction, e.g. COPY TO */
930 errmsg("COPY %s cannot be used with %s", "FREEZE",
931 "COPY TO")));
932
933 if (opts_out->default_print)
934 {
935 if (!is_from)
937 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
938 /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
939 second %s is a COPY with direction, e.g. COPY TO */
940 errmsg("COPY %s cannot be used with %s", "DEFAULT",
941 "COPY TO")));
942
943 /* Don't allow the delimiter to appear in the default string. */
944 if (strchr(opts_out->default_print, opts_out->delim[0]) != NULL)
946 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
947 /*- translator: %s is the name of a COPY option, e.g. NULL */
948 errmsg("COPY delimiter character must not appear in the %s specification",
949 "DEFAULT")));
950
951 /* Don't allow the CSV quote char to appear in the default string. */
952 if (opts_out->csv_mode &&
953 strchr(opts_out->default_print, opts_out->quote[0]) != NULL)
955 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
956 /*- translator: %s is the name of a COPY option, e.g. NULL */
957 errmsg("CSV quote character must not appear in the %s specification",
958 "DEFAULT")));
959
960 /* Don't allow the NULL and DEFAULT string to be the same */
961 if (opts_out->null_print_len == opts_out->default_print_len &&
962 strncmp(opts_out->null_print, opts_out->default_print,
963 opts_out->null_print_len) == 0)
965 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
966 errmsg("NULL specification and DEFAULT specification cannot be the same")));
967 }
968 /* Check on_error */
969 if (opts_out->binary && opts_out->on_error != COPY_ON_ERROR_STOP)
971 (errcode(ERRCODE_SYNTAX_ERROR),
972 errmsg("only ON_ERROR STOP is allowed in BINARY mode")));
973
974 if (opts_out->reject_limit && !opts_out->on_error)
976 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
977 /*- translator: first and second %s are the names of COPY option, e.g.
978 * ON_ERROR, third is the value of the COPY option, e.g. IGNORE */
979 errmsg("COPY %s requires %s to be set to %s",
980 "REJECT_LIMIT", "ON_ERROR", "IGNORE")));
981}
static int defGetCopyHeaderOption(DefElem *def, bool is_from)
Definition: copy.c:374
static int64 defGetCopyRejectLimitOption(DefElem *def)
Definition: copy.c:482
static CopyOnErrorChoice defGetCopyOnErrorChoice(DefElem *def, ParseState *pstate, bool is_from)
Definition: copy.c:446
static CopyLogVerbosityChoice defGetCopyLogVerbosityChoice(DefElem *def, ParseState *pstate)
Definition: copy.c:509
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
#define COPY_HEADER_FALSE
Definition: copy.h:27
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
#define pg_char_to_encoding
Definition: pg_wchar.h:629
int header_line
Definition: copy.h:64
int default_print_len
Definition: copy.h:70
int null_print_len
Definition: copy.h:67
char * quote
Definition: copy.h:72
char * escape
Definition: copy.h:73
char * delim
Definition: copy.h:71
char * defname
Definition: parsenodes.h:843
ParseLoc location
Definition: parsenodes.h:847
Node * arg
Definition: parsenodes.h:844

References DefElem::arg, CopyFormatOptions::binary, castNode, CopyFormatOptions::convert_select, CopyFormatOptions::convert_selectively, COPY_HEADER_FALSE, COPY_ON_ERROR_STOP, CopyFormatOptions::csv_mode, CopyFormatOptions::default_print, CopyFormatOptions::default_print_len, defGetBoolean(), defGetCopyHeaderOption(), 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().