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 struct CopyFormatOptions CopyFormatOptions
 
typedef struct CopyFromStateDataCopyFromState
 
typedef struct CopyToStateDataCopyToState
 
typedef int(* copy_data_source_cb) (void *outbuf, int minread, int maxread)
 

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 57 of file copy.h.

◆ CopyFormatOptions

◆ CopyFromState

Definition at line 54 of file copy.h.

◆ CopyToState

typedef struct CopyToStateData* CopyToState

Definition at line 55 of file copy.h.

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

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, 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().

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

◆ BeginCopyTo()

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

Definition at line 342 of file copyto.c.

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(), copyObject, 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(), CopyFormatOptions::file_encoding, CopyToStateData::file_encoding, CopyToStateData::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(), 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().

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

◆ CopyFrom()

uint64 CopyFrom ( CopyFromState  cstate)

Definition at line 525 of file copyfrom.c.

References AfterTriggerBeginQuery(), AfterTriggerEndQuery(), ErrorContextCallback::arg, Assert, TupleConversionMap::attrMap, FdwRoutine::BeginForeignInsert, CopyMultiInsertBuffer::bistate, 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, CopyMultiInsertBuffer::resultRelInfo, 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().

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

◆ CopyFromErrorCallback()

void CopyFromErrorCallback ( void *  arg)

Definition at line 115 of file copyfrom.c.

References 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, pfree(), snprintf, and UINT64_FORMAT.

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

116 {
117  CopyFromState cstate = (CopyFromState) arg;
118  char curlineno_str[32];
119 
120  snprintf(curlineno_str, sizeof(curlineno_str), UINT64_FORMAT,
121  cstate->cur_lineno);
122 
123  if (cstate->opts.binary)
124  {
125  /* can't usefully display the data */
126  if (cstate->cur_attname)
127  errcontext("COPY %s, line %s, column %s",
128  cstate->cur_relname, curlineno_str,
129  cstate->cur_attname);
130  else
131  errcontext("COPY %s, line %s",
132  cstate->cur_relname, curlineno_str);
133  }
134  else
135  {
136  if (cstate->cur_attname && cstate->cur_attval)
137  {
138  /* error is relevant to a particular column */
139  char *attval;
140 
141  attval = limit_printout_length(cstate->cur_attval);
142  errcontext("COPY %s, line %s, column %s: \"%s\"",
143  cstate->cur_relname, curlineno_str,
144  cstate->cur_attname, 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 %s, column %s: null input",
151  cstate->cur_relname, curlineno_str,
152  cstate->cur_attname);
153  }
154  else
155  {
156  /*
157  * Error is relevant to a particular line.
158  *
159  * If line_buf still contains the correct line, print it.
160  */
161  if (cstate->line_buf_valid)
162  {
163  char *lineval;
164 
165  lineval = limit_printout_length(cstate->line_buf.data);
166  errcontext("COPY %s, line %s: \"%s\"",
167  cstate->cur_relname, curlineno_str, lineval);
168  pfree(lineval);
169  }
170  else
171  {
172  errcontext("COPY %s, line %s",
173  cstate->cur_relname, curlineno_str);
174  }
175  }
176  }
177 }
const char * cur_attname
StringInfoData line_buf
const char * cur_attval
static char * limit_printout_length(const char *str)
Definition: copyfrom.c:185
void pfree(void *pointer)
Definition: mcxt.c:1169
bool binary
Definition: copy.h:32
const char * cur_relname
struct CopyFromStateData * CopyFromState
Definition: copy.h:54
CopyFormatOptions opts
#define errcontext
Definition: elog.h:204
void * arg
#define snprintf
Definition: port.h:216
#define UINT64_FORMAT
Definition: c.h:484

◆ CopyGetAttnums()

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

Definition at line 686 of file copy.c.

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

