v15-0001-miscellaneous-refactoring-tests-for-v15.no-cfbot

application/octet-stream

Filename: v15-0001-miscellaneous-refactoring-tests-for-v15.no-cfbot
Type: application/octet-stream
Part: 0
Message: Re: Extended Statistics set/restore/clear functions.
From dbbba5eb02e4466e8d477a6fef89cc437d57690c Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Wed, 19 Nov 2025 15:40:20 +0800
Subject: [PATCH v15 1/1] miscellaneous refactoring/tests for v15

discussion: https://postgr.es/m/CADkLM=czQ0UUyBn3AiHZfJJWRwXH5e2xn056yG0mpuXpW09RSw@mail.gmail.com
---
 src/backend/utils/adt/pg_ndistinct.c       | 38 ++++++++++++----------
 src/test/regress/expected/pg_ndistinct.out | 36 +++++++++++++++++---
 src/test/regress/sql/pg_ndistinct.sql      |  5 +++
 3 files changed, 57 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/adt/pg_ndistinct.c b/src/backend/utils/adt/pg_ndistinct.c
index 87bc3cf41ae..b777f142f37 100644
--- a/src/backend/utils/adt/pg_ndistinct.c
+++ b/src/backend/utils/adt/pg_ndistinct.c
@@ -33,7 +33,7 @@ typedef enum
 	NDIST_EXPECT_ATTNUM_LIST,
 	NDIST_EXPECT_ATTNUM,
 	NDIST_EXPECT_NDISTINCT,
-	NDIST_EXPECT_COMPLETE
+	NDIST_EXPECT_COMPLETE,
 } NDistinctSemanticState;
 
 typedef struct
@@ -116,6 +116,7 @@ ndistinct_object_start(void *state)
 					errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
 					errdetail("Unexpected parse state: %d", (int) parse->state));
+			break;
 	}
 
 	return JSON_SEM_ACTION_FAILED;
@@ -176,7 +177,7 @@ ndistinct_object_end(void *state)
 				errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
 				errdetail("The \"%s\" key must contain an array of at least %d "
 						  "and no more than %d attributes.",
-						  PG_NDISTINCT_KEY_NDISTINCT, 2, STATS_MAX_DIMENSIONS));
+						  PG_NDISTINCT_KEY_ATTRIBUTES, 2, STATS_MAX_DIMENSIONS));
 		return JSON_SEM_ACTION_FAILED;
 	}
 
@@ -247,7 +248,7 @@ ndistinct_array_end(void *state)
 	switch (parse->state)
 	{
 		case NDIST_EXPECT_ATTNUM:
-			if (parse->attnum_list != NIL)
+			if (list_length(parse->attnum_list) > 0)
 			{
 				/*
 				 * The attribute number list is complete, look for more
@@ -265,7 +266,7 @@ ndistinct_array_end(void *state)
 			break;
 
 		case NDIST_EXPECT_ITEM:
-			if (parse->distinct_items != NIL)
+			if (list_length(parse->distinct_items) > 0)
 			{
 				/* Item list is complete, we are done. */
 				parse->state = NDIST_EXPECT_COMPLETE;
@@ -287,6 +288,7 @@ ndistinct_array_end(void *state)
 					errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
 					errdetail("Array found in unexpected place."));
+			break;
 	}
 
 	return JSON_SEM_ACTION_FAILED;
@@ -326,7 +328,7 @@ ndistinct_object_field_start(void *state, char *fname, bool isnull)
 					errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
 					errdetail("Multiple \"%s\" keys are not allowed.",
-							PG_NDISTINCT_KEY_NDISTINCT));
+							  PG_NDISTINCT_KEY_NDISTINCT));
 			return JSON_SEM_ACTION_FAILED;
 		}
 		parse->found_ndistinct = true;
@@ -379,6 +381,7 @@ ndistinct_array_element_start(void *state, bool isnull)
 					errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
 					errdetail("Unexpected array element."));
+			break;
 	}
 
 	return JSON_SEM_ACTION_FAILED;
@@ -444,11 +447,11 @@ ndistinct_scalar(void *state, char *token, JsonTokenType tokentype)
 						errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 						errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
 						errdetail("Invalid \"%s\" element: %d.",
-									PG_NDISTINCT_KEY_ATTRIBUTES, attnum));
+								  PG_NDISTINCT_KEY_ATTRIBUTES, attnum));
 				return JSON_SEM_ACTION_FAILED;
 			}
 
