]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/varlena.c
Code review for regexp_replace patch. Improve documentation and comments,
[postgresql] / src / backend / utils / adt / varlena.c
1 /*-------------------------------------------------------------------------
2  *
3  * varlena.c
4  *        Functions for the variable-length built-in types.
5  *
6  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.138 2005/10/18 20:38:58 tgl Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include <ctype.h>
18
19 #include "access/tuptoaster.h"
20 #include "catalog/pg_type.h"
21 #include "lib/stringinfo.h"
22 #include "libpq/crypt.h"
23 #include "libpq/pqformat.h"
24 #include "mb/pg_wchar.h"
25 #include "miscadmin.h"
26 #include "parser/scansup.h"
27 #include "regex/regex.h"
28 #include "utils/array.h"
29 #include "utils/builtins.h"
30 #include "utils/lsyscache.h"
31 #include "utils/pg_locale.h"
32
33
34 typedef struct varlena unknown;
35
36 #define DatumGetUnknownP(X)                     ((unknown *) PG_DETOAST_DATUM(X))
37 #define DatumGetUnknownPCopy(X)         ((unknown *) PG_DETOAST_DATUM_COPY(X))
38 #define PG_GETARG_UNKNOWN_P(n)          DatumGetUnknownP(PG_GETARG_DATUM(n))
39 #define PG_GETARG_UNKNOWN_P_COPY(n) DatumGetUnknownPCopy(PG_GETARG_DATUM(n))
40 #define PG_RETURN_UNKNOWN_P(x)          PG_RETURN_POINTER(x)
41
42 #define PG_TEXTARG_GET_STR(arg_) \
43         DatumGetCString(DirectFunctionCall1(textout, PG_GETARG_DATUM(arg_)))
44 #define PG_TEXT_GET_STR(textp_) \
45         DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp_)))
46 #define PG_STR_GET_TEXT(str_) \
47         DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(str_)))
48 #define TEXTLEN(textp) \
49         text_length(PointerGetDatum(textp))
50 #define TEXTPOS(buf_text, from_sub_text) \
51         text_position(buf_text, from_sub_text, 1)
52 #define LEFT(buf_text, from_sub_text) \
53         text_substring(PointerGetDatum(buf_text), \
54                                         1, \
55                                         TEXTPOS(buf_text, from_sub_text) - 1, false)
56
57 static int      text_cmp(text *arg1, text *arg2);
58 static int32 text_length(Datum str);
59 static int32 text_position(text *t1, text *t2, int matchnum);
60 static text *text_substring(Datum str,
61                            int32 start,
62                            int32 length,
63                            bool length_not_specified);
64
65 static void appendStringInfoText(StringInfo str, const text *t);
66
67
68 /*****************************************************************************
69  *       USER I/O ROUTINES                                                                                                               *
70  *****************************************************************************/
71
72
73 #define VAL(CH)                 ((CH) - '0')
74 #define DIG(VAL)                ((VAL) + '0')
75
76 /*
77  *              byteain                 - converts from printable representation of byte array
78  *
79  *              Non-printable characters must be passed as '\nnn' (octal) and are
80  *              converted to internal form.  '\' must be passed as '\\'.
81  *              ereport(ERROR, ...) if bad form.
82  *
83  *              BUGS:
84  *                              The input is scaned twice.
85  *                              The error checking of input is minimal.
86  */
87 Datum
88 byteain(PG_FUNCTION_ARGS)
89 {
90         char       *inputText = PG_GETARG_CSTRING(0);
91         char       *tp;
92         char       *rp;
93         int                     byte;
94         bytea      *result;
95
96         for (byte = 0, tp = inputText; *tp != '\0'; byte++)
97         {
98                 if (tp[0] != '\\')
99                         tp++;
100                 else if ((tp[0] == '\\') &&
101                                  (tp[1] >= '0' && tp[1] <= '3') &&
102                                  (tp[2] >= '0' && tp[2] <= '7') &&
103                                  (tp[3] >= '0' && tp[3] <= '7'))
104                         tp += 4;
105                 else if ((tp[0] == '\\') &&
106                                  (tp[1] == '\\'))
107                         tp += 2;
108                 else
109                 {
110                         /*
111                          * one backslash, not followed by 0 or ### valid octal
112                          */
113                         ereport(ERROR,
114                                         (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
115                                          errmsg("invalid input syntax for type bytea")));
116                 }
117         }
118
119         byte += VARHDRSZ;
120         result = (bytea *) palloc(byte);
121         VARATT_SIZEP(result) = byte;    /* set varlena length */
122
123         tp = inputText;
124         rp = VARDATA(result);
125         while (*tp != '\0')
126         {
127                 if (tp[0] != '\\')
128                         *rp++ = *tp++;
129                 else if ((tp[0] == '\\') &&
130                                  (tp[1] >= '0' && tp[1] <= '3') &&
131                                  (tp[2] >= '0' && tp[2] <= '7') &&
132                                  (tp[3] >= '0' && tp[3] <= '7'))
133                 {
134                         byte = VAL(tp[1]);
135                         byte <<= 3;
136                         byte += VAL(tp[2]);
137                         byte <<= 3;
138                         *rp++ = byte + VAL(tp[3]);
139                         tp += 4;
140                 }
141                 else if ((tp[0] == '\\') &&
142                                  (tp[1] == '\\'))
143                 {
144                         *rp++ = '\\';
145                         tp += 2;
146                 }
147                 else
148                 {
149                         /*
150                          * We should never get here. The first pass should not allow it.
151                          */
152                         ereport(ERROR,
153                                         (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
154                                          errmsg("invalid input syntax for type bytea")));
155                 }
156         }
157
158         PG_RETURN_BYTEA_P(result);
159 }
160
161 /*
162  *              byteaout                - converts to printable representation of byte array
163  *
164  *              Non-printable characters are inserted as '\nnn' (octal) and '\' as
165  *              '\\'.
166  *
167  *              NULL vlena should be an error--returning string with NULL for now.
168  */
169 Datum
170 byteaout(PG_FUNCTION_ARGS)
171 {
172         bytea      *vlena = PG_GETARG_BYTEA_P(0);
173         char       *result;
174         char       *vp;
175         char       *rp;
176         int                     val;                    /* holds unprintable chars */
177         int                     i;
178         int                     len;
179
180         len = 1;                                        /* empty string has 1 char */
181         vp = VARDATA(vlena);
182         for (i = VARSIZE(vlena) - VARHDRSZ; i != 0; i--, vp++)
183         {
184                 if (*vp == '\\')
185                         len += 2;
186                 else if ((unsigned char) *vp < 0x20 || (unsigned char) *vp > 0x7e)
187                         len += 4;
188                 else
189                         len++;
190         }
191         rp = result = (char *) palloc(len);
192         vp = VARDATA(vlena);
193         for (i = VARSIZE(vlena) - VARHDRSZ; i != 0; i--, vp++)
194         {
195                 if (*vp == '\\')
196                 {
197                         *rp++ = '\\';
198                         *rp++ = '\\';
199                 }
200                 else if ((unsigned char) *vp < 0x20 || (unsigned char) *vp > 0x7e)
201                 {
202                         val = *vp;
203                         rp[0] = '\\';
204                         rp[3] = DIG(val & 07);
205                         val >>= 3;
206                         rp[2] = DIG(val & 07);
207                         val >>= 3;
208                         rp[1] = DIG(val & 03);
209                         rp += 4;
210                 }
211                 else
212                         *rp++ = *vp;
213         }
214         *rp = '\0';
215         PG_RETURN_CSTRING(result);
216 }
217
218 /*
219  *              bytearecv                       - converts external binary format to bytea
220  */
221 Datum
222 bytearecv(PG_FUNCTION_ARGS)
223 {
224         StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
225         bytea      *result;
226         int                     nbytes;
227
228         nbytes = buf->len - buf->cursor;
229         result = (bytea *) palloc(nbytes + VARHDRSZ);
230         VARATT_SIZEP(result) = nbytes + VARHDRSZ;
231         pq_copymsgbytes(buf, VARDATA(result), nbytes);
232         PG_RETURN_BYTEA_P(result);
233 }
234
235 /*
236  *              byteasend                       - converts bytea to binary format
237  *
238  * This is a special case: just copy the input...
239  */
240 Datum
241 byteasend(PG_FUNCTION_ARGS)
242 {
243         bytea      *vlena = PG_GETARG_BYTEA_P_COPY(0);
244
245         PG_RETURN_BYTEA_P(vlena);
246 }
247
248
249 /*
250  *              textin                  - converts "..." to internal representation
251  */
252 Datum
253 textin(PG_FUNCTION_ARGS)
254 {
255         char       *inputText = PG_GETARG_CSTRING(0);
256         text       *result;
257         int                     len;
258
259         /* verify encoding */
260         len = strlen(inputText);
261         pg_verifymbstr(inputText, len, false);
262
263         result = (text *) palloc(len + VARHDRSZ);
264         VARATT_SIZEP(result) = len + VARHDRSZ;
265
266         memcpy(VARDATA(result), inputText, len);
267
268         PG_RETURN_TEXT_P(result);
269 }
270
271 /*
272  *              textout                 - converts internal representation to "..."
273  */
274 Datum
275 textout(PG_FUNCTION_ARGS)
276 {
277         text       *t = PG_GETARG_TEXT_P(0);
278         int                     len;
279         char       *result;
280
281         len = VARSIZE(t) - VARHDRSZ;
282         result = (char *) palloc(len + 1);
283         memcpy(result, VARDATA(t), len);
284         result[len] = '\0';
285
286         PG_RETURN_CSTRING(result);
287 }
288
289 /*
290  *              textrecv                        - converts external binary format to text
291  */
292 Datum
293 textrecv(PG_FUNCTION_ARGS)
294 {
295         StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
296         text       *result;
297         char       *str;
298         int                     nbytes;
299
300         str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
301
302         /* verify encoding */
303         pg_verifymbstr(str, nbytes, false);
304
305         result = (text *) palloc(nbytes + VARHDRSZ);
306         VARATT_SIZEP(result) = nbytes + VARHDRSZ;
307         memcpy(VARDATA(result), str, nbytes);
308         pfree(str);
309         PG_RETURN_TEXT_P(result);
310 }
311
312 /*
313  *              textsend                        - converts text to binary format
314  */
315 Datum
316 textsend(PG_FUNCTION_ARGS)
317 {
318         text       *t = PG_GETARG_TEXT_P(0);
319         StringInfoData buf;
320
321         pq_begintypsend(&buf);
322         pq_sendtext(&buf, VARDATA(t), VARSIZE(t) - VARHDRSZ);
323         PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
324 }
325
326
327 /*
328  *              unknownin                       - converts "..." to internal representation
329  */
330 Datum
331 unknownin(PG_FUNCTION_ARGS)
332 {
333         char       *str = PG_GETARG_CSTRING(0);
334
335         /* representation is same as cstring */
336         PG_RETURN_CSTRING(pstrdup(str));
337 }
338
339 /*
340  *              unknownout                      - converts internal representation to "..."
341  */
342 Datum
343 unknownout(PG_FUNCTION_ARGS)
344 {
345         /* representation is same as cstring */
346         char       *str = PG_GETARG_CSTRING(0);
347
348         PG_RETURN_CSTRING(pstrdup(str));
349 }
350
351 /*
352  *              unknownrecv                     - converts external binary format to unknown
353  */
354 Datum
355 unknownrecv(PG_FUNCTION_ARGS)
356 {
357         StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
358         char       *str;
359         int                     nbytes;
360
361         str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
362         /* representation is same as cstring */
363         PG_RETURN_CSTRING(str);
364 }
365
366 /*
367  *              unknownsend                     - converts unknown to binary format
368  */
369 Datum
370 unknownsend(PG_FUNCTION_ARGS)
371 {
372         /* representation is same as cstring */
373         char       *str = PG_GETARG_CSTRING(0);
374         StringInfoData buf;
375
376         pq_begintypsend(&buf);
377         pq_sendtext(&buf, str, strlen(str));
378         PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
379 }
380
381
382 /* ========== PUBLIC ROUTINES ========== */
383
384 /*
385  * textlen -
386  *        returns the logical length of a text*
387  *         (which is less than the VARSIZE of the text*)
388  */
389 Datum
390 textlen(PG_FUNCTION_ARGS)
391 {
392         Datum           str = PG_GETARG_DATUM(0);
393
394         /* try to avoid decompressing argument */
395         PG_RETURN_INT32(text_length(str));
396 }
397
398 /*
399  * text_length -
400  *      Does the real work for textlen()
401  *
402  *      This is broken out so it can be called directly by other string processing
403  *      functions.      Note that the argument is passed as a Datum, to indicate that
404  *      it may still be in compressed form.  We can avoid decompressing it at all
405  *      in some cases.
406  */
407 static int32
408 text_length(Datum str)
409 {
410         /* fastpath when max encoding length is one */
411         if (pg_database_encoding_max_length() == 1)
412                 PG_RETURN_INT32(toast_raw_datum_size(str) - VARHDRSZ);
413         else
414         {
415                 text       *t = DatumGetTextP(str);
416
417                 PG_RETURN_INT32(pg_mbstrlen_with_len(VARDATA(t),
418                                                                                          VARSIZE(t) - VARHDRSZ));
419         }
420 }
421
422 /*
423  * textoctetlen -
424  *        returns the physical length of a text*
425  *         (which is less than the VARSIZE of the text*)
426  */
427 Datum
428 textoctetlen(PG_FUNCTION_ARGS)
429 {
430         Datum           str = PG_GETARG_DATUM(0);
431
432         /* We need not detoast the input at all */
433         PG_RETURN_INT32(toast_raw_datum_size(str) - VARHDRSZ);
434 }
435
436 /*
437  * textcat -
438  *        takes two text* and returns a text* that is the concatenation of
439  *        the two.
440  *
441  * Rewritten by Sapa, sapa@hq.icb.chel.su. 8-Jul-96.
442  * Updated by Thomas, Thomas.Lockhart@jpl.nasa.gov 1997-07-10.
443  * Allocate space for output in all cases.
444  * XXX - thomas 1997-07-10
445  */
446 Datum
447 textcat(PG_FUNCTION_ARGS)
448 {
449         text       *t1 = PG_GETARG_TEXT_P(0);
450         text       *t2 = PG_GETARG_TEXT_P(1);
451         int                     len1,
452                                 len2,
453                                 len;
454         text       *result;
455         char       *ptr;
456
457         len1 = VARSIZE(t1) - VARHDRSZ;
458         if (len1 < 0)
459                 len1 = 0;
460
461         len2 = VARSIZE(t2) - VARHDRSZ;
462         if (len2 < 0)
463                 len2 = 0;
464
465         len = len1 + len2 + VARHDRSZ;
466         result = (text *) palloc(len);
467
468         /* Set size of result string... */
469         VARATT_SIZEP(result) = len;
470
471         /* Fill data field of result string... */
472         ptr = VARDATA(result);
473         if (len1 > 0)
474                 memcpy(ptr, VARDATA(t1), len1);
475         if (len2 > 0)
476                 memcpy(ptr + len1, VARDATA(t2), len2);
477
478         PG_RETURN_TEXT_P(result);
479 }
480
481 /*
482  * text_substr()
483  * Return a substring starting at the specified position.
484  * - thomas 1997-12-31
485  *
486  * Input:
487  *      - string
488  *      - starting position (is one-based)
489  *      - string length
490  *
491  * If the starting position is zero or less, then return from the start of the string
492  *      adjusting the length to be consistent with the "negative start" per SQL92.
493  * If the length is less than zero, return the remaining string.
494  *
495  * Added multibyte support.
496  * - Tatsuo Ishii 1998-4-21
497  * Changed behavior if starting position is less than one to conform to SQL92 behavior.
498  * Formerly returned the entire string; now returns a portion.
499  * - Thomas Lockhart 1998-12-10
500  * Now uses faster TOAST-slicing interface
501  * - John Gray 2002-02-22
502  * Remove "#ifdef MULTIBYTE" and test for encoding_max_length instead. Change
503  * behaviors conflicting with SQL92 to meet SQL92 (if E = S + L < S throw
504  * error; if E < 1, return '', not entire string). Fixed MB related bug when
505  * S > LC and < LC + 4 sometimes garbage characters are returned.
506  * - Joe Conway 2002-08-10
507  */
508 Datum
509 text_substr(PG_FUNCTION_ARGS)
510 {
511         PG_RETURN_TEXT_P(text_substring(PG_GETARG_DATUM(0),
512                                                                         PG_GETARG_INT32(1),
513                                                                         PG_GETARG_INT32(2),
514                                                                         false));
515 }
516
517 /*
518  * text_substr_no_len -
519  *        Wrapper to avoid opr_sanity failure due to
520  *        one function accepting a different number of args.
521  */
522 Datum
523 text_substr_no_len(PG_FUNCTION_ARGS)
524 {
525         PG_RETURN_TEXT_P(text_substring(PG_GETARG_DATUM(0),
526                                                                         PG_GETARG_INT32(1),
527                                                                         -1, true));
528 }
529
530 /*
531  * text_substring -
532  *      Does the real work for text_substr() and text_substr_no_len()
533  *
534  *      This is broken out so it can be called directly by other string processing
535  *      functions.      Note that the argument is passed as a Datum, to indicate that
536  *      it may still be in compressed/toasted form.  We can avoid detoasting all
537  *      of it in some cases.
538  */
539 static text *
540 text_substring(Datum str, int32 start, int32 length, bool length_not_specified)
541 {
542         int32           eml = pg_database_encoding_max_length();
543         int32           S = start;              /* start position */
544         int32           S1;                             /* adjusted start position */
545         int32           L1;                             /* adjusted substring length */
546
547         /* life is easy if the encoding max length is 1 */
548         if (eml == 1)
549         {
550                 S1 = Max(S, 1);
551
552                 if (length_not_specified)               /* special case - get length to end of
553                                                                                  * string */
554                         L1 = -1;
555                 else
556                 {
557                         /* end position */
558                         int                     E = S + length;
559
560                         /*
561                          * A negative value for L is the only way for the end position to
562                          * be before the start. SQL99 says to throw an error.
563                          */
564                         if (E < S)
565                                 ereport(ERROR,
566                                                 (errcode(ERRCODE_SUBSTRING_ERROR),
567                                                  errmsg("negative substring length not allowed")));
568
569                         /*
570                          * A zero or negative value for the end position can happen if the
571                          * start was negative or one. SQL99 says to return a zero-length
572                          * string.
573                          */
574                         if (E < 1)
575                                 return PG_STR_GET_TEXT("");
576
577                         L1 = E - S1;
578                 }
579
580                 /*
581                  * If the start position is past the end of the string, SQL99 says to
582                  * return a zero-length string -- PG_GETARG_TEXT_P_SLICE() will do
583                  * that for us. Convert to zero-based starting position
584                  */
585                 return DatumGetTextPSlice(str, S1 - 1, L1);
586         }
587         else if (eml > 1)
588         {
589                 /*
590                  * When encoding max length is > 1, we can't get LC without
591                  * detoasting, so we'll grab a conservatively large slice now and go
592                  * back later to do the right thing
593                  */
594                 int32           slice_start;
595                 int32           slice_size;
596                 int32           slice_strlen;
597                 text       *slice;
598                 int32           E1;
599                 int32           i;
600                 char       *p;
601                 char       *s;
602                 text       *ret;
603
604                 /*
605                  * if S is past the end of the string, the tuple toaster will return a
606                  * zero-length string to us
607                  */
608                 S1 = Max(S, 1);
609
610                 /*
611                  * We need to start at position zero because there is no way to know
612                  * in advance which byte offset corresponds to the supplied start
613                  * position.
614                  */
615                 slice_start = 0;
616
617                 if (length_not_specified)               /* special case - get length to end of
618                                                                                  * string */
619                         slice_size = L1 = -1;
620                 else
621                 {
622                         int                     E = S + length;
623
624                         /*
625                          * A negative value for L is the only way for the end position to
626                          * be before the start. SQL99 says to throw an error.
627                          */
628                         if (E < S)
629                                 ereport(ERROR,
630                                                 (errcode(ERRCODE_SUBSTRING_ERROR),
631                                                  errmsg("negative substring length not allowed")));
632
633                         /*
634                          * A zero or negative value for the end position can happen if the
635                          * start was negative or one. SQL99 says to return a zero-length
636                          * string.
637                          */
638                         if (E < 1)
639                                 return PG_STR_GET_TEXT("");
640
641                         /*
642                          * if E is past the end of the string, the tuple toaster will
643                          * truncate the length for us
644                          */
645                         L1 = E - S1;
646
647                         /*
648                          * Total slice size in bytes can't be any longer than the start
649                          * position plus substring length times the encoding max length.
650                          */
651                         slice_size = (S1 + L1) * eml;
652                 }
653                 slice = DatumGetTextPSlice(str, slice_start, slice_size);
654
655                 /* see if we got back an empty string */
656                 if ((VARSIZE(slice) - VARHDRSZ) == 0)
657                         return PG_STR_GET_TEXT("");
658
659                 /* Now we can get the actual length of the slice in MB characters */
660                 slice_strlen = pg_mbstrlen_with_len(VARDATA(slice), VARSIZE(slice) - VARHDRSZ);
661
662                 /*
663                  * Check that the start position wasn't > slice_strlen. If so, SQL99
664                  * says to return a zero-length string.
665                  */
666                 if (S1 > slice_strlen)
667                         return PG_STR_GET_TEXT("");
668
669                 /*
670                  * Adjust L1 and E1 now that we know the slice string length. Again
671                  * remember that S1 is one based, and slice_start is zero based.
672                  */
673                 if (L1 > -1)
674                         E1 = Min(S1 + L1, slice_start + 1 + slice_strlen);
675                 else
676                         E1 = slice_start + 1 + slice_strlen;
677
678                 /*
679                  * Find the start position in the slice; remember S1 is not zero based
680                  */
681                 p = VARDATA(slice);
682                 for (i = 0; i < S1 - 1; i++)
683                         p += pg_mblen(p);
684
685                 /* hang onto a pointer to our start position */
686                 s = p;
687
688                 /*
689                  * Count the actual bytes used by the substring of the requested
690                  * length.
691                  */
692                 for (i = S1; i < E1; i++)
693                         p += pg_mblen(p);
694
695                 ret = (text *) palloc(VARHDRSZ + (p - s));
696                 VARATT_SIZEP(ret) = VARHDRSZ + (p - s);
697                 memcpy(VARDATA(ret), s, (p - s));
698
699                 return ret;
700         }
701         else
702                 elog(ERROR, "invalid backend encoding: encoding max length < 1");
703
704         /* not reached: suppress compiler warning */
705         return NULL;
706 }
707
708 /*
709  * textpos -
710  *        Return the position of the specified substring.
711  *        Implements the SQL92 POSITION() function.
712  *        Ref: A Guide To The SQL Standard, Date & Darwen, 1997
713  * - thomas 1997-07-27
714  */
715 Datum
716 textpos(PG_FUNCTION_ARGS)
717 {
718         text       *str = PG_GETARG_TEXT_P(0);
719         text       *search_str = PG_GETARG_TEXT_P(1);
720
721         PG_RETURN_INT32(text_position(str, search_str, 1));
722 }
723
724 /*
725  * text_position -
726  *      Does the real work for textpos()
727  *
728  * Inputs:
729  *              t1 - string to be searched
730  *              t2 - pattern to match within t1
731  *              matchnum - number of the match to be found (1 is the first match)
732  * Result:
733  *              Character index of the first matched char, starting from 1,
734  *              or 0 if no match.
735  *
736  *      This is broken out so it can be called directly by other string processing
737  *      functions.
738  */
739 static int32
740 text_position(text *t1, text *t2, int matchnum)
741 {
742         int                     match = 0,
743                                 pos = 0,
744                                 p,
745                                 px,
746                                 len1,
747                                 len2;
748
749         if (matchnum <= 0)
750                 return 0;                               /* result for 0th match */
751
752         if (VARSIZE(t2) <= VARHDRSZ)
753                 return 1;                               /* result for empty pattern */
754
755         len1 = VARSIZE(t1) - VARHDRSZ;
756         len2 = VARSIZE(t2) - VARHDRSZ;
757
758         if (pg_database_encoding_max_length() == 1)
759         {
760                 /* simple case - single byte encoding */
761                 char       *p1,
762                                    *p2;
763
764                 p1 = VARDATA(t1);
765                 p2 = VARDATA(t2);
766
767                 /* no use in searching str past point where search_str will fit */
768                 px = (len1 - len2);
769
770                 for (p = 0; p <= px; p++)
771                 {
772                         if ((*p1 == *p2) && (strncmp(p1, p2, len2) == 0))
773                         {
774                                 if (++match == matchnum)
775                                 {
776                                         pos = p + 1;
777                                         break;
778                                 }
779                         }
780                         p1++;
781                 }
782         }
783         else
784         {
785                 /* not as simple - multibyte encoding */
786                 pg_wchar   *p1,
787                                    *p2,
788                                    *ps1,
789                                    *ps2;
790
791                 ps1 = p1 = (pg_wchar *) palloc((len1 + 1) * sizeof(pg_wchar));
792                 (void) pg_mb2wchar_with_len(VARDATA(t1), p1, len1);
793                 len1 = pg_wchar_strlen(p1);
794                 ps2 = p2 = (pg_wchar *) palloc((len2 + 1) * sizeof(pg_wchar));
795                 (void) pg_mb2wchar_with_len(VARDATA(t2), p2, len2);
796                 len2 = pg_wchar_strlen(p2);
797
798                 /* no use in searching str past point where search_str will fit */
799                 px = (len1 - len2);
800
801                 for (p = 0; p <= px; p++)
802                 {
803                         if ((*p1 == *p2) && (pg_wchar_strncmp(p1, p2, len2) == 0))
804                         {
805                                 if (++match == matchnum)
806                                 {
807                                         pos = p + 1;
808                                         break;
809                                 }
810                         }
811                         p1++;
812                 }
813
814                 pfree(ps1);
815                 pfree(ps2);
816         }
817
818         return pos;
819 }
820
821 /* varstr_cmp()
822  * Comparison function for text strings with given lengths.
823  * Includes locale support, but must copy strings to temporary memory
824  *      to allow null-termination for inputs to strcoll().
825  * Returns -1, 0 or 1
826  */
827 int
828 varstr_cmp(char *arg1, int len1, char *arg2, int len2)
829 {
830         int                     result;
831
832         /*
833          * Unfortunately, there is no strncoll(), so in the non-C locale case we
834          * have to do some memory copying.      This turns out to be significantly
835          * slower, so we optimize the case where LC_COLLATE is C.  We also try to
836          * optimize relatively-short strings by avoiding palloc/pfree overhead.
837          */
838         if (lc_collate_is_c())
839         {
840                 result = strncmp(arg1, arg2, Min(len1, len2));
841                 if ((result == 0) && (len1 != len2))
842                         result = (len1 < len2) ? -1 : 1;
843         }
844         else
845         {
846 #define STACKBUFLEN             1024
847
848                 char            a1buf[STACKBUFLEN];
849                 char            a2buf[STACKBUFLEN];
850                 char       *a1p,
851                                    *a2p;
852
853 #ifdef WIN32
854                 /* Win32 does not have UTF-8, so we need to map to UTF-16 */
855                 if (GetDatabaseEncoding() == PG_UTF8)
856                 {
857                         int                     a1len;
858                         int                     a2len;
859                         int                     r;
860
861                         if (len1 >= STACKBUFLEN / 2)
862                         {
863                                 a1len = len1 * 2 + 2;
864                                 a1p = palloc(a1len);
865                         }
866                         else
867                         {
868                                 a1len = STACKBUFLEN;
869                                 a1p = a1buf;
870                         }
871                         if (len2 >= STACKBUFLEN / 2)
872                         {
873                                 a2len = len2 * 2 + 2;
874                                 a2p = palloc(a2len);
875                         }
876                         else
877                         {
878                                 a2len = STACKBUFLEN;
879                                 a2p = a2buf;
880                         }
881
882                         /* stupid Microsloth API does not work for zero-length input */
883                         if (len1 == 0)
884                                 r = 0;
885                         else
886                         {
887                                 r = MultiByteToWideChar(CP_UTF8, 0, arg1, len1,
888                                                                                 (LPWSTR) a1p, a1len / 2);
889                                 if (!r)
890                                         ereport(ERROR,
891                                                         (errmsg("could not convert string to UTF16: %lu",
892                                                                         GetLastError())));
893                         }
894                         ((LPWSTR) a1p)[r] = 0;
895
896                         if (len2 == 0)
897                                 r = 0;
898                         else
899                         {
900                                 r = MultiByteToWideChar(CP_UTF8, 0, arg2, len2,
901                                                                                 (LPWSTR) a2p, a2len / 2);
902                                 if (!r)
903                                         ereport(ERROR,
904                                                         (errmsg("could not convert string to UTF16: %lu",
905                                                                         GetLastError())));
906                         }
907                         ((LPWSTR) a2p)[r] = 0;
908
909                         errno = 0;
910                         result = wcscoll((LPWSTR) a1p, (LPWSTR) a2p);
911                         if (result == 2147483647)       /* _NLSCMPERROR; missing from mingw
912                                                                                  * headers */
913                                 ereport(ERROR,
914                                                 (errmsg("could not compare unicode strings: %d",
915                                                                 errno)));
916
917                         if (a1p != a1buf)
918                                 pfree(a1p);
919                         if (a2p != a2buf)
920                                 pfree(a2p);
921
922                         return result;
923                 }
924 #endif   /* WIN32 */
925
926                 if (len1 >= STACKBUFLEN)
927                         a1p = (char *) palloc(len1 + 1);
928                 else
929                         a1p = a1buf;
930                 if (len2 >= STACKBUFLEN)
931                         a2p = (char *) palloc(len2 + 1);
932                 else
933                         a2p = a2buf;
934
935                 memcpy(a1p, arg1, len1);
936                 a1p[len1] = '\0';
937                 memcpy(a2p, arg2, len2);
938                 a2p[len2] = '\0';
939
940                 result = strcoll(a1p, a2p);
941
942                 if (a1p != a1buf)
943                         pfree(a1p);
944                 if (a2p != a2buf)
945                         pfree(a2p);
946         }
947
948         return result;
949 }
950
951
952 /* text_cmp()
953  * Internal comparison function for text strings.
954  * Returns -1, 0 or 1
955  */
956 static int
957 text_cmp(text *arg1, text *arg2)
958 {
959         char       *a1p,
960                            *a2p;
961         int                     len1,
962                                 len2;
963
964         a1p = VARDATA(arg1);
965         a2p = VARDATA(arg2);
966
967         len1 = VARSIZE(arg1) - VARHDRSZ;
968         len2 = VARSIZE(arg2) - VARHDRSZ;
969
970         return varstr_cmp(a1p, len1, a2p, len2);
971 }
972
973 /*
974  * Comparison functions for text strings.
975  *
976  * Note: btree indexes need these routines not to leak memory; therefore,
977  * be careful to free working copies of toasted datums.  Most places don't
978  * need to be so careful.
979  */
980
981 Datum
982 texteq(PG_FUNCTION_ARGS)
983 {
984         text       *arg1 = PG_GETARG_TEXT_P(0);
985         text       *arg2 = PG_GETARG_TEXT_P(1);
986         bool            result;
987
988         /* fast path for different-length inputs */
989         if (VARSIZE(arg1) != VARSIZE(arg2))
990                 result = false;
991         else
992                 result = (text_cmp(arg1, arg2) == 0);
993
994         PG_FREE_IF_COPY(arg1, 0);
995         PG_FREE_IF_COPY(arg2, 1);
996
997         PG_RETURN_BOOL(result);
998 }
999
1000 Datum
1001 textne(PG_FUNCTION_ARGS)
1002 {
1003         text       *arg1 = PG_GETARG_TEXT_P(0);
1004         text       *arg2 = PG_GETARG_TEXT_P(1);
1005         bool            result;
1006
1007         /* fast path for different-length inputs */
1008         if (VARSIZE(arg1) != VARSIZE(arg2))
1009                 result = true;
1010         else
1011                 result = (text_cmp(arg1, arg2) != 0);
1012
1013         PG_FREE_IF_COPY(arg1, 0);
1014         PG_FREE_IF_COPY(arg2, 1);
1015
1016         PG_RETURN_BOOL(result);
1017 }
1018
1019 Datum
1020 text_lt(PG_FUNCTION_ARGS)
1021 {
1022         text       *arg1 = PG_GETARG_TEXT_P(0);
1023         text       *arg2 = PG_GETARG_TEXT_P(1);
1024         bool            result;
1025
1026         result = (text_cmp(arg1, arg2) < 0);
1027
1028         PG_FREE_IF_COPY(arg1, 0);
1029         PG_FREE_IF_COPY(arg2, 1);
1030
1031         PG_RETURN_BOOL(result);
1032 }
1033
1034 Datum
1035 text_le(PG_FUNCTION_ARGS)
1036 {
1037         text       *arg1 = PG_GETARG_TEXT_P(0);
1038         text       *arg2 = PG_GETARG_TEXT_P(1);
1039         bool            result;
1040
1041         result = (text_cmp(arg1, arg2) <= 0);
1042
1043         PG_FREE_IF_COPY(arg1, 0);
1044         PG_FREE_IF_COPY(arg2, 1);
1045
1046         PG_RETURN_BOOL(result);
1047 }
1048
1049 Datum
1050 text_gt(PG_FUNCTION_ARGS)
1051 {
1052         text       *arg1 = PG_GETARG_TEXT_P(0);
1053         text       *arg2 = PG_GETARG_TEXT_P(1);
1054         bool            result;
1055
1056         result = (text_cmp(arg1, arg2) > 0);
1057
1058         PG_FREE_IF_COPY(arg1, 0);
1059         PG_FREE_IF_COPY(arg2, 1);
1060
1061         PG_RETURN_BOOL(result);
1062 }
1063
1064 Datum
1065 text_ge(PG_FUNCTION_ARGS)
1066 {
1067         text       *arg1 = PG_GETARG_TEXT_P(0);
1068         text       *arg2 = PG_GETARG_TEXT_P(1);
1069         bool            result;
1070
1071         result = (text_cmp(arg1, arg2) >= 0);
1072
1073         PG_FREE_IF_COPY(arg1, 0);
1074         PG_FREE_IF_COPY(arg2, 1);
1075
1076         PG_RETURN_BOOL(result);
1077 }
1078
1079 Datum
1080 bttextcmp(PG_FUNCTION_ARGS)
1081 {
1082         text       *arg1 = PG_GETARG_TEXT_P(0);
1083         text       *arg2 = PG_GETARG_TEXT_P(1);
1084         int32           result;
1085
1086         result = text_cmp(arg1, arg2);
1087
1088         PG_FREE_IF_COPY(arg1, 0);
1089         PG_FREE_IF_COPY(arg2, 1);
1090
1091         PG_RETURN_INT32(result);
1092 }
1093
1094
1095 Datum
1096 text_larger(PG_FUNCTION_ARGS)
1097 {
1098         text       *arg1 = PG_GETARG_TEXT_P(0);
1099         text       *arg2 = PG_GETARG_TEXT_P(1);
1100         text       *result;
1101
1102         result = ((text_cmp(arg1, arg2) > 0) ? arg1 : arg2);
1103
1104         PG_RETURN_TEXT_P(result);
1105 }
1106
1107 Datum
1108 text_smaller(PG_FUNCTION_ARGS)
1109 {
1110         text       *arg1 = PG_GETARG_TEXT_P(0);
1111         text       *arg2 = PG_GETARG_TEXT_P(1);
1112         text       *result;
1113
1114         result = ((text_cmp(arg1, arg2) < 0) ? arg1 : arg2);
1115
1116         PG_RETURN_TEXT_P(result);
1117 }
1118
1119
1120 /*
1121  * The following operators support character-by-character comparison
1122  * of text data types, to allow building indexes suitable for LIKE
1123  * clauses.
1124  */
1125
1126 static int
1127 internal_text_pattern_compare(text *arg1, text *arg2)
1128 {
1129         int                     result;
1130
1131         result = memcmp(VARDATA(arg1), VARDATA(arg2),
1132                                         Min(VARSIZE(arg1), VARSIZE(arg2)) - VARHDRSZ);
1133         if (result != 0)
1134                 return result;
1135         else if (VARSIZE(arg1) < VARSIZE(arg2))
1136                 return -1;
1137         else if (VARSIZE(arg1) > VARSIZE(arg2))
1138                 return 1;
1139         else
1140                 return 0;
1141 }
1142
1143
1144 Datum
1145 text_pattern_lt(PG_FUNCTION_ARGS)
1146 {
1147         text       *arg1 = PG_GETARG_TEXT_P(0);
1148         text       *arg2 = PG_GETARG_TEXT_P(1);
1149         int                     result;
1150
1151         result = internal_text_pattern_compare(arg1, arg2);
1152
1153         PG_FREE_IF_COPY(arg1, 0);
1154         PG_FREE_IF_COPY(arg2, 1);
1155
1156         PG_RETURN_BOOL(result < 0);
1157 }
1158
1159
1160 Datum
1161 text_pattern_le(PG_FUNCTION_ARGS)
1162 {
1163         text       *arg1 = PG_GETARG_TEXT_P(0);
1164         text       *arg2 = PG_GETARG_TEXT_P(1);
1165         int                     result;
1166
1167         result = internal_text_pattern_compare(arg1, arg2);
1168
1169         PG_FREE_IF_COPY(arg1, 0);
1170         PG_FREE_IF_COPY(arg2, 1);
1171
1172         PG_RETURN_BOOL(result <= 0);
1173 }
1174
1175
1176 Datum
1177 text_pattern_eq(PG_FUNCTION_ARGS)
1178 {
1179         text       *arg1 = PG_GETARG_TEXT_P(0);
1180         text       *arg2 = PG_GETARG_TEXT_P(1);
1181         int                     result;
1182
1183         if (VARSIZE(arg1) != VARSIZE(arg2))
1184                 result = 1;
1185         else
1186                 result = internal_text_pattern_compare(arg1, arg2);
1187
1188         PG_FREE_IF_COPY(arg1, 0);
1189         PG_FREE_IF_COPY(arg2, 1);
1190
1191         PG_RETURN_BOOL(result == 0);
1192 }
1193
1194
1195 Datum
1196 text_pattern_ge(PG_FUNCTION_ARGS)
1197 {
1198         text       *arg1 = PG_GETARG_TEXT_P(0);
1199         text       *arg2 = PG_GETARG_TEXT_P(1);
1200         int                     result;
1201
1202         result = internal_text_pattern_compare(arg1, arg2);
1203
1204         PG_FREE_IF_COPY(arg1, 0);
1205         PG_FREE_IF_COPY(arg2, 1);
1206
1207         PG_RETURN_BOOL(result >= 0);
1208 }
1209
1210
1211 Datum
1212 text_pattern_gt(PG_FUNCTION_ARGS)
1213 {
1214         text       *arg1 = PG_GETARG_TEXT_P(0);
1215         text       *arg2 = PG_GETARG_TEXT_P(1);
1216         int                     result;
1217
1218         result = internal_text_pattern_compare(arg1, arg2);
1219
1220         PG_FREE_IF_COPY(arg1, 0);
1221         PG_FREE_IF_COPY(arg2, 1);
1222
1223         PG_RETURN_BOOL(result > 0);
1224 }
1225
1226
1227 Datum
1228 text_pattern_ne(PG_FUNCTION_ARGS)
1229 {
1230         text       *arg1 = PG_GETARG_TEXT_P(0);
1231         text       *arg2 = PG_GETARG_TEXT_P(1);
1232         int                     result;
1233
1234         if (VARSIZE(arg1) != VARSIZE(arg2))
1235                 result = 1;
1236         else
1237                 result = internal_text_pattern_compare(arg1, arg2);
1238
1239         PG_FREE_IF_COPY(arg1, 0);
1240         PG_FREE_IF_COPY(arg2, 1);
1241
1242         PG_RETURN_BOOL(result != 0);
1243 }
1244
1245
1246 Datum
1247 bttext_pattern_cmp(PG_FUNCTION_ARGS)
1248 {
1249         text       *arg1 = PG_GETARG_TEXT_P(0);
1250         text       *arg2 = PG_GETARG_TEXT_P(1);
1251         int                     result;
1252
1253         result = internal_text_pattern_compare(arg1, arg2);
1254
1255         PG_FREE_IF_COPY(arg1, 0);
1256         PG_FREE_IF_COPY(arg2, 1);
1257
1258         PG_RETURN_INT32(result);
1259 }
1260
1261
1262 /*-------------------------------------------------------------
1263  * byteaoctetlen
1264  *
1265  * get the number of bytes contained in an instance of type 'bytea'
1266  *-------------------------------------------------------------
1267  */
1268 Datum
1269 byteaoctetlen(PG_FUNCTION_ARGS)
1270 {
1271         Datum           str = PG_GETARG_DATUM(0);
1272
1273         /* We need not detoast the input at all */
1274         PG_RETURN_INT32(toast_raw_datum_size(str) - VARHDRSZ);
1275 }
1276
1277 /*
1278  * byteacat -
1279  *        takes two bytea* and returns a bytea* that is the concatenation of
1280  *        the two.
1281  *
1282  * Cloned from textcat and modified as required.
1283  */
1284 Datum
1285 byteacat(PG_FUNCTION_ARGS)
1286 {
1287         bytea      *t1 = PG_GETARG_BYTEA_P(0);
1288         bytea      *t2 = PG_GETARG_BYTEA_P(1);
1289         int                     len1,
1290                                 len2,
1291                                 len;
1292         bytea      *result;
1293         char       *ptr;
1294
1295         len1 = VARSIZE(t1) - VARHDRSZ;
1296         if (len1 < 0)
1297                 len1 = 0;
1298
1299         len2 = VARSIZE(t2) - VARHDRSZ;
1300         if (len2 < 0)
1301                 len2 = 0;
1302
1303         len = len1 + len2 + VARHDRSZ;
1304         result = (bytea *) palloc(len);
1305
1306         /* Set size of result string... */
1307         VARATT_SIZEP(result) = len;
1308
1309         /* Fill data field of result string... */
1310         ptr = VARDATA(result);
1311         if (len1 > 0)
1312                 memcpy(ptr, VARDATA(t1), len1);
1313         if (len2 > 0)
1314                 memcpy(ptr + len1, VARDATA(t2), len2);
1315
1316         PG_RETURN_BYTEA_P(result);
1317 }
1318
1319 #define PG_STR_GET_BYTEA(str_) \
1320         DatumGetByteaP(DirectFunctionCall1(byteain, CStringGetDatum(str_)))
1321 /*
1322  * bytea_substr()
1323  * Return a substring starting at the specified position.
1324  * Cloned from text_substr and modified as required.
1325  *
1326  * Input:
1327  *      - string
1328  *      - starting position (is one-based)
1329  *      - string length (optional)
1330  *
1331  * If the starting position is zero or less, then return from the start of the string
1332  * adjusting the length to be consistent with the "negative start" per SQL92.
1333  * If the length is less than zero, an ERROR is thrown. If no third argument
1334  * (length) is provided, the length to the end of the string is assumed.
1335  */
1336 Datum
1337 bytea_substr(PG_FUNCTION_ARGS)
1338 {
1339         int                     S = PG_GETARG_INT32(1); /* start position */
1340         int                     S1;                             /* adjusted start position */
1341         int                     L1;                             /* adjusted substring length */
1342
1343         S1 = Max(S, 1);
1344
1345         if (fcinfo->nargs == 2)
1346         {
1347                 /*
1348                  * Not passed a length - PG_GETARG_BYTEA_P_SLICE() grabs everything to
1349                  * the end of the string if we pass it a negative value for length.
1350                  */
1351                 L1 = -1;
1352         }
1353         else
1354         {
1355                 /* end position */
1356                 int                     E = S + PG_GETARG_INT32(2);
1357
1358                 /*
1359                  * A negative value for L is the only way for the end position to be
1360                  * before the start. SQL99 says to throw an error.
1361                  */
1362                 if (E < S)
1363                         ereport(ERROR,
1364                                         (errcode(ERRCODE_SUBSTRING_ERROR),
1365                                          errmsg("negative substring length not allowed")));
1366
1367                 /*
1368                  * A zero or negative value for the end position can happen if the
1369                  * start was negative or one. SQL99 says to return a zero-length
1370                  * string.
1371                  */
1372                 if (E < 1)
1373                         PG_RETURN_BYTEA_P(PG_STR_GET_BYTEA(""));
1374
1375                 L1 = E - S1;
1376         }
1377
1378         /*
1379          * If the start position is past the end of the string, SQL99 says to
1380          * return a zero-length string -- PG_GETARG_TEXT_P_SLICE() will do that
1381          * for us. Convert to zero-based starting position
1382          */
1383         PG_RETURN_BYTEA_P(PG_GETARG_BYTEA_P_SLICE(0, S1 - 1, L1));
1384 }
1385
1386 /*
1387  * bytea_substr_no_len -
1388  *        Wrapper to avoid opr_sanity failure due to
1389  *        one function accepting a different number of args.
1390  */
1391 Datum
1392 bytea_substr_no_len(PG_FUNCTION_ARGS)
1393 {
1394         return bytea_substr(fcinfo);
1395 }
1396
1397 /*
1398  * byteapos -
1399  *        Return the position of the specified substring.
1400  *        Implements the SQL92 POSITION() function.
1401  * Cloned from textpos and modified as required.
1402  */
1403 Datum
1404 byteapos(PG_FUNCTION_ARGS)
1405 {
1406         bytea      *t1 = PG_GETARG_BYTEA_P(0);
1407         bytea      *t2 = PG_GETARG_BYTEA_P(1);
1408         int                     pos;
1409         int                     px,
1410                                 p;
1411         int                     len1,
1412                                 len2;
1413         char       *p1,
1414                            *p2;
1415
1416         if (VARSIZE(t2) <= VARHDRSZ)
1417                 PG_RETURN_INT32(1);             /* result for empty pattern */
1418
1419         len1 = VARSIZE(t1) - VARHDRSZ;
1420         len2 = VARSIZE(t2) - VARHDRSZ;
1421
1422         p1 = VARDATA(t1);
1423         p2 = VARDATA(t2);
1424
1425         pos = 0;
1426         px = (len1 - len2);
1427         for (p = 0; p <= px; p++)
1428         {
1429                 if ((*p2 == *p1) && (memcmp(p1, p2, len2) == 0))
1430                 {
1431                         pos = p + 1;
1432                         break;
1433                 };
1434                 p1++;
1435         };
1436
1437         PG_RETURN_INT32(pos);
1438 }
1439
1440 /*-------------------------------------------------------------
1441  * byteaGetByte
1442  *
1443  * this routine treats "bytea" as an array of bytes.
1444  * It returns the Nth byte (a number between 0 and 255).
1445  *-------------------------------------------------------------
1446  */
1447 Datum
1448 byteaGetByte(PG_FUNCTION_ARGS)
1449 {
1450         bytea      *v = PG_GETARG_BYTEA_P(0);
1451         int32           n = PG_GETARG_INT32(1);
1452         int                     len;
1453         int                     byte;
1454
1455         len = VARSIZE(v) - VARHDRSZ;
1456
1457         if (n < 0 || n >= len)
1458                 ereport(ERROR,
1459                                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1460                                  errmsg("index %d out of valid range, 0..%d",
1461                                                 n, len - 1)));
1462
1463         byte = ((unsigned char *) VARDATA(v))[n];
1464
1465         PG_RETURN_INT32(byte);
1466 }
1467
1468 /*-------------------------------------------------------------
1469  * byteaGetBit
1470  *
1471  * This routine treats a "bytea" type like an array of bits.
1472  * It returns the value of the Nth bit (0 or 1).
1473  *
1474  *-------------------------------------------------------------
1475  */
1476 Datum
1477 byteaGetBit(PG_FUNCTION_ARGS)
1478 {
1479         bytea      *v = PG_GETARG_BYTEA_P(0);
1480         int32           n = PG_GETARG_INT32(1);
1481         int                     byteNo,
1482                                 bitNo;
1483         int                     len;
1484         int                     byte;
1485
1486         len = VARSIZE(v) - VARHDRSZ;
1487
1488         if (n < 0 || n >= len * 8)
1489                 ereport(ERROR,
1490                                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1491                                  errmsg("index %d out of valid range, 0..%d",
1492                                                 n, len * 8 - 1)));
1493
1494         byteNo = n / 8;
1495         bitNo = n % 8;
1496
1497         byte = ((unsigned char *) VARDATA(v))[byteNo];
1498
1499         if (byte & (1 << bitNo))
1500                 PG_RETURN_INT32(1);
1501         else
1502                 PG_RETURN_INT32(0);
1503 }
1504
1505 /*-------------------------------------------------------------
1506  * byteaSetByte
1507  *
1508  * Given an instance of type 'bytea' creates a new one with
1509  * the Nth byte set to the given value.
1510  *
1511  *-------------------------------------------------------------
1512  */
1513 Datum
1514 byteaSetByte(PG_FUNCTION_ARGS)
1515 {
1516         bytea      *v = PG_GETARG_BYTEA_P(0);
1517         int32           n = PG_GETARG_INT32(1);
1518         int32           newByte = PG_GETARG_INT32(2);
1519         int                     len;
1520         bytea      *res;
1521
1522         len = VARSIZE(v) - VARHDRSZ;
1523
1524         if (n < 0 || n >= len)
1525                 ereport(ERROR,
1526                                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1527                                  errmsg("index %d out of valid range, 0..%d",
1528                                                 n, len - 1)));
1529
1530         /*
1531          * Make a copy of the original varlena.
1532          */
1533         res = (bytea *) palloc(VARSIZE(v));
1534         memcpy((char *) res, (char *) v, VARSIZE(v));
1535
1536         /*
1537          * Now set the byte.
1538          */
1539         ((unsigned char *) VARDATA(res))[n] = newByte;
1540
1541         PG_RETURN_BYTEA_P(res);
1542 }
1543
1544 /*-------------------------------------------------------------
1545  * byteaSetBit
1546  *
1547  * Given an instance of type 'bytea' creates a new one with
1548  * the Nth bit set to the given value.
1549  *
1550  *-------------------------------------------------------------
1551  */
1552 Datum
1553 byteaSetBit(PG_FUNCTION_ARGS)
1554 {
1555         bytea      *v = PG_GETARG_BYTEA_P(0);
1556         int32           n = PG_GETARG_INT32(1);
1557         int32           newBit = PG_GETARG_INT32(2);
1558         bytea      *res;
1559         int                     len;
1560         int                     oldByte,
1561                                 newByte;
1562         int                     byteNo,
1563                                 bitNo;
1564
1565         len = VARSIZE(v) - VARHDRSZ;
1566
1567         if (n < 0 || n >= len * 8)
1568                 ereport(ERROR,
1569                                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1570                                  errmsg("index %d out of valid range, 0..%d",
1571                                                 n, len * 8 - 1)));
1572
1573         byteNo = n / 8;
1574         bitNo = n % 8;
1575
1576         /*
1577          * sanity check!
1578          */
1579         if (newBit != 0 && newBit != 1)
1580                 ereport(ERROR,
1581                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1582                                  errmsg("new bit must be 0 or 1")));
1583
1584         /*
1585          * Make a copy of the original varlena.
1586          */
1587         res = (bytea *) palloc(VARSIZE(v));
1588         memcpy((char *) res, (char *) v, VARSIZE(v));
1589
1590         /*
1591          * Update the byte.
1592          */
1593         oldByte = ((unsigned char *) VARDATA(res))[byteNo];
1594
1595         if (newBit == 0)
1596                 newByte = oldByte & (~(1 << bitNo));
1597         else
1598                 newByte = oldByte | (1 << bitNo);
1599
1600         ((unsigned char *) VARDATA(res))[byteNo] = newByte;
1601
1602         PG_RETURN_BYTEA_P(res);
1603 }
1604
1605
1606 /* text_name()
1607  * Converts a text type to a Name type.
1608  */
1609 Datum
1610 text_name(PG_FUNCTION_ARGS)
1611 {
1612         text       *s = PG_GETARG_TEXT_P(0);
1613         Name            result;
1614         int                     len;
1615
1616         len = VARSIZE(s) - VARHDRSZ;
1617
1618         /* Truncate oversize input */
1619         if (len >= NAMEDATALEN)
1620                 len = NAMEDATALEN - 1;
1621
1622 #ifdef STRINGDEBUG
1623         printf("text- convert string length %d (%d) ->%d\n",
1624                    VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);
1625 #endif
1626
1627         result = (Name) palloc(NAMEDATALEN);
1628         memcpy(NameStr(*result), VARDATA(s), len);
1629
1630         /* now null pad to full length... */
1631         while (len < NAMEDATALEN)
1632         {
1633                 *(NameStr(*result) + len) = '\0';
1634                 len++;
1635         }
1636
1637         PG_RETURN_NAME(result);
1638 }
1639
1640 /* name_text()
1641  * Converts a Name type to a text type.
1642  */
1643 Datum
1644 name_text(PG_FUNCTION_ARGS)
1645 {
1646         Name            s = PG_GETARG_NAME(0);
1647         text       *result;
1648         int                     len;
1649
1650         len = strlen(NameStr(*s));
1651
1652 #ifdef STRINGDEBUG
1653         printf("text- convert string length %d (%d) ->%d\n",
1654                    VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);
1655 #endif
1656
1657         result = palloc(VARHDRSZ + len);
1658         VARATT_SIZEP(result) = VARHDRSZ + len;
1659         memcpy(VARDATA(result), NameStr(*s), len);
1660
1661         PG_RETURN_TEXT_P(result);
1662 }
1663
1664
1665 /*
1666  * textToQualifiedNameList - convert a text object to list of names
1667  *
1668  * This implements the input parsing needed by nextval() and other
1669  * functions that take a text parameter representing a qualified name.
1670  * We split the name at dots, downcase if not double-quoted, and
1671  * truncate names if they're too long.
1672  */
1673 List *
1674 textToQualifiedNameList(text *textval)
1675 {
1676         char       *rawname;
1677         List       *result = NIL;
1678         List       *namelist;
1679         ListCell   *l;
1680
1681         /* Convert to C string (handles possible detoasting). */
1682         /* Note we rely on being able to modify rawname below. */
1683         rawname = DatumGetCString(DirectFunctionCall1(textout,
1684                                                                                                   PointerGetDatum(textval)));
1685
1686         if (!SplitIdentifierString(rawname, '.', &namelist))
1687                 ereport(ERROR,
1688                                 (errcode(ERRCODE_INVALID_NAME),
1689                                  errmsg("invalid name syntax")));
1690
1691         if (namelist == NIL)
1692                 ereport(ERROR,
1693                                 (errcode(ERRCODE_INVALID_NAME),
1694                                  errmsg("invalid name syntax")));
1695
1696         foreach(l, namelist)
1697         {
1698                 char       *curname = (char *) lfirst(l);
1699
1700                 result = lappend(result, makeString(pstrdup(curname)));
1701         }
1702
1703         pfree(rawname);
1704         list_free(namelist);
1705
1706         return result;
1707 }
1708
1709 /*
1710  * SplitIdentifierString --- parse a string containing identifiers
1711  *
1712  * This is the guts of textToQualifiedNameList, and is exported for use in
1713  * other situations such as parsing GUC variables.      In the GUC case, it's
1714  * important to avoid memory leaks, so the API is designed to minimize the
1715  * amount of stuff that needs to be allocated and freed.
1716  *
1717  * Inputs:
1718  *      rawstring: the input string; must be overwritable!      On return, it's
1719  *                         been modified to contain the separated identifiers.
1720  *      separator: the separator punctuation expected between identifiers
1721  *                         (typically '.' or ',').      Whitespace may also appear around
1722  *                         identifiers.
1723  * Outputs:
1724  *      namelist: filled with a palloc'd list of pointers to identifiers within
1725  *                        rawstring.  Caller should list_free() this even on error return.
1726  *
1727  * Returns TRUE if okay, FALSE if there is a syntax error in the string.
1728  *
1729  * Note that an empty string is considered okay here, though not in
1730  * textToQualifiedNameList.
1731  */
1732 bool
1733 SplitIdentifierString(char *rawstring, char separator,
1734                                           List **namelist)
1735 {
1736         char       *nextp = rawstring;
1737         bool            done = false;
1738
1739         *namelist = NIL;
1740
1741         while (isspace((unsigned char) *nextp))
1742                 nextp++;                                /* skip leading whitespace */
1743
1744         if (*nextp == '\0')
1745                 return true;                    /* allow empty string */
1746
1747         /* At the top of the loop, we are at start of a new identifier. */
1748         do
1749         {
1750                 char       *curname;
1751                 char       *endp;
1752
1753                 if (*nextp == '\"')
1754                 {
1755                         /* Quoted name --- collapse quote-quote pairs, no downcasing */
1756                         curname = nextp + 1;
1757                         for (;;)
1758                         {
1759                                 endp = strchr(nextp + 1, '\"');
1760                                 if (endp == NULL)
1761                                         return false;           /* mismatched quotes */
1762                                 if (endp[1] != '\"')
1763                                         break;          /* found end of quoted name */
1764                                 /* Collapse adjacent quotes into one quote, and look again */
1765                                 memmove(endp, endp + 1, strlen(endp));
1766                                 nextp = endp;
1767                         }
1768                         /* endp now points at the terminating quote */
1769                         nextp = endp + 1;
1770                 }
1771                 else
1772                 {
1773                         /* Unquoted name --- extends to separator or whitespace */
1774                         char       *downname;
1775                         int                     len;
1776
1777                         curname = nextp;
1778                         while (*nextp && *nextp != separator &&
1779                                    !isspace((unsigned char) *nextp))
1780                                 nextp++;
1781                         endp = nextp;
1782                         if (curname == nextp)
1783                                 return false;   /* empty unquoted name not allowed */
1784
1785                         /*
1786                          * Downcase the identifier, using same code as main lexer does.
1787                          *
1788                          * XXX because we want to overwrite the input in-place, we cannot
1789                          * support a downcasing transformation that increases the string
1790                          * length.      This is not a problem given the current implementation
1791                          * of downcase_truncate_identifier, but we'll probably have to do
1792                          * something about this someday.
1793                          */
1794                         len = endp - curname;
1795                         downname = downcase_truncate_identifier(curname, len, false);
1796                         Assert(strlen(downname) <= len);
1797                         strncpy(curname, downname, len);
1798                         pfree(downname);
1799                 }
1800
1801                 while (isspace((unsigned char) *nextp))
1802                         nextp++;                        /* skip trailing whitespace */
1803
1804                 if (*nextp == separator)
1805                 {
1806                         nextp++;
1807                         while (isspace((unsigned char) *nextp))
1808                                 nextp++;                /* skip leading whitespace for next */
1809                         /* we expect another name, so done remains false */
1810                 }
1811                 else if (*nextp == '\0')
1812                         done = true;
1813                 else
1814                         return false;           /* invalid syntax */
1815
1816                 /* Now safe to overwrite separator with a null */
1817                 *endp = '\0';
1818
1819                 /* Truncate name if it's overlength */
1820                 truncate_identifier(curname, strlen(curname), false);
1821
1822                 /*
1823                  * Finished isolating current name --- add it to list
1824                  */
1825                 *namelist = lappend(*namelist, curname);
1826
1827                 /* Loop back if we didn't reach end of string */
1828         } while (!done);
1829
1830         return true;
1831 }
1832
1833
1834 /*****************************************************************************
1835  *      Comparison Functions used for bytea
1836  *
1837  * Note: btree indexes need these routines not to leak memory; therefore,
1838  * be careful to free working copies of toasted datums.  Most places don't
1839  * need to be so careful.
1840  *****************************************************************************/
1841
1842 Datum
1843 byteaeq(PG_FUNCTION_ARGS)
1844 {
1845         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1846         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1847         int                     len1,
1848                                 len2;
1849         bool            result;
1850
1851         len1 = VARSIZE(arg1) - VARHDRSZ;
1852         len2 = VARSIZE(arg2) - VARHDRSZ;
1853
1854         /* fast path for different-length inputs */
1855         if (len1 != len2)
1856                 result = false;
1857         else
1858                 result = (memcmp(VARDATA(arg1), VARDATA(arg2), len1) == 0);
1859
1860         PG_FREE_IF_COPY(arg1, 0);
1861         PG_FREE_IF_COPY(arg2, 1);
1862
1863         PG_RETURN_BOOL(result);
1864 }
1865
1866 Datum
1867 byteane(PG_FUNCTION_ARGS)
1868 {
1869         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1870         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1871         int                     len1,
1872                                 len2;
1873         bool            result;
1874
1875         len1 = VARSIZE(arg1) - VARHDRSZ;
1876         len2 = VARSIZE(arg2) - VARHDRSZ;
1877
1878         /* fast path for different-length inputs */
1879         if (len1 != len2)
1880                 result = true;
1881         else
1882                 result = (memcmp(VARDATA(arg1), VARDATA(arg2), len1) != 0);
1883
1884         PG_FREE_IF_COPY(arg1, 0);
1885         PG_FREE_IF_COPY(arg2, 1);
1886
1887         PG_RETURN_BOOL(result);
1888 }
1889
1890 Datum
1891 bytealt(PG_FUNCTION_ARGS)
1892 {
1893         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1894         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1895         int                     len1,
1896                                 len2;
1897         int                     cmp;
1898
1899         len1 = VARSIZE(arg1) - VARHDRSZ;
1900         len2 = VARSIZE(arg2) - VARHDRSZ;
1901
1902         cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1903
1904         PG_FREE_IF_COPY(arg1, 0);
1905         PG_FREE_IF_COPY(arg2, 1);
1906
1907         PG_RETURN_BOOL((cmp < 0) || ((cmp == 0) && (len1 < len2)));
1908 }
1909
1910 Datum
1911 byteale(PG_FUNCTION_ARGS)
1912 {
1913         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1914         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1915         int                     len1,
1916                                 len2;
1917         int                     cmp;
1918
1919         len1 = VARSIZE(arg1) - VARHDRSZ;
1920         len2 = VARSIZE(arg2) - VARHDRSZ;
1921
1922         cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1923
1924         PG_FREE_IF_COPY(arg1, 0);
1925         PG_FREE_IF_COPY(arg2, 1);
1926
1927         PG_RETURN_BOOL((cmp < 0) || ((cmp == 0) && (len1 <= len2)));
1928 }
1929
1930 Datum
1931 byteagt(PG_FUNCTION_ARGS)
1932 {
1933         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1934         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1935         int                     len1,
1936                                 len2;
1937         int                     cmp;
1938
1939         len1 = VARSIZE(arg1) - VARHDRSZ;
1940         len2 = VARSIZE(arg2) - VARHDRSZ;
1941
1942         cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1943
1944         PG_FREE_IF_COPY(arg1, 0);
1945         PG_FREE_IF_COPY(arg2, 1);
1946
1947         PG_RETURN_BOOL((cmp > 0) || ((cmp == 0) && (len1 > len2)));
1948 }
1949
1950 Datum
1951 byteage(PG_FUNCTION_ARGS)
1952 {
1953         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1954         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1955         int                     len1,
1956                                 len2;
1957         int                     cmp;
1958
1959         len1 = VARSIZE(arg1) - VARHDRSZ;
1960         len2 = VARSIZE(arg2) - VARHDRSZ;
1961
1962         cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1963
1964         PG_FREE_IF_COPY(arg1, 0);
1965         PG_FREE_IF_COPY(arg2, 1);
1966
1967         PG_RETURN_BOOL((cmp > 0) || ((cmp == 0) && (len1 >= len2)));
1968 }
1969
1970 Datum
1971 byteacmp(PG_FUNCTION_ARGS)
1972 {
1973         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1974         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1975         int                     len1,
1976                                 len2;
1977         int                     cmp;
1978
1979         len1 = VARSIZE(arg1) - VARHDRSZ;
1980         len2 = VARSIZE(arg2) - VARHDRSZ;
1981
1982         cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1983         if ((cmp == 0) && (len1 != len2))
1984                 cmp = (len1 < len2) ? -1 : 1;
1985
1986         PG_FREE_IF_COPY(arg1, 0);
1987         PG_FREE_IF_COPY(arg2, 1);
1988
1989         PG_RETURN_INT32(cmp);
1990 }
1991
1992 /*
1993  * appendStringInfoText
1994  *
1995  * Append a text to str.
1996  * Like appendStringInfoString(str, PG_TEXT_GET_STR(s)) but faster.
1997  */
1998 static void
1999 appendStringInfoText(StringInfo str, const text *t)
2000 {
2001         appendBinaryStringInfo(str, VARDATA(t), VARSIZE(t) - VARHDRSZ);
2002 }
2003
2004 /*
2005  * replace_text
2006  * replace all occurrences of 'old_sub_str' in 'orig_str'
2007  * with 'new_sub_str' to form 'new_str'
2008  *
2009  * returns 'orig_str' if 'old_sub_str' == '' or 'orig_str' == ''
2010  * otherwise returns 'new_str'
2011  */
2012 Datum
2013 replace_text(PG_FUNCTION_ARGS)
2014 {
2015         text       *src_text = PG_GETARG_TEXT_P(0);
2016         text       *from_sub_text = PG_GETARG_TEXT_P(1);
2017         text       *to_sub_text = PG_GETARG_TEXT_P(2);
2018         int                     src_text_len = TEXTLEN(src_text);
2019         int                     from_sub_text_len = TEXTLEN(from_sub_text);
2020         text       *left_text;
2021         text       *right_text;
2022         text       *buf_text;
2023         text       *ret_text;
2024         int                     curr_posn;
2025         StringInfo      str;
2026
2027         if (src_text_len == 0 || from_sub_text_len == 0)
2028                 PG_RETURN_TEXT_P(src_text);
2029
2030         curr_posn = TEXTPOS(src_text, from_sub_text);
2031
2032         /* When the from_sub_text is not found, there is nothing to do. */
2033         if (curr_posn == 0)
2034                 PG_RETURN_TEXT_P(src_text);
2035
2036         str = makeStringInfo();
2037         buf_text = src_text;
2038
2039         while (curr_posn > 0)
2040         {
2041                 left_text = text_substring(PointerGetDatum(buf_text),
2042                                                                    1, curr_posn - 1, false);
2043                 right_text = text_substring(PointerGetDatum(buf_text),
2044                                                                         curr_posn + from_sub_text_len, -1, true);
2045
2046                 appendStringInfoText(str, left_text);
2047                 appendStringInfoText(str, to_sub_text);
2048
2049                 if (buf_text != src_text)
2050                         pfree(buf_text);
2051                 pfree(left_text);
2052                 buf_text = right_text;
2053                 curr_posn = TEXTPOS(buf_text, from_sub_text);
2054         }
2055
2056         appendStringInfoText(str, buf_text);
2057         if (buf_text != src_text)
2058                 pfree(buf_text);
2059
2060         ret_text = PG_STR_GET_TEXT(str->data);
2061         pfree(str->data);
2062         pfree(str);
2063
2064         PG_RETURN_TEXT_P(ret_text);
2065 }
2066
2067 /*
2068  * check_replace_text_has_escape_char
2069  *
2070  * check whether replace_text contains escape char.
2071  */
2072 static bool
2073 check_replace_text_has_escape_char(const text *replace_text)
2074 {
2075         const char *p = VARDATA(replace_text);
2076         const char *p_end = p + (VARSIZE(replace_text) - VARHDRSZ);
2077
2078         if (pg_database_encoding_max_length() == 1)
2079         {
2080                 for (; p < p_end; p++)
2081                 {
2082                         if (*p == '\\')
2083                                 return true;
2084                 }
2085         }
2086         else
2087         {
2088                 for (; p < p_end; p += pg_mblen(p))
2089                 {
2090                         if (*p == '\\')
2091                                 return true;
2092                 }
2093         }
2094
2095         return false;
2096 }
2097
2098 /*
2099  * appendStringInfoRegexpSubstr
2100  *
2101  * Append replace_text to str, substituting regexp back references for
2102  * \n escapes.
2103  */
2104 static void
2105 appendStringInfoRegexpSubstr(StringInfo str, text *replace_text,
2106                                                          regmatch_t *pmatch, text *src_text)
2107 {
2108         const char *p = VARDATA(replace_text);
2109         const char *p_end = p + (VARSIZE(replace_text) - VARHDRSZ);
2110         int                     eml = pg_database_encoding_max_length();
2111
2112         for (;;)
2113         {
2114                 const char *chunk_start = p;
2115                 int                     so;
2116                 int                     eo;
2117
2118                 /* Find next escape char. */
2119                 if (eml == 1)
2120                 {
2121                         for (; p < p_end && *p != '\\'; p++)
2122                                 /* nothing */ ;
2123                 }
2124                 else
2125                 {
2126                         for (; p < p_end && *p != '\\'; p += pg_mblen(p))
2127                                 /* nothing */ ;
2128                 }
2129
2130                 /* Copy the text we just scanned over, if any. */
2131                 if (p > chunk_start)
2132                         appendBinaryStringInfo(str, chunk_start, p - chunk_start);
2133
2134                 /* Done if at end of string, else advance over escape char. */
2135                 if (p >= p_end)
2136                         break;
2137                 p++;
2138
2139                 if (p >= p_end)
2140                 {
2141                         /* Escape at very end of input.  Treat same as unexpected char */
2142                         appendStringInfoChar(str, '\\');
2143                         break;
2144                 }
2145
2146                 if (*p >= '1' && *p <= '9')
2147                 {
2148                         /* Use the back reference of regexp. */
2149                         int                     idx = *p - '0';
2150
2151                         so = pmatch[idx].rm_so;
2152                         eo = pmatch[idx].rm_eo;
2153                         p++;
2154                 }
2155                 else if (*p == '&')
2156                 {
2157                         /* Use the entire matched string. */
2158                         so = pmatch[0].rm_so;
2159                         eo = pmatch[0].rm_eo;
2160                         p++;
2161                 }
2162                 else if (*p == '\\')
2163                 {
2164                         /* \\ means transfer one \ to output. */
2165                         appendStringInfoChar(str, '\\');
2166                         p++;
2167                         continue;
2168                 }
2169                 else
2170                 {
2171                         /*
2172                          * If escape char is not followed by any expected char,
2173                          * just treat it as ordinary data to copy.  (XXX would it be
2174                          * better to throw an error?)
2175                          */
2176                         appendStringInfoChar(str, '\\');
2177                         continue;
2178                 }
2179
2180                 if (so != -1 && eo != -1)
2181                 {
2182                         /*
2183                          * Copy the text that is back reference of regexp.  Because so and
2184                          * eo are counted in characters not bytes, it's easiest to use
2185                          * text_substring to pull out the correct chunk of text.
2186                          */
2187                         text       *append_text;
2188
2189                         append_text = text_substring(PointerGetDatum(src_text),
2190                                                                                  so + 1, (eo - so), false);
2191                         appendStringInfoText(str, append_text);
2192                         pfree(append_text);
2193                 }
2194         }
2195 }
2196
2197 #define REGEXP_REPLACE_BACKREF_CNT              10
2198
2199 /*
2200  * replace_text_regexp
2201  *
2202  * replace text that matches to regexp in src_text to replace_text.
2203  *
2204  * Note: to avoid having to include regex.h in builtins.h, we declare
2205  * the regexp argument as void *, but really it's regex_t *.
2206  */
2207 text *
2208 replace_text_regexp(text *src_text, void *regexp,
2209                                         text *replace_text, bool glob)
2210 {
2211         text       *ret_text;
2212         regex_t    *re = (regex_t *) regexp;
2213         int                     src_text_len = VARSIZE(src_text) - VARHDRSZ;
2214         StringInfo      str = makeStringInfo();
2215         int                     regexec_result;
2216         regmatch_t      pmatch[REGEXP_REPLACE_BACKREF_CNT];
2217         pg_wchar   *data;
2218         size_t          data_len;
2219         int                     search_start;
2220         int                     data_pos;
2221         bool            have_escape;
2222
2223         /* Convert data string to wide characters. */
2224         data = (pg_wchar *) palloc((src_text_len + 1) * sizeof(pg_wchar));
2225         data_len = pg_mb2wchar_with_len(VARDATA(src_text), data, src_text_len);
2226
2227         /* Check whether replace_text has escape char. */
2228         have_escape = check_replace_text_has_escape_char(replace_text);
2229
2230         for (search_start = data_pos = 0; search_start <= data_len;)
2231         {
2232                 regexec_result = pg_regexec(re,
2233                                                                         data,
2234                                                                         data_len,
2235                                                                         search_start,
2236                                                                         NULL,           /* no details */
2237                                                                         REGEXP_REPLACE_BACKREF_CNT,
2238                                                                         pmatch,
2239                                                                         0);
2240
2241                 if (regexec_result != REG_OKAY && regexec_result != REG_NOMATCH)
2242                 {
2243                         char            errMsg[100];
2244
2245                         /* re failed??? */
2246                         pg_regerror(regexec_result, re, errMsg, sizeof(errMsg));
2247                         ereport(ERROR,
2248                                         (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
2249                                          errmsg("regular expression failed: %s", errMsg)));
2250                 }
2251
2252                 if (regexec_result == REG_NOMATCH)
2253                         break;
2254
2255                 /*
2256                  * Copy the text to the left of the match position.  Because we
2257                  * are working with character not byte indexes, it's easiest to
2258                  * use text_substring to pull out the needed data.
2259                  */
2260                 if (pmatch[0].rm_so - data_pos > 0)
2261                 {
2262                         text       *left_text;
2263
2264                         left_text = text_substring(PointerGetDatum(src_text),
2265                                                                            data_pos + 1,
2266                                                                            pmatch[0].rm_so - data_pos,
2267                                                                            false);
2268                         appendStringInfoText(str, left_text);
2269                         pfree(left_text);
2270                 }
2271
2272                 /*
2273                  * Copy the replace_text. Process back references when the
2274                  * replace_text has escape characters.
2275                  */
2276                 if (have_escape)
2277                         appendStringInfoRegexpSubstr(str, replace_text, pmatch, src_text);
2278                 else
2279                         appendStringInfoText(str, replace_text);
2280
2281                 search_start = data_pos = pmatch[0].rm_eo;
2282
2283                 /*
2284                  * When global option is off, replace the first instance only.
2285                  */
2286                 if (!glob)
2287                         break;
2288
2289                 /*
2290                  * Search from next character when the matching text is zero width.
2291                  */
2292                 if (pmatch[0].rm_so == pmatch[0].rm_eo)
2293                         search_start++;
2294         }
2295
2296         /*
2297          * Copy the text to the right of the last match.
2298          */
2299         if (data_pos < data_len)
2300         {
2301                 text       *right_text;
2302
2303                 right_text = text_substring(PointerGetDatum(src_text),
2304                                                                         data_pos + 1, -1, true);
2305                 appendStringInfoText(str, right_text);
2306                 pfree(right_text);
2307         }
2308
2309         ret_text = PG_STR_GET_TEXT(str->data);
2310         pfree(str->data);
2311         pfree(str);
2312         pfree(data);
2313
2314         return ret_text;
2315 }
2316
2317 /*
2318  * split_text
2319  * parse input string
2320  * return ord item (1 based)
2321  * based on provided field separator
2322  */
2323 Datum
2324 split_text(PG_FUNCTION_ARGS)
2325 {
2326         text       *inputstring = PG_GETARG_TEXT_P(0);
2327         text       *fldsep = PG_GETARG_TEXT_P(1);
2328         int                     fldnum = PG_GETARG_INT32(2);
2329         int                     inputstring_len = TEXTLEN(inputstring);
2330         int                     fldsep_len = TEXTLEN(fldsep);
2331         int                     start_posn;
2332         int                     end_posn;
2333         text       *result_text;
2334
2335         /* field number is 1 based */
2336         if (fldnum < 1)
2337                 ereport(ERROR,
2338                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2339                                  errmsg("field position must be greater than zero")));
2340
2341         /* return empty string for empty input string */
2342         if (inputstring_len < 1)
2343                 PG_RETURN_TEXT_P(PG_STR_GET_TEXT(""));
2344
2345         /* empty field separator */
2346         if (fldsep_len < 1)
2347         {
2348                 /* if first field, return input string, else empty string */
2349                 if (fldnum == 1)
2350                         PG_RETURN_TEXT_P(inputstring);
2351                 else
2352                         PG_RETURN_TEXT_P(PG_STR_GET_TEXT(""));
2353         }
2354
2355         start_posn = text_position(inputstring, fldsep, fldnum - 1);
2356         end_posn = text_position(inputstring, fldsep, fldnum);
2357
2358         if ((start_posn == 0) && (end_posn == 0))       /* fldsep not found */
2359         {
2360                 /* if first field, return input string, else empty string */
2361                 if (fldnum == 1)
2362                         PG_RETURN_TEXT_P(inputstring);
2363                 else
2364                         PG_RETURN_TEXT_P(PG_STR_GET_TEXT(""));
2365         }
2366         else if (start_posn == 0)
2367         {
2368                 /* first field requested */
2369                 result_text = LEFT(inputstring, fldsep);
2370                 PG_RETURN_TEXT_P(result_text);
2371         }
2372         else if (end_posn == 0)
2373         {
2374                 /* last field requested */
2375                 result_text = text_substring(PointerGetDatum(inputstring),
2376                                                                          start_posn + fldsep_len,
2377                                                                          -1, true);
2378                 PG_RETURN_TEXT_P(result_text);
2379         }
2380         else
2381         {
2382                 /* interior field requested */
2383                 result_text = text_substring(PointerGetDatum(inputstring),
2384                                                                          start_posn + fldsep_len,
2385                                                                          end_posn - start_posn - fldsep_len,
2386                                                                          false);
2387                 PG_RETURN_TEXT_P(result_text);
2388         }
2389 }
2390
2391 /*
2392  * text_to_array
2393  * parse input string
2394  * return text array of elements
2395  * based on provided field separator
2396  */
2397 Datum
2398 text_to_array(PG_FUNCTION_ARGS)
2399 {
2400         text       *inputstring = PG_GETARG_TEXT_P(0);
2401         text       *fldsep = PG_GETARG_TEXT_P(1);
2402         int                     inputstring_len = TEXTLEN(inputstring);
2403         int                     fldsep_len = TEXTLEN(fldsep);
2404         int                     fldnum;
2405         int                     start_posn;
2406         int                     end_posn;
2407         text       *result_text;
2408         ArrayBuildState *astate = NULL;
2409
2410         /* return NULL for empty input string */
2411         if (inputstring_len < 1)
2412                 PG_RETURN_NULL();
2413
2414         /*
2415          * empty field separator return one element, 1D, array using the input
2416          * string
2417          */
2418         if (fldsep_len < 1)
2419                 PG_RETURN_ARRAYTYPE_P(create_singleton_array(fcinfo, TEXTOID,
2420                                                                                    CStringGetDatum(inputstring), 1));
2421
2422         /* start with end position holding the initial start position */
2423         end_posn = 0;
2424         for (fldnum = 1;; fldnum++) /* field number is 1 based */
2425         {
2426                 Datum           dvalue;
2427                 bool            disnull = false;
2428
2429                 start_posn = end_posn;
2430                 end_posn = text_position(inputstring, fldsep, fldnum);
2431
2432                 if ((start_posn == 0) && (end_posn == 0))               /* fldsep not found */
2433                 {
2434                         if (fldnum == 1)
2435                         {
2436                                 /*
2437                                  * first element return one element, 1D, array using the input
2438                                  * string
2439                                  */
2440                                 PG_RETURN_ARRAYTYPE_P(create_singleton_array(fcinfo, TEXTOID,
2441                                                                                    CStringGetDatum(inputstring), 1));
2442                         }
2443                         else
2444                         {
2445                                 /* otherwise create array and exit */
2446                                 PG_RETURN_ARRAYTYPE_P(makeArrayResult(astate,
2447                                                                                                           CurrentMemoryContext));
2448                         }
2449                 }
2450                 else if (start_posn == 0)
2451                 {
2452                         /* first field requested */
2453                         result_text = LEFT(inputstring, fldsep);
2454                 }
2455                 else if (end_posn == 0)
2456                 {
2457                         /* last field requested */
2458                         result_text = text_substring(PointerGetDatum(inputstring),
2459                                                                                  start_posn + fldsep_len,
2460                                                                                  -1, true);
2461                 }
2462                 else
2463                 {
2464                         /* interior field requested */
2465                         result_text = text_substring(PointerGetDatum(inputstring),
2466                                                                                  start_posn + fldsep_len,
2467                                                                                  end_posn - start_posn - fldsep_len,
2468                                                                                  false);
2469                 }
2470
2471                 /* stash away current value */
2472                 dvalue = PointerGetDatum(result_text);
2473                 astate = accumArrayResult(astate, dvalue,
2474                                                                   disnull, TEXTOID,
2475                                                                   CurrentMemoryContext);
2476         }
2477
2478         /* never reached -- keep compiler quiet */
2479         PG_RETURN_NULL();
2480 }
2481
2482 /*
2483  * array_to_text
2484  * concatenate Cstring representation of input array elements
2485  * using provided field separator
2486  */
2487 Datum
2488 array_to_text(PG_FUNCTION_ARGS)
2489 {
2490         ArrayType  *v = PG_GETARG_ARRAYTYPE_P(0);
2491         char       *fldsep = PG_TEXTARG_GET_STR(1);
2492         int                     nitems,
2493                            *dims,
2494                                 ndims;
2495         char       *p;
2496         Oid                     element_type;
2497         int                     typlen;
2498         bool            typbyval;
2499         char            typalign;
2500         StringInfo      result_str = makeStringInfo();
2501         int                     i;
2502         ArrayMetaState *my_extra;
2503
2504         p = ARR_DATA_PTR(v);
2505         ndims = ARR_NDIM(v);
2506         dims = ARR_DIMS(v);
2507         nitems = ArrayGetNItems(ndims, dims);
2508
2509         /* if there are no elements, return an empty string */
2510         if (nitems == 0)
2511                 PG_RETURN_TEXT_P(PG_STR_GET_TEXT(""));
2512
2513         element_type = ARR_ELEMTYPE(v);
2514
2515         /*
2516          * We arrange to look up info about element type, including its output
2517          * conversion proc, only once per series of calls, assuming the element
2518          * type doesn't change underneath us.
2519          */
2520         my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
2521         if (my_extra == NULL)
2522         {
2523                 fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
2524                                                                                                           sizeof(ArrayMetaState));
2525                 my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
2526                 my_extra->element_type = InvalidOid;
2527         }
2528
2529         if (my_extra->element_type != element_type)
2530         {
2531                 /*
2532                  * Get info about element type, including its output conversion proc
2533                  */
2534                 get_type_io_data(element_type, IOFunc_output,
2535                                                  &my_extra->typlen, &my_extra->typbyval,
2536                                                  &my_extra->typalign, &my_extra->typdelim,
2537                                                  &my_extra->typioparam, &my_extra->typiofunc);
2538                 fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
2539                                           fcinfo->flinfo->fn_mcxt);
2540                 my_extra->element_type = element_type;
2541         }
2542         typlen = my_extra->typlen;
2543         typbyval = my_extra->typbyval;
2544         typalign = my_extra->typalign;
2545
2546         for (i = 0; i < nitems; i++)
2547         {
2548                 Datum           itemvalue;
2549                 char       *value;
2550
2551                 itemvalue = fetch_att(p, typbyval, typlen);
2552
2553                 value = DatumGetCString(FunctionCall1(&my_extra->proc,
2554                                                                                           itemvalue));
2555
2556                 if (i > 0)
2557                         appendStringInfo(result_str, "%s%s", fldsep, value);
2558                 else
2559                         appendStringInfoString(result_str, value);
2560
2561                 p = att_addlength(p, typlen, PointerGetDatum(p));
2562                 p = (char *) att_align(p, typalign);
2563         }
2564
2565         PG_RETURN_TEXT_P(PG_STR_GET_TEXT(result_str->data));
2566 }
2567
2568 #define HEXBASE 16
2569 /*
2570  * Convert a int32 to a string containing a base 16 (hex) representation of
2571  * the number.
2572  */
2573 Datum
2574 to_hex32(PG_FUNCTION_ARGS)
2575 {
2576         uint32          value = (uint32) PG_GETARG_INT32(0);
2577         text       *result_text;
2578         char       *ptr;
2579         const char *digits = "0123456789abcdef";
2580         char            buf[32];                /* bigger than needed, but reasonable */
2581
2582         ptr = buf + sizeof(buf) - 1;
2583         *ptr = '\0';
2584
2585         do
2586         {
2587                 *--ptr = digits[value % HEXBASE];
2588                 value /= HEXBASE;
2589         } while (ptr > buf && value);
2590
2591         result_text = PG_STR_GET_TEXT(ptr);
2592         PG_RETURN_TEXT_P(result_text);
2593 }
2594
2595 /*
2596  * Convert a int64 to a string containing a base 16 (hex) representation of
2597  * the number.
2598  */
2599 Datum
2600 to_hex64(PG_FUNCTION_ARGS)
2601 {
2602         uint64          value = (uint64) PG_GETARG_INT64(0);
2603         text       *result_text;
2604         char       *ptr;
2605         const char *digits = "0123456789abcdef";
2606         char            buf[32];                /* bigger than needed, but reasonable */
2607
2608         ptr = buf + sizeof(buf) - 1;
2609         *ptr = '\0';
2610
2611         do
2612         {
2613                 *--ptr = digits[value % HEXBASE];
2614                 value /= HEXBASE;
2615         } while (ptr > buf && value);
2616
2617         result_text = PG_STR_GET_TEXT(ptr);
2618         PG_RETURN_TEXT_P(result_text);
2619 }
2620
2621 /*
2622  * Create an md5 hash of a text string and return it as hex
2623  *
2624  * md5 produces a 16 byte (128 bit) hash; double it for hex
2625  */
2626 #define MD5_HASH_LEN  32
2627
2628 Datum
2629 md5_text(PG_FUNCTION_ARGS)
2630 {
2631         text       *in_text = PG_GETARG_TEXT_P(0);
2632         size_t          len;
2633         char            hexsum[MD5_HASH_LEN + 1];
2634         text       *result_text;
2635
2636         /* Calculate the length of the buffer using varlena metadata */
2637         len = VARSIZE(in_text) - VARHDRSZ;
2638
2639         /* get the hash result */
2640         if (pg_md5_hash(VARDATA(in_text), len, hexsum) == false)
2641                 ereport(ERROR,
2642                                 (errcode(ERRCODE_OUT_OF_MEMORY),
2643                                  errmsg("out of memory")));
2644
2645         /* convert to text and return it */
2646         result_text = PG_STR_GET_TEXT(hexsum);
2647         PG_RETURN_TEXT_P(result_text);
2648 }
2649
2650 /*
2651  * Create an md5 hash of a bytea field and return it as a hex string:
2652  * 16-byte md5 digest is represented in 32 hex characters.
2653  */
2654 Datum
2655 md5_bytea(PG_FUNCTION_ARGS)
2656 {
2657         bytea      *in = PG_GETARG_BYTEA_P(0);
2658         size_t          len;
2659         char            hexsum[MD5_HASH_LEN + 1];
2660         text       *result_text;
2661
2662         len = VARSIZE(in) - VARHDRSZ;
2663         if (pg_md5_hash(VARDATA(in), len, hexsum) == false)
2664                 ereport(ERROR,
2665                                 (errcode(ERRCODE_OUT_OF_MEMORY),
2666                                  errmsg("out of memory")));
2667
2668         result_text = PG_STR_GET_TEXT(hexsum);
2669         PG_RETURN_TEXT_P(result_text);
2670 }
2671
2672 /*
2673  * Return the size of a datum, possibly compressed
2674  *
2675  * Works on any data type
2676  */
2677 Datum
2678 pg_column_size(PG_FUNCTION_ARGS)
2679 {
2680         Datum           value = PG_GETARG_DATUM(0);
2681         int32           result;
2682         int                     typlen;
2683
2684         /* On first call, get the input type's typlen, and save at *fn_extra */
2685         if (fcinfo->flinfo->fn_extra == NULL)
2686         {
2687                 /* Lookup the datatype of the supplied argument */
2688                 Oid                     argtypeid = get_fn_expr_argtype(fcinfo->flinfo, 0);
2689
2690                 typlen = get_typlen(argtypeid);
2691                 if (typlen == 0)                /* should not happen */
2692                         elog(ERROR, "cache lookup failed for type %u", argtypeid);
2693
2694                 fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
2695                                                                                                           sizeof(int));
2696                 *((int *) fcinfo->flinfo->fn_extra) = typlen;
2697         }
2698         else
2699                 typlen = *((int *) fcinfo->flinfo->fn_extra);
2700
2701         if (typlen == -1)
2702         {
2703                 /* varlena type, possibly toasted */
2704                 result = toast_datum_size(value);
2705         }
2706         else if (typlen == -2)
2707         {
2708                 /* cstring */
2709                 result = strlen(DatumGetCString(value)) + 1;
2710         }
2711         else
2712         {
2713                 /* ordinary fixed-width type */
2714                 result = typlen;
2715         }
2716
2717         PG_RETURN_INT32(result);
2718 }