PostgreSQL Source Code  git master
copyto.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <unistd.h>
#include <sys/stat.h>
#include "access/tableam.h"
#include "commands/copy.h"
#include "commands/progress.h"
#include "executor/execdesc.h"
#include "executor/executor.h"
#include "executor/tuptable.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "storage/fd.h"
#include "tcop/tcopprot.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
Include dependency graph for copyto.c:

Go to the source code of this file.

Data Structures

struct  CopyToStateData
 
struct  DR_copy
 

Macros

#define DUMPSOFAR()
 

Typedefs

typedef enum CopyDest CopyDest
 
typedef struct CopyToStateData CopyToStateData
 

Enumerations

enum  CopyDest { COPY_FILE , COPY_FRONTEND , COPY_CALLBACK }
 

Functions

static void EndCopy (CopyToState cstate)
 
static void ClosePipeToProgram (CopyToState cstate)
 
static void CopyOneRowTo (CopyToState cstate, TupleTableSlot *slot)
 
static void CopyAttributeOutText (CopyToState cstate, const char *string)
 
static void CopyAttributeOutCSV (CopyToState cstate, const char *string, bool use_quote)
 
static void SendCopyBegin (CopyToState cstate)
 
static void SendCopyEnd (CopyToState cstate)
 
static void CopySendData (CopyToState cstate, const void *databuf, int datasize)
 
static void CopySendString (CopyToState cstate, const char *str)
 
static void CopySendChar (CopyToState cstate, char c)
 
static void CopySendEndOfRow (CopyToState cstate)
 
static void CopySendInt32 (CopyToState cstate, int32 val)
 
static void CopySendInt16 (CopyToState cstate, int16 val)
 
CopyToState BeginCopyTo (ParseState *pstate, Relation rel, RawStmt *raw_query, Oid queryRelId, const char *filename, bool is_program, copy_data_dest_cb data_dest_cb, List *attnamelist, List *options)
 
void EndCopyTo (CopyToState cstate)
 
uint64 DoCopyTo (CopyToState cstate)
 
static void copy_dest_startup (DestReceiver *self, int operation, TupleDesc typeinfo)
 
static bool copy_dest_receive (TupleTableSlot *slot, DestReceiver *self)
 
static void copy_dest_shutdown (DestReceiver *self)
 
static void copy_dest_destroy (DestReceiver *self)
 
DestReceiverCreateCopyDestReceiver (void)
 

Variables

static const char BinarySignature [11] = "PGCOPY\n\377\r\n\0"
 

Macro Definition Documentation

◆ DUMPSOFAR

#define DUMPSOFAR ( )
Value:
do { \
if (ptr > start) \
CopySendData(cstate, start, ptr - start); \
} while (0)
return str start

Definition at line 981 of file copyto.c.

Typedef Documentation

◆ CopyDest

typedef enum CopyDest CopyDest

◆ CopyToStateData

Enumeration Type Documentation

◆ CopyDest

enum CopyDest
Enumerator
COPY_FILE 
COPY_FRONTEND 
COPY_CALLBACK 

Definition at line 43 of file copyto.c.

44 {
45  COPY_FILE, /* to file (or a piped program) */
46  COPY_FRONTEND, /* to frontend */
47  COPY_CALLBACK, /* to callback function */
48 } CopyDest;
CopyDest
Definition: copyto.c:44
@ COPY_FILE
Definition: copyto.c:45
@ COPY_CALLBACK
Definition: copyto.c:47
@ COPY_FRONTEND
Definition: copyto.c:46

Function Documentation

◆ BeginCopyTo()

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

Definition at line 350 of file copyto.c.

359 {
360  CopyToState cstate;
361  bool pipe = (filename == NULL && data_dest_cb == NULL);
362  TupleDesc tupDesc;
363  int num_phys_attrs;
364  MemoryContext oldcontext;
365  const int progress_cols[] = {
368  };
369  int64 progress_vals[] = {
371  0
372  };
373 
374  if (rel != NULL && rel->rd_rel->relkind != RELKIND_RELATION)
375  {
376  if (rel->rd_rel->relkind == RELKIND_VIEW)
377  ereport(ERROR,
378  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
379  errmsg("cannot copy from view \"%s\"",
381  errhint("Try the COPY (SELECT ...) TO variant.")));
382  else if (rel->rd_rel->relkind == RELKIND_MATVIEW)
383  ereport(ERROR,
384  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
385  errmsg("cannot copy from materialized view \"%s\"",
387  errhint("Try the COPY (SELECT ...) TO variant.")));
388  else if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
389  ereport(ERROR,
390  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
391  errmsg("cannot copy from foreign table \"%s\"",
393  errhint("Try the COPY (SELECT ...) TO variant.")));
394  else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
395  ereport(ERROR,
396  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
397  errmsg("cannot copy from sequence \"%s\"",
398  RelationGetRelationName(rel))));
399  else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
400  ereport(ERROR,
401  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
402  errmsg("cannot copy from partitioned table \"%s\"",
404  errhint("Try the COPY (SELECT ...) TO variant.")));
405  else
406  ereport(ERROR,
407  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
408  errmsg("cannot copy from non-table relation \"%s\"",
409  RelationGetRelationName(rel))));
410  }
411 
412 
413  /* Allocate workspace and zero all fields */
414  cstate = (CopyToStateData *) palloc0(sizeof(CopyToStateData));
415 
416  /*
417  * We allocate everything used by a cstate in a new memory context. This
418  * avoids memory leaks during repeated use of COPY in a query.
419  */
421  "COPY",
423 
424  oldcontext = MemoryContextSwitchTo(cstate->copycontext);
425 
426  /* Extract options from the statement node tree */
427  ProcessCopyOptions(pstate, &cstate->opts, false /* is_from */ , options);
428 
429  /* Process the source/target relation or query */
430  if (rel)
431  {
432  Assert(!raw_query);
433 
434  cstate->rel = rel;
435 
436  tupDesc = RelationGetDescr(cstate->rel);
437  }
438  else
439  {
440  List *rewritten;
441  Query *query;
442  PlannedStmt *plan;
444 
445  cstate->rel = NULL;
446 
447  /*
448  * Run parse analysis and rewrite. Note this also acquires sufficient
449  * locks on the source table(s).
450  */
451  rewritten = pg_analyze_and_rewrite_fixedparams(raw_query,
452  pstate->p_sourcetext, NULL, 0,
453  NULL);
454 
455  /* check that we got back something we can work with */
456  if (rewritten == NIL)
457  {
458  ereport(ERROR,
459  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
460  errmsg("DO INSTEAD NOTHING rules are not supported for COPY")));
461  }
462  else if (list_length(rewritten) > 1)
463  {
464  ListCell *lc;
465 
466  /* examine queries to determine which error message to issue */
467  foreach(lc, rewritten)
468  {
469  Query *q = lfirst_node(Query, lc);
470 
471  if (q->querySource == QSRC_QUAL_INSTEAD_RULE)
472  ereport(ERROR,
473  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
474  errmsg("conditional DO INSTEAD rules are not supported for COPY")));
475  if (q->querySource == QSRC_NON_INSTEAD_RULE)
476  ereport(ERROR,
477  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
478  errmsg("DO ALSO rules are not supported for COPY")));
479  }
480 
481  ereport(ERROR,
482  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
483  errmsg("multi-statement DO INSTEAD rules are not supported for COPY")));
484  }
485 
486  query = linitial_node(Query, rewritten);
487 
488  /* The grammar allows SELECT INTO, but we don't support that */
489  if (query->utilityStmt != NULL &&
491  ereport(ERROR,
492  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
493  errmsg("COPY (SELECT INTO) is not supported")));
494 
495  /* The only other utility command we could see is NOTIFY */
496  if (query->utilityStmt != NULL)
497  ereport(ERROR,
498  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
499  errmsg("COPY query must not be a utility command")));
500 
501  /*
502  * Similarly the grammar doesn't enforce the presence of a RETURNING
503  * clause, but this is required here.
504  */
505  if (query->commandType != CMD_SELECT &&
506  query->returningList == NIL)
507  {
508  Assert(query->commandType == CMD_INSERT ||
509  query->commandType == CMD_UPDATE ||
510  query->commandType == CMD_DELETE ||
511  query->commandType == CMD_MERGE);
512 
513  ereport(ERROR,
514  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
515  errmsg("COPY query must have a RETURNING clause")));
516  }
517 
518  /* plan the query */
519  plan = pg_plan_query(query, pstate->p_sourcetext,
520  CURSOR_OPT_PARALLEL_OK, NULL);
521 
522  /*
523  * With row-level security and a user using "COPY relation TO", we
524  * have to convert the "COPY relation TO" to a query-based COPY (eg:
525  * "COPY (SELECT * FROM ONLY relation) TO"), to allow the rewriter to
526  * add in any RLS clauses.
527  *
528  * When this happens, we are passed in the relid of the originally
529  * found relation (which we have locked). As the planner will look up
530  * the relation again, we double-check here to make sure it found the
531  * same one that we have locked.
532  */
533  if (queryRelId != InvalidOid)
534  {
535  /*
536  * Note that with RLS involved there may be multiple relations,
537  * and while the one we need is almost certainly first, we don't
538  * make any guarantees of that in the planner, so check the whole
539  * list and make sure we find the original relation.
540  */
541  if (!list_member_oid(plan->relationOids, queryRelId))
542  ereport(ERROR,
543  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
544  errmsg("relation referenced by COPY statement has changed")));
545  }
546 
547  /*
548  * Use a snapshot with an updated command ID to ensure this query sees
549  * results of any previously executed queries.
550  */
553 
554  /* Create dest receiver for COPY OUT */
556  ((DR_copy *) dest)->cstate = cstate;
557 
558  /* Create a QueryDesc requesting no output */
559  cstate->queryDesc = CreateQueryDesc(plan, pstate->p_sourcetext,
562  dest, NULL, NULL, 0);
563 
564  /*
565  * Call ExecutorStart to prepare the plan for execution.
566  *
567  * ExecutorStart computes a result tupdesc for us
568  */
569  ExecutorStart(cstate->queryDesc, 0);
570 
571  tupDesc = cstate->queryDesc->tupDesc;
572  }
573 
574  /* Generate or convert list of attributes to process */
575  cstate->attnumlist = CopyGetAttnums(tupDesc, cstate->rel, attnamelist);
576 
577  num_phys_attrs = tupDesc->natts;
578 
579  /* Convert FORCE_QUOTE name list to per-column flags, check validity */
580  cstate->opts.force_quote_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
581  if (cstate->opts.force_quote_all)
582  {
583  MemSet(cstate->opts.force_quote_flags, true, num_phys_attrs * sizeof(bool));
584  }
585  else if (cstate->opts.force_quote)
586  {
587  List *attnums;
588  ListCell *cur;
589 
590  attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_quote);
591 
592  foreach(cur, attnums)
593  {
594  int attnum = lfirst_int(cur);
595  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
596 
597  if (!list_member_int(cstate->attnumlist, attnum))
598  ereport(ERROR,
599  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
600  /*- translator: %s is the name of a COPY option, e.g. FORCE_NOT_NULL */
601  errmsg("%s column \"%s\" not referenced by COPY",
602  "FORCE_QUOTE", NameStr(attr->attname))));
603  cstate->opts.force_quote_flags[attnum - 1] = true;
604  }
605  }
606 
607  /* Use client encoding when ENCODING option is not specified. */
608  if (cstate->opts.file_encoding < 0)
610  else
611  cstate->file_encoding = cstate->opts.file_encoding;
612 
613  /*
614  * Set up encoding conversion info if the file and server encodings differ
615  * (see also pg_server_to_any).
616  */
617  if (cstate->file_encoding == GetDatabaseEncoding() ||
618  cstate->file_encoding == PG_SQL_ASCII)
619  cstate->need_transcoding = false;
620  else
621  cstate->need_transcoding = true;
622 
623  /* See Multibyte encoding comment above */
625 
626  cstate->copy_dest = COPY_FILE; /* default */
627 
628  if (data_dest_cb)
629  {
630  progress_vals[1] = PROGRESS_COPY_TYPE_CALLBACK;
631  cstate->copy_dest = COPY_CALLBACK;
632  cstate->data_dest_cb = data_dest_cb;
633  }
634  else if (pipe)
635  {
636  progress_vals[1] = PROGRESS_COPY_TYPE_PIPE;
637 
638  Assert(!is_program); /* the grammar does not allow this */
640  cstate->copy_file = stdout;
641  }
642  else
643  {
644  cstate->filename = pstrdup(filename);
645  cstate->is_program = is_program;
646 
647  if (is_program)
648  {
649  progress_vals[1] = PROGRESS_COPY_TYPE_PROGRAM;
650  cstate->copy_file = OpenPipeStream(cstate->filename, PG_BINARY_W);
651  if (cstate->copy_file == NULL)
652  ereport(ERROR,
654  errmsg("could not execute command \"%s\": %m",
655  cstate->filename)));
656  }
657  else
658  {
659  mode_t oumask; /* Pre-existing umask value */
660  struct stat st;
661 
662  progress_vals[1] = PROGRESS_COPY_TYPE_FILE;
663 
664  /*
665  * Prevent write to relative path ... too easy to shoot oneself in
666  * the foot by overwriting a database file ...
667  */
669  ereport(ERROR,
670  (errcode(ERRCODE_INVALID_NAME),
671  errmsg("relative path not allowed for COPY to file")));
672 
673  oumask = umask(S_IWGRP | S_IWOTH);
674  PG_TRY();
675  {
676  cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_W);
677  }
678  PG_FINALLY();
679  {
680  umask(oumask);
681  }
682  PG_END_TRY();
683  if (cstate->copy_file == NULL)
684  {
685  /* copy errno because ereport subfunctions might change it */
686  int save_errno = errno;
687 
688  ereport(ERROR,
690  errmsg("could not open file \"%s\" for writing: %m",
691  cstate->filename),
692  (save_errno == ENOENT || save_errno == EACCES) ?
693  errhint("COPY TO instructs the PostgreSQL server process to write a file. "
694  "You may want a client-side facility such as psql's \\copy.") : 0));
695  }
696 
697  if (fstat(fileno(cstate->copy_file), &st))
698  ereport(ERROR,
700  errmsg("could not stat file \"%s\": %m",
701  cstate->filename)));
702 
703  if (S_ISDIR(st.st_mode))
704  ereport(ERROR,
705  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
706  errmsg("\"%s\" is a directory", cstate->filename)));
707  }
708  }
709 
710  /* initialize progress */
712  cstate->rel ? RelationGetRelid(cstate->rel) : InvalidOid);
713  pgstat_progress_update_multi_param(2, progress_cols, progress_vals);
714 
715  cstate->bytes_processed = 0;
716 
717  MemoryContextSwitchTo(oldcontext);
718 
719  return cstate;
720 }
List * CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
Definition: copy.c:931
void ProcessCopyOptions(ParseState *pstate, CopyFormatOptions *opts_out, bool is_from, List *options)
Definition: copy.c:482
void pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid)
void pgstat_progress_update_multi_param(int nparam, const int *index, const int64 *val)
@ PROGRESS_COMMAND_COPY
#define NameStr(name)
Definition: c.h:737
#define Assert(condition)
Definition: c.h:849
#define PG_BINARY_W
Definition: c.h:1267
#define MemSet(start, val, len)
Definition: c.h:1011
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:113
@ DestRemote
Definition: dest.h:89
@ DestCopyOut
Definition: dest.h:95
struct cursor * cur
Definition: ecpg.c:28
int errcode_for_file_access(void)
Definition: elog.c:876
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define PG_TRY(...)
Definition: elog.h:371
#define PG_END_TRY(...)
Definition: elog.h:396
#define ERROR
Definition: elog.h:39
#define PG_FINALLY(...)
Definition: elog.h:388
#define ereport(elevel,...)
Definition: elog.h:149
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:120
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2606
FILE * OpenPipeStream(const char *command, const char *mode)
Definition: fd.c:2709
bool list_member_int(const List *list, int datum)
Definition: list.c:702
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:722
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
int pg_get_client_encoding(void)
Definition: mbutils.c:336
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void * palloc0(Size size)
Definition: mcxt.c:1347
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
@ CMD_MERGE
Definition: nodes.h:269
@ CMD_INSERT
Definition: nodes.h:267
@ CMD_DELETE
Definition: nodes.h:268
@ CMD_UPDATE
Definition: nodes.h:266
@ CMD_SELECT
Definition: nodes.h:265
@ QSRC_NON_INSTEAD_RULE
Definition: parsenodes.h:40
@ QSRC_QUAL_INSTEAD_RULE
Definition: parsenodes.h:39
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:3307
int16 attnum
Definition: pg_attribute.h:74
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
static char * filename
Definition: pg_dumpall.c:119
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial_node(type, l)
Definition: pg_list.h:181
#define NIL
Definition: pg_list.h:68
#define lfirst_int(lc)
Definition: pg_list.h:173
#define plan(x)
Definition: pg_regress.c:162
@ PG_SQL_ASCII
Definition: pg_wchar.h:226
#define PG_ENCODING_IS_CLIENT_ONLY(_enc)
Definition: pg_wchar.h:284
#define is_absolute_path(filename)
Definition: port.h:103
CommandDest whereToSendOutput
Definition: postgres.c:91
List * pg_analyze_and_rewrite_fixedparams(RawStmt *parsetree, const char *query_string, const Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
Definition: postgres.c:677
PlannedStmt * pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, ParamListInfo boundParams)
Definition: postgres.c:894
#define InvalidOid
Definition: postgres_ext.h:36
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
Definition: pquery.c:67
#define PROGRESS_COPY_COMMAND
Definition: progress.h:144
#define PROGRESS_COPY_TYPE_FILE
Definition: progress.h:153
#define PROGRESS_COPY_COMMAND_TO
Definition: progress.h:150
#define PROGRESS_COPY_TYPE
Definition: progress.h:145
#define PROGRESS_COPY_TYPE_PROGRAM
Definition: progress.h:154
#define PROGRESS_COPY_TYPE_CALLBACK
Definition: progress.h:156
#define PROGRESS_COPY_TYPE_PIPE
Definition: progress.h:155
MemoryContextSwitchTo(old_ctx)
#define RelationGetRelid(relation)
Definition: rel.h:505
#define RelationGetDescr(relation)
Definition: rel.h:531
#define RelationGetRelationName(relation)
Definition: rel.h:539
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:712
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:700
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:770
#define InvalidSnapshot
Definition: snapshot.h:123
bool force_quote_all
Definition: copy.h:77
List * force_quote
Definition: copy.h:76
bool * force_quote_flags
Definition: copy.h:78
int file_encoding
Definition: copy.h:62
MemoryContext copycontext
Definition: copyto.c:90
Relation rel
Definition: copyto.c:77
copy_data_dest_cb data_dest_cb
Definition: copyto.c:82
bool encoding_embeds_ascii
Definition: copyto.c:74
CopyDest copy_dest
Definition: copyto.c:68
bool need_transcoding
Definition: copyto.c:73
bool is_program
Definition: copyto.c:81
FILE * copy_file
Definition: copyto.c:69
int file_encoding
Definition: copyto.c:72
CopyFormatOptions opts
Definition: copyto.c:84
uint64 bytes_processed
Definition: copyto.c:94
char * filename
Definition: copyto.c:80
List * attnumlist
Definition: copyto.c:79
QueryDesc * queryDesc
Definition: copyto.c:78
Definition: copyto.c:99
Definition: pg_list.h:54
const char * p_sourcetext
Definition: parse_node.h:195
TupleDesc tupDesc
Definition: execdesc.h:47
List * returningList
Definition: parsenodes.h:200
CmdType commandType
Definition: parsenodes.h:121
Node * utilityStmt
Definition: parsenodes.h:136
Form_pg_class rd_rel
Definition: rel.h:111
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define S_IWOTH
Definition: win32_port.h:316
#define S_ISDIR(m)
Definition: win32_port.h:325
#define fstat
Definition: win32_port.h:283
#define S_IWGRP
Definition: win32_port.h:304

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

