query-bits.patch
text/plain
Filename: query-bits.patch
Type: text/plain
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| contrib/postgres_fdw/postgres_fdw.c | 4 | 4 |
| src/backend/commands/view.c | 1 | 1 |
| src/backend/executor/functions.c | 4 | 4 |
| src/backend/optimizer/path/allpaths.c | 11 | 11 |
| src/backend/optimizer/plan/analyzejoins.c | 4 | 4 |
| src/backend/optimizer/plan/planagg.c | 4 | 4 |
| src/backend/optimizer/plan/planner.c | 43 | 39 |
| src/backend/optimizer/plan/setrefs.c | 1 | 1 |
| src/backend/optimizer/plan/subselect.c | 6 | 6 |
| src/backend/optimizer/prep/prepjointree.c | 17 | 13 |
| src/backend/optimizer/prep/prepunion.c | 1 | 1 |
| src/backend/optimizer/util/clauses.c | 5 | 5 |
| src/backend/optimizer/util/var.c | 5 | 4 |
| src/backend/parser/analyze.c | 53 | 51 |
| src/backend/parser/parse_cte.c | 1 | 1 |
| src/backend/parser/parse_merge.c | 5 | 5 |
| src/backend/rewrite/rewriteDefine.c | 2 | 2 |
| src/backend/rewrite/rewriteHandler.c | 47 | 43 |
| src/backend/rewrite/rewriteManip.c | 14 | 13 |
| src/backend/rewrite/rewriteSearchCycle.c | 2 | 2 |
| src/backend/tcop/postgres.c | 1 | 1 |
| src/backend/tcop/pquery.c | 3 | 3 |
| src/backend/utils/adt/ruleutils.c | 5 | 5 |
| src/backend/utils/cache/plancache.c | 3 | 3 |
| src/include/nodes/parsenodes.h | 55 | 25 |
| src/include/rewrite/rewriteManip.h | 2 | 2 |
| src/pl/plpgsql/src/pl_exec.c | 4 | 4 |
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..d04443ef97 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_flags);
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_flags);
#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 ||