Skip to content

Commit 1ae6739

Browse files
committed
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.
1 parent 99e57ee commit 1ae6739

File tree

1 file changed

+73
-65
lines changed

1 file changed

+73
-65
lines changed

src/bin/psql/psql.c

Lines changed: 73 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.174 1999/03/30 05:00:42 ishii Exp $
10+
* $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.175 1999/04/15 02:24:41 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -142,6 +142,17 @@ typedef struct _psqlSettings
142142
* password */
143143
} PsqlSettings;
144144

145+
/*
146+
* cur_cmd_source and cur_cmd_interactive are the top of a stack of
147+
* source files (one stack level per recursive invocation of MainLoop).
148+
* It's kinda grotty to make these global variables, but the alternative
149+
* of passing them around through many function parameter lists seems
150+
* worse.
151+
*/
152+
static FILE * cur_cmd_source = stdin; /* current source of command input */
153+
static bool cur_cmd_interactive = false; /* is it an interactive source? */
154+
155+
145156
#ifdef TIOCGWINSZ
146157
struct winsize screen_size;
147158

@@ -172,10 +183,9 @@ static char *gets_noreadline(char *prompt, FILE *source);
172183
static char *gets_readline(char *prompt, FILE *source);
173184
static char *gets_fromFile(char *prompt, FILE *source);
174185
static int listAllDbs(PsqlSettings *pset);
175-
static void SendQuery(bool *success_p, PsqlSettings *pset, const char *query,
176-
const bool copy_in, const bool copy_out, FILE *copystream);
177-
static int
178-
HandleSlashCmds(PsqlSettings *pset, char *line, char *query);
186+
static bool SendQuery(PsqlSettings *pset, const char *query,
187+
FILE *copy_in_stream, FILE *copy_out_stream);
188+
static int HandleSlashCmds(PsqlSettings *pset, char *line, char *query);
179189
static int MainLoop(PsqlSettings *pset, char *query, FILE *source);
180190
static FILE *setFout(PsqlSettings *pset, char *fname);
181191

@@ -1059,7 +1069,7 @@ objectDescription(PsqlSettings *pset, char *object)
10591069

10601070
PQclear(res);
10611071

1062-
SendQuery(&success, pset, descbuf, false, false, NULL);
1072+
success = SendQuery(pset, descbuf, NULL, NULL);
10631073

10641074
return 0;
10651075
}
@@ -1132,14 +1142,18 @@ gets_fromFile(char *prompt, FILE *source)
11321142
}
11331143

