Skip to content

Commit 1d8eeb5

Browse files
committed
resolve conflicts caused by a merge of 'rework_query_walkers', add new regression test pathman_rowmarks
2 parents a98a052 + 66c10c8 commit 1d8eeb5

File tree

4 files changed

+295
-51
lines changed

4 files changed

+295
-51
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ REGRESS = pathman_basic \
1616
pathman_runtime_nodes \
1717
pathman_callbacks \
1818
pathman_domains \
19-
pathman_foreign_keys
19+
pathman_foreign_keys \
20+
pathman_rowmarks
2021
EXTRA_REGRESS_OPTS=--temp-config=$(top_srcdir)/$(subdir)/conf.add
2122
EXTRA_CLEAN = $(EXTENSION)--$(EXTVERSION).sql ./isolation_output
2223

expected/pathman_rowmarks.out

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
CREATE EXTENSION pg_pathman;
2+
CREATE SCHEMA rowmarks;
3+
CREATE TABLE rowmarks.first(id int NOT NULL);
4+
CREATE TABLE rowmarks.second(id int NOT NULL);
5+
INSERT INTO rowmarks.first SELECT generate_series(1, 10);
6+
INSERT INTO rowmarks.second SELECT generate_series(1, 10);
7+
SELECT create_hash_partitions('rowmarks.first', 'id', 5);
8+
create_hash_partitions
9+
------------------------
10+
5
11+
(1 row)
12+
13+
/* Not partitioned */
14+
SELECT * FROM rowmarks.second ORDER BY id FOR UPDATE;
15+
id
16+
----
17+
1
18+
2
19+
3
20+
4
21+
5
22+
6
23+
7
24+
8
25+
9
26+
10
27+
(10 rows)
28+
29+
/* Simple case (plan) */
30+
EXPLAIN (COSTS OFF)
31+
SELECT * FROM rowmarks.first ORDER BY id FOR UPDATE;
32+
QUERY PLAN
33+
---------------------------------------
34+
LockRows
35+
-> Sort
36+
Sort Key: first_0.id
37+
-> Append
38+
-> Seq Scan on first_0
39+
-> Seq Scan on first_1
40+
-> Seq Scan on first_2
41+
-> Seq Scan on first_3
42+
-> Seq Scan on first_4
43+
(9 rows)
44+
45+
/* Simple case (execution) */
46+
SELECT * FROM rowmarks.first ORDER BY id FOR UPDATE;
47+
id
48+
----
49+
1
50+
2
51+
3
52+
4
53+
5
54+
6
55+
7
56+
8
57+
9
58+
10
59+
(10 rows)
60+
61+
SELECT FROM rowmarks.first ORDER BY id FOR UPDATE;
62+
--
63+
(10 rows)
64+
65+
SELECT tableoid > 0 FROM rowmarks.first ORDER BY id FOR UPDATE;
66+
?column?
67+
----------
68+
t
69+
t
70+
t
71+
t
72+
t
73+
t
74+
t
75+
t
76+
t
77+
t
78+
(10 rows)
79+
80+
/* A little harder (plan) */
81+
EXPLAIN (COSTS OFF)
82+
SELECT * FROM rowmarks.first
83+
WHERE id = (SELECT id FROM rowmarks.first
84+
ORDER BY id
85+
OFFSET 10 LIMIT 1
86+
FOR UPDATE)
87+
FOR SHARE;
88+
QUERY PLAN
89+
-----------------------------------------------------
90+
LockRows
91+
InitPlan 1 (returns $1)
92+
-> Limit
93+
-> LockRows
94+
-> Sort
95+
Sort Key: first_0.id
96+
-> Append
97+
-> Seq Scan on first_0
98+
-> Seq Scan on first_1
99+
-> Seq Scan on first_2
100+
-> Seq Scan on first_3
101+
-> Seq Scan on first_4
102+
-> Custom Scan (RuntimeAppend)
103+
-> Seq Scan on first_0 first
104+
Filter: (id = $1)
105+
-> Seq Scan on first_1 first
106+
Filter: (id = $1)
107+
-> Seq Scan on first_2 first
108+
Filter: (id = $1)
109+
-> Seq Scan on first_3 first
110+
Filter: (id = $1)
111+
-> Seq Scan on first_4 first
112+
Filter: (id = $1)
113+
(23 rows)
114+
115+
/* A little harder (execution) */
116+
SELECT * FROM rowmarks.first
117+
WHERE id = (SELECT id FROM rowmarks.first
118+
ORDER BY id
119+
OFFSET 5 LIMIT 1
120+
FOR UPDATE)
121+
FOR SHARE;
122+
id
123+
----
124+
6
125+
(1 row)
126+
127+
/* Two tables (plan) */
128+
EXPLAIN (COSTS OFF)
129+
SELECT * FROM rowmarks.first
130+
WHERE id = (SELECT id FROM rowmarks.second
131+
ORDER BY id
132+
OFFSET 5 LIMIT 1
133+
FOR UPDATE)
134+
FOR SHARE;
135+
QUERY PLAN
136+
----------------------------------------------
137+
LockRows
138+
InitPlan 1 (returns $1)
139+
-> Limit
140+
-> LockRows
141+
-> Sort
142+
Sort Key: second.id
143+
-> Seq Scan on second
144+
-> Custom Scan (RuntimeAppend)
145+
-> Seq Scan on first_0 first
146+
Filter: (id = $1)
147+
-> Seq Scan on first_1 first
148+
Filter: (id = $1)
149+
-> Seq Scan on first_2 first
150+
Filter: (id = $1)
151+
-> Seq Scan on first_3 first
152+
Filter: (id = $1)
153+
-> Seq Scan on first_4 first
154+
Filter: (id = $1)
155+
(18 rows)
156+
157+
/* Two tables (execution) */
158+
SELECT * FROM rowmarks.first
159+
WHERE id = (SELECT id FROM rowmarks.second
160+
ORDER BY id
161+
OFFSET 5 LIMIT 1
162+
FOR UPDATE)
163+
FOR SHARE;
164+
id
165+
----
166+
6
167+
(1 row)
168+
169+
DROP SCHEMA rowmarks CASCADE;
170+
NOTICE: drop cascades to 7 other objects
171+
DETAIL: drop cascades to table rowmarks.first
172+
drop cascades to table rowmarks.second
173+
drop cascades to table rowmarks.first_0
174+
drop cascades to table rowmarks.first_1
175+
drop cascades to table rowmarks.first_2
176+
drop cascades to table rowmarks.first_3
177+
drop cascades to table rowmarks.first_4
178+
DROP EXTENSION pg_pathman;

