1717#include "runtime_merge_append.h"
1818
1919
20+ static int cmp_tlist_vars (const void * a ,const void * b );
21+ static List * sort_rel_tlist (List * tlist );
22+
2023set_join_pathlist_hook_type set_join_pathlist_next = NULL ;
2124set_rel_pathlist_hook_type set_rel_pathlist_hook_next = NULL ;
2225
23-
26+ /* Take care of joins */
2427void
2528pathman_join_pathlist_hook (PlannerInfo * root ,
2629RelOptInfo * joinrel ,
@@ -124,9 +127,7 @@ pathman_join_pathlist_hook(PlannerInfo *root,
124127}
125128}
126129
127- /*
128- * Main hook. All the magic goes here
129- */
130+ /* Cope with simple relations */
130131void
131132pathman_rel_pathlist_hook (PlannerInfo * root ,RelOptInfo * rel ,Index rti ,RangeTblEntry * rte )
132133{
@@ -143,7 +144,7 @@ pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTb
143144if (!pg_pathman_enable )
144145return ;
145146
146- /* This works only for SELECT queries */
147+ /* This works only for SELECT queries(at least for now) */
147148if (root -> parse -> commandType != CMD_SELECT || !inheritance_disabled )
148149return ;
149150
@@ -153,14 +154,14 @@ pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTb
153154if (prel != NULL && found )
154155{
155156ListCell * lc ;
156- int i ;
157157Oid * dsm_arr ;
158158List * ranges ,
159159* wrappers ;
160160PathKey * pathkeyAsc = NULL ,
161161* pathkeyDesc = NULL ;
162162double paramsel = 1.0 ;
163163WalkerContext context ;
164+ int i ;
164165
165166if (prel -> parttype == PT_RANGE )
166167{
@@ -252,6 +253,9 @@ pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTb
252253root -> simple_rte_array = new_rte_array ;
253254}
254255
256+ /* Target list should be sorted in physical order for custom nodes to work */
257+ rel -> reltargetlist = sort_rel_tlist (rel -> reltargetlist );
258+
255259/*
256260 * Iterate all indexes in rangeset and append corresponding child
257261 * relations.
@@ -271,6 +275,7 @@ pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTb
271275set_append_rel_pathlist (root ,rel ,rti ,rte ,pathkeyAsc ,pathkeyDesc );
272276set_append_rel_size (root ,rel ,rti ,rte );
273277
278+ /* No need to go further, return */
274279if (!(pg_pathman_enable_runtimeappend ||
275280pg_pathman_enable_runtime_merge_append ))
276281return ;
@@ -282,6 +287,7 @@ pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTb
282287ParamPathInfo * ppi = get_appendrel_parampathinfo (rel ,inner_required );
283288Path * inner_path = NULL ;
284289
290+ /* Skip if rel contains some join-related stuff or path type mismatched */
285291if (!(IsA (cur_path ,AppendPath )|| IsA (cur_path ,MergeAppendPath ))||
286292rel -> has_eclass_joins ||
287293rel -> joininfo )
@@ -318,3 +324,51 @@ void pg_pathman_enable_assign_hook(bool newval, void *extra)
318324"RuntimeAppend and RuntimeMergeAppend nodes have been %s" ,
319325newval ?"enabled" :"disabled" );
320326}
327+
328+ /*
329+ * Sorts reltargetlist by Var's varattno (physical order) since
330+ * we can't use static build_path_tlist() for our custom nodes.
331+ *
332+ * See create_scan_plan & use_physical_tlist for more details.
333+ */
334+ static List *
335+ sort_rel_tlist (List * tlist )
336+ {
337+ int i ;
338+ int plain_tlist_size = list_length (tlist );
339+ Var * * plain_tlist = palloc (plain_tlist_size * sizeof (Var * ));
340+ ListCell * tlist_cell ;
341+ List * result = NIL ;
342+
343+ i = 0 ;
344+ foreach (tlist_cell ,tlist )
345+ plain_tlist [i ++ ]= lfirst (tlist_cell );
346+
347+ qsort (plain_tlist ,plain_tlist_size ,sizeof (Var * ),cmp_tlist_vars );
348+
349+ for (i = 0 ;i < plain_tlist_size ;i ++ )
350+ result = lappend (result ,plain_tlist [i ]);
351+
352+ return result ;
353+ }
354+
355+ /* Compare Vars by varattno */
356+ static int
357+ cmp_tlist_vars (const void * a ,const void * b )
358+ {
359+ Var * v1 = * (Var * * )a ;
360+ Var * v2 = * (Var * * )b ;
361+
362+ Assert (IsA (v1 ,Var )&& IsA (v2 ,Var ));
363+
364+ if (v1 -> varattno > v2 -> varattno )
365+ return 1 ;
366+ else if (v1 -> varattno < v2 -> varattno )
367+ return -1 ;
368+ else
369+ {
370+ /* XXX: I really doubt this case is ok */
371+ Assert (v1 -> varattno != v2 -> varattno );
372+ return 0 ;
373+ }
374+ }