PostgreSQL Source Code git master
Loading...
Searching...
No Matches
copyfrom.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <unistd.h>
#include <sys/stat.h>
#include "access/heapam.h"
#include "access/tableam.h"
#include "access/xact.h"
#include "catalog/namespace.h"
#include "commands/copyapi.h"
#include "commands/copyfrom_internal.h"
#include "commands/progress.h"
#include "commands/trigger.h"
#include "executor/execPartition.h"
#include "executor/executor.h"
#include "executor/nodeModifyTable.h"
#include "executor/tuptable.h"
#include "foreign/fdwapi.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "nodes/miscnodes.h"
#include "optimizer/optimizer.h"
#include "pgstat.h"
#include "rewrite/rewriteHandler.h"
#include "storage/fd.h"
#include "tcop/tcopprot.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/portal.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/typcache.h"
Include dependency graph for copyfrom.c:

Go to the source code of this file.

Data Structures

struct  CopyMultiInsertBuffer
 
struct  CopyMultiInsertInfo
 

Macros

#define MAX_BUFFERED_TUPLES   1000
 
#define MAX_BUFFERED_BYTES   65535
 
#define MAX_PARTITION_BUFFERS   32
 
#define MAX_COPY_DATA_DISPLAY   100
 

Typedefs

typedef struct CopyMultiInsertBuffer CopyMultiInsertBuffer
 
typedef struct CopyMultiInsertInfo CopyMultiInsertInfo
 

Functions

static void ClosePipeFromProgram (CopyFromState cstate)
 
static void CopyFromTextLikeInFunc (CopyFromState cstate, Oid atttypid, FmgrInfo *finfo, Oid *typioparam)
 
static void CopyFromTextLikeStart (CopyFromState cstate, TupleDesc tupDesc)
 
static void CopyFromTextLikeEnd (CopyFromState cstate)
 
static void CopyFromBinaryInFunc (CopyFromState cstate, Oid atttypid, FmgrInfo *finfo, Oid *typioparam)
 
static void CopyFromBinaryStart (CopyFromState cstate, TupleDesc tupDesc)
 
static void CopyFromBinaryEnd (CopyFromState cstate)
 
static const CopyFromRoutineCopyFromGetRoutine (const CopyFormatOptions *opts)
 
void CopyFromErrorCallback (void *arg)
 
charCopyLimitPrintoutLength (const char *str)
 
static CopyMultiInsertBufferCopyMultiInsertBufferInit (ResultRelInfo *rri)
 
static void CopyMultiInsertInfoSetupBuffer (CopyMultiInsertInfo *miinfo, ResultRelInfo *rri)
 
static void CopyMultiInsertInfoInit (CopyMultiInsertInfo *miinfo, ResultRelInfo *rri, CopyFromState cstate, EState *estate, CommandId mycid, int ti_options)
 
static bool CopyMultiInsertInfoIsFull (CopyMultiInsertInfo *miinfo)
 
static bool CopyMultiInsertInfoIsEmpty (CopyMultiInsertInfo *miinfo)
 
static void CopyMultiInsertBufferFlush (CopyMultiInsertInfo *miinfo, CopyMultiInsertBuffer *buffer, int64 *processed)
 
static void CopyMultiInsertBufferCleanup (CopyMultiInsertInfo *miinfo, CopyMultiInsertBuffer *buffer)
 
static void CopyMultiInsertInfoFlush (CopyMultiInsertInfo *miinfo, ResultRelInfo *curr_rri, int64 *processed)
 
static void CopyMultiInsertInfoCleanup (CopyMultiInsertInfo *miinfo)
 
static TupleTableSlotCopyMultiInsertInfoNextFreeSlot (CopyMultiInsertInfo *miinfo, ResultRelInfo *rri)
 
static void CopyMultiInsertInfoStore (CopyMultiInsertInfo *miinfo, ResultRelInfo *rri, TupleTableSlot *slot, int tuplen, uint64 lineno)
 
uint64 CopyFrom (CopyFromState cstate)
 
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)
 

Variables

static const CopyFromRoutine CopyFromRoutineText
 
static const CopyFromRoutine CopyFromRoutineCSV
 
static const CopyFromRoutine CopyFromRoutineBinary
 

Macro Definition Documentation

◆ MAX_BUFFERED_BYTES

#define MAX_BUFFERED_BYTES   65535

Definition at line 70 of file copyfrom.c.

◆ MAX_BUFFERED_TUPLES

#define MAX_BUFFERED_TUPLES   1000

Definition at line 64 of file copyfrom.c.

◆ MAX_COPY_DATA_DISPLAY

#define MAX_COPY_DATA_DISPLAY   100

◆ MAX_PARTITION_BUFFERS

#define MAX_PARTITION_BUFFERS   32

Definition at line 76 of file copyfrom.c.

Typedef Documentation

◆ CopyMultiInsertBuffer

◆ CopyMultiInsertInfo

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 1534 of file copyfrom.c.

1542{
1543 CopyFromState cstate;
1544 bool pipe = (filename == NULL);
1545 TupleDesc tupDesc;
1547 num_defaults;
1548 FmgrInfo *in_functions;
1549 Oid *typioparams;
1550 int *defmap;
1551 ExprState **defexprs;
1552 MemoryContext oldcontext;
1553 bool volatile_defexprs;
1554 const int progress_cols[] = {
1558 };
1559 int64 progress_vals[] = {
1561 0,
1562 0
1563 };
1564
1565 /* Allocate workspace and zero all fields */
1567
1568 /*
1569 * We allocate everything used by a cstate in a new memory context. This
1570 * avoids memory leaks during repeated use of COPY in a query.
1571 */
1573 "COPY",
1575
1576 oldcontext = MemoryContextSwitchTo(cstate->copycontext);
1577
1578 /* Extract options from the statement node tree */
1579 ProcessCopyOptions(pstate, &cstate->opts, true /* is_from */ , options);
1580
1581 /* Set the format routine */
1582 cstate->routine = CopyFromGetRoutine(&cstate->opts);
1583
1584 /* Process the target relation */
1585 cstate->rel = rel;
1586
1587 tupDesc = RelationGetDescr(cstate->rel);
1588
1589 /* process common options or initialization */
1590
1591 /* Generate or convert list of attributes to process */
1592 cstate->attnumlist = CopyGetAttnums(tupDesc, cstate->rel, attnamelist);
1593
1594 num_phys_attrs = tupDesc->natts;
1595
1596 /* Convert FORCE_NOT_NULL name list to per-column flags, check validity */
1597 cstate->opts.force_notnull_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1598 if (cstate->opts.force_notnull_all)
1599 MemSet(cstate->opts.force_notnull_flags, true, num_phys_attrs * sizeof(bool));
1600 else if (cstate->opts.force_notnull)
1601 {
1602 List *attnums;
1603 ListCell *cur;
1604
1605 attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_notnull);
1606
1607 foreach(cur, attnums)
1608 {
1609 int attnum = lfirst_int(cur);
1610 Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1611
1612 if (!list_member_int(cstate->attnumlist, attnum))
1613 ereport(ERROR,
1615 /*- translator: first %s is the name of a COPY option, e.g. FORCE_NOT_NULL */
1616 errmsg("%s column \"%s\" not referenced by COPY",
1617 "FORCE_NOT_NULL", NameStr(attr->attname))));
1618 cstate->opts.force_notnull_flags[attnum - 1] = true;
1619 }
1620 }
1621
1622 /* Set up soft error handler for ON_ERROR */
1623 if (cstate->opts.on_error != COPY_ON_ERROR_STOP)
1624 {
1627 cstate->escontext->error_occurred = false;
1628
1629 if (cstate->opts.on_error == COPY_ON_ERROR_IGNORE ||
1631 cstate->escontext->details_wanted = false;
1632 }
1633 else
1634 cstate->escontext = NULL;
1635
1636 if (cstate->opts.on_error == COPY_ON_ERROR_SET_NULL)
1637 {
1638 int attr_count = list_length(cstate->attnumlist);
1639
1640 /*
1641 * When data type conversion fails and ON_ERROR is SET_NULL, we need
1642 * ensure that the input column allow null values. ExecConstraints()
1643 * will cover most of the cases, but it does not verify domain
1644 * constraints. Therefore, for constrained domains, the null value
1645 * check must be performed during the initial string-to-datum
1646 * conversion (see CopyFromTextLikeOneRow()).
1647 */
1649
1650 foreach_int(attno, cstate->attnumlist)
1651 {
1652 int i = foreach_current_index(attno);
1653
1654 Form_pg_attribute att = TupleDescAttr(tupDesc, attno - 1);
1655
1656 cstate->domain_with_constraint[i] = DomainHasConstraints(att->atttypid);
1657 }
1658 }
1659
1660 /* Convert FORCE_NULL name list to per-column flags, check validity */
1661 cstate->opts.force_null_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1662 if (cstate->opts.force_null_all)
1663 MemSet(cstate->opts.force_null_flags, true, num_phys_attrs * sizeof(bool));
1664 else if (cstate->opts.force_null)
1665 {
1666 List *attnums;
1667 ListCell *cur;
1668
1669 attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_null);
1670
1671 foreach(cur, attnums)
1672 {
1673 int attnum = lfirst_int(cur);
1674 Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1675
1676 if (!list_member_int(cstate->attnumlist, attnum))
1677 ereport(ERROR,
1679 /*- translator: first %s is the name of a COPY option, e.g. FORCE_NOT_NULL */
1680 errmsg("%s column \"%s\" not referenced by COPY",
1681 "FORCE_NULL", NameStr(attr->attname))));
1682 cstate->opts.force_null_flags[attnum - 1] = true;
1683 }
1684 }
1685
1686 /* Convert convert_selectively name list to per-column flags */
1687 if (cstate->opts.convert_selectively)
1688 {
1689 List *attnums;
1690 ListCell *cur;
1691
1692 cstate->convert_select_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1693
1694 attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.convert_select);
1695
1696 foreach(cur, attnums)
1697 {
1698 int attnum = lfirst_int(cur);
1699 Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1700
1701 if (!list_member_int(cstate->attnumlist, attnum))
1702 ereport(ERROR,
1704 errmsg_internal("selected column \"%s\" not referenced by COPY",
1705 NameStr(attr->attname))));
1706 cstate->convert_select_flags[attnum - 1] = true;
1707 }
1708 }
1709
1710 /* Use client encoding when ENCODING option is not specified. */
1711 if (cstate->opts.file_encoding < 0)
1713 else
1714 cstate->file_encoding = cstate->opts.file_encoding;
1715
1716 /*
1717 * Look up encoding conversion function.
1718 */
1719 if (cstate->file_encoding == GetDatabaseEncoding() ||
1720 cstate->file_encoding == PG_SQL_ASCII ||
1722 {
1723 cstate->need_transcoding = false;
1724 }
1725 else
1726 {
1727 cstate->need_transcoding = true;
1730 if (!OidIsValid(cstate->conversion_proc))
1731 ereport(ERROR,
1733 errmsg("default conversion function for encoding \"%s\" to \"%s\" does not exist",
1736 }
1737
1738 cstate->copy_src = COPY_FILE; /* default */
1739
1740 cstate->whereClause = whereClause;
1741
1742 /* Initialize state variables */
1743 cstate->eol_type = EOL_UNKNOWN;
1744 cstate->cur_relname = RelationGetRelationName(cstate->rel);
1745 cstate->cur_lineno = 0;
1746 cstate->cur_attname = NULL;
1747 cstate->cur_attval = NULL;
1748 cstate->relname_only = false;
1749
1750 /*
1751 * Allocate buffers for the input pipeline.
1752 *
1753 * attribute_buf and raw_buf are used in both text and binary modes, but
1754 * input_buf and line_buf only in text mode.
1755 */
1756 cstate->raw_buf = palloc(RAW_BUF_SIZE + 1);
1757 cstate->raw_buf_index = cstate->raw_buf_len = 0;
1758 cstate->raw_reached_eof = false;
1759
1760 initStringInfo(&cstate->attribute_buf);
1761
1762 /* Assign range table and rteperminfos, we'll need them in CopyFrom. */
1763 if (pstate)
1764 {
1765 cstate->range_table = pstate->p_rtable;
1766 cstate->rteperminfos = pstate->p_rteperminfos;
1767 }
1768
1769 num_defaults = 0;
1770 volatile_defexprs = false;
1771
1772 /*
1773 * Pick up the required catalog information for each attribute in the
1774 * relation, including the input function, the element type (to pass to
1775 * the input function), and info about defaults and constraints. (Which
1776 * input function we use depends on text/binary format choice.)
1777 */
1778 in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
1779 typioparams = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
1780 defmap = (int *) palloc(num_phys_attrs * sizeof(int));
1781 defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *));
1782
1783 for (int attnum = 1; attnum <= num_phys_attrs; attnum++)
1784 {
1785 Form_pg_attribute att = TupleDescAttr(tupDesc, attnum - 1);
1786
1787 /* We don't need info for dropped attributes */
1788 if (att->attisdropped)
1789 continue;
1790
1791 /* Fetch the input function and typioparam info */
1792 cstate->routine->CopyFromInFunc(cstate, att->atttypid,
1793 &in_functions[attnum - 1],
1794 &typioparams[attnum - 1]);
1795
1796 /* Get default info if available */
1797 defexprs[attnum - 1] = NULL;
1798
1799 /*
1800 * We only need the default values for columns that do not appear in
1801 * the column list, unless the DEFAULT option was given. We never need
1802 * default values for generated columns.
1803 */
1804 if ((cstate->opts.default_print != NULL ||
1805 !list_member_int(cstate->attnumlist, attnum)) &&
1806 !att->attgenerated)
1807 {
1808 Expr *defexpr = (Expr *) build_column_default(cstate->rel,
1809 attnum);
1810
1811 if (defexpr != NULL)
1812 {
1813 /* Run the expression through planner */
1814 defexpr = expression_planner(defexpr);
1815
1816 /* Initialize executable expression in copycontext */
1817 defexprs[attnum - 1] = ExecInitExpr(defexpr, NULL);
1818
1819 /* if NOT copied from input */
1820 /* use default value if one exists */
1821 if (!list_member_int(cstate->attnumlist, attnum))
1822 {
1823 defmap[num_defaults] = attnum - 1;
1824 num_defaults++;
1825 }
1826
1827 /*
1828 * If a default expression looks at the table being loaded,
1829 * then it could give the wrong answer when using
1830 * multi-insert. Since database access can be dynamic this is
1831 * hard to test for exactly, so we use the much wider test of
1832 * whether the default expression is volatile. We allow for
1833 * the special case of when the default expression is the
1834 * nextval() of a sequence which in this specific case is
1835 * known to be safe for use with the multi-insert
1836 * optimization. Hence we use this special case function
1837 * checker rather than the standard check for
1838 * contain_volatile_functions(). Note also that we already
1839 * ran the expression through expression_planner().
1840 */
1841 if (!volatile_defexprs)
1842 volatile_defexprs = contain_volatile_functions_not_nextval((Node *) defexpr);
1843 }
1844 }
1845 }
1846
1847 cstate->defaults = (bool *) palloc0(tupDesc->natts * sizeof(bool));
1848
1849 /* initialize progress */
1851 cstate->rel ? RelationGetRelid(cstate->rel) : InvalidOid);
1852 cstate->bytes_processed = 0;
1853
1854 /* We keep those variables in cstate. */
1855 cstate->in_functions = in_functions;
1856 cstate->typioparams = typioparams;
1857 cstate->defmap = defmap;
1858 cstate->defexprs = defexprs;
1859 cstate->volatile_defexprs = volatile_defexprs;
1860 cstate->num_defaults = num_defaults;
1861 cstate->is_program = is_program;
1862
1863 if (data_source_cb)
1864 {
1866 cstate->copy_src = COPY_CALLBACK;
1867 cstate->data_source_cb = data_source_cb;
1868 }
1869 else if (pipe)
1870 {
1872 Assert(!is_program); /* the grammar does not allow this */
1874 ReceiveCopyBegin(cstate);
1875 else
1876 cstate->copy_file = stdin;
1877 }
1878 else
1879 {
1880 cstate->filename = pstrdup(filename);
1881
1882 if (cstate->is_program)
1883 {
1885 cstate->copy_file = OpenPipeStream(cstate->filename, PG_BINARY_R);
1886 if (cstate->copy_file == NULL)
1887 ereport(ERROR,
1889 errmsg("could not execute command \"%s\": %m",
1890 cstate->filename)));
1891 }
1892 else
1893 {
1894 struct stat st;
1895
1897 cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_R);
1898 if (cstate->copy_file == NULL)
1899 {
1900 /* copy errno because ereport subfunctions might change it */
1901 int save_errno = errno;
1902
1903 ereport(ERROR,
1905 errmsg("could not open file \"%s\" for reading: %m",
1906 cstate->filename),
1907 (save_errno == ENOENT || save_errno == EACCES) ?
1908 errhint("COPY FROM instructs the PostgreSQL server process to read a file. "
1909 "You may want a client-side facility such as psql's \\copy.") : 0));
1910 }
1911
1912 if (fstat(fileno(cstate->copy_file), &st))
1913 ereport(ERROR,
1915 errmsg("could not stat file \"%s\": %m",
1916 cstate->filename)));
1917
1918 if (S_ISDIR(st.st_mode))
1919 ereport(ERROR,
1921 errmsg("\"%s\" is a directory", cstate->filename)));
1922
1923 progress_vals[2] = st.st_size;
1924 }
1925 }
1926
1928
1929 cstate->routine->CopyFromStart(cstate, tupDesc);
1930
1931 MemoryContextSwitchTo(oldcontext);
1932
1933 return cstate;
1934}
int16 AttrNumber
Definition attnum.h:21
List * CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
Definition copy.c:1010
void ProcessCopyOptions(ParseState *pstate, CopyFormatOptions *opts_out, bool is_from, List *options)
Definition copy.c:561
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:807
#define PG_BINARY_R
Definition c.h:1348
#define Assert(condition)
Definition c.h:915
int64_t int64
Definition c.h:585
#define MemSet(start, val, len)
Definition c.h:1079
#define OidIsValid(objectId)
Definition c.h:830
bool contain_volatile_functions_not_nextval(Node *clause)
Definition clauses.c:684
static const CopyFromRoutine * CopyFromGetRoutine(const CopyFormatOptions *opts)
Definition copyfrom.c:157
@ EOL_UNKNOWN
#define RAW_BUF_SIZE
void ReceiveCopyBegin(CopyFromState cstate)
@ COPY_FILE
Definition copyto.c:48
@ COPY_CALLBACK
Definition copyto.c:50
@ DestRemote
Definition dest.h:89
struct cursor * cur
Definition ecpg.c:29
int errcode_for_file_access(void)
Definition elog.c:897
int errcode(int sqlerrcode)
Definition elog.c:874
int errhint(const char *fmt,...) pg_attribute_printf(1
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#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:2731
FILE * AllocateFile(const char *name, const char *mode)
Definition fd.c:2628
#define palloc0_array(type, count)
Definition fe_memutils.h:77
#define palloc0_object(type)
Definition fe_memutils.h:75
@ COPY_ON_ERROR_IGNORE
Definition copy.h:37
@ COPY_ON_ERROR_SET_NULL
Definition copy.h:38
@ COPY_ON_ERROR_STOP
Definition copy.h:36
int i
Definition isn.c:77
bool list_member_int(const List *list, int datum)
Definition list.c:702
int GetDatabaseEncoding(void)
Definition mbutils.c:1389
int pg_get_client_encoding(void)
Definition mbutils.c:345
char * pstrdup(const char *in)
Definition mcxt.c:1781
void * palloc0(Size size)
Definition mcxt.c:1417
void * palloc(Size size)
Definition mcxt.c:1387
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:4152
#define makeNode(_type_)
Definition nodes.h:161
static char * errmsg
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
int16 attnum
FormData_pg_attribute * Form_pg_attribute
static char * filename
Definition pg_dumpall.c:133
static int list_length(const List *l)
Definition pg_list.h:152
#define foreach_current_index(var_or_cell)
Definition pg_list.h:403
#define lfirst_int(lc)
Definition pg_list.h:173
#define foreach_int(var, lst)
Definition pg_list.h:470
@ 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:6819
CommandDest whereToSendOutput
Definition postgres.c:93
#define InvalidOid
unsigned int Oid
static int fb(int x)
#define PROGRESS_COPY_COMMAND
Definition progress.h:174
#define PROGRESS_COPY_TYPE_FILE
Definition progress.h:183
#define PROGRESS_COPY_COMMAND_FROM
Definition progress.h:179
#define PROGRESS_COPY_TYPE
Definition progress.h:175
#define PROGRESS_COPY_TYPE_PROGRAM
Definition progress.h:184
#define PROGRESS_COPY_BYTES_TOTAL
Definition progress.h:171
#define PROGRESS_COPY_TYPE_CALLBACK
Definition progress.h:186
#define PROGRESS_COPY_TYPE_PIPE
Definition progress.h:185
#define RelationGetRelid(relation)
Definition rel.h:514
#define RelationGetDescr(relation)
Definition rel.h:540
#define RelationGetRelationName(relation)
Definition rel.h:548
Node * build_column_default(Relation rel, int attrno)
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
bool force_notnull_all
Definition copy.h:79
bool convert_selectively
Definition copy.h:84
CopyOnErrorChoice on_error
Definition copy.h:85
List * force_null
Definition copy.h:81
List * convert_select
Definition copy.h:88
bool force_null_all
Definition copy.h:82
bool * force_notnull_flags
Definition copy.h:80
int file_encoding
Definition copy.h:60
bool * force_null_flags
Definition copy.h:83
char * default_print
Definition copy.h:70
List * force_notnull
Definition copy.h:78
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
Definition pg_list.h:54
Definition nodes.h:135
List * p_rteperminfos
Definition parse_node.h:193
List * p_rtable
Definition parse_node.h:192
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:160
bool DomainHasConstraints(Oid type_id)
Definition typcache.c:1491
#define S_ISDIR(m)
Definition win32_port.h:315
#define fstat
Definition win32_port.h:73

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_SET_NULL, 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::domain_with_constraint, DomainHasConstraints(), CopyFromStateData::eol_type, EOL_UNKNOWN, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg, errmsg_internal(), ERROR, ErrorSaveContext::error_occurred, CopyFromStateData::escontext, ExecInitExpr(), expression_planner(), fb(), 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, foreach_current_index, foreach_int, fstat, GetDatabaseEncoding(), i, CopyFromStateData::in_functions, initStringInfo(), InvalidOid, CopyFromStateData::is_program, lfirst_int, list_length(), 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(), palloc0_array, palloc0_object, 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().

◆ ClosePipeFromProgram()

static void ClosePipeFromProgram ( CopyFromState  cstate)
static

Definition at line 1969 of file copyfrom.c.

1970{
1971 int pclose_rc;
1972
1973 Assert(cstate->is_program);
1974
1976 if (pclose_rc == -1)
1977 ereport(ERROR,
1979 errmsg("could not close pipe to external command: %m")));
1980 else if (pclose_rc != 0)
1981 {
1982 /*
1983 * If we ended a COPY FROM PROGRAM before reaching EOF, then it's
1984 * expectable for the called program to fail with SIGPIPE, and we
1985 * should not report that as an error. Otherwise, SIGPIPE indicates a
1986 * problem.
1987 */
1988 if (!cstate->raw_reached_eof &&
1990 return;
1991
1992 ereport(ERROR,
1994 errmsg("program \"%s\" failed",
1995 cstate->filename),
1997 }
1998}
int int errdetail_internal(const char *fmt,...) pg_attribute_printf(1
int ClosePipeStream(FILE *file)
Definition fd.c:3039
char * wait_result_to_str(int exitstatus)
Definition wait_error.c:33
bool wait_result_is_signal(int exit_status, int signum)
Definition wait_error.c:102
#define SIGPIPE
Definition win32_port.h:163

References Assert, ClosePipeStream(), CopyFromStateData::copy_file, ereport, errcode(), errcode_for_file_access(), errdetail_internal(), errmsg, ERROR, fb(), CopyFromStateData::filename, CopyFromStateData::is_program, CopyFromStateData::raw_reached_eof, SIGPIPE, wait_result_is_signal(), and wait_result_to_str().

Referenced by EndCopyFrom().

◆ CopyFrom()

uint64 CopyFrom ( CopyFromState  cstate)

Definition at line 780 of file copyfrom.c.

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

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_SET_NULL, COPY_ON_ERROR_STOP, CopyFromErrorCallback(), CopyMultiInsertInfoCleanup(), CopyMultiInsertInfoFlush(), CopyMultiInsertInfoInit(), CopyMultiInsertInfoIsEmpty(), CopyMultiInsertInfoIsFull(), CopyMultiInsertInfoNextFreeSlot(), CopyMultiInsertInfoSetupBuffer(), CopyMultiInsertInfoStore(), CreateExecutorState(), CopyFromStateData::cur_lineno, CurrentMemoryContext, ExprContext::ecxt_scantuple, 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(), fb(), 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, CopyFromStateData::volatile_defexprs, and CopyFromStateData::whereClause.

Referenced by copy_table(), and DoCopy().

◆ CopyFromBinaryEnd()

static void CopyFromBinaryEnd ( CopyFromState  cstate)
static

Definition at line 244 of file copyfrom.c.

245{
246 /* nothing to do */
247}

◆ CopyFromBinaryInFunc()

static void CopyFromBinaryInFunc ( CopyFromState  cstate,
Oid  atttypid,
FmgrInfo finfo,
Oid typioparam 
)
static

Definition at line 233 of file copyfrom.c.

235{
237
239 fmgr_info(func_oid, finfo);
240}
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition fmgr.c:128
void getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
Definition lsyscache.c:3160

References fb(), fmgr_info(), and getTypeBinaryInputInfo().

◆ CopyFromBinaryStart()

static void CopyFromBinaryStart ( CopyFromState  cstate,
TupleDesc  tupDesc 
)
static

Definition at line 222 of file copyfrom.c.

223{
224 /* Read and verify binary header */
226}
void ReceiveCopyBinaryHeader(CopyFromState cstate)

References ReceiveCopyBinaryHeader().

◆ CopyFromErrorCallback()

void CopyFromErrorCallback ( void arg)

Definition at line 255 of file copyfrom.c.

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

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

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

◆ CopyFromGetRoutine()

static const CopyFromRoutine * CopyFromGetRoutine ( const CopyFormatOptions opts)
static

Definition at line 157 of file copyfrom.c.

158{
159 if (opts->csv_mode)
160 return &CopyFromRoutineCSV;
161 else if (opts->binary)
162 return &CopyFromRoutineBinary;
163
164 /* default is text */
165 return &CopyFromRoutineText;
166}
static const CopyFromRoutine CopyFromRoutineBinary
Definition copyfrom.c:148
static const CopyFromRoutine CopyFromRoutineText
Definition copyfrom.c:132
static const CopyFromRoutine CopyFromRoutineCSV
Definition copyfrom.c:140
static AmcheckOptions opts
Definition pg_amcheck.c:112

References CopyFromRoutineBinary, CopyFromRoutineCSV, CopyFromRoutineText, and opts.

Referenced by BeginCopyFrom().

◆ CopyFromTextLikeEnd()

static void CopyFromTextLikeEnd ( CopyFromState  cstate)
static

Definition at line 215 of file copyfrom.c.

216{
217 /* nothing to do */
218}

◆ CopyFromTextLikeInFunc()

static void CopyFromTextLikeInFunc ( CopyFromState  cstate,
Oid  atttypid,
FmgrInfo finfo,
Oid typioparam 
)
static

Definition at line 204 of file copyfrom.c.

206{
208
209 getTypeInputInfo(atttypid, &func_oid, typioparam);
210 fmgr_info(func_oid, finfo);
211}
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition lsyscache.c:3094

References fb(), fmgr_info(), and getTypeInputInfo().

◆ CopyFromTextLikeStart()

static void CopyFromTextLikeStart ( CopyFromState  cstate,
TupleDesc  tupDesc 
)
static

Definition at line 170 of file copyfrom.c.

171{
173
174 /*
175 * If encoding conversion is needed, we need another buffer to hold the
176 * converted input data. Otherwise, we can just point input_buf to the
177 * same buffer as raw_buf.
178 */
179 if (cstate->need_transcoding)
180 {
181 cstate->input_buf = (char *) palloc(INPUT_BUF_SIZE + 1);
182 cstate->input_buf_index = cstate->input_buf_len = 0;
183 }
184 else
185 cstate->input_buf = cstate->raw_buf;
186 cstate->input_reached_eof = false;
187
188 initStringInfo(&cstate->line_buf);
189
190 /*
191 * Create workspace for CopyReadAttributes results; used by CSV and text
192 * format.
193 */
195 cstate->max_fields = attr_count;
196 cstate->raw_fields = (char **) palloc(attr_count * sizeof(char *));
197}
#define INPUT_BUF_SIZE

References CopyFromStateData::attnumlist, fb(), initStringInfo(), CopyFromStateData::input_buf, CopyFromStateData::input_buf_index, CopyFromStateData::input_buf_len, INPUT_BUF_SIZE, CopyFromStateData::input_reached_eof, CopyFromStateData::line_buf, list_length(), CopyFromStateData::max_fields, CopyFromStateData::need_transcoding, palloc(), CopyFromStateData::raw_buf, and CopyFromStateData::raw_fields.

◆ CopyLimitPrintoutLength()

char * CopyLimitPrintoutLength ( const char str)

Definition at line 334 of file copyfrom.c.

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

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

Referenced by CopyFromErrorCallback(), and CopyFromTextLikeOneRow().

◆ CopyMultiInsertBufferCleanup()

static void CopyMultiInsertBufferCleanup ( CopyMultiInsertInfo miinfo,
CopyMultiInsertBuffer buffer 
)
inlinestatic

Definition at line 621 of file copyfrom.c.

623{
624 ResultRelInfo *resultRelInfo = buffer->resultRelInfo;
625 int i;
626
627 /* Ensure buffer was flushed */
628 Assert(buffer->nused == 0);
629
630 /* Remove back-link to ourself */
631 resultRelInfo->ri_CopyMultiInsertBuffer = NULL;
632
633 if (resultRelInfo->ri_FdwRoutine == NULL)
634 {
635 Assert(buffer->bistate != NULL);
637 }
638 else
639 Assert(buffer->bistate == NULL);
640
641 /* Since we only create slots on demand, just drop the non-null ones. */
642 for (i = 0; i < MAX_BUFFERED_TUPLES && buffer->slots[i] != NULL; i++)
644
645 if (resultRelInfo->ri_FdwRoutine == NULL)
647 miinfo->ti_options);
648
649 pfree(buffer);
650}
#define MAX_BUFFERED_TUPLES
Definition copyfrom.c:64
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
TupleTableSlot * slots[MAX_BUFFERED_TUPLES]
Definition copyfrom.c:81
ResultRelInfo * resultRelInfo
Definition copyfrom.c:82
BulkInsertState bistate
Definition copyfrom.c:83
static void table_finish_bulk_insert(Relation rel, int options)
Definition tableam.h:1585

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

Referenced by CopyMultiInsertInfoCleanup(), and CopyMultiInsertInfoFlush().

◆ CopyMultiInsertBufferFlush()

static void CopyMultiInsertBufferFlush ( CopyMultiInsertInfo miinfo,
CopyMultiInsertBuffer buffer,
int64 processed 
)
inlinestatic

Definition at line 447 of file copyfrom.c.

450{
451 CopyFromState cstate = miinfo->cstate;
452 EState *estate = miinfo->estate;
453 int nused = buffer->nused;
454 ResultRelInfo *resultRelInfo = buffer->resultRelInfo;
455 TupleTableSlot **slots = buffer->slots;
456 int i;
457
458 if (resultRelInfo->ri_FdwRoutine)
459 {
460 int batch_size = resultRelInfo->ri_BatchSize;
461 int sent = 0;
462
463 Assert(buffer->bistate == NULL);
464
465 /* Ensure that the FDW supports batching and it's enabled */
467 Assert(batch_size > 1);
468
469 /*
470 * We suppress error context information other than the relation name,
471 * if one of the operations below fails.
472 */
473 Assert(!cstate->relname_only);
474 cstate->relname_only = true;
475
476 while (sent < nused)
477 {
478 int size = (batch_size < nused - sent) ? batch_size : (nused - sent);
479 int inserted = size;
481
482 /* insert into foreign table: let the FDW do it */
483 rslots =
484 resultRelInfo->ri_FdwRoutine->ExecForeignBatchInsert(estate,
485 resultRelInfo,
486 &slots[sent],
487 NULL,
488 &inserted);
489
490 sent += size;
491
492 /* No need to do anything if there are no inserted rows */
493 if (inserted <= 0)
494 continue;
495
496 /* Triggers on foreign tables should not have transition tables */
497 Assert(resultRelInfo->ri_TrigDesc == NULL ||
498 resultRelInfo->ri_TrigDesc->trig_insert_new_table == false);
499
500 /* Run AFTER ROW INSERT triggers */
501 if (resultRelInfo->ri_TrigDesc != NULL &&
502 resultRelInfo->ri_TrigDesc->trig_insert_after_row)
503 {
504 Oid relid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
505
506 for (i = 0; i < inserted; i++)
507 {
508 TupleTableSlot *slot = rslots[i];
509
510 /*
511 * AFTER ROW Triggers might reference the tableoid column,
512 * so (re-)initialize tts_tableOid before evaluating them.
513 */
514 slot->tts_tableOid = relid;
515
516 ExecARInsertTriggers(estate, resultRelInfo,
517 slot, NIL,
518 cstate->transition_capture);
519 }
520 }
521
522 /* Update the row counter and progress of the COPY command */
523 *processed += inserted;
525 *processed);
526 }
527
528 for (i = 0; i < nused; i++)
529 ExecClearTuple(slots[i]);
530
531 /* reset relname_only */
532 cstate->relname_only = false;
533 }
534 else
535 {
536 CommandId mycid = miinfo->mycid;
537 int ti_options = miinfo->ti_options;
538 bool line_buf_valid = cstate->line_buf_valid;
540 MemoryContext oldcontext;
541
542 Assert(buffer->bistate != NULL);
543
544 /*
545 * Print error context information correctly, if one of the operations
546 * below fails.
547 */
548 cstate->line_buf_valid = false;
549
550 /*
551 * table_multi_insert may leak memory, so switch to short-lived memory
552 * context before calling it.
553 */
555 table_multi_insert(resultRelInfo->ri_RelationDesc,
556 slots,
557 nused,
558 mycid,
559 ti_options,
560 buffer->bistate);
561 MemoryContextSwitchTo(oldcontext);
562
563 for (i = 0; i < nused; i++)
564 {
565 /*
566 * If there are any indexes, update them for all the inserted
567 * tuples, and run AFTER ROW INSERT triggers.
568 */
569 if (resultRelInfo->ri_NumIndices > 0)
570 {
572
573 cstate->cur_lineno = buffer->linenos[i];
575 ExecInsertIndexTuples(resultRelInfo,
576 estate, 0, buffer->slots[i],
577 NIL, NULL);
578 ExecARInsertTriggers(estate, resultRelInfo,
579 slots[i], recheckIndexes,
580 cstate->transition_capture);
582 }
583
584 /*
585 * There's no indexes, but see if we need to run AFTER ROW INSERT
586 * triggers anyway.
587 */
588 else if (resultRelInfo->ri_TrigDesc != NULL &&
589 (resultRelInfo->ri_TrigDesc->trig_insert_after_row ||
590 resultRelInfo->ri_TrigDesc->trig_insert_new_table))
591 {
592 cstate->cur_lineno = buffer->linenos[i];
593 ExecARInsertTriggers(estate, resultRelInfo,
594 slots[i], NIL,
595 cstate->transition_capture);
596 }
597
598 ExecClearTuple(slots[i]);
599 }
600
601 /* Update the row counter and progress of the COPY command */
602 *processed += nused;
604 *processed);
605
606 /* reset cur_lineno and line_buf_valid to what they were */
607 cstate->line_buf_valid = line_buf_valid;
608 cstate->cur_lineno = save_cur_lineno;
609 }
610
611 /* Mark that all slots are free */
612 buffer->nused = 0;
613}
uint64_t uint64
Definition c.h:589
uint64 linenos[MAX_BUFFERED_TUPLES]
Definition copyfrom.c:86
bool trig_insert_after_row
Definition reltrigger.h:57
static void table_multi_insert(Relation rel, TupleTableSlot **slots, int nslots, CommandId cid, int options, BulkInsertStateData *bistate)
Definition tableam.h:1443

