Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbe634f0

Browse files
committed
improved support for rowmarks (select for share; update; delete; etc)
1 parent62e4952 commitbe634f0

File tree

7 files changed

+234
-185
lines changed

7 files changed

+234
-185
lines changed

‎expected/pathman_rowmarks.out

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,148 @@ FOR SHARE;
168168
6
169169
(1 row)
170170

171+
/* Check updates (plan) */
172+
EXPLAIN (COSTS OFF)
173+
UPDATE rowmarks.second SET id = 2
174+
WHERE rowmarks.second.id IN (SELECT id FROM rowmarks.first WHERE id = 1);
175+
QUERY PLAN
176+
---------------------------------------------
177+
Update on second
178+
-> Nested Loop Semi Join
179+
-> Seq Scan on second
180+
Filter: (id = 1)
181+
-> Materialize
182+
-> Append
183+
-> Seq Scan on first_0
184+
Filter: (id = 1)
185+
(8 rows)
186+
187+
EXPLAIN (COSTS OFF)
188+
UPDATE rowmarks.second SET id = 2
189+
WHERE rowmarks.second.id IN (SELECT id FROM rowmarks.first WHERE id < 1);
190+
QUERY PLAN
191+
---------------------------------------------------
192+
Update on second
193+
-> Hash Join
194+
Hash Cond: (second.id = first_0.id)
195+
-> Seq Scan on second
196+
-> Hash
197+
-> HashAggregate
198+
Group Key: first_0.id
199+
-> Append
200+
-> Seq Scan on first_0
201+
Filter: (id < 1)
202+
-> Seq Scan on first_1
203+
Filter: (id < 1)
204+
-> Seq Scan on first_2
205+
Filter: (id < 1)
206+
-> Seq Scan on first_3
207+
Filter: (id < 1)
208+
-> Seq Scan on first_4
209+
Filter: (id < 1)
210+
(18 rows)
211+
212+
EXPLAIN (COSTS OFF)
213+
UPDATE rowmarks.second SET id = 2
214+
WHERE rowmarks.second.id IN (SELECT id FROM rowmarks.first WHERE id = 1 OR id = 2);
215+
QUERY PLAN
216+
---------------------------------------------
217+
Update on second
218+
-> Hash Semi Join
219+
Hash Cond: (second.id = first_0.id)
220+
-> Seq Scan on second
221+
-> Hash
222+
-> Append
223+
-> Seq Scan on first_0
224+
Filter: (id = 1)
225+
-> Seq Scan on first_1
226+
Filter: (id = 2)
227+
(10 rows)
228+
229+
EXPLAIN (COSTS OFF)
230+
UPDATE rowmarks.second SET id = 2
231+
WHERE rowmarks.second.id IN (SELECT id FROM rowmarks.first WHERE id = 1)
232+
RETURNING *, tableoid::regclass;
233+
QUERY PLAN
234+
---------------------------------------------
235+
Update on second
236+
-> Nested Loop Semi Join
237+
-> Seq Scan on second
238+
Filter: (id = 1)
239+
-> Materialize
240+
-> Append
241+
-> Seq Scan on first_0
242+
Filter: (id = 1)
243+
(8 rows)
244+
245+
/* Check updates (execution) */
246+
UPDATE rowmarks.second SET id = 1
247+
WHERE rowmarks.second.id IN (SELECT id FROM rowmarks.first WHERE id = 1 OR id = 2)
248+
RETURNING *, tableoid::regclass;
249+
id | tableoid
250+
----+-----------------
251+
1 | rowmarks.second
252+
1 | rowmarks.second
253+
(2 rows)
254+
255+
/* Check deletes (plan) */
256+
EXPLAIN (COSTS OFF)
257+
DELETE FROM rowmarks.second
258+
WHERE rowmarks.second.id IN (SELECT id FROM rowmarks.first WHERE id = 1);
259+
QUERY PLAN
260+
---------------------------------------------
261+
Delete on second
262+
-> Nested Loop Semi Join
263+
-> Seq Scan on second
264+
Filter: (id = 1)
265+
-> Materialize
266+
-> Append
267+
-> Seq Scan on first_0
268+
Filter: (id = 1)
269+
(8 rows)
270+
271+
EXPLAIN (COSTS OFF)
272+
DELETE FROM rowmarks.second
273+
WHERE rowmarks.second.id IN (SELECT id FROM rowmarks.first WHERE id < 1);
274+
QUERY PLAN
275+
---------------------------------------------------
276+
Delete on second
277+
-> Hash Join
278+
Hash Cond: (second.id = first_0.id)
279+
-> Seq Scan on second
280+
-> Hash
281+
-> HashAggregate
282+
Group Key: first_0.id
283+
-> Append
284+
-> Seq Scan on first_0
285+
Filter: (id < 1)
286+
-> Seq Scan on first_1
287+
Filter: (id < 1)
288+
-> Seq Scan on first_2
289+
Filter: (id < 1)
290+
-> Seq Scan on first_3
291+
Filter: (id < 1)
292+
-> Seq Scan on first_4
293+
Filter: (id < 1)
294+
(18 rows)
295+
296+
EXPLAIN (COSTS OFF)
297+
DELETE FROM rowmarks.second
298+
WHERE rowmarks.second.id IN (SELECT id FROM rowmarks.first WHERE id = 1 OR id = 2);
299+
QUERY PLAN
300+
---------------------------------------------
301+
Delete on second
302+
-> Hash Semi Join
303+
Hash Cond: (second.id = first_0.id)
304+
-> Seq Scan on second
305+
-> Hash
306+
-> Append
307+
-> Seq Scan on first_0
308+
Filter: (id = 1)
309+
-> Seq Scan on first_1
310+
Filter: (id = 2)
311+
(10 rows)
312+
171313
DROP SCHEMA rowmarks CASCADE;
172314
NOTICE: drop cascades to 7 other objects
173315
DETAIL: drop cascades to table rowmarks.first

‎sql/pathman_rowmarks.sql

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
CREATE EXTENSION pg_pathman;
22
CREATESCHEMArowmarks;
33

4+
5+
46
CREATETABLErowmarks.first(idintNOT NULL);
57
CREATETABLErowmarks.second(idintNOT NULL);
68

@@ -56,6 +58,38 @@ WHERE id = (SELECT id FROM rowmarks.second
5658
FORUPDATE)
5759
FOR SHARE;
5860

61+
/* Check updates (plan)*/
62+
EXPLAIN (COSTS OFF)
63+
UPDATErowmarks.secondSET id=2
64+
WHERErowmarks.second.idIN (SELECT idFROMrowmarks.firstWHERE id=1);
65+
EXPLAIN (COSTS OFF)
66+
UPDATErowmarks.secondSET id=2
67+
WHERErowmarks.second.idIN (SELECT idFROMrowmarks.firstWHERE id<1);
68+
EXPLAIN (COSTS OFF)
69+
UPDATErowmarks.secondSET id=2
70+
WHERErowmarks.second.idIN (SELECT idFROMrowmarks.firstWHERE id=1OR id=2);
71+
EXPLAIN (COSTS OFF)
72+
UPDATErowmarks.secondSET id=2
73+
WHERErowmarks.second.idIN (SELECT idFROMrowmarks.firstWHERE id=1)
74+
RETURNING*, tableoid::regclass;
75+
76+
/* Check updates (execution)*/
77+
UPDATErowmarks.secondSET id=1
78+
WHERErowmarks.second.idIN (SELECT idFROMrowmarks.firstWHERE id=1OR id=2)
79+
RETURNING*, tableoid::regclass;
80+
81+
/* Check deletes (plan)*/
82+
EXPLAIN (COSTS OFF)
83+
DELETEFROMrowmarks.second
84+
WHERErowmarks.second.idIN (SELECT idFROMrowmarks.firstWHERE id=1);
85+
EXPLAIN (COSTS OFF)
86+
DELETEFROMrowmarks.second
87+
WHERErowmarks.second.idIN (SELECT idFROMrowmarks.firstWHERE id<1);
88+
EXPLAIN (COSTS OFF)
89+
DELETEFROMrowmarks.second
90+
WHERErowmarks.second.idIN (SELECT idFROMrowmarks.firstWHERE id=1OR id=2);
91+
92+
5993

6094
DROPSCHEMA rowmarks CASCADE;
6195
DROP EXTENSION pg_pathman;

‎src/compat/rowmarks_fix.c

Lines changed: 18 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -14,165 +14,39 @@
1414

1515
#include"access/sysattr.h"
1616
#include"catalog/pg_type.h"
17-
#include"nodes/relation.h"
1817
#include"nodes/nodeFuncs.h"
18+
#include"optimizer/planmain.h"
1919
#include"utils/builtins.h"
2020
#include"utils/rel.h"
2121

2222

2323
#ifndefNATIVE_PARTITIONING_ROWMARKS
2424

25-
/* Special column name for rowmarks */
26-
#defineTABLEOID_STR(subst)( "pathman_tableoid" subst )
27-
#defineTABLEOID_STR_BASE_LEN( sizeof(TABLEOID_STR("")) - 1 )
2825

29-
30-
staticvoidlock_rows_visitor(Plan*plan,void*context);
31-
staticList*get_tableoids_list(List*tlist);
32-
33-
34-
/* Final rowmark processing for partitioned tables */
3526
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-
Oidparent=getrelid(rc->rti,parse->rtable);
60-
Var*var;
61-
TargetEntry*tle;
62-
charresname[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-
staticList*
93-
get_tableoids_list(List*tlist)
27+
append_tle_for_rowmark(PlannerInfo*root,PlanRowMark*rc)
9428
{
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-
returnresult;
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-
staticvoid
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-
Oidparent_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-
constchar*cur_oid_str=&(te->resname[TABLEOID_STR_BASE_LEN]);
153-
Datumcur_oid_datum;
154-
155-
cur_oid_datum=DirectFunctionCall1(oidin,CStringGetDatum(cur_oid_str));
29+
Var*var;
30+
charresname[32];
31+
TargetEntry*tle;
15632

157-
if (DatumGetObjectId(cur_oid_datum)==parent_oid)
158-
{
159-
charresname[64];
33+
var=makeVar(rc->rti,
34+
TableOidAttributeNumber,
35+
OIDOID,
36+
-1,
37+
InvalidOid,
38+
0);
16039

161-
/* Replace 'TABLEOID_STR:Oid' with 'tableoid:rowmarkId' */
162-
snprintf(resname,sizeof(resname),"tableoid%u",rc->rowmarkId);
163-
te->resname=pstrdup(resname);
40+
snprintf(resname,sizeof(resname),"tableoid%u",rc->rowmarkId);
16441

165-
finished_tes=lappend(finished_tes,te);
166-
}
167-
}
42+
tle=makeTargetEntry((Expr*)var,
43+
list_length(root->processed_tlist)+1,
44+
pstrdup(resname),
45+
true);
16846

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));
47+
root->processed_tlist=lappend(root->processed_tlist,tle);
17248

173-
if (list_length(tableoids)==0)
174-
break;/* nothing to do */
175-
}
49+
add_vars_to_targetlist(root,list_make1(var),bms_make_singleton(0), true);
17650
}
17751

17852
#endif/* NATIVE_PARTITIONING_ROWMARKS */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp