]> granicus.if.org Git - postgresql/commitdiff
Fix tracking of psql script line numbers during \copy from another place.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 10 Mar 2014 19:47:06 +0000 (15:47 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 10 Mar 2014 19:47:40 +0000 (15:47 -0400)
Commit 08146775acd8bfe0fcc509c71857abb928697171 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.

src/bin/psql/common.c
src/bin/psql/copy.c
src/bin/psql/settings.h
src/bin/psql/startup.c

index 3a820faf78f877b4f7b7b87a5dc6a679b466d693..6ca9bbc9d86161ce530c04ee6891c37eb97951ab 100644 (file)
@@ -628,7 +628,7 @@ StoreQueryTuple(const PGresult *result)
  * command.  In that event, we'll marshal data for the COPY and then cycle
  * through any subsequent PGresult objects.
  *
- * When the command string contained no affected COPY command, this function
+ * When the command string contained no such COPY command, this function
  * degenerates to an AcceptResult() call.
  *
  * Changes its argument to point to the last PGresult of the command string,
@@ -688,13 +688,28 @@ ProcessResult(PGresult **results)
                         * Marshal the COPY data.  Either subroutine will get the
                         * connection out of its COPY state, then call PQresultStatus()
                         * once and report any error.
+                        *
+                        * If pset.copyStream is set, use that as data source/sink,
+                        * otherwise use queryFout or cur_cmd_source as appropriate.
                         */
+                       FILE       *copystream = pset.copyStream;
+
                        SetCancelConn();
                        if (result_status == PGRES_COPY_OUT)
-                               success = handleCopyOut(pset.db, pset.queryFout) && success;
+                       {
+                               if (!copystream)
+                                       copystream = pset.queryFout;
+                               success = handleCopyOut(pset.db,
+                                                                               copystream) && success;
+                       }
                        else
-                               success = handleCopyIn(pset.db, pset.cur_cmd_source,
+                       {
+                               if (!copystream)
+                                       copystream = pset.cur_cmd_source;
+                               success = handleCopyIn(pset.db,
+                                                                          copystream,
                                                                           PQbinaryTuples(*results)) && success;
+                       }
                        ResetCancelConn();
 
                        /*
index 9e815b136ed4666f1f8dc930f819b746798c34b9..a058f2ff0d43a5fc9d66bec6882264c31331e72d 100644 (file)
@@ -269,11 +269,8 @@ do_copy(const char *args)
 {
        PQExpBufferData query;
        FILE       *copystream;
-       FILE       *save_file;
-       FILE      **override_file;
        struct copy_options *options;
        bool            success;
-       struct stat st;
 
        /* parse options */
        options = parse_slash_copy(args);
@@ -287,8 +284,6 @@ do_copy(const char *args)
 
        if (options->from)
        {
-               override_file = &pset.cur_cmd_source;
-
                if (options->file)
                {
                        if (options->program)
@@ -308,8 +303,6 @@ do_copy(const char *args)
        }
        else
        {
-               override_file = &pset.queryFout;
-
                if (options->file)
                {
                        if (options->program)
@@ -345,6 +338,7 @@ do_copy(const char *args)
 
        if (!options->program)
        {
+               struct stat st;
                int result;
 
                /* make sure the specified file is not a directory */
@@ -375,11 +369,10 @@ do_copy(const char *args)
        if (options->after_tofrom)
                appendPQExpBufferStr(&query, options->after_tofrom);
 
-       /* Run it like a user command, interposing the data source or sink. */
-       save_file = *override_file;
-       *override_file = copystream;
+       /* run it like a user command, but with copystream as data source/sink */
+       pset.copyStream = copystream;
        success = SendQuery(query.data);
-       *override_file = save_file;
+       pset.copyStream = NULL;
        termPQExpBuffer(&query);
 
        if (options->file != NULL)
index 3e8328db9abea8b71579eb93301c5cc4f223f934..eecffb10736c63d6ee62d1008422ad1a4d6a11af 100644 (file)
@@ -70,6 +70,8 @@ typedef struct _psqlSettings
        FILE       *queryFout;          /* where to send the query results */
        bool            queryFoutPipe;  /* queryFout is from a popen() */
 
+       FILE       *copyStream;         /* Stream to read/write for \copy command */
+
        printQueryOpt popt;
 
        char       *gfname;                     /* one-shot file output argument for \g */
index d5f1c0d4088a80ee5f667a8974d8c40f2c6c3e66..45653a15a806a72676e97b24b0655237fe15b5a3 100644 (file)
@@ -118,6 +118,7 @@ main(int argc, char *argv[])
        pset.encoding = PQenv2encoding();
        pset.queryFout = stdout;
        pset.queryFoutPipe = false;
+       pset.copyStream = NULL;
        pset.cur_cmd_source = stdin;
        pset.cur_cmd_interactive = false;