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