687 {
688  List *attnums = NIL;
689 
690  if (attnamelist == NIL)
691  {
692  /* Generate default column list */
693  int attr_count = tupDesc->natts;
694  int i;
695 
696  for (i = 0; i < attr_count; i++)
697  {
698  if (TupleDescAttr(tupDesc, i)->attisdropped)
699  continue;
700  if (TupleDescAttr(tupDesc, i)->attgenerated)
701  continue;
702  attnums = lappend_int(attnums, i + 1);
703  }
704  }
705  else
706  {
707  /* Validate the user-supplied list and extract attnums */
708  ListCell *l;
709 
710  foreach(l, attnamelist)
711  {
712  char *name = strVal(lfirst(l));
713  int attnum;
714  int i;
715 
716  /* Lookup column name */
717  attnum = InvalidAttrNumber;
718  for (i = 0; i < tupDesc->natts; i++)
719  {
720  Form_pg_attribute att = TupleDescAttr(tupDesc, i);
721 
722  if (att->attisdropped)
723  continue;
724  if (namestrcmp(&(att->attname), name) == 0)
725  {
726  if (att->attgenerated)
727  ereport(ERROR,
728  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
729  errmsg("column \"%s\" is a generated column",
730  name),
731  errdetail("Generated columns cannot be used in COPY.")));
732  attnum = att->attnum;
733  break;
734  }
735  }
736  if (attnum == InvalidAttrNumber)
737  {
738  if (rel != NULL)
739  ereport(ERROR,
740  (errcode(ERRCODE_UNDEFINED_COLUMN),
741  errmsg("column \"%s\" of relation \"%s\" does not exist",
742  name, RelationGetRelationName(rel))));
743  else
744  ereport(ERROR,
745  (errcode(ERRCODE_UNDEFINED_COLUMN),
746  errmsg("column \"%s\" does not exist",
747  name)));
748  }
749  /* Check for duplicates */
750  if (list_member_int(attnums, attnum))
751  ereport(ERROR,
752  (errcode(ERRCODE_DUPLICATE_COLUMN),
753  errmsg("column \"%s\" specified more than once",
754  name)));
755  attnums = lappend_int(attnums, attnum);
756  }
757  }
758 
759  return attnums;
760 }
#define NIL
Definition: pg_list.h:65
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:698
int namestrcmp(Name name, const char *str)
Definition: name.c:247
#define ERROR
Definition: elog.h:46
bool list_member_int(const List *list, int datum)
Definition: list.c:669
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define RelationGetRelationName(relation)
Definition: rel.h:503
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
List * lappend_int(List *list, int datum)
Definition: list.c:354
int16 attnum
Definition: pg_attribute.h:83
#define ereport(elevel,...)
Definition: elog.h:157
#define lfirst(lc)
Definition: pg_list.h:169
const char * name
Definition: encode.c:515
#define InvalidAttrNumber
Definition: attnum.h:23
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
Definition: pg_list.h:50

◆ CreateCopyDestReceiver()

DestReceiver* CreateCopyDestReceiver ( void  )

Definition at line 1302 of file copyto.c.

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

Referenced by CreateDestReceiver().

1303 {
1304  DR_copy *self = (DR_copy *) palloc(sizeof(DR_copy));
1305 
1306  self->pub.receiveSlot = copy_dest_receive;
1307  self->pub.rStartup = copy_dest_startup;
1308  self->pub.rShutdown = copy_dest_shutdown;
1309  self->pub.rDestroy = copy_dest_destroy;
1310  self->pub.mydest = DestCopyOut;
1311 
1312  self->cstate = NULL; /* will be set later */
1313  self->processed = 0;
1314 
1315  return (DestReceiver *) self;
1316 }
static void copy_dest_destroy(DestReceiver *self)
Definition: copyto.c:1293
static bool copy_dest_receive(TupleTableSlot *slot, DestReceiver *self)
Definition: copyto.c:1265
static void copy_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: copyto.c:1256
void * palloc(Size size)
Definition: mcxt.c:1062
static void copy_dest_shutdown(DestReceiver *self)
Definition: copyto.c:1284

◆ DoCopy()

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

Definition at line 64 of file copy.c.

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, SelectStmt::fromClause, get_namespace_name(), GetUserId(), ResTarget::indirection, RangeTblEntry::insertedCols, InvalidOid, CopyStmt::is_from, is_member_of_role(), 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(), SelectStmt::targetList, transformExpr(), ResTarget::val, CopyStmt::whereClause, and XactReadOnly.

