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
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