References Assert, CopyMultiInsertBuffer::bistate, CopyFromStateData::cur_lineno, ExecARInsertTriggers(), ExecClearTuple(), FdwRoutine::ExecForeignBatchInsert, ExecInsertIndexTuples(), fb(), GetPerTupleMemoryContext, i, CopyFromStateData::line_buf_valid, CopyMultiInsertBuffer::linenos, list_free(), MemoryContextSwitchTo(), NIL, CopyMultiInsertBuffer::nused, pgstat_progress_update_param(), PROGRESS_COPY_TUPLES_PROCESSED, RelationGetRelid, CopyFromStateData::relname_only, CopyMultiInsertBuffer::resultRelInfo, ResultRelInfo::ri_BatchSize, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, CopyMultiInsertBuffer::slots, table_multi_insert(), CopyFromStateData::transition_capture, TriggerDesc::trig_insert_after_row, TriggerDesc::trig_insert_new_table, and TupleTableSlot::tts_tableOid.

Referenced by CopyMultiInsertInfoFlush().

◆ CopyMultiInsertBufferInit()

static CopyMultiInsertBuffer * CopyMultiInsertBufferInit ( ResultRelInfo rri)
static

Definition at line 364 of file copyfrom.c.

365{
366 CopyMultiInsertBuffer *buffer;
367
369 memset(buffer->slots, 0, sizeof(TupleTableSlot *) * MAX_BUFFERED_TUPLES);
370 buffer->resultRelInfo = rri;
371 buffer->bistate = (rri->ri_FdwRoutine == NULL) ? GetBulkInsertState() : NULL;
372 buffer->nused = 0;
373
374 return buffer;
375}
#define palloc_object(type)
Definition fe_memutils.h:74

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