-			if (parse->attnum_list != NIL)
+			if (list_length(parse->attnum_list) > 0)
 			{
 				const AttrNumber prev = llast_int(parse->attnum_list);
 
@@ -463,7 +466,7 @@ ndistinct_scalar(void *state, char *token, JsonTokenType tokentype)
 				}
 			}
 
-			parse->attnum_list = lappend_int(parse->attnum_list, (int) attnum);
+			parse->attnum_list = lappend_int(parse->attnum_list, attnum);
 			return JSON_SUCCESS;
 			break;
 
@@ -493,6 +496,7 @@ ndistinct_scalar(void *state, char *token, JsonTokenType tokentype)
 					errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
 					errdetail("Unexpected scalar."));
+			break;
 	}
 
 	return JSON_SEM_ACTION_FAILED;
@@ -614,7 +618,7 @@ pg_ndistinct_in(PG_FUNCTION_ARGS)
 	if (result == JSON_SUCCESS)
 	{
 		MVNDistinct *ndistinct;
-		int			nitems = parse_state.distinct_items->length;
+		int			nitems =  list_length(parse_state.distinct_items);
 		bytea	   *bytes;
 
 		switch (parse_state.state)
@@ -626,7 +630,7 @@ pg_ndistinct_in(PG_FUNCTION_ARGS)
 				 * items.  If we don't, something has been done wrong in one
 				 * of the earlier parsing steps.
 				 */
-				if (parse_state.distinct_items == NIL)
+				if (list_length(parse_state.distinct_items) == 0)
 					elog(ERROR,
 						 "cannot have empty item list after parsing success.");
 				break;
@@ -657,15 +661,15 @@ pg_ndistinct_in(PG_FUNCTION_ARGS)
 		ndistinct->type = STATS_NDISTINCT_TYPE_BASIC;
 		ndistinct->nitems = nitems;
 
-		for (int i = 0; i < nitems; i++)
+		foreach_ptr(MVNDistinctItem, item, parse_state.distinct_items)
 		{
-			MVNDistinctItem *item = parse_state.distinct_items->elements[i].ptr_value;
+			int		idx = foreach_current_index(item);
 
 			/*
 			 * Ensure that this item does not duplicate the attributes of any
 			 * pre-existing item.
 			 */
-			for (int j = 0; j < i; j++)
+			for (int j = 0; j < idx; j++)
 			{
 				if (has_duplicate_attributes(item, &ndistinct->items[j]))
 				{
@@ -679,9 +683,9 @@ pg_ndistinct_in(PG_FUNCTION_ARGS)
 				}
 			}
 
-			ndistinct->items[i].ndistinct = item->ndistinct;
-			ndistinct->items[i].nattributes = item->nattributes;
-			ndistinct->items[i].attributes = item->attributes;
+			ndistinct->items[idx].ndistinct = item->ndistinct;
+			ndistinct->items[idx].nattributes = item->nattributes;
+			ndistinct->items[idx].attributes = item->attributes;
 
 			/*
 			 * Keep track of the first longest attribute list. All other
@@ -690,7 +694,7 @@ pg_ndistinct_in(PG_FUNCTION_ARGS)
 			if (item->nattributes > item_most_attrs)
 			{
 				item_most_attrs = item->nattributes;
-				item_most_attrs_idx = i;
+				item_most_attrs_idx = idx;
 			}
 
 			/*
diff --git a/src/test/regress/expected/pg_ndistinct.out b/src/test/regress/expected/pg_ndistinct.out
index eb3f74a3fff..d2f59efdc15 100644
--- a/src/test/regress/expected/pg_ndistinct.out
+++ b/src/test/regress/expected/pg_ndistinct.out
@@ -71,6 +71,11 @@ ERROR:  malformed pg_ndistinct: "[{"attributes" : [2,3], "attributes" : [1,3], "
 LINE 1: SELECT '[{"attributes" : [2,3], "attributes" : [1,3], "ndist...
                ^
 DETAIL:  Multiple "attributes" keys are not allowed.
+SELECT '[{"attributes" : [2,3], "ndistinct" : 4, "ndistinct" : 4}]'::pg_ndistinct;
+ERROR:  malformed pg_ndistinct: "[{"attributes" : [2,3], "ndistinct" : 4, "ndistinct" : 4}]"
+LINE 1: SELECT '[{"attributes" : [2,3], "ndistinct" : 4, "ndistinct"...
+               ^
+DETAIL:  Multiple "ndistinct" keys are not allowed.
 SELECT * FROM pg_input_error_info('[{"attributes_invalid" : [2,3], "ndistinct" : 4}]', 'pg_ndistinct');
                                    message                                   |                       detail                        | hint | sql_error_code 
 -----------------------------------------------------------------------------+-----------------------------------------------------+------+----------------
@@ -89,6 +94,12 @@ SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "attributes" : [1,3],
  malformed pg_ndistinct: "[{"attributes" : [2,3], "attributes" : [1,3], "ndistinct" : 4}]" | Multiple "attributes" keys are not allowed. |      | 22P02
 (1 row)
 
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "ndistinct" : 4, "ndistinct" : 4}]', 'pg_ndistinct');
+                                       message                                        |                   detail                   | hint | sql_error_code 
+--------------------------------------------------------------------------------------+--------------------------------------------+------+----------------
+ malformed pg_ndistinct: "[{"attributes" : [2,3], "ndistinct" : 4, "ndistinct" : 4}]" | Multiple "ndistinct" keys are not allowed. |      | 22P02
+(1 row)
+
 -- Missing key
 SELECT '[{"attributes" : [2,3]}]'::pg_ndistinct;
 ERROR:  malformed pg_ndistinct: "[{"attributes" : [2,3]}]"
@@ -117,7 +128,7 @@ SELECT '[{"attributes" : [1,2,3,4,5,6,7,8,9], "ndistinct" : 4}]'::pg_ndistinct;
 ERROR:  malformed pg_ndistinct: "[{"attributes" : [1,2,3,4,5,6,7,8,9], "ndistinct" : 4}]"
 LINE 1: SELECT '[{"attributes" : [1,2,3,4,5,6,7,8,9], "ndistinct" : ...
                ^
-DETAIL:  The "ndistinct" key must contain an array of at least 2 and no more than 8 attributes.
+DETAIL:  The "attributes" key must contain an array of at least 2 and no more than 8 attributes.
 -- Special characters
 SELECT '[{"\ud83d\ude04\ud83d\udc36" : [1, 2], "ndistinct" : 4}]'::pg_ndistinct;
 ERROR:  malformed pg_ndistinct: "[{"\ud83d\ude04\ud83d\udc36" : [1, 2], "ndistinct" : 4}]"
@@ -154,7 +165,7 @@ SELECT '[{"attributes" : [2], "ndistinct" : 4}]'::pg_ndistinct;
 ERROR:  malformed pg_ndistinct: "[{"attributes" : [2], "ndistinct" : 4}]"
 LINE 1: SELECT '[{"attributes" : [2], "ndistinct" : 4}]'::pg_ndistin...
                ^
-DETAIL:  The "ndistinct" key must contain an array of at least 2 and no more than 8 attributes.
+DETAIL:  The "attributes" key must contain an array of at least 2 and no more than 8 attributes.
 SELECT '[{"attributes" : [2,null], "ndistinct" : 4}]'::pg_ndistinct;
 ERROR:  malformed pg_ndistinct: "[{"attributes" : [2,null], "ndistinct" : 4}]"
 LINE 1: SELECT '[{"attributes" : [2,null], "ndistinct" : 4}]'::pg_nd...
@@ -195,6 +206,21 @@ ERROR:  malformed pg_ndistinct: "[{"attributes" : [2,3], "ndistinct" : {"a": 1}}
 LINE 1: SELECT '[{"attributes" : [2,3], "ndistinct" : {"a": 1}}]'::p...
                ^
 DETAIL:  Value of "ndistinct" must be an integer.
+SELECT '[{"attributes" : [0,1], "ndistinct" : 1}}]'::pg_ndistinct;
+ERROR:  malformed pg_ndistinct: "[{"attributes" : [0,1], "ndistinct" : 1}}]"
+LINE 1: SELECT '[{"attributes" : [0,1], "ndistinct" : 1}}]'::pg_ndis...
+               ^
+DETAIL:  Invalid "attributes" element: 0.
+SELECT '[{"attributes" : [-7, -9], "ndistinct" : 1}]'::pg_ndistinct;
+ERROR:  malformed pg_ndistinct: "[{"attributes" : [-7, -9], "ndistinct" : 1}]"
+LINE 1: SELECT '[{"attributes" : [-7, -9], "ndistinct" : 1}]'::pg_nd...
+               ^
+DETAIL:  Invalid "attributes" element: -9.
+SELECT '[{"attributes" : [1, -9], "ndistinct" : 1}]'::pg_ndistinct;
+ERROR:  malformed pg_ndistinct: "[{"attributes" : [1, -9], "ndistinct" : 1}]"
+LINE 1: SELECT '[{"attributes" : [1, -9], "ndistinct" : 1}]'::pg_ndi...
+               ^
+DETAIL:  Invalid "attributes" element: -9.
 SELECT '[{"attributes" : 1, "ndistinct" : 4}]'::pg_ndistinct;
 ERROR:  malformed pg_ndistinct: "[{"attributes" : 1, "ndistinct" : 4}]"
 LINE 1: SELECT '[{"attributes" : 1, "ndistinct" : 4}]'::pg_ndistinct...
@@ -228,9 +254,9 @@ SELECT * FROM pg_input_error_info('[{"attributes" : [], "ndistinct" : 1}]', 'pg_
 (1 row)
 
 SELECT * FROM pg_input_error_info('[{"attributes" : [2], "ndistinct" : 4}]', 'pg_ndistinct');
-                              message                              |                                         detail                                         | hint | sql_error_code 
--------------------------------------------------------------------+----------------------------------------------------------------------------------------+------+----------------
- malformed pg_ndistinct: "[{"attributes" : [2], "ndistinct" : 4}]" | The "ndistinct" key must contain an array of at least 2 and no more than 8 attributes. |      | 22P02
+                              message                              |                                         detail                                          | hint | sql_error_code 
+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------+------+----------------
+ malformed pg_ndistinct: "[{"attributes" : [2], "ndistinct" : 4}]" | The "attributes" key must contain an array of at least 2 and no more than 8 attributes. |      | 22P02
 (1 row)
 
 SELECT * FROM pg_input_error_info('[{"attributes" : [2,null], "ndistinct" : 4}]', 'pg_ndistinct');
diff --git a/src/test/regress/sql/pg_ndistinct.sql b/src/test/regress/sql/pg_ndistinct.sql
index 7646dedc2d0..9ba940589d4 100644
--- a/src/test/regress/sql/pg_ndistinct.sql
+++ b/src/test/regress/sql/pg_ndistinct.sql
@@ -15,9 +15,11 @@ SELECT * FROM pg_input_error_info('[null]', 'pg_ndistinct');
 SELECT '[{"attributes_invalid" : [2,3], "ndistinct" : 4}]'::pg_ndistinct;
 SELECT '[{"attributes" : [2,3], "invalid" : 3, "ndistinct" : 4}]'::pg_ndistinct;
 SELECT '[{"attributes" : [2,3], "attributes" : [1,3], "ndistinct" : 4}]'::pg_ndistinct;
+SELECT '[{"attributes" : [2,3], "ndistinct" : 4, "ndistinct" : 4}]'::pg_ndistinct;
 SELECT * FROM pg_input_error_info('[{"attributes_invalid" : [2,3], "ndistinct" : 4}]', 'pg_ndistinct');
 SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "invalid" : 3, "ndistinct" : 4}]', 'pg_ndistinct');
 SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "attributes" : [1,3], "ndistinct" : 4}]', 'pg_ndistinct');
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "ndistinct" : 4, "ndistinct" : 4}]', 'pg_ndistinct');
 
 -- Missing key
 SELECT '[{"attributes" : [2,3]}]'::pg_ndistinct;
@@ -46,6 +48,9 @@ SELECT '[{"attributes" : [2,3], "ndistinct" : []}]'::pg_ndistinct;
 SELECT '[{"attributes" : [2,3], "ndistinct" : [null]}]'::pg_ndistinct;
 SELECT '[{"attributes" : [2,3], "ndistinct" : [1,null]}]'::pg_ndistinct;
 SELECT '[{"attributes" : [2,3], "ndistinct" : {"a": 1}}]'::pg_ndistinct;
+SELECT '[{"attributes" : [0,1], "ndistinct" : 1}}]'::pg_ndistinct;
+SELECT '[{"attributes" : [-7, -9], "ndistinct" : 1}]'::pg_ndistinct;
+SELECT '[{"attributes" : [1, -9], "ndistinct" : 1}]'::pg_ndistinct;
 SELECT '[{"attributes" : 1, "ndistinct" : 4}]'::pg_ndistinct;
 SELECT '[{"attributes" : "a", "ndistinct" : 4}]'::pg_ndistinct;
 SELECT '[{"attributes" : {"a": 1}, "ndistinct" : 1}]'::pg_ndistinct;
-- 
2.34.1