Skip to content

Commit 2a7ac06

Browse files
committed
join_hook -> hooks, move rel_pathlist_hook to 'hooks'
1 parent ef9f5d9 commit 2a7ac06

File tree

8 files changed

+321
-281
lines changed

8 files changed

+321
-281
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# contrib/pg_pathman/Makefile
22

33
MODULE_big = pg_pathman
4-
OBJS = init.o pickyappend.o pg_pathman.o dsm_array.o \
5-
rangeset.o pl_funcs.o worker.o join_hook.o nodes_common.o $(WIN32RES)
4+
OBJS = init.o utils.o pickyappend.o pg_pathman.o dsm_array.o \
5+
rangeset.o pl_funcs.o worker.o hooks.o nodes_common.o $(WIN32RES)
66

77
EXTENSION = pg_pathman
88
EXTVERSION = 0.1

hooks.c

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
#include "postgres.h"
2+
#include "optimizer/cost.h"
3+
#include "optimizer/restrictinfo.h"
4+
#include "hooks.h"
5+
#include "pathman.h"
6+
#include "pickyappend.h"
7+
8+
9+
set_join_pathlist_hook_type set_join_pathlist_next = NULL;
10+
set_rel_pathlist_hook_type set_rel_pathlist_hook_next = NULL;
11+
12+
13+
void
14+
pathman_join_pathlist_hook(PlannerInfo *root,
15+
RelOptInfo *joinrel,
16+
RelOptInfo *outerrel,
17+
RelOptInfo *innerrel,
18+
JoinType jointype,
19+
JoinPathExtraData *extra)
20+
{
21+
JoinCostWorkspace workspace;
22+
Path *outer,
23+
*inner;
24+
Relids inner_required;
25+
RangeTblEntry *inner_entry = root->simple_rte_array[innerrel->relid];
26+
PartRelationInfo *inner_prel;
27+
NestPath *nest_path;
28+
List *pathkeys = NIL;
29+
List *joinrestrictclauses = extra->restrictlist;
30+
List *joinclauses,
31+
*otherclauses;
32+
ListCell *lc;
33+
34+
if (set_join_pathlist_next)
35+
set_join_pathlist_next(root, joinrel, outerrel,
36+
innerrel, jointype, extra);
37+
38+
if (jointype == JOIN_UNIQUE_OUTER ||
39+
jointype == JOIN_UNIQUE_INNER)
40+
{
41+
jointype = JOIN_INNER;
42+
}
43+
44+
if (jointype == JOIN_FULL || !pg_pathman_enable_pickyappend)
45+
return;
46+
47+
if (innerrel->reloptkind != RELOPT_BASEREL ||
48+
!inner_entry->inh ||
49+
!(inner_prel = get_pathman_relation_info(inner_entry->relid, NULL)))
50+
{
51+
return; /* Obviously not our case */
52+
}
53+
54+
/* Extract join clauses which will separate partitions */
55+
if (IS_OUTER_JOIN(extra->sjinfo->jointype))
56+
{
57+
extract_actual_join_clauses(joinrestrictclauses,
58+
&joinclauses, &otherclauses);
59+
}
60+
else
61+
{
62+
/* We can treat all clauses alike for an inner join */
63+
joinclauses = extract_actual_clauses(joinrestrictclauses, false);
64+
otherclauses = NIL;
65+
}
66+
67+
foreach (lc, innerrel->pathlist)
68+
{
69+
AppendPath *cur_inner_path = (AppendPath *) lfirst(lc);
70+
71+
if (!IsA(cur_inner_path, AppendPath))
72+
continue;
73+
74+
outer = outerrel->cheapest_total_path;
75+
76+
inner_required = bms_union(PATH_REQ_OUTER((Path *) cur_inner_path),
77+
bms_make_singleton(outerrel->relid));
78+
79+
inner = create_pickyappend_path(root, cur_inner_path,
80+
get_appendrel_parampathinfo(innerrel,
81+
inner_required),
82+
joinclauses);
83+
84+
initial_cost_nestloop(root, &workspace, jointype,
85+
outer, inner,
86+
extra->sjinfo, &extra->semifactors);
87+
88+
pathkeys = build_join_pathkeys(root, joinrel, jointype, outer->pathkeys);
89+
90+
nest_path = create_nestloop_path(root, joinrel, jointype, &workspace,
91+
extra->sjinfo, &extra->semifactors,
92+
outer, inner, extra->restrictlist,
93+
pathkeys,
94+
calc_nestloop_required_outer(outer, inner));
95+
96+
add_path(joinrel, (Path *) nest_path);
97+
}
98+
}
99+
100+
/*
101+
* Main hook. All the magic goes here
102+
*/
103+
void
104+
pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTblEntry *rte)
105+
{
106+
PartRelationInfo *prel = NULL;
107+
RelOptInfo **new_rel_array;
108+
RangeTblEntry **new_rte_array;
109+
int len;
110+
bool found;
111+
int first_child_relid = 0;
112+
113+
if (!pg_pathman_enable)
114+
return;
115+
116+
/* This works only for SELECT queries */
117+
if (root->parse->commandType != CMD_SELECT || !inheritance_disabled)
118+
return;
119+
120+
/* Lookup partitioning information for parent relation */
121+
prel = get_pathman_relation_info(rte->relid, &found);
122+
123+
if (prel != NULL && found)
124+
{
125+
ListCell *lc;
126+
int i;
127+
Oid *dsm_arr;
128+
List *ranges,
129+
*wrappers;
130+
PathKey *pathkeyAsc = NULL,
131+
*pathkeyDesc = NULL;
132+
133+
if (prel->parttype == PT_RANGE)
134+
{
135+
/*
136+
* Get pathkeys for ascending and descending sort by partition
137+
* column
138+
*/
139+
List *pathkeys;
140+
Var *var;
141+
Oid vartypeid,
142+
varcollid;
143+
int32 type_mod;
144+
TypeCacheEntry *tce;
145+
146+
/* Make Var from patition column */
147+
get_rte_attribute_type(rte, prel->attnum,
148+
&vartypeid, &type_mod, &varcollid);
149+
var = makeVar(rti, prel->attnum, vartypeid, type_mod, varcollid, 0);
150+
var->location = -1;
151+
152+
/* Determine operator type */
153+
tce = lookup_type_cache(var->vartype, TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
154+
155+
/* Make pathkeys */
156+
pathkeys = build_expression_pathkey(root, (Expr *)var, NULL,
157+
tce->lt_opr, NULL, false);
158+
if (pathkeys)
159+
pathkeyAsc = (PathKey *) linitial(pathkeys);
160+
pathkeys = build_expression_pathkey(root, (Expr *)var, NULL,
161+
tce->gt_opr, NULL, false);
162+
if (pathkeys)
163+
pathkeyDesc = (PathKey *) linitial(pathkeys);
164+
}
165+
166+
rte->inh = true;
167+
dsm_arr = (Oid *) dsm_array_get_pointer(&prel->children);
168+
ranges = list_make1_int(make_irange(0, prel->children_count - 1, false));
169+
170+
/* Make wrappers over restrictions and collect final rangeset */
171+
wrappers = NIL;
172+
foreach(lc, rel->baserestrictinfo)
173+
{
174+
WrapperNode *wrap;
175+
176+
RestrictInfo *rinfo = (RestrictInfo*) lfirst(lc);
177+
178+
wrap = walk_expr_tree(NULL, rinfo->clause, prel);
179+
wrappers = lappend(wrappers, wrap);
180+
ranges = irange_list_intersect(ranges, wrap->rangeset);
181+
}
182+
183+
/*
184+
* Expand simple_rte_array and simple_rel_array
185+
*/
186+
187+
if (ranges)
188+
{
189+
len = irange_list_length(ranges);
190+
191+
/* Expand simple_rel_array and simple_rte_array */
192+
new_rel_array = (RelOptInfo **)
193+
palloc0((root->simple_rel_array_size + len) * sizeof(RelOptInfo *));
194+
195+
/* simple_rte_array is an array equivalent of the rtable list */
196+
new_rte_array = (RangeTblEntry **)
197+
palloc0((root->simple_rel_array_size + len) * sizeof(RangeTblEntry *));
198+
199+
/* Copy relations to the new arrays */
200+
for (i = 0; i < root->simple_rel_array_size; i++)
201+
{
202+
new_rel_array[i] = root->simple_rel_array[i];
203+
new_rte_array[i] = root->simple_rte_array[i];
204+
}
205+
206+
/* Free old arrays */
207+
pfree(root->simple_rel_array);
208+
pfree(root->simple_rte_array);
209+
210+
root->simple_rel_array_size += len;
211+
root->simple_rel_array = new_rel_array;
212+
root->simple_rte_array = new_rte_array;
213+
}
214+
215+
/*
216+
* Iterate all indexes in rangeset and append corresponding child
217+
* relations.
218+
*/
219+
foreach(lc, ranges)
220+
{
221+
IndexRange irange = lfirst_irange(lc);
222+
Oid childOid;
223+
224+
for (i = irange_lower(irange); i <= irange_upper(irange); i++)
225+
{
226+
int idx;
227+
228+
childOid = dsm_arr[i];
229+
idx = append_child_relation(root, rel, rti, rte, i, childOid, wrappers);
230+
231+
if (!first_child_relid)
232+
first_child_relid = idx;
233+
}
234+
}
235+
236+
/* Clear old path list */
237+
list_free(rel->pathlist);
238+
239+
rel->pathlist = NIL;
240+
set_append_rel_pathlist(root, rel, rti, rte, pathkeyAsc, pathkeyDesc);
241+
set_append_rel_size(root, rel, rti, rte);
242+
}
243+
244+
/* Invoke original hook if needed */
245+
if (set_rel_pathlist_hook_next != NULL)
246+
set_rel_pathlist_hook_next(root, rel, rti, rte);
247+
}
248+

join_hook.h renamed to hooks.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44
#include "postgres.h"
55
#include "optimizer/paths.h"
66

7-
extern set_join_pathlist_hook_type set_join_pathlist_next;
7+
extern set_join_pathlist_hook_type set_join_pathlist_next;
8+
extern set_rel_pathlist_hook_type set_rel_pathlist_hook_next;
89

910
void pathman_join_pathlist_hook(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel,
1011
RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra);
1112

13+
void pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTblEntry *rte);
14+
1215
#endif

join_hook.c

Lines changed: 0 additions & 95 deletions
This file was deleted.

0 commit comments

Comments
 (0)