aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/adt/varlena.c47
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/pg_aggregate.h3
-rw-r--r--src/include/catalog/pg_proc.h7
-rw-r--r--src/include/utils/builtins.h2
-rw-r--r--src/test/regress/expected/aggregates.out23
-rw-r--r--src/test/regress/sql/aggregates.sql15
7 files changed, 98 insertions, 1 deletions
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index 95893386aae..d66ba065400 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 f366d793661..94b7d897907 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 26966d28372..952e89c94aa 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 ffe07279726..32be6b13747 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 217cd61c849..aa36db630f4 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 2324c7cda82..2ec4eec59b3 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 04ec67b33af..01c2e2d3caf 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;