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

Go to the source code of this file.

Data Structures

struct  CopyFormatOptions
 

Typedefs

typedef enum CopyHeaderChoice CopyHeaderChoice
 
typedef struct CopyFormatOptions CopyFormatOptions
 
typedef struct CopyFromStateDataCopyFromState
 
typedef struct CopyToStateDataCopyToState
 
typedef int(* copy_data_source_cb) (void *outbuf, int minread, int maxread)
 

Enumerations

enum  CopyHeaderChoice { COPY_HEADER_FALSE = 0 , COPY_HEADER_TRUE , COPY_HEADER_MATCH }
 

Functions

void DoCopy (ParseState *state, const CopyStmt *stmt, int stmt_location, int stmt_len, uint64 *processed)
 
void ProcessCopyOptions (ParseState *pstate, CopyFormatOptions *ops_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)
 
uint64 CopyFrom (CopyFromState cstate)
 
DestReceiverCreateCopyDestReceiver (void)
 
CopyToState BeginCopyTo (ParseState *pstate, Relation rel, RawStmt *query, Oid queryRelId, const char *filename, bool is_program, List *attnamelist, List *options)
 
void EndCopyTo (CopyToState cstate)
 
uint64 DoCopyTo (CopyToState cstate)
 
ListCopyGetAttnums (TupleDesc tupDesc, Relation rel, List *attnamelist)
 

Typedef Documentation

◆ copy_data_source_cb

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

Definition at line 68 of file copy.h.

◆ CopyFormatOptions

◆ CopyFromState

Definition at line 65 of file copy.h.

◆ CopyHeaderChoice

◆ CopyToState

typedef struct CopyToStateData* CopyToState

Definition at line 66 of file copy.h.

Enumeration Type Documentation

◆ CopyHeaderChoice

Enumerator
COPY_HEADER_FALSE 
COPY_HEADER_TRUE 
COPY_HEADER_MATCH 

Definition at line 26 of file copy.h.

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

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

1197 {
1198  CopyFromState cstate;
1199  bool pipe = (filename == NULL);
1200  TupleDesc tupDesc;
1201  AttrNumber num_phys_attrs,
1202  num_defaults;
1203  FmgrInfo *in_functions;
1204  Oid *typioparams;
1205  int attnum;
1206  Oid in_func_oid;
1207  int *defmap;
1208  ExprState **defexprs;
1209  MemoryContext oldcontext;
1210  bool volatile_defexprs;
1211  const int progress_cols[] = {
1215  };
1216  int64 progress_vals[] = {
1218  0,
1219  0
1220  };
1221 
1222  /* Allocate workspace and zero all fields */
1223  cstate = (CopyFromStateData *) palloc0(sizeof(CopyFromStateData));
1224 
1225  /*
1226  * We allocate everything used by a cstate in a new memory context. This
1227  * avoids memory leaks during repeated use of COPY in a query.
1228  */
1230  "COPY",
1232 
1233  oldcontext = MemoryContextSwitchTo(cstate->copycontext);
1234 
1235  /* Extract options from the statement node tree */
1236  ProcessCopyOptions(pstate, &cstate->opts, true /* is_from */ , options);
1237 
1238  /* Process the target relation */
1239  cstate->rel = rel;
1240 
1241  tupDesc = RelationGetDescr(cstate->rel);
1242 
1243  /* process common options or initialization */
1244 
1245  /* Generate or convert list of attributes to process */
1246  cstate->attnumlist = CopyGetAttnums(tupDesc, cstate->rel, attnamelist);
1247 
1248  num_phys_attrs = tupDesc->natts;
1249 
1250  /* Convert FORCE_NOT_NULL name list to per-column flags, check validity */
1251  cstate->opts.force_notnull_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1252  if (cstate->opts.force_notnull)
1253  {
1254  List *attnums;
1255  ListCell *cur;
1256 
1257  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_notnull);
1258 
1259  foreach(cur, attnums)
1260  {
1261  int attnum = lfirst_int(cur);
1262  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1263 
1264  if (!list_member_int(cstate->attnumlist, attnum))
1265  ereport(ERROR,
1266  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1267  errmsg("FORCE_NOT_NULL column \"%s\" not referenced by COPY",
1268  NameStr(attr->attname))));
1269  cstate->opts.force_notnull_flags[attnum - 1] = true;
1270  }
1271  }
1272 
1273  /* Convert FORCE_NULL name list to per-column flags, check validity */
1274  cstate->opts.force_null_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1275  if (cstate->opts.force_null)
1276  {
1277  List *attnums;
1278  ListCell *cur;
1279 
1280  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_null);
1281 
1282  foreach(cur, attnums)
1283  {
1284  int attnum = lfirst_int(cur);
1285  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1286 
1287  if (!list_member_int(cstate->attnumlist, attnum))
1288  ereport(ERROR,
1289  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1290  errmsg("FORCE_NULL column \"%s\" not referenced by COPY",
1291  NameStr(attr->attname))));
1292  cstate->opts.force_null_flags[attnum - 1] = true;
1293  }
1294  }
1295 
1296  /* Convert convert_selectively name list to per-column flags */
1297  if (cstate->opts.convert_selectively)
1298  {
1299  List *attnums;
1300  ListCell *cur;
1301 
1302  cstate->convert_select_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1303 
1304  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.convert_select);
1305 
1306  foreach(cur, attnums)
1307  {
1308  int attnum = lfirst_int(cur);
1309  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1310 
1311  if (!list_member_int(cstate->attnumlist, attnum))
1312  ereport(ERROR,
1313  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1314  errmsg_internal("selected column \"%s\" not referenced by COPY",
1315  NameStr(attr->attname))));
1316  cstate->convert_select_flags[attnum - 1] = true;
1317  }
1318  }
1319 
1320  /* Use client encoding when ENCODING option is not specified. */
1321  if (cstate->opts.file_encoding < 0)
1323  else
1324  cstate->file_encoding = cstate->opts.file_encoding;
1325 
1326  /*
1327  * Look up encoding conversion function.
1328  */
1329  if (cstate->file_encoding == GetDatabaseEncoding() ||
1330  cstate->file_encoding == PG_SQL_ASCII ||
1332  {
1333  cstate->need_transcoding = false;
1334  }
1335  else
1336  {
1337  cstate->need_transcoding = true;
1340  }
1341 
1342  cstate->copy_src = COPY_FILE; /* default */
1343 
1344  cstate->whereClause = whereClause;
1345 
1346  /* Initialize state variables */
1347  cstate->eol_type = EOL_UNKNOWN;
1348  cstate->cur_relname = RelationGetRelationName(cstate->rel);
1349  cstate->cur_lineno = 0;
1350  cstate->cur_attname = NULL;
1351  cstate->cur_attval = NULL;
1352 
1353  /*
1354  * Allocate buffers for the input pipeline.
1355  *
1356  * attribute_buf and raw_buf are used in both text and binary modes, but
1357  * input_buf and line_buf only in text mode.
1358  */
1359  cstate->raw_buf = palloc(RAW_BUF_SIZE + 1);
1360  cstate->raw_buf_index = cstate->raw_buf_len = 0;
1361  cstate->raw_reached_eof = false;
1362 
1363  if (!cstate->opts.binary)
1364  {
1365  /*
1366  * If encoding conversion is needed, we need another buffer to hold
1367  * the converted input data. Otherwise, we can just point input_buf
1368  * to the same buffer as raw_buf.
1369  */
1370  if (cstate->need_transcoding)
1371  {
1372  cstate->input_buf = (char *) palloc(INPUT_BUF_SIZE + 1);
1373  cstate->input_buf_index = cstate->input_buf_len = 0;
1374  }
1375  else
1376  cstate->input_buf = cstate->raw_buf;
1377  cstate->input_reached_eof = false;
1378 
1379  initStringInfo(&cstate->line_buf);
1380  }
1381 
1382  initStringInfo(&cstate->attribute_buf);
1383 
1384  /* Assign range table, we'll need it in CopyFrom. */
1385  if (pstate)
1386  cstate->range_table = pstate->p_rtable;
1387 
1388  tupDesc = RelationGetDescr(cstate->rel);
1389  num_phys_attrs = tupDesc->natts;
1390  num_defaults = 0;
1391  volatile_defexprs = false;
1392 
1393  /*
1394  * Pick up the required catalog information for each attribute in the
1395  * relation, including the input function, the element type (to pass to
1396  * the input function), and info about defaults and constraints. (Which
1397  * input function we use depends on text/binary format choice.)
1398  */
1399  in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
1400  typioparams = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
1401  defmap = (int *) palloc(num_phys_attrs * sizeof(int));
1402  defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *));
1403 
1404  for (attnum = 1; attnum <= num_phys_attrs; attnum++)
1405  {
1406  Form_pg_attribute att = TupleDescAttr(tupDesc, attnum - 1);
1407 
1408  /* We don't need info for dropped attributes */
1409  if (att->attisdropped)
1410  continue;
1411 
1412  /* Fetch the input function and typioparam info */
1413  if (cstate->opts.binary)
1414  getTypeBinaryInputInfo(att->atttypid,
1415  &in_func_oid, &typioparams[attnum - 1]);
1416  else
1417  getTypeInputInfo(att->atttypid,
1418  &in_func_oid, &typioparams[attnum - 1]);
1419  fmgr_info(in_func_oid, &in_functions[attnum - 1]);
1420 
1421  /* Get default info if needed */
1422  if (!list_member_int(cstate->attnumlist, attnum) && !att->attgenerated)
1423  {
1424  /* attribute is NOT to be copied from input */
1425  /* use default value if one exists */
1426  Expr *defexpr = (Expr *) build_column_default(cstate->rel,
1427  attnum);
1428 
1429  if (defexpr != NULL)
1430  {
1431  /* Run the expression through planner */
1432  defexpr = expression_planner(defexpr);
1433 
1434  /* Initialize executable expression in copycontext */
1435  defexprs[num_defaults] = ExecInitExpr(defexpr, NULL);
1436  defmap[num_defaults] = attnum - 1;
1437  num_defaults++;
1438 
1439  /*
1440  * If a default expression looks at the table being loaded,
1441  * then it could give the wrong answer when using
1442  * multi-insert. Since database access can be dynamic this is
1443  * hard to test for exactly, so we use the much wider test of
1444  * whether the default expression is volatile. We allow for
1445  * the special case of when the default expression is the
1446  * nextval() of a sequence which in this specific case is
1447  * known to be safe for use with the multi-insert
1448  * optimization. Hence we use this special case function
1449  * checker rather than the standard check for
1450  * contain_volatile_functions().
1451  */
1452  if (!volatile_defexprs)
1453  volatile_defexprs = contain_volatile_functions_not_nextval((Node *) defexpr);
1454  }
1455  }
1456  }
1457 
1458 
1459  /* initialize progress */
1461  cstate->rel ? RelationGetRelid(cstate->rel) : InvalidOid);
1462  cstate->bytes_processed = 0;
1463 
1464  /* We keep those variables in cstate. */
1465  cstate->in_functions = in_functions;
1466  cstate->typioparams = typioparams;
1467  cstate->defmap = defmap;
1468  cstate->defexprs = defexprs;
1469  cstate->volatile_defexprs = volatile_defexprs;
1470  cstate->num_defaults = num_defaults;
1471  cstate->is_program = is_program;
1472 
1473  if (data_source_cb)
1474  {
1475  progress_vals[1] = PROGRESS_COPY_TYPE_CALLBACK;
1476  cstate->copy_src = COPY_CALLBACK;
1477  cstate->data_source_cb = data_source_cb;
1478  }
1479  else if (pipe)
1480  {
1481  progress_vals[1] = PROGRESS_COPY_TYPE_PIPE;
1482  Assert(!is_program); /* the grammar does not allow this */
1484  ReceiveCopyBegin(cstate);
1485  else
1486  cstate->copy_file = stdin;
1487  }
1488  else
1489  {
1490  cstate->filename = pstrdup(filename);
1491 
1492  if (cstate->is_program)
1493  {
1494  progress_vals[1] = PROGRESS_COPY_TYPE_PROGRAM;
1495  cstate->copy_file = OpenPipeStream(cstate->filename, PG_BINARY_R);
1496  if (cstate->copy_file == NULL)
1497  ereport(ERROR,
1499  errmsg("could not execute command \"%s\": %m",
1500  cstate->filename)));
1501  }
1502  else
1503  {
1504  struct stat st;
1505 
1506  progress_vals[1] = PROGRESS_COPY_TYPE_FILE;
1507  cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_R);
1508  if (cstate->copy_file == NULL)
1509  {
1510  /* copy errno because ereport subfunctions might change it */
1511  int save_errno = errno;
1512 
1513  ereport(ERROR,
1515  errmsg("could not open file \"%s\" for reading: %m",
1516  cstate->filename),
1517  (save_errno == ENOENT || save_errno == EACCES) ?
1518  errhint("COPY FROM instructs the PostgreSQL server process to read a file. "
1519  "You may want a client-side facility such as psql's \\copy.") : 0));
1520  }
1521 
1522  if (fstat(fileno(cstate->copy_file), &st))
1523  ereport(ERROR,
1525  errmsg("could not stat file \"%s\": %m",
1526  cstate->filename)));
1527 
1528  if (S_ISDIR(st.st_mode))
1529  ereport(ERROR,
1530  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1531  errmsg("\"%s\" is a directory", cstate->filename)));
1532 
1533  progress_vals[2] = st.st_size;
1534  }
1535  }
1536 
1537  pgstat_progress_update_multi_param(3, progress_cols, progress_vals);
1538 
1539  if (cstate->opts.binary)
1540  {
1541  /* Read and verify binary header */
1542  ReceiveCopyBinaryHeader(cstate);
1543  }
1544 
1545  /* create workspace for CopyReadAttributes results */
1546  if (!cstate->opts.binary)
1547  {
1548  AttrNumber attr_count = list_length(cstate->attnumlist);
1549 
1550  cstate->max_fields = attr_count;
1551  cstate->raw_fields = (char **) palloc(attr_count * sizeof(char *));
1552  }
1553 
1554  MemoryContextSwitchTo(oldcontext);
1555 
1556  return cstate;
1557 }
int16 AttrNumber
Definition: attnum.h:21
List * CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
Definition: copy.c:708
void ProcessCopyOptions(ParseState *pstate, CopyFormatOptions *opts_out, bool is_from, List *options)
Definition: copy.c:391
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:681
#define PG_BINARY_R
Definition: c.h:1270
bool contain_volatile_functions_not_nextval(Node *clause)
Definition: clauses.c:603
@ COPY_CALLBACK
#define INPUT_BUF_SIZE
@ EOL_UNKNOWN
#define RAW_BUF_SIZE
void ReceiveCopyBinaryHeader(CopyFromState cstate)
void ReceiveCopyBegin(CopyFromState cstate)
@ COPY_FILE
Definition: copyto.c:52
@ DestRemote
Definition: dest.h:91
struct cursor * cur
Definition: ecpg.c:28
int errmsg_internal(const char *fmt,...)
Definition: elog.c:991
int errcode_for_file_access(void)
Definition: elog.c:716
int errhint(const char *fmt,...)
Definition: elog.c:1151
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:160
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2461
FILE * OpenPipeStream(const char *command, const char *mode)
Definition: fd.c:2564
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
Assert(fmt[strlen(fmt) - 1] !='\n')
bool list_member_int(const List *list, int datum)
Definition: list.c:681
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2831
void getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
Definition: lsyscache.c:2897
int GetDatabaseEncoding(void)
Definition: mbutils.c:1210
int pg_get_client_encoding(void)
Definition: mbutils.c:336
char * pstrdup(const char *in)
Definition: mcxt.c:1305
void * palloc0(Size size)
Definition: mcxt.c:1099
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
void * palloc(Size size)
Definition: mcxt.c:1068
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
Oid FindDefaultConversionProc(int32 for_encoding, int32 to_encoding)
Definition: namespace.c:3756
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int16 attnum
Definition: pg_attribute.h:83
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
static char * filename
Definition: pg_dumpall.c:94
static int list_length(const List *l)
Definition: pg_list.h:149
#define lfirst_int(lc)
Definition: pg_list.h:170
@ PG_SQL_ASCII
Definition: pg_wchar.h:224
Expr * expression_planner(Expr *expr)
Definition: planner.c:5882
CommandDest whereToSendOutput
Definition: postgres.c:92
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define PROGRESS_COPY_COMMAND
Definition: progress.h:141
#define PROGRESS_COPY_TYPE_FILE
Definition: progress.h:149
#define PROGRESS_COPY_COMMAND_FROM
Definition: progress.h:145
#define PROGRESS_COPY_TYPE
Definition: progress.h:142
#define PROGRESS_COPY_TYPE_PROGRAM
Definition: progress.h:150
#define PROGRESS_COPY_BYTES_TOTAL
Definition: progress.h:138
#define PROGRESS_COPY_TYPE_CALLBACK
Definition: progress.h:152
#define PROGRESS_COPY_TYPE_PIPE
Definition: progress.h:151
#define RelationGetRelid(relation)
Definition: rel.h:489
#define RelationGetDescr(relation)
Definition: rel.h:515
#define RelationGetRelationName(relation)
Definition: rel.h:523
Node * build_column_default(Relation rel, int attrno)
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
bool binary
Definition: copy.h:43
bool convert_selectively
Definition: copy.h:60
List * force_null
Definition: copy.h:58
List * convert_select
Definition: copy.h:61
bool * force_notnull_flags
Definition: copy.h:57
int file_encoding
Definition: copy.h:41
bool * force_null_flags
Definition: copy.h:59
List * force_notnull
Definition: copy.h:56
ExprState ** defexprs
copy_data_source_cb data_source_cb
StringInfoData line_buf
CopyFormatOptions opts
StringInfoData attribute_buf
MemoryContext copycontext
const char * cur_attval
const char * cur_attname
const char * cur_relname
Definition: fmgr.h:57
Definition: pg_list.h:51
Definition: nodes.h:574
List * p_rtable
Definition: parse_node.h:183
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define S_ISDIR(m)
Definition: win32_port.h:324
#define fstat
Definition: win32_port.h:282

