summaryrefslogtreecommitdiffstats
path: root/src/include/utils/plancache.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/utils/plancache.h')
-rw-r--r--src/include/utils/plancache.h235
1 files changed, 235 insertions, 0 deletions
diff --git a/src/include/utils/plancache.h b/src/include/utils/plancache.h
new file mode 100644
index 0000000..522020d
--- /dev/null
+++ b/src/include/utils/plancache.h
@@ -0,0 +1,235 @@
+/*-------------------------------------------------------------------------
+ *
+ * plancache.h
+ * Plan cache definitions.
+ *
+ * See plancache.c for comments.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/plancache.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PLANCACHE_H
+#define PLANCACHE_H
+
+#include "access/tupdesc.h"
+#include "lib/ilist.h"
+#include "nodes/params.h"
+#include "tcop/cmdtag.h"
+#include "utils/queryenvironment.h"
+#include "utils/resowner.h"
+
+
+/* Forward declaration, to avoid including parsenodes.h here */
+struct RawStmt;
+
+/* possible values for plan_cache_mode */
+typedef enum
+{
+ PLAN_CACHE_MODE_AUTO,
+ PLAN_CACHE_MODE_FORCE_GENERIC_PLAN,
+ PLAN_CACHE_MODE_FORCE_CUSTOM_PLAN
+} PlanCacheMode;
+
+/* GUC parameter */
+extern int plan_cache_mode;
+
+#define CACHEDPLANSOURCE_MAGIC 195726186
+#define CACHEDPLAN_MAGIC 953717834
+#define CACHEDEXPR_MAGIC 838275847
+
+/*
+ * CachedPlanSource (which might better have been called CachedQuery)
+ * represents a SQL query that we expect to use multiple times. It stores
+ * the query source text, the raw parse tree, and the analyzed-and-rewritten
+ * query tree, as well as adjunct data. Cache invalidation can happen as a
+ * result of DDL affecting objects used by the query. In that case we discard
+ * the analyzed-and-rewritten query tree, and rebuild it when next needed.
+ *
+ * An actual execution plan, represented by CachedPlan, is derived from the
+ * CachedPlanSource when we need to execute the query. The plan could be
+ * either generic (usable with any set of plan parameters) or custom (for a
+ * specific set of parameters). plancache.c contains the logic that decides
+ * which way to do it for any particular execution. If we are using a generic
+ * cached plan then it is meant to be re-used across multiple executions, so
+ * callers must always treat CachedPlans as read-only.
+ *
+ * Once successfully built and "saved", CachedPlanSources typically live
+ * for the life of the backend, although they can be dropped explicitly.
+ * CachedPlans are reference-counted and go away automatically when the last
+ * reference is dropped. A CachedPlan can outlive the CachedPlanSource it
+ * was created from.
+ *
+ * An "unsaved" CachedPlanSource can be used for generating plans, but it
+ * lives in transient storage and will not be updated in response to sinval
+ * events.
+ *
+ * CachedPlans made from saved CachedPlanSources are likewise in permanent
+ * storage, so to avoid memory leaks, the reference-counted references to them
+ * must be held in permanent data structures or ResourceOwners. CachedPlans
+ * made from unsaved CachedPlanSources are in children of the caller's
+ * memory context, so references to them should not be longer-lived than
+ * that context. (Reference counting is somewhat pro forma in that case,
+ * though it may be useful if the CachedPlan can be discarded early.)
+ *
+ * A CachedPlanSource has two associated memory contexts: one that holds the
+ * struct itself, the query source text and the raw parse tree, and another
+ * context that holds the rewritten query tree and associated data. This
+ * allows the query tree to be discarded easily when it is invalidated.
+ *
+ * Some callers wish to use the CachedPlan API even with one-shot queries
+ * that have no reason to be saved at all. We therefore support a "oneshot"
+ * variant that does no data copying or invalidation checking. In this case
+ * there are no separate memory contexts: the CachedPlanSource struct and
+ * all subsidiary data live in the caller's CurrentMemoryContext, and there
+ * is no way to free memory short of clearing that entire context. A oneshot
+ * plan is always treated as unsaved.
+ *
+ * Note: the string referenced by commandTag is not subsidiary storage;
+ * it is assumed to be a compile-time-constant string. As with portals,
+ * commandTag shall be NULL if and only if the original query string (before
+ * rewriting) was an empty string.
+ */
+typedef struct CachedPlanSource
+{
+ int magic; /* should equal CACHEDPLANSOURCE_MAGIC */
+ struct RawStmt *raw_parse_tree; /* output of raw_parser(), or NULL */
+ const char *query_string; /* source text of query */
+ CommandTag commandTag; /* 'nuff said */
+ Oid *param_types; /* array of parameter type OIDs, or NULL */
+ int num_params; /* length of param_types array */
+ ParserSetupHook parserSetup; /* alternative parameter spec method */
+ void *parserSetupArg;
+ int cursor_options; /* cursor options used for planning */
+ bool fixed_result; /* disallow change in result tupdesc? */
+ TupleDesc resultDesc; /* result type; NULL = doesn't return tuples */
+ MemoryContext context; /* memory context holding all above */
+ /* These fields describe the current analyzed-and-rewritten query tree: */
+ List *query_list; /* list of Query nodes, or NIL if not valid */
+ List *relationOids; /* OIDs of relations the queries depend on */
+ List *invalItems; /* other dependencies, as PlanInvalItems */
+ struct OverrideSearchPath *search_path; /* search_path used for parsing
+ * and planning */
+ MemoryContext query_context; /* context holding the above, or NULL */
+ Oid rewriteRoleId; /* Role ID we did rewriting for */
+ bool rewriteRowSecurity; /* row_security used during rewrite */
+ bool dependsOnRLS; /* is rewritten query specific to the above? */
+ /* If we have a generic plan, this is a reference-counted link to it: */
+ struct CachedPlan *gplan; /* generic plan, or NULL if not valid */
+ /* Some state flags: */
+ bool is_oneshot; /* is it a "oneshot" plan? */
+ bool is_complete; /* has CompleteCachedPlan been done? */
+ bool is_saved; /* has CachedPlanSource been "saved"? */
+ bool is_valid; /* is the query_list currently valid? */
+ int generation; /* increments each time we create a plan */
+ /* If CachedPlanSource has been saved, it is a member of a global list */
+ dlist_node node; /* list link, if is_saved */
+ /* State kept to help decide whether to use custom or generic plans: */
+ double generic_cost; /* cost of generic plan, or -1 if not known */
+ double total_custom_cost; /* total cost of custom plans so far */
+ int num_custom_plans; /* number of plans included in total */
+} CachedPlanSource;
+
+/*
+ * CachedPlan represents an execution plan derived from a CachedPlanSource.
+ * The reference count includes both the link from the parent CachedPlanSource
+ * (if any), and any active plan executions, so the plan can be discarded
+ * exactly when refcount goes to zero. Both the struct itself and the
+ * subsidiary data live in the context denoted by the context field.
+ * This makes it easy to free a no-longer-needed cached plan. (However,
+ * if is_oneshot is true, the context does not belong solely to the CachedPlan
+ * so no freeing is possible.)
+ */
+typedef struct CachedPlan
+{
+ int magic; /* should equal CACHEDPLAN_MAGIC */
+ List *stmt_list; /* list of PlannedStmts */
+ bool is_oneshot; /* is it a "oneshot" plan? */
+ bool is_saved; /* is CachedPlan in a long-lived context? */
+ bool is_valid; /* is the stmt_list currently valid? */
+ Oid planRoleId; /* Role ID the plan was created for */
+ bool dependsOnRole; /* is plan specific to that role? */
+ TransactionId saved_xmin; /* if valid, replan when TransactionXmin
+ * changes from this value */
+ int generation; /* parent's generation number for this plan */
+ int refcount; /* count of live references to this struct */
+ MemoryContext context; /* context containing this CachedPlan */
+} CachedPlan;
+
+/*
+ * CachedExpression is a low-overhead mechanism for caching the planned form
+ * of standalone scalar expressions. While such expressions are not usually
+ * subject to cache invalidation events, that can happen, for example because
+ * of replacement of a SQL function that was inlined into the expression.
+ * The plancache takes care of storing the expression tree and marking it
+ * invalid if a cache invalidation occurs, but the caller must notice the
+ * !is_valid status and discard the obsolete expression without reusing it.
+ * We do not store the original parse tree, only the planned expression;
+ * this is an optimization based on the assumption that we usually will not
+ * need to replan for the life of the session.
+ */
+typedef struct CachedExpression
+{
+ int magic; /* should equal CACHEDEXPR_MAGIC */
+ Node *expr; /* planned form of expression */
+ bool is_valid; /* is the expression still valid? */
+ /* remaining fields should be treated as private to plancache.c: */
+ List *relationOids; /* OIDs of relations the expr depends on */
+ List *invalItems; /* other dependencies, as PlanInvalItems */
+ MemoryContext context; /* context containing this CachedExpression */
+ dlist_node node; /* link in global list of CachedExpressions */
+} CachedExpression;
+
+
+extern void InitPlanCache(void);
+extern void ResetPlanCache(void);
+
+extern CachedPlanSource *CreateCachedPlan(struct RawStmt *raw_parse_tree,
+ const char *query_string,
+ CommandTag commandTag);
+extern CachedPlanSource *CreateOneShotCachedPlan(struct RawStmt *raw_parse_tree,
+ const char *query_string,
+ CommandTag commandTag);
+extern 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);
+
+extern void SaveCachedPlan(CachedPlanSource *plansource);
+extern void DropCachedPlan(CachedPlanSource *plansource);
+
+extern void CachedPlanSetParentContext(CachedPlanSource *plansource,
+ MemoryContext newcontext);
+
+extern CachedPlanSource *CopyCachedPlan(CachedPlanSource *plansource);
+
+extern bool CachedPlanIsValid(CachedPlanSource *plansource);
+
+extern List *CachedPlanGetTargetList(CachedPlanSource *plansource,
+ QueryEnvironment *queryEnv);
+
+extern CachedPlan *GetCachedPlan(CachedPlanSource *plansource,
+ ParamListInfo boundParams,
+ bool useResOwner,
+ QueryEnvironment *queryEnv);
+extern void ReleaseCachedPlan(CachedPlan *plan, bool useResOwner);
+
+extern bool CachedPlanAllowsSimpleValidityCheck(CachedPlanSource *plansource,
+ CachedPlan *plan,
+ ResourceOwner owner);
+extern bool CachedPlanIsSimplyValid(CachedPlanSource *plansource,
+ CachedPlan *plan,
+ ResourceOwner owner);
+
+extern CachedExpression *GetCachedExpression(Node *expr);
+extern void FreeCachedExpression(CachedExpression *cexpr);
+
+#endif /* PLANCACHE_H */