based on Nikhil Benesch idea.
The attached diff is  based on
v1-0002-Rewrite-ArrayCount-to-make-dimensionality-checks.patch.

diff compare v1-0002:
select '{{1,{2}},{2,3}}'::text[];
 ERROR:  malformed array literal: "{{1,{2}},{2,3}}"
 LINE 1: select '{{1,{2}},{2,3}}'::text[];
                ^
-DETAIL:  Unexpected "{" character.
+DETAIL:  Multidimensional arrays must have sub-arrays with matching dimensions.
----------------------------------------------------
 select E'{{1,2},\\{2,3}}'::text[];
 ERROR:  malformed array literal: "{{1,2},\{2,3}}"
 LINE 1: select E'{{1,2},\\{2,3}}'::text[];
                ^
-DETAIL:  Unexpected "\" character.
+DETAIL:  Multidimensional arrays must have sub-arrays with matching dimensions.

-------
new errors details kind of make sense.
From 34055df96fcacc35c61be22d0fdc2a86a7dd854d Mon Sep 17 00:00:00 2001
From: pgaddict <jian.universal...@gmail.com>
Date: Mon, 3 Jul 2023 19:00:13 +0800
Subject: [PATCH 3/3] changed based on Nikhil Benesch idea

---
 src/backend/utils/adt/arrayfuncs.c   | 35 ++++++++++------------------
 src/test/regress/expected/arrays.out |  4 ++--
 2 files changed, 14 insertions(+), 25 deletions(-)

diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 8c5d35f1..a1ebc1cc 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -59,9 +59,9 @@ typedef enum
 	ARRAY_ELEM_STARTED,
 	ARRAY_QUOTED_ELEM_STARTED,
 	ARRAY_QUOTED_ELEM_COMPLETED,
-	ARRAY_ELEM_DELIMITED,
 	ARRAY_LEVEL_COMPLETED,
-	ARRAY_LEVEL_DELIMITED
+	ARRAY_DELIMITED,
+	ARRAY_END
 } ArrayParseState;
 
 /* Working state for array_iterate() */
@@ -473,8 +473,6 @@ ArrayCount(const char *str, int *dim, char typdelim, Node *escontext)
 	int			ndim = 1,
 				nelems[MAXDIM];
 	bool		ndim_frozen = false;
-	bool		in_quotes = false;
-	bool		eoArray = false;
 	bool		empty_array = true;
 	const char *ptr;
 	ArrayParseState parse_state = ARRAY_NO_LEVEL;
@@ -485,7 +483,7 @@ ArrayCount(const char *str, int *dim, char typdelim, Node *escontext)
 
 	/* Scan string until we reach closing brace */
 	ptr = str;