Referenced by CopyMultiInsertInfoSetupBuffer().

◆ CopyMultiInsertInfoCleanup()

static void CopyMultiInsertInfoCleanup ( CopyMultiInsertInfo miinfo)
inlinestatic

Definition at line 717 of file copyfrom.c.

718{
719 ListCell *lc;
720
721 foreach(lc, miinfo->multiInsertBuffers)
723
724 list_free(miinfo->multiInsertBuffers);
725}
static void CopyMultiInsertBufferCleanup(CopyMultiInsertInfo *miinfo, CopyMultiInsertBuffer *buffer)
Definition copyfrom.c:621
#define lfirst(lc)
Definition pg_list.h:172

References CopyMultiInsertBufferCleanup(), fb(), lfirst, and list_free().

Referenced by CopyFrom().

◆ CopyMultiInsertInfoFlush()

static void CopyMultiInsertInfoFlush ( CopyMultiInsertInfo miinfo,
ResultRelInfo curr_rri,
int64 processed 
)
inlinestatic

Definition at line 663 of file copyfrom.c.

665{
666 ListCell *lc;
667
668 foreach(lc, miinfo->multiInsertBuffers)
669 {
671
672 CopyMultiInsertBufferFlush(miinfo, buffer, processed);
673 }
674
675 miinfo->bufferedTuples = 0;
676 miinfo->bufferedBytes = 0;
677
678 /*
679 * Trim the list of tracked buffers down if it exceeds the limit. Here we
680 * remove buffers starting with the ones we created first. It seems less
681 * likely that these older ones will be needed than the ones that were
682 * just created.
683 */
684 while (list_length(miinfo->multiInsertBuffers) > MAX_PARTITION_BUFFERS)
685 {
686 CopyMultiInsertBuffer *buffer;
687
688 buffer = (CopyMultiInsertBuffer *) linitial(miinfo->multiInsertBuffers);
689
690 /*
691 * We never want to remove the buffer that's currently being used, so
692 * if we happen to find that then move it to the end of the list.
693 */
694 if (buffer->resultRelInfo == curr_rri)
695 {
696 /*
697 * The code below would misbehave if we were trying to reduce the
698 * list to less than two items.
699 */
701 "MAX_PARTITION_BUFFERS must be >= 2");
702
703 miinfo->multiInsertBuffers = list_delete_first(miinfo->multiInsertBuffers);
704 miinfo->multiInsertBuffers = lappend(miinfo->multiInsertBuffers, buffer);
705 buffer = (CopyMultiInsertBuffer *) linitial(miinfo->multiInsertBuffers);
706 }
707
709 miinfo->multiInsertBuffers = list_delete_first(miinfo->multiInsertBuffers);
710 }
711}
#define StaticAssertDecl(condition, errmessage)
Definition c.h:980
#define MAX_PARTITION_BUFFERS
Definition copyfrom.c:76
static void CopyMultiInsertBufferFlush(CopyMultiInsertInfo *miinfo, CopyMultiInsertBuffer *buffer, int64 *processed)
Definition copyfrom.c:447
List * lappend(List *list, void *datum)
Definition list.c:339
List * list_delete_first(List *list)
Definition list.c:943
#define linitial(l)
Definition pg_list.h:178

References CopyMultiInsertBufferCleanup(), CopyMultiInsertBufferFlush(), fb(), lappend(), lfirst, linitial, list_delete_first(), list_length(), MAX_PARTITION_BUFFERS, CopyMultiInsertBuffer::resultRelInfo, and StaticAssertDecl.

Referenced by CopyFrom().

◆ CopyMultiInsertInfoInit()

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

Definition at line 401 of file copyfrom.c.

404{
405 miinfo->multiInsertBuffers = NIL;
406 miinfo->bufferedTuples = 0;
407 miinfo->bufferedBytes = 0;
408 miinfo->cstate = cstate;
409 miinfo->estate = estate;
410 miinfo->mycid = mycid;
411 miinfo->ti_options = ti_options;
412
413 /*
414 * Only setup the buffer when not dealing with a partitioned table.
415 * Buffers for partitioned tables will just be setup when we need to send
416 * tuples their way for the first time.
417 */
418 if (rri->ri_RelationDesc->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
420}

References CopyMultiInsertInfoSetupBuffer(), fb(), and NIL.

Referenced by CopyFrom().

◆ CopyMultiInsertInfoIsEmpty()

static bool CopyMultiInsertInfoIsEmpty ( CopyMultiInsertInfo miinfo)
inlinestatic

Definition at line 438 of file copyfrom.c.

439{
440 return miinfo->bufferedTuples == 0;
441}

References fb().

Referenced by CopyFrom().

◆ CopyMultiInsertInfoIsFull()

static bool CopyMultiInsertInfoIsFull ( CopyMultiInsertInfo miinfo)
inlinestatic

Definition at line 426 of file copyfrom.c.

427{
428 if (miinfo->bufferedTuples >= MAX_BUFFERED_TUPLES ||
429 miinfo->bufferedBytes >= MAX_BUFFERED_BYTES)
430 return true;
431 return false;
432}
#define MAX_BUFFERED_BYTES
Definition copyfrom.c:70

References fb(), MAX_BUFFERED_BYTES, and MAX_BUFFERED_TUPLES.

Referenced by CopyFrom().

◆ CopyMultiInsertInfoNextFreeSlot()

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

Definition at line 736 of file copyfrom.c.

738{
739 CopyMultiInsertBuffer *buffer = rri->ri_CopyMultiInsertBuffer;
740 int nused;
741
742 Assert(buffer != NULL);
744
745 nused = buffer->nused;
746
747 if (buffer->slots[nused] == NULL)
748 buffer->slots[nused] = table_slot_create(rri->ri_RelationDesc, NULL);
749 return buffer->slots[nused];
750}

References Assert, fb(), MAX_BUFFERED_TUPLES, CopyMultiInsertBuffer::nused, CopyMultiInsertBuffer::slots, and table_slot_create().

Referenced by CopyFrom().

◆ CopyMultiInsertInfoSetupBuffer()

static void CopyMultiInsertInfoSetupBuffer ( CopyMultiInsertInfo miinfo,
ResultRelInfo rri 
)
inlinestatic

Definition at line 381 of file copyfrom.c.

383{
384 CopyMultiInsertBuffer *buffer;
385
387
388 /* Setup back-link so we can easily find this buffer again */
389 rri->ri_CopyMultiInsertBuffer = buffer;
390 /* Record that we're tracking this buffer */
391 miinfo->multiInsertBuffers = lappend(miinfo->multiInsertBuffers, buffer);
392}
static CopyMultiInsertBuffer * CopyMultiInsertBufferInit(ResultRelInfo *rri)
Definition copyfrom.c:364

References CopyMultiInsertBufferInit(), fb(), and lappend().

Referenced by CopyFrom(), and CopyMultiInsertInfoInit().

◆ CopyMultiInsertInfoStore()

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

Definition at line 757 of file copyfrom.c.

759{
760 CopyMultiInsertBuffer *buffer = rri->ri_CopyMultiInsertBuffer;
761
762 Assert(buffer != NULL);
763 Assert(slot == buffer->slots[buffer->nused]);
764
765 /* Store the line number so we can properly report any errors later */
766 buffer->linenos[buffer->nused] = lineno;
767
768 /* Record this slot as being used */
769 buffer->nused++;
770
771 /* Update how many tuples are stored and their size */
772 miinfo->bufferedTuples++;
773 miinfo->bufferedBytes += tuplen;
774}

References Assert, fb(), CopyMultiInsertBuffer::linenos, CopyMultiInsertBuffer::nused, and CopyMultiInsertBuffer::slots.

Referenced by CopyFrom().

◆ EndCopyFrom()

void EndCopyFrom ( CopyFromState  cstate)

Definition at line 1940 of file copyfrom.c.

1941{
1942 /* Invoke the end callback */
1943 cstate->routine->CopyFromEnd(cstate);
1944
1945 /* No COPY FROM related resources except memory. */
1946 if (cstate->is_program)
1947 {
1948 ClosePipeFromProgram(cstate);
1949 }
1950 else
1951 {
1952 if (cstate->filename != NULL && FreeFile(cstate->copy_file))
1953 ereport(ERROR,
1955 errmsg("could not close file \"%s\": %m",
1956 cstate->filename)));
1957 }
1958
1960
1962 pfree(cstate);
1963}
void pgstat_progress_end_command(void)
static void ClosePipeFromProgram(CopyFromState cstate)
Definition copyfrom.c:1969
int FreeFile(FILE *file)
Definition fd.c:2827
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472
void(* CopyFromEnd)(CopyFromState cstate)
Definition copyapi.h:102

References ClosePipeFromProgram(), CopyFromStateData::copy_file, CopyFromStateData::copycontext, CopyFromRoutine::CopyFromEnd, ereport, errcode_for_file_access(), errmsg, ERROR, fb(), 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().

Variable Documentation

◆ CopyFromRoutineBinary

const CopyFromRoutine CopyFromRoutineBinary
static
Initial value:
= {
.CopyFromInFunc = CopyFromBinaryInFunc,
.CopyFromStart = CopyFromBinaryStart,
.CopyFromOneRow = CopyFromBinaryOneRow,
.CopyFromEnd = CopyFromBinaryEnd,
}
static void CopyFromBinaryEnd(CopyFromState cstate)
Definition copyfrom.c:244
static void CopyFromBinaryStart(CopyFromState cstate, TupleDesc tupDesc)
Definition copyfrom.c:222
static void CopyFromBinaryInFunc(CopyFromState cstate, Oid atttypid, FmgrInfo *finfo, Oid *typioparam)
Definition copyfrom.c:233
bool CopyFromBinaryOneRow(CopyFromState cstate, ExprContext *econtext, Datum *values, bool *nulls)

Definition at line 148 of file copyfrom.c.

148 {
149 .CopyFromInFunc = CopyFromBinaryInFunc,
150 .CopyFromStart = CopyFromBinaryStart,
151 .CopyFromOneRow = CopyFromBinaryOneRow,
152 .CopyFromEnd = CopyFromBinaryEnd,
153};

