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.

Typedefs

typedef struct CopyStateDataCopyState
 
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, CopyState cstate, bool is_from, List *options)
 
CopyState BeginCopyFrom (ParseState *pstate, Relation rel, const char *filename, bool is_program, copy_data_source_cb data_source_cb, List *attnamelist, List *options)
 
void EndCopyFrom (CopyState cstate)
 
bool NextCopyFrom (CopyState cstate, ExprContext *econtext, Datum *values, bool *nulls)
 
bool NextCopyFromRawFields (CopyState cstate, char ***fields, int *nfields)
 
void CopyFromErrorCallback (void *arg)
 
uint64 CopyFrom (CopyState cstate)
 
DestReceiverCreateCopyDestReceiver (void)
 

Typedef Documentation

◆ copy_data_source_cb

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

Definition at line 24 of file copy.h.

◆ CopyState

typedef struct CopyStateData* CopyState

Definition at line 23 of file copy.h.

Function Documentation

◆ BeginCopyFrom()

CopyState BeginCopyFrom ( ParseState pstate,
Relation  rel,
const char *  filename,
bool  is_program,
copy_data_source_cb  data_source_cb,
List attnamelist,
List options 
)

Definition at line 3383 of file copy.c.

References AllocateFile(), Assert, attnum, CopyStateData::attnumlist, CopyStateData::attribute_buf, BeginCopy(), CopyStateData::binary, BinarySignature, build_column_default(), contain_volatile_functions_not_nextval(), COPY_CALLBACK, CopyStateData::copy_dest, CopyStateData::copy_file, CopyStateData::copycontext, CopyGetInt32(), CopyReadBinaryData(), CopyStateData::cur_attname, CopyStateData::cur_attval, CopyStateData::cur_lineno, CopyStateData::cur_relname, CopyStateData::data_source_cb, CopyStateData::defexprs, CopyStateData::defmap, DestRemote, CopyStateData::eol_type, EOL_UNKNOWN, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), ERROR, ExecInitExpr(), expression_planner(), CopyStateData::filename, fmgr_info(), getTypeBinaryInputInfo(), getTypeInputInfo(), CopyStateData::in_functions, initStringInfo(), InvalidOid, CopyStateData::is_program, CopyStateData::line_buf, CopyStateData::line_buf_converted, list_length(), list_member_int(), CopyStateData::max_fields, MemoryContextSwitchTo(), TupleDescData::natts, CopyStateData::num_defaults, OpenPipeStream(), ParseState::p_rtable, palloc(), PG_BINARY_R, pstrdup(), CopyStateData::range_table, CopyStateData::raw_buf, CopyStateData::raw_buf_index, CopyStateData::raw_buf_len, RAW_BUF_SIZE, CopyStateData::raw_fields, CopyStateData::reached_eof, ReceiveCopyBegin(), CopyStateData::rel, RelationGetDescr, RelationGetRelationName, S_ISDIR, stat, TupleDescAttr, CopyStateData::typioparams, CopyStateData::volatile_defexprs, and whereToSendOutput.

Referenced by copy_table(), DoCopy(), file_acquire_sample_rows(), fileBeginForeignScan(), and fileReScanForeignScan().

3390 {
3391  CopyState cstate;
3392  bool pipe = (filename == NULL);
3393  TupleDesc tupDesc;
3394  AttrNumber num_phys_attrs,
3395  num_defaults;
3396  FmgrInfo *in_functions;
3397  Oid *typioparams;
3398  int attnum;
3399  Oid in_func_oid;
3400  int *defmap;
3401  ExprState **defexprs;
3402  MemoryContext oldcontext;
3403  bool volatile_defexprs;
3404 
3405  cstate = BeginCopy(pstate, true, rel, NULL, InvalidOid, attnamelist, options);
3406  oldcontext = MemoryContextSwitchTo(cstate->copycontext);
3407 
3408  /* Initialize state variables */
3409  cstate->reached_eof = false;
3410  cstate->eol_type = EOL_UNKNOWN;
3411  cstate->cur_relname = RelationGetRelationName(cstate->rel);
3412  cstate->cur_lineno = 0;
3413  cstate->cur_attname = NULL;
3414  cstate->cur_attval = NULL;
3415 
3416  /*
3417  * Set up variables to avoid per-attribute overhead. attribute_buf and
3418  * raw_buf are used in both text and binary modes, but we use line_buf
3419  * only in text mode.
3420  */
3421  initStringInfo(&cstate->attribute_buf);
3422  cstate->raw_buf = (char *) palloc(RAW_BUF_SIZE + 1);
3423  cstate->raw_buf_index = cstate->raw_buf_len = 0;
3424  if (!cstate->binary)
3425  {
3426  initStringInfo(&cstate->line_buf);
3427  cstate->line_buf_converted = false;
3428  }
3429 
3430  /* Assign range table, we'll need it in CopyFrom. */
3431  if (pstate)
3432  cstate->range_table = pstate->p_rtable;
3433 
3434  tupDesc = RelationGetDescr(cstate->rel);
3435  num_phys_attrs = tupDesc->natts;
3436  num_defaults = 0;
3437  volatile_defexprs = false;
3438 
3439  /*
3440  * Pick up the required catalog information for each attribute in the
3441  * relation, including the input function, the element type (to pass to
3442  * the input function), and info about defaults and constraints. (Which
3443  * input function we use depends on text/binary format choice.)
3444  */
3445  in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
3446  typioparams = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
3447  defmap = (int *) palloc(num_phys_attrs * sizeof(int));
3448  defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *));
3449 
3450  for (attnum = 1; attnum <= num_phys_attrs; attnum++)
3451  {
3452  Form_pg_attribute att = TupleDescAttr(tupDesc, attnum - 1);
3453 
3454  /* We don't need info for dropped attributes */
3455  if (att->attisdropped)
3456  continue;
3457 
3458  /* Fetch the input function and typioparam info */
3459  if (cstate->binary)
3460  getTypeBinaryInputInfo(att->atttypid,
3461  &in_func_oid, &typioparams[attnum - 1]);
3462  else
3463  getTypeInputInfo(att->atttypid,
3464  &in_func_oid, &typioparams[attnum - 1]);
3465  fmgr_info(in_func_oid, &in_functions[attnum - 1]);
3466 
3467  /* Get default info if needed */
3468  if (!list_member_int(cstate->attnumlist, attnum) && !att->attgenerated)
3469  {
3470  /* attribute is NOT to be copied from input */
3471  /* use default value if one exists */
3472  Expr *defexpr = (Expr *) build_column_default(cstate->rel,
3473  attnum);
3474 
3475  if (defexpr != NULL)
3476  {
3477  /* Run the expression through planner */
3478  defexpr = expression_planner(defexpr);
3479 
3480  /* Initialize executable expression in copycontext */
3481  defexprs[num_defaults] = ExecInitExpr(defexpr, NULL);
3482  defmap[num_defaults] = attnum - 1;
3483  num_defaults++;
3484 
3485  /*
3486  * If a default expression looks at the table being loaded,
3487  * then it could give the wrong answer when using
3488  * multi-insert. Since database access can be dynamic this is
3489  * hard to test for exactly, so we use the much wider test of
3490  * whether the default expression is volatile. We allow for
3491  * the special case of when the default expression is the
3492  * nextval() of a sequence which in this specific case is
3493  * known to be safe for use with the multi-insert
3494  * optimization. Hence we use this special case function
3495  * checker rather than the standard check for
3496  * contain_volatile_functions().
3497  */
3498  if (!volatile_defexprs)
3499  volatile_defexprs = contain_volatile_functions_not_nextval((Node *) defexpr);
3500  }
3501  }
3502  }
3503 
3504  /* We keep those variables in cstate. */
3505  cstate->in_functions = in_functions;
3506  cstate->typioparams = typioparams;
3507  cstate->defmap = defmap;
3508  cstate->defexprs = defexprs;
3509  cstate->volatile_defexprs = volatile_defexprs;
3510  cstate->num_defaults = num_defaults;
3511  cstate->is_program = is_program;
3512 
3513  if (data_source_cb)
3514  {
3515  cstate->copy_dest = COPY_CALLBACK;
3516  cstate->data_source_cb = data_source_cb;
3517  }
3518  else if (pipe)
3519  {
3520  Assert(!is_program); /* the grammar does not allow this */
3522  ReceiveCopyBegin(cstate);
3523  else
3524  cstate->copy_file = stdin;
3525  }
3526  else
3527  {
3528  cstate->filename = pstrdup(filename);
3529 
3530  if (cstate->is_program)
3531  {
3532  cstate->copy_file = OpenPipeStream(cstate->filename, PG_BINARY_R);
3533  if (cstate->copy_file == NULL)
3534  ereport(ERROR,
3536  errmsg("could not execute command \"%s\": %m",
3537  cstate->filename)));
3538  }
3539  else
3540  {
3541  struct stat st;
3542 
3543  cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_R);
3544  if (cstate->copy_file == NULL)
3545  {
3546  /* copy errno because ereport subfunctions might change it */
3547  int save_errno = errno;
3548 
3549  ereport(ERROR,
3551  errmsg("could not open file \"%s\" for reading: %m",
3552  cstate->filename),
3553  (save_errno == ENOENT || save_errno == EACCES) ?
3554  errhint("COPY FROM instructs the PostgreSQL server process to read a file. "
3555  "You may want a client-side facility such as psql's \\copy.") : 0));
3556  }
3557 
3558  if (fstat(fileno(cstate->copy_file), &st))
3559  ereport(ERROR,
3561  errmsg("could not stat file \"%s\": %m",
3562  cstate->filename)));
3563 
3564  if (S_ISDIR(st.st_mode))
3565  ereport(ERROR,
3566  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3567  errmsg("\"%s\" is a directory", cstate->filename)));
3568  }
3569  }
3570 
3571  if (cstate->binary)
3572  {
3573  /* Read and verify binary header */
3574  char readSig[11];
3575  int32 tmp;
3576 
3577  /* Signature */
3578  if (CopyReadBinaryData(cstate, readSig, 11) != 11 ||
3579  memcmp(readSig, BinarySignature, 11) != 0)
3580  ereport(ERROR,
3581  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
3582  errmsg("COPY file signature not recognized")));
3583  /* Flags field */
3584  if (!CopyGetInt32(cstate, &tmp))
3585  ereport(ERROR,
3586  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
3587  errmsg("invalid COPY file header (missing flags)")));
3588  if ((tmp & (1 << 16)) != 0)
3589  ereport(ERROR,
3590  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
3591  errmsg("invalid COPY file header (WITH OIDS)")));
3592  tmp &= ~(1 << 16);
3593  if ((tmp >> 16) != 0)
3594  ereport(ERROR,
3595  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
3596  errmsg("unrecognized critical flags in COPY file header")));
3597  /* Header extension length */
3598  if (!CopyGetInt32(cstate, &tmp) ||
3599  tmp < 0)
3600  ereport(ERROR,
3601  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
3602  errmsg("invalid COPY file header (missing length)")));
3603  /* Skip extension header, if present */
3604  while (tmp-- > 0)
3605  {
3606  if (CopyReadBinaryData(cstate, readSig, 1) != 1)
3607  ereport(ERROR,
3608  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
3609  errmsg("invalid COPY file header (wrong length)")));
3610  }
3611  }
3612 
3613  /* create workspace for CopyReadAttributes results */
3614  if (!cstate->binary)
3615  {
3616  AttrNumber attr_count = list_length(cstate->attnumlist);
3617 
3618  cstate->max_fields = attr_count;
3619  cstate->raw_fields = (char **) palloc(attr_count * sizeof(char *));
3620  }
3621 
3622  MemoryContextSwitchTo(oldcontext);
3623 
3624  return cstate;
3625 }
Definition: fmgr.h:56
List * range_table
Definition: copy.c:184
static CopyState BeginCopy(ParseState *pstate, bool is_from, Relation rel, RawStmt *raw_query, Oid queryRelId, List *attnamelist, List *options)
Definition: copy.c:1507
bool contain_volatile_functions_not_nextval(Node *clause)
Definition: clauses.c:776
static bool CopyGetInt32(CopyState cstate, int32 *val)
Definition: copy.c:747
int errhint(const char *fmt,...)
Definition: elog.c:1071
char ** raw_fields
Definition: copy.c:205
bool binary
Definition: copy.c:136
#define RelationGetDescr(relation)
Definition: rel.h:482
AttrNumber num_defaults
Definition: copy.c:178
FmgrInfo * in_functions
Definition: copy.c:179
List * attnumlist
Definition: copy.c:132
char * filename
Definition: copy.c:133
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
char * pstrdup(const char *in)
Definition: mcxt.c:1186
static void ReceiveCopyBegin(CopyState cstate)
Definition: copy.c:443
Expr * expression_planner(Expr *expr)
Definition: planner.c:6151
StringInfoData line_buf
Definition: copy.c:215
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:529
int raw_buf_index
Definition: copy.c:229
int errcode(int sqlerrcode)
Definition: elog.c:610
unsigned int Oid
Definition: postgres_ext.h:31
bool volatile_defexprs
Definition: copy.c:183
#define PG_BINARY_R
Definition: c.h:1242
bool line_buf_converted
Definition: copy.c:216
signed int int32
Definition: c.h:362
CopyDest copy_dest
Definition: copy.c:117
uint64 cur_lineno
Definition: copy.c:160
const char * cur_attname
Definition: copy.c:161
Relation rel
Definition: copy.c:130
MemoryContext copycontext
Definition: copy.c:167
copy_data_source_cb data_source_cb
Definition: copy.c:135
#define ERROR
Definition: elog.h:43
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
bool list_member_int(const List *list, int datum)
Definition: list.c:654
char * raw_buf
Definition: copy.c:228
ExprState ** defexprs
Definition: copy.c:182
const char * cur_relname
Definition: copy.c:159
int errcode_for_file_access(void)
Definition: elog.c:633
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2322
#define RelationGetRelationName(relation)
Definition: rel.h:490
static const char BinarySignature[11]
Definition: copy.c:357
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
int raw_buf_len
Definition: copy.c:230
static int CopyReadBinaryData(CopyState cstate, char *dest, int nbytes)
Definition: copy.c:827
int max_fields
Definition: copy.c:204
FILE * OpenPipeStream(const char *command, const char *mode)
Definition: fd.c:2425
void getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
Definition: lsyscache.c:2817
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2751
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define stat(a, b)
Definition: win32_port.h:255
Oid * typioparams
Definition: copy.c:180
bool is_program
Definition: copy.c:134
Node * build_column_default(Relation rel, int attrno)
#define RAW_BUF_SIZE
Definition: copy.c:227
#define InvalidOid
Definition: postgres_ext.h:36
int16 attnum
Definition: pg_attribute.h:79
#define ereport(elevel,...)
Definition: elog.h:144
EolType eol_type
Definition: copy.c:124
#define Assert(condition)
Definition: c.h:745
bool reached_eof
Definition: copy.c:122
static int list_length(const List *l)
Definition: pg_list.h:169
#define S_ISDIR(m)
Definition: win32_port.h:296
static char * filename
Definition: pg_dumpall.c:90
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
FILE * copy_file
Definition: copy.c:118
StringInfoData attribute_buf
Definition: copy.c:200
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:123
const char * cur_attval
Definition: copy.c:162
CommandDest whereToSendOutput
Definition: postgres.c:91
int16 AttrNumber
Definition: attnum.h:21
int * defmap
Definition: copy.c:181
List * p_rtable
Definition: parse_node.h:180

◆ CopyFrom()

uint64 CopyFrom ( CopyState  cstate)

Definition at line 2702 of file copy.c.

References AfterTriggerBeginQuery(), AfterTriggerEndQuery(), ErrorContextCallback::arg, Assert, TupleConversionMap::attrMap, FdwRoutine::BeginForeignInsert, ErrorContextCallback::callback, castNode, CHECK_FOR_INTERRUPTS, CheckValidResultRel(), CIM_MULTI, CIM_MULTI_CONDITIONAL, CIM_SINGLE, CMD_INSERT, TupleDescData::constr, contain_volatile_functions(), CopyStateData::copy_dest, COPY_OLD_FE, CopyFromErrorCallback(), CopyMultiInsertInfoCleanup(), CopyMultiInsertInfoFlush(), CopyMultiInsertInfoInit(), CopyMultiInsertInfoIsEmpty(), CopyMultiInsertInfoIsFull(), CopyMultiInsertInfoNextFreeSlot(), CopyMultiInsertInfoSetupBuffer(), CopyMultiInsertInfoStore(), CreateExecutorState(), CopyStateData::cur_lineno, CurrentMemoryContext, ExprContext::ecxt_scantuple, FdwRoutine::EndForeignInsert, ereport, errcode(), errhint(), errmsg(), ERROR, error_context_stack, EState::es_num_result_relations, EState::es_result_relation_info, EState::es_result_relations, EState::es_tupleTable, ExecARInsertTriggers(), ExecASInsertTriggers(), ExecBRInsertTriggers(), ExecBSInsertTriggers(), ExecCleanUpTriggerState(), ExecCleanupTupleRouting(), ExecClearTuple(), ExecCloseIndices(), ExecComputeStoredGenerated(), ExecConstraints(), ExecCopySlot(), ExecFindPartition(), FdwRoutine::ExecForeignInsert, ExecInitQual(), ExecInitRangeTable(), ExecInsertIndexTuples(), ExecIRInsertTriggers(), ExecMaterializeSlot(), ExecOpenIndices(), ExecPartitionCheck(), ExecQual(), ExecResetTupleTable(), ExecSetupPartitionTupleRouting(), ExecStoreVirtualTuple(), execute_attr_map_slot(), FreeBulkInsertState(), FreeExecutorState(), CopyStateData::freeze, GetBulkInsertState(), GetCurrentCommandId(), GetCurrentSubTransactionId(), GetPerTupleExprContext, GetPerTupleMemoryContext, TupleConstr::has_generated_stored, InitResultRelInfo(), InvalidateCatalogSnapshot(), InvalidSubTransactionId, StringInfoData::len, CopyStateData::line_buf, list_free(), makeNode, MakeTransitionCaptureState(), MemoryContextSwitchTo(), ModifyTableState::mt_transition_capture, NextCopyFrom(), NIL, ModifyTableState::operation, PartitionRoutingInfo::pi_PartitionToRootMap, PartitionRoutingInfo::pi_PartitionTupleSlot, PartitionRoutingInfo::pi_RootToPartitionMap, PlanState::plan, pq_endmsgread(), ErrorContextCallback::previous, ModifyTableState::ps, CopyStateData::qualexpr, CopyStateData::range_table, RelationData::rd_att, RelationData::rd_createSubid, RelationData::rd_firstRelfilenodeSubid, RelationData::rd_newRelfilenodeSubid, RelationData::rd_rel, CopyStateData::rel, RelationGetRelationName, RelationGetRelid, ReleaseBulkInsertStatePin(), ResetPerTupleExprContext, ModifyTableState::resultRelInfo, ResultRelInfo::ri_CopyMultiInsertBuffer, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_PartitionCheck, ResultRelInfo::ri_PartitionInfo, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, PlanState::state, TABLE_INSERT_FROZEN, TABLE_INSERT_SKIP_FSM, table_slot_create(), table_tuple_insert(), TransitionCaptureState::tcs_map, TransitionCaptureState::tcs_original_insert_tuple, ThereAreNoPriorRegisteredSnapshots(), ThereAreNoReadyPortals(), CopyStateData::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, CopyStateData::volatile_defexprs, and CopyStateData::whereClause.

Referenced by copy_table(), and DoCopy().

