суббота, 23 октября 2010 г.

AGGREGATE_BITOR

  Агрегатные функции определенные пользователем, так называемые 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