Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 80579f9

Browse files
committed
Move building of child base quals out into a new function
An upcoming patch which changes how inheritance planning works requires adding a new function that does a similar job to set_append_rel_size() but for child target relations. To save it from having to duplicate the qual building code, move that to a separate function first. Here we also change things so that we never attempt to build security quals after detecting some const false child quals. We needlessly used to do this just before we marked the child relation as a dummy rel. In passing, this also moves the partition pruned check to before the qual building code. We don't need to build the child quals before we check if the partition has been pruned. Author: David Rowley Discussion: https://postgr.es/m/CAKJS1f_i+jrrD+if8qC7KPuTAAWsd=dtepgY_7u=P86GDEwm7A@mail.gmail.com
1 parent c93001b commit 80579f9

File tree

1 file changed

+140
-119
lines changed

1 file changed

+140
-119
lines changed

src/backend/optimizer/path/allpaths.c

+140-119
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ static void subquery_push_qual(Query *subquery,
138138
static void recurse_push_qual(Node *setOp, Query *topquery,
139139
RangeTblEntry *rte, Index rti, Node *qual);
140140
static void remove_unused_subquery_outputs(Query *subquery, RelOptInfo *rel);
141+
static bool apply_child_basequals(PlannerInfo *root, RelOptInfo *rel,
142+
RelOptInfo *childrel,
143+
RangeTblEntry *childRTE, AppendRelInfo *appinfo);
141144

142145

143146
/*
@@ -1010,12 +1013,8 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
10101013
int childRTindex;
10111014
RangeTblEntry *childRTE;
10121015
RelOptInfo *childrel;
1013-
List *childquals;
1014-
Index cq_min_security;
1015-
bool have_const_false_cq;
10161016
ListCell *parentvars;
10171017
ListCell *childvars;
1018-
ListCell *lc;
10191018

10201019
/* append_rel_list contains all append rels; ignore others */
10211020
if (appinfo->parent_relid != parentRTindex)
@@ -1031,119 +1030,21 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
10311030
childrel = find_base_rel(root, childRTindex);
10321031
Assert(childrel->reloptkind == RELOPT_OTHER_MEMBER_REL);
10331032

1034-
/*
1035-
* We have to copy the parent's targetlist and quals to the child,
1036-
* with appropriate substitution of variables. However, only the
1037-
* baserestrictinfo quals are needed before we can check for
1038-
* constraint exclusion; so do that first and then check to see if we
1039-
* can disregard this child.
1040-
*
1041-
* The child rel's targetlist might contain non-Var expressions, which
1042-
* means that substitution into the quals could produce opportunities
1043-
* for const-simplification, and perhaps even pseudoconstant quals.
1044-
* Therefore, transform each RestrictInfo separately to see if it
1045-
* reduces to a constant or pseudoconstant. (We must process them
1046-
* separately to keep track of the security level of each qual.)
1047-
*/
1048-
childquals = NIL;
1049-
cq_min_security = UINT_MAX;
1050-
have_const_false_cq = false;
1051-
foreach(lc, rel->baserestrictinfo)
1052-
{
1053-
RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1054-
Node *childqual;
1055-
ListCell *lc2;
1056-
1057-
Assert(IsA(rinfo, RestrictInfo));
1058-
childqual = adjust_appendrel_attrs(root,
1059-
(Node *) rinfo->clause,
1060-
1, &appinfo);
1061-
childqual = eval_const_expressions(root, childqual);
1062-
/* check for flat-out constant */
1063-
if (childqual && IsA(childqual, Const))
1064-
{
1065-
if (((Const *) childqual)->constisnull ||
1066-
!DatumGetBool(((Const *) childqual)->constvalue))
1067-
{
1068-
/* Restriction reduces to constant FALSE or NULL */
1069-
have_const_false_cq = true;
1070-
break;
1071-
}
1072-
/* Restriction reduces to constant TRUE, so drop it */
1073-
continue;
1074-
}
1075-
/* might have gotten an AND clause, if so flatten it */
1076-
foreach(lc2, make_ands_implicit((Expr *) childqual))
1077-
{
1078-
Node *onecq = (Node *) lfirst(lc2);
1079-
bool pseudoconstant;
1080-
1081-
/* check for pseudoconstant (no Vars or volatile functions) */
1082-
pseudoconstant =
1083-
!contain_vars_of_level(onecq, 0) &&
1084-
!contain_volatile_functions(onecq);
1085-
if (pseudoconstant)
1086-
{
1087-
/* tell createplan.c to check for gating quals */
1088-
root->hasPseudoConstantQuals = true;
1089-
}
1090-
/* reconstitute RestrictInfo with appropriate properties */
1091-
childquals = lappend(childquals,
1092-
make_restrictinfo((Expr *) onecq,
1093-
rinfo->is_pushed_down,
1094-
rinfo->outerjoin_delayed,
1095-
pseudoconstant,
1096-
rinfo->security_level,
1097-
NULL, NULL, NULL));
1098-
/* track minimum security level among child quals */
1099-
cq_min_security = Min(cq_min_security, rinfo->security_level);
1100-
}
1101-
}
1102-
1103-
/*
1104-
* In addition to the quals inherited from the parent, we might have
1105-
* securityQuals associated with this particular child node.
1106-
* (Currently this can only happen in appendrels originating from
1107-
* UNION ALL; inheritance child tables don't have their own
1108-
* securityQuals, see expand_inherited_rtentry().) Pull any such
1109-
* securityQuals up into the baserestrictinfo for the child. This is
1110-
* similar to process_security_barrier_quals() for the parent rel,
1111-
* except that we can't make any general deductions from such quals,
1112-
* since they don't hold for the whole appendrel.
1113-
*/
1114-
if (childRTE->securityQuals)
1033+
if (did_pruning && !bms_is_member(appinfo->child_relid, live_children))
11151034
{
1116-
Index security_level = 0;
1117-
1118-
foreach(lc, childRTE->securityQuals)
1119-
{
1120-
List *qualset = (List *) lfirst(lc);
1121-
ListCell *lc2;
1122-
1123-
foreach(lc2, qualset)
1124-
{
1125-
Expr *qual = (Expr *) lfirst(lc2);
1126-
1127-
/* not likely that we'd see constants here, so no check */
1128-
childquals = lappend(childquals,
1129-
make_restrictinfo(qual,
1130-
true, false, false,
1131-
security_level,
1132-
NULL, NULL, NULL));
1133-
cq_min_security = Min(cq_min_security, security_level);
1134-
}
1135-
security_level++;
1136-
}
1137-
Assert(security_level <= root->qual_security_level);
1035+
/* This partition was pruned; skip it. */
1036+
set_dummy_rel_pathlist(childrel);
1037+
continue;
11381038
}
11391039

11401040
/*
1141-
* OK, we've got all the baserestrictinfo quals for this child.
1041+
* We have to copy the parent's targetlist and quals to the child,
1042+
* with appropriate substitution of variables. If any constant false
1043+
* or NULL clauses turn up, we can disregard the child right away.
1044+
* If not, we can apply constraint exclusion with just the
1045+
* baserestrictinfo quals.
11421046
*/
1143-
childrel->baserestrictinfo = childquals;
1144-
childrel->baserestrict_min_security = cq_min_security;
1145-
1146-
if (have_const_false_cq)
1047+
if (!apply_child_basequals(root, rel, childrel, childRTE, appinfo))
11471048
{
11481049
/*
11491050
* Some restriction clause reduced to constant FALSE or NULL after
@@ -1153,13 +1054,6 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
11531054
continue;
11541055
}
11551056

1156-
if (did_pruning && !bms_is_member(appinfo->child_relid, live_children))
1157-
{
1158-
/* This partition was pruned; skip it. */
1159-
set_dummy_rel_pathlist(childrel);
1160-
continue;
1161-
}
1162-
11631057
if (relation_excluded_by_constraints(root, childrel, childRTE))
11641058
{
11651059
/*
@@ -3660,6 +3554,133 @@ generate_partitionwise_join_paths(PlannerInfo *root, RelOptInfo *rel)
36603554
list_free(live_children);
36613555
}
36623556

3557+
/*
3558+
* apply_child_basequals
3559+
* Populate childrel's quals based on rel's quals, translating them using
3560+
* appinfo.
3561+
*
3562+
* If any of the resulting clauses evaluate to false or NULL, we return false
3563+
* and don't apply any quals. Caller can mark the relation as a dummy rel in
3564+
* this case, since it needn't be scanned.
3565+
*
3566+
* If any resulting clauses evaluate to true, they're unnecessary and we don't
3567+
* apply then.
3568+
*/
3569+
static bool
3570+
apply_child_basequals(PlannerInfo *root, RelOptInfo *rel,
3571+
RelOptInfo *childrel, RangeTblEntry *childRTE,
3572+
AppendRelInfo *appinfo)
3573+
{
3574+
List *childquals;
3575+
Index cq_min_security;
3576+
ListCell *lc;
3577+
3578+
/*
3579+
* The child rel's targetlist might contain non-Var expressions, which
3580+
* means that substitution into the quals could produce opportunities for
3581+
* const-simplification, and perhaps even pseudoconstant quals. Therefore,
3582+
* transform each RestrictInfo separately to see if it reduces to a
3583+
* constant or pseudoconstant. (We must process them separately to keep
3584+
* track of the security level of each qual.)
3585+
*/
3586+
childquals = NIL;
3587+
cq_min_security = UINT_MAX;
3588+
foreach(lc, rel->baserestrictinfo)
3589+
{
3590+
RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
3591+
Node *childqual;
3592+
ListCell *lc2;
3593+
3594+
Assert(IsA(rinfo, RestrictInfo));
3595+
childqual = adjust_appendrel_attrs(root,
3596+
(Node *) rinfo->clause,
3597+
1, &appinfo);
3598+
childqual = eval_const_expressions(root, childqual);
3599+
/* check for flat-out constant */
3600+
if (childqual && IsA(childqual, Const))
3601+
{
3602+
if (((Const *) childqual)->constisnull ||
3603+
!DatumGetBool(((Const *) childqual)->constvalue))
3604+
{
3605+
/* Restriction reduces to constant FALSE or NULL */
3606+
return false;
3607+
}
3608+
/* Restriction reduces to constant TRUE, so drop it */
3609+
continue;
3610+
}
3611+
/* might have gotten an AND clause, if so flatten it */
3612+
foreach(lc2, make_ands_implicit((Expr *) childqual))
3613+
{
3614+
Node *onecq = (Node *) lfirst(lc2);
3615+
bool pseudoconstant;
3616+
3617+
/* check for pseudoconstant (no Vars or volatile functions) */
3618+
pseudoconstant =
3619+
!contain_vars_of_level(onecq, 0) &&
3620+
!contain_volatile_functions(onecq);
3621+
if (pseudoconstant)
3622+
{
3623+
/* tell createplan.c to check for gating quals */
3624+
root->hasPseudoConstantQuals = true;
3625+
}
3626+
/* reconstitute RestrictInfo with appropriate properties */
3627+
childquals = lappend(childquals,
3628+
make_restrictinfo((Expr *) onecq,
3629+
rinfo->is_pushed_down,
3630+
rinfo->outerjoin_delayed,
3631+
pseudoconstant,
3632+
rinfo->security_level,
3633+
NULL, NULL, NULL));
3634+
/* track minimum security level among child quals */
3635+
cq_min_security = Min(cq_min_security, rinfo->security_level);
3636+
}
3637+
}
3638+
3639+
/*
3640+
* In addition to the quals inherited from the parent, we might have
3641+
* securityQuals associated with this particular child node. (Currently
3642+
* this can only happen in appendrels originating from UNION ALL;
3643+
* inheritance child tables don't have their own securityQuals, see
3644+
* expand_inherited_rtentry().) Pull any such securityQuals up into the
3645+
* baserestrictinfo for the child. This is similar to
3646+
* process_security_barrier_quals() for the parent rel, except that we
3647+
* can't make any general deductions from such quals, since they don't
3648+
* hold for the whole appendrel.
3649+
*/
3650+
if (childRTE->securityQuals)
3651+
{
3652+
Index security_level = 0;
3653+
3654+
foreach(lc, childRTE->securityQuals)
3655+
{
3656+
List *qualset = (List *) lfirst(lc);
3657+
ListCell *lc2;
3658+
3659+
foreach(lc2, qualset)
3660+
{
3661+
Expr *qual = (Expr *) lfirst(lc2);
3662+
3663+
/* not likely that we'd see constants here, so no check */
3664+
childquals = lappend(childquals,
3665+
make_restrictinfo(qual,
3666+
true, false, false,
3667+
security_level,
3668+
NULL, NULL, NULL));
3669+
cq_min_security = Min(cq_min_security, security_level);
3670+
}
3671+
security_level++;
3672+
}
3673+
Assert(security_level <= root->qual_security_level);
3674+
}
3675+
3676+
/*
3677+
* OK, we've got all the baserestrictinfo quals for this child.
3678+
*/
3679+
childrel->baserestrictinfo = childquals;
3680+
childrel->baserestrict_min_security = cq_min_security;
3681+
3682+
return true;
3683+
}
36633684

36643685
/*****************************************************************************
36653686
* DEBUG SUPPORT

0 commit comments

Comments
 (0)