Skip to content

Commit 27cac1d

Browse files
committed
refactoring, clean code & comments, introduce debug_compat_features.h, new subsystems: 'rowmarks_fix' & 'expand_rte_hook', changed behavior of pathman_rel_pathlist_hook()
1 parent ad49922 commit 27cac1d

19 files changed

+395
-206
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ OBJS = src/init.o src/relation_info.o src/utils.o src/partition_filter.o \
77
src/pl_funcs.o src/pl_range_funcs.o src/pl_hash_funcs.o src/pathman_workers.o \
88
src/hooks.o src/nodes_common.o src/xact_handling.o src/utility_stmt_hooking.o \
99
src/planner_tree_modification.o src/debug_print.o src/partition_creation.o \
10-
src/compat/pg_compat.o src/compat/relation_tags.o $(WIN32RES)
10+
src/compat/pg_compat.o src/compat/relation_tags.o src/compat/expand_rte_hook.o \
11+
src/compat/rowmarks_fix.o $(WIN32RES)
1112

1213
PG_CPPFLAGS = -I$(CURDIR)/src/include
1314

sql/pathman_rowmarks.sql

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
CREATE EXTENSION pg_pathman;
22
CREATE SCHEMA rowmarks;
33

4-
54
CREATE TABLE rowmarks.first(id int NOT NULL);
65
CREATE TABLE rowmarks.second(id int NOT NULL);
76

src/compat/expand_rte_hook.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/* ------------------------------------------------------------------------
2+
*
3+
* expand_rte_hook.c
4+
* Fix rowmarks etc using the 'expand_inherited_rtentry_hook'
5+
* NOTE: this hook exists in PostgresPro
6+
*
7+
* Copyright (c) 2017, Postgres Professional
8+
*
9+
* ------------------------------------------------------------------------
10+
*/
11+
12+
#include "compat/expand_rte_hook.h"
13+
#include "relation_info.h"
14+
#include "init.h"
15+
16+
#include "postgres.h"
17+
#include "optimizer/prep.h"
18+
19+
20+
#ifdef NATIVE_EXPAND_RTE_HOOK
21+
22+
static expand_inherited_rtentry_hook_type expand_inherited_rtentry_hook_next = NULL;
23+
24+
static void pathman_expand_inherited_rtentry_hook(PlannerInfo *root,
25+
RangeTblEntry *rte,
26+
Index rti);
27+
28+
29+
/* Initialize 'expand_inherited_rtentry_hook' */
30+
void
31+
init_expand_rte_hook(void)
32+
{
33+
expand_inherited_rtentry_hook_next = expand_inherited_rtentry_hook;
34+
expand_inherited_rtentry_hook = pathman_expand_inherited_rtentry_hook;
35+
}
36+
37+
38+
/* Fix parent's RowMark (makes 'rowmarks_fix' pointless) */
39+
static void
40+
pathman_expand_inherited_rtentry_hook(PlannerInfo *root,
41+
RangeTblEntry *rte,
42+
Index rti)
43+
{
44+
PlanRowMark *oldrc;
45+
46+
if (!IsPathmanReady())
47+
return;
48+
49+
/* Check that table is partitioned by pg_pathman */
50+
if (!get_pathman_relation_info(rte->relid))
51+
return;
52+
53+
/* HACK: fix rowmark for parent (for preprocess_targetlist() etc) */
54+
oldrc = get_plan_rowmark(root->rowMarks, rti);
55+
if (oldrc)
56+
oldrc->isParent = true;
57+
}
58+
59+
#endif /* NATIVE_EXPAND_RTE_HOOK */

src/compat/pg_compat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* ------------------------------------------------------------------------
22
*
33
* pg_compat.c
4-
* Compatibility tools
4+
* Compatibility tools for PostgreSQL API
55
*
66
* Copyright (c) 2016, Postgres Professional
77
*

