13
13
#include "pickyappend.h"
14
14
15
15
16
+
17
+ /* Compare plans by 'original_order' */
18
+ static int
19
+ cmp_child_scan_common_by_orig_order (const void * ap ,
20
+ const void * bp )
21
+ {
22
+ ChildScanCommon a = * (ChildScanCommon * )ap ;
23
+ ChildScanCommon b = * (ChildScanCommon * )bp ;
24
+
25
+ if (a -> original_order > b -> original_order )
26
+ return 1 ;
27
+ else if (a -> original_order < b -> original_order )
28
+ return -1 ;
29
+ else
30
+ return 0 ;
31
+ }
32
+
16
33
static void
17
34
free_child_scan_common_array (ChildScanCommon * cur_plans ,int n )
18
35
{
@@ -165,6 +182,7 @@ unpack_pickyappend_private(PickyAppendState *scan_state, CustomScan *cscan)
165
182
int nchildren = list_length (custom_oids );
166
183
HTAB * children_table = scan_state -> children_table ;
167
184
HASHCTL * children_table_config = & scan_state -> children_table_config ;
185
+ int i ;
168
186
169
187
memset (children_table_config ,0 ,sizeof (HASHCTL ));
170
188
children_table_config -> keysize = sizeof (Oid );
@@ -174,6 +192,7 @@ unpack_pickyappend_private(PickyAppendState *scan_state, CustomScan *cscan)
174
192
children_table_config ,
175
193
HASH_ELEM |HASH_BLOBS );
176
194
195
+ i = 0 ;
177
196
forboth (oid_cell ,custom_oids ,plan_cell ,cscan -> custom_plans )
178
197
{
179
198
bool child_found ;
@@ -186,6 +205,7 @@ unpack_pickyappend_private(PickyAppendState *scan_state, CustomScan *cscan)
186
205
Assert (!child_found );/* there should be no collisions */
187
206
188
207
child -> content .plan = (Plan * )lfirst (plan_cell );
208
+ child -> original_order = i ++ ;/* will be used in EXPLAIN */
189
209
}
190
210
191
211
scan_state -> children_table = children_table ;
@@ -323,18 +343,6 @@ begin_append_common(CustomScanState *node, EState *estate, int eflags)
323
343
scan_state -> plan_state_table = plan_state_table ;
324
344
scan_state -> custom_expr_states = (List * )ExecInitExpr ((Expr * )scan_state -> custom_exprs ,
325
345
(PlanState * )scan_state );
326
-
327
- /*
328
- * ExecProcNode() won't ReScan plans without params, do this
329
- * provided that there are no external PARAM_EXEC params.
330
- *
331
- * rescan_append_common is required for prepared statements,
332
- * but at the same time we don't want it to be called several
333
- * times within a single run (for example, ExecNestLoop calls
334
- * ExecReScan itself)
335
- */
336
- if (!node -> ss .ps .chgParam && bms_is_empty (node -> ss .ps .plan -> extParam ))
337
- rescan_append_common (node );
338
346
}
339
347
340
348
void
@@ -393,5 +401,49 @@ rescan_append_common(CustomScanState *node)
393
401
void
394
402
explain_append_common (CustomScanState * node ,HTAB * children_table ,ExplainState * es )
395
403
{
396
- /* Nothing to do here */
404
+ PickyAppendState * scan_state = (PickyAppendState * )node ;
405
+
406
+ /* Construct excess PlanStates */
407
+ if (!es -> analyze )
408
+ {
409
+ int allocated = 10 ;
410
+ int used = 0 ;
411
+ ChildScanCommon * custom_ps = palloc (allocated * sizeof (ChildScanCommon ));
412
+ ChildScanCommon child ;
413
+ HASH_SEQ_STATUS seqstat ;
414
+ int i ;
415
+
416
+ /* There can't be any nodes since we're not scanning anything */
417
+ Assert (!node -> custom_ps );
418
+
419
+ hash_seq_init (& seqstat ,scan_state -> children_table );
420
+
421
+ while ((child = (ChildScanCommon )hash_seq_search (& seqstat )))
422
+ {
423
+ if (allocated <=used )
424
+ {
425
+ allocated *=2 ;
426
+ custom_ps = repalloc (custom_ps ,allocated * sizeof (ChildScanCommon ));
427
+ }
428
+
429
+ custom_ps [used ++ ]= child ;
430
+ }
431
+
432
+ /*
433
+ * We have to restore the original plan order
434
+ * which has been lost within the hash table
435
+ */
436
+ qsort (custom_ps ,used ,sizeof (ChildScanCommon ),
437
+ cmp_child_scan_common_by_orig_order );
438
+
439
+ /*
440
+ * These PlanStates will be used by EXPLAIN,
441
+ * pickyappend_end will destroy them eventually
442
+ */
443
+ for (i = 0 ;i < used ;i ++ )
444
+ node -> custom_ps = lappend (node -> custom_ps ,
445
+ ExecInitNode (custom_ps [i ]-> content .plan ,
446
+ node -> ss .ps .state ,
447
+ 0 ));
448
+ }
397
449
}