Referenced by DoCopy(), and test_copy_to_callback().

◆ ClosePipeToProgram()

static void ClosePipeToProgram ( CopyToState  cstate)
static

Definition at line 289 of file copyto.c.

290 {
291  int pclose_rc;
292 
293  Assert(cstate->is_program);
294 
295  pclose_rc = ClosePipeStream(cstate->copy_file);
296  if (pclose_rc == -1)
297  ereport(ERROR,
299  errmsg("could not close pipe to external command: %m")));
300  else if (pclose_rc != 0)
301  {
302  ereport(ERROR,
303  (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
304  errmsg("program \"%s\" failed",
305  cstate->filename),
306  errdetail_internal("%s", wait_result_to_str(pclose_rc))));
307  }
308 }
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1230
int ClosePipeStream(FILE *file)
Definition: fd.c:3014
char * wait_result_to_str(int exitstatus)
Definition: wait_error.c:33

References Assert, ClosePipeStream(), CopyToStateData::copy_file, ereport, errcode(), errcode_for_file_access(), errdetail_internal(), errmsg(), ERROR, CopyToStateData::filename, CopyToStateData::is_program, and wait_result_to_str().

Referenced by CopySendEndOfRow(), and EndCopy().

◆ copy_dest_destroy()

static void copy_dest_destroy ( DestReceiver self)
static