References AllocateFile(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert(), attnum, CopyFromStateData::attnumlist, CopyFromStateData::attribute_buf, CopyFormatOptions::binary, 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, CopyFromStateData::copy_src, CopyFromStateData::copycontext, CopyGetAttnums(), cur, CopyFromStateData::cur_attname, CopyFromStateData::cur_attval, CopyFromStateData::cur_lineno, CopyFromStateData::cur_relname, CurrentMemoryContext, CopyFromStateData::data_source_cb, CopyFromStateData::defexprs, CopyFromStateData::defmap, DestRemote, CopyFromStateData::eol_type, EOL_UNKNOWN, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), errmsg_internal(), ERROR, ExecInitExpr(), expression_planner(), CopyFormatOptions::file_encoding, CopyFromStateData::file_encoding, filename, CopyFromStateData::filename, FindDefaultConversionProc(), fmgr_info(), CopyFormatOptions::force_notnull, CopyFormatOptions::force_notnull_flags, CopyFormatOptions::force_null, CopyFormatOptions::force_null_flags, fstat, GetDatabaseEncoding(), getTypeBinaryInputInfo(), getTypeInputInfo(), CopyFromStateData::in_functions, initStringInfo(), CopyFromStateData::input_buf, CopyFromStateData::input_buf_index, CopyFromStateData::input_buf_len, INPUT_BUF_SIZE, CopyFromStateData::input_reached_eof, InvalidOid, CopyFromStateData::is_program, lfirst_int, CopyFromStateData::line_buf, list_length(), list_member_int(), CopyFromStateData::max_fields, MemoryContextSwitchTo(), NameStr, TupleDescData::natts, CopyFromStateData::need_transcoding, CopyFromStateData::num_defaults, OpenPipeStream(), CopyFromStateData::opts, ParseState::p_rtable, palloc(), palloc0(), PG_BINARY_R, 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_fields, CopyFromStateData::raw_reached_eof, ReceiveCopyBegin(), ReceiveCopyBinaryHeader(), CopyFromStateData::rel, RelationGetDescr, RelationGetRelationName, RelationGetRelid, S_ISDIR, stat::st_mode, stat::st_size, TupleDescAttr, 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 query,
Oid  queryRelId,
const char *  filename,
bool  is_program,
List attnamelist,
List options 
)

Definition at line 341 of file copyto.c.

