@@ -138,6 +138,9 @@ static void subquery_push_qual(Query *subquery,
138138static void recurse_push_qual (Node * setOp , Query * topquery ,
139139 RangeTblEntry * rte , Index rti , Node * qual );
140140static 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