src/compat/relation_tags.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
*
33
* relation_tags.c
44
* Attach custom (Key, Value) pairs to an arbitrary RangeTblEntry
5+
* NOTE: implementations for vanilla and PostgresPro differ
56
*
67
* Copyright (c) 2017, Postgres Professional
78
*

src/compat/rowmarks_fix.c

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/* ------------------------------------------------------------------------
2+
*
3+
* rowmarks_fix.h
4+
* Hack incorrect RowMark generation due to unset 'RTE->inh' flag
5+
* NOTE: this code is only useful for vanilla
6+
*
7+
* Copyright (c) 2017, Postgres Professional
8+
*
9+
* ------------------------------------------------------------------------
10+
*/
11+
12+
#include "compat/rowmarks_fix.h"
13+
#include "planner_tree_modification.h"
14+
15+
#include "access/sysattr.h"
16+
#include "catalog/pg_type.h"
17+
#include "nodes/relation.h"
18+
#include "nodes/nodeFuncs.h"
19+
#include "utils/builtins.h"
20+
#include "utils/rel.h"
21+
22+
23+
#ifndef NATIVE_PARTITIONING_ROWMARKS
24+
25+
/* Special column name for rowmarks */
26+
#define TABLEOID_STR(subst) ( "pathman_tableoid" subst )
27+
#define TABLEOID_STR_BASE_LEN ( sizeof(TABLEOID_STR("")) - 1 )
28+
29+
30+
static void lock_rows_visitor(Plan *plan, void *context);
31+
static List *get_tableoids_list(List *tlist);
32+
33+
34+
/* Final rowmark processing for partitioned tables */
35+
void
36+
postprocess_lock_rows(List *rtable, Plan *plan)
37+
{
38+
plan_tree_walker(plan, lock_rows_visitor, rtable);
39+
}
40+
41+
/*
42+
* Add missing 'TABLEOID_STR%u' junk attributes for inherited partitions
43+
*
44+
* This is necessary since preprocess_targetlist() heavily
45+
* depends on the 'inh' flag which we have to unset.
46+
*
47+
* postprocess_lock_rows() will later transform 'TABLEOID_STR:Oid'
48+
* relnames into 'tableoid:rowmarkId'.
49+
*/
50+
void
51+
rowmark_add_tableoids(Query *parse)
52+
{
53+
ListCell *lc;
54+
55+
/* Generate 'tableoid' for partitioned table rowmark */
56+
foreach (lc, parse->rowMarks)
57+
{
58+
RowMarkClause *rc = (RowMarkClause *) lfirst(lc);
59+
Oid parent = getrelid(rc->rti, parse->rtable);
60+
Var *var;
61+
TargetEntry *tle;
62+
char resname[64];
63+
64+
/* Check that table is partitioned */
65+
if (!get_pathman_relation_info(parent))
66+
continue;
67+
68+
var = makeVar(rc->rti,
69+
TableOidAttributeNumber,
70+
OIDOID,
71+
-1,
72+
InvalidOid,
73+
0);
74+
75+
/* Use parent's Oid as TABLEOID_STR's key (%u) */
76+
snprintf(resname, sizeof(resname), TABLEOID_STR("%u"), parent);
77+
78+
tle = makeTargetEntry((Expr *) var,
79+
list_length(parse->targetList) + 1,
80+
pstrdup(resname),
81+
true);
82+
83+
/* There's no problem here since new attribute is junk */
84+
parse->targetList = lappend(parse->targetList, tle);
85+
}
86+
}
87+
88+
/*
89+
* Extract target entries with resnames beginning with TABLEOID_STR
90+
* and var->varoattno == TableOidAttributeNumber
91+
*/
92+
static List *
93+
get_tableoids_list(List *tlist)
94+
{
95+
List *result = NIL;
96+
ListCell *lc;
97+
98+
foreach (lc, tlist)
99+
{
100+
TargetEntry *te = (TargetEntry *) lfirst(lc);
101+
Var *var = (Var *) te->expr;
102+
103+
if (!IsA(var, Var))
104+
continue;
105+
106+
/* Check that column name begins with TABLEOID_STR & it's tableoid */
107+
if (var->varoattno == TableOidAttributeNumber &&
108+
(te->resname && strlen(te->resname) > TABLEOID_STR_BASE_LEN) &&
109+
0 == strncmp(te->resname, TABLEOID_STR(""), TABLEOID_STR_BASE_LEN))
110+
{
111+
result = lappend(result, te);
112+
}
113+
}
114+
115+
return result;
116+
}
117+
118+
/*
119+
* Find 'TABLEOID_STR%u' attributes that were manually
120+
* created for partitioned tables and replace Oids
121+
* (used for '%u') with expected rc->rowmarkIds
122+
*/
123+
static void
124+
lock_rows_visitor(Plan *plan, void *context)
125+
{
126+
List *rtable = (List *) context;
127+
LockRows *lock_rows = (LockRows *) plan;
128+
Plan *lock_child = outerPlan(plan);
129+
List *tableoids;
130+
ListCell *lc;
131+
132+
if (!IsA(lock_rows, LockRows))
133+
return;
134+
135+
Assert(rtable && IsA(rtable, List) && lock_child);
136+
137+
/* Select tableoid attributes that must be renamed */
138+
tableoids = get_tableoids_list(lock_child->targetlist);
139+
if (!tableoids)
140+
return; /* this LockRows has nothing to do with partitioned table */
141+
142+
foreach (lc, lock_rows->rowMarks)
143+
{
144+
PlanRowMark *rc = (PlanRowMark *) lfirst(lc);
145+
Oid parent_oid = getrelid(rc->rti, rtable);
146+
ListCell *mark_lc;
147+
List *finished_tes = NIL; /* postprocessed target entries */
148+
149+
foreach (mark_lc, tableoids)
150+
{
151+
TargetEntry *te = (TargetEntry *) lfirst(mark_lc);
152+
const char *cur_oid_str = &(te->resname[TABLEOID_STR_BASE_LEN]);
153+
Datum cur_oid_datum;
154+
155+
cur_oid_datum = DirectFunctionCall1(oidin, CStringGetDatum(cur_oid_str));
156+
157+
if (DatumGetObjectId(cur_oid_datum) == parent_oid)
158+
{
159+
char resname[64];
160+
161+
/* Replace 'TABLEOID_STR:Oid' with 'tableoid:rowmarkId' */
162+
snprintf(resname, sizeof(resname), "tableoid%u", rc->rowmarkId);
163+
te->resname = pstrdup(resname);
164+
165+
finished_tes = lappend(finished_tes, te);
166+
}
167+
}
168+
169+
/* Remove target entries that have been processed in this step */
170+
foreach (mark_lc, finished_tes)
171+
tableoids = list_delete_ptr(tableoids, lfirst(mark_lc));
172+
173+
if (list_length(tableoids) == 0)
174+
break; /* nothing to do */
175+
}
176+
}
177+
178+
#endif /* NATIVE_PARTITIONING_ROWMARKS */

