1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-30 06:01:21 +03:00

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.
This commit is contained in:
Heikki Linnakangas
2013-02-27 18:17:21 +02:00
parent 73dc003bee
commit 3d009e45bd
21 changed files with 584 additions and 152 deletions

View File

@@ -505,14 +505,12 @@ pipe_read_line(char *cmd, char *line, int maxsize)
/*
* pclose() plus useful error reporting
* Is this necessary? bjm 2004-05-11
* Originally this was stated to be here because pipe.c had backend linkage.
* Perhaps that's no longer so now we have got rid of pipe.c amd 2012-03-28
*/
int
pclose_check(FILE *stream)
{
int exitstatus;
char *reason;
exitstatus = pclose(stream);
@@ -522,36 +520,21 @@ pclose_check(FILE *stream)
if (exitstatus == -1)
{
/* pclose() itself failed, and hopefully set errno */
perror("pclose failed");
log_error(_("pclose failed: %s"), strerror(errno));
}
else if (WIFEXITED(exitstatus))
log_error(_("child process exited with exit code %d"),
WEXITSTATUS(exitstatus));
else if (WIFSIGNALED(exitstatus))
#if defined(WIN32)
log_error(_("child process was terminated by exception 0x%X"),
WTERMSIG(exitstatus));
#elif defined(HAVE_DECL_SYS_SIGLIST) && HAVE_DECL_SYS_SIGLIST
{
char str[256];
snprintf(str, sizeof(str), "%d: %s", WTERMSIG(exitstatus),
WTERMSIG(exitstatus) < NSIG ?
sys_siglist[WTERMSIG(exitstatus)] : "(unknown)");
log_error(_("child process was terminated by signal %s"), str);
}
#else
log_error(_("child process was terminated by signal %d"),
WTERMSIG(exitstatus));
#endif
else
log_error(_("child process exited with unrecognized status %d"),
exitstatus);
return -1;
{
reason = wait_result_to_str(exitstatus);
log_error("%s", reason);
#ifdef FRONTEND
free(reason);
#else
pfree(reason);
#endif
}
return exitstatus;
}
/*
* set_pglocale_pgservice
*