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 ,
2629 RelOptInfo * 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
143144 if (!pg_pathman_enable )
144145 return ;
145146
146- /* This works only for SELECT queries */
147+ /* This works only for SELECT queries (at least for now) */
147148 if (root -> parse -> commandType != CMD_SELECT || !inheritance_disabled )
148149 return ;
149150
@@ -153,14 +154,14 @@ pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTb
153154 if (prel != NULL && found )
154155 {
155156 ListCell * lc ;
156- int i ;
157157 Oid * dsm_arr ;
158158 List * ranges ,
159159 * wrappers ;
160160 PathKey * pathkeyAsc = NULL ,
161161 * pathkeyDesc = NULL ;
162162 double paramsel = 1.0 ;
163163 WalkerContext context ;
164+ int i ;
164165
165166 if (prel -> parttype == PT_RANGE )
166167 {
@@ -252,6 +253,9 @@ pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTb
252253 root -> 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
271275 set_append_rel_pathlist (root , rel , rti , rte , pathkeyAsc , pathkeyDesc );
272276 set_append_rel_size (root , rel , rti , rte );
273277
278+ /* No need to go further, return */
274279 if (!(pg_pathman_enable_runtimeappend ||
275280 pg_pathman_enable_runtime_merge_append ))
276281 return ;
@@ -282,6 +287,7 @@ pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTb
282287 ParamPathInfo * ppi = get_appendrel_parampathinfo (rel , inner_required );
283288 Path * inner_path = NULL ;
284289
290+ /* Skip if rel contains some join-related stuff or path type mismatched */
285291 if (!(IsA (cur_path , AppendPath ) || IsA (cur_path , MergeAppendPath )) ||
286292 rel -> has_eclass_joins ||
287293 rel -> joininfo )
@@ -318,3 +324,51 @@ void pg_pathman_enable_assign_hook(bool newval, void *extra)
318324 "RuntimeAppend and RuntimeMergeAppend nodes have been %s" ,
319325 newval ? "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+ }
0 commit comments