v6-0007-refactor-ReadArrayStr.patch
application/x-patch
Filename: v6-0007-refactor-ReadArrayStr.patch
Type: application/x-patch
Part: 6
Message:
Re: Cleaning up array_in()
Patch
Format: format-patch
Series: patch v6-0007
Subject: refactor ReadArrayStr.
| File | + | − |
|---|---|---|
| src/backend/utils/adt/arrayfuncs.c | 19 | 36 |
| src/test/regress/expected/arrays.out | 28 | 0 |
| src/test/regress/sql/arrays.sql | 7 | 0 |
From 827f6d75a97a065374a368f5ba772f14c53b72b1 Mon Sep 17 00:00:00 2001
From: pgaddict <jian.universality@gmail.com>
Date: Mon, 11 Sep 2023 12:31:39 +0800
Subject: [PATCH v6 7/7] refactor ReadArrayStr.
array ending error can happen in any of cases(quoted_element, unquoted_element, with backslash, non-backslash).
conslidate it, using a goto ending_errror.
add more tests.
expect_delim state is not enought for case like '{{},}'. You need tracking
current token and previous token to solve cases where a delimiter followed by
a closing brace.
---
src/backend/utils/adt/arrayfuncs.c | 55 ++++++++++------------------
src/test/regress/expected/arrays.out | 28 ++++++++++++++
src/test/regress/sql/arrays.sql | 7 ++++
3 files changed, 54 insertions(+), 36 deletions(-)
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 79f4e1b4..b8f5d59c 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -625,7 +625,7 @@ ReadArrayStr(char **srcptr,
do
{
ArrayToken tok;
-
+ ArrayToken prev_tok;
tok = ReadArrayToken(srcptr, elembuf, typdelim, origStr, escontext);
switch (tok)
@@ -655,7 +655,8 @@ ReadArrayStr(char **srcptr,
}
break;
case ATOK_LEVEL_END:
- if (nest_level == 0)
+ /* cannot precede with a delim. nest_level should larger than 0 */
+ if (prev_tok == ATOK_DELIM || nest_level == 0)
ereturn(escontext, false,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", origStr),
@@ -739,6 +740,7 @@ ReadArrayStr(char **srcptr,
case ATOK_ERROR:
return false;
}
+ prev_tok = tok;
} while (nest_level > 0);
pfree(elembuf);
@@ -788,12 +790,7 @@ ReadArrayToken(char **srcptr, char *elembuf, char typdelim,
switch (*p)
{
case '\0':
- errsave(escontext,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("malformed array literal: \"%s\"",
- origStr)));
- *srcptr = p;
- return ATOK_ERROR;
+ goto ending_error;
case '{':
*srcptr = p + 1;
return ATOK_LEVEL_START;
@@ -825,24 +822,12 @@ quoted_element:
switch (*p)
{
case '\0':
- errsave(escontext,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("malformed array literal: \"%s\"",
- origStr)));
- *srcptr = p;
- return ATOK_ERROR;
+ goto ending_error;
case '\\':
/* Skip backslash, copy next character as-is. */
p++;
if (*p == '\0')
- {
- errsave(escontext,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("malformed array literal: \"%s\"",
- origStr)));
- *srcptr = p;
- return ATOK_ERROR;
- }
+ goto ending_error;
*dst++ = *p++;
break;
case '"':
@@ -863,25 +848,14 @@ unquoted_element:
{
case '\0':
case '{':
- errsave(escontext,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("malformed array literal: \"%s\"",
- origStr)));
- *srcptr = p;
- return ATOK_ERROR;
+ goto ending_error;
case '\\':
/* Skip backslash, copy next character as-is. */
p++;
if (*p == '\0')
- {
- errsave(escontext,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("malformed array literal: \"%s\"",
- origStr)));
- *srcptr = p;
- return ATOK_ERROR;
- }
+ goto ending_error;
*dst++ = *p++;
+ dstendptr = dst;
break;
case '"':
errsave(escontext,
@@ -907,6 +881,15 @@ unquoted_element:
p++;
}
}
+
+ending_error:
+ errsave(escontext,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("malformed array literal: \"%s\"",
+ origStr),
+ errdetail("Unexpected end of input.")));
+ *srcptr = p;
+ return ATOK_ERROR;
}
/*
diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out
index bea0d00b..9bb9924f 100644
--- a/src/test/regress/expected/arrays.out
+++ b/src/test/regress/expected/arrays.out
@@ -1544,6 +1544,34 @@ ERROR: cannot determine type of empty array
LINE 1: select array[];
^
HINT: Explicitly cast to the desired type, for example ARRAY[]::integer[].
+select '{{1,},{1},}'::text[];
+ERROR: malformed array literal: "{{1,},{1},}"
+LINE 1: select '{{1,},{1},}'::text[];
+ ^
+DETAIL: Unexpected "}" character.
+select '{{1,},{1}}'::text[];
+ERROR: malformed array literal: "{{1,},{1}}"
+LINE 1: select '{{1,},{1}}'::text[];
+ ^
+DETAIL: Unexpected "}" character.
+select '{{1,}}'::text[];
+ERROR: malformed array literal: "{{1,}}"
+LINE 1: select '{{1,}}'::text[];
+ ^
+DETAIL: Unexpected "}" character.
+select '{1,}'::text[];
+ERROR: malformed array literal: "{1,}"
+LINE 1: select '{1,}'::text[];
+ ^
+DETAIL: Unexpected "}" character.
+select '[21474836488:21474836489]={1,2}'::int[];
+ERROR: array bound is out of range
+LINE 1: select '[21474836488:21474836489]={1,2}'::int[];
+ ^
+select '[-2147483649:-2147483648]={1,2}'::int[];
+ERROR: array bound is out of range
+LINE 1: select '[-2147483649:-2147483648]={1,2}'::int[];
+ ^
-- none of the above should be accepted
-- all of the following should be accepted
select '{}'::text[];
diff --git a/src/test/regress/sql/arrays.sql b/src/test/regress/sql/arrays.sql
index 5eacb351..6bf18b7d 100644
--- a/src/test/regress/sql/arrays.sql
+++ b/src/test/regress/sql/arrays.sql
@@ -468,6 +468,13 @@ select '[2147483646:2147483647]={1,2}'::int[];
select '[1:-1]={}'::int[];
select '[1:0]={1}'::int[];
select array[];
+select '{{1,},{1},}'::text[];
+select '{{1,},{1}}'::text[];
+select '{{1,}}'::text[];
+select '{1,}'::text[];
+select '[21474836488:21474836489]={1,2}'::int[];
+select '[-2147483649:-2147483648]={1,2}'::int[];
+
-- none of the above should be accepted
-- all of the following should be accepted
--
2.34.1