pg_18_1_fix_restriction_is_always_true.patch
application/x-patch
Filename: pg_18_1_fix_restriction_is_always_true.patch
Type: application/x-patch
Part: 0
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index 01804b085b3..43642b0de64 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -3002,9 +3002,80 @@ add_base_clause_to_rel(PlannerInfo *root, Index relid,
*/
if (!rte->inh || rte->relkind == RELKIND_PARTITIONED_TABLE)
{
- /* Don't add the clause if it is always true */
+ /*
+ * Don't add the clause if it is always true. However, we must keep
+ * IS NOT NULL clauses if a partial index needs them to prove its
+ * predicate is satisfied. Without this, a partial index with
+ * predicate "WHERE col IS NOT NULL" would not be usable for min/max
+ * optimization on a NOT NULL column, because the IS NOT NULL clause
+ * would be removed as "always true" before check_index_predicates
+ * runs.
+ */
if (restriction_is_always_true(root, restrictinfo))
- return;
+ {
+ bool dominated_by_notnull = false;
+
+ /*
+ * Check if this is an IS NOT NULL clause on a simple Var that
+ * matches an IS NOT NULL predicate in some partial index.
+ */
+ if (IsA(restrictinfo->clause, NullTest))
+ {
+ NullTest *ntest = (NullTest *) restrictinfo->clause;
+
+ if (ntest->nulltesttype == IS_NOT_NULL &&
+ IsA(ntest->arg, Var))
+ {
+ Var *var = (Var *) ntest->arg;
+ ListCell *lc;
+
+ foreach(lc, rel->indexlist)
+ {
+ IndexOptInfo *index = (IndexOptInfo *) lfirst(lc);
+ ListCell *lcp;
+
+ /* Skip non-partial indexes */
+ if (index->indpred == NIL)
+ continue;
+
+ /* Check each predicate clause */
+ foreach(lcp, index->indpred)
+ {
+ Node *pred = (Node *) lfirst(lcp);
+
+ if (IsA(pred, NullTest))
+ {
+ NullTest *pntest = (NullTest *) pred;
+
+ if (pntest->nulltesttype == IS_NOT_NULL &&
+ IsA(pntest->arg, Var))
+ {
+ Var *pvar = (Var *) pntest->arg;
+
+ /*
+ * Match if same column. The varno in the
+ * index predicate should already be
+ * adjusted to match the relation.
+ */
+ if (pvar->varno == var->varno &&
+ pvar->varattno == var->varattno)
+ {
+ dominated_by_notnull = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (dominated_by_notnull)
+ break;
+ }
+ }
+ }
+
+ if (!dominated_by_notnull)
+ return;
+ }
/*
* Substitute the origin qual with constant-FALSE if it is provably