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