From: Robert Haas Date: Fri, 23 Dec 2011 13:40:25 +0000 (-0500) Subject: Add bytea_agg, parallel to string_agg. X-Git-Tag: REL9_2_BETA1~656 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d5448c7d31b5af66a809e6580bae9bd31448bfa7;p=postgresql Add bytea_agg, parallel to string_agg. Pavel Stehule --- diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index e7f7fe0e88..2e06346584 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -10908,6 +10908,24 @@ SELECT NULLIF(value, '(none)') ... true if at least one input value is true, otherwise false + + + + bytea_agg + + + bytea_agg(expression) + + + + bytea + + + bytea + + input values concatenated into a bytea + + diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index 95893386aa..d66ba06540 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -396,6 +396,53 @@ byteasend(PG_FUNCTION_ARGS) PG_RETURN_BYTEA_P(vlena); } +Datum +bytea_agg_transfn(PG_FUNCTION_ARGS) +{ + StringInfo state; + + state = PG_ARGISNULL(0) ? NULL : (StringInfo) PG_GETARG_POINTER(0); + + /* Append the value unless null. */ + if (!PG_ARGISNULL(1)) + { + bytea *value = PG_GETARG_BYTEA_PP(1); + + if (state == NULL) + state = makeStringAggState(fcinfo); + + appendBinaryStringInfo(state, VARDATA_ANY(value), VARSIZE_ANY_EXHDR(value)); + } + + /* + * The transition type for bytea_agg() is declared to be "internal", + * which is a pass-by-value type the same size as a pointer. + */ + PG_RETURN_POINTER(state); +} + +Datum +bytea_agg_finalfn(PG_FUNCTION_ARGS) +{ + StringInfo state; + + /* cannot be called directly because of internal-type argument */ + Assert(AggCheckCallContext(fcinfo, NULL)); + + state = PG_ARGISNULL(0) ? NULL : (StringInfo) PG_GETARG_POINTER(0); + + if (state != NULL) + { + bytea *result; + + result = (bytea *) palloc(state->len + VARHDRSZ); + SET_VARSIZE(result, state->len + VARHDRSZ); + memcpy(VARDATA(result), state->data, state->len); + PG_RETURN_BYTEA_P(result); + } + else + PG_RETURN_NULL(); +} /* * textin - converts "..." to internal representation diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index f366d79366..94b7d89790 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201112221 +#define CATALOG_VERSION_NO 201112231 #endif diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h index 26966d2837..952e89c94a 100644 --- a/src/include/catalog/pg_aggregate.h +++ b/src/include/catalog/pg_aggregate.h @@ -226,6 +226,9 @@ DATA(insert ( 2335 array_agg_transfn array_agg_finalfn 0 2281 _null_ )); /* text */ DATA(insert ( 3538 string_agg_transfn string_agg_finalfn 0 2281 _null_ )); +/* bytea */ +DATA(insert ( 3545 bytea_agg_transfn bytea_agg_finalfn 0 2281 _null_ )); + /* * prototypes for functions in pg_aggregate.c */ diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index ffe0727972..32be6b1374 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -2403,12 +2403,19 @@ DATA(insert OID = 2816 ( float8_covar_samp PGNSP PGUID 12 1 0 0 0 f f f t f i DESCR("aggregate final function"); DATA(insert OID = 2817 ( float8_corr PGNSP PGUID 12 1 0 0 0 f f f t f i 1 0 701 "1022" _null_ _null_ _null_ _null_ float8_corr _null_ _null_ _null_ )); DESCR("aggregate final function"); + DATA(insert OID = 3535 ( string_agg_transfn PGNSP PGUID 12 1 0 0 0 f f f f f i 3 0 2281 "2281 25 25" _null_ _null_ _null_ _null_ string_agg_transfn _null_ _null_ _null_ )); DESCR("aggregate transition function"); DATA(insert OID = 3536 ( string_agg_finalfn PGNSP PGUID 12 1 0 0 0 f f f f f i 1 0 25 "2281" _null_ _null_ _null_ _null_ string_agg_finalfn _null_ _null_ _null_ )); DESCR("aggregate final function"); DATA(insert OID = 3538 ( string_agg PGNSP PGUID 12 1 0 0 0 t f f f f i 2 0 25 "25 25" _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )); DESCR("concatenate aggregate input into a string"); +DATA(insert OID = 3543 ( bytea_agg_transfn PGNSP PGUID 12 1 0 0 0 f f f f f i 2 0 2281 "2281 17" _null_ _null_ _null_ _null_ bytea_agg_transfn _null_ _null_ _null_ )); +DESCR("aggregate transition function"); +DATA(insert OID = 3544 ( bytea_agg_finalfn PGNSP PGUID 12 1 0 0 0 f f f f f i 1 0 17 "2281" _null_ _null_ _null_ _null_ bytea_agg_finalfn _null_ _null_ _null_ )); +DESCR("aggregate final function"); +DATA(insert OID = 3545 ( bytea_agg PGNSP PGUID 12 1 0 0 0 t f f f f i 1 0 17 "17" _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )); +DESCR("concatenate aggregate input into a bytea"); /* To ASCII conversion */ DATA(insert OID = 1845 ( to_ascii PGNSP PGUID 12 1 0 0 0 f f f t f i 1 0 25 "25" _null_ _null_ _null_ _null_ to_ascii_default _null_ _null_ _null_ )); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 217cd61c84..aa36db630f 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -769,6 +769,8 @@ extern Datum unknownsend(PG_FUNCTION_ARGS); extern Datum pg_column_size(PG_FUNCTION_ARGS); +extern Datum bytea_agg_transfn(PG_FUNCTION_ARGS); +extern Datum bytea_agg_finalfn(PG_FUNCTION_ARGS); extern Datum string_agg_transfn(PG_FUNCTION_ARGS); extern Datum string_agg_finalfn(PG_FUNCTION_ARGS); diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out index 2324c7cda8..2ec4eec59b 100644 --- a/src/test/regress/expected/aggregates.out +++ b/src/test/regress/expected/aggregates.out @@ -1061,3 +1061,26 @@ select string_agg(distinct f1::text, ',' order by f1::text) from varchar_tbl; - a,ab,abcd (1 row) +-- bytea_agg tests +create table bytea_test_table(v bytea); +select bytea_agg(v) from bytea_test_table; + bytea_agg +----------- + +(1 row) + +insert into bytea_test_table values(decode('ff','hex')); +select bytea_agg(v) from bytea_test_table; + bytea_agg +----------- + \xff +(1 row) + +insert into bytea_test_table values(decode('aa','hex')); +select bytea_agg(v) from bytea_test_table; + bytea_agg +----------- + \xffaa +(1 row) + +drop table bytea_test_table; diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql index 04ec67b33a..01c2e2d3ca 100644 --- a/src/test/regress/sql/aggregates.sql +++ b/src/test/regress/sql/aggregates.sql @@ -416,3 +416,18 @@ select string_agg(distinct f1, ',' order by f1) from varchar_tbl; -- ok select string_agg(distinct f1::text, ',' order by f1) from varchar_tbl; -- not ok 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 + +-- bytea_agg tests +create table bytea_test_table(v bytea); + +select bytea_agg(v) from bytea_test_table; + +insert into bytea_test_table values(decode('ff','hex')); + +select bytea_agg(v) from bytea_test_table; + +insert into bytea_test_table values(decode('aa','hex')); + +select bytea_agg(v) from bytea_test_table; + +drop table bytea_test_table;