@@ -28,9 +28,9 @@ bool pg_pathman_enable_partition_router = true;
2828CustomScanMethods partition_router_plan_methods ;
2929CustomExecMethods partition_router_exec_methods ;
3030
31- static TupleTableSlot * ExecDeleteInternal (ItemPointer tupleid ,
32- EPQState * epqstate ,
33- EState * estate );
31+ static bool ExecDeleteInternal (ItemPointer tupleid ,
32+ EPQState * epqstate ,
33+ EState * estate );
3434
3535void
3636init_partition_router_static_data (void )
6565make_partition_router (Plan * subplan ,
6666 Oid parent_relid ,
6767 Index parent_rti ,
68+ int epq_param ,
6869 List * returning_list )
6970
7071{
@@ -85,16 +86,17 @@ make_partition_router(Plan *subplan,
8586 cscan -> scan .plan .plan_rows = subplan -> plan_rows ;
8687 cscan -> scan .plan .plan_width = subplan -> plan_width ;
8788
88- /* Setup methods and child plan */
89+ /* Setup methods, child plan and param number for EPQ */
8990 cscan -> methods = & partition_router_plan_methods ;
9091 cscan -> custom_plans = list_make1 (pfilter );
91-
92- /* Build an appropriate target list */
93- cscan -> scan .plan .targetlist = pfilter -> targetlist ;
92+ cscan -> custom_private = list_make1 (makeInteger (epq_param ));
9493
9594 /* No physical relation will be scanned */
9695 cscan -> scan .scanrelid = 0 ;
9796
97+ /* Build an appropriate target list */
98+ cscan -> scan .plan .targetlist = pfilter -> targetlist ;
99+
98100 /* FIXME: should we use the same tlist? */
99101 cscan -> custom_scan_tlist = subplan -> targetlist ;
100102
@@ -113,7 +115,9 @@ partition_router_create_scan_state(CustomScan *node)
113115 state -> css .methods = & partition_router_exec_methods ;
114116
115117 /* Extract necessary variables */
118+ state -> epqparam = intVal (linitial (node -> custom_private ));
116119 state -> subplan = (Plan * ) linitial (node -> custom_plans );
120+
117121 return (Node * ) state ;
118122}
119123
@@ -122,6 +126,10 @@ partition_router_begin(CustomScanState *node, EState *estate, int eflags)
122126{
123127 PartitionRouterState * state = (PartitionRouterState * ) node ;
124128
129+ EvalPlanQualInit (& state -> epqstate , estate ,
130+ state -> subplan , NIL ,
131+ state -> epqparam );
132+
125133 /* It's convenient to store PlanState in 'custom_ps' */
126134 node -> custom_ps = list_make1 (ExecInitNode (state -> subplan , estate , eflags ));
127135}
@@ -134,14 +142,14 @@ partition_router_exec(CustomScanState *node)
134142 TupleTableSlot * slot ;
135143 PartitionRouterState * state = (PartitionRouterState * ) node ;
136144
145+ take_next_tuple :
137146 /* execute PartitionFilter child node */
138147 slot = ExecProcNode (child_ps );
139148
140149 if (!TupIsNull (slot ))
141150 {
142151 ResultRelInfo * new_rri , /* new tuple owner */
143152 * old_rri ; /* previous tuple owner */
144- EPQState epqstate ;
145153 PartitionFilterState * child_state ;
146154 char relkind ;
147155 ItemPointerData ctid ;
@@ -203,8 +211,12 @@ partition_router_exec(CustomScanState *node)
203211
204212 /* Delete tuple from old partition */
205213 Assert (ItemPointerIsValid (& ctid ));
206- EvalPlanQualSetSlot (& epqstate , child_state -> subplan_slot );
207- ExecDeleteInternal (& ctid , & epqstate , estate );
214+ EvalPlanQualSetSlot (& state -> epqstate , child_state -> subplan_slot );
215+ if (!ExecDeleteInternal (& ctid , & state -> epqstate , estate ))
216+ {
217+ elog (INFO , "oops, deleted, taking next tuple!" );
218+ goto take_next_tuple ;
219+ }
208220
209221 /* Magic: replace parent's ResultRelInfo with child's one (INSERT) */
210222 estate -> es_result_relation_info = new_rri ;
@@ -244,40 +256,42 @@ partition_router_explain(CustomScanState *node, List *ancestors, ExplainState *e
244256 * ----------------------------------------------------------------
245257 */
246258
247- static TupleTableSlot *
259+ static bool
248260ExecDeleteInternal (ItemPointer tupleid ,
249261 EPQState * epqstate ,
250262 EState * estate )
251263{
252- ResultRelInfo * resultRelInfo ;
253- Relation resultRelationDesc ;
264+ ResultRelInfo * rri ;
265+ Relation rel ;
254266 HTSU_Result result ;
255267 HeapUpdateFailureData hufd ;
256268
257269 /*
258270 * get information on the (current) result relation
259271 */
260- resultRelInfo = estate -> es_result_relation_info ;
261- resultRelationDesc = resultRelInfo -> ri_RelationDesc ;
272+ rri = estate -> es_result_relation_info ;
273+ rel = rri -> ri_RelationDesc ;
262274
263- /* BEFORE ROW DELETE Triggers */
264- if (resultRelInfo -> ri_TrigDesc &&
265- resultRelInfo -> ri_TrigDesc -> trig_delete_before_row )
275+ /* BEFORE ROW UPDATE triggers */
276+ if (rri -> ri_TrigDesc &&
277+ rri -> ri_TrigDesc -> trig_update_before_row )
266278 {
267- bool dodelete ;
268-
269- dodelete = ExecBRDeleteTriggers (estate , epqstate , resultRelInfo ,
270- tupleid , NULL );
279+ elog (INFO , "kek!" );
280+ }
271281
272- if (!dodelete )
273- elog (ERROR , "the old row always should be deleted from child table" );
282+ /* BEFORE ROW DELETE triggers */
283+ if (rri -> ri_TrigDesc &&
284+ rri -> ri_TrigDesc -> trig_delete_before_row )
285+ {
286+ if (!ExecBRDeleteTriggers (estate , epqstate , rri , tupleid , NULL ))
287+ return false;
274288 }
275289
276290 if (tupleid != NULL )
277291 {
278292 /* delete the tuple */
279293ldelete :
280- result = heap_delete_compat (resultRelationDesc , tupleid ,
294+ result = heap_delete_compat (rel , tupleid ,
281295 estate -> es_output_cid ,
282296 estate -> es_crosscheck_snapshot ,
283297 true /* wait for commit */ ,
@@ -292,7 +306,7 @@ ExecDeleteInternal(ItemPointer tupleid,
292306 errhint ("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows." )));
293307
294308 /* Else, already deleted by self; nothing to do */
295- return NULL ;
309+ return false ;
296310
297311 case HeapTupleMayBeUpdated :
298312 break ;
@@ -302,37 +316,39 @@ ExecDeleteInternal(ItemPointer tupleid,
302316 ereport (ERROR ,
303317 (errcode (ERRCODE_T_R_SERIALIZATION_FAILURE ),
304318 errmsg ("could not serialize access due to concurrent update" )));
319+
305320 if (!ItemPointerEquals (tupleid , & hufd .ctid ))
306321 {
307322 TupleTableSlot * epqslot ;
308323
309324 epqslot = EvalPlanQual (estate ,
310325 epqstate ,
311- resultRelationDesc ,
312- resultRelInfo -> ri_RangeTableIndex ,
326+ rel ,
327+ rri -> ri_RangeTableIndex ,
313328 LockTupleExclusive ,
314329 & hufd .ctid ,
315330 hufd .xmax );
331+
316332 if (!TupIsNull (epqslot ))
317333 {
318334 Assert (tupleid != NULL );
319335 * tupleid = hufd .ctid ;
320336 goto ldelete ;
321337 }
322338 }
339+
323340 /* tuple already deleted; nothing to do */
324- return NULL ;
341+ return false ;
325342
326343 default :
327344 elog (ERROR , "unrecognized heap_delete status: %u" , result );
328- return NULL ;
329345 }
330346 }
331347 else
332348 elog (ERROR , "tupleid should be specified for deletion" );
333349
334- /* AFTER ROW DELETE Triggers */
335- ExecARDeleteTriggersCompat (estate , resultRelInfo , tupleid , NULL , NULL );
350+ /* AFTER ROW DELETE triggers */
351+ ExecARDeleteTriggersCompat (estate , rri , tupleid , NULL , NULL );
336352
337- return NULL ;
353+ return true ;
338354}
0 commit comments