Definition at line 1267 of file copyto.c.

1268 {
1269  pfree(self);
1270 }
void pfree(void *pointer)
Definition: mcxt.c:1521

References pfree().

Referenced by CreateCopyDestReceiver().

◆ copy_dest_receive()

static bool copy_dest_receive ( TupleTableSlot slot,
DestReceiver self 
)
static

Definition at line 1239 of file copyto.c.

1240 {
1241  DR_copy *myState = (DR_copy *) self;
1242  CopyToState cstate = myState->cstate;
1243 
1244  /* Send the data */
1245  CopyOneRowTo(cstate, slot);
1246 
1247  /* Increment the number of processed tuples, and report the progress */
1249  ++myState->processed);
1250 
1251  return true;
1252 }
void pgstat_progress_update_param(int index, int64 val)
static void CopyOneRowTo(CopyToState cstate, TupleTableSlot *slot)
Definition: copyto.c:907
#define PROGRESS_COPY_TUPLES_PROCESSED
Definition: progress.h:142
CopyToState cstate
Definition: copyto.c:101
uint64 processed
Definition: copyto.c:102

References CopyOneRowTo(), DR_copy::cstate, pgstat_progress_update_param(), DR_copy::processed, and PROGRESS_COPY_TUPLES_PROCESSED.

Referenced by CreateCopyDestReceiver().

◆ copy_dest_shutdown()

static void copy_dest_shutdown ( DestReceiver self)
static

Definition at line 1258 of file copyto.c.

1259 {
1260  /* no-op */
1261 }

Referenced by CreateCopyDestReceiver().

◆ copy_dest_startup()

static void copy_dest_startup ( DestReceiver self,
int  operation,
TupleDesc  typeinfo 
)
static

Definition at line 1230 of file copyto.c.

1231 {
1232  /* no-op */
1233 }

Referenced by CreateCopyDestReceiver().

◆ CopyAttributeOutCSV()

static void CopyAttributeOutCSV ( CopyToState  cstate,
const char *  string,
bool  use_quote 
)
static

Definition at line 1141 of file copyto.c.

1143 {
1144  const char *ptr;
1145  const char *start;
1146  char c;
1147  char delimc = cstate->opts.delim[0];
1148  char quotec = cstate->opts.quote[0];
1149  char escapec = cstate->opts.escape[0];
1150  bool single_attr = (list_length(cstate->attnumlist) == 1);
1151 
1152  /* force quoting if it matches null_print (before conversion!) */
1153  if (!use_quote && strcmp(string, cstate->opts.null_print) == 0)
1154  use_quote = true;
1155 
1156  if (cstate->need_transcoding)
1157  ptr = pg_server_to_any(string, strlen(string), cstate->file_encoding);
1158  else
1159  ptr = string;
1160 
1161  /*
1162  * Make a preliminary pass to discover if it needs quoting
1163  */
1164  if (!use_quote)
1165  {
1166  /*
1167  * Quote '\.' if it appears alone on a line, so that it will not be
1168  * interpreted as an end-of-data marker. (PG 18 and up will not
1169  * interpret '\.' in CSV that way, except in embedded-in-SQL data; but
1170  * we want the data to be loadable by older versions too. Also, this
1171  * avoids breaking clients that are still using PQgetline().)
1172  */
1173  if (single_attr && strcmp(ptr, "\\.") == 0)
1174  use_quote = true;
1175  else
1176  {
1177  const char *tptr = ptr;
1178 
1179  while ((c = *tptr) != '\0')
1180  {
1181  if (c == delimc || c == quotec || c == '\n' || c == '\r')
1182  {
1183  use_quote = true;
1184  break;
1185  }
1186  if (IS_HIGHBIT_SET(c) && cstate->encoding_embeds_ascii)
1187  tptr += pg_encoding_mblen(cstate->file_encoding, tptr);
1188  else
1189  tptr++;
1190  }
1191  }
1192  }
1193 
1194  if (use_quote)
1195  {
1196  CopySendChar(cstate, quotec);
1197 
1198  /*
1199  * We adopt the same optimization strategy as in CopyAttributeOutText
1200  */
1201  start = ptr;
1202  while ((c = *ptr) != '\0')
1203  {
1204  if (c == quotec || c == escapec)
1205  {
1206  DUMPSOFAR();
1207  CopySendChar(cstate, escapec);
1208  start = ptr; /* we include char in next run */
1209  }
1210  if (IS_HIGHBIT_SET(c) && cstate->encoding_embeds_ascii)
1211  ptr += pg_encoding_mblen(cstate->file_encoding, ptr);
1212  else
1213  ptr++;
1214  }
1215  DUMPSOFAR();
1216 
1217  CopySendChar(cstate, quotec);
1218  }
1219  else
1220  {
1221  /* If it doesn't need quoting, we can just dump it as-is */
1222  CopySendString(cstate, ptr);
1223  }
1224 }
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1146
#define DUMPSOFAR()
Definition: copyto.c:981
static void CopySendChar(CopyToState cstate, char c)
Definition: copyto.c:181
static void CopySendString(CopyToState cstate, const char *str)
Definition: copyto.c:175
char * pg_server_to_any(const char *s, int len, int encoding)
Definition: mbutils.c:749
char * c
char string[11]
Definition: preproc-type.c:52
char * quote
Definition: copy.h:74
char * escape
Definition: copy.h:75
char * null_print
Definition: copy.h:68
char * delim
Definition: copy.h:73
int pg_encoding_mblen(int encoding, const char *mbstr)
Definition: wchar.c:2069

