diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index df29af6371..868393f5d0 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -3950,7 +3950,7 @@ SELECT format('Testing %3$s, %2$s, %s', 'one', 'two', 'three');
trim
- trim ( BOTH
+ trim ( LEADING | TRAILING | BOTH
bytesremoved bytea FROM
bytes bytea )
bytea
@@ -3968,7 +3968,7 @@ SELECT format('Testing %3$s, %2$s, %s', 'one', 'two', 'three');
- trim ( BOTH FROM
+ trim ( LEADING | TRAILING | BOTH FROM
bytes bytea,
bytesremoved bytea )
bytea
diff --git a/src/backend/utils/adt/oracle_compat.c b/src/backend/utils/adt/oracle_compat.c
index 76e666474e..e62913d7c4 100644
--- a/src/backend/utils/adt/oracle_compat.c
+++ b/src/backend/utils/adt/oracle_compat.c
@@ -25,6 +25,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,124 @@ byteatrim(PG_FUNCTION_ARGS)
ptr2start = VARDATA_ANY(set);
end2 = ptr2start + setlen - 1;
- while (m > 0)
- {
- ptr2 = ptr2start;
- while (ptr2 <= end2)
+ if (doltrim) {
+ 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)
- {
- ptr2 = ptr2start;
- while (ptr2 <= end2)
+ if (dortrim) {
+ 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/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index fc2202b843..6eec551105 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5748,6 +5748,12 @@
{ oid => '2015', descr => 'trim both ends of string',
proname => 'btrim', prorettype => 'bytea', proargtypes => 'bytea bytea',
prosrc => 'byteatrim' },
+{ oid => '9612', descr => 'trim left ends of string',
+ proname => 'ltrim', prorettype => 'bytea', proargtypes => 'bytea bytea',
+ prosrc => 'bytealtrim' },
+{ oid => '9613', descr => 'trim right ends 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/strings.out b/src/test/regress/expected/strings.out
index 298b6c48c2..a2bdd0dd36 100644
--- a/src/test/regress/expected/strings.out
+++ b/src/test/regress/expected/strings.out
@@ -2090,6 +2090,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/strings.sql b/src/test/regress/sql/strings.sql
index ad5221ab6b..49f8ee2d51 100644
--- a/src/test/regress/sql/strings.sql
+++ b/src/test/regress/sql/strings.sql
@@ -711,6 +711,8 @@ SELECT repeat('Pg', 4);
SELECT repeat('Pg', -4);
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);