2703 {
2704  ResultRelInfo *resultRelInfo;
2705  ResultRelInfo *target_resultRelInfo;
2706  ResultRelInfo *prevResultRelInfo = NULL;
2707  EState *estate = CreateExecutorState(); /* for ExecConstraints() */
2708  ModifyTableState *mtstate;
2709  ExprContext *econtext;
2710  TupleTableSlot *singleslot = NULL;
2711  MemoryContext oldcontext = CurrentMemoryContext;
2712 
2713  PartitionTupleRouting *proute = NULL;
2714  ErrorContextCallback errcallback;
2715  CommandId mycid = GetCurrentCommandId(true);
2716  int ti_options = 0; /* start with default options for insert */
2717  BulkInsertState bistate = NULL;
2718  CopyInsertMethod insertMethod;
2719  CopyMultiInsertInfo multiInsertInfo = {0}; /* pacify compiler */
2720  uint64 processed = 0;
2721  bool has_before_insert_row_trig;
2722  bool has_instead_insert_row_trig;
2723  bool leafpart_use_multi_insert = false;
2724 
2725  Assert(cstate->rel);
2726 
2727  /*
2728  * The target must be a plain, foreign, or partitioned relation, or have
2729  * an INSTEAD OF INSERT row trigger. (Currently, such triggers are only
2730  * allowed on views, so we only hint about them in the view case.)
2731  */
2732  if (cstate->rel->rd_rel->relkind != RELKIND_RELATION &&
2733  cstate->rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
2734  cstate->rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE &&
2735  !(cstate->rel->trigdesc &&
2737  {
2738  if (cstate->rel->rd_rel->relkind == RELKIND_VIEW)
2739  ereport(ERROR,
2740  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2741  errmsg("cannot copy to view \"%s\"",
2742  RelationGetRelationName(cstate->rel)),
2743  errhint("To enable copying to a view, provide an INSTEAD OF INSERT trigger.")));
2744  else if (cstate->rel->rd_rel->relkind == RELKIND_MATVIEW)
2745  ereport(ERROR,
2746  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2747  errmsg("cannot copy to materialized view \"%s\"",
2748  RelationGetRelationName(cstate->rel))));
2749  else if (cstate->rel->rd_rel->relkind == RELKIND_SEQUENCE)
2750  ereport(ERROR,
2751  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2752  errmsg("cannot copy to sequence \"%s\"",
2753  RelationGetRelationName(cstate->rel))));
2754  else
2755  ereport(ERROR,
2756  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2757  errmsg("cannot copy to non-table relation \"%s\"",
2758  RelationGetRelationName(cstate->rel))));
2759  }
2760 
2761  /*
2762  * If the target file is new-in-transaction, we assume that checking FSM
2763  * for free space is a waste of time. This could possibly be wrong, but
2764  * it's unlikely.
2765  */
2766  if (RELKIND_HAS_STORAGE(cstate->rel->rd_rel->relkind) &&
2769  ti_options |= TABLE_INSERT_SKIP_FSM;
2770 
2771  /*
2772  * Optimize if new relfilenode was created in this subxact or one of its
2773  * committed children and we won't see those rows later as part of an
2774  * earlier scan or command. The subxact test ensures that if this subxact
2775  * aborts then the frozen rows won't be visible after xact cleanup. Note
2776  * that the stronger test of exactly which subtransaction created it is
2777  * crucial for correctness of this optimization. The test for an earlier
2778  * scan or command tolerates false negatives. FREEZE causes other sessions
2779  * to see rows they would not see under MVCC, and a false negative merely
2780  * spreads that anomaly to the current session.
2781  */
2782  if (cstate->freeze)
2783  {
2784  /*
2785  * We currently disallow COPY FREEZE on partitioned tables. The
2786  * reason for this is that we've simply not yet opened the partitions
2787  * to determine if the optimization can be applied to them. We could
2788  * go and open them all here, but doing so may be quite a costly
2789  * overhead for small copies. In any case, we may just end up routing
2790  * tuples to a small number of partitions. It seems better just to
2791  * raise an ERROR for partitioned tables.
2792  */
2793  if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
2794  {
2795  ereport(ERROR,
2796  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2797  errmsg("cannot perform COPY FREEZE on a partitioned table")));
2798  }
2799 
2800  /*
2801  * Tolerate one registration for the benefit of FirstXactSnapshot.
2802  * Scan-bearing queries generally create at least two registrations,
2803  * though relying on that is fragile, as is ignoring ActiveSnapshot.
2804  * Clear CatalogSnapshot to avoid counting its registration. We'll
2805  * still detect ongoing catalog scans, each of which separately
2806  * registers the snapshot it uses.
2807  */
2810  ereport(ERROR,
2811  (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
2812  errmsg("cannot perform COPY FREEZE because of prior transaction activity")));
2813 
2814  if (cstate->rel->rd_createSubid != GetCurrentSubTransactionId() &&
2816  ereport(ERROR,
2817  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2818  errmsg("cannot perform COPY FREEZE because the table was not created or truncated in the current subtransaction")));
2819 
2820  ti_options |= TABLE_INSERT_FROZEN;
2821  }
2822 
2823  /*
2824  * We need a ResultRelInfo so we can use the regular executor's
2825  * index-entry-making machinery. (There used to be a huge amount of code
2826  * here that basically duplicated execUtils.c ...)
2827  */
2828  resultRelInfo = makeNode(ResultRelInfo);
2829  InitResultRelInfo(resultRelInfo,
2830  cstate->rel,
2831  1, /* must match rel's position in range_table */
2832  NULL,
2833  0);
2834  target_resultRelInfo = resultRelInfo;
2835 
2836  /* Verify the named relation is a valid target for INSERT */
2837  CheckValidResultRel(resultRelInfo, CMD_INSERT);
2838 
2839  ExecOpenIndices(resultRelInfo, false);
2840 
2841  estate->es_result_relations = resultRelInfo;
2842  estate->es_num_result_relations = 1;
2843  estate->es_result_relation_info = resultRelInfo;
2844 
2845  ExecInitRangeTable(estate, cstate->range_table);
2846 
2847  /*
2848  * Set up a ModifyTableState so we can let FDW(s) init themselves for
2849  * foreign-table result relation(s).
2850  */
2851  mtstate = makeNode(ModifyTableState);
2852  mtstate->ps.plan = NULL;
2853  mtstate->ps.state = estate;
2854  mtstate->operation = CMD_INSERT;
2855  mtstate->resultRelInfo = estate->es_result_relations;
2856 
2857  if (resultRelInfo->ri_FdwRoutine != NULL &&
2858  resultRelInfo->ri_FdwRoutine->BeginForeignInsert != NULL)
2859  resultRelInfo->ri_FdwRoutine->BeginForeignInsert(mtstate,
2860  resultRelInfo);
2861 
2862  /* Prepare to catch AFTER triggers. */
2864 
2865  /*
2866  * If there are any triggers with transition tables on the named relation,
2867  * we need to be prepared to capture transition tuples.
2868  *
2869  * Because partition tuple routing would like to know about whether
2870  * transition capture is active, we also set it in mtstate, which is
2871  * passed to ExecFindPartition() below.
2872  */
2873  cstate->transition_capture = mtstate->mt_transition_capture =
2875  RelationGetRelid(cstate->rel),
2876  CMD_INSERT);
2877 
2878  /*
2879  * If the named relation is a partitioned table, initialize state for
2880  * CopyFrom tuple routing.
2881  */
2882  if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
2883  proute = ExecSetupPartitionTupleRouting(estate, NULL, cstate->rel);
2884 
2885  if (cstate->whereClause)
2886  cstate->qualexpr = ExecInitQual(castNode(List, cstate->whereClause),
2887  &mtstate->ps);
2888 
2889  /*
2890  * It's generally more efficient to prepare a bunch of tuples for
2891  * insertion, and insert them in one table_multi_insert() call, than call
2892  * table_tuple_insert() separately for every tuple. However, there are a
2893  * number of reasons why we might not be able to do this. These are
2894  * explained below.
2895  */
2896  if (resultRelInfo->ri_TrigDesc != NULL &&
2897  (resultRelInfo->ri_TrigDesc->trig_insert_before_row ||
2898  resultRelInfo->ri_TrigDesc->trig_insert_instead_row))
2899  {
2900  /*
2901  * Can't support multi-inserts when there are any BEFORE/INSTEAD OF
2902  * triggers on the table. Such triggers might query the table we're
2903  * inserting into and act differently if the tuples that have already
2904  * been processed and prepared for insertion are not there.
2905  */
2906  insertMethod = CIM_SINGLE;
2907  }
2908  else if (proute != NULL && resultRelInfo->ri_TrigDesc != NULL &&
2909  resultRelInfo->ri_TrigDesc->trig_insert_new_table)
2910  {
2911  /*
2912  * For partitioned tables we can't support multi-inserts when there
2913  * are any statement level insert triggers. It might be possible to
2914  * allow partitioned tables with such triggers in the future, but for
2915  * now, CopyMultiInsertInfoFlush expects that any before row insert
2916  * and statement level insert triggers are on the same relation.
2917  */
2918  insertMethod = CIM_SINGLE;
2919  }
2920  else if (resultRelInfo->ri_FdwRoutine != NULL ||
2921  cstate->volatile_defexprs)
2922  {
2923  /*
2924  * Can't support multi-inserts to foreign tables or if there are any
2925  * volatile default expressions in the table. Similarly to the
2926  * trigger case above, such expressions may query the table we're
2927  * inserting into.
2928  *
2929  * Note: It does not matter if any partitions have any volatile
2930  * default expressions as we use the defaults from the target of the
2931  * COPY command.
2932  */
2933  insertMethod = CIM_SINGLE;
2934  }
2935  else if (contain_volatile_functions(cstate->whereClause))
2936  {
2937  /*
2938  * Can't support multi-inserts if there are any volatile function
2939  * expressions in WHERE clause. Similarly to the trigger case above,
2940  * such expressions may query the table we're inserting into.
2941  */
2942  insertMethod = CIM_SINGLE;
2943  }
2944  else
2945  {
2946  /*
2947  * For partitioned tables, we may still be able to perform bulk
2948  * inserts. However, the possibility of this depends on which types
2949  * of triggers exist on the partition. We must disable bulk inserts
2950  * if the partition is a foreign table or it has any before row insert
2951  * or insert instead triggers (same as we checked above for the parent
2952  * table). Since the partition's resultRelInfos are initialized only
2953  * when we actually need to insert the first tuple into them, we must
2954  * have the intermediate insert method of CIM_MULTI_CONDITIONAL to
2955  * flag that we must later determine if we can use bulk-inserts for
2956  * the partition being inserted into.
2957  */
2958  if (proute)
2959  insertMethod = CIM_MULTI_CONDITIONAL;
2960  else
2961  insertMethod = CIM_MULTI;
2962 
2963  CopyMultiInsertInfoInit(&multiInsertInfo, resultRelInfo, cstate,
2964  estate, mycid, ti_options);
2965  }
2966 
2967  /*
2968  * If not using batch mode (which allocates slots as needed) set up a
2969  * tuple slot too. When inserting into a partitioned table, we also need
2970  * one, even if we might batch insert, to read the tuple in the root
2971  * partition's form.
2972  */
2973  if (insertMethod == CIM_SINGLE || insertMethod == CIM_MULTI_CONDITIONAL)
2974  {
2975  singleslot = table_slot_create(resultRelInfo->ri_RelationDesc,
2976  &estate->es_tupleTable);
2977  bistate = GetBulkInsertState();
2978  }
2979 
2980  has_before_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
2981  resultRelInfo->ri_TrigDesc->trig_insert_before_row);
2982 
2983  has_instead_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
2984  resultRelInfo->ri_TrigDesc->trig_insert_instead_row);
2985 
2986  /*
2987  * Check BEFORE STATEMENT insertion triggers. It's debatable whether we
2988  * should do this for COPY, since it's not really an "INSERT" statement as
2989  * such. However, executing these triggers maintains consistency with the
2990  * EACH ROW triggers that we already fire on COPY.
2991  */
2992  ExecBSInsertTriggers(estate, resultRelInfo);
2993 
2994  econtext = GetPerTupleExprContext(estate);
2995 
2996  /* Set up callback to identify error line number */
2997  errcallback.callback = CopyFromErrorCallback;
2998  errcallback.arg = (void *) cstate;
2999  errcallback.previous = error_context_stack;
3000  error_context_stack = &errcallback;
3001 
3002  for (;;)
3003  {
3004  TupleTableSlot *myslot;
3005  bool skip_tuple;
3006 
3008 
3009  /*
3010  * Reset the per-tuple exprcontext. We do this after every tuple, to
3011  * clean-up after expression evaluations etc.
3012  */
3013  ResetPerTupleExprContext(estate);
3014 
3015  /* select slot to (initially) load row into */
3016  if (insertMethod == CIM_SINGLE || proute)
3017  {
3018  myslot = singleslot;
3019  Assert(myslot != NULL);
3020  }
3021  else
3022  {
3023  Assert(resultRelInfo == target_resultRelInfo);
3024  Assert(insertMethod == CIM_MULTI);
3025 
3026  myslot = CopyMultiInsertInfoNextFreeSlot(&multiInsertInfo,
3027  resultRelInfo);
3028  }
3029 
3030  /*
3031  * Switch to per-tuple context before calling NextCopyFrom, which does
3032  * evaluate default expressions etc. and requires per-tuple context.
3033  */
3035 
3036  ExecClearTuple(myslot);
3037 
3038  /* Directly store the values/nulls array in the slot */
3039  if (!NextCopyFrom(cstate, econtext, myslot->tts_values, myslot->tts_isnull))
3040  break;
3041 
3042  ExecStoreVirtualTuple(myslot);
3043 
3044  /*
3045  * Constraints and where clause might reference the tableoid column,
3046  * so (re-)initialize tts_tableOid before evaluating them.
3047  */
3048  myslot->tts_tableOid = RelationGetRelid(target_resultRelInfo->ri_RelationDesc);
3049 
3050  /* Triggers and stuff need to be invoked in query context. */
3051  MemoryContextSwitchTo(oldcontext);
3052 
3053  if (cstate->whereClause)
3054  {
3055  econtext->ecxt_scantuple = myslot;
3056  /* Skip items that don't match COPY's WHERE clause */
3057  if (!ExecQual(cstate->qualexpr, econtext))
3058  continue;
3059  }
3060 
3061  /* Determine the partition to insert the tuple into */
3062  if (proute)
3063  {
3064  TupleConversionMap *map;
3065 
3066  /*
3067  * Attempt to find a partition suitable for this tuple.
3068  * ExecFindPartition() will raise an error if none can be found or
3069  * if the found partition is not suitable for INSERTs.
3070  */
3071  resultRelInfo = ExecFindPartition(mtstate, target_resultRelInfo,
3072  proute, myslot, estate);
3073 
3074  if (prevResultRelInfo != resultRelInfo)
3075  {
3076  /* Determine which triggers exist on this partition */
3077  has_before_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
3078  resultRelInfo->ri_TrigDesc->trig_insert_before_row);
3079 
3080  has_instead_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
3081  resultRelInfo->ri_TrigDesc->trig_insert_instead_row);
3082 
3083  /*
3084  * Disable multi-inserts when the partition has BEFORE/INSTEAD
3085  * OF triggers, or if the partition is a foreign partition.
3086  */
3087  leafpart_use_multi_insert = insertMethod == CIM_MULTI_CONDITIONAL &&
3088  !has_before_insert_row_trig &&
3089  !has_instead_insert_row_trig &&
3090  resultRelInfo->ri_FdwRoutine == NULL;
3091 
3092  /* Set the multi-insert buffer to use for this partition. */
3093  if (leafpart_use_multi_insert)
3094  {
3095  if (resultRelInfo->ri_CopyMultiInsertBuffer == NULL)
3096  CopyMultiInsertInfoSetupBuffer(&multiInsertInfo,
3097  resultRelInfo);
3098  }
3099  else if (insertMethod == CIM_MULTI_CONDITIONAL &&
3100  !CopyMultiInsertInfoIsEmpty(&multiInsertInfo))
3101  {
3102  /*
3103  * Flush pending inserts if this partition can't use
3104  * batching, so rows are visible to triggers etc.
3105  */
3106  CopyMultiInsertInfoFlush(&multiInsertInfo, resultRelInfo);
3107  }
3108 
3109  if (bistate != NULL)
3110  ReleaseBulkInsertStatePin(bistate);
3111  prevResultRelInfo = resultRelInfo;
3112  }
3113 
3114  /*
3115  * For ExecInsertIndexTuples() to work on the partition's indexes
3116  */
3117  estate->es_result_relation_info = resultRelInfo;
3118 
3119  /*
3120  * If we're capturing transition tuples, we might need to convert
3121  * from the partition rowtype to root rowtype.
3122  */
3123  if (cstate->transition_capture != NULL)
3124  {
3125  if (has_before_insert_row_trig)
3126  {
3127  /*
3128  * If there are any BEFORE triggers on the partition,
3129  * we'll have to be ready to convert their result back to
3130  * tuplestore format.
3131  */
3133  cstate->transition_capture->tcs_map =
3134  resultRelInfo->ri_PartitionInfo->pi_PartitionToRootMap;
3135  }
3136  else
3137  {
3138  /*
3139  * Otherwise, just remember the original unconverted
3140  * tuple, to avoid a needless round trip conversion.
3141  */
3143  cstate->transition_capture->tcs_map = NULL;
3144  }
3145  }
3146 
3147  /*
3148  * We might need to convert from the root rowtype to the partition
3149  * rowtype.
3150  */
3151  map = resultRelInfo->ri_PartitionInfo->pi_RootToPartitionMap;
3152  if (insertMethod == CIM_SINGLE || !leafpart_use_multi_insert)
3153  {
3154  /* non batch insert */
3155  if (map != NULL)
3156  {
3157  TupleTableSlot *new_slot;
3158 
3159  new_slot = resultRelInfo->ri_PartitionInfo->pi_PartitionTupleSlot;
3160  myslot = execute_attr_map_slot(map->attrMap, myslot, new_slot);
3161  }
3162  }
3163  else
3164  {
3165  /*
3166  * Prepare to queue up tuple for later batch insert into
3167  * current partition.
3168  */
3169  TupleTableSlot *batchslot;
3170 
3171  /* no other path available for partitioned table */
3172  Assert(insertMethod == CIM_MULTI_CONDITIONAL);
3173 
3174  batchslot = CopyMultiInsertInfoNextFreeSlot(&multiInsertInfo,
3175  resultRelInfo);
3176 
3177  if (map != NULL)
3178  myslot = execute_attr_map_slot(map->attrMap, myslot,
3179  batchslot);
3180  else
3181  {
3182  /*
3183  * This looks more expensive than it is (Believe me, I
3184  * optimized it away. Twice.). The input is in virtual
3185  * form, and we'll materialize the slot below - for most
3186  * slot types the copy performs the work materialization
3187  * would later require anyway.
3188  */
3189  ExecCopySlot(batchslot, myslot);
3190  myslot = batchslot;
3191  }
3192  }
3193 
3194  /* ensure that triggers etc see the right relation */
3195  myslot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
3196  }
3197 
3198  skip_tuple = false;
3199 
3200  /* BEFORE ROW INSERT Triggers */
3201  if (has_before_insert_row_trig)
3202  {
3203  if (!ExecBRInsertTriggers(estate, resultRelInfo, myslot))
3204  skip_tuple = true; /* "do nothing" */
3205  }
3206 
3207  if (!skip_tuple)
3208  {
3209  /*
3210  * If there is an INSTEAD OF INSERT ROW trigger, let it handle the
3211  * tuple. Otherwise, proceed with inserting the tuple into the
3212  * table or foreign table.
3213  */
3214  if (has_instead_insert_row_trig)
3215  {
3216  ExecIRInsertTriggers(estate, resultRelInfo, myslot);
3217  }
3218  else
3219  {
3220  /* Compute stored generated columns */
3221  if (resultRelInfo->ri_RelationDesc->rd_att->constr &&
3223  ExecComputeStoredGenerated(estate, myslot, CMD_INSERT);
3224 
3225  /*
3226  * If the target is a plain table, check the constraints of
3227  * the tuple.
3228  */
3229  if (resultRelInfo->ri_FdwRoutine == NULL &&
3230  resultRelInfo->ri_RelationDesc->rd_att->constr)
3231  ExecConstraints(resultRelInfo, myslot, estate);
3232 
3233  /*
3234  * Also check the tuple against the partition constraint, if
3235  * there is one; except that if we got here via tuple-routing,
3236  * we don't need to if there's no BR trigger defined on the
3237  * partition.
3238  */
3239  if (resultRelInfo->ri_PartitionCheck &&
3240  (proute == NULL || has_before_insert_row_trig))
3241  ExecPartitionCheck(resultRelInfo, myslot, estate, true);
3242 
3243  /* Store the slot in the multi-insert buffer, when enabled. */
3244  if (insertMethod == CIM_MULTI || leafpart_use_multi_insert)
3245  {
3246  /*
3247  * The slot previously might point into the per-tuple
3248  * context. For batching it needs to be longer lived.
3249  */
3250  ExecMaterializeSlot(myslot);
3251 
3252  /* Add this tuple to the tuple buffer */
3253  CopyMultiInsertInfoStore(&multiInsertInfo,
3254  resultRelInfo, myslot,
3255  cstate->line_buf.len,
3256  cstate->cur_lineno);
3257 
3258  /*
3259  * If enough inserts have queued up, then flush all
3260  * buffers out to their tables.
3261  */
3262  if (CopyMultiInsertInfoIsFull(&multiInsertInfo))
3263  CopyMultiInsertInfoFlush(&multiInsertInfo, resultRelInfo);
3264  }
3265  else
3266  {
3267  List *recheckIndexes = NIL;
3268 
3269  /* OK, store the tuple */
3270  if (resultRelInfo->ri_FdwRoutine != NULL)
3271  {
3272  myslot = resultRelInfo->ri_FdwRoutine->ExecForeignInsert(estate,
3273  resultRelInfo,
3274  myslot,
3275  NULL);
3276 
3277  if (myslot == NULL) /* "do nothing" */
3278  continue; /* next tuple please */
3279 
3280  /*
3281  * AFTER ROW Triggers might reference the tableoid
3282  * column, so (re-)initialize tts_tableOid before
3283  * evaluating them.
3284  */
3285  myslot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
3286  }
3287  else
3288  {
3289  /* OK, store the tuple and create index entries for it */
3290  table_tuple_insert(resultRelInfo->ri_RelationDesc,
3291  myslot, mycid, ti_options, bistate);
3292 
3293  if (resultRelInfo->ri_NumIndices > 0)
3294  recheckIndexes = ExecInsertIndexTuples(myslot,
3295  estate,
3296  false,
3297  NULL,
3298  NIL);
3299  }
3300 
3301  /* AFTER ROW INSERT Triggers */
3302  ExecARInsertTriggers(estate, resultRelInfo, myslot,
3303  recheckIndexes, cstate->transition_capture);
3304 
3305  list_free(recheckIndexes);
3306  }
3307  }
3308 
3309  /*
3310  * We count only tuples not suppressed by a BEFORE INSERT trigger
3311  * or FDW; this is the same definition used by nodeModifyTable.c
3312  * for counting tuples inserted by an INSERT command.
3313  */
3314  processed++;
3315  }
3316  }
3317 
3318  /* Flush any remaining buffered tuples */
3319  if (insertMethod != CIM_SINGLE)
3320  {
3321  if (!CopyMultiInsertInfoIsEmpty(&multiInsertInfo))
3322  CopyMultiInsertInfoFlush(&multiInsertInfo, NULL);
3323  }
3324 
3325  /* Done, clean up */
3326  error_context_stack = errcallback.previous;
3327 
3328  if (bistate != NULL)
3329  FreeBulkInsertState(bistate);
3330 
3331  MemoryContextSwitchTo(oldcontext);
3332 
3333  /*
3334  * In the old protocol, tell pqcomm that we can process normal protocol
3335  * messages again.
3336  */
3337  if (cstate->copy_dest == COPY_OLD_FE)
3338  pq_endmsgread();
3339 
3340  /* Execute AFTER STATEMENT insertion triggers */
3341  ExecASInsertTriggers(estate, target_resultRelInfo, cstate->transition_capture);
3342 
3343  /* Handle queued AFTER triggers */
3344  AfterTriggerEndQuery(estate);
3345 
3346  ExecResetTupleTable(estate->es_tupleTable, false);
3347 
3348  /* Allow the FDW to shut down */
3349  if (target_resultRelInfo->ri_FdwRoutine != NULL &&
3350  target_resultRelInfo->ri_FdwRoutine->EndForeignInsert != NULL)
3351  target_resultRelInfo->ri_FdwRoutine->EndForeignInsert(estate,
3352  target_resultRelInfo);
3353 
3354  /* Tear down the multi-insert buffer data */
3355  if (insertMethod != CIM_SINGLE)
3356  CopyMultiInsertInfoCleanup(&multiInsertInfo);
3357 
3358  ExecCloseIndices(target_resultRelInfo);
3359 
3360  /* Close all the partitioned tables, leaf partitions, and their indices */
3361  if (proute)
3362  ExecCleanupTupleRouting(mtstate, proute);
3363 
3364  /* Close any trigger target relations */
3365  ExecCleanUpTriggerState(estate);
3366 
3367  FreeExecutorState(estate);
3368 
3369  return processed;
3370 }
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition: tableam.c:91
int ri_NumIndices
Definition: execnodes.h:416
Node * whereClause
Definition: copy.c:156
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:534
void ExecInitRangeTable(EState *estate, List *rangeTable)
Definition: execUtils.c:765
void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, Relation partition_root, int instrument_options)
Definition: execMain.c:1277
Relation ri_RelationDesc
Definition: execnodes.h:413
List * range_table
Definition: copy.c:184
static void CopyMultiInsertInfoStore(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri, TupleTableSlot *slot, int tuplen, uint64 lineno)
Definition: copy.c:2679
int errhint(const char *fmt,...)
Definition: elog.c:1071
void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot, List *recheckIndexes, TransitionCaptureState *transition_capture)
Definition: trigger.c:2268
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition: execnodes.h:493
void CopyFromErrorCallback(void *arg)
Definition: copy.c:2284
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
#define ResetPerTupleExprContext(estate)
Definition: executor.h:516
#define TABLE_INSERT_FROZEN
Definition: tableam.h:133
#define castNode(_type_, nodeptr)
Definition: nodes.h:598
BeginForeignInsert_function BeginForeignInsert
Definition: fdwapi.h:215
ResultRelInfo * resultRelInfo
Definition: execnodes.h:1174
ExecForeignInsert_function ExecForeignInsert
Definition: fdwapi.h:211
struct PartitionRoutingInfo * ri_PartitionInfo
Definition: execnodes.h:490
void ExecComputeStoredGenerated(EState *estate, TupleTableSlot *slot, CmdType cmdtype)
static void CopyMultiInsertInfoSetupBuffer(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri)
Definition: copy.c:2407
void ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1897
StringInfoData line_buf
Definition: copy.c:215
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool ThereAreNoPriorRegisteredSnapshots(void)
Definition: snapmgr.c:1689
int errcode(int sqlerrcode)
Definition: elog.c:610
CmdType operation
Definition: execnodes.h:1166
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:103
Datum * tts_values
Definition: tuptable.h:126
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:726
EState * state
Definition: execnodes.h:947
Form_pg_class rd_rel
Definition: rel.h:109
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:370
bool volatile_defexprs
Definition: copy.c:183
void(* callback)(void *arg)
Definition: elog.h:229
struct ErrorContextCallback * previous
Definition: elog.h:228
static void CopyMultiInsertInfoInit(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri, CopyState cstate, EState *estate, CommandId mycid, int ti_options)
Definition: copy.c:2427
static void table_tuple_insert(Relation rel, TupleTableSlot *slot, CommandId cid, int options, struct BulkInsertStateData *bistate)
Definition: tableam.h:1153
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:209
void ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative)
Definition: execIndexing.c:151
CopyDest copy_dest
Definition: copy.c:117
ErrorContextCallback * error_context_stack
Definition: elog.c:92
uint64 cur_lineno
Definition: copy.c:160
bool trig_insert_instead_row
Definition: reltrigger.h:58
void FreeExecutorState(EState *estate)
Definition: execUtils.c:191
Relation rel
Definition: copy.c:130
#define GetPerTupleExprContext(estate)
Definition: executor.h:507
BulkInsertState GetBulkInsertState(void)
Definition: heapam.c:1789
bool trig_insert_new_table
Definition: reltrigger.h:75
bool has_generated_stored
Definition: tupdesc.h:45
TupleConversionMap * pi_RootToPartitionMap
Definition: execPartition.h:37
bool ThereAreNoReadyPortals(void)
Definition: portalmem.c:1209
#define ERROR
Definition: elog.h:43
PlanState ps
Definition: execnodes.h:1165
void ExecCleanupTupleRouting(ModifyTableState *mtstate, PartitionTupleRouting *proute)
bool ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2192
static bool CopyMultiInsertInfoIsFull(CopyMultiInsertInfo *miinfo)
Definition: copy.c:2452
TupleConversionMap * tcs_map
Definition: trigger.h:74
static bool CopyMultiInsertInfoIsEmpty(CopyMultiInsertInfo *miinfo)
Definition: copy.c:2464
List * ExecInsertIndexTuples(TupleTableSlot *slot, EState *estate, bool noDupErr, bool *specConflict, List *arbiterIndexes)
Definition: execIndexing.c:273
TriggerDesc * trigdesc
Definition: rel.h:115
void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation)
Definition: execMain.c:1076
void ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2130
struct TransitionCaptureState * mt_transition_capture
Definition: execnodes.h:1191
bool * tts_isnull
Definition: tuptable.h:128
static void CopyMultiInsertInfoFlush(CopyMultiInsertInfo *miinfo, ResultRelInfo *curr_rri)
Definition: copy.c:2595
TupleConstr * constr
Definition: tupdesc.h:85
ResultRelInfo * es_result_relations
Definition: execnodes.h:525
#define RelationGetRelationName(relation)
Definition: rel.h:490
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:442
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
PartitionTupleRouting * ExecSetupPartitionTupleRouting(EState *estate, ModifyTableState *mtstate, Relation rel)
AttrMap * attrMap
Definition: tupconvert.h:27
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:512
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:425
EState * CreateExecutorState(void)
Definition: execUtils.c:89
SubTransactionId rd_createSubid
Definition: rel.h:102
Definition: copy.c:94
bool trig_insert_before_row
Definition: reltrigger.h:56
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
List * es_tupleTable
Definition: execnodes.h:557
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:1161
void ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo, TransitionCaptureState *transition_capture)
Definition: trigger.c:2181
TransitionCaptureState * MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType)
Definition: trigger.c:4310
int es_num_result_relations
Definition: execnodes.h:526
#define TABLE_INSERT_SKIP_FSM
Definition: tableam.h:132
TupleConversionMap * pi_PartitionToRootMap
Definition: execPartition.h:43
List * ri_PartitionCheck
Definition: execnodes.h:481
TupleDesc rd_att
Definition: rel.h:110
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition: tuptable.h:443
bool freeze
Definition: copy.c:137
Plan * plan
Definition: execnodes.h:945
void pq_endmsgread(void)
Definition: pqcomm.c:1221
#define ereport(elevel,...)
Definition: elog.h:144
void AfterTriggerBeginQuery(void)
Definition: trigger.c:4432
#define makeNode(_type_)
Definition: nodes.h:577
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition: tupconvert.c:177
#define Assert(condition)
Definition: c.h:745
void FreeBulkInsertState(BulkInsertState bistate)
Definition: heapam.c:1803
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:710
bool ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2283
CopyInsertMethod
Definition: copy.c:91
bool NextCopyFrom(CopyState cstate, ExprContext *econtext, Datum *values, bool *nulls)
Definition: copy.c:3691
static TupleTableSlot * CopyMultiInsertInfoNextFreeSlot(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri)
Definition: copy.c:2660
static void CopyMultiInsertInfoCleanup(CopyMultiInsertInfo *miinfo)
Definition: copy.c:2641
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:226
#define InvalidSubTransactionId
Definition: c.h:526
void ReleaseBulkInsertStatePin(BulkInsertState bistate)
Definition: heapam.c:1815
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:512
void ExecCleanUpTriggerState(EState *estate)
Definition: execMain.c:1454
void AfterTriggerEndQuery(EState *estate)
Definition: trigger.c:4452
int errmsg(const char *fmt,...)
Definition: elog.c:824
void list_free(List *list)
Definition: list.c:1376
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
Definition: execMain.c:1783
TransitionCaptureState * transition_capture
Definition: copy.c:187
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:748
ResultRelInfo * ExecFindPartition(ModifyTableState *mtstate, ResultRelInfo *rootResultRelInfo, PartitionTupleRouting *proute, TupleTableSlot *slot, EState *estate)
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:456
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Definition: execIndexing.c:226
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1522
EndForeignInsert_function EndForeignInsert
Definition: fdwapi.h:216
TupleTableSlot * pi_PartitionTupleSlot
Definition: execPartition.h:49
TupleTableSlot * tcs_original_insert_tuple
Definition: trigger.h:83
ExprState * qualexpr
Definition: copy.c:185
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:527

◆ CopyFromErrorCallback()

void CopyFromErrorCallback ( void *  arg)

Definition at line 2284 of file copy.c.

References CopyStateData::binary, CopyStateData::cur_attname, CopyStateData::cur_attval, CopyStateData::cur_lineno, CopyStateData::cur_relname, StringInfoData::data, errcontext, limit_printout_length(), CopyStateData::line_buf, CopyStateData::line_buf_converted, CopyStateData::line_buf_valid, CopyStateData::need_transcoding, pfree(), snprintf, and UINT64_FORMAT.

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

2285 {
2286  CopyState cstate = (CopyState) arg;
2287  char curlineno_str[32];
2288 
2289  snprintf(curlineno_str, sizeof(curlineno_str), UINT64_FORMAT,
2290  cstate->cur_lineno);
2291 
2292  if (cstate->binary)
2293  {
2294  /* can't usefully display the data */
2295  if (cstate->cur_attname)
2296  errcontext("COPY %s, line %s, column %s",
2297  cstate->cur_relname, curlineno_str,
2298  cstate->cur_attname);
2299  else
2300  errcontext("COPY %s, line %s",
2301  cstate->cur_relname, curlineno_str);
2302  }
2303  else
2304  {
2305  if (cstate->cur_attname && cstate->cur_attval)
2306  {
2307  /* error is relevant to a particular column */
2308  char *attval;
2309 
2310  attval = limit_printout_length(cstate->cur_attval);
2311  errcontext("COPY %s, line %s, column %s: \"%s\"",
2312  cstate->cur_relname, curlineno_str,
2313  cstate->cur_attname, attval);
2314  pfree(attval);
2315  }
2316  else if (cstate->cur_attname)
2317  {
2318  /* error is relevant to a particular column, value is NULL */
2319  errcontext("COPY %s, line %s, column %s: null input",
2320  cstate->cur_relname, curlineno_str,
2321  cstate->cur_attname);
2322  }
2323  else
2324  {
2325  /*
2326  * Error is relevant to a particular line.
2327  *
2328  * If line_buf still contains the correct line, and it's already
2329  * transcoded, print it. If it's still in a foreign encoding, it's
2330  * quite likely that the error is precisely a failure to do
2331  * encoding conversion (ie, bad data). We dare not try to convert
2332  * it, and at present there's no way to regurgitate it without
2333  * conversion. So we have to punt and just report the line number.
2334  */
2335  if (cstate->line_buf_valid &&
2336  (cstate->line_buf_converted || !cstate->need_transcoding))
2337  {
2338  char *lineval;
2339 
2340  lineval = limit_printout_length(cstate->line_buf.data);
2341  errcontext("COPY %s, line %s: \"%s\"",
2342  cstate->cur_relname, curlineno_str, lineval);
2343  pfree(lineval);
2344  }
2345  else
2346  {
2347  errcontext("COPY %s, line %s",
2348  cstate->cur_relname, curlineno_str);
2349  }
2350  }
2351  }
2352 }
bool binary
Definition: copy.c:136
bool need_transcoding
Definition: copy.c:126
StringInfoData line_buf
Definition: copy.c:215
bool line_buf_valid
Definition: copy.c:217
bool line_buf_converted
Definition: copy.c:216
uint64 cur_lineno
Definition: copy.c:160
const char * cur_attname
Definition: copy.c:161
void pfree(void *pointer)
Definition: mcxt.c:1056
static char * limit_printout_length(const char *str)
Definition: copy.c:2360
const char * cur_relname
Definition: copy.c:159
#define errcontext
Definition: elog.h:185
struct CopyStateData * CopyState
Definition: copy.h:23
void * arg
const char * cur_attval
Definition: copy.c:162
#define snprintf
Definition: port.h:193
#define UINT64_FORMAT
Definition: c.h:417