References CopyToStateData::attnumlist, CopySendChar(), CopySendString(), CopyFormatOptions::delim, DUMPSOFAR, CopyToStateData::encoding_embeds_ascii, CopyFormatOptions::escape, CopyToStateData::file_encoding, IS_HIGHBIT_SET, list_length(), CopyToStateData::need_transcoding, CopyFormatOptions::null_print, CopyToStateData::opts, pg_encoding_mblen(), pg_server_to_any(), CopyFormatOptions::quote, and start.

Referenced by CopyOneRowTo(), and DoCopyTo().

◆ CopyAttributeOutText()

static void CopyAttributeOutText ( CopyToState  cstate,
const char *  string 
)
static

Definition at line 988 of file copyto.c.

989 {
990  const char *ptr;
991  const char *start;
992  char c;
993  char delimc = cstate->opts.delim[0];
994 
995  if (cstate->need_transcoding)
996  ptr = pg_server_to_any(string, strlen(string), cstate->file_encoding);
997  else
998  ptr = string;
999 
1000  /*
1001  * We have to grovel through the string searching for control characters
1002  * and instances of the delimiter character. In most cases, though, these
1003  * are infrequent. To avoid overhead from calling CopySendData once per
1004  * character, we dump out all characters between escaped characters in a
1005  * single call. The loop invariant is that the data from "start" to "ptr"
1006  * can be sent literally, but hasn't yet been.
1007  *
1008  * We can skip pg_encoding_mblen() overhead when encoding is safe, because
1009  * in valid backend encodings, extra bytes of a multibyte character never
1010  * look like ASCII. This loop is sufficiently performance-critical that
1011  * it's worth making two copies of it to get the IS_HIGHBIT_SET() test out
1012  * of the normal safe-encoding path.
1013  */
1014  if (cstate->encoding_embeds_ascii)
1015  {
1016  start = ptr;
1017  while ((c = *ptr) != '\0')
1018  {
1019  if ((unsigned char) c < (unsigned char) 0x20)
1020  {
1021  /*
1022  * \r and \n must be escaped, the others are traditional. We
1023  * prefer to dump these using the C-like notation, rather than
1024  * a backslash and the literal character, because it makes the
1025  * dump file a bit more proof against Microsoftish data
1026  * mangling.
1027  */
1028  switch (c)
1029  {
1030  case '\b':
1031  c = 'b';
1032  break;
1033  case '\f':
1034  c = 'f';
1035  break;
1036  case '\n':
1037  c = 'n';
1038  break;
1039  case '\r':
1040  c = 'r';
1041  break;
1042  case '\t':
1043  c = 't';
1044  break;
1045  case '\v':
1046  c = 'v';
1047  break;
1048  default:
1049  /* If it's the delimiter, must backslash it */
1050  if (c == delimc)
1051  break;
1052  /* All ASCII control chars are length 1 */
1053  ptr++;
1054  continue; /* fall to end of loop */
1055  }
1056  /* if we get here, we need to convert the control char */
1057  DUMPSOFAR();
1058  CopySendChar(cstate, '\\');
1059  CopySendChar(cstate, c);
1060  start = ++ptr; /* do not include char in next run */
1061  }
1062  else if (c == '\\' || c == delimc)
1063  {
1064  DUMPSOFAR();
1065  CopySendChar(cstate, '\\');
1066  start = ptr++; /* we include char in next run */
1067  }
1068  else if (IS_HIGHBIT_SET(c))
1069  ptr += pg_encoding_mblen(cstate->file_encoding, ptr);
1070  else
1071  ptr++;
1072  }
1073  }
1074  else
1075  {
1076  start = ptr;
1077  while ((c = *ptr) != '\0')
1078  {
1079  if ((unsigned char) c < (unsigned char) 0x20)
1080  {
1081  /*
1082  * \r and \n must be escaped, the others are traditional. We
1083  * prefer to dump these using the C-like notation, rather than
1084  * a backslash and the literal character, because it makes the
1085  * dump file a bit more proof against Microsoftish data
1086  * mangling.
1087  */
1088  switch (c)
1089  {
1090  case '\b':
1091  c = 'b';
1092  break;
1093  case '\f':
1094  c = 'f';
1095  break;
1096  case '\n':
1097  c = 'n';
1098  break;
1099  case '\r':
1100  c = 'r';
1101  break;
1102  case '\t':
1103  c = 't';
1104  break;
1105  case '\v':
1106  c = 'v';
1107  break;
1108  default:
1109  /* If it's the delimiter, must backslash it */
1110  if (c == delimc)
1111  break;
1112  /* All ASCII control chars are length 1 */
1113  ptr++;
1114  continue; /* fall to end of loop */
1115  }
1116  /* if we get here, we need to convert the control char */
1117  DUMPSOFAR();
1118  CopySendChar(cstate, '\\');
1119  CopySendChar(cstate, c);
1120  start = ++ptr; /* do not include char in next run */
1121  }
1122  else if (c == '\\' || c == delimc)
1123  {
1124  DUMPSOFAR();
1125  CopySendChar(cstate, '\\');
1126  start = ptr++; /* we include char in next run */
1127  }
1128  else
1129  ptr++;
1130  }
1131  }
1132 
1133  DUMPSOFAR();
1134 }

References CopySendChar(), CopyFormatOptions::delim, DUMPSOFAR, CopyToStateData::encoding_embeds_ascii, CopyToStateData::file_encoding, IS_HIGHBIT_SET, CopyToStateData::need_transcoding, CopyToStateData::opts, pg_encoding_mblen(), pg_server_to_any(), and start.

Referenced by CopyOneRowTo(), and DoCopyTo().

◆ CopyOneRowTo()

static void CopyOneRowTo ( CopyToState  cstate,
TupleTableSlot slot 
)
static

Definition at line 907 of file copyto.c.

