Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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/copyapi.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 CopyToTextLikeStart (CopyToState cstate, TupleDesc tupDesc)
 
static void CopyToTextLikeOutFunc (CopyToState cstate, Oid atttypid, FmgrInfo *finfo)
 
static void CopyToTextOneRow (CopyToState cstate, TupleTableSlot *slot)
 
static void CopyToCSVOneRow (CopyToState cstate, TupleTableSlot *slot)
 
static void CopyToTextLikeOneRow (CopyToState cstate, TupleTableSlot *slot, bool is_csv)
 
static void CopyToTextLikeEnd (CopyToState cstate)
 
static void CopyToBinaryStart (CopyToState cstate, TupleDesc tupDesc)
 
static void CopyToBinaryOutFunc (CopyToState cstate, Oid atttypid, FmgrInfo *finfo)
 
static void CopyToBinaryOneRow (CopyToState cstate, TupleTableSlot *slot)
 
static void CopyToBinaryEnd (CopyToState cstate)
 
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 CopySendTextLikeEndOfRow (CopyToState cstate)
 
static void CopySendInt32 (CopyToState cstate, int32 val)
 
static void CopySendInt16 (CopyToState cstate, int16 val)
 
static const CopyToRoutineCopyToGetRoutine (const CopyFormatOptions *opts)
 
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"
 
static const CopyToRoutine CopyToRoutineText
 
static const CopyToRoutine CopyToRoutineCSV
 
static const CopyToRoutine CopyToRoutineBinary
 

Macro Definition Documentation

◆ DUMPSOFAR

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

Definition at line 1140 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 623 of file copyto.c.

632{
633 CopyToState cstate;
634 bool pipe = (filename == NULL && data_dest_cb == NULL);
635 TupleDesc tupDesc;
636 int num_phys_attrs;
637 MemoryContext oldcontext;
638 const int progress_cols[] = {
641 };
642 int64 progress_vals[] = {
644 0
645 };
646
647 if (rel != NULL && rel->rd_rel->relkind != RELKIND_RELATION)
648 {
649 if (rel->rd_rel->relkind == RELKIND_VIEW)
651 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
652 errmsg("cannot copy from view \"%s\"",
654 errhint("Try the COPY (SELECT ...) TO variant.")));
655 else if (rel->rd_rel->relkind == RELKIND_MATVIEW)
656 {
657 if (!RelationIsPopulated(rel))
659 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
660 errmsg("cannot copy from unpopulated materialized view \"%s\"",
662 errhint("Use the REFRESH MATERIALIZED VIEW command."));
663 }
664 else if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
666 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
667 errmsg("cannot copy from foreign table \"%s\"",
669 errhint("Try the COPY (SELECT ...) TO variant.")));
670 else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
672 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
673 errmsg("cannot copy from sequence \"%s\"",
675 else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
677 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
678 errmsg("cannot copy from partitioned table \"%s\"",
680 errhint("Try the COPY (SELECT ...) TO variant.")));
681 else
683 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
684 errmsg("cannot copy from non-table relation \"%s\"",
686 }
687
688
689 /* Allocate workspace and zero all fields */
690 cstate = (CopyToStateData *) palloc0(sizeof(CopyToStateData));
691
692 /*
693 * We allocate everything used by a cstate in a new memory context. This
694 * avoids memory leaks during repeated use of COPY in a query.
695 */
697 "COPY",
699
700 oldcontext = MemoryContextSwitchTo(cstate->copycontext);
701
702 /* Extract options from the statement node tree */
703 ProcessCopyOptions(pstate, &cstate->opts, false /* is_from */ , options);
704
705 /* Set format routine */
706 cstate->routine = CopyToGetRoutine(&cstate->opts);
707
708 /* Process the source/target relation or query */
709 if (rel)
710 {
711 Assert(!raw_query);
712
713 cstate->rel = rel;
714
715 tupDesc = RelationGetDescr(cstate->rel);
716 }
717 else
718 {
719 List *rewritten;
720 Query *query;
723
724 cstate->rel = NULL;
725
726 /*
727 * Run parse analysis and rewrite. Note this also acquires sufficient
728 * locks on the source table(s).
729 */
730 rewritten = pg_analyze_and_rewrite_fixedparams(raw_query,
731 pstate->p_sourcetext, NULL, 0,
732 NULL);
733
734 /* check that we got back something we can work with */
735 if (rewritten == NIL)
736 {
738 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
739 errmsg("DO INSTEAD NOTHING rules are not supported for COPY")));
740 }
741 else if (list_length(rewritten) > 1)
742 {
743 ListCell *lc;
744
745 /* examine queries to determine which error message to issue */
746 foreach(lc, rewritten)
747 {
748 Query *q = lfirst_node(Query, lc);
749
750 if (q->querySource == QSRC_QUAL_INSTEAD_RULE)
752 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
753 errmsg("conditional DO INSTEAD rules are not supported for COPY")));
754 if (q->querySource == QSRC_NON_INSTEAD_RULE)
756 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
757 errmsg("DO ALSO rules are not supported for COPY")));
758 }
759
761 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
762 errmsg("multi-statement DO INSTEAD rules are not supported for COPY")));
763 }
764
765 query = linitial_node(Query, rewritten);
766
767 /* The grammar allows SELECT INTO, but we don't support that */
768 if (query->utilityStmt != NULL &&
771 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
772 errmsg("COPY (SELECT INTO) is not supported")));
773
774 /* The only other utility command we could see is NOTIFY */
775 if (query->utilityStmt != NULL)
777 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
778 errmsg("COPY query must not be a utility command")));
779
780 /*
781 * Similarly the grammar doesn't enforce the presence of a RETURNING
782 * clause, but this is required here.
783 */
784 if (query->commandType != CMD_SELECT &&
785 query->returningList == NIL)
786 {
787 Assert(query->commandType == CMD_INSERT ||
788 query->commandType == CMD_UPDATE ||
789 query->commandType == CMD_DELETE ||
790 query->commandType == CMD_MERGE);
791
793 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
794 errmsg("COPY query must have a RETURNING clause")));
795 }
796
797 /* plan the query */
798 plan = pg_plan_query(query, pstate->p_sourcetext,
800
801 /*
802 * With row-level security and a user using "COPY relation TO", we
803 * have to convert the "COPY relation TO" to a query-based COPY (eg:
804 * "COPY (SELECT * FROM ONLY relation) TO"), to allow the rewriter to
805 * add in any RLS clauses.
806 *
807 * When this happens, we are passed in the relid of the originally
808 * found relation (which we have locked). As the planner will look up
809 * the relation again, we double-check here to make sure it found the
810 * same one that we have locked.
811 */
812 if (queryRelId != InvalidOid)
813 {
814 /*
815 * Note that with RLS involved there may be multiple relations,
816 * and while the one we need is almost certainly first, we don't
817 * make any guarantees of that in the planner, so check the whole
818 * list and make sure we find the original relation.
819 */
820 if (!list_member_oid(plan->relationOids, queryRelId))
822 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
823 errmsg("relation referenced by COPY statement has changed")));
824 }
825
826 /*
827 * Use a snapshot with an updated command ID to ensure this query sees
828 * results of any previously executed queries.
829 */
832
833 /* Create dest receiver for COPY OUT */
835 ((DR_copy *) dest)->cstate = cstate;
836
837 /* Create a QueryDesc requesting no output */
838 cstate->queryDesc = CreateQueryDesc(plan, pstate->p_sourcetext,
841 dest, NULL, NULL, 0);
842
843 /*
844 * Call ExecutorStart to prepare the plan for execution.
845 *
846 * ExecutorStart computes a result tupdesc for us
847 */
848 ExecutorStart(cstate->queryDesc, 0);
849
850 tupDesc = cstate->queryDesc->tupDesc;
851 }
852
853 /* Generate or convert list of attributes to process */
854 cstate->attnumlist = CopyGetAttnums(tupDesc, cstate->rel, attnamelist);
855
856 num_phys_attrs = tupDesc->natts;
857
858 /* Convert FORCE_QUOTE name list to per-column flags, check validity */
859 cstate->opts.force_quote_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
860 if (cstate->opts.force_quote_all)
861 {
862 MemSet(cstate->opts.force_quote_flags, true, num_phys_attrs * sizeof(bool));
863 }
864 else if (cstate->opts.force_quote)
865 {
866 List *attnums;
867 ListCell *cur;
868
869 attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.force_quote);
870
871 foreach(cur, attnums)
872 {
873 int attnum = lfirst_int(cur);
874 Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
875
876 if (!list_member_int(cstate->attnumlist, attnum))
878 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
879 /*- translator: %s is the name of a COPY option, e.g. FORCE_NOT_NULL */
880 errmsg("%s column \"%s\" not referenced by COPY",
881 "FORCE_QUOTE", NameStr(attr->attname))));
882 cstate->opts.force_quote_flags[attnum - 1] = true;
883 }
884 }
885
886 /* Use client encoding when ENCODING option is not specified. */
887 if (cstate->opts.file_encoding < 0)
889 else
890 cstate->file_encoding = cstate->opts.file_encoding;
891
892 /*
893 * Set up encoding conversion info if the file and server encodings differ
894 * (see also pg_server_to_any).
895 */
896 if (cstate->file_encoding == GetDatabaseEncoding() ||
897 cstate->file_encoding == PG_SQL_ASCII)
898 cstate->need_transcoding = false;
899 else
900 cstate->need_transcoding = true;
901
902 /* See Multibyte encoding comment above */
904
905 cstate->copy_dest = COPY_FILE; /* default */
906
907 if (data_dest_cb)
908 {
909 progress_vals[1] = PROGRESS_COPY_TYPE_CALLBACK;
910 cstate->copy_dest = COPY_CALLBACK;
911 cstate->data_dest_cb = data_dest_cb;
912 }
913 else if (pipe)
914 {
915 progress_vals[1] = PROGRESS_COPY_TYPE_PIPE;
916
917 Assert(!is_program); /* the grammar does not allow this */
919 cstate->copy_file = stdout;
920 }
921 else
922 {
923 cstate->filename = pstrdup(filename);
924 cstate->is_program = is_program;
925
926 if (is_program)
927 {
928 progress_vals[1] = PROGRESS_COPY_TYPE_PROGRAM;
929 cstate->copy_file = OpenPipeStream(cstate->filename, PG_BINARY_W);
930 if (cstate->copy_file == NULL)
933 errmsg("could not execute command \"%s\": %m",
934 cstate->filename)));
935 }
936 else
937 {
938 mode_t oumask; /* Pre-existing umask value */
939 struct stat st;
940
941 progress_vals[1] = PROGRESS_COPY_TYPE_FILE;
942
943 /*
944 * Prevent write to relative path ... too easy to shoot oneself in
945 * the foot by overwriting a database file ...
946 */
949 (errcode(ERRCODE_INVALID_NAME),
950 errmsg("relative path not allowed for COPY to file")));
951
952 oumask = umask(S_IWGRP | S_IWOTH);
953 PG_TRY();
954 {
955 cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_W);
956 }
957 PG_FINALLY();
958 {
959 umask(oumask);
960 }
961 PG_END_TRY();
962 if (cstate->copy_file == NULL)
963 {
964 /* copy errno because ereport subfunctions might change it */
965 int save_errno = errno;
966
969 errmsg("could not open file \"%s\" for writing: %m",
970 cstate->filename),
971 (save_errno == ENOENT || save_errno == EACCES) ?
972 errhint("COPY TO instructs the PostgreSQL server process to write a file. "
973 "You may want a client-side facility such as psql's \\copy.") : 0));
974 }
975
976 if (fstat(fileno(cstate->copy_file), &st))
979 errmsg("could not stat file \"%s\": %m",
980 cstate->filename)));
981
982 if (S_ISDIR(st.st_mode))
984 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
985 errmsg("\"%s\" is a directory", cstate->filename)));
986 }
987 }
988
989 /* initialize progress */
991 cstate->rel ? RelationGetRelid(cstate->rel) : InvalidOid);
992 pgstat_progress_update_multi_param(2, progress_cols, progress_vals);
993
994 cstate->bytes_processed = 0;
995
996 MemoryContextSwitchTo(oldcontext);
997
998 return cstate;
999}
List * CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
Definition: copy.c:945
void ProcessCopyOptions(ParseState *pstate, CopyFormatOptions *opts_out, bool is_from, List *options)
Definition: copy.c:496
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:717
int64_t int64
Definition: c.h:499
#define PG_BINARY_W
Definition: c.h:1247
#define MemSet(start, val, len)
Definition: c.h:991
static const CopyToRoutine * CopyToGetRoutine(const CopyFormatOptions *opts)
Definition: copyto.c:177
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:113
@ DestRemote
Definition: dest.h:89
@ DestCopyOut
Definition: dest.h:95
struct cursor * cur
Definition: ecpg.c:29
int errcode_for_file_access(void)
Definition: elog.c:877
int errhint(const char *fmt,...)
Definition: elog.c:1318
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#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:123
FILE * OpenPipeStream(const char *command, const char *mode)
Definition: fd.c:2747
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2644
Assert(PointerIsAligned(start, uint64))
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:1262
int pg_get_client_encoding(void)
Definition: mbutils.c:337
char * pstrdup(const char *in)
Definition: mcxt.c:1703
void * palloc0(Size size)
Definition: mcxt.c:1351
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:164
@ CMD_MERGE
Definition: nodes.h:275
@ CMD_INSERT
Definition: nodes.h:273
@ CMD_DELETE
Definition: nodes.h:274
@ CMD_UPDATE
Definition: nodes.h:272
@ CMD_SELECT
Definition: nodes.h:271
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
@ QSRC_NON_INSTEAD_RULE
Definition: parsenodes.h:40
@ QSRC_QUAL_INSTEAD_RULE
Definition: parsenodes.h:39
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:3385
int16 attnum
Definition: pg_attribute.h:74
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:202
static char * filename
Definition: pg_dumpall.c:124
#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:161
@ 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:104
PlannedStmt * pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, ParamListInfo boundParams)
Definition: postgres.c:882
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:665
#define InvalidOid
Definition: postgres_ext.h:35
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
Definition: pquery.c:68
#define PROGRESS_COPY_COMMAND
Definition: progress.h:146
#define PROGRESS_COPY_TYPE_FILE
Definition: progress.h:155
#define PROGRESS_COPY_COMMAND_TO
Definition: progress.h:152
#define PROGRESS_COPY_TYPE
Definition: progress.h:147
#define PROGRESS_COPY_TYPE_PROGRAM
Definition: progress.h:156
#define PROGRESS_COPY_TYPE_CALLBACK
Definition: progress.h:158
#define PROGRESS_COPY_TYPE_PIPE
Definition: progress.h:157
#define RelationGetRelid(relation)
Definition: rel.h:516
#define RelationGetDescr(relation)
Definition: rel.h:542
#define RelationGetRelationName(relation)
Definition: rel.h:550
#define RelationIsPopulated(relation)
Definition: rel.h:688
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:731
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:719
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:787
#define InvalidSnapshot
Definition: snapshot.h:119
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:93
Relation rel
Definition: copyto.c:80
const CopyToRoutine * routine
Definition: copyto.c:68
copy_data_dest_cb data_dest_cb
Definition: copyto.c:85
bool encoding_embeds_ascii
Definition: copyto.c:77
CopyDest copy_dest
Definition: copyto.c:71
bool need_transcoding
Definition: copyto.c:76
bool is_program
Definition: copyto.c:84
FILE * copy_file
Definition: copyto.c:72
int file_encoding
Definition: copyto.c:75
CopyFormatOptions opts
Definition: copyto.c:87
uint64 bytes_processed
Definition: copyto.c:97
char * filename
Definition: copyto.c:83
List * attnumlist
Definition: copyto.c:82
QueryDesc * queryDesc
Definition: copyto.c:81
Definition: pg_list.h:54
const char * p_sourcetext
Definition: parse_node.h:209
TupleDesc tupDesc
Definition: execdesc.h:47
List * returningList
Definition: parsenodes.h:209
CmdType commandType
Definition: parsenodes.h:121
Node * utilityStmt
Definition: parsenodes.h:136
Form_pg_class rd_rel
Definition: rel.h:111
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:160
#define S_IWOTH
Definition: win32_port.h:306
#define S_ISDIR(m)
Definition: win32_port.h:315
#define fstat
Definition: win32_port.h:273
#define S_IWGRP
Definition: win32_port.h:294

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(), CopyToGetRoutine(), 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, RelationIsPopulated, Query::returningList, CopyToStateData::routine, 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 562 of file copyto.c.