349 {
350  CopyToState cstate;
351  bool pipe = (filename == NULL);
352  TupleDesc tupDesc;
353  int num_phys_attrs;
354  MemoryContext oldcontext;
355  const int progress_cols[] = {
358  };
359  int64 progress_vals[] = {
361  0
362  };
363 
364  if (rel != NULL && rel->rd_rel->relkind != RELKIND_RELATION)
365  {
366  if (rel->rd_rel->relkind == RELKIND_VIEW)
367  ereport(ERROR,
368  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
369  errmsg("cannot copy from view \"%s\"",
371  errhint("Try the COPY (SELECT ...) TO variant.")));
372  else if (rel->rd_rel->relkind == RELKIND_MATVIEW)
373  ereport(ERROR,
374  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
375  errmsg("cannot copy from materialized view \"%s\"",
377  errhint("Try the COPY (SELECT ...) TO variant.")));
378  else if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
379  ereport(ERROR,
380  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
381  errmsg("cannot copy from foreign table \"%s\"",
383  errhint("Try the COPY (SELECT ...) TO variant.")));
384  else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
385  ereport(ERROR,
386  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
387  errmsg("cannot copy from sequence \"%s\"",
388  RelationGetRelationName(rel))));
389  else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
390  ereport(ERROR,
391  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
392  errmsg("cannot copy from partitioned table \"%s\"",
394  errhint("Try the COPY (SELECT ...) TO variant.")));
395  else
396  ereport(ERROR,
397  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
398  errmsg("cannot copy from non-table relation \"%s\"",
399  RelationGetRelationName(rel))));
400  }
401 
402 
403  /* Allocate workspace and zero all fields */
404  cstate = (CopyToStateData *) palloc0(sizeof(CopyToStateData));
405 
406  /*
407  * We allocate everything used by a cstate in a new memory context. This
408  * avoids memory leaks during repeated use of COPY in a query.
409  */
411  "COPY",
413 
414  oldcontext = MemoryContextSwitchTo(cstate->copycontext);
415 
416  /* Extract options from the statement node tree */
417  ProcessCopyOptions(pstate, &cstate->opts, false /* is_from */ , options);
418 
419  /* Process the source/target relation or query */
420  if (rel)
421  {
422  Assert(!raw_query);
423 
424  cstate->rel = rel;
425 
426  tupDesc = RelationGetDescr(cstate->rel);
427  }
428  else
429  {
430  List *rewritten;
431  Query *query;
432  PlannedStmt *plan;
434 
435  cstate->rel = NULL;
436 
437  /*
438  * Run parse analysis and rewrite. Note this also acquires sufficient
439  * locks on the source table(s).
440  */
441  rewritten = pg_analyze_and_rewrite_fixedparams(raw_query,
442  pstate->p_sourcetext, NULL, 0,
443  NULL);
444 
445  /* check that we got back something we can work with */
446  if (rewritten == NIL)
447  {
448  ereport(ERROR,
449  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
450  errmsg("DO INSTEAD NOTHING rules are not supported for COPY")));
451  }
452  else if (list_length(rewritten) > 1)
453  {
454  ListCell *lc;
455 
456  /* examine queries to determine which error message to issue */
457  foreach(lc, rewritten)
458  {
459  Query *q = lfirst_node(Query, lc);
460 
462  ereport(ERROR,
463  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
464  errmsg("conditional DO INSTEAD rules are not supported for COPY")));
466  ereport(ERROR,
467  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
468  errmsg("DO ALSO rules are not supported for the COPY")));
469  }
470 
471  ereport(ERROR,
472  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
473  errmsg("multi-statement DO INSTEAD rules are not supported for COPY")));
474  }
475 
476  query = linitial_node(Query, rewritten);
477 
478  /* The grammar allows SELECT INTO, but we don't support that */
479  if (query->utilityStmt != NULL &&
481  ereport(ERROR,
482  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
483  errmsg("COPY (SELECT INTO) is not supported")));
484 
485  Assert(query->utilityStmt == NULL);
486 
487  /*
488  * Similarly the grammar doesn't enforce the presence of a RETURNING
489  * clause, but this is required here.
490  */
491  if (query->commandType != CMD_SELECT &&
492  query->returningList == NIL)
493  {
494  Assert(query->commandType == CMD_INSERT ||
495  query->commandType == CMD_UPDATE ||
496  query->commandType == CMD_DELETE);
497 
498  ereport(ERROR,
499  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
500  errmsg("COPY query must have a RETURNING clause")));
501  }
502 
503  /* plan the query */
504  plan = pg_plan_query(query, pstate->p_sourcetext,
505  CURSOR_OPT_PARALLEL_OK, NULL);
506 
507  /*
508  * With row-level security and a user using "COPY relation TO", we
509  * have to convert the "COPY relation TO" to a query-based COPY (eg:
510  * "COPY (SELECT * FROM relation) TO"), to allow the rewriter to add
511  * in any RLS clauses.
512  *
513  * When this happens, we are passed in the relid of the originally
514  * found relation (which we have locked). As the planner will look up
515  * the relation again, we double-check here to make sure it found the
516  * same one that we have locked.
517  */
518  if (queryRelId != InvalidOid)
519  {
520  /*
521  * Note that with RLS involved there may be multiple relations,
522  * and while the one we need is almost certainly first, we don't
523  * make any guarantees of that in the planner, so check the whole
524  * list and make sure we find the original relation.
525  */
526  if (!list_member_oid(plan->relationOids, queryRelId))
527  ereport(ERROR,
528  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
529  errmsg("relation referenced by COPY statement has changed")));
530  }
531 
532  /*
533  * Use a snapshot with an updated command ID to ensure this query sees
534  * results of any previously executed queries.
535  */
538 
539  /* Create dest receiver for COPY OUT */
541  ((DR_copy *) dest)->cstate = cstate;
542 
543  /* Create a QueryDesc requesting no output */
544  cstate->queryDesc = CreateQueryDesc(plan, pstate->p_sourcetext,
547  dest, NULL, NULL, 0);
548 
549  /*
550  * Call ExecutorStart to prepare the plan for execution.
551  *
552  * ExecutorStart computes a result tupdesc for us
553  */
554  ExecutorStart(cstate->queryDesc, 0);
555 
556  tupDesc = cstate->queryDesc->tupDesc;
557  }
558 
559  /* Generate or convert list of attributes to process */
560  cstate->attnumlist = CopyGetAttnums(tupDesc, cstate->rel, attnamelist);
561 
562  num_phys_attrs = tupDesc->natts;
563 
564  /* Convert FORCE_QUOTE name list to per-column flags, check validity */
565  cstate->opts.force_quote_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
566  if (cstate->opts.force_quote_all)
567  {
568  int i;
569 
570  for (i = 0; i < num_phys_attrs; i++)
571  cstate->opts.force_quote_flags[i] = true;
572  }
573  else if (cstate->opts.force_quote)
574  {
575  List *attnums;
576  ListCell *cur;
577 
578  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_quote);
579 
580  foreach(cur, attnums)
581  {
582  int attnum = lfirst_int(cur);
583  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
584 
585  if (!list_member_int(cstate->attnumlist, attnum))
586  ereport(ERROR,
587  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
588  errmsg("FORCE_QUOTE column \"%s\" not referenced by COPY",
589  NameStr(attr->attname))));
590  cstate->opts.force_quote_flags[attnum - 1] = true;
591  }
592  }
593 
594  /* Convert FORCE_NOT_NULL name list to per-column flags, check validity */
595  cstate->opts.force_notnull_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
596  if (cstate->opts.force_notnull)
597  {
598  List *attnums;
599  ListCell *cur;
600 
601  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_notnull);
602 
603  foreach(cur, attnums)
604  {
605  int attnum = lfirst_int(cur);
606  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
607 
608  if (!list_member_int(cstate->attnumlist, attnum))
609  ereport(ERROR,
610  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
611  errmsg("FORCE_NOT_NULL column \"%s\" not referenced by COPY",
612  NameStr(attr->attname))));
613  cstate->opts.force_notnull_flags[attnum - 1] = true;
614  }
615  }
616 
617  /* Convert FORCE_NULL name list to per-column flags, check validity */
618  cstate->opts.force_null_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
619  if (cstate->opts.force_null)
620  {
621  List *attnums;
622  ListCell *cur;
623 
624  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_null);
625 
626  foreach(cur, attnums)
627  {
628  int attnum = lfirst_int(cur);
629  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
630 
631  if (!list_member_int(cstate->attnumlist, attnum))
632  ereport(ERROR,
633  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
634  errmsg("FORCE_NULL column \"%s\" not referenced by COPY",
635  NameStr(attr->attname))));
636  cstate->opts.force_null_flags[attnum - 1] = true;
637  }
638  }
639 
640  /* Use client encoding when ENCODING option is not specified. */
641  if (cstate->opts.file_encoding < 0)
643  else
644  cstate->file_encoding = cstate->opts.file_encoding;
645 
646  /*
647  * Set up encoding conversion info. Even if the file and server encodings
648  * are the same, we must apply pg_any_to_server() to validate data in
649  * multibyte encodings.
650  */
651  cstate->need_transcoding =
652  (cstate->file_encoding != GetDatabaseEncoding() ||
654  /* See Multibyte encoding comment above */
656 
657  cstate->copy_dest = COPY_FILE; /* default */
658 
659  if (pipe)
660  {
661  progress_vals[1] = PROGRESS_COPY_TYPE_PIPE;
662 
663  Assert(!is_program); /* the grammar does not allow this */
665  cstate->copy_file = stdout;
666  }
667  else
668  {
669  cstate->filename = pstrdup(filename);
670  cstate->is_program = is_program;
671 
672  if (is_program)
673  {
674  progress_vals[1] = PROGRESS_COPY_TYPE_PROGRAM;
675  cstate->copy_file = OpenPipeStream(cstate->filename, PG_BINARY_W);
676  if (cstate->copy_file == NULL)
677  ereport(ERROR,
679  errmsg("could not execute command \"%s\": %m",
680  cstate->filename)));
681  }
682  else
683  {
684  mode_t oumask; /* Pre-existing umask value */
685  struct stat st;
686 
687  progress_vals[1] = PROGRESS_COPY_TYPE_FILE;
688 
689  /*
690  * Prevent write to relative path ... too easy to shoot oneself in
691  * the foot by overwriting a database file ...
692  */
694  ereport(ERROR,
695  (errcode(ERRCODE_INVALID_NAME),
696  errmsg("relative path not allowed for COPY to file")));
697 
698  oumask = umask(S_IWGRP | S_IWOTH);
699  PG_TRY();
700  {
701  cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_W);
702  }
703  PG_FINALLY();
704  {
705  umask(oumask);
706  }
707  PG_END_TRY();
708  if (cstate->copy_file == NULL)
709  {
710  /* copy errno because ereport subfunctions might change it */
711  int save_errno = errno;
712 
713  ereport(ERROR,
715  errmsg("could not open file \"%s\" for writing: %m",
716  cstate->filename),
717  (save_errno == ENOENT || save_errno == EACCES) ?
718  errhint("COPY TO instructs the PostgreSQL server process to write a file. "
719  "You may want a client-side facility such as psql's \\copy.") : 0));
720  }
721 
722  if (fstat(fileno(cstate->copy_file), &st))
723  ereport(ERROR,
725  errmsg("could not stat file \"%s\": %m",
726  cstate->filename)));
727 
728  if (S_ISDIR(st.st_mode))
729  ereport(ERROR,
730  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
731  errmsg("\"%s\" is a directory", cstate->filename)));
732  }
733  }
734 
735  /* initialize progress */
737  cstate->rel ? RelationGetRelid(cstate->rel) : InvalidOid);
738  pgstat_progress_update_multi_param(2, progress_cols, progress_vals);
739 
740  cstate->bytes_processed = 0;
741 
742  MemoryContextSwitchTo(oldcontext);
743 
744  return cstate;
745 }
#define PG_BINARY_W
Definition: c.h:1271
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:113
@ DestCopyOut
Definition: dest.h:97
#define PG_END_TRY()
Definition: elog.h:324
#define PG_TRY()
Definition: elog.h:299
#define PG_FINALLY()
Definition: elog.h:316
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:131
int i
Definition: isn.c:73
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:701
int pg_database_encoding_max_length(void)
Definition: mbutils.c:1495
#define IsA(nodeptr, _type_)
Definition: nodes.h:624
@ CMD_INSERT
Definition: nodes.h:723
@ CMD_DELETE
Definition: nodes.h:724
@ CMD_UPDATE
Definition: nodes.h:722
@ CMD_SELECT
Definition: nodes.h:721
@ QSRC_NON_INSTEAD_RULE
Definition: parsenodes.h:46
@ QSRC_QUAL_INSTEAD_RULE
Definition: parsenodes.h:45
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:3177
#define lfirst_node(type, lc)
Definition: pg_list.h:172
#define linitial_node(type, l)
Definition: pg_list.h:177
#define NIL
Definition: pg_list.h:65
#define PG_ENCODING_IS_CLIENT_ONLY(_enc)
Definition: pg_wchar.h:282
#define is_absolute_path(filename)
Definition: port.h:89
List * pg_analyze_and_rewrite_fixedparams(RawStmt *parsetree, const char *query_string, const Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
Definition: postgres.c:640
PlannedStmt * pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, ParamListInfo boundParams)
Definition: postgres.c:865
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
Definition: pquery.c:67
#define PROGRESS_COPY_COMMAND_TO
Definition: progress.h:146
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:745
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:733
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:803
#define InvalidSnapshot
Definition: snapshot.h:123
bool force_quote_all
Definition: copy.h:54
List * force_quote
Definition: copy.h:53
bool * force_quote_flags
Definition: copy.h:55
MemoryContext copycontext
Definition: copyto.c:95
Relation rel
Definition: copyto.c:83
bool encoding_embeds_ascii
Definition: copyto.c:80
CopyDest copy_dest
Definition: copyto.c:74
bool need_transcoding
Definition: copyto.c:79
bool is_program
Definition: copyto.c:87
FILE * copy_file
Definition: copyto.c:75
int file_encoding
Definition: copyto.c:78
CopyFormatOptions opts
Definition: copyto.c:89
uint64 bytes_processed
Definition: copyto.c:99
char * filename
Definition: copyto.c:86
List * attnumlist
Definition: copyto.c:85
QueryDesc * queryDesc
Definition: copyto.c:84
const char * p_sourcetext
Definition: parse_node.h:182
List * relationOids
Definition: plannodes.h:81
TupleDesc tupDesc
Definition: execdesc.h:47
List * returningList
Definition: parsenodes.h:161
QuerySource querySource
Definition: parsenodes.h:123
CmdType commandType
Definition: parsenodes.h:121
Node * utilityStmt
Definition: parsenodes.h:129
Form_pg_class rd_rel
Definition: rel.h:109
#define S_IWOTH
Definition: win32_port.h:315
#define S_IWGRP
Definition: win32_port.h:303

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

Referenced by DoCopy().

◆ CopyFrom()

uint64 CopyFrom ( CopyFromState  cstate)

Definition at line 528 of file copyfrom.c.

529 {
530  ResultRelInfo *resultRelInfo;
531  ResultRelInfo *target_resultRelInfo;
532  ResultRelInfo *prevResultRelInfo = NULL;
533  EState *estate = CreateExecutorState(); /* for ExecConstraints() */
534  ModifyTableState *mtstate;
535  ExprContext *econtext;
536  TupleTableSlot *singleslot = NULL;
537  MemoryContext oldcontext = CurrentMemoryContext;
538 
539  PartitionTupleRouting *proute = NULL;
540  ErrorContextCallback errcallback;
541  CommandId mycid = GetCurrentCommandId(true);
542  int ti_options = 0; /* start with default options for insert */
543  BulkInsertState bistate = NULL;
544  CopyInsertMethod insertMethod;
545  CopyMultiInsertInfo multiInsertInfo = {0}; /* pacify compiler */
546  int64 processed = 0;
547  int64 excluded = 0;
548  bool has_before_insert_row_trig;
549  bool has_instead_insert_row_trig;
550  bool leafpart_use_multi_insert = false;
551 
552  Assert(cstate->rel);
553  Assert(list_length(cstate->range_table) == 1);
554 
555  /*
556  * The target must be a plain, foreign, or partitioned relation, or have
557  * an INSTEAD OF INSERT row trigger. (Currently, such triggers are only
558  * allowed on views, so we only hint about them in the view case.)
559  */
560  if (cstate->rel->rd_rel->relkind != RELKIND_RELATION &&
561  cstate->rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
562  cstate->rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE &&
563  !(cstate->rel->trigdesc &&
565  {
566  if (cstate->rel->rd_rel->relkind == RELKIND_VIEW)
567  ereport(ERROR,
568  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
569  errmsg("cannot copy to view \"%s\"",
570  RelationGetRelationName(cstate->rel)),
571  errhint("To enable copying to a view, provide an INSTEAD OF INSERT trigger.")));
572  else if (cstate->rel->rd_rel->relkind == RELKIND_MATVIEW)
573  ereport(ERROR,
574  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
575  errmsg("cannot copy to materialized view \"%s\"",
576  RelationGetRelationName(cstate->rel))));
577  else if (cstate->rel->rd_rel->relkind == RELKIND_SEQUENCE)
578  ereport(ERROR,
579  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
580  errmsg("cannot copy to sequence \"%s\"",
581  RelationGetRelationName(cstate->rel))));
582  else
583  ereport(ERROR,
584  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
585  errmsg("cannot copy to non-table relation \"%s\"",
586  RelationGetRelationName(cstate->rel))));
587  }
588 
589  /*
590  * If the target file is new-in-transaction, we assume that checking FSM
591  * for free space is a waste of time. This could possibly be wrong, but
592  * it's unlikely.
593  */
594  if (RELKIND_HAS_STORAGE(cstate->rel->rd_rel->relkind) &&
597  ti_options |= TABLE_INSERT_SKIP_FSM;
598 
599  /*
600  * Optimize if new relfilenode was created in this subxact or one of its
601  * committed children and we won't see those rows later as part of an
602  * earlier scan or command. The subxact test ensures that if this subxact
603  * aborts then the frozen rows won't be visible after xact cleanup. Note
604  * that the stronger test of exactly which subtransaction created it is
605  * crucial for correctness of this optimization. The test for an earlier
606  * scan or command tolerates false negatives. FREEZE causes other sessions
607  * to see rows they would not see under MVCC, and a false negative merely
608  * spreads that anomaly to the current session.
609  */
610  if (cstate->opts.freeze)
611  {
612  /*
613  * We currently disallow COPY FREEZE on partitioned tables. The
614  * reason for this is that we've simply not yet opened the partitions
615  * to determine if the optimization can be applied to them. We could
616  * go and open them all here, but doing so may be quite a costly
617  * overhead for small copies. In any case, we may just end up routing
618  * tuples to a small number of partitions. It seems better just to
619  * raise an ERROR for partitioned tables.
620  */
621  if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
622  {
623  ereport(ERROR,
624  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
625  errmsg("cannot perform COPY FREEZE on a partitioned table")));
626  }
627 
628  /*
629  * Tolerate one registration for the benefit of FirstXactSnapshot.
630  * Scan-bearing queries generally create at least two registrations,
631  * though relying on that is fragile, as is ignoring ActiveSnapshot.
632  * Clear CatalogSnapshot to avoid counting its registration. We'll
633  * still detect ongoing catalog scans, each of which separately
634  * registers the snapshot it uses.
635  */
638  ereport(ERROR,
639  (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
640  errmsg("cannot perform COPY FREEZE because of prior transaction activity")));
641 
642  if (cstate->rel->rd_createSubid != GetCurrentSubTransactionId() &&
644  ereport(ERROR,
645  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
646  errmsg("cannot perform COPY FREEZE because the table was not created or truncated in the current subtransaction")));
647 
648  ti_options |= TABLE_INSERT_FROZEN;
649  }
650 
651  /*
652  * We need a ResultRelInfo so we can use the regular executor's
653  * index-entry-making machinery. (There used to be a huge amount of code
654  * here that basically duplicated execUtils.c ...)
655  */
656  ExecInitRangeTable(estate, cstate->range_table);
657  resultRelInfo = target_resultRelInfo = makeNode(ResultRelInfo);
658  ExecInitResultRelation(estate, resultRelInfo, 1);
659 
660  /* Verify the named relation is a valid target for INSERT */
661  CheckValidResultRel(resultRelInfo, CMD_INSERT);
662 
663  ExecOpenIndices(resultRelInfo, false);
664 
665  /*
666  * Set up a ModifyTableState so we can let FDW(s) init themselves for
667  * foreign-table result relation(s).
668  */
669  mtstate = makeNode(ModifyTableState);
670  mtstate->ps.plan = NULL;
671  mtstate->ps.state = estate;
672  mtstate->operation = CMD_INSERT;
673  mtstate->mt_nrels = 1;
674  mtstate->resultRelInfo = resultRelInfo;
675  mtstate->rootResultRelInfo = resultRelInfo;
676 
677  if (resultRelInfo->ri_FdwRoutine != NULL &&
678  resultRelInfo->ri_FdwRoutine->BeginForeignInsert != NULL)
679  resultRelInfo->ri_FdwRoutine->BeginForeignInsert(mtstate,
680  resultRelInfo);
681 
682  /* Prepare to catch AFTER triggers. */
684 
685  /*
686  * If there are any triggers with transition tables on the named relation,
687  * we need to be prepared to capture transition tuples.
688  *
689  * Because partition tuple routing would like to know about whether
690  * transition capture is active, we also set it in mtstate, which is
691  * passed to ExecFindPartition() below.
692  */
693  cstate->transition_capture = mtstate->mt_transition_capture =
695  RelationGetRelid(cstate->rel),
696  CMD_INSERT);
697 
698  /*
699  * If the named relation is a partitioned table, initialize state for
700  * CopyFrom tuple routing.
701  */
702  if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
703  proute = ExecSetupPartitionTupleRouting(estate, cstate->rel);
704 
705  if (cstate->whereClause)
706  cstate->qualexpr = ExecInitQual(castNode(List, cstate->whereClause),
707  &mtstate->ps);
708 
709  /*
710  * It's generally more efficient to prepare a bunch of tuples for
711  * insertion, and insert them in one table_multi_insert() call, than call
712  * table_tuple_insert() separately for every tuple. However, there are a
713  * number of reasons why we might not be able to do this. These are
714  * explained below.
715  */
716  if (resultRelInfo->ri_TrigDesc != NULL &&
717  (resultRelInfo->ri_TrigDesc->trig_insert_before_row ||
718  resultRelInfo->ri_TrigDesc->trig_insert_instead_row))
719  {
720  /*
721  * Can't support multi-inserts when there are any BEFORE/INSTEAD OF
722  * triggers on the table. Such triggers might query the table we're
723  * inserting into and act differently if the tuples that have already
724  * been processed and prepared for insertion are not there.
725  */
726  insertMethod = CIM_SINGLE;
727  }
728  else if (proute != NULL && resultRelInfo->ri_TrigDesc != NULL &&
729  resultRelInfo->ri_TrigDesc->trig_insert_new_table)
730  {
731  /*
732  * For partitioned tables we can't support multi-inserts when there
733  * are any statement level insert triggers. It might be possible to
734  * allow partitioned tables with such triggers in the future, but for
735  * now, CopyMultiInsertInfoFlush expects that any before row insert
736  * and statement level insert triggers are on the same relation.
737  */
738  insertMethod = CIM_SINGLE;
739  }
740  else if (resultRelInfo->ri_FdwRoutine != NULL ||
741  cstate->volatile_defexprs)
742  {
743  /*
744  * Can't support multi-inserts to foreign tables or if there are any
745  * volatile default expressions in the table. Similarly to the
746  * trigger case above, such expressions may query the table we're
747  * inserting into.
748  *
749  * Note: It does not matter if any partitions have any volatile
750  * default expressions as we use the defaults from the target of the
751  * COPY command.
752  */
753  insertMethod = CIM_SINGLE;
754  }
755  else if (contain_volatile_functions(cstate->whereClause))
756  {
757  /*
758  * Can't support multi-inserts if there are any volatile function
759  * expressions in WHERE clause. Similarly to the trigger case above,
760  * such expressions may query the table we're inserting into.
761  */
762  insertMethod = CIM_SINGLE;
763  }
764  else
765  {
766  /*
767  * For partitioned tables, we may still be able to perform bulk
768  * inserts. However, the possibility of this depends on which types
769  * of triggers exist on the partition. We must disable bulk inserts
770  * if the partition is a foreign table or it has any before row insert
771  * or insert instead triggers (same as we checked above for the parent
772  * table). Since the partition's resultRelInfos are initialized only
773  * when we actually need to insert the first tuple into them, we must
774  * have the intermediate insert method of CIM_MULTI_CONDITIONAL to
775  * flag that we must later determine if we can use bulk-inserts for
776  * the partition being inserted into.
777  */
778  if (proute)
779  insertMethod = CIM_MULTI_CONDITIONAL;
780  else
781  insertMethod = CIM_MULTI;
782 
783  CopyMultiInsertInfoInit(&multiInsertInfo, resultRelInfo, cstate,
784  estate, mycid, ti_options);
785  }
786 
787  /*
788  * If not using batch mode (which allocates slots as needed) set up a
789  * tuple slot too. When inserting into a partitioned table, we also need
790  * one, even if we might batch insert, to read the tuple in the root
791  * partition's form.
792  */
793  if (insertMethod == CIM_SINGLE || insertMethod == CIM_MULTI_CONDITIONAL)
794  {
795  singleslot = table_slot_create(resultRelInfo->ri_RelationDesc,
796  &estate->es_tupleTable);
797  bistate = GetBulkInsertState();
798  }
799 
800  has_before_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
801  resultRelInfo->ri_TrigDesc->trig_insert_before_row);
802 
803  has_instead_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
804  resultRelInfo->ri_TrigDesc->trig_insert_instead_row);
805 
806  /*
807  * Check BEFORE STATEMENT insertion triggers. It's debatable whether we
808  * should do this for COPY, since it's not really an "INSERT" statement as
809  * such. However, executing these triggers maintains consistency with the
810  * EACH ROW triggers that we already fire on COPY.
811  */
812  ExecBSInsertTriggers(estate, resultRelInfo);
813 
814  econtext = GetPerTupleExprContext(estate);
815 
816  /* Set up callback to identify error line number */
817  errcallback.callback = CopyFromErrorCallback;
818  errcallback.arg = (void *) cstate;
819  errcallback.previous = error_context_stack;
820  error_context_stack = &errcallback;
821 
822  for (;;)
823  {
824  TupleTableSlot *myslot;
825  bool skip_tuple;
826 
828 
829  /*
830  * Reset the per-tuple exprcontext. We do this after every tuple, to
831  * clean-up after expression evaluations etc.
832  */
833  ResetPerTupleExprContext(estate);
834 
835  /* select slot to (initially) load row into */
836  if (insertMethod == CIM_SINGLE || proute)
837  {
838  myslot = singleslot;
839  Assert(myslot != NULL);
840  }
841  else
842  {
843  Assert(resultRelInfo == target_resultRelInfo);
844  Assert(insertMethod == CIM_MULTI);
845 
846  myslot = CopyMultiInsertInfoNextFreeSlot(&multiInsertInfo,
847  resultRelInfo);
848  }
849 
850  /*
851  * Switch to per-tuple context before calling NextCopyFrom, which does
852  * evaluate default expressions etc. and requires per-tuple context.
853  */
855 
856  ExecClearTuple(myslot);
857 
858  /* Directly store the values/nulls array in the slot */
859  if (!NextCopyFrom(cstate, econtext, myslot->tts_values, myslot->tts_isnull))
860  break;
861 
862  ExecStoreVirtualTuple(myslot);
863 
864  /*
865  * Constraints and where clause might reference the tableoid column,
866  * so (re-)initialize tts_tableOid before evaluating them.
867  */
868  myslot->tts_tableOid = RelationGetRelid(target_resultRelInfo->ri_RelationDesc);
869 
870  /* Triggers and stuff need to be invoked in query context. */
871  MemoryContextSwitchTo(oldcontext);
872 
873  if (cstate->whereClause)
874  {
875  econtext->ecxt_scantuple = myslot;
876  /* Skip items that don't match COPY's WHERE clause */
877  if (!ExecQual(cstate->qualexpr, econtext))
878  {
879  /*
880  * Report that this tuple was filtered out by the WHERE
881  * clause.
882  */
884  ++excluded);
885  continue;
886  }
887  }
888 
889  /* Determine the partition to insert the tuple into */
890  if (proute)
891  {
892  TupleConversionMap *map;
893 
894  /*
895  * Attempt to find a partition suitable for this tuple.
896  * ExecFindPartition() will raise an error if none can be found or
897  * if the found partition is not suitable for INSERTs.
898  */
899  resultRelInfo = ExecFindPartition(mtstate, target_resultRelInfo,
900  proute, myslot, estate);
901 
902  if (prevResultRelInfo != resultRelInfo)
903  {
904  /* Determine which triggers exist on this partition */
905  has_before_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
906  resultRelInfo->ri_TrigDesc->trig_insert_before_row);
907 
908  has_instead_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
909  resultRelInfo->ri_TrigDesc->trig_insert_instead_row);
910 
911  /*
912  * Disable multi-inserts when the partition has BEFORE/INSTEAD
913  * OF triggers, or if the partition is a foreign partition.
914  */
915  leafpart_use_multi_insert = insertMethod == CIM_MULTI_CONDITIONAL &&
916  !has_before_insert_row_trig &&
917  !has_instead_insert_row_trig &&
918  resultRelInfo->ri_FdwRoutine == NULL;
919 
920  /* Set the multi-insert buffer to use for this partition. */
921  if (leafpart_use_multi_insert)
922  {
923  if (resultRelInfo->ri_CopyMultiInsertBuffer == NULL)
924  CopyMultiInsertInfoSetupBuffer(&multiInsertInfo,
925  resultRelInfo);
926  }
927  else if (insertMethod == CIM_MULTI_CONDITIONAL &&
928  !CopyMultiInsertInfoIsEmpty(&multiInsertInfo))
929  {
930  /*
931  * Flush pending inserts if this partition can't use
932  * batching, so rows are visible to triggers etc.
933  */
934  CopyMultiInsertInfoFlush(&multiInsertInfo, resultRelInfo);
935  }
936 
937  if (bistate != NULL)
938  ReleaseBulkInsertStatePin(bistate);
939  prevResultRelInfo = resultRelInfo;
940  }
941 
942  /*
943  * If we're capturing transition tuples, we might need to convert
944  * from the partition rowtype to root rowtype. But if there are no
945  * BEFORE triggers on the partition that could change the tuple,
946  * we can just remember the original unconverted tuple to avoid a
947  * needless round trip conversion.
948  */
949  if (cstate->transition_capture != NULL)
951  !has_before_insert_row_trig ? myslot : NULL;
952 
953  /*
954  * We might need to convert from the root rowtype to the partition
955  * rowtype.
956  */
957  map = resultRelInfo->ri_RootToPartitionMap;
958  if (insertMethod == CIM_SINGLE || !leafpart_use_multi_insert)
959  {
960  /* non batch insert */
961  if (map != NULL)
962  {
963  TupleTableSlot *new_slot;
964 
965  new_slot = resultRelInfo->ri_PartitionTupleSlot;
966  myslot = execute_attr_map_slot(map->attrMap, myslot, new_slot);
967  }
968  }
969  else
970  {
971  /*
972  * Prepare to queue up tuple for later batch insert into
973  * current partition.
974  */
975  TupleTableSlot *batchslot;
976 
977  /* no other path available for partitioned table */
978  Assert(insertMethod == CIM_MULTI_CONDITIONAL);
979 
980  batchslot = CopyMultiInsertInfoNextFreeSlot(&multiInsertInfo,
981  resultRelInfo);
982 
983  if (map != NULL)
984  myslot = execute_attr_map_slot(map->attrMap, myslot,
985  batchslot);
986  else
987  {
988  /*
989  * This looks more expensive than it is (Believe me, I
990  * optimized it away. Twice.). The input is in virtual
991  * form, and we'll materialize the slot below - for most
992  * slot types the copy performs the work materialization
993  * would later require anyway.
994  */
995  ExecCopySlot(batchslot, myslot);
996  myslot = batchslot;
997  }
998  }
999 
1000  /* ensure that triggers etc see the right relation */
1001  myslot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
1002  }
1003 
1004  skip_tuple = false;
1005 
1006  /* BEFORE ROW INSERT Triggers */
1007  if (has_before_insert_row_trig)
1008  {
1009  if (!ExecBRInsertTriggers(estate, resultRelInfo, myslot))
1010  skip_tuple = true; /* "do nothing" */
1011  }
1012 
1013  if (!skip_tuple)
1014  {
1015  /*
1016  * If there is an INSTEAD OF INSERT ROW trigger, let it handle the
1017  * tuple. Otherwise, proceed with inserting the tuple into the
1018  * table or foreign table.
1019  */
1020  if (has_instead_insert_row_trig)
1021  {
1022  ExecIRInsertTriggers(estate, resultRelInfo, myslot);
1023  }
1024  else
1025  {
1026  /* Compute stored generated columns */
1027  if (resultRelInfo->ri_RelationDesc->rd_att->constr &&
1029  ExecComputeStoredGenerated(resultRelInfo, estate, myslot,
1030  CMD_INSERT);
1031 
1032  /*
1033  * If the target is a plain table, check the constraints of
1034  * the tuple.
1035  */
1036  if (resultRelInfo->ri_FdwRoutine == NULL &&
1037  resultRelInfo->ri_RelationDesc->rd_att->constr)
1038  ExecConstraints(resultRelInfo, myslot, estate);
1039 
1040  /*
1041  * Also check the tuple against the partition constraint, if
1042  * there is one; except that if we got here via tuple-routing,
1043  * we don't need to if there's no BR trigger defined on the
1044  * partition.
1045  */
1046  if (resultRelInfo->ri_RelationDesc->rd_rel->relispartition &&
1047  (proute == NULL || has_before_insert_row_trig))
1048  ExecPartitionCheck(resultRelInfo, myslot, estate, true);
1049 
1050  /* Store the slot in the multi-insert buffer, when enabled. */
1051  if (insertMethod == CIM_MULTI || leafpart_use_multi_insert)
1052  {
1053  /*
1054  * The slot previously might point into the per-tuple
1055  * context. For batching it needs to be longer lived.
1056  */
1057  ExecMaterializeSlot(myslot);
1058 
1059  /* Add this tuple to the tuple buffer */
1060  CopyMultiInsertInfoStore(&multiInsertInfo,
1061  resultRelInfo, myslot,
1062  cstate->line_buf.len,
1063  cstate->cur_lineno);
1064 
1065  /*
1066  * If enough inserts have queued up, then flush all
1067  * buffers out to their tables.
1068  */
1069  if (CopyMultiInsertInfoIsFull(&multiInsertInfo))
1070  CopyMultiInsertInfoFlush(&multiInsertInfo, resultRelInfo);
1071  }
1072  else
1073  {
1074  List *recheckIndexes = NIL;
1075 
1076  /* OK, store the tuple */
1077  if (resultRelInfo->ri_FdwRoutine != NULL)
1078  {
1079  myslot = resultRelInfo->ri_FdwRoutine->ExecForeignInsert(estate,
1080  resultRelInfo,
1081  myslot,
1082  NULL);
1083 
1084  if (myslot == NULL) /* "do nothing" */
1085  continue; /* next tuple please */
1086 
1087  /*
1088  * AFTER ROW Triggers might reference the tableoid
1089  * column, so (re-)initialize tts_tableOid before
1090  * evaluating them.
1091  */
1092  myslot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
1093  }
1094  else
1095  {
1096  /* OK, store the tuple and create index entries for it */
1097  table_tuple_insert(resultRelInfo->ri_RelationDesc,
1098  myslot, mycid, ti_options, bistate);
1099 
1100  if (resultRelInfo->ri_NumIndices > 0)
1101  recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
1102  myslot,
1103  estate,
1104  false,
1105  false,
1106  NULL,
1107  NIL);
1108  }
1109 
1110  /* AFTER ROW INSERT Triggers */
1111  ExecARInsertTriggers(estate, resultRelInfo, myslot,
1112  recheckIndexes, cstate->transition_capture);
1113 
1114  list_free(recheckIndexes);
1115  }
1116  }
1117 
1118  /*
1119  * We count only tuples not suppressed by a BEFORE INSERT trigger
1120  * or FDW; this is the same definition used by nodeModifyTable.c
1121  * for counting tuples inserted by an INSERT command. Update
1122  * progress of the COPY command as well.
1123  */
1125  ++processed);
1126  }
1127  }
1128 
1129  /* Flush any remaining buffered tuples */
1130  if (insertMethod != CIM_SINGLE)
1131  {
1132  if (!CopyMultiInsertInfoIsEmpty(&multiInsertInfo))
1133  CopyMultiInsertInfoFlush(&multiInsertInfo, NULL);
1134  }
1135 
1136  /* Done, clean up */
1137  error_context_stack = errcallback.previous;
1138 
1139  if (bistate != NULL)
1140  FreeBulkInsertState(bistate);
1141 
1142  MemoryContextSwitchTo(oldcontext);
1143 
1144  /* Execute AFTER STATEMENT insertion triggers */
1145  ExecASInsertTriggers(estate, target_resultRelInfo, cstate->transition_capture);
1146 
1147  /* Handle queued AFTER triggers */
1148  AfterTriggerEndQuery(estate);
1149 
1150  ExecResetTupleTable(estate->es_tupleTable, false);
1151 
1152  /* Allow the FDW to shut down */
1153  if (target_resultRelInfo->ri_FdwRoutine != NULL &&
1154  target_resultRelInfo->ri_FdwRoutine->EndForeignInsert != NULL)
1155  target_resultRelInfo->ri_FdwRoutine->EndForeignInsert(estate,
1156  target_resultRelInfo);
1157 
1158  /* Tear down the multi-insert buffer data */
1159  if (insertMethod != CIM_SINGLE)
1160  CopyMultiInsertInfoCleanup(&multiInsertInfo);
1161 
1162  /* Close all the partitioned tables, leaf partitions, and their indices */
1163  if (proute)
1164  ExecCleanupTupleRouting(mtstate, proute);
1165 
1166  /* Close the result relations, including any trigger target relations */
1167  ExecCloseResultRelations(estate);
1169 
1170  FreeExecutorState(estate);
1171 
1172  return processed;
1173 }
void pgstat_progress_update_param(int index, int64 val)
#define InvalidSubTransactionId
Definition: c.h:593
uint32 CommandId
Definition: c.h:601
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:496
static void CopyMultiInsertInfoSetupBuffer(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri)
Definition: copyfrom.c:235
static void CopyMultiInsertInfoInit(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri, CopyFromState cstate, EState *estate, CommandId mycid, int ti_options)
Definition: copyfrom.c:255
static void CopyMultiInsertInfoStore(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri, TupleTableSlot *slot, int tuplen, uint64 lineno)
Definition: copyfrom.c:505
static void CopyMultiInsertInfoCleanup(CopyMultiInsertInfo *miinfo)
Definition: copyfrom.c:467
static bool CopyMultiInsertInfoIsFull(CopyMultiInsertInfo *miinfo)
Definition: copyfrom.c:280
static TupleTableSlot * CopyMultiInsertInfoNextFreeSlot(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri)
Definition: copyfrom.c:486
static void CopyMultiInsertInfoFlush(CopyMultiInsertInfo *miinfo, ResultRelInfo *curr_rri)
Definition: copyfrom.c:421
static bool CopyMultiInsertInfoIsEmpty(CopyMultiInsertInfo *miinfo)
Definition: copyfrom.c:292
void CopyFromErrorCallback(void *arg)
Definition: copyfrom.c:115
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:93
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:209
List * ExecInsertIndexTuples(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool update, bool noDupErr, bool *specConflict, List *arbiterIndexes)
Definition: execIndexing.c:284
void ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative)
Definition: execIndexing.c:156
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
Definition: execMain.c:1782
void ExecCloseResultRelations(EState *estate)
Definition: execMain.c:1507
void ExecCloseRangeTableRelations(EState *estate)
Definition: execMain.c:1567
void ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1906
void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation)
Definition: execMain.c:994
ResultRelInfo * ExecFindPartition(ModifyTableState *mtstate, ResultRelInfo *rootResultRelInfo, PartitionTupleRouting *proute, TupleTableSlot *slot, EState *estate)
PartitionTupleRouting * ExecSetupPartitionTupleRouting(EState *estate, Relation rel)
void ExecCleanupTupleRouting(ModifyTableState *mtstate, PartitionTupleRouting *proute)
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:1191
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1552
void ExecInitRangeTable(EState *estate, List *rangeTable)
Definition: execUtils.c:751
void ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo, Index rti)
Definition: execUtils.c:834
EState * CreateExecutorState(void)
Definition: execUtils.c:90
void FreeExecutorState(EState *estate)
Definition: execUtils.c:186
#define ResetPerTupleExprContext(estate)
Definition: executor.h:546
#define GetPerTupleExprContext(estate)
Definition: executor.h:537
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:542
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:400
void ReleaseBulkInsertStatePin(BulkInsertState bistate)
Definition: heapam.c:1999
BulkInsertState GetBulkInsertState(void)
Definition: heapam.c:1973
void FreeBulkInsertState(BulkInsertState bistate)
Definition: heapam.c:1987
void list_free(List *list)
Definition: list.c:1505
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
void ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo, EState *estate, TupleTableSlot *slot, CmdType cmdtype)
#define makeNode(_type_)
Definition: nodes.h:621
#define castNode(_type_, nodeptr)
Definition: nodes.h:642
bool ThereAreNoReadyPortals(void)
Definition: portalmem.c:1171
#define PROGRESS_COPY_TUPLES_PROCESSED
Definition: progress.h:139
#define PROGRESS_COPY_TUPLES_EXCLUDED
Definition: progress.h:140
bool ThereAreNoPriorRegisteredSnapshots(void)
Definition: snapmgr.c:1621
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:456
bool freeze
Definition: copy.h:44
TransitionCaptureState * transition_capture
List * es_tupleTable
Definition: execnodes.h:634
struct ErrorContextCallback * previous
Definition: elog.h:232
void(* callback)(void *arg)
Definition: elog.h:233
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:232
EndForeignInsert_function EndForeignInsert
Definition: fdwapi.h:239
BeginForeignInsert_function BeginForeignInsert
Definition: fdwapi.h:238
ExecForeignInsert_function ExecForeignInsert
Definition: fdwapi.h:232
CmdType operation
Definition: execnodes.h:1226
ResultRelInfo * resultRelInfo
Definition: execnodes.h:1230
PlanState ps
Definition: execnodes.h:1225
ResultRelInfo * rootResultRelInfo
Definition: execnodes.h:1238
struct TransitionCaptureState * mt_transition_capture
Definition: execnodes.h:1264
Plan * plan
Definition: execnodes.h:998
EState * state
Definition: execnodes.h:1000
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:103
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
TriggerDesc * trigdesc
Definition: rel.h:115
TupleDesc rd_att
Definition: rel.h:110
SubTransactionId rd_createSubid
Definition: rel.h:102
TupleTableSlot * ri_PartitionTupleSlot
Definition: execnodes.h:540
int ri_NumIndices
Definition: execnodes.h:436
Relation ri_RelationDesc
Definition: execnodes.h:433
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition: execnodes.h:552
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:460
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:477
TupleConversionMap * ri_RootToPartitionMap
Definition: execnodes.h:539
TupleTableSlot * tcs_original_insert_tuple
Definition: trigger.h:76
bool trig_insert_instead_row
Definition: reltrigger.h:58
bool trig_insert_new_table
Definition: reltrigger.h:75
bool trig_insert_before_row
Definition: reltrigger.h:56
bool has_generated_stored
Definition: tupdesc.h:45
AttrMap * attrMap
Definition: tupconvert.h:28
TupleConstr * constr
Definition: tupdesc.h:85
Oid tts_tableOid
Definition: tuptable.h:131
bool * tts_isnull
Definition: tuptable.h:128
Datum * tts_values
Definition: tuptable.h:126
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition: tableam.c:91
#define TABLE_INSERT_FROZEN
Definition: tableam.h:237
#define TABLE_INSERT_SKIP_FSM
Definition: tableam.h:236
static void table_tuple_insert(Relation rel, TupleTableSlot *slot, CommandId cid, int options, struct BulkInsertStateData *bistate)
Definition: tableam.h:1373
void ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2408
bool ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2472
bool ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2565
void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot, List *recheckIndexes, TransitionCaptureState *transition_capture)
Definition: trigger.c:2548
TransitionCaptureState * MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType)
Definition: trigger.c:4825
void ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo, TransitionCaptureState *transition_capture)
Definition: trigger.c:2459
void AfterTriggerEndQuery(EState *estate)
Definition: trigger.c:4981
void AfterTriggerBeginQuery(void)
Definition: trigger.c:4961
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition: tupconvert.c:177
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: tuptable.h:475
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition: tuptable.h:443
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:776
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:814

