Skip to content

Commit 5609d03

Browse files
committed
refactoring, move join_pathlist_hook to join_hook.c, add nodes_common
1 parent c713fb8 commit 5609d03

File tree

8 files changed

+237
-197
lines changed

8 files changed

+237
-197
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +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 rangeset.o pl_funcs.o worker.o $(WIN32RES)
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)
56

67
EXTENSION = pg_pathman
78
EXTVERSION = 0.1

join_hook.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#include "postgres.h"
2+
#include "optimizer/cost.h"
3+
#include "optimizer/restrictinfo.h"
4+
#include "join_hook.h"
5+
#include "pickyappend.h"
6+
7+
8+
set_join_pathlist_hook_type set_join_pathlist_next = NULL;
9+
10+
void
11+
pathman_join_pathlist_hook(PlannerInfo *root,
12+
RelOptInfo *joinrel,
13+
RelOptInfo *outerrel,
14+
RelOptInfo *innerrel,
15+
JoinType jointype,
16+
JoinPathExtraData *extra)
17+
{
18+
JoinCostWorkspace workspace;
19+
Path *outer,
20+
*inner;
21+
Relids inner_required;
22+
RangeTblEntry *inner_entry = root->simple_rte_array[innerrel->relid];
23+
PartRelationInfo *inner_prel;
24+
NestPath *nest_path;
25+
List *pathkeys = NIL;
26+
List *joinrestrictclauses = extra->restrictlist;
27+
List *joinclauses,
28+
*otherclauses;
29+
ListCell *lc;
30+
31+
if (set_join_pathlist_next)
32+
set_join_pathlist_next(root, joinrel, outerrel,
33+
innerrel, jointype, extra);
34+
35+
if (jointype == JOIN_FULL || !pg_pathman_enable_pickyappend)
36+
return;
37+
38+
if (innerrel->reloptkind != RELOPT_BASEREL ||
39+
!inner_entry->inh ||
40+
!(inner_prel = get_pathman_relation_info(inner_entry->relid, NULL)))
41+
{
42+
return; /* Obviously not our case */
43+
}
44+
45+
/* Extract join clauses which will separate partitions */
46+
if (IS_OUTER_JOIN(extra->sjinfo->jointype))
47+
{
48+
extract_actual_join_clauses(joinrestrictclauses,
49+
&joinclauses, &otherclauses);
50+
}
51+
else
52+
{
53+
/* We can treat all clauses alike for an inner join */
54+
joinclauses = extract_actual_clauses(joinrestrictclauses, false);
55+
otherclauses = NIL;
56+
}
57+
58+
foreach (lc, innerrel->pathlist)
59+
{
60+
AppendPath *cur_inner_path = (AppendPath *) lfirst(lc);
61+
62+
if (!IsA(cur_inner_path, AppendPath))
63+
continue;
64+
65+
outer = outerrel->cheapest_total_path;
66+
67+
inner_required = bms_union(PATH_REQ_OUTER((Path *) cur_inner_path),
68+
bms_make_singleton(outerrel->relid));
69+
70+
inner = create_pickyappend_path(root, cur_inner_path,
71+
get_appendrel_parampathinfo(innerrel,
72+
inner_required),
73+
joinclauses);
74+
75+
initial_cost_nestloop(root, &workspace, jointype,
76+
outer, inner,
77+
extra->sjinfo, &extra->semifactors);
78+
79+
pathkeys = build_join_pathkeys(root, joinrel, jointype, outer->pathkeys);
80+
81+
nest_path = create_nestloop_path(root, joinrel, jointype, &workspace,
82+
extra->sjinfo, &extra->semifactors,
83+
outer, inner, extra->restrictlist,
84+
pathkeys,
85+
calc_nestloop_required_outer(outer, inner));
86+
87+
add_path(joinrel, (Path *) nest_path);
88+
}
89+
}

join_hook.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef JOIN_HOOK_H
2+
#define JOIN_HOOK_H
3+
4+
#include "postgres.h"
5+
#include "optimizer/paths.h"
6+
7+
extern set_join_pathlist_hook_type set_join_pathlist_next;
8+
9+
void pathman_join_pathlist_hook(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel,
10+
RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra);
11+
12+
#endif

nodes_common.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include "postgres.h"
2+
#include "optimizer/paths.h"
3+
#include "nodes_common.h"
4+
5+
6+
/* Compare plans by 'original_order' */
7+
static int
8+
cmp_child_scan_common_by_orig_order(const void *ap,
9+
const void *bp)
10+
{
11+
ChildScanCommon a = *(ChildScanCommon *) ap;
12+
ChildScanCommon b = *(ChildScanCommon *) bp;
13+
14+
if (a->original_order > b->original_order)
15+
return 1;
16+
else if (a->original_order < b->original_order)
17+
return -1;
18+
else
19+
return 0;
20+
}
21+
22+
void
23+
explain_common(CustomScanState *node, HTAB* children_table, ExplainState *es)
24+
{
25+
/* Construct excess PlanStates */
26+
if (!es->analyze)
27+
{
28+
int allocated = 10;
29+
int used = 0;
30+
ChildScanCommon *custom_ps = palloc(allocated * sizeof(ChildScanCommon));
31+
ChildScanCommon child;
32+
HASH_SEQ_STATUS seqstat;
33+
int i;
34+
35+
/* There can't be any nodes since we're not scanning anything */
36+
Assert(!node->custom_ps);
37+
38+
hash_seq_init(&seqstat, children_table);
39+
40+
while ((child = (ChildScanCommon) hash_seq_search(&seqstat)))
41+
{
42+
if (allocated <= used)
43+
{
44+
allocated *= 2;
45+
custom_ps = repalloc(custom_ps, allocated * sizeof(ChildScanCommon));
46+
}
47+
48+
custom_ps[used++] = child;
49+
}
50+
51+
/*
52+
* We have to restore the original plan order
53+
* which has been lost within the hash table
54+
*/
55+
qsort(custom_ps, used, sizeof(ChildScanCommon),
56+
cmp_child_scan_common_by_orig_order);
57+
58+
/*
59+
* These PlanStates will be used by EXPLAIN,
60+
* arrangeappend_end will destroy them eventually
61+
*/
62+
for (i = 0; i < used; i++)
63+
node->custom_ps = lappend(node->custom_ps,
64+
ExecInitNode(custom_ps[i]->content.plan,
65+
node->ss.ps.state,
66+
0));
67+
}
68+
}

nodes_common.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#ifndef NODES_COMMON_H
2+
#define NODES_COMMON_H
3+
4+
#include "commands/explain.h"
5+
#include "pathman.h"
6+
7+
8+
/*
9+
* Element of the plan_state_table
10+
*/
11+
typedef struct
12+
{
13+
Oid relid; /* partition relid (key) */
14+
PlanState *ps; /* reusable plan state */
15+
} PreservedPlanState;
16+
17+
typedef struct
18+
{
19+
Oid relid; /* partition relid */
20+
21+
union
22+
{
23+
Path *path;
24+
Plan *plan;
25+
PlanState *plan_state;
26+
} content;
27+
28+
int original_order; /* for sorting in EXPLAIN */
29+
} ChildScanCommonData;
30+
31+
typedef ChildScanCommonData *ChildScanCommon;
32+
33+
/*
34+
* Destroy exhausted plan states
35+
*/
36+
inline static void
37+
clear_plan_states(CustomScanState *scan_state)
38+
{
39+
ListCell *state_cell;
40+
41+
foreach (state_cell, scan_state->custom_ps)
42+
{
43+
ExecEndNode((PlanState *) lfirst(state_cell));
44+
}
45+
}
46+
47+
void
48+
explain_common(CustomScanState *node, HTAB *children_table, ExplainState *es);
49+
50+
#endif

pg_pathman.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "catalog/pg_operator.h"
4242
#include "catalog/pg_type.h"
4343
#include "foreign/fdwapi.h"
44+
#include "join_hook.h"
4445
#include "pickyappend.h"
4546

4647
PG_MODULE_MAGIC;

0 commit comments

Comments
 (0)