diff --git a/regress/expected/expr.out b/regress/expected/expr.out index 806a6f65c..6299ce9e5 100644 --- a/regress/expected/expr.out +++ b/regress/expected/expr.out @@ -4903,9 +4903,9 @@ $$) AS (results agtype); SELECT * FROM cypher('expr', $$ RETURN split("a,b,c,d,e,f", "") $$) AS (results agtype); - results ---------------------------------------------------------- - ["a", ",", "b", ",", "c", ",", "d", ",", "e", ",", "f"] + results +----------------- + ["a,b,c,d,e,f"] (1 row) SELECT * FROM cypher('expr', $$ @@ -5014,6 +5014,57 @@ ERROR: function age_split() does not exist LINE 1: SELECT * FROM age_split(); ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts. +-- regex metacharacters should be treated as literal delimiters (#2568) +SELECT * FROM cypher('expr', $$ + RETURN split("a.b.c", ".") +$$) AS (results agtype); + results +----------------- + ["a", "b", "c"] +(1 row) + +SELECT * FROM cypher('expr', $$ + RETURN split("a|b|c", "|") +$$) AS (results agtype); + results +----------------- + ["a", "b", "c"] +(1 row) + +SELECT * FROM cypher('expr', $$ + RETURN split("a+b+c", "+") +$$) AS (results agtype); + results +----------------- + ["a", "b", "c"] +(1 row) + +SELECT * FROM cypher('expr', $$ + RETURN split("a.b.c.d", ".") +$$) AS (results agtype); + results +---------------------- + ["a", "b", "c", "d"] +(1 row) + +SELECT * FROM age_split('a.b.c', '.'); + age_split +----------------- + ["a", "b", "c"] +(1 row) + +SELECT * FROM age_split('a|b|c', '|'); + age_split +----------------- + ["a", "b", "c"] +(1 row) + +SELECT * FROM age_split('a+b+c', '+'); + age_split +----------------- + ["a", "b", "c"] +(1 row) + -- -- replace() -- diff --git a/regress/sql/expr.sql b/regress/sql/expr.sql index d4d900a1c..3f382119f 100644 --- a/regress/sql/expr.sql +++ b/regress/sql/expr.sql @@ -2098,6 +2098,22 @@ SELECT * FROM age_split(123456789, ','); SELECT * FROM age_split('a,b,c,d,e,f', -1); SELECT * FROM age_split('a,b,c,d,e,f'); SELECT * FROM age_split(); +-- regex metacharacters should be treated as literal delimiters (#2568) +SELECT * FROM cypher('expr', $$ + RETURN split("a.b.c", ".") +$$) AS (results agtype); +SELECT * FROM cypher('expr', $$ + RETURN split("a|b|c", "|") +$$) AS (results agtype); +SELECT * FROM cypher('expr', $$ + RETURN split("a+b+c", "+") +$$) AS (results agtype); +SELECT * FROM cypher('expr', $$ + RETURN split("a.b.c.d", ".") +$$) AS (results agtype); +SELECT * FROM age_split('a.b.c', '.'); +SELECT * FROM age_split('a|b|c', '|'); +SELECT * FROM age_split('a+b+c', '+'); -- -- replace() diff --git a/src/backend/utils/adt/agtype.c b/src/backend/utils/adt/agtype.c index cc9cc7717..8de018a6b 100644 --- a/src/backend/utils/adt/agtype.c +++ b/src/backend/utils/adt/agtype.c @@ -9480,8 +9480,13 @@ Datum age_split(PG_FUNCTION_ARGS) /* * We need the strings as a text strings so that we can let PG deal with * multibyte characters in the string. The result is an ArrayType + * + * Use text_to_array (SQL string_to_array, literal split) instead of regexp_split_to_array + * so that the delimiter is treated as a plain string, not a regular + * expression. This matches openCypher semantics and is consistent with + * age_replace(), which already treats the delimiter literally. */ - text_array = DirectFunctionCall2Coll(regexp_split_to_array, + text_array = DirectFunctionCall2Coll(text_to_array, DEFAULT_COLLATION_OID, PointerGetDatum(text_string), PointerGetDatum(text_delimiter));