References AfterTriggerBeginQuery(), AfterTriggerEndQuery(), ErrorContextCallback::arg, Assert(), TupleConversionMap::attrMap, FdwRoutine::BeginForeignInsert, ErrorContextCallback::callback, castNode, CHECK_FOR_INTERRUPTS, CheckValidResultRel(), CIM_MULTI, CIM_MULTI_CONDITIONAL, CIM_SINGLE, CMD_INSERT, TupleDescData::constr, contain_volatile_functions(), CopyFromErrorCallback(), CopyMultiInsertInfoCleanup(), CopyMultiInsertInfoFlush(), CopyMultiInsertInfoInit(), CopyMultiInsertInfoIsEmpty(), CopyMultiInsertInfoIsFull(), CopyMultiInsertInfoNextFreeSlot(), CopyMultiInsertInfoSetupBuffer(), CopyMultiInsertInfoStore(), CreateExecutorState(), CopyFromStateData::cur_lineno, CurrentMemoryContext, ExprContext::ecxt_scantuple, FdwRoutine::EndForeignInsert, ereport, errcode(), errhint(), errmsg(), ERROR, error_context_stack, EState::es_tupleTable, ExecARInsertTriggers(), ExecASInsertTriggers(), ExecBRInsertTriggers(), ExecBSInsertTriggers(), ExecCleanupTupleRouting(), ExecClearTuple(), ExecCloseRangeTableRelations(), ExecCloseResultRelations(), ExecComputeStoredGenerated(), ExecConstraints(), ExecCopySlot(), ExecFindPartition(), FdwRoutine::ExecForeignInsert, ExecInitQual(), ExecInitRangeTable(), ExecInitResultRelation(), ExecInsertIndexTuples(), ExecIRInsertTriggers(), ExecMaterializeSlot(), ExecOpenIndices(), ExecPartitionCheck(), ExecQual(), ExecResetTupleTable(), ExecSetupPartitionTupleRouting(), ExecStoreVirtualTuple(), execute_attr_map_slot(), FreeBulkInsertState(), FreeExecutorState(), CopyFormatOptions::freeze, GetBulkInsertState(), GetCurrentCommandId(), GetCurrentSubTransactionId(), GetPerTupleExprContext, GetPerTupleMemoryContext, TupleConstr::has_generated_stored, InvalidateCatalogSnapshot(), InvalidSubTransactionId, StringInfoData::len, CopyFromStateData::line_buf, list_free(), list_length(), makeNode, MakeTransitionCaptureState(), MemoryContextSwitchTo(), ModifyTableState::mt_nrels, ModifyTableState::mt_transition_capture, NextCopyFrom(), NIL, ModifyTableState::operation, CopyFromStateData::opts, pgstat_progress_update_param(), PlanState::plan, ErrorContextCallback::previous, PROGRESS_COPY_TUPLES_EXCLUDED, PROGRESS_COPY_TUPLES_PROCESSED, ModifyTableState::ps, CopyFromStateData::qualexpr, CopyFromStateData::range_table, RelationData::rd_att, RelationData::rd_createSubid, RelationData::rd_firstRelfilenodeSubid, RelationData::rd_newRelfilenodeSubid, RelationData::rd_rel, CopyFromStateData::rel, RelationGetRelationName, RelationGetRelid, ReleaseBulkInsertStatePin(), ResetPerTupleExprContext, ModifyTableState::resultRelInfo, ResultRelInfo::ri_CopyMultiInsertBuffer, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_PartitionTupleSlot, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_RootToPartitionMap, ResultRelInfo::ri_TrigDesc, ModifyTableState::rootResultRelInfo, 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 115 of file copyfrom.c.

