PostgreSQL Source Code  git master
plancache.h File Reference
#include "access/tupdesc.h"
#include "lib/ilist.h"
#include "nodes/params.h"
#include "utils/queryenvironment.h"
Include dependency graph for plancache.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  CachedPlanSource
 
struct  CachedPlan
 
struct  CachedExpression
 

Macros

#define CACHEDPLANSOURCE_MAGIC   195726186
 
#define CACHEDPLAN_MAGIC   953717834
 
#define CACHEDEXPR_MAGIC   838275847
 

Typedefs

typedef struct CachedPlanSource CachedPlanSource
 
typedef struct CachedPlan CachedPlan
 
typedef struct CachedExpression CachedExpression
 

Enumerations

enum  PlanCacheMode { PLAN_CACHE_MODE_AUTO, PLAN_CACHE_MODE_FORCE_GENERIC_PLAN, PLAN_CACHE_MODE_FORCE_CUSTOM_PLAN }
 

Functions

void InitPlanCache (void)
 
void ResetPlanCache (void)
 
CachedPlanSourceCreateCachedPlan (struct RawStmt *raw_parse_tree, const char *query_string, const char *commandTag)
 
CachedPlanSourceCreateOneShotCachedPlan (struct RawStmt *raw_parse_tree, const char *query_string, const char *commandTag)
 
void CompleteCachedPlan (CachedPlanSource *plansource, List *querytree_list, MemoryContext querytree_context, Oid *param_types, int num_params, ParserSetupHook parserSetup, void *parserSetupArg, int cursor_options, bool fixed_result)
 
void SaveCachedPlan (CachedPlanSource *plansource)
 
void DropCachedPlan (CachedPlanSource *plansource)
 
void CachedPlanSetParentContext (CachedPlanSource *plansource, MemoryContext newcontext)
 
CachedPlanSourceCopyCachedPlan (CachedPlanSource *plansource)
 
bool CachedPlanIsValid (CachedPlanSource *plansource)
 
ListCachedPlanGetTargetList (CachedPlanSource *plansource, QueryEnvironment *queryEnv)
 
CachedPlanGetCachedPlan (CachedPlanSource *plansource, ParamListInfo boundParams, bool useResOwner, QueryEnvironment *queryEnv)
 
void ReleaseCachedPlan (CachedPlan *plan, bool useResOwner)
 
CachedExpressionGetCachedExpression (Node *expr)
 
void FreeCachedExpression (CachedExpression *cexpr)
 

Variables

int plan_cache_mode
 

Macro Definition Documentation

◆ CACHEDEXPR_MAGIC

#define CACHEDEXPR_MAGIC   838275847

◆ CACHEDPLAN_MAGIC

#define CACHEDPLAN_MAGIC   953717834

◆ CACHEDPLANSOURCE_MAGIC

Typedef Documentation

◆ CachedExpression

◆ CachedPlan

typedef struct CachedPlan CachedPlan

◆ CachedPlanSource

Enumeration Type Documentation

◆ PlanCacheMode

Enumerator
PLAN_CACHE_MODE_AUTO 
PLAN_CACHE_MODE_FORCE_GENERIC_PLAN 
PLAN_CACHE_MODE_FORCE_CUSTOM_PLAN 

Definition at line 27 of file plancache.h.

Function Documentation

◆ CachedPlanGetTargetList()

List* CachedPlanGetTargetList ( CachedPlanSource plansource,
QueryEnvironment queryEnv 
)

Definition at line 1428 of file plancache.c.

References Assert, CACHEDPLANSOURCE_MAGIC, FetchStatementTargetList(), CachedPlanSource::is_complete, CachedPlanSource::magic, NIL, CachedPlanSource::query_list, QueryListGetPrimaryStmt(), CachedPlanSource::resultDesc, and RevalidateCachedQuery().

Referenced by exec_describe_statement_message(), and FetchPreparedStatementTargetList().

1430 {
1431  Query *pstmt;
1432 
1433  /* Assert caller is doing things in a sane order */
1434  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1435  Assert(plansource->is_complete);
1436 
1437  /*
1438  * No work needed if statement doesn't return tuples (we assume this
1439  * feature cannot be changed by an invalidation)
1440  */
1441  if (plansource->resultDesc == NULL)
1442  return NIL;
1443 
1444  /* Make sure the querytree list is valid and we have parse-time locks */
1445  RevalidateCachedQuery(plansource, queryEnv);
1446 
1447  /* Get the primary statement and find out what it returns */
1448  pstmt = QueryListGetPrimaryStmt(plansource->query_list);
1449 
1450  return FetchStatementTargetList((Node *) pstmt);
1451 }
#define NIL
Definition: pg_list.h:65
Definition: nodes.h:525
TupleDesc resultDesc
Definition: plancache.h:105
List * FetchStatementTargetList(Node *stmt)
Definition: pquery.c:358
static Query * QueryListGetPrimaryStmt(List *stmts)
Definition: plancache.c:1541
static List * RevalidateCachedQuery(CachedPlanSource *plansource, QueryEnvironment *queryEnv)
Definition: plancache.c:553
#define Assert(condition)
Definition: c.h:733
List * query_list
Definition: plancache.h:108
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:37

◆ CachedPlanIsValid()

bool CachedPlanIsValid ( CachedPlanSource plansource)

Definition at line 1415 of file plancache.c.

References Assert, CACHEDPLANSOURCE_MAGIC, CachedPlanSource::is_valid, and CachedPlanSource::magic.

Referenced by SPI_plan_is_valid().

1416 {
1417  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1418  return plansource->is_valid;
1419 }
#define Assert(condition)
Definition: c.h:733
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:37

◆ CachedPlanSetParentContext()

void CachedPlanSetParentContext ( CachedPlanSource plansource,
MemoryContext  newcontext 
)

Definition at line 1287 of file plancache.c.

References Assert, CACHEDPLAN_MAGIC, CACHEDPLANSOURCE_MAGIC, CachedPlanSource::context, CachedPlan::context, elog, ERROR, CachedPlanSource::gplan, CachedPlanSource::is_complete, CachedPlanSource::is_oneshot, CachedPlanSource::is_saved, CachedPlanSource::magic, CachedPlan::magic, and MemoryContextSetParent().

Referenced by _SPI_make_plan_non_temp().

