2222#include "access/xact.h"
2323#include "catalog/namespace.h"
2424#include "commands/copy.h"
25+ #include "commands/defrem.h"
2526#include "commands/trigger.h"
2627#include "commands/tablecmds.h"
2728#include "foreign/fdwapi.h"
@@ -105,6 +106,26 @@ is_pathman_related_copy(Node *parsetree)
105106 /* Check that relation is partitioned */
106107 if (get_pathman_relation_info (parent_relid ))
107108 {
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+
108129 /* Emit ERROR if we can't see the necessary symbols */
109130 #ifdef DISABLE_PATHMAN_COPY
110131 elog (ERROR , "COPY is not supported for partitioned tables on Windows" );
@@ -467,11 +488,6 @@ PathmanCopyFrom(CopyState cstate, Relation parent_rel,
467488
468489 uint64 processed = 0 ;
469490
470- /* We do not support freeze */
471- if (cstate -> freeze )
472- elog (ERROR , "freeze is not supported for partitioned tables" );
473-
474-
475491 tupDesc = RelationGetDescr (parent_rel );
476492
477493 parent_result_rel = makeNode (ResultRelInfo );
@@ -633,11 +649,13 @@ PathmanCopyFrom(CopyState cstate, Relation parent_rel,
633649 recheckIndexes = ExecInsertIndexTuples (slot , & (tuple -> t_self ),
634650 estate , false, NULL , NIL );
635651 }
652+ #ifdef PG_SHARDMAN
636653 else /* FDW table */
637654 {
638655 child_result_rel -> ri_FdwRoutine -> ForeignNextCopyFrom (
639656 estate , child_result_rel , cstate );
640657 }
658+ #endif
641659
642660 /* AFTER ROW INSERT Triggers (FIXME: NULL transition) */
643661 ExecARInsertTriggersCompat (estate , child_result_rel , tuple ,
@@ -694,25 +712,51 @@ prepare_rri_for_copy(ResultRelInfoHolder *rri_holder,
694712{
695713 ResultRelInfo * rri = rri_holder -> result_rel_info ;
696714 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 ;
703715
704716 if (fdw_routine != NULL )
705717 {
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 )));
716760 }
717761}
718762
@@ -723,13 +767,15 @@ static void
723767finish_rri_copy (ResultRelInfoHolder * rri_holder ,
724768 const ResultPartsStorage * rps_storage )
725769{
770+ #ifdef PG_SHARDMAN
726771 ResultRelInfo * resultRelInfo = rri_holder -> result_rel_info ;
727772
728773 if (resultRelInfo -> ri_FdwRoutine )
729774 {
730775 resultRelInfo -> ri_FdwRoutine -> EndForeignCopyFrom (
731776 rps_storage -> estate , resultRelInfo );
732777 }
778+ #endif
733779}
734780
735781/*
0 commit comments