From 3d009e45bde2a2681826ef549637ada76508b597 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Wed, 27 Feb 2013 18:17:21 +0200 Subject: Add support for piping COPY to/from an external program. This includes backend "COPY TO/FROM PROGRAM '...'" syntax, and corresponding psql \copy syntax. Like with reading/writing files, the backend version is superuser-only, and in the psql version, the program is run in the client. In the passing, the psql \copy STDIN/STDOUT syntax is subtly changed: if you the stdin/stdout is quoted, it's now interpreted as a filename. For example, "\copy foo from 'stdin'" now reads from a file called 'stdin', not from standard input. Before this, there was no way to specify a filename called stdin, stdout, pstdin or pstdout. This creates a new function in pgport, wait_result_to_str(), which can be used to convert the exit status of a process, as returned by wait(3), to a human-readable string. Etsuro Fujita, reviewed by Amit Kapila. --- src/include/commands/copy.h | 2 +- src/include/nodes/parsenodes.h | 1 + src/include/parser/kwlist.h | 1 + src/include/port.h | 3 +++ src/include/storage/fd.h | 4 ++++ 5 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src/include') diff --git a/src/include/commands/copy.h b/src/include/commands/copy.h index 725c277ecfd..5860e4cf6b2 100644 --- a/src/include/commands/copy.h +++ b/src/include/commands/copy.h @@ -26,7 +26,7 @@ extern Oid DoCopy(const CopyStmt *stmt, const char *queryString, extern void ProcessCopyOptions(CopyState cstate, bool is_from, List *options); extern CopyState BeginCopyFrom(Relation rel, const char *filename, - List *attnamelist, List *options); + bool is_program, List *attnamelist, List *options); extern void EndCopyFrom(CopyState cstate); extern bool NextCopyFrom(CopyState cstate, ExprContext *econtext, Datum *values, bool *nulls, Oid *tupleOid); diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index d8678e5b3fd..d54990d39c1 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1407,6 +1407,7 @@ typedef struct CopyStmt List *attlist; /* List of column names (as Strings), or NIL * for all columns */ bool is_from; /* TO or FROM */ + bool is_program; /* is 'filename' a program to popen? */ char *filename; /* filename, or NULL for STDIN/STDOUT */ List *options; /* List of DefElem nodes */ } CopyStmt; diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h index 03aa7616409..6f67a65f3d1 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -292,6 +292,7 @@ PG_KEYWORD("prior", PRIOR, UNRESERVED_KEYWORD) PG_KEYWORD("privileges", PRIVILEGES, UNRESERVED_KEYWORD) PG_KEYWORD("procedural", PROCEDURAL, UNRESERVED_KEYWORD) PG_KEYWORD("procedure", PROCEDURE, UNRESERVED_KEYWORD) +PG_KEYWORD("program", PROGRAM, UNRESERVED_KEYWORD) PG_KEYWORD("quote", QUOTE, UNRESERVED_KEYWORD) PG_KEYWORD("range", RANGE, UNRESERVED_KEYWORD) PG_KEYWORD("read", READ, UNRESERVED_KEYWORD) diff --git a/src/include/port.h b/src/include/port.h index 99d3a9b7fec..c5d0e0a9709 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -465,4 +465,7 @@ extern int pg_mkdir_p(char *path, int omode); /* port/quotes.c */ extern char *escape_single_quotes_ascii(const char *src); +/* port/wait_error.c */ +extern char *wait_result_to_str(int exit_status); + #endif /* PG_PORT_H */ diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h index bd36c9d7fca..90b4933ecb5 100644 --- a/src/include/storage/fd.h +++ b/src/include/storage/fd.h @@ -80,6 +80,10 @@ extern char *FilePathName(File file); extern FILE *AllocateFile(const char *name, const char *mode); extern int FreeFile(FILE *file); +/* Operations that allow use of pipe streams (popen/pclose) */ +extern FILE *OpenPipeStream(const char *command, const char *mode); +extern int ClosePipeStream(FILE *file); + /* Operations to allow use of the library routines */ extern DIR *AllocateDir(const char *dirname); extern struct dirent *ReadDir(DIR *dir, const char *dirname); -- cgit v1.2.3