2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2017, PostgreSQL Global Development Group
8 #include "postgres_fe.h"
14 #include <unistd.h> /* for isatty */
16 #include <io.h> /* I think */
20 #include "pqexpbuffer.h"
25 #include "stringutils.h"
30 * -- parses \copy command line
32 * The documented syntax is:
33 * \copy tablename [(columnlist)] from|to filename [options]
34 * \copy ( query stmt ) to filename [options]
36 * where 'filename' can be one of the following:
37 * '<file path>' | PROGRAM '<command>' | stdin | stdout | pstdout | pstdout
38 * and 'query' can be one of the following:
39 * SELECT | UPDATE | INSERT | DELETE
41 * An undocumented fact is that you can still write BINARY before the
42 * tablename; this is a hangover from the pre-7.3 syntax. The options
43 * syntax varies across backend versions, but we avoid all that mess
44 * by just transmitting the stuff after the filename literally.
46 * table name can be double-quoted and can have a schema part.
47 * column names can be double-quoted.
48 * filename can be single-quoted like SQL literals.
49 * command must be single-quoted like SQL literals.
51 * returns a malloc'ed structure with the options, or NULL on parsing error
56 char *before_tofrom; /* COPY string before TO/FROM */
57 char *after_tofrom; /* COPY string after TO/FROM filename */
58 char *file; /* NULL = stdin/stdout */
59 bool program; /* is 'file' a program to popen? */
60 bool psql_inout; /* true = use psql stdin/stdout */
61 bool from; /* true = FROM, false = TO */
66 free_copy_options(struct copy_options * ptr)
70 free(ptr->before_tofrom);
71 free(ptr->after_tofrom);
77 /* concatenate "more" onto "var", freeing the original value of *var */
79 xstrcat(char **var, const char *more)
83 newvar = psprintf("%s%s", *var, more);
89 static struct copy_options *
90 parse_slash_copy(const char *args)
92 struct copy_options *result;
94 const char *whitespace = " \t\n\r";
95 char nonstd_backslash = standard_strings() ? 0 : '\\';
99 psql_error("\\copy: arguments required\n");
103 result = pg_malloc0(sizeof(struct copy_options));
105 result->before_tofrom = pg_strdup(""); /* initialize for appending */
107 token = strtokx(args, whitespace, ".,()", "\"",
108 0, false, false, pset.encoding);
112 /* The following can be removed when we drop 7.3 syntax support */
113 if (pg_strcasecmp(token, "binary") == 0)
115 xstrcat(&result->before_tofrom, token);
116 token = strtokx(NULL, whitespace, ".,()", "\"",
117 0, false, false, pset.encoding);
122 /* Handle COPY (query) case */
129 xstrcat(&result->before_tofrom, " ");
130 xstrcat(&result->before_tofrom, token);
131 token = strtokx(NULL, whitespace, "()", "\"'",
132 nonstd_backslash, true, false, pset.encoding);
137 else if (token[0] == ')')
142 xstrcat(&result->before_tofrom, " ");
143 xstrcat(&result->before_tofrom, token);
144 token = strtokx(NULL, whitespace, ".,()", "\"",
145 0, false, false, pset.encoding);
150 * strtokx() will not have returned a multi-character token starting with
151 * '.', so we don't need strcmp() here. Likewise for '(', etc, below.
155 /* handle schema . table */
156 xstrcat(&result->before_tofrom, token);
157 token = strtokx(NULL, whitespace, ".,()", "\"",
158 0, false, false, pset.encoding);
161 xstrcat(&result->before_tofrom, token);
162 token = strtokx(NULL, whitespace, ".,()", "\"",
163 0, false, false, pset.encoding);
170 /* handle parenthesized column list */
173 xstrcat(&result->before_tofrom, " ");
174 xstrcat(&result->before_tofrom, token);
175 token = strtokx(NULL, whitespace, "()", "\"",
176 0, false, false, pset.encoding);
182 xstrcat(&result->before_tofrom, " ");
183 xstrcat(&result->before_tofrom, token);
184 token = strtokx(NULL, whitespace, ".,()", "\"",
185 0, false, false, pset.encoding);
190 if (pg_strcasecmp(token, "from") == 0)
192 else if (pg_strcasecmp(token, "to") == 0)
193 result->from = false;
197 /* { 'filename' | PROGRAM 'command' | STDIN | STDOUT | PSTDIN | PSTDOUT } */
198 token = strtokx(NULL, whitespace, ";", "'",
199 0, false, false, pset.encoding);
203 if (pg_strcasecmp(token, "program") == 0)
207 token = strtokx(NULL, whitespace, ";", "'",
208 0, false, false, pset.encoding);
213 * The shell command must be quoted. This isn't fool-proof, but
214 * catches most quoting errors.
216 toklen = strlen(token);
217 if (token[0] != '\'' || toklen < 2 || token[toklen - 1] != '\'')
220 strip_quotes(token, '\'', 0, pset.encoding);
222 result->program = true;
223 result->file = pg_strdup(token);
225 else if (pg_strcasecmp(token, "stdin") == 0 ||
226 pg_strcasecmp(token, "stdout") == 0)
230 else if (pg_strcasecmp(token, "pstdin") == 0 ||
231 pg_strcasecmp(token, "pstdout") == 0)
233 result->psql_inout = true;
238 /* filename can be optionally quoted */
239 strip_quotes(token, '\'', 0, pset.encoding);
240 result->file = pg_strdup(token);
241 expand_tilde(&result->file);
244 /* Collect the rest of the line (COPY options) */
245 token = strtokx(NULL, "", NULL, NULL,
246 0, false, false, pset.encoding);
248 result->after_tofrom = pg_strdup(token);
254 psql_error("\\copy: parse error at \"%s\"\n", token);
256 psql_error("\\copy: parse error at end of line\n");
257 free_copy_options(result);
264 * Execute a \copy command (frontend copy). We have to open a file (or execute
265 * a command), then submit a COPY query to the backend and either feed it data
266 * from the file or route its response into the file.
269 do_copy(const char *args)
271 PQExpBufferData query;
273 struct copy_options *options;
277 options = parse_slash_copy(args);
282 /* prepare to read or write the target file */
283 if (options->file && !options->program)
284 canonicalize_path(options->file);
290 if (options->program)
295 copystream = popen(options->file, PG_BINARY_R);
298 copystream = fopen(options->file, PG_BINARY_R);
300 else if (!options->psql_inout)
301 copystream = pset.cur_cmd_source;
309 if (options->program)
314 disable_sigpipe_trap();
315 copystream = popen(options->file, PG_BINARY_W);
318 copystream = fopen(options->file, PG_BINARY_W);
320 else if (!options->psql_inout)
321 copystream = pset.queryFout;
328 if (options->program)
329 psql_error("could not execute command \"%s\": %s\n",
330 options->file, strerror(errno));
332 psql_error("%s: %s\n",
333 options->file, strerror(errno));
334 free_copy_options(options);
338 if (!options->program)
343 /* make sure the specified file is not a directory */
344 if ((result = fstat(fileno(copystream), &st)) < 0)
345 psql_error("could not stat file \"%s\": %s\n",
346 options->file, strerror(errno));
348 if (result == 0 && S_ISDIR(st.st_mode))
349 psql_error("%s: cannot copy from/to a directory\n",
352 if (result < 0 || S_ISDIR(st.st_mode))
355 free_copy_options(options);
360 /* build the command we will send to the backend */
361 initPQExpBuffer(&query);
362 printfPQExpBuffer(&query, "COPY ");
363 appendPQExpBufferStr(&query, options->before_tofrom);
365 appendPQExpBufferStr(&query, " FROM STDIN ");
367 appendPQExpBufferStr(&query, " TO STDOUT ");
368 if (options->after_tofrom)
369 appendPQExpBufferStr(&query, options->after_tofrom);
371 /* run it like a user command, but with copystream as data source/sink */
372 pset.copyStream = copystream;
373 success = SendQuery(query.data);
374 pset.copyStream = NULL;
375 termPQExpBuffer(&query);
377 if (options->file != NULL)
379 if (options->program)
381 int pclose_rc = pclose(copystream);
386 psql_error("could not close pipe to external command: %s\n",
390 char *reason = wait_result_to_str(pclose_rc);
392 psql_error("%s: %s\n", options->file,
393 reason ? reason : "");
399 restore_sigpipe_trap();
403 if (fclose(copystream) != 0)
405 psql_error("%s: %s\n", options->file, strerror(errno));
410 free_copy_options(options);
416 * Functions for handling COPY IN/OUT data transfer.
418 * If you want to use COPY TO STDOUT/FROM STDIN in your application,
419 * this is the code to steal ;)
424 * receives data as a result of a COPY ... TO STDOUT command
426 * conn should be a database connection that you just issued COPY TO on
427 * and got back a PGRES_COPY_OUT result.
428 * copystream is the file stream for the data to go to.
429 * The final status for the COPY is returned into *res (but note
430 * we already reported the error, if it's not a success result).
432 * result is true if successful, false if not.
435 handleCopyOut(PGconn *conn, FILE *copystream, PGresult **res)
443 ret = PQgetCopyData(conn, &buf, 0);
446 break; /* done or server/connection error */
450 if (OK && fwrite(buf, 1, ret, copystream) != ret)
452 psql_error("could not write COPY data: %s\n",
454 /* complain only once, keep reading data from server */
461 if (OK && fflush(copystream))
463 psql_error("could not write COPY data: %s\n",
470 psql_error("COPY data transfer failed: %s", PQerrorMessage(conn));
475 * Check command status and return to normal libpq state.
477 * If for some reason libpq is still reporting PGRES_COPY_OUT state, we
478 * would like to forcibly exit that state, since our caller would be
479 * unable to distinguish that situation from reaching the next COPY in a
480 * command string that happened to contain two consecutive COPY TO STDOUT
481 * commands. However, libpq provides no API for doing that, and in
482 * principle it's a libpq bug anyway if PQgetCopyData() returns -1 or -2
483 * but hasn't exited COPY_OUT state internally. So we ignore the
486 *res = PQgetResult(conn);
487 if (PQresultStatus(*res) != PGRES_COMMAND_OK)
489 psql_error("%s", PQerrorMessage(conn));
498 * sends data to complete a COPY ... FROM STDIN command
500 * conn should be a database connection that you just issued COPY FROM on
501 * and got back a PGRES_COPY_IN result.
502 * copystream is the file stream to read the data from.
503 * isbinary can be set from PQbinaryTuples().
504 * The final status for the COPY is returned into *res (but note
505 * we already reported the error, if it's not a success result).
507 * result is true if successful, false if not.
510 /* read chunk size for COPY IN - size is not critical */
511 #define COPYBUFSIZ 8192
514 handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, PGresult **res)
517 char buf[COPYBUFSIZ];
521 * Establish longjmp destination for exiting from wait-for-input. (This is
522 * only effective while sigint_interrupt_enabled is TRUE.)
524 if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
526 /* got here with longjmp */
528 /* Terminate data transfer */
530 (PQprotocolVersion(conn) < 3) ? NULL :
531 _("canceled by user"));
537 /* Prompt if interactive input */
538 if (isatty(fileno(copystream)))
542 puts(_("Enter data to be copied followed by a newline.\n"
543 "End with a backslash and a period on a line by itself."));
552 /* interactive input probably silly, but give one prompt anyway */
555 const char *prompt = get_prompt(PROMPT_COPY);
557 fputs(prompt, stdout);
565 /* enable longjmp while waiting for input */
566 sigint_interrupt_enabled = true;
568 buflen = fread(buf, 1, COPYBUFSIZ, copystream);
570 sigint_interrupt_enabled = false;
575 if (PQputCopyData(conn, buf, buflen) <= 0)
584 bool copydone = false;
587 { /* for each input line ... */
593 const char *prompt = get_prompt(PROMPT_COPY);
595 fputs(prompt, stdout);
603 { /* for each bufferload in line ... */
607 /* enable longjmp while waiting for input */
608 sigint_interrupt_enabled = true;
610 fgresult = fgets(buf, sizeof(buf), copystream);
612 sigint_interrupt_enabled = false;
620 linelen = strlen(buf);
622 /* current line is done? */
623 if (linelen > 0 && buf[linelen - 1] == '\n')
626 /* check for EOF marker, but not on a partial line */
630 * This code erroneously assumes '\.' on a line alone
631 * inside a quoted CSV string terminates the \copy.
632 * http://www.postgresql.org/message-id/E1TdNVQ-0001ju-GO@w
633 * rigleys.postgresql.org
635 if (strcmp(buf, "\\.\n") == 0 ||
636 strcmp(buf, "\\.\r\n") == 0)
645 if (PQputCopyData(conn, buf, linelen) <= 0)
653 if (copystream == pset.cur_cmd_source)
661 /* Check for read error */
662 if (ferror(copystream))
666 * Terminate data transfer. We can't send an error message if we're using
667 * protocol version 2.
669 if (PQputCopyEnd(conn,
670 (OK || PQprotocolVersion(conn) < 3) ? NULL :
671 _("aborted because of read failure")) <= 0)
677 * Check command status and return to normal libpq state.
679 * We do not want to return with the status still PGRES_COPY_IN: our
680 * caller would be unable to distinguish that situation from reaching the
681 * next COPY in a command string that happened to contain two consecutive
682 * COPY FROM STDIN commands. We keep trying PQputCopyEnd() in the hope
683 * it'll work eventually. (What's actually likely to happen is that in
684 * attempting to flush the data, libpq will eventually realize that the
685 * connection is lost. But that's fine; it will get us out of COPY_IN
686 * state, which is what we need.)
688 while (*res = PQgetResult(conn), PQresultStatus(*res) == PGRES_COPY_IN)
692 /* We can't send an error message if we're using protocol version 2 */
694 (PQprotocolVersion(conn) < 3) ? NULL :
695 _("trying to exit copy mode"));
697 if (PQresultStatus(*res) != PGRES_COMMAND_OK)
699 psql_error("%s", PQerrorMessage(conn));