Skip to content

Commit bf138e2

Browse files
author
Thomas G. Lockhart
committed
Add routines for text trimming on both ends, substring, and string position.
Used to support SQL92 compatibility.
1 parent d95c93b commit bf138e2

File tree

2 files changed

+147
-39
lines changed

2 files changed

+147
-39
lines changed

src/backend/utils/adt/oracle_compat.c

Lines changed: 82 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* Edmund Mergl <E.Mergl@bawue.de>
33
*
4-
* $Id: oracle_compat.c,v 1.6 1997/05/07 02:46:45 scrappy Exp $
4+
* $Id: oracle_compat.c,v 1.7 1997/07/29 16:12:01 thomas Exp $
55
*
66
*/
77

@@ -15,6 +15,7 @@ text *upper(text *string);
1515
text *initcap(text *string);
1616
text *lpad(text *string1, int4 len, text *string2);
1717
text *rpad(text *string1, int4 len, text *string2);
18+
text *btrim(text *string, text *set);
1819
text *ltrim(text *string, text *set);
1920
text *rtrim(text *string, text *set);
2021
text *substr(text *string, int4 m, int4 n);
@@ -246,6 +247,81 @@ rpad(text *string1, int4 len, text *string2)
246247
}
247248

248249

250+
/********************************************************************
251+
*
252+
* btrim
253+
*
254+
* Syntax:
255+
*
256+
* text *btrim(text *string, text *set)
257+
*
258+
* Purpose:
259+
*
260+
* Returns string with characters removed from the front and back
261+
* up to the first character not in set.
262+
*
263+
********************************************************************/
264+
265+
text *
266+
btrim(text *string, text *set)
267+
{
268+
text *ret;
269+
char *ptr, *end, *ptr2, *end2;
270+
int m;
271+
272+
if ((string == (text *)NULL) ||
273+
((m = VARSIZE(string) - VARHDRSZ) <= 0) ||
274+
(set == (text *)NULL) ||
275+
((VARSIZE(set) - VARHDRSZ) <= 0))
276+
return string;
277+
278+
ptr = VARDATA(string);
279+
ptr2 = VARDATA(set);
280+
end2 = VARDATA(set) + VARSIZE(set) - VARHDRSZ - 1;
281+
282+
while (m--) {
283+
while (ptr2 <= end2) {
284+
if (*ptr == *ptr2) {
285+
break;
286+
}
287+
++ptr2;
288+
}
289+
if (*ptr != *ptr2) {
290+
break;
291+
}
292+
ptr++;
293+
ptr2 = VARDATA(set);
294+
}
295+
296+
++m;
297+
298+
end = VARDATA(string) + VARSIZE(string) - VARHDRSZ - 1;
299+
ptr2 = VARDATA(set);
300+
301+
while (m--) {
302+
while (ptr2 <= end2) {
303+
if (*end == *ptr2) {
304+
break;
305+
}
306+
++ptr2;
307+
}
308+
if (*end != *ptr2) {
309+
break;
310+
}
311+
--end;
312+
ptr2 = VARDATA(set);
313+
}
314+
315+
++m;
316+
317+
ret = (text *)palloc(VARHDRSZ + m);
318+
VARSIZE(ret) = VARHDRSZ + m;
319+
memcpy(VARDATA(ret),ptr,m);
320+
321+
return ret;
322+
} /* btrim() */
323+
324+
249325
/********************************************************************
250326
*
251327
* ltrim
@@ -265,7 +341,7 @@ text *
265341
ltrim(text *string, text *set)
266342
{
267343
text *ret;
268-
char *ptr, *ptr2, *end2, *ptr_ret;
344+
char *ptr, *ptr2, *end2;
269345
int m;
270346

271347
if ((string == (text *)NULL) ||
@@ -297,11 +373,7 @@ ltrim(text *string, text *set)
297373
ret = (text *)palloc(VARHDRSZ + m);
298374
VARSIZE(ret) = VARHDRSZ + m;
299375

300-
ptr_ret = VARDATA(ret);
301-
302-
while (m--) {
303-
*ptr_ret++ = *ptr++;
304-
}
376+
memcpy(VARDATA(ret),ptr,m);
305377

306378
return ret;
307379
}
@@ -357,6 +429,9 @@ rtrim(text *string, text *set)
357429

358430
ret = (text *)palloc(VARHDRSZ + m);
359431
VARSIZE(ret) = VARHDRSZ + m;
432+
#if FALSE
433+
memcpy(VARDATA(ret),ptr-VARSIZE(ret)+m,m);
434+
#endif
360435

361436
ptr_ret = VARDATA(ret) + m - 1;
362437

@@ -454,11 +529,3 @@ translate(text *string, char from, char to)
454529

455530

456531
/* EOF */
457-
458-
459-
460-
461-
462-
463-
464-

src/backend/utils/adt/varlena.c

Lines changed: 65 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.16 1997/06/11 05:18:02 vadim Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.17 1997/07/29 16:12:07 thomas Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -216,40 +216,81 @@ int textlen (text* t)
216216
/*
217217
* textcat -
218218
* takes two text* and returns a text* that is the concatentation of
219-
* the two
220-
*/
221-
222-
/*
223-
* Rewrited by Sapa, sapa@hq.icb.chel.su. 8-Jul-96.
219+
* the two.
220+
*
221+
* Rewritten by Sapa, sapa@hq.icb.chel.su. 8-Jul-96.
222+
* Updated by Thomas, Thomas.Lockhart@jpl.nasa.gov 1997-07-10.
223+
* Allocate space for output in all cases.
224+
* XXX - thomas 1997-07-10
225+
* As in previous code, allow concatenation when one string is NULL.
226+
* Is this OK?
224227
*/
225228

226229
text*
227230
textcat(text* t1, text* t2)
228231
{
229-
int len1, len2, newlen;
232+
int len1, len2, len;
230233
char *ptr;
231234
text* result;
232235

233-
/* Check for NULL strings... */
234-
if (t1 == NULL) return t2;
235-
if (t2 == NULL) return t1;
236+
if (!PointerIsValid(t1) && !PointerIsValid(t2))
237+
return(NULL);
236238

237-
/* Check for ZERO-LENGTH strings... */
238-
/* I use <= instead of == , I know - it's paranoia, but... */
239-
if((len1 = VARSIZE(t1) - VARHDRSZ) <= 0) return t2;
240-
if((len2 = VARSIZE(t2) - VARHDRSZ) <= 0) return t1;
239+
len1 = (PointerIsValid(t1)? (VARSIZE(t1) - VARHDRSZ): 0);
240+
if (len1 < 0) len1 = 0;
241+
len2 = (PointerIsValid(t2)? (VARSIZE(t2) - VARHDRSZ): 0);
242+
if (len2 < 0) len2 = 0;
241243

242-
result = (text *)palloc(newlen = len1 + len2 + VARHDRSZ);
244+
result = PALLOC(len = len1 + len2 + VARHDRSZ);
243245

244246
/* Fill data field of result string... */
245-
memcpy(ptr = VARDATA(result), VARDATA(t1), len1);
246-
memcpy(ptr + len1, VARDATA(t2), len2);
247+
ptr = VARDATA(result);
248+
if (PointerIsValid(t1)) memcpy(ptr, VARDATA(t1), len1);
249+
if (PointerIsValid(t2)) memcpy(ptr + len1, VARDATA(t2), len2);
247250

248251
/* Set size of result string... */
249-
VARSIZE(result) = newlen;
252+
VARSIZE(result) = len;
250253

251-
return result;
252-
}
254+
return(result);
255+
} /* textcat() */
256+
257+
/*
258+
* textpos -
259+
* Return the position of the specified substring.
260+
* Implements the SQL92 POSITION() function.
261+
* Ref: A Guide To The SQL Standard, Date & Darwen, 1997
262+
* - thomas 1997-07-27
263+
*/
264+
265+
int32
266+
textpos(text* t1, text* t2)
267+
{
268+
int pos;
269+
int px, p;
270+
int len1, len2;
271+
char *p1, *p2;
272+
273+
if (!PointerIsValid(t1) || !PointerIsValid(t2))
274+
return(0);
275+
276+
if (VARSIZE(t2) <= 0)
277+
return(1);
278+
279+
len1 = (VARSIZE(t1) - VARHDRSZ);
280+
len2 = (VARSIZE(t2) - VARHDRSZ);
281+
p1 = VARDATA(t1);
282+
p2 = VARDATA(t2);
283+
pos = 0;
284+
px = (len1 - len2);
285+
for (p = 0; p <= px; p++) {
286+
if ((*p2 == *p1) && (strncmp(p1, p2, len2) == 0)) {
287+
pos = p + 1;
288+
break;
289+
};
290+
p1++;
291+
};
292+
return(pos);
293+
} /* textpos() */
253294

254295
/*
255296
* texteq - returns 1 iff arguments are equal
@@ -269,15 +310,15 @@ texteq(struct varlena *arg1, struct varlena *arg2)
269310
a2p = arg2->vl_dat;
270311
/*
271312
* Varlenas are stored as the total size (data + size variable)
272-
* followed by the data. The size variable is an int32 so the
273-
* length of the data is the total length less sizeof(int32)
313+
* followed by the data.
314+
* Use VARHDRSZ instead of explicit sizeof() - thomas 1997-07-10
274315
*/
275-
len -= sizeof(int32);
316+
len -= VARHDRSZ;
276317
while (len-- != 0)
277318
if (*a1p++ != *a2p++)
278319
return((bool) 0);
279320
return((bool) 1);
280-
}
321+
} /* texteq() */
281322

282323
bool
283324
textne(struct varlena *arg1, struct varlena *arg2)

0 commit comments

Comments
 (0)