563{
564 int pclose_rc;
565
566 Assert(cstate->is_program);
567
568 pclose_rc = ClosePipeStream(cstate->copy_file);
569 if (pclose_rc == -1)
572 errmsg("could not close pipe to external command: %m")));
573 else if (pclose_rc != 0)
574 {
576 (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
577 errmsg("program \"%s\" failed",
578 cstate->filename),
579 errdetail_internal("%s", wait_result_to_str(pclose_rc))));
580 }
581}
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1231
int ClosePipeStream(FILE *file)
Definition: fd.c:3055
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 1426 of file copyto.c.

1427{
1428 pfree(self);
1429}
void pfree(void *pointer)
Definition: mcxt.c:1528

References pfree().

Referenced by CreateCopyDestReceiver().

◆ copy_dest_receive()

static bool copy_dest_receive ( TupleTableSlot slot,
DestReceiver self 
)
static

Definition at line 1398 of file copyto.c.

1399{
1400 DR_copy *myState = (DR_copy *) self;
1401 CopyToState cstate = myState->cstate;
1402
1403 /* Send the data */
1404 CopyOneRowTo(cstate, slot);
1405
1406 /* Increment the number of processed tuples, and report the progress */
1408 ++myState->processed);
1409
1410 return true;
1411}
void pgstat_progress_update_param(int index, int64 val)
static void CopyOneRowTo(CopyToState cstate, TupleTableSlot *slot)
Definition: copyto.c:1122
#define PROGRESS_COPY_TUPLES_PROCESSED
Definition: progress.h:144
CopyToState cstate
Definition: copyto.c:104
uint64 processed
Definition: copyto.c:105

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 1417 of file copyto.c.

1418{
1419 /* no-op */
1420}

Referenced by CreateCopyDestReceiver().

◆ copy_dest_startup()

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

Definition at line 1389 of file copyto.c.

1390{
1391 /* no-op */
1392}

Referenced by CreateCopyDestReceiver().

◆ CopyAttributeOutCSV()

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

Definition at line 1300 of file copyto.c.

