<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/copy.sgml,v 1.64 2005/05/06 03:38:05 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/copy.sgml,v 1.65 2005/05/07 02:22:45 momjian Exp $
PostgreSQL documentation
-->
COPY <replaceable class="parameter">tablename</replaceable> [ ( <replaceable class="parameter">column</replaceable> [, ...] ) ]
FROM { '<replaceable class="parameter">filename</replaceable>' | STDIN }
[ [ WITH ]
- [ BINARY ]
+ [ BINARY ]
[ OIDS ]
[ DELIMITER [ AS ] '<replaceable class="parameter">delimiter</replaceable>' ]
[ NULL [ AS ] '<replaceable class="parameter">null string</replaceable>' ]
- [ CSV [ QUOTE [ AS ] '<replaceable class="parameter">quote</replaceable>' ]
+ [ CSV [ HEADER ]
+ [ QUOTE [ AS ] '<replaceable class="parameter">quote</replaceable>' ]
[ ESCAPE [ AS ] '<replaceable class="parameter">escape</replaceable>' ]
[ FORCE NOT NULL <replaceable class="parameter">column</replaceable> [, ...] ]
TO { '<replaceable class="parameter">filename</replaceable>' | STDOUT }
[ [ WITH ]
[ BINARY ]
+ [ HEADER ]
[ OIDS ]
[ DELIMITER [ AS ] '<replaceable class="parameter">delimiter</replaceable>' ]
[ NULL [ AS ] '<replaceable class="parameter">null string</replaceable>' ]
- [ CSV [ QUOTE [ AS ] '<replaceable class="parameter">quote</replaceable>' ]
+ [ CSV [ HEADER ]
+ [ QUOTE [ AS ] '<replaceable class="parameter">quote</replaceable>' ]
[ ESCAPE [ AS ] '<replaceable class="parameter">escape</replaceable>' ]
[ FORCE QUOTE <replaceable class="parameter">column</replaceable> [, ...] ]
</synopsis>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><literal>HEADER</literal></term>
+ <listitem>
+ <para>
+ Specifies the file contains a header line with the names of each
+ column in the file. On output, the first line contains the column
+ names from the table, and on input, the first line is ignored.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><replaceable class="parameter">quote</replaceable></term>
<listitem>
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.243 2005/05/06 17:24:53 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.244 2005/05/07 02:22:46 momjian Exp $
*
*-------------------------------------------------------------------------
*/
/* non-export function prototypes */
static void DoCopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
char *delim, char *null_print, bool csv_mode, char *quote,
- char *escape, List *force_quote_atts, bool fe_copy);
+ char *escape, List *force_quote_atts, bool header_line, bool fe_copy);
static void CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
char *delim, char *null_print, bool csv_mode, char *quote, char *escape,
- List *force_quote_atts);
+ List *force_quote_atts, bool header_line);
static void CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
char *delim, char *null_print, bool csv_mode, char *quote, char *escape,
- List *force_notnull_atts);
+ List *force_notnull_atts, bool header_line);
static bool CopyReadLine(char * quote, char * escape);
static char *CopyReadAttribute(const char *delim, const char *null_print,
CopyReadResult *result, bool *isnull);
bool binary = false;
bool oids = false;
bool csv_mode = false;
+ bool header_line = false;
char *delim = NULL;
char *quote = NULL;
char *escape = NULL;
errmsg("conflicting or redundant options")));
csv_mode = intVal(defel->arg);
}
+ else if (strcmp(defel->defname, "header") == 0)
+ {
+ if (header_line)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+ header_line = intVal(defel->arg);
+ }
else if (strcmp(defel->defname, "quote") == 0)
{
if (quote)
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("COPY delimiter must be a single character")));
+ /* Check header */
+ if (!csv_mode && header_line)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("COPY HEADER available only in CSV mode")));
+
/* Check quote */
if (!csv_mode && quote != NULL)
ereport(ERROR,
}
}
CopyFrom(rel, attnumlist, binary, oids, delim, null_print, csv_mode,
- quote, escape, force_notnull_atts);
+ quote, escape, force_notnull_atts, header_line);
}
else
{ /* copy from database to file */
}
DoCopyTo(rel, attnumlist, binary, oids, delim, null_print, csv_mode,
- quote, escape, force_quote_atts, fe_copy);
+ quote, escape, force_quote_atts, header_line, fe_copy);
}
if (!pipe)
static void
DoCopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
char *delim, char *null_print, bool csv_mode, char *quote,
- char *escape, List *force_quote_atts, bool fe_copy)
+ char *escape, List *force_quote_atts, bool header_line, bool fe_copy)
{
PG_TRY();
{
SendCopyBegin(binary, list_length(attnumlist));
CopyTo(rel, attnumlist, binary, oids, delim, null_print, csv_mode,
- quote, escape, force_quote_atts);
+ quote, escape, force_quote_atts, header_line);
if (fe_copy)
SendCopyEnd(binary);
static void
CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
char *delim, char *null_print, bool csv_mode, char *quote,
- char *escape, List *force_quote_atts)
+ char *escape, List *force_quote_atts, bool header_line)
{
HeapTuple tuple;
TupleDesc tupDesc;
null_print = (char *)
pg_server_to_client((unsigned char *) null_print,
strlen(null_print));
+
+ /* if a header has been requested send the line */
+ if (header_line)
+ {
+ bool hdr_delim = false;
+ char *colname;
+
+ foreach(cur, attnumlist)
+ {
+ int attnum = lfirst_int(cur);
+
+ if (hdr_delim)
+ CopySendChar(delim[0]);
+ hdr_delim = true;
+
+ colname = NameStr(attr[attnum - 1]->attname);
+
+ CopyAttributeOutCSV(colname, delim, quote, escape,
+ strcmp(colname, null_print) == 0);
+ }
+
+ CopySendEndOfRow(binary);
+
+ }
}
scandesc = heap_beginscan(rel, ActiveSnapshot, 0, NULL);
static void
CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
char *delim, char *null_print, bool csv_mode, char *quote,
- char *escape, List *force_notnull_atts)
+ char *escape, List *force_notnull_atts, bool header_line)
{
HeapTuple tuple;
TupleDesc tupDesc;
errcontext.previous = error_context_stack;
error_context_stack = &errcontext;
+ /* on input just throw the header line away */
+ if (header_line)
+ {
+ copy_lineno++;
+ done = CopyReadLine(quote, escape) ;
+ }
+
while (!done)
{
bool skip_tuple;