The Query structure has an increasing number of bool attributes. This is
likely to increase in the future. And they have the same properties.
Wouldn't it be better to store them in bits? Common statements don't use
them, so they have little impact. This also saves memory space.
--
Quan Zongliang
diff --git a/contrib/postgres_fdw/postgres_fdw.c
b/contrib/postgres_fdw/postgres_fdw.c
index 142dcfc995..a28d625147 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -3341,7 +3341,7 @@ estimate_path_cost_size(PlannerInfo *root,
/* Collect statistics about aggregates for estimating
costs. */
MemSet(&aggcosts, 0, sizeof(AggClauseCosts));
- if (root->parse->hasAggs)
+ if (QueryHasAggs(root->parse))
{
get_agg_clause_costs(root, AGGSPLIT_SIMPLE,
&aggcosts);
}
@@ -6762,7 +6762,7 @@ add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo
*input_rel,
Cost total_cost;
/* Nothing to be done, if there is no grouping or aggregation required.
*/
- if (!parse->groupClause && !parse->groupingSets && !parse->hasAggs &&
+ if (!parse->groupClause && !parse->groupingSets && !QueryHasAggs(parse)
&&
!root->hasHavingQual)
return;
@@ -6859,7 +6859,7 @@ add_foreign_ordered_paths(PlannerInfo *root, RelOptInfo
*input_rel,
Assert(parse->sortClause);
/* We don't support cases where there are any SRFs in the targetlist */
- if (parse->hasTargetSRFs)
+ if (QueryHasTargetSRFs(parse))
return;
/* Save the input_rel as outerrel in fpinfo */
@@ -7007,7 +7007,7 @@ add_foreign_final_paths(PlannerInfo *root, RelOptInfo
*input_rel,
return;
/* We don't support cases where there are any SRFs in the targetlist */
- if (parse->hasTargetSRFs)
+ if (QueryHasTargetSRFs(parse))
return;
/* Save the input_rel as outerrel in fpinfo */
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index dce898c751..e328bd9242 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -398,7 +398,7 @@ DefineView(ViewStmt *stmt, const char *queryString,
* DefineQueryRewrite(), but that function will complain about a bogus
ON
* SELECT rule, and we'd rather the message complain about a view.
*/
- if (viewParse->hasModifyingCTE)
+ if (QueryHasModifyingCTE(viewParse))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("views must not contain data-modifying
statements in WITH")));
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 0f811fd2fc..cdc94f082d 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -488,7 +488,7 @@ init_execution_state(List *queryTree_list,
/* Utility commands require no planning. */
stmt = makeNode(PlannedStmt);
stmt->commandType = CMD_UTILITY;
- stmt->canSetTag = queryTree->canSetTag;
+ stmt->canSetTag = QueryCanSetTag(queryTree);
stmt->utilityStmt = queryTree->utilityStmt;
stmt->stmt_location = queryTree->stmt_location;
stmt->stmt_len = queryTree->stmt_len;
@@ -540,7 +540,7 @@ init_execution_state(List *queryTree_list,
newes->stmt = stmt;
newes->qd = NULL;
- if (queryTree->canSetTag)
+ if (QueryCanSetTag(queryTree))
lasttages = newes;
preves = newes;
@@ -1650,7 +1650,7 @@ check_sql_fn_retval(List *queryTreeLists,
{
Query *q = lfirst_node(Query, lc2);
- if (q->canSetTag)
+ if (QueryCanSetTag(q))
{
parse = q;
parse_cell = lc2;
@@ -1934,7 +1934,7 @@ tlist_coercion_finished:
newquery = makeNode(Query);
newquery->commandType = CMD_SELECT;
newquery->querySource = parse->querySource;
- newquery->canSetTag = true;
+ QuerySetFlag(newquery, CAN_SET_TAG);
newquery->targetList = upper_tlist;
/* We need a moderately realistic colnames list for the
subquery RTE */
diff --git a/src/backend/optimizer/path/allpaths.c
b/src/backend/optimizer/path/allpaths.c
index d404fbf262..bd359fd636 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -2595,7 +2595,7 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
* so then it might be useful to use
for the WindowAgg's
* runCondition.
*/
- if (!subquery->hasWindowFuncs ||
+ if (!QueryHasWindowFuncs(subquery) ||
check_and_push_window_quals(subquery, rte, rti, clause,
&run_cond_attrs))
{
@@ -2633,7 +2633,7 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
* we'd better tell the subquery to plan for full retrieval. (XXX This
* could probably be made more intelligent ...)
*/
- if (parse->hasAggs ||
+ if (QueryHasAggs(parse) ||
parse->groupClause ||
parse->groupingSets ||
root->hasHavingQual ||
@@ -3604,8 +3604,8 @@ subquery_is_pushdown_safe(Query *subquery, Query
*topquery,
/* Check points 3, 4, and 5 */
if (subquery->distinctClause ||
- subquery->hasWindowFuncs ||
- subquery->hasTargetSRFs)
+ QueryHasWindowFuncs(subquery) ||
+ QueryHasTargetSRFs(subquery))
safetyInfo->unsafeVolatile = true;
/*
@@ -3726,7 +3726,7 @@ check_output_expressions(Query *subquery,
pushdown_safety_info *safetyInfo)
continue; /* ignore resjunk
columns */
/* Functions returning sets are unsafe (point 1) */
- if (subquery->hasTargetSRFs &&
+ if (QueryHasTargetSRFs(subquery) &&
(safetyInfo->unsafeFlags[tle->resno] &
UNSAFE_HAS_SET_FUNC) == 0 &&
expression_returns_set((Node *) tle->expr))
@@ -3745,7 +3745,7 @@ check_output_expressions(Query *subquery,
pushdown_safety_info *safetyInfo)
}
/* If subquery uses DISTINCT ON, check point 3 */
- if (subquery->hasDistinctOn &&
+ if (QueryHasDistinctOn(subquery) &&
(safetyInfo->unsafeFlags[tle->resno] &
UNSAFE_NOTIN_DISTINCTON_CLAUSE) == 0 &&
!targetIsInSortList(tle, InvalidOid,
subquery->distinctClause))
@@ -3756,7 +3756,7 @@ check_output_expressions(Query *subquery,
pushdown_safety_info *safetyInfo)
}
/* If subquery uses window functions, check point 4 */
- if (subquery->hasWindowFuncs &&
+ if (QueryHasWindowFuncs(subquery) &&
(safetyInfo->unsafeFlags[tle->resno] &
UNSAFE_NOTIN_DISTINCTON_CLAUSE) == 0 &&
!targetIsInAllPartitionLists(tle, subquery))
@@ -3985,14 +3985,14 @@ subquery_push_qual(Query *subquery, RangeTblEntry *rte,
Index rti, Node *qual)
qual = ReplaceVarsFromTargetList(qual, rti, 0, rte,
subquery->targetList,
REPLACEVARS_REPORT_ERROR, 0,
-
&subquery->hasSubLinks);
+
&subquery->flags);
/*
* Now attach the qual to the proper place: normally WHERE, but
if the
* subquery uses grouping or aggregation, put it in HAVING
(since the
* qual really refers to the group-result rows).
*/
- if (subquery->hasAggs || subquery->groupClause ||
subquery->groupingSets || subquery->havingQual)
+ if (QueryHasAggs(subquery) || subquery->groupClause ||
subquery->groupingSets || subquery->havingQual)
subquery->havingQual =
make_and_qual(subquery->havingQual, qual);
else
subquery->jointree->quals =
@@ -4086,7 +4086,7 @@ remove_unused_subquery_outputs(Query *subquery,
RelOptInfo *rel,
* If subquery has regular DISTINCT (not DISTINCT ON), we're wasting our
* time: all its output columns must be used in the distinctClause.
*/
- if (subquery->distinctClause && !subquery->hasDistinctOn)
+ if (subquery->distinctClause && !QueryHasDistinctOn(subquery))
return;
/*
@@ -4147,7 +4147,7 @@ remove_unused_subquery_outputs(Query *subquery,
RelOptInfo *rel,
* If it contains a set-returning function, we can't remove it
since
* that could change the number of rows returned by the
subquery.
*/
- if (subquery->hasTargetSRFs &&
+ if (QueryHasTargetSRFs(subquery) &&
expression_returns_set(texpr))
continue;
diff --git a/src/backend/optimizer/plan/analyzejoins.c
b/src/backend/optimizer/plan/analyzejoins.c
index e494acd51a..618fed25fb 100644
--- a/src/backend/optimizer/plan/analyzejoins.c
+++ b/src/backend/optimizer/plan/analyzejoins.c
@@ -1010,14 +1010,14 @@ bool
query_supports_distinctness(Query *query)
{
/* SRFs break distinctness except with DISTINCT, see below */
- if (query->hasTargetSRFs && query->distinctClause == NIL)
+ if (QueryHasTargetSRFs(query) && query->distinctClause == NIL)
return false;
/* check for features we can prove distinctness with */
if (query->distinctClause != NIL ||
query->groupClause != NIL ||
query->groupingSets != NIL ||
- query->hasAggs ||
+ QueryHasAggs(query) ||
query->havingQual ||
query->setOperations)
return true;
@@ -1081,7 +1081,7 @@ query_is_distinct_for(Query *query, List *colnos, List
*opids)
* columns, it would be safe because they'd be expanded before grouping.
* But it doesn't currently seem worth the effort to check for that.)
*/
- if (query->hasTargetSRFs)
+ if (QueryHasTargetSRFs(query))
return false;
/*
@@ -1131,7 +1131,7 @@ query_is_distinct_for(Query *query, List *colnos, List
*opids)
* If we have no GROUP BY, but do have aggregates or HAVING,
then the
* result is at most one row so it's surely unique, for any
operators.
*/
- if (query->hasAggs || query->havingQual)
+ if (QueryHasAggs(query) || query->havingQual)
return true;
}
diff --git a/src/backend/optimizer/plan/planagg.c
b/src/backend/optimizer/plan/planagg.c
index 700c0b7ac7..fe5daaa332 100644
--- a/src/backend/optimizer/plan/planagg.c
+++ b/src/backend/optimizer/plan/planagg.c
@@ -84,7 +84,7 @@ preprocess_minmax_aggregates(PlannerInfo *root)
Assert(root->minmax_aggs == NIL);
/* Nothing to do if query has no aggregates */
- if (!parse->hasAggs)
+ if (!QueryHasAggs(parse))
return;
Assert(!parse->setOperations); /* shouldn't get here if a setop */
@@ -98,7 +98,7 @@ preprocess_minmax_aggregates(PlannerInfo *root)
* so there's not much point in optimizing MIN/MAX.
*/
if (parse->groupClause || list_length(parse->groupingSets) > 1 ||
- parse->hasWindowFuncs)
+ QueryHasWindowFuncs(parse))
return;
/*
@@ -379,8 +379,8 @@ build_minmax_path(PlannerInfo *root, MinMaxAggInfo *mminfo,
parse->havingQual = NULL;
subroot->hasHavingQual = false;
parse->distinctClause = NIL;
- parse->hasDistinctOn = false;
- parse->hasAggs = false;
+ QueryClearFlag(parse, HAS_DISTINCT_ON);
+ QueryClearFlag(parse, HAS_AGGS);
/* Build "target IS NOT NULL" expression */
ntest = makeNode(NullTest);
diff --git a/src/backend/optimizer/plan/planner.c
b/src/backend/optimizer/plan/planner.c
index be4e182869..a18832507f 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -348,7 +348,7 @@ standard_planner(Query *parse, const char *query_string,
int cursorOptions,
if ((cursorOptions & CURSOR_OPT_PARALLEL_OK) != 0 &&
IsUnderPostmaster &&
parse->commandType == CMD_SELECT &&
- !parse->hasModifyingCTE &&
+ !QueryHasModifyingCTE(parse) &&
max_parallel_workers_per_gather > 0 &&
!IsParallelWorker())
{
@@ -540,8 +540,8 @@ standard_planner(Query *parse, const char *query_string,
int cursorOptions,
result->commandType = parse->commandType;
result->queryId = parse->queryId;
result->hasReturning = (parse->returningList != NIL);
- result->hasModifyingCTE = parse->hasModifyingCTE;
- result->canSetTag = parse->canSetTag;
+ result->hasModifyingCTE = QueryHasModifyingCTE(parse);
+ result->canSetTag = QueryCanSetTag(parse);
result->transientPlan = glob->transientPlan;
result->dependsOnRole = glob->dependsOnRole;
result->parallelModeNeeded = glob->parallelModeNeeded;
@@ -707,7 +707,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
* into subqueries; if we pull up any subqueries below, their SubLinks
are
* processed just before pulling them up.
*/
- if (parse->hasSubLinks)
+ if (QueryHasSubLinks(parse))
pull_up_sublinks(root);
/*
@@ -834,8 +834,12 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
EXPRKIND_TARGET);
/* Constant-folding might have removed all set-returning functions */
- if (parse->hasTargetSRFs)
- parse->hasTargetSRFs = expression_returns_set((Node *)
parse->targetList);
+ if (QueryHasTargetSRFs(parse))
+ {
+ QueryCondSetFlag(parse,
+ expression_returns_set((Node *)
parse->targetList),
+ HAS_TARGET_SRFS);
+ }
newWithCheckOptions = NIL;
foreach(l, parse->withCheckOptions)
@@ -1189,7 +1193,7 @@ preprocess_expression(PlannerInfo *root, Node *expr, int
kind)
}
/* Expand SubLinks to SubPlans */
- if (root->parse->hasSubLinks)
+ if (QueryHasSubLinks(root->parse))
expr = SS_process_sublinks(root, expr, (kind == EXPRKIND_QUAL));
/*
@@ -1368,7 +1372,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
is_parallel_safe(root, (Node *) final_target->exprs);
/* The setop result tlist couldn't contain any SRFs */
- Assert(!parse->hasTargetSRFs);
+ Assert(!QueryHasTargetSRFs(parse));
final_targets = final_targets_contain_srfs = NIL;
/*
@@ -1446,7 +1450,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
* pathtargets, else some copies of the Aggref nodes might
escape
* being marked.
*/
- if (parse->hasAggs)
+ if (QueryHasAggs(parse))
{
preprocess_aggrefs(root, (Node *)
root->processed_tlist);
preprocess_aggrefs(root, (Node *) parse->havingQual);
@@ -1458,7 +1462,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
* too.) Note that they could all have been eliminated by
constant
* folding, in which case we don't need to do any more work.
*/
- if (parse->hasWindowFuncs)
+ if (QueryHasWindowFuncs(parse))
{
wflists = find_window_functions((Node *)
root->processed_tlist,
list_length(parse->windowClause));
@@ -1474,7 +1478,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
activeWindows = select_active_windows(root,
wflists);
}
else
- parse->hasWindowFuncs = false;
+ QueryClearFlag(parse, HAS_WINDOW_FUNCS);
}
/*
@@ -1483,7 +1487,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
* that is needed in MIN/MAX-optimizable cases will have to be
* duplicated in planagg.c.
*/
- if (parse->hasAggs)
+ if (QueryHasAggs(parse))
preprocess_minmax_aggregates(root);
/*
@@ -1495,9 +1499,9 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
if (parse->groupClause ||
parse->groupingSets ||
parse->distinctClause ||
- parse->hasAggs ||
- parse->hasWindowFuncs ||
- parse->hasTargetSRFs ||
+ QueryHasAggs(parse) ||
+ QueryHasWindowFuncs(parse) ||
+ QueryHasTargetSRFs(parse) ||
root->hasHavingQual)
root->limit_tuples = -1.0;
else
@@ -1573,7 +1577,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
* should emit grouping_target.
*/
have_grouping = (parse->groupClause || parse->groupingSets ||
- parse->hasAggs ||
root->hasHavingQual);
+ QueryHasAggs(parse) ||
root->hasHavingQual);
if (have_grouping)
{
scanjoin_target = make_group_input_target(root,
final_target);
@@ -1592,7 +1596,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
* each of the named targets with a SRF-free version, and
remember the
* list of additional projection steps we need to add
afterwards.
*/
- if (parse->hasTargetSRFs)
+ if (QueryHasTargetSRFs(parse))
{
/* final_target doesn't recompute any SRFs in
sort_input_target */
split_pathtarget_at_srfs(root, final_target,
sort_input_target,
@@ -1664,7 +1668,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
grouping_target_parallel_safe,
gset_data);
/* Fix things up if grouping_target contains SRFs */
- if (parse->hasTargetSRFs)
+ if (QueryHasTargetSRFs(parse))
adjust_paths_for_srfs(root, current_rel,
grouping_targets,
grouping_targets_contain_srfs);
@@ -1684,7 +1688,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
wflists,
activeWindows);
/* Fix things up if sort_input_target contains SRFs */
- if (parse->hasTargetSRFs)
+ if (QueryHasTargetSRFs(parse))
adjust_paths_for_srfs(root, current_rel,
sort_input_targets,
sort_input_targets_contain_srfs);
@@ -1718,7 +1722,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
have_postponed_srfs ? -1.0 :
limit_tuples);
/* Fix things up if final_target contains SRFs */
- if (parse->hasTargetSRFs)
+ if (QueryHasTargetSRFs(parse))
adjust_paths_for_srfs(root, current_rel,
final_targets,
final_targets_contain_srfs);
@@ -1955,7 +1959,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
create_modifytable_path(root, final_rel,
path,
parse->commandType,
-
parse->canSetTag,
+
QueryCanSetTag(parse),
parse->resultRelation,
rootRelation,
root->partColsUpdated,
@@ -3573,7 +3577,7 @@ get_number_of_groups(PlannerInfo *root,
/* Empty grouping sets ... one result row for each one */
dNumGroups = list_length(parse->groupingSets);
}
- else if (parse->hasAggs || root->hasHavingQual)
+ else if (QueryHasAggs(parse) || root->hasHavingQual)
{
/* Plain aggregation, one result row */
dNumGroups = 1;
@@ -3776,7 +3780,7 @@ is_degenerate_grouping(PlannerInfo *root)
Query *parse = root->parse;
return (root->hasHavingQual || parse->groupingSets) &&
- !parse->hasAggs && parse->groupClause == NIL;
+ !QueryHasAggs(parse) && parse->groupClause == NIL;
}
/*
@@ -4665,7 +4669,7 @@ create_partial_distinct_paths(PlannerInfo *root,
RelOptInfo *input_rel,
parse = root->parse;
/* can't do parallel DISTINCT ON */
- if (parse->hasDistinctOn)
+ if (QueryHasDistinctOn(parse))
return;
partial_distinct_rel = fetch_upper_rel(root, UPPERREL_PARTIAL_DISTINCT,
@@ -4855,7 +4859,7 @@ create_final_distinct_paths(PlannerInfo *root, RelOptInfo
*input_rel,
bool allow_hash;
/* Estimate number of distinct rows there will be */
- if (parse->groupClause || parse->groupingSets || parse->hasAggs ||
+ if (parse->groupClause || parse->groupingSets || QueryHasAggs(parse) ||
root->hasHavingQual)
{
/*
@@ -4902,7 +4906,7 @@ create_final_distinct_paths(PlannerInfo *root, RelOptInfo
*input_rel,
ListCell *lc;
double limittuples = root->distinct_pathkeys == NIL ?
1.0 : -1.0;
- if (parse->hasDistinctOn &&
+ if (QueryHasDistinctOn(parse) &&
list_length(root->distinct_pathkeys) <
list_length(root->sort_pathkeys))
needed_pathkeys = root->sort_pathkeys;
@@ -5011,7 +5015,7 @@ create_final_distinct_paths(PlannerInfo *root, RelOptInfo
*input_rel,
*/
if (distinct_rel->pathlist == NIL)
allow_hash = true; /* we have no alternatives */
- else if (parse->hasDistinctOn || !enable_hashagg)
+ else if (QueryHasDistinctOn(parse) || !enable_hashagg)
allow_hash = false; /* policy-based decision not to
hash */
else
allow_hash = true; /* default */
@@ -5839,7 +5843,7 @@ make_window_input_target(PlannerInfo *root,
int i;
ListCell *lc;
- Assert(root->parse->hasWindowFuncs);
+ Assert(QueryHasWindowFuncs(root->parse));
/*
* Collect the sortgroupref numbers of window PARTITION/ORDER BY clauses
@@ -6123,7 +6127,7 @@ make_sort_input_target(PlannerInfo *root,
* Check for SRF or volatile functions. Check the SRF
case first
* because we must know whether we have any postponed
SRFs.
*/
- if (parse->hasTargetSRFs &&
+ if (QueryHasTargetSRFs(parse) &&
expression_returns_set((Node *) expr))
{
/* We'll decide below whether these are
postponable */
@@ -6163,7 +6167,7 @@ make_sort_input_target(PlannerInfo *root,
{
/* For sortgroupref cols, just check if any contain
SRFs */
if (!have_srf_sortcols &&
- parse->hasTargetSRFs &&
+ QueryHasTargetSRFs(parse) &&
expression_returns_set((Node *) expr))
have_srf_sortcols = true;
}
@@ -6845,7 +6849,7 @@ add_paths_to_grouping_rel(PlannerInfo *root, RelOptInfo
*input_rel,
path, true, can_hash,
gd, agg_costs, dNumGroups);
}
- else if (parse->hasAggs)
+ else if (QueryHasAggs(parse))
{
/*
* We have aggregation, possibly with
plain GROUP BY. Make
@@ -6920,7 +6924,7 @@ add_paths_to_grouping_rel(PlannerInfo *root, RelOptInfo
*input_rel,
if (path == NULL)
continue;
- if (parse->hasAggs)
+ if (QueryHasAggs(parse))
add_path(grouped_rel, (Path *)
create_agg_path(root,
grouped_rel,
@@ -7105,7 +7109,7 @@ create_partial_grouping_paths(PlannerInfo *root,
*/
MemSet(agg_partial_costs, 0, sizeof(AggClauseCosts));
MemSet(agg_final_costs, 0, sizeof(AggClauseCosts));
- if (parse->hasAggs)
+ if (QueryHasAggs(parse))
{
/* partial phase */
get_agg_clause_costs(root, AGGSPLIT_INITIAL_SERIAL,
@@ -7136,7 +7140,7 @@ create_partial_grouping_paths(PlannerInfo *root,
if (can_sort && cheapest_total_path != NULL)
{
/* This should have been checked previously */
- Assert(parse->hasAggs || parse->groupClause);
+ Assert(QueryHasAggs(parse) || parse->groupClause);
/*
* Use any available suitably-sorted path as input, and also
consider
@@ -7171,7 +7175,7 @@ create_partial_grouping_paths(PlannerInfo *root,
if (path == NULL)
continue;
- if (parse->hasAggs)
+ if (QueryHasAggs(parse))
add_path(partially_grouped_rel, (Path *)
create_agg_path(root,
partially_grouped_rel,
@@ -7228,7 +7232,7 @@ create_partial_grouping_paths(PlannerInfo *root,
if (path == NULL)
continue;
- if (parse->hasAggs)
+ if (QueryHasAggs(parse))
add_partial_path(partially_grouped_rel,
(Path *)
create_agg_path(root,
partially_grouped_rel,
@@ -7258,7 +7262,7 @@ create_partial_grouping_paths(PlannerInfo *root,
if (can_hash && cheapest_total_path != NULL)
{
/* Checked above */
- Assert(parse->hasAggs || parse->groupClause);
+ Assert(QueryHasAggs(parse) || parse->groupClause);
add_path(partially_grouped_rel, (Path *)
create_agg_path(root,
@@ -7401,7 +7405,7 @@ can_partial_agg(PlannerInfo *root)
{
Query *parse = root->parse;
- if (!parse->hasAggs && parse->groupClause == NIL)
+ if (!QueryHasAggs(parse) && parse->groupClause == NIL)
{
/*
* We don't know how to do parallel aggregation unless we have
either
@@ -7560,7 +7564,7 @@ apply_scanjoin_target_to_paths(PlannerInfo *root,
* cheapest-path fields, which is a good thing because they're bogus
right
* now.)
*/
- if (root->parse->hasTargetSRFs)
+ if (QueryHasTargetSRFs(root->parse))
adjust_paths_for_srfs(root, rel,
scanjoin_targets,
scanjoin_targets_contain_srfs);
diff --git a/src/backend/optimizer/plan/setrefs.c
b/src/backend/optimizer/plan/setrefs.c
index 22a1fa29f3..3c45431d84 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -3600,7 +3600,7 @@ extract_query_dependencies_walker(Node *node, PlannerInfo
*context)
}
/* Remember if any Query has RLS quals applied by rewriter */
- if (query->hasRowSecurity)
+ if (QueryHasRowSecurity(query))
context->glob->dependsOnRole = true;
/* Collect relation OIDs in this Query's rtable */
diff --git a/src/backend/optimizer/plan/subselect.c
b/src/backend/optimizer/plan/subselect.c
index 47e14723d2..e65a1a1740 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -1562,11 +1562,11 @@ simplify_EXISTS_query(PlannerInfo *root, Query *query)
*/
if (query->commandType != CMD_SELECT ||
query->setOperations ||
- query->hasAggs ||
+ QueryHasAggs(query) ||
query->groupingSets ||
- query->hasWindowFuncs ||
- query->hasTargetSRFs ||
- query->hasModifyingCTE ||
+ QueryHasWindowFuncs(query) ||
+ QueryHasTargetSRFs(query) ||
+ QueryHasModifyingCTE(query) ||
query->havingQual ||
query->limitOffset ||
query->rowMarks)
@@ -1618,7 +1618,7 @@ simplify_EXISTS_query(PlannerInfo *root, Query *query)
query->windowClause = NIL;
query->distinctClause = NIL;
query->sortClause = NIL;
- query->hasDistinctOn = false;
+ QueryClearFlag(query, HAS_DISTINCT_ON);
return true;
}
@@ -1779,7 +1779,7 @@ convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect,
if (contain_vars_of_level((Node *) newWhere, 1) ||
contain_vars_of_level((Node *) rightargs, 1))
return NULL;
- if (root->parse->hasAggs &&
+ if (QueryHasAggs(root->parse) &&
(contain_aggs_of_level((Node *) newWhere, 1) ||
contain_aggs_of_level((Node *) rightargs, 1)))
return NULL;
diff --git a/src/backend/optimizer/prep/prepjointree.c
b/src/backend/optimizer/prep/prepjointree.c
index aa83dd3636..5b85aa8ff9 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -49,7 +49,7 @@ typedef struct pullup_replace_vars_context
RangeTblEntry *target_rte; /* RTE of subquery */
Relids relids; /* relids within subquery, as
numbered after
* pullup (set
only if target_rte->lateral) */
- bool *outer_hasSubLinks; /* -> outer query's hasSubLinks */
+ int *outer_flags; /* -> outer query's flags */
int varno; /* varno of subquery */
bool wrap_non_vars; /* do we need all non-Var outputs to be
PHVs? */
Node **rv_cache; /* cache for results with PHVs */
@@ -168,7 +168,7 @@ transform_MERGE_to_join(Query *parse)
* outer join so that we process all unmatched tuples from the source
* relation. If none exist, we can use an inner join.
*/
- if (parse->mergeUseOuterJoin)
+ if (QueryMergeUseOuterJoin(parse))
jointype = JOIN_RIGHT;
else
jointype = JOIN_INNER;
@@ -1028,7 +1028,7 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode,
RangeTblEntry *rte,
* Pull up any SubLinks within the subquery's quals, so that we don't
* leave unoptimized SubLinks behind.
*/
- if (subquery->hasSubLinks)
+ if (QueryHasSubLinks(subquery))
pull_up_sublinks(subroot);
/*
@@ -1119,7 +1119,7 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode,
RangeTblEntry *rte,
true, true);
else /* won't need relids */
rvcontext.relids = NULL;
- rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
+ rvcontext.outer_flags = &parse->flags;
rvcontext.varno = varno;
/* this flag will be set below, if needed */
rvcontext.wrap_non_vars = false;
@@ -1260,10 +1260,14 @@ pull_up_simple_subquery(PlannerInfo *root, Node
*jtnode, RangeTblEntry *rte,
* and VALUES RTEs copied up from the subquery. So it's necessary to
copy
* subquery->hasSubLinks anyway. Perhaps this can be improved someday.
*/
- parse->hasSubLinks |= subquery->hasSubLinks;
+ QueryCondSetFlag(parse,
+ QueryHasSubLinks(parse) || QueryHasSubLinks(subquery),
+ HAS_SUB_LINKS);
/* If subquery had any RLS conditions, now main query does too */
- parse->hasRowSecurity |= subquery->hasRowSecurity;
+ QueryCondSetFlag(parse,
+ QueryHasRowSecurity(parse) ||
QueryHasRowSecurity(subquery),
+ HAS_ROW_SECURITY);
/*
* subquery won't be pulled up if it hasAggs, hasWindowFuncs, or
@@ -1512,9 +1516,9 @@ is_simple_subquery(PlannerInfo *root, Query *subquery,
RangeTblEntry *rte,
* that case the locking was originally declared in the upper query
* anyway.
*/
- if (subquery->hasAggs ||
- subquery->hasWindowFuncs ||
- subquery->hasTargetSRFs ||
+ if (QueryHasAggs(subquery) ||
+ QueryHasWindowFuncs(subquery) ||
+ QueryHasTargetSRFs(subquery) ||
subquery->groupClause ||
subquery->groupingSets ||
subquery->havingQual ||
@@ -1522,7 +1526,7 @@ is_simple_subquery(PlannerInfo *root, Query *subquery,
RangeTblEntry *rte,
subquery->distinctClause ||
subquery->limitOffset ||
subquery->limitCount ||
- subquery->hasForUpdate ||
+ QueryHasForUpdate(subquery) ||
subquery->cteList)
return false;
@@ -1665,7 +1669,7 @@ pull_up_simple_values(PlannerInfo *root, Node *jtnode,
RangeTblEntry *rte)
rvcontext.targetlist = tlist;
rvcontext.target_rte = rte;
rvcontext.relids = NULL;
- rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
+ rvcontext.outer_flags = &parse->flags;
rvcontext.varno = varno;
rvcontext.wrap_non_vars = false;
/* initialize cache array with indexes 0 .. length(tlist) */
@@ -1826,7 +1830,7 @@ pull_up_constant_function(PlannerInfo *root, Node *jtnode,
*/
rvcontext.relids = NULL;
- rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
+ rvcontext.outer_flags = &parse->flags;
rvcontext.varno = ((RangeTblRef *) jtnode)->rtindex;
/* this flag will be set below, if needed */
rvcontext.wrap_non_vars = false;
@@ -2302,7 +2306,7 @@ pullup_replace_vars(Node *expr,
pullup_replace_vars_context *context)
context->varno, 0,
pullup_replace_vars_callback,
(void *)
context,
-
context->outer_hasSubLinks);
+
context->outer_flags);
}
static Node *
diff --git a/src/backend/optimizer/prep/prepunion.c
b/src/backend/optimizer/prep/prepunion.c
index c939b5a45f..354aae9464 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -340,7 +340,7 @@ recurse_set_operations(Node *setOp, PlannerInfo *root,
{
if (subquery->groupClause || subquery->groupingSets ||
subquery->distinctClause ||
- subroot->hasHavingQual || subquery->hasAggs)
+ subroot->hasHavingQual ||
QueryHasAggs(subquery))
*pNumGroups = subpath->rows;
else
*pNumGroups = estimate_num_groups(subroot,
diff --git a/src/backend/optimizer/util/clauses.c
b/src/backend/optimizer/util/clauses.c
index edc25d712e..3d513194a3 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -4672,10 +4672,10 @@ inline_function(Oid funcid, Oid result_type, Oid
result_collid,
*/
if (!IsA(querytree, Query) ||
querytree->commandType != CMD_SELECT ||
- querytree->hasAggs ||
- querytree->hasWindowFuncs ||
- querytree->hasTargetSRFs ||
- querytree->hasSubLinks ||
+ QueryHasAggs(querytree) ||
+ QueryHasWindowFuncs(querytree) ||
+ QueryHasTargetSRFs(querytree) ||
+ QueryHasSubLinks(querytree) ||
querytree->cteList ||
querytree->rtable ||
querytree->jointree->fromlist ||
@@ -5298,7 +5298,7 @@ inline_set_returning_function(PlannerInfo *root,
RangeTblEntry *rte)
* We must also notice if the inserted query adds a dependency on the
* calling role due to RLS quals.
*/
- if (querytree->hasRowSecurity)
+ if (QueryHasRowSecurity(querytree))
root->glob->dependsOnRole = true;
return querytree;
diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c
index 844fc30978..4e1d2a5e1c 100644
--- a/src/backend/optimizer/util/var.c
+++ b/src/backend/optimizer/util/var.c
@@ -756,9 +756,9 @@ flatten_join_alias_vars(PlannerInfo *root, Query *query,
Node *node)
context.query = query;
context.sublevels_up = 0;
/* flag whether join aliases could possibly contain SubLinks */
- context.possible_sublink = query->hasSubLinks;
+ context.possible_sublink = QueryHasSubLinks(query);
/* if hasSubLinks is already true, no need to work hard */
- context.inserted_sublink = query->hasSubLinks;
+ context.inserted_sublink = QueryHasSubLinks(query);
return flatten_join_alias_vars_mutator(node, &context);
}
@@ -881,12 +881,13 @@ flatten_join_alias_vars_mutator(Node *node,
context->sublevels_up++;
save_inserted_sublink = context->inserted_sublink;
- context->inserted_sublink = ((Query *) node)->hasSubLinks;
+ context->inserted_sublink = QueryHasSubLinks(((Query *) node));
newnode = query_tree_mutator((Query *) node,
flatten_join_alias_vars_mutator,
(void
*) context,
QTW_IGNORE_JOINALIASES);
- newnode->hasSubLinks |= context->inserted_sublink;
+ if (context->inserted_sublink)
+ QuerySetFlag(newnode, HAS_SUB_LINKS);
context->inserted_sublink = save_inserted_sublink;
context->sublevels_up--;
return (Node *) newnode;
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index dbdf6bf896..7b67016d36 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -420,7 +420,7 @@ transformStmt(ParseState *pstate, Node *parseTree)
/* Mark as original query until we learn differently */
result->querySource = QSRC_ORIGINAL;
- result->canSetTag = true;
+ QuerySetFlag(result, CAN_SET_TAG);
return result;
}
@@ -519,9 +519,9 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
/* process the WITH clause independently of all else */
if (stmt->withClause)
{
- qry->hasRecursive = stmt->withClause->recursive;
+ QueryCondSetFlag(qry, stmt->withClause->recursive,
HAS_RECURSIVE);
qry->cteList = transformWithClause(pstate, stmt->withClause);
- qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
+ QueryCondSetFlag(qry, pstate->p_hasModifyingCTE,
HAS_MODIFYING_CTE);
}
/* set up range table with just the result rel */
@@ -560,10 +560,10 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
qry->rteperminfos = pstate->p_rteperminfos;
qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
- qry->hasSubLinks = pstate->p_hasSubLinks;
- qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
- qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
- qry->hasAggs = pstate->p_hasAggs;
+ QueryCondSetFlag(qry, pstate->p_hasSubLinks, HAS_SUB_LINKS);
+ QueryCondSetFlag(qry, pstate->p_hasWindowFuncs, HAS_WINDOW_FUNCS);
+ QueryCondSetFlag(qry, pstate->p_hasTargetSRFs, HAS_TARGET_SRFS);
+ QueryCondSetFlag(qry, pstate->p_hasAggs, HAS_AGGS);
assign_query_collations(pstate, qry);
@@ -607,9 +607,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
/* process the WITH clause independently of all else */
if (stmt->withClause)
{
- qry->hasRecursive = stmt->withClause->recursive;
+ QueryCondSetFlag(qry, stmt->withClause->recursive,
HAS_RECURSIVE);
qry->cteList = transformWithClause(pstate, stmt->withClause);
- qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
+ QueryCondSetFlag(qry, pstate->p_hasModifyingCTE,
HAS_MODIFYING_CTE);
}
qry->override = stmt->override;
@@ -987,8 +987,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
qry->rteperminfos = pstate->p_rteperminfos;
qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
- qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
- qry->hasSubLinks = pstate->p_hasSubLinks;
+ QueryCondSetFlag(qry, pstate->p_hasTargetSRFs, HAS_TARGET_SRFS);
+ QueryCondSetFlag(qry, pstate->p_hasSubLinks, HAS_SUB_LINKS);
assign_query_collations(pstate, qry);
@@ -1335,9 +1335,9 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
/* process the WITH clause independently of all else */
if (stmt->withClause)
{
- qry->hasRecursive = stmt->withClause->recursive;
+ QueryCondSetFlag(qry, stmt->withClause->recursive,
HAS_RECURSIVE);
qry->cteList = transformWithClause(pstate, stmt->withClause);
- qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
+ QueryCondSetFlag(qry, pstate->p_hasModifyingCTE,
HAS_MODIFYING_CTE);
}
/* Complain if we get called from someplace where INTO is not allowed */
@@ -1396,7 +1396,7 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
if (stmt->distinctClause == NIL)
{
qry->distinctClause = NIL;
- qry->hasDistinctOn = false;
+ QueryClearFlag(qry, HAS_DISTINCT_ON);
}
else if (linitial(stmt->distinctClause) == NULL)
{
@@ -1405,7 +1405,7 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
&qry->targetList,
qry->sortClause,
false);
- qry->hasDistinctOn = false;
+ QueryClearFlag(qry, HAS_DISTINCT_ON);
}
else
{
@@ -1414,7 +1414,7 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
stmt->distinctClause,
&qry->targetList,
qry->sortClause);
- qry->hasDistinctOn = true;
+ QuerySetFlag(qry, HAS_DISTINCT_ON);
}
/* transform LIMIT */
@@ -1439,10 +1439,11 @@ transformSelectStmt(ParseState *pstate, SelectStmt
*stmt)
qry->rteperminfos = pstate->p_rteperminfos;
qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
- qry->hasSubLinks = pstate->p_hasSubLinks;
- qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
- qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
- qry->hasAggs = pstate->p_hasAggs;
+ QueryCondSetFlag(qry, pstate->p_hasSubLinks, HAS_SUB_LINKS);
+ QueryCondSetFlag(qry, pstate->p_hasWindowFuncs, HAS_WINDOW_FUNCS);
+ QueryCondSetFlag(qry, pstate->p_hasTargetSRFs, HAS_TARGET_SRFS);
+ QueryCondSetFlag(qry, pstate->p_hasAggs, HAS_AGGS);
+
foreach(l, stmt->lockingClause)
{
@@ -1498,9 +1499,9 @@ transformValuesClause(ParseState *pstate, SelectStmt
*stmt)
/* process the WITH clause independently of all else */
if (stmt->withClause)
{
- qry->hasRecursive = stmt->withClause->recursive;
+ QueryCondSetFlag(qry, stmt->withClause->recursive,
HAS_RECURSIVE);
qry->cteList = transformWithClause(pstate, stmt->withClause);
- qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
+ QueryCondSetFlag(qry, pstate->p_hasModifyingCTE,
HAS_MODIFYING_CTE);
}
/*
@@ -1668,7 +1669,7 @@ transformValuesClause(ParseState *pstate, SelectStmt
*stmt)
qry->rteperminfos = pstate->p_rteperminfos;
qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
- qry->hasSubLinks = pstate->p_hasSubLinks;
+ QueryCondSetFlag(qry, pstate->p_hasSubLinks, HAS_SUB_LINKS);
assign_query_collations(pstate, qry);
@@ -1765,9 +1766,9 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt
*stmt)
/* Process the WITH clause independently of all else */
if (withClause)
{
- qry->hasRecursive = withClause->recursive;
+ QueryCondSetFlag(qry, withClause->recursive, HAS_RECURSIVE);
qry->cteList = transformWithClause(pstate, withClause);
- qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
+ QueryCondSetFlag(qry, pstate->p_hasModifyingCTE,
HAS_MODIFYING_CTE);
}
/*
@@ -1915,10 +1916,10 @@ transformSetOperationStmt(ParseState *pstate,
SelectStmt *stmt)
qry->rteperminfos = pstate->p_rteperminfos;
qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
- qry->hasSubLinks = pstate->p_hasSubLinks;
- qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
- qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
- qry->hasAggs = pstate->p_hasAggs;
+ QueryCondSetFlag(qry, pstate->p_hasSubLinks, HAS_SUB_LINKS);
+ QueryCondSetFlag(qry, pstate->p_hasWindowFuncs, HAS_WINDOW_FUNCS);
+ QueryCondSetFlag(qry, pstate->p_hasTargetSRFs, HAS_TARGET_SRFS);
+ QueryCondSetFlag(qry, pstate->p_hasAggs, HAS_AGGS);
foreach(l, lockingClause)
{
@@ -2379,7 +2380,7 @@ transformReturnStmt(ParseState *pstate, ReturnStmt *stmt)
Query *qry = makeNode(Query);
qry->commandType = CMD_SELECT;
- qry->isReturn = true;
+ QuerySetFlag(qry, IS_RETURN);
qry->targetList = list_make1(makeTargetEntry((Expr *)
transformExpr(pstate, stmt->returnval, EXPR_KIND_SELECT_TARGET),
1, NULL, false));
@@ -2389,10 +2390,10 @@ transformReturnStmt(ParseState *pstate, ReturnStmt
*stmt)
qry->rtable = pstate->p_rtable;
qry->rteperminfos = pstate->p_rteperminfos;
qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
- qry->hasSubLinks = pstate->p_hasSubLinks;
- qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
- qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
- qry->hasAggs = pstate->p_hasAggs;
+ QueryCondSetFlag(qry, pstate->p_hasSubLinks, HAS_SUB_LINKS);
+ QueryCondSetFlag(qry, pstate->p_hasWindowFuncs, HAS_WINDOW_FUNCS);
+ QueryCondSetFlag(qry, pstate->p_hasTargetSRFs, HAS_TARGET_SRFS);
+ QueryCondSetFlag(qry, pstate->p_hasAggs, HAS_AGGS);
assign_query_collations(pstate, qry);
@@ -2417,9 +2418,9 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
/* process the WITH clause independently of all else */
if (stmt->withClause)
{
- qry->hasRecursive = stmt->withClause->recursive;
+ QueryCondSetFlag(qry, stmt->withClause->recursive,
HAS_RECURSIVE);
qry->cteList = transformWithClause(pstate, stmt->withClause);
- qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
+ QueryCondSetFlag(qry, pstate->p_hasModifyingCTE,
HAS_MODIFYING_CTE);
}
qry->resultRelation = setTargetTable(pstate, stmt->relation,
@@ -2457,8 +2458,9 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
qry->rteperminfos = pstate->p_rteperminfos;
qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
- qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
- qry->hasSubLinks = pstate->p_hasSubLinks;
+ QueryCondSetFlag(qry, pstate->p_hasTargetSRFs, HAS_TARGET_SRFS);
+ QueryCondSetFlag(qry, pstate->p_hasSubLinks, HAS_SUB_LINKS);
+
assign_query_collations(pstate, qry);
@@ -2781,7 +2783,7 @@ transformPLAssignStmt(ParseState *pstate, PLAssignStmt
*stmt)
if (sstmt->distinctClause == NIL)
{
qry->distinctClause = NIL;
- qry->hasDistinctOn = false;
+ QueryClearFlag(qry, HAS_DISTINCT_ON);
}
else if (linitial(sstmt->distinctClause) == NULL)
{
@@ -2790,7 +2792,7 @@ transformPLAssignStmt(ParseState *pstate, PLAssignStmt
*stmt)
&qry->targetList,
qry->sortClause,
false);
- qry->hasDistinctOn = false;
+ QueryClearFlag(qry, HAS_DISTINCT_ON);
}
else
{
@@ -2799,7 +2801,7 @@ transformPLAssignStmt(ParseState *pstate, PLAssignStmt
*stmt)
sstmt->distinctClause,
&qry->targetList,
qry->sortClause);
- qry->hasDistinctOn = true;
+ QuerySetFlag(qry, HAS_DISTINCT_ON);
}
/* transform LIMIT */
@@ -2820,10 +2822,10 @@ transformPLAssignStmt(ParseState *pstate, PLAssignStmt
*stmt)
qry->rteperminfos = pstate->p_rteperminfos;
qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
- qry->hasSubLinks = pstate->p_hasSubLinks;
- qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
- qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
- qry->hasAggs = pstate->p_hasAggs;
+ QueryCondSetFlag(qry, pstate->p_hasSubLinks, HAS_SUB_LINKS);
+ QueryCondSetFlag(qry, pstate->p_hasWindowFuncs, HAS_WINDOW_FUNCS);
+ QueryCondSetFlag(qry, pstate->p_hasTargetSRFs, HAS_TARGET_SRFS);
+ QueryCondSetFlag(qry, pstate->p_hasAggs, HAS_AGGS);
foreach(l, sstmt->lockingClause)
{
@@ -2887,7 +2889,7 @@ transformDeclareCursorStmt(ParseState *pstate,
DeclareCursorStmt *stmt)
* allowed, but the semantics of when the updates occur might be
* surprising.)
*/
- if (query->hasModifyingCTE)
+ if (QueryHasModifyingCTE(query))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("DECLARE CURSOR must not contain
data-modifying statements in WITH")));
@@ -3014,7 +3016,7 @@ transformCreateTableAsStmt(ParseState *pstate,
CreateTableAsStmt *stmt)
* materialized view. It's not sufficiently clear what the user
would
* want to happen if the MV is refreshed or incrementally
maintained.
*/
- if (query->hasModifyingCTE)
+ if (QueryHasModifyingCTE(query))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("materialized views must not
use data-modifying statements in WITH")));
@@ -3254,21 +3256,21 @@ CheckSelectLocking(Query *qry, LockClauseStrength
strength)
translator: %s is a SQL row locking clause such as FOR UPDATE
*/
errmsg("%s is not allowed with HAVING clause",
LCS_asString(strength))));
- if (qry->hasAggs)
+ if (QueryHasAggs(qry))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/*------
translator: %s is a SQL row locking clause such as FOR UPDATE
*/
errmsg("%s is not allowed with aggregate
functions",
LCS_asString(strength))));
- if (qry->hasWindowFuncs)
+ if (QueryHasWindowFuncs(qry))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/*------
translator: %s is a SQL row locking clause such as FOR UPDATE
*/
errmsg("%s is not allowed with window
functions",
LCS_asString(strength))));
- if (qry->hasTargetSRFs)
+ if (QueryHasTargetSRFs(qry))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/*------
@@ -3523,7 +3525,7 @@ applyLockingClause(Query *qry, Index rtindex,
/* If it's an explicit clause, make sure hasForUpdate gets set */
if (!pushedDown)
- qry->hasForUpdate = true;
+ QuerySetFlag(qry, HAS_FOR_UPDATE);
/* Check for pre-existing entry for same rtindex */
if ((rc = get_parse_rowmark(qry, rtindex)) != NULL)
diff --git a/src/backend/parser/parse_cte.c b/src/backend/parser/parse_cte.c
index 3c88c9abba..5719b437cb 100644
--- a/src/backend/parser/parse_cte.c
+++ b/src/backend/parser/parse_cte.c
@@ -346,7 +346,7 @@ analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
* matters for data-modifying statements, for which the flag will be
* propagated to the ModifyTable plan node.)
*/
- query->canSetTag = false;
+ QueryClearFlag(query, CAN_SET_TAG);
if (!cte->cterecursive)
{
diff --git a/src/backend/parser/parse_merge.c b/src/backend/parser/parse_merge.c
index 5f6a683ab9..bdecfb2246 100644
--- a/src/backend/parser/parse_merge.c
+++ b/src/backend/parser/parse_merge.c
@@ -108,7 +108,7 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
Assert(pstate->p_ctenamespace == NIL);
qry->commandType = CMD_MERGE;
- qry->hasRecursive = false;
+ QueryClearFlag(qry, HAS_RECURSIVE);
/* process the WITH clause independently of all else */
if (stmt->withClause)
@@ -119,7 +119,7 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
errmsg("WITH RECURSIVE is not
supported for MERGE statement")));
qry->cteList = transformWithClause(pstate, stmt->withClause);
- qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
+ QueryCondSetFlag(qry, pstate->p_hasModifyingCTE,
HAS_MODIFYING_CTE);
}
/*
@@ -259,7 +259,7 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
/* Use an outer join if any INSERT actions exist in the
command. */
if (action->commandType == CMD_INSERT)
- qry->mergeUseOuterJoin = true;
+ QuerySetFlag(qry, MERGE_USE_OUTERJOIN);
/*
* Set namespace for the specific action. This must be done
before
@@ -393,8 +393,8 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
/* RETURNING could potentially be added in the future, but not in SQL
std */
qry->returningList = NULL;
- qry->hasTargetSRFs = false;
- qry->hasSubLinks = pstate->p_hasSubLinks;
+ QueryClearFlag(qry, HAS_TARGET_SRFS);
+ QueryCondSetFlag(qry, pstate->p_hasSubLinks, HAS_SUB_LINKS);
assign_query_collations(pstate, qry);
diff --git a/src/backend/rewrite/rewriteDefine.c
b/src/backend/rewrite/rewriteDefine.c
index b449244a53..e0ed3f6148 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -350,7 +350,7 @@ DefineQueryRewrite(const char *rulename,
/*
* ... it cannot contain data-modifying WITH ...
*/
- if (query->hasModifyingCTE)
+ if (QueryHasModifyingCTE(query))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("rules on SELECT must not
contain data-modifying statements in WITH")));
@@ -685,7 +685,7 @@ setRuleCheckAsUser_Query(Query *qry, Oid userid)
}
/* If there are sublinks, search for them and process their RTEs */
- if (qry->hasSubLinks)
+ if (QueryHasSubLinks(qry))
query_tree_walker(qry, setRuleCheckAsUser_walker, (void *)
&userid,
QTW_IGNORE_RC_SUBQUERIES);
}
diff --git a/src/backend/rewrite/rewriteHandler.c
b/src/backend/rewrite/rewriteHandler.c
index f60b34deb6..42b23a6d84 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -292,7 +292,7 @@ AcquireRewriteLocks(Query *parsetree,
* Recurse into sublink subqueries, too. But we already did the ones in
* the rtable and cteList.
*/
- if (parsetree->hasSubLinks)
+ if (QueryHasSubLinks(parsetree))
query_tree_walker(parsetree, acquireLocksOnSubLinks, &context,
QTW_IGNORE_RC_SUBQUERIES);
}
@@ -457,7 +457,7 @@ rewriteRuleAction(Query *parsetree,
* There could have been some SubLinks in parsetree's rtable, in which
* case we'd better mark the sub_action correctly.
*/
- if (parsetree->hasSubLinks && !sub_action->hasSubLinks)
+ if (QueryHasSubLinks(parsetree) && !QueryHasSubLinks(sub_action))
{
foreach(lc, parsetree->rtable)
{
@@ -466,28 +466,28 @@ rewriteRuleAction(Query *parsetree,
switch (rte->rtekind)
{
case RTE_RELATION:
- sub_action->hasSubLinks =
- checkExprHasSubLink((Node *)
rte->tablesample);
+ QueryCondSetFlag(sub_action,
+ checkExprHasSubLink((Node *)
rte->tablesample), HAS_SUB_LINKS);
break;
case RTE_FUNCTION:
- sub_action->hasSubLinks =
- checkExprHasSubLink((Node *)
rte->functions);
+ QueryCondSetFlag(sub_action,
+ checkExprHasSubLink((Node *)
rte->functions), HAS_SUB_LINKS);
break;
case RTE_TABLEFUNC:
- sub_action->hasSubLinks =
- checkExprHasSubLink((Node *)
rte->tablefunc);
+ QueryCondSetFlag(sub_action,
+ checkExprHasSubLink((Node *)
rte->tablefunc), HAS_SUB_LINKS);
break;
case RTE_VALUES:
- sub_action->hasSubLinks =
- checkExprHasSubLink((Node *)
rte->values_lists);
+ QueryCondSetFlag(sub_action,
+ checkExprHasSubLink((Node *)
rte->values_lists), HAS_SUB_LINKS);
break;
default:
/* other RTE types don't contain bare
expressions */
break;
}
- sub_action->hasSubLinks |=
- checkExprHasSubLink((Node *)
rte->securityQuals);
- if (sub_action->hasSubLinks)
+ if (checkExprHasSubLink((Node *) rte->securityQuals))
+ QuerySetFlag(sub_action, HAS_SUB_LINKS);
+ if (QueryHasSubLinks(sub_action))
break; /* no need to keep
scanning rtable */
}
}
@@ -499,7 +499,8 @@ rewriteRuleAction(Query *parsetree,
* this is a no-op because RLS conditions aren't added till later, but
it
* seems like good future-proofing to do this anyway.)
*/
- sub_action->hasRowSecurity |= parsetree->hasRowSecurity;
+ if(QueryHasRowSecurity(parsetree))
+ QuerySetFlag(sub_action, HAS_ROW_SECURITY);
/*
* Each rule action's jointree should be the main parsetree's jointree
@@ -546,9 +547,9 @@ rewriteRuleAction(Query *parsetree,
* There could have been some SubLinks in newjointree,
in which
* case we'd better mark the sub_action correctly.
*/
- if (parsetree->hasSubLinks && !sub_action->hasSubLinks)
- sub_action->hasSubLinks =
- checkExprHasSubLink((Node *)
newjointree);
+ if (QueryHasSubLinks(parsetree) &&
!QueryHasSubLinks(sub_action))
+ QueryCondSetFlag(sub_action,
+
checkExprHasSubLink((Node *) newjointree), HAS_SUB_LINKS);
}
}
@@ -590,8 +591,10 @@ rewriteRuleAction(Query *parsetree,
sub_action->cteList = list_concat(sub_action->cteList,
copyObject(parsetree->cteList));
/* ... and don't forget about the associated flags */
- sub_action->hasRecursive |= parsetree->hasRecursive;
- sub_action->hasModifyingCTE |= parsetree->hasModifyingCTE;
+ if (QueryHasRecursive(parsetree))
+ QuerySetFlag(sub_action, HAS_RECURSIVE);
+ if (QueryHasModifyingCTE(parsetree))
+ QuerySetFlag(sub_action, HAS_MODIFYING_CTE);
/*
* If rule_action is different from sub_action (i.e., the rule
action
@@ -605,7 +608,7 @@ rewriteRuleAction(Query *parsetree,
* have to increment ctelevelsup in RTEs and SubLinks copied
from the
* original query. For now, it doesn't seem worth the trouble.
*/
- if (sub_action->hasModifyingCTE && rule_action != sub_action)
+ if (QueryHasModifyingCTE(sub_action) && rule_action !=
sub_action)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("INSERT ... SELECT rule actions
are not supported for queries having data-modifying statements in WITH")));
@@ -672,15 +675,16 @@ rewriteRuleAction(Query *parsetree,
rule_action->returningList,
REPLACEVARS_REPORT_ERROR,
0,
-
&rule_action->hasSubLinks);
+
&rule_action->flags);
/*
* There could have been some SubLinks in parsetree's
returningList,
* in which case we'd better mark the rule_action correctly.
*/
- if (parsetree->hasSubLinks && !rule_action->hasSubLinks)
- rule_action->hasSubLinks =
- checkExprHasSubLink((Node *)
rule_action->returningList);
+ if (QueryHasSubLinks(parsetree) &&
!QueryHasSubLinks(rule_action))
+ QueryCondSetFlag(rule_action,
+
checkExprHasSubLink((Node *) rule_action->returningList),
+ HAS_SUB_LINKS);
}
return rule_action;
@@ -2154,7 +2158,7 @@ fireRIRrules(Query *parsetree, List *activeRIRs)
* Recurse into sublink subqueries, too. But we already did the ones in
* the rtable and cteList.
*/
- if (parsetree->hasSubLinks)
+ if (QueryHasSubLinks(parsetree))
query_tree_walker(parsetree, fireRIRonSubLink, (void *)
activeRIRs,
QTW_IGNORE_RC_SUBQUERIES);
@@ -2253,9 +2257,9 @@ fireRIRrules(Query *parsetree, List *activeRIRs)
* applies, or if the new quals had sublinks.
*/
if (hasRowSecurity)
- parsetree->hasRowSecurity = true;
+ QuerySetFlag(parsetree, HAS_ROW_SECURITY);
if (hasSubLinks)
- parsetree->hasSubLinks = true;
+ QuerySetFlag(parsetree, HAS_SUB_LINKS);
table_close(rel, NoLock);
}
@@ -2311,7 +2315,7 @@ CopyAndAddInvertedQual(Query *parsetree,
REPLACEVARS_CHANGE_VARNO :
REPLACEVARS_SUBSTITUTE_NULL,
rt_index,
-
&parsetree->hasSubLinks);
+
&parsetree->flags);
/* And attach the fixed qual */
AddInvertedQual(parsetree, new_qual);
@@ -2419,7 +2423,7 @@ fireRules(Query *parsetree,
returning_flag);
rule_action->querySource = qsrc;
- rule_action->canSetTag = false; /* might change later */
+ QueryClearFlag(rule_action, CAN_SET_TAG); /* might
change later */
results = lappend(results, rule_action);
}
@@ -2622,13 +2626,13 @@ view_query_is_auto_updatable(Query *viewquery, bool
check_cols)
* These restrictions ensure that each row of the view corresponds to a
* unique row in the underlying base relation.
*/
- if (viewquery->hasAggs)
+ if (QueryHasAggs(viewquery))
return gettext_noop("Views that return aggregate functions are
not automatically updatable.");
- if (viewquery->hasWindowFuncs)
+ if (QueryHasWindowFuncs(viewquery))
return gettext_noop("Views that return window functions are not
automatically updatable.");
- if (viewquery->hasTargetSRFs)
+ if (QueryHasTargetSRFs(viewquery))
return gettext_noop("Views that return set-returning functions
are not automatically updatable.");
/*
@@ -3212,7 +3216,7 @@ rewriteTargetView(Query *parsetree, Relation view)
* be any subqueries in the range table or CTEs, so we can skip those,
as
* in AcquireRewriteLocks.
*/
- if (viewquery->hasSubLinks)
+ if (QueryHasSubLinks(viewquery))
{
acquireLocksOnSubLinks_context context;
@@ -3473,7 +3477,7 @@ rewriteTargetView(Query *parsetree, Relation view)
tmp_tlist,
REPLACEVARS_REPORT_ERROR,
0,
-
&parsetree->hasSubLinks);
+
&parsetree->flags);
}
/*
@@ -3524,8 +3528,8 @@ rewriteTargetView(Query *parsetree, Relation view)
* Make sure that the query is marked correctly if the
added qual
* has sublinks.
*/
- if (!parsetree->hasSubLinks)
- parsetree->hasSubLinks =
checkExprHasSubLink(viewqual);
+ if (!QueryHasSubLinks(parsetree))
+ QueryCondSetFlag(parsetree,
checkExprHasSubLink(viewqual), HAS_SUB_LINKS);
}
else
AddQual(parsetree, (Node *) viewqual);
@@ -3596,9 +3600,9 @@ rewriteTargetView(Query *parsetree, Relation view)
* case the same qual will have already been
added, and this
* check will already have been done.
*/
- if (!parsetree->hasSubLinks &&
+ if (!QueryHasSubLinks(parsetree) &&
parsetree->commandType != CMD_UPDATE)
- parsetree->hasSubLinks =
checkExprHasSubLink(wco->qual);
+ QueryCondSetFlag(parsetree,
checkExprHasSubLink(wco->qual), HAS_SUB_LINKS);
}
}
}
@@ -3670,7 +3674,7 @@ RewriteQuery(Query *parsetree, List *rewrite_events, int
orig_rt_length)
errmsg("DO INSTEAD NOTIFY
rules are not supported for data-modifying statements in WITH")));
}
/* WITH queries should never be canSetTag */
- Assert(!ctequery->canSetTag);
+ Assert(!QueryCanSetTag(ctequery));
/* Push the single Query back into the CTE node */
cte->ctequery = (Node *) ctequery;
}
@@ -4211,7 +4215,7 @@ QueryRewrite(Query *parsetree)
* This function is only applied to top-level original queries
*/
Assert(parsetree->querySource == QSRC_ORIGINAL);
- Assert(parsetree->canSetTag);
+ Assert(QueryCanSetTag(parsetree));
/*
* Step 1
@@ -4265,7 +4269,7 @@ QueryRewrite(Query *parsetree)
if (query->querySource == QSRC_ORIGINAL)
{
- Assert(query->canSetTag);
+ Assert(QueryCanSetTag(query));
Assert(!foundOriginalQuery);
foundOriginalQuery = true;
#ifndef USE_ASSERT_CHECKING
@@ -4274,7 +4278,7 @@ QueryRewrite(Query *parsetree)
}
else
{
- Assert(!query->canSetTag);
+ Assert(!QueryCanSetTag(query));
if (query->commandType == origCmdType &&
(query->querySource == QSRC_INSTEAD_RULE ||
query->querySource == QSRC_QUAL_INSTEAD_RULE))
@@ -4283,7 +4287,7 @@ QueryRewrite(Query *parsetree)
}
if (!foundOriginalQuery && lastInstead != NULL)
- lastInstead->canSetTag = true;
+ QuerySetFlag(lastInstead, CAN_SET_TAG);
return results;
}
diff --git a/src/backend/rewrite/rewriteManip.c
b/src/backend/rewrite/rewriteManip.c
index 76c97a5b28..7fb2859b8f 100644
--- a/src/backend/rewrite/rewriteManip.c
+++ b/src/backend/rewrite/rewriteManip.c
@@ -1102,8 +1102,8 @@ AddQual(Query *parsetree, Node *qual)
* Make sure query is marked correctly if added qual has sublinks. Need
* not search qual when query is already marked.
*/
- if (!parsetree->hasSubLinks)
- parsetree->hasSubLinks = checkExprHasSubLink(copy);
+ if (!QueryHasSubLinks(parsetree))
+ QueryCondSetFlag(parsetree, checkExprHasSubLink(copy),
HAS_SUB_LINKS);
}
@@ -1334,7 +1334,7 @@ Node *
replace_rte_variables(Node *node, int target_varno, int sublevels_up,
replace_rte_variables_callback
callback,
void *callback_arg,
- bool *outer_hasSubLinks)
+ int *outer_flags)
{
Node *result;
replace_rte_variables_context context;
@@ -1349,9 +1349,9 @@ replace_rte_variables(Node *node, int target_varno, int
sublevels_up,
* detect new sublinks because the query already has some.
*/
if (node && IsA(node, Query))
- context.inserted_sublink = ((Query *) node)->hasSubLinks;
- else if (outer_hasSubLinks)
- context.inserted_sublink = *outer_hasSubLinks;
+ context.inserted_sublink = QueryHasSubLinks((Query *) node);
+ else if (outer_flags)
+ context.inserted_sublink = QueryFlagIsSet(*outer_flags,
HAS_SUB_LINKS);
else
context.inserted_sublink = false;
@@ -1367,9 +1367,9 @@ replace_rte_variables(Node *node, int target_varno, int
sublevels_up,
if (context.inserted_sublink)
{
if (result && IsA(result, Query))
- ((Query *) result)->hasSubLinks = true;
- else if (outer_hasSubLinks)
- *outer_hasSubLinks = true;
+ QuerySetFlag(((Query *) result), HAS_SUB_LINKS);
+ else if (outer_flags)
+ QueryFlagSet(*outer_flags, HAS_SUB_LINKS);
else
elog(ERROR, "replace_rte_variables inserted a SubLink,
but has noplace to record it");
}
@@ -1428,12 +1428,13 @@ replace_rte_variables_mutator(Node *node,
context->sublevels_up++;
save_inserted_sublink = context->inserted_sublink;
- context->inserted_sublink = ((Query *) node)->hasSubLinks;
+ context->inserted_sublink = QueryHasSubLinks((Query *) node);
newnode = query_tree_mutator((Query *) node,
replace_rte_variables_mutator,
(void
*) context,
0);
- newnode->hasSubLinks |= context->inserted_sublink;
+ if (context->inserted_sublink)
+ QuerySetFlag(newnode, HAS_SUB_LINKS);
context->inserted_sublink = save_inserted_sublink;
context->sublevels_up--;
return (Node *) newnode;
@@ -1764,7 +1765,7 @@ ReplaceVarsFromTargetList(Node *node,
List *targetlist,
ReplaceVarsNoMatchOption
nomatch_option,
int nomatch_varno,
- bool *outer_hasSubLinks)
+ int *outer_flags)
{
ReplaceVarsFromTargetList_context context;
@@ -1776,5 +1777,5 @@ ReplaceVarsFromTargetList(Node *node,
return replace_rte_variables(node, target_varno, sublevels_up,
ReplaceVarsFromTargetList_callback,
(void *)
&context,
-
outer_hasSubLinks);
+ outer_flags);
}
diff --git a/src/backend/rewrite/rewriteSearchCycle.c
b/src/backend/rewrite/rewriteSearchCycle.c
index 911a901808..d3cd02c4e0 100644
--- a/src/backend/rewrite/rewriteSearchCycle.c
+++ b/src/backend/rewrite/rewriteSearchCycle.c
@@ -278,7 +278,7 @@ rewriteSearchAndCycle(CommonTableExpr *cte)
*/
newq1 = makeNode(Query);
newq1->commandType = CMD_SELECT;
- newq1->canSetTag = true;
+ QuerySetFlag(newq1, CAN_SET_TAG);
newrte = makeNode(RangeTblEntry);
newrte->rtekind = RTE_SUBQUERY;
@@ -365,7 +365,7 @@ rewriteSearchAndCycle(CommonTableExpr *cte)
*/
newq2 = makeNode(Query);
newq2->commandType = CMD_SELECT;
- newq2->canSetTag = true;
+ QuerySetFlag(newq2, CAN_SET_TAG);
newrte = makeNode(RangeTblEntry);
newrte->rtekind = RTE_SUBQUERY;
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2c63b7875a..18100128cc 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -984,7 +984,7 @@ pg_plan_queries(List *querytrees, const char *query_string,
int cursorOptions,
/* Utility commands require no planning. */
stmt = makeNode(PlannedStmt);
stmt->commandType = CMD_UTILITY;
- stmt->canSetTag = query->canSetTag;
+ stmt->canSetTag = QueryCanSetTag(query);
stmt->utilityStmt = query->utilityStmt;
stmt->stmt_location = query->stmt_location;
stmt->stmt_len = query->stmt_len;
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index 0c45fcf318..329fc05ac4 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -225,11 +225,11 @@ ChoosePortalStrategy(List *stmts)
{
Query *query = (Query *) stmt;
- if (query->canSetTag)
+ if (QueryCanSetTag(query))
{
if (query->commandType == CMD_SELECT)
{
- if (query->hasModifyingCTE)
+ if (QueryHasModifyingCTE(query))
return PORTAL_ONE_MOD_WITH;
else
return PORTAL_ONE_SELECT;
@@ -283,7 +283,7 @@ ChoosePortalStrategy(List *stmts)
{
Query *query = (Query *) stmt;
- if (query->canSetTag)
+ if (QueryCanSetTag(query))
{
if (++nSetTag > 1)
return PORTAL_MULTI_QUERY; /* no
need to look further */
diff --git a/src/backend/utils/adt/ruleutils.c
b/src/backend/utils/adt/ruleutils.c
index a928a8c55d..daec49c286 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -5562,7 +5562,7 @@ get_with_clause(Query *query, deparse_context *context)
appendStringInfoChar(buf, ' ');
}
- if (query->hasRecursive)
+ if (QueryHasRecursive(query))
sep = "WITH RECURSIVE ";
else
sep = "WITH ";
@@ -5763,7 +5763,7 @@ get_select_query_def(Query *query, deparse_context
*context,
}
/* Add FOR [KEY] UPDATE/SHARE clauses if present */
- if (query->hasForUpdate)
+ if (QueryHasForUpdate(query))
{
foreach(l, query->rowMarks)
{
@@ -5916,7 +5916,7 @@ get_basic_select_query(Query *query, deparse_context
*context,
/*
* Build up the query string - first we say SELECT
*/
- if (query->isReturn)
+ if (QueryIsReturn(query))
appendStringInfoString(buf, "RETURN");
else
appendStringInfoString(buf, "SELECT");
@@ -5924,7 +5924,7 @@ get_basic_select_query(Query *query, deparse_context
*context,
/* Add the DISTINCT clause if given */
if (query->distinctClause != NIL)
{
- if (query->hasDistinctOn)
+ if (QueryHasDistinctOn(query))
{
appendStringInfoString(buf, " DISTINCT ON (");
sep = "";
@@ -6898,7 +6898,7 @@ get_update_query_targetlist_def(Query *query, List
*targetList,
* entries.
*/
ma_sublinks = NIL;
- if (query->hasSubLinks) /* else there can't be any */
+ if (QueryHasSubLinks(query)) /* else there can't be any */
{
foreach(l, targetList)
{
diff --git a/src/backend/utils/cache/plancache.c
b/src/backend/utils/cache/plancache.c
index 5194cbf2cc..fcf371622a 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -1384,7 +1384,7 @@ CachedPlanAllowsSimpleValidityCheck(CachedPlanSource
*plansource,
if (query->commandType == CMD_UTILITY)
return false;
- if (query->rtable || query->cteList || query->hasSubLinks)
+ if (query->rtable || query->cteList || QueryHasSubLinks(query))
return false;
}
@@ -1760,7 +1760,7 @@ QueryListGetPrimaryStmt(List *stmts)
{
Query *stmt = lfirst_node(Query, lc);
- if (stmt->canSetTag)
+ if (QueryCanSetTag(stmt))
return stmt;
}
return NULL;
@@ -1907,7 +1907,7 @@ ScanQueryForLocks(Query *parsetree, bool acquire)
* Recurse into sublink subqueries, too. But we already did the ones in
* the rtable and cteList.
*/
- if (parsetree->hasSubLinks)
+ if (QueryHasSubLinks(parsetree))
{
query_tree_walker(parsetree, ScanQueryWalker,
(void *) &acquire,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index d5b08ded44..ecaefe9b1a 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -129,9 +129,6 @@ typedef struct Query
*/
uint64 queryId pg_node_attr(equal_ignore, query_jumble_ignore,
read_write_ignore, read_as(0));
- /* do I set the command result tag? */
- bool canSetTag pg_node_attr(query_jumble_ignore);
-
Node *utilityStmt; /* non-null if commandType ==
CMD_UTILITY */
/*
@@ -141,26 +138,7 @@ typedef struct Query
*/
int resultRelation
pg_node_attr(query_jumble_ignore);
- /* has aggregates in tlist or havingQual */
- bool hasAggs pg_node_attr(query_jumble_ignore);
- /* has window functions in tlist */
- bool hasWindowFuncs pg_node_attr(query_jumble_ignore);
- /* has set-returning functions in tlist */
- bool hasTargetSRFs pg_node_attr(query_jumble_ignore);
- /* has subquery SubLink */
- bool hasSubLinks pg_node_attr(query_jumble_ignore);
- /* distinctClause is from DISTINCT ON */
- bool hasDistinctOn pg_node_attr(query_jumble_ignore);
- /* WITH RECURSIVE was specified */
- bool hasRecursive pg_node_attr(query_jumble_ignore);
- /* has INSERT/UPDATE/DELETE in WITH */
- bool hasModifyingCTE pg_node_attr(query_jumble_ignore);
- /* FOR [KEY] UPDATE/SHARE was specified */
- bool hasForUpdate pg_node_attr(query_jumble_ignore);
- /* rewriter has applied some RLS policy */
- bool hasRowSecurity pg_node_attr(query_jumble_ignore);
- /* is a RETURN statement */
- bool isReturn pg_node_attr(query_jumble_ignore);
+ int flags pg_node_attr(query_jumble_ignore);
List *cteList; /* WITH list (of CommonTableExpr's) */
@@ -175,8 +153,6 @@ typedef struct Query
* also USING
clause for MERGE */
List *mergeActionList; /* list of actions for MERGE (only) */
- /* whether to use outer join */
- bool mergeUseOuterJoin pg_node_attr(query_jumble_ignore);
List *targetList; /* target list (of TargetEntry) */
@@ -230,6 +206,60 @@ typedef struct Query
int stmt_len pg_node_attr(query_jumble_ignore);
} Query;
+/* do I set the command result tag? */
+#define QUERY_CAN_SET_TAG (1)
+/* has aggregates in tlist or havingQual */
+#define QUERY_HAS_AGGS (1 << 1)
+/* has window functions in tlist */
+#define QUERY_HAS_WINDOW_FUNCS (1 << 2)
+/* has set-returning functions in tlist */
+#define QUERY_HAS_TARGET_SRFS (1 << 3)
+/* has subquery SubLink */
+#define QUERY_HAS_SUB_LINKS (1 << 4)
+/* distinctClause is from DISTINCT ON */
+#define QUERY_HAS_DISTINCT_ON (1 << 5)
+/* WITH RECURSIVE was specified */
+#define QUERY_HAS_RECURSIVE (1 << 6)
+/* has INSERT/UPDATE/DELETE in WITH */
+#define QUERY_HAS_MODIFYING_CTE (1 << 7)
+/* FOR [KEY] UPDATE/SHARE was specified */
+#define QUERY_HAS_FOR_UPDATE (1 << 8)
+/* rewriter has applied some RLS policy */
+#define QUERY_HAS_ROW_SECURITY (1 << 9)
+/* is a RETURN statement */
+#define QUERY_IS_RETURN (1 << 10)
+/* whether to use outer join */
+#define QUERY_MERGE_USE_OUTERJOIN (1 << 11)
+
+#define QueryCanSetTag(query) ((query)->flags &
QUERY_CAN_SET_TAG)
+#define QueryHasAggs(query) ((query)->flags
& QUERY_HAS_AGGS)
+#define QueryHasWindowFuncs(query) ((query)->flags &
QUERY_HAS_WINDOW_FUNCS)
+#define QueryHasTargetSRFs(query) ((query)->flags &
QUERY_HAS_TARGET_SRFS)
+#define QueryHasSubLinks(query) ((query)->flags &
QUERY_HAS_SUB_LINKS)
+#define QueryHasDistinctOn(query) ((query)->flags &
QUERY_HAS_DISTINCT_ON)
+#define QueryHasRecursive(query) ((query)->flags &
QUERY_HAS_RECURSIVE)
+#define QueryHasModifyingCTE(query) ((query)->flags &
QUERY_HAS_MODIFYING_CTE)
+#define QueryHasForUpdate(query) ((query)->flags &
QUERY_HAS_FOR_UPDATE)
+#define QueryHasRowSecurity(query) ((query)->flags &
QUERY_HAS_ROW_SECURITY)
+#define QueryIsReturn(query) ((query)->flags &
QUERY_IS_RETURN)
+#define QueryMergeUseOuterJoin(query) ((query)->flags &
QUERY_MERGE_USE_OUTERJOIN)
+
+#define QueryFlagSet(flags, fname) ((flags) |=
(QUERY_##fname))
+#define QuerySetFlag(query, fname)
QueryFlagSet((query)->flags, fname)
+
+#define QueryFlagIsSet(flags, fname) ((flags) & (QUERY_##fname))
+
+#define QueryFlagClear(flags, fname) ((flags) &= ~(QUERY_##fname))
+#define QueryClearFlag(query, fname) QueryFlagClear((query)->flags,
fname)
+
+#define QueryCondSetFlag(query, cond, pname) \
+ { \
+ if (cond) \
+ QuerySetFlag(query, pname); \
+ else \
+ QueryClearFlag(query, pname); \
+ }
+
/****************************************************************************
* Supporting data structures for Parse Trees
diff --git a/src/include/rewrite/rewriteManip.h
b/src/include/rewrite/rewriteManip.h
index ac6d2049e8..2bb8bb1314 100644
--- a/src/include/rewrite/rewriteManip.h
+++ b/src/include/rewrite/rewriteManip.h
@@ -76,7 +76,7 @@ extern Node *replace_rte_variables(Node *node,
int
target_varno, int sublevels_up,
replace_rte_variables_callback callback,
void
*callback_arg,
- bool
*outer_hasSubLinks);
+ int
*outer_hasSubLinks);
extern Node *replace_rte_variables_mutator(Node *node,
replace_rte_variables_context *context);
@@ -91,6 +91,6 @@ extern Node *ReplaceVarsFromTargetList(Node *node,
List
*targetlist,
ReplaceVarsNoMatchOption nomatch_option,
int
nomatch_varno,
- bool
*outer_hasSubLinks);
+ int
*outer_hasSubLinks);
#endif /* REWRITEMANIP_H */
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 6d1691340c..e7f3652863 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -8020,10 +8020,10 @@ exec_simple_check_plan(PLpgSQL_execstate *estate,
PLpgSQL_expr *expr)
* inlining a SQL function; otherwise, inlining could change our
* conclusion about whether an expression is simple, which we don't
want.)
*/
- if (query->hasAggs ||
- query->hasWindowFuncs ||
- query->hasTargetSRFs ||
- query->hasSubLinks ||
+ if (QueryHasAggs(query) ||
+ QueryHasWindowFuncs(query) ||
+ QueryHasTargetSRFs(query) ||
+ QueryHasSubLinks(query) ||
query->cteList ||
query->jointree->fromlist ||
query->jointree->quals ||