]> granicus.if.org Git - postgresql/commitdiff
Implement '\copy from -' to support reading copy data from the same
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 20 Jan 2004 23:48:56 +0000 (23:48 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 20 Jan 2004 23:48:56 +0000 (23:48 +0000)
source the \copy came from.  Also, fix prompting logic so that initial
and per-line prompts appear for all cases of reading from an interactive
terminal.  Patch by Mark Feit, with some kibitzing by Tom Lane.

doc/src/sgml/ref/psql-ref.sgml
src/bin/psql/common.c
src/bin/psql/copy.c
src/bin/psql/copy.h

index 50ea0c910ee9b7be16017c86b2ea7b626f7e32e4..2e17c0310a08efb666e1267cd81f522d99b6ee03 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.103 2004/01/20 19:49:34 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.104 2004/01/20 23:48:56 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -705,7 +705,7 @@ testdb=>
         <term><literal>\copy <replaceable class="parameter">table</replaceable>
        [ ( <replaceable class="parameter">column_list</replaceable> ) ]
         { <literal>from</literal> | <literal>to</literal> }
-       <replaceable class="parameter">filename</replaceable> | stdin | stdout
+       { <replaceable class="parameter">filename</replaceable> | stdin | stdout | - }
         [ <literal>with</literal> ] 
             [ <literal>oids</literal> ] 
             [ <literal>delimiter [as] </literal> '<replaceable class="parameter">character</replaceable>' ]
@@ -720,26 +720,41 @@ testdb=>
         reading or writing the specified file,
         <application>psql</application> reads or writes the file and
         routes the data between the server and the local file system.
-       This means that file accessibility and privileges are those
-       of the local user, not the server, and no SQL superuser
-       privileges are required.
+        This means that file accessibility and privileges are those of
+        the local user, not the server, and no SQL superuser
+        privileges are required.
        </para>
 
        <para>
        The syntax of the command is similar to that of the
-       <acronym>SQL</acronym> <command>COPY</command> command.  (See its
-       description for the details.)  Note that, because of this,
+       <acronym>SQL</acronym> <xref linkend="sql-copy"
+       endterm="sql-copy-title"> command.  Note that, because of this,
        special parsing rules apply to the <command>\copy</command>
        command. In particular, the variable substitution rules and
        backslash escapes do not apply.
        </para>
 
+       <para>
+       For <literal>\copy <replaceable
+       class="parameter">table</replaceable> from <replaceable
+       class="parameter">filename</replaceable></literal> operations,
+       <application>psql</application> adds the option of using a
+       hyphen instead of <replaceable
+       class="parameter">filename</replaceable>.  This causes
+       <literal>\copy</literal> to read rows from the same source that
+       issued the command, continuing until <literal>\.</literal> is
+       read or the stream reaches <acronym>EOF</>.  This option is
+       useful for populating tables in-line within a SQL script file.
+       In contrast, <literal>\copy from stdin</> always reads from
+       <application>psql</application>'s standard input.
+       </para>
+
         <tip>
         <para>
        This operation is not as efficient as the <acronym>SQL</acronym>
        <command>COPY</command> command because all data must pass
        through the client/server connection. For large
-       amounts of data the other technique may be preferable.
+       amounts of data the <acronym>SQL</acronym> command may be preferable.
         </para>
         </tip>
 
@@ -747,11 +762,12 @@ testdb=>
         <para>
         Note the difference in interpretation of
         <literal>stdin</literal> and <literal>stdout</literal> between
-        client and server copies: in a client copy these always
+       <literal>\copy</literal> and <command>COPY</command>.
+       In <literal>\copy</literal> these always
         refer to <application>psql</application>'s input and output
-        stream. On a server copy <literal>stdin</literal> comes from
-        wherever the <command>COPY</command> itself came from (for
-        example, a script run with the <option>-f</option> option), and
+        streams. In <command>COPY</command>, <literal>stdin</literal> comes
+       from wherever the <command>COPY</command> itself came from (for
+        example, a script run with the <option>-f</option> option), while
         <literal>stdout</literal> refers to the query output stream (see
         <command>\o</command> meta-command below).
         </para>
index 1e113ac49aa21ad73c3c0c0e9fc2c992b4fbcb73..ed3649dfe1dc52c8b662d58985d84b160fae4e8a 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2003, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.79 2004/01/09 21:12:20 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.80 2004/01/20 23:48:56 tgl Exp $
  */
 #include "postgres_fe.h"
 #include "common.h"
@@ -513,12 +513,7 @@ ProcessCopyResult(PGresult *results)
                        break;
 
                case PGRES_COPY_IN:
-                       if (pset.cur_cmd_interactive && !QUIET())
-                               puts(gettext("Enter data to be copied followed by a newline.\n"
-                                                        "End with a backslash and a period on a line by itself."));
-
-                       success = handleCopyIn(pset.db, pset.cur_cmd_source,
-                         pset.cur_cmd_interactive ? get_prompt(PROMPT_COPY) : NULL);
+                       success = handleCopyIn(pset.db, pset.cur_cmd_source);
                        break;
 
                default:
index 36937d2606e47db4237a54498c534adabd3fb467..e852dd5b7a1948964565eca45335803c689000af 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2003, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.36 2004/01/09 21:12:20 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.37 2004/01/20 23:48:56 tgl Exp $
  */
 #include "postgres_fe.h"
 #include "copy.h"
@@ -23,6 +23,7 @@
 
 #include "settings.h"
 #include "common.h"
+#include "prompt.h"
 #include "stringutils.h"
 
 #ifdef WIN32
@@ -53,6 +54,7 @@ struct copy_options
        char       *table;
        char       *column_list;
        char       *file;                       /* NULL = stdin/stdout */
+       bool            in_dash;                /* true = use src stream not true stdin */
        bool            from;
        bool            binary;
        bool            oids;
@@ -218,10 +220,25 @@ parse_slash_copy(const char *args)
 
        if (strcasecmp(token, "stdin") == 0 ||
                strcasecmp(token, "stdout") == 0)
+       {
+               result->in_dash = false;
+               result->file = NULL;
+       }
+       else if (strcmp(token, "-") == 0)
+       {
+               /* Can't do this on output */
+               if (!result->from)
+                       goto error;
+
+               result->in_dash = true;
                result->file = NULL;
+       }
        else
+       {
+               result->in_dash = false;
                result->file = xstrdup(token);
-       expand_tilde(&result->file);
+               expand_tilde(&result->file);
+       }
 
        token = strtokx(NULL, whitespace, NULL, NULL,
                                        0, false, pset.encoding);
@@ -362,8 +379,10 @@ do_copy(const char *args)
        {
                if (options->file)
                        copystream = fopen(options->file, "r");
+               else if (options->in_dash)
+                       copystream = pset.cur_cmd_source;
                else
-                       copystream = stdin;
+                       copystream = stdin;
        }
        else
        {
@@ -401,7 +420,7 @@ do_copy(const char *args)
                        success = handleCopyOut(pset.db, copystream);
                        break;
                case PGRES_COPY_IN:
-                       success = handleCopyIn(pset.db, copystream, NULL);
+                       success = handleCopyIn(pset.db, copystream);
                        break;
                case PGRES_NONFATAL_ERROR:
                case PGRES_FATAL_ERROR:
@@ -416,7 +435,7 @@ do_copy(const char *args)
 
        PQclear(result);
 
-       if (copystream != stdout && copystream != stdin)
+       if (options->file != NULL)
                fclose(copystream);
        free_copy_options(options);
        return success;
@@ -486,13 +505,12 @@ handleCopyOut(PGconn *conn, FILE *copystream)
  * conn should be a database connection that you just called COPY FROM on
  * (and which gave you PGRES_COPY_IN back);
  * copystream is the file stream you want the input to come from
- * prompt is something to display to request user input (only makes sense
- *      if stdin is an interactive tty)
  */
 
 bool
-handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt)
+handleCopyIn(PGconn *conn, FILE *copystream)
 {
+       const char *prompt;
        bool            copydone = false;
        bool            firstload;
        bool            linedone;
@@ -503,10 +521,17 @@ handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt)
        int                     ret;
        unsigned int linecount = 0;
 
-       if (prompt)                                     /* disable prompt if not interactive */
+       /* Prompt if interactive input */
+       if (isatty(fileno(copystream)))
+       {
+               if (!QUIET())
+                       puts(gettext("Enter data to be copied followed by a newline.\n"
+                               "End with a backslash and a period on a line by itself."));
+               prompt = get_prompt(PROMPT_COPY);
+       }
+       else
        {
-               if (!isatty(fileno(copystream)))
-                       prompt = NULL;
+               prompt = NULL;
        }
 
        while (!copydone)
index 0f6a688796993cf23be90fc5ea6ce09f50f06190..8daf4a2609afd9327db19c19d14aaf4a9990558c 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2003, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/copy.h,v 1.14 2003/11/29 19:52:06 pgsql Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/copy.h,v 1.15 2004/01/20 23:48:56 tgl Exp $
  */
 #ifndef COPY_H
 #define COPY_H
@@ -17,6 +17,6 @@ bool          do_copy(const char *args);
 /* lower level processors for copy in/out streams */
 
 bool           handleCopyOut(PGconn *conn, FILE *copystream);
-bool           handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt);
+bool           handleCopyIn(PGconn *conn, FILE *copystream);
 
 #endif