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

Commit0132ddd

Browse files
committed
Allow private state in certain planner data structures.
Extension that make extensive use of planner hooks may want tocoordinate their efforts, for example to avoid duplicate computation,but that's currently difficult because there's no really good way topass data between different hooks.To make that easier, allow for storage of extension-managed privatestate in PlannerGlobal, PlannerInfo, and RelOptInfo, along verysimilar lines to what we have permitted for ExplainState since commitc65bc2e.Reviewed-by: Andrei Lepikhov <lepihov@gmail.com>Reviewed-by: Melanie Plageman <melanieplageman@gmail.com>Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>Discussion:http://postgr.es/m/CA+TgmoYWKHU2hKr62Toyzh-kTDEnMDeLw7gkOOnjL-TnOUq0kQ@mail.gmail.com
1 parentafd532c commit0132ddd

File tree

5 files changed

+269
-0
lines changed

5 files changed

+269
-0
lines changed

‎src/backend/optimizer/util/Makefile‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ include $(top_builddir)/src/Makefile.global
1515
OBJS =\
1616
appendinfo.o\
1717
clauses.o\
18+
extendplan.o\
1819
inherit.o\
1920
joininfo.o\
2021
orclauses.o\
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* extendplan.c
4+
* Extend core planner objects with additional private state
5+
*
6+
* Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7+
* Portions Copyright (c) 1994-5, Regents of the University of California
8+
*
9+
* The interfaces defined in this file make it possible for loadable
10+
* modules to store their own private state inside of key planner data
11+
* structures -- specifically, the PlannerGlobal, PlannerInfo, and
12+
* RelOptInfo structures. This can make it much easier to write
13+
* reasonably efficient planner extensions; for instance, code that
14+
* uses set_join_pathlist_hook can arrange to compute a key intermediate
15+
* result once per joinrel rather than on every call.
16+
*
17+
* IDENTIFICATION
18+
* src/backend/optimizer/util/extendplan.c
19+
*
20+
*-------------------------------------------------------------------------
21+
*/
22+
#include"postgres.h"
23+
24+
#include"optimizer/extendplan.h"
25+
#include"port/pg_bitutils.h"
26+
#include"utils/memutils.h"
27+
28+
staticconstchar**PlannerExtensionNameArray=NULL;
29+
staticintPlannerExtensionNamesAssigned=0;
30+
staticintPlannerExtensionNamesAllocated=0;
31+
32+
/*
33+
* Map the name of a planner extension to an integer ID.
34+
*
35+
* Within the lifetime of a particular backend, the same name will be mapped
36+
* to the same ID every time. IDs are not stable across backends. Use the ID
37+
* that you get from this function to call the remaining functions in this
38+
* file.
39+
*/
40+
int
41+
GetPlannerExtensionId(constchar*extension_name)
42+
{
43+
/* Search for an existing extension by this name; if found, return ID. */
44+
for (inti=0;i<PlannerExtensionNamesAssigned;++i)
45+
if (strcmp(PlannerExtensionNameArray[i],extension_name)==0)
46+
returni;
47+
48+
/* If there is no array yet, create one. */
49+
if (PlannerExtensionNameArray==NULL)
50+
{
51+
PlannerExtensionNamesAllocated=16;
52+
PlannerExtensionNameArray= (constchar**)
53+
MemoryContextAlloc(TopMemoryContext,
54+
PlannerExtensionNamesAllocated
55+
*sizeof(char*));
56+
}
57+
58+
/* If there's an array but it's currently full, expand it. */
59+
if (PlannerExtensionNamesAssigned >=PlannerExtensionNamesAllocated)
60+
{
61+
inti=pg_nextpower2_32(PlannerExtensionNamesAssigned+1);
62+
63+
PlannerExtensionNameArray= (constchar**)
64+
repalloc(PlannerExtensionNameArray,i*sizeof(char*));
65+
PlannerExtensionNamesAllocated=i;
66+
}
67+
68+
/* Assign and return new ID. */
69+
PlannerExtensionNameArray[PlannerExtensionNamesAssigned]=extension_name;
70+
returnPlannerExtensionNamesAssigned++;
71+
}
72+
73+
/*
74+
* Store extension-specific state into a PlannerGlobal.
75+
*/
76+
void
77+
SetPlannerGlobalExtensionState(PlannerGlobal*glob,intextension_id,
78+
void*opaque)
79+
{
80+
Assert(extension_id >=0);
81+
82+
/* If there is no array yet, create one. */
83+
if (glob->extension_state==NULL)
84+
{
85+
MemoryContextplanner_cxt;
86+
Sizesz;
87+
88+
planner_cxt=GetMemoryChunkContext(glob);
89+
glob->extension_state_allocated=
90+
Max(4,pg_nextpower2_32(extension_id+1));
91+
sz=glob->extension_state_allocated*sizeof(void*);
92+
glob->extension_state=MemoryContextAllocZero(planner_cxt,sz);
93+
}
94+
95+
/* If there's an array but it's currently full, expand it. */
96+
if (extension_id >=glob->extension_state_allocated)
97+
{
98+
inti;
99+
100+
i=pg_nextpower2_32(extension_id+1);
101+
glob->extension_state= (void**)
102+
repalloc0(glob->extension_state,
103+
glob->extension_state_allocated*sizeof(void*),
104+
i*sizeof(void*));
105+
glob->extension_state_allocated=i;
106+
}
107+
108+
glob->extension_state[extension_id]=opaque;
109+
}
110+
111+
/*
112+
* Store extension-specific state into a PlannerInfo.
113+
*/
114+
void
115+
SetPlannerInfoExtensionState(PlannerInfo*root,intextension_id,
116+
void*opaque)
117+
{
118+
Assert(extension_id >=0);
119+
120+
/* If there is no array yet, create one. */
121+
if (root->extension_state==NULL)
122+
{
123+
Sizesz;
124+
125+
root->extension_state_allocated=
126+
Max(4,pg_nextpower2_32(extension_id+1));
127+
sz=root->extension_state_allocated*sizeof(void*);
128+
root->extension_state=MemoryContextAllocZero(root->planner_cxt,sz);
129+
}
130+
131+
/* If there's an array but it's currently full, expand it. */
132+
if (extension_id >=root->extension_state_allocated)
133+
{
134+
inti;
135+
136+
i=pg_nextpower2_32(extension_id+1);
137+
root->extension_state= (void**)
138+
repalloc0(root->extension_state,
139+
root->extension_state_allocated*sizeof(void*),
140+
i*sizeof(void*));
141+
root->extension_state_allocated=i;
142+
}
143+
144+
root->extension_state[extension_id]=opaque;
145+
}
146+
147+
/*
148+
* Store extension-specific state into a RelOptInfo.
149+
*/
150+
void
151+
SetRelOptInfoExtensionState(RelOptInfo*rel,intextension_id,
152+
void*opaque)
153+
{
154+
Assert(extension_id >=0);
155+
156+
/* If there is no array yet, create one. */
157+
if (rel->extension_state==NULL)
158+
{
159+
MemoryContextplanner_cxt;
160+
Sizesz;
161+
162+
planner_cxt=GetMemoryChunkContext(rel);
163+
rel->extension_state_allocated=
164+
Max(4,pg_nextpower2_32(extension_id+1));
165+
sz=rel->extension_state_allocated*sizeof(void*);
166+
rel->extension_state=MemoryContextAllocZero(planner_cxt,sz);
167+
}
168+
169+
/* If there's an array but it's currently full, expand it. */
170+
if (extension_id >=rel->extension_state_allocated)
171+
{
172+
inti;
173+
174+
i=pg_nextpower2_32(extension_id+1);
175+
rel->extension_state= (void**)
176+
repalloc0(rel->extension_state,
177+
rel->extension_state_allocated*sizeof(void*),
178+
i*sizeof(void*));
179+
rel->extension_state_allocated=i;
180+
}
181+
182+
rel->extension_state[extension_id]=opaque;
183+
}

‎src/backend/optimizer/util/meson.build‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
backend_sources+=files(
44
'appendinfo.c',
55
'clauses.c',
6+
'extendplan.c',
67
'inherit.c',
78
'joininfo.c',
89
'orclauses.c',

‎src/include/nodes/pathnodes.h‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,10 @@ typedef struct PlannerGlobal
185185

186186
/* hash table for NOT NULL attnums of relations */
187187
structHTAB*rel_notnullatts_hashpg_node_attr(read_write_ignore);
188+
189+
/* extension state */
190+
void**extension_statepg_node_attr(read_write_ignore);
191+
intextension_state_allocated;
188192
}PlannerGlobal;
189193

190194
/* macro for fetching the Plan associated with a SubPlan node */
@@ -586,6 +590,10 @@ struct PlannerInfo
586590

587591
/* PartitionPruneInfos added in this query's plan. */
588592
List*partPruneInfos;
593+
594+
/* extension state */
595+
void**extension_statepg_node_attr(read_write_ignore);
596+
intextension_state_allocated;
589597
};
590598

591599

@@ -1097,6 +1105,10 @@ typedef struct RelOptInfo
10971105
List**partexprspg_node_attr(read_write_ignore);
10981106
/* Nullable partition key expressions */
10991107
List**nullable_partexprspg_node_attr(read_write_ignore);
1108+
1109+
/* extension state */
1110+
void**extension_statepg_node_attr(read_write_ignore);
1111+
intextension_state_allocated;
11001112
}RelOptInfo;
11011113

