aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2024-10-08 13:52:14 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2024-10-08 13:52:14 -0400
commit2d24fd942c7010247c5b7b54b416acf7f4592a4e (patch)
tree0d47a0410c1f864ba9f139cac7e758dd088cd6de /src
parent57f37024712702350b714cf64215077f1d75c568 (diff)
downloadpostgresql-2d24fd942c7010247c5b7b54b416acf7f4592a4e.tar.gz
postgresql-2d24fd942c7010247c5b7b54b416acf7f4592a4e.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/adt/varlena.c38
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/pg_aggregate.dat6
-rw-r--r--src/include/catalog/pg_proc.dat13
-rw-r--r--src/test/regress/expected/aggregates.out28
-rw-r--r--src/test/regress/expected/opr_sanity.out2
-rw-r--r--src/test/regress/sql/aggregates.sql11
7 files changed, 97 insertions, 3 deletions
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index d46ed3ccf9f..533bebc1c7b 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -3932,6 +3932,44 @@ byteacmp(PG_FUNCTION_ARGS)
}
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)
{
SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 504bbe53276..4d4a2dd7afa 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -57,6 +57,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202410021
+#define CATALOG_VERSION_NO 202410081
#endif
diff --git a/src/include/catalog/pg_aggregate.dat b/src/include/catalog/pg_aggregate.dat
index b6b6352d917..6ba6a997c29 100644
--- a/src/include/catalog/pg_aggregate.dat
+++ b/src/include/catalog/pg_aggregate.dat
@@ -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',
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 77f54a79e6a..3ae31a614ce 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -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',
diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out
index 8ac13b562c4..e14e7356567 100644
--- a/src/test/regress/expected/aggregates.out
+++ b/src/test/regress/expected/aggregates.out
@@ -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);
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index 0d734169f11..34a32bd11d2 100644
--- a/src/test/regress/expected/opr_sanity.out
+++ b/src/test/regress/expected/opr_sanity.out
@@ -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
diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql
index ca6d1bcfb7f..ddf38bafb42 100644
--- a/src/test/regress/sql/aggregates.sql
+++ b/src/test/regress/sql/aggregates.sql
@@ -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