908 {
909  FmgrInfo *out_functions = cstate->out_functions;
910  MemoryContext oldcontext;
911 
913  oldcontext = MemoryContextSwitchTo(cstate->rowcontext);
914 
915  if (cstate->opts.binary)
916  {
917  /* Binary per-tuple header */
918  CopySendInt16(cstate, list_length(cstate->attnumlist));
919  }
920 
921  /* Make sure the tuple is fully deconstructed */
922  slot_getallattrs(slot);
923 
924  if (!cstate->opts.binary)
925  {
926  bool need_delim = false;
927 
928  foreach_int(attnum, cstate->attnumlist)
929  {
930  Datum value = slot->tts_values[attnum - 1];
931  bool isnull = slot->tts_isnull[attnum - 1];
932  char *string;
933 
934  if (need_delim)
935  CopySendChar(cstate, cstate->opts.delim[0]);
936  need_delim = true;
937 
938  if (isnull)
939  CopySendString(cstate, cstate->opts.null_print_client);
940  else
941  {
942  string = OutputFunctionCall(&out_functions[attnum - 1],
943  value);
944  if (cstate->opts.csv_mode)
945  CopyAttributeOutCSV(cstate, string,
946  cstate->opts.force_quote_flags[attnum - 1]);
947  else
948  CopyAttributeOutText(cstate, string);
949  }
950  }
951  }
952  else
953  {
954  foreach_int(attnum, cstate->attnumlist)
955  {
956  Datum value = slot->tts_values[attnum - 1];
957  bool isnull = slot->tts_isnull[attnum - 1];
958  bytea *outputbytes;
959 
960  if (isnull)
961  CopySendInt32(cstate, -1);
962  else
963  {
964  outputbytes = SendFunctionCall(&out_functions[attnum - 1],
965  value);
966  CopySendInt32(cstate, VARSIZE(outputbytes) - VARHDRSZ);
967  CopySendData(cstate, VARDATA(outputbytes),
968  VARSIZE(outputbytes) - VARHDRSZ);
969  }
970  }
971  }
972 
973  CopySendEndOfRow(cstate);
974 
975  MemoryContextSwitchTo(oldcontext);
976 }
#define VARHDRSZ
Definition: c.h:683
static void CopySendInt32(CopyToState cstate, int32 val)
Definition: copyto.c:265
static void CopyAttributeOutCSV(CopyToState cstate, const char *string, bool use_quote)
Definition: copyto.c:1141
static void CopyAttributeOutText(CopyToState cstate, const char *string)
Definition: copyto.c:988
static void CopySendInt16(CopyToState cstate, int16 val)
Definition: copyto.c:277
static void CopySendData(CopyToState cstate, const void *databuf, int datasize)
Definition: copyto.c:169
static void CopySendEndOfRow(CopyToState cstate)
Definition: copyto.c:187
bytea * SendFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1744
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1683
static struct @157 value
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
#define foreach_int(var, lst)
Definition: pg_list.h:470
uintptr_t Datum
Definition: postgres.h:64
bool binary
Definition: copy.h:64
char * null_print_client
Definition: copy.h:70
bool csv_mode
Definition: copy.h:66
FmgrInfo * out_functions
Definition: copyto.c:92
MemoryContext rowcontext
Definition: copyto.c:93
Definition: fmgr.h:57
bool * tts_isnull
Definition: tuptable.h:127
Datum * tts_values
Definition: tuptable.h:125
Definition: c.h:678
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:368
#define VARDATA(PTR)
Definition: varatt.h:278
#define VARSIZE(PTR)
Definition: varatt.h:279

References attnum, CopyToStateData::attnumlist, CopyFormatOptions::binary, CopyAttributeOutCSV(), CopyAttributeOutText(), CopySendChar(), CopySendData(), CopySendEndOfRow(), CopySendInt16(), CopySendInt32(), CopySendString(), CopyFormatOptions::csv_mode, CopyFormatOptions::delim, CopyFormatOptions::force_quote_flags, foreach_int, list_length(), MemoryContextReset(), MemoryContextSwitchTo(), CopyFormatOptions::null_print_client, CopyToStateData::opts, CopyToStateData::out_functions, OutputFunctionCall(), CopyToStateData::rowcontext, SendFunctionCall(), slot_getallattrs(), TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, value, VARDATA, VARHDRSZ, and VARSIZE.

Referenced by copy_dest_receive(), and DoCopyTo().

◆ CopySendChar()

static void CopySendChar ( CopyToState  cstate,
char  c 
)
static

Definition at line 181 of file copyto.c.

182 {
184 }
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:204
StringInfo fe_msgbuf
Definition: copyto.c:70

References appendStringInfoCharMacro, and CopyToStateData::fe_msgbuf.

Referenced by CopyAttributeOutCSV(), CopyAttributeOutText(), CopyOneRowTo(), CopySendEndOfRow(), and DoCopyTo().

◆ CopySendData()

static void CopySendData ( CopyToState  cstate,
const void *  databuf,
int  datasize 
)
static

Definition at line 169 of file copyto.c.

170 {
171  appendBinaryStringInfo(cstate->fe_msgbuf, databuf, datasize);
172 }
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:233

References appendBinaryStringInfo(), and CopyToStateData::fe_msgbuf.

Referenced by CopyOneRowTo(), CopySendInt16(), CopySendInt32(), and DoCopyTo().

◆ CopySendEndOfRow()

static void CopySendEndOfRow ( CopyToState  cstate)
static

Definition at line 187 of file copyto.c.

188 {
189  StringInfo fe_msgbuf = cstate->fe_msgbuf;
190 
191  switch (cstate->copy_dest)
192  {
193  case COPY_FILE:
194  if (!cstate->opts.binary)
195  {
196  /* Default line termination depends on platform */
197 #ifndef WIN32
198  CopySendChar(cstate, '\n');
199 #else
200  CopySendString(cstate, "\r\n");
201 #endif
202  }
203 
204  if (fwrite(fe_msgbuf->data, fe_msgbuf->len, 1,
205  cstate->copy_file) != 1 ||
206  ferror(cstate->copy_file))
207  {
208  if (cstate->is_program)
209  {
210  if (errno == EPIPE)
211  {
212  /*
213  * The pipe will be closed automatically on error at
214  * the end of transaction, but we might get a better
215  * error message from the subprocess' exit code than
216  * just "Broken Pipe"
217  */
218  ClosePipeToProgram(cstate);
219 
220  /*
221  * If ClosePipeToProgram() didn't throw an error, the
222  * program terminated normally, but closed the pipe
223  * first. Restore errno, and throw an error.
224  */
225  errno = EPIPE;
226  }
227  ereport(ERROR,
229  errmsg("could not write to COPY program: %m")));
230  }
231  else
232  ereport(ERROR,
234  errmsg("could not write to COPY file: %m")));
235  }
236  break;
237  case COPY_FRONTEND:
238  /* The FE/BE protocol uses \n as newline for all platforms */
239  if (!cstate->opts.binary)
240  CopySendChar(cstate, '\n');
241 
242  /* Dump the accumulated row as one CopyData message */
243  (void) pq_putmessage(PqMsg_CopyData, fe_msgbuf->data, fe_msgbuf->len);
244  break;
245  case COPY_CALLBACK:
246  cstate->data_dest_cb(fe_msgbuf->data, fe_msgbuf->len);
247  break;
248  }
249 
250  /* Update the progress */
251  cstate->bytes_processed += fe_msgbuf->len;
253 
254  resetStringInfo(fe_msgbuf);
255 }
static void ClosePipeToProgram(CopyToState cstate)
Definition: copyto.c:289
#define pq_putmessage(msgtype, s, len)
Definition: libpq.h:49
#define PROGRESS_COPY_BYTES_PROCESSED
Definition: progress.h:140
#define PqMsg_CopyData
Definition: protocol.h:65
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:78

