88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.243 2005/05/06 17:24:53 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.244 2005/05/07 02:22:46 momjian Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -131,13 +131,13 @@ static bool line_buf_converted;
131131/* non-export function prototypes */
132132static void DoCopyTo (Relation rel , List * attnumlist , bool binary , bool oids ,
133133 char * delim , char * null_print , bool csv_mode , char * quote ,
134- char * escape , List * force_quote_atts , bool fe_copy );
134+ char * escape , List * force_quote_atts , bool header_line , bool fe_copy );
135135static void CopyTo (Relation rel , List * attnumlist , bool binary , bool oids ,
136136 char * delim , char * null_print , bool csv_mode , char * quote , char * escape ,
137- List * force_quote_atts );
137+ List * force_quote_atts , bool header_line );
138138static void CopyFrom (Relation rel , List * attnumlist , bool binary , bool oids ,
139139 char * delim , char * null_print , bool csv_mode , char * quote , char * escape ,
140- List * force_notnull_atts );
140+ List * force_notnull_atts , bool header_line );
141141static bool CopyReadLine (char * quote , char * escape );
142142static char * CopyReadAttribute (const char * delim , const char * null_print ,
143143 CopyReadResult * result , bool * isnull );
@@ -695,6 +695,7 @@ DoCopy(const CopyStmt *stmt)
695695 bool binary = false;
696696 bool oids = false;
697697 bool csv_mode = false;
698+ bool header_line = false;
698699 char * delim = NULL ;
699700 char * quote = NULL ;
700701 char * escape = NULL ;
@@ -752,6 +753,14 @@ DoCopy(const CopyStmt *stmt)
752753 errmsg ("conflicting or redundant options" )));
753754 csv_mode = intVal (defel -> arg );
754755 }
756+ else if (strcmp (defel -> defname , "header" ) == 0 )
757+ {
758+ if (header_line )
759+ ereport (ERROR ,
760+ (errcode (ERRCODE_SYNTAX_ERROR ),
761+ errmsg ("conflicting or redundant options" )));
762+ header_line = intVal (defel -> arg );
763+ }
755764 else if (strcmp (defel -> defname , "quote" ) == 0 )
756765 {
757766 if (quote )
@@ -825,6 +834,12 @@ DoCopy(const CopyStmt *stmt)
825834 (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
826835 errmsg ("COPY delimiter must be a single character" )));
827836
837+ /* Check header */
838+ if (!csv_mode && header_line )
839+ ereport (ERROR ,
840+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
841+ errmsg ("COPY HEADER available only in CSV mode" )));
842+
828843 /* Check quote */
829844 if (!csv_mode && quote != NULL )
830845 ereport (ERROR ,
@@ -1015,7 +1030,7 @@ DoCopy(const CopyStmt *stmt)
10151030 }
10161031 }
10171032 CopyFrom (rel , attnumlist , binary , oids , delim , null_print , csv_mode ,
1018- quote , escape , force_notnull_atts );
1033+ quote , escape , force_notnull_atts , header_line );
10191034 }
10201035 else
10211036 { /* copy from database to file */
@@ -1079,7 +1094,7 @@ DoCopy(const CopyStmt *stmt)
10791094 }
10801095
10811096 DoCopyTo (rel , attnumlist , binary , oids , delim , null_print , csv_mode ,
1082- quote , escape , force_quote_atts , fe_copy );
1097+ quote , escape , force_quote_atts , header_line , fe_copy );
10831098 }
10841099
10851100 if (!pipe )
@@ -1111,15 +1126,15 @@ DoCopy(const CopyStmt *stmt)
11111126static void
11121127DoCopyTo (Relation rel , List * attnumlist , bool binary , bool oids ,
11131128 char * delim , char * null_print , bool csv_mode , char * quote ,
1114- char * escape , List * force_quote_atts , bool fe_copy )
1129+ char * escape , List * force_quote_atts , bool header_line , bool fe_copy )
11151130{
11161131 PG_TRY ();
11171132 {
11181133 if (fe_copy )
11191134 SendCopyBegin (binary , list_length (attnumlist ));
11201135
11211136 CopyTo (rel , attnumlist , binary , oids , delim , null_print , csv_mode ,
1122- quote , escape , force_quote_atts );
1137+ quote , escape , force_quote_atts , header_line );
11231138
11241139 if (fe_copy )
11251140 SendCopyEnd (binary );
@@ -1143,7 +1158,7 @@ DoCopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
11431158static void
11441159CopyTo (Relation rel , List * attnumlist , bool binary , bool oids ,
11451160 char * delim , char * null_print , bool csv_mode , char * quote ,
1146- char * escape , List * force_quote_atts )
1161+ char * escape , List * force_quote_atts , bool header_line )
11471162{
11481163 HeapTuple tuple ;
11491164 TupleDesc tupDesc ;
@@ -1226,6 +1241,30 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
12261241 null_print = (char * )
12271242 pg_server_to_client ((unsigned char * ) null_print ,
12281243 strlen (null_print ));
1244+
1245+ /* if a header has been requested send the line */
1246+ if (header_line )
1247+ {
1248+ bool hdr_delim = false;
1249+ char * colname ;
1250+
1251+ foreach (cur , attnumlist )
1252+ {
1253+ int attnum = lfirst_int (cur );
1254+
1255+ if (hdr_delim )
1256+ CopySendChar (delim [0 ]);
1257+ hdr_delim = true;
1258+
1259+ colname = NameStr (attr [attnum - 1 ]-> attname );
1260+
1261+ CopyAttributeOutCSV (colname , delim , quote , escape ,
1262+ strcmp (colname , null_print ) == 0 );
1263+ }
1264+
1265+ CopySendEndOfRow (binary );
1266+
1267+ }
12291268 }
12301269
12311270 scandesc = heap_beginscan (rel , ActiveSnapshot , 0 , NULL );
@@ -1427,7 +1466,7 @@ limit_printout_length(StringInfo buf)
14271466static void
14281467CopyFrom (Relation rel , List * attnumlist , bool binary , bool oids ,
14291468 char * delim , char * null_print , bool csv_mode , char * quote ,
1430- char * escape , List * force_notnull_atts )
1469+ char * escape , List * force_notnull_atts , bool header_line )
14311470{
14321471 HeapTuple tuple ;
14331472 TupleDesc tupDesc ;
@@ -1653,6 +1692,13 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
16531692 errcontext .previous = error_context_stack ;
16541693 error_context_stack = & errcontext ;
16551694
1695+ /* on input just throw the header line away */
1696+ if (header_line )
1697+ {
1698+ copy_lineno ++ ;
1699+ done = CopyReadLine (quote , escape ) ;
1700+ }
1701+
16561702 while (!done )
16571703 {
16581704 bool skip_tuple ;
0 commit comments