PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
plancache.h File Reference
#include "access/tupdesc.h"
#include "nodes/params.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
 

Macros

#define CACHEDPLANSOURCE_MAGIC   195726186
 
#define CACHEDPLAN_MAGIC   953717834
 

Typedefs

typedef struct CachedPlanSource CachedPlanSource
 
typedef struct CachedPlan CachedPlan
 

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)
 
CachedPlanGetCachedPlan (CachedPlanSource *plansource, ParamListInfo boundParams, bool useResOwner)
 
void ReleaseCachedPlan (CachedPlan *plan, bool useResOwner)
 

Macro Definition Documentation

#define CACHEDPLAN_MAGIC   953717834

Typedef Documentation

Function Documentation

List* CachedPlanGetTargetList ( CachedPlanSource plansource)

Definition at line 1421 of file plancache.c.

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

Referenced by exec_describe_statement_message(), and FetchPreparedStatementTargetList().

1422 {
1423  Query *pstmt;
1424 
1425  /* Assert caller is doing things in a sane order */
1426  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1427  Assert(plansource->is_complete);
1428 
1429  /*
1430  * No work needed if statement doesn't return tuples (we assume this
1431  * feature cannot be changed by an invalidation)
1432  */
1433  if (plansource->resultDesc == NULL)
1434  return NIL;
1435 
1436  /* Make sure the querytree list is valid and we have parse-time locks */
1437  RevalidateCachedQuery(plansource);
1438 
1439  /* Get the primary statement and find out what it returns */
1440  pstmt = QueryListGetPrimaryStmt(plansource->query_list);
1441 
1442  return FetchStatementTargetList((Node *) pstmt);
1443 }
#define NIL
Definition: pg_list.h:69
Definition: nodes.h:508
TupleDesc resultDesc
Definition: plancache.h:91
List * FetchStatementTargetList(Node *stmt)
Definition: pquery.c:352
static Query * QueryListGetPrimaryStmt(List *stmts)
Definition: plancache.c:1454
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
List * query_list
Definition: plancache.h:94
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:24
static List * RevalidateCachedQuery(CachedPlanSource *plansource)
Definition: plancache.c:556
bool CachedPlanIsValid ( CachedPlanSource plansource)

Definition at line 1408 of file plancache.c.

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

Referenced by SPI_plan_is_valid().

1409 {
1410  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1411  return plansource->is_valid;
1412 }
#define Assert(condition)
Definition: c.h:670
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:24
void CachedPlanSetParentContext ( CachedPlanSource plansource,
MemoryContext  newcontext 
)

Definition at line 1280 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().

1282 {
1283  /* Assert caller is doing things in a sane order */
1284  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1285  Assert(plansource->is_complete);
1286 
1287  /* These seem worth real tests, though */
1288  if (plansource->is_saved)
1289  elog(ERROR, "cannot move a saved cached plan to another context");
1290  if (plansource->is_oneshot)
1291  elog(ERROR, "cannot move a one-shot cached plan to another context");
1292 
1293  /* OK, let the caller keep the plan where he wishes */
1294  MemoryContextSetParent(plansource->context, newcontext);
1295 
1296  /*
1297  * The query_context needs no special handling, since it's a child of
1298  * plansource->context. But if there's a generic plan, it should be
1299  * maintained as a sibling of plansource->context.
1300  */
1301  if (plansource->gplan)
1302  {
1303  Assert(plansource->gplan->magic == CACHEDPLAN_MAGIC);
1304  MemoryContextSetParent(plansource->gplan->context, newcontext);
1305  }
1306 }
#define CACHEDPLAN_MAGIC
Definition: plancache.h:25
MemoryContext context
Definition: plancache.h:92
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:317
MemoryContext context
Definition: plancache.h:142
struct CachedPlan * gplan
Definition: plancache.h:104
#define ERROR
Definition: elog.h:43
#define Assert(condition)
Definition: c.h:670
#define elog
Definition: elog.h:219
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:24
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 324 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(), NULL, 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().

333 {
334  MemoryContext source_context = plansource->context;
336 
337  /* Assert caller is doing things in a sane order */
338  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
339  Assert(!plansource->is_complete);
340 
341  /*
342  * If caller supplied a querytree_context, reparent it underneath the
343  * CachedPlanSource's context; otherwise, create a suitable context and
344  * copy the querytree_list into it. But no data copying should be done
345  * for one-shot plans; for those, assume the passed querytree_list is
346  * sufficiently long-lived.
347  */
348  if (plansource->is_oneshot)
349  {
350  querytree_context = CurrentMemoryContext;
351  }
352  else if (querytree_context != NULL)
353  {
354  MemoryContextSetParent(querytree_context, source_context);
355  MemoryContextSwitchTo(querytree_context);
356  }
357  else
358  {
359  /* Again, it's a good bet the querytree_context can be small */
360  querytree_context = AllocSetContextCreate(source_context,
361  "CachedPlanQuery",
363  MemoryContextSwitchTo(querytree_context);
364  querytree_list = (List *) copyObject(querytree_list);
365  }
366 
367  plansource->query_context = querytree_context;
368  plansource->query_list = querytree_list;
369 
370  if (!plansource->is_oneshot && !IsTransactionStmtPlan(plansource))
371  {
372  /*
373  * Use the planner machinery to extract dependencies. Data is saved
374  * in query_context. (We assume that not a lot of extra cruft is
375  * created by this call.) We can skip this for one-shot plans, and
376  * transaction control commands have no such dependencies anyway.
377  */
378  extract_query_dependencies((Node *) querytree_list,
379  &plansource->relationOids,
380  &plansource->invalItems,
381  &plansource->dependsOnRLS);
382 
383  /* Update RLS info as well. */
384  plansource->rewriteRoleId = GetUserId();
385  plansource->rewriteRowSecurity = row_security;
386 
387  /*
388  * Also save the current search_path in the query_context. (This
389  * should not generate much extra cruft either, since almost certainly
390  * the path is already valid.) Again, we don't really need this for
391  * one-shot plans; and we *must* skip this for transaction control
392  * commands, because this could result in catalog accesses.
393  */
394  plansource->search_path = GetOverrideSearchPath(querytree_context);
395  }
396 
397  /*
398  * Save the final parameter types (or other parameter specification data)
399  * into the source_context, as well as our other parameters. Also save
400  * the result tuple descriptor.
401  */
402  MemoryContextSwitchTo(source_context);
403 
404  if (num_params > 0)
405  {
406  plansource->param_types = (Oid *) palloc(num_params * sizeof(Oid));
407  memcpy(plansource->param_types, param_types, num_params * sizeof(Oid));
408  }
409  else
410  plansource->param_types = NULL;
411  plansource->num_params = num_params;
412  plansource->parserSetup = parserSetup;
413  plansource->parserSetupArg = parserSetupArg;
414  plansource->cursor_options = cursor_options;
415  plansource->fixed_result = fixed_result;
416  plansource->resultDesc = PlanCacheComputeResultDesc(querytree_list);
417 
418  MemoryContextSwitchTo(oldcxt);
419 
420  plansource->is_complete = true;
421  plansource->is_valid = true;
422 }
MemoryContext context
Definition: plancache.h:92
bool rewriteRowSecurity
Definition: plancache.h:101
Oid GetUserId(void)
Definition: miscinit.c:283
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:317
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:508
unsigned int Oid
Definition: postgres_ext.h:31
TupleDesc resultDesc
Definition: plancache.h:91
void * copyObject(const void *from)
Definition: copyfuncs.c:4475
List * invalItems
Definition: plancache.h:96
OverrideSearchPath * GetOverrideSearchPath(MemoryContext context)
Definition: namespace.c:3115
Oid * param_types
Definition: plancache.h:85
List * relationOids
Definition: plancache.h:95
void * parserSetupArg
Definition: plancache.h:88
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
ParserSetupHook parserSetup
Definition: plancache.h:87
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
#define NULL
Definition: c.h:226
bool row_security
Definition: guc.c:448
#define Assert(condition)
Definition: c.h:670
void extract_query_dependencies(Node *query, List **relationOids, List **invalItems, bool *hasRowSecurity)
Definition: setrefs.c:2477
void * palloc(Size size)
Definition: mcxt.c:891
MemoryContext query_context
Definition: plancache.h:99
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:162
List * query_list
Definition: plancache.h:94
#define IsTransactionStmtPlan(plansource)
Definition: plancache.c:78
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:24
Definition: pg_list.h:45
static TupleDesc PlanCacheComputeResultDesc(List *stmt_list)
Definition: plancache.c:1665
struct OverrideSearchPath * search_path
Definition: plancache.h:97
CachedPlanSource* CopyCachedPlan ( CachedPlanSource plansource)

Definition at line 1318 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, MemoryContextSwitchTo(), CachedPlanSource::next_saved, NULL, 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().

1319 {
1320  CachedPlanSource *newsource;
1321  MemoryContext source_context;
1322  MemoryContext querytree_context;
1323  MemoryContext oldcxt;
1324 
1325  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1326  Assert(plansource->is_complete);
1327 
1328  /*
1329  * One-shot plans can't be copied, because we haven't taken care that
1330  * parsing/planning didn't scribble on the raw parse tree or querytrees.
1331  */
1332  if (plansource->is_oneshot)
1333  elog(ERROR, "cannot copy a one-shot cached plan");
1334 
1336  "CachedPlanSource",
1338 
1339  oldcxt = MemoryContextSwitchTo(source_context);
1340 
1341  newsource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
1342  newsource->magic = CACHEDPLANSOURCE_MAGIC;
1343  newsource->raw_parse_tree = copyObject(plansource->raw_parse_tree);
1344  newsource->query_string = pstrdup(plansource->query_string);
1345  newsource->commandTag = plansource->commandTag;
1346  if (plansource->num_params > 0)
1347  {
1348  newsource->param_types = (Oid *)
1349  palloc(plansource->num_params * sizeof(Oid));
1350  memcpy(newsource->param_types, plansource->param_types,
1351  plansource->num_params * sizeof(Oid));
1352  }
1353  else
1354  newsource->param_types = NULL;
1355  newsource->num_params = plansource->num_params;
1356  newsource->parserSetup = plansource->parserSetup;
1357  newsource->parserSetupArg = plansource->parserSetupArg;
1358  newsource->cursor_options = plansource->cursor_options;
1359  newsource->fixed_result = plansource->fixed_result;
1360  if (plansource->resultDesc)
1361  newsource->resultDesc = CreateTupleDescCopy(plansource->resultDesc);
1362  else
1363  newsource->resultDesc = NULL;
1364  newsource->context = source_context;
1365 
1366  querytree_context = AllocSetContextCreate(source_context,
1367  "CachedPlanQuery",
1369  MemoryContextSwitchTo(querytree_context);
1370  newsource->query_list = (List *) copyObject(plansource->query_list);
1371  newsource->relationOids = (List *) copyObject(plansource->relationOids);
1372  newsource->invalItems = (List *) copyObject(plansource->invalItems);
1373  if (plansource->search_path)
1374  newsource->search_path = CopyOverrideSearchPath(plansource->search_path);
1375  newsource->query_context = querytree_context;
1376  newsource->rewriteRoleId = plansource->rewriteRoleId;
1377  newsource->rewriteRowSecurity = plansource->rewriteRowSecurity;
1378  newsource->dependsOnRLS = plansource->dependsOnRLS;
1379 
1380  newsource->gplan = NULL;
1381 
1382  newsource->is_oneshot = false;
1383  newsource->is_complete = true;
1384  newsource->is_saved = false;
1385  newsource->is_valid = plansource->is_valid;
1386  newsource->generation = plansource->generation;
1387  newsource->next_saved = NULL;
1388 
1389  /* We may as well copy any acquired cost knowledge */
1390  newsource->generic_cost = plansource->generic_cost;
1391  newsource->total_custom_cost = plansource->total_custom_cost;
1392  newsource->num_custom_plans = plansource->num_custom_plans;
1393 
1394  MemoryContextSwitchTo(oldcxt);
1395 
1396  return newsource;
1397 }
MemoryContext context
Definition: plancache.h:92
bool rewriteRowSecurity
Definition: plancache.h:101
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:141
const char * commandTag
Definition: plancache.h:84
char * pstrdup(const char *in)
Definition: mcxt.c:1165
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned int Oid
Definition: postgres_ext.h:31
double total_custom_cost
Definition: plancache.h:115
struct CachedPlan * gplan
Definition: plancache.h:104
TupleDesc resultDesc
Definition: plancache.h:91
void * copyObject(const void *from)
Definition: copyfuncs.c:4475
struct CachedPlanSource * next_saved
Definition: plancache.h:112
#define ERROR
Definition: elog.h:43
OverrideSearchPath * CopyOverrideSearchPath(OverrideSearchPath *path)
Definition: namespace.c:3151
List * invalItems
Definition: plancache.h:96
Oid * param_types
Definition: plancache.h:85
List * relationOids
Definition: plancache.h:95
void * parserSetupArg
Definition: plancache.h:88
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
ParserSetupHook parserSetup
Definition: plancache.h:87
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
void * palloc0(Size size)
Definition: mcxt.c:920
#define NULL
Definition: c.h:226
double generic_cost
Definition: plancache.h:114
#define Assert(condition)
Definition: c.h:670
const char * query_string
Definition: plancache.h:83
struct RawStmt * raw_parse_tree
Definition: plancache.h:82
void * palloc(Size size)
Definition: mcxt.c:891
MemoryContext query_context
Definition: plancache.h:99
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:162
List * query_list
Definition: plancache.h:94
#define elog
Definition: elog.h:219
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:24
Definition: pg_list.h:45
struct OverrideSearchPath * search_path
Definition: plancache.h:97
CachedPlanSource* CreateCachedPlan ( struct RawStmt raw_parse_tree,
const char *  query_string,
const char *  commandTag 
)

Definition at line 151 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, MemoryContextSwitchTo(), CachedPlanSource::next_saved, NIL, NULL, 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().

154 {
155  CachedPlanSource *plansource;
156  MemoryContext source_context;
157  MemoryContext oldcxt;
158 
159  Assert(query_string != NULL); /* required as of 8.4 */
160 
161  /*
162  * Make a dedicated memory context for the CachedPlanSource and its
163  * permanent subsidiary data. It's probably not going to be large, but
164  * just in case, allow it to grow large. Initially it's a child of the
165  * caller's context (which we assume to be transient), so that it will be
166  * cleaned up on error.
167  */
169  "CachedPlanSource",
171 
172  /*
173  * Create and fill the CachedPlanSource struct within the new context.
174  * Most fields are just left empty for the moment.
175  */
176  oldcxt = MemoryContextSwitchTo(source_context);
177 
178  plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
179  plansource->magic = CACHEDPLANSOURCE_MAGIC;
180  plansource->raw_parse_tree = copyObject(raw_parse_tree);
181  plansource->query_string = pstrdup(query_string);
182  plansource->commandTag = commandTag;
183  plansource->param_types = NULL;
184  plansource->num_params = 0;
185  plansource->parserSetup = NULL;
186  plansource->parserSetupArg = NULL;
187  plansource->cursor_options = 0;
188  plansource->fixed_result = false;
189  plansource->resultDesc = NULL;
190  plansource->context = source_context;
191  plansource->query_list = NIL;
192  plansource->relationOids = NIL;
193  plansource->invalItems = NIL;
194  plansource->search_path = NULL;
195  plansource->query_context = NULL;
196  plansource->rewriteRoleId = InvalidOid;
197  plansource->rewriteRowSecurity = false;
198  plansource->dependsOnRLS = false;
199  plansource->gplan = NULL;
200  plansource->is_oneshot = false;
201  plansource->is_complete = false;
202  plansource->is_saved = false;
203  plansource->is_valid = false;
204  plansource->generation = 0;
205  plansource->next_saved = NULL;
206  plansource->generic_cost = -1;
207  plansource->total_custom_cost = 0;
208  plansource->num_custom_plans = 0;
209 
210  MemoryContextSwitchTo(oldcxt);
211 
212  return plansource;
213 }
MemoryContext context
Definition: plancache.h:92
#define NIL
Definition: pg_list.h:69
bool rewriteRowSecurity
Definition: plancache.h:101
const char * commandTag
Definition: plancache.h:84
char * pstrdup(const char *in)
Definition: mcxt.c:1165
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
double total_custom_cost
Definition: plancache.h:115
struct CachedPlan * gplan
Definition: plancache.h:104
TupleDesc resultDesc
Definition: plancache.h:91
void * copyObject(const void *from)
Definition: copyfuncs.c:4475
struct CachedPlanSource * next_saved
Definition: plancache.h:112
List * invalItems
Definition: plancache.h:96
Oid * param_types
Definition: plancache.h:85
List * relationOids
Definition: plancache.h:95
void * parserSetupArg
Definition: plancache.h:88
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
ParserSetupHook parserSetup
Definition: plancache.h:87
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
void * palloc0(Size size)
Definition: mcxt.c:920
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:226
double generic_cost
Definition: plancache.h:114
#define Assert(condition)
Definition: c.h:670
const char * query_string
Definition: plancache.h:83
struct RawStmt * raw_parse_tree
Definition: plancache.h:82
MemoryContext query_context
Definition: plancache.h:99
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:162
List * query_list
Definition: plancache.h:94
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:24
struct OverrideSearchPath * search_path
Definition: plancache.h:97
CachedPlanSource* CreateOneShotCachedPlan ( struct RawStmt raw_parse_tree,
const char *  query_string,
const char *  commandTag 
)

Definition at line 234 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, CachedPlanSource::next_saved, NIL, NULL, 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().

237 {
238  CachedPlanSource *plansource;
239 
240  Assert(query_string != NULL); /* required as of 8.4 */
241 
242  /*
243  * Create and fill the CachedPlanSource struct within the caller's memory
244  * context. Most fields are just left empty for the moment.
245  */
246  plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
247  plansource->magic = CACHEDPLANSOURCE_MAGIC;
248  plansource->raw_parse_tree = raw_parse_tree;
249  plansource->query_string = query_string;
250  plansource->commandTag = commandTag;
251  plansource->param_types = NULL;
252  plansource->num_params = 0;
253  plansource->parserSetup = NULL;
254  plansource->parserSetupArg = NULL;
255  plansource->cursor_options = 0;
256  plansource->fixed_result = false;
257  plansource->resultDesc = NULL;
258  plansource->context = CurrentMemoryContext;
259  plansource->query_list = NIL;
260  plansource->relationOids = NIL;
261  plansource->invalItems = NIL;
262  plansource->search_path = NULL;
263  plansource->query_context = NULL;
264  plansource->rewriteRoleId = InvalidOid;
265  plansource->rewriteRowSecurity = false;
266  plansource->dependsOnRLS = false;
267  plansource->gplan = NULL;
268  plansource->is_oneshot = true;
269  plansource->is_complete = false;
270  plansource->is_saved = false;
271  plansource->is_valid = false;
272  plansource->generation = 0;
273  plansource->next_saved = NULL;
274  plansource->generic_cost = -1;
275  plansource->total_custom_cost = 0;
276  plansource->num_custom_plans = 0;
277 
278  return plansource;
279 }
MemoryContext context
Definition: plancache.h:92
#define NIL
Definition: pg_list.h:69
bool rewriteRowSecurity
Definition: plancache.h:101
const char * commandTag
Definition: plancache.h:84
double total_custom_cost
Definition: plancache.h:115
struct CachedPlan * gplan
Definition: plancache.h:104
TupleDesc resultDesc
Definition: plancache.h:91
struct CachedPlanSource * next_saved
Definition: plancache.h:112
List * invalItems
Definition: plancache.h:96
Oid * param_types
Definition: plancache.h:85
List * relationOids
Definition: plancache.h:95
void * parserSetupArg
Definition: plancache.h:88
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
ParserSetupHook parserSetup
Definition: plancache.h:87
void * palloc0(Size size)
Definition: mcxt.c:920
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:226
double generic_cost
Definition: plancache.h:114
#define Assert(condition)
Definition: c.h:670
const char * query_string
Definition: plancache.h:83
struct RawStmt * raw_parse_tree
Definition: plancache.h:82
MemoryContext query_context
Definition: plancache.h:99
List * query_list
Definition: plancache.h:94
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:24
struct OverrideSearchPath * search_path
Definition: plancache.h:97
void DropCachedPlan ( CachedPlanSource plansource)

Definition at line 485 of file plancache.c.

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

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

486 {
487  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
488 
489  /* If it's been saved, remove it from the list */
490  if (plansource->is_saved)
491  {
492  if (first_saved_plan == plansource)
493  first_saved_plan = plansource->next_saved;
494  else
495  {
496  CachedPlanSource *psrc;
497 
498  for (psrc = first_saved_plan; psrc; psrc = psrc->next_saved)
499  {
500  if (psrc->next_saved == plansource)
501  {
502  psrc->next_saved = plansource->next_saved;
503  break;
504  }
505  }
506  }
507  plansource->is_saved = false;
508  }
509 
510  /* Decrement generic CachePlan's refcount and drop if no longer needed */
511  ReleaseGenericPlan(plansource);
512 
513  /* Mark it no longer valid */
514  plansource->magic = 0;
515 
516  /*
517  * Remove the CachedPlanSource and all subsidiary data (including the
518  * query_context if any). But if it's a one-shot we can't free anything.
519  */
520  if (!plansource->is_oneshot)
521  MemoryContextDelete(plansource->context);
522 }
MemoryContext context
Definition: plancache.h:92
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
static void ReleaseGenericPlan(CachedPlanSource *plansource)
Definition: plancache.c:528
struct CachedPlanSource * next_saved
Definition: plancache.h:112
static CachedPlanSource * first_saved_plan
Definition: plancache.c:88
#define Assert(condition)
Definition: c.h:670
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:24
CachedPlan* GetCachedPlan ( CachedPlanSource plansource,
ParamListInfo  boundParams,
bool  useResOwner 
)

Definition at line 1131 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, NULL, 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().

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

Definition at line 115 of file plancache.c.

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

Referenced by InitPostgres().

116 {
124 }
static void PlanCacheFuncCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: plancache.c:1766
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1403
static void PlanCacheRelCallback(Datum arg, Oid relid)
Definition: plancache.c:1701
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1379
uintptr_t Datum
Definition: postgres.h:374
static void PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: plancache.c:1845
void ReleaseCachedPlan ( CachedPlan plan,
bool  useResOwner 
)

Definition at line 1252 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().

1253 {
1254  Assert(plan->magic == CACHEDPLAN_MAGIC);
1255  if (useResOwner)
1256  {
1257  Assert(plan->is_saved);
1259  }
1260  Assert(plan->refcount > 0);
1261  plan->refcount--;
1262  if (plan->refcount == 0)
1263  {
1264  /* Mark it no longer valid */
1265  plan->magic = 0;
1266 
1267  /* One-shot plans do not own their context, so we can't free them */
1268  if (!plan->is_oneshot)
1270  }
1271 }
#define CACHEDPLAN_MAGIC
Definition: plancache.h:25
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
int refcount
Definition: plancache.h:141
MemoryContext context
Definition: plancache.h:142
void ResourceOwnerForgetPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
Definition: resowner.c:1073
bool is_saved
Definition: plancache.h:134
#define Assert(condition)
Definition: c.h:670
bool is_oneshot
Definition: plancache.h:133
void ResetPlanCache ( void  )

Definition at line 1854 of file plancache.c.

References Assert, CACHEDPLANSOURCE_MAGIC, castNode, CMD_UTILITY, Query::commandType, CachedPlanSource::gplan, CachedPlanSource::is_valid, CachedPlan::is_valid, IsTransactionStmtPlan, lfirst, CachedPlanSource::magic, CachedPlanSource::next_saved, CachedPlanSource::query_list, UtilityContainsQuery(), and Query::utilityStmt.

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

1855 {
1856  CachedPlanSource *plansource;
1857 
1858  for (plansource = first_saved_plan; plansource; plansource = plansource->next_saved)
1859  {
1860  ListCell *lc;
1861 
1862  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1863 
1864  /* No work if it's already invalidated */
1865  if (!plansource->is_valid)
1866  continue;
1867 
1868  /*
1869  * We *must not* mark transaction control statements as invalid,
1870  * particularly not ROLLBACK, because they may need to be executed in
1871  * aborted transactions when we can't revalidate them (cf bug #5269).
1872  */
1873  if (IsTransactionStmtPlan(plansource))
1874  continue;
1875 
1876  /*
1877  * In general there is no point in invalidating utility statements
1878  * since they have no plans anyway. So invalidate it only if it
1879  * contains at least one non-utility statement, or contains a utility
1880  * statement that contains a pre-analyzed query (which could have
1881  * dependencies.)
1882  */
1883  foreach(lc, plansource->query_list)
1884  {
1885  Query *query = castNode(Query, lfirst(lc));
1886 
1887  if (query->commandType != CMD_UTILITY ||
1889  {
1890  /* non-utility statement, so invalidate */
1891  plansource->is_valid = false;
1892  if (plansource->gplan)
1893  plansource->gplan->is_valid = false;
1894  /* no need to look further */
1895  break;
1896  }
1897  }
1898  }
1899 }
bool is_valid
Definition: plancache.h:135
#define castNode(_type_, nodeptr)
Definition: nodes.h:577
Node * utilityStmt
Definition: parsenodes.h:111
struct CachedPlan * gplan
Definition: plancache.h:104
Query * UtilityContainsQuery(Node *parsetree)
Definition: utility.c:1835
struct CachedPlanSource * next_saved
Definition: plancache.h:112
static CachedPlanSource * first_saved_plan
Definition: plancache.c:88
CmdType commandType
Definition: parsenodes.h:103
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
List * query_list
Definition: plancache.h:94
#define IsTransactionStmtPlan(plansource)
Definition: plancache.c:78
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:24
void SaveCachedPlan ( CachedPlanSource plansource)

Definition at line 440 of file plancache.c.

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

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

441 {
442  /* Assert caller is doing things in a sane order */
443  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
444  Assert(plansource->is_complete);
445  Assert(!plansource->is_saved);
446 
447  /* This seems worth a real test, though */
448  if (plansource->is_oneshot)
449  elog(ERROR, "cannot save one-shot cached plan");
450 
451  /*
452  * In typical use, this function would be called before generating any
453  * plans from the CachedPlanSource. If there is a generic plan, moving it
454  * into CacheMemoryContext would be pretty risky since it's unclear
455  * whether the caller has taken suitable care with making references
456  * long-lived. Best thing to do seems to be to discard the plan.
457  */
458  ReleaseGenericPlan(plansource);
459 
460  /*
461  * Reparent the source memory context under CacheMemoryContext so that it
462  * will live indefinitely. The query_context follows along since it's
463  * already a child of the other one.
464  */
466 
467  /*
468  * Add the entry to the global list of cached plans.
469  */
470  plansource->next_saved = first_saved_plan;
471  first_saved_plan = plansource;
472 
473  plansource->is_saved = true;
474 }
MemoryContext context
Definition: plancache.h:92
static void ReleaseGenericPlan(CachedPlanSource *plansource)
Definition: plancache.c:528
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:317
struct CachedPlanSource * next_saved
Definition: plancache.h:112
#define ERROR
Definition: elog.h:43
static CachedPlanSource * first_saved_plan
Definition: plancache.c:88
#define Assert(condition)
Definition: c.h:670
#define elog
Definition: elog.h:219
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:24
MemoryContext CacheMemoryContext
Definition: mcxt.c:46