Thread: Passing fdw_private data from PlanForeignScan to PlanForeignModify
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
--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
--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