]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/varlena.c
Fix arg coerect match text type, per Tom.
[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-2001, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.78 2001/11/19 19:15:07 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include <ctype.h>
18
19 #include "mb/pg_wchar.h"
20 #include "miscadmin.h"
21 #include "utils/builtins.h"
22
23 static int      text_cmp(text *arg1, text *arg2);
24
25
26 /*****************************************************************************
27  *       USER I/O ROUTINES                                                                                                               *
28  *****************************************************************************/
29
30
31 #define VAL(CH)                 ((CH) - '0')
32 #define DIG(VAL)                ((VAL) + '0')
33
34 /*
35  *              byteain                 - converts from printable representation of byte array
36  *
37  *              Non-printable characters must be passed as '\nnn' (octal) and are
38  *              converted to internal form.  '\' must be passed as '\\'.
39  *              elog(ERROR, ...) if bad form.
40  *
41  *              BUGS:
42  *                              The input is scaned twice.
43  *                              The error checking of input is minimal.
44  */
45 Datum
46 byteain(PG_FUNCTION_ARGS)
47 {
48         char       *inputText = PG_GETARG_CSTRING(0);
49         char       *tp;
50         char       *rp;
51         int                     byte;
52         bytea      *result;
53
54         for (byte = 0, tp = inputText; *tp != '\0'; byte++)
55         {
56                 if (tp[0] != '\\')
57                         tp++;
58                 else if ((tp[0] == '\\') &&
59                                  (tp[1] >= '0' && tp[1] <= '3') &&
60                                  (tp[2] >= '0' && tp[2] <= '7') &&
61                                  (tp[3] >= '0' && tp[3] <= '7'))
62                         tp += 4;
63                 else if ((tp[0] == '\\') &&
64                                  (tp[1] == '\\'))
65                         tp += 2;
66                 else
67                 {
68                         /*
69                          * one backslash, not followed by 0 or ### valid octal
70                          */
71                         elog(ERROR, "Bad input string for type bytea");
72                 }
73         }
74
75         byte += VARHDRSZ;
76         result = (bytea *) palloc(byte);
77         result->vl_len = byte;          /* set varlena length */
78
79         tp = inputText;
80         rp = result->vl_dat;
81         while (*tp != '\0')
82         {
83                 if (tp[0] != '\\')
84                         *rp++ = *tp++;
85                 else if ((tp[0] == '\\') &&
86                                  (tp[1] >= '0' && tp[1] <= '3') &&
87                                  (tp[2] >= '0' && tp[2] <= '7') &&
88                                  (tp[3] >= '0' && tp[3] <= '7'))
89                 {
90                         byte = VAL(tp[1]);
91                         byte <<= 3;
92                         byte += VAL(tp[2]);
93                         byte <<= 3;
94                         *rp++ = byte + VAL(tp[3]);
95                         tp += 4;
96                 }
97                 else if ((tp[0] == '\\') &&
98                                  (tp[1] == '\\'))
99                 {
100                         *rp++ = '\\';
101                         tp += 2;
102                 }
103                 else
104                 {
105                         /*
106                          * We should never get here. The first pass should not allow
107                          * it.
108                          */
109                         elog(ERROR, "Bad input string for type bytea");
110                 }
111         }
112
113         PG_RETURN_BYTEA_P(result);
114 }
115
116 /*
117  *              byteaout                - converts to printable representation of byte array
118  *
119  *              Non-printable characters are inserted as '\nnn' (octal) and '\' as
120  *              '\\'.
121  *
122  *              NULL vlena should be an error--returning string with NULL for now.
123  */
124 Datum
125 byteaout(PG_FUNCTION_ARGS)
126 {
127         bytea      *vlena = PG_GETARG_BYTEA_P(0);
128         char       *result;
129         char       *vp;
130         char       *rp;
131         int                     val;                    /* holds unprintable chars */
132         int                     i;
133         int                     len;
134
135         len = 1;                                        /* empty string has 1 char */
136         vp = vlena->vl_dat;
137         for (i = vlena->vl_len - VARHDRSZ; i != 0; i--, vp++)
138         {
139                 if (*vp == '\\')
140                         len += 2;
141                 else if (isprint((unsigned char) *vp))
142                         len++;
143                 else
144                         len += 4;
145         }
146         rp = result = (char *) palloc(len);
147         vp = vlena->vl_dat;
148         for (i = vlena->vl_len - VARHDRSZ; i != 0; i--, vp++)
149         {
150                 if (*vp == '\\')
151                 {
152                         *rp++ = '\\';
153                         *rp++ = '\\';
154                 }
155                 else if (isprint((unsigned char) *vp))
156                         *rp++ = *vp;
157                 else
158                 {
159                         val = *vp;
160                         rp[0] = '\\';
161                         rp[3] = DIG(val & 07);
162                         val >>= 3;
163                         rp[2] = DIG(val & 07);
164                         val >>= 3;
165                         rp[1] = DIG(val & 03);
166                         rp += 4;
167                 }
168         }
169         *rp = '\0';
170         PG_RETURN_CSTRING(result);
171 }
172
173
174 /*
175  *              textin                  - converts "..." to internal representation
176  */
177 Datum
178 textin(PG_FUNCTION_ARGS)
179 {
180         char       *inputText = PG_GETARG_CSTRING(0);
181         text       *result;
182         int                     len;
183
184 #ifdef MULTIBYTE
185         char       *ermsg;
186 #endif
187
188         len = strlen(inputText) + VARHDRSZ;
189
190 #ifdef MULTIBYTE
191         if ((ermsg = pg_verifymbstr(inputText, len - VARHDRSZ)))
192                 elog(ERROR, "%s", ermsg);
193 #endif
194
195         result = (text *) palloc(len);
196         VARATT_SIZEP(result) = len;
197
198         memcpy(VARDATA(result), inputText, len - VARHDRSZ);
199
200 #ifdef CYR_RECODE
201         convertstr(VARDATA(result), len - VARHDRSZ, 0);
202 #endif
203
204         PG_RETURN_TEXT_P(result);
205 }
206
207 /*
208  *              textout                 - converts internal representation to "..."
209  */
210 Datum
211 textout(PG_FUNCTION_ARGS)
212 {
213         text       *t = PG_GETARG_TEXT_P(0);
214         int                     len;
215         char       *result;
216
217         len = VARSIZE(t) - VARHDRSZ;
218         result = (char *) palloc(len + 1);
219         memcpy(result, VARDATA(t), len);
220         result[len] = '\0';
221
222 #ifdef CYR_RECODE
223         convertstr(result, len, 1);
224 #endif
225
226         PG_RETURN_CSTRING(result);
227 }
228
229
230 /* ========== PUBLIC ROUTINES ========== */
231
232 /*
233  * textlen -
234  *        returns the logical length of a text*
235  *         (which is less than the VARSIZE of the text*)
236  */
237 Datum
238 textlen(PG_FUNCTION_ARGS)
239 {
240         text       *t = PG_GETARG_TEXT_P(0);
241
242 #ifdef MULTIBYTE
243         /* optimization for single byte encoding */
244         if (pg_database_encoding_max_length() <= 1)
245                 PG_RETURN_INT32(VARSIZE(t) - VARHDRSZ);
246
247         PG_RETURN_INT32(
248                 pg_mbstrlen_with_len(VARDATA(t), VARSIZE(t) - VARHDRSZ)
249                 );
250 #else
251         PG_RETURN_INT32(VARSIZE(t) - VARHDRSZ);
252 #endif
253 }
254
255 /*
256  * textoctetlen -
257  *        returns the physical length of a text*
258  *         (which is less than the VARSIZE of the text*)
259  */
260 Datum
261 textoctetlen(PG_FUNCTION_ARGS)
262 {
263         text    *arg = PG_GETARG_TEXT_P(0);
264
265         PG_RETURN_INT32(VARSIZE(arg) - VARHDRSZ);
266 }
267
268 /*
269  * textcat -
270  *        takes two text* and returns a text* that is the concatenation of
271  *        the two.
272  *
273  * Rewritten by Sapa, sapa@hq.icb.chel.su. 8-Jul-96.
274  * Updated by Thomas, Thomas.Lockhart@jpl.nasa.gov 1997-07-10.
275  * Allocate space for output in all cases.
276  * XXX - thomas 1997-07-10
277  */
278 Datum
279 textcat(PG_FUNCTION_ARGS)
280 {
281         text       *t1 = PG_GETARG_TEXT_P(0);
282         text       *t2 = PG_GETARG_TEXT_P(1);
283         int                     len1,
284                                 len2,
285                                 len;
286         text       *result;
287         char       *ptr;
288
289         len1 = (VARSIZE(t1) - VARHDRSZ);
290         if (len1 < 0)
291                 len1 = 0;
292
293         len2 = (VARSIZE(t2) - VARHDRSZ);
294         if (len2 < 0)
295                 len2 = 0;
296
297         len = len1 + len2 + VARHDRSZ;
298         result = (text *) palloc(len);
299
300         /* Set size of result string... */
301         VARATT_SIZEP(result) = len;
302
303         /* Fill data field of result string... */
304         ptr = VARDATA(result);
305         if (len1 > 0)
306                 memcpy(ptr, VARDATA(t1), len1);
307         if (len2 > 0)
308                 memcpy(ptr + len1, VARDATA(t2), len2);
309
310         PG_RETURN_TEXT_P(result);
311 }
312
313 /*
314  * text_substr()
315  * Return a substring starting at the specified position.
316  * - thomas 1997-12-31
317  *
318  * Input:
319  *      - string
320  *      - starting position (is one-based)
321  *      - string length
322  *
323  * If the starting position is zero or less, then return from the start of the string
324  *      adjusting the length to be consistent with the "negative start" per SQL92.
325  * If the length is less than zero, return the remaining string.
326  *
327  * Note that the arguments operate on octet length,
328  *      so not aware of multi-byte character sets.
329  *
330  * Added multi-byte support.
331  * - Tatsuo Ishii 1998-4-21
332  * Changed behavior if starting position is less than one to conform to SQL92 behavior.
333  * Formerly returned the entire string; now returns a portion.
334  * - Thomas Lockhart 1998-12-10
335  */
336 Datum
337 text_substr(PG_FUNCTION_ARGS)
338 {
339         text       *string = PG_GETARG_TEXT_P(0);
340         int32           m = PG_GETARG_INT32(1);
341         int32           n = PG_GETARG_INT32(2);
342         text       *ret;
343         int                     len;
344
345 #ifdef MULTIBYTE
346         int                     i;
347         char       *p;
348 #endif
349
350         len = VARSIZE(string) - VARHDRSZ;
351 #ifdef MULTIBYTE
352         len = pg_mbstrlen_with_len(VARDATA(string), len);
353 #endif
354
355         /* starting position after the end of the string? */
356         if (m > len)
357         {
358                 m = 1;
359                 n = 0;
360         }
361
362         /*
363          * starting position before the start of the string? then offset into
364          * the string per SQL92 spec...
365          */
366         else if (m < 1)
367         {
368                 n += (m - 1);
369                 m = 1;
370         }
371
372         /* m will now become a zero-based starting position */
373         m--;
374         if (((m + n) > len) || (n < 0))
375                 n = (len - m);
376
377 #ifdef MULTIBYTE
378         p = VARDATA(string);
379         for (i = 0; i < m; i++)
380                 p += pg_mblen(p);
381         m = p - VARDATA(string);
382         for (i = 0; i < n; i++)
383                 p += pg_mblen(p);
384         n = p - (VARDATA(string) + m);
385 #endif
386
387         ret = (text *) palloc(VARHDRSZ + n);
388         VARATT_SIZEP(ret) = VARHDRSZ + n;
389
390         memcpy(VARDATA(ret), VARDATA(string) + m, n);
391
392         PG_RETURN_TEXT_P(ret);
393 }
394
395 /*
396  * textpos -
397  *        Return the position of the specified substring.
398  *        Implements the SQL92 POSITION() function.
399  *        Ref: A Guide To The SQL Standard, Date & Darwen, 1997
400  * - thomas 1997-07-27
401  *
402  * Added multi-byte support.
403  * - Tatsuo Ishii 1998-4-21
404  */
405 Datum
406 textpos(PG_FUNCTION_ARGS)
407 {
408         text       *t1 = PG_GETARG_TEXT_P(0);
409         text       *t2 = PG_GETARG_TEXT_P(1);
410         int                     pos;
411         int                     px,
412                                 p;
413         int                     len1,
414                                 len2;
415         pg_wchar   *p1,
416                            *p2;
417
418 #ifdef MULTIBYTE
419         pg_wchar   *ps1,
420                            *ps2;
421 #endif
422
423         if (VARSIZE(t2) <= VARHDRSZ)
424                 PG_RETURN_INT32(1);             /* result for empty pattern */
425
426         len1 = (VARSIZE(t1) - VARHDRSZ);
427         len2 = (VARSIZE(t2) - VARHDRSZ);
428 #ifdef MULTIBYTE
429         ps1 = p1 = (pg_wchar *) palloc((len1 + 1) * sizeof(pg_wchar));
430         (void) pg_mb2wchar_with_len((unsigned char *) VARDATA(t1), p1, len1);
431         len1 = pg_wchar_strlen(p1);
432         ps2 = p2 = (pg_wchar *) palloc((len2 + 1) * sizeof(pg_wchar));
433         (void) pg_mb2wchar_with_len((unsigned char *) VARDATA(t2), p2, len2);
434         len2 = pg_wchar_strlen(p2);
435 #else
436         p1 = VARDATA(t1);
437         p2 = VARDATA(t2);
438 #endif
439         pos = 0;
440         px = (len1 - len2);
441         for (p = 0; p <= px; p++)
442         {
443 #ifdef MULTIBYTE
444                 if ((*p2 == *p1) && (pg_wchar_strncmp(p1, p2, len2) == 0))
445 #else
446                 if ((*p2 == *p1) && (strncmp(p1, p2, len2) == 0))
447 #endif
448                 {
449                         pos = p + 1;
450                         break;
451                 };
452                 p1++;
453         };
454 #ifdef MULTIBYTE
455         pfree(ps1);
456         pfree(ps2);
457 #endif
458         PG_RETURN_INT32(pos);
459 }
460
461 /* varstr_cmp()
462  * Comparison function for text strings with given lengths.
463  * Includes locale support, but must copy strings to temporary memory
464  *      to allow null-termination for inputs to strcoll().
465  * Returns -1, 0 or 1
466  */
467 int
468 varstr_cmp(char *arg1, int len1, char *arg2, int len2)
469 {
470         int                     result;
471         char       *a1p,
472                            *a2p;
473
474 #ifdef USE_LOCALE
475         a1p = (char *) palloc(len1 + 1);
476         a2p = (char *) palloc(len2 + 1);
477
478         memcpy(a1p, arg1, len1);
479         *(a1p + len1) = '\0';
480         memcpy(a2p, arg2, len2);
481         *(a2p + len2) = '\0';
482
483         result = strcoll(a1p, a2p);
484
485         pfree(a1p);
486         pfree(a2p);
487
488 #else
489
490         a1p = arg1;
491         a2p = arg2;
492
493         result = strncmp(a1p, a2p, Min(len1, len2));
494         if ((result == 0) && (len1 != len2))
495                 result = (len1 < len2) ? -1 : 1;
496 #endif
497
498         return result;
499 }
500
501
502 /* text_cmp()
503  * Internal comparison function for text strings.
504  * Returns -1, 0 or 1
505  */
506 static int
507 text_cmp(text *arg1, text *arg2)
508 {
509         char       *a1p,
510                            *a2p;
511         int                     len1,
512                                 len2;
513
514         a1p = VARDATA(arg1);
515         a2p = VARDATA(arg2);
516
517         len1 = VARSIZE(arg1) - VARHDRSZ;
518         len2 = VARSIZE(arg2) - VARHDRSZ;
519
520         return varstr_cmp(a1p, len1, a2p, len2);
521 }
522
523 /*
524  * Comparison functions for text strings.
525  *
526  * Note: btree indexes need these routines not to leak memory; therefore,
527  * be careful to free working copies of toasted datums.  Most places don't
528  * need to be so careful.
529  */
530
531 Datum
532 texteq(PG_FUNCTION_ARGS)
533 {
534         text       *arg1 = PG_GETARG_TEXT_P(0);
535         text       *arg2 = PG_GETARG_TEXT_P(1);
536         bool            result;
537
538         /* fast path for different-length inputs */
539         if (VARSIZE(arg1) != VARSIZE(arg2))
540                 result = false;
541         else
542                 result = (text_cmp(arg1, arg2) == 0);
543
544         PG_FREE_IF_COPY(arg1, 0);
545         PG_FREE_IF_COPY(arg2, 1);
546
547         PG_RETURN_BOOL(result);
548 }
549
550 Datum
551 textne(PG_FUNCTION_ARGS)
552 {
553         text       *arg1 = PG_GETARG_TEXT_P(0);
554         text       *arg2 = PG_GETARG_TEXT_P(1);
555         bool            result;
556
557         /* fast path for different-length inputs */
558         if (VARSIZE(arg1) != VARSIZE(arg2))
559                 result = true;
560         else
561                 result = (text_cmp(arg1, arg2) != 0);
562
563         PG_FREE_IF_COPY(arg1, 0);
564         PG_FREE_IF_COPY(arg2, 1);
565
566         PG_RETURN_BOOL(result);
567 }
568
569 Datum
570 text_lt(PG_FUNCTION_ARGS)
571 {
572         text       *arg1 = PG_GETARG_TEXT_P(0);
573         text       *arg2 = PG_GETARG_TEXT_P(1);
574         bool            result;
575
576         result = (text_cmp(arg1, arg2) < 0);
577
578         PG_FREE_IF_COPY(arg1, 0);
579         PG_FREE_IF_COPY(arg2, 1);
580
581         PG_RETURN_BOOL(result);
582 }
583
584 Datum
585 text_le(PG_FUNCTION_ARGS)
586 {
587         text       *arg1 = PG_GETARG_TEXT_P(0);
588         text       *arg2 = PG_GETARG_TEXT_P(1);
589         bool            result;
590
591         result = (text_cmp(arg1, arg2) <= 0);
592
593         PG_FREE_IF_COPY(arg1, 0);
594         PG_FREE_IF_COPY(arg2, 1);
595
596         PG_RETURN_BOOL(result);
597 }
598
599 Datum
600 text_gt(PG_FUNCTION_ARGS)
601 {
602         text       *arg1 = PG_GETARG_TEXT_P(0);
603         text       *arg2 = PG_GETARG_TEXT_P(1);
604         bool            result;
605
606         result = (text_cmp(arg1, arg2) > 0);
607
608         PG_FREE_IF_COPY(arg1, 0);
609         PG_FREE_IF_COPY(arg2, 1);
610
611         PG_RETURN_BOOL(result);
612 }
613
614 Datum
615 text_ge(PG_FUNCTION_ARGS)
616 {
617         text       *arg1 = PG_GETARG_TEXT_P(0);
618         text       *arg2 = PG_GETARG_TEXT_P(1);
619         bool            result;
620
621         result = (text_cmp(arg1, arg2) >= 0);
622
623         PG_FREE_IF_COPY(arg1, 0);
624         PG_FREE_IF_COPY(arg2, 1);
625
626         PG_RETURN_BOOL(result);
627 }
628
629 Datum
630 bttextcmp(PG_FUNCTION_ARGS)
631 {
632         text       *arg1 = PG_GETARG_TEXT_P(0);
633         text       *arg2 = PG_GETARG_TEXT_P(1);
634         int32           result;
635
636         result = text_cmp(arg1, arg2);
637
638         PG_FREE_IF_COPY(arg1, 0);
639         PG_FREE_IF_COPY(arg2, 1);
640
641         PG_RETURN_INT32(result);
642 }
643
644
645 Datum
646 text_larger(PG_FUNCTION_ARGS)
647 {
648         text       *arg1 = PG_GETARG_TEXT_P(0);
649         text       *arg2 = PG_GETARG_TEXT_P(1);
650         text       *result;
651
652         result = ((text_cmp(arg1, arg2) > 0) ? arg1 : arg2);
653
654         PG_RETURN_TEXT_P(result);
655 }
656
657 Datum
658 text_smaller(PG_FUNCTION_ARGS)
659 {
660         text       *arg1 = PG_GETARG_TEXT_P(0);
661         text       *arg2 = PG_GETARG_TEXT_P(1);
662         text       *result;
663
664         result = ((text_cmp(arg1, arg2) < 0) ? arg1 : arg2);
665
666         PG_RETURN_TEXT_P(result);
667 }
668
669 /*-------------------------------------------------------------
670  * byteaoctetlen
671  *
672  * get the number of bytes contained in an instance of type 'bytea'
673  *-------------------------------------------------------------
674  */
675 Datum
676 byteaoctetlen(PG_FUNCTION_ARGS)
677 {
678         bytea      *v = PG_GETARG_BYTEA_P(0);
679
680         PG_RETURN_INT32(VARSIZE(v) - VARHDRSZ);
681 }
682
683 /*
684  * byteacat -
685  *        takes two bytea* and returns a bytea* that is the concatenation of
686  *        the two.
687  *
688  * Cloned from textcat and modified as required.
689  */
690 Datum
691 byteacat(PG_FUNCTION_ARGS)
692 {
693         bytea      *t1 = PG_GETARG_BYTEA_P(0);
694         bytea      *t2 = PG_GETARG_BYTEA_P(1);
695         int                     len1,
696                                 len2,
697                                 len;
698         bytea      *result;
699         char       *ptr;
700
701         len1 = (VARSIZE(t1) - VARHDRSZ);
702         if (len1 < 0)
703                 len1 = 0;
704
705         len2 = (VARSIZE(t2) - VARHDRSZ);
706         if (len2 < 0)
707                 len2 = 0;
708
709         len = len1 + len2 + VARHDRSZ;
710         result = (bytea *) palloc(len);
711
712         /* Set size of result string... */
713         VARATT_SIZEP(result) = len;
714
715         /* Fill data field of result string... */
716         ptr = VARDATA(result);
717         if (len1 > 0)
718                 memcpy(ptr, VARDATA(t1), len1);
719         if (len2 > 0)
720                 memcpy(ptr + len1, VARDATA(t2), len2);
721
722         PG_RETURN_BYTEA_P(result);
723 }
724
725 /*
726  * bytea_substr()
727  * Return a substring starting at the specified position.
728  * Cloned from text_substr and modified as required.
729  *
730  * Input:
731  *      - string
732  *      - starting position (is one-based)
733  *      - string length
734  *
735  * If the starting position is zero or less, then return from the start of the string
736  * adjusting the length to be consistent with the "negative start" per SQL92.
737  * If the length is less than zero, return the remaining string.
738  *
739  */
740 Datum
741 bytea_substr(PG_FUNCTION_ARGS)
742 {
743         bytea      *string = PG_GETARG_BYTEA_P(0);
744         int32           m = PG_GETARG_INT32(1);
745         int32           n = PG_GETARG_INT32(2);
746         bytea      *ret;
747         int                     len;
748
749         len = VARSIZE(string) - VARHDRSZ;
750
751         /* starting position after the end of the string? */
752         if (m > len)
753         {
754                 m = 1;
755                 n = 0;
756         }
757
758         /*
759          * starting position before the start of the string? then offset into
760          * the string per SQL92 spec...
761          */
762         else if (m < 1)
763         {
764                 n += (m - 1);
765                 m = 1;
766         }
767
768         /* m will now become a zero-based starting position */
769         m--;
770         if (((m + n) > len) || (n < 0))
771                 n = (len - m);
772
773         ret = (bytea *) palloc(VARHDRSZ + n);
774         VARATT_SIZEP(ret) = VARHDRSZ + n;
775
776         memcpy(VARDATA(ret), VARDATA(string) + m, n);
777
778         PG_RETURN_BYTEA_P(ret);
779 }
780
781 /*
782  * byteapos -
783  *        Return the position of the specified substring.
784  *        Implements the SQL92 POSITION() function.
785  * Cloned from textpos and modified as required.
786  */
787 Datum
788 byteapos(PG_FUNCTION_ARGS)
789 {
790         bytea      *t1 = PG_GETARG_BYTEA_P(0);
791         bytea      *t2 = PG_GETARG_BYTEA_P(1);
792         int                     pos;
793         int                     px,
794                                 p;
795         int                     len1,
796                                 len2;
797         char       *p1,
798                            *p2;
799
800         if (VARSIZE(t2) <= VARHDRSZ)
801                 PG_RETURN_INT32(1);             /* result for empty pattern */
802
803         len1 = (VARSIZE(t1) - VARHDRSZ);
804         len2 = (VARSIZE(t2) - VARHDRSZ);
805
806         p1 = VARDATA(t1);
807         p2 = VARDATA(t2);
808
809         pos = 0;
810         px = (len1 - len2);
811         for (p = 0; p <= px; p++)
812         {
813                 if ((*p2 == *p1) && (memcmp(p1, p2, len2) == 0))
814                 {
815                         pos = p + 1;
816                         break;
817                 };
818                 p1++;
819         };
820
821         PG_RETURN_INT32(pos);
822 }
823
824 /*-------------------------------------------------------------
825  * byteaGetByte
826  *
827  * this routine treats "bytea" as an array of bytes.
828  * It returns the Nth byte (a number between 0 and 255).
829  *-------------------------------------------------------------
830  */
831 Datum
832 byteaGetByte(PG_FUNCTION_ARGS)
833 {
834         bytea      *v = PG_GETARG_BYTEA_P(0);
835         int32           n = PG_GETARG_INT32(1);
836         int                     len;
837         int                     byte;
838
839         len = VARSIZE(v) - VARHDRSZ;
840
841         if (n < 0 || n >= len)
842                 elog(ERROR, "byteaGetByte: index %d out of range [0..%d]",
843                          n, len - 1);
844
845         byte = ((unsigned char *) VARDATA(v))[n];
846
847         PG_RETURN_INT32(byte);
848 }
849
850 /*-------------------------------------------------------------
851  * byteaGetBit
852  *
853  * This routine treats a "bytea" type like an array of bits.
854  * It returns the value of the Nth bit (0 or 1).
855  *
856  *-------------------------------------------------------------
857  */
858 Datum
859 byteaGetBit(PG_FUNCTION_ARGS)
860 {
861         bytea      *v = PG_GETARG_BYTEA_P(0);
862         int32           n = PG_GETARG_INT32(1);
863         int                     byteNo,
864                                 bitNo;
865         int                     len;
866         int                     byte;
867
868         len = VARSIZE(v) - VARHDRSZ;
869
870         if (n < 0 || n >= len * 8)
871                 elog(ERROR, "byteaGetBit: index %d out of range [0..%d]",
872                          n, len * 8 - 1);
873
874         byteNo = n / 8;
875         bitNo = n % 8;
876
877         byte = ((unsigned char *) VARDATA(v))[byteNo];
878
879         if (byte & (1 << bitNo))
880                 PG_RETURN_INT32(1);
881         else
882                 PG_RETURN_INT32(0);
883 }
884
885 /*-------------------------------------------------------------
886  * byteaSetByte
887  *
888  * Given an instance of type 'bytea' creates a new one with
889  * the Nth byte set to the given value.
890  *
891  *-------------------------------------------------------------
892  */
893 Datum
894 byteaSetByte(PG_FUNCTION_ARGS)
895 {
896         bytea      *v = PG_GETARG_BYTEA_P(0);
897         int32           n = PG_GETARG_INT32(1);
898         int32           newByte = PG_GETARG_INT32(2);
899         int                     len;
900         bytea      *res;
901
902         len = VARSIZE(v) - VARHDRSZ;
903
904         if (n < 0 || n >= len)
905                 elog(ERROR, "byteaSetByte: index %d out of range [0..%d]",
906                          n, len - 1);
907
908         /*
909          * Make a copy of the original varlena.
910          */
911         res = (bytea *) palloc(VARSIZE(v));
912         memcpy((char *) res, (char *) v, VARSIZE(v));
913
914         /*
915          * Now set the byte.
916          */
917         ((unsigned char *) VARDATA(res))[n] = newByte;
918
919         PG_RETURN_BYTEA_P(res);
920 }
921
922 /*-------------------------------------------------------------
923  * byteaSetBit
924  *
925  * Given an instance of type 'bytea' creates a new one with
926  * the Nth bit set to the given value.
927  *
928  *-------------------------------------------------------------
929  */
930 Datum
931 byteaSetBit(PG_FUNCTION_ARGS)
932 {
933         bytea      *v = PG_GETARG_BYTEA_P(0);
934         int32           n = PG_GETARG_INT32(1);
935         int32           newBit = PG_GETARG_INT32(2);
936         bytea      *res;
937         int                     len;
938         int                     oldByte,
939                                 newByte;
940         int                     byteNo,
941                                 bitNo;
942
943         len = VARSIZE(v) - VARHDRSZ;
944
945         if (n < 0 || n >= len * 8)
946                 elog(ERROR, "byteaSetBit: index %d out of range [0..%d]",
947                          n, len * 8 - 1);
948
949         byteNo = n / 8;
950         bitNo = n % 8;
951
952         /*
953          * sanity check!
954          */
955         if (newBit != 0 && newBit != 1)
956                 elog(ERROR, "byteaSetBit: new bit must be 0 or 1");
957
958         /*
959          * Make a copy of the original varlena.
960          */
961         res = (bytea *) palloc(VARSIZE(v));
962         memcpy((char *) res, (char *) v, VARSIZE(v));
963
964         /*
965          * Update the byte.
966          */
967         oldByte = ((unsigned char *) VARDATA(res))[byteNo];
968
969         if (newBit == 0)
970                 newByte = oldByte & (~(1 << bitNo));
971         else
972                 newByte = oldByte | (1 << bitNo);
973
974         ((unsigned char *) VARDATA(res))[byteNo] = newByte;
975
976         PG_RETURN_BYTEA_P(res);
977 }
978
979
980 /* text_name()
981  * Converts a text type to a Name type.
982  */
983 Datum
984 text_name(PG_FUNCTION_ARGS)
985 {
986         text       *s = PG_GETARG_TEXT_P(0);
987         Name            result;
988         int                     len;
989
990         len = VARSIZE(s) - VARHDRSZ;
991
992         /* Truncate oversize input */
993         if (len >= NAMEDATALEN)
994                 len = NAMEDATALEN - 1;
995
996 #ifdef STRINGDEBUG
997         printf("text- convert string length %d (%d) ->%d\n",
998                    VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);
999 #endif
1000
1001         result = (Name) palloc(NAMEDATALEN);
1002         memcpy(NameStr(*result), VARDATA(s), len);
1003
1004         /* now null pad to full length... */
1005         while (len < NAMEDATALEN)
1006         {
1007                 *(NameStr(*result) + len) = '\0';
1008                 len++;
1009         }
1010
1011         PG_RETURN_NAME(result);
1012 }
1013
1014 /* name_text()
1015  * Converts a Name type to a text type.
1016  */
1017 Datum
1018 name_text(PG_FUNCTION_ARGS)
1019 {
1020         Name            s = PG_GETARG_NAME(0);
1021         text       *result;
1022         int                     len;
1023
1024         len = strlen(NameStr(*s));
1025
1026 #ifdef STRINGDEBUG
1027         printf("text- convert string length %d (%d) ->%d\n",
1028                    VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);
1029 #endif
1030
1031         result = palloc(VARHDRSZ + len);
1032         VARATT_SIZEP(result) = VARHDRSZ + len;
1033         memcpy(VARDATA(result), NameStr(*s), len);
1034
1035         PG_RETURN_TEXT_P(result);
1036 }
1037
1038
1039 /*****************************************************************************
1040  *      Comparison Functions used for bytea
1041  *
1042  * Note: btree indexes need these routines not to leak memory; therefore,
1043  * be careful to free working copies of toasted datums.  Most places don't
1044  * need to be so careful.
1045  *****************************************************************************/
1046
1047 Datum
1048 byteaeq(PG_FUNCTION_ARGS)
1049 {
1050         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1051         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1052         int                     len1,
1053                                 len2;
1054         bool            result;
1055
1056         len1 = VARSIZE(arg1) - VARHDRSZ;
1057         len2 = VARSIZE(arg2) - VARHDRSZ;
1058
1059         /* fast path for different-length inputs */
1060         if (len1 != len2)
1061                 result = false;
1062         else
1063                 result = (memcmp(VARDATA(arg1), VARDATA(arg2), len1) == 0);
1064
1065         PG_FREE_IF_COPY(arg1, 0);
1066         PG_FREE_IF_COPY(arg2, 1);
1067
1068         PG_RETURN_BOOL(result);
1069 }
1070
1071 Datum
1072 byteane(PG_FUNCTION_ARGS)
1073 {
1074         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1075         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1076         int                     len1,
1077                                 len2;
1078         bool            result;
1079
1080         len1 = VARSIZE(arg1) - VARHDRSZ;
1081         len2 = VARSIZE(arg2) - VARHDRSZ;
1082
1083         /* fast path for different-length inputs */
1084         if (len1 != len2)
1085                 result = true;
1086         else
1087                 result = (memcmp(VARDATA(arg1), VARDATA(arg2), len1) != 0);
1088
1089         PG_FREE_IF_COPY(arg1, 0);
1090         PG_FREE_IF_COPY(arg2, 1);
1091
1092         PG_RETURN_BOOL(result);
1093 }
1094
1095 Datum
1096 bytealt(PG_FUNCTION_ARGS)
1097 {
1098         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1099         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1100         int                     len1,
1101                                 len2;
1102         int                     cmp;
1103
1104         len1 = VARSIZE(arg1) - VARHDRSZ;
1105         len2 = VARSIZE(arg2) - VARHDRSZ;
1106
1107         cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1108
1109         PG_FREE_IF_COPY(arg1, 0);
1110         PG_FREE_IF_COPY(arg2, 1);
1111
1112         PG_RETURN_BOOL((cmp < 0) || ((cmp == 0) && (len1 < len2)));
1113 }
1114
1115 Datum
1116 byteale(PG_FUNCTION_ARGS)
1117 {
1118         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1119         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1120         int                     len1,
1121                                 len2;
1122         int                     cmp;
1123
1124         len1 = VARSIZE(arg1) - VARHDRSZ;
1125         len2 = VARSIZE(arg2) - VARHDRSZ;
1126
1127         cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1128
1129         PG_FREE_IF_COPY(arg1, 0);
1130         PG_FREE_IF_COPY(arg2, 1);
1131
1132         PG_RETURN_BOOL((cmp < 0) || ((cmp == 0) && (len1 <= len2)));
1133 }
1134
1135 Datum
1136 byteagt(PG_FUNCTION_ARGS)
1137 {
1138         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1139         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1140         int                     len1,
1141                                 len2;
1142         int                     cmp;
1143
1144         len1 = VARSIZE(arg1) - VARHDRSZ;
1145         len2 = VARSIZE(arg2) - VARHDRSZ;
1146
1147         cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1148
1149         PG_FREE_IF_COPY(arg1, 0);
1150         PG_FREE_IF_COPY(arg2, 1);
1151
1152         PG_RETURN_BOOL((cmp > 0) || ((cmp == 0) && (len1 > len2)));
1153 }
1154
1155 Datum
1156 byteage(PG_FUNCTION_ARGS)
1157 {
1158         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1159         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1160         int                     len1,
1161                                 len2;
1162         int                     cmp;
1163
1164         len1 = VARSIZE(arg1) - VARHDRSZ;
1165         len2 = VARSIZE(arg2) - VARHDRSZ;
1166
1167         cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1168
1169         PG_FREE_IF_COPY(arg1, 0);
1170         PG_FREE_IF_COPY(arg2, 1);
1171
1172         PG_RETURN_BOOL((cmp > 0) || ((cmp == 0) && (len1 >= len2)));
1173 }
1174
1175 Datum
1176 byteacmp(PG_FUNCTION_ARGS)
1177 {
1178         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1179         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1180         int                     len1,
1181                                 len2;
1182         int                     cmp;
1183
1184         len1 = VARSIZE(arg1) - VARHDRSZ;
1185         len2 = VARSIZE(arg2) - VARHDRSZ;
1186
1187         cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1188         if ((cmp == 0) && (len1 != len2))
1189                 cmp = (len1 < len2) ? -1 : 1;
1190
1191         PG_FREE_IF_COPY(arg1, 0);
1192         PG_FREE_IF_COPY(arg2, 1);
1193
1194         PG_RETURN_INT32(cmp);
1195 }