Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : * oracle_compat.c
3 : : * Oracle compatible functions.
4 : : *
5 : : * Copyright (c) 1996-2025, PostgreSQL Global Development Group
6 : : *
7 : : * Author: Edmund Mergl <E.Mergl@bawue.de>
8 : : * Multibyte enhancement: Tatsuo Ishii <ishii@postgresql.org>
9 : : *
10 : : *
11 : : * IDENTIFICATION
12 : : * src/backend/utils/adt/oracle_compat.c
13 : : *
14 : : *-------------------------------------------------------------------------
15 : : */
16 : : #include "postgres.h"
17 : :
18 : : #include "common/int.h"
19 : : #include "mb/pg_wchar.h"
20 : : #include "miscadmin.h"
21 : : #include "utils/builtins.h"
22 : : #include "utils/formatting.h"
23 : : #include "utils/memutils.h"
24 : : #include "varatt.h"
25 : :
26 : :
27 : : static text *dotrim(const char *string, int stringlen,
28 : : const char *set, int setlen,
29 : : bool doltrim, bool dortrim);
30 : : static bytea *dobyteatrim(bytea *string, bytea *set,
31 : : bool doltrim, bool dortrim);
32 : :
33 : :
34 : : /********************************************************************
35 : : *
36 : : * lower
37 : : *
38 : : * Syntax:
39 : : *
40 : : * text lower(text string)
41 : : *
42 : : * Purpose:
43 : : *
44 : : * Returns string, with all letters forced to lowercase.
45 : : *
46 : : ********************************************************************/
47 : :
48 : : Datum
9193 tgl@sss.pgh.pa.us 49 :CBC 75267 : lower(PG_FUNCTION_ARGS)
50 : : {
5931 bruce@momjian.us 51 : 75267 : text *in_string = PG_GETARG_TEXT_PP(0);
52 : : char *out_string;
53 : : text *result;
54 : :
6265 tgl@sss.pgh.pa.us 55 [ + + ]: 75267 : out_string = str_tolower(VARDATA_ANY(in_string),
5324 peter_e@gmx.net 56 [ - + - - :ECB (90892) : VARSIZE_ANY_EXHDR(in_string),
- - - - +
+ ]
57 : : PG_GET_COLLATION());
6284 bruce@momjian.us 58 :CBC 75267 : result = cstring_to_text(out_string);
59 : 75267 : pfree(out_string);
60 : :
61 : 75267 : PG_RETURN_TEXT_P(result);
62 : : }
63 : :
64 : :
65 : : /********************************************************************
66 : : *
67 : : * upper
68 : : *
69 : : * Syntax:
70 : : *
71 : : * text upper(text string)
72 : : *
73 : : * Purpose:
74 : : *
75 : : * Returns string, with all letters forced to uppercase.
76 : : *
77 : : ********************************************************************/
78 : :
79 : : Datum
9193 tgl@sss.pgh.pa.us 80 : 525346 : upper(PG_FUNCTION_ARGS)
81 : : {
5931 bruce@momjian.us 82 : 525346 : text *in_string = PG_GETARG_TEXT_PP(0);
83 : : char *out_string;
84 : : text *result;
85 : :
6265 tgl@sss.pgh.pa.us 86 [ + + ]: 525346 : out_string = str_toupper(VARDATA_ANY(in_string),
5324 peter_e@gmx.net 87 [ - + - - :ECB (525162) : VARSIZE_ANY_EXHDR(in_string),
- - - - +
+ ]
88 : : PG_GET_COLLATION());
6284 bruce@momjian.us 89 :CBC 525346 : result = cstring_to_text(out_string);
90 : 525346 : pfree(out_string);
91 : :
92 : 525346 : PG_RETURN_TEXT_P(result);
93 : : }
94 : :
95 : :
96 : : /********************************************************************
97 : : *
98 : : * initcap
99 : : *
100 : : * Syntax:
101 : : *
102 : : * text initcap(text string)
103 : : *
104 : : * Purpose:
105 : : *
106 : : * Returns string, with first letter of each word in uppercase, all
107 : : * other letters in lowercase. A word is defined as a sequence of
108 : : * alphanumeric characters, delimited by non-alphanumeric
109 : : * characters.
110 : : *
111 : : ********************************************************************/
112 : :
113 : : Datum
9193 tgl@sss.pgh.pa.us 114 : 113 : initcap(PG_FUNCTION_ARGS)
115 : : {
5931 bruce@momjian.us 116 : 113 : text *in_string = PG_GETARG_TEXT_PP(0);
117 : : char *out_string;
118 : : text *result;
119 : :
6265 tgl@sss.pgh.pa.us 120 [ + + ]: 113 : out_string = str_initcap(VARDATA_ANY(in_string),
5324 peter_e@gmx.net 121 [ - + - - :ECB (113) : VARSIZE_ANY_EXHDR(in_string),
- - - - +
+ ]
122 : : PG_GET_COLLATION());
6284 bruce@momjian.us 123 :CBC 113 : result = cstring_to_text(out_string);
124 : 113 : pfree(out_string);
125 : :
126 : 113 : PG_RETURN_TEXT_P(result);
127 : : }
128 : :
129 : : Datum
225 jdavis@postgresql.or 130 : 12 : casefold(PG_FUNCTION_ARGS)
131 : : {
132 : 12 : text *in_string = PG_GETARG_TEXT_PP(0);
133 : : char *out_string;
134 : : text *result;
135 : :
136 [ - + ]: 12 : out_string = str_casefold(VARDATA_ANY(in_string),
225 jdavis@postgresql.or 137 [ - + - - :ECB (12) : VARSIZE_ANY_EXHDR(in_string),
- - - - -
+ ]
138 : : PG_GET_COLLATION());
225 jdavis@postgresql.or 139 :CBC 12 : result = cstring_to_text(out_string);
140 : 12 : pfree(out_string);
141 : :
142 : 12 : PG_RETURN_TEXT_P(result);
143 : : }
144 : :
145 : :
146 : : /********************************************************************
147 : : *
148 : : * lpad
149 : : *
150 : : * Syntax:
151 : : *
152 : : * text lpad(text string1, int4 len, text string2)
153 : : *
154 : : * Purpose:
155 : : *
156 : : * Returns string1, left-padded to length len with the sequence of
157 : : * characters in string2. If len is less than the length of string1,
158 : : * instead truncate (on the right) to len.
159 : : *
160 : : ********************************************************************/
161 : :
162 : : Datum
9216 tgl@sss.pgh.pa.us 163 : 16385 : lpad(PG_FUNCTION_ARGS)
164 : : {
6560 165 : 16385 : text *string1 = PG_GETARG_TEXT_PP(0);
9216 166 : 16385 : int32 len = PG_GETARG_INT32(1);
6560 167 : 16385 : text *string2 = PG_GETARG_TEXT_PP(2);
168 : : text *ret;
169 : : char *ptr1,
170 : : *ptr2,
171 : : *ptr2start,
172 : : *ptr2end,
173 : : *ptr_ret;
174 : : int m,
175 : : s1len,
176 : : s2len;
177 : : int bytelen;
178 : :
179 : : /* Negative len is silently taken as zero */
9039 180 [ + + ]: 16385 : if (len < 0)
181 : 3 : len = 0;
182 : :
6560 183 [ - + - - : 16385 : s1len = VARSIZE_ANY_EXHDR(string1);
- - - - -
+ ]
9039 184 [ - + ]: 16385 : if (s1len < 0)
9039 tgl@sss.pgh.pa.us 185 :UBC 0 : s1len = 0; /* shouldn't happen */
186 : :
6560 tgl@sss.pgh.pa.us 187 [ - + - - :CBC 16385 : s2len = VARSIZE_ANY_EXHDR(string2);
- - - - -
+ ]
9039 188 [ - + ]: 16385 : if (s2len < 0)
9039 tgl@sss.pgh.pa.us 189 :UBC 0 : s2len = 0; /* shouldn't happen */
190 : :
6560 tgl@sss.pgh.pa.us 191 [ - + ]:CBC 16385 : s1len = pg_mbstrlen_with_len(VARDATA_ANY(string1), s1len);
192 : :
9039 193 [ + + ]: 16385 : if (s1len > len)
194 : 35 : s1len = len; /* truncate string1 to len chars */
195 : :
196 [ + + ]: 16385 : if (s2len <= 0)
197 : 3 : len = s1len; /* nothing to pad with, so don't pad */
198 : :
199 : : /* compute worst-case output length */
1199 200 [ + - ]: 16385 : if (unlikely(pg_mul_s32_overflow(pg_database_encoding_max_length(), len,
201 : 16385 : &bytelen)) ||
202 [ + - ]: 16385 : unlikely(pg_add_s32_overflow(bytelen, VARHDRSZ, &bytelen)) ||
203 [ - + ]: 16385 : unlikely(!AllocSizeIsValid(bytelen)))
8077 tgl@sss.pgh.pa.us 204 [ # # ]:UBC 0 : ereport(ERROR,
205 : : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
206 : : errmsg("requested length too large")));
207 : :
1199 tgl@sss.pgh.pa.us 208 :CBC 16385 : ret = (text *) palloc(bytelen);
209 : :
9039 210 : 16385 : m = len - s1len;
211 : :
6560 212 [ - + ]: 16385 : ptr2 = ptr2start = VARDATA_ANY(string2);
9039 213 : 16385 : ptr2end = ptr2 + s2len;
10226 bruce@momjian.us 214 : 16385 : ptr_ret = VARDATA(ret);
215 : :
8749 ishii@postgresql.org 216 [ + + ]: 17443 : while (m--)
217 : : {
8717 bruce@momjian.us 218 : 1058 : int mlen = pg_mblen(ptr2);
219 : :
220 : 1058 : memcpy(ptr_ret, ptr2, mlen);
221 : 1058 : ptr_ret += mlen;
222 : 1058 : ptr2 += mlen;
223 [ + + ]: 1058 : if (ptr2 == ptr2end) /* wrap around at end of s2 */
6560 tgl@sss.pgh.pa.us 224 : 1046 : ptr2 = ptr2start;
225 : : }
226 : :
227 [ - + ]: 16385 : ptr1 = VARDATA_ANY(string1);
228 : :
8749 ishii@postgresql.org 229 [ + + ]: 48121 : while (s1len--)
230 : : {
8717 bruce@momjian.us 231 : 31736 : int mlen = pg_mblen(ptr1);
232 : :
233 : 31736 : memcpy(ptr_ret, ptr1, mlen);
234 : 31736 : ptr_ret += mlen;
235 : 31736 : ptr1 += mlen;
236 : : }
237 : :
6766 tgl@sss.pgh.pa.us 238 : 16385 : SET_VARSIZE(ret, ptr_ret - (char *) ret);
239 : :
9216 240 : 16385 : PG_RETURN_TEXT_P(ret);
241 : : }
242 : :
243 : :
244 : : /********************************************************************
245 : : *
246 : : * rpad
247 : : *
248 : : * Syntax:
249 : : *
250 : : * text rpad(text string1, int4 len, text string2)
251 : : *
252 : : * Purpose:
253 : : *
254 : : * Returns string1, right-padded to length len with the sequence of
255 : : * characters in string2. If len is less than the length of string1,
256 : : * instead truncate (on the right) to len.
257 : : *
258 : : ********************************************************************/
259 : :
260 : : Datum
261 : 22 : rpad(PG_FUNCTION_ARGS)
262 : : {
6560 263 : 22 : text *string1 = PG_GETARG_TEXT_PP(0);
9216 264 : 22 : int32 len = PG_GETARG_INT32(1);
6560 265 : 22 : text *string2 = PG_GETARG_TEXT_PP(2);
266 : : text *ret;
267 : : char *ptr1,
268 : : *ptr2,
269 : : *ptr2start,
270 : : *ptr2end,
271 : : *ptr_ret;
272 : : int m,
273 : : s1len,
274 : : s2len;
275 : : int bytelen;
276 : :
277 : : /* Negative len is silently taken as zero */
9039 278 [ + + ]: 22 : if (len < 0)
279 : 3 : len = 0;
280 : :
6560 281 [ - + - - : 22 : s1len = VARSIZE_ANY_EXHDR(string1);
- - - - -
+ ]
9039 282 [ - + ]: 22 : if (s1len < 0)
9039 tgl@sss.pgh.pa.us 283 :UBC 0 : s1len = 0; /* shouldn't happen */
284 : :
6560 tgl@sss.pgh.pa.us 285 [ - + - - :CBC 22 : s2len = VARSIZE_ANY_EXHDR(string2);
- - - - -
+ ]
9039 286 [ - + ]: 22 : if (s2len < 0)
9039 tgl@sss.pgh.pa.us 287 :UBC 0 : s2len = 0; /* shouldn't happen */
288 : :
6560 tgl@sss.pgh.pa.us 289 [ - + ]:CBC 22 : s1len = pg_mbstrlen_with_len(VARDATA_ANY(string1), s1len);
290 : :
9039 291 [ + + ]: 22 : if (s1len > len)
292 : 6 : s1len = len; /* truncate string1 to len chars */
293 : :
294 [ + + ]: 22 : if (s2len <= 0)
295 : 3 : len = s1len; /* nothing to pad with, so don't pad */
296 : :
297 : : /* compute worst-case output length */
1199 298 [ + - ]: 22 : if (unlikely(pg_mul_s32_overflow(pg_database_encoding_max_length(), len,
299 : 22 : &bytelen)) ||
300 [ + - ]: 22 : unlikely(pg_add_s32_overflow(bytelen, VARHDRSZ, &bytelen)) ||
301 [ - + ]: 22 : unlikely(!AllocSizeIsValid(bytelen)))
8077 tgl@sss.pgh.pa.us 302 [ # # ]:UBC 0 : ereport(ERROR,
303 : : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
304 : : errmsg("requested length too large")));
305 : :
1199 tgl@sss.pgh.pa.us 306 :CBC 22 : ret = (text *) palloc(bytelen);
307 : :
9039 308 : 22 : m = len - s1len;
309 : :
6560 310 [ - + ]: 22 : ptr1 = VARDATA_ANY(string1);
10226 bruce@momjian.us 311 : 22 : ptr_ret = VARDATA(ret);
312 : :
8749 ishii@postgresql.org 313 [ + + ]: 54 : while (s1len--)
314 : : {
8717 bruce@momjian.us 315 : 32 : int mlen = pg_mblen(ptr1);
316 : :
317 : 32 : memcpy(ptr_ret, ptr1, mlen);
318 : 32 : ptr_ret += mlen;
319 : 32 : ptr1 += mlen;
320 : : }
321 : :
6560 tgl@sss.pgh.pa.us 322 [ - + ]: 22 : ptr2 = ptr2start = VARDATA_ANY(string2);
9039 323 : 22 : ptr2end = ptr2 + s2len;
324 : :
8749 ishii@postgresql.org 325 [ + + ]: 960052 : while (m--)
326 : : {
8717 bruce@momjian.us 327 : 960030 : int mlen = pg_mblen(ptr2);
328 : :
329 : 960030 : memcpy(ptr_ret, ptr2, mlen);
330 : 960030 : ptr_ret += mlen;
331 : 960030 : ptr2 += mlen;
332 [ + + ]: 960030 : if (ptr2 == ptr2end) /* wrap around at end of s2 */
6560 tgl@sss.pgh.pa.us 333 : 960018 : ptr2 = ptr2start;
334 : : }
335 : :
6766 336 : 22 : SET_VARSIZE(ret, ptr_ret - (char *) ret);
337 : :
9216 338 : 22 : PG_RETURN_TEXT_P(ret);
339 : : }
340 : :
341 : :
342 : : /********************************************************************
343 : : *
344 : : * btrim
345 : : *
346 : : * Syntax:
347 : : *
348 : : * text btrim(text string, text set)
349 : : *
350 : : * Purpose:
351 : : *
352 : : * Returns string with characters removed from the front and back
353 : : * up to the first character not in set.
354 : : *
355 : : ********************************************************************/
356 : :
357 : : Datum
9193 358 : 10 : btrim(PG_FUNCTION_ARGS)
359 : : {
6560 360 : 10 : text *string = PG_GETARG_TEXT_PP(0);
361 : 10 : text *set = PG_GETARG_TEXT_PP(1);
362 : : text *ret;
363 : :
364 [ - + - - : 10 : ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),
- - - - -
+ - + ]
365 [ - + - - : 10 : VARDATA_ANY(set), VARSIZE_ANY_EXHDR(set),
- - - - -
+ - + ]
366 : : true, true);
367 : :
8142 368 : 10 : PG_RETURN_TEXT_P(ret);
369 : : }
370 : :
371 : : /********************************************************************
372 : : *
373 : : * btrim1 --- btrim with set fixed as ' '
374 : : *
375 : : ********************************************************************/
376 : :
377 : : Datum
378 : 281 : btrim1(PG_FUNCTION_ARGS)
379 : : {
6560 380 : 281 : text *string = PG_GETARG_TEXT_PP(0);
381 : : text *ret;
382 : :
383 [ - + - - : 281 : ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),
- - - - -
+ - + ]
384 : : " ", 1,
385 : : true, true);
386 : :
8142 387 : 281 : PG_RETURN_TEXT_P(ret);
388 : : }
389 : :
390 : : /*
391 : : * Common implementation for btrim, ltrim, rtrim
392 : : */
393 : : static text *
394 : 17166 : dotrim(const char *string, int stringlen,
395 : : const char *set, int setlen,
396 : : bool doltrim, bool dortrim)
397 : : {
398 : : int i;
399 : :
400 : : /* Nothing to do if either string or set is empty */
401 [ + - + - ]: 17166 : if (stringlen > 0 && setlen > 0)
402 : : {
403 [ + + ]: 17166 : if (pg_database_encoding_max_length() > 1)
404 : : {
405 : : /*
406 : : * In the multibyte-encoding case, build arrays of pointers to
407 : : * character starts, so that we can avoid inefficient checks in
408 : : * the inner loops.
409 : : */
410 : : const char **stringchars;
411 : : const char **setchars;
412 : : int *stringmblen;
413 : : int *setmblen;
414 : : int stringnchars;
415 : : int setnchars;
416 : : int resultndx;
417 : : int resultnchars;
418 : : const char *p;
419 : : int len;
420 : : int mblen;
421 : : const char *str_pos;
422 : : int str_len;
423 : :
424 : 17155 : stringchars = (const char **) palloc(stringlen * sizeof(char *));
425 : 17155 : stringmblen = (int *) palloc(stringlen * sizeof(int));
426 : 17155 : stringnchars = 0;
427 : 17155 : p = string;
428 : 17155 : len = stringlen;
429 [ + + ]: 152702 : while (len > 0)
430 : : {
431 : 135547 : stringchars[stringnchars] = p;
432 : 135547 : stringmblen[stringnchars] = mblen = pg_mblen(p);
433 : 135547 : stringnchars++;
434 : 135547 : p += mblen;
435 : 135547 : len -= mblen;
436 : : }
437 : :
438 : 17155 : setchars = (const char **) palloc(setlen * sizeof(char *));
439 : 17155 : setmblen = (int *) palloc(setlen * sizeof(int));
440 : 17155 : setnchars = 0;
441 : 17155 : p = set;
442 : 17155 : len = setlen;
443 [ + + ]: 34757 : while (len > 0)
444 : : {
445 : 17602 : setchars[setnchars] = p;
446 : 17602 : setmblen[setnchars] = mblen = pg_mblen(p);
447 : 17602 : setnchars++;
448 : 17602 : p += mblen;
449 : 17602 : len -= mblen;
450 : : }
451 : :
452 : 17155 : resultndx = 0; /* index in stringchars[] */
453 : 17155 : resultnchars = stringnchars;
454 : :
455 [ + + ]: 17155 : if (doltrim)
456 : : {
457 [ + - ]: 28294 : while (resultnchars > 0)
458 : : {
459 : 28294 : str_pos = stringchars[resultndx];
460 : 28294 : str_len = stringmblen[resultndx];
461 [ + + ]: 42605 : for (i = 0; i < setnchars; i++)
462 : : {
463 [ + - ]: 28354 : if (str_len == setmblen[i] &&
464 [ + + ]: 28354 : memcmp(str_pos, setchars[i], str_len) == 0)
465 : 14043 : break;
466 : : }
467 [ + + ]: 28294 : if (i >= setnchars)
468 : 14251 : break; /* no match here */
469 : 14043 : string += str_len;
470 : 14043 : stringlen -= str_len;
471 : 14043 : resultndx++;
472 : 14043 : resultnchars--;
473 : : }
474 : : }
475 : :
476 [ + + ]: 17155 : if (dortrim)
477 : : {
478 [ + - ]: 37354 : while (resultnchars > 0)
479 : : {
480 : 37354 : str_pos = stringchars[resultndx + resultnchars - 1];
481 : 37354 : str_len = stringmblen[resultndx + resultnchars - 1];
482 [ + + ]: 41770 : for (i = 0; i < setnchars; i++)
483 : : {
484 [ + - ]: 38575 : if (str_len == setmblen[i] &&
485 [ + + ]: 38575 : memcmp(str_pos, setchars[i], str_len) == 0)
486 : 34159 : break;
487 : : }
488 [ + + ]: 37354 : if (i >= setnchars)
489 : 3195 : break; /* no match here */
490 : 34159 : stringlen -= str_len;
491 : 34159 : resultnchars--;
492 : : }
493 : : }
494 : :
495 : 17155 : pfree(stringchars);
496 : 17155 : pfree(stringmblen);
497 : 17155 : pfree(setchars);
498 : 17155 : pfree(setmblen);
499 : : }
500 : : else
501 : : {
502 : : /*
503 : : * In the single-byte-encoding case, we don't need such overhead.
504 : : */
505 [ - + ]: 11 : if (doltrim)
506 : : {
8142 tgl@sss.pgh.pa.us 507 [ # # ]:UBC 0 : while (stringlen > 0)
508 : : {
8069 bruce@momjian.us 509 : 0 : char str_ch = *string;
510 : :
8142 tgl@sss.pgh.pa.us 511 [ # # ]: 0 : for (i = 0; i < setlen; i++)
512 : : {
513 [ # # ]: 0 : if (str_ch == set[i])
514 : 0 : break;
515 : : }
516 [ # # ]: 0 : if (i >= setlen)
517 : 0 : break; /* no match here */
518 : 0 : string++;
519 : 0 : stringlen--;
520 : : }
521 : : }
522 : :
8142 tgl@sss.pgh.pa.us 523 [ + - ]:CBC 11 : if (dortrim)
524 : : {
525 [ + - ]: 22 : while (stringlen > 0)
526 : : {
8069 bruce@momjian.us 527 : 22 : char str_ch = string[stringlen - 1];
528 : :
8142 tgl@sss.pgh.pa.us 529 [ + + ]: 33 : for (i = 0; i < setlen; i++)
530 : : {
531 [ + + ]: 22 : if (str_ch == set[i])
532 : 11 : break;
533 : : }
534 [ + + ]: 22 : if (i >= setlen)
535 : 11 : break; /* no match here */
536 : 11 : stringlen--;
537 : : }
538 : : }
539 : : }
540 : : }
541 : :
542 : : /* Return selected portion of string */
6374 543 : 17166 : return cstring_to_text_with_len(string, stringlen);
544 : : }
545 : :
546 : : /*
547 : : * Common implementation for bytea versions of btrim, ltrim, rtrim
548 : : */
549 : : bytea *
1692 550 : 18 : dobyteatrim(bytea *string, bytea *set, bool doltrim, bool dortrim)
551 : : {
552 : : bytea *ret;
553 : : char *ptr,
554 : : *end,
555 : : *ptr2,
556 : : *ptr2start,
557 : : *end2;
558 : : int m,
559 : : stringlen,
560 : : setlen;
561 : :
6560 562 [ - + - - : 18 : stringlen = VARSIZE_ANY_EXHDR(string);
- - - - -
+ ]
563 [ - + - - : 18 : setlen = VARSIZE_ANY_EXHDR(set);
- - - - -
+ ]
564 : :
565 [ + + + + ]: 18 : if (stringlen <= 0 || setlen <= 0)
1692 566 : 6 : return string;
567 : :
6560 568 : 12 : m = stringlen;
569 [ - + ]: 12 : ptr = VARDATA_ANY(string);
570 : 12 : end = ptr + stringlen - 1;
571 [ - + ]: 12 : ptr2start = VARDATA_ANY(set);
572 : 12 : end2 = ptr2start + setlen - 1;
573 : :
1692 574 [ + + ]: 12 : if (doltrim)
575 : : {
576 [ + - ]: 18 : while (m > 0)
577 : : {
578 : 18 : ptr2 = ptr2start;
579 [ + + ]: 27 : while (ptr2 <= end2)
580 : : {
581 [ + + ]: 18 : if (*ptr == *ptr2)
582 : 9 : break;
583 : 9 : ++ptr2;
584 : : }
585 [ + + ]: 18 : if (ptr2 > end2)
8758 bruce@momjian.us 586 : 9 : break;
1692 tgl@sss.pgh.pa.us 587 : 9 : ptr++;
588 : 9 : m--;
589 : : }
590 : : }
591 : :
592 [ + + ]: 12 : if (dortrim)
593 : : {
594 [ + - ]: 18 : while (m > 0)
595 : : {
596 : 18 : ptr2 = ptr2start;
597 [ + + ]: 27 : while (ptr2 <= end2)
598 : : {
599 [ + + ]: 18 : if (*end == *ptr2)
600 : 9 : break;
601 : 9 : ++ptr2;
602 : : }
603 [ + + ]: 18 : if (ptr2 > end2)
8758 bruce@momjian.us 604 : 9 : break;
1692 tgl@sss.pgh.pa.us 605 : 9 : end--;
606 : 9 : m--;
607 : : }
608 : : }
609 : :
8758 bruce@momjian.us 610 : 12 : ret = (bytea *) palloc(VARHDRSZ + m);
6766 tgl@sss.pgh.pa.us 611 : 12 : SET_VARSIZE(ret, VARHDRSZ + m);
8758 bruce@momjian.us 612 : 12 : memcpy(VARDATA(ret), ptr, m);
1692 tgl@sss.pgh.pa.us 613 : 12 : return ret;
614 : : }
615 : :
616 : : /********************************************************************
617 : : *
618 : : * byteatrim
619 : : *
620 : : * Syntax:
621 : : *
622 : : * bytea byteatrim(bytea string, bytea set)
623 : : *
624 : : * Purpose:
625 : : *
626 : : * Returns string with characters removed from the front and back
627 : : * up to the first character not in set.
628 : : *
629 : : * Cloned from btrim and modified as required.
630 : : ********************************************************************/
631 : :
632 : : Datum
633 : 12 : byteatrim(PG_FUNCTION_ARGS)
634 : : {
635 : 12 : bytea *string = PG_GETARG_BYTEA_PP(0);
636 : 12 : bytea *set = PG_GETARG_BYTEA_PP(1);
637 : : bytea *ret;
638 : :
639 : 12 : ret = dobyteatrim(string, set, true, true);
640 : :
641 : 12 : PG_RETURN_BYTEA_P(ret);
642 : : }
643 : :
644 : : /********************************************************************
645 : : *
646 : : * bytealtrim
647 : : *
648 : : * Syntax:
649 : : *
650 : : * bytea bytealtrim(bytea string, bytea set)
651 : : *
652 : : * Purpose:
653 : : *
654 : : * Returns string with initial characters removed up to the first
655 : : * character not in set.
656 : : *
657 : : ********************************************************************/
658 : :
659 : : Datum
660 : 3 : bytealtrim(PG_FUNCTION_ARGS)
661 : : {
662 : 3 : bytea *string = PG_GETARG_BYTEA_PP(0);
663 : 3 : bytea *set = PG_GETARG_BYTEA_PP(1);
664 : : bytea *ret;
665 : :
666 : 3 : ret = dobyteatrim(string, set, true, false);
667 : :
668 : 3 : PG_RETURN_BYTEA_P(ret);
669 : : }
670 : :
671 : : /********************************************************************
672 : : *
673 : : * byteartrim
674 : : *
675 : : * Syntax:
676 : : *
677 : : * bytea byteartrim(bytea string, bytea set)
678 : : *
679 : : * Purpose:
680 : : *
681 : : * Returns string with final characters removed after the last
682 : : * character not in set.
683 : : *
684 : : ********************************************************************/
685 : :
686 : : Datum
687 : 3 : byteartrim(PG_FUNCTION_ARGS)
688 : : {
689 : 3 : bytea *string = PG_GETARG_BYTEA_PP(0);
690 : 3 : bytea *set = PG_GETARG_BYTEA_PP(1);
691 : : bytea *ret;
692 : :
693 : 3 : ret = dobyteatrim(string, set, false, true);
694 : :
8758 bruce@momjian.us 695 : 3 : PG_RETURN_BYTEA_P(ret);
696 : : }
697 : :
698 : : /********************************************************************
699 : : *
700 : : * ltrim
701 : : *
702 : : * Syntax:
703 : : *
704 : : * text ltrim(text string, text set)
705 : : *
706 : : * Purpose:
707 : : *
708 : : * Returns string with initial characters removed up to the first
709 : : * character not in set.
710 : : *
711 : : ********************************************************************/
712 : :
713 : : Datum
9193 tgl@sss.pgh.pa.us 714 : 13956 : ltrim(PG_FUNCTION_ARGS)
715 : : {
6560 716 : 13956 : text *string = PG_GETARG_TEXT_PP(0);
717 : 13956 : text *set = PG_GETARG_TEXT_PP(1);
718 : : text *ret;
719 : :
720 [ - + - - : 13956 : ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),
- - - - +
+ + + ]
721 [ - + - - : 13956 : VARDATA_ANY(set), VARSIZE_ANY_EXHDR(set),
- - - - -
+ - + ]
722 : : true, false);
723 : :
8142 724 : 13956 : PG_RETURN_TEXT_P(ret);
725 : : }
726 : :
727 : : /********************************************************************
728 : : *
729 : : * ltrim1 --- ltrim with set fixed as ' '
730 : : *
731 : : ********************************************************************/
732 : :
733 : : Datum
734 : 4 : ltrim1(PG_FUNCTION_ARGS)
735 : : {
6560 736 : 4 : text *string = PG_GETARG_TEXT_PP(0);
737 : : text *ret;
738 : :
739 [ - + - - : 4 : ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),
- - - - -
+ - + ]
740 : : " ", 1,
741 : : true, false);
742 : :
9193 743 : 4 : PG_RETURN_TEXT_P(ret);
744 : : }
745 : :
746 : : /********************************************************************
747 : : *
748 : : * rtrim
749 : : *
750 : : * Syntax:
751 : : *
752 : : * text rtrim(text string, text set)
753 : : *
754 : : * Purpose:
755 : : *
756 : : * Returns string with final characters removed after the last
757 : : * character not in set.
758 : : *
759 : : ********************************************************************/
760 : :
761 : : Datum
762 : 153 : rtrim(PG_FUNCTION_ARGS)
763 : : {
6560 764 : 153 : text *string = PG_GETARG_TEXT_PP(0);
765 : 153 : text *set = PG_GETARG_TEXT_PP(1);
766 : : text *ret;
767 : :
768 [ - + - - : 153 : ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),
- - - - -
+ - + ]
769 [ - + - - : 153 : VARDATA_ANY(set), VARSIZE_ANY_EXHDR(set),
- - - - -
+ - + ]
770 : : false, true);
771 : :
8142 772 : 153 : PG_RETURN_TEXT_P(ret);
773 : : }
774 : :
775 : : /********************************************************************
776 : : *
777 : : * rtrim1 --- rtrim with set fixed as ' '
778 : : *
779 : : ********************************************************************/
780 : :
781 : : Datum
782 : 2762 : rtrim1(PG_FUNCTION_ARGS)
783 : : {
6560 784 : 2762 : text *string = PG_GETARG_TEXT_PP(0);
785 : : text *ret;
786 : :
787 [ - + - - : 2762 : ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),
- - - - +
+ + + ]
788 : : " ", 1,
789 : : false, true);
790 : :
9193 791 : 2762 : PG_RETURN_TEXT_P(ret);
792 : : }
793 : :
794 : :
795 : : /********************************************************************
796 : : *
797 : : * translate
798 : : *
799 : : * Syntax:
800 : : *
801 : : * text translate(text string, text from, text to)
802 : : *
803 : : * Purpose:
804 : : *
805 : : * Returns string after replacing all occurrences of characters in from
806 : : * with the corresponding character in to. If from is longer than to,
807 : : * occurrences of the extra characters in from are deleted.
808 : : * Improved by Edwin Ramirez <ramirez@doc.mssm.edu>.
809 : : *
810 : : ********************************************************************/
811 : :
812 : : Datum
813 : 17 : translate(PG_FUNCTION_ARGS)
814 : : {
6560 815 : 17 : text *string = PG_GETARG_TEXT_PP(0);
816 : 17 : text *from = PG_GETARG_TEXT_PP(1);
817 : 17 : text *to = PG_GETARG_TEXT_PP(2);
818 : : text *result;
819 : : char *from_ptr,
820 : : *to_ptr,
821 : : *to_end;
822 : : char *source,
823 : : *target;
824 : : int m,
825 : : fromlen,
826 : : tolen,
827 : : retlen,
828 : : i;
829 : : int bytelen;
830 : : int len;
831 : : int source_len;
832 : : int from_index;
833 : :
834 [ - + - - : 17 : m = VARSIZE_ANY_EXHDR(string);
- - - - -
+ ]
835 [ + + ]: 17 : if (m <= 0)
9193 836 : 3 : PG_RETURN_TEXT_P(string);
6559 837 [ - + ]: 14 : source = VARDATA_ANY(string);
838 : :
6560 839 [ - + - - : 14 : fromlen = VARSIZE_ANY_EXHDR(from);
- - - - -
+ ]
840 [ - + ]: 14 : from_ptr = VARDATA_ANY(from);
841 [ - + - - : 14 : tolen = VARSIZE_ANY_EXHDR(to);
- - - - -
+ ]
842 [ - + ]: 14 : to_ptr = VARDATA_ANY(to);
920 843 : 14 : to_end = to_ptr + tolen;
844 : :
845 : : /*
846 : : * The worst-case expansion is to substitute a max-length character for a
847 : : * single-byte character at each position of the string.
848 : : */
1199 849 [ + - ]: 14 : if (unlikely(pg_mul_s32_overflow(pg_database_encoding_max_length(), m,
850 : 14 : &bytelen)) ||
851 [ + - ]: 14 : unlikely(pg_add_s32_overflow(bytelen, VARHDRSZ, &bytelen)) ||
852 [ - + ]: 14 : unlikely(!AllocSizeIsValid(bytelen)))
6559 tgl@sss.pgh.pa.us 853 [ # # ]:UBC 0 : ereport(ERROR,
854 : : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
855 : : errmsg("requested length too large")));
856 : :
1199 tgl@sss.pgh.pa.us 857 :CBC 14 : result = (text *) palloc(bytelen);
858 : :
9306 859 : 14 : target = VARDATA(result);
9307 lockhart@fourpalms.o 860 : 14 : retlen = 0;
861 : :
8749 ishii@postgresql.org 862 [ + + ]: 140 : while (m > 0)
863 : : {
864 : 126 : source_len = pg_mblen(source);
865 : 126 : from_index = 0;
866 : :
867 [ + + ]: 342 : for (i = 0; i < fromlen; i += len)
868 : : {
8717 bruce@momjian.us 869 : 247 : len = pg_mblen(&from_ptr[i]);
870 [ + - ]: 247 : if (len == source_len &&
871 [ + + ]: 247 : memcmp(source, &from_ptr[i], len) == 0)
872 : 31 : break;
873 : :
874 : 216 : from_index++;
875 : : }
8749 ishii@postgresql.org 876 [ + + ]: 126 : if (i < fromlen)
877 : : {
878 : : /* substitute, or delete if no corresponding "to" character */
8717 bruce@momjian.us 879 : 31 : char *p = to_ptr;
880 : :
881 [ + + ]: 48 : for (i = 0; i < from_index; i++)
882 : : {
920 tgl@sss.pgh.pa.us 883 [ + + ]: 20 : if (p >= to_end)
8717 bruce@momjian.us 884 : 3 : break;
920 tgl@sss.pgh.pa.us 885 : 17 : p += pg_mblen(p);
886 : : }
887 [ + + ]: 31 : if (p < to_end)
888 : : {
8717 bruce@momjian.us 889 : 25 : len = pg_mblen(p);
890 : 25 : memcpy(target, p, len);
891 : 25 : target += len;
892 : 25 : retlen += len;
893 : : }
894 : : }
895 : : else
896 : : {
897 : : /* no match, so copy */
898 : 95 : memcpy(target, source, source_len);
899 : 95 : target += source_len;
900 : 95 : retlen += source_len;
901 : : }
902 : :
8749 ishii@postgresql.org 903 : 126 : source += source_len;
904 : 126 : m -= source_len;
905 : : }
906 : :
6766 tgl@sss.pgh.pa.us 907 : 14 : SET_VARSIZE(result, retlen + VARHDRSZ);
908 : :
909 : : /*
910 : : * The function result is probably much bigger than needed, if we're using
911 : : * a multibyte encoding, but it's not worth reallocating it; the result
912 : : * probably won't live long anyway.
913 : : */
914 : :
9193 915 : 14 : PG_RETURN_TEXT_P(result);
916 : : }
917 : :
918 : : /********************************************************************
919 : : *
920 : : * ascii
921 : : *
922 : : * Syntax:
923 : : *
924 : : * int ascii(text string)
925 : : *
926 : : * Purpose:
927 : : *
928 : : * Returns the decimal representation of the first character from
929 : : * string.
930 : : * If the string is empty we return 0.
931 : : * If the database encoding is UTF8, we return the Unicode codepoint.
932 : : * If the database encoding is any other multi-byte encoding, we
933 : : * return the value of the first byte if it is an ASCII character
934 : : * (range 1 .. 127), or raise an error.
935 : : * For all other encodings we return the value of the first byte,
936 : : * (range 1..255).
937 : : *
938 : : ********************************************************************/
939 : :
940 : : Datum
941 : 29 : ascii(PG_FUNCTION_ARGS)
942 : : {
6560 943 : 29 : text *string = PG_GETARG_TEXT_PP(0);
6505 bruce@momjian.us 944 : 29 : int encoding = GetDatabaseEncoding();
945 : : unsigned char *data;
946 : :
6560 tgl@sss.pgh.pa.us 947 [ + + - - : 29 : if (VARSIZE_ANY_EXHDR(string) <= 0)
- - - - +
+ + + ]
9193 948 : 3 : PG_RETURN_INT32(0);
949 : :
6560 950 [ + + ]: 26 : data = (unsigned char *) VARDATA_ANY(string);
951 : :
6563 andrew@dunslane.net 952 [ + - - + ]: 26 : if (encoding == PG_UTF8 && *data > 127)
953 : : {
954 : : /* return the code point for Unicode */
955 : :
6505 bruce@momjian.us 956 :UBC 0 : int result = 0,
957 : 0 : tbytes = 0,
958 : : i;
959 : :
6563 andrew@dunslane.net 960 [ # # ]: 0 : if (*data >= 0xF0)
961 : : {
962 : 0 : result = *data & 0x07;
963 : 0 : tbytes = 3;
964 : : }
965 [ # # ]: 0 : else if (*data >= 0xE0)
966 : : {
967 : 0 : result = *data & 0x0F;
968 : 0 : tbytes = 2;
969 : : }
970 : : else
971 : : {
6505 bruce@momjian.us 972 [ # # ]: 0 : Assert(*data > 0xC0);
6563 andrew@dunslane.net 973 : 0 : result = *data & 0x1f;
974 : 0 : tbytes = 1;
975 : : }
976 : :
6505 bruce@momjian.us 977 [ # # ]: 0 : Assert(tbytes > 0);
978 : :
6563 andrew@dunslane.net 979 [ # # ]: 0 : for (i = 1; i <= tbytes; i++)
980 : : {
6505 bruce@momjian.us 981 [ # # ]: 0 : Assert((data[i] & 0xC0) == 0x80);
6563 andrew@dunslane.net 982 : 0 : result = (result << 6) + (data[i] & 0x3f);
983 : : }
984 : :
985 : 0 : PG_RETURN_INT32(result);
986 : : }
987 : : else
988 : : {
6563 andrew@dunslane.net 989 [ + - - + ]:CBC 26 : if (pg_encoding_max_length(encoding) > 1 && *data > 127)
6563 andrew@dunslane.net 990 [ # # ]:UBC 0 : ereport(ERROR,
991 : : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
992 : : errmsg("requested character too large")));
993 : :
994 : :
6563 andrew@dunslane.net 995 :CBC 26 : PG_RETURN_INT32((int32) *data);
996 : : }
997 : : }
998 : :
999 : : /********************************************************************
1000 : : *
1001 : : * chr
1002 : : *
1003 : : * Syntax:
1004 : : *
1005 : : * text chr(int val)
1006 : : *
1007 : : * Purpose:
1008 : : *
1009 : : * Returns the character having the binary equivalent to val.
1010 : : *
1011 : : * For UTF8 we treat the argument as a Unicode code point.
1012 : : * For other multi-byte encodings we raise an error for arguments
1013 : : * outside the strict ASCII range (1..127).
1014 : : *
1015 : : * It's important that we don't ever return a value that is not valid
1016 : : * in the database encoding, so that this doesn't become a way for
1017 : : * invalid data to enter the database.
1018 : : *
1019 : : ********************************************************************/
1020 : :
1021 : : Datum
6505 bruce@momjian.us 1022 : 271809 : chr (PG_FUNCTION_ARGS)
1023 : : {
1370 peter@eisentraut.org 1024 : 271809 : int32 arg = PG_GETARG_INT32(0);
1025 : : uint32 cvalue;
1026 : : text *result;
6505 bruce@momjian.us 1027 : 271809 : int encoding = GetDatabaseEncoding();
1028 : :
1029 : : /*
1030 : : * Error out on arguments that make no sense or that we can't validly
1031 : : * represent in the encoding.
1032 : : */
1370 peter@eisentraut.org 1033 [ - + ]: 271809 : if (arg < 0)
1370 peter@eisentraut.org 1034 [ # # ]:UBC 0 : ereport(ERROR,
1035 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1036 : : errmsg("character number must be positive")));
1370 peter@eisentraut.org 1037 [ + + ]:CBC 271809 : else if (arg == 0)
1038 [ + - ]: 3 : ereport(ERROR,
1039 : : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1040 : : errmsg("null character not permitted")));
1041 : :
1042 : 271806 : cvalue = arg;
1043 : :
6563 andrew@dunslane.net 1044 [ + - - + ]: 271806 : if (encoding == PG_UTF8 && cvalue > 127)
6563 andrew@dunslane.net 1045 :UBC 0 : {
1046 : : /* for Unicode we treat the argument as a code point */
1047 : : int bytes;
1048 : : unsigned char *wch;
1049 : :
1050 : : /*
1051 : : * We only allow valid Unicode code points; per RFC3629 that stops at
1052 : : * U+10FFFF, even though 4-byte UTF8 sequences can hold values up to
1053 : : * U+1FFFFF.
1054 : : */
4131 tgl@sss.pgh.pa.us 1055 [ # # ]: 0 : if (cvalue > 0x0010ffff)
6563 andrew@dunslane.net 1056 [ # # ]: 0 : ereport(ERROR,
1057 : : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1058 : : errmsg("requested character too large for encoding: %u",
1059 : : cvalue)));
1060 : :
1061 [ # # ]: 0 : if (cvalue > 0xffff)
1062 : 0 : bytes = 4;
1063 [ # # ]: 0 : else if (cvalue > 0x07ff)
1064 : 0 : bytes = 3;
1065 : : else
1066 : 0 : bytes = 2;
1067 : :
1068 : 0 : result = (text *) palloc(VARHDRSZ + bytes);
1069 : 0 : SET_VARSIZE(result, VARHDRSZ + bytes);
4131 tgl@sss.pgh.pa.us 1070 : 0 : wch = (unsigned char *) VARDATA(result);
1071 : :
6563 andrew@dunslane.net 1072 [ # # ]: 0 : if (bytes == 2)
1073 : : {
1074 : 0 : wch[0] = 0xC0 | ((cvalue >> 6) & 0x1F);
3812 heikki.linnakangas@i 1075 : 0 : wch[1] = 0x80 | (cvalue & 0x3F);
1076 : : }
6563 andrew@dunslane.net 1077 [ # # ]: 0 : else if (bytes == 3)
1078 : : {
1079 : 0 : wch[0] = 0xE0 | ((cvalue >> 12) & 0x0F);
1080 : 0 : wch[1] = 0x80 | ((cvalue >> 6) & 0x3F);
1081 : 0 : wch[2] = 0x80 | (cvalue & 0x3F);
1082 : : }
1083 : : else
1084 : : {
1085 : 0 : wch[0] = 0xF0 | ((cvalue >> 18) & 0x07);
1086 : 0 : wch[1] = 0x80 | ((cvalue >> 12) & 0x3F);
1087 : 0 : wch[2] = 0x80 | ((cvalue >> 6) & 0x3F);
1088 : 0 : wch[3] = 0x80 | (cvalue & 0x3F);
1089 : : }
1090 : :
1091 : : /*
1092 : : * The preceding range check isn't sufficient, because UTF8 excludes
1093 : : * Unicode "surrogate pair" codes. Make sure what we created is valid
1094 : : * UTF8.
1095 : : */
4131 tgl@sss.pgh.pa.us 1096 [ # # ]: 0 : if (!pg_utf8_islegal(wch, bytes))
1097 [ # # ]: 0 : ereport(ERROR,
1098 : : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1099 : : errmsg("requested character not valid for encoding: %u",
1100 : : cvalue)));
1101 : : }
1102 : : else
1103 : : {
1104 : : bool is_mb;
1105 : :
6563 andrew@dunslane.net 1106 :CBC 271806 : is_mb = pg_encoding_max_length(encoding) > 1;
1107 : :
6472 1108 [ + - + - : 271806 : if ((is_mb && (cvalue > 127)) || (!is_mb && (cvalue > 255)))
- + - - ]
6563 andrew@dunslane.net 1109 [ # # ]:UBC 0 : ereport(ERROR,
1110 : : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1111 : : errmsg("requested character too large for encoding: %u",
1112 : : cvalue)));
1113 : :
6563 andrew@dunslane.net 1114 :CBC 271806 : result = (text *) palloc(VARHDRSZ + 1);
1115 : 271806 : SET_VARSIZE(result, VARHDRSZ + 1);
1116 : 271806 : *VARDATA(result) = (char) cvalue;
1117 : : }
1118 : :
9216 tgl@sss.pgh.pa.us 1119 : 271806 : PG_RETURN_TEXT_P(result);
1120 : : }
1121 : :
1122 : : /********************************************************************
1123 : : *
1124 : : * repeat
1125 : : *
1126 : : * Syntax:
1127 : : *
1128 : : * text repeat(text string, int val)
1129 : : *
1130 : : * Purpose:
1131 : : *
1132 : : * Repeat string by val.
1133 : : *
1134 : : ********************************************************************/
1135 : :
1136 : : Datum
1137 : 24815 : repeat(PG_FUNCTION_ARGS)
1138 : : {
6560 1139 : 24815 : text *string = PG_GETARG_TEXT_PP(0);
8934 bruce@momjian.us 1140 : 24815 : int32 count = PG_GETARG_INT32(1);
1141 : : text *result;
1142 : : int slen,
1143 : : tlen;
1144 : : int i;
1145 : : char *cp,
1146 : : *sp;
1147 : :
9283 lockhart@fourpalms.o 1148 [ + + ]: 24815 : if (count < 0)
1149 : 3 : count = 0;
1150 : :
6560 tgl@sss.pgh.pa.us 1151 [ - + - - : 24815 : slen = VARSIZE_ANY_EXHDR(string);
- - - - -
+ ]
1152 : :
2825 andres@anarazel.de 1153 [ + - ]: 24815 : if (unlikely(pg_mul_s32_overflow(count, slen, &tlen)) ||
1199 tgl@sss.pgh.pa.us 1154 [ + - ]: 24815 : unlikely(pg_add_s32_overflow(tlen, VARHDRSZ, &tlen)) ||
1155 [ - + ]: 24815 : unlikely(!AllocSizeIsValid(tlen)))
2825 andres@anarazel.de 1156 [ # # ]:UBC 0 : ereport(ERROR,
1157 : : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1158 : : errmsg("requested length too large")));
1159 : :
9283 lockhart@fourpalms.o 1160 :CBC 24815 : result = (text *) palloc(tlen);
1161 : :
6766 tgl@sss.pgh.pa.us 1162 : 24815 : SET_VARSIZE(result, tlen);
9283 lockhart@fourpalms.o 1163 : 24815 : cp = VARDATA(result);
6560 tgl@sss.pgh.pa.us 1164 [ - + ]: 24815 : sp = VARDATA_ANY(string);
9283 lockhart@fourpalms.o 1165 [ + + ]: 23998655 : for (i = 0; i < count; i++)
1166 : : {
6560 tgl@sss.pgh.pa.us 1167 : 23973840 : memcpy(cp, sp, slen);
9283 lockhart@fourpalms.o 1168 : 23973840 : cp += slen;
1927 mail@joeconway.com 1169 [ - + ]: 23973840 : CHECK_FOR_INTERRUPTS();
1170 : : }
1171 : :
9216 tgl@sss.pgh.pa.us 1172 : 24815 : PG_RETURN_TEXT_P(result);
1173 : : }
|