PostgreSQL Source Code git master
extendplan.c
Go to the documentation of this file.
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
25#include "port/pg_bitutils.h"
26#include "utils/memutils.h"
27
28static const char **PlannerExtensionNameArray = NULL;
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 */
40int
41GetPlannerExtensionId(const char *extension_name)
42{
43 /* Search for an existing extension by this name; if found, return ID. */
44 for (int i = 0; i < PlannerExtensionNamesAssigned; ++i)
45 if (strcmp(PlannerExtensionNameArray[i], extension_name) == 0)
46 return i;
47
48 /* If there is no array yet, create one. */
49 if (PlannerExtensionNameArray == NULL)
50 {
52 PlannerExtensionNameArray = (const char **)
55 * sizeof(char *));
56 }
57
58 /* If there's an array but it's currently full, expand it. */
60 {
62
63 PlannerExtensionNameArray = (const char **)
64 repalloc(PlannerExtensionNameArray, i * sizeof(char *));
66 }
67
68 /* Assign and return new ID. */
71}
72
73/*
74 * Store extension-specific state into a PlannerGlobal.
75 */
76void
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 MemoryContext planner_cxt;
86 Size sz;
87
88 planner_cxt = GetMemoryChunkContext(glob);
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 int i;
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 *));
106 }
107
108 glob->extension_state[extension_id] = opaque;
109}
110
111/*
112 * Store extension-specific state into a PlannerInfo.
113 */
114void
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 Size sz;
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 int i;
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 */
150void
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 MemoryContext planner_cxt;
160 Size sz;
161
162 planner_cxt = GetMemoryChunkContext(rel);
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 int i;
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 *));
180 }
181
182 rel->extension_state[extension_id] = opaque;
183}
#define Max(x, y)
Definition: c.h:997
size_t Size
Definition: c.h:610
static const char ** PlannerExtensionNameArray
Definition: extendplan.c:28
static int PlannerExtensionNamesAssigned
Definition: extendplan.c:29
void SetRelOptInfoExtensionState(RelOptInfo *rel, int extension_id, void *opaque)
Definition: extendplan.c:151
void SetPlannerInfoExtensionState(PlannerInfo *root, int extension_id, void *opaque)
Definition: extendplan.c:115
int GetPlannerExtensionId(const char *extension_name)
Definition: extendplan.c:41
static int PlannerExtensionNamesAllocated
Definition: extendplan.c:30
void SetPlannerGlobalExtensionState(PlannerGlobal *glob, int extension_id, void *opaque)
Definition: extendplan.c:77
Assert(PointerIsAligned(start, uint64))
int i
Definition: isn.c:77
void * repalloc0(void *pointer, Size oldsize, Size size)
Definition: mcxt.c:1682
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1229
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1263
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1610
MemoryContext TopMemoryContext
Definition: mcxt.c:166
MemoryContext GetMemoryChunkContext(void *pointer)
Definition: mcxt.c:753
static uint32 pg_nextpower2_32(uint32 num)
Definition: pg_bitutils.h:189
tree ctl root
Definition: radixtree.h:1857
int extension_state_allocated
Definition: pathnodes.h:191
int extension_state_allocated
Definition: pathnodes.h:1124