@@ -10,6 +10,7 @@ static const char BOM[3] = "\xEF\xBB\xBF";
1010typedef struct {
1111 char delim ;
1212 bool with_bom ;
13+ bool header ;
1314} CsvOptions ;
1415
1516typedef struct {
@@ -59,14 +60,15 @@ static void parse_csv_options(HeapTupleHeader opts_hdr, CsvOptions *csv_opts) {
5960 // defaults
6061 csv_opts -> delim = ',' ;
6162 csv_opts -> with_bom = false;
63+ csv_opts -> header = true;
6264
6365 if (opts_hdr == NULL ) return ;
6466
6567 TupleDesc desc = lookup_rowtype_tupdesc (HeapTupleHeaderGetTypeId (opts_hdr ),
6668 HeapTupleHeaderGetTypMod (opts_hdr ));
6769
68- Datum values [2 ];
69- bool nulls [2 ];
70+ Datum values [3 ];
71+ bool nulls [3 ];
7072
7173 heap_deform_tuple (
7274 & (HeapTupleData ){.t_len = HeapTupleHeaderGetDatumLength (opts_hdr ), .t_data = opts_hdr }, desc ,
@@ -84,6 +86,10 @@ static void parse_csv_options(HeapTupleHeader opts_hdr, CsvOptions *csv_opts) {
8486 csv_opts -> with_bom = DatumGetBool (values [1 ]);
8587 }
8688
89+ if (!nulls [2 ]) {
90+ csv_opts -> header = DatumGetBool (values [2 ]);
91+ }
92+
8793 ReleaseTupleDesc (desc );
8894}
8995
@@ -128,19 +134,21 @@ Datum csv_agg_transfn(PG_FUNCTION_ARGS) {
128134 if (state -> options -> with_bom ) appendBinaryStringInfo (& state -> accum_buf , BOM , sizeof (BOM ));
129135
130136 // build header row
131- for (int i = 0 ; i < tdesc -> natts ; i ++ ) {
132- Form_pg_attribute att = TupleDescAttr (tdesc , i );
133- if (att -> attisdropped ) // pg always keeps dropped columns, guard against this
134- continue ;
137+ if (state -> options -> header ) {
138+ for (int i = 0 ; i < tdesc -> natts ; i ++ ) {
139+ Form_pg_attribute att = TupleDescAttr (tdesc , i );
140+ if (att -> attisdropped ) // pg always keeps dropped columns, guard against this
141+ continue ;
135142
136- if (i > 0 ) // only append delimiter after the first value
137- appendStringInfoChar (& state -> accum_buf , state -> options -> delim );
143+ if (i > 0 ) // only append delimiter after the first value
144+ appendStringInfoChar (& state -> accum_buf , state -> options -> delim );
138145
139- char * cstr = NameStr (att -> attname );
140- csv_append_field (& state -> accum_buf , cstr , strlen (cstr ), state -> options -> delim );
141- }
146+ char * cstr = NameStr (att -> attname );
147+ csv_append_field (& state -> accum_buf , cstr , strlen (cstr ), state -> options -> delim );
148+ }
142149
143- appendStringInfoChar (& state -> accum_buf , NEWLINE );
150+ appendStringInfoChar (& state -> accum_buf , NEWLINE );
151+ }
144152
145153 state -> tupdesc = tdesc ;
146154 state -> header_done = true;
0 commit comments