diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/utils/adt/oracle_compat.c | 152 | ||||
-rw-r--r-- | src/backend/utils/adt/ruleutils.c | 2 | ||||
-rw-r--r-- | src/include/catalog/catversion.h | 2 | ||||
-rw-r--r-- | src/include/catalog/pg_proc.dat | 8 | ||||
-rw-r--r-- | src/test/regress/expected/create_view.out | 10 | ||||
-rw-r--r-- | src/test/regress/expected/strings.out | 12 | ||||
-rw-r--r-- | src/test/regress/sql/create_view.sql | 5 | ||||
-rw-r--r-- | src/test/regress/sql/strings.sql | 2 |
8 files changed, 149 insertions, 44 deletions
diff --git a/src/backend/utils/adt/oracle_compat.c b/src/backend/utils/adt/oracle_compat.c index 99077a90b9..f737aa6fbd 100644 --- a/src/backend/utils/adt/oracle_compat.c +++ b/src/backend/utils/adt/oracle_compat.c @@ -24,6 +24,8 @@ static text *dotrim(const char *string, int stringlen, const char *set, int setlen, bool doltrim, bool dortrim); +static bytea *dobyteatrim(bytea *string, bytea *set, + bool doltrim, bool dortrim); /******************************************************************** @@ -521,27 +523,12 @@ dotrim(const char *string, int stringlen, return cstring_to_text_with_len(string, stringlen); } -/******************************************************************** - * - * byteatrim - * - * Syntax: - * - * bytea byteatrim(bytea string, bytea set) - * - * Purpose: - * - * Returns string with characters removed from the front and back - * up to the first character not in set. - * - * Cloned from btrim and modified as required. - ********************************************************************/ - -Datum -byteatrim(PG_FUNCTION_ARGS) +/* + * Common implementation for bytea versions of btrim, ltrim, rtrim + */ +bytea * +dobyteatrim(bytea *string, bytea *set, bool doltrim, bool dortrim) { - bytea *string = PG_GETARG_BYTEA_PP(0); - bytea *set = PG_GETARG_BYTEA_PP(1); bytea *ret; char *ptr, *end, @@ -556,7 +543,7 @@ byteatrim(PG_FUNCTION_ARGS) setlen = VARSIZE_ANY_EXHDR(set); if (stringlen <= 0 || setlen <= 0) - PG_RETURN_BYTEA_P(string); + return string; m = stringlen; ptr = VARDATA_ANY(string); @@ -564,39 +551,126 @@ byteatrim(PG_FUNCTION_ARGS) ptr2start = VARDATA_ANY(set); end2 = ptr2start + setlen - 1; - while (m > 0) + if (doltrim) { - ptr2 = ptr2start; - while (ptr2 <= end2) + while (m > 0) { - if (*ptr == *ptr2) + ptr2 = ptr2start; + while (ptr2 <= end2) + { + if (*ptr == *ptr2) + break; + ++ptr2; + } + if (ptr2 > end2) break; - ++ptr2; + ptr++; + m--; } - if (ptr2 > end2) - break; - ptr++; - m--; } - while (m > 0) + if (dortrim) { - ptr2 = ptr2start; - while (ptr2 <= end2) + while (m > 0) { - if (*end == *ptr2) + ptr2 = ptr2start; + while (ptr2 <= end2) + { + if (*end == *ptr2) + break; + ++ptr2; + } + if (ptr2 > end2) break; - ++ptr2; + end--; + m--; } - if (ptr2 > end2) - break; - end--; - m--; } ret = (bytea *) palloc(VARHDRSZ + m); SET_VARSIZE(ret, VARHDRSZ + m); memcpy(VARDATA(ret), ptr, m); + return ret; +} + +/******************************************************************** + * + * byteatrim + * + * Syntax: + * + * bytea byteatrim(bytea string, bytea set) + * + * Purpose: + * + * Returns string with characters removed from the front and back + * up to the first character not in set. + * + * Cloned from btrim and modified as required. + ********************************************************************/ + +Datum +byteatrim(PG_FUNCTION_ARGS) +{ + bytea *string = PG_GETARG_BYTEA_PP(0); + bytea *set = PG_GETARG_BYTEA_PP(1); + bytea *ret; + + ret = dobyteatrim(string, set, true, true); + + PG_RETURN_BYTEA_P(ret); +} + +/******************************************************************** + * + * bytealtrim + * + * Syntax: + * + * bytea bytealtrim(bytea string, bytea set) + * + * Purpose: + * + * Returns string with initial characters removed up to the first + * character not in set. + * + ********************************************************************/ + +Datum +bytealtrim(PG_FUNCTION_ARGS) +{ + bytea *string = PG_GETARG_BYTEA_PP(0); + bytea *set = PG_GETARG_BYTEA_PP(1); + bytea *ret; + + ret = dobyteatrim(string, set, true, false); + + PG_RETURN_BYTEA_P(ret); +} + +/******************************************************************** + * + * byteartrim + * + * Syntax: + * + * bytea byteartrim(bytea string, bytea set) + * + * Purpose: + * + * Returns string with final characters removed after the last + * character not in set. + * + ********************************************************************/ + +Datum +byteartrim(PG_FUNCTION_ARGS) +{ + bytea *string = PG_GETARG_BYTEA_PP(0); + bytea *set = PG_GETARG_BYTEA_PP(1); + bytea *ret; + + ret = dobyteatrim(string, set, false, true); PG_RETURN_BYTEA_P(ret); } diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index db803b4388..8a1fbda572 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -9680,6 +9680,7 @@ get_func_sql_syntax(FuncExpr *expr, deparse_context *context) appendStringInfoChar(buf, ')'); return true; + case F_LTRIM_BYTEA_BYTEA: case F_LTRIM_TEXT: case F_LTRIM_TEXT_TEXT: /* TRIM() */ @@ -9694,6 +9695,7 @@ get_func_sql_syntax(FuncExpr *expr, deparse_context *context) appendStringInfoChar(buf, ')'); return true; + case F_RTRIM_BYTEA_BYTEA: case F_RTRIM_TEXT: case F_RTRIM_TEXT_TEXT: /* TRIM() */ diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 385d108c29..ee0049dc97 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202101171 +#define CATALOG_VERSION_NO 202101181 #endif diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index dd64c3bd60..b5f52d4e4a 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -5779,9 +5779,15 @@ { oid => '2014', descr => 'position of substring', proname => 'position', prorettype => 'int4', proargtypes => 'bytea bytea', prosrc => 'byteapos' }, -{ oid => '2015', descr => 'trim both ends of string', +{ oid => '2015', descr => 'trim selected bytes from both ends of string', proname => 'btrim', prorettype => 'bytea', proargtypes => 'bytea bytea', prosrc => 'byteatrim' }, +{ oid => '9612', descr => 'trim selected bytes from left end of string', + proname => 'ltrim', prorettype => 'bytea', proargtypes => 'bytea bytea', + prosrc => 'bytealtrim' }, +{ oid => '9613', descr => 'trim selected bytes from right end of string', + proname => 'rtrim', prorettype => 'bytea', proargtypes => 'bytea bytea', + prosrc => 'byteartrim' }, { oid => '2019', descr => 'convert timestamp with time zone to time', proname => 'time', provolatile => 's', prorettype => 'time', diff --git a/src/test/regress/expected/create_view.out b/src/test/regress/expected/create_view.out index b234d2d4f9..bd5fe60450 100644 --- a/src/test/regress/expected/create_view.out +++ b/src/test/regress/expected/create_view.out @@ -1735,7 +1735,10 @@ select substring('foo' from 'oo') as ssf, -- historically-permitted abuse trim(' ' from ' foo ') as bt, trim(leading ' ' from ' foo ') as lt, - trim(trailing ' foo ') as rt; + trim(trailing ' foo ') as rt, + trim(E'\\000'::bytea from E'\\000Tom\\000'::bytea) as btb, + trim(leading E'\\000'::bytea from E'\\000Tom\\000'::bytea) as ltb, + trim(trailing E'\\000'::bytea from E'\\000Tom\\000'::bytea) as rtb; select pg_get_viewdef('tt201v', true); pg_get_viewdef ----------------------------------------------------------------------------------------------- @@ -1753,7 +1756,10 @@ select pg_get_viewdef('tt201v', true); "substring"('foo'::text, 'oo'::text) AS ssf, + TRIM(BOTH ' '::text FROM ' foo '::text) AS bt, + TRIM(LEADING ' '::text FROM ' foo '::text) AS lt, + - TRIM(TRAILING FROM ' foo '::text) AS rt; + TRIM(TRAILING FROM ' foo '::text) AS rt, + + TRIM(BOTH '\x00'::bytea FROM '\x00546f6d00'::bytea) AS btb, + + TRIM(LEADING '\x00'::bytea FROM '\x00546f6d00'::bytea) AS ltb, + + TRIM(TRAILING '\x00'::bytea FROM '\x00546f6d00'::bytea) AS rtb; (1 row) -- corner cases with empty join conditions diff --git a/src/test/regress/expected/strings.out b/src/test/regress/expected/strings.out index 595bd2446e..7c91afa6e4 100644 --- a/src/test/regress/expected/strings.out +++ b/src/test/regress/expected/strings.out @@ -2131,6 +2131,18 @@ SELECT trim(E'\\000'::bytea from E'\\000Tom\\000'::bytea); Tom (1 row) +SELECT trim(leading E'\\000'::bytea from E'\\000Tom\\000'::bytea); + ltrim +--------- + Tom\000 +(1 row) + +SELECT trim(trailing E'\\000'::bytea from E'\\000Tom\\000'::bytea); + rtrim +--------- + \000Tom +(1 row) + SELECT btrim(E'\\000trim\\000'::bytea, E'\\000'::bytea); btrim ------- diff --git a/src/test/regress/sql/create_view.sql b/src/test/regress/sql/create_view.sql index 6d4dd53965..fbd1313b9c 100644 --- a/src/test/regress/sql/create_view.sql +++ b/src/test/regress/sql/create_view.sql @@ -605,7 +605,10 @@ select substring('foo' from 'oo') as ssf, -- historically-permitted abuse trim(' ' from ' foo ') as bt, trim(leading ' ' from ' foo ') as lt, - trim(trailing ' foo ') as rt; + trim(trailing ' foo ') as rt, + trim(E'\\000'::bytea from E'\\000Tom\\000'::bytea) as btb, + trim(leading E'\\000'::bytea from E'\\000Tom\\000'::bytea) as ltb, + trim(trailing E'\\000'::bytea from E'\\000Tom\\000'::bytea) as rtb; select pg_get_viewdef('tt201v', true); -- corner cases with empty join conditions diff --git a/src/test/regress/sql/strings.sql b/src/test/regress/sql/strings.sql index ca465d050f..ef4bfb008a 100644 --- a/src/test/regress/sql/strings.sql +++ b/src/test/regress/sql/strings.sql @@ -722,6 +722,8 @@ SELECT SUBSTRING('string'::bytea FROM -10 FOR 2147483646) AS "string"; SELECT SUBSTRING('string'::bytea FROM -10 FOR -2147483646) AS "error"; SELECT trim(E'\\000'::bytea from E'\\000Tom\\000'::bytea); +SELECT trim(leading E'\\000'::bytea from E'\\000Tom\\000'::bytea); +SELECT trim(trailing E'\\000'::bytea from E'\\000Tom\\000'::bytea); SELECT btrim(E'\\000trim\\000'::bytea, E'\\000'::bytea); SELECT btrim(''::bytea, E'\\000'::bytea); SELECT btrim(E'\\000trim\\000'::bytea, ''::bytea); |