sql/pathman_rowmarks.sql

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
CREATE EXTENSION pg_pathman;
2+
CREATE SCHEMA rowmarks;
3+
4+
5+
CREATE TABLE rowmarks.first(id int NOT NULL);
6+
CREATE TABLE rowmarks.second(id int NOT NULL);
7+
8+
INSERT INTO rowmarks.first SELECT generate_series(1, 10);
9+
INSERT INTO rowmarks.second SELECT generate_series(1, 10);
10+
11+
12+
SELECT create_hash_partitions('rowmarks.first', 'id', 5);
13+
14+
/* Not partitioned */
15+
SELECT * FROM rowmarks.second ORDER BY id FOR UPDATE;
16+
17+
/* Simple case (plan) */
18+
EXPLAIN (COSTS OFF)
19+
SELECT * FROM rowmarks.first ORDER BY id FOR UPDATE;
20+
21+
/* Simple case (execution) */
22+
SELECT * FROM rowmarks.first ORDER BY id FOR UPDATE;
23+
SELECT FROM rowmarks.first ORDER BY id FOR UPDATE;
24+
SELECT tableoid > 0 FROM rowmarks.first ORDER BY id FOR UPDATE;
25+
26+
/* A little harder (plan) */
27+
EXPLAIN (COSTS OFF)
28+
SELECT * FROM rowmarks.first
29+
WHERE id = (SELECT id FROM rowmarks.first
30+
ORDER BY id
31+
OFFSET 10 LIMIT 1
32+
FOR UPDATE)
33+
FOR SHARE;
34+
35+
/* A little harder (execution) */
36+
SELECT * FROM rowmarks.first
37+
WHERE id = (SELECT id FROM rowmarks.first
38+
ORDER BY id
39+
OFFSET 5 LIMIT 1
40+
FOR UPDATE)
41+
FOR SHARE;
42+
43+
/* Two tables (plan) */
44+
EXPLAIN (COSTS OFF)
45+
SELECT * FROM rowmarks.first
46+
WHERE id = (SELECT id FROM rowmarks.second
47+
ORDER BY id
48+
OFFSET 5 LIMIT 1
49+
FOR UPDATE)
50+
FOR SHARE;
51+
52+
/* Two tables (execution) */
53+
SELECT * FROM rowmarks.first
54+
WHERE id = (SELECT id FROM rowmarks.second
55+
ORDER BY id
56+
OFFSET 5 LIMIT 1
57+
FOR UPDATE)
58+
FOR SHARE;
59+
60+
61+
DROP SCHEMA rowmarks CASCADE;
62+
DROP EXTENSION pg_pathman;

