Implement '\copy from -' to support reading copy data from the same
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.
This commit is contained in:
parent
0f8a313508
commit
04cc4e18dd
@ -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
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -705,7 +705,7 @@ testdb=>
|
|||||||
<term><literal>\copy <replaceable class="parameter">table</replaceable>
|
<term><literal>\copy <replaceable class="parameter">table</replaceable>
|
||||||
[ ( <replaceable class="parameter">column_list</replaceable> ) ]
|
[ ( <replaceable class="parameter">column_list</replaceable> ) ]
|
||||||
{ <literal>from</literal> | <literal>to</literal> }
|
{ <literal>from</literal> | <literal>to</literal> }
|
||||||
<replaceable class="parameter">filename</replaceable> | stdin | stdout
|
{ <replaceable class="parameter">filename</replaceable> | stdin | stdout | - }
|
||||||
[ <literal>with</literal> ]
|
[ <literal>with</literal> ]
|
||||||
[ <literal>oids</literal> ]
|
[ <literal>oids</literal> ]
|
||||||
[ <literal>delimiter [as] </literal> '<replaceable class="parameter">character</replaceable>' ]
|
[ <literal>delimiter [as] </literal> '<replaceable class="parameter">character</replaceable>' ]
|
||||||
@ -720,26 +720,41 @@ testdb=>
|
|||||||
reading or writing the specified file,
|
reading or writing the specified file,
|
||||||
<application>psql</application> reads or writes the file and
|
<application>psql</application> reads or writes the file and
|
||||||
routes the data between the server and the local file system.
|
routes the data between the server and the local file system.
|
||||||
This means that file accessibility and privileges are those
|
This means that file accessibility and privileges are those of
|
||||||
of the local user, not the server, and no SQL superuser
|
the local user, not the server, and no SQL superuser
|
||||||
privileges are required.
|
privileges are required.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The syntax of the command is similar to that of the
|
The syntax of the command is similar to that of the
|
||||||
<acronym>SQL</acronym> <command>COPY</command> command. (See its
|
<acronym>SQL</acronym> <xref linkend="sql-copy"
|
||||||
description for the details.) Note that, because of this,
|
endterm="sql-copy-title"> command. Note that, because of this,
|
||||||
special parsing rules apply to the <command>\copy</command>
|
special parsing rules apply to the <command>\copy</command>
|
||||||
command. In particular, the variable substitution rules and
|
command. In particular, the variable substitution rules and
|
||||||
backslash escapes do not apply.
|
backslash escapes do not apply.
|
||||||
</para>
|
</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>
|
<tip>
|
||||||
<para>
|
<para>
|
||||||
This operation is not as efficient as the <acronym>SQL</acronym>
|
This operation is not as efficient as the <acronym>SQL</acronym>
|
||||||
<command>COPY</command> command because all data must pass
|
<command>COPY</command> command because all data must pass
|
||||||
through the client/server connection. For large
|
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>
|
</para>
|
||||||
</tip>
|
</tip>
|
||||||
|
|
||||||
@ -747,11 +762,12 @@ testdb=>
|
|||||||
<para>
|
<para>
|
||||||
Note the difference in interpretation of
|
Note the difference in interpretation of
|
||||||
<literal>stdin</literal> and <literal>stdout</literal> between
|
<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
|
refer to <application>psql</application>'s input and output
|
||||||
stream. On a server copy <literal>stdin</literal> comes from
|
streams. In <command>COPY</command>, <literal>stdin</literal> comes
|
||||||
wherever the <command>COPY</command> itself came from (for
|
from wherever the <command>COPY</command> itself came from (for
|
||||||
example, a script run with the <option>-f</option> option), and
|
example, a script run with the <option>-f</option> option), while
|
||||||
<literal>stdout</literal> refers to the query output stream (see
|
<literal>stdout</literal> refers to the query output stream (see
|
||||||
<command>\o</command> meta-command below).
|
<command>\o</command> meta-command below).
|
||||||
</para>
|
</para>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2003, PostgreSQL Global Development Group
|
* 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 "postgres_fe.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
@ -513,12 +513,7 @@ ProcessCopyResult(PGresult *results)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PGRES_COPY_IN:
|
case PGRES_COPY_IN:
|
||||||
if (pset.cur_cmd_interactive && !QUIET())
|
success = handleCopyIn(pset.db, pset.cur_cmd_source);
|
||||||
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);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2003, PostgreSQL Global Development Group
|
* 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 "postgres_fe.h"
|
||||||
#include "copy.h"
|
#include "copy.h"
|
||||||
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "prompt.h"
|
||||||
#include "stringutils.h"
|
#include "stringutils.h"
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@ -53,6 +54,7 @@ struct copy_options
|
|||||||
char *table;
|
char *table;
|
||||||
char *column_list;
|
char *column_list;
|
||||||
char *file; /* NULL = stdin/stdout */
|
char *file; /* NULL = stdin/stdout */
|
||||||
|
bool in_dash; /* true = use src stream not true stdin */
|
||||||
bool from;
|
bool from;
|
||||||
bool binary;
|
bool binary;
|
||||||
bool oids;
|
bool oids;
|
||||||
@ -218,10 +220,25 @@ parse_slash_copy(const char *args)
|
|||||||
|
|
||||||
if (strcasecmp(token, "stdin") == 0 ||
|
if (strcasecmp(token, "stdin") == 0 ||
|
||||||
strcasecmp(token, "stdout") == 0)
|
strcasecmp(token, "stdout") == 0)
|
||||||
|
{
|
||||||
|
result->in_dash = false;
|
||||||
result->file = NULL;
|
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
|
else
|
||||||
|
{
|
||||||
|
result->in_dash = false;
|
||||||
result->file = xstrdup(token);
|
result->file = xstrdup(token);
|
||||||
expand_tilde(&result->file);
|
expand_tilde(&result->file);
|
||||||
|
}
|
||||||
|
|
||||||
token = strtokx(NULL, whitespace, NULL, NULL,
|
token = strtokx(NULL, whitespace, NULL, NULL,
|
||||||
0, false, pset.encoding);
|
0, false, pset.encoding);
|
||||||
@ -362,6 +379,8 @@ do_copy(const char *args)
|
|||||||
{
|
{
|
||||||
if (options->file)
|
if (options->file)
|
||||||
copystream = fopen(options->file, "r");
|
copystream = fopen(options->file, "r");
|
||||||
|
else if (options->in_dash)
|
||||||
|
copystream = pset.cur_cmd_source;
|
||||||
else
|
else
|
||||||
copystream = stdin;
|
copystream = stdin;
|
||||||
}
|
}
|
||||||
@ -401,7 +420,7 @@ do_copy(const char *args)
|
|||||||
success = handleCopyOut(pset.db, copystream);
|
success = handleCopyOut(pset.db, copystream);
|
||||||
break;
|
break;
|
||||||
case PGRES_COPY_IN:
|
case PGRES_COPY_IN:
|
||||||
success = handleCopyIn(pset.db, copystream, NULL);
|
success = handleCopyIn(pset.db, copystream);
|
||||||
break;
|
break;
|
||||||
case PGRES_NONFATAL_ERROR:
|
case PGRES_NONFATAL_ERROR:
|
||||||
case PGRES_FATAL_ERROR:
|
case PGRES_FATAL_ERROR:
|
||||||
@ -416,7 +435,7 @@ do_copy(const char *args)
|
|||||||
|
|
||||||
PQclear(result);
|
PQclear(result);
|
||||||
|
|
||||||
if (copystream != stdout && copystream != stdin)
|
if (options->file != NULL)
|
||||||
fclose(copystream);
|
fclose(copystream);
|
||||||
free_copy_options(options);
|
free_copy_options(options);
|
||||||
return success;
|
return success;
|
||||||
@ -486,13 +505,12 @@ handleCopyOut(PGconn *conn, FILE *copystream)
|
|||||||
* conn should be a database connection that you just called COPY FROM on
|
* conn should be a database connection that you just called COPY FROM on
|
||||||
* (and which gave you PGRES_COPY_IN back);
|
* (and which gave you PGRES_COPY_IN back);
|
||||||
* copystream is the file stream you want the input to come from
|
* 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
|
bool
|
||||||
handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt)
|
handleCopyIn(PGconn *conn, FILE *copystream)
|
||||||
{
|
{
|
||||||
|
const char *prompt;
|
||||||
bool copydone = false;
|
bool copydone = false;
|
||||||
bool firstload;
|
bool firstload;
|
||||||
bool linedone;
|
bool linedone;
|
||||||
@ -503,9 +521,16 @@ handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt)
|
|||||||
int ret;
|
int ret;
|
||||||
unsigned int linecount = 0;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2003, PostgreSQL Global Development Group
|
* 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
|
#ifndef COPY_H
|
||||||
#define COPY_H
|
#define COPY_H
|
||||||
@ -17,6 +17,6 @@ bool do_copy(const char *args);
|
|||||||
/* lower level processors for copy in/out streams */
|
/* lower level processors for copy in/out streams */
|
||||||
|
|
||||||
bool handleCopyOut(PGconn *conn, FILE *copystream);
|
bool handleCopyOut(PGconn *conn, FILE *copystream);
|
||||||
bool handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt);
|
bool handleCopyIn(PGconn *conn, FILE *copystream);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user