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.73 2001/09/14 17:46:40 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++)
60 else if ( (tp[0] == '\\') &&
61 (tp[1] >= '0' && tp[1] <= '3') &&
62 (tp[2] >= '0' && tp[2] <= '7') &&
63 (tp[3] >= '0' && tp[3] <= '7') )
67 else if ( (tp[0] == '\\') &&
75 * one backslash, not followed by 0 or ### valid octal
77 elog(ERROR, "Bad input string for type bytea");
82 result = (bytea *) palloc(byte);
83 result->vl_len = byte; /* set varlena length */
93 else if ( (tp[0] == '\\') &&
94 (tp[1] >= '0' && tp[1] <= '3') &&
95 (tp[2] >= '0' && tp[2] <= '7') &&
96 (tp[3] >= '0' && tp[3] <= '7') )
102 *rp++ = byte + VAL(tp[3]);
105 else if ( (tp[0] == '\\') &&
114 * We should never get here. The first pass should
117 elog(ERROR, "Bad input string for type bytea");
121 PG_RETURN_BYTEA_P(result);
125 * byteaout - converts to printable representation of byte array
127 * Non-printable characters are inserted as '\nnn' (octal) and '\' as
130 * NULL vlena should be an error--returning string with NULL for now.
133 byteaout(PG_FUNCTION_ARGS)
135 bytea *vlena = PG_GETARG_BYTEA_P(0);
139 int val; /* holds unprintable chars */
143 len = 1; /* empty string has 1 char */
145 for (i = vlena->vl_len - VARHDRSZ; i != 0; i--, vp++)
149 else if (isprint((unsigned char) *vp))
154 rp = result = (char *) palloc(len);
156 for (i = vlena->vl_len - VARHDRSZ; i != 0; i--, vp++)
163 else if (isprint((unsigned char) *vp))
169 rp[3] = DIG(val & 07);
171 rp[2] = DIG(val & 07);
173 rp[1] = DIG(val & 03);
178 PG_RETURN_CSTRING(result);
183 * textin - converts "..." to internal representation
186 textin(PG_FUNCTION_ARGS)
188 char *inputText = PG_GETARG_CSTRING(0);
195 len = strlen(inputText) + VARHDRSZ;
198 if ((ermsg = pg_verifymbstr(inputText, len - VARHDRSZ)))
199 elog(ERROR,"%s",ermsg);
202 result = (text *) palloc(len);
203 VARATT_SIZEP(result) = len;
205 memcpy(VARDATA(result), inputText, len - VARHDRSZ);
208 convertstr(VARDATA(result), len - VARHDRSZ, 0);
211 PG_RETURN_TEXT_P(result);
215 * textout - converts internal representation to "..."
218 textout(PG_FUNCTION_ARGS)
220 text *t = PG_GETARG_TEXT_P(0);
224 len = VARSIZE(t) - VARHDRSZ;
225 result = (char *) palloc(len + 1);
226 memcpy(result, VARDATA(t), len);
230 convertstr(result, len, 1);
233 PG_RETURN_CSTRING(result);
237 /* ========== PUBLIC ROUTINES ========== */
241 * returns the logical length of a text*
242 * (which is less than the VARSIZE of the text*)
245 textlen(PG_FUNCTION_ARGS)
247 text *t = PG_GETARG_TEXT_P(0);
257 l = VARSIZE(t) - VARHDRSZ;
265 PG_RETURN_INT32(len);
267 PG_RETURN_INT32(VARSIZE(t) - VARHDRSZ);
273 * returns the physical length of a text*
274 * (which is less than the VARSIZE of the text*)
276 * XXX is it actually appropriate to return the compressed length
277 * when the value is compressed? It's not at all clear to me that
278 * this is what SQL92 has in mind ...
281 textoctetlen(PG_FUNCTION_ARGS)
283 struct varattrib *t = (struct varattrib *) PG_GETARG_RAW_VARLENA_P(0);
285 if (!VARATT_IS_EXTERNAL(t))
286 PG_RETURN_INT32(VARATT_SIZE(t) - VARHDRSZ);
288 PG_RETURN_INT32(t->va_content.va_external.va_extsize);
293 * takes two text* and returns a text* that is the concatenation of
296 * Rewritten by Sapa, sapa@hq.icb.chel.su. 8-Jul-96.
297 * Updated by Thomas, Thomas.Lockhart@jpl.nasa.gov 1997-07-10.
298 * Allocate space for output in all cases.
299 * XXX - thomas 1997-07-10
302 textcat(PG_FUNCTION_ARGS)
304 text *t1 = PG_GETARG_TEXT_P(0);
305 text *t2 = PG_GETARG_TEXT_P(1);
312 len1 = (VARSIZE(t1) - VARHDRSZ);
316 len2 = (VARSIZE(t2) - VARHDRSZ);
320 len = len1 + len2 + VARHDRSZ;
321 result = (text *) palloc(len);
323 /* Set size of result string... */
324 VARATT_SIZEP(result) = len;
326 /* Fill data field of result string... */
327 ptr = VARDATA(result);
329 memcpy(ptr, VARDATA(t1), len1);
331 memcpy(ptr + len1, VARDATA(t2), len2);
333 PG_RETURN_TEXT_P(result);
338 * Return a substring starting at the specified position.
339 * - thomas 1997-12-31
343 * - starting position (is one-based)
346 * If the starting position is zero or less, then return from the start of the string
347 * adjusting the length to be consistant with the "negative start" per SQL92.
348 * If the length is less than zero, return the remaining string.
350 * Note that the arguments operate on octet length,
351 * so not aware of multi-byte character sets.
353 * Added multi-byte support.
354 * - Tatsuo Ishii 1998-4-21
355 * Changed behavior if starting position is less than one to conform to SQL92 behavior.
356 * Formerly returned the entire string; now returns a portion.
357 * - Thomas Lockhart 1998-12-10
360 text_substr(PG_FUNCTION_ARGS)
362 text *string = PG_GETARG_TEXT_P(0);
363 int32 m = PG_GETARG_INT32(1);
364 int32 n = PG_GETARG_INT32(2);
374 len = VARSIZE(string) - VARHDRSZ;
376 len = pg_mbstrlen_with_len(VARDATA(string), len);
379 /* starting position after the end of the string? */
387 * starting position before the start of the string? then offset into
388 * the string per SQL92 spec...
396 /* m will now become a zero-based starting position */
398 if (((m + n) > len) || (n < 0))
403 for (i = 0; i < m; i++)
405 m = p - VARDATA(string);
406 for (i = 0; i < n; i++)
408 n = p - (VARDATA(string) + m);
411 ret = (text *) palloc(VARHDRSZ + n);
412 VARATT_SIZEP(ret) = VARHDRSZ + n;
414 memcpy(VARDATA(ret), VARDATA(string) + m, n);
416 PG_RETURN_TEXT_P(ret);
421 * Return the position of the specified substring.
422 * Implements the SQL92 POSITION() function.
423 * Ref: A Guide To The SQL Standard, Date & Darwen, 1997
424 * - thomas 1997-07-27
426 * Added multi-byte support.
427 * - Tatsuo Ishii 1998-4-21
430 textpos(PG_FUNCTION_ARGS)
432 text *t1 = PG_GETARG_TEXT_P(0);
433 text *t2 = PG_GETARG_TEXT_P(1);
448 if (VARSIZE(t2) <= VARHDRSZ)
449 PG_RETURN_INT32(1); /* result for empty pattern */
451 len1 = (VARSIZE(t1) - VARHDRSZ);
452 len2 = (VARSIZE(t2) - VARHDRSZ);
454 ps1 = p1 = (pg_wchar *) palloc((len1 + 1) * sizeof(pg_wchar));
455 (void) pg_mb2wchar_with_len((unsigned char *) VARDATA(t1), p1, len1);
456 len1 = pg_wchar_strlen(p1);
457 ps2 = p2 = (pg_wchar *) palloc((len2 + 1) * sizeof(pg_wchar));
458 (void) pg_mb2wchar_with_len((unsigned char *) VARDATA(t2), p2, len2);
459 len2 = pg_wchar_strlen(p2);
466 for (p = 0; p <= px; p++)
469 if ((*p2 == *p1) && (pg_wchar_strncmp(p1, p2, len2) == 0))
471 if ((*p2 == *p1) && (strncmp(p1, p2, len2) == 0))
483 PG_RETURN_INT32(pos);
487 * Comparison function for text strings with given lengths.
488 * Includes locale support, but must copy strings to temporary memory
489 * to allow null-termination for inputs to strcoll().
493 varstr_cmp(char *arg1, int len1, char *arg2, int len2)
500 a1p = (char *) palloc(len1 + 1);
501 a2p = (char *) palloc(len2 + 1);
503 memcpy(a1p, arg1, len1);
504 *(a1p + len1) = '\0';
505 memcpy(a2p, arg2, len2);
506 *(a2p + len2) = '\0';
508 result = strcoll(a1p, a2p);
518 result = strncmp(a1p, a2p, Min(len1, len2));
519 if ((result == 0) && (len1 != len2))
520 result = (len1 < len2) ? -1 : 1;
528 * Internal comparison function for text strings.
532 text_cmp(text *arg1, text *arg2)
542 len1 = VARSIZE(arg1) - VARHDRSZ;
543 len2 = VARSIZE(arg2) - VARHDRSZ;
545 return varstr_cmp(a1p, len1, a2p, len2);
549 * Comparison functions for text strings.
551 * Note: btree indexes need these routines not to leak memory; therefore,
552 * be careful to free working copies of toasted datums. Most places don't
553 * need to be so careful.
557 texteq(PG_FUNCTION_ARGS)
559 text *arg1 = PG_GETARG_TEXT_P(0);
560 text *arg2 = PG_GETARG_TEXT_P(1);
563 /* fast path for different-length inputs */
564 if (VARSIZE(arg1) != VARSIZE(arg2))
567 result = (text_cmp(arg1, arg2) == 0);
569 PG_FREE_IF_COPY(arg1, 0);
570 PG_FREE_IF_COPY(arg2, 1);
572 PG_RETURN_BOOL(result);
576 textne(PG_FUNCTION_ARGS)
578 text *arg1 = PG_GETARG_TEXT_P(0);
579 text *arg2 = PG_GETARG_TEXT_P(1);
582 /* fast path for different-length inputs */
583 if (VARSIZE(arg1) != VARSIZE(arg2))
586 result = (text_cmp(arg1, arg2) != 0);
588 PG_FREE_IF_COPY(arg1, 0);
589 PG_FREE_IF_COPY(arg2, 1);
591 PG_RETURN_BOOL(result);
595 text_lt(PG_FUNCTION_ARGS)
597 text *arg1 = PG_GETARG_TEXT_P(0);
598 text *arg2 = PG_GETARG_TEXT_P(1);
601 result = (text_cmp(arg1, arg2) < 0);
603 PG_FREE_IF_COPY(arg1, 0);
604 PG_FREE_IF_COPY(arg2, 1);
606 PG_RETURN_BOOL(result);
610 text_le(PG_FUNCTION_ARGS)
612 text *arg1 = PG_GETARG_TEXT_P(0);
613 text *arg2 = PG_GETARG_TEXT_P(1);
616 result = (text_cmp(arg1, arg2) <= 0);
618 PG_FREE_IF_COPY(arg1, 0);
619 PG_FREE_IF_COPY(arg2, 1);
621 PG_RETURN_BOOL(result);
625 text_gt(PG_FUNCTION_ARGS)
627 text *arg1 = PG_GETARG_TEXT_P(0);
628 text *arg2 = PG_GETARG_TEXT_P(1);
631 result = (text_cmp(arg1, arg2) > 0);
633 PG_FREE_IF_COPY(arg1, 0);
634 PG_FREE_IF_COPY(arg2, 1);
636 PG_RETURN_BOOL(result);
640 text_ge(PG_FUNCTION_ARGS)
642 text *arg1 = PG_GETARG_TEXT_P(0);
643 text *arg2 = PG_GETARG_TEXT_P(1);
646 result = (text_cmp(arg1, arg2) >= 0);
648 PG_FREE_IF_COPY(arg1, 0);
649 PG_FREE_IF_COPY(arg2, 1);
651 PG_RETURN_BOOL(result);
655 bttextcmp(PG_FUNCTION_ARGS)
657 text *arg1 = PG_GETARG_TEXT_P(0);
658 text *arg2 = PG_GETARG_TEXT_P(1);
661 result = text_cmp(arg1, arg2);
663 PG_FREE_IF_COPY(arg1, 0);
664 PG_FREE_IF_COPY(arg2, 1);
666 PG_RETURN_INT32(result);
671 text_larger(PG_FUNCTION_ARGS)
673 text *arg1 = PG_GETARG_TEXT_P(0);
674 text *arg2 = PG_GETARG_TEXT_P(1);
677 result = ((text_cmp(arg1, arg2) > 0) ? arg1 : arg2);
679 PG_RETURN_TEXT_P(result);
683 text_smaller(PG_FUNCTION_ARGS)
685 text *arg1 = PG_GETARG_TEXT_P(0);
686 text *arg2 = PG_GETARG_TEXT_P(1);
689 result = ((text_cmp(arg1, arg2) < 0) ? arg1 : arg2);
691 PG_RETURN_TEXT_P(result);
694 /*-------------------------------------------------------------
697 * get the number of bytes contained in an instance of type 'bytea'
698 *-------------------------------------------------------------
701 byteaoctetlen(PG_FUNCTION_ARGS)
703 bytea *v = PG_GETARG_BYTEA_P(0);
705 PG_RETURN_INT32(VARSIZE(v) - VARHDRSZ);
710 * takes two bytea* and returns a bytea* that is the concatenation of
713 * Cloned from textcat and modified as required.
716 byteacat(PG_FUNCTION_ARGS)
718 bytea *t1 = PG_GETARG_BYTEA_P(0);
719 bytea *t2 = PG_GETARG_BYTEA_P(1);
726 len1 = (VARSIZE(t1) - VARHDRSZ);
730 len2 = (VARSIZE(t2) - VARHDRSZ);
734 len = len1 + len2 + VARHDRSZ;
735 result = (bytea *) palloc(len);
737 /* Set size of result string... */
738 VARATT_SIZEP(result) = len;
740 /* Fill data field of result string... */
741 ptr = VARDATA(result);
743 memcpy(ptr, VARDATA(t1), len1);
745 memcpy(ptr + len1, VARDATA(t2), len2);
747 PG_RETURN_BYTEA_P(result);
752 * Return a substring starting at the specified position.
753 * Cloned from text_substr and modified as required.
757 * - starting position (is one-based)
760 * If the starting position is zero or less, then return from the start of the string
761 * adjusting the length to be consistant with the "negative start" per SQL92.
762 * If the length is less than zero, return the remaining string.
766 bytea_substr(PG_FUNCTION_ARGS)
768 bytea *string = PG_GETARG_BYTEA_P(0);
769 int32 m = PG_GETARG_INT32(1);
770 int32 n = PG_GETARG_INT32(2);
774 len = VARSIZE(string) - VARHDRSZ;
776 /* starting position after the end of the string? */
784 * starting position before the start of the string? then offset into
785 * the string per SQL92 spec...
793 /* m will now become a zero-based starting position */
795 if (((m + n) > len) || (n < 0))
798 ret = (bytea *) palloc(VARHDRSZ + n);
799 VARATT_SIZEP(ret) = VARHDRSZ + n;
801 memcpy(VARDATA(ret), VARDATA(string) + m, n);
803 PG_RETURN_BYTEA_P(ret);
808 * Return the position of the specified substring.
809 * Implements the SQL92 POSITION() function.
810 * Cloned from textpos and modified as required.
813 byteapos(PG_FUNCTION_ARGS)
815 bytea *t1 = PG_GETARG_BYTEA_P(0);
816 bytea *t2 = PG_GETARG_BYTEA_P(1);
825 if (VARSIZE(t2) <= VARHDRSZ)
826 PG_RETURN_INT32(1); /* result for empty pattern */
828 len1 = (VARSIZE(t1) - VARHDRSZ);
829 len2 = (VARSIZE(t2) - VARHDRSZ);
836 for (p = 0; p <= px; p++)
838 if ((*p2 == *p1) && (memcmp(p1, p2, len2) == 0))
846 PG_RETURN_INT32(pos);
849 /*-------------------------------------------------------------
852 * this routine treats "bytea" as an array of bytes.
853 * It returns the Nth byte (a number between 0 and 255).
854 *-------------------------------------------------------------
857 byteaGetByte(PG_FUNCTION_ARGS)
859 bytea *v = PG_GETARG_BYTEA_P(0);
860 int32 n = PG_GETARG_INT32(1);
864 len = VARSIZE(v) - VARHDRSZ;
866 if (n < 0 || n >= len)
867 elog(ERROR, "byteaGetByte: index %d out of range [0..%d]",
870 byte = ((unsigned char *) VARDATA(v))[n];
872 PG_RETURN_INT32(byte);
875 /*-------------------------------------------------------------
878 * This routine treats a "bytea" type like an array of bits.
879 * It returns the value of the Nth bit (0 or 1).
881 *-------------------------------------------------------------
884 byteaGetBit(PG_FUNCTION_ARGS)
886 bytea *v = PG_GETARG_BYTEA_P(0);
887 int32 n = PG_GETARG_INT32(1);
893 len = VARSIZE(v) - VARHDRSZ;
895 if (n < 0 || n >= len * 8)
896 elog(ERROR, "byteaGetBit: index %d out of range [0..%d]",
902 byte = ((unsigned char *) VARDATA(v))[byteNo];
904 if (byte & (1 << bitNo))
910 /*-------------------------------------------------------------
913 * Given an instance of type 'bytea' creates a new one with
914 * the Nth byte set to the given value.
916 *-------------------------------------------------------------
919 byteaSetByte(PG_FUNCTION_ARGS)
921 bytea *v = PG_GETARG_BYTEA_P(0);
922 int32 n = PG_GETARG_INT32(1);
923 int32 newByte = PG_GETARG_INT32(2);
927 len = VARSIZE(v) - VARHDRSZ;
929 if (n < 0 || n >= len)
930 elog(ERROR, "byteaSetByte: index %d out of range [0..%d]",
934 * Make a copy of the original varlena.
936 res = (bytea *) palloc(VARSIZE(v));
937 memcpy((char *) res, (char *) v, VARSIZE(v));
942 ((unsigned char *) VARDATA(res))[n] = newByte;
944 PG_RETURN_BYTEA_P(res);
947 /*-------------------------------------------------------------
950 * Given an instance of type 'bytea' creates a new one with
951 * the Nth bit set to the given value.
953 *-------------------------------------------------------------
956 byteaSetBit(PG_FUNCTION_ARGS)
958 bytea *v = PG_GETARG_BYTEA_P(0);
959 int32 n = PG_GETARG_INT32(1);
960 int32 newBit = PG_GETARG_INT32(2);
968 len = VARSIZE(v) - VARHDRSZ;
970 if (n < 0 || n >= len * 8)
971 elog(ERROR, "byteaSetBit: index %d out of range [0..%d]",
980 if (newBit != 0 && newBit != 1)
981 elog(ERROR, "byteaSetBit: new bit must be 0 or 1");
984 * Make a copy of the original varlena.
986 res = (bytea *) palloc(VARSIZE(v));
987 memcpy((char *) res, (char *) v, VARSIZE(v));
992 oldByte = ((unsigned char *) VARDATA(res))[byteNo];
995 newByte = oldByte & (~(1 << bitNo));
997 newByte = oldByte | (1 << bitNo);
999 ((unsigned char *) VARDATA(res))[byteNo] = newByte;
1001 PG_RETURN_BYTEA_P(res);
1006 * Converts a text type to a Name type.
1009 text_name(PG_FUNCTION_ARGS)
1011 text *s = PG_GETARG_TEXT_P(0);
1015 len = VARSIZE(s) - VARHDRSZ;
1017 /* Truncate oversize input */
1018 if (len >= NAMEDATALEN)
1019 len = NAMEDATALEN - 1;
1022 printf("text- convert string length %d (%d) ->%d\n",
1023 VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);
1026 result = (Name) palloc(NAMEDATALEN);
1027 memcpy(NameStr(*result), VARDATA(s), len);
1029 /* now null pad to full length... */
1030 while (len < NAMEDATALEN)
1032 *(NameStr(*result) + len) = '\0';
1036 PG_RETURN_NAME(result);
1040 * Converts a Name type to a text type.
1043 name_text(PG_FUNCTION_ARGS)
1045 Name s = PG_GETARG_NAME(0);
1049 len = strlen(NameStr(*s));
1052 printf("text- convert string length %d (%d) ->%d\n",
1053 VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);
1056 result = palloc(VARHDRSZ + len);
1057 VARATT_SIZEP(result) = VARHDRSZ + len;
1058 memcpy(VARDATA(result), NameStr(*s), len);
1060 PG_RETURN_TEXT_P(result);
1064 /*****************************************************************************
1065 * Comparison Functions used for bytea
1067 * Note: btree indexes need these routines not to leak memory; therefore,
1068 * be careful to free working copies of toasted datums. Most places don't
1069 * need to be so careful.
1070 *****************************************************************************/
1073 byteaeq(PG_FUNCTION_ARGS)
1075 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1076 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1081 len1 = VARSIZE(arg1) - VARHDRSZ;
1082 len2 = VARSIZE(arg2) - VARHDRSZ;
1084 /* fast path for different-length inputs */
1088 result = (memcmp(VARDATA(arg1), VARDATA(arg2), len1) == 0);
1090 PG_FREE_IF_COPY(arg1, 0);
1091 PG_FREE_IF_COPY(arg2, 1);
1093 PG_RETURN_BOOL(result);
1097 byteane(PG_FUNCTION_ARGS)
1099 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1100 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1105 len1 = VARSIZE(arg1) - VARHDRSZ;
1106 len2 = VARSIZE(arg2) - VARHDRSZ;
1108 /* fast path for different-length inputs */
1112 result = (memcmp(VARDATA(arg1), VARDATA(arg2), len1) != 0);
1114 PG_FREE_IF_COPY(arg1, 0);
1115 PG_FREE_IF_COPY(arg2, 1);
1117 PG_RETURN_BOOL(result);
1121 bytealt(PG_FUNCTION_ARGS)
1123 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1124 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1129 len1 = VARSIZE(arg1) - VARHDRSZ;
1130 len2 = VARSIZE(arg2) - VARHDRSZ;
1132 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1134 PG_FREE_IF_COPY(arg1, 0);
1135 PG_FREE_IF_COPY(arg2, 1);
1137 PG_RETURN_BOOL((cmp < 0) || ((cmp == 0) && (len1 < len2)));
1141 byteale(PG_FUNCTION_ARGS)
1143 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1144 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1149 len1 = VARSIZE(arg1) - VARHDRSZ;
1150 len2 = VARSIZE(arg2) - VARHDRSZ;
1152 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1154 PG_FREE_IF_COPY(arg1, 0);
1155 PG_FREE_IF_COPY(arg2, 1);
1157 PG_RETURN_BOOL((cmp < 0) || ((cmp == 0) && (len1 <= len2)));
1161 byteagt(PG_FUNCTION_ARGS)
1163 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1164 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1169 len1 = VARSIZE(arg1) - VARHDRSZ;
1170 len2 = VARSIZE(arg2) - VARHDRSZ;
1172 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1174 PG_FREE_IF_COPY(arg1, 0);
1175 PG_FREE_IF_COPY(arg2, 1);
1177 PG_RETURN_BOOL((cmp > 0) || ((cmp == 0) && (len1 > len2)));
1181 byteage(PG_FUNCTION_ARGS)
1183 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1184 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1189 len1 = VARSIZE(arg1) - VARHDRSZ;
1190 len2 = VARSIZE(arg2) - VARHDRSZ;
1192 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1194 PG_FREE_IF_COPY(arg1, 0);
1195 PG_FREE_IF_COPY(arg2, 1);
1197 PG_RETURN_BOOL((cmp > 0) || ((cmp == 0) && (len1 >= len2)));
1201 byteacmp(PG_FUNCTION_ARGS)
1203 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1204 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1209 len1 = VARSIZE(arg1) - VARHDRSZ;
1210 len2 = VARSIZE(arg2) - VARHDRSZ;
1212 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1213 if ((cmp == 0) && (len1 != len2))
1214 cmp = (len1 < len2) ? -1 : 1;
1216 PG_FREE_IF_COPY(arg1, 0);
1217 PG_FREE_IF_COPY(arg2, 1);
1219 PG_RETURN_INT32(cmp);