QlikView 11 – Call EDX task from web-client on click button

Введение

Загрузку данных в QlikView-отчетах (с расширением .qvw) можно осуществить несколькими путями:
1. В разработчике отчетов (Qv.exe), нажав кнопку Загрузка.
2. При запуске разработчика с опцией загрузки: qv.exe /r reportname.qvw
3. Используя консоль управления QlikView Management Console (http://localhost:4780/qmc/SourceDocuments.htm), в которой настраивается задание по расписанию (scheduler task) для выбранного отчета.
4. В веб-клиенте для пользователей (Access Point), используя внешние расширения (QlikView Extension), которые запускают задания по расписанию созданные в QlikView Management Console (QlikView Management Service).
Первые два метода (1, 2) применяют для загрузки новых данных вручную. Два нижних метода (3, 4), автоматизируют процесс обновления данных в отчетах. Метод 4 работает в связке с методом 3, и привносит расширенные возможности автоматизации обновления данных в отчетах самим пользователем отчета.

Загрузка данных в web-клиенте QlikView по нажатию кнопки

За основу инструкции взяты файлы и информация, предоставленные на сайте: http://qvextcalledxfromajax.codeplex.com/wikipage?title=Installation&referringTitle=Documentation.
CallEDXFromAjax_ArchitectureOverview

Все настройки выполнялись на машине под Windows Server 2008 R2, где развернута серверная часть QlikView 11.

1. Для начала качаем файлы:
• The web service — EDX Wrapper Webservice v1.0.1.zip
• The QlikView extension — CallEDXFromAjax_v1_0_0.qar
2. Разархивируем EDX Wrapper Webservice v1.0.1.zip на диск C (получим C:\ EDXWrapper_v_1_0_1).
3. От имени администратора запускаем CallEDXFromAjax_v1_0_0.qar, который проинсталлирует новые расширения для QlikView в профиль пользователя (будет создана папка с объектами %LOCALAPPDATA%\QlikTech\QlikView\Extensions\Objects\CallEDXFromAjax).
4. Чтобы эти расширения могли использовать все пользователи QlikView, следует скопировать папку %LOCALAPPDATA%\QlikTech\QlikView\Extensions\Objects\CallEDXFromAjax в C:\ProgramData\QlikTech\QlikViewServer\Extensions\Objects.

5. Далее настраиваем веб-службу EDX Wrapper Webservice на IIS 7.0 под .NET Framework 4.0.30319.
5.1. Заходим в консоль IIS (Internet Information Services (IIS) Manager)
5.2. Добавляем новый веб сайт с именем EDXWrapper и портом 8080:

Web Site

5.3. Затем добавим в пул приложений новый пул EDXWrapper с поддержкой .NET Framework 4.0.30319:

App pool properties

5.4. Проверяем в добавленном сайте EDXWrapper версию используемого aspnet_client (должна присутствовать в списке версия 4_0_30319):

Если в списке отсутствует версия aspnet_client – system_web — 4_0_30319, то следует выполнить следующий код в командной строке:
cmd> C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe –i
После чего в ISS во всех веб сайтах должна появиться версия aspnet client – 4.0.30319.

5.5. Перезапускаем IIS.
5.6. Проверяем работу нашего сайта, для этого в Internet Explorer вводим адрес: http://localhost:8080/QlikViewTasks.asmx
home edxtrigger
В разделе TiggerEDXTask можно проверить работу процесса обновления данных в отчете, но для этого следует выполнить п.6 данной инструкции.
test edxtrigger

6. Создаем задание по расписанию в QlikView Management Console для обновления данных в имеющемся отчете (в моем случае отчет KPI.qvw).
6.1. Для этого заходим в консоль управления QlikView Management Console и переходим в раздел Documents. Поскольку отчеты размещены в каталоге по умолчанию C:\ProgramData\QlikTech\SourceDocuments, то заходим в закладку Source Documents и выбираем отчет, например, KPI.qvw.
console docs

6.2. Справа нажимаем на кнопку (Add Task Manually). Откроется окно настройки задания. В закладке General – задаем имя задания (например, KPITASK) и включаем его (Enabled).
task general
В закладке Reload разрешаем перезагрузку (Enable).
tasks reload
Далее переходим в закладку Triggers и добавляем ( Add) новый триггер, срабатывающий на событие On an external events. Пароль можно не задавать.
trigger edx
В остальных закладках (Reduce, Distribute, Document Information, Server) я оставил все как есть по умолчанию.
После того, как все параметры заданы, жмем Apply.

7. Задание создано, теперь заходим в разработчик отчетов (QV.exe), где нужно добавить новый объект для обновления данных из веб-клиента.
7.1. В разработчике открываем наш отчет (например, KPI.qvw), далее включаем вид WebView.
qv web mode

7.2. Жмем по форме правой кнопкой мыши и в контекстном меню выбираем Новый Объект Листа (New object page).
new object

7.3. В открывшемся меню заходим в Объекты расширения и выбираем Call EDX From Ajax. И перетаскиваем объект на форму отчета.
New object on form

7.4. Далее заходим в Свойства нового объекта и настраиваем его.
edx properties
В Свойствах в разделе Call EDX From Ajax параметру Webservice URL задаем значение: http://:<QV server>:<port>/QlikViewTasks.asmx (где <QV server> — имя компьютера, где установлена серверная часть QlikView, <port> — указанный в IIS, 8080).

NOTE:
Следует знать, что имя компьютера указывается также, как и при вызове QlikView Access Point. Например, если веб-клиент вызывается http://srvqv.test.int:8080/qlikview/index.htm, тогда в параметре Webservice URL указывается адрес: http://srvqv.test.int:8080/QlikViewTasks.asmx.

Для параметра Task Name: имя задания созданного в п.6 (в моем случае, KPITASK).
edx properties 1
В разделе Behaviour оставляем все по умолчанию, и переходим в раздел Translation, где зададим новое имя для кнопки и уведомления выполнения загрузки.
edx properties 2
В разделе Caption задаем имя объекту, например, Load data.
edx properties 3

7.5. Теперь уменьшим размер нашего объекта, чтобы он мог разместиться на форме, и сохраним все изменения в отчете.
resize edx on form

ВНИМАНИЕ! Объект Call EDX From Ajax предназначен и работает только в веб-клиенте QlikView (Access Point)! В разработчике отчетов (Qv.exe) он не поддерживается, и при нажатии будет выдавать ошибку:
warning
А также Call EDX From Ajax корректно работает в браузере Internet Explorer 8, 9, 10, 11.

8. Откроем наш отчет (KPI.qvw) в веб-клиенте QlikView через Internet Explorer, и испытаем добавленный в него объект Call EDX From Ajax. Нажмем на кнопку UPLOAD и дождемся выполнения загрузки данных:
web-client
EDX status
Если все завершилось успешно, то все настройки были выполнены, верно. Иначе сверьте свои настройки с данной инструкцией, или проверяйте корректность вашего кода в редакторе скриптов, или смотрите в сторону прав доступа.

Создание DDL-trigger для событий CREATE, ALTER, DROP

  • Oracle 10g, 11g

Для начала создадим таблицу, куда триггер будет регистрировать события CREATE, ALTER, DROP.

CREATE TABLE TESTER.DDL_LOG
(DDL_ID       INTEGER,
VER_ID       INTEGER,
ATTEMPT_DT   DATE,
OPERATION    VARCHAR2(30 BYTE),
COMP         VARCHAR2(128 BYTE),
MODULE       VARCHAR2(255 BYTE),
OS_USER      VARCHAR2(255 BYTE),
DB_USER      VARCHAR2(30 BYTE),
OBJ_OWNER    VARCHAR2(30 BYTE),
OBJECT_NAME  VARCHAR2(30 BYTE),
OBJECT_TYPE  VARCHAR2(30 BYTE),
SQL_TEXT     CLOB,
SQL_LENGTH   NUMBER);

, где ddl_id — порядковый номер строк,
ver_id — порядковый номер версии по группе [obj_owner, object_name, object_type],
attempt_dt — дата изменения объекта,
operation — операция (CREATE|ALTER|DROP),
comp — хост, с которого выполнялось событие,
module — программный модуль, в котором выполнялось событие,
os_user — ОС пользователь,
db_user — БД пользователь,
obj_owner  — схема, к которой относится объект,
object_name — имя объекта,
object_type — тип объекта,
sql_text — тело объекта (программный код),
sql_length — длина кода в символах

Создадим еще последовательность для генерации порядкового номера строк таблицы.

CREATE SEQUENCE TESTER.ddl_log_seq
START WITH 0
increment by 1
MAXVALUE 999999999
MINVALUE 0
NOCYCLE
NOCACHE
ORDER;

Теперь создадим DDL-триггер, который будет срабатывать после событий CREATE, ALTER, DROP, и повесим его на базу (создавать под учеткой as sysdba).

CREATE OR REPLACE TRIGGER DDL_TRIGGER
AFTER CREATE OR ALTER OR DROP ON DATABASE
DECLARE
vddl_id NUMBER;
vver_id NUMBER;
temp_clob CLOB;
sql_clob CLOB;
vsql_text ora_name_list_t;
n NUMBER;
text RAW(1000);
text_blob BLOB;
convert_warn INTEGER;
dest_offset  INTEGER := 1;
src_offset   INTEGER := 1;
lang_context INTEGER := DBMS_LOB.default_lang_ctx;
csid         INTEGER := DBMS_LOB.default_csid;

BEGIN

-- Если нужно, то указываем, для каких схем и типов объектов будет срабатывать триггер после событий CREATE, ALTER, DROP
IF ora_dict_obj_owner IN ('BIB', 'BIPS', 'BANKS', 'MTB', 'RAILWAY', 'STUSER') AND ora_dict_obj_type IN ('TABLE', 'PROCEDURE', 'FUNCTION', 'PACKAGE') THEN

-- Формируем номер для новой строки
SELECT TESTER.ddl_log_seq.nextval INTO vddl_id FROM dual;

-- Формируем последовательный номер версии для группы [obj_owner,object_name,object_type]
SELECT CASE
WHEN EXISTs(SELECT count(1) vver_id FROM TESTER.ddl_log
WHERE obj_owner = ora_dict_obj_owner
AND object_name = ora_dict_obj_name AND object_type = ora_dict_obj_type
GROUP BY obj_owner,object_name,object_type)
THEN (SELECT max(ver_id)+1 vver_id FROM TESTER.ddl_log
WHERE obj_owner = ora_dict_obj_owner
AND object_name = ora_dict_obj_name AND object_type = ora_dict_obj_type
GROUP BY obj_owner,object_name,object_type)
ELSE 1
END INTO vver_id
FROM dual;

-- Получаем программный код объекта в CLOB после DDL-события (построчное склеивание для кодировки AL32UTF8 и не только)
n := ora_sql_txt(vsql_text);
DBMS_LOB.CREATETEMPORARY(text_blob,true);
DBMS_LOB.open(text_blob,dbms_lob.lob_readwrite);
FOR i IN 1 .. n LOOP
text:=UTL_RAW.CAST_TO_RAW(vsql_text(i));
DBMS_LOB.writeappend(text_blob,utl_raw.length(text),text);
END LOOP;

DBMS_LOB.createtemporary(sql_clob, true);
DBMS_LOB.converttoclob (sql_clob,
text_blob,
DBMS_LOB.getlength (text_blob),
dest_offset,
src_offset,
csid,
lang_context,
convert_warn);

DBMS_LOB.close(text_blob);
DBMS_LOB.FreeTEMPORARY(text_blob);

-- Событие СREATE
IF ora_sysevent = 'CREATE' THEN

INSERT INTO TESTER.ddl_log
SELECT vddl_id, vver_id, SYSDATE, ora_sysevent, sys_context('USERENV','HOST'), sys_context('USERENV','MODULE'),
sys_context('USERENV','OS_USER'), USER, ora_dict_obj_owner, ora_dict_obj_name, ora_dict_obj_type,
EMPTY_CLOB(), 0 FROM DUAL;

-- Блокируем строку для апдейта поля типа CLOB
SELECT sql_text into temp_clob
FROM TESTER.ddl_log
WHERE ddl_id = vddl_id AND ver_id = vver_id
FOR UPDATE OF sql_text, sql_length;

UPDATE TESTER.ddl_log set sql_text = sql_clob, sql_length = dbms_lob.getlength(sql_clob)
WHERE ddl_id = vddl_id AND ver_id = vver_id;

-- Событие DROP
ELSIF ora_sysevent = 'DROP' THEN

INSERT INTO TESTER.ddl_log
SELECT vddl_id, vver_id, SYSDATE, ora_sysevent, sys_context('USERENV','HOST'), sys_context('USERENV','MODULE'),
sys_context('USERENV','OS_USER'), USER, ora_dict_obj_owner, ora_dict_obj_name, ora_dict_obj_type,
EMPTY_CLOB(), 0 FROM DUAL;

SELECT sql_text into temp_clob
FROM TESTER.ddl_log
WHERE ddl_id = vddl_id AND ver_id = vver_id
FOR UPDATE OF sql_text, sql_length;

UPDATE TESTER.ddl_log set sql_text = sql_clob, sql_length = 0
WHERE ddl_id = vddl_id AND ver_id = vver_id;

-- Событие ALTER
ELSE
-- Для некторых объектов получить программный код после изменения можно только, используя пакет DBMS_METADATA
IF ora_dict_obj_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE') THEN

sql_clob:=trim(DBMS_METADATA.GET_DDL(ora_dict_obj_type,ora_dict_obj_name,ora_dict_obj_owner,'COMPATIBLE','ORACLE','DDL'));

END IF;

INSERT INTO TESTER.ddl_log
SELECT vddl_id, vver_id, SYSDATE, ora_sysevent, sys_context('USERENV','HOST'), sys_context('USERENV','MODULE'),
sys_context('USERENV','OS_USER'), USER, ora_dict_obj_owner, ora_dict_obj_name, ora_dict_obj_type,
EMPTY_CLOB(), NULL FROM DUAL;

SELECT sql_text into temp_clob
FROM TESTER.ddl_log
WHERE ddl_id = vddl_id AND ver_id = vver_id
FOR UPDATE OF sql_text;

UPDATE TESTER.ddl_log SET sql_text = sql_clob, sql_length = dbms_lob.getlength(sql_clob)
WHERE ddl_id = vddl_id AND ver_id = vver_id;
END IF;
END IF;
END;

Для включения/октлючения триггера (выполнять под учеткой as sysdba).

ALTER TRIGGER DDL_TRIGGER ENABLE;
ALTER TRIGGER DDL_TRIGGER DISABLE;