1302{
1303 const char *ptr;
1304 const char *start;
1305 char c;
1306 char delimc = cstate->opts.delim[0];
1307 char quotec = cstate->opts.quote[0];
1308 char escapec = cstate->opts.escape[0];
1309 bool single_attr = (list_length(cstate->attnumlist) == 1);
1310
1311 /* force quoting if it matches null_print (before conversion!) */
1312 if (!use_quote && strcmp(string, cstate->opts.null_print) == 0)
1313 use_quote = true;
1314
1315 if (cstate->need_transcoding)
1316 ptr = pg_server_to_any(string, strlen(string), cstate->file_encoding);
1317 else
1318 ptr = string;
1319
1320 /*
1321 * Make a preliminary pass to discover if it needs quoting
1322 */
1323 if (!use_quote)
1324 {
1325 /*
1326 * Quote '\.' if it appears alone on a line, so that it will not be
1327 * interpreted as an end-of-data marker. (PG 18 and up will not
1328 * interpret '\.' in CSV that way, except in embedded-in-SQL data; but
1329 * we want the data to be loadable by older versions too. Also, this
1330 * avoids breaking clients that are still using PQgetline().)
1331 */
1332 if (single_attr && strcmp(ptr, "\\.") == 0)
1333 use_quote = true;
1334 else
1335 {
1336 const char *tptr = ptr;
1337
1338 while ((c = *tptr) != '\0')
1339 {
1340 if (c == delimc || c == quotec || c == '\n' || c == '\r')
1341 {
1342 use_quote = true;
1343 break;
1344 }
1345 if (IS_HIGHBIT_SET(c) && cstate->encoding_embeds_ascii)
1346 tptr += pg_encoding_mblen(cstate->file_encoding, tptr);
1347 else
1348 tptr++;
1349 }
1350 }
1351 }
1352
1353 if (use_quote)
1354 {
1355 CopySendChar(cstate, quotec);
1356
1357 /*
1358 * We adopt the same optimization strategy as in CopyAttributeOutText
1359 */
1360 start = ptr;
1361 while ((c = *ptr) != '\0')
1362 {
1363 if (c == quotec || c == escapec)
1364 {
1365 DUMPSOFAR();
1366 CopySendChar(cstate, escapec);
1367 start = ptr; /* we include char in next run */
1368 }
1369 if (IS_HIGHBIT_SET(c) && cstate->encoding_embeds_ascii)
1370 ptr += pg_encoding_mblen(cstate->file_encoding, ptr);
1371 else
1372 ptr++;
1373 }
1374 DUMPSOFAR();
1375
1376 CopySendChar(cstate, quotec);
1377 }
1378 else
1379 {
1380 /* If it doesn't need quoting, we can just dump it as-is */
1381 CopySendString(cstate, ptr);
1382 }
1383}
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1126
#define DUMPSOFAR()
Definition: copyto.c:1140
static void CopySendChar(CopyToState cstate, char c)
Definition: copyto.c:439
static void CopySendString(CopyToState cstate, const char *str)
Definition: copyto.c:433
char * pg_server_to_any(const char *s, int len, int encoding)
Definition: mbutils.c:750
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:2135

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

◆ CopyAttributeOutText()

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

Definition at line 1147 of file copyto.c.

1148{
1149 const char *ptr;
1150 const char *start;
1151 char c;
1152 char delimc = cstate->opts.delim[0];
1153
1154 if (cstate->need_transcoding)
1155 ptr = pg_server_to_any(string, strlen(string), cstate->file_encoding);
1156 else
1157 ptr = string;
1158
1159 /*
1160 * We have to grovel through the string searching for control characters
1161 * and instances of the delimiter character. In most cases, though, these
1162 * are infrequent. To avoid overhead from calling CopySendData once per
1163 * character, we dump out all characters between escaped characters in a
1164 * single call. The loop invariant is that the data from "start" to "ptr"
1165 * can be sent literally, but hasn't yet been.
1166 *
1167 * We can skip pg_encoding_mblen() overhead when encoding is safe, because
1168 * in valid backend encodings, extra bytes of a multibyte character never
1169 * look like ASCII. This loop is sufficiently performance-critical that
1170 * it's worth making two copies of it to get the IS_HIGHBIT_SET() test out
1171 * of the normal safe-encoding path.
1172 */
1173 if (cstate->encoding_embeds_ascii)
1174 {
1175 start = ptr;
1176 while ((c = *ptr) != '\0')
1177 {
1178 if ((unsigned char) c < (unsigned char) 0x20)
1179 {
1180 /*
1181 * \r and \n must be escaped, the others are traditional. We
1182 * prefer to dump these using the C-like notation, rather than
1183 * a backslash and the literal character, because it makes the
1184 * dump file a bit more proof against Microsoftish data
1185 * mangling.
1186 */
1187 switch (c)
1188 {
1189 case '\b':
1190 c = 'b';
1191 break;
1192 case '\f':
1193 c = 'f';
1194 break;
1195 case '\n':
1196 c = 'n';
1197 break;
1198 case '\r':
1199 c = 'r';
1200 break;
1201 case '\t':
1202 c = 't';
1203 break;
1204 case '\v':
1205 c = 'v';
1206 break;
1207 default:
1208 /* If it's the delimiter, must backslash it */
1209 if (c == delimc)
1210 break;
1211 /* All ASCII control chars are length 1 */
1212 ptr++;
1213 continue; /* fall to end of loop */
1214 }
1215 /* if we get here, we need to convert the control char */
1216 DUMPSOFAR();
1217 CopySendChar(cstate, '\\');
1218 CopySendChar(cstate, c);
1219 start = ++ptr; /* do not include char in next run */
1220 }
1221 else if (c == '\\' || c == delimc)
1222 {
1223 DUMPSOFAR();
1224 CopySendChar(cstate, '\\');
1225 start = ptr++; /* we include char in next run */
1226 }
1227 else if (IS_HIGHBIT_SET(c))
1228 ptr += pg_encoding_mblen(cstate->file_encoding, ptr);
1229 else
1230 ptr++;
1231 }
1232 }
1233 else
1234 {
1235 start = ptr;
1236 while ((c = *ptr) != '\0')
1237 {
1238 if ((unsigned char) c < (unsigned char) 0x20)
1239 {
1240 /*
1241 * \r and \n must be escaped, the others are traditional. We
1242 * prefer to dump these using the C-like notation, rather than
1243 * a backslash and the literal character, because it makes the
1244 * dump file a bit more proof against Microsoftish data
1245 * mangling.
1246 */
1247 switch (c)
1248 {
1249 case '\b':
1250 c = 'b';
1251 break;
1252 case '\f':
1253 c = 'f';
1254 break;
1255 case '\n':
1256 c = 'n';
1257 break;
1258 case '\r':
1259 c = 'r';
1260 break;
1261 case '\t':
1262 c = 't';
1263 break;
1264 case '\v':
1265 c = 'v';
1266 break;
1267 default:
1268 /* If it's the delimiter, must backslash it */
1269 if (c == delimc)
1270 break;
1271 /* All ASCII control chars are length 1 */
1272 ptr++;
1273 continue; /* fall to end of loop */
1274 }
1275 /* if we get here, we need to convert the control char */
1276 DUMPSOFAR();
1277 CopySendChar(cstate, '\\');
1278 CopySendChar(cstate, c);
1279 start = ++ptr; /* do not include char in next run */
1280 }
1281 else if (c == '\\' || c == delimc)
1282 {
1283 DUMPSOFAR();
1284 CopySendChar(cstate, '\\');
1285 start = ptr++; /* we include char in next run */
1286 }
1287 else
1288 ptr++;
1289 }
1290 }
1291
1292 DUMPSOFAR();
1293}

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

◆ CopyOneRowTo()

static void CopyOneRowTo ( CopyToState  cstate,
TupleTableSlot slot 
)
inlinestatic

Definition at line 1122 of file copyto.c.

1123{
1124 MemoryContext oldcontext;
1125
1127 oldcontext = MemoryContextSwitchTo(cstate->rowcontext);
1128
1129 /* Make sure the tuple is fully deconstructed */
1130 slot_getallattrs(slot);
1131
1132 cstate->routine->CopyToOneRow(cstate, slot);
1133
1134 MemoryContextSwitchTo(oldcontext);
1135}
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
void(* CopyToOneRow)(CopyToState cstate, TupleTableSlot *slot)
Definition: copyapi.h:49
MemoryContext rowcontext
Definition: copyto.c:96
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:372

