Commit a90db34b authored by Bruce Momjian's avatar Bruce Momjian

The attached patch (against HEAD) implements

  COPY x (a,d,c,b) from stdin;
  COPY x (a,c) to stdout;

as well as the corresponding changes to pg_dump to use the new
functionality.  This functionality is not available when using
the BINARY option.  If a column is not specified in the COPY FROM
statement, its default values will be used.

In addition to this functionality, I tweaked a couple of the
error messages emitted by the new COPY <options> checks.

Brent Verner
parent fc5372e0
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/copy.sgml,v 1.32 2002/06/20 16:00:43 momjian Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/ref/copy.sgml,v 1.33 2002/07/18 04:43:50 momjian Exp $
PostgreSQL documentation
-->
......@@ -21,7 +21,8 @@ PostgreSQL documentation
<date>1999-12-11</date>
</refsynopsisdivinfo>
<synopsis>
COPY <replaceable class="parameter">table</replaceable>
COPY <replaceable class="parameter">table</replaceable>
[ ( <replaceable class="parameter">column</replaceable> [, ...] ) ]
FROM { '<replaceable class="parameter">filename</replaceable>' | <filename>stdin</filename> }
[ [ WITH ]
[ BINARY ]
......@@ -29,6 +30,7 @@ COPY <replaceable class="parameter">table</replaceable>
[ DELIMITER [ AS ] '<replaceable class="parameter">delimiter</replaceable>' ]
[ NULL [ AS ] '<replaceable class="parameter">null string</replaceable>' ] ]
COPY <replaceable class="parameter">table</replaceable>
[ ( <replaceable class="parameter">column</replaceable> [, ...] ) ]
TO { '<replaceable class="parameter">filename</replaceable>' | <filename>stdout</filename> }
[ [ WITH ]
[ BINARY ]
......@@ -55,6 +57,16 @@ COPY <replaceable class="parameter">table</replaceable>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">column list</replaceable></term>
<listitem>
<para>
An optional list of columns to be copied. If no column list is
specified, all columns will be used.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">filename</replaceable></term>
......@@ -187,6 +199,14 @@ ERROR: <replaceable>reason</replaceable>
whatever is in the table already).
</para>
<para>
When using the optional column list syntax, <command>COPY TO</command>
and <command>COPY FROM</command> will only copy the specified
columns' values to/from the table. If a column in the table
is not in the column list, <command>COPY FROM</command> will insert
default values for that column if a default value is defined.
</para>
<para>
<command>COPY</command> with a file name instructs the
<productname>PostgreSQL</productname> backend to directly read from
......
This diff is collapsed.
......@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.343 2002/07/18 04:41:45 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.344 2002/07/18 04:43:50 momjian Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
......@@ -1262,31 +1262,32 @@ opt_id: ColId { $$ = $1; }
/*****************************************************************************
*
* QUERY :
* COPY <relname> FROM/TO [WITH options]
* COPY <relname> ['(' columnList ')'] FROM/TO [WITH options]
*
* BINARY, OIDS, and DELIMITERS kept in old locations
* for backward compatibility. 2002-06-18
*
*****************************************************************************/
CopyStmt: COPY opt_binary qualified_name opt_oids copy_from
copy_file_name copy_delimiter opt_with copy_opt_list
CopyStmt: COPY opt_binary qualified_name opt_column_list opt_oids
copy_from copy_file_name copy_delimiter opt_with copy_opt_list
{
CopyStmt *n = makeNode(CopyStmt);
n->relation = $3;
n->is_from = $5;
n->filename = $6;
n->attlist = $4;
n->is_from = $6;
n->filename = $7;
n->options = NIL;
/* Concatenate user-supplied flags */
if ($2)
n->options = lappend(n->options, $2);
if ($4)
n->options = lappend(n->options, $4);
if ($7)
n->options = lappend(n->options, $7);
if ($9)
n->options = nconc(n->options, $9);
if ($5)
n->options = lappend(n->options, $5);
if ($8)
n->options = lappend(n->options, $8);
if ($10)
n->options = nconc(n->options, $10);
$$ = (Node *)n;
}
;
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.103 2002/06/20 20:29:34 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.104 2002/07/18 04:43:50 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -43,7 +43,6 @@ static List *adjustJoinTreeList(Query *parsetree, bool removert, int rt_index);
static void rewriteTargetList(Query *parsetree, Relation target_relation);
static TargetEntry *process_matched_tle(TargetEntry *src_tle,
TargetEntry *prior_tle);
static Node *build_column_default(Relation rel, int attrno);
static void markQueryForUpdate(Query *qry, bool skipOldNew);
static List *matchLocks(CmdType event, RuleLock *rulelocks,
int varno, Query *parsetree);
......@@ -411,7 +410,7 @@ process_matched_tle(TargetEntry *src_tle,
*
* If there is no default, return a NULL instead.
*/
static Node *
Node *
build_column_default(Relation rel, int attrno)
{
TupleDesc rd_att = rel->rd_att;
......
......@@ -22,7 +22,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.271 2002/07/12 18:43:18 tgl Exp $
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.272 2002/07/18 04:43:50 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -133,6 +133,7 @@ static char *GetPrivileges(Archive *AH, const char *s, const char *type);
static int dumpBlobs(Archive *AH, char *, void *);
static int dumpDatabase(Archive *AH);
static const char *getAttrName(int attrnum, TableInfo *tblInfo);
static const char* fmtCopyColumnList(const TableInfo* ti);
extern char *optarg;
extern int optind,
......@@ -842,6 +843,7 @@ dumpClasses_nodumpData(Archive *fout, char *oid, void *dctxv)
int ret;
bool copydone;
char copybuf[COPYBUFSIZ];
const char* column_list;
if (g_verbose)
write_msg(NULL, "dumping out the contents of table %s\n", classname);
......@@ -854,17 +856,19 @@ dumpClasses_nodumpData(Archive *fout, char *oid, void *dctxv)
*/
selectSourceSchema(tbinfo->relnamespace->nspname);
column_list = fmtCopyColumnList(tbinfo);
if (oids && hasoids)
{
appendPQExpBuffer(q, "COPY %s WITH OIDS TO stdout;",
appendPQExpBuffer(q, "COPY %s %s WITH OIDS TO stdout;",
fmtQualifiedId(tbinfo->relnamespace->nspname,
classname));
classname),column_list);
}
else
{
appendPQExpBuffer(q, "COPY %s TO stdout;",
appendPQExpBuffer(q, "COPY %s %s TO stdout;",
fmtQualifiedId(tbinfo->relnamespace->nspname,
classname));
classname), column_list);
}
res = PQexec(g_conn, q->data);
if (!res ||
......@@ -1189,8 +1193,9 @@ dumpClasses(const TableInfo *tblinfo, const int numTables, Archive *fout,
{
/* Dump/restore using COPY */
dumpFn = dumpClasses_nodumpData;
sprintf(copyBuf, "COPY %s %sFROM stdin;\n",
fmtId(tblinfo[i].relname, force_quotes),
sprintf(copyBuf, "COPY %s %s %sFROM stdin;\n",
fmtQualifiedId(tblinfo[i].relnamespace->nspname,tblinfo[i].relname),
fmtCopyColumnList(&(tblinfo[i])),
(oids && tblinfo[i].hasoids) ? "WITH OIDS " : "");
copyStmt = copyBuf;
}
......@@ -5860,3 +5865,38 @@ fmtQualifiedId(const char *schema, const char *id)
return id_return->data;
}
/*
* return a column list clause for the qualified relname.
* returns an empty string if the remote server is older than
* 7.3.
*/
static const char*
fmtCopyColumnList(const TableInfo* ti)
{
static PQExpBuffer q = NULL;
int numatts = ti->numatts;
char** attnames = ti->attnames;
int i;
if (g_fout->remoteVersion < 70300 )
return "";
if (q) /* first time through? */
resetPQExpBuffer(q);
else
q = createPQExpBuffer();
resetPQExpBuffer(q);
appendPQExpBuffer(q,"(");
for (i = 0; i < numatts; i++)
{
if( i > 0 )
appendPQExpBuffer(q,",");
appendPQExpBuffer(q, fmtId(attnames[i], force_quotes));
}
appendPQExpBuffer(q, ")");
return q->data;
}
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: parsenodes.h,v 1.189 2002/07/18 04:42:29 momjian Exp $
* $Id: parsenodes.h,v 1.190 2002/07/18 04:43:51 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -884,6 +884,7 @@ typedef struct CopyStmt
{
NodeTag type;
RangeVar *relation; /* the relation to copy */
List *attlist;
bool is_from; /* TO or FROM */
char *filename; /* if NULL, use stdin/stdout */
List *options; /* List of DefElem nodes */
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: rewriteHandler.h,v 1.19 2002/06/20 20:29:52 momjian Exp $
* $Id: rewriteHandler.h,v 1.20 2002/07/18 04:43:51 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -16,7 +16,7 @@
#include "nodes/parsenodes.h"
extern List *QueryRewrite(Query *parsetree);
extern Node *build_column_default(Relation rel, int attrno);
#endif /* REWRITEHANDLER_H */
......@@ -74,4 +74,4 @@ test: select_views alter_table portals_p2 rules foreign_key
# The sixth group of parallel test
# ----------
# "plpgsql" cannot run concurrently with "rules"
test: limit plpgsql temp domain rangefuncs
test: limit plpgsql temp domain rangefuncs copy2
# $Header: /cvsroot/pgsql/src/test/regress/serial_schedule,v 1.10 2002/06/20 17:09:42 momjian Exp $
# $Header: /cvsroot/pgsql/src/test/regress/serial_schedule,v 1.11 2002/07/18 04:43:51 momjian Exp $
# This should probably be in an order similar to parallel_schedule.
test: boolean
test: char
......@@ -80,6 +80,7 @@ test: rules
test: foreign_key
test: limit
test: plpgsql
test: copy2
test: temp
test: domain
test: rangefuncs
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment