From 43005ebda2f694cd08dffd5674ffa4609ef5b8bc Mon Sep 17 00:00:00 2001
From: root <root@localhost.localdomain>
Date: Tue, 19 Jan 2021 20:04:45 -0500
Subject: [PATCH] add nullif case for eval_const_expressions

---
 src/backend/optimizer/util/clauses.c | 28 ++++++++++++++++++++++++++++
 src/test/regress/expected/case.out   | 25 +++++++++++++++++++++++++
 src/test/regress/sql/case.sql        | 11 +++++++++++
 3 files changed, 64 insertions(+)

diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 51d26a0..924b294 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -2430,6 +2430,34 @@ eval_const_expressions_mutator(Node *node,
 				newexpr->location = expr->location;
 				return (Node *) newexpr;
 			}
+		case T_NullIfExpr:
+			{
+				/*
+				 * Since NullIf is not common enough to deserve specially
+				 * optimized code, use ece_generic_processing and
+				 * ece_evaluate_expr to simplify the code as much as possible.
+				 */
+				NullIfExpr	   *expr;
+				ListCell	   *arg;
+				bool			has_nonconst_input = false;
+
+				/* Copy the node and const-simplify its arguments */
+				expr = (NullIfExpr *) ece_generic_processing(node);
+
+				/* If either argument is NULL they can't be equal */
+				foreach(arg, expr->args)
+				{
+					if (!IsA(lfirst(arg), Const))
+						has_nonconst_input = true;
+					else if (((Const *) lfirst(arg))->constisnull)
+						return (Node *) linitial(expr->args);
+				}
+
+				if (!has_nonconst_input)
+					return ece_evaluate_expr(expr);
+
+				return (Node *) expr;
+			}
 		case T_ScalarArrayOpExpr:
 			{
 				ScalarArrayOpExpr *saop;
diff --git a/src/test/regress/expected/case.out b/src/test/regress/expected/case.out
index 7fcfe9a..f5136c1 100644
--- a/src/test/regress/expected/case.out
+++ b/src/test/regress/expected/case.out
@@ -263,6 +263,31 @@ SELECT *
  4 |   | 2 | -4
 (2 rows)
 
+-- Tests for constant subexpression simplification
+explain (costs off)
+SELECT * FROM CASE_TBL WHERE NULLIF(1, 2) = 2;
+        QUERY PLAN        
+--------------------------
+ Result
+   One-Time Filter: false
+(2 rows)
+
+explain (costs off)
+SELECT * FROM CASE_TBL WHERE NULLIF(1, 1) IS NOT NULL;
+        QUERY PLAN        
+--------------------------
+ Result
+   One-Time Filter: false
+(2 rows)
+
+explain (costs off)
+SELECT * FROM CASE_TBL WHERE NULLIF(1, null) = 2;
+        QUERY PLAN        
+--------------------------
+ Result
+   One-Time Filter: false
+(2 rows)
+
 --
 -- Examples of updates involving tables
 --
diff --git a/src/test/regress/sql/case.sql b/src/test/regress/sql/case.sql
index 0655d26..83fe43b 100644
--- a/src/test/regress/sql/case.sql
+++ b/src/test/regress/sql/case.sql
@@ -137,6 +137,17 @@ SELECT *
   FROM CASE_TBL a, CASE2_TBL b
   WHERE COALESCE(f,b.i) = 2;
 
+-- Tests for constant subexpression simplification
+
+explain (costs off)
+SELECT * FROM CASE_TBL WHERE NULLIF(1, 2) = 2;
+
+explain (costs off)
+SELECT * FROM CASE_TBL WHERE NULLIF(1, 1) IS NOT NULL;
+
+explain (costs off)
+SELECT * FROM CASE_TBL WHERE NULLIF(1, null) = 2;
+
 --
 -- Examples of updates involving tables
 --
-- 
1.8.3.1