References CopyToRoutine::CopyToOneRow, MemoryContextReset(), MemoryContextSwitchTo(), CopyToStateData::routine, CopyToStateData::rowcontext, and slot_getallattrs().

Referenced by copy_dest_receive(), and DoCopyTo().

◆ CopySendChar()

static void CopySendChar ( CopyToState  cstate,
char  c 
)
static

Definition at line 439 of file copyto.c.

440{
442}
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:231
StringInfo fe_msgbuf
Definition: copyto.c:73

References appendStringInfoCharMacro, and CopyToStateData::fe_msgbuf.

Referenced by CopyAttributeOutCSV(), CopyAttributeOutText(), CopySendTextLikeEndOfRow(), CopyToTextLikeOneRow(), and CopyToTextLikeStart().

◆ CopySendData()

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

Definition at line 427 of file copyto.c.

428{
429 appendBinaryStringInfo(cstate->fe_msgbuf, databuf, datasize);
430}
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:281

References appendBinaryStringInfo(), and CopyToStateData::fe_msgbuf.

Referenced by CopySendInt16(), CopySendInt32(), CopyToBinaryOneRow(), and CopyToBinaryStart().

◆ CopySendEndOfRow()

static void CopySendEndOfRow ( CopyToState  cstate)
static

Definition at line 445 of file copyto.c.

446{
447 StringInfo fe_msgbuf = cstate->fe_msgbuf;
448
449 switch (cstate->copy_dest)
450 {
451 case COPY_FILE:
452 if (fwrite(fe_msgbuf->data, fe_msgbuf->len, 1,
453 cstate->copy_file) != 1 ||
454 ferror(cstate->copy_file))
455 {
456 if (cstate->is_program)
457 {
458 if (errno == EPIPE)
459 {
460 /*
461 * The pipe will be closed automatically on error at
462 * the end of transaction, but we might get a better
463 * error message from the subprocess' exit code than
464 * just "Broken Pipe"
465 */
466 ClosePipeToProgram(cstate);
467
468 /*
469 * If ClosePipeToProgram() didn't throw an error, the
470 * program terminated normally, but closed the pipe
471 * first. Restore errno, and throw an error.
472 */
473 errno = EPIPE;
474 }
477 errmsg("could not write to COPY program: %m")));
478 }
479 else
482 errmsg("could not write to COPY file: %m")));
483 }
484 break;
485 case COPY_FRONTEND:
486 /* Dump the accumulated row as one CopyData message */
487 (void) pq_putmessage(PqMsg_CopyData, fe_msgbuf->data, fe_msgbuf->len);
488 break;
489 case COPY_CALLBACK:
490 cstate->data_dest_cb(fe_msgbuf->data, fe_msgbuf->len);
491 break;
492 }
493
494 /* Update the progress */
495 cstate->bytes_processed += fe_msgbuf->len;
497
498 resetStringInfo(fe_msgbuf);
499}
static void ClosePipeToProgram(CopyToState cstate)
Definition: copyto.c:562
#define pq_putmessage(msgtype, s, len)
Definition: libpq.h:49
#define PROGRESS_COPY_BYTES_PROCESSED
Definition: progress.h:142
#define PqMsg_CopyData
Definition: protocol.h:65
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:126

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

Referenced by CopySendTextLikeEndOfRow(), CopyToBinaryEnd(), and CopyToBinaryOneRow().

◆ CopySendInt16()

static void CopySendInt16 ( CopyToState  cstate,
int16  val 
)
inlinestatic

Definition at line 550 of file copyto.c.

551{
552 uint16 buf;
553
554 buf = pg_hton16((uint16) val);
555 CopySendData(cstate, &buf, sizeof(buf));
556}
uint16_t uint16
Definition: c.h:501
static void CopySendData(CopyToState cstate, const void *databuf, int datasize)
Definition: copyto.c:427
long val
Definition: informix.c:689
#define pg_hton16(x)
Definition: pg_bswap.h:120
static char * buf
Definition: pg_test_fsync.c:72

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

Referenced by CopyToBinaryEnd(), and CopyToBinaryOneRow().

◆ CopySendInt32()

static void CopySendInt32 ( CopyToState  cstate,
int32  val 
)
inlinestatic

Definition at line 538 of file copyto.c.

539{
540 uint32 buf;
541
542 buf = pg_hton32((uint32) val);
543 CopySendData(cstate, &buf, sizeof(buf));
544}
uint32_t uint32
Definition: c.h:502
#define pg_hton32(x)
Definition: pg_bswap.h:121

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

Referenced by CopyToBinaryOneRow(), and CopyToBinaryStart().

◆ CopySendString()

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

Definition at line 433 of file copyto.c.

434{
435 appendBinaryStringInfo(cstate->fe_msgbuf, str, strlen(str));
436}
const char * str

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

Referenced by CopyAttributeOutCSV(), CopySendTextLikeEndOfRow(), and CopyToTextLikeOneRow().

◆ CopySendTextLikeEndOfRow()

static void CopySendTextLikeEndOfRow ( CopyToState  cstate)
inlinestatic

Definition at line 506 of file copyto.c.

507{
508 switch (cstate->copy_dest)
509 {
510 case COPY_FILE:
511 /* Default line termination depends on platform */
512#ifndef WIN32
513 CopySendChar(cstate, '\n');
514#else
515 CopySendString(cstate, "\r\n");
516#endif
517 break;
518 case COPY_FRONTEND:
519 /* The FE/BE protocol uses \n as newline for all platforms */
520 CopySendChar(cstate, '\n');
521 break;
522 default:
523 break;
524 }
525
526 /* Now take the actions related to the end of a row */
527 CopySendEndOfRow(cstate);
528}
static void CopySendEndOfRow(CopyToState cstate)
Definition: copyto.c:445

References CopyToStateData::copy_dest, COPY_FILE, COPY_FRONTEND, CopySendChar(), CopySendEndOfRow(), and CopySendString().

Referenced by CopyToTextLikeOneRow(), and CopyToTextLikeStart().

◆ CopyToBinaryEnd()

static void CopyToBinaryEnd ( CopyToState  cstate)
static

Definition at line 378 of file copyto.c.

379{
380 /* Generate trailer for a binary copy */
381 CopySendInt16(cstate, -1);
382 /* Need to flush out the trailer */
383 CopySendEndOfRow(cstate);
384}
static void CopySendInt16(CopyToState cstate, int16 val)
Definition: copyto.c:550

References CopySendEndOfRow(), and CopySendInt16().

