17
17
#include "runtime_merge_append.h"
18
18
19
19
20
+ static int cmp_tlist_vars (const void * a , const void * b );
21
+ static List * sort_rel_tlist (List * tlist );
22
+
20
23
set_join_pathlist_hook_type set_join_pathlist_next = NULL ;
21
24
set_rel_pathlist_hook_type set_rel_pathlist_hook_next = NULL ;
22
25
23
-
26
+ /* Take care of joins */
24
27
void
25
28
pathman_join_pathlist_hook (PlannerInfo * root ,
26
29
RelOptInfo * joinrel ,
@@ -124,9 +127,7 @@ pathman_join_pathlist_hook(PlannerInfo *root,
124
127
}
125
128
}
126
129
127
- /*
128
- * Main hook. All the magic goes here
129
- */
130
+ /* Cope with simple relations */
130
131
void
131
132
pathman_rel_pathlist_hook (PlannerInfo * root , RelOptInfo * rel , Index rti , RangeTblEntry * rte )
132
133
{
@@ -143,7 +144,7 @@ pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTb
143
144
if (!pg_pathman_enable )
144
145
return ;
145
146
146
- /* This works only for SELECT queries */
147
+ /* This works only for SELECT queries (at least for now) */
147
148
if (root -> parse -> commandType != CMD_SELECT || !inheritance_disabled )
148
149
return ;
149
150
@@ -153,14 +154,14 @@ pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTb
153
154
if (prel != NULL && found )
154
155
{
155
156
ListCell * lc ;
156
- int i ;
157
157
Oid * dsm_arr ;
158
158
List * ranges ,
159
159
* wrappers ;
160
160
PathKey * pathkeyAsc = NULL ,
161
161
* pathkeyDesc = NULL ;
162
162
double paramsel = 1.0 ;
163
163
WalkerContext context ;
164
+ int i ;
164
165
165
166
if (prel -> parttype == PT_RANGE )
166
167
{
@@ -252,6 +253,9 @@ pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTb
252
253
root -> simple_rte_array = new_rte_array ;
253
254
}
254
255
256
+ /* Target list should be sorted in physical order for custom nodes to work */
257
+ rel -> reltargetlist = sort_rel_tlist (rel -> reltargetlist );
258
+
255
259
/*
256
260
* Iterate all indexes in rangeset and append corresponding child
257
261
* relations.
@@ -271,6 +275,7 @@ pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTb
271
275
set_append_rel_pathlist (root , rel , rti , rte , pathkeyAsc , pathkeyDesc );
272
276
set_append_rel_size (root , rel , rti , rte );
273
277
278
+ /* No need to go further, return */
274
279
if (!(pg_pathman_enable_runtimeappend ||
275
280
pg_pathman_enable_runtime_merge_append ))
276
281
return ;
@@ -282,6 +287,7 @@ pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTb
282
287
ParamPathInfo * ppi = get_appendrel_parampathinfo (rel , inner_required );
283
288
Path * inner_path = NULL ;
284
289
290
+ /* Skip if rel contains some join-related stuff or path type mismatched */
285
291
if (!(IsA (cur_path , AppendPath ) || IsA (cur_path , MergeAppendPath )) ||
286
292
rel -> has_eclass_joins ||
287
293
rel -> joininfo )
@@ -318,3 +324,51 @@ void pg_pathman_enable_assign_hook(bool newval, void *extra)
318
324
"RuntimeAppend and RuntimeMergeAppend nodes have been %s" ,
319
325
newval ? "enabled" : "disabled" );
320
326
}
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