From d046a4bea07a09b2e5bc519b16b331713523ee65 Mon Sep 17 00:00:00 2001
From: Svetlana Derevyanko <s.derevyanko@postgrespro.ru>
Date: Fri, 5 Dec 2025 10:37:17 +0300
Subject: [PATCH v1] Teach STRICT functions with VARIADIC "any" arguments to
 distinguish between NULL element and NULL array

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

diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index bda4c4eb292..4a261866d95 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -4616,6 +4616,8 @@ evaluate_function(Oid funcid, Oid result_type, int32 result_typmod,
 	Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
 	bool		has_nonconst_input = false;
 	bool		has_null_input = false;
+	bool		has_variadic_null = false;
+	int			i = 0;
 	ListCell   *arg;
 	FuncExpr   *newexpr;
 
@@ -4644,11 +4646,34 @@ evaluate_function(Oid funcid, Oid result_type, int32 result_typmod,
 	foreach(arg, args)
 	{
 		if (IsA(lfirst(arg), Const))
-			has_null_input |= ((Const *) lfirst(arg))->constisnull;
+		{
+			if (i < funcform->pronargs - 1)
+				has_null_input |= ((Const *) lfirst(arg))->constisnull;
+			else
+			{
+				/*
+				 * For VARIADIC "any" last args are not constructed into an
+				 * array, but funcform->pronargs is calculated as if they
+				 * were. However, we still want has_null_input to not be set
+				 * in true if null argument is part of the VARIADIC array.
+				 */
+				if (funcform->provariadic)
+				{
+					has_variadic_null |= ((Const *) lfirst(arg))->constisnull;
+				}
+				else			/* last argument for non-variadic */
+					has_null_input |= ((Const *) lfirst(arg))->constisnull;
+			}
+		}
 		else
 			has_nonconst_input = true;
+		i++;
 	}
 
+	/* VARIADIC "any" argument is null. */
+	if (has_variadic_null && (i == funcform->pronargs))
+		has_null_input |= has_variadic_null;
+
 	/*
 	 * If the function is strict and has a constant-NULL input, it will never
 	 * be called at all, so we can replace the call by a NULL constant, even
-- 
2.34.1