References CopyFormatOptions::binary, CopyToStateData::bytes_processed, ClosePipeToProgram(), COPY_CALLBACK, CopyToStateData::copy_dest, COPY_FILE, CopyToStateData::copy_file, COPY_FRONTEND, CopySendChar(), CopySendString(), StringInfoData::data, CopyToStateData::data_dest_cb, ereport, errcode_for_file_access(), errmsg(), ERROR, CopyToStateData::fe_msgbuf, CopyToStateData::is_program, StringInfoData::len, CopyToStateData::opts, pgstat_progress_update_param(), pq_putmessage, PqMsg_CopyData, PROGRESS_COPY_BYTES_PROCESSED, and resetStringInfo().

Referenced by CopyOneRowTo(), and DoCopyTo().

◆ CopySendInt16()

static void CopySendInt16 ( CopyToState  cstate,
int16  val 
)
inlinestatic

Definition at line 277 of file copyto.c.

278 {
279  uint16 buf;
280 
281  buf = pg_hton16((uint16) val);
282  CopySendData(cstate, &buf, sizeof(buf));
283 }
unsigned short uint16
Definition: c.h:505
long val
Definition: informix.c:689
#define pg_hton16(x)
Definition: pg_bswap.h:120
static char * buf
Definition: pg_test_fsync.c:73

References buf, CopySendData(), pg_hton16, and val.

Referenced by CopyOneRowTo(), and DoCopyTo().

◆ CopySendInt32()

static void CopySendInt32 ( CopyToState  cstate,
int32  val 
)
inlinestatic

Definition at line 265 of file copyto.c.

266 {
267  uint32 buf;
268 
269  buf = pg_hton32((uint32) val);
270  CopySendData(cstate, &buf, sizeof(buf));
271 }
unsigned int uint32
Definition: c.h:506
#define pg_hton32(x)
Definition: pg_bswap.h:121

References buf, CopySendData(), pg_hton32, and val.

Referenced by CopyOneRowTo(), and DoCopyTo().

◆ CopySendString()

static void CopySendString ( CopyToState  cstate,
const char *  str 
)
static

Definition at line 175 of file copyto.c.

176 {
177  appendBinaryStringInfo(cstate->fe_msgbuf, str, strlen(str));
178 }
const char * str

References appendBinaryStringInfo(), CopyToStateData::fe_msgbuf, and str.

Referenced by CopyAttributeOutCSV(), CopyOneRowTo(), and CopySendEndOfRow().

◆ CreateCopyDestReceiver()

DestReceiver* CreateCopyDestReceiver ( void  )

Definition at line 1276 of file copyto.c.

1277 {
1278  DR_copy *self = (DR_copy *) palloc(sizeof(DR_copy));
1279 
1280  self->pub.receiveSlot = copy_dest_receive;
1281  self->pub.rStartup = copy_dest_startup;
1282  self->pub.rShutdown = copy_dest_shutdown;
1283  self->pub.rDestroy = copy_dest_destroy;
1284  self->pub.mydest = DestCopyOut;
1285 
1286  self->cstate = NULL; /* will be set later */
1287  self->processed = 0;
1288 
1289  return (DestReceiver *) self;
1290 }
static bool copy_dest_receive(TupleTableSlot *slot, DestReceiver *self)
Definition: copyto.c:1239
static void copy_dest_destroy(DestReceiver *self)
Definition: copyto.c:1267
static void copy_dest_shutdown(DestReceiver *self)
Definition: copyto.c:1258
static void copy_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: copyto.c:1230
void * palloc(Size size)
Definition: mcxt.c:1317

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

Referenced by CreateDestReceiver().

◆ DoCopyTo()

uint64 DoCopyTo ( CopyToState  cstate)

Definition at line 747 of file copyto.c.

