aboutsummaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorKevin Grittner <kgrittn@postgresql.org>2017-03-31 23:17:18 -0500
committerKevin Grittner <kgrittn@postgresql.org>2017-03-31 23:17:18 -0500
commit18ce3a4ab22d2984f8540ab480979c851dae5338 (patch)
treeff63f19ee776dfe26c675abacb8558bb60c5b0b6 /src/include
parent25dc142a49c60c3107480c487cd8444dc83f9bdf (diff)
downloadpostgresql-18ce3a4ab22d2984f8540ab480979c851dae5338.tar.gz
postgresql-18ce3a4ab22d2984f8540ab480979c851dae5338.zip
Add infrastructure to support EphemeralNamedRelation references.
A QueryEnvironment concept is added, which allows new types of objects to be passed into queries from parsing on through execution. At this point, the only thing implemented is a collection of EphemeralNamedRelation objects -- relations which can be referenced by name in queries, but do not exist in the catalogs. The only type of ENR implemented is NamedTuplestore, but provision is made to add more types fairly easily. An ENR can carry its own TupleDesc or reference a relation in the catalogs by relid. Although these features can be used without SPI, convenience functions are added to SPI so that ENRs can easily be used by code run through SPI. The initial use of all this is going to be transition tables in AFTER triggers, but that will be added to each PL as a separate commit. An incidental effect of this patch is to produce a more informative error message if an attempt is made to modify the contents of a CTE from a referencing DML statement. No tests previously covered that possibility, so one is added. Kevin Grittner and Thomas Munro Reviewed by Heikki Linnakangas, David Fetter, and Thomas Munro with valuable comments and suggestions from many others
Diffstat (limited to 'src/include')
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/commands/createas.h3
-rw-r--r--src/include/commands/explain.h9
-rw-r--r--src/include/commands/prepare.h4
-rw-r--r--src/include/executor/execdesc.h2
-rw-r--r--src/include/executor/nodeNamedtuplestorescan.h24
-rw-r--r--src/include/executor/spi.h7
-rw-r--r--src/include/executor/spi_priv.h2
-rw-r--r--src/include/nodes/execnodes.h21
-rw-r--r--src/include/nodes/nodes.h2
-rw-r--r--src/include/nodes/parsenodes.h6
-rw-r--r--src/include/nodes/plannodes.h10
-rw-r--r--src/include/optimizer/cost.h3
-rw-r--r--src/include/optimizer/pathnode.h2
-rw-r--r--src/include/parser/analyze.h2
-rw-r--r--src/include/parser/parse_enr.h22
-rw-r--r--src/include/parser/parse_node.h3
-rw-r--r--src/include/parser/parse_relation.h4
-rw-r--r--src/include/tcop/tcopprot.h7
-rw-r--r--src/include/tcop/utility.h5
-rw-r--r--src/include/utils/plancache.h10
-rw-r--r--src/include/utils/portal.h1
-rw-r--r--src/include/utils/queryenvironment.h74
-rw-r--r--src/include/utils/tuplestore.h2
24 files changed, 211 insertions, 16 deletions
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index d067b757b0f..48c5a570a08 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201703311
+#define CATALOG_VERSION_NO 201703312
#endif
diff --git a/src/include/commands/createas.h b/src/include/commands/createas.h
index 7b78cc4a13a..0fb9990e043 100644
--- a/src/include/commands/createas.h
+++ b/src/include/commands/createas.h
@@ -18,10 +18,11 @@
#include "nodes/params.h"
#include "nodes/parsenodes.h"
#include "tcop/dest.h"
+#include "utils/queryenvironment.h"
extern ObjectAddress ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString,
- ParamListInfo params, char *completionTag);
+ ParamListInfo params, QueryEnvironment *queryEnv, char *completionTag);
extern int GetIntoRelEFlags(IntoClause *intoClause);
diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h
index 9191e186c15..b77f81db97e 100644
--- a/src/include/commands/explain.h
+++ b/src/include/commands/explain.h
@@ -62,19 +62,20 @@ extern PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook;
extern void ExplainQuery(ParseState *pstate, ExplainStmt *stmt, const char *queryString,
- ParamListInfo params, DestReceiver *dest);
+ ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest);
extern ExplainState *NewExplainState(void);
extern TupleDesc ExplainResultDesc(ExplainStmt *stmt);
extern void ExplainOneUtility(Node *utilityStmt, IntoClause *into,
- ExplainState *es,
- const char *queryString, ParamListInfo params);
+ ExplainState *es, const char *queryString,
+ ParamListInfo params, QueryEnvironment *queryEnv);
extern void ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into,
ExplainState *es, const char *queryString,
- ParamListInfo params, const instr_time *planduration);
+ ParamListInfo params, QueryEnvironment *queryEnv,
+ const instr_time *planduration);
extern void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc);
extern void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc);
diff --git a/src/include/commands/prepare.h b/src/include/commands/prepare.h
index d8d22edbbcd..c60e6f30b88 100644
--- a/src/include/commands/prepare.h
+++ b/src/include/commands/prepare.h
@@ -42,8 +42,8 @@ extern void ExecuteQuery(ExecuteStmt *stmt, IntoClause *intoClause,
DestReceiver *dest, char *completionTag);
extern void DeallocateQuery(DeallocateStmt *stmt);
extern void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into,
- ExplainState *es,
- const char *queryString, ParamListInfo params);
+ ExplainState *es, const char *queryString,
+ ParamListInfo params, QueryEnvironment *queryEnv);
/* Low-level access to stored prepared statements */
extern void StorePreparedStatement(const char *stmt_name,
diff --git a/src/include/executor/execdesc.h b/src/include/executor/execdesc.h
index 87e7ca85082..37de6f20113 100644
--- a/src/include/executor/execdesc.h
+++ b/src/include/executor/execdesc.h
@@ -40,6 +40,7 @@ typedef struct QueryDesc
Snapshot crosscheck_snapshot; /* crosscheck for RI update/delete */
DestReceiver *dest; /* the destination for tuple output */
ParamListInfo params; /* param values being passed in */
+ QueryEnvironment *queryEnv; /* query environment passed in */
int instrument_options; /* OR of InstrumentOption flags */
/* These fields are set by ExecutorStart */
@@ -61,6 +62,7 @@ extern QueryDesc *CreateQueryDesc(PlannedStmt *plannedstmt,
Snapshot crosscheck_snapshot,
DestReceiver *dest,
ParamListInfo params,
+ QueryEnvironment *queryEnv,
int instrument_options);
extern void FreeQueryDesc(QueryDesc *qdesc);
diff --git a/src/include/executor/nodeNamedtuplestorescan.h b/src/include/executor/nodeNamedtuplestorescan.h
new file mode 100644
index 00000000000..9ef477e7ff2
--- /dev/null
+++ b/src/include/executor/nodeNamedtuplestorescan.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeNamedtuplestorescan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeNamedtuplestorescan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODENAMEDTUPLESTORESCAN_H
+#define NODENAMEDTUPLESTORESCAN_H
+
+#include "nodes/execnodes.h"
+
+extern NamedTuplestoreScanState *ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflags);
+extern TupleTableSlot *ExecNamedTuplestoreScan(NamedTuplestoreScanState *node);
+extern void ExecEndNamedTuplestoreScan(NamedTuplestoreScanState *node);
+extern void ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState *node);
+
+#endif /* NODENAMEDTUPLESTORESCAN_H */
diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h
index a18ae63245d..e2e8bb95539 100644
--- a/src/include/executor/spi.h
+++ b/src/include/executor/spi.h
@@ -43,6 +43,8 @@ typedef struct _SPI_plan *SPIPlanPtr;
#define SPI_ERROR_NOATTRIBUTE (-9)
#define SPI_ERROR_NOOUTFUNC (-10)
#define SPI_ERROR_TYPUNKNOWN (-11)
+#define SPI_ERROR_REL_DUPLICATE (-12)
+#define SPI_ERROR_REL_NOT_FOUND (-13)
#define SPI_OK_CONNECT 1
#define SPI_OK_FINISH 2
@@ -58,6 +60,8 @@ typedef struct _SPI_plan *SPIPlanPtr;
#define SPI_OK_DELETE_RETURNING 12
#define SPI_OK_UPDATE_RETURNING 13
#define SPI_OK_REWRITTEN 14
+#define SPI_OK_REL_REGISTER 15
+#define SPI_OK_REL_UNREGISTER 16
/* These used to be functions, now just no-ops for backwards compatibility */
#define SPI_push() ((void) 0)
@@ -146,6 +150,9 @@ extern void SPI_scroll_cursor_fetch(Portal, FetchDirection direction, long count
extern void SPI_scroll_cursor_move(Portal, FetchDirection direction, long count);
extern void SPI_cursor_close(Portal portal);
+extern int SPI_register_relation(EphemeralNamedRelation enr);
+extern int SPI_unregister_relation(const char *name);
+
extern void AtEOXact_SPI(bool isCommit);
extern void AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid);
diff --git a/src/include/executor/spi_priv.h b/src/include/executor/spi_priv.h
index db8b59c3874..49aa7c94e79 100644
--- a/src/include/executor/spi_priv.h
+++ b/src/include/executor/spi_priv.h
@@ -14,6 +14,7 @@
#define SPI_PRIV_H
#include "executor/spi.h"
+#include "utils/queryenvironment.h"
#define _SPI_PLAN_MAGIC 569278163
@@ -31,6 +32,7 @@ typedef struct
MemoryContext execCxt; /* executor context */
MemoryContext savedcxt; /* context of SPI_connect's caller */
SubTransactionId connectSubid; /* ID of connecting subtransaction */
+ QueryEnvironment *queryEnv; /* query environment setup for SPI level */
} _SPI_connection;
/*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 11a68500eea..fa992449f47 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -22,6 +22,7 @@
#include "nodes/params.h"
#include "nodes/plannodes.h"
#include "utils/hsearch.h"
+#include "utils/queryenvironment.h"
#include "utils/reltrigger.h"
#include "utils/sortsupport.h"
#include "utils/tuplestore.h"
@@ -431,6 +432,8 @@ typedef struct EState
ParamListInfo es_param_list_info; /* values of external params */
ParamExecData *es_param_exec_vals; /* values of internal params */
+ QueryEnvironment *es_queryEnv; /* query environment */
+
/* Other working state: */
MemoryContext es_query_cxt; /* per-query context in which EState lives */
@@ -1446,6 +1449,24 @@ typedef struct CteScanState
} CteScanState;
/* ----------------
+ * NamedTuplestoreScanState information
+ *
+ * NamedTuplestoreScan nodes are used to scan a Tuplestore created and
+ * named prior to execution of the query. An example is a transition
+ * table for an AFTER trigger.
+ *
+ * Multiple NamedTuplestoreScan nodes can read out from the same Tuplestore.
+ * ----------------
+ */
+typedef struct NamedTuplestoreScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ int readptr; /* index of my tuplestore read pointer */
+ TupleDesc tupdesc; /* format of the tuples in the tuplestore */
+ Tuplestorestate *relation; /* the rows */
+} NamedTuplestoreScanState;
+
+/* ----------------
* WorkTableScanState information
*
* WorkTableScan nodes are used to scan the work table created by
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 963ce45ae33..177853b3bf9 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -63,6 +63,7 @@ typedef enum NodeTag
T_ValuesScan,
T_TableFuncScan,
T_CteScan,
+ T_NamedTuplestoreScan,
T_WorkTableScan,
T_ForeignScan,
T_CustomScan,
@@ -114,6 +115,7 @@ typedef enum NodeTag
T_TableFuncScanState,
T_ValuesScanState,
T_CteScanState,
+ T_NamedTuplestoreScanState,
T_WorkTableScanState,
T_ForeignScanState,
T_CustomScanState,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 3a71dd5b37d..b2afd508180 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -906,7 +906,8 @@ typedef enum RTEKind
RTE_FUNCTION, /* function in FROM */
RTE_TABLEFUNC, /* TableFunc(.., column list) */
RTE_VALUES, /* VALUES (<exprlist>), (<exprlist>), ... */
- RTE_CTE /* common table expr (WITH list element) */
+ RTE_CTE, /* common table expr (WITH list element) */
+ RTE_NAMEDTUPLESTORE /* tuplestore, e.g. for AFTER triggers */
} RTEKind;
typedef struct RangeTblEntry
@@ -993,6 +994,9 @@ typedef struct RangeTblEntry
List *coltypmods; /* integer list of column typmods */
List *colcollations; /* OID list of column collation OIDs */
+ char *enrname; /* name of ephemeral named relation */
+ double enrtuples; /* estimated or actual from caller */
+
/*
* Fields valid in all RTEs:
*/
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 6e531b62386..a2dd26f8a9c 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -528,6 +528,16 @@ typedef struct CteScan
} CteScan;
/* ----------------
+ * NamedTuplestoreScan node
+ * ----------------
+ */
+typedef struct NamedTuplestoreScan
+{
+ Scan scan;
+ char *enrname; /* Name given to Ephemeral Named Relation */
+} NamedTuplestoreScan;
+
+/* ----------------
* WorkTableScan node
* ----------------
*/
diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h
index d9a9b12a06c..6909359bcff 100644
--- a/src/include/optimizer/cost.h
+++ b/src/include/optimizer/cost.h
@@ -98,6 +98,8 @@ extern void cost_tablefuncscan(Path *path, PlannerInfo *root,
RelOptInfo *baserel, ParamPathInfo *param_info);
extern void cost_ctescan(Path *path, PlannerInfo *root,
RelOptInfo *baserel, ParamPathInfo *param_info);
+extern void cost_namedtuplestorescan(Path *path, PlannerInfo *root,
+ RelOptInfo *baserel, ParamPathInfo *param_info);
extern void cost_recursive_union(Path *runion, Path *nrterm, Path *rterm);
extern void cost_sort(Path *path, PlannerInfo *root,
List *pathkeys, Cost input_cost, double tuples, int width,
@@ -187,6 +189,7 @@ extern void set_values_size_estimates(PlannerInfo *root, RelOptInfo *rel);
extern void set_cte_size_estimates(PlannerInfo *root, RelOptInfo *rel,
double cte_rows);
extern void set_tablefunc_size_estimates(PlannerInfo *root, RelOptInfo *rel);
+extern void set_namedtuplestore_size_estimates(PlannerInfo *root, RelOptInfo *rel);
extern void set_foreign_size_estimates(PlannerInfo *root, RelOptInfo *rel);
extern PathTarget *set_pathtarget_cost_width(PlannerInfo *root, PathTarget *target);
extern double compute_bitmap_pages(PlannerInfo *root, RelOptInfo *baserel,
diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h
index c72c7e02cbb..82d4e8701c8 100644
--- a/src/include/optimizer/pathnode.h
+++ b/src/include/optimizer/pathnode.h
@@ -100,6 +100,8 @@ extern Path *create_tablefuncscan_path(PlannerInfo *root, RelOptInfo *rel,
Relids required_outer);
extern Path *create_ctescan_path(PlannerInfo *root, RelOptInfo *rel,
Relids required_outer);
+extern Path *create_namedtuplestorescan_path(PlannerInfo *root, RelOptInfo *rel,
+ Relids required_outer);
extern Path *create_worktablescan_path(PlannerInfo *root, RelOptInfo *rel,
Relids required_outer);
extern ForeignPath *create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel,
diff --git a/src/include/parser/analyze.h b/src/include/parser/analyze.h
index 17259409a72..9b33ba5dfd1 100644
--- a/src/include/parser/analyze.h
+++ b/src/include/parser/analyze.h
@@ -23,7 +23,7 @@ extern PGDLLIMPORT post_parse_analyze_hook_type post_parse_analyze_hook;
extern Query *parse_analyze(RawStmt *parseTree, const char *sourceText,
- Oid *paramTypes, int numParams);
+ Oid *paramTypes, int numParams, QueryEnvironment *queryEnv);
extern Query *parse_analyze_varparams(RawStmt *parseTree, const char *sourceText,
Oid **paramTypes, int *numParams);
diff --git a/src/include/parser/parse_enr.h b/src/include/parser/parse_enr.h
new file mode 100644
index 00000000000..48a7576f2c2
--- /dev/null
+++ b/src/include/parser/parse_enr.h
@@ -0,0 +1,22 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_enr.h
+ * Internal definitions for parser
+ *
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/parse_enr.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_ENR_H
+#define PARSE_ENR_H
+
+#include "parser/parse_node.h"
+
+extern bool name_matches_visible_ENR(ParseState *pstate, const char *refname);
+extern EphemeralNamedRelationMetadata get_visible_ENR(ParseState *pstate, const char *refname);
+
+#endif /* PARSE_ENR_H */
diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h
index 3a25d9598d6..1035bad322c 100644
--- a/src/include/parser/parse_node.h
+++ b/src/include/parser/parse_node.h
@@ -15,6 +15,7 @@
#define PARSE_NODE_H
#include "nodes/parsenodes.h"
+#include "utils/queryenvironment.h"
#include "utils/relcache.h"
@@ -188,6 +189,8 @@ struct ParseState
bool p_resolve_unknowns; /* resolve unknown-type SELECT outputs
* as type text */
+ QueryEnvironment *p_queryEnv; /* curr env, incl refs to enclosing env */
+
/* Flags telling about things found in the query: */
bool p_hasAggs;
bool p_hasWindowFuncs;
diff --git a/src/include/parser/parse_relation.h b/src/include/parser/parse_relation.h
index 515c06cfef6..2f42cc8ef07 100644
--- a/src/include/parser/parse_relation.h
+++ b/src/include/parser/parse_relation.h
@@ -42,6 +42,7 @@ extern RangeTblEntry *refnameRangeTblEntry(ParseState *pstate,
extern CommonTableExpr *scanNameSpaceForCTE(ParseState *pstate,
const char *refname,
Index *ctelevelsup);
+extern bool scanNameSpaceForENR(ParseState *pstate, const char *refname);
extern void checkNameSpaceConflicts(ParseState *pstate, List *namespace1,
List *namespace2);
extern int RTERangeTablePosn(ParseState *pstate,
@@ -107,6 +108,9 @@ extern RangeTblEntry *addRangeTableEntryForCTE(ParseState *pstate,
Index levelsup,
RangeVar *rv,
bool inFromCl);
+extern RangeTblEntry *addRangeTableEntryForENR(ParseState *pstate,
+ RangeVar *rv,
+ bool inFromCl);
extern bool isLockedRefname(ParseState *pstate, const char *refname);
extern void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte,
bool addToJoinList,
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index 1958be85b72..f1a34a1c724 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -24,6 +24,7 @@
#include "nodes/plannodes.h"
#include "storage/procsignal.h"
#include "utils/guc.h"
+#include "utils/queryenvironment.h"
/* Required daylight between max_stack_depth and the kernel limit, in bytes */
@@ -49,11 +50,13 @@ extern int log_statement;
extern List *pg_parse_query(const char *query_string);
extern List *pg_analyze_and_rewrite(RawStmt *parsetree,
const char *query_string,
- Oid *paramTypes, int numParams);
+ Oid *paramTypes, int numParams,
+ QueryEnvironment *queryEnv);
extern List *pg_analyze_and_rewrite_params(RawStmt *parsetree,
const char *query_string,
ParserSetupHook parserSetup,
- void *parserSetupArg);
+ void *parserSetupArg,
+ QueryEnvironment *queryEnv);
extern PlannedStmt *pg_plan_query(Query *querytree, int cursorOptions,
ParamListInfo boundParams);
extern List *pg_plan_queries(List *querytrees, int cursorOptions,
diff --git a/src/include/tcop/utility.h b/src/include/tcop/utility.h
index 4f8d3539001..90f1215aec8 100644
--- a/src/include/tcop/utility.h
+++ b/src/include/tcop/utility.h
@@ -26,15 +26,18 @@ typedef enum
/* Hook for plugins to get control in ProcessUtility() */
typedef void (*ProcessUtility_hook_type) (PlannedStmt *pstmt,
const char *queryString, ProcessUtilityContext context,
- ParamListInfo params,
+ ParamListInfo params,
+ QueryEnvironment *queryEnv,
DestReceiver *dest, char *completionTag);
extern PGDLLIMPORT ProcessUtility_hook_type ProcessUtility_hook;
extern void ProcessUtility(PlannedStmt *pstmt, const char *queryString,
ProcessUtilityContext context, ParamListInfo params,
+ QueryEnvironment *queryEnv,
DestReceiver *dest, char *completionTag);
extern void standard_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
ProcessUtilityContext context, ParamListInfo params,
+ QueryEnvironment *queryEnv,
DestReceiver *dest, char *completionTag);
extern bool UtilityReturnsTuples(Node *parsetree);
diff --git a/src/include/utils/plancache.h b/src/include/utils/plancache.h
index 84952d56e70..48d4ac94b2a 100644
--- a/src/include/utils/plancache.h
+++ b/src/include/utils/plancache.h
@@ -17,6 +17,7 @@
#include "access/tupdesc.h"
#include "nodes/params.h"
+#include "utils/queryenvironment.h"
/* Forward declaration, to avoid including parsenodes.h here */
struct RawStmt;
@@ -148,7 +149,8 @@ extern void ResetPlanCache(void);
extern CachedPlanSource *CreateCachedPlan(struct RawStmt *raw_parse_tree,
const char *query_string,
- const char *commandTag);
+ const char *commandTag,
+ QueryEnvironment *queryEnv);
extern CachedPlanSource *CreateOneShotCachedPlan(struct RawStmt *raw_parse_tree,
const char *query_string,
const char *commandTag);
@@ -172,11 +174,13 @@ extern CachedPlanSource *CopyCachedPlan(CachedPlanSource *plansource);
extern bool CachedPlanIsValid(CachedPlanSource *plansource);
-extern List *CachedPlanGetTargetList(CachedPlanSource *plansource);
+extern List *CachedPlanGetTargetList(CachedPlanSource *plansource,
+ QueryEnvironment *queryEnv);
extern CachedPlan *GetCachedPlan(CachedPlanSource *plansource,
ParamListInfo boundParams,
- bool useResOwner);
+ bool useResOwner,
+ QueryEnvironment *queryEnv);
extern void ReleaseCachedPlan(CachedPlan *plan, bool useResOwner);
#endif /* PLANCACHE_H */
diff --git a/src/include/utils/portal.h b/src/include/utils/portal.h
index e7c5a8bd091..ef3898c98cb 100644
--- a/src/include/utils/portal.h
+++ b/src/include/utils/portal.h
@@ -137,6 +137,7 @@ typedef struct PortalData
CachedPlan *cplan; /* CachedPlan, if stmts are from one */
ParamListInfo portalParams; /* params to pass to query */
+ QueryEnvironment *queryEnv; /* environment for query */
/* Features/options */
PortalStrategy strategy; /* see above */
diff --git a/src/include/utils/queryenvironment.h b/src/include/utils/queryenvironment.h
new file mode 100644
index 00000000000..b4f65a19768
--- /dev/null
+++ b/src/include/utils/queryenvironment.h
@@ -0,0 +1,74 @@
+/*-------------------------------------------------------------------------
+ *
+ * queryenvironment.h
+ * Access to functions to mutate the query environment and retrieve the
+ * actual data related to entries (if any).
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/queryenvironment.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef QUERYENVIRONMENT_H
+#define QUERYENVIRONMENT_H
+
+#include "access/tupdesc.h"
+
+
+typedef enum EphemeralNameRelationType
+{
+ ENR_NAMED_TUPLESTORE /* named tuplestore relation; e.g., deltas */
+} EphemeralNameRelationType;
+
+/*
+ * Some ephemeral named relations must match some relation (e.g., trigger
+ * transition tables), so to properly handle cached plans and DDL, we should
+ * carry the OID of that relation. In other cases an ENR might be independent
+ * of any relation which is stored in the system catalogs, so we need to be
+ * able to directly store the TupleDesc. We never need both.
+ */
+typedef struct EphemeralNamedRelationMetadataData
+{
+ char *name; /* name used to identify the relation */
+
+ /* only one of the next two fields should be used */
+ Oid reliddesc; /* oid of relation to get tupdesc */
+ TupleDesc tupdesc; /* description of result rows */
+
+ EphemeralNameRelationType enrtype; /* to identify type of relation */
+ double enrtuples; /* estimated number of tuples */
+} EphemeralNamedRelationMetadataData;
+
+typedef EphemeralNamedRelationMetadataData *EphemeralNamedRelationMetadata;
+
+/*
+ * Ephemeral Named Relation data; used for parsing named relations not in the
+ * catalog, like transition tables in AFTER triggers.
+ */
+typedef struct EphemeralNamedRelationData
+{
+ EphemeralNamedRelationMetadataData md;
+ void *reldata; /* structure for execution-time access to data */
+} EphemeralNamedRelationData;
+
+typedef EphemeralNamedRelationData *EphemeralNamedRelation;
+
+/*
+ * This is an opaque structure outside of queryenvironment.c itself. The
+ * intention is to be able to change the implementation or add new context
+ * features without needing to change existing code for use of existing
+ * features.
+ */
+typedef struct QueryEnvironment QueryEnvironment;
+
+
+extern QueryEnvironment *create_queryEnv(void);
+extern EphemeralNamedRelationMetadata get_visible_ENR_metadata(QueryEnvironment *queryEnv, const char *refname);
+extern void register_ENR(QueryEnvironment *queryEnv, EphemeralNamedRelation enr);
+extern void unregister_ENR(QueryEnvironment *queryEnv, const char *name);
+extern EphemeralNamedRelation get_ENR(QueryEnvironment *queryEnv, const char *name);
+extern TupleDesc ENRMetadataGetTupDesc(EphemeralNamedRelationMetadata enrmd);
+
+#endif /* QUERYENVIRONMENT_H */
diff --git a/src/include/utils/tuplestore.h b/src/include/utils/tuplestore.h
index a52a5470372..b31ede882b9 100644
--- a/src/include/utils/tuplestore.h
+++ b/src/include/utils/tuplestore.h
@@ -78,6 +78,8 @@ extern bool tuplestore_advance(Tuplestorestate *state, bool forward);
extern bool tuplestore_skiptuples(Tuplestorestate *state,
int64 ntuples, bool forward);
+extern int64 tuplestore_tuple_count(Tuplestorestate *state);
+
extern bool tuplestore_ateof(Tuplestorestate *state);
extern void tuplestore_rescan(Tuplestorestate *state);