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.78 2001/11/19 19:15:07 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);
243 /* optimization for single byte encoding */
244 if (pg_database_encoding_max_length() <= 1)
245 PG_RETURN_INT32(VARSIZE(t) - VARHDRSZ);
248 pg_mbstrlen_with_len(VARDATA(t), VARSIZE(t) - VARHDRSZ)
251 PG_RETURN_INT32(VARSIZE(t) - VARHDRSZ);
257 * returns the physical length of a text*
258 * (which is less than the VARSIZE of the text*)
261 textoctetlen(PG_FUNCTION_ARGS)
263 text *arg = PG_GETARG_TEXT_P(0);
265 PG_RETURN_INT32(VARSIZE(arg) - VARHDRSZ);
270 * takes two text* and returns a text* that is the concatenation of
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
279 textcat(PG_FUNCTION_ARGS)
281 text *t1 = PG_GETARG_TEXT_P(0);
282 text *t2 = PG_GETARG_TEXT_P(1);
289 len1 = (VARSIZE(t1) - VARHDRSZ);
293 len2 = (VARSIZE(t2) - VARHDRSZ);
297 len = len1 + len2 + VARHDRSZ;
298 result = (text *) palloc(len);
300 /* Set size of result string... */
301 VARATT_SIZEP(result) = len;
303 /* Fill data field of result string... */
304 ptr = VARDATA(result);
306 memcpy(ptr, VARDATA(t1), len1);
308 memcpy(ptr + len1, VARDATA(t2), len2);
310 PG_RETURN_TEXT_P(result);
315 * Return a substring starting at the specified position.
316 * - thomas 1997-12-31
320 * - starting position (is one-based)
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.
327 * Note that the arguments operate on octet length,
328 * so not aware of multi-byte character sets.
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
337 text_substr(PG_FUNCTION_ARGS)
339 text *string = PG_GETARG_TEXT_P(0);
340 int32 m = PG_GETARG_INT32(1);
341 int32 n = PG_GETARG_INT32(2);
350 len = VARSIZE(string) - VARHDRSZ;
352 len = pg_mbstrlen_with_len(VARDATA(string), len);
355 /* starting position after the end of the string? */
363 * starting position before the start of the string? then offset into
364 * the string per SQL92 spec...
372 /* m will now become a zero-based starting position */
374 if (((m + n) > len) || (n < 0))
379 for (i = 0; i < m; i++)
381 m = p - VARDATA(string);
382 for (i = 0; i < n; i++)
384 n = p - (VARDATA(string) + m);
387 ret = (text *) palloc(VARHDRSZ + n);
388 VARATT_SIZEP(ret) = VARHDRSZ + n;
390 memcpy(VARDATA(ret), VARDATA(string) + m, n);
392 PG_RETURN_TEXT_P(ret);
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
402 * Added multi-byte support.
403 * - Tatsuo Ishii 1998-4-21
406 textpos(PG_FUNCTION_ARGS)
408 text *t1 = PG_GETARG_TEXT_P(0);
409 text *t2 = PG_GETARG_TEXT_P(1);
423 if (VARSIZE(t2) <= VARHDRSZ)
424 PG_RETURN_INT32(1); /* result for empty pattern */
426 len1 = (VARSIZE(t1) - VARHDRSZ);
427 len2 = (VARSIZE(t2) - VARHDRSZ);
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);
441 for (p = 0; p <= px; p++)
444 if ((*p2 == *p1) && (pg_wchar_strncmp(p1, p2, len2) == 0))
446 if ((*p2 == *p1) && (strncmp(p1, p2, len2) == 0))
458 PG_RETURN_INT32(pos);
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().
468 varstr_cmp(char *arg1, int len1, char *arg2, int len2)
475 a1p = (char *) palloc(len1 + 1);
476 a2p = (char *) palloc(len2 + 1);
478 memcpy(a1p, arg1, len1);
479 *(a1p + len1) = '\0';
480 memcpy(a2p, arg2, len2);
481 *(a2p + len2) = '\0';
483 result = strcoll(a1p, a2p);
493 result = strncmp(a1p, a2p, Min(len1, len2));
494 if ((result == 0) && (len1 != len2))
495 result = (len1 < len2) ? -1 : 1;
503 * Internal comparison function for text strings.
507 text_cmp(text *arg1, text *arg2)
517 len1 = VARSIZE(arg1) - VARHDRSZ;
518 len2 = VARSIZE(arg2) - VARHDRSZ;
520 return varstr_cmp(a1p, len1, a2p, len2);
524 * Comparison functions for text strings.
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.
532 texteq(PG_FUNCTION_ARGS)
534 text *arg1 = PG_GETARG_TEXT_P(0);
535 text *arg2 = PG_GETARG_TEXT_P(1);
538 /* fast path for different-length inputs */
539 if (VARSIZE(arg1) != VARSIZE(arg2))
542 result = (text_cmp(arg1, arg2) == 0);
544 PG_FREE_IF_COPY(arg1, 0);
545 PG_FREE_IF_COPY(arg2, 1);
547 PG_RETURN_BOOL(result);
551 textne(PG_FUNCTION_ARGS)
553 text *arg1 = PG_GETARG_TEXT_P(0);
554 text *arg2 = PG_GETARG_TEXT_P(1);
557 /* fast path for different-length inputs */
558 if (VARSIZE(arg1) != VARSIZE(arg2))
561 result = (text_cmp(arg1, arg2) != 0);
563 PG_FREE_IF_COPY(arg1, 0);
564 PG_FREE_IF_COPY(arg2, 1);
566 PG_RETURN_BOOL(result);
570 text_lt(PG_FUNCTION_ARGS)
572 text *arg1 = PG_GETARG_TEXT_P(0);
573 text *arg2 = PG_GETARG_TEXT_P(1);
576 result = (text_cmp(arg1, arg2) < 0);
578 PG_FREE_IF_COPY(arg1, 0);
579 PG_FREE_IF_COPY(arg2, 1);
581 PG_RETURN_BOOL(result);
585 text_le(PG_FUNCTION_ARGS)
587 text *arg1 = PG_GETARG_TEXT_P(0);
588 text *arg2 = PG_GETARG_TEXT_P(1);
591 result = (text_cmp(arg1, arg2) <= 0);
593 PG_FREE_IF_COPY(arg1, 0);
594 PG_FREE_IF_COPY(arg2, 1);
596 PG_RETURN_BOOL(result);
600 text_gt(PG_FUNCTION_ARGS)
602 text *arg1 = PG_GETARG_TEXT_P(0);
603 text *arg2 = PG_GETARG_TEXT_P(1);
606 result = (text_cmp(arg1, arg2) > 0);
608 PG_FREE_IF_COPY(arg1, 0);
609 PG_FREE_IF_COPY(arg2, 1);
611 PG_RETURN_BOOL(result);
615 text_ge(PG_FUNCTION_ARGS)
617 text *arg1 = PG_GETARG_TEXT_P(0);
618 text *arg2 = PG_GETARG_TEXT_P(1);
621 result = (text_cmp(arg1, arg2) >= 0);
623 PG_FREE_IF_COPY(arg1, 0);
624 PG_FREE_IF_COPY(arg2, 1);
626 PG_RETURN_BOOL(result);
630 bttextcmp(PG_FUNCTION_ARGS)
632 text *arg1 = PG_GETARG_TEXT_P(0);
633 text *arg2 = PG_GETARG_TEXT_P(1);
636 result = text_cmp(arg1, arg2);
638 PG_FREE_IF_COPY(arg1, 0);
639 PG_FREE_IF_COPY(arg2, 1);
641 PG_RETURN_INT32(result);
646 text_larger(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) > 0) ? arg1 : arg2);
654 PG_RETURN_TEXT_P(result);
658 text_smaller(PG_FUNCTION_ARGS)
660 text *arg1 = PG_GETARG_TEXT_P(0);
661 text *arg2 = PG_GETARG_TEXT_P(1);
664 result = ((text_cmp(arg1, arg2) < 0) ? arg1 : arg2);
666 PG_RETURN_TEXT_P(result);
669 /*-------------------------------------------------------------
672 * get the number of bytes contained in an instance of type 'bytea'
673 *-------------------------------------------------------------
676 byteaoctetlen(PG_FUNCTION_ARGS)
678 bytea *v = PG_GETARG_BYTEA_P(0);
680 PG_RETURN_INT32(VARSIZE(v) - VARHDRSZ);
685 * takes two bytea* and returns a bytea* that is the concatenation of
688 * Cloned from textcat and modified as required.
691 byteacat(PG_FUNCTION_ARGS)
693 bytea *t1 = PG_GETARG_BYTEA_P(0);
694 bytea *t2 = PG_GETARG_BYTEA_P(1);
701 len1 = (VARSIZE(t1) - VARHDRSZ);
705 len2 = (VARSIZE(t2) - VARHDRSZ);
709 len = len1 + len2 + VARHDRSZ;
710 result = (bytea *) palloc(len);
712 /* Set size of result string... */
713 VARATT_SIZEP(result) = len;
715 /* Fill data field of result string... */
716 ptr = VARDATA(result);
718 memcpy(ptr, VARDATA(t1), len1);
720 memcpy(ptr + len1, VARDATA(t2), len2);
722 PG_RETURN_BYTEA_P(result);
727 * Return a substring starting at the specified position.
728 * Cloned from text_substr and modified as required.
732 * - starting position (is one-based)
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.
741 bytea_substr(PG_FUNCTION_ARGS)
743 bytea *string = PG_GETARG_BYTEA_P(0);
744 int32 m = PG_GETARG_INT32(1);
745 int32 n = PG_GETARG_INT32(2);
749 len = VARSIZE(string) - VARHDRSZ;
751 /* starting position after the end of the string? */
759 * starting position before the start of the string? then offset into
760 * the string per SQL92 spec...
768 /* m will now become a zero-based starting position */
770 if (((m + n) > len) || (n < 0))
773 ret = (bytea *) palloc(VARHDRSZ + n);
774 VARATT_SIZEP(ret) = VARHDRSZ + n;
776 memcpy(VARDATA(ret), VARDATA(string) + m, n);
778 PG_RETURN_BYTEA_P(ret);
783 * Return the position of the specified substring.
784 * Implements the SQL92 POSITION() function.
785 * Cloned from textpos and modified as required.
788 byteapos(PG_FUNCTION_ARGS)
790 bytea *t1 = PG_GETARG_BYTEA_P(0);
791 bytea *t2 = PG_GETARG_BYTEA_P(1);
800 if (VARSIZE(t2) <= VARHDRSZ)
801 PG_RETURN_INT32(1); /* result for empty pattern */
803 len1 = (VARSIZE(t1) - VARHDRSZ);
804 len2 = (VARSIZE(t2) - VARHDRSZ);
811 for (p = 0; p <= px; p++)
813 if ((*p2 == *p1) && (memcmp(p1, p2, len2) == 0))
821 PG_RETURN_INT32(pos);
824 /*-------------------------------------------------------------
827 * this routine treats "bytea" as an array of bytes.
828 * It returns the Nth byte (a number between 0 and 255).
829 *-------------------------------------------------------------
832 byteaGetByte(PG_FUNCTION_ARGS)
834 bytea *v = PG_GETARG_BYTEA_P(0);
835 int32 n = PG_GETARG_INT32(1);
839 len = VARSIZE(v) - VARHDRSZ;
841 if (n < 0 || n >= len)
842 elog(ERROR, "byteaGetByte: index %d out of range [0..%d]",
845 byte = ((unsigned char *) VARDATA(v))[n];
847 PG_RETURN_INT32(byte);
850 /*-------------------------------------------------------------
853 * This routine treats a "bytea" type like an array of bits.
854 * It returns the value of the Nth bit (0 or 1).
856 *-------------------------------------------------------------
859 byteaGetBit(PG_FUNCTION_ARGS)
861 bytea *v = PG_GETARG_BYTEA_P(0);
862 int32 n = PG_GETARG_INT32(1);
868 len = VARSIZE(v) - VARHDRSZ;
870 if (n < 0 || n >= len * 8)
871 elog(ERROR, "byteaGetBit: index %d out of range [0..%d]",
877 byte = ((unsigned char *) VARDATA(v))[byteNo];
879 if (byte & (1 << bitNo))
885 /*-------------------------------------------------------------
888 * Given an instance of type 'bytea' creates a new one with
889 * the Nth byte set to the given value.
891 *-------------------------------------------------------------
894 byteaSetByte(PG_FUNCTION_ARGS)
896 bytea *v = PG_GETARG_BYTEA_P(0);
897 int32 n = PG_GETARG_INT32(1);
898 int32 newByte = PG_GETARG_INT32(2);
902 len = VARSIZE(v) - VARHDRSZ;
904 if (n < 0 || n >= len)
905 elog(ERROR, "byteaSetByte: index %d out of range [0..%d]",
909 * Make a copy of the original varlena.
911 res = (bytea *) palloc(VARSIZE(v));
912 memcpy((char *) res, (char *) v, VARSIZE(v));
917 ((unsigned char *) VARDATA(res))[n] = newByte;
919 PG_RETURN_BYTEA_P(res);
922 /*-------------------------------------------------------------
925 * Given an instance of type 'bytea' creates a new one with
926 * the Nth bit set to the given value.
928 *-------------------------------------------------------------
931 byteaSetBit(PG_FUNCTION_ARGS)
933 bytea *v = PG_GETARG_BYTEA_P(0);
934 int32 n = PG_GETARG_INT32(1);
935 int32 newBit = PG_GETARG_INT32(2);
943 len = VARSIZE(v) - VARHDRSZ;
945 if (n < 0 || n >= len * 8)
946 elog(ERROR, "byteaSetBit: index %d out of range [0..%d]",
955 if (newBit != 0 && newBit != 1)
956 elog(ERROR, "byteaSetBit: new bit must be 0 or 1");
959 * Make a copy of the original varlena.
961 res = (bytea *) palloc(VARSIZE(v));
962 memcpy((char *) res, (char *) v, VARSIZE(v));
967 oldByte = ((unsigned char *) VARDATA(res))[byteNo];
970 newByte = oldByte & (~(1 << bitNo));
972 newByte = oldByte | (1 << bitNo);
974 ((unsigned char *) VARDATA(res))[byteNo] = newByte;
976 PG_RETURN_BYTEA_P(res);
981 * Converts a text type to a Name type.
984 text_name(PG_FUNCTION_ARGS)
986 text *s = PG_GETARG_TEXT_P(0);
990 len = VARSIZE(s) - VARHDRSZ;
992 /* Truncate oversize input */
993 if (len >= NAMEDATALEN)
994 len = NAMEDATALEN - 1;
997 printf("text- convert string length %d (%d) ->%d\n",
998 VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);
1001 result = (Name) palloc(NAMEDATALEN);
1002 memcpy(NameStr(*result), VARDATA(s), len);
1004 /* now null pad to full length... */
1005 while (len < NAMEDATALEN)
1007 *(NameStr(*result) + len) = '\0';
1011 PG_RETURN_NAME(result);
1015 * Converts a Name type to a text type.
1018 name_text(PG_FUNCTION_ARGS)
1020 Name s = PG_GETARG_NAME(0);
1024 len = strlen(NameStr(*s));
1027 printf("text- convert string length %d (%d) ->%d\n",
1028 VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);
1031 result = palloc(VARHDRSZ + len);
1032 VARATT_SIZEP(result) = VARHDRSZ + len;
1033 memcpy(VARDATA(result), NameStr(*s), len);
1035 PG_RETURN_TEXT_P(result);
1039 /*****************************************************************************
1040 * Comparison Functions used for bytea
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 *****************************************************************************/
1048 byteaeq(PG_FUNCTION_ARGS)
1050 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1051 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1056 len1 = VARSIZE(arg1) - VARHDRSZ;
1057 len2 = VARSIZE(arg2) - VARHDRSZ;
1059 /* fast path for different-length inputs */
1063 result = (memcmp(VARDATA(arg1), VARDATA(arg2), len1) == 0);
1065 PG_FREE_IF_COPY(arg1, 0);
1066 PG_FREE_IF_COPY(arg2, 1);
1068 PG_RETURN_BOOL(result);
1072 byteane(PG_FUNCTION_ARGS)
1074 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1075 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1080 len1 = VARSIZE(arg1) - VARHDRSZ;
1081 len2 = VARSIZE(arg2) - VARHDRSZ;
1083 /* fast path for different-length inputs */
1087 result = (memcmp(VARDATA(arg1), VARDATA(arg2), len1) != 0);
1089 PG_FREE_IF_COPY(arg1, 0);
1090 PG_FREE_IF_COPY(arg2, 1);
1092 PG_RETURN_BOOL(result);
1096 bytealt(PG_FUNCTION_ARGS)
1098 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1099 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1104 len1 = VARSIZE(arg1) - VARHDRSZ;
1105 len2 = VARSIZE(arg2) - VARHDRSZ;
1107 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1109 PG_FREE_IF_COPY(arg1, 0);
1110 PG_FREE_IF_COPY(arg2, 1);
1112 PG_RETURN_BOOL((cmp < 0) || ((cmp == 0) && (len1 < len2)));
1116 byteale(PG_FUNCTION_ARGS)
1118 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1119 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1124 len1 = VARSIZE(arg1) - VARHDRSZ;
1125 len2 = VARSIZE(arg2) - VARHDRSZ;
1127 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1129 PG_FREE_IF_COPY(arg1, 0);
1130 PG_FREE_IF_COPY(arg2, 1);
1132 PG_RETURN_BOOL((cmp < 0) || ((cmp == 0) && (len1 <= len2)));
1136 byteagt(PG_FUNCTION_ARGS)
1138 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1139 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1144 len1 = VARSIZE(arg1) - VARHDRSZ;
1145 len2 = VARSIZE(arg2) - VARHDRSZ;
1147 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1149 PG_FREE_IF_COPY(arg1, 0);
1150 PG_FREE_IF_COPY(arg2, 1);
1152 PG_RETURN_BOOL((cmp > 0) || ((cmp == 0) && (len1 > len2)));
1156 byteage(PG_FUNCTION_ARGS)
1158 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1159 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1164 len1 = VARSIZE(arg1) - VARHDRSZ;
1165 len2 = VARSIZE(arg2) - VARHDRSZ;
1167 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1169 PG_FREE_IF_COPY(arg1, 0);
1170 PG_FREE_IF_COPY(arg2, 1);
1172 PG_RETURN_BOOL((cmp > 0) || ((cmp == 0) && (len1 >= len2)));
1176 byteacmp(PG_FUNCTION_ARGS)
1178 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1179 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1184 len1 = VARSIZE(arg1) - VARHDRSZ;
1185 len2 = VARSIZE(arg2) - VARHDRSZ;
1187 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1188 if ((cmp == 0) && (len1 != len2))
1189 cmp = (len1 < len2) ? -1 : 1;
1191 PG_FREE_IF_COPY(arg1, 0);
1192 PG_FREE_IF_COPY(arg2, 1);
1194 PG_RETURN_INT32(cmp);