◆ CreateCopyDestReceiver()

DestReceiver* CreateCopyDestReceiver ( void  )

Definition at line 5201 of file copy.c.

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

Referenced by CreateDestReceiver().

5202 {
5203  DR_copy *self = (DR_copy *) palloc(sizeof(DR_copy));
5204 
5205  self->pub.receiveSlot = copy_dest_receive;
5206  self->pub.rStartup = copy_dest_startup;
5207  self->pub.rShutdown = copy_dest_shutdown;
5208  self->pub.rDestroy = copy_dest_destroy;
5209  self->pub.mydest = DestCopyOut;
5210 
5211  self->cstate = NULL; /* will be set later */
5212  self->processed = 0;
5213 
5214  return (DestReceiver *) self;
5215 }
Definition: copy.c:236
static void copy_dest_destroy(DestReceiver *self)
Definition: copy.c:5192
static void copy_dest_shutdown(DestReceiver *self)
Definition: copy.c:5183
static void copy_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: copy.c:5158
static bool copy_dest_receive(TupleTableSlot *slot, DestReceiver *self)
Definition: copy.c:5167
void * palloc(Size size)
Definition: mcxt.c:949

◆ DoCopy()

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

Definition at line 888 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, CopyStateData::rel, 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, CopyStateData::whereClause, CopyStmt::whereClause, and XactReadOnly.

Referenced by standard_ProcessUtility().