src/hooks.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include "compat/pg_compat.h"
1212
#include "compat/relation_tags.h"
13+
#include "compat/rowmarks_fix.h"
1314

1415
#include "hooks.h"
1516
#include "init.h"
@@ -207,14 +208,16 @@ pathman_rel_pathlist_hook(PlannerInfo *root,
207208
if (!IsPathmanReady())
208209
return;
209210

210-
/* This works only for SELECTs or INSERTs on simple relations */
211+
/*
212+
* Skip if it's a result relation (UPDATE | DELETE | INSERT),
213+
* or not a (partitioned) physical relation at all.
214+
*/
211215
if (rte->rtekind != RTE_RELATION ||
212216
rte->relkind != RELKIND_RELATION ||
213-
(root->parse->commandType != CMD_SELECT &&
214-
root->parse->commandType != CMD_INSERT)) /* INSERT INTO ... SELECT ... */
217+
root->parse->resultRelation == rti)
215218
return;
216219

217-
/* Skip if this table is not allowed to act as parent (see FROM ONLY) */
220+
/* Skip if this table is not allowed to act as parent (e.g. FROM ONLY) */
218221
if (PARENTHOOD_DISALLOWED == get_rel_parenthood_status(root->parse->queryId, rte))
219222
return;
220223

@@ -245,7 +248,7 @@ pathman_rel_pathlist_hook(PlannerInfo *root,
245248
int32 type_mod;
246249
TypeCacheEntry *tce;
247250

248-
/* Make Var from patition column */
251+
/* Make Var from partition column */
249252
get_rte_attribute_type(rte, prel->attnum,
250253
&vartypeid, &type_mod, &varcollid);
251254
var = makeVar(rti, prel->attnum, vartypeid, type_mod, varcollid, 0);
@@ -255,17 +258,18 @@ pathman_rel_pathlist_hook(PlannerInfo *root,
255258
tce = lookup_type_cache(var->vartype, TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
256259

257260
/* Make pathkeys */
258-
pathkeys = build_expression_pathkey(root, (Expr *)var, NULL,
261+
pathkeys = build_expression_pathkey(root, (Expr *) var, NULL,
259262
tce->lt_opr, NULL, false);
260263
if (pathkeys)
261264
pathkeyAsc = (PathKey *) linitial(pathkeys);
262-
pathkeys = build_expression_pathkey(root, (Expr *)var, NULL,
265+
pathkeys = build_expression_pathkey(root, (Expr *) var, NULL,
263266
tce->gt_opr, NULL, false);
264267
if (pathkeys)
265268
pathkeyDesc = (PathKey *) linitial(pathkeys);
266269
}
267270

268-
rte->inh = true; /* we must restore 'inh' flag! */
271+
/* HACK: we must restore 'inh' flag! */
272+
rte->inh = true;
269273

270274
children = PrelGetChildrenArray(prel);
271275
ranges = list_make1_irange(make_irange(0, PrelLastChild(prel), IR_COMPLETE));
@@ -475,7 +479,7 @@ pathman_planner_hook(Query *parse, int cursorOptions, ParamListInfo boundParams)
475479
{
476480
if (pathman_ready)
477481
{
478-
/* Increment parenthood_statuses refcount */
482+
/* Increment relation tags refcount */
479483
incr_refcount_relation_tags();
480484

481485
/* Modify query tree if needed */
@@ -496,7 +500,7 @@ pathman_planner_hook(Query *parse, int cursorOptions, ParamListInfo boundParams)
496500
/* Add PartitionFilter node for INSERT queries */
497501
ExecuteForPlanTree(result, add_partition_filters);
498502

499-
/* Decrement parenthood_statuses refcount */
503+
/* Decrement relation tags refcount */
500504
decr_refcount_relation_tags();
501505

502506
/* HACK: restore queryId set by pg_stat_statements */
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/* ------------------------------------------------------------------------
2+
*
3+
* debug_custom_features.h
4+
* Macros to control PgPro-related features etc
5+
*
6+
* Copyright (c) 2017, Postgres Professional
7+
*
8+
* ------------------------------------------------------------------------
9+
*/
10+
11+
/* Main toggle */
12+
#define ENABLE_PGPRO_PATCHES
13+
14+
/* PgPro exclusive features */
15+
#define ENABLE_EXPAND_RTE_HOOK
16+
#define ENABLE_RELATION_TAGS
17+
#define ENABLE_PATHMAN_AWARE_COPY_WIN32
18+
19+
/* Hacks for vanilla */
20+
#define ENABLE_ROWMARKS_FIX

0 commit comments

Comments
 (0)