Агрегатные функции определенные пользователем, так называемые user-defined aggregate functions создают используя следующий интерфейс
Это моя вторая функция, о AGGREGATE_STRING напишу чуть позднее. Реализовав AGGREGATE_BITOR, я конечно же зашел в поисковик и сразу же нашел аналог на Radino’s blog (Bitwise OR Aggregate Function).
Разница лишь в том, что я заменил "операцию логического побитового ИЛИ" одноименной функцией BITOR. Об этой, а также о других битовых функциях можно почитать на www.orafaq.com.
CREATE FUNCTION bitor(x IN NUMBER, y IN NUMBER) RETURN NUMBER AS
BEGIN
RETURN x + y - bitand(x,y);
END;
/
GRANT EXECUTE on BITOR to PUBLIC;
--User must have privilege create public synonym;
CREATE PUBLIC SYNONYM BITOR FOR BITOR;
Таким образом, код AGGREGATE_BITOR получился более понятен:
CREATE OR REPLACE TYPE T_AGGREGATE_BITOR as object (
value number,
static function ODCIAggregateInitialize(sctx in out t_aggregate_bitor)
return number,
member function ODCIAggregateIterate (self in out t_aggregate_bitor,
p_value in number)
return number,
member function ODCIAggregateTerminate (self in t_aggregate_bitor,
return_value out number,
flags in number )
return number,
member function ODCIAggregateMerge(self in out t_aggregate_bitor,
ctx2 in t_aggregate_bitor )
return number
);
/
CREATE OR REPLACE TYPE BODY T_AGGREGATE_BITOR is
static function ODCIAggregateInitialize(sctx in out t_aggregate_bitor)
return number is
begin
sctx := t_aggregate_bitor(0);
return ODCIConst.Success;
end;
member function ODCIAggregateIterate(
self in out t_aggregate_bitor, p_value in number)
return number is
begin
value := BITOR(value, p_value);
return ODCIConst.Success;
end;
member function ODCIAggregateTerminate(self in t_aggregate_bitor,
return_value out number, flags in number) return number is
begin
return_value := value;
return ODCIConst.Success;
end;
member function ODCIAggregateMerge(self in out t_aggregate_bitor,
ctx2 in t_aggregate_bitor) return number is
begin
value := BITOR(value, ctx2.value);
return ODCIConst.Success;
end;
end;
/
Сама агрегатная функция:
CREATE OR REPLACE FUNCTION AGGREGATE_BITOR (input NUMBER) return NUMBER
parallel_enable aggregate using T_AGGREGATE_BITOR;
/
CREATE PUBLIC SYNONYM AGGREGATE_BITOR FOR AGGREGATE_BITOR;
Проверим в действии, значение флагов для тестирования возьмем тут Bitwise OR Aggregate Function:
with bitor_test as (
select 'table1' name, 5 flags -- 0101
from dual
union all
select 'table2', 1 -- 0001
from dual
union all
select 'table3', 9 -- 1001
from dual
union all
select 'table4', 12 -- 1100
from dual
)
SELECT AGGREGATE_BITOR(flags) FROM bitor_test;
AGGREGATE_BITOR(FLAGS)
---------------------
13