11021114
/*

‎src/include/optimizer/extendplan.h‎

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* extendplan.h
4+
* Extend core planner objects with additional private state
5+
*
6+
*
7+
* Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
8+
* Portions Copyright (c) 1994, Regents of the University of California
9+
*
10+
* src/include/optimizer/extendplan.h
11+
*
12+
*-------------------------------------------------------------------------
13+
*/
14+
#ifndefEXTENDPLAN_H
15+
#defineEXTENDPLAN_H
16+
17+
#include"nodes/pathnodes.h"
18+
19+
externintGetPlannerExtensionId(constchar*extension_name);
20+
21+
/*
22+
* Get extension-specific state from a PlannerGlobal.
23+
*/
24+
staticinlinevoid*
25+
GetPlannerGlobalExtensionState(PlannerGlobal*glob,intextension_id)
26+
{
27+
Assert(extension_id >=0);
28+
29+
if (extension_id >=glob->extension_state_allocated)
30+
returnNULL;
31+
32+
returnglob->extension_state[extension_id];
33+
}
34+
35+
/*
36+
* Get extension-specific state from a PlannerInfo.
37+
*/
38+
staticinlinevoid*
39+
GetPlannerInfoExtensionState(PlannerInfo*root,intextension_id)
40+
{
41+
Assert(extension_id >=0);
42+
43+
if (extension_id >=root->extension_state_allocated)
44+
returnNULL;
45+
46+
returnroot->extension_state[extension_id];
47+
}
48+
49+
/*
50+
* Get extension-specific state from a PlannerInfo.
51+
*/
52+
staticinlinevoid*
53+
GetRelOptInfoExtensionState(RelOptInfo*rel,intextension_id)
54+
{
55+
Assert(extension_id >=0);
56+
57+
if (extension_id >=rel->extension_state_allocated)
58+
returnNULL;
59+
60+
returnrel->extension_state[extension_id];
61+
}
62+
63+
/* Functions to store private state into various planner objects */
64+
externvoidSetPlannerGlobalExtensionState(PlannerGlobal*glob,
65+
intextension_id,
66+
void*opaque);
67+
externvoidSetPlannerInfoExtensionState(PlannerInfo*root,intextension_id,
68+
void*opaque);
69+
externvoidSetRelOptInfoExtensionState(RelOptInfo*rel,intextension_id,
70+
void*opaque);
71+
72+
#endif

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp