From 0bfed151e366b2e0389356613713ae33d859382e Mon Sep 17 00:00:00 2001
From: Corey Huinker <corey.huinker@gmail.com>
Date: Wed, 13 Dec 2023 04:00:47 -0500
Subject: [PATCH v3 8/9] Allow explicit nulls in container lookups.

Allow key_lookup_object() and key_lookup_array() to treat explicit JSONB
jbvNull values the same as if the key were omitted entirely.

This allows export functions to create the keyed object via a query
without worrying about removing the key if there is no underlying data.

Also, having a key existing with an affirmative "there is no data here"
is more clear than the key missing.
---
 src/backend/statistics/statistics.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/src/backend/statistics/statistics.c b/src/backend/statistics/statistics.c
index e54f1c9162..b1f0396d47 100644
--- a/src/backend/statistics/statistics.c
+++ b/src/backend/statistics/statistics.c
@@ -528,16 +528,19 @@ JsonbContainer *key_lookup_object(JsonbContainer *cont, const char *key)
 	if (!getKeyJsonValueFromContainer(cont, key, strlen(key), &j))
 		return NULL;
 
+	if (j.type == jbvNull)
+		return NULL;
+
 	if (j.type != jbvBinary)
 		ereport(ERROR,
 		  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-		   errmsg("invalid statistics format, %s must be an object but is type %s",
+		   errmsg("invalid statistics format, %s must be an object or null but is type %s",
 				  key, JsonbTypeName(&j))));
 
 	if (!JsonContainerIsObject(j.val.binary.data))
 		ereport(ERROR,
 		  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-		   errmsg("invalid statistics format, %s must be an object but is type %s",
+		   errmsg("invalid statistics format, %s must be an object or null but is type %s",
 				  key, JsonbContainerTypeName(j.val.binary.data))));
 
 	return j.val.binary.data;
@@ -553,16 +556,19 @@ JsonbContainer *key_lookup_array(JsonbContainer *cont, const char *key)
 	if (!getKeyJsonValueFromContainer(cont, key, strlen(key), &j))
 		return NULL;
 
+	if (j.type == jbvNull)
+		return NULL;
+
 	if (j.type != jbvBinary)
 		ereport(ERROR,
 		  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-		   errmsg("invalid statistics format, %s must be an array but is type %s",
+		   errmsg("invalid statistics format, %s must be an array or null but is type %s",
 				  key, JsonbTypeName(&j))));
 
 	if (!JsonContainerIsArray(j.val.binary.data))
 		ereport(ERROR,
 		  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-		   errmsg("invalid statistics format, %s must be an array but is type %s",
+		   errmsg("invalid statistics format, %s must be an array or null but is type %s",
 				  key, JsonbContainerTypeName(j.val.binary.data))));
 
 	return j.val.binary.data;
-- 
2.43.0

