Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cc89414

Browse files
committed
Merge branch 'picky_nodes' into arrange_append
2 parents de2b9bd + b127837 commit cc89414

20 files changed

+941
-622
lines changed

.gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
.deps
2+
results/pg_pathman.out
3+
regression.diffs
4+
regression.out
25
*.o
36
*.so
4-
pg_pathman--*.sql
7+
pg_pathman--*.sql

Makefile

+2-2
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 runtimeappend.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

dsm_array.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ resize_dsm_array(DsmArray *arr, size_t entry_size, size_t length)
290290
}
291291

292292
void *
293-
dsm_array_get_pointer(const DsmArray* arr)
293+
dsm_array_get_pointer(const DsmArray *arr)
294294
{
295295
return (char *) dsm_segment_address(segment) + arr->offset + sizeof(BlockHeader);
296296
}

hooks.c

+333
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,333 @@
1+
/* ------------------------------------------------------------------------
2+
*
3+
* hooks.c
4+
* definitions of rel_pathlist and join_pathlist hooks
5+
*
6+
* Copyright (c) 2016, Postgres Professional
7+
*
8+
* ------------------------------------------------------------------------
9+
*/
10+
#include "postgres.h"
11+
#include "optimizer/cost.h"
12+
#include "optimizer/restrictinfo.h"
13+
#include "hooks.h"
14+
#include "utils.h"
15+
#include "pathman.h"
16+
#include "runtimeappend.h"
17+
18+
19+
set_join_pathlist_hook_type set_join_pathlist_next = NULL;
20+
set_rel_pathlist_hook_type set_rel_pathlist_hook_next = NULL;
21+
22+
23+
void
24+
pathman_join_pathlist_hook(PlannerInfo *root,
25+
RelOptInfo *joinrel,
26+
RelOptInfo *outerrel,
27+
RelOptInfo *innerrel,
28+
JoinType jointype,
29+
JoinPathExtraData *extra)
30+
{
31+
JoinCostWorkspace workspace;
32+
Path *outer,
33+
*inner;
34+
Relids inner_required;
35+
RangeTblEntry *inner_entry = root->simple_rte_array[innerrel->relid];
36+
PartRelationInfo *inner_prel;
37+
NestPath *nest_path;
38+
List *pathkeys = NIL;
39+
List *joinrestrictclauses = extra->restrictlist;
40+
List *joinclauses,
41+
*otherclauses;
42+
ListCell *lc;
43+
double paramsel;
44+
45+
if (set_join_pathlist_next)
46+
set_join_pathlist_next(root, joinrel, outerrel,
47+
innerrel, jointype, extra);
48+
49+
if (jointype == JOIN_UNIQUE_OUTER ||
50+
jointype == JOIN_UNIQUE_INNER)
51+
{
52+
jointype = JOIN_INNER;
53+
}
54+
55+
if (jointype == JOIN_FULL || !pg_pathman_enable_runtimeappend)
56+
return;
57+
58+
if (innerrel->reloptkind != RELOPT_BASEREL ||
59+
!inner_entry->inh ||
60+
!(inner_prel = get_pathman_relation_info(inner_entry->relid, NULL)))
61+
{
62+
return; /* Obviously not our case */
63+
}
64+
65+
/* Extract join clauses which will separate partitions */
66+
if (IS_OUTER_JOIN(extra->sjinfo->jointype))
67+
{
68+
extract_actual_join_clauses(joinrestrictclauses,
69+
&joinclauses, &otherclauses);
70+
}
71+
else
72+
{
73+
/* We can treat all clauses alike for an inner join */
74+
joinclauses = extract_actual_clauses(joinrestrictclauses, false);
75+
otherclauses = NIL;
76+
}
77+
78+
paramsel = 1.0;
79+
foreach (lc, joinclauses)
80+
{
81+
WrapperNode *wrap;
82+
83+
wrap = walk_expr_tree(NULL, (Expr *) lfirst(lc), inner_prel);
84+
paramsel *= wrap->paramsel;
85+
}
86+
87+
foreach (lc, innerrel->pathlist)
88+
{
89+
AppendPath *cur_inner_path = (AppendPath *) lfirst(lc);
90+
91+
if (!IsA(cur_inner_path, AppendPath))
92+
continue;
93+
94+
outer = outerrel->cheapest_total_path;
95+
96+
inner_required = bms_union(PATH_REQ_OUTER((Path *) cur_inner_path),
97+
bms_make_singleton(outerrel->relid));
98+
99+
inner = create_runtimeappend_path(root, cur_inner_path,
100+
get_appendrel_parampathinfo(innerrel,
101+
inner_required),
102+
joinclauses, paramsel);
103+
104+
initial_cost_nestloop(root, &workspace, jointype,
105+
outer, inner,
106+
extra->sjinfo, &extra->semifactors);
107+
108+
pathkeys = build_join_pathkeys(root, joinrel, jointype, outer->pathkeys);
109+
110+
nest_path = create_nestloop_path(root, joinrel, jointype, &workspace,
111+
extra->sjinfo, &extra->semifactors,
112+
outer, inner, extra->restrictlist,
113+
pathkeys,
114+
calc_nestloop_required_outer(outer, inner));
115+
116+
add_path(joinrel, (Path *) nest_path);
117+
}
118+
}
119+
120+
/*
121+
* Main hook. All the magic goes here
122+
*/
123+
void
124+
pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTblEntry *rte)
125+
{
126+
PartRelationInfo *prel = NULL;
127+
RangeTblEntry **new_rte_array;
128+
RelOptInfo **new_rel_array;
129+
bool found;
130+
int len;
131+
int first_child_relid = 0;
132+
133+
/* Invoke original hook if needed */
134+
if (set_rel_pathlist_hook_next != NULL)
135+
set_rel_pathlist_hook_next(root, rel, rti, rte);
136+
137+
if (!pg_pathman_enable)
138+
return;
139+
140+
/* This works only for SELECT queries */
141+
if (root->parse->commandType != CMD_SELECT || !inheritance_disabled)
142+
return;
143+
144+
/* Lookup partitioning information for parent relation */
145+
prel = get_pathman_relation_info(rte->relid, &found);
146+
147+
if (prel != NULL && found)
148+
{
149+
ListCell *lc;
150+
int i;
151+
Oid *dsm_arr;
152+
List *ranges,
153+
*wrappers;
154+
PathKey *pathkeyAsc = NULL,
155+
*pathkeyDesc = NULL;
156+
double paramsel = 1.0;
157+
158+
if (prel->parttype == PT_RANGE)
159+
{
160+
/*
161+
* Get pathkeys for ascending and descending sort by partition
162+
* column
163+
*/
164+
List *pathkeys;
165+
Var *var;
166+
Oid vartypeid,
167+
varcollid;
168+
int32 type_mod;
169+
TypeCacheEntry *tce;
170+
171+
/* Make Var from patition column */
172+
get_rte_attribute_type(rte, prel->attnum,
173+
&vartypeid, &type_mod, &varcollid);
174+
var = makeVar(rti, prel->attnum, vartypeid, type_mod, varcollid, 0);
175+
var->location = -1;
176+
177+
/* Determine operator type */
178+
tce = lookup_type_cache(var->vartype, TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
179+
180+
/* Make pathkeys */
181+
pathkeys = build_expression_pathkey(root, (Expr *)var, NULL,
182+
tce->lt_opr, NULL, false);
183+
if (pathkeys)
184+
pathkeyAsc = (PathKey *) linitial(pathkeys);
185+
pathkeys = build_expression_pathkey(root, (Expr *)var, NULL,
186+
tce->gt_opr, NULL, false);
187+
if (pathkeys)
188+
pathkeyDesc = (PathKey *) linitial(pathkeys);
189+
}
190+
191+
rte->inh = true;
192+
dsm_arr = (Oid *) dsm_array_get_pointer(&prel->children);
193+
ranges = list_make1_int(make_irange(0, prel->children_count - 1, false));
194+
195+
/* Make wrappers over restrictions and collect final rangeset */
196+
wrappers = NIL;
197+
foreach(lc, rel->baserestrictinfo)
198+
{
199+
WrapperNode *wrap;
200+
201+
RestrictInfo *rinfo = (RestrictInfo*) lfirst(lc);
202+
203+
wrap = walk_expr_tree(NULL, rinfo->clause, prel);
204+
paramsel *= wrap->paramsel;
205+
wrappers = lappend(wrappers, wrap);
206+
ranges = irange_list_intersect(ranges, wrap->rangeset);
207+
}
208+
209+
/*
210+
* Expand simple_rte_array and simple_rel_array
211+
*/
212+
213+
if (ranges)
214+
{
215+
len = irange_list_length(ranges);
216+
217+
/* Expand simple_rel_array and simple_rte_array */
218+
new_rel_array = (RelOptInfo **)
219+
palloc0((root->simple_rel_array_size + len) * sizeof(RelOptInfo *));
220+
221+
/* simple_rte_array is an array equivalent of the rtable list */
222+
new_rte_array = (RangeTblEntry **)
223+
palloc0((root->simple_rel_array_size + len) * sizeof(RangeTblEntry *));
224+
225+
/* Copy relations to the new arrays */
226+
for (i = 0; i < root->simple_rel_array_size; i++)
227+
{
228+
new_rel_array[i] = root->simple_rel_array[i];
229+
new_rte_array[i] = root->simple_rte_array[i];
230+
}
231+
232+
/* Free old arrays */
233+
pfree(root->simple_rel_array);
234+
pfree(root->simple_rte_array);
235+
236+
root->simple_rel_array_size += len;
237+
root->simple_rel_array = new_rel_array;
238+
root->simple_rte_array = new_rte_array;
239+
}
240+
241+
/*
242+
* Iterate all indexes in rangeset and append corresponding child
243+
* relations.
244+
*/
245+
foreach(lc, ranges)
246+
{
247+
IndexRange irange = lfirst_irange(lc);
248+
Oid childOid;
249+
250+
for (i = irange_lower(irange); i <= irange_upper(irange); i++)
251+
{
252+
int idx;
253+
254+
childOid = dsm_arr[i];
255+
idx = append_child_relation(root, rel, rti, rte, i, childOid, wrappers);
256+
257+
if (!first_child_relid)
258+
first_child_relid = idx;
259+
}
260+
}
261+
262+
/* Clear old path list */
263+
list_free(rel->pathlist);
264+
265+
rel->pathlist = NIL;
266+
set_append_rel_pathlist(root, rel, rti, rte, pathkeyAsc, pathkeyDesc);
267+
set_append_rel_size(root, rel, rti, rte);
268+
269+
if (!pg_pathman_enable_runtimeappend)
270+
return;
271+
272+
foreach (lc, rel->pathlist)
273+
{
274+
AppendPath *cur_path = (AppendPath *) lfirst(lc);
275+
Relids inner_required = PATH_REQ_OUTER((Path *) cur_path);
276+
ParamPathInfo *ppi = get_appendrel_parampathinfo(rel, inner_required);
277+
Path *inner_path;
278+
ListCell *subpath_cell;
279+
List *runtime_quals = NIL;
280+
281+
if (!IsA(cur_path, AppendPath) ||
282+
rel->has_eclass_joins ||
283+
rel->joininfo)
284+
{
285+
continue;
286+
}
287+
288+
foreach (subpath_cell, cur_path->subpaths)
289+
{
290+
Path *subpath = (Path *) lfirst(subpath_cell);
291+
RelOptInfo *child_rel = subpath->parent;
292+
List *quals;
293+
ListCell *qual_cell;
294+
ReplaceVarsContext repl_var_cxt;
295+
296+
repl_var_cxt.child = subpath->parent;
297+
repl_var_cxt.parent = rel;
298+
repl_var_cxt.sublevels_up = 0;
299+
300+
quals = extract_actual_clauses(child_rel->baserestrictinfo, false);
301+
302+
/* Do not proceed if there's a rel containing quals without params */
303+
if (!clause_contains_params((Node *) quals))
304+
{
305+
runtime_quals = NIL; /* skip this path */
306+
break;
307+
}
308+
309+
/* Replace child Vars with a parent rel's Var */
310+
quals = (List *) replace_child_vars_with_parent_var((Node *) quals,
311+
&repl_var_cxt);
312+
313+
/* Combine unique quals for RuntimeAppend */
314+
foreach (qual_cell, quals)
315+
runtime_quals = list_append_unique(runtime_quals,
316+
(Node *) lfirst(qual_cell));
317+
}
318+
319+
/*
320+
* Dismiss RuntimeAppend if there
321+
* are no parameterized quals
322+
*/
323+
if (runtime_quals == NIL)
324+
continue;
325+
326+
inner_path = create_runtimeappend_path(root, cur_path,
327+
ppi, runtime_quals,
328+
paramsel);
329+
330+
add_path(rel, inner_path);
331+
}
332+
}
333+
}

hooks.h

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* ------------------------------------------------------------------------
2+
*
3+
* hooks.h
4+
* prototypes of rel_pathlist and join_pathlist hooks
5+
*
6+
* Copyright (c) 2016, Postgres Professional
7+
*
8+
* ------------------------------------------------------------------------
9+
*/
10+
#ifndef JOIN_HOOK_H
11+
#define JOIN_HOOK_H
12+
13+
#include "postgres.h"
14+
#include "optimizer/paths.h"
15+
16+
extern set_join_pathlist_hook_type set_join_pathlist_next;
17+
extern set_rel_pathlist_hook_type set_rel_pathlist_hook_next;
18+
19+
void pathman_join_pathlist_hook(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel,
20+
RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra);
21+
22+
void pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTblEntry *rte);
23+
24+
#endif

0 commit comments

Comments
 (0)