aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas G. Lockhart <lockhart@fourpalms.org>1997-07-29 16:12:07 +0000
committerThomas G. Lockhart <lockhart@fourpalms.org>1997-07-29 16:12:07 +0000
commitbf138e213963e05c68b7ea2122d47f6a56d5ac16 (patch)
tree627c1c2a7b8eaf0350c461fd49775cc5c14cbe08 /src
parentd95c93bf9988e11f22b67e370854ed18545a099b (diff)
downloadpostgresql-bf138e213963e05c68b7ea2122d47f6a56d5ac16.tar.gz
postgresql-bf138e213963e05c68b7ea2122d47f6a56d5ac16.zip
Add routines for text trimming on both ends, substring, and string position.
Used to support SQL92 compatibility.
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/adt/oracle_compat.c97
-rw-r--r--src/backend/utils/adt/varlena.c89
2 files changed, 147 insertions, 39 deletions
diff --git a/src/backend/utils/adt/oracle_compat.c b/src/backend/utils/adt/oracle_compat.c
index 7f509aa48c4..6082311c54a 100644
--- a/src/backend/utils/adt/oracle_compat.c
+++ b/src/backend/utils/adt/oracle_compat.c
@@ -1,7 +1,7 @@
/*
* Edmund Mergl <E.Mergl@bawue.de>
*
- * $Id: oracle_compat.c,v 1.6 1997/05/07 02:46:45 scrappy Exp $
+ * $Id: oracle_compat.c,v 1.7 1997/07/29 16:12:01 thomas Exp $
*
*/
@@ -15,6 +15,7 @@ text *upper(text *string);
text *initcap(text *string);
text *lpad(text *string1, int4 len, text *string2);
text *rpad(text *string1, int4 len, text *string2);
+text *btrim(text *string, text *set);
text *ltrim(text *string, text *set);
text *rtrim(text *string, text *set);
text *substr(text *string, int4 m, int4 n);
@@ -248,6 +249,81 @@ rpad(text *string1, int4 len, text *string2)
/********************************************************************
*
+ * btrim
+ *
+ * Syntax:
+ *
+ * text *btrim(text *string, text *set)
+ *
+ * Purpose:
+ *
+ * Returns string with characters removed from the front and back
+ * up to the first character not in set.
+ *
+ ********************************************************************/
+
+text *
+btrim(text *string, text *set)
+{
+ text *ret;
+ char *ptr, *end, *ptr2, *end2;
+ int m;
+
+ if ((string == (text *)NULL) ||
+ ((m = VARSIZE(string) - VARHDRSZ) <= 0) ||
+ (set == (text *)NULL) ||
+ ((VARSIZE(set) - VARHDRSZ) <= 0))
+ return string;
+
+ ptr = VARDATA(string);
+ ptr2 = VARDATA(set);
+ end2 = VARDATA(set) + VARSIZE(set) - VARHDRSZ - 1;
+
+ while (m--) {
+ while (ptr2 <= end2) {
+ if (*ptr == *ptr2) {
+ break;
+ }
+ ++ptr2;
+ }
+ if (*ptr != *ptr2) {
+ break;
+ }
+ ptr++;
+ ptr2 = VARDATA(set);
+ }
+
+ ++m;
+
+ end = VARDATA(string) + VARSIZE(string) - VARHDRSZ - 1;
+ ptr2 = VARDATA(set);
+
+ while (m--) {
+ while (ptr2 <= end2) {
+ if (*end == *ptr2) {
+ break;
+ }
+ ++ptr2;
+ }
+ if (*end != *ptr2) {
+ break;
+ }
+ --end;
+ ptr2 = VARDATA(set);
+ }
+
+ ++m;
+
+ ret = (text *)palloc(VARHDRSZ + m);
+ VARSIZE(ret) = VARHDRSZ + m;
+ memcpy(VARDATA(ret),ptr,m);
+
+ return ret;
+} /* btrim() */
+
+
+/********************************************************************
+ *
* ltrim
*
* Syntax:
@@ -265,7 +341,7 @@ text *
ltrim(text *string, text *set)
{
text *ret;
- char *ptr, *ptr2, *end2, *ptr_ret;
+ char *ptr, *ptr2, *end2;
int m;
if ((string == (text *)NULL) ||
@@ -297,11 +373,7 @@ ltrim(text *string, text *set)
ret = (text *)palloc(VARHDRSZ + m);
VARSIZE(ret) = VARHDRSZ + m;
- ptr_ret = VARDATA(ret);
-
- while (m--) {
- *ptr_ret++ = *ptr++;
- }
+ memcpy(VARDATA(ret),ptr,m);
return ret;
}
@@ -357,6 +429,9 @@ rtrim(text *string, text *set)
ret = (text *)palloc(VARHDRSZ + m);
VARSIZE(ret) = VARHDRSZ + m;
+#if FALSE
+ memcpy(VARDATA(ret),ptr-VARSIZE(ret)+m,m);
+#endif
ptr_ret = VARDATA(ret) + m - 1;
@@ -454,11 +529,3 @@ translate(text *string, char from, char to)
/* EOF */
-
-
-
-
-
-
-
-
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index d33ea702bbb..91bfdfaca23 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.16 1997/06/11 05:18:02 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.17 1997/07/29 16:12:07 thomas Exp $
*
*-------------------------------------------------------------------------
*/
@@ -216,40 +216,81 @@ int textlen (text* t)
/*
* textcat -
* takes two text* and returns a text* that is the concatentation of
- * the two
- */
-
-/*
- * Rewrited by Sapa, sapa@hq.icb.chel.su. 8-Jul-96.
+ * the two.
+ *
+ * Rewritten by Sapa, sapa@hq.icb.chel.su. 8-Jul-96.
+ * Updated by Thomas, Thomas.Lockhart@jpl.nasa.gov 1997-07-10.
+ * Allocate space for output in all cases.
+ * XXX - thomas 1997-07-10
+ * As in previous code, allow concatenation when one string is NULL.
+ * Is this OK?
*/
text*
textcat(text* t1, text* t2)
{
- int len1, len2, newlen;
+ int len1, len2, len;
char *ptr;
text* result;
- /* Check for NULL strings... */
- if (t1 == NULL) return t2;
- if (t2 == NULL) return t1;
+ if (!PointerIsValid(t1) && !PointerIsValid(t2))
+ return(NULL);
- /* Check for ZERO-LENGTH strings... */
- /* I use <= instead of == , I know - it's paranoia, but... */
- if((len1 = VARSIZE(t1) - VARHDRSZ) <= 0) return t2;
- if((len2 = VARSIZE(t2) - VARHDRSZ) <= 0) return t1;
+ len1 = (PointerIsValid(t1)? (VARSIZE(t1) - VARHDRSZ): 0);
+ if (len1 < 0) len1 = 0;
+ len2 = (PointerIsValid(t2)? (VARSIZE(t2) - VARHDRSZ): 0);
+ if (len2 < 0) len2 = 0;
- result = (text *)palloc(newlen = len1 + len2 + VARHDRSZ);
+ result = PALLOC(len = len1 + len2 + VARHDRSZ);
/* Fill data field of result string... */
- memcpy(ptr = VARDATA(result), VARDATA(t1), len1);
- memcpy(ptr + len1, VARDATA(t2), len2);
+ ptr = VARDATA(result);
+ if (PointerIsValid(t1)) memcpy(ptr, VARDATA(t1), len1);
+ if (PointerIsValid(t2)) memcpy(ptr + len1, VARDATA(t2), len2);
/* Set size of result string... */
- VARSIZE(result) = newlen;
+ VARSIZE(result) = len;
- return result;
-}
+ return(result);
+} /* textcat() */
+
+/*
+ * textpos -
+ * Return the position of the specified substring.
+ * Implements the SQL92 POSITION() function.
+ * Ref: A Guide To The SQL Standard, Date & Darwen, 1997
+ * - thomas 1997-07-27
+ */
+
+int32
+textpos(text* t1, text* t2)
+{
+ int pos;
+ int px, p;
+ int len1, len2;
+ char *p1, *p2;
+
+ if (!PointerIsValid(t1) || !PointerIsValid(t2))
+ return(0);
+
+ if (VARSIZE(t2) <= 0)
+ return(1);
+
+ len1 = (VARSIZE(t1) - VARHDRSZ);
+ len2 = (VARSIZE(t2) - VARHDRSZ);
+ p1 = VARDATA(t1);
+ p2 = VARDATA(t2);
+ pos = 0;
+ px = (len1 - len2);
+ for (p = 0; p <= px; p++) {
+ if ((*p2 == *p1) && (strncmp(p1, p2, len2) == 0)) {
+ pos = p + 1;
+ break;
+ };
+ p1++;
+ };
+ return(pos);
+} /* textpos() */
/*
* texteq - returns 1 iff arguments are equal
@@ -269,15 +310,15 @@ texteq(struct varlena *arg1, struct varlena *arg2)
a2p = arg2->vl_dat;
/*
* Varlenas are stored as the total size (data + size variable)
- * followed by the data. The size variable is an int32 so the
- * length of the data is the total length less sizeof(int32)
+ * followed by the data.
+ * Use VARHDRSZ instead of explicit sizeof() - thomas 1997-07-10
*/
- len -= sizeof(int32);
+ len -= VARHDRSZ;
while (len-- != 0)
if (*a1p++ != *a2p++)
return((bool) 0);
return((bool) 1);
-}
+} /* texteq() */
bool
textne(struct varlena *arg1, struct varlena *arg2)