11341144
/*
1135-
* SendQuery: send the query string to the backend return *success_p = 1 if
1136-
* the query executed successfully returns *success_p = 0 otherwise
1145+
* SendQuery: send the query string to the backend.
1146+
*
1147+
* Return true if the query executed successfully, false otherwise.
1148+
*
1149+
* If not NULL, copy_in_stream and copy_out_stream are files to redirect
1150+
* copy in/out data to.
11371151
*/
1138-
static void
1139-
SendQuery(bool *success_p, PsqlSettings *pset, const char *query,
1140-
const bool copy_in, const bool copy_out, FILE *copystream)
1152+
static bool
1153+
SendQuery(PsqlSettings *pset, const char *query,
1154+
FILE *copy_in_stream, FILE *copy_out_stream)
11411155
{
1142-
1156+
bool success = false;
11431157
PGresult *results;
11441158
PGnotify *notify;
11451159

@@ -1164,7 +1178,7 @@ SendQuery(bool *success_p, PsqlSettings *pset, const char *query,
11641178
if (results == NULL)
11651179
{
11661180
fprintf(stderr, "%s", PQerrorMessage(pset->db));
1167-
*success_p = false;
1181+
success = false;
11681182
}
11691183
else
11701184
{
@@ -1180,11 +1194,9 @@ SendQuery(bool *success_p, PsqlSettings *pset, const char *query,
11801194
fp = setFout(&settings_copy, pset->gfname);
11811195
if (!fp || fp == stdout)
11821196
{
1183-
*success_p = false;
1197+
success = false;
11841198
break;
11851199
}
1186-
else
1187-
*success_p = true;
11881200
PQprint(fp,
11891201
results,
11901202
&pset->opt);
@@ -1194,48 +1206,49 @@ SendQuery(bool *success_p, PsqlSettings *pset, const char *query,
11941206
fclose(fp);
11951207
free(pset->gfname);
11961208
pset->gfname = NULL;
1209+
success = true;
11971210
break;
11981211
}
11991212
else
12001213
{
1201-
*success_p = true;
1214+
success = true;
12021215
PQprint(pset->queryFout,
12031216
results,
12041217
&(pset->opt));
12051218
fflush(pset->queryFout);
12061219
}
12071220
break;
12081221
case PGRES_EMPTY_QUERY:
1209-
*success_p = true;
1222+
success = true;
12101223
break;
12111224
case PGRES_COMMAND_OK:
1212-
*success_p = true;
1225+
success = true;
12131226
if (!pset->quiet)
12141227
printf("%s\n", PQcmdStatus(results));
12151228
break;
12161229
case PGRES_COPY_OUT:
1217-
if (copy_out)
1218-
*success_p = handleCopyOut(pset->db, copystream);
1230+
if (copy_out_stream)
1231+
success = handleCopyOut(pset->db, copy_out_stream);
12191232
else
12201233
{
1221-
if (!pset->quiet)
1234+
if (pset->queryFout == stdout && !pset->quiet)
12221235
printf("Copy command returns...\n");
12231236

1224-
*success_p = handleCopyOut(pset->db, stdout);
1237+
success = handleCopyOut(pset->db, pset->queryFout);
12251238
}
12261239
break;
12271240
case PGRES_COPY_IN:
1228-
if (copy_in)
1229-
*success_p = handleCopyIn(pset->db, false, copystream);
1241+
if (copy_in_stream)
1242+
success = handleCopyIn(pset->db, false, copy_in_stream);
12301243
else
1231-
*success_p = handleCopyIn(pset->db,
1232-
!pset->quiet && !pset->notty,
1233-
stdin);
1244+
success = handleCopyIn(pset->db,
1245+
cur_cmd_interactive && !pset->quiet,
1246+
cur_cmd_source);
12341247
break;
12351248
case PGRES_NONFATAL_ERROR:
12361249
case PGRES_FATAL_ERROR:
12371250
case PGRES_BAD_RESPONSE:
1238-
*success_p = false;
1251+
success = false;
12391252
fprintf(stderr, "%s", PQerrorMessage(pset->db));
12401253
break;
12411254
}
@@ -1259,6 +1272,7 @@ SendQuery(bool *success_p, PsqlSettings *pset, const char *query,
12591272
if (results)
12601273
PQclear(results);
12611274
}
1275+
return success;
12621276
}
12631277

12641278

@@ -1495,7 +1509,9 @@ do_copy(const char *args, PsqlSettings *pset)
14951509
{
14961510
bool success;/* The query succeeded at the backend */
14971511

1498-
SendQuery(&success, pset, query, from, !from, copystream);
1512+
success = SendQuery(pset, query,
1513+
from ? copystream : (FILE*) NULL,
1514+
!from ? copystream : (FILE*) NULL);
14991515
fclose(copystream);
15001516
if (!pset->quiet)
15011517
{
@@ -1999,7 +2015,7 @@ HandleSlashCmds(PsqlSettings *pset,
19992015
strcat(descbuf, "' ");
20002016
}
20012017
strcat(descbuf, "ORDER BY aggname, type;");
2002-
SendQuery(&success, pset, descbuf, false, false, NULL);
2018+
success = SendQuery(pset, descbuf, NULL, NULL);
20032019
}
20042020
else if (strncmp(cmd, "dd", 2) == 0)
20052021
/* descriptions */
@@ -2036,7 +2052,7 @@ HandleSlashCmds(PsqlSettings *pset,
20362052
strcat(descbuf, "' ");
20372053
}
20382054
strcat(descbuf, "ORDER BY result, function, arguments;");
2039-
SendQuery(&success, pset, descbuf, false, false, NULL);
2055+
success = SendQuery(pset, descbuf, NULL, NULL);
20402056
}
20412057
else if (strncmp(cmd, "di", 2) == 0)
20422058
/* only indices */
@@ -2110,7 +2126,7 @@ HandleSlashCmds(PsqlSettings *pset,
21102126
strcat(descbuf, "' ");
21112127
}
21122128
strcat(descbuf, "ORDER BY op, left_arg, right_arg, result;");
2113-
SendQuery(&success, pset, descbuf, false, false, NULL);
2129+
success = SendQuery(pset, descbuf, NULL, NULL);
21142130
}
21152131
else if (strncmp(cmd, "ds", 2) == 0)
21162132
/* only sequences */
@@ -2139,7 +2155,7 @@ HandleSlashCmds(PsqlSettings *pset,
21392155
strcat(descbuf, optarg2);
21402156
strcat(descbuf, "' ");
21412157
}
2142-
SendQuery(&success, pset, descbuf, false, false, NULL);
2158+
success = SendQuery(pset, descbuf, NULL, NULL);
21432159
}
21442160
else if (!optarg)
21452161
/* show tables, sequences and indices */
@@ -2413,7 +2429,6 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
24132429
char *line; /* line of input */
24142430
char *xcomment; /* start of extended comment */
24152431
int len; /* length of the line */
2416-
bool query_alloced = false;
24172432
int successResult = 1;
24182433
int slashCmdStatus = CMD_SEND;
24192434

@@ -2431,31 +2446,25 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
24312446
*/
24322447

24332448
bool querySent = false;
2434-
bool interactive;
24352449
READ_ROUTINE GetNextLine;
2436-
bool eof = 0;
2437-
2438-
/* We've reached the end of our command input. */
2450+
bool eof = false; /* end of our command input? */
24392451
bool success;
24402452
char in_quote; /* == 0 for no in_quote */
24412453
bool was_bslash; /* backslash */
24422454
int paren_level;
24432455
char *query_start;
2456+
/* Stack the prior command source */
2457+
FILE *prev_cmd_source = cur_cmd_source;
2458+
bool prev_cmd_interactive = cur_cmd_interactive;
24442459

2445-
if (query_alloced == false)
2446-
{
2447-
if ((query = malloc(MAX_QUERY_BUFFER)) == NULL)
2448-
{
2449-
2450-
perror("Memory Allocation Failed");
2460+
/* Establish new source */
2461+
cur_cmd_source = source;
2462+
cur_cmd_interactive = ((source == stdin) && !pset->notty);
24512463

2452-
}
2453-
else
2454-
query_alloced = true;
2455-
}
2464+
if ((query = malloc(MAX_QUERY_BUFFER)) == NULL)
2465+
perror("Memory Allocation Failed");
24562466

2457-
interactive = ((source == stdin) && !pset->notty);
2458-
if (interactive)
2467+
if (cur_cmd_interactive)
24592468
{
24602469
if (pset->prompt)
24612470
free(pset->prompt);
@@ -2504,7 +2513,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
25042513
}
25052514
else
25062515
{
2507-
if (interactive && !pset->quiet)
2516+
if (cur_cmd_interactive && !pset->quiet)
25082517
{
25092518
if (in_quote && in_quote == PROMPT_SINGLEQUOTE)
25102519
pset->prompt[strlen(pset->prompt) - 3] = PROMPT_SINGLEQUOTE;
@@ -2519,7 +2528,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
25192528
}
25202529
line = GetNextLine(pset->prompt, source);
25212530
#ifdef USE_HISTORY
2522-
if (interactive && pset->useReadline && line != NULL)
2531+
if (cur_cmd_interactive && pset->useReadline && line != NULL)
25232532
add_history(line); /* save non-empty lines in history */
25242533
#endif
25252534
}
@@ -2528,7 +2537,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
25282537
* query - pointer to current command query_start - placeholder
25292538
* for next command
25302539
*/
2531-
if (line == NULL || (!interactive && *line == '\0'))
2540+
if (line == NULL || (!cur_cmd_interactive && *line == '\0'))
25322541
{ /* No more input. Time to quit, or \i
25332542
* done */
25342543
if (!pset->quiet)
@@ -2554,7 +2563,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
25542563
line = rightTrim(line);
25552564

25562565
/* echo back if input is from file */
2557-
if (!interactive && !pset->singleStep && !pset->quiet)
2566+
if (!cur_cmd_interactive && !pset->singleStep && !pset->quiet)
25582567
fprintf(stderr, "%s\n", line);
25592568

25602569
slashCmdStatus = CMD_UNKNOWN;
@@ -2569,7 +2578,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
25692578

25702579
if (pset->singleLineMode)
25712580
{
2572-
SendQuery(&success, pset, line, false, false, NULL);
2581+
success = SendQuery(pset, line, NULL, NULL);
25732582
successResult &= success;
25742583
querySent = true;
25752584
}
@@ -2697,7 +2706,7 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
26972706
else
26982707
strcpy(query, query_start);
26992708
}
2700-
SendQuery(&success, pset, query, false, false, NULL);
2709+
success = SendQuery(pset, query, NULL, NULL);
27012710
successResult &= success;
27022711
line[i + 1] = hold_char;
27032712
query_start = line + i + 1;
@@ -2793,17 +2802,21 @@ MainLoop(PsqlSettings *pset, char *query, FILE *source)
27932802
/* had a backslash-g? force the query to be sent */
27942803
if (slashCmdStatus == CMD_SEND)
27952804
{
2796-
SendQuery(&success, pset, query, false, false, NULL);
2805+
success = SendQuery(pset, query, NULL, NULL);
27972806
successResult &= success;
27982807
xcomment = NULL;
27992808
in_quote = false;
28002809
paren_level = 0;
28012810
querySent = true;
28022811
}
28032812
} /* while */
2804-
if (query_alloced)
2813+
2814+
if (query)
28052815
free(query);
28062816

2817+
cur_cmd_source = prev_cmd_source;
2818+
cur_cmd_interactive = prev_cmd_interactive;
2819+
28072820
return successResult;
28082821
} /* MainLoop() */
28092822

@@ -3038,12 +3051,7 @@ main(int argc, char **argv)
30383051
else
30393052
{
30403053
if (singleQuery)
3041-
{
3042-
bool success;/* The query succeeded at the backend */
3043-
3044-
SendQuery(&success, &settings, singleQuery, false, false, NULL);
3045-
successResult = success;
3046-
}
3054+
successResult = SendQuery(&settings, singleQuery, NULL, NULL);
30473055
else
30483056
successResult = MainLoop(&settings, NULL, stdin);
30493057
}

0 commit comments

Comments
 (0)