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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy