22
22
#include "access/xact.h"
23
23
#include "catalog/namespace.h"
24
24
#include "commands/copy.h"
25
+ #include "commands/defrem.h"
25
26
#include "commands/trigger.h"
26
27
#include "commands/tablecmds.h"
27
28
#include "foreign/fdwapi.h"
@@ -64,10 +65,10 @@ static uint64 PathmanCopyFrom(CopyState cstate,
64
65
List * range_table ,
65
66
bool old_protocol );
66
67
67
- static void prepare_rri_for_copy (EState * estate ,
68
- ResultRelInfoHolder * rri_holder ,
69
- const ResultPartsStorage * rps_storage ,
70
- void * arg );
68
+ static void prepare_rri_for_copy (ResultRelInfoHolder * rri_holder ,
69
+ const ResultPartsStorage * rps_storage );
70
+ static void finish_rri_copy ( ResultRelInfoHolder * rri_holder ,
71
+ const ResultPartsStorage * rps_storage );
71
72
72
73
73
74
/*
@@ -110,12 +111,18 @@ is_pathman_related_copy(Node *parsetree)
110
111
/* Analyze options list */
111
112
foreach (lc , copy_stmt -> options )
112
113
{
113
- DefElem * defel = (DefElem * ) lfirst (lc );
114
-
115
- Assert (IsA (defel , DefElem ));
114
+ DefElem * defel = lfirst_node (DefElem , lc );
116
115
117
116
/* We do not support freeze */
118
- if (strcmp (defel -> defname , "freeze" ) == 0 )
117
+ /*
118
+ * It would be great to allow copy.c extract option value and
119
+ * check it ready. However, there is no possibility (hooks) to do
120
+ * that before messaging 'ok, begin streaming data' to the client,
121
+ * which is ugly and confusing: e.g. it would require us to
122
+ * actually send something in regression tests before we notice
123
+ * the error.
124
+ */
125
+ if (strcmp (defel -> defname , "freeze" ) == 0 && defGetBoolean (defel ))
119
126
elog (ERROR , "freeze is not supported for partitioned tables" );
120
127
}
121
128
@@ -481,7 +488,6 @@ PathmanCopyFrom(CopyState cstate, Relation parent_rel,
481
488
482
489
uint64 processed = 0 ;
483
490
484
-
485
491
tupDesc = RelationGetDescr (parent_rel );
486
492
487
493
parent_result_rel = makeNode (ResultRelInfo );
@@ -499,7 +505,7 @@ PathmanCopyFrom(CopyState cstate, Relation parent_rel,
499
505
/* Initialize ResultPartsStorage */
500
506
init_result_parts_storage (& parts_storage , estate , false,
501
507
ResultPartsStorageStandard ,
502
- prepare_rri_for_copy , NULL );
508
+ prepare_rri_for_copy , cstate );
503
509
parts_storage .saved_rel_info = parent_result_rel ;
504
510
505
511
/* Set up a tuple slot too */
@@ -634,13 +640,22 @@ PathmanCopyFrom(CopyState cstate, Relation parent_rel,
634
640
/* Check the constraints of the tuple */
635
641
if (child_result_rel -> ri_RelationDesc -> rd_att -> constr )
636
642
ExecConstraints (child_result_rel , slot , estate );
643
+ if (!child_result_rel -> ri_FdwRoutine )
644
+ {
645
+ /* OK, store the tuple and create index entries for it */
646
+ simple_heap_insert (child_result_rel -> ri_RelationDesc , tuple );
637
647
638
- /* OK, store the tuple and create index entries for it */
639
- simple_heap_insert (child_result_rel -> ri_RelationDesc , tuple );
640
-
641
- if (child_result_rel -> ri_NumIndices > 0 )
642
- recheckIndexes = ExecInsertIndexTuples (slot , & (tuple -> t_self ),
643
- estate , false, NULL , NIL );
648
+ if (child_result_rel -> ri_NumIndices > 0 )
649
+ recheckIndexes = ExecInsertIndexTuples (slot , & (tuple -> t_self ),
650
+ estate , false, NULL , NIL );
651
+ }
652
+ #ifdef PG_SHARDMAN
653
+ else /* FDW table */
654
+ {
655
+ child_result_rel -> ri_FdwRoutine -> ForeignNextCopyFrom (
656
+ estate , child_result_rel , cstate );
657
+ }
658
+ #endif
644
659
645
660
/* AFTER ROW INSERT Triggers (FIXME: NULL transition) */
646
661
ExecARInsertTriggersCompat (estate , child_result_rel , tuple ,
@@ -678,7 +693,7 @@ PathmanCopyFrom(CopyState cstate, Relation parent_rel,
678
693
ExecResetTupleTable (estate -> es_tupleTable , false);
679
694
680
695
/* Close partitions and destroy hash table */
681
- fini_result_parts_storage (& parts_storage , true);
696
+ fini_result_parts_storage (& parts_storage , true, finish_rri_copy );
682
697
683
698
/* Close parent's indices */
684
699
ExecCloseIndices (parent_result_rel );
@@ -689,20 +704,58 @@ PathmanCopyFrom(CopyState cstate, Relation parent_rel,
689
704
}
690
705
691
706
/*
692
- * COPY FROM does not support FDWs, emit ERROR .
707
+ * Init COPY FROM, if supported .
693
708
*/
694
709
static void
695
- prepare_rri_for_copy (EState * estate ,
696
- ResultRelInfoHolder * rri_holder ,
697
- const ResultPartsStorage * rps_storage ,
698
- void * arg )
710
+ prepare_rri_for_copy (ResultRelInfoHolder * rri_holder ,
711
+ const ResultPartsStorage * rps_storage )
699
712
{
700
- ResultRelInfo * rri = rri_holder -> result_rel_info ;
701
- FdwRoutine * fdw_routine = rri -> ri_FdwRoutine ;
713
+ ResultRelInfo * rri = rri_holder -> result_rel_info ;
714
+ FdwRoutine * fdw_routine = rri -> ri_FdwRoutine ;
702
715
703
716
if (fdw_routine != NULL )
717
+ {
718
+ /*
719
+ * If this Postgres has no idea about shardman, behave as usual:
720
+ * vanilla Postgres doesn't support COPY FROM to foreign partitions.
721
+ * However, shardman patches to core extend FDW API to allow it.
722
+ */
723
+ #ifdef PG_SHARDMAN
724
+ /* shardman COPY FROM requested? */
725
+ if (* find_rendezvous_variable (
726
+ "shardman_pathman_copy_from_rendezvous" ) != NULL &&
727
+ FdwCopyFromIsSupported (fdw_routine ))
728
+ {
729
+ CopyState cstate = (CopyState ) rps_storage -> callback_arg ;
730
+ ResultRelInfo * parent_rri = rps_storage -> saved_rel_info ;
731
+ EState * estate = rps_storage -> estate ;
732
+
733
+ fdw_routine -> BeginForeignCopyFrom (estate , rri , cstate , parent_rri );
734
+ return ;
735
+ }
736
+ #endif
737
+
704
738
elog (ERROR , "cannot copy to foreign partition \"%s\"" ,
705
739
get_rel_name (RelationGetRelid (rri -> ri_RelationDesc )));
740
+ }
741
+ }
742
+
743
+ /*
744
+ * Shut down FDWs.
745
+ */
746
+ static void
747
+ finish_rri_copy (ResultRelInfoHolder * rri_holder ,
748
+ const ResultPartsStorage * rps_storage )
749
+ {
750
+ #ifdef PG_SHARDMAN
751
+ ResultRelInfo * resultRelInfo = rri_holder -> result_rel_info ;
752
+
753
+ if (resultRelInfo -> ri_FdwRoutine )
754
+ {
755
+ resultRelInfo -> ri_FdwRoutine -> EndForeignCopyFrom (
756
+ rps_storage -> estate , resultRelInfo );
757
+ }
758
+ #endif
706
759
}
707
760
708
761
/*
0 commit comments