src/utils.c

Lines changed: 53 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ static void change_varnos_in_restrinct_info(RestrictInfo *rinfo,
4040
static bool change_varno_walker(Node *node, change_varno_context *context);
4141
static List *get_tableoids_list(List *tlist);
4242
static void lock_rows_visitor(Plan *plan, void *context);
43+
static bool rowmark_add_tableoids_walker(Node *node, void *context);
4344

4445

4546
/*
@@ -451,6 +452,57 @@ plan_tree_walker(Plan *plan,
451452
visitor(plan, context);
452453
}
453454

455+
static bool
456+
rowmark_add_tableoids_walker(Node *node, void *context)
457+
{
458+
if (node == NULL)
459+
return false;
460+
461+
if (IsA(node, Query))
462+
{
463+
Query *parse = (Query *) node;
464+
ListCell *lc;
465+
466+
/* Generate 'tableoid' for partitioned table rowmark */
467+
foreach (lc, parse->rowMarks)
468+
{
469+
RowMarkClause *rc = (RowMarkClause *) lfirst(lc);
470+
Oid parent = getrelid(rc->rti, parse->rtable);
471+
Var *var;
472+
TargetEntry *tle;
473+
char resname[64];
474+
475+
/* Check that table is partitioned */
476+
if (!get_pathman_relation_info(parent))
477+
continue;
478+
479+
var = makeVar(rc->rti,
480+
TableOidAttributeNumber,
481+
OIDOID,
482+
-1,
483+
InvalidOid,
484+
0);
485+
486+
/* Use parent's Oid as TABLEOID_STR's key (%u) */
487+
snprintf(resname, sizeof(resname), TABLEOID_STR("%u"), parent);
488+
489+
tle = makeTargetEntry((Expr *) var,
490+
list_length(parse->targetList) + 1,
491+
pstrdup(resname),
492+
true);
493+
494+
/* There's no problem here since new attribute is junk */
495+
parse->targetList = lappend(parse->targetList, tle);
496+
}
497+
498+
return query_tree_walker((Query *) node,
499+
rowmark_add_tableoids_walker,
500+
NULL, 0);
501+
}
502+
503+
return expression_tree_walker(node, rowmark_add_tableoids_walker, NULL);
504+
}
505+
454506
/*
455507
* Add missing 'TABLEOID_STR%u' junk attributes for inherited partitions
456508
*
@@ -463,56 +515,7 @@ plan_tree_walker(Plan *plan,
463515
void
464516
rowmark_add_tableoids(Query *parse)
465517
{
466-
ListCell *lc;
467-
468-
check_stack_depth();
469-
470-
foreach(lc, parse->rtable)
471-
{
472-
RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
473-
474-
switch(rte->rtekind)
475-
{
476-
case RTE_SUBQUERY:
477-
rowmark_add_tableoids(rte->subquery);
478-
break;
479-
480-
default:
481-
break;
482-
}
483-
}
484-
485-
/* Generate 'tableoid' for partitioned table rowmark */
486-
foreach (lc, parse->rowMarks)
487-
{
488-
RowMarkClause *rc = (RowMarkClause *) lfirst(lc);
489-
Oid parent = getrelid(rc->rti, parse->rtable);
490-
Var *var;
491-
TargetEntry *tle;
492-
char resname[64];
493-
494-
/* Check that table is partitioned */
495-
if (!get_pathman_relation_info(parent))
496-
continue;
497-
498-
var = makeVar(rc->rti,
499-
TableOidAttributeNumber,
500-
OIDOID,
501-
-1,
502-
InvalidOid,
503-
0);
504-
505-
/* Use parent's Oid as TABLEOID_STR's key (%u) */
506-
snprintf(resname, sizeof(resname), TABLEOID_STR("%u"), parent);
507-
508-
tle = makeTargetEntry((Expr *) var,
509-
list_length(parse->targetList) + 1,
510-
pstrdup(resname),
511-
true);
512-
513-
/* There's no problem here since new attribute is junk */
514-
parse->targetList = lappend(parse->targetList, tle);
515-
}
518+
rowmark_add_tableoids_walker((Node *) parse, NULL);
516519
}
517520

518521
/*

0 commit comments

Comments
 (0)