v2-0001-Disregard-nulls-in-SAOP-rightarg-array-list-durin.patch

text/plain

Filename: v2-0001-Disregard-nulls-in-SAOP-rightarg-array-list-durin.patch
Type: text/plain
Part: 0
Message: Re: constraint exclusion and nulls in IN (..) clause

Patch

Format: format-patch
Series: patch v2-0001
Subject: Disregard nulls in SAOP rightarg array/list during CE
File+
src/backend/optimizer/util/predtest.c 28 0
src/test/regress/expected/inherit.out 1 5
From b68afd6323852b7a503e634aef3699b922b9d567 Mon Sep 17 00:00:00 2001
From: amit <amitlangote09@gmail.com>
Date: Thu, 1 Feb 2018 11:32:23 +0900
Subject: [PATCH v2] Disregard nulls in SAOP rightarg array/list during CE

---
 src/backend/optimizer/util/predtest.c | 28 ++++++++++++++++++++++++++++
 src/test/regress/expected/inherit.out |  6 +-----
 2 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c
index 8106010329..5efd7f688b 100644
--- a/src/backend/optimizer/util/predtest.c
+++ b/src/backend/optimizer/util/predtest.c
@@ -905,6 +905,7 @@ boolexpr_startup_fn(Node *clause, PredIterInfo info)
 typedef struct
 {
 	OpExpr		opexpr;
+	bool		opisstrict;		/* Is the operator strict? */
 	Const		constexpr;
 	int			next_elem;
 	int			num_elems;
@@ -957,6 +958,12 @@ arrayconst_startup_fn(Node *clause, PredIterInfo info)
 	state->constexpr.constbyval = elmbyval;
 	lsecond(state->opexpr.args) = &state->constexpr;
 
+	/*
+	 * Record if the operator is strict to perform appropriate action on
+	 * encountering null values in the element array.
+	 */
+	state->opisstrict = op_strict(saop->opno);
+
 	/* Initialize iteration state */
 	state->next_elem = 0;
 }
@@ -968,6 +975,12 @@ arrayconst_next_fn(PredIterInfo info)
 
 	if (state->next_elem >= state->num_elems)
 		return NULL;
+	/* skip nulls if ok to do so */
+	if (state->opisstrict)
+	{
+		while (state->elem_nulls[state->next_elem])
+			state->next_elem++;
+	}
 	state->constexpr.constvalue = state->elem_values[state->next_elem];
 	state->constexpr.constisnull = state->elem_nulls[state->next_elem];
 	state->next_elem++;
@@ -992,6 +1005,7 @@ arrayconst_cleanup_fn(PredIterInfo info)
 typedef struct
 {
 	OpExpr		opexpr;
+	bool		opisstrict;		/* Is the operator strict? */
 	ListCell   *next;
 } ArrayExprIterState;
 
@@ -1016,6 +1030,12 @@ arrayexpr_startup_fn(Node *clause, PredIterInfo info)
 	state->opexpr.inputcollid = saop->inputcollid;
 	state->opexpr.args = list_copy(saop->args);
 
+	/*
+	 * Record if the operator is strict to perform appropriate action on
+	 * encountering null values in the element array.
+	 */
+	state->opisstrict = op_strict(saop->opno);
+
 	/* Initialize iteration variable to first member of ArrayExpr */
 	arrayexpr = (ArrayExpr *) lsecond(saop->args);
 	state->next = list_head(arrayexpr->elements);
@@ -1028,6 +1048,14 @@ arrayexpr_next_fn(PredIterInfo info)
 
 	if (state->next == NULL)
 		return NULL;
+	/* skip nulls if ok to do so */
+	if (state->opisstrict)
+	{
+		Node *node = (Node *) lfirst(state->next);
+
+		while (IsA(node, Const) && ((Const *) node)->constisnull)
+			state->next = lnext(state->next);
+	}
 	lsecond(state->opexpr.args) = lfirst(state->next);
 	state->next = lnext(state->next);
 	return (Node *) &(state->opexpr);
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
index a79f891da7..d56e5d25d9 100644
--- a/src/test/regress/expected/inherit.out
+++ b/src/test/regress/expected/inherit.out
@@ -1715,11 +1715,7 @@ explain (costs off) select * from list_parted where a = 'ab' or a in (null, 'cd'
  Append
    ->  Seq Scan on part_ab_cd
          Filter: (((a)::text = 'ab'::text) OR ((a)::text = ANY ('{NULL,cd}'::text[])))
-   ->  Seq Scan on part_ef_gh
-         Filter: (((a)::text = 'ab'::text) OR ((a)::text = ANY ('{NULL,cd}'::text[])))
-   ->  Seq Scan on part_null_xy
-         Filter: (((a)::text = 'ab'::text) OR ((a)::text = ANY ('{NULL,cd}'::text[])))
-(7 rows)
+(3 rows)
 
 explain (costs off) select * from list_parted where a = 'ab';
                 QUERY PLAN                
-- 
2.11.0