Skip to content

Commit b315b76

Browse files
committed
Fix tracking of psql script line numbers during \copy from another place.
Commit 0814677 changed do_copy() to temporarily scribble on pset.cur_cmd_source. That was a mighty ugly bit of code in any case, but in particular it broke handleCopyIn's ability to tell whether it was reading from the current script source file (in which case pset.lineno should be incremented for each line of COPY data), or from someplace else (in which case it shouldn't). The former case still worked, the latter not so much. The visible effect was that line numbers reported for errors in a script file would be wrong if there were an earlier \copy that was reading anything other than inline-in-the-script-file data. To fix, introduce another pset field that holds the file do_copy wants the COPY code to use. This is a little bit ugly, but less so than passing the file down explicitly through several layers that aren't COPY-specific. Extracted from a larger patch by Kumar Rajeev Rastogi; that patch also changes printing of COPY command tags, which is not a bug fix and shouldn't get back-patched. This particular idea was from a suggestion by Amit Khandekar, if I'm reading the thread correctly. Back-patch to 9.2 where the faulty code was introduced.
1 parent 2570d93 commit b315b76

File tree

4 files changed

+24
-13
lines changed

4 files changed

+24
-13
lines changed

src/bin/psql/common.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ PrintQueryTuples(const PGresult *results)
639639
* command. In that event, we'll marshal data for the COPY and then cycle
640640
* through any subsequent PGresult objects.
641641
*
642-
* When the command string contained no affected COPY command, this function
642+
* When the command string contained no such COPY command, this function
643643
* degenerates to an AcceptResult() call.
644644
*
645645
* Changes its argument to point to the last PGresult of the command string,
@@ -699,13 +699,28 @@ ProcessResult(PGresult **results)
699699
* Marshal the COPY data. Either subroutine will get the
700700
* connection out of its COPY state, then call PQresultStatus()
701701
* once and report any error.
702+
*
703+
* If pset.copyStream is set, use that as data source/sink,
704+
* otherwise use queryFout or cur_cmd_source as appropriate.
702705
*/
706+
FILE *copystream = pset.copyStream;
707+
703708
SetCancelConn();
704709
if (result_status == PGRES_COPY_OUT)
705-
success = handleCopyOut(pset.db, pset.queryFout) && success;
710+
{
711+
if (!copystream)
712+
copystream = pset.queryFout;
713+
success = handleCopyOut(pset.db,
714+
copystream) && success;
715+
}
706716
else
707-
success = handleCopyIn(pset.db, pset.cur_cmd_source,
717+
{
718+
if (!copystream)
719+
copystream = pset.cur_cmd_source;
720+
success = handleCopyIn(pset.db,
721+
copystream,
708722
PQbinaryTuples(*results)) && success;
723+
}
709724
ResetCancelConn();
710725

711726
/*

src/bin/psql/copy.c

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,6 @@ do_copy(const char *args)
244244
{
245245
PQExpBufferData query;
246246
FILE *copystream;
247-
FILE *save_file;
248-
FILE **override_file;
249247
struct copy_options *options;
250248
bool success;
251249
struct stat st;
@@ -262,8 +260,6 @@ do_copy(const char *args)
262260

263261
if (options->from)
264262
{
265-
override_file = &pset.cur_cmd_source;
266-
267263
if (options->file)
268264
copystream = fopen(options->file, PG_BINARY_R);
269265
else if (!options->psql_inout)
@@ -273,8 +269,6 @@ do_copy(const char *args)
273269
}
274270
else
275271
{
276-
override_file = &pset.queryFout;
277-
278272
if (options->file)
279273
copystream = fopen(options->file, PG_BINARY_W);
280274
else if (!options->psql_inout)
@@ -313,11 +307,10 @@ do_copy(const char *args)
313307
if (options->after_tofrom)
314308
appendPQExpBufferStr(&query, options->after_tofrom);
315309

316-
/* Run it like a user command, interposing the data source or sink. */
317-
save_file = *override_file;
318-
*override_file = copystream;
310+
/* run it like a user command, but with copystream as data source/sink */
311+
pset.copyStream = copystream;
319312
success = SendQuery(query.data);
320-
*override_file = save_file;
313+
pset.copyStream = NULL;
321314
termPQExpBuffer(&query);
322315

323316
if (options->file != NULL)

src/bin/psql/settings.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ typedef struct _psqlSettings
7070
FILE *queryFout; /* where to send the query results */
7171
bool queryFoutPipe; /* queryFout is from a popen() */
7272

73+
FILE *copyStream; /* Stream to read/write for \copy command */
74+
7375
printQueryOpt popt;
7476

7577
char *gfname; /* one-shot file output argument for \g */

src/bin/psql/startup.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ main(int argc, char *argv[])
120120
pset.encoding = PQenv2encoding();
121121
pset.queryFout = stdout;
122122
pset.queryFoutPipe = false;
123+
pset.copyStream = NULL;
123124
pset.cur_cmd_source = stdin;
124125
pset.cur_cmd_interactive = false;
125126

0 commit comments

Comments
 (0)