1
0
mirror of https://github.com/postgres/postgres.git synced 2025-04-22 23:02:54 +03:00

Add min and max aggregates for bytea type.

Similar to a0f1fce80, although we chose to duplicate logic
rather than invoke byteacmp, primarily to avoid repeat detoasting.

Marat Buharov, Aleksander Alekseev

Discussion: https://postgr.es/m/CAPCEVGXiASjodos4P8pgyV7ixfVn-ZgG9YyiRZRbVqbGmfuDyg@mail.gmail.com
This commit is contained in:
Tom Lane 2024-10-08 13:52:14 -04:00
parent 57f3702471
commit 2d24fd942c
8 changed files with 99 additions and 5 deletions

View File

@ -22125,7 +22125,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 also arrays and composite types containing sortable data types.
@ -22144,7 +22144,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 also arrays and composite types containing sortable data types.

View File

@ -3931,6 +3931,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)
{

View File

@ -57,6 +57,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 202410021
#define CATALOG_VERSION_NO 202410081
#endif

View File

@ -161,6 +161,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',
@ -232,6 +235,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',

View File

@ -1314,6 +1314,13 @@
proname => 'text_smaller', proleakproof => 't', prorettype => 'text',
proargtypes => 'text text', prosrc => 'text_smaller' },
{ oid => '8920', descr => 'larger of two',
proname => 'bytea_larger', proleakproof => 't', prorettype => 'bytea',
proargtypes => 'bytea bytea', prosrc => 'bytea_larger' },
{ oid => '8921', 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' },
@ -6879,6 +6886,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 => '8922', 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',
@ -6952,6 +6962,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 => '8923', 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',

View File

@ -1950,7 +1950,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
@ -1984,6 +1984,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);

View File

@ -876,6 +876,8 @@ uuid_extract_timestamp(uuid)
uuid_extract_version(uuid)
crc32(bytea)
crc32c(bytea)
bytea_larger(bytea,bytea)
bytea_smaller(bytea,bytea)
-- restore normal output mode
\a\t
-- List of functions used by libpq's fe-lobj.c

View File

@ -747,7 +747,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;
@ -762,6 +762,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