Referenced by standard_ProcessUtility().

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 (!is_member_of_role(GetUserId(), ROLE_PG_EXECUTE_SERVER_PROGRAM))
84  ereport(ERROR,
85  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
86  errmsg("must be superuser or a member 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 && !is_member_of_role(GetUserId(), ROLE_PG_READ_SERVER_FILES))
93  ereport(ERROR,
94  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
95  errmsg("must be superuser or a member 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 && !is_member_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES))
100  ereport(ERROR,
101  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
102  errmsg("must be superuser or a member 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 'Value' node (see
226  * nodes/value.h) that corresponds to the column name
227  * respectively.
228  */
229  cr = makeNode(ColumnRef);
230  cr->fields = list_make1(lfirst(lc));
231  cr->location = -1;
232 
233  /* Build the ResTarget and add the ColumnRef to it. */
234  target = makeNode(ResTarget);
235  target->name = NULL;
236  target->indirection = NIL;
237  target->val = (Node *) cr;
238  target->location = -1;
239 
240  /* Add each column to the SELECT statement's target list */
241  targetList = lappend(targetList, target);
242  }
243  }
244 
245  /*
246  * Build RangeVar for from clause, fully qualified based on the
247  * relation which we have opened and locked.
248  */
251  -1);
252 
253  /* Build query */
254  select = makeNode(SelectStmt);
255  select->targetList = targetList;
256  select->fromClause = list_make1(from);
257 
258  query = makeNode(RawStmt);
259  query->stmt = (Node *) select;
260  query->stmt_location = stmt_location;
261  query->stmt_len = stmt_len;
262 
263  /*
264  * Close the relation for now, but keep the lock on it to prevent
265  * changes between now and when we start the query-based COPY.
266  *
267  * We'll reopen it later as part of the query-based COPY.
268  */
269  table_close(rel, NoLock);
270  rel = NULL;
271  }
272  }
273  else
274  {
275  Assert(stmt->query);
276 
277  query = makeNode(RawStmt);
278  query->stmt = stmt->query;
279  query->stmt_location = stmt_location;
280  query->stmt_len = stmt_len;
281 
282  relid = InvalidOid;
283  rel = NULL;
284  }
285 
286  if (is_from)
287  {
288  CopyFromState cstate;
289 
290  Assert(rel);
291 
292  /* check read-only transaction and parallel mode */
293  if (XactReadOnly && !rel->rd_islocaltemp)
294  PreventCommandIfReadOnly("COPY FROM");
295 
296  cstate = BeginCopyFrom(pstate, rel, whereClause,
297  stmt->filename, stmt->is_program,
298  NULL, stmt->attlist, stmt->options);
299  *processed = CopyFrom(cstate); /* copy from file to database */
300  EndCopyFrom(cstate);
301  }
302  else
303  {
304  CopyToState cstate;
305 
306  cstate = BeginCopyTo(pstate, rel, query, relid,
307  stmt->filename, stmt->is_program,
308  stmt->attlist, stmt->options);
309  *processed = DoCopyTo(cstate); /* copy from database to file */
310  EndCopyTo(cstate);
311  }
312 
313  if (rel != NULL)
314  table_close(rel, NoLock);
315 }
List * indirection
Definition: parsenodes.h:453
#define NIL
Definition: pg_list.h:65
Node * whereClause
Definition: parsenodes.h:2106
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Node * val
Definition: parsenodes.h:454
int errhint(const char *fmt,...)
Definition: elog.c:1156
List * attlist
Definition: parsenodes.h:2100
List * fromClause
Definition: parsenodes.h:1650
#define RelationGetDescr(relation)
Definition: rel.h:495
int LOCKMODE
Definition: lockdefs.h:26
char * name
Definition: parsenodes.h:452
Oid GetUserId(void)
Definition: miscinit.c:478
uint64 CopyFrom(CopyFromState cstate)
Definition: copyfrom.c:525
char * pstrdup(const char *in)
Definition: mcxt.c:1299
bool rd_islocaltemp
Definition: rel.h:60
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:94
#define AccessShareLock
Definition: lockdefs.h:36
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
Definition: nodes.h:539
struct cursor * cur
Definition: ecpg.c:28
int errcode(int sqlerrcode)
Definition: elog.c:698
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2090
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
AclMode requiredPerms
Definition: parsenodes.h:1145
unsigned int Oid
Definition: postgres_ext.h:31
bool is_program
Definition: parsenodes.h:2103
void EndCopyTo(CopyToState cstate)
Definition: copyto.c:760
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
int location
Definition: parsenodes.h:248
int location
Definition: parsenodes.h:455
#define list_make1(x1)
Definition: pg_list.h:206
void assign_expr_collations(ParseState *pstate, Node *expr)
RangeTblEntry * p_rte
Definition: parse_node.h:268
Bitmapset * selectedCols
Definition: parsenodes.h:1147
#define ERROR
Definition: elog.h:46
#define lfirst_int(lc)
Definition: pg_list.h:170
RangeVar * relation
Definition: parsenodes.h:2097
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
Node * stmt
Definition: parsenodes.h:1560
#define NoLock
Definition: lockdefs.h:34
List * targetList
Definition: parsenodes.h:1649
#define RowExclusiveLock
Definition: lockdefs.h:38
Expr * canonicalize_qual(Expr *qual, bool is_check)
Definition: prepqual.c:293
List * options
Definition: parsenodes.h:2105
#define select(n, r, w, e, timeout)
Definition: win32_port.h:464
#define RelationGetRelationName(relation)
Definition: rel.h:503
List * lappend(List *list, void *datum)
Definition: list.c:336
#define ACL_SELECT
Definition: parsenodes.h:83
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:719
int stmt_len
Definition: parsenodes.h:1562
int stmt_location
Definition: parsenodes.h:1561
Relation table_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: table.c:102
#define InvalidOid
Definition: postgres_ext.h:36
CopyToState BeginCopyTo(ParseState *pstate, Relation rel, RawStmt *raw_query, Oid queryRelId, const char *filename, bool is_program, List *attnamelist, List *options)
Definition: copyto.c:342
#define ereport(elevel,...)
Definition: elog.h:157
bool XactReadOnly
Definition: xact.c:78
bool is_member_of_role(Oid member, Oid role)
Definition: acl.c:4869
int check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
Definition: rls.c:52
#define makeNode(_type_)
Definition: nodes.h:587
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:1186
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
#define ACL_INSERT
Definition: parsenodes.h:82
List * CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
Definition: copy.c:686
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:408
void EndCopyFrom(CopyFromState cstate)
Definition: copyfrom.c:1564
Node * query
Definition: parsenodes.h:2098
bool is_from
Definition: parsenodes.h:2102
int errmsg(const char *fmt,...)
Definition: elog.c:909
Bitmapset * insertedCols
Definition: parsenodes.h:1148
bool ExecCheckRTPerms(List *rangeTable, bool ereport_on_violation)
Definition: execMain.c:568
char * filename
Definition: parsenodes.h:2104
uint64 DoCopyTo(CopyToState cstate)
Definition: copyto.c:779
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:469
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:422
List * fields
Definition: parsenodes.h:247
#define RelationGetNamespace(relation)
Definition: rel.h:510
Node * coerce_to_boolean(ParseState *pstate, Node *node, const char *constructName)

◆ DoCopyTo()

uint64 DoCopyTo ( CopyToState  cstate)

Definition at line 779 of file copyto.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, attname, attnum, CopyToStateData::attnumlist, CopyFormatOptions::binary, BinarySignature, CHECK_FOR_INTERRUPTS, CopyAttributeOutCSV(), CopyOneRowTo(), CopySendChar(), CopySendData(), CopySendEndOfRow(), CopySendInt16(), CopySendInt32(), 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().

780 {
781  bool pipe = (cstate->filename == NULL);
782  bool fe_copy = (pipe && whereToSendOutput == DestRemote);
783  TupleDesc tupDesc;
784  int num_phys_attrs;
785  ListCell *cur;
786  uint64 processed;
787 
788  if (fe_copy)
789  SendCopyBegin(cstate);
790 
791  if (cstate->rel)
792  tupDesc = RelationGetDescr(cstate->rel);
793  else
794  tupDesc = cstate->queryDesc->tupDesc;
795  num_phys_attrs = tupDesc->natts;
796  cstate->opts.null_print_client = cstate->opts.null_print; /* default */
797 
798  /* We use fe_msgbuf as a per-row buffer regardless of copy_dest */
799  cstate->fe_msgbuf = makeStringInfo();
800 
801  /* Get info about the columns we need to process. */
802  cstate->out_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
803  foreach(cur, cstate->attnumlist)
804  {
805  int attnum = lfirst_int(cur);
806  Oid out_func_oid;
807  bool isvarlena;
808  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
809 
810  if (cstate->opts.binary)
811  getTypeBinaryOutputInfo(attr->atttypid,
812  &out_func_oid,
813  &isvarlena);
814  else
815  getTypeOutputInfo(attr->atttypid,
816  &out_func_oid,
817  &isvarlena);
818  fmgr_info(out_func_oid, &cstate->out_functions[attnum - 1]);
819  }
820 
821  /*
822  * Create a temporary memory context that we can reset once per row to
823  * recover palloc'd memory. This avoids any problems with leaks inside
824  * datatype output routines, and should be faster than retail pfree's
825  * anyway. (We don't need a whole econtext as CopyFrom does.)
826  */
828  "COPY TO",
830 
831  if (cstate->opts.binary)
832  {
833  /* Generate header for a binary copy */
834  int32 tmp;
835 
836  /* Signature */
837  CopySendData(cstate, BinarySignature, 11);
838  /* Flags field */
839  tmp = 0;
840  CopySendInt32(cstate, tmp);
841  /* No header extension */
842  tmp = 0;
843  CopySendInt32(cstate, tmp);
844  }
845  else
846  {
847  /*
848  * For non-binary copy, we need to convert null_print to file
849  * encoding, because it will be sent directly with CopySendString.
850  */
851  if (cstate->need_transcoding)
853  cstate->opts.null_print_len,
854  cstate->file_encoding);
855 
856  /* if a header has been requested send the line */
857  if (cstate->opts.header_line)
858  {
859  bool hdr_delim = false;
860 
861  foreach(cur, cstate->attnumlist)
862  {
863  int attnum = lfirst_int(cur);
864  char *colname;
865 
866  if (hdr_delim)
867  CopySendChar(cstate, cstate->opts.delim[0]);
868  hdr_delim = true;
869 
870  colname = NameStr(TupleDescAttr(tupDesc, attnum - 1)->attname);
871 
872  CopyAttributeOutCSV(cstate, colname, false,
873  list_length(cstate->attnumlist) == 1);
874  }
875 
876  CopySendEndOfRow(cstate);
877  }
878  }
879 
880  if (cstate->rel)
881  {
882  TupleTableSlot *slot;
883  TableScanDesc scandesc;
884 
885  scandesc = table_beginscan(cstate->rel, GetActiveSnapshot(), 0, NULL);
886  slot = table_slot_create(cstate->rel, NULL);
887 
888  processed = 0;
889  while (table_scan_getnextslot(scandesc, ForwardScanDirection, slot))
890  {
892 
893  /* Deconstruct the tuple ... */
894  slot_getallattrs(slot);
895 
896  /* Format and send the data */
897  CopyOneRowTo(cstate, slot);
898 
899  /*
900  * Increment the number of processed tuples, and report the
901  * progress.
902  */
904  ++processed);
905  }
906 
908  table_endscan(scandesc);
909  }
910  else
911  {
912  /* run the plan --- the dest receiver will send tuples */
913  ExecutorRun(cstate->queryDesc, ForwardScanDirection, 0L, true);
914  processed = ((DR_copy *) cstate->queryDesc->dest)->processed;
915  }
916 
917  if (cstate->opts.binary)
918  {
919  /* Generate trailer for a binary copy */
920  CopySendInt16(cstate, -1);
921  /* Need to flush out the trailer */
922  CopySendEndOfRow(cstate);
923  }
924 
926 
927  if (fe_copy)
928  SendCopyEnd(cstate);
929 
930  return processed;
931 }
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition: tableam.c:91
int file_encoding
Definition: copyto.c:78
Definition: fmgr.h:56
int null_print_len
Definition: copy.h:37
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
#define AllocSetContextCreate
Definition: memutils.h:173
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2854
Relation rel
Definition: copyto.c:83
static void CopyAttributeOutCSV(CopyToState cstate, char *string, bool use_quote, bool single_attr)
Definition: copyto.c:1171
bool need_transcoding
Definition: copyto.c:79
FmgrInfo * out_functions
Definition: copyto.c:97
#define RelationGetDescr(relation)
Definition: rel.h:495
static void SendCopyEnd(CopyToState cstate)
Definition: copyto.c:156
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:786
static void CopySendInt16(CopyToState cstate, int16 val)
Definition: copyto.c:280
struct cursor * cur
Definition: ecpg.c:28
char * null_print_client
Definition: copy.h:38
MemoryContext rowcontext
Definition: copyto.c:98
static bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
Definition: tableam.h:1032
unsigned int Oid
Definition: postgres_ext.h:31
char * null_print
Definition: copy.h:36
char * pg_server_to_any(const char *s, int len, int encoding)
Definition: mbutils.c:749
signed int int32
Definition: c.h:429
static void CopyOneRowTo(CopyToState cstate, TupleTableSlot *slot)
Definition: copyto.c:937
QueryDesc * queryDesc
Definition: copyto.c:84
static void SendCopyBegin(CopyToState cstate)
Definition: copyto.c:139
List * attnumlist
Definition: copyto.c:85
NameData attname
Definition: pg_attribute.h:41
static TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key)
Definition: tableam.h:883
#define lfirst_int(lc)
Definition: pg_list.h:170
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:298
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
bool binary
Definition: copy.h:32
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:354
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1254
bool header_line
Definition: copy.h:35
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
static void CopySendInt32(CopyToState cstate, int32 val)
Definition: copyto.c:268
TupleDesc tupDesc
Definition: execdesc.h:47
StringInfo fe_msgbuf
Definition: copyto.c:76
void getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
Definition: lsyscache.c:2920
char * delim
Definition: copy.h:39
static void CopySendData(CopyToState cstate, const void *databuf, int datasize)
Definition: copyto.c:175
#define PROGRESS_COPY_TUPLES_PROCESSED
Definition: progress.h:139
int16 attnum
Definition: pg_attribute.h:83
void pgstat_progress_update_param(int index, int64 val)
static const char BinarySignature[11]
Definition: copyto.c:112
static int list_length(const List *l)
Definition: pg_list.h:149
CopyFormatOptions opts
Definition: copyto.c:89
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:991
DestReceiver * dest
Definition: execdesc.h:41
void * palloc(Size size)
Definition: mcxt.c:1062
static void CopySendChar(CopyToState cstate, char c)
Definition: copyto.c:187
#define NameStr(name)
Definition: c.h:681
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120
CommandDest whereToSendOutput
Definition: postgres.c:92
char * filename
Definition: copyto.c:86
static void CopySendEndOfRow(CopyToState cstate)
Definition: copyto.c:193

◆ EndCopyFrom()

void EndCopyFrom ( CopyFromState  cstate)

Definition at line 1564 of file copyfrom.c.

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

1565 {
1566  /* No COPY FROM related resources except memory. */
1567  if (cstate->is_program)
1568  {
1569  ClosePipeFromProgram(cstate);
1570  }
1571  else
1572  {
1573  if (cstate->filename != NULL && FreeFile(cstate->copy_file))
1574  ereport(ERROR,
1576  errmsg("could not close file \"%s\": %m",
1577  cstate->filename)));
1578  }
1579 
1581 
1583  pfree(cstate);
1584 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
void pgstat_progress_end_command(void)
MemoryContext copycontext
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ERROR
Definition: elog.h:46
static void ClosePipeFromProgram(CopyFromState cstate)
Definition: copyfrom.c:1590
int errcode_for_file_access(void)
Definition: elog.c:721
#define ereport(elevel,...)
Definition: elog.h:157
int FreeFile(FILE *file)
Definition: fd.c:2572
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ EndCopyTo()

void EndCopyTo ( CopyToState  cstate)

Definition at line 760 of file copyto.c.

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

Referenced by DoCopy().

761 {
762  if (cstate->queryDesc != NULL)
763  {
764  /* Close down the query and free resources. */
765  ExecutorFinish(cstate->queryDesc);
766  ExecutorEnd(cstate->queryDesc);
767  FreeQueryDesc(cstate->queryDesc);
769  }
770 
771  /* Clean up storage */
772  EndCopy(cstate);
773 }
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:105
void PopActiveSnapshot(void)
Definition: snapmgr.c:759
static void EndCopy(CopyToState cstate)
Definition: copyto.c:317
QueryDesc * queryDesc
Definition: copyto.c:84
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:459
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:399

◆ NextCopyFrom()

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

Definition at line 804 of file copyfromparse.c.

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, and CopyFromStateData::typioparams.

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

806 {
807  TupleDesc tupDesc;
808  AttrNumber num_phys_attrs,
809  attr_count,
810  num_defaults = cstate->num_defaults;
811  FmgrInfo *in_functions = cstate->in_functions;
812  Oid *typioparams = cstate->typioparams;
813  int i;
814  int *defmap = cstate->defmap;
815  ExprState **defexprs = cstate->defexprs;
816 
817  tupDesc = RelationGetDescr(cstate->rel);
818  num_phys_attrs = tupDesc->natts;
819  attr_count = list_length(cstate->attnumlist);
820 
821  /* Initialize all values for row to NULL */
822  MemSet(values, 0, num_phys_attrs * sizeof(Datum));
823  MemSet(nulls, true, num_phys_attrs * sizeof(bool));
824 
825  if (!cstate->opts.binary)
826  {
827  char **field_strings;
828  ListCell *cur;
829  int fldct;
830  int fieldno;
831  char *string;
832 
833  /* read raw fields in the next line */
834  if (!NextCopyFromRawFields(cstate, &field_strings, &fldct))
835  return false;
836 
837  /* check for overflowing fields */
838  if (attr_count > 0 && fldct > attr_count)
839  ereport(ERROR,
840  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
841  errmsg("extra data after last expected column")));
842 
843  fieldno = 0;
844 
845  /* Loop to read the user attributes on the line. */
846  foreach(cur, cstate->attnumlist)
847  {
848  int attnum = lfirst_int(cur);
849  int m = attnum - 1;
850  Form_pg_attribute att = TupleDescAttr(tupDesc, m);
851 
852  if (fieldno >= fldct)
853  ereport(ERROR,
854  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
855  errmsg("missing data for column \"%s\"",
856  NameStr(att->attname))));
857  string = field_strings[fieldno++];
858 
859  if (cstate->convert_select_flags &&
860  !cstate->convert_select_flags[m])
861  {
862  /* ignore input field, leaving column as NULL */
863  continue;
864  }
865 
866  if (cstate->opts.csv_mode)
867  {
868  if (string == NULL &&
869  cstate->opts.force_notnull_flags[m])
870  {
871  /*
872  * FORCE_NOT_NULL option is set and column is NULL -
873  * convert it to the NULL string.
874  */
875  string = cstate->opts.null_print;
876  }
877  else if (string != NULL && cstate->opts.force_null_flags[m]
878  && strcmp(string, cstate->opts.null_print) == 0)
879  {
880  /*
881  * FORCE_NULL option is set and column matches the NULL
882  * string. It must have been quoted, or otherwise the
883  * string would already have been set to NULL. Convert it
884  * to NULL as specified.
885  */
886  string = NULL;
887  }
888  }
889 
890  cstate->cur_attname = NameStr(att->attname);
891  cstate->cur_attval = string;
892  values[m] = InputFunctionCall(&in_functions[m],
893  string,
894  typioparams[m],
895  att->atttypmod);
896  if (string != NULL)
897  nulls[m] = false;
898  cstate->cur_attname = NULL;
899  cstate->cur_attval = NULL;
900  }
901 
902  Assert(fieldno == attr_count);
903  }
904  else
905  {
906  /* binary */
907  int16 fld_count;
908  ListCell *cur;
909 
910  cstate->cur_lineno++;
911 
912  if (!CopyGetInt16(cstate, &fld_count))
913  {
914  /* EOF detected (end of file, or protocol-level EOF) */
915  return false;
916  }
917 
918  if (fld_count == -1)
919  {
920  /*
921  * Received EOF marker. Wait for the protocol-level EOF, and
922  * complain if it doesn't come immediately. In COPY FROM STDIN,
923  * this ensures that we correctly handle CopyFail, if client
924  * chooses to send that now. When copying from file, we could
925  * ignore the rest of the file like in text mode, but we choose to
926  * be consistent with the COPY FROM STDIN case.
927  */
928  char dummy;
929 
930  if (CopyReadBinaryData(cstate, &dummy, 1) > 0)
931  ereport(ERROR,
932  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
933  errmsg("received copy data after EOF marker")));
934  return false;
935  }
936 
937  if (fld_count != attr_count)
938  ereport(ERROR,
939  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
940  errmsg("row field count is %d, expected %d",
941  (int) fld_count, attr_count)));
942 
943  foreach(cur, cstate->attnumlist)
944  {
945  int attnum = lfirst_int(cur);
946  int m = attnum - 1;
947  Form_pg_attribute att = TupleDescAttr(tupDesc, m);
948 
949  cstate->cur_attname = NameStr(att->attname);
950  values[m] = CopyReadBinaryAttribute(cstate,
951  &in_functions[m],
952  typioparams[m],
953  att->atttypmod,
954  &nulls[m]);
955  cstate->cur_attname = NULL;
956  }
957  }
958 
959  /*
960  * Now compute and insert any defaults available for the columns not
961  * provided by the input data. Anything not processed here or above will
962  * remain NULL.
963  */
964  for (i = 0; i < num_defaults; i++)
965  {
966  /*
967  * The caller must supply econtext and have switched into the
968  * per-tuple memory context in it.
969  */
970  Assert(econtext != NULL);
972 
973  values[defmap[i]] = ExecEvalExpr(defexprs[i], econtext,
974  &nulls[defmap[i]]);
975  }
976 
977  return true;
978 }
signed short int16
Definition: c.h:428
Definition: fmgr.h:56
bool NextCopyFromRawFields(CopyFromState cstate, char ***fields, int *nfields)
const char * cur_attname
#define RelationGetDescr(relation)
Definition: rel.h:495
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:234
struct cursor * cur
Definition: ecpg.c:28
int errcode(int sqlerrcode)
Definition: elog.c:698
static bool CopyGetInt16(CopyFromState cstate, int16 *val)
#define MemSet(start, val, len)
Definition: c.h:1008
const char * cur_attval
unsigned int Oid
Definition: postgres_ext.h:31
char * null_print
Definition: copy.h:36
static int CopyReadBinaryData(CopyFromState cstate, char *dest, int nbytes)
ExprState ** defexprs
#define ERROR
Definition: elog.h:46
#define lfirst_int(lc)
Definition: pg_list.h:170
bool binary
Definition: copy.h:32
bool csv_mode
Definition: copy.h:34
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:316
char string[11]
Definition: preproc-type.c:46
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
uintptr_t Datum
Definition: postgres.h:411
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1529
int16 attnum
Definition: pg_attribute.h:83
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
bool * force_null_flags
Definition: copy.h:48
static int list_length(const List *l)
Definition: pg_list.h:149
CopyFormatOptions opts
static Datum values[MAXATTR]
Definition: bootstrap.c:166
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
#define NameStr(name)
Definition: c.h:681
static Datum CopyReadBinaryAttribute(CopyFromState cstate, FmgrInfo *flinfo, Oid typioparam, int32 typmod, bool *isnull)
int16 AttrNumber
Definition: attnum.h:21
bool * force_notnull_flags
Definition: copy.h:46

◆ NextCopyFromRawFields()

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

Definition at line 753 of file copyfromparse.c.

References Assert, CopyFormatOptions::binary, CopyReadAttributesCSV(), CopyReadAttributesText(), CopyReadLine(), CopyFormatOptions::csv_mode, CopyFromStateData::cur_lineno, CopyFormatOptions::header_line, StringInfoData::len, CopyFromStateData::line_buf, CopyFromStateData::opts, and CopyFromStateData::raw_fields.

Referenced by NextCopyFrom().

754 {
755  int fldct;
756  bool done;
757 
758  /* only available for text or csv input */
759  Assert(!cstate->opts.binary);
760 
761  /* on input just throw the header line away */
762  if (cstate->cur_lineno == 0 && cstate->opts.header_line)
763  {
764  cstate->cur_lineno++;
765  if (CopyReadLine(cstate))
766  return false; /* done */
767  }
768 
769  cstate->cur_lineno++;
770 
771  /* Actually read the line into memory here */
772  done = CopyReadLine(cstate);
773 
774  /*
775  * EOF at start of line means we're done. If we see EOF after some
776  * characters, we act as though it was newline followed by EOF, ie,
777  * process the line and then exit loop on next iteration.
778  */
779  if (done && cstate->line_buf.len == 0)
780  return false;
781 
782  /* Parse the line into de-escaped field values */
783  if (cstate->opts.csv_mode)
784  fldct = CopyReadAttributesCSV(cstate);
785  else
786  fldct = CopyReadAttributesText(cstate);
787 
788  *fields = cstate->raw_fields;
789  *nfields = fldct;
790  return true;
791 }
StringInfoData line_buf
static bool CopyReadLine(CopyFromState cstate)
bool binary
Definition: copy.h:32
bool csv_mode
Definition: copy.h:34
bool header_line
Definition: copy.h:35
static int CopyReadAttributesText(CopyFromState cstate)
#define Assert(condition)
Definition: c.h:804
CopyFormatOptions opts
static int CopyReadAttributesCSV(CopyFromState cstate)

◆ ProcessCopyOptions()

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

Definition at line 334 of file copy.c.

References DefElem::arg, CopyFormatOptions::binary, castNode, CopyFormatOptions::convert_select, CopyFormatOptions::convert_selectively, CopyFormatOptions::csv_mode, defGetBoolean(), defGetString(), DefElem::defname, CopyFormatOptions::delim, ereport, errcode(), errmsg(), ERROR, CopyFormatOptions::escape, CopyFormatOptions::file_encoding, 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().

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