PostgreSQL Source Code  git master
copyfrom.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * copyfrom.c
4  * COPY <table> FROM file/program/client
5  *
6  * This file contains routines needed to efficiently load tuples into a
7  * table. That includes looking up the correct partition, firing triggers,
8  * calling the table AM function to insert the data, and updating indexes.
9  * Reading data from the input file or client and parsing it into Datums
10  * is handled in copyfromparse.c.
11  *
12  * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
13  * Portions Copyright (c) 1994, Regents of the University of California
14  *
15  *
16  * IDENTIFICATION
17  * src/backend/commands/copyfrom.c
18  *
19  *-------------------------------------------------------------------------
20  */
21 #include "postgres.h"
22 
23 #include <ctype.h>
24 #include <unistd.h>
25 #include <sys/stat.h>
26 
27 #include "access/heapam.h"
28 #include "access/htup_details.h"
29 #include "access/tableam.h"
30 #include "access/xact.h"
31 #include "access/xlog.h"
32 #include "catalog/namespace.h"
33 #include "commands/copy.h"
35 #include "commands/progress.h"
36 #include "commands/trigger.h"
37 #include "executor/execPartition.h"
38 #include "executor/executor.h"
40 #include "executor/tuptable.h"
41 #include "foreign/fdwapi.h"
42 #include "libpq/libpq.h"
43 #include "libpq/pqformat.h"
44 #include "miscadmin.h"
45 #include "optimizer/optimizer.h"
46 #include "pgstat.h"
47 #include "rewrite/rewriteHandler.h"
48 #include "storage/fd.h"
49 #include "tcop/tcopprot.h"
50 #include "utils/lsyscache.h"
51 #include "utils/memutils.h"
52 #include "utils/portal.h"
53 #include "utils/rel.h"
54 #include "utils/snapmgr.h"
55 
56 /*
57  * No more than this many tuples per CopyMultiInsertBuffer
58  *
59  * Caution: Don't make this too big, as we could end up with this many
60  * CopyMultiInsertBuffer items stored in CopyMultiInsertInfo's
61  * multiInsertBuffers list. Increasing this can cause quadratic growth in
62  * memory requirements during copies into partitioned tables with a large
63  * number of partitions.
64  */
65 #define MAX_BUFFERED_TUPLES 1000
66 
67 /*
68  * Flush buffers if there are >= this many bytes, as counted by the input
69  * size, of tuples stored.
70  */
71 #define MAX_BUFFERED_BYTES 65535
72 
73 /* Trim the list of buffers back down to this number after flushing */
74 #define MAX_PARTITION_BUFFERS 32
75 
76 /* Stores multi-insert data related to a single relation in CopyFrom. */
77 typedef struct CopyMultiInsertBuffer
78 {
79  TupleTableSlot *slots[MAX_BUFFERED_TUPLES]; /* Array to store tuples */
80  ResultRelInfo *resultRelInfo; /* ResultRelInfo for 'relid' */
81  BulkInsertState bistate; /* BulkInsertState for this rel */
82  int nused; /* number of 'slots' containing tuples */
83  uint64 linenos[MAX_BUFFERED_TUPLES]; /* Line # of tuple in copy
84  * stream */
86 
87 /*
88  * Stores one or many CopyMultiInsertBuffers and details about the size and
89  * number of tuples which are stored in them. This allows multiple buffers to
90  * exist at once when COPYing into a partitioned table.
91  */
92 typedef struct CopyMultiInsertInfo
93 {
94  List *multiInsertBuffers; /* List of tracked CopyMultiInsertBuffers */
95  int bufferedTuples; /* number of tuples buffered over all buffers */
96  int bufferedBytes; /* number of bytes from all buffered tuples */
97  CopyFromState cstate; /* Copy state for this CopyMultiInsertInfo */
98  EState *estate; /* Executor state used for COPY */
99  CommandId mycid; /* Command Id used for COPY */
100  int ti_options; /* table insert options */
102 
103 
104 /* non-export function prototypes */
105 static char *limit_printout_length(const char *str);
106 
107 static void ClosePipeFromProgram(CopyFromState cstate);
108 
109 /*
110  * error context callback for COPY FROM
111  *
112  * The argument for the error context must be CopyFromState.
113  */
114 void
116 {
117  CopyFromState cstate = (CopyFromState) arg;
118 
119  if (cstate->opts.binary)
120  {
121  /* can't usefully display the data */
122  if (cstate->cur_attname)
123  errcontext("COPY %s, line %llu, column %s",
124  cstate->cur_relname,
125  (unsigned long long) cstate->cur_lineno,
126  cstate->cur_attname);
127  else
128  errcontext("COPY %s, line %llu",
129  cstate->cur_relname,
130  (unsigned long long) cstate->cur_lineno);
131  }
132  else
133  {
134  if (cstate->cur_attname && cstate->cur_attval)
135  {
136  /* error is relevant to a particular column */
137  char *attval;
138 
139  attval = limit_printout_length(cstate->cur_attval);
140  errcontext("COPY %s, line %llu, column %s: \"%s\"",
141  cstate->cur_relname,
142  (unsigned long long) cstate->cur_lineno,
143  cstate->cur_attname,
144  attval);
145  pfree(attval);
146  }
147  else if (cstate->cur_attname)
148  {
149  /* error is relevant to a particular column, value is NULL */
150  errcontext("COPY %s, line %llu, column %s: null input",
151  cstate->cur_relname,
152  (unsigned long long) cstate->cur_lineno,
153  cstate->cur_attname);
154  }
155  else
156  {
157  /*
158  * Error is relevant to a particular line.
159  *
160  * If line_buf still contains the correct line, print it.
161  */
162  if (cstate->line_buf_valid)
163  {
164  char *lineval;
165 
166  lineval = limit_printout_length(cstate->line_buf.data);
167  errcontext("COPY %s, line %llu: \"%s\"",
168  cstate->cur_relname,
169  (unsigned long long) cstate->cur_lineno, lineval);
170  pfree(lineval);
171  }
172  else
173  {
174  errcontext("COPY %s, line %llu",
175  cstate->cur_relname,
176  (unsigned long long) cstate->cur_lineno);
177  }
178  }
179  }
180 }
181 
182 /*
183  * Make sure we don't print an unreasonable amount of COPY data in a message.
184  *
185  * Returns a pstrdup'd copy of the input.
186  */
187 static char *
189 {
190 #define MAX_COPY_DATA_DISPLAY 100
191 
192  int slen = strlen(str);
193  int len;
194  char *res;
195 
196  /* Fast path if definitely okay */
197  if (slen <= MAX_COPY_DATA_DISPLAY)
198  return pstrdup(str);
199 
200  /* Apply encoding-dependent truncation */
202 
203  /*
204  * Truncate, and add "..." to show we truncated the input.
205  */
206  res = (char *) palloc(len + 4);
207  memcpy(res, str, len);
208  strcpy(res + len, "...");
209 
210  return res;
211 }
212 
213 /*
214  * Allocate memory and initialize a new CopyMultiInsertBuffer for this
215  * ResultRelInfo.
216  */
217 static CopyMultiInsertBuffer *
219 {
220  CopyMultiInsertBuffer *buffer;
221 
222  buffer = (CopyMultiInsertBuffer *) palloc(sizeof(CopyMultiInsertBuffer));
223  memset(buffer->slots, 0, sizeof(TupleTableSlot *) * MAX_BUFFERED_TUPLES);
224  buffer->resultRelInfo = rri;
225  buffer->bistate = GetBulkInsertState();
226  buffer->nused = 0;
227 
228  return buffer;
229 }
230 
231 /*
232  * Make a new buffer for this ResultRelInfo.
233  */
234 static inline void
236  ResultRelInfo *rri)
237 {
238  CopyMultiInsertBuffer *buffer;
239 
240  buffer = CopyMultiInsertBufferInit(rri);
241 
242  /* Setup back-link so we can easily find this buffer again */
243  rri->ri_CopyMultiInsertBuffer = buffer;
244  /* Record that we're tracking this buffer */
245  miinfo->multiInsertBuffers = lappend(miinfo->multiInsertBuffers, buffer);
246 }
247 
248 /*
249  * Initialize an already allocated CopyMultiInsertInfo.
250  *
251  * If rri is a non-partitioned table then a CopyMultiInsertBuffer is set up
252  * for that table.
253  */
254 static void
256  CopyFromState cstate, EState *estate, CommandId mycid,
257  int ti_options)
258 {
259  miinfo->multiInsertBuffers = NIL;
260  miinfo->bufferedTuples = 0;
261  miinfo->bufferedBytes = 0;
262  miinfo->cstate = cstate;
263  miinfo->estate = estate;
264  miinfo->mycid = mycid;
265  miinfo->ti_options = ti_options;
266 
267  /*
268  * Only setup the buffer when not dealing with a partitioned table.
269  * Buffers for partitioned tables will just be setup when we need to send
270  * tuples their way for the first time.
271  */
272  if (rri->ri_RelationDesc->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
273  CopyMultiInsertInfoSetupBuffer(miinfo, rri);
274 }
275 
276 /*
277  * Returns true if the buffers are full
278  */
279 static inline bool
281 {
282  if (miinfo->bufferedTuples >= MAX_BUFFERED_TUPLES ||
284  return true;
285  return false;
286 }
287 
288 /*
289  * Returns true if we have no buffered tuples
290  */
291 static inline bool
293 {
294  return miinfo->bufferedTuples == 0;
295 }
296 
297 /*
298  * Write the tuples stored in 'buffer' out to the table.
299  */
300 static inline void
302  CopyMultiInsertBuffer *buffer)
303 {
304  MemoryContext oldcontext;
305  int i;
306  uint64 save_cur_lineno;
307  CopyFromState cstate = miinfo->cstate;
308  EState *estate = miinfo->estate;
309  CommandId mycid = miinfo->mycid;
310  int ti_options = miinfo->ti_options;
311  bool line_buf_valid = cstate->line_buf_valid;
312  int nused = buffer->nused;
313  ResultRelInfo *resultRelInfo = buffer->resultRelInfo;
314  TupleTableSlot **slots = buffer->slots;
315 
316  /*
317  * Print error context information correctly, if one of the operations
318  * below fails.
319  */
320  cstate->line_buf_valid = false;
321  save_cur_lineno = cstate->cur_lineno;
322 
323  /*
324  * table_multi_insert may leak memory, so switch to short-lived memory
325  * context before calling it.
326  */
327  oldcontext = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
328  table_multi_insert(resultRelInfo->ri_RelationDesc,
329  slots,
330  nused,
331  mycid,
332  ti_options,
333  buffer->bistate);
334  MemoryContextSwitchTo(oldcontext);
335 
336  for (i = 0; i < nused; i++)
337  {
338  /*
339  * If there are any indexes, update them for all the inserted tuples,
340  * and run AFTER ROW INSERT triggers.
341  */
342  if (resultRelInfo->ri_NumIndices > 0)
343  {
344  List *recheckIndexes;
345 
346  cstate->cur_lineno = buffer->linenos[i];
347  recheckIndexes =
348  ExecInsertIndexTuples(resultRelInfo,
349  buffer->slots[i], estate, false, false,
350  NULL, NIL);
351  ExecARInsertTriggers(estate, resultRelInfo,
352  slots[i], recheckIndexes,
353  cstate->transition_capture);
354  list_free(recheckIndexes);
355  }
356 
357  /*
358  * There's no indexes, but see if we need to run AFTER ROW INSERT
359  * triggers anyway.
360  */
361  else if (resultRelInfo->ri_TrigDesc != NULL &&
362  (resultRelInfo->ri_TrigDesc->trig_insert_after_row ||
363  resultRelInfo->ri_TrigDesc->trig_insert_new_table))
364  {
365  cstate->cur_lineno = buffer->linenos[i];
366  ExecARInsertTriggers(estate, resultRelInfo,
367  slots[i], NIL, cstate->transition_capture);
368  }
369 
370  ExecClearTuple(slots[i]);
371  }
372 
373  /* Mark that all slots are free */
374  buffer->nused = 0;
375 
376  /* reset cur_lineno and line_buf_valid to what they were */
377  cstate->line_buf_valid = line_buf_valid;
378  cstate->cur_lineno = save_cur_lineno;
379 }
380 
381 /*
382  * Drop used slots and free member for this buffer.
383  *
384  * The buffer must be flushed before cleanup.
385  */
386 static inline void
388  CopyMultiInsertBuffer *buffer)
389 {
390  int i;
391 
392  /* Ensure buffer was flushed */
393  Assert(buffer->nused == 0);
394 
395  /* Remove back-link to ourself */
396  buffer->resultRelInfo->ri_CopyMultiInsertBuffer = NULL;
397 
398  FreeBulkInsertState(buffer->bistate);
399 
400  /* Since we only create slots on demand, just drop the non-null ones. */
401  for (i = 0; i < MAX_BUFFERED_TUPLES && buffer->slots[i] != NULL; i++)
403 
405  miinfo->ti_options);
406 
407  pfree(buffer);
408 }
409 
410 /*
411  * Write out all stored tuples in all buffers out to the tables.
412  *
413  * Once flushed we also trim the tracked buffers list down to size by removing
414  * the buffers created earliest first.
415  *
416  * Callers should pass 'curr_rri' as the ResultRelInfo that's currently being
417  * used. When cleaning up old buffers we'll never remove the one for
418  * 'curr_rri'.
419  */
420 static inline void
422 {
423  ListCell *lc;
424 
425  foreach(lc, miinfo->multiInsertBuffers)
426  {
428 
429  CopyMultiInsertBufferFlush(miinfo, buffer);
430  }
431 
432  miinfo->bufferedTuples = 0;
433  miinfo->bufferedBytes = 0;
434 
435  /*
436  * Trim the list of tracked buffers down if it exceeds the limit. Here we
437  * remove buffers starting with the ones we created first. It seems less
438  * likely that these older ones will be needed than the ones that were
439  * just created.
440  */
442  {
443  CopyMultiInsertBuffer *buffer;
444 
445  buffer = (CopyMultiInsertBuffer *) linitial(miinfo->multiInsertBuffers);
446 
447  /*
448  * We never want to remove the buffer that's currently being used, so
449  * if we happen to find that then move it to the end of the list.
450  */
451  if (buffer->resultRelInfo == curr_rri)
452  {
454  miinfo->multiInsertBuffers = lappend(miinfo->multiInsertBuffers, buffer);
455  buffer = (CopyMultiInsertBuffer *) linitial(miinfo->multiInsertBuffers);
456  }
457 
458  CopyMultiInsertBufferCleanup(miinfo, buffer);
460  }
461 }
462 
463 /*
464  * Cleanup allocated buffers and free memory
465  */
466 static inline void
468 {
469  ListCell *lc;
470 
471  foreach(lc, miinfo->multiInsertBuffers)
473 
474  list_free(miinfo->multiInsertBuffers);
475 }
476 
477 /*
478  * Get the next TupleTableSlot that the next tuple should be stored in.
479  *
480  * Callers must ensure that the buffer is not full.
481  *
482  * Note: 'miinfo' is unused but has been included for consistency with the
483  * other functions in this area.
484  */
485 static inline TupleTableSlot *
487  ResultRelInfo *rri)
488 {
490  int nused = buffer->nused;
491 
492  Assert(buffer != NULL);
493  Assert(nused < MAX_BUFFERED_TUPLES);
494 
495  if (buffer->slots[nused] == NULL)
496  buffer->slots[nused] = table_slot_create(rri->ri_RelationDesc, NULL);
497  return buffer->slots[nused];
498 }
499 
500 /*
501  * Record the previously reserved TupleTableSlot that was reserved by
502  * CopyMultiInsertInfoNextFreeSlot as being consumed.
503  */
504 static inline void
506  TupleTableSlot *slot, int tuplen, uint64 lineno)
507 {
509 
510  Assert(buffer != NULL);
511  Assert(slot == buffer->slots[buffer->nused]);
512 
513  /* Store the line number so we can properly report any errors later */
514  buffer->linenos[buffer->nused] = lineno;
515 
516  /* Record this slot as being used */
517  buffer->nused++;
518 
519  /* Update how many tuples are stored and their size */
520  miinfo->bufferedTuples++;
521  miinfo->bufferedBytes += tuplen;
522 }
523 
524 /*
525  * Copy FROM file to relation.
526  */
527 uint64
529 {
530  ResultRelInfo *resultRelInfo;
531  ResultRelInfo *target_resultRelInfo;
532  ResultRelInfo *prevResultRelInfo = NULL;
533  EState *estate = CreateExecutorState(); /* for ExecConstraints() */
534  ModifyTableState *mtstate;
535  ExprContext *econtext;
536  TupleTableSlot *singleslot = NULL;
537  MemoryContext oldcontext = CurrentMemoryContext;
538 
539  PartitionTupleRouting *proute = NULL;
540  ErrorContextCallback errcallback;
541  CommandId mycid = GetCurrentCommandId(true);
542  int ti_options = 0; /* start with default options for insert */
543  BulkInsertState bistate = NULL;
544  CopyInsertMethod insertMethod;
545  CopyMultiInsertInfo multiInsertInfo = {0}; /* pacify compiler */
546  int64 processed = 0;
547  int64 excluded = 0;
548  bool has_before_insert_row_trig;
549  bool has_instead_insert_row_trig;
550  bool leafpart_use_multi_insert = false;
551 
552  Assert(cstate->rel);
553  Assert(list_length(cstate->range_table) == 1);
554 
555  /*
556  * The target must be a plain, foreign, or partitioned relation, or have
557  * an INSTEAD OF INSERT row trigger. (Currently, such triggers are only
558  * allowed on views, so we only hint about them in the view case.)
559  */
560  if (cstate->rel->rd_rel->relkind != RELKIND_RELATION &&
561  cstate->rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
562  cstate->rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE &&
563  !(cstate->rel->trigdesc &&
565  {
566  if (cstate->rel->rd_rel->relkind == RELKIND_VIEW)
567  ereport(ERROR,
568  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
569  errmsg("cannot copy to view \"%s\"",
570  RelationGetRelationName(cstate->rel)),
571  errhint("To enable copying to a view, provide an INSTEAD OF INSERT trigger.")));
572  else if (cstate->rel->rd_rel->relkind == RELKIND_MATVIEW)
573  ereport(ERROR,
574  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
575  errmsg("cannot copy to materialized view \"%s\"",
576  RelationGetRelationName(cstate->rel))));
577  else if (cstate->rel->rd_rel->relkind == RELKIND_SEQUENCE)
578  ereport(ERROR,
579  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
580  errmsg("cannot copy to sequence \"%s\"",
581  RelationGetRelationName(cstate->rel))));
582  else
583  ereport(ERROR,
584  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
585  errmsg("cannot copy to non-table relation \"%s\"",
586  RelationGetRelationName(cstate->rel))));
587  }
588 
589  /*
590  * If the target file is new-in-transaction, we assume that checking FSM
591  * for free space is a waste of time. This could possibly be wrong, but
592  * it's unlikely.
593  */
594  if (RELKIND_HAS_STORAGE(cstate->rel->rd_rel->relkind) &&
597  ti_options |= TABLE_INSERT_SKIP_FSM;
598 
599  /*
600  * Optimize if new relfilenode was created in this subxact or one of its
601  * committed children and we won't see those rows later as part of an
602  * earlier scan or command. The subxact test ensures that if this subxact
603  * aborts then the frozen rows won't be visible after xact cleanup. Note
604  * that the stronger test of exactly which subtransaction created it is
605  * crucial for correctness of this optimization. The test for an earlier
606  * scan or command tolerates false negatives. FREEZE causes other sessions
607  * to see rows they would not see under MVCC, and a false negative merely
608  * spreads that anomaly to the current session.
609  */
610  if (cstate->opts.freeze)
611  {
612  /*
613  * We currently disallow COPY FREEZE on partitioned tables. The
614  * reason for this is that we've simply not yet opened the partitions
615  * to determine if the optimization can be applied to them. We could
616  * go and open them all here, but doing so may be quite a costly
617  * overhead for small copies. In any case, we may just end up routing
618  * tuples to a small number of partitions. It seems better just to
619  * raise an ERROR for partitioned tables.
620  */
621  if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
622  {
623  ereport(ERROR,
624  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
625  errmsg("cannot perform COPY FREEZE on a partitioned table")));
626  }
627 
628  /*
629  * Tolerate one registration for the benefit of FirstXactSnapshot.
630  * Scan-bearing queries generally create at least two registrations,
631  * though relying on that is fragile, as is ignoring ActiveSnapshot.
632  * Clear CatalogSnapshot to avoid counting its registration. We'll
633  * still detect ongoing catalog scans, each of which separately
634  * registers the snapshot it uses.
635  */
638  ereport(ERROR,
639  (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
640  errmsg("cannot perform COPY FREEZE because of prior transaction activity")));
641 
642  if (cstate->rel->rd_createSubid != GetCurrentSubTransactionId() &&
644  ereport(ERROR,
645  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
646  errmsg("cannot perform COPY FREEZE because the table was not created or truncated in the current subtransaction")));
647 
648  ti_options |= TABLE_INSERT_FROZEN;
649  }
650 
651  /*
652  * We need a ResultRelInfo so we can use the regular executor's
653  * index-entry-making machinery. (There used to be a huge amount of code
654  * here that basically duplicated execUtils.c ...)
655  */
656  ExecInitRangeTable(estate, cstate->range_table);
657  resultRelInfo = target_resultRelInfo = makeNode(ResultRelInfo);
658  ExecInitResultRelation(estate, resultRelInfo, 1);
659 
660  /* Verify the named relation is a valid target for INSERT */
661  CheckValidResultRel(resultRelInfo, CMD_INSERT);
662 
663  ExecOpenIndices(resultRelInfo, false);
664 
665  /*
666  * Set up a ModifyTableState so we can let FDW(s) init themselves for
667  * foreign-table result relation(s).
668  */
669  mtstate = makeNode(ModifyTableState);
670  mtstate->ps.plan = NULL;
671  mtstate->ps.state = estate;
672  mtstate->operation = CMD_INSERT;
673  mtstate->mt_nrels = 1;
674  mtstate->resultRelInfo = resultRelInfo;
675  mtstate->rootResultRelInfo = resultRelInfo;
676 
677  if (resultRelInfo->ri_FdwRoutine != NULL &&
678  resultRelInfo->ri_FdwRoutine->BeginForeignInsert != NULL)
679  resultRelInfo->ri_FdwRoutine->BeginForeignInsert(mtstate,
680  resultRelInfo);
681 
682  /* Prepare to catch AFTER triggers. */
684 
685  /*
686  * If there are any triggers with transition tables on the named relation,
687  * we need to be prepared to capture transition tuples.
688  *
689  * Because partition tuple routing would like to know about whether
690  * transition capture is active, we also set it in mtstate, which is
691  * passed to ExecFindPartition() below.
692  */
693  cstate->transition_capture = mtstate->mt_transition_capture =
695  RelationGetRelid(cstate->rel),
696  CMD_INSERT);
697 
698  /*
699  * If the named relation is a partitioned table, initialize state for
700  * CopyFrom tuple routing.
701  */
702  if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
703  proute = ExecSetupPartitionTupleRouting(estate, cstate->rel);
704 
705  if (cstate->whereClause)
706  cstate->qualexpr = ExecInitQual(castNode(List, cstate->whereClause),
707  &mtstate->ps);
708 
709  /*
710  * It's generally more efficient to prepare a bunch of tuples for
711  * insertion, and insert them in one table_multi_insert() call, than call
712  * table_tuple_insert() separately for every tuple. However, there are a
713  * number of reasons why we might not be able to do this. These are
714  * explained below.
715  */
716  if (resultRelInfo->ri_TrigDesc != NULL &&
717  (resultRelInfo->ri_TrigDesc->trig_insert_before_row ||
718  resultRelInfo->ri_TrigDesc->trig_insert_instead_row))
719  {
720  /*
721  * Can't support multi-inserts when there are any BEFORE/INSTEAD OF
722  * triggers on the table. Such triggers might query the table we're
723  * inserting into and act differently if the tuples that have already
724  * been processed and prepared for insertion are not there.
725  */
726  insertMethod = CIM_SINGLE;
727  }
728  else if (proute != NULL && resultRelInfo->ri_TrigDesc != NULL &&
729  resultRelInfo->ri_TrigDesc->trig_insert_new_table)
730  {
731  /*
732  * For partitioned tables we can't support multi-inserts when there
733  * are any statement level insert triggers. It might be possible to
734  * allow partitioned tables with such triggers in the future, but for
735  * now, CopyMultiInsertInfoFlush expects that any before row insert
736  * and statement level insert triggers are on the same relation.
737  */
738  insertMethod = CIM_SINGLE;
739  }
740  else if (resultRelInfo->ri_FdwRoutine != NULL ||
741  cstate->volatile_defexprs)
742  {
743  /*
744  * Can't support multi-inserts to foreign tables or if there are any
745  * volatile default expressions in the table. Similarly to the
746  * trigger case above, such expressions may query the table we're
747  * inserting into.
748  *
749  * Note: It does not matter if any partitions have any volatile
750  * default expressions as we use the defaults from the target of the
751  * COPY command.
752  */
753  insertMethod = CIM_SINGLE;
754  }
755  else if (contain_volatile_functions(cstate->whereClause))
756  {
757  /*
758  * Can't support multi-inserts if there are any volatile function
759  * expressions in WHERE clause. Similarly to the trigger case above,
760  * such expressions may query the table we're inserting into.
761  */
762  insertMethod = CIM_SINGLE;
763  }
764  else
765  {
766  /*
767  * For partitioned tables, we may still be able to perform bulk
768  * inserts. However, the possibility of this depends on which types
769  * of triggers exist on the partition. We must disable bulk inserts
770  * if the partition is a foreign table or it has any before row insert
771  * or insert instead triggers (same as we checked above for the parent
772  * table). Since the partition's resultRelInfos are initialized only
773  * when we actually need to insert the first tuple into them, we must
774  * have the intermediate insert method of CIM_MULTI_CONDITIONAL to
775  * flag that we must later determine if we can use bulk-inserts for
776  * the partition being inserted into.
777  */
778  if (proute)
779  insertMethod = CIM_MULTI_CONDITIONAL;
780  else
781  insertMethod = CIM_MULTI;
782 
783  CopyMultiInsertInfoInit(&multiInsertInfo, resultRelInfo, cstate,
784  estate, mycid, ti_options);
785  }
786 
787  /*
788  * If not using batch mode (which allocates slots as needed) set up a
789  * tuple slot too. When inserting into a partitioned table, we also need
790  * one, even if we might batch insert, to read the tuple in the root
791  * partition's form.
792  */
793  if (insertMethod == CIM_SINGLE || insertMethod == CIM_MULTI_CONDITIONAL)
794  {
795  singleslot = table_slot_create(resultRelInfo->ri_RelationDesc,
796  &estate->es_tupleTable);
797  bistate = GetBulkInsertState();
798  }
799 
800  has_before_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
801  resultRelInfo->ri_TrigDesc->trig_insert_before_row);
802 
803  has_instead_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
804  resultRelInfo->ri_TrigDesc->trig_insert_instead_row);
805 
806  /*
807  * Check BEFORE STATEMENT insertion triggers. It's debatable whether we
808  * should do this for COPY, since it's not really an "INSERT" statement as
809  * such. However, executing these triggers maintains consistency with the
810  * EACH ROW triggers that we already fire on COPY.
811  */
812  ExecBSInsertTriggers(estate, resultRelInfo);
813 
814  econtext = GetPerTupleExprContext(estate);
815 
816  /* Set up callback to identify error line number */
817  errcallback.callback = CopyFromErrorCallback;
818  errcallback.arg = (void *) cstate;
819  errcallback.previous = error_context_stack;
820  error_context_stack = &errcallback;
821 
822  for (;;)
823  {
824  TupleTableSlot *myslot;
825  bool skip_tuple;
826 
828 
829  /*
830  * Reset the per-tuple exprcontext. We do this after every tuple, to
831  * clean-up after expression evaluations etc.
832  */
833  ResetPerTupleExprContext(estate);
834 
835  /* select slot to (initially) load row into */
836  if (insertMethod == CIM_SINGLE || proute)
837  {
838  myslot = singleslot;
839  Assert(myslot != NULL);
840  }
841  else
842  {
843  Assert(resultRelInfo == target_resultRelInfo);
844  Assert(insertMethod == CIM_MULTI);
845 
846  myslot = CopyMultiInsertInfoNextFreeSlot(&multiInsertInfo,
847  resultRelInfo);
848  }
849 
850  /*
851  * Switch to per-tuple context before calling NextCopyFrom, which does
852  * evaluate default expressions etc. and requires per-tuple context.
853  */
855 
856  ExecClearTuple(myslot);
857 
858  /* Directly store the values/nulls array in the slot */
859  if (!NextCopyFrom(cstate, econtext, myslot->tts_values, myslot->tts_isnull))
860  break;
861 
862  ExecStoreVirtualTuple(myslot);
863 
864  /*
865  * Constraints and where clause might reference the tableoid column,
866  * so (re-)initialize tts_tableOid before evaluating them.
867  */
868  myslot->tts_tableOid = RelationGetRelid(target_resultRelInfo->ri_RelationDesc);
869 
870  /* Triggers and stuff need to be invoked in query context. */
871  MemoryContextSwitchTo(oldcontext);
872 
873  if (cstate->whereClause)
874  {
875  econtext->ecxt_scantuple = myslot;
876  /* Skip items that don't match COPY's WHERE clause */
877  if (!ExecQual(cstate->qualexpr, econtext))
878  {
879  /*
880  * Report that this tuple was filtered out by the WHERE
881  * clause.
882  */
884  ++excluded);
885  continue;
886  }
887  }
888 
889  /* Determine the partition to insert the tuple into */
890  if (proute)
891  {
892  TupleConversionMap *map;
893 
894  /*
895  * Attempt to find a partition suitable for this tuple.
896  * ExecFindPartition() will raise an error if none can be found or
897  * if the found partition is not suitable for INSERTs.
898  */
899  resultRelInfo = ExecFindPartition(mtstate, target_resultRelInfo,
900  proute, myslot, estate);
901 
902  if (prevResultRelInfo != resultRelInfo)
903  {
904  /* Determine which triggers exist on this partition */
905  has_before_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
906  resultRelInfo->ri_TrigDesc->trig_insert_before_row);
907 
908  has_instead_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
909  resultRelInfo->ri_TrigDesc->trig_insert_instead_row);
910 
911  /*
912  * Disable multi-inserts when the partition has BEFORE/INSTEAD
913  * OF triggers, or if the partition is a foreign partition.
914  */
915  leafpart_use_multi_insert = insertMethod == CIM_MULTI_CONDITIONAL &&
916  !has_before_insert_row_trig &&
917  !has_instead_insert_row_trig &&
918  resultRelInfo->ri_FdwRoutine == NULL;
919 
920  /* Set the multi-insert buffer to use for this partition. */
921  if (leafpart_use_multi_insert)
922  {
923  if (resultRelInfo->ri_CopyMultiInsertBuffer == NULL)
924  CopyMultiInsertInfoSetupBuffer(&multiInsertInfo,
925  resultRelInfo);
926  }
927  else if (insertMethod == CIM_MULTI_CONDITIONAL &&
928  !CopyMultiInsertInfoIsEmpty(&multiInsertInfo))
929  {
930  /*
931  * Flush pending inserts if this partition can't use
932  * batching, so rows are visible to triggers etc.
933  */
934  CopyMultiInsertInfoFlush(&multiInsertInfo, resultRelInfo);
935  }
936 
937  if (bistate != NULL)
938  ReleaseBulkInsertStatePin(bistate);
939  prevResultRelInfo = resultRelInfo;
940  }
941 
942  /*
943  * If we're capturing transition tuples, we might need to convert
944  * from the partition rowtype to root rowtype. But if there are no
945  * BEFORE triggers on the partition that could change the tuple,
946  * we can just remember the original unconverted tuple to avoid a
947  * needless round trip conversion.
948  */
949  if (cstate->transition_capture != NULL)
951  !has_before_insert_row_trig ? myslot : NULL;
952 
953  /*
954  * We might need to convert from the root rowtype to the partition
955  * rowtype.
956  */
957  map = resultRelInfo->ri_RootToPartitionMap;
958  if (insertMethod == CIM_SINGLE || !leafpart_use_multi_insert)
959  {
960  /* non batch insert */
961  if (map != NULL)
962  {
963  TupleTableSlot *new_slot;
964 
965  new_slot = resultRelInfo->ri_PartitionTupleSlot;
966  myslot = execute_attr_map_slot(map->attrMap, myslot, new_slot);
967  }
968  }
969  else
970  {
971  /*
972  * Prepare to queue up tuple for later batch insert into
973  * current partition.
974  */
975  TupleTableSlot *batchslot;
976 
977  /* no other path available for partitioned table */
978  Assert(insertMethod == CIM_MULTI_CONDITIONAL);
979 
980  batchslot = CopyMultiInsertInfoNextFreeSlot(&multiInsertInfo,
981  resultRelInfo);
982 
983  if (map != NULL)
984  myslot = execute_attr_map_slot(map->attrMap, myslot,
985  batchslot);
986  else
987  {
988  /*
989  * This looks more expensive than it is (Believe me, I
990  * optimized it away. Twice.). The input is in virtual
991  * form, and we'll materialize the slot below - for most
992  * slot types the copy performs the work materialization
993  * would later require anyway.
994  */
995  ExecCopySlot(batchslot, myslot);
996  myslot = batchslot;
997  }
998  }
999 
1000  /* ensure that triggers etc see the right relation */
1001  myslot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
1002  }
1003 
1004  skip_tuple = false;
1005 
1006  /* BEFORE ROW INSERT Triggers */
1007  if (has_before_insert_row_trig)
1008  {
1009  if (!ExecBRInsertTriggers(estate, resultRelInfo, myslot))
1010  skip_tuple = true; /* "do nothing" */
1011  }
1012 
1013  if (!skip_tuple)
1014  {
1015  /*
1016  * If there is an INSTEAD OF INSERT ROW trigger, let it handle the
1017  * tuple. Otherwise, proceed with inserting the tuple into the
1018  * table or foreign table.
1019  */
1020  if (has_instead_insert_row_trig)
1021  {
1022  ExecIRInsertTriggers(estate, resultRelInfo, myslot);
1023  }
1024  else
1025  {
1026  /* Compute stored generated columns */
1027  if (resultRelInfo->ri_RelationDesc->rd_att->constr &&
1029  ExecComputeStoredGenerated(resultRelInfo, estate, myslot,
1030  CMD_INSERT);
1031 
1032  /*
1033  * If the target is a plain table, check the constraints of
1034  * the tuple.
1035  */
1036  if (resultRelInfo->ri_FdwRoutine == NULL &&
1037  resultRelInfo->ri_RelationDesc->rd_att->constr)
1038  ExecConstraints(resultRelInfo, myslot, estate);
1039 
1040  /*
1041  * Also check the tuple against the partition constraint, if
1042  * there is one; except that if we got here via tuple-routing,
1043  * we don't need to if there's no BR trigger defined on the
1044  * partition.
1045  */
1046  if (resultRelInfo->ri_RelationDesc->rd_rel->relispartition &&
1047  (proute == NULL || has_before_insert_row_trig))
1048  ExecPartitionCheck(resultRelInfo, myslot, estate, true);
1049 
1050  /* Store the slot in the multi-insert buffer, when enabled. */
1051  if (insertMethod == CIM_MULTI || leafpart_use_multi_insert)
1052  {
1053  /*
1054  * The slot previously might point into the per-tuple
1055  * context. For batching it needs to be longer lived.
1056  */
1057  ExecMaterializeSlot(myslot);
1058 
1059  /* Add this tuple to the tuple buffer */
1060  CopyMultiInsertInfoStore(&multiInsertInfo,
1061  resultRelInfo, myslot,
1062  cstate->line_buf.len,
1063  cstate->cur_lineno);
1064 
1065  /*
1066  * If enough inserts have queued up, then flush all
1067  * buffers out to their tables.
1068  */
1069  if (CopyMultiInsertInfoIsFull(&multiInsertInfo))
1070  CopyMultiInsertInfoFlush(&multiInsertInfo, resultRelInfo);
1071  }
1072  else
1073  {
1074  List *recheckIndexes = NIL;
1075 
1076  /* OK, store the tuple */
1077  if (resultRelInfo->ri_FdwRoutine != NULL)
1078  {
1079  myslot = resultRelInfo->ri_FdwRoutine->ExecForeignInsert(estate,
1080  resultRelInfo,
1081  myslot,
1082  NULL);
1083 
1084  if (myslot == NULL) /* "do nothing" */
1085  continue; /* next tuple please */
1086 
1087  /*
1088  * AFTER ROW Triggers might reference the tableoid
1089  * column, so (re-)initialize tts_tableOid before
1090  * evaluating them.
1091  */
1092  myslot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
1093  }
1094  else
1095  {
1096  /* OK, store the tuple and create index entries for it */
1097  table_tuple_insert(resultRelInfo->ri_RelationDesc,
1098  myslot, mycid, ti_options, bistate);
1099 
1100  if (resultRelInfo->ri_NumIndices > 0)
1101  recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
1102  myslot,
1103  estate,
1104  false,
1105  false,
1106  NULL,
1107  NIL);
1108  }
1109 
1110  /* AFTER ROW INSERT Triggers */
1111  ExecARInsertTriggers(estate, resultRelInfo, myslot,
1112  recheckIndexes, cstate->transition_capture);
1113 
1114  list_free(recheckIndexes);
1115  }
1116  }
1117 
1118  /*
1119  * We count only tuples not suppressed by a BEFORE INSERT trigger
1120  * or FDW; this is the same definition used by nodeModifyTable.c
1121  * for counting tuples inserted by an INSERT command. Update
1122  * progress of the COPY command as well.
1123  */
1125  ++processed);
1126  }
1127  }
1128 
1129  /* Flush any remaining buffered tuples */
1130  if (insertMethod != CIM_SINGLE)
1131  {
1132  if (!CopyMultiInsertInfoIsEmpty(&multiInsertInfo))
1133  CopyMultiInsertInfoFlush(&multiInsertInfo, NULL);
1134  }
1135 
1136  /* Done, clean up */
1137  error_context_stack = errcallback.previous;
1138 
1139  if (bistate != NULL)
1140  FreeBulkInsertState(bistate);
1141 
1142  MemoryContextSwitchTo(oldcontext);
1143 
1144  /* Execute AFTER STATEMENT insertion triggers */
1145  ExecASInsertTriggers(estate, target_resultRelInfo, cstate->transition_capture);
1146 
1147  /* Handle queued AFTER triggers */
1148  AfterTriggerEndQuery(estate);
1149 
1150  ExecResetTupleTable(estate->es_tupleTable, false);
1151 
1152  /* Allow the FDW to shut down */
1153  if (target_resultRelInfo->ri_FdwRoutine != NULL &&
1154  target_resultRelInfo->ri_FdwRoutine->EndForeignInsert != NULL)
1155  target_resultRelInfo->ri_FdwRoutine->EndForeignInsert(estate,
1156  target_resultRelInfo);
1157 
1158  /* Tear down the multi-insert buffer data */
1159  if (insertMethod != CIM_SINGLE)
1160  CopyMultiInsertInfoCleanup(&multiInsertInfo);
1161 
1162  /* Close all the partitioned tables, leaf partitions, and their indices */
1163  if (proute)
1164  ExecCleanupTupleRouting(mtstate, proute);
1165 
1166  /* Close the result relations, including any trigger target relations */
1167  ExecCloseResultRelations(estate);
1169 
1170  FreeExecutorState(estate);
1171 
1172  return processed;
1173 }
1174 
1175 /*
1176  * Setup to read tuples from a file for COPY FROM.
1177  *
1178  * 'rel': Used as a template for the tuples
1179  * 'whereClause': WHERE clause from the COPY FROM command
1180  * 'filename': Name of server-local file to read, NULL for STDIN
1181  * 'is_program': true if 'filename' is program to execute
1182  * 'data_source_cb': callback that provides the input data
1183  * 'attnamelist': List of char *, columns to include. NIL selects all cols.
1184  * 'options': List of DefElem. See copy_opt_item in gram.y for selections.
1185  *
1186  * Returns a CopyFromState, to be passed to NextCopyFrom and related functions.
1187  */
1190  Relation rel,
1191  Node *whereClause,
1192  const char *filename,
1193  bool is_program,
1194  copy_data_source_cb data_source_cb,
1195  List *attnamelist,
1196  List *options)
1197 {
1198  CopyFromState cstate;
1199  bool pipe = (filename == NULL);
1200  TupleDesc tupDesc;
1201  AttrNumber num_phys_attrs,
1202  num_defaults;
1203  FmgrInfo *in_functions;
1204  Oid *typioparams;
1205  int attnum;
1206  Oid in_func_oid;
1207  int *defmap;
1208  ExprState **defexprs;
1209  MemoryContext oldcontext;
1210  bool volatile_defexprs;
1211  const int progress_cols[] = {
1215  };
1216  int64 progress_vals[] = {
1218  0,
1219  0
1220  };
1221 
1222  /* Allocate workspace and zero all fields */
1223  cstate = (CopyFromStateData *) palloc0(sizeof(CopyFromStateData));
1224 
1225  /*
1226  * We allocate everything used by a cstate in a new memory context. This
1227  * avoids memory leaks during repeated use of COPY in a query.
1228  */
1230  "COPY",
1232 
1233  oldcontext = MemoryContextSwitchTo(cstate->copycontext);
1234 
1235  /* Extract options from the statement node tree */
1236  ProcessCopyOptions(pstate, &cstate->opts, true /* is_from */ , options);
1237 
1238  /* Process the target relation */
1239  cstate->rel = rel;
1240 
1241  tupDesc = RelationGetDescr(cstate->rel);
1242 
1243  /* process common options or initialization */
1244 
1245  /* Generate or convert list of attributes to process */
1246  cstate->attnumlist = CopyGetAttnums(tupDesc, cstate->rel, attnamelist);
1247 
1248  num_phys_attrs = tupDesc->natts;
1249 
1250  /* Convert FORCE_NOT_NULL name list to per-column flags, check validity */
1251  cstate->opts.force_notnull_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1252  if (cstate->opts.force_notnull)
1253  {
1254  List *attnums;
1255  ListCell *cur;
1256 
1257  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_notnull);
1258 
1259  foreach(cur, attnums)
1260  {
1261  int attnum = lfirst_int(cur);
1262  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1263 
1264  if (!list_member_int(cstate->attnumlist, attnum))
1265  ereport(ERROR,
1266  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1267  errmsg("FORCE_NOT_NULL column \"%s\" not referenced by COPY",
1268  NameStr(attr->attname))));
1269  cstate->opts.force_notnull_flags[attnum - 1] = true;
1270  }
1271  }
1272 
1273  /* Convert FORCE_NULL name list to per-column flags, check validity */
1274  cstate->opts.force_null_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1275  if (cstate->opts.force_null)
1276  {
1277  List *attnums;
1278  ListCell *cur;
1279 
1280  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_null);
1281 
1282  foreach(cur, attnums)
1283  {
1284  int attnum = lfirst_int(cur);
1285  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1286 
1287  if (!list_member_int(cstate->attnumlist, attnum))
1288  ereport(ERROR,
1289  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1290  errmsg("FORCE_NULL column \"%s\" not referenced by COPY",
1291  NameStr(attr->attname))));
1292  cstate->opts.force_null_flags[attnum - 1] = true;
1293  }
1294  }
1295 
1296  /* Convert convert_selectively name list to per-column flags */
1297  if (cstate->opts.convert_selectively)
1298  {
1299  List *attnums;
1300  ListCell *cur;
1301 
1302  cstate->convert_select_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
1303 
1304  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.convert_select);
1305 
1306  foreach(cur, attnums)
1307  {
1308  int attnum = lfirst_int(cur);
1309  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1310 
1311  if (!list_member_int(cstate->attnumlist, attnum))
1312  ereport(ERROR,
1313  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1314  errmsg_internal("selected column \"%s\" not referenced by COPY",
1315  NameStr(attr->attname))));
1316  cstate->convert_select_flags[attnum - 1] = true;
1317  }
1318  }
1319 
1320  /* Use client encoding when ENCODING option is not specified. */
1321  if (cstate->opts.file_encoding < 0)
1323  else
1324  cstate->file_encoding = cstate->opts.file_encoding;
1325 
1326  /*
1327  * Look up encoding conversion function.
1328  */
1329  if (cstate->file_encoding == GetDatabaseEncoding() ||
1330  cstate->file_encoding == PG_SQL_ASCII ||
1332  {
1333  cstate->need_transcoding = false;
1334  }
1335  else
1336  {
1337  cstate->need_transcoding = true;
1340  }
1341 
1342  cstate->copy_src = COPY_FILE; /* default */
1343 
1344  cstate->whereClause = whereClause;
1345 
1346  /* Initialize state variables */
1347  cstate->eol_type = EOL_UNKNOWN;
1348  cstate->cur_relname = RelationGetRelationName(cstate->rel);
1349  cstate->cur_lineno = 0;
1350  cstate->cur_attname = NULL;
1351  cstate->cur_attval = NULL;
1352 
1353  /*
1354  * Allocate buffers for the input pipeline.
1355  *
1356  * attribute_buf and raw_buf are used in both text and binary modes, but
1357  * input_buf and line_buf only in text mode.
1358  */
1359  cstate->raw_buf = palloc(RAW_BUF_SIZE + 1);
1360  cstate->raw_buf_index = cstate->raw_buf_len = 0;
1361  cstate->raw_reached_eof = false;
1362 
1363  if (!cstate->opts.binary)
1364  {
1365  /*
1366  * If encoding conversion is needed, we need another buffer to hold
1367  * the converted input data. Otherwise, we can just point input_buf
1368  * to the same buffer as raw_buf.
1369  */
1370  if (cstate->need_transcoding)
1371  {
1372  cstate->input_buf = (char *) palloc(INPUT_BUF_SIZE + 1);
1373  cstate->input_buf_index = cstate->input_buf_len = 0;
1374  }
1375  else
1376  cstate->input_buf = cstate->raw_buf;
1377  cstate->input_reached_eof = false;
1378 
1379  initStringInfo(&cstate->line_buf);
1380  }
1381 
1382  initStringInfo(&cstate->attribute_buf);
1383 
1384  /* Assign range table, we'll need it in CopyFrom. */
1385  if (pstate)
1386  cstate->range_table = pstate->p_rtable;
1387 
1388  tupDesc = RelationGetDescr(cstate->rel);
1389  num_phys_attrs = tupDesc->natts;
1390  num_defaults = 0;
1391  volatile_defexprs = false;
1392 
1393  /*
1394  * Pick up the required catalog information for each attribute in the
1395  * relation, including the input function, the element type (to pass to
1396  * the input function), and info about defaults and constraints. (Which
1397  * input function we use depends on text/binary format choice.)
1398  */
1399  in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
1400  typioparams = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
1401  defmap = (int *) palloc(num_phys_attrs * sizeof(int));
1402  defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *));
1403 
1404  for (attnum = 1; attnum <= num_phys_attrs; attnum++)
1405  {
1406  Form_pg_attribute att = TupleDescAttr(tupDesc, attnum - 1);
1407 
1408  /* We don't need info for dropped attributes */
1409  if (att->attisdropped)
1410  continue;
1411 
1412  /* Fetch the input function and typioparam info */
1413  if (cstate->opts.binary)
1414  getTypeBinaryInputInfo(att->atttypid,
1415  &in_func_oid, &typioparams[attnum - 1]);
1416  else
1417  getTypeInputInfo(att->atttypid,
1418  &in_func_oid, &typioparams[attnum - 1]);
1419  fmgr_info(in_func_oid, &in_functions[attnum - 1]);
1420 
1421  /* Get default info if needed */
1422  if (!list_member_int(cstate->attnumlist, attnum) && !att->attgenerated)
1423  {
1424  /* attribute is NOT to be copied from input */
1425  /* use default value if one exists */
1426  Expr *defexpr = (Expr *) build_column_default(cstate->rel,
1427  attnum);
1428 
1429  if (defexpr != NULL)
1430  {
1431  /* Run the expression through planner */
1432  defexpr = expression_planner(defexpr);
1433 
1434  /* Initialize executable expression in copycontext */
1435  defexprs[num_defaults] = ExecInitExpr(defexpr, NULL);
1436  defmap[num_defaults] = attnum - 1;
1437  num_defaults++;
1438 
1439  /*
1440  * If a default expression looks at the table being loaded,
1441  * then it could give the wrong answer when using
1442  * multi-insert. Since database access can be dynamic this is
1443  * hard to test for exactly, so we use the much wider test of
1444  * whether the default expression is volatile. We allow for
1445  * the special case of when the default expression is the
1446  * nextval() of a sequence which in this specific case is
1447  * known to be safe for use with the multi-insert
1448  * optimization. Hence we use this special case function
1449  * checker rather than the standard check for
1450  * contain_volatile_functions().
1451  */
1452  if (!volatile_defexprs)
1453  volatile_defexprs = contain_volatile_functions_not_nextval((Node *) defexpr);
1454  }
1455  }
1456  }
1457 
1458 
1459  /* initialize progress */
1461  cstate->rel ? RelationGetRelid(cstate->rel) : InvalidOid);
1462  cstate->bytes_processed = 0;
1463 
1464  /* We keep those variables in cstate. */
1465  cstate->in_functions = in_functions;
1466  cstate->typioparams = typioparams;
1467  cstate->defmap = defmap;
1468  cstate->defexprs = defexprs;
1469  cstate->volatile_defexprs = volatile_defexprs;
1470  cstate->num_defaults = num_defaults;
1471  cstate->is_program = is_program;
1472 
1473  if (data_source_cb)
1474  {
1475  progress_vals[1] = PROGRESS_COPY_TYPE_CALLBACK;
1476  cstate->copy_src = COPY_CALLBACK;
1477  cstate->data_source_cb = data_source_cb;
1478  }
1479  else if (pipe)
1480  {
1481  progress_vals[1] = PROGRESS_COPY_TYPE_PIPE;
1482  Assert(!is_program); /* the grammar does not allow this */
1484  ReceiveCopyBegin(cstate);
1485  else
1486  cstate->copy_file = stdin;
1487  }
1488  else
1489  {
1490  cstate->filename = pstrdup(filename);
1491 
1492  if (cstate->is_program)
1493  {
1494  progress_vals[1] = PROGRESS_COPY_TYPE_PROGRAM;
1495  cstate->copy_file = OpenPipeStream(cstate->filename, PG_BINARY_R);
1496  if (cstate->copy_file == NULL)
1497  ereport(ERROR,
1499  errmsg("could not execute command \"%s\": %m",
1500  cstate->filename)));
1501  }
1502  else
1503  {
1504  struct stat st;
1505 
1506  progress_vals[1] = PROGRESS_COPY_TYPE_FILE;
1507  cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_R);
1508  if (cstate->copy_file == NULL)
1509  {
1510  /* copy errno because ereport subfunctions might change it */
1511  int save_errno = errno;
1512 
1513  ereport(ERROR,
1515  errmsg("could not open file \"%s\" for reading: %m",
1516  cstate->filename),
1517  (save_errno == ENOENT || save_errno == EACCES) ?
1518  errhint("COPY FROM instructs the PostgreSQL server process to read a file. "
1519  "You may want a client-side facility such as psql's \\copy.") : 0));
1520  }
1521 
1522  if (fstat(fileno(cstate->copy_file), &st))
1523  ereport(ERROR,
1525  errmsg("could not stat file \"%s\": %m",
1526  cstate->filename)));
1527 
1528  if (S_ISDIR(st.st_mode))
1529  ereport(ERROR,
1530  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1531  errmsg("\"%s\" is a directory", cstate->filename)));
1532 
1533  progress_vals[2] = st.st_size;
1534  }
1535  }
1536 
1537  pgstat_progress_update_multi_param(3, progress_cols, progress_vals);
1538 
1539  if (cstate->opts.binary)
1540  {
1541  /* Read and verify binary header */
1542  ReceiveCopyBinaryHeader(cstate);
1543  }
1544 
1545  /* create workspace for CopyReadAttributes results */
1546  if (!cstate->opts.binary)
1547  {
1548  AttrNumber attr_count = list_length(cstate->attnumlist);
1549 
1550  cstate->max_fields = attr_count;
1551  cstate->raw_fields = (char **) palloc(attr_count * sizeof(char *));
1552  }
1553 
1554  MemoryContextSwitchTo(oldcontext);
1555 
1556  return cstate;
1557 }
1558 
1559 /*
1560  * Clean up storage and release resources for COPY FROM.
1561  */
1562 void
1564 {
1565  /* No COPY FROM related resources except memory. */
1566  if (cstate->is_program)
1567  {
1568  ClosePipeFromProgram(cstate);
1569  }
1570  else
1571  {
1572  if (cstate->filename != NULL && FreeFile(cstate->copy_file))
1573  ereport(ERROR,
1575  errmsg("could not close file \"%s\": %m",
1576  cstate->filename)));
1577  }
1578 
1580 
1582  pfree(cstate);
1583 }
1584 
1585 /*
1586  * Closes the pipe from an external program, checking the pclose() return code.
1587  */
1588 static void
1590 {
1591  int pclose_rc;
1592 
1593  Assert(cstate->is_program);
1594 
1595  pclose_rc = ClosePipeStream(cstate->copy_file);
1596  if (pclose_rc == -1)
1597  ereport(ERROR,
1599  errmsg("could not close pipe to external command: %m")));
1600  else if (pclose_rc != 0)
1601  {
1602  /*
1603  * If we ended a COPY FROM PROGRAM before reaching EOF, then it's
1604  * expectable for the called program to fail with SIGPIPE, and we
1605  * should not report that as an error. Otherwise, SIGPIPE indicates a
1606  * problem.
1607  */
1608  if (!cstate->raw_reached_eof &&
1609  wait_result_is_signal(pclose_rc, SIGPIPE))
1610  return;
1611 
1612  ereport(ERROR,
1613  (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
1614  errmsg("program \"%s\" failed",
1615  cstate->filename),
1616  errdetail_internal("%s", wait_result_to_str(pclose_rc))));
1617  }
1618 }
int16 AttrNumber
Definition: attnum.h:21
List * CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
Definition: copy.c:708
void ProcessCopyOptions(ParseState *pstate, CopyFormatOptions *opts_out, bool is_from, List *options)
Definition: copy.c:391
void pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid)
void pgstat_progress_update_param(int index, int64 val)
void pgstat_progress_update_multi_param(int nparam, const int *index, const int64 *val)
void pgstat_progress_end_command(void)
@ PROGRESS_COMMAND_COPY
#define NameStr(name)
Definition: c.h:681
#define PG_BINARY_R
Definition: c.h:1270
#define InvalidSubTransactionId
Definition: c.h:593
uint32 CommandId
Definition: c.h:601
bool contain_volatile_functions_not_nextval(Node *clause)
Definition: clauses.c:603
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:496
static void CopyMultiInsertInfoSetupBuffer(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri)
Definition: copyfrom.c:235
static CopyMultiInsertBuffer * CopyMultiInsertBufferInit(ResultRelInfo *rri)
Definition: copyfrom.c:218
static void CopyMultiInsertInfoInit(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri, CopyFromState cstate, EState *estate, CommandId mycid, int ti_options)
Definition: copyfrom.c:255
static void CopyMultiInsertInfoStore(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri, TupleTableSlot *slot, int tuplen, uint64 lineno)
Definition: copyfrom.c:505
static void CopyMultiInsertInfoCleanup(CopyMultiInsertInfo *miinfo)
Definition: copyfrom.c:467
#define MAX_PARTITION_BUFFERS
Definition: copyfrom.c:74
struct CopyMultiInsertInfo CopyMultiInsertInfo
#define MAX_BUFFERED_TUPLES
Definition: copyfrom.c:65
static bool CopyMultiInsertInfoIsFull(CopyMultiInsertInfo *miinfo)
Definition: copyfrom.c:280
CopyFromState BeginCopyFrom(ParseState *pstate, Relation rel, Node *whereClause, const char *filename, bool is_program, copy_data_source_cb data_source_cb, List *attnamelist, List *options)
Definition: copyfrom.c:1189
static TupleTableSlot * CopyMultiInsertInfoNextFreeSlot(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri)
Definition: copyfrom.c:486
static void CopyMultiInsertBufferFlush(CopyMultiInsertInfo *miinfo, CopyMultiInsertBuffer *buffer)
Definition: copyfrom.c:301
static void ClosePipeFromProgram(CopyFromState cstate)
Definition: copyfrom.c:1589
#define MAX_BUFFERED_BYTES
Definition: copyfrom.c:71
static void CopyMultiInsertBufferCleanup(CopyMultiInsertInfo *miinfo, CopyMultiInsertBuffer *buffer)
Definition: copyfrom.c:387
uint64 CopyFrom(CopyFromState cstate)
Definition: copyfrom.c:528
void EndCopyFrom(CopyFromState cstate)
Definition: copyfrom.c:1563
static char * limit_printout_length(const char *str)
Definition: copyfrom.c:188
static void CopyMultiInsertInfoFlush(CopyMultiInsertInfo *miinfo, ResultRelInfo *curr_rri)
Definition: copyfrom.c:421
static bool CopyMultiInsertInfoIsEmpty(CopyMultiInsertInfo *miinfo)
Definition: copyfrom.c:292
struct CopyMultiInsertBuffer CopyMultiInsertBuffer
#define MAX_COPY_DATA_DISPLAY
void CopyFromErrorCallback(void *arg)
Definition: copyfrom.c:115
@ COPY_CALLBACK
CopyInsertMethod
@ CIM_SINGLE
@ CIM_MULTI_CONDITIONAL
@ CIM_MULTI
#define INPUT_BUF_SIZE
@ EOL_UNKNOWN
#define RAW_BUF_SIZE
void ReceiveCopyBinaryHeader(CopyFromState cstate)
void ReceiveCopyBegin(CopyFromState cstate)
bool NextCopyFrom(CopyFromState cstate, ExprContext *econtext, Datum *values, bool *nulls)
@ COPY_FILE
Definition: copyto.c:52
@ DestRemote
Definition: dest.h:91
struct cursor * cur
Definition: ecpg.c:28
int errmsg_internal(const char *fmt,...)
Definition: elog.c:991
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1064
int errcode_for_file_access(void)
Definition: elog.c:716
ErrorContextCallback * error_context_stack
Definition: elog.c:93
int errhint(const char *fmt,...)
Definition: elog.c:1151
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define errcontext
Definition: elog.h:190
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:209
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:160
List * ExecInsertIndexTuples(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool update, bool noDupErr, bool *specConflict, List *arbiterIndexes)
Definition: execIndexing.c:284
void ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative)
Definition: execIndexing.c:156
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
Definition: execMain.c:1782
void ExecCloseResultRelations(EState *estate)
Definition: execMain.c:1507
void ExecCloseRangeTableRelations(EState *estate)
Definition: execMain.c:1567
void ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1906
void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation)
Definition: execMain.c:994
ResultRelInfo * ExecFindPartition(ModifyTableState *mtstate, ResultRelInfo *rootResultRelInfo, PartitionTupleRouting *proute, TupleTableSlot *slot, EState *estate)
PartitionTupleRouting * ExecSetupPartitionTupleRouting(EState *estate, Relation rel)
void ExecCleanupTupleRouting(ModifyTableState *mtstate, PartitionTupleRouting *proute)
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:1191
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1552
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1254
void ExecInitRangeTable(EState *estate, List *rangeTable)
Definition: execUtils.c:751
void ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo, Index rti)
Definition: execUtils.c:834
EState * CreateExecutorState(void)
Definition: execUtils.c:90
void FreeExecutorState(EState *estate)
Definition: execUtils.c:186
#define ResetPerTupleExprContext(estate)
Definition: executor.h:546
#define GetPerTupleExprContext(estate)
Definition: executor.h:537
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:542
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:400
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2461
int ClosePipeStream(FILE *file)
Definition: fd.c:2870
int FreeFile(FILE *file)
Definition: fd.c:2660
FILE * OpenPipeStream(const char *command, const char *mode)
Definition: fd.c:2564
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
void ReleaseBulkInsertStatePin(BulkInsertState bistate)
Definition: heapam.c:1999
BulkInsertState GetBulkInsertState(void)
Definition: heapam.c:1973
void FreeBulkInsertState(BulkInsertState bistate)
Definition: heapam.c:1987
struct CopyFromStateData * CopyFromState
Definition: copy.h:65
int(* copy_data_source_cb)(void *outbuf, int minread, int maxread)
Definition: copy.h:68
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
Definition: list.c:336
List * list_delete_first(List *list)
Definition: list.c:902
void list_free(List *list)
Definition: list.c:1505
bool list_member_int(const List *list, int datum)
Definition: list.c:681
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2831
void getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
Definition: lsyscache.c:2897
int GetDatabaseEncoding(void)
Definition: mbutils.c:1210
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:1026
int pg_get_client_encoding(void)
Definition: mbutils.c:336
char * pstrdup(const char *in)
Definition: mcxt.c:1305
void pfree(void *pointer)
Definition: mcxt.c:1175
void * palloc0(Size size)
Definition: mcxt.c:1099
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
void * palloc(Size size)
Definition: mcxt.c:1068
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
Oid FindDefaultConversionProc(int32 for_encoding, int32 to_encoding)
Definition: namespace.c:3756
void ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo, EState *estate, TupleTableSlot *slot, CmdType cmdtype)
@ CMD_INSERT
Definition: nodes.h:723
#define makeNode(_type_)
Definition: nodes.h:621
#define castNode(_type_, nodeptr)
Definition: nodes.h:642
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int16 attnum
Definition: pg_attribute.h:83
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
void * arg
const void size_t len
static char * filename
Definition: pg_dumpall.c:94
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
#define NIL
Definition: pg_list.h:65
#define lfirst_int(lc)
Definition: pg_list.h:170
#define linitial(l)
Definition: pg_list.h:174
@ PG_SQL_ASCII
Definition: pg_wchar.h:224
Expr * expression_planner(Expr *expr)
Definition: planner.c:5882
bool ThereAreNoReadyPortals(void)
Definition: portalmem.c:1171
CommandDest whereToSendOutput
Definition: postgres.c:92
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define PROGRESS_COPY_COMMAND
Definition: progress.h:141
#define PROGRESS_COPY_TYPE_FILE
Definition: progress.h:149
#define PROGRESS_COPY_COMMAND_FROM
Definition: progress.h:145
#define PROGRESS_COPY_TUPLES_PROCESSED
Definition: progress.h:139
#define PROGRESS_COPY_TUPLES_EXCLUDED
Definition: progress.h:140
#define PROGRESS_COPY_TYPE
Definition: progress.h:142
#define PROGRESS_COPY_TYPE_PROGRAM
Definition: progress.h:150
#define PROGRESS_COPY_BYTES_TOTAL
Definition: progress.h:138
#define PROGRESS_COPY_TYPE_CALLBACK
Definition: progress.h:152
#define PROGRESS_COPY_TYPE_PIPE
Definition: progress.h:151
#define RelationGetRelid(relation)
Definition: rel.h:489
#define RelationGetDescr(relation)
Definition: rel.h:515
#define RelationGetRelationName(relation)
Definition: rel.h:523
Node * build_column_default(Relation rel, int attrno)
bool ThereAreNoPriorRegisteredSnapshots(void)
Definition: snapmgr.c:1621
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:456
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
bool freeze
Definition: copy.h:44
bool binary
Definition: copy.h:43
bool convert_selectively
Definition: copy.h:60
List * force_null
Definition: copy.h:58
List * convert_select
Definition: copy.h:61
bool * force_notnull_flags
Definition: copy.h:57
int file_encoding
Definition: copy.h:41
bool * force_null_flags
Definition: copy.h:59
List * force_notnull
Definition: copy.h:56
ExprState ** defexprs
copy_data_source_cb data_source_cb
StringInfoData line_buf
CopyFormatOptions opts
StringInfoData attribute_buf
TransitionCaptureState * transition_capture
MemoryContext copycontext
const char * cur_attval
const char * cur_attname
const char * cur_relname
TupleTableSlot * slots[MAX_BUFFERED_TUPLES]
Definition: copyfrom.c:79
ResultRelInfo * resultRelInfo
Definition: copyfrom.c:80
uint64 linenos[MAX_BUFFERED_TUPLES]
Definition: copyfrom.c:83
BulkInsertState bistate
Definition: copyfrom.c:81
EState * estate
Definition: copyfrom.c:98
CommandId mycid
Definition: copyfrom.c:99
List * multiInsertBuffers
Definition: copyfrom.c:94
CopyFromState cstate
Definition: copyfrom.c:97
List * es_tupleTable
Definition: execnodes.h:634
struct ErrorContextCallback * previous
Definition: elog.h:232
void(* callback)(void *arg)
Definition: elog.h:233
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:232
EndForeignInsert_function EndForeignInsert
Definition: fdwapi.h:239
BeginForeignInsert_function BeginForeignInsert
Definition: fdwapi.h:238
ExecForeignInsert_function ExecForeignInsert
Definition: fdwapi.h:232
Definition: fmgr.h:57
Definition: pg_list.h:51
CmdType operation
Definition: execnodes.h:1226
ResultRelInfo * resultRelInfo
Definition: execnodes.h:1230
PlanState ps
Definition: execnodes.h:1225
ResultRelInfo * rootResultRelInfo
Definition: execnodes.h:1238
struct TransitionCaptureState * mt_transition_capture
Definition: execnodes.h:1264
Definition: nodes.h:574
List * p_rtable
Definition: parse_node.h:183
Plan * plan
Definition: execnodes.h:998
EState * state
Definition: execnodes.h:1000
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:103
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
TriggerDesc * trigdesc
Definition: rel.h:115
TupleDesc rd_att
Definition: rel.h:110
SubTransactionId rd_createSubid
Definition: rel.h:102
Form_pg_class rd_rel
Definition: rel.h:109
TupleTableSlot * ri_PartitionTupleSlot
Definition: execnodes.h:540
int ri_NumIndices
Definition: execnodes.h:436
Relation ri_RelationDesc
Definition: execnodes.h:433
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition: execnodes.h:552
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:460
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:477
TupleConversionMap * ri_RootToPartitionMap
Definition: execnodes.h:539
TupleTableSlot * tcs_original_insert_tuple
Definition: trigger.h:76
bool trig_insert_instead_row
Definition: reltrigger.h:58
bool trig_insert_after_row
Definition: reltrigger.h:57
bool trig_insert_new_table
Definition: reltrigger.h:75
bool trig_insert_before_row
Definition: reltrigger.h:56
bool has_generated_stored
Definition: tupdesc.h:45
AttrMap * attrMap
Definition: tupconvert.h:28
TupleConstr * constr
Definition: tupdesc.h:85
Oid tts_tableOid
Definition: tuptable.h:131
bool * tts_isnull
Definition: tuptable.h:128
Datum * tts_values
Definition: tuptable.h:126
__int64 st_size
Definition: win32_port.h:273
unsigned short st_mode
Definition: win32_port.h:268
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition: tableam.c:91
#define TABLE_INSERT_FROZEN
Definition: tableam.h:237
#define TABLE_INSERT_SKIP_FSM
Definition: tableam.h:236
static void table_finish_bulk_insert(Relation rel, int options)
Definition: tableam.h:1566
static void table_multi_insert(Relation rel, TupleTableSlot **slots, int nslots, CommandId cid, int options, struct BulkInsertStateData *bistate)
Definition: tableam.h:1428
static void table_tuple_insert(Relation rel, TupleTableSlot *slot, CommandId cid, int options, struct BulkInsertStateData *bistate)
Definition: tableam.h:1373
void ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2408
bool ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2472
bool ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2565
void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot, List *recheckIndexes, TransitionCaptureState *transition_capture)
Definition: trigger.c:2548
TransitionCaptureState * MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType)
Definition: trigger.c:4825
void ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo, TransitionCaptureState *transition_capture)
Definition: trigger.c:2459
void AfterTriggerEndQuery(EState *estate)
Definition: trigger.c:4981
void AfterTriggerBeginQuery(void)
Definition: trigger.c:4961
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition: tupconvert.c:177
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: tuptable.h:475
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition: tuptable.h:443
char * wait_result_to_str(int exitstatus)
Definition: wait_error.c:32
bool wait_result_is_signal(int exit_status, int signum)
Definition: wait_error.c:92
#define SIGPIPE
Definition: win32_port.h:172
#define S_ISDIR(m)
Definition: win32_port.h:324
#define fstat
Definition: win32_port.h:282
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:776
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:814