From 182ff831442886e2be8fd4f30d6253f682174ba1 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Thu, 11 May 2017 17:11:47 +0300
Subject: [PATCH 1/1] Const-eval ScalarArrayOpExprs

---
 src/backend/optimizer/util/clauses.c | 44 ++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index a1dafc8e0f..16ac1af40c 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -2657,6 +2657,50 @@ eval_const_expressions_mutator(Node *node,
 				newexpr->location = expr->location;
 				return (Node *) newexpr;
 			}
+		case T_ScalarArrayOpExpr:
+			{
+				ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
+				List	   *args;
+				ScalarArrayOpExpr *newexpr;
+				Expr	   *scalararg;
+				Expr	   *arrayarg;
+
+				/*
+				 * Need to get OID of underlying function.  Okay to scribble
+				 * on input to this extent.
+				 */
+				set_sa_opfuncid(expr);
+
+				/* Reduce constants in the scalar and array arguments. */
+				args = (List *) expression_tree_mutator((Node *) expr->args,
+											  eval_const_expressions_mutator,
+														(void *) context);
+
+				newexpr = makeNode(ScalarArrayOpExpr);
+				newexpr->opno = expr->opno;
+				newexpr->opfuncid = expr->opfuncid;
+				newexpr->useOr = expr->useOr;
+				newexpr->inputcollid = expr->inputcollid;
+				newexpr->args = args;
+				newexpr->location = expr->location;
+
+				Assert(list_length(args) == 2);
+				scalararg = (Expr *) linitial(newexpr->args);
+				arrayarg = (Expr *) lsecond(newexpr->args);
+
+				/*
+				 * If constant arguments, and it's an immutable function, we
+				 * can evaluate it now.
+				 */
+				if (IsA(scalararg, Const) && IsA(arrayarg, Const) &&
+					func_volatile(expr->opfuncid) == PROVOLATILE_IMMUTABLE)
+					return (Node *) evaluate_expr((Expr *) newexpr,
+												  BOOLOID,
+												  -1,
+												  InvalidOid);
+
+				return (Node *) newexpr;
+			}
 		case T_DistinctExpr:
 			{
 				DistinctExpr *expr = (DistinctExpr *) node;
-- 
2.11.0

