1 /*-------------------------------------------------------------------------
4 * Functions for the variable-length built-in types.
6 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.74 2001/10/25 05:49:46 momjian Exp $
13 *-------------------------------------------------------------------------
19 #include "mb/pg_wchar.h"
20 #include "miscadmin.h"
21 #include "utils/builtins.h"
23 static int text_cmp(text *arg1, text *arg2);
26 /*****************************************************************************
28 *****************************************************************************/
31 #define VAL(CH) ((CH) - '0')
32 #define DIG(VAL) ((VAL) + '0')
35 * byteain - converts from printable representation of byte array
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.
42 * The input is scaned twice.
43 * The error checking of input is minimal.
46 byteain(PG_FUNCTION_ARGS)
48 char *inputText = PG_GETARG_CSTRING(0);
54 for (byte = 0, tp = inputText; *tp != '\0'; byte++)
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'))
63 else if ((tp[0] == '\\') &&
69 * one backslash, not followed by 0 or ### valid octal
71 elog(ERROR, "Bad input string for type bytea");
76 result = (bytea *) palloc(byte);
77 result->vl_len = byte; /* set varlena length */
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'))
94 *rp++ = byte + VAL(tp[3]);
97 else if ((tp[0] == '\\') &&
106 * We should never get here. The first pass should not allow
109 elog(ERROR, "Bad input string for type bytea");
113 PG_RETURN_BYTEA_P(result);
117 * byteaout - converts to printable representation of byte array
119 * Non-printable characters are inserted as '\nnn' (octal) and '\' as
122 * NULL vlena should be an error--returning string with NULL for now.
125 byteaout(PG_FUNCTION_ARGS)
127 bytea *vlena = PG_GETARG_BYTEA_P(0);
131 int val; /* holds unprintable chars */
135 len = 1; /* empty string has 1 char */
137 for (i = vlena->vl_len - VARHDRSZ; i != 0; i--, vp++)
141 else if (isprint((unsigned char) *vp))
146 rp = result = (char *) palloc(len);
148 for (i = vlena->vl_len - VARHDRSZ; i != 0; i--, vp++)
155 else if (isprint((unsigned char) *vp))
161 rp[3] = DIG(val & 07);
163 rp[2] = DIG(val & 07);
165 rp[1] = DIG(val & 03);
170 PG_RETURN_CSTRING(result);
175 * textin - converts "..." to internal representation
178 textin(PG_FUNCTION_ARGS)
180 char *inputText = PG_GETARG_CSTRING(0);
188 len = strlen(inputText) + VARHDRSZ;
191 if ((ermsg = pg_verifymbstr(inputText, len - VARHDRSZ)))
192 elog(ERROR, "%s", ermsg);
195 result = (text *) palloc(len);
196 VARATT_SIZEP(result) = len;
198 memcpy(VARDATA(result), inputText, len - VARHDRSZ);
201 convertstr(VARDATA(result), len - VARHDRSZ, 0);
204 PG_RETURN_TEXT_P(result);
208 * textout - converts internal representation to "..."
211 textout(PG_FUNCTION_ARGS)
213 text *t = PG_GETARG_TEXT_P(0);
217 len = VARSIZE(t) - VARHDRSZ;
218 result = (char *) palloc(len + 1);
219 memcpy(result, VARDATA(t), len);
223 convertstr(result, len, 1);
226 PG_RETURN_CSTRING(result);
230 /* ========== PUBLIC ROUTINES ========== */
234 * returns the logical length of a text*
235 * (which is less than the VARSIZE of the text*)
238 textlen(PG_FUNCTION_ARGS)
240 text *t = PG_GETARG_TEXT_P(0);
250 l = VARSIZE(t) - VARHDRSZ;
258 PG_RETURN_INT32(len);
260 PG_RETURN_INT32(VARSIZE(t) - VARHDRSZ);
266 * returns the physical length of a text*
267 * (which is less than the VARSIZE of the text*)
269 * XXX is it actually appropriate to return the compressed length
270 * when the value is compressed? It's not at all clear to me that
271 * this is what SQL92 has in mind ...
274 textoctetlen(PG_FUNCTION_ARGS)
276 struct varattrib *t = (struct varattrib *) PG_GETARG_RAW_VARLENA_P(0);
278 if (!VARATT_IS_EXTERNAL(t))
279 PG_RETURN_INT32(VARATT_SIZE(t) - VARHDRSZ);
281 PG_RETURN_INT32(t->va_content.va_external.va_extsize);
286 * takes two text* and returns a text* that is the concatenation of
289 * Rewritten by Sapa, sapa@hq.icb.chel.su. 8-Jul-96.
290 * Updated by Thomas, Thomas.Lockhart@jpl.nasa.gov 1997-07-10.
291 * Allocate space for output in all cases.
292 * XXX - thomas 1997-07-10
295 textcat(PG_FUNCTION_ARGS)
297 text *t1 = PG_GETARG_TEXT_P(0);
298 text *t2 = PG_GETARG_TEXT_P(1);
305 len1 = (VARSIZE(t1) - VARHDRSZ);
309 len2 = (VARSIZE(t2) - VARHDRSZ);
313 len = len1 + len2 + VARHDRSZ;
314 result = (text *) palloc(len);
316 /* Set size of result string... */
317 VARATT_SIZEP(result) = len;
319 /* Fill data field of result string... */
320 ptr = VARDATA(result);
322 memcpy(ptr, VARDATA(t1), len1);
324 memcpy(ptr + len1, VARDATA(t2), len2);
326 PG_RETURN_TEXT_P(result);
331 * Return a substring starting at the specified position.
332 * - thomas 1997-12-31
336 * - starting position (is one-based)
339 * If the starting position is zero or less, then return from the start of the string
340 * adjusting the length to be consistant with the "negative start" per SQL92.
341 * If the length is less than zero, return the remaining string.
343 * Note that the arguments operate on octet length,
344 * so not aware of multi-byte character sets.
346 * Added multi-byte support.
347 * - Tatsuo Ishii 1998-4-21
348 * Changed behavior if starting position is less than one to conform to SQL92 behavior.
349 * Formerly returned the entire string; now returns a portion.
350 * - Thomas Lockhart 1998-12-10
353 text_substr(PG_FUNCTION_ARGS)
355 text *string = PG_GETARG_TEXT_P(0);
356 int32 m = PG_GETARG_INT32(1);
357 int32 n = PG_GETARG_INT32(2);
366 len = VARSIZE(string) - VARHDRSZ;
368 len = pg_mbstrlen_with_len(VARDATA(string), len);
371 /* starting position after the end of the string? */
379 * starting position before the start of the string? then offset into
380 * the string per SQL92 spec...
388 /* m will now become a zero-based starting position */
390 if (((m + n) > len) || (n < 0))
395 for (i = 0; i < m; i++)
397 m = p - VARDATA(string);
398 for (i = 0; i < n; i++)
400 n = p - (VARDATA(string) + m);
403 ret = (text *) palloc(VARHDRSZ + n);
404 VARATT_SIZEP(ret) = VARHDRSZ + n;
406 memcpy(VARDATA(ret), VARDATA(string) + m, n);
408 PG_RETURN_TEXT_P(ret);
413 * Return the position of the specified substring.
414 * Implements the SQL92 POSITION() function.
415 * Ref: A Guide To The SQL Standard, Date & Darwen, 1997
416 * - thomas 1997-07-27
418 * Added multi-byte support.
419 * - Tatsuo Ishii 1998-4-21
422 textpos(PG_FUNCTION_ARGS)
424 text *t1 = PG_GETARG_TEXT_P(0);
425 text *t2 = PG_GETARG_TEXT_P(1);
439 if (VARSIZE(t2) <= VARHDRSZ)
440 PG_RETURN_INT32(1); /* result for empty pattern */
442 len1 = (VARSIZE(t1) - VARHDRSZ);
443 len2 = (VARSIZE(t2) - VARHDRSZ);
445 ps1 = p1 = (pg_wchar *) palloc((len1 + 1) * sizeof(pg_wchar));
446 (void) pg_mb2wchar_with_len((unsigned char *) VARDATA(t1), p1, len1);
447 len1 = pg_wchar_strlen(p1);
448 ps2 = p2 = (pg_wchar *) palloc((len2 + 1) * sizeof(pg_wchar));
449 (void) pg_mb2wchar_with_len((unsigned char *) VARDATA(t2), p2, len2);
450 len2 = pg_wchar_strlen(p2);
457 for (p = 0; p <= px; p++)
460 if ((*p2 == *p1) && (pg_wchar_strncmp(p1, p2, len2) == 0))
462 if ((*p2 == *p1) && (strncmp(p1, p2, len2) == 0))
474 PG_RETURN_INT32(pos);
478 * Comparison function for text strings with given lengths.
479 * Includes locale support, but must copy strings to temporary memory
480 * to allow null-termination for inputs to strcoll().
484 varstr_cmp(char *arg1, int len1, char *arg2, int len2)
491 a1p = (char *) palloc(len1 + 1);
492 a2p = (char *) palloc(len2 + 1);
494 memcpy(a1p, arg1, len1);
495 *(a1p + len1) = '\0';
496 memcpy(a2p, arg2, len2);
497 *(a2p + len2) = '\0';
499 result = strcoll(a1p, a2p);
509 result = strncmp(a1p, a2p, Min(len1, len2));
510 if ((result == 0) && (len1 != len2))
511 result = (len1 < len2) ? -1 : 1;
519 * Internal comparison function for text strings.
523 text_cmp(text *arg1, text *arg2)
533 len1 = VARSIZE(arg1) - VARHDRSZ;
534 len2 = VARSIZE(arg2) - VARHDRSZ;
536 return varstr_cmp(a1p, len1, a2p, len2);
540 * Comparison functions for text strings.
542 * Note: btree indexes need these routines not to leak memory; therefore,
543 * be careful to free working copies of toasted datums. Most places don't
544 * need to be so careful.
548 texteq(PG_FUNCTION_ARGS)
550 text *arg1 = PG_GETARG_TEXT_P(0);
551 text *arg2 = PG_GETARG_TEXT_P(1);
554 /* fast path for different-length inputs */
555 if (VARSIZE(arg1) != VARSIZE(arg2))
558 result = (text_cmp(arg1, arg2) == 0);
560 PG_FREE_IF_COPY(arg1, 0);
561 PG_FREE_IF_COPY(arg2, 1);
563 PG_RETURN_BOOL(result);
567 textne(PG_FUNCTION_ARGS)
569 text *arg1 = PG_GETARG_TEXT_P(0);
570 text *arg2 = PG_GETARG_TEXT_P(1);
573 /* fast path for different-length inputs */
574 if (VARSIZE(arg1) != VARSIZE(arg2))
577 result = (text_cmp(arg1, arg2) != 0);
579 PG_FREE_IF_COPY(arg1, 0);
580 PG_FREE_IF_COPY(arg2, 1);
582 PG_RETURN_BOOL(result);
586 text_lt(PG_FUNCTION_ARGS)
588 text *arg1 = PG_GETARG_TEXT_P(0);
589 text *arg2 = PG_GETARG_TEXT_P(1);
592 result = (text_cmp(arg1, arg2) < 0);
594 PG_FREE_IF_COPY(arg1, 0);
595 PG_FREE_IF_COPY(arg2, 1);
597 PG_RETURN_BOOL(result);
601 text_le(PG_FUNCTION_ARGS)
603 text *arg1 = PG_GETARG_TEXT_P(0);
604 text *arg2 = PG_GETARG_TEXT_P(1);
607 result = (text_cmp(arg1, arg2) <= 0);
609 PG_FREE_IF_COPY(arg1, 0);
610 PG_FREE_IF_COPY(arg2, 1);
612 PG_RETURN_BOOL(result);
616 text_gt(PG_FUNCTION_ARGS)
618 text *arg1 = PG_GETARG_TEXT_P(0);
619 text *arg2 = PG_GETARG_TEXT_P(1);
622 result = (text_cmp(arg1, arg2) > 0);
624 PG_FREE_IF_COPY(arg1, 0);
625 PG_FREE_IF_COPY(arg2, 1);
627 PG_RETURN_BOOL(result);
631 text_ge(PG_FUNCTION_ARGS)
633 text *arg1 = PG_GETARG_TEXT_P(0);
634 text *arg2 = PG_GETARG_TEXT_P(1);
637 result = (text_cmp(arg1, arg2) >= 0);
639 PG_FREE_IF_COPY(arg1, 0);
640 PG_FREE_IF_COPY(arg2, 1);
642 PG_RETURN_BOOL(result);
646 bttextcmp(PG_FUNCTION_ARGS)
648 text *arg1 = PG_GETARG_TEXT_P(0);
649 text *arg2 = PG_GETARG_TEXT_P(1);
652 result = text_cmp(arg1, arg2);
654 PG_FREE_IF_COPY(arg1, 0);
655 PG_FREE_IF_COPY(arg2, 1);
657 PG_RETURN_INT32(result);
662 text_larger(PG_FUNCTION_ARGS)
664 text *arg1 = PG_GETARG_TEXT_P(0);
665 text *arg2 = PG_GETARG_TEXT_P(1);
668 result = ((text_cmp(arg1, arg2) > 0) ? arg1 : arg2);
670 PG_RETURN_TEXT_P(result);
674 text_smaller(PG_FUNCTION_ARGS)
676 text *arg1 = PG_GETARG_TEXT_P(0);
677 text *arg2 = PG_GETARG_TEXT_P(1);
680 result = ((text_cmp(arg1, arg2) < 0) ? arg1 : arg2);
682 PG_RETURN_TEXT_P(result);
685 /*-------------------------------------------------------------
688 * get the number of bytes contained in an instance of type 'bytea'
689 *-------------------------------------------------------------
692 byteaoctetlen(PG_FUNCTION_ARGS)
694 bytea *v = PG_GETARG_BYTEA_P(0);
696 PG_RETURN_INT32(VARSIZE(v) - VARHDRSZ);
701 * takes two bytea* and returns a bytea* that is the concatenation of
704 * Cloned from textcat and modified as required.
707 byteacat(PG_FUNCTION_ARGS)
709 bytea *t1 = PG_GETARG_BYTEA_P(0);
710 bytea *t2 = PG_GETARG_BYTEA_P(1);
717 len1 = (VARSIZE(t1) - VARHDRSZ);
721 len2 = (VARSIZE(t2) - VARHDRSZ);
725 len = len1 + len2 + VARHDRSZ;
726 result = (bytea *) palloc(len);
728 /* Set size of result string... */
729 VARATT_SIZEP(result) = len;
731 /* Fill data field of result string... */
732 ptr = VARDATA(result);
734 memcpy(ptr, VARDATA(t1), len1);
736 memcpy(ptr + len1, VARDATA(t2), len2);
738 PG_RETURN_BYTEA_P(result);
743 * Return a substring starting at the specified position.
744 * Cloned from text_substr and modified as required.
748 * - starting position (is one-based)
751 * If the starting position is zero or less, then return from the start of the string
752 * adjusting the length to be consistant with the "negative start" per SQL92.
753 * If the length is less than zero, return the remaining string.
757 bytea_substr(PG_FUNCTION_ARGS)
759 bytea *string = PG_GETARG_BYTEA_P(0);
760 int32 m = PG_GETARG_INT32(1);
761 int32 n = PG_GETARG_INT32(2);
765 len = VARSIZE(string) - VARHDRSZ;
767 /* starting position after the end of the string? */
775 * starting position before the start of the string? then offset into
776 * the string per SQL92 spec...
784 /* m will now become a zero-based starting position */
786 if (((m + n) > len) || (n < 0))
789 ret = (bytea *) palloc(VARHDRSZ + n);
790 VARATT_SIZEP(ret) = VARHDRSZ + n;
792 memcpy(VARDATA(ret), VARDATA(string) + m, n);
794 PG_RETURN_BYTEA_P(ret);
799 * Return the position of the specified substring.
800 * Implements the SQL92 POSITION() function.
801 * Cloned from textpos and modified as required.
804 byteapos(PG_FUNCTION_ARGS)
806 bytea *t1 = PG_GETARG_BYTEA_P(0);
807 bytea *t2 = PG_GETARG_BYTEA_P(1);
816 if (VARSIZE(t2) <= VARHDRSZ)
817 PG_RETURN_INT32(1); /* result for empty pattern */
819 len1 = (VARSIZE(t1) - VARHDRSZ);
820 len2 = (VARSIZE(t2) - VARHDRSZ);
827 for (p = 0; p <= px; p++)
829 if ((*p2 == *p1) && (memcmp(p1, p2, len2) == 0))
837 PG_RETURN_INT32(pos);
840 /*-------------------------------------------------------------
843 * this routine treats "bytea" as an array of bytes.
844 * It returns the Nth byte (a number between 0 and 255).
845 *-------------------------------------------------------------
848 byteaGetByte(PG_FUNCTION_ARGS)
850 bytea *v = PG_GETARG_BYTEA_P(0);
851 int32 n = PG_GETARG_INT32(1);
855 len = VARSIZE(v) - VARHDRSZ;
857 if (n < 0 || n >= len)
858 elog(ERROR, "byteaGetByte: index %d out of range [0..%d]",
861 byte = ((unsigned char *) VARDATA(v))[n];
863 PG_RETURN_INT32(byte);
866 /*-------------------------------------------------------------
869 * This routine treats a "bytea" type like an array of bits.
870 * It returns the value of the Nth bit (0 or 1).
872 *-------------------------------------------------------------
875 byteaGetBit(PG_FUNCTION_ARGS)
877 bytea *v = PG_GETARG_BYTEA_P(0);
878 int32 n = PG_GETARG_INT32(1);
884 len = VARSIZE(v) - VARHDRSZ;
886 if (n < 0 || n >= len * 8)
887 elog(ERROR, "byteaGetBit: index %d out of range [0..%d]",
893 byte = ((unsigned char *) VARDATA(v))[byteNo];
895 if (byte & (1 << bitNo))
901 /*-------------------------------------------------------------
904 * Given an instance of type 'bytea' creates a new one with
905 * the Nth byte set to the given value.
907 *-------------------------------------------------------------
910 byteaSetByte(PG_FUNCTION_ARGS)
912 bytea *v = PG_GETARG_BYTEA_P(0);
913 int32 n = PG_GETARG_INT32(1);
914 int32 newByte = PG_GETARG_INT32(2);
918 len = VARSIZE(v) - VARHDRSZ;
920 if (n < 0 || n >= len)
921 elog(ERROR, "byteaSetByte: index %d out of range [0..%d]",
925 * Make a copy of the original varlena.
927 res = (bytea *) palloc(VARSIZE(v));
928 memcpy((char *) res, (char *) v, VARSIZE(v));
933 ((unsigned char *) VARDATA(res))[n] = newByte;
935 PG_RETURN_BYTEA_P(res);
938 /*-------------------------------------------------------------
941 * Given an instance of type 'bytea' creates a new one with
942 * the Nth bit set to the given value.
944 *-------------------------------------------------------------
947 byteaSetBit(PG_FUNCTION_ARGS)
949 bytea *v = PG_GETARG_BYTEA_P(0);
950 int32 n = PG_GETARG_INT32(1);
951 int32 newBit = PG_GETARG_INT32(2);
959 len = VARSIZE(v) - VARHDRSZ;
961 if (n < 0 || n >= len * 8)
962 elog(ERROR, "byteaSetBit: index %d out of range [0..%d]",
971 if (newBit != 0 && newBit != 1)
972 elog(ERROR, "byteaSetBit: new bit must be 0 or 1");
975 * Make a copy of the original varlena.
977 res = (bytea *) palloc(VARSIZE(v));
978 memcpy((char *) res, (char *) v, VARSIZE(v));
983 oldByte = ((unsigned char *) VARDATA(res))[byteNo];
986 newByte = oldByte & (~(1 << bitNo));
988 newByte = oldByte | (1 << bitNo);
990 ((unsigned char *) VARDATA(res))[byteNo] = newByte;
992 PG_RETURN_BYTEA_P(res);
997 * Converts a text type to a Name type.
1000 text_name(PG_FUNCTION_ARGS)
1002 text *s = PG_GETARG_TEXT_P(0);
1006 len = VARSIZE(s) - VARHDRSZ;
1008 /* Truncate oversize input */
1009 if (len >= NAMEDATALEN)
1010 len = NAMEDATALEN - 1;
1013 printf("text- convert string length %d (%d) ->%d\n",
1014 VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);
1017 result = (Name) palloc(NAMEDATALEN);
1018 memcpy(NameStr(*result), VARDATA(s), len);
1020 /* now null pad to full length... */
1021 while (len < NAMEDATALEN)
1023 *(NameStr(*result) + len) = '\0';
1027 PG_RETURN_NAME(result);
1031 * Converts a Name type to a text type.
1034 name_text(PG_FUNCTION_ARGS)
1036 Name s = PG_GETARG_NAME(0);
1040 len = strlen(NameStr(*s));
1043 printf("text- convert string length %d (%d) ->%d\n",
1044 VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);
1047 result = palloc(VARHDRSZ + len);
1048 VARATT_SIZEP(result) = VARHDRSZ + len;
1049 memcpy(VARDATA(result), NameStr(*s), len);
1051 PG_RETURN_TEXT_P(result);
1055 /*****************************************************************************
1056 * Comparison Functions used for bytea
1058 * Note: btree indexes need these routines not to leak memory; therefore,
1059 * be careful to free working copies of toasted datums. Most places don't
1060 * need to be so careful.
1061 *****************************************************************************/
1064 byteaeq(PG_FUNCTION_ARGS)
1066 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1067 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1072 len1 = VARSIZE(arg1) - VARHDRSZ;
1073 len2 = VARSIZE(arg2) - VARHDRSZ;
1075 /* fast path for different-length inputs */
1079 result = (memcmp(VARDATA(arg1), VARDATA(arg2), len1) == 0);
1081 PG_FREE_IF_COPY(arg1, 0);
1082 PG_FREE_IF_COPY(arg2, 1);
1084 PG_RETURN_BOOL(result);
1088 byteane(PG_FUNCTION_ARGS)
1090 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1091 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1096 len1 = VARSIZE(arg1) - VARHDRSZ;
1097 len2 = VARSIZE(arg2) - VARHDRSZ;
1099 /* fast path for different-length inputs */
1103 result = (memcmp(VARDATA(arg1), VARDATA(arg2), len1) != 0);
1105 PG_FREE_IF_COPY(arg1, 0);
1106 PG_FREE_IF_COPY(arg2, 1);
1108 PG_RETURN_BOOL(result);
1112 bytealt(PG_FUNCTION_ARGS)
1114 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1115 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1120 len1 = VARSIZE(arg1) - VARHDRSZ;
1121 len2 = VARSIZE(arg2) - VARHDRSZ;
1123 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1125 PG_FREE_IF_COPY(arg1, 0);
1126 PG_FREE_IF_COPY(arg2, 1);
1128 PG_RETURN_BOOL((cmp < 0) || ((cmp == 0) && (len1 < len2)));
1132 byteale(PG_FUNCTION_ARGS)
1134 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1135 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1140 len1 = VARSIZE(arg1) - VARHDRSZ;
1141 len2 = VARSIZE(arg2) - VARHDRSZ;
1143 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1145 PG_FREE_IF_COPY(arg1, 0);
1146 PG_FREE_IF_COPY(arg2, 1);
1148 PG_RETURN_BOOL((cmp < 0) || ((cmp == 0) && (len1 <= len2)));
1152 byteagt(PG_FUNCTION_ARGS)
1154 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1155 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1160 len1 = VARSIZE(arg1) - VARHDRSZ;
1161 len2 = VARSIZE(arg2) - VARHDRSZ;
1163 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1165 PG_FREE_IF_COPY(arg1, 0);
1166 PG_FREE_IF_COPY(arg2, 1);
1168 PG_RETURN_BOOL((cmp > 0) || ((cmp == 0) && (len1 > len2)));
1172 byteage(PG_FUNCTION_ARGS)
1174 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1175 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1180 len1 = VARSIZE(arg1) - VARHDRSZ;
1181 len2 = VARSIZE(arg2) - VARHDRSZ;
1183 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1185 PG_FREE_IF_COPY(arg1, 0);
1186 PG_FREE_IF_COPY(arg2, 1);
1188 PG_RETURN_BOOL((cmp > 0) || ((cmp == 0) && (len1 >= len2)));
1192 byteacmp(PG_FUNCTION_ARGS)
1194 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1195 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1200 len1 = VARSIZE(arg1) - VARHDRSZ;
1201 len2 = VARSIZE(arg2) - VARHDRSZ;
1203 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1204 if ((cmp == 0) && (len1 != len2))
1205 cmp = (len1 < len2) ? -1 : 1;
1207 PG_FREE_IF_COPY(arg1, 0);
1208 PG_FREE_IF_COPY(arg2, 1);
1210 PG_RETURN_INT32(cmp);