Skip to content

Commit fbda4ec

Browse files
committed
fix tlist projections, use varoattno for expr walker
1 parent e841962 commit fbda4ec

File tree

5 files changed

+149
-14
lines changed

5 files changed

+149
-14
lines changed

nodes_common.c

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,33 @@ get_partition_oids(List *ranges, int *n, PartRelationInfo *prel)
137137
return result;
138138
}
139139

140+
/* Replace Vars' varnos with the value provided by 'parent' */
141+
static List *
142+
replace_tlist_varnos(List *child_tlist, RelOptInfo *parent)
143+
{
144+
ListCell *lc;
145+
List *result = NIL;
146+
int i = 1; /* resnos begin with 1 */
147+
148+
foreach (lc, child_tlist)
149+
{
150+
Var *var = (Var *) ((TargetEntry *) lfirst(lc))->expr;
151+
Var *newvar = palloc(sizeof(Var));
152+
153+
Assert(IsA(var, Var));
154+
155+
*newvar = *var;
156+
newvar->varno = parent->relid;
157+
newvar->varnoold = parent->relid;
158+
159+
result = lappend(result, makeTargetEntry((Expr *) newvar,
160+
i++, /* item's index */
161+
NULL, false));
162+
}
163+
164+
return result;
165+
}
166+
140167
static void
141168
pack_runtimeappend_private(CustomScan *cscan, RuntimeAppendPath *path)
142169
{
@@ -277,25 +304,72 @@ create_append_plan_common(PlannerInfo *root, RelOptInfo *rel,
277304
RuntimeAppendPath *gpath = (RuntimeAppendPath *) best_path;
278305
CustomScan *cscan;
279306

280-
/* HACK: kill me plz, it severely breaks IndexOnlyScan */
307+
cscan = makeNode(CustomScan);
308+
cscan->custom_scan_tlist = NIL;
309+
281310
if (custom_plans)
282311
{
283312
ListCell *lc1,
284313
*lc2;
285314

286315
forboth (lc1, gpath->cpath.custom_paths, lc2, custom_plans)
287316
{
288-
Plan *child_plan = (Plan *) lfirst(lc2);
289-
RelOptInfo *child_rel = ((Path *) lfirst(lc1))->parent;
317+
Plan *child_plan = (Plan *) lfirst(lc2);
318+
RelOptInfo *child_rel = ((Path *) lfirst(lc1))->parent;
290319

291-
child_plan->targetlist = build_physical_tlist(root, child_rel);
320+
/* We inforce IndexOnlyScans to return all available columns */
321+
if (IsA(child_plan, IndexOnlyScan))
322+
{
323+
IndexOptInfo *indexinfo = ((IndexPath *) lfirst(lc1))->indexinfo;
324+
RangeTblEntry *rentry = root->simple_rte_array[child_rel->relid];
325+
Relation child_relation;
326+
327+
/* TODO: find out whether we need locks or not */
328+
child_relation = heap_open(rentry->relid, NoLock);
329+
child_plan->targetlist = build_index_tlist(root, indexinfo,
330+
child_relation);
331+
heap_close(child_relation, NoLock);
332+
333+
if (!cscan->custom_scan_tlist)
334+
{
335+
/* Set appropriate tlist for child scans */
336+
cscan->custom_scan_tlist =
337+
replace_tlist_varnos(child_plan->targetlist, rel);
338+
339+
/* Replace parent's tlist as well */
340+
tlist = cscan->custom_scan_tlist;
341+
}
342+
}
343+
else
344+
child_plan->targetlist = build_physical_tlist(root, child_rel);
292345
}
346+
347+
/*
348+
* Go through the other (non-IOS) plans and replace their
349+
* physical tlists with the new 'custom_scan_tlist'.
350+
*/
351+
if (cscan->custom_scan_tlist)
352+
forboth (lc1, gpath->cpath.custom_paths, lc2, custom_plans)
353+
{
354+
Plan *child_plan = (Plan *) lfirst(lc2);
355+
RelOptInfo *child_rel = ((Path *) lfirst(lc1))->parent;
356+
357+
if (!IsA(child_plan, IndexOnlyScan))
358+
child_plan->targetlist =
359+
replace_tlist_varnos(cscan->custom_scan_tlist, child_rel);
360+
}
293361
}
294362

295-
cscan = makeNode(CustomScan);
296363
cscan->scan.plan.qual = NIL;
297364
cscan->scan.plan.targetlist = tlist;
298-
cscan->custom_scan_tlist = tlist;
365+
366+
/*
367+
* Initialize custom_scan_tlist if it's not
368+
* ready yet (there are no IndexOnlyScans).
369+
*/
370+
if (!cscan->custom_scan_tlist)
371+
cscan->custom_scan_tlist = tlist;
372+
299373
cscan->scan.scanrelid = 0;
300374

301375
cscan->custom_exprs = get_actual_clauses(clauses);

pg_pathman.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,13 +1304,13 @@ handle_opexpr(const OpExpr *expr, WalkerContext *context)
13041304
if (list_length(expr->args) == 2)
13051305
{
13061306
if (IsA(linitial(expr->args), Var)
1307-
&& ((Var *)linitial(expr->args))->varattno == prel->attnum)
1307+
&& ((Var *)linitial(expr->args))->varoattno == prel->attnum)
13081308
{
13091309
firstarg = (Node *) linitial(expr->args);
13101310
secondarg = (Node *) lsecond(expr->args);
13111311
}
13121312
else if (IsA(lsecond(expr->args), Var)
1313-
&& ((Var *)lsecond(expr->args))->varattno == prel->attnum)
1313+
&& ((Var *)lsecond(expr->args))->varoattno == prel->attnum)
13141314
{
13151315
firstarg = (Node *) lsecond(expr->args);
13161316
secondarg = (Node *) linitial(expr->args);

runtime_merge_append.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -260,15 +260,15 @@ create_runtimemergeappend_plan(PlannerInfo *root, RelOptInfo *rel,
260260
* but it seems like a good idea to check the sort column numbers
261261
* explicitly, to ensure the tlists really do match up.
262262
*/
263-
Assert(numsortkeys == node_numCols);
263+
Assert(numsortkeys == mag.numCols);
264264
if (memcmp(sortColIdx, mag.sortColIdx,
265265
numsortkeys * sizeof(AttrNumber)) != 0)
266266
elog(ERROR, "RuntimeMergeAppend child's targetlist doesn't match RuntimeMergeAppend");
267-
Assert(memcmp(sortOperators, node_sortOperators,
267+
Assert(memcmp(sortOperators, mag.sortOperators,
268268
numsortkeys * sizeof(Oid)) == 0);
269-
Assert(memcmp(collations, node_collations,
269+
Assert(memcmp(collations, mag.collations,
270270
numsortkeys * sizeof(Oid)) == 0);
271-
Assert(memcmp(nullsFirst, node_nullsFirst,
271+
Assert(memcmp(nullsFirst, mag.nullsFirst,
272272
numsortkeys * sizeof(bool)) == 0);
273273

274274
/* Now, insert a Sort node if subplan isn't sufficiently ordered */

utils.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
*/
1010
#include "utils.h"
1111
#include "nodes/nodeFuncs.h"
12+
#include "nodes/makefuncs.h"
1213
#include "parser/parse_param.h"
1314
#include "utils/builtins.h"
1415
#include "rewrite/rewriteManip.h"
16+
#include "catalog/heap.h"
1517

1618

1719
static bool clause_contains_params_walker(Node *node, void *context);
@@ -36,6 +38,10 @@ clause_contains_params_walker(Node *node, void *context)
3638
context);
3739
}
3840

41+
/* NOTE: Used for debug */
42+
#ifdef __GNUC__
43+
__attribute__((unused))
44+
#endif
3945
static char *
4046
bms_print(Bitmapset *bms)
4147
{
@@ -49,3 +55,57 @@ bms_print(Bitmapset *bms)
4955

5056
return str.data;
5157
}
58+
59+
List *
60+
build_index_tlist(PlannerInfo *root, IndexOptInfo *index,
61+
Relation heapRelation)
62+
{
63+
List *tlist = NIL;
64+
Index varno = index->rel->relid;
65+
ListCell *indexpr_item;
66+
int i;
67+
68+
indexpr_item = list_head(index->indexprs);
69+
for (i = 0; i < index->ncolumns; i++)
70+
{
71+
int indexkey = index->indexkeys[i];
72+
Expr *indexvar;
73+
74+
if (indexkey != 0)
75+
{
76+
/* simple column */
77+
Form_pg_attribute att_tup;
78+
79+
if (indexkey < 0)
80+
att_tup = SystemAttributeDefinition(indexkey,
81+
heapRelation->rd_rel->relhasoids);
82+
else
83+
att_tup = heapRelation->rd_att->attrs[indexkey - 1];
84+
85+
indexvar = (Expr *) makeVar(varno,
86+
indexkey,
87+
att_tup->atttypid,
88+
att_tup->atttypmod,
89+
att_tup->attcollation,
90+
0);
91+
}
92+
else
93+
{
94+
/* expression column */
95+
if (indexpr_item == NULL)
96+
elog(ERROR, "wrong number of index expressions");
97+
indexvar = (Expr *) lfirst(indexpr_item);
98+
indexpr_item = lnext(indexpr_item);
99+
}
100+
101+
tlist = lappend(tlist,
102+
makeTargetEntry(indexvar,
103+
i + 1,
104+
NULL,
105+
false));
106+
}
107+
if (indexpr_item != NULL)
108+
elog(ERROR, "wrong number of index expressions");
109+
110+
return tlist;
111+
}

utils.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define UTILS_H
1212

1313
#include "postgres.h"
14+
#include "utils/rel.h"
1415
#include "nodes/relation.h"
1516
#include "nodes/nodeFuncs.h"
1617

@@ -23,7 +24,7 @@ typedef struct
2324

2425
bool clause_contains_params(Node *clause);
2526

26-
int cmp_tlist_vars(const void *a, const void *b);
27-
List * sort_rel_tlist(List *tlist);
27+
List * build_index_tlist(PlannerInfo *root, IndexOptInfo *index,
28+
Relation heapRelation);
2829

2930
#endif

0 commit comments

Comments
 (0)