◆ CopyToBinaryOneRow()

static void CopyToBinaryOneRow ( CopyToState  cstate,
TupleTableSlot slot 
)
static

Definition at line 345 of file copyto.c.

346{
347 FmgrInfo *out_functions = cstate->out_functions;
348
349 /* Binary per-tuple header */
350 CopySendInt16(cstate, list_length(cstate->attnumlist));
351
353 {
354 Datum value = slot->tts_values[attnum - 1];
355 bool isnull = slot->tts_isnull[attnum - 1];
356
357 if (isnull)
358 {
359 CopySendInt32(cstate, -1);
360 }
361 else
362 {
363 bytea *outputbytes;
364
365 outputbytes = SendFunctionCall(&out_functions[attnum - 1],
366 value);
367 CopySendInt32(cstate, VARSIZE(outputbytes) - VARHDRSZ);
368 CopySendData(cstate, VARDATA(outputbytes),
369 VARSIZE(outputbytes) - VARHDRSZ);
370 }
371 }
372
373 CopySendEndOfRow(cstate);
374}
#define VARHDRSZ
Definition: c.h:663
static void CopySendInt32(CopyToState cstate, int32 val)
Definition: copyto.c:538
bytea * SendFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1744
static struct @165 value
#define foreach_int(var, lst)
Definition: pg_list.h:470
uintptr_t Datum
Definition: postgres.h:69
FmgrInfo * out_functions
Definition: copyto.c:95
Definition: fmgr.h:57
bool * tts_isnull
Definition: tuptable.h:127
Datum * tts_values
Definition: tuptable.h:125
Definition: c.h:658
#define VARDATA(PTR)
Definition: varatt.h:278
#define VARSIZE(PTR)
Definition: varatt.h:279

References attnum, CopyToStateData::attnumlist, CopySendData(), CopySendEndOfRow(), CopySendInt16(), CopySendInt32(), foreach_int, list_length(), CopyToStateData::out_functions, SendFunctionCall(), TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, value, VARDATA, VARHDRSZ, and VARSIZE.

◆ CopyToBinaryOutFunc()

static void CopyToBinaryOutFunc ( CopyToState  cstate,
Oid  atttypid,
FmgrInfo finfo 
)
static

Definition at line 333 of file copyto.c.

334{
335 Oid func_oid;
336 bool is_varlena;
337
338 /* Set output function for an attribute */
339 getTypeBinaryOutputInfo(atttypid, &func_oid, &is_varlena);
340 fmgr_info(func_oid, finfo);
341}
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
void getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
Definition: lsyscache.c:3113
unsigned int Oid
Definition: postgres_ext.h:30

References fmgr_info(), and getTypeBinaryOutputInfo().

◆ CopyToBinaryStart()

static void CopyToBinaryStart ( CopyToState  cstate,
TupleDesc  tupDesc 
)
static

Definition at line 314 of file copyto.c.

315{
316 int32 tmp;
317
318 /* Signature */
319 CopySendData(cstate, BinarySignature, 11);
320 /* Flags field */
321 tmp = 0;
322 CopySendInt32(cstate, tmp);
323 /* No header extension */
324 tmp = 0;
325 CopySendInt32(cstate, tmp);
326}
int32_t int32
Definition: c.h:498
static const char BinarySignature[11]
Definition: copyto.c:109

References BinarySignature, CopySendData(), and CopySendInt32().

◆ CopyToCSVOneRow()

static void CopyToCSVOneRow ( CopyToState  cstate,
TupleTableSlot slot 
)
static

Definition at line 252 of file copyto.c.

253{
254 CopyToTextLikeOneRow(cstate, slot, true);
255}
static void CopyToTextLikeOneRow(CopyToState cstate, TupleTableSlot *slot, bool is_csv)
Definition: copyto.c:264

References CopyToTextLikeOneRow().

◆ CopyToGetRoutine()

static const CopyToRoutine * CopyToGetRoutine ( const CopyFormatOptions opts)
static

Definition at line 177 of file copyto.c.

178{
179 if (opts->csv_mode)
180 return &CopyToRoutineCSV;
181 else if (opts->binary)
182 return &CopyToRoutineBinary;
183
184 /* default is text */
185 return &CopyToRoutineText;
186}
static const CopyToRoutine CopyToRoutineCSV
Definition: copyto.c:160
static const CopyToRoutine CopyToRoutineText
Definition: copyto.c:152
static const CopyToRoutine CopyToRoutineBinary
Definition: copyto.c:168
static AmcheckOptions opts
Definition: pg_amcheck.c:112

References CopyToRoutineBinary, CopyToRoutineCSV, CopyToRoutineText, and opts.

Referenced by BeginCopyTo().

◆ CopyToTextLikeEnd()

static void CopyToTextLikeEnd ( CopyToState  cstate)
static

Definition at line 304 of file copyto.c.

305{
306 /* Nothing to do here */
307}

◆ CopyToTextLikeOneRow()

static pg_attribute_always_inline void CopyToTextLikeOneRow ( CopyToState  cstate,
TupleTableSlot slot,
bool  is_csv 
)
static

Definition at line 264 of file copyto.c.

267{
268 bool need_delim = false;
269 FmgrInfo *out_functions = cstate->out_functions;
270
272 {
273 Datum value = slot->tts_values[attnum - 1];
274 bool isnull = slot->tts_isnull[attnum - 1];
275
276 if (need_delim)
277 CopySendChar(cstate, cstate->opts.delim[0]);
278 need_delim = true;
279
280 if (isnull)
281 {
282 CopySendString(cstate, cstate->opts.null_print_client);
283 }
284 else
285 {
286 char *string;
287
288 string = OutputFunctionCall(&out_functions[attnum - 1],
289 value);
290
291 if (is_csv)
292 CopyAttributeOutCSV(cstate, string,
293 cstate->opts.force_quote_flags[attnum - 1]);
294 else
295 CopyAttributeOutText(cstate, string);
296 }
297 }
298
300}
static void CopyAttributeOutCSV(CopyToState cstate, const char *string, bool use_quote)
Definition: copyto.c:1300
static void CopyAttributeOutText(CopyToState cstate, const char *string)
Definition: copyto.c:1147
static void CopySendTextLikeEndOfRow(CopyToState cstate)
Definition: copyto.c:506
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1683
char * null_print_client
Definition: copy.h:70

References attnum, CopyToStateData::attnumlist, CopyAttributeOutCSV(), CopyAttributeOutText(), CopySendChar(), CopySendString(), CopySendTextLikeEndOfRow(), CopyFormatOptions::delim, CopyFormatOptions::force_quote_flags, foreach_int, CopyFormatOptions::null_print_client, CopyToStateData::opts, CopyToStateData::out_functions, OutputFunctionCall(), TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, and value.

