13
13
14
14
#include "postgres.h"
15
15
16
+ #include <sys/types.h>
17
+ #include <sys/stat.h>
18
+ #include <unistd.h>
19
+
16
20
#include "access/reloptions.h"
17
21
#include "catalog/pg_foreign_table.h"
18
22
#include "catalog/pg_foreign_server.h"
@@ -61,7 +65,10 @@ static struct FileFdwOption valid_options[] = {
61
65
62
66
/* FIXME: implement force_not_null option */
63
67
64
- /* Centinel */
68
+ /* Local option */
69
+ { "textarray" , ForeignTableRelationId },
70
+
71
+ /* Sentinel */
65
72
{ NULL , InvalidOid }
66
73
};
67
74
@@ -70,8 +77,9 @@ static struct FileFdwOption valid_options[] = {
70
77
*/
71
78
typedef struct FileFdwPrivate {
72
79
char * filename ;
80
+ bool textarray ; /* make a text array rather than a tuple */
73
81
Relation rel ; /* scan target relation */
74
- CopyState cstate ; /* state of reaind file */
82
+ CopyState cstate ; /* state of read in file */
75
83
List * options ; /* merged generic options, excluding filename */
76
84
} FileFdwPrivate ;
77
85
@@ -91,6 +99,8 @@ static void fileIterate(FdwExecutionState *festate, TupleTableSlot *slot);
91
99
static void fileEndScan (FdwExecutionState * festate );
92
100
static void fileReScan (FdwExecutionState * festate );
93
101
102
+ /* text array support */
103
+ static void makeTextArray (TupleTableSlot * slot , char * * raw_fields , int nfields );
94
104
/*
95
105
* Helper functions
96
106
*/
@@ -142,7 +152,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
142
152
(errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
143
153
errmsg ("only superuser can change foreign table options" )));
144
154
145
- /* Vaidate each options */
155
+ /* Validate each options */
146
156
foreach (cell , options_list )
147
157
{
148
158
DefElem * def = lfirst (cell );
@@ -298,6 +308,8 @@ filePlanRelScan(Oid foreigntableid, PlannerInfo *root, RelOptInfo *rel)
298
308
{
299
309
Const * relid ;
300
310
Value * filename = NULL ;
311
+ bool textarray = false;
312
+ Const * textarray_param ;
301
313
ulong size ;
302
314
FdwPlan * fplan ;
303
315
ForeignTable * table ;
@@ -346,6 +358,30 @@ filePlanRelScan(Oid foreigntableid, PlannerInfo *root, RelOptInfo *rel)
346
358
(errcode (ERRCODE_FDW_UNABLE_TO_CREATE_REPLY ),
347
359
errmsg ("filename is required for file_fdw scan" )));
348
360
361
+ /*
362
+ * Split textarray option off from the list because it's handled
363
+ * here instead of being passed as another parameter to BeginCopyFrom().
364
+ */
365
+ prev = NULL ;
366
+ foreach (lc , options )
367
+ {
368
+ DefElem * def = lfirst (lc );
369
+ if (strcmp (def -> defname , "textarray" ) == 0 )
370
+ {
371
+ textarray = defGetBoolean (def );
372
+ options = list_delete_cell (options , lc , prev );
373
+ break ;
374
+ }
375
+ prev = lc ;
376
+ }
377
+ textarray_param = (Const * ) makeBoolConst (textarray ,false);
378
+
379
+ if (text_array )
380
+ {
381
+ /* make sure the table has one column and it's oy type text[] */
382
+ /* XXX fill in this piece */
383
+ }
384
+
349
385
/* Construct FdwPlan and store relid and options in private area */
350
386
fplan = makeNode (FdwPlan );
351
387
size = estimate_costs (strVal (filename ), rel ,
@@ -354,6 +390,7 @@ filePlanRelScan(Oid foreigntableid, PlannerInfo *root, RelOptInfo *rel)
354
390
fplan -> fdw_private = NIL ;
355
391
fplan -> fdw_private = lappend (fplan -> fdw_private , relid );
356
392
fplan -> fdw_private = lappend (fplan -> fdw_private , filename );
393
+ fplan -> fdw_private = lappend (fplan -> fdw_private , textarray_param );
357
394
fplan -> fdw_private = lappend (fplan -> fdw_private , options );
358
395
359
396
return fplan ;
@@ -374,6 +411,7 @@ fileBeginScan(FdwPlan *fplan, ParamListInfo params)
374
411
Const * relid_const ;
375
412
Oid relid ;
376
413
Value * filename ;
414
+ Const * textarray ;
377
415
List * options ;
378
416
Relation rel ;
379
417
CopyState cstate ;
@@ -385,7 +423,8 @@ fileBeginScan(FdwPlan *fplan, ParamListInfo params)
385
423
/* Get oid of the relation and option list from private area of FdwPlan. */
386
424
relid_const = list_nth (fplan -> fdw_private , 0 );
387
425
filename = list_nth (fplan -> fdw_private , 1 );
388
- options = list_nth (fplan -> fdw_private , 2 );
426
+ textarray = list_nth (fplan -> fdw_private , 2 );
427
+ options = list_nth (fplan -> fdw_private , 3 );
389
428
390
429
relid = DatumGetObjectId (relid_const -> constvalue );
391
430
@@ -405,6 +444,7 @@ fileBeginScan(FdwPlan *fplan, ParamListInfo params)
405
444
festate = palloc0 (sizeof (FdwExecutionState ));
406
445
fdw_private = palloc0 (sizeof (FileFdwPrivate ));
407
446
fdw_private -> filename = strVal (filename );
447
+ fdw_private -> textarray = textarray -> constvalue ;
408
448
fdw_private -> rel = rel ;
409
449
fdw_private -> cstate = cstate ;
410
450
fdw_private -> options = options ;
@@ -438,8 +478,22 @@ fileIterate(FdwExecutionState *festate, TupleTableSlot *slot)
438
478
* EOF.
439
479
*/
440
480
ExecClearTuple (slot );
441
- found = NextCopyFrom (fdw_private -> cstate , slot -> tts_values , slot -> tts_isnull ,
442
- NULL );
481
+ if (fdw_private -> textarray )
482
+ {
483
+ char * * raw_fields ;
484
+ int nfields ;
485
+
486
+ found = NextLineCopyFrom (fdw_private -> cstate , & raw_fields , & nfields ,
487
+ NULL );
488
+ if (found )
489
+ makeTextArray (slot , raw_fields , nfields );
490
+ }
491
+ else
492
+ {
493
+ /* let the COPY code do the work */
494
+ found = NextCopyFrom (fdw_private -> cstate , slot -> tts_values ,
495
+ slot -> tts_isnull , NULL );
496
+ }
443
497
if (found )
444
498
ExecStoreVirtualTuple (slot );
445
499
@@ -546,3 +600,8 @@ estimate_costs(const char *filename, RelOptInfo *baserel,
546
600
return stat_buf .st_size ;
547
601
}
548
602
603
+ static void
604
+ makeTextArray (TupleTableSlot * slot , char * * raw_fields , int nfields )
605
+ {
606
+
607
+ }
0 commit comments