diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 135590ba574..785886af714 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -22048,7 +22048,7 @@ SELECT NULLIF(value, '(none)') ... as well as inet, interval, money, oid, pg_lsn, tid, xid8, - and arrays of any of these types. + and also arrays and composite types containing sortable data types. Yes @@ -22067,7 +22067,7 @@ SELECT NULLIF(value, '(none)') ... as well as inet, interval, money, oid, pg_lsn, tid, xid8, - and arrays of any of these types. + and also arrays and composite types containing sortable data types. Yes diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c index 0214c23a1d4..18bbb62e9a1 100644 --- a/src/backend/utils/adt/rowtypes.c +++ b/src/backend/utils/adt/rowtypes.c @@ -1315,6 +1315,24 @@ btrecordcmp(PG_FUNCTION_ARGS) PG_RETURN_INT32(record_cmp(fcinfo)); } +Datum +record_larger(PG_FUNCTION_ARGS) +{ + if (record_cmp(fcinfo) > 0) + PG_RETURN_DATUM(PG_GETARG_DATUM(0)); + else + PG_RETURN_DATUM(PG_GETARG_DATUM(1)); +} + +Datum +record_smaller(PG_FUNCTION_ARGS) +{ + if (record_cmp(fcinfo) < 0) + PG_RETURN_DATUM(PG_GETARG_DATUM(0)); + else + PG_RETURN_DATUM(PG_GETARG_DATUM(1)); +} + /* * record_image_cmp : diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 87b52fffdde..3254e7ab929 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -57,6 +57,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202407101 +#define CATALOG_VERSION_NO 202407111 #endif diff --git a/src/include/catalog/pg_aggregate.dat b/src/include/catalog/pg_aggregate.dat index 5f13532abcc..b6b6352d917 100644 --- a/src/include/catalog/pg_aggregate.dat +++ b/src/include/catalog/pg_aggregate.dat @@ -140,6 +140,9 @@ { aggfnoid => 'max(anyarray)', aggtransfn => 'array_larger', aggcombinefn => 'array_larger', aggsortop => '>(anyarray,anyarray)', aggtranstype => 'anyarray' }, +{ aggfnoid => 'max(record)', aggtransfn => 'record_larger', + aggcombinefn => 'record_larger', aggsortop => '>(record,record)', + aggtranstype => 'record' }, { aggfnoid => 'max(bpchar)', aggtransfn => 'bpchar_larger', aggcombinefn => 'bpchar_larger', aggsortop => '>(bpchar,bpchar)', aggtranstype => 'bpchar' }, @@ -208,6 +211,9 @@ { aggfnoid => 'min(anyarray)', aggtransfn => 'array_smaller', aggcombinefn => 'array_smaller', aggsortop => '<(anyarray,anyarray)', aggtranstype => 'anyarray' }, +{ aggfnoid => 'min(record)', aggtransfn => 'record_smaller', + aggcombinefn => 'record_smaller', aggsortop => '<(record,record)', + aggtranstype => 'record' }, { aggfnoid => 'min(bpchar)', aggtransfn => 'bpchar_smaller', aggcombinefn => 'bpchar_smaller', aggsortop => '<(bpchar,bpchar)', aggtranstype => 'bpchar' }, diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 0d140003e74..73d9cf85826 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -6754,6 +6754,9 @@ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'anyarray', proargtypes => 'anyarray', prosrc => 'aggregate_dummy' }, +{ oid => '8595', descr => 'maximum value of all record input values', + proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'record', + proargtypes => 'record', prosrc => 'aggregate_dummy' }, { oid => '2244', descr => 'maximum value of all bpchar input values', proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'bpchar', proargtypes => 'bpchar', prosrc => 'aggregate_dummy' }, @@ -6824,6 +6827,9 @@ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'anyarray', proargtypes => 'anyarray', prosrc => 'aggregate_dummy' }, +{ oid => '8596', descr => 'minimum value of all record input values', + proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'record', + proargtypes => 'record', prosrc => 'aggregate_dummy' }, { oid => '2245', descr => 'minimum value of all bpchar input values', proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'bpchar', proargtypes => 'bpchar', prosrc => 'aggregate_dummy' }, @@ -8343,7 +8349,7 @@ prosrc => 'generate_series_timestamptz' }, { oid => '6274', descr => 'non-persistent series generator', proname => 'generate_series', prorows => '1000', - prosupport => 'generate_series_timestamp_support', proretset => 't', + prosupport => 'generate_series_timestamp_support', proretset => 't', prorettype => 'timestamptz', proargtypes => 'timestamptz timestamptz interval text', prosrc => 'generate_series_timestamptz_at_zone' }, @@ -10358,6 +10364,12 @@ { oid => '2987', descr => 'less-equal-greater', proname => 'btrecordcmp', prorettype => 'int4', proargtypes => 'record record', prosrc => 'btrecordcmp' }, +{ oid => '8597', descr => 'larger of two', + proname => 'record_larger', prorettype => 'record', + proargtypes => 'record record', prosrc => 'record_larger' }, +{ oid => '8598', descr => 'smaller of two', + proname => 'record_smaller', prorettype => 'record', + proargtypes => 'record record', prosrc => 'record_smaller' }, { oid => '6192', descr => 'hash', proname => 'hash_record', prorettype => 'int4', proargtypes => 'record', diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out index 1c1ca7573ad..a5596ab2106 100644 --- a/src/test/regress/expected/aggregates.out +++ b/src/test/regress/expected/aggregates.out @@ -269,6 +269,31 @@ SELECT stddev_pop('nan'::numeric), stddev_samp('nan'::numeric); NaN | (1 row) +-- verify correct results for min(record) and max(record) aggregates +SELECT max(row(a,b)) FROM aggtest; + max +-------------- + (100,99.097) +(1 row) + +SELECT max(row(b,a)) FROM aggtest; + max +------------- + (324.78,42) +(1 row) + +SELECT min(row(a,b)) FROM aggtest; + min +------------- + (0,0.09561) +(1 row) + +SELECT min(row(b,a)) FROM aggtest; + min +------------- + (0.09561,0) +(1 row) + -- verify correct results for null and NaN inputs select sum(null::int4) from generate_series(1,3); sum diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql index 1a18ca3d8fe..ca6d1bcfb7f 100644 --- a/src/test/regress/sql/aggregates.sql +++ b/src/test/regress/sql/aggregates.sql @@ -78,6 +78,12 @@ SELECT stddev_pop('inf'::numeric), stddev_samp('inf'::numeric); SELECT var_pop('nan'::numeric), var_samp('nan'::numeric); SELECT stddev_pop('nan'::numeric), stddev_samp('nan'::numeric); +-- verify correct results for min(record) and max(record) aggregates +SELECT max(row(a,b)) FROM aggtest; +SELECT max(row(b,a)) FROM aggtest; +SELECT min(row(a,b)) FROM aggtest; +SELECT min(row(b,a)) FROM aggtest; + -- verify correct results for null and NaN inputs select sum(null::int4) from generate_series(1,3); select sum(null::int8) from generate_series(1,3);