Referenced by CopyToCSVOneRow(), and CopyToTextOneRow().

◆ CopyToTextLikeOutFunc()

static void CopyToTextLikeOutFunc ( CopyToState  cstate,
Oid  atttypid,
FmgrInfo finfo 
)
static

Definition at line 233 of file copyto.c.

234{
235 Oid func_oid;
236 bool is_varlena;
237
238 /* Set output function for an attribute */
239 getTypeOutputInfo(atttypid, &func_oid, &is_varlena);
240 fmgr_info(func_oid, finfo);
241}
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:3047

References fmgr_info(), and getTypeOutputInfo().

◆ CopyToTextLikeStart()

static void CopyToTextLikeStart ( CopyToState  cstate,
TupleDesc  tupDesc 
)
static

Definition at line 190 of file copyto.c.

191{
192 /*
193 * For non-binary copy, we need to convert null_print to file encoding,
194 * because it will be sent directly with CopySendString.
195 */
196 if (cstate->need_transcoding)
198 cstate->opts.null_print_len,
199 cstate->file_encoding);
200
201 /* if a header has been requested send the line */
202 if (cstate->opts.header_line)
203 {
204 ListCell *cur;
205 bool hdr_delim = false;
206
207 foreach(cur, cstate->attnumlist)
208 {
209 int attnum = lfirst_int(cur);
210 char *colname;
211
212 if (hdr_delim)
213 CopySendChar(cstate, cstate->opts.delim[0]);
214 hdr_delim = true;
215
216 colname = NameStr(TupleDescAttr(tupDesc, attnum - 1)->attname);
217
218 if (cstate->opts.csv_mode)
219 CopyAttributeOutCSV(cstate, colname, false);
220 else
221 CopyAttributeOutText(cstate, colname);
222 }
223
225 }
226}
NameData attname
Definition: pg_attribute.h:41
int null_print_len
Definition: copy.h:69
CopyHeaderChoice header_line
Definition: copy.h:67
bool csv_mode
Definition: copy.h:66

References attname, attnum, CopyToStateData::attnumlist, CopyAttributeOutCSV(), CopyAttributeOutText(), CopySendChar(), CopySendTextLikeEndOfRow(), CopyFormatOptions::csv_mode, cur, CopyFormatOptions::delim, CopyToStateData::file_encoding, CopyFormatOptions::header_line, lfirst_int, NameStr, CopyToStateData::need_transcoding, CopyFormatOptions::null_print, CopyFormatOptions::null_print_client, CopyFormatOptions::null_print_len, CopyToStateData::opts, pg_server_to_any(), and TupleDescAttr().

◆ CopyToTextOneRow()

static void CopyToTextOneRow ( CopyToState  cstate,
TupleTableSlot slot 
)
static

Definition at line 245 of file copyto.c.

246{
247 CopyToTextLikeOneRow(cstate, slot, false);
248}

References CopyToTextLikeOneRow().

◆ CreateCopyDestReceiver()

DestReceiver * CreateCopyDestReceiver ( void  )

Definition at line 1435 of file copyto.c.

1436{
1437 DR_copy *self = (DR_copy *) palloc(sizeof(DR_copy));
1438
1443 self->pub.mydest = DestCopyOut;
1444
1445 self->cstate = NULL; /* will be set later */
1446 self->processed = 0;
1447
1448 return (DestReceiver *) self;
1449}
static bool copy_dest_receive(TupleTableSlot *slot, DestReceiver *self)
Definition: copyto.c:1398
static void copy_dest_destroy(DestReceiver *self)
Definition: copyto.c:1426
static void copy_dest_shutdown(DestReceiver *self)
Definition: copyto.c:1417
static void copy_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: copyto.c:1389
void * palloc(Size size)
Definition: mcxt.c:1321
DestReceiver pub
Definition: copyto.c:103
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: dest.h:121
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:124
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:118
void(* rDestroy)(DestReceiver *self)
Definition: dest.h:126
CommandDest mydest
Definition: dest.h:128

References copy_dest_destroy(), copy_dest_receive(), copy_dest_shutdown(), copy_dest_startup(), DR_copy::cstate, DestCopyOut, _DestReceiver::mydest, palloc(), DR_copy::processed, DR_copy::pub, _DestReceiver::rDestroy, _DestReceiver::receiveSlot, _DestReceiver::rShutdown, and _DestReceiver::rStartup.

Referenced by CreateDestReceiver().

◆ DoCopyTo()

uint64 DoCopyTo ( CopyToState  cstate)

Definition at line 1026 of file copyto.c.

