Skip to content

Commit 551f4f2

Browse files
committed
Do COPY FROM to foreign parts only when needed.
That is, when 1) pg_pathman was compiled against postgres with shardman patches. 2) Shardman's COPY FROM was explicitly asked by setting renderzvous var. Also, check for 'freeze' option early, as before, to keep regression tests as they are.
1 parent 74f40cc commit 551f4f2

File tree

1 file changed

+67
-21
lines changed

1 file changed

+67
-21
lines changed

src/utility_stmt_hooking.c

Lines changed: 67 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
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
723767
finish_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

Comments
 (0)