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

Commitc08c648

Browse files
committed
introduce subsystem compat/relation_tags
1 parent0a0d2cf commitc08c648

File tree

6 files changed

+328
-120
lines changed

6 files changed

+328
-120
lines changed

‎Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ 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$(WIN32RES)
10+
src/compat/pg_compat.osrc/compat/relation_tags.o$(WIN32RES)
1111

1212
PG_CPPFLAGS = -I$(CURDIR)/src/include
1313

‎src/compat/relation_tags.c

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
/* ------------------------------------------------------------------------
2+
*
3+
* relation_tags.c
4+
*Attach custom (Key, Value) pairs to an arbitrary RangeTblEntry
5+
*
6+
* Copyright (c) 2017, Postgres Professional
7+
*
8+
* ------------------------------------------------------------------------
9+
*/
10+
11+
#include"compat/relation_tags.h"
12+
#include"planner_tree_modification.h"
13+
14+
#include"nodes/nodes.h"
15+
16+
17+
/*
18+
* This table is used to ensure that partitioned relation
19+
* cant't be used with both and without ONLY modifiers.
20+
*/
21+
staticHTAB*per_table_relation_tags=NULL;
22+
staticintper_table_relation_tags_refcount=0;
23+
24+
25+
/* private struct stored by parenthood lists */
26+
typedefstruct
27+
{
28+
Oidrelid;/* key (part #1) */
29+
uint32queryId;/* key (part #2) */
30+
List*relation_tags;
31+
}relation_tags_entry;
32+
33+
34+
/* Look through RTE's relation tags */
35+
List*
36+
rte_fetch_tag(constuint32query_id,
37+
constRangeTblEntry*rte,
38+
constchar*key)
39+
{
40+
relation_tags_entry*htab_entry,
41+
htab_key= {rte->relid,query_id,NIL/* unused */ };
42+
43+
AssertArg(rte);
44+
AssertArg(key);
45+
46+
/* Skip if table is not initialized */
47+
if (per_table_relation_tags)
48+
{
49+
/* Search by 'htab_key' */
50+
htab_entry=hash_search(per_table_relation_tags,
51+
&htab_key,HASH_FIND,NULL);
52+
53+
if (htab_entry)
54+
returnrelation_tags_search(htab_entry->relation_tags,key);
55+
}
56+
57+
/* Not found, return stub value */
58+
returnNIL;
59+
}
60+
61+
/* Attach new relation tag to RTE. Returns KVP with duplicate key. */
62+
List*
63+
rte_attach_tag(constuint32query_id,
64+
RangeTblEntry*rte,
65+
List*key_value_pair)
66+
{
67+
relation_tags_entry*htab_entry,
68+
htab_key= {rte->relid,query_id,NIL/* unused */ };
69+
boolfound;
70+
MemoryContextold_mcxt;
71+
72+
AssertArg(rte);
73+
AssertArg(key_value_pair&&list_length(key_value_pair)==2);
74+
75+
/* We prefer to initialize this table lazily */
76+
if (!per_table_relation_tags)
77+
{
78+
constlongstart_elems=50;
79+
HASHCTLhashctl;
80+
81+
memset(&hashctl,0,sizeof(HASHCTL));
82+
hashctl.entrysize=sizeof(relation_tags_entry);
83+
hashctl.keysize= offsetof(relation_tags_entry,relation_tags);
84+
hashctl.hcxt=TAG_MEMORY_CONTEXT;
85+
86+
per_table_relation_tags=hash_create("Custom tags for RangeTblEntry",
87+
start_elems,&hashctl,
88+
HASH_ELEM |HASH_BLOBS);
89+
}
90+
91+
/* Search by 'htab_key' */
92+
htab_entry=hash_search(per_table_relation_tags,
93+
&htab_key,HASH_ENTER,&found);
94+
95+
if (found)
96+
{
97+
constchar*current_key;
98+
99+
/* Extract key of this KVP */
100+
rte_deconstruct_tag(key_value_pair,&current_key,NULL);
101+
102+
/* Check if this KVP already exists */
103+
returnrelation_tags_search(htab_entry->relation_tags,current_key);
104+
}
105+
106+
/* Don't forget to initialize list! */
107+
elsehtab_entry->relation_tags=NIL;
108+
109+
/* Add this KVP */
110+
old_mcxt=MemoryContextSwitchTo(TAG_MEMORY_CONTEXT);
111+
htab_entry->relation_tags=lappend(htab_entry->relation_tags,
112+
key_value_pair);
113+
MemoryContextSwitchTo(old_mcxt);
114+
115+
/* Success! */
116+
returnNIL;
117+
}
118+
119+
120+
121+
/* Extract key & value from 'key_value_pair' */
122+
void
123+
rte_deconstruct_tag(constList*key_value_pair,
124+
constchar**key,/* ret value #1 */
125+
constValue**value)/* ret value #2 */
126+
{
127+
constchar*r_key;
128+
constValue*r_value;
129+
130+
AssertArg(key_value_pair&&list_length(key_value_pair)==2);
131+
132+
r_key= (constchar*)strVal(linitial(key_value_pair));
133+
r_value= (constValue*)lsecond(key_value_pair);
134+
135+
/* Check that 'key' is valid */
136+
Assert(IsA(linitial(key_value_pair),String));
137+
138+
/* Check that 'value' is valid or NULL */
139+
Assert(r_value==NULL||
140+
IsA(r_value,Integer)||
141+
IsA(r_value,Float)||
142+
IsA(r_value,String));
143+
144+
/* Finally return key & value */
145+
if (key)*key=r_key;
146+
if (value)*value=r_value;
147+
}
148+
149+
/* Search through list of 'relation_tags' */
150+
List*
151+
relation_tags_search(List*relation_tags,constchar*key)
152+
{
153+
ListCell*lc;
154+
155+
AssertArg(key);
156+
157+
/* Scan KVP list */
158+
foreach (lc,relation_tags)
159+
{
160+
List*current_kvp= (List*)lfirst(lc);
161+
constchar*current_key;
162+
163+
/* Extract key of this KVP */
164+
rte_deconstruct_tag(current_kvp,&current_key,NULL);
165+
166+
/* Check if this is the KVP we're looking for */
167+
if (strcmp(key,current_key)==0)
168+
returncurrent_kvp;
169+
}
170+
171+
/* Nothing! */
172+
returnNIL;
173+
}
174+
175+
176+
177+
/* Increate usage counter by 1 */
178+
void
179+
incr_refcount_relation_tags(void)
180+
{
181+
/* Increment reference counter */
182+
if (++per_table_relation_tags_refcount <=0)
183+
elog(WARNING,"imbalanced %s",
184+
CppAsString(incr_refcount_relation_tags));
185+
}
186+
187+
/* Return current value of usage counter */
188+
uint32
189+
get_refcount_relation_tags(void)
190+
{
191+
/* incr_refcount_parenthood_statuses() is called by pathman_planner_hook() */
192+
returnper_table_relation_tags_refcount;
193+
}
194+
195+
/* Reset all cached statuses if needed (query end) */
196+
void
197+
decr_refcount_relation_tags(void)
198+
{
199+
/* Decrement reference counter */
200+
if (--per_table_relation_tags_refcount<0)
201+
elog(WARNING,"imbalanced %s",
202+
CppAsString(decr_refcount_relation_tags));
203+
204+
/* Free resources if no one is using them */
205+
if (per_table_relation_tags_refcount==0)
206+
{
207+
reset_query_id_generator();
208+
209+
hash_destroy(per_table_relation_tags);
210+
per_table_relation_tags=NULL;
211+
}
212+
}

