1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-18 02:02:55 +03:00

Allow casting between bytea and integer types.

This allows smallint, integer, and bigint values to be cast to and
from bytea. The bytea value is the two's complement representation of
the integer, with the most significant byte first. For example:

  1234::bytea -> \x000004d2
  (-1234)::bytea -> \xfffffb2e

Author: Aleksander Alekseev <aleksander@timescale.com>
Reviewed-by: Joel Jacobson <joel@compiler.org>
Reviewed-by: Yugo Nagata <nagata@sraoss.co.jp>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Dean Rasheed <dean.a.rasheed@gmail.com>
Discussion: https://postgr.es/m/CAJ7c6TPtOp6%2BkFX5QX3fH1SVr7v65uHr-7yEJ%3DGMGQi5uhGtcA%40mail.gmail.com
This commit is contained in:
Dean Rasheed
2025-03-07 09:31:18 +00:00
parent d611f8b158
commit 6da469bada
8 changed files with 281 additions and 1 deletions

View File

@@ -4057,6 +4057,102 @@ bytea_sortsupport(PG_FUNCTION_ARGS)
PG_RETURN_VOID();
}
/* Cast bytea -> int2 */
Datum
bytea_int2(PG_FUNCTION_ARGS)
{
bytea *v = PG_GETARG_BYTEA_PP(0);
int len = VARSIZE_ANY_EXHDR(v);
uint16 result;
/* Check that the byte array is not too long */
if (len > sizeof(result))
ereport(ERROR,
errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("smallint out of range"));
/* Convert it to an integer; most significant bytes come first */
result = 0;
for (int i = 0; i < len; i++)
{
result <<= BITS_PER_BYTE;
result |= ((unsigned char *) VARDATA_ANY(v))[i];
}
PG_RETURN_INT16(result);
}
/* Cast bytea -> int4 */
Datum
bytea_int4(PG_FUNCTION_ARGS)
{
bytea *v = PG_GETARG_BYTEA_PP(0);
int len = VARSIZE_ANY_EXHDR(v);
uint32 result;
/* Check that the byte array is not too long */
if (len > sizeof(result))
ereport(ERROR,
errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range"));
/* Convert it to an integer; most significant bytes come first */
result = 0;
for (int i = 0; i < len; i++)
{
result <<= BITS_PER_BYTE;
result |= ((unsigned char *) VARDATA_ANY(v))[i];
}
PG_RETURN_INT32(result);
}
/* Cast bytea -> int8 */
Datum
bytea_int8(PG_FUNCTION_ARGS)
{
bytea *v = PG_GETARG_BYTEA_PP(0);
int len = VARSIZE_ANY_EXHDR(v);
uint64 result;
/* Check that the byte array is not too long */
if (len > sizeof(result))
ereport(ERROR,
errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range"));
/* Convert it to an integer; most significant bytes come first */
result = 0;
for (int i = 0; i < len; i++)
{
result <<= BITS_PER_BYTE;
result |= ((unsigned char *) VARDATA_ANY(v))[i];
}
PG_RETURN_INT64(result);
}
/* Cast int2 -> bytea; can just use int2send() */
Datum
int2_bytea(PG_FUNCTION_ARGS)
{
return int2send(fcinfo);
}
/* Cast int4 -> bytea; can just use int4send() */
Datum
int4_bytea(PG_FUNCTION_ARGS)
{
return int4send(fcinfo);
}
/* Cast int8 -> bytea; can just use int8send() */
Datum
int8_bytea(PG_FUNCTION_ARGS)
{
return int8send(fcinfo);
}
/*
* appendStringInfoText
*