@@ -170,7 +170,8 @@ static PruneStepResult *perform_pruning_combine_step(PartitionPruneContext *cont
170
170
static bool match_boolean_partition_clause (Oid partopfamily , Expr * clause ,
171
171
Expr * partkey , Expr * * outconst );
172
172
static bool partkey_datum_from_expr (PartitionPruneContext * context ,
173
- Expr * expr , int stateidx , Datum * value );
173
+ Expr * expr , int stateidx ,
174
+ Datum * value , bool * isnull );
174
175
175
176
176
177
/*
@@ -184,8 +185,9 @@ static bool partkey_datum_from_expr(PartitionPruneContext *context,
184
185
* indexes.
185
186
*
186
187
* If no non-Const expressions are being compared to the partition key in any
187
- * of the 'partitioned_rels', then we return NIL. In such a case run-time
188
- * partition pruning would be useless, since the planner did it already.
188
+ * of the 'partitioned_rels', then we return NIL to indicate no run-time
189
+ * pruning should be performed. Run-time pruning would be useless, since the
190
+ * pruning done during planning will have pruned everything that can be.
189
191
*/
190
192
List *
191
193
make_partition_pruneinfo (PlannerInfo * root , List * partition_rels ,
@@ -2835,14 +2837,33 @@ perform_pruning_base_step(PartitionPruneContext *context,
2835
2837
Expr * expr ;
2836
2838
int stateidx ;
2837
2839
Datum datum ;
2840
+ bool isnull ;
2838
2841
2839
2842
expr = lfirst (lc1 );
2840
2843
stateidx = PruneCxtStateIdx (context -> partnatts ,
2841
2844
opstep -> step .step_id , keyno );
2842
- if (partkey_datum_from_expr (context , expr , stateidx , & datum ))
2845
+ if (partkey_datum_from_expr (context , expr , stateidx ,
2846
+ & datum , & isnull ))
2843
2847
{
2844
2848
Oid cmpfn ;
2845
2849
2850
+ /*
2851
+ * Since we only allow strict operators in pruning steps, any
2852
+ * null-valued comparison value must cause the comparison to
2853
+ * fail, so that no partitions could match.
2854
+ */
2855
+ if (isnull )
2856
+ {
2857
+ PruneStepResult * result ;
2858
+
2859
+ result = (PruneStepResult * ) palloc (sizeof (PruneStepResult ));
2860
+ result -> bound_offsets = NULL ;
2861
+ result -> scan_default = false;
2862
+ result -> scan_null = false;
2863
+
2864
+ return result ;
2865
+ }
2866
+
2846
2867
/*
2847
2868
* If we're going to need a different comparison function than
2848
2869
* the one cached in the PartitionKey, we'll need to look up
@@ -3072,8 +3093,8 @@ match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey,
3072
3093
* Evaluate expression for potential partition pruning
3073
3094
*
3074
3095
* Evaluate 'expr', whose ExprState is stateidx of the context exprstate
3075
- * array; set *value to the resulting Datum. Return true if evaluation was
3076
- * possible, otherwise false.
3096
+ * array; set *value and *isnull to the resulting Datum and nullflag.
3097
+ * Return true if evaluation was possible, otherwise false.
3077
3098
*
3078
3099
* Note that the evaluated result may be in the per-tuple memory context of
3079
3100
* context->planstate->ps_ExprContext, and we may have leaked other memory
@@ -3082,11 +3103,16 @@ match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey,
3082
3103
*/
3083
3104
static bool
3084
3105
partkey_datum_from_expr (PartitionPruneContext * context ,
3085
- Expr * expr , int stateidx , Datum * value )
3106
+ Expr * expr , int stateidx ,
3107
+ Datum * value , bool * isnull )
3086
3108
{
3087
3109
if (IsA (expr , Const ))
3088
3110
{
3089
- * value = ((Const * ) expr )-> constvalue ;
3111
+ /* We can always determine the value of a constant */
3112
+ Const * con = (Const * ) expr ;
3113
+
3114
+ * value = con -> constvalue ;
3115
+ * isnull = con -> constisnull ;
3090
3116
return true;
3091
3117
}
3092
3118
else
@@ -3105,14 +3131,10 @@ partkey_datum_from_expr(PartitionPruneContext *context,
3105
3131
{
3106
3132
ExprState * exprstate ;
3107
3133
ExprContext * ectx ;
3108
- bool isNull ;
3109
3134
3110
3135
exprstate = context -> exprstates [stateidx ];
3111
3136
ectx = context -> planstate -> ps_ExprContext ;
3112
- * value = ExecEvalExprSwitchContext (exprstate , ectx , & isNull );
3113
- if (isNull )
3114
- return false;
3115
-
3137
+ * value = ExecEvalExprSwitchContext (exprstate , ectx , isnull );
3116
3138
return true;
3117
3139
}
3118
3140
}
0 commit comments