116 {
117  CopyFromState cstate = (CopyFromState) arg;
118 
119  if (cstate->opts.binary)
120  {
121  /* can't usefully display the data */
122  if (cstate->cur_attname)
123  errcontext("COPY %s, line %llu, column %s",
124  cstate->cur_relname,
125  (unsigned long long) cstate->cur_lineno,
126  cstate->cur_attname);
127  else
128  errcontext("COPY %s, line %llu",
129  cstate->cur_relname,
130  (unsigned long long) cstate->cur_lineno);
131  }
132  else
133  {
134  if (cstate->cur_attname && cstate->cur_attval)
135  {
136  /* error is relevant to a particular column */
137  char *attval;
138 
139  attval = limit_printout_length(cstate->cur_attval);
140  errcontext("COPY %s, line %llu, column %s: \"%s\"",
141  cstate->cur_relname,
142  (unsigned long long) cstate->cur_lineno,
143  cstate->cur_attname,
144  attval);
145  pfree(attval);
146  }
147  else if (cstate->cur_attname)
148  {
149  /* error is relevant to a particular column, value is NULL */
150  errcontext("COPY %s, line %llu, column %s: null input",
151  cstate->cur_relname,
152  (unsigned long long) cstate->cur_lineno,
153  cstate->cur_attname);
154  }
155  else
156  {
157  /*
158  * Error is relevant to a particular line.
159  *
160  * If line_buf still contains the correct line, print it.
161  */
162  if (cstate->line_buf_valid)
163  {
164  char *lineval;
165 
166  lineval = limit_printout_length(cstate->line_buf.data);
167  errcontext("COPY %s, line %llu: \"%s\"",
168  cstate->cur_relname,
169  (unsigned long long) cstate->cur_lineno, lineval);
170  pfree(lineval);
171  }
172  else
173  {
174  errcontext("COPY %s, line %llu",
175  cstate->cur_relname,
176  (unsigned long long) cstate->cur_lineno);
177  }
178  }
179  }
180 }
static char * limit_printout_length(const char *str)
Definition: copyfrom.c:188
#define errcontext
Definition: elog.h:190
struct CopyFromStateData * CopyFromState
Definition: copy.h:65
void pfree(void *pointer)
Definition: mcxt.c:1175
void * arg

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

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

◆ CopyGetAttnums()

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

Definition at line 708 of file copy.c.

709 {
710  List *attnums = NIL;
711 
712  if (attnamelist == NIL)
713  {
714  /* Generate default column list */
715  int attr_count = tupDesc->natts;
716  int i;
717 
718  for (i = 0; i < attr_count; i++)
719  {
720  if (TupleDescAttr(tupDesc, i)->attisdropped)
721  continue;
722  if (TupleDescAttr(tupDesc, i)->attgenerated)
723  continue;
724  attnums = lappend_int(attnums, i + 1);
725  }
726  }
727  else
728  {
729  /* Validate the user-supplied list and extract attnums */
730  ListCell *l;
731 
732  foreach(l, attnamelist)
733  {
734  char *name = strVal(lfirst(l));
735  int attnum;
736  int i;
737 
738  /* Lookup column name */
740  for (i = 0; i < tupDesc->natts; i++)
741  {
742  Form_pg_attribute att = TupleDescAttr(tupDesc, i);
743 
744  if (att->attisdropped)
745  continue;
746  if (namestrcmp(&(att->attname), name) == 0)
747  {
748  if (att->attgenerated)
749  ereport(ERROR,
750  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
751  errmsg("column \"%s\" is a generated column",
752  name),
753  errdetail("Generated columns cannot be used in COPY.")));
754  attnum = att->attnum;
755  break;
756  }
757  }
758  if (attnum == InvalidAttrNumber)
759  {
760  if (rel != NULL)
761  ereport(ERROR,
762  (errcode(ERRCODE_UNDEFINED_COLUMN),
763  errmsg("column \"%s\" of relation \"%s\" does not exist",
764  name, RelationGetRelationName(rel))));
765  else
766  ereport(ERROR,
767  (errcode(ERRCODE_UNDEFINED_COLUMN),
768  errmsg("column \"%s\" does not exist",
769  name)));
770  }
771  /* Check for duplicates */
772  if (list_member_int(attnums, attnum))
773  ereport(ERROR,
774  (errcode(ERRCODE_DUPLICATE_COLUMN),
775  errmsg("column \"%s\" specified more than once",
776  name)));
777  attnums = lappend_int(attnums, attnum);
778  }
779  }
780 
781  return attnums;
782 }
#define InvalidAttrNumber
Definition: attnum.h:23
int errdetail(const char *fmt,...)
Definition: elog.c:1037
const char * name
Definition: encode.c:561
List * lappend_int(List *list, int datum)
Definition: list.c:354
int namestrcmp(Name name, const char *str)
Definition: name.c:247
#define lfirst(lc)
Definition: pg_list.h:169
#define strVal(v)
Definition: value.h:72

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

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

◆ CreateCopyDestReceiver()

DestReceiver* CreateCopyDestReceiver ( void  )

Definition at line 1296 of file copyto.c.

1297 {
1298  DR_copy *self = (DR_copy *) palloc(sizeof(DR_copy));
1299 
1300  self->pub.receiveSlot = copy_dest_receive;
1301  self->pub.rStartup = copy_dest_startup;
1302  self->pub.rShutdown = copy_dest_shutdown;
1303  self->pub.rDestroy = copy_dest_destroy;
1304  self->pub.mydest = DestCopyOut;
1305 
1306  self->cstate = NULL; /* will be set later */
1307  self->processed = 0;
1308 
1309  return (DestReceiver *) self;
1310 }
static bool copy_dest_receive(TupleTableSlot *slot, DestReceiver *self)
Definition: copyto.c:1259
static void copy_dest_destroy(DestReceiver *self)
Definition: copyto.c:1287
static void copy_dest_shutdown(DestReceiver *self)
Definition: copyto.c:1278
static void copy_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: copyto.c:1250

References copy_dest_destroy(), copy_dest_receive(), copy_dest_shutdown(), copy_dest_startup(), DestCopyOut, and palloc().

Referenced by CreateDestReceiver().

◆ DoCopy()

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

Definition at line 64 of file copy.c.

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

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

Referenced by standard_ProcessUtility().

◆ DoCopyTo()

uint64 DoCopyTo ( CopyToState  cstate)

Definition at line 770 of file copyto.c.

771 {
772  bool pipe = (cstate->filename == NULL);
773  bool fe_copy = (pipe && whereToSendOutput == DestRemote);
774  TupleDesc tupDesc;
775  int num_phys_attrs;
776  ListCell *cur;
777  uint64 processed;
778 
779  if (fe_copy)
780  SendCopyBegin(cstate);
781 
782  if (cstate->rel)
783  tupDesc = RelationGetDescr(cstate->rel);
784  else
785  tupDesc = cstate->queryDesc->tupDesc;
786  num_phys_attrs = tupDesc->natts;
787  cstate->opts.null_print_client = cstate->opts.null_print; /* default */
788 
789  /* We use fe_msgbuf as a per-row buffer regardless of copy_dest */
790  cstate->fe_msgbuf = makeStringInfo();
791 
792  /* Get info about the columns we need to process. */
793  cstate->out_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
794  foreach(cur, cstate->attnumlist)
795  {
796  int attnum = lfirst_int(cur);
797  Oid out_func_oid;
798  bool isvarlena;
799  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
800 
801  if (cstate->opts.binary)
802  getTypeBinaryOutputInfo(attr->atttypid,
803  &out_func_oid,
804  &isvarlena);
805  else
806  getTypeOutputInfo(attr->atttypid,
807  &out_func_oid,
808  &isvarlena);
809  fmgr_info(out_func_oid, &cstate->out_functions[attnum - 1]);
810  }
811 
812  /*
813  * Create a temporary memory context that we can reset once per row to
814  * recover palloc'd memory. This avoids any problems with leaks inside
815  * datatype output routines, and should be faster than retail pfree's
816  * anyway. (We don't need a whole econtext as CopyFrom does.)
817  */
819  "COPY TO",
821 
822  if (cstate->opts.binary)
823  {
824  /* Generate header for a binary copy */
825  int32 tmp;
826 
827  /* Signature */
828  CopySendData(cstate, BinarySignature, 11);
829  /* Flags field */
830  tmp = 0;
831  CopySendInt32(cstate, tmp);
832  /* No header extension */
833  tmp = 0;
834  CopySendInt32(cstate, tmp);
835  }
836  else
837  {
838  /*
839  * For non-binary copy, we need to convert null_print to file
840  * encoding, because it will be sent directly with CopySendString.
841  */
842  if (cstate->need_transcoding)
844  cstate->opts.null_print_len,
845  cstate->file_encoding);
846 
847  /* if a header has been requested send the line */
848  if (cstate->opts.header_line)
849  {
850  bool hdr_delim = false;
851 
852  foreach(cur, cstate->attnumlist)
853  {
854  int attnum = lfirst_int(cur);
855  char *colname;
856 
857  if (hdr_delim)
858  CopySendChar(cstate, cstate->opts.delim[0]);
859  hdr_delim = true;
860 
861  colname = NameStr(TupleDescAttr(tupDesc, attnum - 1)->attname);
862 
863  if (cstate->opts.csv_mode)
864  CopyAttributeOutCSV(cstate, colname, false,
865  list_length(cstate->attnumlist) == 1);
866  else
867  CopyAttributeOutText(cstate, colname);
868  }
869 
870  CopySendEndOfRow(cstate);
871  }
872  }
873 
874  if (cstate->rel)
875  {
876  TupleTableSlot *slot;
877  TableScanDesc scandesc;
878 
879  scandesc = table_beginscan(cstate->rel, GetActiveSnapshot(), 0, NULL);
880  slot = table_slot_create(cstate->rel, NULL);
881 
882  processed = 0;
883  while (table_scan_getnextslot(scandesc, ForwardScanDirection, slot))
884  {
886 
887  /* Deconstruct the tuple ... */
888  slot_getallattrs(slot);
889 
890  /* Format and send the data */
891  CopyOneRowTo(cstate, slot);
892 
893  /*
894  * Increment the number of processed tuples, and report the
895  * progress.
896  */
898  ++processed);
899  }
900 
902  table_endscan(scandesc);
903  }
904  else
905  {
906  /* run the plan --- the dest receiver will send tuples */
907  ExecutorRun(cstate->queryDesc, ForwardScanDirection, 0L, true);
908  processed = ((DR_copy *) cstate->queryDesc->dest)->processed;
909  }
910 
911  if (cstate->opts.binary)
912  {
913  /* Generate trailer for a binary copy */
914  CopySendInt16(cstate, -1);
915  /* Need to flush out the trailer */
916  CopySendEndOfRow(cstate);
917  }
918 
920 
921  if (fe_copy)
922  SendCopyEnd(cstate);
923 
924  return processed;
925 }
signed int int32
Definition: c.h:429
static void CopySendInt32(CopyToState cstate, int32 val)
Definition: copyto.c:267
static void CopyAttributeOutText(CopyToState cstate, const char *string)
Definition: copyto.c:1012
static void CopySendInt16(CopyToState cstate, int16 val)
Definition: copyto.c:279
static void CopySendData(CopyToState cstate, const void *databuf, int datasize)
Definition: copyto.c:174
static void CopySendChar(CopyToState cstate, char c)
Definition: copyto.c:186
static void CopyAttributeOutCSV(CopyToState cstate, const char *string, bool use_quote, bool single_attr)
Definition: copyto.c:1165
static void SendCopyBegin(CopyToState cstate)
Definition: copyto.c:138
static void SendCopyEnd(CopyToState cstate)
Definition: copyto.c:155
static void CopySendEndOfRow(CopyToState cstate)
Definition: copyto.c:192
static void CopyOneRowTo(CopyToState cstate, TupleTableSlot *slot)
Definition: copyto.c:931
static const char BinarySignature[11]
Definition: copyto.c:111
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:300
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1254
void getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
Definition: lsyscache.c:2930
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2864
char * pg_server_to_any(const char *s, int len, int encoding)
Definition: mbutils.c:749
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
NameData attname
Definition: pg_attribute.h:41
@ ForwardScanDirection
Definition: sdir.h:26
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
int null_print_len
Definition: copy.h:48
CopyHeaderChoice header_line
Definition: copy.h:46
char * null_print
Definition: copy.h:47
char * delim
Definition: copy.h:50
char * null_print_client
Definition: copy.h:49
bool csv_mode
Definition: copy.h:45
FmgrInfo * out_functions
Definition: copyto.c:97
MemoryContext rowcontext
Definition: copyto.c:98
StringInfo fe_msgbuf
Definition: copyto.c:76
DestReceiver * dest
Definition: execdesc.h:41
static TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key)
Definition: tableam.h:885
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:993
static bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
Definition: tableam.h:1034
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:354

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, attname, attnum, CopyToStateData::attnumlist, CopyFormatOptions::binary, BinarySignature, CHECK_FOR_INTERRUPTS, CopyAttributeOutCSV(), CopyAttributeOutText(), CopyOneRowTo(), CopySendChar(), CopySendData(), CopySendEndOfRow(), CopySendInt16(), CopySendInt32(), CopyFormatOptions::csv_mode, cur, CurrentMemoryContext, CopyFormatOptions::delim, QueryDesc::dest, DestRemote, ExecDropSingleTupleTableSlot(), ExecutorRun(), CopyToStateData::fe_msgbuf, CopyToStateData::file_encoding, CopyToStateData::filename, fmgr_info(), ForwardScanDirection, GetActiveSnapshot(), getTypeBinaryOutputInfo(), getTypeOutputInfo(), CopyFormatOptions::header_line, lfirst_int, list_length(), makeStringInfo(), MemoryContextDelete(), NameStr, TupleDescData::natts, CopyToStateData::need_transcoding, CopyFormatOptions::null_print, CopyFormatOptions::null_print_client, CopyFormatOptions::null_print_len, CopyToStateData::opts, CopyToStateData::out_functions, palloc(), pg_server_to_any(), pgstat_progress_update_param(), PROGRESS_COPY_TUPLES_PROCESSED, CopyToStateData::queryDesc, CopyToStateData::rel, RelationGetDescr, CopyToStateData::rowcontext, SendCopyBegin(), SendCopyEnd(), slot_getallattrs(), table_beginscan(), table_endscan(), table_scan_getnextslot(), table_slot_create(), QueryDesc::tupDesc, TupleDescAttr, and whereToSendOutput.

