Commit 1ae6739e authored by Tom Lane's avatar Tom Lane

psql did the wrong thing with COPY FROM STDIN inside a file

sourced with \i (tried to read data from the terminal, rather than from
the source file; this breaks pg_dump scripts read with \i).  Also, \o file
followed by COPY TO STDOUT wrote to terminal not designated file.
All better now.
parent 99e57ee8
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.174 1999/03/30 05:00:42 ishii Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.175 1999/04/15 02:24:41 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -142,6 +142,17 @@ typedef struct _psqlSettings ...@@ -142,6 +142,17 @@ typedef struct _psqlSettings
* password */ * password */
} PsqlSettings; } PsqlSettings;
/*
* cur_cmd_source and cur_cmd_interactive are the top of a stack of
* source files (one stack level per recursive invocation of MainLoop).
* It's kinda grotty to make these global variables, but the alternative
* of passing them around through many function parameter lists seems
* worse.
*/
static FILE * cur_cmd_source = stdin; /* current source of command input */
static bool cur_cmd_interactive = false; /* is it an interactive source? */
#ifdef TIOCGWINSZ #ifdef TIOCGWINSZ
struct winsize screen_size; struct winsize screen_size;
...@@ -172,10 +183,9 @@ static char *gets_noreadline(char *prompt, FILE *source); ...@@ -172,10 +183,9 @@ static char *gets_noreadline(char *prompt, FILE *source);
static char *gets_readline(char *prompt, FILE *source); static char *gets_readline(char *prompt, FILE *source);
static char *gets_fromFile(char *prompt, FILE *source); static char *gets_fromFile(char *prompt, FILE *source);
static int listAllDbs(PsqlSettings *pset); static int listAllDbs(PsqlSettings *pset);
static void SendQuery(bool *success_p, PsqlSettings *pset, const char *query, static bool SendQuery(PsqlSettings *pset, const char *query,
const bool copy_in, const bool copy_out, FILE *copystream); FILE *copy_in_stream, FILE *copy_out_stream);
static int static int HandleSlashCmds(PsqlSettings *pset, char *line, char *query);
HandleSlashCmds(PsqlSettings *pset, char *line, char *query);
static int MainLoop(PsqlSettings *pset, char *query, FILE *source); static int MainLoop(PsqlSettings *pset, char *query, FILE *source);
static FILE *setFout(PsqlSettings *pset, char *fname); static FILE *setFout(PsqlSettings *pset, char *fname);
...@@ -1059,7 +1069,7 @@ objectDescription(PsqlSettings *pset, char *object) ...@@ -1059,7 +1069,7 @@ objectDescription(PsqlSettings *pset, char *object)
PQclear(res); PQclear(res);
SendQuery(&success, pset, descbuf, false, false, NULL); success = SendQuery(pset, descbuf, NULL, NULL);
return 0; return 0;
} }
...@@ -1132,14 +1142,18 @@ gets_fromFile(char *prompt, FILE *source) ...@@ -1132,14 +1142,18 @@ gets_fromFile(char *prompt, FILE *source)
} }
/* /*
* SendQuery: send the query string to the backend return *success_p = 1 if * SendQuery: send the query string to the backend.
* the query executed successfully returns *success_p = 0 otherwise *
* Return true if the query executed successfully, false otherwise.
*
* If not NULL, copy_in_stream and copy_out_stream are files to redirect
* copy in/out data to.
*/ */
static void static bool
SendQuery(bool *success_p, PsqlSettings *pset, const char *query, SendQuery(PsqlSettings *pset, const char *query,
const bool copy_in, const bool copy_out, FILE *copystream) FILE *copy_in_stream, FILE *copy_out_stream)
{ {
bool success = false;
PGresult *results; PGresult *results;
PGnotify *notify; PGnotify *notify;
...@@ -1164,7 +1178,7 @@ SendQuery(bool *success_p, PsqlSettings *pset, const char *query, ...@@ -1164,7 +1178,7 @@ SendQuery(bool *success_p, PsqlSettings *pset, const char *query,
if (results == NULL) if (results == NULL)
{ {
fprintf(stderr, "%s", PQerrorMessage(pset->db)); fprintf(stderr, "%s", PQerrorMessage(pset->db));
*success_p = false; success = false;
} }
else else
{ {
...@@ -1180,11 +1194,9 @@ SendQuery(bool *success_p, PsqlSettings *pset, const char *query, ...@@ -1180,11 +1194,9 @@ SendQuery(bool *success_p, PsqlSettings *pset, const char *query,
fp = setFout(&settings_copy, pset->gfname); fp = setFout(&settings_copy, pset->gfname);
if (!fp || fp == stdout) if (!fp || fp == stdout)
{ {
*success_p = false; success = false;
break; break;
} }
else
*success_p = true;
PQprint(fp, PQprint(fp,
results, results,
&pset->opt); &pset->opt);
...@@ -1194,11 +1206,12 @@ SendQuery(bool *success_p, PsqlSettings *pset, const char *query, ...@@ -1194,11 +1206,12 @@ SendQuery(bool *success_p, PsqlSettings *pset, const char *query,
fclose(fp); fclose(fp);
free(pset->gfname); free(pset->gfname);
pset->gfname = NULL; pset->gfname = NULL;
success = true;
break; break;
} }
else else
{ {
*success_p = true; success = true;
PQprint(pset->queryFout, PQprint(pset->queryFout,
results, results,
&(pset->opt)); &(pset->opt));
...@@ -1206,36 +1219,36 @@ SendQuery(bool *success_p, PsqlSettings *pset, const char *query, ...@@ -1206,36 +1219,36 @@ SendQuery(bool *success_p, PsqlSettings *pset, const char *query,
} }
break; break;
case PGRES_EMPTY_QUERY: case PGRES_EMPTY_QUERY:
*success_p = true; success = true;
break; break;
case PGRES_COMMAND_OK: case PGRES_COMMAND_OK:
*success_p = true; success = true;
if (!pset->quiet) if (!pset->quiet)
printf("%s\n", PQcmdStatus(results)); printf("%s\n", PQcmdStatus(results));
break; break;
case PGRES_COPY_OUT: case PGRES_COPY_OUT:
if (copy_out) if (copy_out_stream)
*success_p = handleCopyOut(pset->db, copystream); success = handleCopyOut(pset->db, copy_out_stream);
else else
{ {
if (!pset->quiet) if (pset->queryFout == stdout && !pset->quiet)
printf("Copy command returns...\n"); printf("Copy command returns...\n");
*success_p = handleCopyOut(pset->db, stdout); success = handleCopyOut(pset->db, pset->queryFout);
} }
break; break;
case PGRES_COPY_IN: case PGRES_COPY_IN:
if (copy_in) if (copy_in_stream)
*success_p = handleCopyIn(pset->db, false, copystream); success = handleCopyIn(pset->db, false, copy_in_stream);
else else
*success_p = handleCopyIn(pset->db, success = handleCopyIn(pset->db,
!pset->quiet && !pset->notty, cur_cmd_interactive && !pset->quiet,
stdin); cur_cmd_source);
break; break;
case PGRES_NONFATAL_ERROR: case PGRES_NONFATAL_ERROR:
case PGRES_FATAL_ERROR: case PGRES_FATAL_ERROR:
case PGRES_BAD_RESPONSE: case PGRES_BAD_RESPONSE:
*success_p = false; success = false;
fprintf(stderr, "%s", PQerrorMessage(pset->db)); fprintf(stderr, "%s", PQerrorMessage(pset->db));
break; break;
} }
...@@ -1259,6 +1272,7 @@ SendQuery(bool *success_p, PsqlSettings *pset, const char *query, ...@@ -1259,6 +1272,7 @@ SendQuery(bool *success_p, PsqlSettings *pset, const char *query,
if (results) if (results)
PQclear(results); PQclear(results);
} }
return success;
} }
...@@ -1495,7 +1509,9 @@ do_copy(const char *args, PsqlSettings *pset) ...@@ -1495,7 +1509,9 @@ do_copy(const char *args, PsqlSettings *pset)
{ {
bool success;/* The query succeeded at the backend */ bool success;/* The query succeeded at the backend */
SendQuery(&success, pset, query, from, !from, copystream); success = SendQuery(pset, query,
from ? copystream : (FILE*) NULL,
!from ? copystream : (FILE*) NULL);
fclose(copystream); fclose(copystream);
if (!pset->quiet) if (!pset->quiet)
{ {
...@@ -1999,7 +2015,7 @@ HandleSlashCmds(PsqlSettings *pset, ...@@ -1999,7 +2015,7 @@ HandleSlashCmds(PsqlSettings *pset,
strcat(descbuf, "' "); strcat(descbuf, "' ");
} }
strcat(descbuf, "ORDER BY aggname, type;"); strcat(descbuf, "ORDER BY aggname, type;");
SendQuery(&success, pset, descbuf, false, false, NULL); success = SendQuery(pset, descbuf, NULL, NULL);
} }
else if (strncmp(cmd, "dd", 2) == 0) else if (strncmp(cmd, "dd", 2) == 0)
/* descriptions */ /* descriptions */
...@@ -2036,7 +2052,7 @@ HandleSlashCmds(PsqlSettings *pset, ...@@ -2036,7 +2052,7 @@ HandleSlashCmds(PsqlSettings *pset,
strcat(descbuf, "' "); strcat(descbuf, "' ");
} }
strcat(descbuf, "ORDER BY result, function, arguments;"); strcat(descbuf, "ORDER BY result, function, arguments;");
SendQuery(&success, pset, descbuf, false, false, NULL); success = SendQuery(pset, descbuf, NULL, NULL);
} }
else if (strncmp(cmd, "di", 2) == 0) else if (strncmp(cmd, "di", 2) == 0)
/* only indices */ /* only indices */
...@@ -2110,7 +2126,7 @@ HandleSlashCmds(PsqlSettings *pset, ...@@ -2110,7 +2126,7 @@ HandleSlashCmds(PsqlSettings *pset,
strcat(descbuf, "' "); strcat(descbuf, "' ");
} }
strcat(descbuf, "ORDER BY op, left_arg, right_arg, result;"); strcat(descbuf, "ORDER BY op, left_arg, right_arg, result;");
SendQuery(&success, pset, descbuf, false, false, NULL); success = SendQuery(pset, descbuf, NULL, NULL);
} }
else if (strncmp(cmd, "ds", 2) == 0) else if (strncmp(cmd, "ds", 2) == 0)
/* only sequences */ /* only sequences */
...@@ -2139,7 +2155,7 @@ HandleSlashCmds(PsqlSettings *pset, ...@@ -2139,7 +2155,7 @@ HandleSlashCmds(PsqlSettings *pset,
strcat(descbuf, optarg2); strcat(descbuf, optarg2);
strcat(descbuf, "' "); strcat(descbuf, "' ");
} }
SendQuery(&success, pset, descbuf, false, false, NULL); success = SendQuery(pset, descbuf, NULL, NULL);
} }
else if (!optarg) else if (!optarg)
/* show tables, sequences and indices */ /* show tables, sequences and indices */
...@@ -2413,7 +2429,6 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source) ...@@ -2413,7 +2429,6 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
char *line; /* line of input */ char *line; /* line of input */
char *xcomment; /* start of extended comment */ char *xcomment; /* start of extended comment */
int len; /* length of the line */ int len; /* length of the line */
bool query_alloced = false;
int successResult = 1; int successResult = 1;
int slashCmdStatus = CMD_SEND; int slashCmdStatus = CMD_SEND;
...@@ -2431,31 +2446,25 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source) ...@@ -2431,31 +2446,25 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
*/ */
bool querySent = false; bool querySent = false;
bool interactive;
READ_ROUTINE GetNextLine; READ_ROUTINE GetNextLine;
bool eof = 0; bool eof = false; /* end of our command input? */
/* We've reached the end of our command input. */
bool success; bool success;
char in_quote; /* == 0 for no in_quote */ char in_quote; /* == 0 for no in_quote */
bool was_bslash; /* backslash */ bool was_bslash; /* backslash */
int paren_level; int paren_level;
char *query_start; char *query_start;
/* Stack the prior command source */
FILE *prev_cmd_source = cur_cmd_source;
bool prev_cmd_interactive = cur_cmd_interactive;
if (query_alloced == false) /* Establish new source */
{ cur_cmd_source = source;
if ((query = malloc(MAX_QUERY_BUFFER)) == NULL) cur_cmd_interactive = ((source == stdin) && !pset->notty);
{
perror("Memory Allocation Failed");
} if ((query = malloc(MAX_QUERY_BUFFER)) == NULL)
else perror("Memory Allocation Failed");
query_alloced = true;
}
interactive = ((source == stdin) && !pset->notty); if (cur_cmd_interactive)
if (interactive)
{ {
if (pset->prompt) if (pset->prompt)
free(pset->prompt); free(pset->prompt);
...@@ -2504,7 +2513,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source) ...@@ -2504,7 +2513,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
} }
else else
{ {
if (interactive && !pset->quiet) if (cur_cmd_interactive && !pset->quiet)
{ {
if (in_quote && in_quote == PROMPT_SINGLEQUOTE) if (in_quote && in_quote == PROMPT_SINGLEQUOTE)
pset->prompt[strlen(pset->prompt) - 3] = PROMPT_SINGLEQUOTE; pset->prompt[strlen(pset->prompt) - 3] = PROMPT_SINGLEQUOTE;
...@@ -2519,7 +2528,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source) ...@@ -2519,7 +2528,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
} }
line = GetNextLine(pset->prompt, source); line = GetNextLine(pset->prompt, source);
#ifdef USE_HISTORY #ifdef USE_HISTORY
if (interactive && pset->useReadline && line != NULL) if (cur_cmd_interactive && pset->useReadline && line != NULL)
add_history(line); /* save non-empty lines in history */ add_history(line); /* save non-empty lines in history */
#endif #endif
} }
...@@ -2528,7 +2537,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source) ...@@ -2528,7 +2537,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
* query - pointer to current command query_start - placeholder * query - pointer to current command query_start - placeholder
* for next command * for next command
*/ */
if (line == NULL || (!interactive && *line == '\0')) if (line == NULL || (!cur_cmd_interactive && *line == '\0'))
{ /* No more input. Time to quit, or \i { /* No more input. Time to quit, or \i
* done */ * done */
if (!pset->quiet) if (!pset->quiet)
...@@ -2554,7 +2563,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source) ...@@ -2554,7 +2563,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
line = rightTrim(line); line = rightTrim(line);
/* echo back if input is from file */ /* echo back if input is from file */
if (!interactive && !pset->singleStep && !pset->quiet) if (!cur_cmd_interactive && !pset->singleStep && !pset->quiet)
fprintf(stderr, "%s\n", line); fprintf(stderr, "%s\n", line);
slashCmdStatus = CMD_UNKNOWN; slashCmdStatus = CMD_UNKNOWN;
...@@ -2569,7 +2578,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source) ...@@ -2569,7 +2578,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
if (pset->singleLineMode) if (pset->singleLineMode)
{ {
SendQuery(&success, pset, line, false, false, NULL); success = SendQuery(pset, line, NULL, NULL);
successResult &= success; successResult &= success;
querySent = true; querySent = true;
} }
...@@ -2697,7 +2706,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source) ...@@ -2697,7 +2706,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
else else
strcpy(query, query_start); strcpy(query, query_start);
} }
SendQuery(&success, pset, query, false, false, NULL); success = SendQuery(pset, query, NULL, NULL);
successResult &= success; successResult &= success;
line[i + 1] = hold_char; line[i + 1] = hold_char;
query_start = line + i + 1; query_start = line + i + 1;
...@@ -2793,7 +2802,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source) ...@@ -2793,7 +2802,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
/* had a backslash-g? force the query to be sent */ /* had a backslash-g? force the query to be sent */
if (slashCmdStatus == CMD_SEND) if (slashCmdStatus == CMD_SEND)
{ {
SendQuery(&success, pset, query, false, false, NULL); success = SendQuery(pset, query, NULL, NULL);
successResult &= success; successResult &= success;
xcomment = NULL; xcomment = NULL;
in_quote = false; in_quote = false;
...@@ -2801,9 +2810,13 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source) ...@@ -2801,9 +2810,13 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
querySent = true; querySent = true;
} }
} /* while */ } /* while */
if (query_alloced)
if (query)
free(query); free(query);
cur_cmd_source = prev_cmd_source;
cur_cmd_interactive = prev_cmd_interactive;
return successResult; return successResult;
} /* MainLoop() */ } /* MainLoop() */
...@@ -3038,12 +3051,7 @@ main(int argc, char **argv) ...@@ -3038,12 +3051,7 @@ main(int argc, char **argv)
else else
{ {
if (singleQuery) if (singleQuery)
{ successResult = SendQuery(&settings, singleQuery, NULL, NULL);
bool success;/* The query succeeded at the backend */
SendQuery(&success, &settings, singleQuery, false, false, NULL);
successResult = success;
}
else else
successResult = MainLoop(&settings, NULL, stdin); successResult = MainLoop(&settings, NULL, stdin);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment