v1-delta.patch

text/plain

Filename: v1-delta.patch
Type: text/plain
Part: 0
Message: Re: Problem with default partition pruning

Patch

Format: unified
Series: patch v1
File+
src/backend/partitioning/partprune.c 29 23
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c
index 8317318156..aa32a50477 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -795,6 +795,27 @@ gen_partprune_steps_internal(GeneratePruningStepsContext *context,
 					Expr	   *arg = lfirst(lc1);
 					bool		arg_contradictory;
 					List	   *argsteps;
+					List	   *partconstr = rel->partition_qual;
+
+					/*
+					 * If this OR argument can be proved false for this
+					 * partition, given its partition constraint, we can
+					 * ignore it, that is not try to pass it to the pruning
+					 * code.  We should do that especially to avoid pruning
+					 * code wrongly failing to prune the default partition.
+					 */
+					if (partconstr)
+					{
+						partconstr = (List *)
+							expression_planner((Expr *) partconstr);
+						if (rel->relid != 1)
+							ChangeVarNodes((Node *) partconstr, 1,
+										   rel->relid, 0);
+						if (predicate_refuted_by(partconstr,
+												 list_make1(arg),
+												 false))
+							continue;
+					}
 
 					argsteps =
 						gen_partprune_steps_internal(context, rel,
@@ -822,32 +843,13 @@ gen_partprune_steps_internal(GeneratePruningStepsContext *context,
 						 * an arg.  To indicate that to the pruning code, we
 						 * must construct a dummy PartitionPruneStepCombine
 						 * whose source_stepids is set to an empty List.
-						 * However, if we can prove using constraint exclusion
-						 * that the clause refutes the table's partition
-						 * constraint (if it's sub-partitioned), we need not
-						 * bother with that.  That is, we effectively ignore
-						 * this OR arm.
 						 */
-						List	   *partconstr = rel->partition_qual;
 						PartitionPruneStep *orstep;
 
 						/* Just ignore this argument. */
 						if (arg_contradictory)
 							continue;
 
-						if (partconstr)
-						{
-							partconstr = (List *)
-								expression_planner((Expr *) partconstr);
-							if (rel->relid != 1)
-								ChangeVarNodes((Node *) partconstr, 1,
-											   rel->relid, 0);
-							if (predicate_refuted_by(partconstr,
-													 list_make1(arg),
-													 false))
-								continue;
-						}
-
 						orstep = gen_prune_step_combine(context, NIL,
 														PARTPRUNE_COMBINE_UNION);
 						arg_stepids = lappend_int(arg_stepids, orstep->step_id);
@@ -2759,15 +2761,19 @@ get_matching_range_bounds(PartitionPruneContext *context,
 				 * instead as the offset of the upper bound of the greatest
 				 * partition that may contain lookup value.  If the lookup
 				 * value had exactly matched the bound, but it isn't
-				 * inclusive, no need add the adjacent partition.  If 'off' is
-				 * -1 indicating that all bounds are greater, then we simply
-				 * end up adding the first bound's offset, that is, 0.
+				 * inclusive, no need add the adjacent partition.
 				 */
-				else if (off < 0 || !is_equal || inclusive)
+				else if (!is_equal || inclusive)
 					maxoff = off + 1;
 				else
 					maxoff = off;
 			}
+			else
+				/*
+				 * 'off' is -1 indicating that all bounds are greater, so just
+				 * set the first bound's offset as maxoff.
+				 */
+				maxoff = off + 1;
 			break;
 
 		default: