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