Thread: Passing fdw_private data from PlanForeignScan to PlanForeignModify

Passing fdw_private data from PlanForeignScan to PlanForeignModify

From
Bernd Helmle
Date:
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



Bernd Helmle <mailings@oopsware.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



Re: Passing fdw_private data from PlanForeignScan to PlanForeignModify

From
Bernd Helmle
Date:

--On 13. Juni 2013 11:06:31 -0400 Tom Lane <tgl@sss.pgh.pa.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



Bernd Helmle <mailings@oopsware.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
sometimeswe 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
relisn'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



Re: Passing fdw_private data from PlanForeignScan to PlanForeignModify

From
Bernd Helmle
Date:

--On 13. Juni 2013 18:12:05 -0400 Tom Lane <tgl@sss.pgh.pa.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