1027{
1028 bool pipe = (cstate->filename == NULL && cstate->data_dest_cb == NULL);
1029 bool fe_copy = (pipe && whereToSendOutput == DestRemote);
1030 TupleDesc tupDesc;
1031 int num_phys_attrs;
1032 ListCell *cur;
1033 uint64 processed;
1034
1035 if (fe_copy)
1036 SendCopyBegin(cstate);
1037
1038 if (cstate->rel)
1039 tupDesc = RelationGetDescr(cstate->rel);
1040 else
1041 tupDesc = cstate->queryDesc->tupDesc;
1042 num_phys_attrs = tupDesc->natts;
1043 cstate->opts.null_print_client = cstate->opts.null_print; /* default */
1044
1045 /* We use fe_msgbuf as a per-row buffer regardless of copy_dest */
1046 cstate->fe_msgbuf = makeStringInfo();
1047
1048 /* Get info about the columns we need to process. */
1049 cstate->out_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
1050 foreach(cur, cstate->attnumlist)
1051 {
1052 int attnum = lfirst_int(cur);
1053 Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
1054
1055 cstate->routine->CopyToOutFunc(cstate, attr->atttypid,
1056 &cstate->out_functions[attnum - 1]);
1057 }
1058
1059 /*
1060 * Create a temporary memory context that we can reset once per row to
1061 * recover palloc'd memory. This avoids any problems with leaks inside
1062 * datatype output routines, and should be faster than retail pfree's
1063 * anyway. (We don't need a whole econtext as CopyFrom does.)
1064 */
1066 "COPY TO",
1068
1069 cstate->routine->CopyToStart(cstate, tupDesc);
1070
1071 if (cstate->rel)
1072 {
1073 TupleTableSlot *slot;
1074 TableScanDesc scandesc;
1075
1076 scandesc = table_beginscan(cstate->rel, GetActiveSnapshot(), 0, NULL);
1077 slot = table_slot_create(cstate->rel, NULL);
1078
1079 processed = 0;
1080 while (table_scan_getnextslot(scandesc, ForwardScanDirection, slot))
1081 {
1083
1084 /* Deconstruct the tuple ... */
1085 slot_getallattrs(slot);
1086
1087 /* Format and send the data */
1088 CopyOneRowTo(cstate, slot);
1089
1090 /*
1091 * Increment the number of processed tuples, and report the
1092 * progress.
1093 */
1095 ++processed);
1096 }
1097
1099 table_endscan(scandesc);
1100 }
1101 else
1102 {
1103 /* run the plan --- the dest receiver will send tuples */
1105 processed = ((DR_copy *) cstate->queryDesc->dest)->processed;
1106 }
1107
1108 cstate->routine->CopyToEnd(cstate);
1109
1111
1112 if (fe_copy)
1113 SendCopyEnd(cstate);
1114
1115 return processed;
1116}
uint64_t uint64
Definition: c.h:503
static void SendCopyBegin(CopyToState cstate)
Definition: copyto.c:391
static void SendCopyEnd(CopyToState cstate)
Definition: copyto.c:408
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition: execMain.c:298
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1443
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
@ ForwardScanDirection
Definition: sdir.h:28
StringInfo makeStringInfo(void)
Definition: stringinfo.c:72
void(* CopyToOutFunc)(CopyToState cstate, Oid atttypid, FmgrInfo *finfo)
Definition: copyapi.h:34
void(* CopyToEnd)(CopyToState cstate)
Definition: copyapi.h:54
void(* CopyToStart)(CopyToState cstate, TupleDesc tupDesc)
Definition: copyapi.h:44
DestReceiver * dest
Definition: execdesc.h:41
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition: tableam.c:92
static TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key)
Definition: tableam.h:870
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:979
static bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
Definition: tableam.h:1015

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, attnum, CopyToStateData::attnumlist, CHECK_FOR_INTERRUPTS, CopyOneRowTo(), CopyToRoutine::CopyToEnd, CopyToRoutine::CopyToOutFunc, CopyToRoutine::CopyToStart, cur, CurrentMemoryContext, CopyToStateData::data_dest_cb, QueryDesc::dest, DestRemote, ExecDropSingleTupleTableSlot(), ExecutorRun(), CopyToStateData::fe_msgbuf, CopyToStateData::filename, ForwardScanDirection, GetActiveSnapshot(), lfirst_int, makeStringInfo(), MemoryContextDelete(), TupleDescData::natts, CopyFormatOptions::null_print, CopyFormatOptions::null_print_client, CopyToStateData::opts, CopyToStateData::out_functions, palloc(), pgstat_progress_update_param(), PROGRESS_COPY_TUPLES_PROCESSED, CopyToStateData::queryDesc, CopyToStateData::rel, RelationGetDescr, CopyToStateData::routine, 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 587 of file copyto.c.

588{
589 if (cstate->is_program)
590 {
591 ClosePipeToProgram(cstate);
592 }
593 else
594 {
595 if (cstate->filename != NULL && FreeFile(cstate->copy_file))
598 errmsg("could not close file \"%s\": %m",
599 cstate->filename)));
600 }
601
603
605 pfree(cstate);
606}
void pgstat_progress_end_command(void)
int FreeFile(FILE *file)
Definition: fd.c:2843

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 1005 of file copyto.c.

1006{
1007 if (cstate->queryDesc != NULL)
1008 {
1009 /* Close down the query and free resources. */
1010 ExecutorFinish(cstate->queryDesc);
1011 ExecutorEnd(cstate->queryDesc);
1012 FreeQueryDesc(cstate->queryDesc);
1014 }
1015
1016 /* Clean up storage */
1017 EndCopy(cstate);
1018}
static void EndCopy(CopyToState cstate)
Definition: copyto.c:587
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:467
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:407
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:106
void PopActiveSnapshot(void)
Definition: snapmgr.c:762

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 391 of file copyto.c.

392{
394 int natts = list_length(cstate->attnumlist);
395 int16 format = (cstate->opts.binary ? 1 : 0);
396 int i;
397
399 pq_sendbyte(&buf, format); /* overall format */
400 pq_sendint16(&buf, natts);
401 for (i = 0; i < natts; i++)
402 pq_sendint16(&buf, format); /* per-column formats */
404 cstate->copy_dest = COPY_FRONTEND;
405}
int16_t int16
Definition: c.h:497
int i
Definition: isn.c:77
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
bool binary
Definition: copy.h:64

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 408 of file copyto.c.

409{
410 /* Shouldn't have any unsent data */
411 Assert(cstate->fe_msgbuf->len == 0);
412 /* Send Copy Done message */
414}
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 109 of file copyto.c.

Referenced by CopyToBinaryStart().

◆ CopyToRoutineBinary

const CopyToRoutine CopyToRoutineBinary
static
Initial value:
= {
.CopyToStart = CopyToBinaryStart,
.CopyToOutFunc = CopyToBinaryOutFunc,
.CopyToOneRow = CopyToBinaryOneRow,
.CopyToEnd = CopyToBinaryEnd,
}
static void CopyToBinaryOutFunc(CopyToState cstate, Oid atttypid, FmgrInfo *finfo)
Definition: copyto.c:333
static void CopyToBinaryOneRow(CopyToState cstate, TupleTableSlot *slot)
Definition: copyto.c:345
static void CopyToBinaryStart(CopyToState cstate, TupleDesc tupDesc)
Definition: copyto.c:314
static void CopyToBinaryEnd(CopyToState cstate)
Definition: copyto.c:378

Definition at line 168 of file copyto.c.

Referenced by CopyToGetRoutine().

◆ CopyToRoutineCSV

const CopyToRoutine CopyToRoutineCSV
static
Initial value:
= {
.CopyToStart = CopyToTextLikeStart,
.CopyToOutFunc = CopyToTextLikeOutFunc,
.CopyToOneRow = CopyToCSVOneRow,
.CopyToEnd = CopyToTextLikeEnd,
}
static void CopyToTextLikeEnd(CopyToState cstate)
Definition: copyto.c:304
static void CopyToTextLikeOutFunc(CopyToState cstate, Oid atttypid, FmgrInfo *finfo)
Definition: copyto.c:233
static void CopyToTextLikeStart(CopyToState cstate, TupleDesc tupDesc)
Definition: copyto.c:190
static void CopyToCSVOneRow(CopyToState cstate, TupleTableSlot *slot)
Definition: copyto.c:252

Definition at line 160 of file copyto.c.

Referenced by CopyToGetRoutine().

◆ CopyToRoutineText

const CopyToRoutine CopyToRoutineText
static
Initial value:
= {
.CopyToStart = CopyToTextLikeStart,
.CopyToOutFunc = CopyToTextLikeOutFunc,
.CopyToOneRow = CopyToTextOneRow,
.CopyToEnd = CopyToTextLikeEnd,
}
static void CopyToTextOneRow(CopyToState cstate, TupleTableSlot *slot)
Definition: copyto.c:245

Definition at line 152 of file copyto.c.

Referenced by CopyToGetRoutine().