891 {
892  CopyState cstate;
893  bool is_from = stmt->is_from;
894  bool pipe = (stmt->filename == NULL);
895  Relation rel;
896  Oid relid;
897  RawStmt *query = NULL;
898  Node *whereClause = NULL;
899 
900  /*
901  * Disallow COPY to/from file or program except to users with the
902  * appropriate role.
903  */
904  if (!pipe)
905  {
906  if (stmt->is_program)
907  {
908  if (!is_member_of_role(GetUserId(), DEFAULT_ROLE_EXECUTE_SERVER_PROGRAM))
909  ereport(ERROR,
910  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
911  errmsg("must be superuser or a member of the pg_execute_server_program role to COPY to or from an external program"),
912  errhint("Anyone can COPY to stdout or from stdin. "
913  "psql's \\copy command also works for anyone.")));
914  }
915  else
916  {
917  if (is_from && !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_SERVER_FILES))
918  ereport(ERROR,
919  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
920  errmsg("must be superuser or a member of the pg_read_server_files role to COPY from a file"),
921  errhint("Anyone can COPY to stdout or from stdin. "
922  "psql's \\copy command also works for anyone.")));
923 
924  if (!is_from && !is_member_of_role(GetUserId(), DEFAULT_ROLE_WRITE_SERVER_FILES))
925  ereport(ERROR,
926  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
927  errmsg("must be superuser or a member of the pg_write_server_files role to COPY to a file"),
928  errhint("Anyone can COPY to stdout or from stdin. "
929  "psql's \\copy command also works for anyone.")));
930  }
931  }
932 
933  if (stmt->relation)
934  {
935  LOCKMODE lockmode = is_from ? RowExclusiveLock : AccessShareLock;
936  ParseNamespaceItem *nsitem;
937  RangeTblEntry *rte;
938  TupleDesc tupDesc;
939  List *attnums;
940  ListCell *cur;
941 
942  Assert(!stmt->query);
943 
944  /* Open and lock the relation, using the appropriate lock type. */
945  rel = table_openrv(stmt->relation, lockmode);
946 
947  relid = RelationGetRelid(rel);
948 
949  nsitem = addRangeTableEntryForRelation(pstate, rel, lockmode,
950  NULL, false, false);
951  rte = nsitem->p_rte;
952  rte->requiredPerms = (is_from ? ACL_INSERT : ACL_SELECT);
953 
954  if (stmt->whereClause)
955  {
956  /* add nsitem to query namespace */
957  addNSItemToQuery(pstate, nsitem, false, true, true);
958 
959  /* Transform the raw expression tree */
960  whereClause = transformExpr(pstate, stmt->whereClause, EXPR_KIND_COPY_WHERE);
961 
962  /* Make sure it yields a boolean result. */
963  whereClause = coerce_to_boolean(pstate, whereClause, "WHERE");
964 
965  /* we have to fix its collations too */
966  assign_expr_collations(pstate, whereClause);
967 
968  whereClause = eval_const_expressions(NULL, whereClause);
969 
970  whereClause = (Node *) canonicalize_qual((Expr *) whereClause, false);
971  whereClause = (Node *) make_ands_implicit((Expr *) whereClause);
972  }
973 
974  tupDesc = RelationGetDescr(rel);
975  attnums = CopyGetAttnums(tupDesc, rel, stmt->attlist);
976  foreach(cur, attnums)
977  {
978  int attno = lfirst_int(cur) -
980 
981  if (is_from)
982  rte->insertedCols = bms_add_member(rte->insertedCols, attno);
983  else
984  rte->selectedCols = bms_add_member(rte->selectedCols, attno);
985  }
986  ExecCheckRTPerms(pstate->p_rtable, true);
987 
988  /*
989  * Permission check for row security policies.
990  *
991  * check_enable_rls will ereport(ERROR) if the user has requested
992  * something invalid and will otherwise indicate if we should enable
993  * RLS (returns RLS_ENABLED) or not for this COPY statement.
994  *
995  * If the relation has a row security policy and we are to apply it
996  * then perform a "query" copy and allow the normal query processing
997  * to handle the policies.
998  *
999  * If RLS is not enabled for this, then just fall through to the
1000  * normal non-filtering relation handling.
1001  */
1002  if (check_enable_rls(rte->relid, InvalidOid, false) == RLS_ENABLED)
1003  {
1004  SelectStmt *select;
1005  ColumnRef *cr;
1006  ResTarget *target;
1007  RangeVar *from;
1008  List *targetList = NIL;
1009 
1010  if (is_from)
1011  ereport(ERROR,
1012  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1013  errmsg("COPY FROM not supported with row-level security"),
1014  errhint("Use INSERT statements instead.")));
1015 
1016  /*
1017  * Build target list
1018  *
1019  * If no columns are specified in the attribute list of the COPY
1020  * command, then the target list is 'all' columns. Therefore, '*'
1021  * should be used as the target list for the resulting SELECT
1022  * statement.
1023  *
1024  * In the case that columns are specified in the attribute list,
1025  * create a ColumnRef and ResTarget for each column and add them
1026  * to the target list for the resulting SELECT statement.
1027  */
1028  if (!stmt->attlist)
1029  {
1030  cr = makeNode(ColumnRef);
1031  cr->fields = list_make1(makeNode(A_Star));
1032  cr->location = -1;
1033 
1034  target = makeNode(ResTarget);
1035  target->name = NULL;
1036  target->indirection = NIL;
1037  target->val = (Node *) cr;
1038  target->location = -1;
1039 
1040  targetList = list_make1(target);
1041  }
1042  else
1043  {
1044  ListCell *lc;
1045 
1046  foreach(lc, stmt->attlist)
1047  {
1048  /*
1049  * Build the ColumnRef for each column. The ColumnRef
1050  * 'fields' property is a String 'Value' node (see
1051  * nodes/value.h) that corresponds to the column name
1052  * respectively.
1053  */
1054  cr = makeNode(ColumnRef);
1055  cr->fields = list_make1(lfirst(lc));
1056  cr->location = -1;
1057 
1058  /* Build the ResTarget and add the ColumnRef to it. */
1059  target = makeNode(ResTarget);
1060  target->name = NULL;
1061  target->indirection = NIL;
1062  target->val = (Node *) cr;
1063  target->location = -1;
1064 
1065  /* Add each column to the SELECT statement's target list */
1066  targetList = lappend(targetList, target);
1067  }
1068  }
1069 
1070  /*
1071  * Build RangeVar for from clause, fully qualified based on the
1072  * relation which we have opened and locked.
1073  */
1076  -1);
1077 
1078  /* Build query */
1079  select = makeNode(SelectStmt);
1080  select->targetList = targetList;
1081  select->fromClause = list_make1(from);
1082 
1083  query = makeNode(RawStmt);
1084  query->stmt = (Node *) select;
1085  query->stmt_location = stmt_location;
1086  query->stmt_len = stmt_len;
1087 
1088  /*
1089  * Close the relation for now, but keep the lock on it to prevent
1090  * changes between now and when we start the query-based COPY.
1091  *
1092  * We'll reopen it later as part of the query-based COPY.
1093  */
1094  table_close(rel, NoLock);
1095  rel = NULL;
1096  }
1097  }
1098  else
1099  {
1100  Assert(stmt->query);
1101 
1102  query = makeNode(RawStmt);
1103  query->stmt = stmt->query;
1104  query->stmt_location = stmt_location;
1105  query->stmt_len = stmt_len;
1106 
1107  relid = InvalidOid;
1108  rel = NULL;
1109  }
1110 
1111  if (is_from)
1112  {
1113  Assert(rel);
1114 
1115  /* check read-only transaction and parallel mode */
1116  if (XactReadOnly && !rel->rd_islocaltemp)
1117  PreventCommandIfReadOnly("COPY FROM");
1118 
1119  cstate = BeginCopyFrom(pstate, rel, stmt->filename, stmt->is_program,
1120  NULL, stmt->attlist, stmt->options);
1121  cstate->whereClause = whereClause;
1122  *processed = CopyFrom(cstate); /* copy from file to database */
1123  EndCopyFrom(cstate);
1124  }
1125  else
1126  {
1127  cstate = BeginCopyTo(pstate, rel, query, relid,
1128  stmt->filename, stmt->is_program,
1129  stmt->attlist, stmt->options);
1130  *processed = DoCopyTo(cstate); /* copy from database to file */
1131  EndCopyTo(cstate);
1132  }
1133 
1134  if (rel != NULL)
1135  table_close(rel, NoLock);
1136 }
List * indirection
Definition: parsenodes.h:442
Node * whereClause
Definition: copy.c:156
#define NIL
Definition: pg_list.h:65
Node * whereClause
Definition: parsenodes.h:2019
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
Node * val
Definition: parsenodes.h:443
int errhint(const char *fmt,...)
Definition: elog.c:1071
List * attlist
Definition: parsenodes.h:2013
List * fromClause
Definition: parsenodes.h:1598
#define RelationGetDescr(relation)
Definition: rel.h:482
int LOCKMODE
Definition: lockdefs.h:26
char * name
Definition: parsenodes.h:441
Oid GetUserId(void)
Definition: miscinit.c:450
CopyState BeginCopyFrom(ParseState *pstate, Relation rel, const char *filename, bool is_program, copy_data_source_cb data_source_cb, List *attnamelist, List *options)
Definition: copy.c:3383
char * pstrdup(const char *in)
Definition: mcxt.c:1186
bool rd_islocaltemp
Definition: rel.h:60
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:145
#define AccessShareLock
Definition: lockdefs.h:36
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
Definition: nodes.h:529
struct cursor * cur
Definition: ecpg.c:28
int errcode(int sqlerrcode)
Definition: elog.c:610
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2255
uint64 CopyFrom(CopyState cstate)
Definition: copy.c:2702
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
AclMode requiredPerms
Definition: parsenodes.h:1119
unsigned int Oid
Definition: postgres_ext.h:31
bool is_program
Definition: parsenodes.h:2016
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
int location
Definition: parsenodes.h:237
int location
Definition: parsenodes.h:444
#define list_make1(x1)
Definition: pg_list.h:227
void assign_expr_collations(ParseState *pstate, Node *expr)
RangeTblEntry * p_rte
Definition: parse_node.h:257
Bitmapset * selectedCols
Definition: parsenodes.h:1121
static CopyState BeginCopyTo(ParseState *pstate, Relation rel, RawStmt *query, Oid queryRelId, const char *filename, bool is_program, List *attnamelist, List *options)
Definition: copy.c:1872
#define ERROR
Definition: elog.h:43
#define lfirst_int(lc)
Definition: pg_list.h:191
RangeVar * relation
Definition: parsenodes.h:2010
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3191
Node * stmt
Definition: parsenodes.h:1508
#define NoLock
Definition: lockdefs.h:34
List * targetList
Definition: parsenodes.h:1597
static uint64 DoCopyTo(CopyState cstate)
Definition: copy.c:2008
#define RowExclusiveLock
Definition: lockdefs.h:38
Expr * canonicalize_qual(Expr *qual, bool is_check)
Definition: prepqual.c:292
List * options
Definition: parsenodes.h:2018
#define select(n, r, w, e, timeout)
Definition: win32_port.h:436
#define RelationGetRelationName(relation)
Definition: rel.h:490
List * lappend(List *list, void *datum)
Definition: list.c:321
static List * CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
Definition: copy.c:5077
#define ACL_SELECT
Definition: parsenodes.h:75
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:718
int stmt_len
Definition: parsenodes.h:1510
int stmt_location
Definition: parsenodes.h:1509
Relation table_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: table.c:68
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:144
bool XactReadOnly
Definition: xact.c:78
bool is_member_of_role(Oid member, Oid role)
Definition: acl.c:4916
int check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
Definition: rls.c:52
void EndCopyFrom(CopyState cstate)
Definition: copy.c:3876
#define makeNode(_type_)
Definition: nodes.h:577
#define Assert(condition)
Definition: c.h:745
#define lfirst(lc)
Definition: pg_list.h:190
#define ACL_INSERT
Definition: parsenodes.h:74
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:407
Node * query
Definition: parsenodes.h:2011
bool is_from
Definition: parsenodes.h:2015
int errmsg(const char *fmt,...)
Definition: elog.c:824
Bitmapset * insertedCols
Definition: parsenodes.h:1122
bool ExecCheckRTPerms(List *rangeTable, bool ereport_on_violation)
Definition: execMain.c:571
char * filename
Definition: parsenodes.h:2017
static void EndCopyTo(CopyState cstate)
Definition: copy.c:2043
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:456
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:422
List * fields
Definition: parsenodes.h:236
#define RelationGetNamespace(relation)
Definition: rel.h:497
Node * coerce_to_boolean(ParseState *pstate, Node *node, const char *constructName)

◆ EndCopyFrom()

void EndCopyFrom ( CopyState  cstate)

Definition at line 3876 of file copy.c.

References EndCopy().

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

3877 {
3878  /* No COPY FROM related resources except memory. */
3879 
3880  EndCopy(cstate);
3881 }
static void EndCopy(CopyState cstate)
Definition: copy.c:1849

◆ NextCopyFrom()

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

Definition at line 3691 of file copy.c.

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

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

