Пользовательская агрегатная функция внутри пакета

Я пытаюсь написать пользовательскую агрегатную функцию в Oracle и сгруппировать эту функцию внутри пакета вместе с некоторыми другими функциями, которые у меня есть. В качестве примера (для имитации моей проблемы) предположим, что моя пользовательская агрегация для суммирования чисел выглядит так:

CREATE OR REPLACE TYPE SUM_AGGREGATOR_TYPE AS OBJECT (
    summation NUMBER,

    STATIC FUNCTION ODCIAggregateInitialize(agg_context IN OUT
       SUM_AGGREGATOR_TYPE) RETURN NUMBER,

    MEMBER FUNCTION ODCIAggregateIterate(self IN OUT SUM_AGGREGATOR_TYPE,
        next_number IN NUMBER) RETURN NUMBER,

    MEMBER FUNCTION ODCIAggregateMerge(self IN OUT SUM_AGGREGATOR_TYPE,
        para_context IN SUM_AGGREGATOR_TYPE) RETURN NUMBER,

    MEMBER FUNCTION ODCIAggregateTerminate(self IN SUM_AGGREGATOR_TYPE,
        return_value OUT NUMBER, flags IN NUMBER) RETURN NUMBER
);

CREATE OR REPLACE TYPE BODY SUM_AGGREGATOR_TYPE IS

  STATIC FUNCTION ODCIAggregateInitialize(agg_context IN OUT
    SUM_AGGREGATOR_TYPE)
      RETURN NUMBER IS
  BEGIN
    agg_context := SUM_AGGREGATOR_TYPE(NULL);
    RETURN ODCIConst.Success;
  END;


  MEMBER FUNCTION ODCIAggregateIterate(self IN OUT SUM_AGGREGATOR_TYPE,
    next_number IN NUMBER)
      RETURN NUMBER IS
  BEGIN
    IF self.summation IS NULL THEN
        self.summation := next_number;
    ELSIF summation IS NOT NULL THEN
        self.summation := self.summation + next_number;
    END IF;
    RETURN ODCIConst.Success;
  END;

  MEMBER FUNCTION ODCIAggregateMerge(self IN OUT SUM_AGGREGATOR_TYPE,
    para_context IN SUM_AGGREGATOR_TYPE)
      RETURN NUMBER IS
  BEGIN
    self.summation := self.summation + para_context.summation;
    RETURN ODCIConst.Success;
  END;

  MEMBER FUNCTION ODCIAggregateTerminate(self IN SUM_AGGREGATOR_TYPE,
    return_value OUT NUMBER, flags IN NUMBER)
      RETURN NUMBER IS
  BEGIN
    return_value := self.summation;
    return ODCIConst.Success;
  END;

END;

Если я напишу следующее определение функции:

CREATE OR REPLACE FUNCTION MY_SUM(input NUMBER)
  RETURN NUMBER PARALLEL_ENABLE AGGREGATE USING SUM_AGGREGATOR_TYPE;

и соответствующее объявление типа для проверки:

CREATE OR REPLACE TYPE VECTOR
IS
  TABLE OF NUMBER;

это утверждение:

select my_sum(column_value) from table(vector(1, 2, 1, 45, 22, -1));

дает правильный результат 70. Однако создание пакета с определением функции:

CREATE OR REPLACE PACKAGE MY_FUNCTIONS AS
  FUNCTION MY_SUM(input NUMBER)
    RETURN NUMBER PARALLEL_ENABLE AGGREGATE USING SUM_AGGREGATOR_TYPE;
END;

и вызывая его через:

select MY_FUNCTIONS.my_sum(column_value) from table(vector(1, 2, 1, 45, 22, -1));

взрывается с

ORA-00600: internal error code, arguments: [17090], [], [], [], [], [], [], [], [], [], [], [] 

Возможно ли иметь пользовательские агрегатные функции, вложенные в объявления пакетов?


person wcmatthysen    schedule 30.11.2010    source источник
comment
«ORA-00600» обычно указывает на ошибку Oracle — иногда из-за неожиданных комбинаций функций. Какую именно версию Oracle вы используете?   -  person Jeffrey Kemp    schedule 30.11.2010
comment
Я использую Oracle 11g Release 2 (11.2.0.1.0).   -  person wcmatthysen    schedule 30.11.2010
comment
Есть ли у вас новости по этому вопросу? У меня тоже проблемы, но в моем случае соединение обрывается ORA-03113: end-of-file on communication channel. Думаю, это даже хуже, чем ORA-00600. Когда я проверяю SELECT * FROM ALL_PROCEDURES, я вижу, что определяемый пользователем агрегат был правильно создан и зарегистрирован...   -  person Lukas Eder    schedule 05.08.2012
comment
Нет, пока ничего не слышал. Я опубликовал сообщение об этой ошибке на форумах Oracle. Не стесняйтесь следите за моим сообщением там.   -  person wcmatthysen    schedule 24.09.2012


Ответы (1)


Oracle использует ORA-00600 для оповещения о необработанных исключениях, т. е. об ошибках. Первый аргумент указывает на исключение; ORA-17090 — это общая «операция не разрешена». Часто они ограничены определенными перестановками версии базы данных и платформы ОС. В других случаях это просто означает, что мы делаем что-то действительно необычное.

Считается ли включение пользовательской агрегатной функции внутри пакета «действительно необычным»? Не уверена. Конечно, нам разрешено включать функции картриджей данных в функции PL/SQL. Но определяемые пользователем агрегаты — это особый случай ODCI. Хотя в документации нет явного правила против пакетов, все примеры реализуют агрегат с использованием CREATE FUNCTION.

Так что делать? Что ж, сообщения ORA-00600 требуют вмешательства службы поддержки Oracle, так как для этого требуется исправление. Если у вас есть учетная запись службы поддержки, вы можете узнайте больше об этой проблеме здесь. Вам нужно будет поднять iTAR, чтобы получить дальнейшее разрешение. В противном случае, боюсь, вам не повезло.

person APC    schedule 30.11.2010
comment
Странно, что это не поддерживается. Я опубликую это на форумах Oracle, чтобы узнать, что они скажут. - person wcmatthysen; 30.11.2010
comment
Создано сообщение на форуме Oracle: forums.oracle.com/forums/ так что ребята из Oracle могут проследить за этим. - person wcmatthysen; 01.12.2010
comment
На вопрос, который я задал здесь , кажется, что определяемая пользователем агрегатная функция работает, когда вы создаете только функцию, но не работает внутри пакета. В моем случае (~ 3 года спустя) ошибка не выдается, но возвращается неверный вывод. Итак, всем, кто, как и я, натыкается на этот вопрос: если ваши определяемые пользователем агрегатные функции не работают в пакете, попробуйте использовать только функцию. - person Lawtonfogle; 14.08.2013
comment
Это верно, определение функции вне пакета является решением, однако весь смысл использования пакета заключается в том, чтобы избежать загрязнения пространства имен путем группировки связанных функций/процедур внутри пакета. - person wcmatthysen; 15.08.2013