1289 {
1290  /* Assert caller is doing things in a sane order */
1291  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1292  Assert(plansource->is_complete);
1293 
1294  /* These seem worth real tests, though */
1295  if (plansource->is_saved)
1296  elog(ERROR, "cannot move a saved cached plan to another context");
1297  if (plansource->is_oneshot)
1298  elog(ERROR, "cannot move a one-shot cached plan to another context");
1299 
1300  /* OK, let the caller keep the plan where he wishes */
1301  MemoryContextSetParent(plansource->context, newcontext);
1302 
1303  /*
1304  * The query_context needs no special handling, since it's a child of
1305  * plansource->context. But if there's a generic plan, it should be
1306  * maintained as a sibling of plansource->context.
1307  */
1308  if (plansource->gplan)
1309  {
1310  Assert(plansource->gplan->magic == CACHEDPLAN_MAGIC);
1311  MemoryContextSetParent(plansource->gplan->context, newcontext);
1312  }
1313 }
#define CACHEDPLAN_MAGIC
Definition: plancache.h:38
MemoryContext context
Definition: plancache.h:106
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:354
MemoryContext context
Definition: plancache.h:156
struct CachedPlan * gplan
Definition: plancache.h:118
#define ERROR
Definition: elog.h:43
#define Assert(condition)
Definition: c.h:733
#define elog(elevel,...)
Definition: elog.h:228
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:37

◆ CompleteCachedPlan()

void CompleteCachedPlan ( CachedPlanSource plansource,
List querytree_list,
MemoryContext  querytree_context,
Oid param_types,
int  num_params,
ParserSetupHook  parserSetup,
void *  parserSetupArg,
int  cursor_options,
bool  fixed_result 
)

Definition at line 336 of file plancache.c.

References ALLOCSET_START_SMALL_SIZES, AllocSetContextCreate, Assert, CACHEDPLANSOURCE_MAGIC, CachedPlanSource::context, copyObject, CurrentMemoryContext, CachedPlanSource::cursor_options, CachedPlanSource::dependsOnRLS, extract_query_dependencies(), CachedPlanSource::fixed_result, GetOverrideSearchPath(), GetUserId(), CachedPlanSource::invalItems, CachedPlanSource::is_complete, CachedPlanSource::is_oneshot, CachedPlanSource::is_valid, IsTransactionStmtPlan, CachedPlanSource::magic, MemoryContextSetParent(), MemoryContextSwitchTo(), CachedPlanSource::num_params, palloc(), CachedPlanSource::param_types, CachedPlanSource::parserSetup, CachedPlanSource::parserSetupArg, PlanCacheComputeResultDesc(), CachedPlanSource::query_context, CachedPlanSource::query_list, CachedPlanSource::relationOids, CachedPlanSource::resultDesc, CachedPlanSource::rewriteRoleId, CachedPlanSource::rewriteRowSecurity, row_security, and CachedPlanSource::search_path.

Referenced by _SPI_execute_plan(), _SPI_prepare_plan(), exec_parse_message(), and PrepareQuery().