3693 {
3694  TupleDesc tupDesc;
3695  AttrNumber num_phys_attrs,
3696  attr_count,
3697  num_defaults = cstate->num_defaults;
3698  FmgrInfo *in_functions = cstate->in_functions;
3699  Oid *typioparams = cstate->typioparams;
3700  int i;
3701  int *defmap = cstate->defmap;
3702  ExprState **defexprs = cstate->defexprs;
3703 
3704  tupDesc = RelationGetDescr(cstate->rel);
3705  num_phys_attrs = tupDesc->natts;
3706  attr_count = list_length(cstate->attnumlist);
3707 
3708  /* Initialize all values for row to NULL */
3709  MemSet(values, 0, num_phys_attrs * sizeof(Datum));
3710  MemSet(nulls, true, num_phys_attrs * sizeof(bool));
3711 
3712  if (!cstate->binary)
3713  {
3714  char **field_strings;
3715  ListCell *cur;
3716  int fldct;
3717  int fieldno;
3718  char *string;
3719 
3720  /* read raw fields in the next line */
3721  if (!NextCopyFromRawFields(cstate, &field_strings, &fldct))
3722  return false;
3723 
3724  /* check for overflowing fields */
3725  if (attr_count > 0 && fldct > attr_count)
3726  ereport(ERROR,
3727  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
3728  errmsg("extra data after last expected column")));
3729 
3730  fieldno = 0;
3731 
3732  /* Loop to read the user attributes on the line. */
3733  foreach(cur, cstate->attnumlist)
3734  {
3735  int attnum = lfirst_int(cur);
3736  int m = attnum - 1;
3737  Form_pg_attribute att = TupleDescAttr(tupDesc, m);
3738 
3739  if (fieldno >= fldct)
3740  ereport(ERROR,
3741  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
3742  errmsg("missing data for column \"%s\"",
3743  NameStr(att->attname))));
3744  string = field_strings[fieldno++];
3745 
3746  if (cstate->convert_select_flags &&
3747  !cstate->convert_select_flags[m])
3748  {
3749  /* ignore input field, leaving column as NULL */
3750  continue;
3751  }
3752 
3753  if (cstate->csv_mode)
3754  {
3755  if (string == NULL &&
3756  cstate->force_notnull_flags[m])
3757  {
3758  /*
3759  * FORCE_NOT_NULL option is set and column is NULL -
3760  * convert it to the NULL string.
3761  */
3762  string = cstate->null_print;
3763  }
3764  else if (string != NULL && cstate->force_null_flags[m]
3765  && strcmp(string, cstate->null_print) == 0)
3766  {
3767  /*
3768  * FORCE_NULL option is set and column matches the NULL
3769  * string. It must have been quoted, or otherwise the
3770  * string would already have been set to NULL. Convert it
3771  * to NULL as specified.
3772  */
3773  string = NULL;
3774  }
3775  }
3776 
3777  cstate->cur_attname = NameStr(att->attname);
3778  cstate->cur_attval = string;
3779  values[m] = InputFunctionCall(&in_functions[m],
3780  string,
3781  typioparams[m],
3782  att->atttypmod);
3783  if (string != NULL)
3784  nulls[m] = false;
3785  cstate->cur_attname = NULL;
3786  cstate->cur_attval = NULL;
3787  }
3788 
3789  Assert(fieldno == attr_count);
3790  }
3791  else
3792  {
3793  /* binary */
3794  int16 fld_count;
3795  ListCell *cur;
3796 
3797  cstate->cur_lineno++;
3798 
3799  if (!CopyGetInt16(cstate, &fld_count))
3800  {
3801  /* EOF detected (end of file, or protocol-level EOF) */
3802  return false;
3803  }
3804 
3805  if (fld_count == -1)
3806  {
3807  /*
3808  * Received EOF marker. In a V3-protocol copy, wait for the
3809  * protocol-level EOF, and complain if it doesn't come
3810  * immediately. This ensures that we correctly handle CopyFail,
3811  * if client chooses to send that now.
3812  *
3813  * Note that we MUST NOT try to read more data in an old-protocol
3814  * copy, since there is no protocol-level EOF marker then. We
3815  * could go either way for copy from file, but choose to throw
3816  * error if there's data after the EOF marker, for consistency
3817  * with the new-protocol case.
3818  */
3819  char dummy;
3820 
3821  if (cstate->copy_dest != COPY_OLD_FE &&
3822  CopyReadBinaryData(cstate, &dummy, 1) > 0)
3823  ereport(ERROR,
3824  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
3825  errmsg("received copy data after EOF marker")));
3826  return false;
3827  }
3828 
3829  if (fld_count != attr_count)
3830  ereport(ERROR,
3831  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
3832  errmsg("row field count is %d, expected %d",
3833  (int) fld_count, attr_count)));
3834 
3835  foreach(cur, cstate->attnumlist)
3836  {
3837  int attnum = lfirst_int(cur);
3838  int m = attnum - 1;
3839  Form_pg_attribute att = TupleDescAttr(tupDesc, m);
3840 
3841  cstate->cur_attname = NameStr(att->attname);
3842  values[m] = CopyReadBinaryAttribute(cstate,
3843  &in_functions[m],
3844  typioparams[m],
3845  att->atttypmod,
3846  &nulls[m]);
3847  cstate->cur_attname = NULL;
3848  }
3849  }
3850 
3851  /*
3852  * Now compute and insert any defaults available for the columns not
3853  * provided by the input data. Anything not processed here or above will
3854  * remain NULL.
3855  */
3856  for (i = 0; i < num_defaults; i++)
3857  {
3858  /*
3859  * The caller must supply econtext and have switched into the
3860  * per-tuple memory context in it.
3861  */
3862  Assert(econtext != NULL);
3864 
3865  values[defmap[i]] = ExecEvalExpr(defexprs[i], econtext,
3866  &nulls[defmap[i]]);
3867  }
3868 
3869  return true;
3870 }
signed short int16
Definition: c.h:361
bool NextCopyFromRawFields(CopyState cstate, char ***fields, int *nfields)
Definition: copy.c:3639
Definition: fmgr.h:56
bool csv_mode
Definition: copy.c:138
bool binary
Definition: copy.c:136
#define RelationGetDescr(relation)
Definition: rel.h:482
static Datum CopyReadBinaryAttribute(CopyState cstate, FmgrInfo *flinfo, Oid typioparam, int32 typmod, bool *isnull)
Definition: copy.c:4770
FmgrInfo * in_functions
Definition: copy.c:179
AttrNumber num_defaults
Definition: copy.c:178
List * attnumlist
Definition: copy.c:132
#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:610
#define MemSet(start, val, len)
Definition: c.h:978
unsigned int Oid
Definition: postgres_ext.h:31
bool * force_null_flags
Definition: copy.c:152
bool * convert_select_flags
Definition: copy.c:155
CopyDest copy_dest
Definition: copy.c:117
uint64 cur_lineno
Definition: copy.c:160
char * null_print
Definition: copy.c:140
const char * cur_attname
Definition: copy.c:161
Relation rel
Definition: copy.c:130
#define ERROR
Definition: elog.h:43
#define lfirst_int(lc)
Definition: pg_list.h:191
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:290
ExprState ** defexprs
Definition: copy.c:182
char string[11]
Definition: preproc-type.c:46
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
static int CopyReadBinaryData(CopyState cstate, char *dest, int nbytes)
Definition: copy.c:827
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
Oid * typioparams
Definition: copy.c:180
uintptr_t Datum
Definition: postgres.h:367
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1533
int16 attnum
Definition: pg_attribute.h:79
#define ereport(elevel,...)
Definition: elog.h:144
bool * force_notnull_flags
Definition: copy.c:150
#define Assert(condition)
Definition: c.h:745
static int list_length(const List *l)
Definition: pg_list.h:169
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
#define NameStr(name)
Definition: c.h:622
static bool CopyGetInt16(CopyState cstate, int16 *val)
Definition: copy.c:776
const char * cur_attval
Definition: copy.c:162
int16 AttrNumber
Definition: attnum.h:21
int * defmap
Definition: copy.c:181

◆ NextCopyFromRawFields()

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

Definition at line 3639 of file copy.c.

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

Referenced by NextCopyFrom().

3640 {
3641  int fldct;
3642  bool done;
3643 
3644  /* only available for text or csv input */
3645  Assert(!cstate->binary);
3646 
3647  /* on input just throw the header line away */
3648  if (cstate->cur_lineno == 0 && cstate->header_line)
3649  {
3650  cstate->cur_lineno++;
3651  if (CopyReadLine(cstate))
3652  return false; /* done */
3653  }
3654 
3655  cstate->cur_lineno++;
3656 
3657  /* Actually read the line into memory here */
3658  done = CopyReadLine(cstate);
3659 
3660  /*
3661  * EOF at start of line means we're done. If we see EOF after some
3662  * characters, we act as though it was newline followed by EOF, ie,
3663  * process the line and then exit loop on next iteration.
3664  */
3665  if (done && cstate->line_buf.len == 0)
3666  return false;
3667 
3668  /* Parse the line into de-escaped field values */
3669  if (cstate->csv_mode)
3670  fldct = CopyReadAttributesCSV(cstate);
3671  else
3672  fldct = CopyReadAttributesText(cstate);
3673 
3674  *fields = cstate->raw_fields;
3675  *nfields = fldct;
3676  return true;
3677 }
bool csv_mode
Definition: copy.c:138
char ** raw_fields
Definition: copy.c:205
bool binary
Definition: copy.c:136
StringInfoData line_buf
Definition: copy.c:215
static int CopyReadAttributesCSV(CopyState cstate)
Definition: copy.c:4601
uint64 cur_lineno
Definition: copy.c:160
bool header_line
Definition: copy.c:139
#define Assert(condition)
Definition: c.h:745
static bool CopyReadLine(CopyState cstate)
Definition: copy.c:3892
static int CopyReadAttributesText(CopyState cstate)
Definition: copy.c:4373

◆ ProcessCopyOptions()

void ProcessCopyOptions ( ParseState pstate,
CopyState  cstate,
bool  is_from,
List options 
)

Definition at line 1156 of file copy.c.

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

Referenced by BeginCopy(), and file_fdw_validator().

1160 {
1161  bool format_specified = false;
1162  ListCell *option;
1163 
1164  /* Support external use for option sanity checking */
1165  if (cstate == NULL)
1166  cstate = (CopyStateData *) palloc0(sizeof(CopyStateData));
1167 
1168  cstate->is_copy_from = is_from;
1169 
1170  cstate->file_encoding = -1;
1171 
1172  /* Extract options from the statement node tree */
1173  foreach(option, options)
1174  {
1175  DefElem *defel = lfirst_node(DefElem, option);
1176 
1177  if (strcmp(defel->defname, "format") == 0)
1178  {
1179  char *fmt = defGetString(defel);
1180 
1181  if (format_specified)
1182  ereport(ERROR,
1183  (errcode(ERRCODE_SYNTAX_ERROR),
1184  errmsg("conflicting or redundant options"),
1185  parser_errposition(pstate, defel->location)));
1186  format_specified = true;
1187  if (strcmp(fmt, "text") == 0)
1188  /* default format */ ;
1189  else if (strcmp(fmt, "csv") == 0)
1190  cstate->csv_mode = true;
1191  else if (strcmp(fmt, "binary") == 0)
1192  cstate->binary = true;
1193  else
1194  ereport(ERROR,
1195  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1196  errmsg("COPY format \"%s\" not recognized", fmt),
1197  parser_errposition(pstate, defel->location)));
1198  }
1199  else if (strcmp(defel->defname, "freeze") == 0)
1200  {
1201  if (cstate->freeze)
1202  ereport(ERROR,
1203  (errcode(ERRCODE_SYNTAX_ERROR),
1204  errmsg("conflicting or redundant options"),
1205  parser_errposition(pstate, defel->location)));
1206  cstate->freeze = defGetBoolean(defel);
1207  }
1208  else if (strcmp(defel->defname, "delimiter") == 0)
1209  {
1210  if (cstate->delim)
1211  ereport(ERROR,
1212  (errcode(ERRCODE_SYNTAX_ERROR),
1213  errmsg("conflicting or redundant options"),
1214  parser_errposition(pstate, defel->location)));
1215  cstate->delim = defGetString(defel);
1216  }
1217  else if (strcmp(defel->defname, "null") == 0)
1218  {
1219  if (cstate->null_print)
1220  ereport(ERROR,
1221  (errcode(ERRCODE_SYNTAX_ERROR),
1222  errmsg("conflicting or redundant options"),
1223  parser_errposition(pstate, defel->location)));
1224  cstate->null_print = defGetString(defel);
1225  }
1226  else if (strcmp(defel->defname, "header") == 0)
1227  {
1228  if (cstate->header_line)
1229  ereport(ERROR,
1230  (errcode(ERRCODE_SYNTAX_ERROR),
1231  errmsg("conflicting or redundant options"),
1232  parser_errposition(pstate, defel->location)));
1233  cstate->header_line = defGetBoolean(defel);
1234  }
1235  else if (strcmp(defel->defname, "quote") == 0)
1236  {
1237  if (cstate->quote)
1238  ereport(ERROR,
1239  (errcode(ERRCODE_SYNTAX_ERROR),
1240  errmsg("conflicting or redundant options"),
1241  parser_errposition(pstate, defel->location)));
1242  cstate->quote = defGetString(defel);
1243  }
1244  else if (strcmp(defel->defname, "escape") == 0)
1245  {
1246  if (cstate->escape)
1247  ereport(ERROR,
1248  (errcode(ERRCODE_SYNTAX_ERROR),
1249  errmsg("conflicting or redundant options"),
1250  parser_errposition(pstate, defel->location)));
1251  cstate->escape = defGetString(defel);
1252  }
1253  else if (strcmp(defel->defname, "force_quote") == 0)
1254  {
1255  if (cstate->force_quote || cstate->force_quote_all)
1256  ereport(ERROR,
1257  (errcode(ERRCODE_SYNTAX_ERROR),
1258  errmsg("conflicting or redundant options"),
1259  parser_errposition(pstate, defel->location)));
1260  if (defel->arg && IsA(defel->arg, A_Star))
1261  cstate->force_quote_all = true;
1262  else if (defel->arg && IsA(defel->arg, List))
1263  cstate->force_quote = castNode(List, defel->arg);
1264  else
1265  ereport(ERROR,
1266  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1267  errmsg("argument to option \"%s\" must be a list of column names",
1268  defel->defname),
1269  parser_errposition(pstate, defel->location)));
1270  }
1271  else if (strcmp(defel->defname, "force_not_null") == 0)
1272  {
1273  if (cstate->force_notnull)
1274  ereport(ERROR,
1275  (errcode(ERRCODE_SYNTAX_ERROR),
1276  errmsg("conflicting or redundant options"),
1277  parser_errposition(pstate, defel->location)));
1278  if (defel->arg && IsA(defel->arg, List))
1279  cstate->force_notnull = castNode(List, defel->arg);
1280  else
1281  ereport(ERROR,
1282  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1283  errmsg("argument to option \"%s\" must be a list of column names",
1284  defel->defname),
1285  parser_errposition(pstate, defel->location)));
1286  }
1287  else if (strcmp(defel->defname, "force_null") == 0)
1288  {
1289  if (cstate->force_null)
1290  ereport(ERROR,
1291  (errcode(ERRCODE_SYNTAX_ERROR),
1292  errmsg("conflicting or redundant options")));
1293  if (defel->arg && IsA(defel->arg, List))
1294  cstate->force_null = castNode(List, defel->arg);
1295  else
1296  ereport(ERROR,
1297  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1298  errmsg("argument to option \"%s\" must be a list of column names",
1299  defel->defname),
1300  parser_errposition(pstate, defel->location)));
1301  }
1302  else if (strcmp(defel->defname, "convert_selectively") == 0)
1303  {
1304  /*
1305  * Undocumented, not-accessible-from-SQL option: convert only the
1306  * named columns to binary form, storing the rest as NULLs. It's
1307  * allowed for the column list to be NIL.
1308  */
1309  if (cstate->convert_selectively)
1310  ereport(ERROR,
1311  (errcode(ERRCODE_SYNTAX_ERROR),
1312  errmsg("conflicting or redundant options"),
1313  parser_errposition(pstate, defel->location)));
1314  cstate->convert_selectively = true;
1315  if (defel->arg == NULL || IsA(defel->arg, List))
1316  cstate->convert_select = castNode(List, defel->arg);
1317  else
1318  ereport(ERROR,
1319  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1320  errmsg("argument to option \"%s\" must be a list of column names",
1321  defel->defname),
1322  parser_errposition(pstate, defel->location)));
1323  }
1324  else if (strcmp(defel->defname, "encoding") == 0)
1325  {
1326  if (cstate->file_encoding >= 0)
1327  ereport(ERROR,
1328  (errcode(ERRCODE_SYNTAX_ERROR),
1329  errmsg("conflicting or redundant options"),
1330  parser_errposition(pstate, defel->location)));
1332  if (cstate->file_encoding < 0)
1333  ereport(ERROR,
1334  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1335  errmsg("argument to option \"%s\" must be a valid encoding name",
1336  defel->defname),
1337  parser_errposition(pstate, defel->location)));
1338  }
1339  else
1340  ereport(ERROR,
1341  (errcode(ERRCODE_SYNTAX_ERROR),
1342  errmsg("option \"%s\" not recognized",
1343  defel->defname),
1344  parser_errposition(pstate, defel->location)));
1345  }
1346 
1347  /*
1348  * Check for incompatible options (must do these two before inserting
1349  * defaults)
1350  */
1351  if (cstate->binary && cstate->delim)
1352  ereport(ERROR,
1353  (errcode(ERRCODE_SYNTAX_ERROR),
1354  errmsg("cannot specify DELIMITER in BINARY mode")));
1355 
1356  if (cstate->binary && cstate->null_print)
1357  ereport(ERROR,
1358  (errcode(ERRCODE_SYNTAX_ERROR),
1359  errmsg("cannot specify NULL in BINARY mode")));
1360 
1361  /* Set defaults for omitted options */
1362  if (!cstate->delim)
1363  cstate->delim = cstate->csv_mode ? "," : "\t";
1364 
1365  if (!cstate->null_print)
1366  cstate->null_print = cstate->csv_mode ? "" : "\\N";
1367  cstate->null_print_len = strlen(cstate->null_print);
1368 
1369  if (cstate->csv_mode)
1370  {
1371  if (!cstate->quote)
1372  cstate->quote = "\"";
1373  if (!cstate->escape)
1374  cstate->escape = cstate->quote;
1375  }
1376 
1377  /* Only single-byte delimiter strings are supported. */
1378  if (strlen(cstate->delim) != 1)
1379  ereport(ERROR,
1380  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1381  errmsg("COPY delimiter must be a single one-byte character")));
1382 
1383  /* Disallow end-of-line characters */
1384  if (strchr(cstate->delim, '\r') != NULL ||
1385  strchr(cstate->delim, '\n') != NULL)
1386  ereport(ERROR,
1387  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1388  errmsg("COPY delimiter cannot be newline or carriage return")));
1389 
1390  if (strchr(cstate->null_print, '\r') != NULL ||
1391  strchr(cstate->null_print, '\n') != NULL)
1392  ereport(ERROR,
1393  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1394  errmsg("COPY null representation cannot use newline or carriage return")));
1395 
1396  /*
1397  * Disallow unsafe delimiter characters in non-CSV mode. We can't allow
1398  * backslash because it would be ambiguous. We can't allow the other
1399  * cases because data characters matching the delimiter must be
1400  * backslashed, and certain backslash combinations are interpreted
1401  * non-literally by COPY IN. Disallowing all lower case ASCII letters is
1402  * more than strictly necessary, but seems best for consistency and
1403  * future-proofing. Likewise we disallow all digits though only octal
1404  * digits are actually dangerous.
1405  */
1406  if (!cstate->csv_mode &&
1407  strchr("\\.abcdefghijklmnopqrstuvwxyz0123456789",
1408  cstate->delim[0]) != NULL)
1409  ereport(ERROR,
1410  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1411  errmsg("COPY delimiter cannot be \"%s\"", cstate->delim)));
1412 
1413  /* Check header */
1414  if (!cstate->csv_mode && cstate->header_line)
1415  ereport(ERROR,
1416  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1417  errmsg("COPY HEADER available only in CSV mode")));
1418 
1419  /* Check quote */
1420  if (!cstate->csv_mode && cstate->quote != NULL)
1421  ereport(ERROR,
1422  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1423  errmsg("COPY quote available only in CSV mode")));
1424 
1425  if (cstate->csv_mode && strlen(cstate->quote) != 1)
1426  ereport(ERROR,
1427  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1428  errmsg("COPY quote must be a single one-byte character")));
1429 
1430  if (cstate->csv_mode && cstate->delim[0] == cstate->quote[0])
1431  ereport(ERROR,
1432  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1433  errmsg("COPY delimiter and quote must be different")));
1434 
1435  /* Check escape */
1436  if (!cstate->csv_mode && cstate->escape != NULL)
1437  ereport(ERROR,
1438  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1439  errmsg("COPY escape available only in CSV mode")));
1440 
1441  if (cstate->csv_mode && strlen(cstate->escape) != 1)
1442  ereport(ERROR,
1443  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1444  errmsg("COPY escape must be a single one-byte character")));
1445 
1446  /* Check force_quote */
1447  if (!cstate->csv_mode && (cstate->force_quote || cstate->force_quote_all))
1448  ereport(ERROR,
1449  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1450  errmsg("COPY force quote available only in CSV mode")));
1451  if ((cstate->force_quote || cstate->force_quote_all) && is_from)
1452  ereport(ERROR,
1453  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1454  errmsg("COPY force quote only available using COPY TO")));
1455 
1456  /* Check force_notnull */
1457  if (!cstate->csv_mode && cstate->force_notnull != NIL)
1458  ereport(ERROR,
1459  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1460  errmsg("COPY force not null available only in CSV mode")));
1461  if (cstate->force_notnull != NIL && !is_from)
1462  ereport(ERROR,
1463  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1464  errmsg("COPY force not null only available using COPY FROM")));
1465 
1466  /* Check force_null */
1467  if (!cstate->csv_mode && cstate->force_null != NIL)
1468  ereport(ERROR,
1469  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1470  errmsg("COPY force null available only in CSV mode")));
1471 
1472  if (cstate->force_null != NIL && !is_from)
1473  ereport(ERROR,
1474  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1475  errmsg("COPY force null only available using COPY FROM")));
1476 
1477  /* Don't allow the delimiter to appear in the null string. */
1478  if (strchr(cstate->null_print, cstate->delim[0]) != NULL)
1479  ereport(ERROR,
1480  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1481  errmsg("COPY delimiter must not appear in the NULL specification")));
1482 
1483  /* Don't allow the CSV quote char to appear in the null string. */
1484  if (cstate->csv_mode &&
1485  strchr(cstate->null_print, cstate->quote[0]) != NULL)
1486  ereport(ERROR,
1487  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1488  errmsg("CSV quote character must not appear in the NULL specification")));
1489 }
#define NIL
Definition: pg_list.h:65
bool csv_mode
Definition: copy.c:138
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
int pg_char_to_encoding(const char *name)
Definition: encnames.c:550
bool binary
Definition: copy.c:136
#define castNode(_type_, nodeptr)
Definition: nodes.h:598
int errcode(int sqlerrcode)
Definition: elog.c:610
char * delim
Definition: copy.c:143
char * null_print
Definition: copy.c:140
bool defGetBoolean(DefElem *def)
Definition: define.c:111
#define ERROR
Definition: elog.h:43
char * defGetString(DefElem *def)
Definition: define.c:49
#define lfirst_node(type, lc)
Definition: pg_list.h:193
char * quote
Definition: copy.c:144
int location
Definition: parsenodes.h:735
bool is_copy_from
Definition: copy.c:121
char * escape
Definition: copy.c:145
int null_print_len
Definition: copy.c:141
List * force_null
Definition: copy.c:151
Node * arg
Definition: parsenodes.h:733
int file_encoding
Definition: copy.c:125
void * palloc0(Size size)
Definition: mcxt.c:980
bool header_line
Definition: copy.c:139
bool freeze
Definition: copy.c:137
#define ereport(elevel,...)
Definition: elog.h:144
List * force_notnull
Definition: copy.c:149
List * convert_select
Definition: copy.c:154
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
bool force_quote_all
Definition: copy.c:147
int errmsg(const char *fmt,...)
Definition: elog.c:824
char * defname
Definition: parsenodes.h:732
Definition: pg_list.h:50
List * force_quote
Definition: copy.c:146
bool convert_selectively
Definition: copy.c:153