v7-0007-refactor-ReadArrayStr.patch
text/x-patch
Filename: v7-0007-refactor-ReadArrayStr.patch
Type: text/x-patch
Part: 6
Message:
Re: Cleaning up array_in()
Patch
Format: format-patch
Series: patch v7-0007
Subject: refactor ReadArrayStr.
| File | + | − |
|---|---|---|
| src/backend/utils/adt/arrayfuncs.c | 20 | 36 |
| src/test/regress/expected/arrays.out | 28 | 0 |
| src/test/regress/sql/arrays.sql | 7 | 0 |
From 585c6b0b072de05a86ad1471ddff412f2b493090 Mon Sep 17 00:00:00 2001
From: pgaddict <jian.universality@gmail.com>
Date: Tue, 12 Sep 2023 16:19:04 +0800
Subject: [PATCH v7 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 | 56 ++++++++++------------------
src/test/regress/expected/arrays.out | 28 ++++++++++++++
src/test/regress/sql/arrays.sql | 7 ++++
3 files changed, 55 insertions(+), 36 deletions(-)
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 1c61b6d8..1e158ecd 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -596,7 +596,7 @@ ReadArrayStr(char **srcptr,
bool dimensions_specified = ndim != 0;
bool ndim_frozen;
int nelems[MAXDIM];
-
+ ArrayToken prev_tok;
/* The caller already checked this */
Assert(**srcptr == '{');
@@ -622,6 +622,7 @@ ReadArrayStr(char **srcptr,
expect_delim = false;
nest_level = 0;
nitems = 0;
+ prev_tok = ATOK_LEVEL_START; /* initialize it */
do
{
ArrayToken tok;
@@ -655,7 +656,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 +741,7 @@ ReadArrayStr(char **srcptr,
case ATOK_ERROR:
return false;
}
+ prev_tok = tok;
} while (nest_level > 0);
pfree(elembuf);
@@ -788,12 +791,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 +823,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 +849,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 +882,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