‎src/hooks.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010

1111
#include"compat/pg_compat.h"
12+
#include"compat/relation_tags.h"
1213

1314
#include"hooks.h"
1415
#include"init.h"
@@ -214,8 +215,7 @@ pathman_rel_pathlist_hook(PlannerInfo *root,
214215
return;
215216

216217
/* Skip if this table is not allowed to act as parent (see FROM ONLY) */
217-
if (PARENTHOOD_DISALLOWED==get_rel_parenthood_status(root->parse->queryId,
218-
rte->relid))
218+
if (PARENTHOOD_DISALLOWED==get_rel_parenthood_status(root->parse->queryId,rte))
219219
return;
220220

221221
/* Proceed iff relation 'rel' is partitioned */
@@ -476,7 +476,7 @@ pathman_planner_hook(Query *parse, int cursorOptions, ParamListInfo boundParams)
476476
if (pathman_ready)
477477
{
478478
/* Increment parenthood_statuses refcount */
479-
incr_refcount_parenthood_statuses();
479+
incr_refcount_relation_tags();
480480

481481
/* Modify query tree if needed */
482482
pathman_transform_query(parse);
@@ -497,7 +497,7 @@ pathman_planner_hook(Query *parse, int cursorOptions, ParamListInfo boundParams)
497497
ExecuteForPlanTree(result,add_partition_filters);
498498

499499
/* Decrement parenthood_statuses refcount */
500-
decr_refcount_parenthood_statuses();
500+
decr_refcount_relation_tags();
501501

502502
/* HACK: restore queryId set by pg_stat_statements */
503503
result->queryId=query_id;
@@ -509,7 +509,7 @@ pathman_planner_hook(Query *parse, int cursorOptions, ParamListInfo boundParams)
509509
if (pathman_ready)
510510
{
511511
/* Caught an ERROR, decrease refcount */
512-
decr_refcount_parenthood_statuses();
512+
decr_refcount_relation_tags();
513513
}
514514

515515
/* Rethrow ERROR further */
@@ -552,7 +552,7 @@ pathman_post_parse_analysis_hook(ParseState *pstate, Query *query)
552552
}
553553

554554
/* Process inlined SQL functions (we've already entered planning stage) */
555-
if (IsPathmanReady()&&get_refcount_parenthood_statuses()>0)
555+
if (IsPathmanReady()&&get_refcount_relation_tags()>0)
556556
{
557557
/* Check that pg_pathman is the last extension loaded */
558558
if (post_parse_analyze_hook!=pathman_post_parse_analysis_hook)

‎src/include/compat/relation_tags.h

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/* ------------------------------------------------------------------------
2+
*
3+
* relation_tags.h
4+
*Attach custom (Key, Value) pairs to an arbitrary RangeTblEntry
5+
*
6+
* Copyright (c) 2017, Postgres Professional
7+
*
8+
* ------------------------------------------------------------------------
9+
*/
10+
11+
#ifndefRELATION_TAGS_H
12+
#defineRELATION_TAGS_H
13+
14+
15+
#include"pathman.h"
16+
17+
#include"postgres.h"
18+
#include"nodes/relation.h"
19+
#include"nodes/value.h"
20+
#include"utils/memutils.h"
21+
22+
23+
24+
/* Memory context we're going to use for TAGs */
25+
#defineTAG_MEMORY_CONTEXT TopTransactionContext
26+
27+
/* Safe TAG constructor (Integer) */
28+
staticinlineList*
29+
make_rte_tag_int(char*key,intvalue)
30+
{
31+
List*kvp;
32+
MemoryContextold_mcxt;
33+
34+
/* Allocate TAG in a persistent memory context */
35+
old_mcxt=MemoryContextSwitchTo(TAG_MEMORY_CONTEXT);
36+
kvp=list_make2(makeString(key),makeInteger(value));
37+
MemoryContextSwitchTo(old_mcxt);
38+
39+
returnkvp;
40+
}
41+
42+
43+
44+
List*rte_fetch_tag(constuint32query_id,
45+
constRangeTblEntry*rte,
46+
constchar*key);
47+
48+
List*rte_attach_tag(constuint32query_id,
49+
RangeTblEntry*rte,
50+
List*key_value_pair);
51+
52+
53+
List*relation_tags_search(List*custom_tags,
54+
constchar*key);
55+
56+
voidrte_deconstruct_tag(constList*key_value_pair,
57+
constchar**key,
58+
constValue**value);
59+
60+
61+
voidincr_refcount_relation_tags(void);
62+
uint32get_refcount_relation_tags(void);
63+
voiddecr_refcount_relation_tags(void);
64+
65+
66+
#endif/* RELATION_TAGS_H */

‎src/include/planner_tree_modification.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
#include"nodes/nodeFuncs.h"
2121

2222

23+
/* Query ID generator */
24+
voidassign_query_id(Query*query);
25+
voidreset_query_id_generator(void);
26+
2327
/* Plan tree rewriting utility */
2428
voidplan_tree_walker(Plan*plan,
2529
void (*visitor) (Plan*plan,void*context),
@@ -41,12 +45,12 @@ typedef enum
4145
PARENTHOOD_ALLOWED/* children are enabled (default) */
4246
}rel_parenthood_status;
4347

44-
voidassign_rel_parenthood_status(uint32query_id,Oidrelid,
48+
#definePARENTHOOD_TAG CppAsString(PARENTHOOD)
49+
50+
voidassign_rel_parenthood_status(uint32query_id,
51+
RangeTblEntry*rte,
4552
rel_parenthood_statusnew_status);
46-
rel_parenthood_statusget_rel_parenthood_status(uint32query_id,Oidrelid);
47-
voidincr_refcount_parenthood_statuses(void);
48-
uint32get_refcount_parenthood_statuses(void);
49-
voiddecr_refcount_parenthood_statuses(void);
53+
rel_parenthood_statusget_rel_parenthood_status(uint32query_id,RangeTblEntry*rte);
5054

5155

5256
#endif/* PLANNER_TREE_MODIFICATION_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp