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.80 2002/03/30 01:02:42 tgl 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
335 * Now uses faster TOAST-slicing interface
336 * - John Gray 2002-02-22
339 text_substr(PG_FUNCTION_ARGS)
342 int32 m = PG_GETARG_INT32(1);
343 int32 n = PG_GETARG_INT32(2);
355 * starting position before the start of the string? then offset into
356 * the string per SQL92 spec...
363 /* Check for m > octet length is made in TOAST access routine */
365 /* m will now become a zero-based starting position */
370 eml = pg_database_encoding_max_length ();
375 sn = (m + n) * eml + 3; /* +3 to avoid mb characters overhanging slice end */
379 string = PG_GETARG_TEXT_P_SLICE (0, sm, sn);
383 PG_RETURN_TEXT_P (string);
386 PG_RETURN_NULL(); /* notreached: suppress compiler warning */
389 len = pg_mbstrlen_with_len (VARDATA (string), sn - 3);
397 if (((m + n) > len) || (n < 0))
401 for (i = 0; i < m; i++)
403 m = p - VARDATA(string);
404 for (i = 0; i < n; i++)
406 n = p - (VARDATA(string) + m);
408 ret = (text *) palloc(VARHDRSZ + n);
409 VARATT_SIZEP(ret) = VARHDRSZ + n;
411 memcpy(VARDATA(ret), VARDATA(string) + m, n);
413 PG_RETURN_TEXT_P(ret);
419 * Return the position of the specified substring.
420 * Implements the SQL92 POSITION() function.
421 * Ref: A Guide To The SQL Standard, Date & Darwen, 1997
422 * - thomas 1997-07-27
424 * Added multi-byte support.
425 * - Tatsuo Ishii 1998-4-21
428 textpos(PG_FUNCTION_ARGS)
430 text *t1 = PG_GETARG_TEXT_P(0);
431 text *t2 = PG_GETARG_TEXT_P(1);
445 if (VARSIZE(t2) <= VARHDRSZ)
446 PG_RETURN_INT32(1); /* result for empty pattern */
448 len1 = (VARSIZE(t1) - VARHDRSZ);
449 len2 = (VARSIZE(t2) - VARHDRSZ);
451 ps1 = p1 = (pg_wchar *) palloc((len1 + 1) * sizeof(pg_wchar));
452 (void) pg_mb2wchar_with_len((unsigned char *) VARDATA(t1), p1, len1);
453 len1 = pg_wchar_strlen(p1);
454 ps2 = p2 = (pg_wchar *) palloc((len2 + 1) * sizeof(pg_wchar));
455 (void) pg_mb2wchar_with_len((unsigned char *) VARDATA(t2), p2, len2);
456 len2 = pg_wchar_strlen(p2);
463 for (p = 0; p <= px; p++)
466 if ((*p2 == *p1) && (pg_wchar_strncmp(p1, p2, len2) == 0))
468 if ((*p2 == *p1) && (strncmp(p1, p2, len2) == 0))
480 PG_RETURN_INT32(pos);
484 * Comparison function for text strings with given lengths.
485 * Includes locale support, but must copy strings to temporary memory
486 * to allow null-termination for inputs to strcoll().
490 varstr_cmp(char *arg1, int len1, char *arg2, int len2)
497 a1p = (char *) palloc(len1 + 1);
498 a2p = (char *) palloc(len2 + 1);
500 memcpy(a1p, arg1, len1);
501 *(a1p + len1) = '\0';
502 memcpy(a2p, arg2, len2);
503 *(a2p + len2) = '\0';
505 result = strcoll(a1p, a2p);
515 result = strncmp(a1p, a2p, Min(len1, len2));
516 if ((result == 0) && (len1 != len2))
517 result = (len1 < len2) ? -1 : 1;
525 * Internal comparison function for text strings.
529 text_cmp(text *arg1, text *arg2)
539 len1 = VARSIZE(arg1) - VARHDRSZ;
540 len2 = VARSIZE(arg2) - VARHDRSZ;
542 return varstr_cmp(a1p, len1, a2p, len2);
546 * Comparison functions for text strings.
548 * Note: btree indexes need these routines not to leak memory; therefore,
549 * be careful to free working copies of toasted datums. Most places don't
550 * need to be so careful.
554 texteq(PG_FUNCTION_ARGS)
556 text *arg1 = PG_GETARG_TEXT_P(0);
557 text *arg2 = PG_GETARG_TEXT_P(1);
560 /* fast path for different-length inputs */
561 if (VARSIZE(arg1) != VARSIZE(arg2))
564 result = (text_cmp(arg1, arg2) == 0);
566 PG_FREE_IF_COPY(arg1, 0);
567 PG_FREE_IF_COPY(arg2, 1);
569 PG_RETURN_BOOL(result);
573 textne(PG_FUNCTION_ARGS)
575 text *arg1 = PG_GETARG_TEXT_P(0);
576 text *arg2 = PG_GETARG_TEXT_P(1);
579 /* fast path for different-length inputs */
580 if (VARSIZE(arg1) != VARSIZE(arg2))
583 result = (text_cmp(arg1, arg2) != 0);
585 PG_FREE_IF_COPY(arg1, 0);
586 PG_FREE_IF_COPY(arg2, 1);
588 PG_RETURN_BOOL(result);
592 text_lt(PG_FUNCTION_ARGS)
594 text *arg1 = PG_GETARG_TEXT_P(0);
595 text *arg2 = PG_GETARG_TEXT_P(1);
598 result = (text_cmp(arg1, arg2) < 0);
600 PG_FREE_IF_COPY(arg1, 0);
601 PG_FREE_IF_COPY(arg2, 1);
603 PG_RETURN_BOOL(result);
607 text_le(PG_FUNCTION_ARGS)
609 text *arg1 = PG_GETARG_TEXT_P(0);
610 text *arg2 = PG_GETARG_TEXT_P(1);
613 result = (text_cmp(arg1, arg2) <= 0);
615 PG_FREE_IF_COPY(arg1, 0);
616 PG_FREE_IF_COPY(arg2, 1);
618 PG_RETURN_BOOL(result);
622 text_gt(PG_FUNCTION_ARGS)
624 text *arg1 = PG_GETARG_TEXT_P(0);
625 text *arg2 = PG_GETARG_TEXT_P(1);
628 result = (text_cmp(arg1, arg2) > 0);
630 PG_FREE_IF_COPY(arg1, 0);
631 PG_FREE_IF_COPY(arg2, 1);
633 PG_RETURN_BOOL(result);
637 text_ge(PG_FUNCTION_ARGS)
639 text *arg1 = PG_GETARG_TEXT_P(0);
640 text *arg2 = PG_GETARG_TEXT_P(1);
643 result = (text_cmp(arg1, arg2) >= 0);
645 PG_FREE_IF_COPY(arg1, 0);
646 PG_FREE_IF_COPY(arg2, 1);
648 PG_RETURN_BOOL(result);
652 bttextcmp(PG_FUNCTION_ARGS)
654 text *arg1 = PG_GETARG_TEXT_P(0);
655 text *arg2 = PG_GETARG_TEXT_P(1);
658 result = text_cmp(arg1, arg2);
660 PG_FREE_IF_COPY(arg1, 0);
661 PG_FREE_IF_COPY(arg2, 1);
663 PG_RETURN_INT32(result);
668 text_larger(PG_FUNCTION_ARGS)
670 text *arg1 = PG_GETARG_TEXT_P(0);
671 text *arg2 = PG_GETARG_TEXT_P(1);
674 result = ((text_cmp(arg1, arg2) > 0) ? arg1 : arg2);
676 PG_RETURN_TEXT_P(result);
680 text_smaller(PG_FUNCTION_ARGS)
682 text *arg1 = PG_GETARG_TEXT_P(0);
683 text *arg2 = PG_GETARG_TEXT_P(1);
686 result = ((text_cmp(arg1, arg2) < 0) ? arg1 : arg2);
688 PG_RETURN_TEXT_P(result);
691 /*-------------------------------------------------------------
694 * get the number of bytes contained in an instance of type 'bytea'
695 *-------------------------------------------------------------
698 byteaoctetlen(PG_FUNCTION_ARGS)
700 bytea *v = PG_GETARG_BYTEA_P(0);
702 PG_RETURN_INT32(VARSIZE(v) - VARHDRSZ);
707 * takes two bytea* and returns a bytea* that is the concatenation of
710 * Cloned from textcat and modified as required.
713 byteacat(PG_FUNCTION_ARGS)
715 bytea *t1 = PG_GETARG_BYTEA_P(0);
716 bytea *t2 = PG_GETARG_BYTEA_P(1);
723 len1 = (VARSIZE(t1) - VARHDRSZ);
727 len2 = (VARSIZE(t2) - VARHDRSZ);
731 len = len1 + len2 + VARHDRSZ;
732 result = (bytea *) palloc(len);
734 /* Set size of result string... */
735 VARATT_SIZEP(result) = len;
737 /* Fill data field of result string... */
738 ptr = VARDATA(result);
740 memcpy(ptr, VARDATA(t1), len1);
742 memcpy(ptr + len1, VARDATA(t2), len2);
744 PG_RETURN_BYTEA_P(result);
749 * Return a substring starting at the specified position.
750 * Cloned from text_substr and modified as required.
754 * - starting position (is one-based)
757 * If the starting position is zero or less, then return from the start of the string
758 * adjusting the length to be consistent with the "negative start" per SQL92.
759 * If the length is less than zero, return the remaining string.
763 bytea_substr(PG_FUNCTION_ARGS)
765 int32 m = PG_GETARG_INT32(1);
766 int32 n = PG_GETARG_INT32(2);
769 * starting position before the start of the string? then offset into
770 * the string per SQL92 spec...
778 /* m will now become a zero-based starting position */
781 PG_RETURN_BYTEA_P(PG_GETARG_BYTEA_P_SLICE (0, m, n));
786 * Return the position of the specified substring.
787 * Implements the SQL92 POSITION() function.
788 * Cloned from textpos and modified as required.
791 byteapos(PG_FUNCTION_ARGS)
793 bytea *t1 = PG_GETARG_BYTEA_P(0);
794 bytea *t2 = PG_GETARG_BYTEA_P(1);
803 if (VARSIZE(t2) <= VARHDRSZ)
804 PG_RETURN_INT32(1); /* result for empty pattern */
806 len1 = (VARSIZE(t1) - VARHDRSZ);
807 len2 = (VARSIZE(t2) - VARHDRSZ);
814 for (p = 0; p <= px; p++)
816 if ((*p2 == *p1) && (memcmp(p1, p2, len2) == 0))
824 PG_RETURN_INT32(pos);
827 /*-------------------------------------------------------------
830 * this routine treats "bytea" as an array of bytes.
831 * It returns the Nth byte (a number between 0 and 255).
832 *-------------------------------------------------------------
835 byteaGetByte(PG_FUNCTION_ARGS)
837 bytea *v = PG_GETARG_BYTEA_P(0);
838 int32 n = PG_GETARG_INT32(1);
842 len = VARSIZE(v) - VARHDRSZ;
844 if (n < 0 || n >= len)
845 elog(ERROR, "byteaGetByte: index %d out of range [0..%d]",
848 byte = ((unsigned char *) VARDATA(v))[n];
850 PG_RETURN_INT32(byte);
853 /*-------------------------------------------------------------
856 * This routine treats a "bytea" type like an array of bits.
857 * It returns the value of the Nth bit (0 or 1).
859 *-------------------------------------------------------------
862 byteaGetBit(PG_FUNCTION_ARGS)
864 bytea *v = PG_GETARG_BYTEA_P(0);
865 int32 n = PG_GETARG_INT32(1);
871 len = VARSIZE(v) - VARHDRSZ;
873 if (n < 0 || n >= len * 8)
874 elog(ERROR, "byteaGetBit: index %d out of range [0..%d]",
880 byte = ((unsigned char *) VARDATA(v))[byteNo];
882 if (byte & (1 << bitNo))
888 /*-------------------------------------------------------------
891 * Given an instance of type 'bytea' creates a new one with
892 * the Nth byte set to the given value.
894 *-------------------------------------------------------------
897 byteaSetByte(PG_FUNCTION_ARGS)
899 bytea *v = PG_GETARG_BYTEA_P(0);
900 int32 n = PG_GETARG_INT32(1);
901 int32 newByte = PG_GETARG_INT32(2);
905 len = VARSIZE(v) - VARHDRSZ;
907 if (n < 0 || n >= len)
908 elog(ERROR, "byteaSetByte: index %d out of range [0..%d]",
912 * Make a copy of the original varlena.
914 res = (bytea *) palloc(VARSIZE(v));
915 memcpy((char *) res, (char *) v, VARSIZE(v));
920 ((unsigned char *) VARDATA(res))[n] = newByte;
922 PG_RETURN_BYTEA_P(res);
925 /*-------------------------------------------------------------
928 * Given an instance of type 'bytea' creates a new one with
929 * the Nth bit set to the given value.
931 *-------------------------------------------------------------
934 byteaSetBit(PG_FUNCTION_ARGS)
936 bytea *v = PG_GETARG_BYTEA_P(0);
937 int32 n = PG_GETARG_INT32(1);
938 int32 newBit = PG_GETARG_INT32(2);
946 len = VARSIZE(v) - VARHDRSZ;
948 if (n < 0 || n >= len * 8)
949 elog(ERROR, "byteaSetBit: index %d out of range [0..%d]",
958 if (newBit != 0 && newBit != 1)
959 elog(ERROR, "byteaSetBit: new bit must be 0 or 1");
962 * Make a copy of the original varlena.
964 res = (bytea *) palloc(VARSIZE(v));
965 memcpy((char *) res, (char *) v, VARSIZE(v));
970 oldByte = ((unsigned char *) VARDATA(res))[byteNo];
973 newByte = oldByte & (~(1 << bitNo));
975 newByte = oldByte | (1 << bitNo);
977 ((unsigned char *) VARDATA(res))[byteNo] = newByte;
979 PG_RETURN_BYTEA_P(res);
984 * Converts a text type to a Name type.
987 text_name(PG_FUNCTION_ARGS)
989 text *s = PG_GETARG_TEXT_P(0);
993 len = VARSIZE(s) - VARHDRSZ;
995 /* Truncate oversize input */
996 if (len >= NAMEDATALEN)
997 len = NAMEDATALEN - 1;
1000 printf("text- convert string length %d (%d) ->%d\n",
1001 VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);
1004 result = (Name) palloc(NAMEDATALEN);
1005 memcpy(NameStr(*result), VARDATA(s), len);
1007 /* now null pad to full length... */
1008 while (len < NAMEDATALEN)
1010 *(NameStr(*result) + len) = '\0';
1014 PG_RETURN_NAME(result);
1018 * Converts a Name type to a text type.
1021 name_text(PG_FUNCTION_ARGS)
1023 Name s = PG_GETARG_NAME(0);
1027 len = strlen(NameStr(*s));
1030 printf("text- convert string length %d (%d) ->%d\n",
1031 VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);
1034 result = palloc(VARHDRSZ + len);
1035 VARATT_SIZEP(result) = VARHDRSZ + len;
1036 memcpy(VARDATA(result), NameStr(*s), len);
1038 PG_RETURN_TEXT_P(result);
1043 * textToQualifiedNameList - convert a text object to list of names
1045 * This implements the input parsing needed by nextval() and other
1046 * functions that take a text parameter representing a qualified name.
1047 * We split the name at dots, downcase if not double-quoted, and
1048 * truncate names if they're too long.
1050 * This is a kluge, really, and exists only for historical reasons.
1051 * A better notation for such functions would be nextval(relname).
1054 textToQualifiedNameList(text *textval, const char *caller)
1060 /* Convert to C string (handles possible detoasting). */
1061 /* Note we rely on being able to modify rawname below. */
1062 rawname = DatumGetCString(DirectFunctionCall1(textout,
1063 PointerGetDatum(textval)));
1075 /* Quoted name --- collapse quote-quote pairs, no downcasing */
1076 curname = nextp + 1;
1079 endp = strchr(nextp + 1, '\"');
1081 elog(ERROR, "%s: invalid quoted name: mismatched quotes",
1083 if (endp[1] != '\"')
1084 break; /* found end of quoted name */
1085 /* Collapse adjacent quotes into one quote, and look again */
1086 memmove(endp, endp+1, strlen(endp));
1094 elog(ERROR, "%s: invalid name syntax",
1098 elog(ERROR, "%s: invalid name syntax",
1104 /* Unquoted name --- extends to next dot */
1105 if (*nextp == '\0') /* empty name not okay here */
1106 elog(ERROR, "%s: invalid name syntax",
1109 endp = strchr(nextp, '.');
1115 elog(ERROR, "%s: invalid name syntax",
1119 nextp = nextp + strlen(nextp);
1121 * It's important that this match the identifier downcasing code
1122 * used by backend/parser/scan.l.
1124 for (cp = curname; *cp; cp++)
1126 if (isupper((unsigned char) *cp))
1127 *cp = tolower((unsigned char) *cp);
1131 /* Truncate name if it's overlength; again, should match scan.l */
1132 curlen = strlen(curname);
1133 if (curlen >= NAMEDATALEN)
1136 curlen = pg_mbcliplen(curname, curlen, NAMEDATALEN - 1);
1137 curname[curlen] = '\0';
1139 curname[NAMEDATALEN - 1] = '\0';
1144 * Finished isolating current name --- add it to list
1146 result = lappend(result, makeString(pstrdup(curname)));
1148 * Loop back if we found a dot
1158 /*****************************************************************************
1159 * Comparison Functions used for bytea
1161 * Note: btree indexes need these routines not to leak memory; therefore,
1162 * be careful to free working copies of toasted datums. Most places don't
1163 * need to be so careful.
1164 *****************************************************************************/
1167 byteaeq(PG_FUNCTION_ARGS)
1169 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1170 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1175 len1 = VARSIZE(arg1) - VARHDRSZ;
1176 len2 = VARSIZE(arg2) - VARHDRSZ;
1178 /* fast path for different-length inputs */
1182 result = (memcmp(VARDATA(arg1), VARDATA(arg2), len1) == 0);
1184 PG_FREE_IF_COPY(arg1, 0);
1185 PG_FREE_IF_COPY(arg2, 1);
1187 PG_RETURN_BOOL(result);
1191 byteane(PG_FUNCTION_ARGS)
1193 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1194 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1199 len1 = VARSIZE(arg1) - VARHDRSZ;
1200 len2 = VARSIZE(arg2) - VARHDRSZ;
1202 /* fast path for different-length inputs */
1206 result = (memcmp(VARDATA(arg1), VARDATA(arg2), len1) != 0);
1208 PG_FREE_IF_COPY(arg1, 0);
1209 PG_FREE_IF_COPY(arg2, 1);
1211 PG_RETURN_BOOL(result);
1215 bytealt(PG_FUNCTION_ARGS)
1217 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1218 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1223 len1 = VARSIZE(arg1) - VARHDRSZ;
1224 len2 = VARSIZE(arg2) - VARHDRSZ;
1226 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1228 PG_FREE_IF_COPY(arg1, 0);
1229 PG_FREE_IF_COPY(arg2, 1);
1231 PG_RETURN_BOOL((cmp < 0) || ((cmp == 0) && (len1 < len2)));
1235 byteale(PG_FUNCTION_ARGS)
1237 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1238 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1243 len1 = VARSIZE(arg1) - VARHDRSZ;
1244 len2 = VARSIZE(arg2) - VARHDRSZ;
1246 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1248 PG_FREE_IF_COPY(arg1, 0);
1249 PG_FREE_IF_COPY(arg2, 1);
1251 PG_RETURN_BOOL((cmp < 0) || ((cmp == 0) && (len1 <= len2)));
1255 byteagt(PG_FUNCTION_ARGS)
1257 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1258 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1263 len1 = VARSIZE(arg1) - VARHDRSZ;
1264 len2 = VARSIZE(arg2) - VARHDRSZ;
1266 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1268 PG_FREE_IF_COPY(arg1, 0);
1269 PG_FREE_IF_COPY(arg2, 1);
1271 PG_RETURN_BOOL((cmp > 0) || ((cmp == 0) && (len1 > len2)));
1275 byteage(PG_FUNCTION_ARGS)
1277 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1278 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1283 len1 = VARSIZE(arg1) - VARHDRSZ;
1284 len2 = VARSIZE(arg2) - VARHDRSZ;
1286 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1288 PG_FREE_IF_COPY(arg1, 0);
1289 PG_FREE_IF_COPY(arg2, 1);
1291 PG_RETURN_BOOL((cmp > 0) || ((cmp == 0) && (len1 >= len2)));
1295 byteacmp(PG_FUNCTION_ARGS)
1297 bytea *arg1 = PG_GETARG_BYTEA_P(0);
1298 bytea *arg2 = PG_GETARG_BYTEA_P(1);
1303 len1 = VARSIZE(arg1) - VARHDRSZ;
1304 len2 = VARSIZE(arg2) - VARHDRSZ;
1306 cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1307 if ((cmp == 0) && (len1 != len2))
1308 cmp = (len1 < len2) ? -1 : 1;
1310 PG_FREE_IF_COPY(arg1, 0);
1311 PG_FREE_IF_COPY(arg2, 1);
1313 PG_RETURN_INT32(cmp);