8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -131,13 +131,13 @@ static bool line_buf_converted;
131
131
/* non-export function prototypes */
132
132
static void DoCopyTo (Relation rel , List * attnumlist , bool binary , bool oids ,
133
133
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 );
135
135
static void CopyTo (Relation rel , List * attnumlist , bool binary , bool oids ,
136
136
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 );
138
138
static void CopyFrom (Relation rel , List * attnumlist , bool binary , bool oids ,
139
139
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 );
141
141
static bool CopyReadLine (char * quote , char * escape );
142
142
static char * CopyReadAttribute (const char * delim , const char * null_print ,
143
143
CopyReadResult * result , bool * isnull );
@@ -695,6 +695,7 @@ DoCopy(const CopyStmt *stmt)
695
695
bool binary = false;
696
696
bool oids = false;
697
697
bool csv_mode = false;
698
+ bool header_line = false;
698
699
char * delim = NULL ;
699
700
char * quote = NULL ;
700
701
char * escape = NULL ;
@@ -752,6 +753,14 @@ DoCopy(const CopyStmt *stmt)
752
753
errmsg ("conflicting or redundant options" )));
753
754
csv_mode = intVal (defel -> arg );
754
755
}
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
+ }
755
764
else if (strcmp (defel -> defname , "quote" ) == 0 )
756
765
{
757
766
if (quote )
@@ -825,6 +834,12 @@ DoCopy(const CopyStmt *stmt)
825
834
(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
826
835
errmsg ("COPY delimiter must be a single character" )));
827
836
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
+
828
843
/* Check quote */
829
844
if (!csv_mode && quote != NULL )
830
845
ereport (ERROR ,
@@ -1015,7 +1030,7 @@ DoCopy(const CopyStmt *stmt)
1015
1030
}
1016
1031
}
1017
1032
CopyFrom (rel , attnumlist , binary , oids , delim , null_print , csv_mode ,
1018
- quote , escape , force_notnull_atts );
1033
+ quote , escape , force_notnull_atts , header_line );
1019
1034
}
1020
1035
else
1021
1036
{ /* copy from database to file */
@@ -1079,7 +1094,7 @@ DoCopy(const CopyStmt *stmt)
1079
1094
}
1080
1095
1081
1096
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 );
1083
1098
}
1084
1099
1085
1100
if (!pipe )
@@ -1111,15 +1126,15 @@ DoCopy(const CopyStmt *stmt)
1111
1126
static void
1112
1127
DoCopyTo (Relation rel , List * attnumlist , bool binary , bool oids ,
1113
1128
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 )
1115
1130
{
1116
1131
PG_TRY ();
1117
1132
{
1118
1133
if (fe_copy )
1119
1134
SendCopyBegin (binary , list_length (attnumlist ));
1120
1135
1121
1136
CopyTo (rel , attnumlist , binary , oids , delim , null_print , csv_mode ,
1122
- quote , escape , force_quote_atts );
1137
+ quote , escape , force_quote_atts , header_line );
1123
1138
1124
1139
if (fe_copy )
1125
1140
SendCopyEnd (binary );
@@ -1143,7 +1158,7 @@ DoCopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
1143
1158
static void
1144
1159
CopyTo (Relation rel , List * attnumlist , bool binary , bool oids ,
1145
1160
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 )
1147
1162
{
1148
1163
HeapTuple tuple ;
1149
1164
TupleDesc tupDesc ;
@@ -1226,6 +1241,30 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
1226
1241
null_print = (char * )
1227
1242
pg_server_to_client ((unsigned char * ) null_print ,
1228
1243
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
+ }
1229
1268
}
1230
1269
1231
1270
scandesc = heap_beginscan (rel , ActiveSnapshot , 0 , NULL );
@@ -1427,7 +1466,7 @@ limit_printout_length(StringInfo buf)
1427
1466
static void
1428
1467
CopyFrom (Relation rel , List * attnumlist , bool binary , bool oids ,
1429
1468
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 )
1431
1470
{
1432
1471
HeapTuple tuple ;
1433
1472
TupleDesc tupDesc ;
@@ -1653,6 +1692,13 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
1653
1692
errcontext .previous = error_context_stack ;
1654
1693
error_context_stack = & errcontext ;
1655
1694
1695
+ /* on input just throw the header line away */
1696
+ if (header_line )
1697
+ {
1698
+ copy_lineno ++ ;
1699
+ done = CopyReadLine (quote , escape ) ;
1700
+ }
1701
+
1656
1702
while (!done )
1657
1703
{
1658
1704
bool skip_tuple ;
0 commit comments