@@ -16,6 +16,128 @@ CustomPathMethodspickyappend_path_methods;
1616CustomScanMethods pickyappend_plan_methods ;
1717CustomExecMethods pickyappend_exec_methods ;
1818
19+
20+ static void
21+ clear_plan_states (ChildScanCommon * selected_plans ,int n )
22+ {
23+ int i ;
24+
25+ if (!selected_plans )
26+ return ;
27+
28+ for (i = 0 ;i < n ;i ++ )
29+ {
30+ ChildScanCommon child = selected_plans [i ];
31+
32+ ExecEndNode (child -> content .plan_state );
33+ }
34+ }
35+
36+ static void
37+ transform_plans_into_states (ChildScanCommon * selected_plans ,int n ,EState * estate )
38+ {
39+ int i ;
40+
41+ for (i = 0 ;i < n ;i ++ )
42+ {
43+ ChildScanCommon child = selected_plans [i ];
44+
45+ child -> content_type = CHILD_PLAN_STATE ;
46+ child -> content .plan_state = ExecInitNode (child -> content .plan ,estate ,0 );
47+ }
48+ }
49+
50+ static ChildScanCommon *
51+ select_required_plans (ChildScanCommon * children ,int nchildren ,
52+ Oid * parts ,int nparts ,
53+ int * nres )
54+ {
55+ ChildScanCommon * children_end = children + nchildren ;
56+ Oid * parts_end = parts + nparts ;
57+ int allocated = 10 ;
58+ int used = 0 ;
59+ ChildScanCommon * result = palloc (10 * sizeof (ChildScanCommon ));
60+
61+ while (children < children_end && parts < parts_end )
62+ {
63+ if ((* children )-> relid < * parts )
64+ children ++ ;
65+ else
66+ {
67+ if (!(* parts < (* children )-> relid ))
68+ {
69+ ChildScanCommon child = palloc (sizeof (ChildScanCommonData ));
70+
71+ if (allocated <=used )
72+ {
73+ allocated *=2 ;
74+ result = repalloc (result ,allocated * sizeof (ChildScanCommon ));
75+ }
76+
77+ child -> content_type = CHILD_PLAN ;
78+ child -> content .plan = (* children )-> content .plan ;
79+ child -> relid = (* children )-> relid ;
80+
81+ result [used ++ ]= child ;
82+ children ++ ;
83+ }
84+ parts ++ ;
85+ }
86+ }
87+
88+ * nres = used ;
89+ return result ;
90+ }
91+
92+ /* qsort comparison function for oids */
93+ static int
94+ oid_cmp (const void * p1 ,const void * p2 )
95+ {
96+ Oid v1 = * ((const Oid * )p1 );
97+ Oid v2 = * ((const Oid * )p2 );
98+
99+ if (v1 < v2 )
100+ return -1 ;
101+ if (v1 > v2 )
102+ return 1 ;
103+ return 0 ;
104+ }
105+
106+ static Oid *
107+ get_partition_oids (List * ranges ,int * n ,PartRelationInfo * prel )
108+ {
109+ ListCell * range_cell ;
110+ int allocated = 10 ;
111+ int used = 0 ;
112+ Oid * result = palloc (allocated * sizeof (Oid ));
113+ Oid * children = dsm_array_get_pointer (& prel -> children );
114+
115+ foreach (range_cell ,ranges )
116+ {
117+ int i ;
118+ int a = irange_lower (lfirst_irange (range_cell ));
119+ int b = irange_upper (lfirst_irange (range_cell ));
120+
121+ for (i = a ;i <=b ;i ++ )
122+ {
123+ if (allocated <=used )
124+ {
125+ allocated *=2 ;
126+ result = repalloc (result ,allocated * sizeof (Oid ));
127+ }
128+
129+ Assert (i < prel -> children_count );
130+ result [used ++ ]= children [i ];
131+ }
132+ }
133+
134+ if (used > 1 )
135+ qsort (result ,used ,sizeof (Oid ),oid_cmp );
136+
137+ * n = used ;
138+ return result ;
139+ }
140+
19141static int
20142cmp_child_scan_common (const void * a ,const void * b )
21143{
@@ -175,7 +297,7 @@ pathman_join_pathlist_hook(PlannerInfo *root,
175297}
176298
177299static void
178- save_pickyappend_private (CustomScan * cscan ,PickyAppendPath * path , PlannerInfo * root )
300+ save_pickyappend_private (CustomScan * cscan ,PickyAppendPath * path )
179301{
180302ChildScanCommon * children = path -> children ;
181303int nchildren = path -> nchildren ;
@@ -205,8 +327,6 @@ unpack_pickyappend_private(PickyAppendState *scan_state, CustomScan *cscan)
205327ListCell * cur_plan ;
206328int i ;
207329
208- scan_state -> relid = linitial_oid (linitial (cscan -> custom_private ));
209-
210330i = 0 ;
211331forboth (cur_oid ,custom_oids ,cur_plan ,cscan -> custom_plans )
212332{
@@ -218,6 +338,10 @@ unpack_pickyappend_private(PickyAppendState *scan_state, CustomScan *cscan)
218338
219339children [i ++ ]= child ;
220340}
341+
342+ scan_state -> relid = linitial_oid (linitial (cscan -> custom_private ));
343+ scan_state -> children = children ;
344+ scan_state -> nchildren = nchildren ;
221345}
222346
223347Plan *
@@ -235,10 +359,11 @@ create_pickyappend_plan(PlannerInfo *root, RelOptInfo *rel,
235359cscan -> scan .scanrelid = 0 ;
236360
237361cscan -> custom_exprs = gpath -> cpath .custom_private ;
362+ cscan -> custom_plans = custom_plans ;
238363
239364cscan -> methods = & pickyappend_plan_methods ;
240365
241- save_pickyappend_private (cscan ,gpath , root );
366+ save_pickyappend_private (cscan ,gpath );
242367
243368return & cscan -> scan .plan ;
244369}
@@ -257,23 +382,61 @@ pickyappend_create_scan_state(CustomScan *node)
257382
258383scan_state -> prel = get_pathman_relation_info (scan_state -> relid ,NULL );
259384
385+ scan_state -> cur_plans = NULL ;
386+ scan_state -> ncur_plans = 0 ;
387+ scan_state -> running_idx = 0 ;
388+
260389return (Node * )scan_state ;
261390}
262391
263392void
264393pickyappend_begin (CustomScanState * node ,EState * estate ,int eflags )
265394{
395+ PickyAppendState * scan_state = (PickyAppendState * )node ;
396+
397+ scan_state -> custom_expr_states = (List * )ExecInitExpr ((Expr * )scan_state -> custom_exprs ,
398+ (PlanState * )scan_state );
266399}
267400
268401TupleTableSlot *
269402pickyappend_exec (CustomScanState * node )
270403{
404+ PickyAppendState * scan_state = (PickyAppendState * )node ;
405+
406+ while (scan_state -> running_idx < scan_state -> ncur_plans )
407+ {
408+ ChildScanCommon child = scan_state -> cur_plans [scan_state -> running_idx ];
409+ PlanState * state = child -> content .plan_state ;
410+ TupleTableSlot * slot = NULL ;
411+ bool quals ;
412+
413+ for (;;)
414+ {
415+ slot = ExecProcNode (state );
416+
417+ if (TupIsNull (slot ))
418+ break ;
419+
420+ node -> ss .ps .ps_ExprContext -> ecxt_scantuple = slot ;
421+ quals = ExecQual (scan_state -> custom_expr_states ,
422+ node -> ss .ps .ps_ExprContext , false);
423+
424+ if (quals )
425+ return slot ;
426+ }
427+
428+ scan_state -> running_idx ++ ;
429+ }
430+
271431return NULL ;
272432}
273433
274434void
275435pickyappend_end (CustomScanState * node )
276436{
437+ PickyAppendState * scan_state = (PickyAppendState * )node ;
438+
439+ clear_plan_states (scan_state -> cur_plans ,scan_state -> ncur_plans );
277440}
278441
279442void
@@ -284,26 +447,38 @@ pickyappend_rescan(CustomScanState *node)
284447PartRelationInfo * prel = scan_state -> prel ;
285448List * ranges ;
286449ListCell * lc ;
450+ Oid * parts ;
451+ int nparts ;
287452
288453ranges = list_make1_int (make_irange (0 ,prel -> children_count - 1 , false));
289454
290455foreach (lc ,scan_state -> custom_exprs )
291456{
292- WrapperNode * wn ;
293- WalkerContext wcxt ;
457+ WrapperNode * wn ;
458+ WalkerContext wcxt ;
294459
295460wcxt .econtext = econtext ;
296461wn = walk_expr_tree (& wcxt , (Expr * )lfirst (lc ),prel );
297462
298463ranges = irange_list_intersect (ranges ,wn -> rangeset );
299464}
300465
301- foreach (lc ,ranges )
302- {
303- elog (LOG ,"lower: %d, upper: %d" ,
304- irange_lower (lfirst_irange (lc )),
305- irange_upper (lfirst_irange (lc )));
306- }
466+ parts = get_partition_oids (ranges ,& nparts ,prel );
467+
468+ clear_plan_states (scan_state -> cur_plans ,scan_state -> ncur_plans );
469+
470+ scan_state -> cur_plans = select_required_plans (scan_state -> children ,
471+ scan_state -> nchildren ,
472+ parts ,nparts ,
473+ & scan_state -> ncur_plans );
474+ pfree (parts );
475+
476+ transform_plans_into_states (scan_state -> cur_plans ,scan_state -> ncur_plans ,
477+ scan_state -> css .ss .ps .state );
478+
479+ scan_state -> running_idx = 0 ;
480+
481+ /* elog(LOG, "nparts: %d, plans: %d", nparts, nplans); */
307482}
308483
309484void