@@ -138,6 +138,9 @@ static void subquery_push_qual(Query *subquery,
138
138
static void recurse_push_qual (Node * setOp , Query * topquery ,
139
139
RangeTblEntry * rte , Index rti , Node * qual );
140
140
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 );
141
144
142
145
143
146
/*
@@ -1010,12 +1013,8 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
1010
1013
int childRTindex ;
1011
1014
RangeTblEntry * childRTE ;
1012
1015
RelOptInfo * childrel ;
1013
- List * childquals ;
1014
- Index cq_min_security ;
1015
- bool have_const_false_cq ;
1016
1016
ListCell * parentvars ;
1017
1017
ListCell * childvars ;
1018
- ListCell * lc ;
1019
1018
1020
1019
/* append_rel_list contains all append rels; ignore others */
1021
1020
if (appinfo -> parent_relid != parentRTindex )
@@ -1031,119 +1030,21 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
1031
1030
childrel = find_base_rel (root , childRTindex );
1032
1031
Assert (childrel -> reloptkind == RELOPT_OTHER_MEMBER_REL );
1033
1032
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 ))
1115
1034
{
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 ;
1138
1038
}
1139
1039
1140
1040
/*
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.
1142
1046
*/
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 ))
1147
1048
{
1148
1049
/*
1149
1050
* Some restriction clause reduced to constant FALSE or NULL after
@@ -1153,13 +1054,6 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
1153
1054
continue ;
1154
1055
}
1155
1056
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
-
1163
1057
if (relation_excluded_by_constraints (root , childrel , childRTE ))
1164
1058
{
1165
1059
/*
@@ -3660,6 +3554,133 @@ generate_partitionwise_join_paths(PlannerInfo *root, RelOptInfo *rel)
3660
3554
list_free (live_children );
3661
3555
}
3662
3556
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
+ }
3663
3684
3664
3685
/*****************************************************************************
3665
3686
* DEBUG SUPPORT
0 commit comments