Referenced by DoCopy().

◆ EndCopyFrom()

void EndCopyFrom ( CopyFromState  cstate)

Definition at line 1563 of file copyfrom.c.

1564 {
1565  /* No COPY FROM related resources except memory. */
1566  if (cstate->is_program)
1567  {
1568  ClosePipeFromProgram(cstate);
1569  }
1570  else
1571  {
1572  if (cstate->filename != NULL && FreeFile(cstate->copy_file))
1573  ereport(ERROR,
1575  errmsg("could not close file \"%s\": %m",
1576  cstate->filename)));
1577  }
1578 
1580 
1582  pfree(cstate);
1583 }
void pgstat_progress_end_command(void)
static void ClosePipeFromProgram(CopyFromState cstate)
Definition: copyfrom.c:1589
int FreeFile(FILE *file)
Definition: fd.c:2660

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

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

◆ EndCopyTo()

void EndCopyTo ( CopyToState  cstate)

Definition at line 751 of file copyto.c.

752 {
753  if (cstate->queryDesc != NULL)
754  {
755  /* Close down the query and free resources. */
756  ExecutorFinish(cstate->queryDesc);
757  ExecutorEnd(cstate->queryDesc);
758  FreeQueryDesc(cstate->queryDesc);
760  }
761 
762  /* Clean up storage */
763  EndCopy(cstate);
764 }
static void EndCopy(CopyToState cstate)
Definition: copyto.c:316
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:461
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:401
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:105
void PopActiveSnapshot(void)
Definition: snapmgr.c:776

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

Referenced by DoCopy().

◆ NextCopyFrom()

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

Definition at line 852 of file copyfromparse.c.

854 {
855  TupleDesc tupDesc;
856  AttrNumber num_phys_attrs,
857  attr_count,
858  num_defaults = cstate->num_defaults;
859  FmgrInfo *in_functions = cstate->in_functions;
860  Oid *typioparams = cstate->typioparams;
861  int i;
862  int *defmap = cstate->defmap;
863  ExprState **defexprs = cstate->defexprs;
864 
865  tupDesc = RelationGetDescr(cstate->rel);
866  num_phys_attrs = tupDesc->natts;
867  attr_count = list_length(cstate->attnumlist);
868 
869  /* Initialize all values for row to NULL */
870  MemSet(values, 0, num_phys_attrs * sizeof(Datum));
871  MemSet(nulls, true, num_phys_attrs * sizeof(bool));
872 
873  if (!cstate->opts.binary)
874  {
875  char **field_strings;
876  ListCell *cur;
877  int fldct;
878  int fieldno;
879  char *string;
880 
881  /* read raw fields in the next line */
882  if (!NextCopyFromRawFields(cstate, &field_strings, &fldct))
883  return false;
884 
885  /* check for overflowing fields */
886  if (attr_count > 0 && fldct > attr_count)
887  ereport(ERROR,
888  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
889  errmsg("extra data after last expected column")));
890 
891  fieldno = 0;
892 
893  /* Loop to read the user attributes on the line. */
894  foreach(cur, cstate->attnumlist)
895  {
896  int attnum = lfirst_int(cur);
897  int m = attnum - 1;
898  Form_pg_attribute att = TupleDescAttr(tupDesc, m);
899 
900  if (fieldno >= fldct)
901  ereport(ERROR,
902  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
903  errmsg("missing data for column \"%s\"",
904  NameStr(att->attname))));
905  string = field_strings[fieldno++];
906 
907  if (cstate->convert_select_flags &&
908  !cstate->convert_select_flags[m])
909  {
910  /* ignore input field, leaving column as NULL */
911  continue;
912  }
913 
914  if (cstate->opts.csv_mode)
915  {
916  if (string == NULL &&
917  cstate->opts.force_notnull_flags[m])
918  {
919  /*
920  * FORCE_NOT_NULL option is set and column is NULL -
921  * convert it to the NULL string.
922  */
923  string = cstate->opts.null_print;
924  }
925  else if (string != NULL && cstate->opts.force_null_flags[m]
926  && strcmp(string, cstate->opts.null_print) == 0)
927  {
928  /*
929  * FORCE_NULL option is set and column matches the NULL
930  * string. It must have been quoted, or otherwise the
931  * string would already have been set to NULL. Convert it
932  * to NULL as specified.
933  */
934  string = NULL;
935  }
936  }
937 
938  cstate->cur_attname = NameStr(att->attname);
939  cstate->cur_attval = string;
940  values[m] = InputFunctionCall(&in_functions[m],
941  string,
942  typioparams[m],
943  att->atttypmod);
944  if (string != NULL)
945  nulls[m] = false;
946  cstate->cur_attname = NULL;
947  cstate->cur_attval = NULL;
948  }
949 
950  Assert(fieldno == attr_count);
951  }
952  else
953  {
954  /* binary */
955  int16 fld_count;
956  ListCell *cur;
957 
958  cstate->cur_lineno++;
959 
960  if (!CopyGetInt16(cstate, &fld_count))
961  {
962  /* EOF detected (end of file, or protocol-level EOF) */
963  return false;
964  }
965 
966  if (fld_count == -1)
967  {
968  /*
969  * Received EOF marker. Wait for the protocol-level EOF, and
970  * complain if it doesn't come immediately. In COPY FROM STDIN,
971  * this ensures that we correctly handle CopyFail, if client
972  * chooses to send that now. When copying from file, we could
973  * ignore the rest of the file like in text mode, but we choose to
974  * be consistent with the COPY FROM STDIN case.
975  */
976  char dummy;
977 
978  if (CopyReadBinaryData(cstate, &dummy, 1) > 0)
979  ereport(ERROR,
980  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
981  errmsg("received copy data after EOF marker")));
982  return false;
983  }
984 
985  if (fld_count != attr_count)
986  ereport(ERROR,
987  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
988  errmsg("row field count is %d, expected %d",
989  (int) fld_count, attr_count)));
990 
991  foreach(cur, cstate->attnumlist)
992  {
993  int attnum = lfirst_int(cur);
994  int m = attnum - 1;
995  Form_pg_attribute att = TupleDescAttr(tupDesc, m);
996 
997  cstate->cur_attname = NameStr(att->attname);
998  values[m] = CopyReadBinaryAttribute(cstate,
999  &in_functions[m],
1000  typioparams[m],
1001  att->atttypmod,
1002  &nulls[m]);
1003  cstate->cur_attname = NULL;
1004  }
1005  }
1006 
1007  /*
1008  * Now compute and insert any defaults available for the columns not
1009  * provided by the input data. Anything not processed here or above will
1010  * remain NULL.
1011  */
1012  for (i = 0; i < num_defaults; i++)
1013  {
1014  /*
1015  * The caller must supply econtext and have switched into the
1016  * per-tuple memory context in it.
1017  */
1018  Assert(econtext != NULL);
1020 
1021  values[defmap[i]] = ExecEvalExpr(defexprs[i], econtext,
1022  &nulls[defmap[i]]);
1023  }
1024 
1025  return true;
1026 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
signed short int16
Definition: c.h:428
#define MemSet(start, val, len)
Definition: c.h:1008
static bool CopyGetInt16(CopyFromState cstate, int16 *val)
static Datum CopyReadBinaryAttribute(CopyFromState cstate, FmgrInfo *flinfo, Oid typioparam, int32 typmod, bool *isnull)
static int CopyReadBinaryData(CopyFromState cstate, char *dest, int nbytes)
bool NextCopyFromRawFields(CopyFromState cstate, char ***fields, int *nfields)
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:320
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1515
uintptr_t Datum
Definition: postgres.h:411
char string[11]
Definition: preproc-type.c:46
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:240

References Assert(), attnum, CopyFromStateData::attnumlist, CopyFormatOptions::binary, CopyFromStateData::convert_select_flags, CopyGetInt16(), CopyReadBinaryAttribute(), CopyReadBinaryData(), CopyFormatOptions::csv_mode, cur, CopyFromStateData::cur_attname, CopyFromStateData::cur_attval, CopyFromStateData::cur_lineno, CurrentMemoryContext, CopyFromStateData::defexprs, CopyFromStateData::defmap, ExprContext::ecxt_per_tuple_memory, ereport, errcode(), errmsg(), ERROR, ExecEvalExpr(), CopyFormatOptions::force_notnull_flags, CopyFormatOptions::force_null_flags, i, CopyFromStateData::in_functions, InputFunctionCall(), lfirst_int, list_length(), MemSet, NameStr, TupleDescData::natts, NextCopyFromRawFields(), CopyFormatOptions::null_print, CopyFromStateData::num_defaults, CopyFromStateData::opts, CopyFromStateData::rel, RelationGetDescr, TupleDescAttr, CopyFromStateData::typioparams, and values.

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

◆ NextCopyFromRawFields()

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

Definition at line 754 of file copyfromparse.c.

755 {
756  int fldct;
757  bool done;
758 
759  /* only available for text or csv input */
760  Assert(!cstate->opts.binary);
761 
762  /* on input check that the header line is correct if needed */
763  if (cstate->cur_lineno == 0 && cstate->opts.header_line)
764  {
765  ListCell *cur;
766  TupleDesc tupDesc;
767 
768  tupDesc = RelationGetDescr(cstate->rel);
769 
770  cstate->cur_lineno++;
771  done = CopyReadLine(cstate);
772 
773  if (cstate->opts.header_line == COPY_HEADER_MATCH)
774  {
775  int fldnum;
776 
777  if (cstate->opts.csv_mode)
778  fldct = CopyReadAttributesCSV(cstate);
779  else
780  fldct = CopyReadAttributesText(cstate);
781 
782  if (fldct != list_length(cstate->attnumlist))
783  ereport(ERROR,
784  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
785  errmsg("wrong number of fields in header line: field count is %d, expected %d",
786  fldct, list_length(cstate->attnumlist))));
787 
788  fldnum = 0;
789  foreach(cur, cstate->attnumlist)
790  {
791  int attnum = lfirst_int(cur);
792  char *colName = cstate->raw_fields[attnum - 1];
793  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
794 
795  fldnum++;
796 
797  if (colName == NULL)
798  ereport(ERROR,
799  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
800  errmsg("column name mismatch in header line field %d: got null value (\"%s\"), expected \"%s\"",
801  fldnum, cstate->opts.null_print, NameStr(attr->attname))));
802 
803  if (namestrcmp(&attr->attname, colName) != 0)
804  {
805  ereport(ERROR,
806  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
807  errmsg("column name mismatch in header line field %d: got \"%s\", expected \"%s\"",
808  fldnum, colName, NameStr(attr->attname))));
809  }
810  }
811  }
812 
813  if (done)
814  return false;
815  }
816 
817  cstate->cur_lineno++;
818 
819  /* Actually read the line into memory here */
820  done = CopyReadLine(cstate);
821 
822  /*
823  * EOF at start of line means we're done. If we see EOF after some
824  * characters, we act as though it was newline followed by EOF, ie,
825  * process the line and then exit loop on next iteration.
826  */
827  if (done && cstate->line_buf.len == 0)
828  return false;
829 
830  /* Parse the line into de-escaped field values */
831  if (cstate->opts.csv_mode)
832  fldct = CopyReadAttributesCSV(cstate);
833  else
834  fldct = CopyReadAttributesText(cstate);
835 
836  *fields = cstate->raw_fields;
837  *nfields = fldct;
838  return true;
839 }
static int CopyReadAttributesCSV(CopyFromState cstate)
static int CopyReadAttributesText(CopyFromState cstate)
static bool CopyReadLine(CopyFromState cstate)