345 {
346  MemoryContext source_context = plansource->context;
348 
349  /* Assert caller is doing things in a sane order */
350  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
351  Assert(!plansource->is_complete);
352 
353  /*
354  * If caller supplied a querytree_context, reparent it underneath the
355  * CachedPlanSource's context; otherwise, create a suitable context and
356  * copy the querytree_list into it. But no data copying should be done
357  * for one-shot plans; for those, assume the passed querytree_list is
358  * sufficiently long-lived.
359  */
360  if (plansource->is_oneshot)
361  {
362  querytree_context = CurrentMemoryContext;
363  }
364  else if (querytree_context != NULL)
365  {
366  MemoryContextSetParent(querytree_context, source_context);
367  MemoryContextSwitchTo(querytree_context);
368  }
369  else
370  {
371  /* Again, it's a good bet the querytree_context can be small */
372  querytree_context = AllocSetContextCreate(source_context,
373  "CachedPlanQuery",
375  MemoryContextSwitchTo(querytree_context);
376  querytree_list = copyObject(querytree_list);
377  }
378 
379  plansource->query_context = querytree_context;
380  plansource->query_list = querytree_list;
381 
382  if (!plansource->is_oneshot && !IsTransactionStmtPlan(plansource))
383  {
384  /*
385  * Use the planner machinery to extract dependencies. Data is saved
386  * in query_context. (We assume that not a lot of extra cruft is
387  * created by this call.) We can skip this for one-shot plans, and
388  * transaction control commands have no such dependencies anyway.
389  */
390  extract_query_dependencies((Node *) querytree_list,
391  &plansource->relationOids,
392  &plansource->invalItems,
393  &plansource->dependsOnRLS);
394 
395  /* Update RLS info as well. */
396  plansource->rewriteRoleId = GetUserId();
397  plansource->rewriteRowSecurity = row_security;
398 
399  /*
400  * Also save the current search_path in the query_context. (This
401  * should not generate much extra cruft either, since almost certainly
402  * the path is already valid.) Again, we don't really need this for
403  * one-shot plans; and we *must* skip this for transaction control
404  * commands, because this could result in catalog accesses.
405  */
406  plansource->search_path = GetOverrideSearchPath(querytree_context);
407  }
408 
409  /*
410  * Save the final parameter types (or other parameter specification data)
411  * into the source_context, as well as our other parameters. Also save
412  * the result tuple descriptor.
413  */
414  MemoryContextSwitchTo(source_context);
415 
416  if (num_params > 0)
417  {
418  plansource->param_types = (Oid *) palloc(num_params * sizeof(Oid));
419  memcpy(plansource->param_types, param_types, num_params * sizeof(Oid));
420  }
421  else
422  plansource->param_types = NULL;
423  plansource->num_params = num_params;
424  plansource->parserSetup = parserSetup;
425  plansource->parserSetupArg = parserSetupArg;
426  plansource->cursor_options = cursor_options;
427  plansource->fixed_result = fixed_result;
428  plansource->resultDesc = PlanCacheComputeResultDesc(querytree_list);
429 
430  MemoryContextSwitchTo(oldcxt);
431 
432  plansource->is_complete = true;
433  plansource->is_valid = true;
434 }
MemoryContext context
Definition: plancache.h:106
bool rewriteRowSecurity
Definition: plancache.h:115
#define AllocSetContextCreate
Definition: memutils.h:170
Oid GetUserId(void)
Definition: miscinit.c:380
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:354
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:525
unsigned int Oid
Definition: postgres_ext.h:31
TupleDesc resultDesc
Definition: plancache.h:105
List * invalItems
Definition: plancache.h:110
OverrideSearchPath * GetOverrideSearchPath(MemoryContext context)
Definition: namespace.c:3352
Oid * param_types
Definition: plancache.h:99
List * relationOids
Definition: plancache.h:109
void * parserSetupArg
Definition: plancache.h:102
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
ParserSetupHook parserSetup
Definition: plancache.h:101
bool row_security
Definition: guc.c:502
#define Assert(condition)
Definition: c.h:733
void extract_query_dependencies(Node *query, List **relationOids, List **invalItems, bool *hasRowSecurity)
Definition: setrefs.c:2758
void * palloc(Size size)
Definition: mcxt.c:949
MemoryContext query_context
Definition: plancache.h:113
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:209
List * query_list
Definition: plancache.h:108
#define IsTransactionStmtPlan(plansource)
Definition: plancache.c:82
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:37
#define copyObject(obj)
Definition: nodes.h:641
static TupleDesc PlanCacheComputeResultDesc(List *stmt_list)
Definition: plancache.c:1728
struct OverrideSearchPath * search_path
Definition: plancache.h:111

◆ CopyCachedPlan()

CachedPlanSource* CopyCachedPlan ( CachedPlanSource plansource)

Definition at line 1325 of file plancache.c.

References ALLOCSET_START_SMALL_SIZES, AllocSetContextCreate, Assert, CACHEDPLANSOURCE_MAGIC, CachedPlanSource::commandTag, CachedPlanSource::context, copyObject, CopyOverrideSearchPath(), CreateTupleDescCopy(), CurrentMemoryContext, CachedPlanSource::cursor_options, CachedPlanSource::dependsOnRLS, elog, ERROR, CachedPlanSource::fixed_result, CachedPlanSource::generation, CachedPlanSource::generic_cost, CachedPlanSource::gplan, CachedPlanSource::invalItems, CachedPlanSource::is_complete, CachedPlanSource::is_oneshot, CachedPlanSource::is_saved, CachedPlanSource::is_valid, CachedPlanSource::magic, MemoryContextSetIdentifier(), MemoryContextSwitchTo(), CachedPlanSource::num_custom_plans, CachedPlanSource::num_params, palloc(), palloc0(), CachedPlanSource::param_types, CachedPlanSource::parserSetup, CachedPlanSource::parserSetupArg, pstrdup(), CachedPlanSource::query_context, CachedPlanSource::query_list, CachedPlanSource::query_string, CachedPlanSource::raw_parse_tree, CachedPlanSource::relationOids, CachedPlanSource::resultDesc, CachedPlanSource::rewriteRoleId, CachedPlanSource::rewriteRowSecurity, CachedPlanSource::search_path, and CachedPlanSource::total_custom_cost.

Referenced by _SPI_save_plan().

1326 {
1327  CachedPlanSource *newsource;
1328  MemoryContext source_context;
1329  MemoryContext querytree_context;
1330  MemoryContext oldcxt;
1331 
1332  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1333  Assert(plansource->is_complete);
1334 
1335  /*
1336  * One-shot plans can't be copied, because we haven't taken care that
1337  * parsing/planning didn't scribble on the raw parse tree or querytrees.
1338  */
1339  if (plansource->is_oneshot)
1340  elog(ERROR, "cannot copy a one-shot cached plan");
1341 
1343  "CachedPlanSource",
1345 
1346  oldcxt = MemoryContextSwitchTo(source_context);
1347 
1348  newsource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
1349  newsource->magic = CACHEDPLANSOURCE_MAGIC;
1350  newsource->raw_parse_tree = copyObject(plansource->raw_parse_tree);
1351  newsource->query_string = pstrdup(plansource->query_string);
1352  MemoryContextSetIdentifier(source_context, newsource->query_string);
1353  newsource->commandTag = plansource->commandTag;
1354  if (plansource->num_params > 0)
1355  {
1356  newsource->param_types = (Oid *)
1357  palloc(plansource->num_params * sizeof(Oid));
1358  memcpy(newsource->param_types, plansource->param_types,
1359  plansource->num_params * sizeof(Oid));
1360  }
1361  else
1362  newsource->param_types = NULL;
1363  newsource->num_params = plansource->num_params;
1364  newsource->parserSetup = plansource->parserSetup;
1365  newsource->parserSetupArg = plansource->parserSetupArg;
1366  newsource->cursor_options = plansource->cursor_options;
1367  newsource->fixed_result = plansource->fixed_result;
1368  if (plansource->resultDesc)
1369  newsource->resultDesc = CreateTupleDescCopy(plansource->resultDesc);
1370  else
1371  newsource->resultDesc = NULL;
1372  newsource->context = source_context;
1373 
1374  querytree_context = AllocSetContextCreate(source_context,
1375  "CachedPlanQuery",
1377  MemoryContextSwitchTo(querytree_context);
1378  newsource->query_list = copyObject(plansource->query_list);
1379  newsource->relationOids = copyObject(plansource->relationOids);
1380  newsource->invalItems = copyObject(plansource->invalItems);
1381  if (plansource->search_path)
1382  newsource->search_path = CopyOverrideSearchPath(plansource->search_path);
1383  newsource->query_context = querytree_context;
1384  newsource->rewriteRoleId = plansource->rewriteRoleId;
1385  newsource->rewriteRowSecurity = plansource->rewriteRowSecurity;
1386  newsource->dependsOnRLS = plansource->dependsOnRLS;
1387 
1388  newsource->gplan = NULL;
1389 
1390  newsource->is_oneshot = false;
1391  newsource->is_complete = true;
1392  newsource->is_saved = false;
1393  newsource->is_valid = plansource->is_valid;
1394  newsource->generation = plansource->generation;
1395 
1396  /* We may as well copy any acquired cost knowledge */
1397  newsource->generic_cost = plansource->generic_cost;
1398  newsource->total_custom_cost = plansource->total_custom_cost;
1399  newsource->num_custom_plans = plansource->num_custom_plans;
1400 
1401  MemoryContextSwitchTo(oldcxt);
1402 
1403  return newsource;
1404 }
MemoryContext context
Definition: plancache.h:106
bool rewriteRowSecurity
Definition: plancache.h:115
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#define AllocSetContextCreate
Definition: memutils.h:170
const char * commandTag
Definition: plancache.h:98
char * pstrdup(const char *in)
Definition: mcxt.c:1186
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned int Oid
Definition: postgres_ext.h:31
double total_custom_cost
Definition: plancache.h:129
struct CachedPlan * gplan
Definition: plancache.h:118
TupleDesc resultDesc
Definition: plancache.h:105
#define ERROR
Definition: elog.h:43
OverrideSearchPath * CopyOverrideSearchPath(OverrideSearchPath *path)
Definition: namespace.c:3388
List * invalItems
Definition: plancache.h:110
Oid * param_types
Definition: plancache.h:99
List * relationOids
Definition: plancache.h:109
void * parserSetupArg
Definition: plancache.h:102
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
ParserSetupHook parserSetup
Definition: plancache.h:101
void * palloc0(Size size)
Definition: mcxt.c:980
double generic_cost
Definition: plancache.h:128
#define Assert(condition)
Definition: c.h:733
const char * query_string
Definition: plancache.h:97
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition: mcxt.c:329
struct RawStmt * raw_parse_tree
Definition: plancache.h:96
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:228
MemoryContext query_context
Definition: plancache.h:113
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:209
List * query_list
Definition: plancache.h:108
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:37
#define copyObject(obj)
Definition: nodes.h:641
struct OverrideSearchPath * search_path
Definition: plancache.h:111

◆ CreateCachedPlan()

CachedPlanSource* CreateCachedPlan ( struct RawStmt raw_parse_tree,
const char *  query_string,
const char *  commandTag 
)

Definition at line 164 of file plancache.c.

References ALLOCSET_START_SMALL_SIZES, AllocSetContextCreate, Assert, CACHEDPLANSOURCE_MAGIC, CachedPlanSource::commandTag, CachedPlanSource::context, copyObject, CurrentMemoryContext, CachedPlanSource::cursor_options, CachedPlanSource::dependsOnRLS, CachedPlanSource::fixed_result, CachedPlanSource::generation, CachedPlanSource::generic_cost, CachedPlanSource::gplan, InvalidOid, CachedPlanSource::invalItems, CachedPlanSource::is_complete, CachedPlanSource::is_oneshot, CachedPlanSource::is_saved, CachedPlanSource::is_valid, CachedPlanSource::magic, MemoryContextSetIdentifier(), MemoryContextSwitchTo(), NIL, CachedPlanSource::num_custom_plans, CachedPlanSource::num_params, palloc0(), CachedPlanSource::param_types, CachedPlanSource::parserSetup, CachedPlanSource::parserSetupArg, pstrdup(), CachedPlanSource::query_context, CachedPlanSource::query_list, CachedPlanSource::query_string, CachedPlanSource::raw_parse_tree, CachedPlanSource::relationOids, CachedPlanSource::resultDesc, CachedPlanSource::rewriteRoleId, CachedPlanSource::rewriteRowSecurity, CachedPlanSource::search_path, and CachedPlanSource::total_custom_cost.

Referenced by _SPI_prepare_plan(), exec_parse_message(), and PrepareQuery().

167 {
168  CachedPlanSource *plansource;
169  MemoryContext source_context;
170  MemoryContext oldcxt;
171 
172  Assert(query_string != NULL); /* required as of 8.4 */
173 
174  /*
175  * Make a dedicated memory context for the CachedPlanSource and its
176  * permanent subsidiary data. It's probably not going to be large, but
177  * just in case, allow it to grow large. Initially it's a child of the
178  * caller's context (which we assume to be transient), so that it will be
179  * cleaned up on error.
180  */
182  "CachedPlanSource",
184 
185  /*
186  * Create and fill the CachedPlanSource struct within the new context.
187  * Most fields are just left empty for the moment.
188  */
189  oldcxt = MemoryContextSwitchTo(source_context);
190 
191  plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
192  plansource->magic = CACHEDPLANSOURCE_MAGIC;
193  plansource->raw_parse_tree = copyObject(raw_parse_tree);
194  plansource->query_string = pstrdup(query_string);
195  MemoryContextSetIdentifier(source_context, plansource->query_string);
196  plansource->commandTag = commandTag;
197  plansource->param_types = NULL;
198  plansource->num_params = 0;
199  plansource->parserSetup = NULL;
200  plansource->parserSetupArg = NULL;
201  plansource->cursor_options = 0;
202  plansource->fixed_result = false;
203  plansource->resultDesc = NULL;
204  plansource->context = source_context;
205  plansource->query_list = NIL;
206  plansource->relationOids = NIL;
207  plansource->invalItems = NIL;
208  plansource->search_path = NULL;
209  plansource->query_context = NULL;
210  plansource->rewriteRoleId = InvalidOid;
211  plansource->rewriteRowSecurity = false;
212  plansource->dependsOnRLS = false;
213  plansource->gplan = NULL;
214  plansource->is_oneshot = false;
215  plansource->is_complete = false;
216  plansource->is_saved = false;
217  plansource->is_valid = false;
218  plansource->generation = 0;
219  plansource->generic_cost = -1;
220  plansource->total_custom_cost = 0;
221  plansource->num_custom_plans = 0;
222 
223  MemoryContextSwitchTo(oldcxt);
224 
225  return plansource;
226 }
MemoryContext context
Definition: plancache.h:106
#define NIL
Definition: pg_list.h:65
bool rewriteRowSecurity
Definition: plancache.h:115
#define AllocSetContextCreate
Definition: memutils.h:170
const char * commandTag
Definition: plancache.h:98
char * pstrdup(const char *in)
Definition: mcxt.c:1186
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
double total_custom_cost
Definition: plancache.h:129
struct CachedPlan * gplan
Definition: plancache.h:118
TupleDesc resultDesc
Definition: plancache.h:105
List * invalItems
Definition: plancache.h:110
Oid * param_types
Definition: plancache.h:99
List * relationOids
Definition: plancache.h:109
void * parserSetupArg
Definition: plancache.h:102
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
ParserSetupHook parserSetup
Definition: plancache.h:101
void * palloc0(Size size)
Definition: mcxt.c:980
#define InvalidOid
Definition: postgres_ext.h:36
double generic_cost
Definition: plancache.h:128
#define Assert(condition)
Definition: c.h:733
const char * query_string
Definition: plancache.h:97
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition: mcxt.c:329
struct RawStmt * raw_parse_tree
Definition: plancache.h:96
MemoryContext query_context
Definition: plancache.h:113
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:209
List * query_list
Definition: plancache.h:108
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:37
#define copyObject(obj)
Definition: nodes.h:641
struct OverrideSearchPath * search_path
Definition: plancache.h:111

◆ CreateOneShotCachedPlan()

CachedPlanSource* CreateOneShotCachedPlan ( struct RawStmt raw_parse_tree,
const char *  query_string,
const char *  commandTag 
)

Definition at line 247 of file plancache.c.

References Assert, CACHEDPLANSOURCE_MAGIC, CachedPlanSource::commandTag, CachedPlanSource::context, CurrentMemoryContext, CachedPlanSource::cursor_options, CachedPlanSource::dependsOnRLS, CachedPlanSource::fixed_result, CachedPlanSource::generation, CachedPlanSource::generic_cost, CachedPlanSource::gplan, InvalidOid, CachedPlanSource::invalItems, CachedPlanSource::is_complete, CachedPlanSource::is_oneshot, CachedPlanSource::is_saved, CachedPlanSource::is_valid, CachedPlanSource::magic, NIL, CachedPlanSource::num_custom_plans, CachedPlanSource::num_params, palloc0(), CachedPlanSource::param_types, CachedPlanSource::parserSetup, CachedPlanSource::parserSetupArg, CachedPlanSource::query_context, CachedPlanSource::query_list, CachedPlanSource::query_string, CachedPlanSource::raw_parse_tree, CachedPlanSource::relationOids, CachedPlanSource::resultDesc, CachedPlanSource::rewriteRoleId, CachedPlanSource::rewriteRowSecurity, CachedPlanSource::search_path, and CachedPlanSource::total_custom_cost.

Referenced by _SPI_prepare_oneshot_plan().

250 {
251  CachedPlanSource *plansource;
252 
253  Assert(query_string != NULL); /* required as of 8.4 */
254 
255  /*
256  * Create and fill the CachedPlanSource struct within the caller's memory
257  * context. Most fields are just left empty for the moment.
258  */
259  plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
260  plansource->magic = CACHEDPLANSOURCE_MAGIC;
261  plansource->raw_parse_tree = raw_parse_tree;
262  plansource->query_string = query_string;
263  plansource->commandTag = commandTag;
264  plansource->param_types = NULL;
265  plansource->num_params = 0;
266  plansource->parserSetup = NULL;
267  plansource->parserSetupArg = NULL;
268  plansource->cursor_options = 0;
269  plansource->fixed_result = false;
270  plansource->resultDesc = NULL;
271  plansource->context = CurrentMemoryContext;
272  plansource->query_list = NIL;
273  plansource->relationOids = NIL;
274  plansource->invalItems = NIL;
275  plansource->search_path = NULL;
276  plansource->query_context = NULL;
277  plansource->rewriteRoleId = InvalidOid;
278  plansource->rewriteRowSecurity = false;
279  plansource->dependsOnRLS = false;
280  plansource->gplan = NULL;
281  plansource->is_oneshot = true;
282  plansource->is_complete = false;
283  plansource->is_saved = false;
284  plansource->is_valid = false;
285  plansource->generation = 0;
286  plansource->generic_cost = -1;
287  plansource->total_custom_cost = 0;
288  plansource->num_custom_plans = 0;
289 
290  return plansource;
291 }
MemoryContext context
Definition: plancache.h:106
#define NIL
Definition: pg_list.h:65
bool rewriteRowSecurity
Definition: plancache.h:115
const char * commandTag
Definition: plancache.h:98
double total_custom_cost
Definition: plancache.h:129
struct CachedPlan * gplan
Definition: plancache.h:118
TupleDesc resultDesc
Definition: plancache.h:105
List * invalItems
Definition: plancache.h:110
Oid * param_types
Definition: plancache.h:99
List * relationOids
Definition: plancache.h:109
void * parserSetupArg
Definition: plancache.h:102
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
ParserSetupHook parserSetup
Definition: plancache.h:101
void * palloc0(Size size)
Definition: mcxt.c:980
#define InvalidOid
Definition: postgres_ext.h:36
double generic_cost
Definition: plancache.h:128
#define Assert(condition)
Definition: c.h:733
const char * query_string
Definition: plancache.h:97
struct RawStmt * raw_parse_tree
Definition: plancache.h:96
MemoryContext query_context
Definition: plancache.h:113
List * query_list
Definition: plancache.h:108
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:37
struct OverrideSearchPath * search_path
Definition: plancache.h:111

◆ DropCachedPlan()

void DropCachedPlan ( CachedPlanSource plansource)

Definition at line 496 of file plancache.c.

References Assert, CACHEDPLANSOURCE_MAGIC, CachedPlanSource::context, dlist_delete(), CachedPlanSource::is_oneshot, CachedPlanSource::is_saved, CachedPlanSource::magic, MemoryContextDelete(), CachedPlanSource::node, and ReleaseGenericPlan().

Referenced by drop_unnamed_stmt(), DropAllPreparedStatements(), DropPreparedStatement(), and SPI_freeplan().

497 {
498  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
499 
500  /* If it's been saved, remove it from the list */
501  if (plansource->is_saved)
502  {
503  dlist_delete(&plansource->node);
504  plansource->is_saved = false;
505  }
506 
507  /* Decrement generic CachedPlan's refcount and drop if no longer needed */
508  ReleaseGenericPlan(plansource);
509 
510  /* Mark it no longer valid */
511  plansource->magic = 0;
512 
513  /*
514  * Remove the CachedPlanSource and all subsidiary data (including the
515  * query_context if any). But if it's a one-shot we can't free anything.
516  */
517  if (!plansource->is_oneshot)
518  MemoryContextDelete(plansource->context);
519 }
MemoryContext context
Definition: plancache.h:106
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
static void ReleaseGenericPlan(CachedPlanSource *plansource)
Definition: plancache.c:525
static void dlist_delete(dlist_node *node)
Definition: ilist.h:358
#define Assert(condition)
Definition: c.h:733
dlist_node node
Definition: plancache.h:126
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:37

◆ FreeCachedExpression()

void FreeCachedExpression ( CachedExpression cexpr)

Definition at line 1522 of file plancache.c.

References Assert, CACHEDEXPR_MAGIC, CachedExpression::context, dlist_delete(), CachedExpression::magic, MemoryContextDelete(), and CachedExpression::node.

Referenced by get_cast_hashentry().

1523 {
1524  /* Sanity check */
1525  Assert(cexpr->magic == CACHEDEXPR_MAGIC);
1526  /* Unlink from global list */
1527  dlist_delete(&cexpr->node);
1528  /* Free all storage associated with CachedExpression */
1529  MemoryContextDelete(cexpr->context);
1530 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
MemoryContext context
Definition: plancache.h:179
#define CACHEDEXPR_MAGIC
Definition: plancache.h:39
static void dlist_delete(dlist_node *node)
Definition: ilist.h:358
#define Assert(condition)
Definition: c.h:733
dlist_node node
Definition: plancache.h:180

◆ GetCachedExpression()

CachedExpression* GetCachedExpression ( Node expr)

Definition at line 1465 of file plancache.c.

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, CACHEDEXPR_MAGIC, CacheMemoryContext, CachedExpression::context, copyObject, CurrentMemoryContext, dlist_push_tail(), CachedExpression::expr, expression_planner_with_deps(), CachedExpression::invalItems, CachedExpression::is_valid, CachedExpression::magic, MemoryContextSetParent(), MemoryContextSwitchTo(), CachedExpression::node, palloc(), and CachedExpression::relationOids.

Referenced by get_cast_hashentry().

1466 {
1467  CachedExpression *cexpr;
1468  List *relationOids;
1469  List *invalItems;
1470  MemoryContext cexpr_context;
1471  MemoryContext oldcxt;
1472 
1473  /*
1474  * Pass the expression through the planner, and collect dependencies.
1475  * Everything built here is leaked in the caller's context; that's
1476  * intentional to minimize the size of the permanent data structure.
1477  */
1478  expr = (Node *) expression_planner_with_deps((Expr *) expr,
1479  &relationOids,
1480  &invalItems);
1481 
1482  /*
1483  * Make a private memory context, and copy what we need into that. To
1484  * avoid leaking a long-lived context if we fail while copying data, we
1485  * initially make the context under the caller's context.
1486  */
1488  "CachedExpression",
1490 
1491  oldcxt = MemoryContextSwitchTo(cexpr_context);
1492 
1493  cexpr = (CachedExpression *) palloc(sizeof(CachedExpression));
1494  cexpr->magic = CACHEDEXPR_MAGIC;
1495  cexpr->expr = copyObject(expr);
1496  cexpr->is_valid = true;
1497  cexpr->relationOids = copyObject(relationOids);
1498  cexpr->invalItems = copyObject(invalItems);
1499  cexpr->context = cexpr_context;
1500 
1501  MemoryContextSwitchTo(oldcxt);
1502 
1503  /*
1504  * Reparent the expr's memory context under CacheMemoryContext so that it
1505  * will live indefinitely.
1506  */
1508 
1509  /*
1510  * Add the entry to the global list of cached expressions.
1511  */
1513 
1514  return cexpr;
1515 }
#define AllocSetContextCreate
Definition: memutils.h:170
MemoryContext context
Definition: plancache.h:179
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:354
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:202
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:317
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:525
static dlist_head cached_expression_list
Definition: plancache.c:97
List * relationOids
Definition: plancache.h:177
List * invalItems
Definition: plancache.h:178
#define CACHEDEXPR_MAGIC
Definition: plancache.h:39
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
dlist_node node
Definition: plancache.h:180
Expr * expression_planner_with_deps(Expr *expr, List **relationOids, List **invalItems)
Definition: planner.c:6072
void * palloc(Size size)
Definition: mcxt.c:949
#define copyObject(obj)
Definition: nodes.h:641
Definition: pg_list.h:50
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ GetCachedPlan()

CachedPlan* GetCachedPlan ( CachedPlanSource plansource,
ParamListInfo  boundParams,
bool  useResOwner,
QueryEnvironment queryEnv 
)

Definition at line 1138 of file plancache.c.

References Assert, BuildCachedPlan(), cached_plan_cost(), CACHEDPLAN_MAGIC, CACHEDPLANSOURCE_MAGIC, CacheMemoryContext, CheckCachedPlan(), choose_custom_plan(), CachedPlanSource::context, CachedPlan::context, CurrentResourceOwner, elog, ERROR, CachedPlanSource::generic_cost, CachedPlanSource::gplan, CachedPlanSource::is_complete, CachedPlanSource::is_saved, CachedPlan::is_saved, CachedPlanSource::magic, CachedPlan::magic, MemoryContextGetParent(), MemoryContextSetParent(), NIL, CachedPlanSource::num_custom_plans, CachedPlan::refcount, ReleaseGenericPlan(), ResourceOwnerEnlargePlanCacheRefs(), ResourceOwnerRememberPlanCacheRef(), RevalidateCachedQuery(), and CachedPlanSource::total_custom_cost.

Referenced by _SPI_execute_plan(), exec_bind_message(), ExecuteQuery(), ExplainExecuteQuery(), SPI_cursor_open_internal(), and SPI_plan_get_cached_plan().

1140 {
1141  CachedPlan *plan = NULL;
1142  List *qlist;
1143  bool customplan;
1144 
1145  /* Assert caller is doing things in a sane order */
1146  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1147  Assert(plansource->is_complete);
1148  /* This seems worth a real test, though */
1149  if (useResOwner && !plansource->is_saved)
1150  elog(ERROR, "cannot apply ResourceOwner to non-saved cached plan");
1151 
1152  /* Make sure the querytree list is valid and we have parse-time locks */
1153  qlist = RevalidateCachedQuery(plansource, queryEnv);
1154 
1155  /* Decide whether to use a custom plan */
1156  customplan = choose_custom_plan(plansource, boundParams);
1157 
1158  if (!customplan)
1159  {
1160  if (CheckCachedPlan(plansource))
1161  {
1162  /* We want a generic plan, and we already have a valid one */
1163  plan = plansource->gplan;
1164  Assert(plan->magic == CACHEDPLAN_MAGIC);
1165  }
1166  else
1167  {
1168  /* Build a new generic plan */
1169  plan = BuildCachedPlan(plansource, qlist, NULL, queryEnv);
1170  /* Just make real sure plansource->gplan is clear */
1171  ReleaseGenericPlan(plansource);
1172  /* Link the new generic plan into the plansource */
1173  plansource->gplan = plan;
1174  plan->refcount++;
1175  /* Immediately reparent into appropriate context */
1176  if (plansource->is_saved)
1177  {
1178  /* saved plans all live under CacheMemoryContext */
1180  plan->is_saved = true;
1181  }
1182  else
1183  {
1184  /* otherwise, it should be a sibling of the plansource */
1186  MemoryContextGetParent(plansource->context));
1187  }
1188  /* Update generic_cost whenever we make a new generic plan */
1189  plansource->generic_cost = cached_plan_cost(plan, false);
1190 
1191  /*
1192  * If, based on the now-known value of generic_cost, we'd not have
1193  * chosen to use a generic plan, then forget it and make a custom
1194  * plan. This is a bit of a wart but is necessary to avoid a
1195  * glitch in behavior when the custom plans are consistently big
1196  * winners; at some point we'll experiment with a generic plan and
1197  * find it's a loser, but we don't want to actually execute that
1198  * plan.
1199  */
1200  customplan = choose_custom_plan(plansource, boundParams);
1201 
1202  /*
1203  * If we choose to plan again, we need to re-copy the query_list,
1204  * since the planner probably scribbled on it. We can force
1205  * BuildCachedPlan to do that by passing NIL.
1206  */
1207  qlist = NIL;
1208  }
1209  }
1210 
1211  if (customplan)
1212  {
1213  /* Build a custom plan */
1214  plan = BuildCachedPlan(plansource, qlist, boundParams, queryEnv);
1215  /* Accumulate total costs of custom plans, but 'ware overflow */
1216  if (plansource->num_custom_plans < INT_MAX)
1217  {
1218  plansource->total_custom_cost += cached_plan_cost(plan, true);
1219  plansource->num_custom_plans++;
1220  }
1221  }
1222 
1223  Assert(plan != NULL);
1224 
1225  /* Flag the plan as in use by caller */
1226  if (useResOwner)
1228  plan->refcount++;
1229  if (useResOwner)
1231 
1232  /*
1233  * Saved plans should be under CacheMemoryContext so they will not go away
1234  * until their reference count goes to zero. In the generic-plan cases we
1235  * already took care of that, but for a custom plan, do it as soon as we
1236  * have created a reference-counted link.
1237  */
1238  if (customplan && plansource->is_saved)
1239  {
1241  plan->is_saved = true;
1242  }
1243 
1244  return plan;
1245 }
#define CACHEDPLAN_MAGIC
Definition: plancache.h:38
MemoryContext context
Definition: plancache.h:106
static CachedPlan * BuildCachedPlan(CachedPlanSource *plansource, List *qlist, ParamListInfo boundParams, QueryEnvironment *queryEnv)
Definition: plancache.c:877
#define NIL
Definition: pg_list.h:65
static void ReleaseGenericPlan(CachedPlanSource *plansource)
Definition: plancache.c:525
MemoryContext MemoryContextGetParent(MemoryContext context)
Definition: mcxt.c:439
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:354
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
int refcount
Definition: plancache.h:155
void ResourceOwnerRememberPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
Definition: resowner.c:1108
void ResourceOwnerEnlargePlanCacheRefs(ResourceOwner owner)
Definition: resowner.c:1097
MemoryContext context
Definition: plancache.h:156
double total_custom_cost
Definition: plancache.h:129
struct CachedPlan * gplan
Definition: plancache.h:118
#define ERROR
Definition: elog.h:43
static List * RevalidateCachedQuery(CachedPlanSource *plansource, QueryEnvironment *queryEnv)
Definition: plancache.c:553
bool is_saved
Definition: plancache.h:148
double generic_cost
Definition: plancache.h:128
#define Assert(condition)
Definition: c.h:733
static bool CheckCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:793
#define elog(elevel,...)
Definition: elog.h:228
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:37
Definition: pg_list.h:50
static bool choose_custom_plan(CachedPlanSource *plansource, ParamListInfo boundParams)
Definition: plancache.c:1016
MemoryContext CacheMemoryContext
Definition: mcxt.c:47
static double cached_plan_cost(CachedPlan *plan, bool include_planner)
Definition: plancache.c:1073

◆ InitPlanCache()

void InitPlanCache ( void  )

Definition at line 127 of file plancache.c.

References AMOPOPID, CacheRegisterRelcacheCallback(), CacheRegisterSyscacheCallback(), FOREIGNDATAWRAPPEROID, FOREIGNSERVEROID, NAMESPACEOID, OPEROID, PlanCacheObjectCallback(), PlanCacheRelCallback(), PlanCacheSysCallback(), PROCOID, and TYPEOID.

Referenced by InitPostgres().

128 {
137 }
static void PlanCacheObjectCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: plancache.c:1848
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1468
static void PlanCacheRelCallback(Datum arg, Oid relid)
Definition: plancache.c:1764
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1426
uintptr_t Datum
Definition: postgres.h:367
static void PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: plancache.c:1957

◆ ReleaseCachedPlan()

void ReleaseCachedPlan ( CachedPlan plan,
bool  useResOwner 
)

Definition at line 1259 of file plancache.c.

References Assert, CACHEDPLAN_MAGIC, CachedPlan::context, CurrentResourceOwner, CachedPlan::is_oneshot, CachedPlan::is_saved, CachedPlan::magic, MemoryContextDelete(), CachedPlan::refcount, and ResourceOwnerForgetPlanCacheRef().

Referenced by _SPI_execute_plan(), exec_eval_simple_expr(), exec_simple_check_plan(), ExplainExecuteQuery(), PortalReleaseCachedPlan(), ReleaseGenericPlan(), ResourceOwnerReleaseInternal(), and SPI_cursor_open_internal().

1260 {
1261  Assert(plan->magic == CACHEDPLAN_MAGIC);
1262  if (useResOwner)
1263  {
1264  Assert(plan->is_saved);
1266  }
1267  Assert(plan->refcount > 0);
1268  plan->refcount--;
1269  if (plan->refcount == 0)
1270  {
1271  /* Mark it no longer valid */
1272  plan->magic = 0;
1273 
1274  /* One-shot plans do not own their context, so we can't free them */
1275  if (!plan->is_oneshot)
1277  }
1278 }
#define CACHEDPLAN_MAGIC
Definition: plancache.h:38
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
int refcount
Definition: plancache.h:155
MemoryContext context
Definition: plancache.h:156
void ResourceOwnerForgetPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
Definition: resowner.c:1117
bool is_saved
Definition: plancache.h:148
#define Assert(condition)
Definition: c.h:733
bool is_oneshot
Definition: plancache.h:147

◆ ResetPlanCache()

void ResetPlanCache ( void  )

Definition at line 1966 of file plancache.c.

References Assert, CACHEDEXPR_MAGIC, CACHEDPLANSOURCE_MAGIC, CMD_UTILITY, Query::commandType, dlist_iter::cur, dlist_container, dlist_foreach, CachedPlanSource::gplan, CachedPlanSource::is_valid, CachedPlan::is_valid, CachedExpression::is_valid, IsTransactionStmtPlan, lfirst_node, CachedPlanSource::magic, CachedExpression::magic, CachedPlanSource::query_list, UtilityContainsQuery(), and Query::utilityStmt.

Referenced by assign_session_replication_role(), DiscardAll(), DiscardCommand(), and PlanCacheSysCallback().

1967 {
1968  dlist_iter iter;
1969 
1971  {
1973  node, iter.cur);
1974  ListCell *lc;
1975 
1976  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1977 
1978  /* No work if it's already invalidated */
1979  if (!plansource->is_valid)
1980  continue;
1981 
1982  /*
1983  * We *must not* mark transaction control statements as invalid,
1984  * particularly not ROLLBACK, because they may need to be executed in
1985  * aborted transactions when we can't revalidate them (cf bug #5269).
1986  */
1987  if (IsTransactionStmtPlan(plansource))
1988  continue;
1989 
1990  /*
1991  * In general there is no point in invalidating utility statements
1992  * since they have no plans anyway. So invalidate it only if it
1993  * contains at least one non-utility statement, or contains a utility
1994  * statement that contains a pre-analyzed query (which could have
1995  * dependencies.)
1996  */
1997  foreach(lc, plansource->query_list)
1998  {
1999  Query *query = lfirst_node(Query, lc);
2000 
2001  if (query->commandType != CMD_UTILITY ||
2003  {
2004  /* non-utility statement, so invalidate */
2005  plansource->is_valid = false;
2006  if (plansource->gplan)
2007  plansource->gplan->is_valid = false;
2008  /* no need to look further */
2009  break;
2010  }
2011  }
2012  }
2013 
2014  /* Likewise invalidate cached expressions */
2016  {
2018  node, iter.cur);
2019 
2020  Assert(cexpr->magic == CACHEDEXPR_MAGIC);
2021 
2022  cexpr->is_valid = false;
2023  }
2024 }
bool is_valid
Definition: plancache.h:149
#define dlist_foreach(iter, lhead)
Definition: ilist.h:507
Node * utilityStmt
Definition: parsenodes.h:120
static dlist_head cached_expression_list
Definition: plancache.c:97
struct CachedPlan * gplan
Definition: plancache.h:118
Query * UtilityContainsQuery(Node *parsetree)
Definition: utility.c:1907
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
#define lfirst_node(type, lc)
Definition: pg_list.h:193
#define CACHEDEXPR_MAGIC
Definition: plancache.h:39
static dlist_head saved_plan_list
Definition: plancache.c:92
dlist_node * cur
Definition: ilist.h:161
CmdType commandType
Definition: parsenodes.h:112
#define Assert(condition)
Definition: c.h:733
List * query_list
Definition: plancache.h:108
#define IsTransactionStmtPlan(plansource)
Definition: plancache.c:82
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:37

◆ SaveCachedPlan()

void SaveCachedPlan ( CachedPlanSource plansource)

Definition at line 452 of file plancache.c.

References Assert, CACHEDPLANSOURCE_MAGIC, CacheMemoryContext, CachedPlanSource::context, dlist_push_tail(), elog, ERROR, CachedPlanSource::is_complete, CachedPlanSource::is_oneshot, CachedPlanSource::is_saved, CachedPlanSource::magic, MemoryContextSetParent(), CachedPlanSource::node, and ReleaseGenericPlan().

Referenced by _SPI_save_plan(), exec_parse_message(), SPI_keepplan(), and StorePreparedStatement().

453 {
454  /* Assert caller is doing things in a sane order */
455  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
456  Assert(plansource->is_complete);
457  Assert(!plansource->is_saved);
458 
459  /* This seems worth a real test, though */
460  if (plansource->is_oneshot)
461  elog(ERROR, "cannot save one-shot cached plan");
462 
463  /*
464  * In typical use, this function would be called before generating any
465  * plans from the CachedPlanSource. If there is a generic plan, moving it
466  * into CacheMemoryContext would be pretty risky since it's unclear
467  * whether the caller has taken suitable care with making references
468  * long-lived. Best thing to do seems to be to discard the plan.
469  */
470  ReleaseGenericPlan(plansource);
471 
472  /*
473  * Reparent the source memory context under CacheMemoryContext so that it
474  * will live indefinitely. The query_context follows along since it's
475  * already a child of the other one.
476  */
478 
479  /*
480  * Add the entry to the global list of cached plans.
481  */
482  dlist_push_tail(&saved_plan_list, &plansource->node);
483 
484  plansource->is_saved = true;
485 }
MemoryContext context
Definition: plancache.h:106
static void ReleaseGenericPlan(CachedPlanSource *plansource)
Definition: plancache.c:525
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:354
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:317
#define ERROR
Definition: elog.h:43
static dlist_head saved_plan_list
Definition: plancache.c:92
#define Assert(condition)
Definition: c.h:733
dlist_node node
Definition: plancache.h:126
#define elog(elevel,...)
Definition: elog.h:228
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:37
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

Variable Documentation

◆ plan_cache_mode

int plan_cache_mode

Definition at line 119 of file plancache.c.

Referenced by choose_custom_plan().