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
pull/182/head
Tom Lane 11 months ago
parent 57f3702471
commit 2d24fd942c
  1. 4
      doc/src/sgml/func.sgml
  2. 38
      src/backend/utils/adt/varlena.c
  3. 2
      src/include/catalog/catversion.h
  4. 6
      src/include/catalog/pg_aggregate.dat
  5. 13
      src/include/catalog/pg_proc.dat
  6. 28
      src/test/regress/expected/aggregates.out
  7. 2
      src/test/regress/expected/opr_sanity.out
  8. 11
      src/test/regress/sql/aggregates.sql

@ -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.

@ -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)
{

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

@ -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',

@ -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',

@ -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);

@ -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

@ -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

Loading…
Cancel
Save