Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * bytea.c
4 : * Functions for the bytea type.
5 : *
6 : * Portions Copyright (c) 2025, PostgreSQL Global Development Group
7 : *
8 : *
9 : * IDENTIFICATION
10 : * src/backend/utils/adt/bytea.c
11 : *
12 : *-------------------------------------------------------------------------
13 : */
14 :
15 : #include "postgres.h"
16 :
17 : #include "access/detoast.h"
18 : #include "catalog/pg_collation_d.h"
19 : #include "catalog/pg_type_d.h"
20 : #include "common/int.h"
21 : #include "fmgr.h"
22 : #include "libpq/pqformat.h"
23 : #include "port/pg_bitutils.h"
24 : #include "utils/builtins.h"
25 : #include "utils/bytea.h"
26 : #include "utils/fmgrprotos.h"
27 : #include "utils/memutils.h"
28 : #include "utils/sortsupport.h"
29 : #include "utils/varlena.h"
30 : #include "varatt.h"
31 :
32 : /* GUC variable */
33 : int bytea_output = BYTEA_OUTPUT_HEX;
34 :
35 : static bytea *bytea_catenate(bytea *t1, bytea *t2);
36 : static bytea *bytea_substring(Datum str, int S, int L,
37 : bool length_not_specified);
38 : static bytea *bytea_overlay(bytea *t1, bytea *t2, int sp, int sl);
39 :
40 : /*
41 : * bytea_catenate
42 : * Guts of byteacat(), broken out so it can be used by other functions
43 : *
44 : * Arguments can be in short-header form, but not compressed or out-of-line
45 : */
46 : static bytea *
47 1558 : bytea_catenate(bytea *t1, bytea *t2)
48 : {
49 : bytea *result;
50 : int len1,
51 : len2,
52 : len;
53 : char *ptr;
54 :
55 1558 : len1 = VARSIZE_ANY_EXHDR(t1);
56 1558 : len2 = VARSIZE_ANY_EXHDR(t2);
57 :
58 : /* paranoia ... probably should throw error instead? */
59 1558 : if (len1 < 0)
60 0 : len1 = 0;
61 1558 : if (len2 < 0)
62 0 : len2 = 0;
63 :
64 1558 : len = len1 + len2 + VARHDRSZ;
65 1558 : result = (bytea *) palloc(len);
66 :
67 : /* Set size of result string... */
68 1558 : SET_VARSIZE(result, len);
69 :
70 : /* Fill data field of result string... */
71 1558 : ptr = VARDATA(result);
72 1558 : if (len1 > 0)
73 1558 : memcpy(ptr, VARDATA_ANY(t1), len1);
74 1558 : if (len2 > 0)
75 1540 : memcpy(ptr + len1, VARDATA_ANY(t2), len2);
76 :
77 1558 : return result;
78 : }
79 :
80 : #define PG_STR_GET_BYTEA(str_) \
81 : DatumGetByteaPP(DirectFunctionCall1(byteain, CStringGetDatum(str_)))
82 :
83 : static bytea *
84 4058 : bytea_substring(Datum str,
85 : int S,
86 : int L,
87 : bool length_not_specified)
88 : {
89 : int32 S1; /* adjusted start position */
90 : int32 L1; /* adjusted substring length */
91 : int32 E; /* end position */
92 :
93 : /*
94 : * The logic here should generally match text_substring().
95 : */
96 4058 : S1 = Max(S, 1);
97 :
98 4058 : if (length_not_specified)
99 : {
100 : /*
101 : * Not passed a length - DatumGetByteaPSlice() grabs everything to the
102 : * end of the string if we pass it a negative value for length.
103 : */
104 3954 : L1 = -1;
105 : }
106 104 : else if (L < 0)
107 : {
108 : /* SQL99 says to throw an error for E < S, i.e., negative length */
109 12 : ereport(ERROR,
110 : (errcode(ERRCODE_SUBSTRING_ERROR),
111 : errmsg("negative substring length not allowed")));
112 : L1 = -1; /* silence stupider compilers */
113 : }
114 92 : else if (pg_add_s32_overflow(S, L, &E))
115 : {
116 : /*
117 : * L could be large enough for S + L to overflow, in which case the
118 : * substring must run to end of string.
119 : */
120 6 : L1 = -1;
121 : }
122 : else
123 : {
124 : /*
125 : * A zero or negative value for the end position can happen if the
126 : * start was negative or one. SQL99 says to return a zero-length
127 : * string.
128 : */
129 86 : if (E < 1)
130 0 : return PG_STR_GET_BYTEA("");
131 :
132 86 : L1 = E - S1;
133 : }
134 :
135 : /*
136 : * If the start position is past the end of the string, SQL99 says to
137 : * return a zero-length string -- DatumGetByteaPSlice() will do that for
138 : * us. We need only convert S1 to zero-based starting position.
139 : */
140 4046 : return DatumGetByteaPSlice(str, S1 - 1, L1);
141 : }
142 :
143 : static bytea *
144 18 : bytea_overlay(bytea *t1, bytea *t2, int sp, int sl)
145 : {
146 : bytea *result;
147 : bytea *s1;
148 : bytea *s2;
149 : int sp_pl_sl;
150 :
151 : /*
152 : * Check for possible integer-overflow cases. For negative sp, throw a
153 : * "substring length" error because that's what should be expected
154 : * according to the spec's definition of OVERLAY().
155 : */
156 18 : if (sp <= 0)
157 0 : ereport(ERROR,
158 : (errcode(ERRCODE_SUBSTRING_ERROR),
159 : errmsg("negative substring length not allowed")));
160 18 : if (pg_add_s32_overflow(sp, sl, &sp_pl_sl))
161 0 : ereport(ERROR,
162 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
163 : errmsg("integer out of range")));
164 :
165 18 : s1 = bytea_substring(PointerGetDatum(t1), 1, sp - 1, false);
166 18 : s2 = bytea_substring(PointerGetDatum(t1), sp_pl_sl, -1, true);
167 18 : result = bytea_catenate(s1, t2);
168 18 : result = bytea_catenate(result, s2);
169 :
170 18 : return result;
171 : }
172 :
173 : /*****************************************************************************
174 : * USER I/O ROUTINES *
175 : *****************************************************************************/
176 :
177 : #define VAL(CH) ((CH) - '0')
178 : #define DIG(VAL) ((VAL) + '0')
179 :
180 : /*
181 : * byteain - converts from printable representation of byte array
182 : *
183 : * Non-printable characters must be passed as '\nnn' (octal) and are
184 : * converted to internal form. '\' must be passed as '\\'.
185 : */
186 : Datum
187 1387828 : byteain(PG_FUNCTION_ARGS)
188 : {
189 1387828 : char *inputText = PG_GETARG_CSTRING(0);
190 1387828 : Node *escontext = fcinfo->context;
191 1387828 : size_t len = strlen(inputText);
192 : size_t bc;
193 : char *tp;
194 : char *rp;
195 : bytea *result;
196 :
197 : /* Recognize hex input */
198 1387828 : if (inputText[0] == '\\' && inputText[1] == 'x')
199 : {
200 112244 : bc = (len - 2) / 2 + VARHDRSZ; /* maximum possible length */
201 112244 : result = palloc(bc);
202 112244 : bc = hex_decode_safe(inputText + 2, len - 2, VARDATA(result),
203 : escontext);
204 112232 : SET_VARSIZE(result, bc + VARHDRSZ); /* actual length */
205 :
206 112232 : PG_RETURN_BYTEA_P(result);
207 : }
208 :
209 : /* Else, it's the traditional escaped style */
210 1275584 : result = (bytea *) palloc(len + VARHDRSZ); /* maximum possible length */
211 :
212 1275584 : tp = inputText;
213 1275584 : rp = VARDATA(result);
214 9570618 : while (*tp != '\0')
215 : {
216 8295046 : if (tp[0] != '\\')
217 8294102 : *rp++ = *tp++;
218 944 : else if ((tp[1] >= '0' && tp[1] <= '3') &&
219 920 : (tp[2] >= '0' && tp[2] <= '7') &&
220 920 : (tp[3] >= '0' && tp[3] <= '7'))
221 920 : {
222 : int v;
223 :
224 920 : v = VAL(tp[1]);
225 920 : v <<= 3;
226 920 : v += VAL(tp[2]);
227 920 : v <<= 3;
228 920 : *rp++ = v + VAL(tp[3]);
229 :
230 920 : tp += 4;
231 : }
232 24 : else if (tp[1] == '\\')
233 : {
234 12 : *rp++ = '\\';
235 12 : tp += 2;
236 : }
237 : else
238 : {
239 : /*
240 : * one backslash, not followed by another or ### valid octal
241 : */
242 12 : ereturn(escontext, (Datum) 0,
243 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
244 : errmsg("invalid input syntax for type %s", "bytea")));
245 : }
246 : }
247 :
248 1275572 : bc = rp - VARDATA(result); /* actual length */
249 1275572 : SET_VARSIZE(result, bc + VARHDRSZ);
250 :
251 1275572 : PG_RETURN_BYTEA_P(result);
252 : }
253 :
254 : /*
255 : * byteaout - converts to printable representation of byte array
256 : *
257 : * In the traditional escaped format, non-printable characters are
258 : * printed as '\nnn' (octal) and '\' as '\\'.
259 : */
260 : Datum
261 562130 : byteaout(PG_FUNCTION_ARGS)
262 : {
263 562130 : bytea *vlena = PG_GETARG_BYTEA_PP(0);
264 : char *result;
265 : char *rp;
266 :
267 562130 : if (bytea_output == BYTEA_OUTPUT_HEX)
268 : {
269 : /* Print hex format */
270 561740 : rp = result = palloc(VARSIZE_ANY_EXHDR(vlena) * 2 + 2 + 1);
271 561740 : *rp++ = '\\';
272 561740 : *rp++ = 'x';
273 561740 : rp += hex_encode(VARDATA_ANY(vlena), VARSIZE_ANY_EXHDR(vlena), rp);
274 : }
275 390 : else if (bytea_output == BYTEA_OUTPUT_ESCAPE)
276 : {
277 : /* Print traditional escaped format */
278 : char *vp;
279 : uint64 len;
280 : int i;
281 :
282 390 : len = 1; /* empty string has 1 char */
283 390 : vp = VARDATA_ANY(vlena);
284 217720 : for (i = VARSIZE_ANY_EXHDR(vlena); i != 0; i--, vp++)
285 : {
286 217330 : if (*vp == '\\')
287 6 : len += 2;
288 217324 : else if ((unsigned char) *vp < 0x20 || (unsigned char) *vp > 0x7e)
289 498 : len += 4;
290 : else
291 216826 : len++;
292 : }
293 :
294 : /*
295 : * In principle len can't overflow uint32 if the input fit in 1GB, but
296 : * for safety let's check rather than relying on palloc's internal
297 : * check.
298 : */
299 390 : if (len > MaxAllocSize)
300 0 : ereport(ERROR,
301 : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
302 : errmsg_internal("result of bytea output conversion is too large")));
303 390 : rp = result = (char *) palloc(len);
304 :
305 390 : vp = VARDATA_ANY(vlena);
306 217720 : for (i = VARSIZE_ANY_EXHDR(vlena); i != 0; i--, vp++)
307 : {
308 217330 : if (*vp == '\\')
309 : {
310 6 : *rp++ = '\\';
311 6 : *rp++ = '\\';
312 : }
313 217324 : else if ((unsigned char) *vp < 0x20 || (unsigned char) *vp > 0x7e)
314 498 : {
315 : int val; /* holds unprintable chars */
316 :
317 498 : val = *vp;
318 498 : rp[0] = '\\';
319 498 : rp[3] = DIG(val & 07);
320 498 : val >>= 3;
321 498 : rp[2] = DIG(val & 07);
322 498 : val >>= 3;
323 498 : rp[1] = DIG(val & 03);
324 498 : rp += 4;
325 : }
326 : else
327 216826 : *rp++ = *vp;
328 : }
329 : }
330 : else
331 : {
332 0 : elog(ERROR, "unrecognized \"bytea_output\" setting: %d",
333 : bytea_output);
334 : rp = result = NULL; /* keep compiler quiet */
335 : }
336 562130 : *rp = '\0';
337 562130 : PG_RETURN_CSTRING(result);
338 : }
339 :
340 : /*
341 : * bytearecv - converts external binary format to bytea
342 : */
343 : Datum
344 107714 : bytearecv(PG_FUNCTION_ARGS)
345 : {
346 107714 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
347 : bytea *result;
348 : int nbytes;
349 :
350 107714 : nbytes = buf->len - buf->cursor;
351 107714 : result = (bytea *) palloc(nbytes + VARHDRSZ);
352 107714 : SET_VARSIZE(result, nbytes + VARHDRSZ);
353 107714 : pq_copymsgbytes(buf, VARDATA(result), nbytes);
354 107714 : PG_RETURN_BYTEA_P(result);
355 : }
356 :
357 : /*
358 : * byteasend - converts bytea to binary format
359 : *
360 : * This is a special case: just copy the input...
361 : */
362 : Datum
363 69042 : byteasend(PG_FUNCTION_ARGS)
364 : {
365 69042 : bytea *vlena = PG_GETARG_BYTEA_P_COPY(0);
366 :
367 69042 : PG_RETURN_BYTEA_P(vlena);
368 : }
369 :
370 : Datum
371 258774 : bytea_string_agg_transfn(PG_FUNCTION_ARGS)
372 : {
373 : StringInfo state;
374 :
375 258774 : state = PG_ARGISNULL(0) ? NULL : (StringInfo) PG_GETARG_POINTER(0);
376 :
377 : /* Append the value unless null, preceding it with the delimiter. */
378 258774 : if (!PG_ARGISNULL(1))
379 : {
380 243774 : bytea *value = PG_GETARG_BYTEA_PP(1);
381 243774 : bool isfirst = false;
382 :
383 : /*
384 : * You might think we can just throw away the first delimiter, however
385 : * we must keep it as we may be a parallel worker doing partial
386 : * aggregation building a state to send to the main process. We need
387 : * to keep the delimiter of every aggregation so that the combine
388 : * function can properly join up the strings of two separately
389 : * partially aggregated results. The first delimiter is only stripped
390 : * off in the final function. To know how much to strip off the front
391 : * of the string, we store the length of the first delimiter in the
392 : * StringInfo's cursor field, which we don't otherwise need here.
393 : */
394 243774 : if (state == NULL)
395 : {
396 : MemoryContext aggcontext;
397 : MemoryContext oldcontext;
398 :
399 188 : if (!AggCheckCallContext(fcinfo, &aggcontext))
400 : {
401 : /* cannot be called directly because of internal-type argument */
402 0 : elog(ERROR, "bytea_string_agg_transfn called in non-aggregate context");
403 : }
404 :
405 : /*
406 : * Create state in aggregate context. It'll stay there across
407 : * subsequent calls.
408 : */
409 188 : oldcontext = MemoryContextSwitchTo(aggcontext);
410 188 : state = makeStringInfo();
411 188 : MemoryContextSwitchTo(oldcontext);
412 :
413 188 : isfirst = true;
414 : }
415 :
416 243774 : if (!PG_ARGISNULL(2))
417 : {
418 243762 : bytea *delim = PG_GETARG_BYTEA_PP(2);
419 :
420 243762 : appendBinaryStringInfo(state, VARDATA_ANY(delim),
421 243762 : VARSIZE_ANY_EXHDR(delim));
422 243762 : if (isfirst)
423 182 : state->cursor = VARSIZE_ANY_EXHDR(delim);
424 : }
425 :
426 243774 : appendBinaryStringInfo(state, VARDATA_ANY(value),
427 243774 : VARSIZE_ANY_EXHDR(value));
428 : }
429 :
430 : /*
431 : * The transition type for string_agg() is declared to be "internal",
432 : * which is a pass-by-value type the same size as a pointer.
433 : */
434 258774 : if (state)
435 258728 : PG_RETURN_POINTER(state);
436 46 : PG_RETURN_NULL();
437 : }
438 :
439 : Datum
440 154 : bytea_string_agg_finalfn(PG_FUNCTION_ARGS)
441 : {
442 : StringInfo state;
443 :
444 : /* cannot be called directly because of internal-type argument */
445 : Assert(AggCheckCallContext(fcinfo, NULL));
446 :
447 154 : state = PG_ARGISNULL(0) ? NULL : (StringInfo) PG_GETARG_POINTER(0);
448 :
449 154 : if (state != NULL)
450 : {
451 : /* As per comment in transfn, strip data before the cursor position */
452 : bytea *result;
453 148 : int strippedlen = state->len - state->cursor;
454 :
455 148 : result = (bytea *) palloc(strippedlen + VARHDRSZ);
456 148 : SET_VARSIZE(result, strippedlen + VARHDRSZ);
457 148 : memcpy(VARDATA(result), &state->data[state->cursor], strippedlen);
458 148 : PG_RETURN_BYTEA_P(result);
459 : }
460 : else
461 6 : PG_RETURN_NULL();
462 : }
463 :
464 : /*-------------------------------------------------------------
465 : * byteaoctetlen
466 : *
467 : * get the number of bytes contained in an instance of type 'bytea'
468 : *-------------------------------------------------------------
469 : */
470 : Datum
471 650 : byteaoctetlen(PG_FUNCTION_ARGS)
472 : {
473 650 : Datum str = PG_GETARG_DATUM(0);
474 :
475 : /* We need not detoast the input at all */
476 650 : PG_RETURN_INT32(toast_raw_datum_size(str) - VARHDRSZ);
477 : }
478 :
479 : /*
480 : * byteacat -
481 : * takes two bytea* and returns a bytea* that is the concatenation of
482 : * the two.
483 : *
484 : * Cloned from textcat and modified as required.
485 : */
486 : Datum
487 1522 : byteacat(PG_FUNCTION_ARGS)
488 : {
489 1522 : bytea *t1 = PG_GETARG_BYTEA_PP(0);
490 1522 : bytea *t2 = PG_GETARG_BYTEA_PP(1);
491 :
492 1522 : PG_RETURN_BYTEA_P(bytea_catenate(t1, t2));
493 : }
494 :
495 : /*
496 : * byteaoverlay
497 : * Replace specified substring of first string with second
498 : *
499 : * The SQL standard defines OVERLAY() in terms of substring and concatenation.
500 : * This code is a direct implementation of what the standard says.
501 : */
502 : Datum
503 6 : byteaoverlay(PG_FUNCTION_ARGS)
504 : {
505 6 : bytea *t1 = PG_GETARG_BYTEA_PP(0);
506 6 : bytea *t2 = PG_GETARG_BYTEA_PP(1);
507 6 : int sp = PG_GETARG_INT32(2); /* substring start position */
508 6 : int sl = PG_GETARG_INT32(3); /* substring length */
509 :
510 6 : PG_RETURN_BYTEA_P(bytea_overlay(t1, t2, sp, sl));
511 : }
512 :
513 : Datum
514 12 : byteaoverlay_no_len(PG_FUNCTION_ARGS)
515 : {
516 12 : bytea *t1 = PG_GETARG_BYTEA_PP(0);
517 12 : bytea *t2 = PG_GETARG_BYTEA_PP(1);
518 12 : int sp = PG_GETARG_INT32(2); /* substring start position */
519 : int sl;
520 :
521 12 : sl = VARSIZE_ANY_EXHDR(t2); /* defaults to length(t2) */
522 12 : PG_RETURN_BYTEA_P(bytea_overlay(t1, t2, sp, sl));
523 : }
524 :
525 : /*
526 : * bytea_substr()
527 : * Return a substring starting at the specified position.
528 : * Cloned from text_substr and modified as required.
529 : *
530 : * Input:
531 : * - string
532 : * - starting position (is one-based)
533 : * - string length (optional)
534 : *
535 : * If the starting position is zero or less, then return from the start of the string
536 : * adjusting the length to be consistent with the "negative start" per SQL.
537 : * If the length is less than zero, an ERROR is thrown. If no third argument
538 : * (length) is provided, the length to the end of the string is assumed.
539 : */
540 : Datum
541 86 : bytea_substr(PG_FUNCTION_ARGS)
542 : {
543 86 : PG_RETURN_BYTEA_P(bytea_substring(PG_GETARG_DATUM(0),
544 : PG_GETARG_INT32(1),
545 : PG_GETARG_INT32(2),
546 : false));
547 : }
548 :
549 : /*
550 : * bytea_substr_no_len -
551 : * Wrapper to avoid opr_sanity failure due to
552 : * one function accepting a different number of args.
553 : */
554 : Datum
555 3936 : bytea_substr_no_len(PG_FUNCTION_ARGS)
556 : {
557 3936 : PG_RETURN_BYTEA_P(bytea_substring(PG_GETARG_DATUM(0),
558 : PG_GETARG_INT32(1),
559 : -1,
560 : true));
561 : }
562 :
563 : /*
564 : * bit_count
565 : */
566 : Datum
567 6 : bytea_bit_count(PG_FUNCTION_ARGS)
568 : {
569 6 : bytea *t1 = PG_GETARG_BYTEA_PP(0);
570 :
571 6 : PG_RETURN_INT64(pg_popcount(VARDATA_ANY(t1), VARSIZE_ANY_EXHDR(t1)));
572 : }
573 :
574 : /*
575 : * byteapos -
576 : * Return the position of the specified substring.
577 : * Implements the SQL POSITION() function.
578 : * Cloned from textpos and modified as required.
579 : */
580 : Datum
581 30 : byteapos(PG_FUNCTION_ARGS)
582 : {
583 30 : bytea *t1 = PG_GETARG_BYTEA_PP(0);
584 30 : bytea *t2 = PG_GETARG_BYTEA_PP(1);
585 : int pos;
586 : int px,
587 : p;
588 : int len1,
589 : len2;
590 : char *p1,
591 : *p2;
592 :
593 30 : len1 = VARSIZE_ANY_EXHDR(t1);
594 30 : len2 = VARSIZE_ANY_EXHDR(t2);
595 :
596 30 : if (len2 <= 0)
597 6 : PG_RETURN_INT32(1); /* result for empty pattern */
598 :
599 24 : p1 = VARDATA_ANY(t1);
600 24 : p2 = VARDATA_ANY(t2);
601 :
602 24 : pos = 0;
603 24 : px = (len1 - len2);
604 54 : for (p = 0; p <= px; p++)
605 : {
606 42 : if ((*p2 == *p1) && (memcmp(p1, p2, len2) == 0))
607 : {
608 12 : pos = p + 1;
609 12 : break;
610 : };
611 30 : p1++;
612 : };
613 :
614 24 : PG_RETURN_INT32(pos);
615 : }
616 :
617 : /*-------------------------------------------------------------
618 : * byteaGetByte
619 : *
620 : * this routine treats "bytea" as an array of bytes.
621 : * It returns the Nth byte (a number between 0 and 255).
622 : *-------------------------------------------------------------
623 : */
624 : Datum
625 76 : byteaGetByte(PG_FUNCTION_ARGS)
626 : {
627 76 : bytea *v = PG_GETARG_BYTEA_PP(0);
628 76 : int32 n = PG_GETARG_INT32(1);
629 : int len;
630 : int byte;
631 :
632 76 : len = VARSIZE_ANY_EXHDR(v);
633 :
634 76 : if (n < 0 || n >= len)
635 6 : ereport(ERROR,
636 : (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
637 : errmsg("index %d out of valid range, 0..%d",
638 : n, len - 1)));
639 :
640 70 : byte = ((unsigned char *) VARDATA_ANY(v))[n];
641 :
642 70 : PG_RETURN_INT32(byte);
643 : }
644 :
645 : /*-------------------------------------------------------------
646 : * byteaGetBit
647 : *
648 : * This routine treats a "bytea" type like an array of bits.
649 : * It returns the value of the Nth bit (0 or 1).
650 : *
651 : *-------------------------------------------------------------
652 : */
653 : Datum
654 12 : byteaGetBit(PG_FUNCTION_ARGS)
655 : {
656 12 : bytea *v = PG_GETARG_BYTEA_PP(0);
657 12 : int64 n = PG_GETARG_INT64(1);
658 : int byteNo,
659 : bitNo;
660 : int len;
661 : int byte;
662 :
663 12 : len = VARSIZE_ANY_EXHDR(v);
664 :
665 12 : if (n < 0 || n >= (int64) len * 8)
666 6 : ereport(ERROR,
667 : (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
668 : errmsg("index %" PRId64 " out of valid range, 0..%" PRId64,
669 : n, (int64) len * 8 - 1)));
670 :
671 : /* n/8 is now known < len, so safe to cast to int */
672 6 : byteNo = (int) (n / 8);
673 6 : bitNo = (int) (n % 8);
674 :
675 6 : byte = ((unsigned char *) VARDATA_ANY(v))[byteNo];
676 :
677 6 : if (byte & (1 << bitNo))
678 6 : PG_RETURN_INT32(1);
679 : else
680 0 : PG_RETURN_INT32(0);
681 : }
682 :
683 : /*-------------------------------------------------------------
684 : * byteaSetByte
685 : *
686 : * Given an instance of type 'bytea' creates a new one with
687 : * the Nth byte set to the given value.
688 : *
689 : *-------------------------------------------------------------
690 : */
691 : Datum
692 12 : byteaSetByte(PG_FUNCTION_ARGS)
693 : {
694 12 : bytea *res = PG_GETARG_BYTEA_P_COPY(0);
695 12 : int32 n = PG_GETARG_INT32(1);
696 12 : int32 newByte = PG_GETARG_INT32(2);
697 : int len;
698 :
699 12 : len = VARSIZE(res) - VARHDRSZ;
700 :
701 12 : if (n < 0 || n >= len)
702 6 : ereport(ERROR,
703 : (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
704 : errmsg("index %d out of valid range, 0..%d",
705 : n, len - 1)));
706 :
707 : /*
708 : * Now set the byte.
709 : */
710 6 : ((unsigned char *) VARDATA(res))[n] = newByte;
711 :
712 6 : PG_RETURN_BYTEA_P(res);
713 : }
714 :
715 : /*-------------------------------------------------------------
716 : * byteaSetBit
717 : *
718 : * Given an instance of type 'bytea' creates a new one with
719 : * the Nth bit set to the given value.
720 : *
721 : *-------------------------------------------------------------
722 : */
723 : Datum
724 12 : byteaSetBit(PG_FUNCTION_ARGS)
725 : {
726 12 : bytea *res = PG_GETARG_BYTEA_P_COPY(0);
727 12 : int64 n = PG_GETARG_INT64(1);
728 12 : int32 newBit = PG_GETARG_INT32(2);
729 : int len;
730 : int oldByte,
731 : newByte;
732 : int byteNo,
733 : bitNo;
734 :
735 12 : len = VARSIZE(res) - VARHDRSZ;
736 :
737 12 : if (n < 0 || n >= (int64) len * 8)
738 6 : ereport(ERROR,
739 : (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
740 : errmsg("index %" PRId64 " out of valid range, 0..%" PRId64,
741 : n, (int64) len * 8 - 1)));
742 :
743 : /* n/8 is now known < len, so safe to cast to int */
744 6 : byteNo = (int) (n / 8);
745 6 : bitNo = (int) (n % 8);
746 :
747 : /*
748 : * sanity check!
749 : */
750 6 : if (newBit != 0 && newBit != 1)
751 0 : ereport(ERROR,
752 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
753 : errmsg("new bit must be 0 or 1")));
754 :
755 : /*
756 : * Update the byte.
757 : */
758 6 : oldByte = ((unsigned char *) VARDATA(res))[byteNo];
759 :
760 6 : if (newBit == 0)
761 6 : newByte = oldByte & (~(1 << bitNo));
762 : else
763 0 : newByte = oldByte | (1 << bitNo);
764 :
765 6 : ((unsigned char *) VARDATA(res))[byteNo] = newByte;
766 :
767 6 : PG_RETURN_BYTEA_P(res);
768 : }
769 :
770 : /*
771 : * Return reversed bytea
772 : */
773 : Datum
774 18 : bytea_reverse(PG_FUNCTION_ARGS)
775 : {
776 18 : bytea *v = PG_GETARG_BYTEA_PP(0);
777 18 : const char *p = VARDATA_ANY(v);
778 18 : int len = VARSIZE_ANY_EXHDR(v);
779 18 : const char *endp = p + len;
780 18 : bytea *result = palloc(len + VARHDRSZ);
781 18 : char *dst = (char *) VARDATA(result) + len;
782 :
783 18 : SET_VARSIZE(result, len + VARHDRSZ);
784 :
785 36 : while (p < endp)
786 18 : *(--dst) = *p++;
787 :
788 18 : PG_RETURN_BYTEA_P(result);
789 : }
790 :
791 :
792 : /*****************************************************************************
793 : * Comparison Functions used for bytea
794 : *
795 : * Note: btree indexes need these routines not to leak memory; therefore,
796 : * be careful to free working copies of toasted datums. Most places don't
797 : * need to be so careful.
798 : *****************************************************************************/
799 :
800 : Datum
801 10478 : byteaeq(PG_FUNCTION_ARGS)
802 : {
803 10478 : Datum arg1 = PG_GETARG_DATUM(0);
804 10478 : Datum arg2 = PG_GETARG_DATUM(1);
805 : bool result;
806 : Size len1,
807 : len2;
808 :
809 : /*
810 : * We can use a fast path for unequal lengths, which might save us from
811 : * having to detoast one or both values.
812 : */
813 10478 : len1 = toast_raw_datum_size(arg1);
814 10478 : len2 = toast_raw_datum_size(arg2);
815 10478 : if (len1 != len2)
816 4400 : result = false;
817 : else
818 : {
819 6078 : bytea *barg1 = DatumGetByteaPP(arg1);
820 6078 : bytea *barg2 = DatumGetByteaPP(arg2);
821 :
822 6078 : result = (memcmp(VARDATA_ANY(barg1), VARDATA_ANY(barg2),
823 : len1 - VARHDRSZ) == 0);
824 :
825 6078 : PG_FREE_IF_COPY(barg1, 0);
826 6078 : PG_FREE_IF_COPY(barg2, 1);
827 : }
828 :
829 10478 : PG_RETURN_BOOL(result);
830 : }
831 :
832 : Datum
833 768 : byteane(PG_FUNCTION_ARGS)
834 : {
835 768 : Datum arg1 = PG_GETARG_DATUM(0);
836 768 : Datum arg2 = PG_GETARG_DATUM(1);
837 : bool result;
838 : Size len1,
839 : len2;
840 :
841 : /*
842 : * We can use a fast path for unequal lengths, which might save us from
843 : * having to detoast one or both values.
844 : */
845 768 : len1 = toast_raw_datum_size(arg1);
846 768 : len2 = toast_raw_datum_size(arg2);
847 768 : if (len1 != len2)
848 0 : result = true;
849 : else
850 : {
851 768 : bytea *barg1 = DatumGetByteaPP(arg1);
852 768 : bytea *barg2 = DatumGetByteaPP(arg2);
853 :
854 768 : result = (memcmp(VARDATA_ANY(barg1), VARDATA_ANY(barg2),
855 : len1 - VARHDRSZ) != 0);
856 :
857 768 : PG_FREE_IF_COPY(barg1, 0);
858 768 : PG_FREE_IF_COPY(barg2, 1);
859 : }
860 :
861 768 : PG_RETURN_BOOL(result);
862 : }
863 :
864 : Datum
865 8346 : bytealt(PG_FUNCTION_ARGS)
866 : {
867 8346 : bytea *arg1 = PG_GETARG_BYTEA_PP(0);
868 8346 : bytea *arg2 = PG_GETARG_BYTEA_PP(1);
869 : int len1,
870 : len2;
871 : int cmp;
872 :
873 8346 : len1 = VARSIZE_ANY_EXHDR(arg1);
874 8346 : len2 = VARSIZE_ANY_EXHDR(arg2);
875 :
876 8346 : cmp = memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), Min(len1, len2));
877 :
878 8346 : PG_FREE_IF_COPY(arg1, 0);
879 8346 : PG_FREE_IF_COPY(arg2, 1);
880 :
881 8346 : PG_RETURN_BOOL((cmp < 0) || ((cmp == 0) && (len1 < len2)));
882 : }
883 :
884 : Datum
885 6356 : byteale(PG_FUNCTION_ARGS)
886 : {
887 6356 : bytea *arg1 = PG_GETARG_BYTEA_PP(0);
888 6356 : bytea *arg2 = PG_GETARG_BYTEA_PP(1);
889 : int len1,
890 : len2;
891 : int cmp;
892 :
893 6356 : len1 = VARSIZE_ANY_EXHDR(arg1);
894 6356 : len2 = VARSIZE_ANY_EXHDR(arg2);
895 :
896 6356 : cmp = memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), Min(len1, len2));
897 :
898 6356 : PG_FREE_IF_COPY(arg1, 0);
899 6356 : PG_FREE_IF_COPY(arg2, 1);
900 :
901 6356 : PG_RETURN_BOOL((cmp < 0) || ((cmp == 0) && (len1 <= len2)));
902 : }
903 :
904 : Datum
905 6366 : byteagt(PG_FUNCTION_ARGS)
906 : {
907 6366 : bytea *arg1 = PG_GETARG_BYTEA_PP(0);
908 6366 : bytea *arg2 = PG_GETARG_BYTEA_PP(1);
909 : int len1,
910 : len2;
911 : int cmp;
912 :
913 6366 : len1 = VARSIZE_ANY_EXHDR(arg1);
914 6366 : len2 = VARSIZE_ANY_EXHDR(arg2);
915 :
916 6366 : cmp = memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), Min(len1, len2));
917 :
918 6366 : PG_FREE_IF_COPY(arg1, 0);
919 6366 : PG_FREE_IF_COPY(arg2, 1);
920 :
921 6366 : PG_RETURN_BOOL((cmp > 0) || ((cmp == 0) && (len1 > len2)));
922 : }
923 :
924 : Datum
925 5054 : byteage(PG_FUNCTION_ARGS)
926 : {
927 5054 : bytea *arg1 = PG_GETARG_BYTEA_PP(0);
928 5054 : bytea *arg2 = PG_GETARG_BYTEA_PP(1);
929 : int len1,
930 : len2;
931 : int cmp;
932 :
933 5054 : len1 = VARSIZE_ANY_EXHDR(arg1);
934 5054 : len2 = VARSIZE_ANY_EXHDR(arg2);
935 :
936 5054 : cmp = memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), Min(len1, len2));
937 :
938 5054 : PG_FREE_IF_COPY(arg1, 0);
939 5054 : PG_FREE_IF_COPY(arg2, 1);
940 :
941 5054 : PG_RETURN_BOOL((cmp > 0) || ((cmp == 0) && (len1 >= len2)));
942 : }
943 :
944 : Datum
945 94592 : byteacmp(PG_FUNCTION_ARGS)
946 : {
947 94592 : bytea *arg1 = PG_GETARG_BYTEA_PP(0);
948 94592 : bytea *arg2 = PG_GETARG_BYTEA_PP(1);
949 : int len1,
950 : len2;
951 : int cmp;
952 :
953 94592 : len1 = VARSIZE_ANY_EXHDR(arg1);
954 94592 : len2 = VARSIZE_ANY_EXHDR(arg2);
955 :
956 94592 : cmp = memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), Min(len1, len2));
957 94592 : if ((cmp == 0) && (len1 != len2))
958 3400 : cmp = (len1 < len2) ? -1 : 1;
959 :
960 94592 : PG_FREE_IF_COPY(arg1, 0);
961 94592 : PG_FREE_IF_COPY(arg2, 1);
962 :
963 94592 : PG_RETURN_INT32(cmp);
964 : }
965 :
966 : Datum
967 24 : bytea_larger(PG_FUNCTION_ARGS)
968 : {
969 24 : bytea *arg1 = PG_GETARG_BYTEA_PP(0);
970 24 : bytea *arg2 = PG_GETARG_BYTEA_PP(1);
971 : bytea *result;
972 : int len1,
973 : len2;
974 : int cmp;
975 :
976 24 : len1 = VARSIZE_ANY_EXHDR(arg1);
977 24 : len2 = VARSIZE_ANY_EXHDR(arg2);
978 :
979 24 : cmp = memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), Min(len1, len2));
980 24 : result = ((cmp > 0) || ((cmp == 0) && (len1 > len2)) ? arg1 : arg2);
981 :
982 24 : PG_RETURN_BYTEA_P(result);
983 : }
984 :
985 : Datum
986 24 : bytea_smaller(PG_FUNCTION_ARGS)
987 : {
988 24 : bytea *arg1 = PG_GETARG_BYTEA_PP(0);
989 24 : bytea *arg2 = PG_GETARG_BYTEA_PP(1);
990 : bytea *result;
991 : int len1,
992 : len2;
993 : int cmp;
994 :
995 24 : len1 = VARSIZE_ANY_EXHDR(arg1);
996 24 : len2 = VARSIZE_ANY_EXHDR(arg2);
997 :
998 24 : cmp = memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), Min(len1, len2));
999 24 : result = ((cmp < 0) || ((cmp == 0) && (len1 < len2)) ? arg1 : arg2);
1000 :
1001 24 : PG_RETURN_BYTEA_P(result);
1002 : }
1003 :
1004 : Datum
1005 44 : bytea_sortsupport(PG_FUNCTION_ARGS)
1006 : {
1007 44 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
1008 : MemoryContext oldcontext;
1009 :
1010 44 : oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
1011 :
1012 : /* Use generic string SortSupport, forcing "C" collation */
1013 44 : varstr_sortsupport(ssup, BYTEAOID, C_COLLATION_OID);
1014 :
1015 44 : MemoryContextSwitchTo(oldcontext);
1016 :
1017 44 : PG_RETURN_VOID();
1018 : }
1019 :
1020 : /* Cast bytea -> int2 */
1021 : Datum
1022 36 : bytea_int2(PG_FUNCTION_ARGS)
1023 : {
1024 36 : bytea *v = PG_GETARG_BYTEA_PP(0);
1025 36 : int len = VARSIZE_ANY_EXHDR(v);
1026 : uint16 result;
1027 :
1028 : /* Check that the byte array is not too long */
1029 36 : if (len > sizeof(result))
1030 6 : ereport(ERROR,
1031 : errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1032 : errmsg("smallint out of range"));
1033 :
1034 : /* Convert it to an integer; most significant bytes come first */
1035 30 : result = 0;
1036 72 : for (int i = 0; i < len; i++)
1037 : {
1038 42 : result <<= BITS_PER_BYTE;
1039 42 : result |= ((unsigned char *) VARDATA_ANY(v))[i];
1040 : }
1041 :
1042 30 : PG_RETURN_INT16(result);
1043 : }
1044 :
1045 : /* Cast bytea -> int4 */
1046 : Datum
1047 36 : bytea_int4(PG_FUNCTION_ARGS)
1048 : {
1049 36 : bytea *v = PG_GETARG_BYTEA_PP(0);
1050 36 : int len = VARSIZE_ANY_EXHDR(v);
1051 : uint32 result;
1052 :
1053 : /* Check that the byte array is not too long */
1054 36 : if (len > sizeof(result))
1055 6 : ereport(ERROR,
1056 : errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1057 : errmsg("integer out of range"));
1058 :
1059 : /* Convert it to an integer; most significant bytes come first */
1060 30 : result = 0;
1061 108 : for (int i = 0; i < len; i++)
1062 : {
1063 78 : result <<= BITS_PER_BYTE;
1064 78 : result |= ((unsigned char *) VARDATA_ANY(v))[i];
1065 : }
1066 :
1067 30 : PG_RETURN_INT32(result);
1068 : }
1069 :
1070 : /* Cast bytea -> int8 */
1071 : Datum
1072 36 : bytea_int8(PG_FUNCTION_ARGS)
1073 : {
1074 36 : bytea *v = PG_GETARG_BYTEA_PP(0);
1075 36 : int len = VARSIZE_ANY_EXHDR(v);
1076 : uint64 result;
1077 :
1078 : /* Check that the byte array is not too long */
1079 36 : if (len > sizeof(result))
1080 6 : ereport(ERROR,
1081 : errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1082 : errmsg("bigint out of range"));
1083 :
1084 : /* Convert it to an integer; most significant bytes come first */
1085 30 : result = 0;
1086 180 : for (int i = 0; i < len; i++)
1087 : {
1088 150 : result <<= BITS_PER_BYTE;
1089 150 : result |= ((unsigned char *) VARDATA_ANY(v))[i];
1090 : }
1091 :
1092 30 : PG_RETURN_INT64(result);
1093 : }
1094 :
1095 : /* Cast int2 -> bytea; can just use int2send() */
1096 : Datum
1097 12 : int2_bytea(PG_FUNCTION_ARGS)
1098 : {
1099 12 : return int2send(fcinfo);
1100 : }
1101 :
1102 : /* Cast int4 -> bytea; can just use int4send() */
1103 : Datum
1104 40972 : int4_bytea(PG_FUNCTION_ARGS)
1105 : {
1106 40972 : return int4send(fcinfo);
1107 : }
1108 :
1109 : /* Cast int8 -> bytea; can just use int8send() */
1110 : Datum
1111 12 : int8_bytea(PG_FUNCTION_ARGS)
1112 : {
1113 12 : return int8send(fcinfo);
1114 : }
|