P8-Panels/db/PKG_P8PANELS_VISUAL.pck

1132 lines
61 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

create or replace package PKG_P8PANELS_VISUAL as
/* Константы - типы данных */
SDATA_TYPE_STR constant PKG_STD.TSTRING := 'STR'; -- Тип данных "строка"
SDATA_TYPE_NUMB constant PKG_STD.TSTRING := 'NUMB'; -- Тип данных "число"
SDATA_TYPE_DATE constant PKG_STD.TSTRING := 'DATE'; -- Тип данных "дата"
/* Константы - направление сортировки */
SORDER_DIRECTION_ASC constant PKG_STD.TSTRING := 'ASC'; -- По возрастанию
SORDER_DIRECTION_DESC constant PKG_STD.TSTRING := 'DESC'; -- По убыванию
/* Типы данных - значение колонки таблицы данных */
type TCOL_VAL is record
(
SVALUE PKG_STD.TLSTRING, -- Значение (строка)
NVALUE PKG_STD.TNUMBER, -- Значение (число)
DVALUE PKG_STD.TLDATE -- Значение (дата)
);
/* Типы данных - коллекция значений колонки таблицы данных */
type TCOL_VALS is table of TCOL_VAL;
/* Типы данных - описатель колонки таблицы данных */
type TCOL_DEF is record
(
SNAME PKG_STD.TSTRING, -- Наименование
SCAPTION PKG_STD.TSTRING, -- Заголовок
SDATA_TYPE PKG_STD.TSTRING, -- Тип данных (см. константы SDATA_TYPE_*)
SCOND_FROM PKG_STD.TSTRING, -- Наименование нижней границы условия отбора
SCOND_TO PKG_STD.TSTRING, -- Наименование верхней границы условия отбора
BVISIBLE boolean, -- Разрешить отображение
BORDER boolean, -- Разрешить сортировку
BFILTER boolean, -- Разрешить отбор
RCOL_VALS TCOL_VALS -- Предопределённые значения
);
/* Типы данных - коллекция описателей колонок таблицы данных */
type TCOL_DEFS is table of TCOL_DEF;
/* Типы данных - колонка */
type TCOL is record
(
SNAME PKG_STD.TSTRING, -- Наименование
RCOL_VAL TCOL_VAL -- Значение
);
/* Типы данных - коллекция колонок */
type TCOLS is table of TCOL;
/* Типы данных - строка */
type TROW is record
(
RCOLS TCOLS -- Колонки
);
/* Типы данных - коллекция строк */
type TROWS is table of TROW;
/* Типы данных - таблица данных */
type TDATA_GRID is record
(
RCOL_DEFS TCOL_DEFS, -- Описание колонок
RROWS TROWS -- Данные строк
);
/* Типы данных - фильтр */
type TFILTER is record
(
SNAME PKG_STD.TSTRING, -- Наименование
SFROM PKG_STD.TSTRING, -- Значение "с"
STO PKG_STD.TSTRING -- Значение "по"
);
/* Типы данных - коллекция фильтров */
type TFILTERS is table of TFILTER;
/* Типы данных - сортировка */
type TORDER is record
(
SNAME PKG_STD.TSTRING, -- Наименование
SDIRECTION PKG_STD.TSTRING -- Направление (см. константы SORDER_DIRECTION_*)
);
/* Типы данных - коллекция сортировок */
type TORDERS is table of TORDER;
/* Расчет диапаона выдаваемых записей */
procedure UTL_ROWS_LIMITS_CALC
(
NPAGE_NUMBER in number, -- Номер страницы (игнорируется при NPAGE_SIZE=0)
NPAGE_SIZE in number, -- Количество записей на странице (0 - все)
NROW_FROM out number, -- Нижняя граница диапазона
NROW_TO out number -- Верхняя граница диапазона
);
/* Формирование наименования условия отбора для нижней границы */
function UTL_COND_NAME_MAKE_FROM
(
SNAME in varchar2 -- Наименование колонки
) return varchar2; -- Результат
/* Формирование наименования условия отбора для верхней границы */
function UTL_COND_NAME_MAKE_TO
(
SNAME in varchar2 -- Наименование колонки
) return varchar2; -- Результат
/* Добавление значения в коллекцию */
procedure TCOL_VALS_ADD
(
RCOL_VALS in out nocopy TCOL_VALS, -- Коллекция значений
SVALUE in varchar2 := null, -- Значение (строка)
NVALUE in number := null, -- Значение (число)
DVALUE in date := null, -- Значение (дата)
BCLEAR in boolean := false -- Флаг очистки коллекции (false - не очищать, true - очистить коллекцию перед добавлением)
);
/* Формирование строки */
function TROW_MAKE
return TROW; -- Результат работы
/* Добавление колонки к строке */
procedure TROW_ADD_COL
(
RROW in out nocopy TROW, -- Строка
SNAME in varchar2, -- Наименование колонки
SVALUE in varchar2 := null, -- Значение (строка)
NVALUE in number := null, -- Значение (число)
DVALUE in date := null, -- Значение (дата)
BCLEAR in boolean := false -- Флаг очистки коллекции (false - не очищать, true - очистить коллекцию перед добавлением)
);
/* Добавление строковой колонки к строке из курсора динамического запроса */
procedure TROW_ADD_CUR_COLS
(
RROW in out nocopy TROW, -- Строка
SNAME in varchar2, -- Наименование колонки
ICURSOR in integer, -- Курсор
NPOSITION in number, -- Номер колонки в курсоре
BCLEAR in boolean := false -- Флаг очистки коллекции (false - не очищать, true - очистить коллекцию перед добавлением)
);
/* Добавление числовой колонки к строке из курсора динамического запроса */
procedure TROW_ADD_CUR_COLN
(
RROW in out nocopy TROW, -- Строка
SNAME in varchar2, -- Наименование колонки
ICURSOR in integer, -- Курсор
NPOSITION in number, -- Номер колонки в курсоре
BCLEAR in boolean := false -- Флаг очистки коллекции (false - не очищать, true - очистить коллекцию перед добавлением)
);
/* Добавление колонки типа "дата" к строке из курсора динамического запроса */
procedure TROW_ADD_CUR_COLD
(
RROW in out nocopy TROW, -- Строка
SNAME in varchar2, -- Наименование колонки
ICURSOR in integer, -- Курсор
NPOSITION in number, -- Номер колонки в курсоре
BCLEAR in boolean := false -- Флаг очистки коллекции (false - не очищать, true - очистить коллекцию перед добавлением)
);
/* Формирование таблицы данныз */
function TDATA_GRID_MAKE
return TDATA_GRID; -- Результат работы
/* Поиск описания колонки в таблице данных по наименованию */
function TDATA_GRID_FIND_COL_DEF
(
RDATA_GRID in TDATA_GRID, -- Описание таблицы данных
SNAME in varchar2 -- Наименование колонки
) return TCOL_DEF; -- Найденное описание (null - если не нашли)
/* Добавление описания колонки к таблице данных */
procedure TDATA_GRID_ADD_COL_DEF
(
RDATA_GRID in out nocopy TDATA_GRID, -- Описание таблицы данных
SNAME in varchar2, -- Наименование колонки
SCAPTION in varchar2, -- Заголовок колонки
SDATA_TYPE in varchar2 := SDATA_TYPE_STR, -- Тип данных колонки (см. константы SDATA_TYPE_*)
SCOND_FROM in varchar2 := null, -- Наименование нижней границы условия отбора (null - используется UTL_COND_NAME_MAKE_FROM)
SCOND_TO in varchar2 := null, -- Наименование верхней границы условия отбора (null - используется UTL_COND_NAME_MAKE_TO)
BVISIBLE in boolean := true, -- Разрешить отображение
BORDER in boolean := false, -- Разрешить сортировку по колонке
BFILTER in boolean := false, -- Разрешить отбор по колонке
RCOL_VALS in TCOL_VALS := null, -- Предопределённые значения колонки
BCLEAR in boolean := false -- Флаг очистки коллекции описаний колонок таблицы данных (false - не очищать, true - очистить коллекцию перед добавлением)
);
/* Добавление описания колонки к таблице данных */
procedure TDATA_GRID_ADD_ROW
(
RDATA_GRID in out nocopy TDATA_GRID, -- Описание таблицы данных
RROW in TROW, -- Строка
BCLEAR in boolean := false -- Флаг очистки коллекции строк таблицы данных (false - не очищать, true - очистить коллекцию перед добавлением)
);
/* Сериализация таблицы данных */
function TDATA_GRID_TO_XML
(
RDATA_GRID in TDATA_GRID, -- Описание таблицы данных
NINCLUDE_DEF in number := 1 -- Включить описание колонок (0 - нет, 1 - да)
) return clob; -- XML-описание
/* Конвертация значений фильтра в число */
procedure TFILTER_TO_NUMBER
(
RFILTER in TFILTER, -- Фильтр
NFROM out number, -- Значение нижней границы диапазона
NTO out number -- Значение верхней границы диапазона
);
/* Конвертация значений фильтра в дату */
procedure TFILTER_TO_DATE
(
RFILTER in TFILTER, -- Фильтр
DFROM out date, -- Значение нижней границы диапазона
DTO out date -- Значение верхней границы диапазона
);
/* Поиск фильтра в коллекции */
function TFILTERS_FIND
(
RFILTERS in TFILTERS, -- Коллекция фильтров
SNAME in varchar2 -- Наименование
) return TFILTER; -- Найденный фильтр (null - если не нашли)
/* Десериализация фильтров */
function TFILTERS_FROM_XML
(
CFILTERS in clob -- Сериализованное представление фильтров (BASE64(<filters><name>ИМЯ</name><from>ЗНАЧЕНИЕ</from><to>ЗНАЧЕНИЕ</to></filters>...))
) return TFILTERS; -- Результат работы
/* Применение параметров фильтрации в запросе */
procedure TFILTERS_SET_QUERY
(
NIDENT in number, -- Идентификатор отбора
NCOMPANY in number, -- Рег. номер организации
NPARENT in number := null, -- Рег. номер родителя
SUNIT in varchar2, -- Код раздела
SPROCEDURE in varchar2, -- Наименование серверной процедуры отбора
RDATA_GRID in TDATA_GRID, -- Описание таблицы данных
RFILTERS in TFILTERS -- Коллекция фильтров
);
/* Десериализация сортировок */
function TORDERS_FROM_XML
(
CORDERS in clob -- Сериализованное представление сотрировок (BASE64(<orders><name>ИМЯ</name><direction>ASC/DESC</direction></orders>...))
) return TORDERS; -- Результат работы
/* Применение параметров сортировки в запросе */
procedure TORDERS_SET_QUERY
(
RDATA_GRID in TDATA_GRID, -- Описание таблицы
RORDERS in TORDERS, -- Коллекция сортировок
SPATTERN in varchar2, -- Шаблон для подстановки условий отбора в запрос
CSQL in out nocopy clob -- Буфер запроса
);
end PKG_P8PANELS_VISUAL;
/
create or replace package body PKG_P8PANELS_VISUAL as
/* Константы - тэги запросов */
SRQ_TAG_XROOT constant PKG_STD.TSTRING := 'XROOT'; -- Тэг для корня данных запроса
SRQ_TAG_XFILTERS constant PKG_STD.TSTRING := 'filters'; -- Тэг для строк данных
SRQ_TAG_XORDERS constant PKG_STD.TSTRING := 'orders'; -- Тэг для описания колонок
SRQ_TAG_SNAME constant PKG_STD.TSTRING := 'name'; -- Тэг для наименования
SRQ_TAG_SDIRECTION constant PKG_STD.TSTRING := 'direction'; -- Тэг для направления
SRQ_TAG_SFROM constant PKG_STD.TSTRING := 'from'; -- Тэг для значения "с"
SRQ_TAG_STO constant PKG_STD.TSTRING := 'to'; -- Тэг для значения "по"
/* Константы - тэги ответов */
SRESP_TAG_XDATA constant PKG_STD.TSTRING := 'XDATA'; -- Тэг для корня описания данных
SRESP_TAG_XROWS constant PKG_STD.TSTRING := 'XROWS'; -- Тэг для строк данных
SRESP_TAG_XCOLUMNS_DEF constant PKG_STD.TSTRING := 'XCOLUMNS_DEF'; -- Тэг для описания колонок
/* Константы - атрибуты ответов */
SRESP_ATTR_NAME constant PKG_STD.TSTRING := 'name'; -- Атрибут для наименования
SRESP_ATTR_CAPTION constant PKG_STD.TSTRING := 'caption'; -- Атрибут для подписи
SRESP_ATTR_DATA_TYPE constant PKG_STD.TSTRING := 'dataType'; -- Атрибут для типа данных
SRESP_ATTR_VISIBLE constant PKG_STD.TSTRING := 'visible'; -- Атрибут для флага видимости
SRESP_ATTR_ORDER constant PKG_STD.TSTRING := 'order'; -- Атрибут для флага сортировки
SRESP_ATTR_FILTER constant PKG_STD.TSTRING := 'filter'; -- Атрибут для флага отбора
SRESP_ATTR_VALUES constant PKG_STD.TSTRING := 'values'; -- Атрибут для значений
/* Константы - параметры условий отбора */
SCOND_FROM_POSTFIX constant PKG_STD.TSTRING := 'From'; -- Постфикс наименования нижней границы условия отбора
SCOND_TO_POSTFIX constant PKG_STD.TSTRING := 'To'; -- Постфикс наименования верхней границы условия отбора
/* Расчет диапаона выдаваемых записей */
procedure UTL_ROWS_LIMITS_CALC
(
NPAGE_NUMBER in number, -- Номер страницы (игнорируется при NPAGE_SIZE=0)
NPAGE_SIZE in number, -- Количество записей на странице (0 - все)
NROW_FROM out number, -- Нижняя граница диапазона
NROW_TO out number -- Верхняя граница диапазона
)
is
begin
if (COALESCE(NPAGE_SIZE, 0) <= 0)
then
NROW_FROM := 1;
NROW_TO := 1000000000;
else
NROW_FROM := COALESCE(NPAGE_NUMBER, 1) * NPAGE_SIZE - NPAGE_SIZE + 1;
NROW_TO := COALESCE(NPAGE_NUMBER, 1) * NPAGE_SIZE;
end if;
end UTL_ROWS_LIMITS_CALC;
/* Формирование наименования условия отбора для нижней границы */
function UTL_COND_NAME_MAKE_FROM
(
SNAME in varchar2 -- Наименование колонки
) return varchar2 -- Результат
is
begin
return SNAME || SCOND_FROM_POSTFIX;
end UTL_COND_NAME_MAKE_FROM;
/* Формирование наименования условия отбора для верхней границы */
function UTL_COND_NAME_MAKE_TO
(
SNAME in varchar2 -- Наименование колонки
) return varchar2 -- Результат
is
begin
return SNAME || SCOND_TO_POSTFIX;
end UTL_COND_NAME_MAKE_TO;
/* Формирование значения */
function TCOL_VAL_MAKE
(
SVALUE in varchar2, -- Значение (строка)
NVALUE in number, -- Значение (число)
DVALUE in date -- Значение (дата)
) return TCOL_VAL -- Результат работы
is
RRES TCOL_VAL; -- Буфер для результата
begin
/* Формируем объект */
RRES.SVALUE := SVALUE;
RRES.NVALUE := NVALUE;
RRES.DVALUE := DVALUE;
/* Возвращаем результат */
return RRES;
end TCOL_VAL_MAKE;
/* Добавление значения в коллекцию */
procedure TCOL_VALS_ADD
(
RCOL_VALS in out nocopy TCOL_VALS, -- Коллекция значений
SVALUE in varchar2 := null, -- Значение (строка)
NVALUE in number := null, -- Значение (число)
DVALUE in date := null, -- Значение (дата)
BCLEAR in boolean := false -- Флаг очистки коллекции (false - не очищать, true - очистить коллекцию перед добавлением)
)
is
begin
/* Инициализируем коллекцию если необходимо */
if ((RCOL_VALS is null) or (BCLEAR)) then
RCOL_VALS := TCOL_VALS();
end if;
/* Добавляем элемент */
RCOL_VALS.EXTEND();
RCOL_VALS(RCOL_VALS.LAST) := TCOL_VAL_MAKE(SVALUE => SVALUE, NVALUE => NVALUE, DVALUE => DVALUE);
end TCOL_VALS_ADD;
/* Формирование описания колонки */
function TCOL_DEF_MAKE
(
SNAME in varchar2, -- Наименование
SCAPTION in varchar2, -- Заголовок
SDATA_TYPE in varchar2 := SDATA_TYPE_STR, -- Тип данных (см. константы SDATA_TYPE_*)
SCOND_FROM in varchar2 := null, -- Наименование нижней границы условия отбора (null - используется UTL_COND_NAME_MAKE_FROM)
SCOND_TO in varchar2 := null, -- Наименование верхней границы условия отбора (null - используется UTL_COND_NAME_MAKE_TO)
BVISIBLE in boolean := true, -- Разрешить отображение
BORDER in boolean := false, -- Разрешить сортировку
BFILTER in boolean := false, -- Разрешить отбор
RCOL_VALS in TCOL_VALS := null -- Предопределённые значения
) return TCOL_DEF -- Результат работы
is
RRES TCOL_DEF; -- Буфер для результата
begin
/* Формируем объект */
RRES.SNAME := SNAME;
RRES.SCAPTION := SCAPTION;
RRES.SDATA_TYPE := COALESCE(SDATA_TYPE, SDATA_TYPE_STR);
RRES.SCOND_FROM := COALESCE(SCOND_FROM, UTL_COND_NAME_MAKE_FROM(SNAME => SNAME));
RRES.SCOND_TO := COALESCE(SCOND_TO, UTL_COND_NAME_MAKE_TO(SNAME => SNAME));
RRES.BVISIBLE := COALESCE(BVISIBLE, true);
RRES.BORDER := COALESCE(BORDER, false);
RRES.BFILTER := COALESCE(BFILTER, false);
RRES.RCOL_VALS := COALESCE(RCOL_VALS, TCOL_VALS());
/* Возвращаем результат */
return RRES;
end TCOL_DEF_MAKE;
/* Добавление описания колонки в коллекцию */
procedure TCOL_DEFS_ADD
(
RCOL_DEFS in out nocopy TCOL_DEFS, -- Коллекция описаний колонок
SNAME in varchar2, -- Наименование
SCAPTION in varchar2, -- Заголовок
SDATA_TYPE in varchar2 := SDATA_TYPE_STR, -- Тип данных (см. константы SDATA_TYPE_*)
SCOND_FROM in varchar2 := null, -- Наименование нижней границы условия отбора (null - используется UTL_COND_NAME_MAKE_FROM)
SCOND_TO in varchar2 := null, -- Наименование верхней границы условия отбора (null - используется UTL_COND_NAME_MAKE_TO)
BVISIBLE in boolean := true, -- Разрешить отображение
BORDER in boolean := false, -- Разрешить сортировку
BFILTER in boolean := false, -- Разрешить отбор
RCOL_VALS in TCOL_VALS := null, -- Предопределённые значения
BCLEAR in boolean := false -- Флаг очистки коллекции (false - не очищать, true - очистить коллекцию перед добавлением)
)
is
begin
/* Инициализируем коллекцию если необходимо */
if ((RCOL_DEFS is null) or (BCLEAR)) then
RCOL_DEFS := TCOL_DEFS();
end if;
/* Добавляем элемент */
RCOL_DEFS.EXTEND();
RCOL_DEFS(RCOL_DEFS.LAST) := TCOL_DEF_MAKE(SNAME => SNAME,
SCAPTION => SCAPTION,
SDATA_TYPE => SDATA_TYPE,
SCOND_FROM => SCOND_FROM,
SCOND_TO => SCOND_TO,
BVISIBLE => BVISIBLE,
BORDER => BORDER,
BFILTER => BFILTER,
RCOL_VALS => RCOL_VALS);
end TCOL_DEFS_ADD;
/* Поиск описания колонки по наименованию */
function TCOL_DEFS_FIND
(
RCOL_DEFS in TCOL_DEFS, -- Описание колонок таблицы данных
SNAME in varchar2 -- Наименование
) return TCOL_DEF -- Найденное описание (null - если не нашли)
is
begin
/* Обходим колонки из коллекции описаний */
if ((RCOL_DEFS is not null) and (RCOL_DEFS.COUNT > 0)) then
for I in RCOL_DEFS.FIRST .. RCOL_DEFS.LAST
loop
if (RCOL_DEFS(I).SNAME = SNAME) then
return RCOL_DEFS(I);
end if;
end loop;
end if;
/* Ничего не нашли */
return null;
end TCOL_DEFS_FIND;
/* Сериализация описания колонки таблицы данных */
procedure TCOL_DEFS_TO_XML
(
RCOL_DEFS in TCOL_DEFS -- Описание колонок таблицы данных
)
is
begin
/* Обходим колонки из коллекции */
if ((RCOL_DEFS is not null) and (RCOL_DEFS.COUNT > 0)) then
for I in RCOL_DEFS.FIRST .. RCOL_DEFS.LAST
loop
/* Открываем описание колонки */
PKG_XFAST.DOWN_NODE(SNAME => SRESP_TAG_XCOLUMNS_DEF);
/* Атрибуты колонки */
PKG_XFAST.ATTR(SNAME => SRESP_ATTR_NAME, SVALUE => RCOL_DEFS(I).SNAME);
PKG_XFAST.ATTR(SNAME => SRESP_ATTR_CAPTION, SVALUE => RCOL_DEFS(I).SCAPTION);
PKG_XFAST.ATTR(SNAME => SRESP_ATTR_DATA_TYPE, SVALUE => RCOL_DEFS(I).SDATA_TYPE);
PKG_XFAST.ATTR(SNAME => SRESP_ATTR_VISIBLE, BVALUE => RCOL_DEFS(I).BVISIBLE);
PKG_XFAST.ATTR(SNAME => SRESP_ATTR_ORDER, BVALUE => RCOL_DEFS(I).BORDER);
PKG_XFAST.ATTR(SNAME => SRESP_ATTR_FILTER, BVALUE => RCOL_DEFS(I).BFILTER);
/* Предопределённые значения */
if (RCOL_DEFS(I).RCOL_VALS is not null) and (RCOL_DEFS(I).RCOL_VALS.COUNT > 0) then
for V in RCOL_DEFS(I).RCOL_VALS.FIRST .. RCOL_DEFS(I).RCOL_VALS.LAST
loop
/* Открываем описание предопределённого значения */
PKG_XFAST.DOWN_NODE(SNAME => SRESP_ATTR_VALUES);
/* Значение */
case RCOL_DEFS(I).SDATA_TYPE
when SDATA_TYPE_STR then
PKG_XFAST.VALUE(SVALUE => RCOL_DEFS(I).RCOL_VALS(V).SVALUE);
when SDATA_TYPE_NUMB then
PKG_XFAST.VALUE(NVALUE => RCOL_DEFS(I).RCOL_VALS(V).NVALUE);
when SDATA_TYPE_DATE then
PKG_XFAST.VALUE(DVALUE => RCOL_DEFS(I).RCOL_VALS(V).DVALUE);
else
P_EXCEPTION(0,
'Описание колонки "%s" таблицы данных содержит неподдерживаемый тип данных ("%s").',
COALESCE(RCOL_DEFS(I).SNAME, '<НЕ ОПРЕДЕЛЕНА>'),
COALESCE(RCOL_DEFS(I).SDATA_TYPE, '<НЕ ОПРЕДЕЛЁН>'));
end case;
/* Закрываем описание предопределённого значения */
PKG_XFAST.UP();
end loop;
end if;
/* Закрываем описание колонки */
PKG_XFAST.UP();
end loop;
end if;
end TCOL_DEFS_TO_XML;
/* Формирование колонки */
function TCOL_MAKE
(
SNAME in varchar2, -- Наименование колонки
SVALUE in varchar2 := null, -- Значение (строка)
NVALUE in number := null, -- Значение (число)
DVALUE in date := null -- Значение (дата)
) return TCOL -- Результат работы
is
RRES TCOL; -- Буфер для результата
begin
/* Формируем объект */
RRES.SNAME := SNAME;
RRES.RCOL_VAL := TCOL_VAL_MAKE(SVALUE => SVALUE, NVALUE => NVALUE, DVALUE => DVALUE);
/* Возвращаем результат */
return RRES;
end TCOL_MAKE;
/* Добавление колонки в коллекцию */
procedure TCOLS_ADD
(
RCOLS in out nocopy TCOLS, -- Коллекция колонок
SNAME in varchar2, -- Наименование колонки
SVALUE in varchar2 := null, -- Значение (строка)
NVALUE in number := null, -- Значение (число)
DVALUE in date := null, -- Значение (дата)
BCLEAR in boolean := false -- Флаг очистки коллекции (false - не очищать, true - очистить коллекцию перед добавлением)
)
is
begin
/* Инициализируем коллекцию если необходимо */
if ((RCOLS is null) or (BCLEAR)) then
RCOLS := TCOLS();
end if;
/* Добавляем элемент */
RCOLS.EXTEND();
RCOLS(RCOLS.LAST) := TCOL_MAKE(SNAME => SNAME, SVALUE => SVALUE, NVALUE => NVALUE, DVALUE => DVALUE);
end TCOLS_ADD;
/* Формирование строки */
function TROW_MAKE
return TROW -- Результат работы
is
RRES TROW; -- Буфер для результата
begin
/* Формируем объект */
RRES.RCOLS := TCOLS();
/* Возвращаем результат */
return RRES;
end TROW_MAKE;
/* Добавление колонки к строке */
procedure TROW_ADD_COL
(
RROW in out nocopy TROW, -- Строка
SNAME in varchar2, -- Наименование колонки
SVALUE in varchar2 := null, -- Значение (строка)
NVALUE in number := null, -- Значение (число)
DVALUE in date := null, -- Значение (дата)
BCLEAR in boolean := false -- Флаг очистки коллекции (false - не очищать, true - очистить коллекцию перед добавлением)
)
is
begin
/* Сформируем колонку и добавим её к коллекции колонок строки */
TCOLS_ADD(RCOLS => RROW.RCOLS, SNAME => SNAME, SVALUE => SVALUE, NVALUE => NVALUE, DVALUE => DVALUE, BCLEAR => BCLEAR);
end TROW_ADD_COL;
/* Добавление строковой колонки к строке из курсора динамического запроса */
procedure TROW_ADD_CUR_COLS
(
RROW in out nocopy TROW, -- Строка
SNAME in varchar2, -- Наименование колонки
ICURSOR in integer, -- Курсор
NPOSITION in number, -- Номер колонки в курсоре
BCLEAR in boolean := false -- Флаг очистки коллекции (false - не очищать, true - очистить коллекцию перед добавлением)
)
is
SVALUE PKG_STD.TLSTRING; -- Буфер для значения курсора
begin
/* Читаем данные из курсора */
PKG_SQL_DML.COLUMN_VALUE_STR(ICURSOR => ICURSOR, IPOSITION => NPOSITION, SVALUE => SVALUE);
/* Сформируем колонку и добавим её к коллекции колонок строки */
TCOLS_ADD(RCOLS => RROW.RCOLS, SNAME => SNAME, SVALUE => SVALUE, NVALUE => null, DVALUE => null, BCLEAR => BCLEAR);
end TROW_ADD_CUR_COLS;
/* Добавление числовой колонки к строке из курсора динамического запроса */
procedure TROW_ADD_CUR_COLN
(
RROW in out nocopy TROW, -- Строка
SNAME in varchar2, -- Наименование колонки
ICURSOR in integer, -- Курсор
NPOSITION in number, -- Номер колонки в курсоре
BCLEAR in boolean := false -- Флаг очистки коллекции (false - не очищать, true - очистить коллекцию перед добавлением)
)
is
NVALUE PKG_STD.TNUMBER; -- Буфер для значения курсора
begin
/* Читаем данные из курсора */
PKG_SQL_DML.COLUMN_VALUE_NUM(ICURSOR => ICURSOR, IPOSITION => NPOSITION, NVALUE => NVALUE);
/* Сформируем колонку и добавим её к коллекции колонок строки */
TCOLS_ADD(RCOLS => RROW.RCOLS, SNAME => SNAME, SVALUE => null, NVALUE => NVALUE, DVALUE => null, BCLEAR => BCLEAR);
end TROW_ADD_CUR_COLN;
/* Добавление колонки типа "дата" к строке из курсора динамического запроса */
procedure TROW_ADD_CUR_COLD
(
RROW in out nocopy TROW, -- Строка
SNAME in varchar2, -- Наименование колонки
ICURSOR in integer, -- Курсор
NPOSITION in number, -- Номер колонки в курсоре
BCLEAR in boolean := false -- Флаг очистки коллекции (false - не очищать, true - очистить коллекцию перед добавлением)
)
is
DVALUE PKG_STD.TLDATE; -- Буфер для значения курсора
begin
/* Читаем данные из курсора */
PKG_SQL_DML.COLUMN_VALUE_DATE(ICURSOR => ICURSOR, IPOSITION => NPOSITION, DVALUE => DVALUE);
/* Сформируем колонку и добавим её к коллекции колонок строки */
TCOLS_ADD(RCOLS => RROW.RCOLS, SNAME => SNAME, SVALUE => null, NVALUE => null, DVALUE => DVALUE, BCLEAR => BCLEAR);
end TROW_ADD_CUR_COLD;
/* Сериализация строки данных таблицы данных */
procedure TROWS_TO_XML
(
RCOL_DEFS in TCOL_DEFS, -- Описание колонок таблицы данных
RROWS in TROWS -- Строки таблицы данных
)
is
RCOL_DEF TCOL_DEF; -- Описание текущей сериализуемой колонки
begin
/* Обходим строки из коллекции */
if ((RROWS is not null) and (RROWS.COUNT > 0)) then
for I in RROWS.FIRST .. RROWS.LAST
loop
/* Открываем строку */
PKG_XFAST.DOWN_NODE(SNAME => SRESP_TAG_XROWS);
/* Обходим колонки строки */
if ((RROWS(I).RCOLS is not null) and (RROWS(I).RCOLS.COUNT > 0)) then
for J in RROWS(I).RCOLS.FIRST .. RROWS(I).RCOLS.LAST
loop
/* Найдём описание колонки */
RCOL_DEF := TCOL_DEFS_FIND(RCOL_DEFS => RCOL_DEFS, SNAME => RROWS(I).RCOLS(J).SNAME);
if (RCOL_DEF.SNAME is null) then
P_EXCEPTION(0,
'Описание колонки "%s" таблицы данных не определено.',
RROWS(I).RCOLS(J).SNAME);
end if;
/* Добавлением значение колонки как атрибут строки */
case RCOL_DEF.SDATA_TYPE
when SDATA_TYPE_STR then
PKG_XFAST.ATTR(SNAME => RROWS(I).RCOLS(J).SNAME, SVALUE => RROWS(I).RCOLS(J).RCOL_VAL.SVALUE);
when SDATA_TYPE_NUMB then
PKG_XFAST.ATTR(SNAME => RROWS(I).RCOLS(J).SNAME, NVALUE => RROWS(I).RCOLS(J).RCOL_VAL.NVALUE);
when SDATA_TYPE_DATE then
PKG_XFAST.ATTR(SNAME => RROWS(I).RCOLS(J).SNAME, DVALUE => RROWS(I).RCOLS(J).RCOL_VAL.DVALUE);
else
P_EXCEPTION(0,
'Описание колонки "%s" таблицы данных содержит неподдерживаемый тип данных ("%s").',
RCOL_DEFS(I).SNAME,
COALESCE(RCOL_DEFS(I).SDATA_TYPE, '<НЕ ОПРЕДЕЛЁН>'));
end case;
end loop;
end if;
/* Закрываем строку */
PKG_XFAST.UP();
end loop;
end if;
end TROWS_TO_XML;
/* Формирование таблицы данныз */
function TDATA_GRID_MAKE
return TDATA_GRID -- Результат работы
is
RRES TDATA_GRID; -- Буфер для результата
begin
/* Формируем объект */
RRES.RCOL_DEFS := TCOL_DEFS();
RRES.RROWS := TROWS();
/* Возвращаем результат */
return RRES;
end TDATA_GRID_MAKE;
/* Поиск описания колонки в таблице данных по наименованию */
function TDATA_GRID_FIND_COL_DEF
(
RDATA_GRID in TDATA_GRID, -- Описание таблицы данных
SNAME in varchar2 -- Наименование колонки
) return TCOL_DEF -- Найденное описание (null - если не нашли)
is
begin
return TCOL_DEFS_FIND(RCOL_DEFS => RDATA_GRID.RCOL_DEFS, SNAME => SNAME);
end TDATA_GRID_FIND_COL_DEF;
/* Добавление описания колонки к таблице данных */
procedure TDATA_GRID_ADD_COL_DEF
(
RDATA_GRID in out nocopy TDATA_GRID, -- Описание таблицы данных
SNAME in varchar2, -- Наименование колонки
SCAPTION in varchar2, -- Заголовок колонки
SDATA_TYPE in varchar2 := SDATA_TYPE_STR, -- Тип данных колонки (см. константы SDATA_TYPE_*)
SCOND_FROM in varchar2 := null, -- Наименование нижней границы условия отбора (null - используется UTL_COND_NAME_MAKE_FROM)
SCOND_TO in varchar2 := null, -- Наименование верхней границы условия отбора (null - используется UTL_COND_NAME_MAKE_TO)
BVISIBLE in boolean := true, -- Разрешить отображение
BORDER in boolean := false, -- Разрешить сортировку по колонке
BFILTER in boolean := false, -- Разрешить отбор по колонке
RCOL_VALS in TCOL_VALS := null, -- Предопределённые значения колонки
BCLEAR in boolean := false -- Флаг очистки коллекции описаний колонок таблицы данных (false - не очищать, true - очистить коллекцию перед добавлением)
)
is
begin
/* Формируем описание и добавляем в коллекцию таблицы данных */
TCOL_DEFS_ADD(RCOL_DEFS => RDATA_GRID.RCOL_DEFS,
SNAME => SNAME,
SCAPTION => SCAPTION,
SDATA_TYPE => SDATA_TYPE,
SCOND_FROM => SCOND_FROM,
SCOND_TO => SCOND_TO,
BVISIBLE => BVISIBLE,
BORDER => BORDER,
BFILTER => BFILTER,
RCOL_VALS => RCOL_VALS,
BCLEAR => BCLEAR);
end TDATA_GRID_ADD_COL_DEF;
/* Добавление описания колонки к таблице данных */
procedure TDATA_GRID_ADD_ROW
(
RDATA_GRID in out nocopy TDATA_GRID, -- Описание таблицы данных
RROW in TROW, -- Строка
BCLEAR in boolean := false -- Флаг очистки коллекции строк таблицы данных (false - не очищать, true - очистить коллекцию перед добавлением)
)
is
begin
/* Инициализируем коллекцию если необходимо */
if ((RDATA_GRID.RROWS is null) or (BCLEAR)) then
RDATA_GRID.RROWS := TROWS();
end if;
/* Добавляем элемент */
RDATA_GRID.RROWS.EXTEND();
RDATA_GRID.RROWS(RDATA_GRID.RROWS.LAST) := RROW;
end TDATA_GRID_ADD_ROW;
/* Сериализация таблицы данных */
function TDATA_GRID_TO_XML
(
RDATA_GRID in TDATA_GRID, -- Описание таблицы данных
NINCLUDE_DEF in number := 1 -- Включить описание колонок (0 - нет, 1 - да)
) return clob -- XML-описание
is
CRES clob; -- Буфер для результата
begin
/* Начинаем формирование XML */
PKG_XFAST.PROLOGUE(ITYPE => PKG_XFAST.CONTENT_);
/* Открываем корень */
PKG_XFAST.DOWN_NODE(SNAME => SRESP_TAG_XDATA);
/* Если необходимо включить описание колонок */
if (NINCLUDE_DEF = 1) then
TCOL_DEFS_TO_XML(RCOL_DEFS => RDATA_GRID.RCOL_DEFS);
end if;
/* Формируем описание строк */
TROWS_TO_XML(RCOL_DEFS => RDATA_GRID.RCOL_DEFS,RROWS => RDATA_GRID.RROWS);
/* Закрываем корень */
PKG_XFAST.UP();
/* Сериализуем */
CRES := PKG_XFAST.SERIALIZE_TO_CLOB();
/* Завершаем формирование XML */
PKG_XFAST.EPILOGUE();
/* Возвращаем полученное */
return CRES;
exception
when others then
/* Завершаем формирование XML */
PKG_XFAST.EPILOGUE();
/* Вернем ошибку */
PKG_STATE.DIAGNOSTICS_STACKED();
P_EXCEPTION(0, PKG_STATE.SQL_ERRM());
end TDATA_GRID_TO_XML;
/* Конвертация значений фильтра в число */
procedure TFILTER_TO_NUMBER
(
RFILTER in TFILTER, -- Фильтр
NFROM out number, -- Значение нижней границы диапазона
NTO out number -- Значение верхней границы диапазона
)
is
begin
/* Нижняя граница диапазона */
if (RFILTER.SFROM is not null) then
begin
NFROM := PKG_P8PANELS_BASE.UTL_S2N(SVALUE => RFILTER.SFROM);
exception
when others then
P_EXCEPTION(0,
'Неверный формат числа (%s) в указанной нижней границе диапазона фильтра.',
RFILTER.SFROM);
end;
end if;
/* Верхняя граница диапазона */
if (RFILTER.STO is not null) then
begin
NTO := PKG_P8PANELS_BASE.UTL_S2N(SVALUE => RFILTER.STO);
exception
when others then
P_EXCEPTION(0,
'Неверный формат числа (%s) в указанной верхней границе диапазона фильтра.',
RFILTER.STO);
end;
end if;
end TFILTER_TO_NUMBER;
/* Конвертация значений фильтра в дату */
procedure TFILTER_TO_DATE
(
RFILTER in TFILTER, -- Фильтр
DFROM out date, -- Значение нижней границы диапазона
DTO out date -- Значение верхней границы диапазона
)
is
begin
/* Нижняя граница диапазона */
if (RFILTER.SFROM is not null) then
begin
DFROM := PKG_P8PANELS_BASE.UTL_S2D(SVALUE => RFILTER.SFROM);
exception
when others then
P_EXCEPTION(0,
'Неверный формат даты (%s) в указанной нижней границе диапазона фильтра.',
RFILTER.SFROM);
end;
end if;
/* Верхняя граница диапазона */
if (RFILTER.STO is not null) then
begin
DTO := PKG_P8PANELS_BASE.UTL_S2D(SVALUE => RFILTER.STO);
exception
when others then
P_EXCEPTION(0,
'Неверный формат даты (%s) в указанной верхней границе диапазона фильтра.',
RFILTER.STO);
end;
end if;
end TFILTER_TO_DATE;
/* Формирование фильтра */
function TFILTER_MAKE
(
SNAME in varchar2, -- Наименование
SFROM in varchar2, -- Значение "с"
STO in varchar2 -- Значение "по"
) return TFILTER -- Результат работы
is
RRES TFILTER; -- Буфер для результата
begin
/* Формируем объект */
RRES.SNAME := SNAME;
RRES.SFROM := SFROM;
RRES.STO := STO;
/* Возвращаем результат */
return RRES;
end TFILTER_MAKE;
/* Поиск фильтра в коллекции */
function TFILTERS_FIND
(
RFILTERS in TFILTERS, -- Коллекция фильтров
SNAME in varchar2 -- Наименование
) return TFILTER -- Найденный фильтр (null - если не нашли)
is
begin
/* Обходим фильтры из коллекции */
if ((RFILTERS is not null) and (RFILTERS.COUNT > 0)) then
for I in RFILTERS.FIRST .. RFILTERS.LAST
loop
if (RFILTERS(I).SNAME = SNAME) then
return RFILTERS(I);
end if;
end loop;
end if;
/* Ничего не нашли */
return null;
end TFILTERS_FIND;
/* Десериализация фильтров */
function TFILTERS_FROM_XML
(
CFILTERS in clob -- Сериализованное представление фильтров (BASE64(<filters><name>ИМЯ</name><from>ЗНАЧЕНИЕ</from><to>ЗНАЧЕНИЕ</to></filters>...))
) return TFILTERS -- Результат работы
is
RFILTERS TFILTERS; -- Буфер для результата работы
XDOC PKG_XPATH.TDOCUMENT; -- Документ XML
XROOT PKG_XPATH.TNODE; -- Корень документа XML
XNODE PKG_XPATH.TNODE; -- Буфер узла документа
XNODES PKG_XPATH.TNODES; -- Буфер коллекции узлов документа
begin
/* Вернём выходную коллекцию */
RFILTERS := TFILTERS();
/* Разбираем XML */
XDOC := PKG_XPATH.PARSE_FROM_CLOB(LCXML => '<' || SRQ_TAG_XROOT || '>' ||
BLOB2CLOB(LBDATA => BASE64_DECODE(LCSRCE => CFILTERS),
SCHARSET => PKG_CHARSET.CHARSET_UTF_()) || '</' ||
SRQ_TAG_XROOT || '>');
/* Считываем корневой узел */
XROOT := PKG_XPATH.ROOT_NODE(RDOCUMENT => XDOC);
/* Считывание списка записей */
XNODES := PKG_XPATH.LIST_NODES(RPARENT_NODE => XROOT, SPATTERN => '/' || SRQ_TAG_XROOT || '/' || SRQ_TAG_XFILTERS);
/* Цикл по списку записией */
for I in 1 .. PKG_XPATH.COUNT_NODES(RNODES => XNODES)
loop
/* Считаем элемент по его номеру */
XNODE := PKG_XPATH.ITEM_NODE(RNODES => XNODES, INUMBER => I);
/* Добавим его в коллекцию */
RFILTERS.EXTEND();
RFILTERS(RFILTERS.LAST) := TFILTER_MAKE(SNAME => PKG_XPATH.VALUE(RNODE => XNODE, SPATTERN => SRQ_TAG_SNAME),
SFROM => PKG_XPATH.VALUE(RNODE => XNODE, SPATTERN => SRQ_TAG_SFROM),
STO => PKG_XPATH.VALUE(RNODE => XNODE, SPATTERN => SRQ_TAG_STO));
end loop;
/* Освободим документ */
PKG_XPATH.FREE(RDOCUMENT => XDOC);
/* Вернём результат */
return RFILTERS;
exception
when others then
/* Освободим документ */
PKG_XPATH.FREE(RDOCUMENT => XDOC);
/* Вернем ошибку */
PKG_STATE.DIAGNOSTICS_STACKED();
P_EXCEPTION(0, PKG_STATE.SQL_ERRM());
end TFILTERS_FROM_XML;
/* Применение параметров фильтрации в запросе */
procedure TFILTERS_SET_QUERY
(
NIDENT in number, -- Идентификатор отбора
NCOMPANY in number, -- Рег. номер организации
NPARENT in number := null, -- Рег. номер родителя
SUNIT in varchar2, -- Код раздела
SPROCEDURE in varchar2, -- Наименование серверной процедуры отбора
RDATA_GRID in TDATA_GRID, -- Описание таблицы данных
RFILTERS in TFILTERS -- Коллекция фильтров
)
is
RCOL_DEF TCOL_DEF; -- Описание текущей фильтруемой колонки
BENUM boolean; -- Флаг начиличия перечисляемых значений
NFROM PKG_STD.TNUMBER; -- Буфер для верхней границы диапазона отбора чисел
NTO PKG_STD.TNUMBER; -- Буфер для нижней границы диапазона отбора чисел
DFROM PKG_STD.TLDATE; -- Буфер для верхней границы диапазона отбора дат
DTO PKG_STD.TLDATE; -- Буфер для нижней границы диапазона отбора дат
begin
/* Формирование условий отбора - Пролог */
PKG_COND_BROKER.PROLOGUE(IMODE => PKG_COND_BROKER.MODE_SMART_, NIDENT => NIDENT);
/* Формирование условий отбора - Установка процедуры серверного отбора */
PKG_COND_BROKER.SET_PROCEDURE(SPROCEDURE_NAME => SPROCEDURE);
/* Формирование условий отбора - Установка раздела */
PKG_COND_BROKER.SET_UNIT(SUNITCODE => SUNIT);
/* Формирование условий отбора - Установка организации */
PKG_COND_BROKER.SET_COMPANY(NCOMPANY => NCOMPANY);
/* Формирование условий отбора - Установка родителя */
if (NPARENT is not null) then
PKG_COND_BROKER.SET_PARENT(NPARENT => NPARENT);
end if;
/* Обходим фильтр, если задан */
if ((RFILTERS is not null) and (RFILTERS.COUNT > 0)) then
for I in RFILTERS.FIRST .. RFILTERS.LAST
loop
/* Найдем фильтруемую колонку в описании */
RCOL_DEF := TCOL_DEFS_FIND(RCOL_DEFS => RDATA_GRID.RCOL_DEFS, SNAME => RFILTERS(I).SNAME);
if (RCOL_DEF.SNAME is not null) then
/* Определимся с наличием перечисляемых значений */
if ((RCOL_DEF.RCOL_VALS is not null) and (RCOL_DEF.RCOL_VALS.COUNT > 0)) then
BENUM := true;
else
BENUM := false;
end if;
/* Установим для неё условие отобра согласно типу данных */
case RCOL_DEF.SDATA_TYPE
when SDATA_TYPE_STR then
begin
if (BENUM) then
PKG_COND_BROKER.SET_CONDITION_ESTR(SCONDITION_NAME => RCOL_DEF.SCOND_FROM,
SCONDITION_ESTR => RFILTERS(I).SFROM,
ICASE_INSENSITIVE => 1);
else
PKG_COND_BROKER.SET_CONDITION_STR(SCONDITION_NAME => RCOL_DEF.SCOND_FROM,
SCONDITION_VALUE => RFILTERS(I).SFROM,
ICASE_INSENSITIVE => 1);
end if;
end;
when SDATA_TYPE_NUMB then
begin
if (BENUM) then
PKG_COND_BROKER.SET_CONDITION_ENUM(SCONDITION_NAME => RCOL_DEF.SCOND_FROM,
SCONDITION_ENUM => RFILTERS(I).SFROM);
else
TFILTER_TO_NUMBER(RFILTER => RFILTERS(I), NFROM => NFROM, NTO => NTO);
if (NFROM is not null) then
PKG_COND_BROKER.SET_CONDITION_NUM(SCONDITION_NAME => RCOL_DEF.SCOND_FROM,
NCONDITION_VALUE => NFROM);
end if;
if (NTO is not null) then
PKG_COND_BROKER.SET_CONDITION_NUM(SCONDITION_NAME => RCOL_DEF.SCOND_TO, NCONDITION_VALUE => NTO);
end if;
end if;
end;
when SDATA_TYPE_DATE then
begin
if (BENUM) then
PKG_COND_BROKER.SET_CONDITION_EDATE(SCONDITION_NAME => RCOL_DEF.SCOND_FROM,
SCONDITION_EDATE => RFILTERS(I).SFROM);
else
TFILTER_TO_DATE(RFILTER => RFILTERS(I), DFROM => DFROM, DTO => DTO);
if (DFROM is not null) then
PKG_COND_BROKER.SET_CONDITION_DATE(SCONDITION_NAME => RCOL_DEF.SCOND_FROM,
DCONDITION_VALUE => DFROM);
end if;
if (DTO is not null) then
PKG_COND_BROKER.SET_CONDITION_DATE(SCONDITION_NAME => RCOL_DEF.SCOND_TO, DCONDITION_VALUE => DTO);
end if;
end if;
end;
else
P_EXCEPTION(0,
'Описание колонки "%s" таблицы данных содержит неподдерживаемый тип данных ("%s").',
RCOL_DEF.SNAME,
COALESCE(RCOL_DEF.SDATA_TYPE, '<НЕ ОПРЕДЕЛЁН>'));
end case;
end if;
end loop;
end if;
/* Формирование условий отбора - Эпилог */
PKG_COND_BROKER.EPILOGUE();
end TFILTERS_SET_QUERY;
/* Формирование сортировки */
function TORDER_MAKE
(
SNAME in varchar2, -- Наименование
SDIRECTION in varchar2 -- Направление (см. константы SORDER_DIRECTION_*)
) return TORDER -- Результат работы
is
RRES TORDER; -- Буфер для результата
begin
/* Формируем объект */
RRES.SNAME := SNAME;
RRES.SDIRECTION := SDIRECTION;
/* Возвращаем результат */
return RRES;
end TORDER_MAKE;
/* Десериализация сортировок */
function TORDERS_FROM_XML
(
CORDERS in clob -- Сериализованное представление сотрировок (BASE64(<orders><name>ИМЯ</name><direction>ASC/DESC</direction></orders>...))
) return TORDERS -- Результат работы
is
RORDERS TORDERS; -- Буфер для результата работы
XDOC PKG_XPATH.TDOCUMENT; -- Документ XML
XROOT PKG_XPATH.TNODE; -- Корень документа XML
XNODE PKG_XPATH.TNODE; -- Буфер узла документа
XNODES PKG_XPATH.TNODES; -- Буфер коллекции узлов документа
begin
/* Инициализируем выходную коллекцию */
RORDERS := TORDERS();
/* Разбираем XML */
XDOC := PKG_XPATH.PARSE_FROM_CLOB(LCXML => '<' || SRQ_TAG_XROOT || '>' ||
BLOB2CLOB(LBDATA => BASE64_DECODE(LCSRCE => CORDERS),
SCHARSET => PKG_CHARSET.CHARSET_UTF_()) || '</' ||
SRQ_TAG_XROOT || '>');
/* Считываем корневой узел */
XROOT := PKG_XPATH.ROOT_NODE(RDOCUMENT => XDOC);
/* Считывание списка записей */
XNODES := PKG_XPATH.LIST_NODES(RPARENT_NODE => XROOT, SPATTERN => '/' || SRQ_TAG_XROOT || '/' || SRQ_TAG_XORDERS);
/* Цикл по списку записией */
for I in 1 .. PKG_XPATH.COUNT_NODES(RNODES => XNODES)
loop
/* Считаем элемент по его номеру */
XNODE := PKG_XPATH.ITEM_NODE(RNODES => XNODES, INUMBER => I);
/* Добавим его в коллекцию */
RORDERS.EXTEND();
RORDERS(RORDERS.LAST) := TORDER_MAKE(SNAME => PKG_XPATH.VALUE(RNODE => XNODE, SPATTERN => SRQ_TAG_SNAME),
SDIRECTION => PKG_XPATH.VALUE(RNODE => XNODE, SPATTERN => SRQ_TAG_SDIRECTION));
end loop;
/* Освободим документ */
PKG_XPATH.FREE(RDOCUMENT => XDOC);
/* Вернём результат */
return RORDERS;
exception
when others then
/* Освободим документ */
PKG_XPATH.FREE(RDOCUMENT => XDOC);
/* Вернем ошибку */
PKG_STATE.DIAGNOSTICS_STACKED();
P_EXCEPTION(0, PKG_STATE.SQL_ERRM());
end TORDERS_FROM_XML;
/* Применение параметров сортировки в запросе */
procedure TORDERS_SET_QUERY
(
RDATA_GRID in TDATA_GRID, -- Описание таблицы
RORDERS in TORDERS, -- Коллекция сортировок
SPATTERN in varchar2, -- Шаблон для подстановки условий отбора в запрос
CSQL in out nocopy clob -- Буфер запроса
)
is
CSQL_ORDERS clob; -- Буфер для условий сортировки в запросе
begin
/* Если сортировка задана */
if ((RORDERS is not null) and (RORDERS.COUNT > 0)) then
CSQL_ORDERS := ' order by ';
for I in RORDERS.FIRST .. RORDERS.LAST
loop
/* Перед добавлением в запрос - обязательная проверка, чтобы избежать SQL-инъекций */
if ((TCOL_DEFS_FIND(RCOL_DEFS => RDATA_GRID.RCOL_DEFS, SNAME => RORDERS(I).SNAME).SNAME is not null) and
(RORDERS(I).SDIRECTION in (SORDER_DIRECTION_ASC, SORDER_DIRECTION_DESC))) then
CSQL_ORDERS := CSQL_ORDERS || RORDERS(I).SNAME || ' ' || RORDERS(I).SDIRECTION;
if (I < RORDERS.LAST) then
CSQL_ORDERS := CSQL_ORDERS || ', ';
end if;
end if;
end loop;
end if;
CSQL := replace(CSQL, SPATTERN, CSQL_ORDERS);
end TORDERS_SET_QUERY;
end PKG_P8PANELS_VISUAL;
/