@@ -1361,6 +1361,9 @@ range_agg_transfn(PG_FUNCTION_ARGS)
13611361
13621362/*
13631363 * range_agg_finalfn: use our internal array to merge touching ranges.
1364+ *
1365+ * Shared by range_agg_finalfn(anyrange) and
1366+ * multirange_agg_finalfn(anymultirange).
13641367 */
13651368Datum
13661369range_agg_finalfn (PG_FUNCTION_ARGS )
@@ -1396,6 +1399,64 @@ range_agg_finalfn(PG_FUNCTION_ARGS)
13961399 PG_RETURN_MULTIRANGE_P (make_multirange (mltrngtypoid , typcache -> rngtype , range_count , ranges ));
13971400}
13981401
1402+ /*
1403+ * multirange_agg_transfn: combine adjacent/overlapping multiranges.
1404+ *
1405+ * All we do here is gather the input multiranges' ranges into an array so
1406+ * that the finalfn can sort and combine them.
1407+ */
1408+ Datum
1409+ multirange_agg_transfn (PG_FUNCTION_ARGS )
1410+ {
1411+ MemoryContext aggContext ;
1412+ Oid mltrngtypoid ;
1413+ TypeCacheEntry * typcache ;
1414+ TypeCacheEntry * rngtypcache ;
1415+ ArrayBuildState * state ;
1416+
1417+ if (!AggCheckCallContext (fcinfo , & aggContext ))
1418+ elog (ERROR , "multirange_agg_transfn called in non-aggregate context" );
1419+
1420+ mltrngtypoid = get_fn_expr_argtype (fcinfo -> flinfo , 1 );
1421+ if (!type_is_multirange (mltrngtypoid ))
1422+ elog (ERROR , "range_agg must be called with a multirange" );
1423+
1424+ typcache = multirange_get_typcache (fcinfo , mltrngtypoid );
1425+ rngtypcache = typcache -> rngtype ;
1426+
1427+ if (PG_ARGISNULL (0 ))
1428+ state = initArrayResult (rngtypcache -> type_id , aggContext , false);
1429+ else
1430+ state = (ArrayBuildState * ) PG_GETARG_POINTER (0 );
1431+
1432+ /* skip NULLs */
1433+ if (!PG_ARGISNULL (1 ))
1434+ {
1435+ MultirangeType * current ;
1436+ int32 range_count ;
1437+ RangeType * * ranges ;
1438+
1439+ current = PG_GETARG_MULTIRANGE_P (1 );
1440+ multirange_deserialize (rngtypcache , current , & range_count , & ranges );
1441+ if (range_count == 0 )
1442+ {
1443+ /*
1444+ * Add an empty range so we get an empty result (not a null result).
1445+ */
1446+ accumArrayResult (state ,
1447+ RangeTypePGetDatum (make_empty_range (rngtypcache )),
1448+ false, rngtypcache -> type_id , aggContext );
1449+ }
1450+ else
1451+ {
1452+ for (int32 i = 0 ; i < range_count ; i ++ )
1453+ accumArrayResult (state , RangeTypePGetDatum (ranges [i ]), false, rngtypcache -> type_id , aggContext );
1454+ }
1455+ }
1456+
1457+ PG_RETURN_POINTER (state );
1458+ }
1459+
13991460Datum
14001461multirange_intersect_agg_transfn (PG_FUNCTION_ARGS )
14011462{
0 commit comments