748 {
749  bool pipe = (cstate->filename == NULL && cstate->data_dest_cb == NULL);
750  bool fe_copy = (pipe && whereToSendOutput == DestRemote);
751  TupleDesc tupDesc;
752  int num_phys_attrs;
753  ListCell *cur;
754  uint64 processed;
755 
756  if (fe_copy)
757  SendCopyBegin(cstate);
758 
759  if (cstate->rel)
760  tupDesc = RelationGetDescr(cstate->rel);
761  else
762  tupDesc = cstate->queryDesc->tupDesc;
763  num_phys_attrs = tupDesc->natts;
764  cstate->opts.null_print_client = cstate->opts.null_print; /* default */
765 
766  /* We use fe_msgbuf as a per-row buffer regardless of copy_dest */
767  cstate->fe_msgbuf = makeStringInfo();
768 
769  /* Get info about the columns we need to process. */
770  cstate->out_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
771  foreach(cur, cstate->attnumlist)
772  {
773  int attnum = lfirst_int(cur);
774  Oid out_func_oid;
775  bool isvarlena;
776  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
777 
778  if (cstate->opts.binary)
779  getTypeBinaryOutputInfo(attr->atttypid,
780  &out_func_oid,
781  &isvarlena);
782  else
783  getTypeOutputInfo(attr->atttypid,
784  &out_func_oid,
785  &isvarlena);
786  fmgr_info(out_func_oid, &cstate->out_functions[attnum - 1]);
787  }
788 
789  /*
790  * Create a temporary memory context that we can reset once per row to
791  * recover palloc'd memory. This avoids any problems with leaks inside
792  * datatype output routines, and should be faster than retail pfree's
793  * anyway. (We don't need a whole econtext as CopyFrom does.)
794  */
796  "COPY TO",
798 
799  if (cstate->opts.binary)
800  {
801  /* Generate header for a binary copy */
802  int32 tmp;
803 
804  /* Signature */
805  CopySendData(cstate, BinarySignature, 11);
806  /* Flags field */
807  tmp = 0;
808  CopySendInt32(cstate, tmp);
809  /* No header extension */
810  tmp = 0;
811  CopySendInt32(cstate, tmp);
812  }
813  else
814  {
815  /*
816  * For non-binary copy, we need to convert null_print to file
817  * encoding, because it will be sent directly with CopySendString.
818  */
819  if (cstate->need_transcoding)
821  cstate->opts.null_print_len,
822  cstate->file_encoding);
823 
824  /* if a header has been requested send the line */
825  if (cstate->opts.header_line)
826  {
827  bool hdr_delim = false;
828 
829  foreach(cur, cstate->attnumlist)
830  {
831  int attnum = lfirst_int(cur);
832  char *colname;
833 
834  if (hdr_delim)
835  CopySendChar(cstate, cstate->opts.delim[0]);
836  hdr_delim = true;
837 
838  colname = NameStr(TupleDescAttr(tupDesc, attnum - 1)->attname);
839 
840  if (cstate->opts.csv_mode)
841  CopyAttributeOutCSV(cstate, colname, false);
842  else
843  CopyAttributeOutText(cstate, colname);
844  }
845 
846  CopySendEndOfRow(cstate);
847  }
848  }
849 
850  if (cstate->rel)
851  {
852  TupleTableSlot *slot;
853  TableScanDesc scandesc;
854 
855  scandesc = table_beginscan(cstate->rel, GetActiveSnapshot(), 0, NULL);
856  slot = table_slot_create(cstate->rel, NULL);
857 
858  processed = 0;
859  while (table_scan_getnextslot(scandesc, ForwardScanDirection, slot))
860  {
862 
863  /* Deconstruct the tuple ... */
864  slot_getallattrs(slot);
865 
866  /* Format and send the data */
867  CopyOneRowTo(cstate, slot);
868 
869  /*
870  * Increment the number of processed tuples, and report the
871  * progress.
872  */
874  ++processed);
875  }
876 
878  table_endscan(scandesc);
879  }
880  else
881  {
882  /* run the plan --- the dest receiver will send tuples */
883  ExecutorRun(cstate->queryDesc, ForwardScanDirection, 0, true);
884  processed = ((DR_copy *) cstate->queryDesc->dest)->processed;
885  }
886 
887  if (cstate->opts.binary)
888  {
889  /* Generate trailer for a binary copy */
890  CopySendInt16(cstate, -1);
891  /* Need to flush out the trailer */
892  CopySendEndOfRow(cstate);
893  }
894 
896 
897  if (fe_copy)
898  SendCopyEnd(cstate);
899 
900  return processed;
901 }
signed int int32
Definition: c.h:496
static void SendCopyBegin(CopyToState cstate)
Definition: copyto.c:133
static void SendCopyEnd(CopyToState cstate)
Definition: copyto.c:150
static const char BinarySignature[11]
Definition: copyto.c:106
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:295
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1341
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
void getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
Definition: lsyscache.c:2973
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2907
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
NameData attname
Definition: pg_attribute.h:41
unsigned int Oid
Definition: postgres_ext.h:31
@ ForwardScanDirection
Definition: sdir.h:28
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
int null_print_len
Definition: copy.h:69
CopyHeaderChoice header_line
Definition: copy.h:67
DestReceiver * dest
Definition: execdesc.h:41
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition: tableam.c:91
static TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key)
Definition: tableam.h:908
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:1019
static bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
Definition: tableam.h:1055

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

Referenced by DoCopy(), and test_copy_to_callback().

◆ EndCopy()

static void EndCopy ( CopyToState  cstate)
static

Definition at line 314 of file copyto.c.

315 {
316  if (cstate->is_program)
317  {
318  ClosePipeToProgram(cstate);
319  }
320  else
321  {
322  if (cstate->filename != NULL && FreeFile(cstate->copy_file))
323  ereport(ERROR,
325  errmsg("could not close file \"%s\": %m",
326  cstate->filename)));
327  }
328 
330 
332  pfree(cstate);
333 }
void pgstat_progress_end_command(void)
int FreeFile(FILE *file)
Definition: fd.c:2804

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

Referenced by EndCopyTo().

◆ EndCopyTo()

void EndCopyTo ( CopyToState  cstate)

Definition at line 726 of file copyto.c.

727 {
728  if (cstate->queryDesc != NULL)
729  {
730  /* Close down the query and free resources. */
731  ExecutorFinish(cstate->queryDesc);
732  ExecutorEnd(cstate->queryDesc);
733  FreeQueryDesc(cstate->queryDesc);
735  }
736 
737  /* Clean up storage */
738  EndCopy(cstate);
739 }
static void EndCopy(CopyToState cstate)
Definition: copyto.c:314
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:465
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:405
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:105
void PopActiveSnapshot(void)
Definition: snapmgr.c:743

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

Referenced by DoCopy(), and test_copy_to_callback().

◆ SendCopyBegin()

static void SendCopyBegin ( CopyToState  cstate)
static

Definition at line 133 of file copyto.c.

134 {
136  int natts = list_length(cstate->attnumlist);
137  int16 format = (cstate->opts.binary ? 1 : 0);
138  int i;
139 
141  pq_sendbyte(&buf, format); /* overall format */
142  pq_sendint16(&buf, natts);
143  for (i = 0; i < natts; i++)
144  pq_sendint16(&buf, format); /* per-column formats */
145  pq_endmessage(&buf);
146  cstate->copy_dest = COPY_FRONTEND;
147 }
signed short int16
Definition: c.h:495
int i
Definition: isn.c:73
static char format
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:296
void pq_beginmessage(StringInfo buf, char msgtype)
Definition: pqformat.c:88
static void pq_sendbyte(StringInfo buf, uint8 byt)
Definition: pqformat.h:160
static void pq_sendint16(StringInfo buf, uint16 i)
Definition: pqformat.h:136
#define PqMsg_CopyOutResponse
Definition: protocol.h:46

References CopyToStateData::attnumlist, CopyFormatOptions::binary, buf, CopyToStateData::copy_dest, COPY_FRONTEND, format, i, list_length(), CopyToStateData::opts, pq_beginmessage(), pq_endmessage(), pq_sendbyte(), pq_sendint16(), and PqMsg_CopyOutResponse.

Referenced by DoCopyTo().

◆ SendCopyEnd()

static void SendCopyEnd ( CopyToState  cstate)
static

Definition at line 150 of file copyto.c.

151 {
152  /* Shouldn't have any unsent data */
153  Assert(cstate->fe_msgbuf->len == 0);
154  /* Send Copy Done message */
156 }
void pq_putemptymessage(char msgtype)
Definition: pqformat.c:388
#define PqMsg_CopyDone
Definition: protocol.h:64

References Assert, CopyToStateData::fe_msgbuf, StringInfoData::len, pq_putemptymessage(), and PqMsg_CopyDone.

Referenced by DoCopyTo().

Variable Documentation

◆ BinarySignature

const char BinarySignature[11] = "PGCOPY\n\377\r\n\0"
static

Definition at line 106 of file copyto.c.

Referenced by DoCopyTo().