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"
@@ -105,6 +106,26 @@ is_pathman_related_copy(Node *parsetree)
105
106
/* Check that relation is partitioned */
106
107
if (get_pathman_relation_info (parent_relid ))
107
108
{
109
+ ListCell * lc ;
110
+
111
+ /* Analyze options list */
112
+ foreach (lc , copy_stmt -> options )
113
+ {
114
+ DefElem * defel = lfirst_node (DefElem , lc );
115
+
116
+ /* We do not support freeze */
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 ))
126
+ elog (ERROR , "freeze is not supported for partitioned tables" );
127
+ }
128
+
108
129
/* Emit ERROR if we can't see the necessary symbols */
109
130
#ifdef DISABLE_PATHMAN_COPY
110
131
elog (ERROR , "COPY is not supported for partitioned tables on Windows" );
@@ -467,11 +488,6 @@ PathmanCopyFrom(CopyState cstate, Relation parent_rel,
467
488
468
489
uint64 processed = 0 ;
469
490
470
- /* We do not support freeze */
471
- if (cstate -> freeze )
472
- elog (ERROR , "freeze is not supported for partitioned tables" );
473
-
474
-
475
491
tupDesc = RelationGetDescr (parent_rel );
476
492
477
493
parent_result_rel = makeNode (ResultRelInfo );
@@ -633,11 +649,13 @@ PathmanCopyFrom(CopyState cstate, Relation parent_rel,
633
649
recheckIndexes = ExecInsertIndexTuples (slot , & (tuple -> t_self ),
634
650
estate , false, NULL , NIL );
635
651
}
652
+ #ifdef PG_SHARDMAN
636
653
else /* FDW table */
637
654
{
638
655
child_result_rel -> ri_FdwRoutine -> ForeignNextCopyFrom (
639
656
estate , child_result_rel , cstate );
640
657
}
658
+ #endif
641
659
642
660
/* AFTER ROW INSERT Triggers (FIXME: NULL transition) */
643
661
ExecARInsertTriggersCompat (estate , child_result_rel , tuple ,
@@ -694,25 +712,51 @@ prepare_rri_for_copy(ResultRelInfoHolder *rri_holder,
694
712
{
695
713
ResultRelInfo * rri = rri_holder -> result_rel_info ;
696
714
FdwRoutine * fdw_routine = rri -> ri_FdwRoutine ;
697
- CopyState cstate = (CopyState ) rps_storage -> callback_arg ;
698
- ResultRelInfo * parent_rri ;
699
- const char * parent_relname ;
700
- EState * estate ;
701
-
702
- estate = rps_storage -> estate ;
703
715
704
716
if (fdw_routine != NULL )
705
717
{
706
- parent_rri = rps_storage -> saved_rel_info ;
707
- parent_relname = psprintf (
708
- "%s.%s" , "public" ,
709
- quote_identifier (RelationGetRelationName (parent_rri -> ri_RelationDesc )));
710
- if (!FdwCopyFromIsSupported (fdw_routine ))
711
- ereport (ERROR ,
712
- (errcode (ERRCODE_WRONG_OBJECT_TYPE ),
713
- errmsg ("FDW adapter for relation \"%s\" doesn't support COPY FROM" ,
714
- RelationGetRelationName (rri -> ri_RelationDesc ))));
715
- fdw_routine -> BeginForeignCopyFrom (estate , rri , cstate , parent_relname );
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
+ * though currently postgres_fdw does so in a bit perverted way: we
723
+ * redirect COPY FROM to parent table on foreign server, assuming it
724
+ * exists, and let it direct tuple to proper partition. This is
725
+ * because otherwise we have to modify logic of managing connections
726
+ * in postgres_fdw and keep many connections open to one server from
727
+ * one backend.
728
+ */
729
+ #ifndef PG_SHARDMAN
730
+ goto bail_out ; /* to avoid 'unused label' warning */
731
+ #else
732
+ { /* separate block to avoid 'unused var' warnings */
733
+ CopyState cstate = (CopyState ) rps_storage -> callback_arg ;
734
+ ResultRelInfo * parent_rri ;
735
+ const char * parent_relname ;
736
+ EState * estate ;
737
+
738
+ /* shardman COPY FROM requested? */
739
+ if (* find_rendezvous_variable (
740
+ "shardman_pathman_copy_from_rendezvous" ) == NULL )
741
+ goto bail_out ;
742
+
743
+ estate = rps_storage -> estate ;
744
+ parent_rri = rps_storage -> saved_rel_info ;
745
+ parent_relname = psprintf (
746
+ "%s.%s" , "public" ,
747
+ quote_identifier (RelationGetRelationName (parent_rri -> ri_RelationDesc )));
748
+ if (!FdwCopyFromIsSupported (fdw_routine ))
749
+ ereport (ERROR ,
750
+ (errcode (ERRCODE_WRONG_OBJECT_TYPE ),
751
+ errmsg ("FDW adapter for relation \"%s\" doesn't support COPY FROM" ,
752
+ RelationGetRelationName (rri -> ri_RelationDesc ))));
753
+ fdw_routine -> BeginForeignCopyFrom (estate , rri , cstate , parent_relname );
754
+ return ;
755
+ }
756
+ #endif
757
+ bail_out :
758
+ elog (ERROR , "cannot copy to foreign partition \"%s\"" ,
759
+ get_rel_name (RelationGetRelid (rri -> ri_RelationDesc )));
716
760
}
717
761
}
718
762
@@ -723,13 +767,15 @@ static void
723
767
finish_rri_copy (ResultRelInfoHolder * rri_holder ,
724
768
const ResultPartsStorage * rps_storage )
725
769
{
770
+ #ifdef PG_SHARDMAN
726
771
ResultRelInfo * resultRelInfo = rri_holder -> result_rel_info ;
727
772
728
773
if (resultRelInfo -> ri_FdwRoutine )
729
774
{
730
775
resultRelInfo -> ri_FdwRoutine -> EndForeignCopyFrom (
731
776
rps_storage -> estate , resultRelInfo );
732
777
}
778
+ #endif
733
779
}
734
780
735
781
/*
0 commit comments