mirror of
https://github.com/postgres/postgres.git
synced 2025-07-07 00:36:50 +03:00
Add COPY WITH CVS HEADER to allow a heading line as the first line in
COPY. Andrew Dunstan
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -131,13 +131,13 @@ static bool line_buf_converted;
|
||||
/* 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);
|
||||
@ -695,6 +695,7 @@ DoCopy(const CopyStmt *stmt)
|
||||
bool binary = false;
|
||||
bool oids = false;
|
||||
bool csv_mode = false;
|
||||
bool header_line = false;
|
||||
char *delim = NULL;
|
||||
char *quote = NULL;
|
||||
char *escape = NULL;
|
||||
@ -752,6 +753,14 @@ DoCopy(const CopyStmt *stmt)
|
||||
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)
|
||||
@ -825,6 +834,12 @@ DoCopy(const CopyStmt *stmt)
|
||||
(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,
|
||||
@ -1015,7 +1030,7 @@ DoCopy(const CopyStmt *stmt)
|
||||
}
|
||||
}
|
||||
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 */
|
||||
@ -1079,7 +1094,7 @@ DoCopy(const CopyStmt *stmt)
|
||||
}
|
||||
|
||||
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)
|
||||
@ -1111,7 +1126,7 @@ DoCopy(const CopyStmt *stmt)
|
||||
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();
|
||||
{
|
||||
@ -1119,7 +1134,7 @@ DoCopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
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);
|
||||
@ -1143,7 +1158,7 @@ DoCopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
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;
|
||||
@ -1226,6 +1241,30 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
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);
|
||||
@ -1427,7 +1466,7 @@ limit_printout_length(StringInfo buf)
|
||||
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;
|
||||
@ -1653,6 +1692,13 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
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;
|
||||
|
Reference in New Issue
Block a user