create function first_nonnull( one anyelement, two anyelement )
returns anyelement
as $$
begin
return one;
end
$$
language plpgsql strict;
create function last_nonnull( one anyelement, two anyelement )
returns anyelement
as $$
begin
return two;
end
$$
language plpgsql strict;
create aggregate first_nonnull( anyelement )
(
stype = anyelement
, sfunc = first_nonnull
);
create aggregate last_nonnull( anyelement )
(
stype = anyelement
, sfunc = last_nonnull
);
create function first( head anyarray, tail anyelement )
returns anyarray
as $$
begin
if head is null or head = '{}' then
return ARRAY[tail];
end if;
return head;
end
$$
language plpgsql;
create function last( head anyarray, tail anyelement )
returns anyarray
as $$
begin
return ARRAY[tail];
end
$$
language plpgsql;
create function first( head anyarray )
returns anyelement
as $$
begin
return head[1];
end
$$
language plpgsql;
create aggregate first( anyelement )
(
stype = anyarray
, initcond = '{}'
, sfunc = first
, finalfunc = first
);
create aggregate last( anyelement )
(
stype = anyarray
, initcond = '{}'
, sfunc = last
, finalfunc = first
);
####
select first(v), first_nonnull(v), last(v), last_nonnull(v)
from ( select NULL::text as v union all
select 'one' as v union all select 'two' as v ) as q
union all
select first(v), first_nonnull(v), last(v), last_nonnull(v)
from ( select 'one'::text as v union all
select 'two' as v union all select NULL as v ) as q;
####
first | first_nonnull | last | last_nonnull
-------+---------------+------+--------------
| one | two | two
one | one | | two
(2 rows)