Re: Passing fdw_private data from PlanForeignScan to PlanForeignModify

Lists: pgsql-hackers
From: Bernd Helmle <mailings(at)oopsware(dot)de>
To: pgsql-hackers(at)postgresql(dot)org
Subject: Passing fdw_private data from PlanForeignScan to PlanForeignModify
Date: 2013-06-13 12:02:54
Message-ID: 5B403C914B5ED69C995AB8C4@apophis.credativ.lan
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

I'm currently implementing DML actions in the informix FDW module and
trying to understand how UPDATE/DELETE actions interact with the various
structures, especially how states between the associated ForeignScan and
ForeignModify actions could be transmitted. As far as i understood, with
e.g. an UPDATE action on a foreign table you get the following sequence of
callbacks:

GetForeignRelSize
GetForeignPaths
GetForeignPlan

PlanForeignModify

BeginForeignScan

BeginForeignModify

<repeats>
IterateForeignScan

ExecForeignUpdate

</repeats>

EndForeignScan

EndForeignModify

During the planning phase, the Informix FDW currently plans a server side
cursor, which identifier i'd like to pass into the planning phase of the
modify action to reuse it in conjunction with UPDATE ... WHERE CURRENT OF.

I understand that the ModifyTable structure passed to PlanForeignModify has
a list of associated plan nodes, from which i can access the ForeignScan
plan node associated with the current modify action, thus having access to
the fdw_private data generated during the planning phase of the ForeigScan
node. However, it's a list and i currently don't understand on how to
reference the associated ForeignScan node reliably, given that there are
cases with more than one node in this list.

Any pointers, someone?

--
Thanks

Bernd


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Bernd Helmle <mailings(at)oopsware(dot)de>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: Passing fdw_private data from PlanForeignScan to PlanForeignModify
Date: 2013-06-13 15:06:31
Message-ID: 22682.1371135991@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Bernd Helmle <mailings(at)oopsware(dot)de> writes:
> During the planning phase, the Informix FDW currently plans a server side
> cursor, which identifier i'd like to pass into the planning phase of the
> modify action to reuse it in conjunction with UPDATE ... WHERE CURRENT OF.

> I understand that the ModifyTable structure passed to PlanForeignModify has
> a list of associated plan nodes, from which i can access the ForeignScan
> plan node associated with the current modify action, thus having access to
> the fdw_private data generated during the planning phase of the ForeigScan
> node. However, it's a list and i currently don't understand on how to
> reference the associated ForeignScan node reliably, given that there are
> cases with more than one node in this list.

The subplan_index argument to PlanForeignModify is the list index to
use, unless I'm misunderstanding something about this. However, in join
cases the ForeignScan node will be buried down inside a join nest, so
locating it in the plan tree could be rather difficult. My
recommendation would be to see if you can't save the relevant info in
the RelOptInfo node for the relation, probably during GetForeignPlan,
and then get it from there in PlanForeignModify instead of digging in
the plan tree. (You can use the fdw_private field of RelOptInfo for
whatever you need in this line.)

regards, tom lane


From: Bernd Helmle <mailings(at)oopsware(dot)de>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: Passing fdw_private data from PlanForeignScan to PlanForeignModify
Date: 2013-06-13 22:00:23
Message-ID: 00B3A90CC3E2A8BB67D0FC2D@localhost
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

--On 13. Juni 2013 11:06:31 -0400 Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> wrote:

> My
> recommendation would be to see if you can't save the relevant info in
> the RelOptInfo node for the relation, probably during GetForeignPlan,
> and then get it from there in PlanForeignModify instead of digging in
> the plan tree. (You can use the fdw_private field of RelOptInfo for
> whatever you need in this line.)

Hmm, I tried this already, but maybe i'm doing something entirely wrong
here.

What i tried before was to access (in PlanForeignModify) the RelOptInfo
structure through PlannerInfo->simple_rel_array, assuming the the
resultRelation index points to the right array member. However, that didn't
work, the fdw_private List is not the one filled by GetForeignPlan...is
there another way to get back the RelOptInfo worked on earlier?

--
Thanks

Bernd


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Bernd Helmle <mailings(at)oopsware(dot)de>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: Passing fdw_private data from PlanForeignScan to PlanForeignModify
Date: 2013-06-13 22:12:05
Message-ID: 19844.1371161525@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Bernd Helmle <mailings(at)oopsware(dot)de> writes:
> What i tried before was to access (in PlanForeignModify) the RelOptInfo
> structure through PlannerInfo->simple_rel_array, assuming the the
> resultRelation index points to the right array member. However, that didn't
> work, the fdw_private List is not the one filled by GetForeignPlan...is
> there another way to get back the RelOptInfo worked on earlier?

It should work ... *if* there was in fact a RelOptInfo worked on
earlier. There sometimes isn't. You might need to do something like
what make_modifytable() has to do to call you in the first place:

/*
* If possible, we want to get the FdwRoutine from our RelOptInfo for
* the table. But sometimes we don't have a RelOptInfo and must get
* it the hard way. (In INSERT, the target relation is not scanned,
* so it's not a baserel; and there are also corner cases for
* updatable views where the target rel isn't a baserel.)
*/
if (rti < root->simple_rel_array_size &&
root->simple_rel_array[rti] != NULL)
{
RelOptInfo *resultRel = root->simple_rel_array[rti];

fdwroutine = resultRel->fdwroutine;
}
else
{
RangeTblEntry *rte = planner_rt_fetch(rti, root);

Assert(rte->rtekind == RTE_RELATION);
if (rte->relkind == RELKIND_FOREIGN_TABLE)
fdwroutine = GetFdwRoutineByRelId(rte->relid);
else
fdwroutine = NULL;
}

if (fdwroutine != NULL &&
fdwroutine->PlanForeignModify != NULL)
fdw_private = fdwroutine->PlanForeignModify(root, node, rti, i);

[ jargon alert: "baserel" here basically means "a table the query has
to scan". ]

regards, tom lane


From: Bernd Helmle <mailings(at)oopsware(dot)de>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: Passing fdw_private data from PlanForeignScan to PlanForeignModify
Date: 2013-07-01 15:34:24
Message-ID: 2EC3C2B1067A1C975C7BEF9F@apophis.credativ.lan
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

--On 13. Juni 2013 18:12:05 -0400 Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> wrote:

>> What i tried before was to access (in PlanForeignModify) the RelOptInfo
>> structure through PlannerInfo->simple_rel_array, assuming the the
>> resultRelation index points to the right array member. However, that
>> didn't work, the fdw_private List is not the one filled by
>> GetForeignPlan...is there another way to get back the RelOptInfo worked
>> on earlier?
>
> It should work ... *if* there was in fact a RelOptInfo worked on
> earlier. There sometimes isn't. You might need to do something like
> what make_modifytable() has to do to call you in the first place:

Sorry for the late feedback, didn't manage to get back to this earlier.

This works indeed, the RelOptInfo structure stored in simple_rel_array (if
present) allows
a FDW to access its earlier scan state, assigned in GetForeignPlan() for
example.

Thanks for the hints!

--

Bernd