Referenced by CopyFromGetRoutine().

◆ CopyFromRoutineCSV

const CopyFromRoutine CopyFromRoutineCSV
static
Initial value:
= {
.CopyFromInFunc = CopyFromTextLikeInFunc,
.CopyFromStart = CopyFromTextLikeStart,
.CopyFromOneRow = CopyFromCSVOneRow,
.CopyFromEnd = CopyFromTextLikeEnd,
}
static void CopyFromTextLikeStart(CopyFromState cstate, TupleDesc tupDesc)
Definition copyfrom.c:170
static void CopyFromTextLikeInFunc(CopyFromState cstate, Oid atttypid, FmgrInfo *finfo, Oid *typioparam)
Definition copyfrom.c:204
static void CopyFromTextLikeEnd(CopyFromState cstate)
Definition copyfrom.c:215
bool CopyFromCSVOneRow(CopyFromState cstate, ExprContext *econtext, Datum *values, bool *nulls)

Definition at line 140 of file copyfrom.c.

140 {
141 .CopyFromInFunc = CopyFromTextLikeInFunc,
142 .CopyFromStart = CopyFromTextLikeStart,
143 .CopyFromOneRow = CopyFromCSVOneRow,
144 .CopyFromEnd = CopyFromTextLikeEnd,
145};

Referenced by CopyFromGetRoutine().

◆ CopyFromRoutineText

const CopyFromRoutine CopyFromRoutineText
static
Initial value:
= {
.CopyFromInFunc = CopyFromTextLikeInFunc,
.CopyFromStart = CopyFromTextLikeStart,
.CopyFromOneRow = CopyFromTextOneRow,
.CopyFromEnd = CopyFromTextLikeEnd,
}
bool CopyFromTextOneRow(CopyFromState cstate, ExprContext *econtext, Datum *values, bool *nulls)

Definition at line 132 of file copyfrom.c.

132 {
133 .CopyFromInFunc = CopyFromTextLikeInFunc,
134 .CopyFromStart = CopyFromTextLikeStart,
135 .CopyFromOneRow = CopyFromTextOneRow,
136 .CopyFromEnd = CopyFromTextLikeEnd,
137};

Referenced by CopyFromGetRoutine().