diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/utils/adt/varlena.c | 96 | ||||
-rw-r--r-- | src/include/catalog/catversion.h | 2 | ||||
-rw-r--r-- | src/include/catalog/pg_cast.dat | 14 | ||||
-rw-r--r-- | src/include/catalog/pg_proc.dat | 19 | ||||
-rw-r--r-- | src/test/regress/expected/opr_sanity.out | 3 | ||||
-rw-r--r-- | src/test/regress/expected/strings.out | 102 | ||||
-rw-r--r-- | src/test/regress/sql/strings.sql | 29 |
7 files changed, 264 insertions, 1 deletions
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index e4556571703..cdf185ea00b 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -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 * diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index f0962e17b33..f427a89618b 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -57,6 +57,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202503031 +#define CATALOG_VERSION_NO 202503071 #endif diff --git a/src/include/catalog/pg_cast.dat b/src/include/catalog/pg_cast.dat index a26ba34e869..ab46be606f0 100644 --- a/src/include/catalog/pg_cast.dat +++ b/src/include/catalog/pg_cast.dat @@ -320,6 +320,20 @@ { castsource => 'varchar', casttarget => 'name', castfunc => 'name(varchar)', castcontext => 'i', castmethod => 'f' }, +# Allow explicit coercions between bytea and integer types +{ castsource => 'int2', casttarget => 'bytea', castfunc => 'bytea(int2)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'bytea', castfunc => 'bytea(int4)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'int8', casttarget => 'bytea', castfunc => 'bytea(int8)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'bytea', casttarget => 'int2', castfunc => 'int2(bytea)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'bytea', casttarget => 'int4', castfunc => 'int4(bytea)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'bytea', casttarget => 'int8', castfunc => 'int8(bytea)', + castcontext => 'e', castmethod => 'f' }, + # Allow explicit coercions between int4 and "char" { castsource => 'char', casttarget => 'int4', castfunc => 'int4(char)', castcontext => 'e', castmethod => 'f' }, diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 134b3dd8689..cede992b6e2 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -1165,6 +1165,25 @@ proname => 'name', proleakproof => 't', prorettype => 'name', proargtypes => 'bpchar', prosrc => 'bpchar_name' }, +{ oid => '8577', descr => 'convert int2 to bytea', + proname => 'bytea', proleakproof => 't', prorettype => 'bytea', + proargtypes => 'int2', prosrc => 'int2_bytea' }, +{ oid => '8578', descr => 'convert int4 to bytea', + proname => 'bytea', proleakproof => 't', prorettype => 'bytea', + proargtypes => 'int4', prosrc => 'int4_bytea' }, +{ oid => '8579', descr => 'convert int8 to bytea', + proname => 'bytea', proleakproof => 't', prorettype => 'bytea', + proargtypes => 'int8', prosrc => 'int8_bytea' }, +{ oid => '8580', descr => 'convert bytea to int2', + proname => 'int2', prorettype => 'int2', + proargtypes => 'bytea', prosrc => 'bytea_int2' }, +{ oid => '8581', descr => 'convert bytea to int4', + proname => 'int4', prorettype => 'int4', + proargtypes => 'bytea', prosrc => 'bytea_int4' }, +{ oid => '8582', descr => 'convert bytea to int8', + proname => 'int8', prorettype => 'int8', + proargtypes => 'bytea', prosrc => 'bytea_int8' }, + { oid => '449', descr => 'hash', proname => 'hashint2', prorettype => 'int4', proargtypes => 'int2', prosrc => 'hashint2' }, diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index b673642ad1d..20bf9ea9cdf 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -875,6 +875,9 @@ uuid_extract_timestamp(uuid) uuid_extract_version(uuid) crc32(bytea) crc32c(bytea) +bytea(smallint) +bytea(integer) +bytea(bigint) bytea_larger(bytea,bytea) bytea_smaller(bytea,bytea) -- Check that functions without argument are not marked as leakproof. diff --git a/src/test/regress/expected/strings.out b/src/test/regress/expected/strings.out index b65bb2d5368..f8cba9f5b24 100644 --- a/src/test/regress/expected/strings.out +++ b/src/test/regress/expected/strings.out @@ -2359,6 +2359,108 @@ SELECT set_byte('\x1234567890abcdef00'::bytea, 7, 11); SELECT set_byte('\x1234567890abcdef00'::bytea, 99, 11); -- error ERROR: index 99 out of valid range, 0..8 -- +-- conversions between bytea and integer types +-- +SELECT 0x1234::int2::bytea AS "\x1234", (-0x1234)::int2::bytea AS "\xedcc"; + \x1234 | \xedcc +--------+-------- + \x1234 | \xedcc +(1 row) + +SELECT 0x12345678::int4::bytea AS "\x12345678", (-0x12345678)::int4::bytea AS "\xedcba988"; + \x12345678 | \xedcba988 +------------+------------ + \x12345678 | \xedcba988 +(1 row) + +SELECT 0x1122334455667788::int8::bytea AS "\x1122334455667788", + (-0x1122334455667788)::int8::bytea AS "\xeeddccbbaa998878"; + \x1122334455667788 | \xeeddccbbaa998878 +--------------------+-------------------- + \x1122334455667788 | \xeeddccbbaa998878 +(1 row) + +SELECT ''::bytea::int2 AS "0"; + 0 +--- + 0 +(1 row) + +SELECT '\x12'::bytea::int2 AS "18"; + 18 +---- + 18 +(1 row) + +SELECT '\x1234'::bytea::int2 AS "4460"; + 4460 +------ + 4660 +(1 row) + +SELECT '\x123456'::bytea::int2; -- error +ERROR: smallint out of range +SELECT ''::bytea::int4 AS "0"; + 0 +--- + 0 +(1 row) + +SELECT '\x12'::bytea::int4 AS "18"; + 18 +---- + 18 +(1 row) + +SELECT '\x12345678'::bytea::int4 AS "305419896"; + 305419896 +----------- + 305419896 +(1 row) + +SELECT '\x123456789A'::bytea::int4; -- error +ERROR: integer out of range +SELECT ''::bytea::int8 AS "0"; + 0 +--- + 0 +(1 row) + +SELECT '\x12'::bytea::int8 AS "18"; + 18 +---- + 18 +(1 row) + +SELECT '\x1122334455667788'::bytea::int8 AS "1234605616436508552"; + 1234605616436508552 +--------------------- + 1234605616436508552 +(1 row) + +SELECT '\x112233445566778899'::bytea::int8; -- error +ERROR: bigint out of range +-- min/max integer values +SELECT '\x8000'::bytea::int2 AS "-32768", '\x7FFF'::bytea::int2 AS "32767"; + -32768 | 32767 +--------+------- + -32768 | 32767 +(1 row) + +SELECT '\x80000000'::bytea::int4 AS "-2147483648", '\x7FFFFFFF'::bytea::int4 AS "2147483647"; + -2147483648 | 2147483647 +-------------+------------ + -2147483648 | 2147483647 +(1 row) + +SELECT '\x8000000000000000'::bytea::int8 AS "-9223372036854775808", + '\x7FFFFFFFFFFFFFFF'::bytea::int8 AS "9223372036854775807"; + -9223372036854775808 | 9223372036854775807 +----------------------+--------------------- + -9223372036854775808 | 9223372036854775807 +(1 row) + +-- -- test behavior of escape_string_warning and standard_conforming_strings options -- set escape_string_warning = off; diff --git a/src/test/regress/sql/strings.sql b/src/test/regress/sql/strings.sql index 8e0f3a0e75f..4deb0683d57 100644 --- a/src/test/regress/sql/strings.sql +++ b/src/test/regress/sql/strings.sql @@ -752,6 +752,35 @@ SELECT set_byte('\x1234567890abcdef00'::bytea, 7, 11); SELECT set_byte('\x1234567890abcdef00'::bytea, 99, 11); -- error -- +-- conversions between bytea and integer types +-- +SELECT 0x1234::int2::bytea AS "\x1234", (-0x1234)::int2::bytea AS "\xedcc"; +SELECT 0x12345678::int4::bytea AS "\x12345678", (-0x12345678)::int4::bytea AS "\xedcba988"; +SELECT 0x1122334455667788::int8::bytea AS "\x1122334455667788", + (-0x1122334455667788)::int8::bytea AS "\xeeddccbbaa998878"; + +SELECT ''::bytea::int2 AS "0"; +SELECT '\x12'::bytea::int2 AS "18"; +SELECT '\x1234'::bytea::int2 AS "4460"; +SELECT '\x123456'::bytea::int2; -- error + +SELECT ''::bytea::int4 AS "0"; +SELECT '\x12'::bytea::int4 AS "18"; +SELECT '\x12345678'::bytea::int4 AS "305419896"; +SELECT '\x123456789A'::bytea::int4; -- error + +SELECT ''::bytea::int8 AS "0"; +SELECT '\x12'::bytea::int8 AS "18"; +SELECT '\x1122334455667788'::bytea::int8 AS "1234605616436508552"; +SELECT '\x112233445566778899'::bytea::int8; -- error + +-- min/max integer values +SELECT '\x8000'::bytea::int2 AS "-32768", '\x7FFF'::bytea::int2 AS "32767"; +SELECT '\x80000000'::bytea::int4 AS "-2147483648", '\x7FFFFFFF'::bytea::int4 AS "2147483647"; +SELECT '\x8000000000000000'::bytea::int8 AS "-9223372036854775808", + '\x7FFFFFFFFFFFFFFF'::bytea::int8 AS "9223372036854775807"; + +-- -- test behavior of escape_string_warning and standard_conforming_strings options -- set escape_string_warning = off; |