-	while (!eoArray)
+	while (parse_state != ARRAY_END)
 	{
 		bool		new_element = false;
 
@@ -507,7 +505,7 @@ ArrayCount(const char *str, int *dim, char typdelim, Node *escontext)
 				switch (parse_state)
 				{
 					case ARRAY_LEVEL_STARTED:
-					case ARRAY_ELEM_DELIMITED:
+					case ARRAY_DELIMITED:
 						/* start new unquoted element */
 						parse_state = ARRAY_ELEM_STARTED;
 						new_element = true;
@@ -542,17 +540,11 @@ ArrayCount(const char *str, int *dim, char typdelim, Node *escontext)
 				switch (parse_state)
 				{
 					case ARRAY_LEVEL_STARTED:
-					case ARRAY_ELEM_DELIMITED:
-						/* start new quoted element */
-						Assert(!in_quotes);
-						in_quotes = true;
+					case ARRAY_DELIMITED:
 						parse_state = ARRAY_QUOTED_ELEM_STARTED;
 						new_element = true;
 						break;
 					case ARRAY_QUOTED_ELEM_STARTED:
-						/* already in element, end it */
-						Assert(in_quotes);
-						in_quotes = false;
 						parse_state = ARRAY_QUOTED_ELEM_COMPLETED;
 						break;
 					default:
@@ -563,7 +555,7 @@ ArrayCount(const char *str, int *dim, char typdelim, Node *escontext)
 				}
 				break;
 			case '{':
-				if (!in_quotes)
+				if (parse_state != ARRAY_QUOTED_ELEM_STARTED)
 				{
 					/*
 					 * A left brace can occur if no nesting has occurred yet,
@@ -571,7 +563,7 @@ ArrayCount(const char *str, int *dim, char typdelim, Node *escontext)
 					 */
 					if (parse_state != ARRAY_NO_LEVEL &&
 						parse_state != ARRAY_LEVEL_STARTED &&
-						parse_state != ARRAY_LEVEL_DELIMITED)
+						parse_state != ARRAY_DELIMITED)
 						ereturn(escontext, -1,
 								(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 								 errmsg("malformed array literal: \"%s\"", str),
@@ -602,7 +594,7 @@ ArrayCount(const char *str, int *dim, char typdelim, Node *escontext)
 				}
 				break;
 			case '}':
-				if (!in_quotes)
+				if (parse_state != ARRAY_QUOTED_ELEM_STARTED)
 				{
 					/*
 					 * A right brace can occur after an element start, an
@@ -656,11 +648,11 @@ ArrayCount(const char *str, int *dim, char typdelim, Node *escontext)
 					}
 					/* Done if this is the outermost level's '}' */
 					if (nest_level == 0)
-						eoArray = true;
+						parse_state	= ARRAY_END;
 				}
 				break;
 			default:
-				if (!in_quotes)
+                if (parse_state != ARRAY_QUOTED_ELEM_STARTED)
 				{
 					if (*ptr == typdelim)
 					{
@@ -676,10 +668,7 @@ ArrayCount(const char *str, int *dim, char typdelim, Node *escontext)
 									 errmsg("malformed array literal: \"%s\"", str),
 									 errdetail("Unexpected \"%c\" character.",
 											   typdelim)));
-						if (parse_state == ARRAY_LEVEL_COMPLETED)
-							parse_state = ARRAY_LEVEL_DELIMITED;
-						else
-							parse_state = ARRAY_ELEM_DELIMITED;
+						parse_state	= ARRAY_DELIMITED;									
 					}
 					else if (!array_isspace(*ptr))
 					{
@@ -696,7 +685,7 @@ ArrayCount(const char *str, int *dim, char typdelim, Node *escontext)
 						switch (parse_state)
 						{
 							case ARRAY_LEVEL_STARTED:
-							case ARRAY_ELEM_DELIMITED:
+							case ARRAY_DELIMITED:
 								/* start new unquoted element */
 								parse_state = ARRAY_ELEM_STARTED;
 								new_element = true;
diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out
index 71fa12f8..4f206a11 100644
--- a/src/test/regress/expected/arrays.out
+++ b/src/test/regress/expected/arrays.out
@@ -1475,12 +1475,12 @@ select '{{1,{2}},{2,3}}'::text[];
 ERROR:  malformed array literal: "{{1,{2}},{2,3}}"
 LINE 1: select '{{1,{2}},{2,3}}'::text[];
                ^
-DETAIL:  Unexpected "{" character.
+DETAIL:  Multidimensional arrays must have sub-arrays with matching dimensions.
 select E'{{1,2},\\{2,3}}'::text[];
 ERROR:  malformed array literal: "{{1,2},\{2,3}}"
 LINE 1: select E'{{1,2},\\{2,3}}'::text[];
                ^
-DETAIL:  Unexpected "\" character.
+DETAIL:  Multidimensional arrays must have sub-arrays with matching dimensions.
 select '{{"1 2" x},{3}}'::text[];
 ERROR:  malformed array literal: "{{"1 2" x},{3}}"
 LINE 1: select '{{"1 2" x},{3}}'::text[];
-- 
2.34.1

Reply via email to