@@ -16,6 +16,128 @@ CustomPathMethodspickyappend_path_methods;
16
16
CustomScanMethods pickyappend_plan_methods ;
17
17
CustomExecMethods pickyappend_exec_methods ;
18
18
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
+
19
141
static int
20
142
cmp_child_scan_common (const void * a ,const void * b )
21
143
{
@@ -175,7 +297,7 @@ pathman_join_pathlist_hook(PlannerInfo *root,
175
297
}
176
298
177
299
static void
178
- save_pickyappend_private (CustomScan * cscan ,PickyAppendPath * path , PlannerInfo * root )
300
+ save_pickyappend_private (CustomScan * cscan ,PickyAppendPath * path )
179
301
{
180
302
ChildScanCommon * children = path -> children ;
181
303
int nchildren = path -> nchildren ;
@@ -205,8 +327,6 @@ unpack_pickyappend_private(PickyAppendState *scan_state, CustomScan *cscan)
205
327
ListCell * cur_plan ;
206
328
int i ;
207
329
208
- scan_state -> relid = linitial_oid (linitial (cscan -> custom_private ));
209
-
210
330
i = 0 ;
211
331
forboth (cur_oid ,custom_oids ,cur_plan ,cscan -> custom_plans )
212
332
{
@@ -218,6 +338,10 @@ unpack_pickyappend_private(PickyAppendState *scan_state, CustomScan *cscan)
218
338
219
339
children [i ++ ]= child ;
220
340
}
341
+
342
+ scan_state -> relid = linitial_oid (linitial (cscan -> custom_private ));
343
+ scan_state -> children = children ;
344
+ scan_state -> nchildren = nchildren ;
221
345
}
222
346
223
347
Plan *
@@ -235,10 +359,11 @@ create_pickyappend_plan(PlannerInfo *root, RelOptInfo *rel,
235
359
cscan -> scan .scanrelid = 0 ;
236
360
237
361
cscan -> custom_exprs = gpath -> cpath .custom_private ;
362
+ cscan -> custom_plans = custom_plans ;
238
363
239
364
cscan -> methods = & pickyappend_plan_methods ;
240
365
241
- save_pickyappend_private (cscan ,gpath , root );
366
+ save_pickyappend_private (cscan ,gpath );
242
367
243
368
return & cscan -> scan .plan ;
244
369
}
@@ -257,23 +382,61 @@ pickyappend_create_scan_state(CustomScan *node)
257
382
258
383
scan_state -> prel = get_pathman_relation_info (scan_state -> relid ,NULL );
259
384
385
+ scan_state -> cur_plans = NULL ;
386
+ scan_state -> ncur_plans = 0 ;
387
+ scan_state -> running_idx = 0 ;
388
+
260
389
return (Node * )scan_state ;
261
390
}
262
391
263
392
void
264
393
pickyappend_begin (CustomScanState * node ,EState * estate ,int eflags )
265
394
{
395
+ PickyAppendState * scan_state = (PickyAppendState * )node ;
396
+
397
+ scan_state -> custom_expr_states = (List * )ExecInitExpr ((Expr * )scan_state -> custom_exprs ,
398
+ (PlanState * )scan_state );
266
399
}
267
400
268
401
TupleTableSlot *
269
402
pickyappend_exec (CustomScanState * node )
270
403
{
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
+
271
431
return NULL ;
272
432
}
273
433
274
434
void
275
435
pickyappend_end (CustomScanState * node )
276
436
{
437
+ PickyAppendState * scan_state = (PickyAppendState * )node ;
438
+
439
+ clear_plan_states (scan_state -> cur_plans ,scan_state -> ncur_plans );
277
440
}
278
441
279
442
void
@@ -284,26 +447,38 @@ pickyappend_rescan(CustomScanState *node)
284
447
PartRelationInfo * prel = scan_state -> prel ;
285
448
List * ranges ;
286
449
ListCell * lc ;
450
+ Oid * parts ;
451
+ int nparts ;
287
452
288
453
ranges = list_make1_int (make_irange (0 ,prel -> children_count - 1 , false));
289
454
290
455
foreach (lc ,scan_state -> custom_exprs )
291
456
{
292
- WrapperNode * wn ;
293
- WalkerContext wcxt ;
457
+ WrapperNode * wn ;
458
+ WalkerContext wcxt ;
294
459
295
460
wcxt .econtext = econtext ;
296
461
wn = walk_expr_tree (& wcxt , (Expr * )lfirst (lc ),prel );
297
462
298
463
ranges = irange_list_intersect (ranges ,wn -> rangeset );
299
464
}
300
465
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); */
307
482
}
308
483
309
484
void