References Assert(), attnum, CopyFromStateData::attnumlist, CopyFormatOptions::binary, COPY_HEADER_MATCH, CopyReadAttributesCSV(), CopyReadAttributesText(), CopyReadLine(), CopyFormatOptions::csv_mode, cur, CopyFromStateData::cur_lineno, ereport, errcode(), errmsg(), ERROR, CopyFormatOptions::header_line, StringInfoData::len, lfirst_int, CopyFromStateData::line_buf, list_length(), NameStr, namestrcmp(), CopyFormatOptions::null_print, CopyFromStateData::opts, CopyFromStateData::raw_fields, CopyFromStateData::rel, RelationGetDescr, and TupleDescAttr.

Referenced by NextCopyFrom().

◆ ProcessCopyOptions()

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

Definition at line 391 of file copy.c.

395 {
396  bool format_specified = false;
397  bool freeze_specified = false;
398  bool header_specified = false;
399  ListCell *option;
400 
401  /* Support external use for option sanity checking */
402  if (opts_out == NULL)
403  opts_out = (CopyFormatOptions *) palloc0(sizeof(CopyFormatOptions));
404 
405  opts_out->file_encoding = -1;
406 
407  /* Extract options from the statement node tree */
408  foreach(option, options)
409  {
410  DefElem *defel = lfirst_node(DefElem, option);
411 
412  if (strcmp(defel->defname, "format") == 0)
413  {
414  char *fmt = defGetString(defel);
415 
416  if (format_specified)
417  errorConflictingDefElem(defel, pstate);
418  format_specified = true;
419  if (strcmp(fmt, "text") == 0)
420  /* default format */ ;
421  else if (strcmp(fmt, "csv") == 0)
422  opts_out->csv_mode = true;
423  else if (strcmp(fmt, "binary") == 0)
424  opts_out->binary = true;
425  else
426  ereport(ERROR,
427  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
428  errmsg("COPY format \"%s\" not recognized", fmt),
429  parser_errposition(pstate, defel->location)));
430  }
431  else if (strcmp(defel->defname, "freeze") == 0)
432  {
433  if (freeze_specified)
434  errorConflictingDefElem(defel, pstate);
435  freeze_specified = true;
436  opts_out->freeze = defGetBoolean(defel);
437  }
438  else if (strcmp(defel->defname, "delimiter") == 0)
439  {
440  if (opts_out->delim)
441  errorConflictingDefElem(defel, pstate);
442  opts_out->delim = defGetString(defel);
443  }
444  else if (strcmp(defel->defname, "null") == 0)
445  {
446  if (opts_out->null_print)
447  errorConflictingDefElem(defel, pstate);
448  opts_out->null_print = defGetString(defel);
449  }
450  else if (strcmp(defel->defname, "header") == 0)
451  {
452  if (header_specified)
453  errorConflictingDefElem(defel, pstate);
454  header_specified = true;
455  opts_out->header_line = defGetCopyHeaderChoice(defel);
456  }
457  else if (strcmp(defel->defname, "quote") == 0)
458  {
459  if (opts_out->quote)
460  errorConflictingDefElem(defel, pstate);
461  opts_out->quote = defGetString(defel);
462  }
463  else if (strcmp(defel->defname, "escape") == 0)
464  {
465  if (opts_out->escape)
466  errorConflictingDefElem(defel, pstate);
467  opts_out->escape = defGetString(defel);
468  }
469  else if (strcmp(defel->defname, "force_quote") == 0)
470  {
471  if (opts_out->force_quote || opts_out->force_quote_all)
472  errorConflictingDefElem(defel, pstate);
473  if (defel->arg && IsA(defel->arg, A_Star))
474  opts_out->force_quote_all = true;
475  else if (defel->arg && IsA(defel->arg, List))
476  opts_out->force_quote = castNode(List, defel->arg);
477  else
478  ereport(ERROR,
479  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
480  errmsg("argument to option \"%s\" must be a list of column names",
481  defel->defname),
482  parser_errposition(pstate, defel->location)));
483  }
484  else if (strcmp(defel->defname, "force_not_null") == 0)
485  {
486  if (opts_out->force_notnull)
487  errorConflictingDefElem(defel, pstate);
488  if (defel->arg && IsA(defel->arg, List))
489  opts_out->force_notnull = castNode(List, defel->arg);
490  else
491  ereport(ERROR,
492  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
493  errmsg("argument to option \"%s\" must be a list of column names",
494  defel->defname),
495  parser_errposition(pstate, defel->location)));
496  }
497  else if (strcmp(defel->defname, "force_null") == 0)
498  {
499  if (opts_out->force_null)
500  errorConflictingDefElem(defel, pstate);
501  if (defel->arg && IsA(defel->arg, List))
502  opts_out->force_null = castNode(List, defel->arg);
503  else
504  ereport(ERROR,
505  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
506  errmsg("argument to option \"%s\" must be a list of column names",
507  defel->defname),
508  parser_errposition(pstate, defel->location)));
509  }
510  else if (strcmp(defel->defname, "convert_selectively") == 0)
511  {
512  /*
513  * Undocumented, not-accessible-from-SQL option: convert only the
514  * named columns to binary form, storing the rest as NULLs. It's
515  * allowed for the column list to be NIL.
516  */
517  if (opts_out->convert_selectively)
518  errorConflictingDefElem(defel, pstate);
519  opts_out->convert_selectively = true;
520  if (defel->arg == NULL || IsA(defel->arg, List))
521  opts_out->convert_select = castNode(List, defel->arg);
522  else
523  ereport(ERROR,
524  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
525  errmsg("argument to option \"%s\" must be a list of column names",
526  defel->defname),
527  parser_errposition(pstate, defel->location)));
528  }
529  else if (strcmp(defel->defname, "encoding") == 0)
530  {
531  if (opts_out->file_encoding >= 0)
532  errorConflictingDefElem(defel, pstate);
533  opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
534  if (opts_out->file_encoding < 0)
535  ereport(ERROR,
536  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
537  errmsg("argument to option \"%s\" must be a valid encoding name",
538  defel->defname),
539  parser_errposition(pstate, defel->location)));
540  }
541  else
542  ereport(ERROR,
543  (errcode(ERRCODE_SYNTAX_ERROR),
544  errmsg("option \"%s\" not recognized",
545  defel->defname),
546  parser_errposition(pstate, defel->location)));
547  }
548 
549  /*
550  * Check for incompatible options (must do these two before inserting
551  * defaults)
552  */
553  if (opts_out->binary && opts_out->delim)
554  ereport(ERROR,
555  (errcode(ERRCODE_SYNTAX_ERROR),
556  errmsg("cannot specify DELIMITER in BINARY mode")));
557 
558  if (opts_out->binary && opts_out->null_print)
559  ereport(ERROR,
560  (errcode(ERRCODE_SYNTAX_ERROR),
561  errmsg("cannot specify NULL in BINARY mode")));
562 
563  /* Set defaults for omitted options */
564  if (!opts_out->delim)
565  opts_out->delim = opts_out->csv_mode ? "," : "\t";
566 
567  if (!opts_out->null_print)
568  opts_out->null_print = opts_out->csv_mode ? "" : "\\N";
569  opts_out->null_print_len = strlen(opts_out->null_print);
570 
571  if (opts_out->csv_mode)
572  {
573  if (!opts_out->quote)
574  opts_out->quote = "\"";
575  if (!opts_out->escape)
576  opts_out->escape = opts_out->quote;
577  }
578 
579  /* Only single-byte delimiter strings are supported. */
580  if (strlen(opts_out->delim) != 1)
581  ereport(ERROR,
582  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
583  errmsg("COPY delimiter must be a single one-byte character")));
584 
585  /* Disallow end-of-line characters */
586  if (strchr(opts_out->delim, '\r') != NULL ||
587  strchr(opts_out->delim, '\n') != NULL)
588  ereport(ERROR,
589  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
590  errmsg("COPY delimiter cannot be newline or carriage return")));
591 
592  if (strchr(opts_out->null_print, '\r') != NULL ||
593  strchr(opts_out->null_print, '\n') != NULL)
594  ereport(ERROR,
595  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
596  errmsg("COPY null representation cannot use newline or carriage return")));
597 
598  /*
599  * Disallow unsafe delimiter characters in non-CSV mode. We can't allow
600  * backslash because it would be ambiguous. We can't allow the other
601  * cases because data characters matching the delimiter must be
602  * backslashed, and certain backslash combinations are interpreted
603  * non-literally by COPY IN. Disallowing all lower case ASCII letters is
604  * more than strictly necessary, but seems best for consistency and
605  * future-proofing. Likewise we disallow all digits though only octal
606  * digits are actually dangerous.
607  */
608  if (!opts_out->csv_mode &&
609  strchr("\\.abcdefghijklmnopqrstuvwxyz0123456789",
610  opts_out->delim[0]) != NULL)
611  ereport(ERROR,
612  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
613  errmsg("COPY delimiter cannot be \"%s\"", opts_out->delim)));
614 
615  /* Check header */
616  if (opts_out->binary && opts_out->header_line)
617  ereport(ERROR,
618  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
619  errmsg("cannot specify HEADER in BINARY mode")));
620 
621  /* Check quote */
622  if (!opts_out->csv_mode && opts_out->quote != NULL)
623  ereport(ERROR,
624  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
625  errmsg("COPY quote available only in CSV mode")));
626 
627  if (opts_out->csv_mode && strlen(opts_out->quote) != 1)
628  ereport(ERROR,
629  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
630  errmsg("COPY quote must be a single one-byte character")));
631 
632  if (opts_out->csv_mode && opts_out->delim[0] == opts_out->quote[0])
633  ereport(ERROR,
634  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
635  errmsg("COPY delimiter and quote must be different")));
636 
637  /* Check escape */
638  if (!opts_out->csv_mode && opts_out->escape != NULL)
639  ereport(ERROR,
640  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
641  errmsg("COPY escape available only in CSV mode")));
642 
643  if (opts_out->csv_mode && strlen(opts_out->escape) != 1)
644  ereport(ERROR,
645  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
646  errmsg("COPY escape must be a single one-byte character")));
647 
648  /* Check force_quote */
649  if (!opts_out->csv_mode && (opts_out->force_quote || opts_out->force_quote_all))
650  ereport(ERROR,
651  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
652  errmsg("COPY force quote available only in CSV mode")));
653  if ((opts_out->force_quote || opts_out->force_quote_all) && is_from)
654  ereport(ERROR,
655  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
656  errmsg("COPY force quote only available using COPY TO")));
657 
658  /* Check force_notnull */
659  if (!opts_out->csv_mode && opts_out->force_notnull != NIL)
660  ereport(ERROR,
661  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
662  errmsg("COPY force not null available only in CSV mode")));
663  if (opts_out->force_notnull != NIL && !is_from)
664  ereport(ERROR,
665  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
666  errmsg("COPY force not null only available using COPY FROM")));
667 
668  /* Check force_null */
669  if (!opts_out->csv_mode && opts_out->force_null != NIL)
670  ereport(ERROR,
671  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
672  errmsg("COPY force null available only in CSV mode")));
673 
674  if (opts_out->force_null != NIL && !is_from)
675  ereport(ERROR,
676  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
677  errmsg("COPY force null only available using COPY FROM")));
678 
679  /* Don't allow the delimiter to appear in the null string. */
680  if (strchr(opts_out->null_print, opts_out->delim[0]) != NULL)
681  ereport(ERROR,
682  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
683  errmsg("COPY delimiter must not appear in the NULL specification")));
684 
685  /* Don't allow the CSV quote char to appear in the null string. */
686  if (opts_out->csv_mode &&
687  strchr(opts_out->null_print, opts_out->quote[0]) != NULL)
688  ereport(ERROR,
689  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
690  errmsg("CSV quote character must not appear in the NULL specification")));
691 }
static CopyHeaderChoice defGetCopyHeaderChoice(DefElem *def)
Definition: copy.c:321
bool defGetBoolean(DefElem *def)
Definition: define.c:108
char * defGetString(DefElem *def)
Definition: define.c:49
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:352
int pg_char_to_encoding(const char *name)
Definition: encnames.c:550
static void const char * fmt
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
char * defname
Definition: parsenodes.h:765
int location
Definition: parsenodes.h:769
Node * arg
Definition: parsenodes.h:766

References DefElem::arg, CopyFormatOptions::binary, castNode, CopyFormatOptions::convert_select, CopyFormatOptions::convert_selectively, CopyFormatOptions::csv_mode, defGetBoolean(), defGetCopyHeaderChoice(), defGetString(), DefElem::defname, CopyFormatOptions::delim, ereport, errcode(), errmsg(), ERROR, errorConflictingDefElem(), CopyFormatOptions::escape, CopyFormatOptions::file_encoding, fmt, CopyFormatOptions::force_notnull, CopyFormatOptions::force_null, CopyFormatOptions::force_quote, CopyFormatOptions::force_quote_all, CopyFormatOptions::freeze, CopyFormatOptions::header_line, IsA, lfirst_node, DefElem::location, NIL, CopyFormatOptions::null_print, CopyFormatOptions::null_print_len, palloc0(), parser_errposition(), pg_char_to_encoding(), and CopyFormatOptions::quote.

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