summaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorTom Lane2017-01-14 21:02:35 +0000
committerTom Lane2017-01-14 21:02:35 +0000
commitab1f0c8225714aaa18d2f9ca4f80cd009f145421 (patch)
tree76cddd3b6b74474384d799fd61a4f211094ea55b /src/include
parent75abb955dfef064f2fbc5c043f37fff8d0262ffe (diff)
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of representation of lists of statements. It's always been the case that the output of parse analysis is a list of Query nodes, whatever the types of the individual statements in the list. This patch brings similar consistency to the outputs of raw parsing and planning steps: * The output of raw parsing is now always a list of RawStmt nodes; the statement-type-dependent nodes are one level down from that. * The output of pg_plan_queries() is now always a list of PlannedStmt nodes, even for utility statements. In the case of a utility statement, "planning" just consists of wrapping a CMD_UTILITY PlannedStmt around the utility node. This list representation is now used in Portal and CachedPlan plan lists, replacing the former convention of intermixing PlannedStmts with bare utility-statement nodes. Now, every list of statements has a consistent head-node type depending on how far along it is in processing. This allows changing many places that formerly used generic "Node *" pointers to use a more specific pointer type, thus reducing the number of IsA() tests and casts needed, as well as improving code clarity. Also, the post-parse-analysis representation of DECLARE CURSOR is changed so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained SELECT remains a child of the DeclareCursorStmt rather than getting flipped around to be the other way. It's now true for both Query and PlannedStmt that utilityStmt is non-null if and only if commandType is CMD_UTILITY. That allows simplifying a lot of places that were testing both fields. (I think some of those were just defensive programming, but in many places, it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.) Because PlannedStmt carries a canSetTag field, we're also able to get rid of some ad-hoc rules about how to reconstruct canSetTag for a bare utility statement; specifically, the assumption that a utility is canSetTag if and only if it's the only one in its list. While I see no near-term need for relaxing that restriction, it's nice to get rid of the ad-hocery. The API of ProcessUtility() is changed so that what it's passed is the wrapper PlannedStmt not just the bare utility statement. This will affect all users of ProcessUtility_hook, but the changes are pretty trivial; see the affected contrib modules for examples of the minimum change needed. (Most compilers should give pointer-type-mismatch warnings for uncorrected code.) There's also a change in the API of ExplainOneQuery_hook, to pass through cursorOptions instead of expecting hook functions to know what to pick. This is needed because of the DECLARE CURSOR changes, but really should have been done in 9.6; it's unlikely that any extant hook functions know about using CURSOR_OPT_PARALLEL_OK. Finally, teach gram.y to save statement boundary locations in RawStmt nodes, and pass those through to Query and PlannedStmt nodes. This allows more intelligent handling of cases where a source query string contains multiple statements. This patch doesn't actually do anything with the information, but a follow-on patch will. (Passing this information through cleanly is the true motivation for these changes; while I think this is all good cleanup, it's unlikely we'd have bothered without this end goal.) catversion bump because addition of location fields to struct Query affects stored rules. This patch is by me, but it owes a good deal to Fabien Coelho who did a lot of preliminary work on the problem, and also reviewed the patch. Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
Diffstat (limited to 'src/include')
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/commands/copy.h3
-rw-r--r--src/include/commands/explain.h1
-rw-r--r--src/include/commands/portalcmds.h2
-rw-r--r--src/include/commands/prepare.h3
-rw-r--r--src/include/commands/schemacmds.h3
-rw-r--r--src/include/commands/view.h3
-rw-r--r--src/include/executor/execdesc.h9
-rw-r--r--src/include/nodes/nodes.h1
-rw-r--r--src/include/nodes/parsenodes.h65
-rw-r--r--src/include/nodes/plannodes.h15
-rw-r--r--src/include/parser/analyze.h8
-rw-r--r--src/include/tcop/tcopprot.h5
-rw-r--r--src/include/tcop/utility.h8
-rw-r--r--src/include/utils/plancache.h12
-rw-r--r--src/include/utils/portal.h5
16 files changed, 95 insertions, 50 deletions
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 95cfd53eeca..29604b6f4ed 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201612231
+#define CATALOG_VERSION_NO 201701141
#endif
diff --git a/src/include/commands/copy.h b/src/include/commands/copy.h
index 4785631cef9..d63ca0f5e99 100644
--- a/src/include/commands/copy.h
+++ b/src/include/commands/copy.h
@@ -22,7 +22,8 @@
/* CopyStateData is private in commands/copy.c */
typedef struct CopyStateData *CopyState;
-extern Oid DoCopy(ParseState *state, const CopyStmt *stmt,
+extern void DoCopy(ParseState *state, const CopyStmt *stmt,
+ int stmt_location, int stmt_len,
uint64 *processed);
extern void ProcessCopyOptions(ParseState *pstate, CopyState cstate, bool is_from, List *options);
diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h
index 1820dd66bb2..9191e186c15 100644
--- a/src/include/commands/explain.h
+++ b/src/include/commands/explain.h
@@ -49,6 +49,7 @@ typedef struct ExplainState
/* Hook for plugins to get control in ExplainOneQuery() */
typedef void (*ExplainOneQuery_hook_type) (Query *query,
+ int cursorOptions,
IntoClause *into,
ExplainState *es,
const char *queryString,
diff --git a/src/include/commands/portalcmds.h b/src/include/commands/portalcmds.h
index 0ae9b7213cd..8f0e6c48f49 100644
--- a/src/include/commands/portalcmds.h
+++ b/src/include/commands/portalcmds.h
@@ -18,7 +18,7 @@
#include "utils/portal.h"
-extern void PerformCursorOpen(PlannedStmt *stmt, ParamListInfo params,
+extern void PerformCursorOpen(DeclareCursorStmt *cstmt, ParamListInfo params,
const char *queryString, bool isTopLevel);
extern void PerformPortalFetch(FetchStmt *stmt, DestReceiver *dest,
diff --git a/src/include/commands/prepare.h b/src/include/commands/prepare.h
index 0a3a8addca1..d8d22edbbcd 100644
--- a/src/include/commands/prepare.h
+++ b/src/include/commands/prepare.h
@@ -35,7 +35,8 @@ typedef struct
/* Utility statements PREPARE, EXECUTE, DEALLOCATE, EXPLAIN EXECUTE */
-extern void PrepareQuery(PrepareStmt *stmt, const char *queryString);
+extern void PrepareQuery(PrepareStmt *stmt, const char *queryString,
+ int stmt_location, int stmt_len);
extern void ExecuteQuery(ExecuteStmt *stmt, IntoClause *intoClause,
const char *queryString, ParamListInfo params,
DestReceiver *dest, char *completionTag);
diff --git a/src/include/commands/schemacmds.h b/src/include/commands/schemacmds.h
index 087878ddc33..f07a389c7f6 100644
--- a/src/include/commands/schemacmds.h
+++ b/src/include/commands/schemacmds.h
@@ -19,7 +19,8 @@
#include "nodes/parsenodes.h"
extern Oid CreateSchemaCommand(CreateSchemaStmt *parsetree,
- const char *queryString);
+ const char *queryString,
+ int stmt_location, int stmt_len);
extern void RemoveSchemaById(Oid schemaOid);
diff --git a/src/include/commands/view.h b/src/include/commands/view.h
index 648665ebe5d..39763913c80 100644
--- a/src/include/commands/view.h
+++ b/src/include/commands/view.h
@@ -19,7 +19,8 @@
extern void validateWithCheckOption(char *value);
-extern ObjectAddress DefineView(ViewStmt *stmt, const char *queryString);
+extern ObjectAddress DefineView(ViewStmt *stmt, const char *queryString,
+ int stmt_location, int stmt_len);
extern void StoreViewQuery(Oid viewOid, Query *viewParse, bool replace);
diff --git a/src/include/executor/execdesc.h b/src/include/executor/execdesc.h
index 2c221255dcb..c99ea818158 100644
--- a/src/include/executor/execdesc.h
+++ b/src/include/executor/execdesc.h
@@ -34,8 +34,7 @@ typedef struct QueryDesc
{
/* These fields are provided by CreateQueryDesc */
CmdType operation; /* CMD_SELECT, CMD_UPDATE, etc. */
- PlannedStmt *plannedstmt; /* planner's output, or null if utility */
- Node *utilitystmt; /* utility statement, or null */
+ PlannedStmt *plannedstmt; /* planner's output (could be utility, too) */
const char *sourceText; /* source text of the query */
Snapshot snapshot; /* snapshot to use for query */
Snapshot crosscheck_snapshot; /* crosscheck for RI update/delete */
@@ -61,12 +60,6 @@ extern QueryDesc *CreateQueryDesc(PlannedStmt *plannedstmt,
ParamListInfo params,
int instrument_options);
-extern QueryDesc *CreateUtilityQueryDesc(Node *utilitystmt,
- const char *sourceText,
- Snapshot snapshot,
- DestReceiver *dest,
- ParamListInfo params);
-
extern void FreeQueryDesc(QueryDesc *qdesc);
#endif /* EXECDESC_H */
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index a1bb0ac5cb8..4c4319bcabf 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -301,6 +301,7 @@ typedef enum NodeTag
/*
* TAGS FOR STATEMENT NODES (mostly in parsenodes.h)
*/
+ T_RawStmt,
T_Query,
T_PlannedStmt,
T_InsertStmt,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 7ceaa22c33b..edb5cd21521 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -7,7 +7,9 @@
* This is a byte (not character) offset in the original source text, to be
* used for positioning an error cursor when there is an error related to
* the node. Access to the original source text is needed to make use of
- * the location.
+ * the location. At the topmost (statement) level, we also provide a
+ * statement length, likewise measured in bytes, for convenience in
+ * identifying statement boundaries in multi-statement source strings.
*
*
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
@@ -89,9 +91,7 @@ typedef uint32 AclMode; /* a bitmask of privilege bits */
* for further processing by the rewriter and planner.
*
* Utility statements (i.e. non-optimizable statements) have the
- * utilityStmt field set, and the Query itself is mostly dummy.
- * DECLARE CURSOR is a special case: it is represented like a SELECT,
- * but the original DeclareCursorStmt is stored in utilityStmt.
+ * utilityStmt field set, and the rest of the Query is mostly dummy.
*
* Planning converts a Query tree into a Plan tree headed by a PlannedStmt
* node --- the Query structure is not used by the executor.
@@ -108,8 +108,7 @@ typedef struct Query
bool canSetTag; /* do I set the command result tag? */
- Node *utilityStmt; /* non-null if this is DECLARE CURSOR or a
- * non-optimizable statement */
+ Node *utilityStmt; /* non-null if commandType == CMD_UTILITY */
int resultRelation; /* rtable index of target relation for
* INSERT/UPDATE/DELETE; 0 for SELECT */
@@ -162,6 +161,15 @@ typedef struct Query
* are only added during rewrite and
* therefore are not written out as
* part of Query. */
+
+ /*
+ * The following two fields identify the portion of the source text string
+ * containing this query. They are typically only populated in top-level
+ * Queries, not in sub-queries. When not set, they might both be zero, or
+ * both be -1 meaning "unknown".
+ */
+ int stmt_location; /* start location, or -1 if unknown */
+ int stmt_len; /* length in bytes; 0 means "rest of string" */
} Query;
@@ -1308,6 +1316,30 @@ typedef struct TriggerTransition
} TriggerTransition;
/*****************************************************************************
+ * Raw Grammar Output Statements
+ *****************************************************************************/
+
+/*
+ * RawStmt --- container for any one statement's raw parse tree
+ *
+ * Parse analysis converts a raw parse tree headed by a RawStmt node into
+ * an analyzed statement headed by a Query node. For optimizable statements,
+ * the conversion is complex. For utility statements, the parser usually just
+ * transfers the raw parse tree (sans RawStmt) into the utilityStmt field of
+ * the Query node, and all the useful work happens at execution time.
+ *
+ * stmt_location/stmt_len identify the portion of the source text string
+ * containing this raw statement (useful for multi-statement strings).
+ */
+typedef struct RawStmt
+{
+ NodeTag type;
+ Node *stmt; /* raw parse tree */
+ int stmt_location; /* start location, or -1 if unknown */
+ int stmt_len; /* length in bytes; 0 means "rest of string" */
+} RawStmt;
+
+/*****************************************************************************
* Optimizable Statements
*****************************************************************************/
@@ -1474,6 +1506,9 @@ typedef struct SetOperationStmt
* statements do need attention from parse analysis, and this is
* done by routines in parser/parse_utilcmd.c after ProcessUtility
* receives the command for execution.
+ * DECLARE CURSOR, EXPLAIN, and CREATE TABLE AS are special cases:
+ * they contain optimizable statements, which get processed normally
+ * by parser/analyze.c.
*****************************************************************************/
/*
@@ -1794,7 +1829,7 @@ typedef struct CopyStmt
NodeTag type;
RangeVar *relation; /* the relation to copy */
Node *query; /* the query (SELECT or DML statement with
- * RETURNING) to copy */
+ * RETURNING) to copy, as a raw parse tree */
List *attlist; /* List of column names (as Strings), or NIL
* for all columns */
bool is_from; /* TO or FROM */
@@ -2472,9 +2507,9 @@ typedef struct SecLabelStmt
/* ----------------------
* Declare Cursor Statement
*
- * Note: the "query" field of DeclareCursorStmt is only used in the raw grammar
- * output. After parse analysis it's set to null, and the Query points to the
- * DeclareCursorStmt, not vice versa.
+ * The "query" field is initially a raw parse tree, and is converted to a
+ * Query node during parse analysis. Note that rewriting and planning
+ * of the query are always postponed until execution.
* ----------------------
*/
#define CURSOR_OPT_BINARY 0x0001 /* BINARY */
@@ -2493,7 +2528,7 @@ typedef struct DeclareCursorStmt
NodeTag type;
char *portalname; /* name of the portal (cursor) */
int options; /* bitmask of options (see above) */
- Node *query; /* the raw SELECT query */
+ Node *query; /* the query (see comments above) */
} DeclareCursorStmt;
/* ----------------------
@@ -2841,7 +2876,7 @@ typedef struct ViewStmt
NodeTag type;
RangeVar *view; /* the view to be created */
List *aliases; /* target column names */
- Node *query; /* the SELECT query */
+ Node *query; /* the SELECT query (as a raw parse tree) */
bool replace; /* replace an existing view? */
List *options; /* options from WITH clause */
ViewCheckOption withCheckOption; /* WITH CHECK OPTION */
@@ -2950,9 +2985,9 @@ typedef struct VacuumStmt
/* ----------------------
* Explain Statement
*
- * The "query" field is either a raw parse tree (SelectStmt, InsertStmt, etc)
- * or a Query node if parse analysis has been done. Note that rewriting and
- * planning of the query are always postponed until execution of EXPLAIN.
+ * The "query" field is initially a raw parse tree, and is converted to a
+ * Query node during parse analysis. Note that rewriting and planning
+ * of the query are always postponed until execution.
* ----------------------
*/
typedef struct ExplainStmt
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 692a62698ed..6810f8c0993 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -31,13 +31,18 @@
*
* The output of the planner is a Plan tree headed by a PlannedStmt node.
* PlannedStmt holds the "one time" information needed by the executor.
+ *
+ * For simplicity in APIs, we also wrap utility statements in PlannedStmt
+ * nodes; in such cases, commandType == CMD_UTILITY, the statement itself
+ * is in the utilityStmt field, and the rest of the struct is mostly dummy.
+ * (We do use canSetTag, stmt_location, stmt_len, and possibly queryId.)
* ----------------
*/
typedef struct PlannedStmt
{
NodeTag type;
- CmdType commandType; /* select|insert|update|delete */
+ CmdType commandType; /* select|insert|update|delete|utility */
uint32 queryId; /* query identifier (copied from Query) */
@@ -60,8 +65,6 @@ typedef struct PlannedStmt
/* rtable indexes of target relations for INSERT/UPDATE/DELETE */
List *resultRelations; /* integer list of RT indexes, or NIL */
- Node *utilityStmt; /* non-null if this is DECLARE CURSOR */
-
List *subplans; /* Plan trees for SubPlan expressions */
Bitmapset *rewindPlanIDs; /* indices of subplans that require REWIND */
@@ -73,6 +76,12 @@ typedef struct PlannedStmt
List *invalItems; /* other dependencies, as PlanInvalItems */
int nParamExec; /* number of PARAM_EXEC Params used */
+
+ Node *utilityStmt; /* non-null if this is utility stmt */
+
+ /* statement location in source string (copied from Query) */
+ int stmt_location; /* start location, or -1 if unknown */
+ int stmt_len; /* length in bytes; 0 means "rest of string" */
} PlannedStmt;
/* macro for fetching the Plan associated with a SubPlan node */
diff --git a/src/include/parser/analyze.h b/src/include/parser/analyze.h
index 3bf4edd0bf2..a7e5c55ab4f 100644
--- a/src/include/parser/analyze.h
+++ b/src/include/parser/analyze.h
@@ -22,19 +22,19 @@ typedef void (*post_parse_analyze_hook_type) (ParseState *pstate,
extern PGDLLIMPORT post_parse_analyze_hook_type post_parse_analyze_hook;
-extern Query *parse_analyze(Node *parseTree, const char *sourceText,
+extern Query *parse_analyze(RawStmt *parseTree, const char *sourceText,
Oid *paramTypes, int numParams);
-extern Query *parse_analyze_varparams(Node *parseTree, const char *sourceText,
+extern Query *parse_analyze_varparams(RawStmt *parseTree, const char *sourceText,
Oid **paramTypes, int *numParams);
extern Query *parse_sub_analyze(Node *parseTree, ParseState *parentParseState,
CommonTableExpr *parentCTE,
bool locked_from_parent);
-extern Query *transformTopLevelStmt(ParseState *pstate, Node *parseTree);
+extern Query *transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree);
extern Query *transformStmt(ParseState *pstate, Node *parseTree);
-extern bool analyze_requires_snapshot(Node *parseTree);
+extern bool analyze_requires_snapshot(RawStmt *parseTree);
extern const char *LCS_asString(LockClauseStrength strength);
extern void CheckSelectLocking(Query *qry, LockClauseStrength strength);
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index 54da6b65efb..1958be85b72 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -47,9 +47,10 @@ typedef enum
extern int log_statement;
extern List *pg_parse_query(const char *query_string);
-extern List *pg_analyze_and_rewrite(Node *parsetree, const char *query_string,
+extern List *pg_analyze_and_rewrite(RawStmt *parsetree,
+ const char *query_string,
Oid *paramTypes, int numParams);
-extern List *pg_analyze_and_rewrite_params(Node *parsetree,
+extern List *pg_analyze_and_rewrite_params(RawStmt *parsetree,
const char *query_string,
ParserSetupHook parserSetup,
void *parserSetupArg);
diff --git a/src/include/tcop/utility.h b/src/include/tcop/utility.h
index 42c52a1c757..4f8d3539001 100644
--- a/src/include/tcop/utility.h
+++ b/src/include/tcop/utility.h
@@ -24,16 +24,16 @@ typedef enum
} ProcessUtilityContext;
/* Hook for plugins to get control in ProcessUtility() */
-typedef void (*ProcessUtility_hook_type) (Node *parsetree,
+typedef void (*ProcessUtility_hook_type) (PlannedStmt *pstmt,
const char *queryString, ProcessUtilityContext context,
ParamListInfo params,
DestReceiver *dest, char *completionTag);
extern PGDLLIMPORT ProcessUtility_hook_type ProcessUtility_hook;
-extern void ProcessUtility(Node *parsetree, const char *queryString,
+extern void ProcessUtility(PlannedStmt *pstmt, const char *queryString,
ProcessUtilityContext context, ParamListInfo params,
DestReceiver *dest, char *completionTag);
-extern void standard_ProcessUtility(Node *parsetree, const char *queryString,
+extern void standard_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
ProcessUtilityContext context, ParamListInfo params,
DestReceiver *dest, char *completionTag);
@@ -47,6 +47,6 @@ extern const char *CreateCommandTag(Node *parsetree);
extern LogStmtLevel GetCommandLogLevel(Node *parsetree);
-extern bool CommandIsReadOnly(Node *parsetree);
+extern bool CommandIsReadOnly(PlannedStmt *pstmt);
#endif /* UTILITY_H */
diff --git a/src/include/utils/plancache.h b/src/include/utils/plancache.h
index 9ee0bc6e9f1..84952d56e70 100644
--- a/src/include/utils/plancache.h
+++ b/src/include/utils/plancache.h
@@ -18,6 +18,9 @@
#include "access/tupdesc.h"
#include "nodes/params.h"
+/* Forward declaration, to avoid including parsenodes.h here */
+struct RawStmt;
+
#define CACHEDPLANSOURCE_MAGIC 195726186
#define CACHEDPLAN_MAGIC 953717834
@@ -76,7 +79,7 @@
typedef struct CachedPlanSource
{
int magic; /* should equal CACHEDPLANSOURCE_MAGIC */
- Node *raw_parse_tree; /* output of raw_parser(), or NULL */
+ struct RawStmt *raw_parse_tree; /* output of raw_parser(), or NULL */
const char *query_string; /* source text of query */
const char *commandTag; /* command tag (a constant!), or NULL */
Oid *param_types; /* array of parameter type OIDs, or NULL */
@@ -126,8 +129,7 @@ typedef struct CachedPlanSource
typedef struct CachedPlan
{
int magic; /* should equal CACHEDPLAN_MAGIC */
- List *stmt_list; /* list of statement nodes (PlannedStmts and
- * bare utility statements) */
+ 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? */
@@ -144,10 +146,10 @@ typedef struct CachedPlan
extern void InitPlanCache(void);
extern void ResetPlanCache(void);
-extern CachedPlanSource *CreateCachedPlan(Node *raw_parse_tree,
+extern CachedPlanSource *CreateCachedPlan(struct RawStmt *raw_parse_tree,
const char *query_string,
const char *commandTag);
-extern CachedPlanSource *CreateOneShotCachedPlan(Node *raw_parse_tree,
+extern CachedPlanSource *CreateOneShotCachedPlan(struct RawStmt *raw_parse_tree,
const char *query_string,
const char *commandTag);
extern void CompleteCachedPlan(CachedPlanSource *plansource,
diff --git a/src/include/utils/portal.h b/src/include/utils/portal.h
index 8359416b15e..dc76acd0a42 100644
--- a/src/include/utils/portal.h
+++ b/src/include/utils/portal.h
@@ -133,7 +133,7 @@ typedef struct PortalData
/* The query or queries the portal will execute */
const char *sourceText; /* text of query (as of 8.4, never NULL) */
const char *commandTag; /* command tag for original query */
- List *stmts; /* PlannedStmts and/or utility statements */
+ List *stmts; /* list of PlannedStmts */
CachedPlan *cplan; /* CachedPlan, if stmts are from one */
ParamListInfo portalParams; /* params to pass to query */
@@ -201,7 +201,6 @@ typedef struct PortalData
*/
#define PortalGetQueryDesc(portal) ((portal)->queryDesc)
#define PortalGetHeapMemory(portal) ((portal)->heap)
-#define PortalGetPrimaryStmt(portal) PortalListGetPrimaryStmt((portal)->stmts)
/* Prototypes for functions in utils/mmgr/portalmem.c */
@@ -232,7 +231,7 @@ extern void PortalDefineQuery(Portal portal,
const char *commandTag,
List *stmts,
CachedPlan *cplan);
-extern Node *PortalListGetPrimaryStmt(List *stmts);
+extern PlannedStmt *PortalGetPrimaryStmt(Portal portal);
extern void PortalCreateHoldStore(Portal portal);
extern void PortalHashTableDeleteAll(void);
extern bool ThereAreNoReadyPortals(void);