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 <[email protected]>
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