V5 patch. I've added more tests with different bytea sizes --
With best regards, Marat Bukharov чт, 4 июл. 2024 г. в 15:29, Aleksander Alekseev <aleksan...@timescale.com>: > > Hi Marat, > > > V4 path with fixed usage PG_GETARG_BYTEA_PP instead of PG_GETARG_TEXT_PP > > Thanks for the patch. > > Please add it to the nearest open commitfest [1]. > > ``` > +select min(v) from bytea_test_table; > + min > +------ > + \xaa > +(1 row) > + > +select max(v) from bytea_test_table; > + max > +------ > + \xff > +(1 row) > ``` > > If I understand correctly, all the v's are of the same size. If this > is the case you should add more test cases. > > [1]: https://commitfest.postgresql.org/ > > -- > Best regards, > Aleksander Alekseev
From 3bc3786ede117442b06d6cbe36a7b015d76a7cf4 Mon Sep 17 00:00:00 2001 From: Marat Bukharov <mara...@yandex-team.ru> Date: Wed, 24 Jul 2024 17:37:31 +0300 Subject: [PATCH v5] add bytea agg funcs --- doc/src/sgml/func.sgml | 4 +-- src/backend/utils/adt/varlena.c | 38 ++++++++++++++++++++++++ src/include/catalog/pg_aggregate.dat | 6 ++++ src/include/catalog/pg_proc.dat | 13 ++++++++ src/test/regress/expected/aggregates.out | 28 ++++++++++++++++- src/test/regress/expected/opr_sanity.out | 2 ++ src/test/regress/sql/aggregates.sql | 11 ++++++- 7 files changed, 98 insertions(+), 4 deletions(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index f1f22a1960..891f7a4259 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -21976,7 +21976,7 @@ SELECT NULLIF(value, '(none)') ... <para> Computes the maximum of the non-null input values. Available for any numeric, string, date/time, or enum type, - as well as <type>inet</type>, <type>interval</type>, + as well as <type>bytea</type>, <type>inet</type>, <type>interval</type>, <type>money</type>, <type>oid</type>, <type>pg_lsn</type>, <type>tid</type>, <type>xid8</type>, and arrays of any of these types. @@ -21995,7 +21995,7 @@ SELECT NULLIF(value, '(none)') ... <para> Computes the minimum of the non-null input values. Available for any numeric, string, date/time, or enum type, - as well as <type>inet</type>, <type>interval</type>, + as well as <type>bytea</type>, <type>inet</type>, <type>interval</type>, <type>money</type>, <type>oid</type>, <type>pg_lsn</type>, <type>tid</type>, <type>xid8</type>, and arrays of any of these types. diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index d2e2e9bbba..e80c789442 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -3956,6 +3956,44 @@ byteacmp(PG_FUNCTION_ARGS) PG_RETURN_INT32(cmp); } +Datum +bytea_larger(PG_FUNCTION_ARGS) +{ + bytea *arg1 = PG_GETARG_BYTEA_PP(0); + bytea *arg2 = PG_GETARG_BYTEA_PP(1); + bytea *result; + int len1, + len2; + int cmp; + + len1 = VARSIZE_ANY_EXHDR(arg1); + len2 = VARSIZE_ANY_EXHDR(arg2); + + cmp = memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), Min(len1, len2)); + result = ((cmp > 0) || ((cmp == 0) && (len1 > len2)) ? arg1 : arg2); + + PG_RETURN_BYTEA_P(result); +} + +Datum +bytea_smaller(PG_FUNCTION_ARGS) +{ + bytea *arg1 = PG_GETARG_BYTEA_PP(0); + bytea *arg2 = PG_GETARG_BYTEA_PP(1); + bytea *result; + int len1, + len2; + int cmp; + + len1 = VARSIZE_ANY_EXHDR(arg1); + len2 = VARSIZE_ANY_EXHDR(arg2); + + cmp = memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), Min(len1, len2)); + result = ((cmp < 0) || ((cmp == 0) && (len1 < len2)) ? arg1 : arg2); + + PG_RETURN_BYTEA_P(result); +} + Datum bytea_sortsupport(PG_FUNCTION_ARGS) { diff --git a/src/include/catalog/pg_aggregate.dat b/src/include/catalog/pg_aggregate.dat index 5f13532abc..970d9a70fd 100644 --- a/src/include/catalog/pg_aggregate.dat +++ b/src/include/catalog/pg_aggregate.dat @@ -158,6 +158,9 @@ { aggfnoid => 'max(xid8)', aggtransfn => 'xid8_larger', aggcombinefn => 'xid8_larger', aggsortop => '>(xid8,xid8)', aggtranstype => 'xid8' }, +{ aggfnoid => 'max(bytea)', aggtransfn => 'bytea_larger', + aggcombinefn => 'bytea_larger', aggsortop => '>(bytea,bytea)', + aggtranstype => 'bytea' }, # min { aggfnoid => 'min(int8)', aggtransfn => 'int8smaller', @@ -226,6 +229,9 @@ { aggfnoid => 'min(xid8)', aggtransfn => 'xid8_smaller', aggcombinefn => 'xid8_smaller', aggsortop => '<(xid8,xid8)', aggtranstype => 'xid8' }, +{ aggfnoid => 'min(bytea)', aggtransfn => 'bytea_smaller', + aggcombinefn => 'bytea_smaller', aggsortop => '<(bytea,bytea)', + aggtranstype => 'bytea' }, # count { aggfnoid => 'count(any)', aggtransfn => 'int8inc_any', diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index d4ac578ae6..f16f17ef3a 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -1278,6 +1278,13 @@ proname => 'text_smaller', proleakproof => 't', prorettype => 'text', proargtypes => 'text text', prosrc => 'text_smaller' }, +{ oid => '6347', descr => 'larger of two', + proname => 'bytea_larger', proleakproof => 't', prorettype => 'bytea', + proargtypes => 'bytea bytea', prosrc => 'bytea_larger' }, +{ oid => '6348', descr => 'smaller of two', + proname => 'bytea_smaller', proleakproof => 't', prorettype => 'bytea', + proargtypes => 'bytea bytea', prosrc => 'bytea_smaller' }, + { oid => '460', descr => 'I/O', proname => 'int8in', prorettype => 'int8', proargtypes => 'cstring', prosrc => 'int8in' }, @@ -6764,6 +6771,9 @@ { oid => '5099', descr => 'maximum value of all xid8 input values', proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'xid8', proargtypes => 'xid8', prosrc => 'aggregate_dummy' }, +{ oid => '6349', descr => 'maximum value of all bytea input values', + proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'bytea', + proargtypes => 'bytea', prosrc => 'aggregate_dummy' }, { oid => '2131', descr => 'minimum value of all bigint input values', proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'int8', @@ -6834,6 +6844,9 @@ { oid => '5100', descr => 'minimum value of all xid8 input values', proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'xid8', proargtypes => 'xid8', prosrc => 'aggregate_dummy' }, +{ oid => '6350', descr => 'minimum value of all bytea input values', + proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'bytea', + proargtypes => 'bytea', prosrc => 'aggregate_dummy' }, # count has two forms: count(any) and count(*) { oid => '2147', diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out index 1c1ca7573a..69d91df779 100644 --- a/src/test/regress/expected/aggregates.out +++ b/src/test/regress/expected/aggregates.out @@ -1925,7 +1925,7 @@ select string_agg(distinct f1::text, ',' order by f1::text) from varchar_tbl; - a,ab,abcd (1 row) --- string_agg bytea tests +-- string_agg, min, max bytea tests create table bytea_test_table(v bytea); select string_agg(v, '') from bytea_test_table; string_agg @@ -1959,6 +1959,32 @@ select string_agg(v, decode('ee', 'hex')) from bytea_test_table; \xffeeaa (1 row) +select min(v) from bytea_test_table; + min +------ + \xaa +(1 row) + +select max(v) from bytea_test_table; + max +------ + \xff +(1 row) + +insert into bytea_test_table values(decode('ffff','hex')); +insert into bytea_test_table values(decode('aaaa','hex')); +select min(v) from bytea_test_table; + min +------ + \xaa +(1 row) + +select max(v) from bytea_test_table; + max +-------- + \xffff +(1 row) + drop table bytea_test_table; -- Test parallel string_agg and array_agg create table pagg_test (x int, y int) with (autovacuum_enabled = off); diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index 9d047b21b8..087e349894 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -874,6 +874,8 @@ xid8ne(xid8,xid8) xid8cmp(xid8,xid8) uuid_extract_timestamp(uuid) uuid_extract_version(uuid) +bytea_larger(bytea,bytea) +bytea_smaller(bytea,bytea) -- restore normal output mode \a\t -- List of functions used by libpq's fe-lobj.c diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql index 1a18ca3d8f..935e7360c6 100644 --- a/src/test/regress/sql/aggregates.sql +++ b/src/test/regress/sql/aggregates.sql @@ -741,7 +741,7 @@ select string_agg(distinct f1::text, ',' order by f1) from varchar_tbl; -- not select string_agg(distinct f1, ',' order by f1::text) from varchar_tbl; -- not ok select string_agg(distinct f1::text, ',' order by f1::text) from varchar_tbl; -- ok --- string_agg bytea tests +-- string_agg, min, max bytea tests create table bytea_test_table(v bytea); select string_agg(v, '') from bytea_test_table; @@ -756,6 +756,15 @@ select string_agg(v, '') from bytea_test_table; select string_agg(v, NULL) from bytea_test_table; select string_agg(v, decode('ee', 'hex')) from bytea_test_table; +select min(v) from bytea_test_table; +select max(v) from bytea_test_table; + +insert into bytea_test_table values(decode('ffff','hex')); +insert into bytea_test_table values(decode('aaaa','hex')); + +select min(v) from bytea_test_table; +select max(v) from bytea_test_table; + drop table bytea_test_table; -- Test parallel string_agg and array_agg -- 2.44.2