Краткое руководство разработчика метаданных Teiid

Введение

Teiid - это технология, позволяющая данные различной природы хранения, структуры, расположения и происхождения - представлять в едином виде: в виде реляционной базы данных. Такая база данных называется виртуальной, т. к. существует только в Teiid, реальной СУБД в традиционном понимании под ней нет. Такой процесс представления данных называется виртуализацией. В виртуальной базе данных могут быть представлены данные из таких источников как: текстовые файлы, электронные таблицы (как Excel, так и Google Spreadsheet, и др.), реляционные базы данных, иерархические хранилища (Modeshape), Web-сервисы, и многие другие. Кроме того, имеется возможность реализации собственных источников данных для Teiid.

Teiid как подсистема виртуализации разнородных данных, основывается на метаданных, описанных в виртуальной базе данных (далее VDB). Физически виртуальная база данных представляет из себя файл формата XML, поименованный обязательно как *-vdb. xml.

В VDB содержатся общая информация (наименование, описание, версия), а так же описания т. н. моделей. Модель - это структурная единица VDB. В модели описываются виртуальные таблицы, на языке DDL SQL, дополненным опциями Teiid (о них ниже).

Идейно, в рамках Планирования, в VDB содержатся виртуальные таблицы (т. н. "витрины") для каких-либо сущностей Планирования. На данном этапе это могут быть бизнес-объекты и регистры.

Общую структуру VDB можно посмотреть по ссылке https://docs. jboss. org/author/display/teiid811final/VDB+Definition

НЕ нашли? Не то? Что вы ищете?

но проще всего разрабатывать VDB не с нуля, а пользоваться автоматически сгенерированной VDB по конкретному классу бизнес-объекта, или регистра, с некоторой доводкой руками после генерации.

Для простоты, будем рассматривать VDB на примере готового vdb-файла полученного в п.1

1. Генерация VDB по классу документа

Для сокращения времени разработки VDB и минимизации рутины и ошибок при её описании, был создан минималистичный вспомогательный сервис для автоматической генерации базового наполнения vdb-файла. Если у вас локально развернуто Web Планирование с установленным на нем Teiid, то генератор доступен по URL: http://localhost:8080/teiid-services/metadatagen

Он принимает полное (с именем пакета) имя класса бизнес-объекта, или класса сущности – для регистра, имя файла, в который будет записан результат, и имя сервиса, обслуживающего данный вид документа.

Файл с указанным именем будет перезаписан, если он уже существует.

Имя сервиса вводится без пакета, для бизнес-объектов оно соответствует имени интерфейса сервиса, обслуживающего этот б/о.

Например

Для регистров:

Регистры "План расходов", "Заявки", "Уточнения", "Уведомления" - имя сервиса: "ExpendsRegistryService";

регистр "ПОБА" - имя сервиса: "LimitingAmountRegistryService";

регистр "ОБАС" - имя сервиса: "ObasRegistryService";

регистр "ИФДБ" - имя сервиса: "IfdbRegistryService".

Когда вы заполните все поля генератора и нажмете кнопку "Выполнить", в файле, указанном в качестве файла VDB будет сгенерировано описание VDB, соответствующее структуре указанного класса документа.

2. Специфика VDB для регистров

В VDB для регистра генерируется одна модель (тэг <model>) с именем, соответствующем краткому имени класса регистра, например ExpendPlanRegistrySkeleton.

Поскольку регистр по своей природе имеет плоскую структуру, в этой модели создаётся запись о единственной таблице виртуальной базы данных, в которую пишутся все атрибуты всех уровней и справочников переданного класса регистра. В будущем, как мы увидим, чтобы выполнить через Teiid простой запрос к данным регистра, потребуется один SELECT-запрос к этой таблице.

Регистровые виртуальные таблицы не имеют специальных зарезервированных контекстных атрибутов, в отличие от бизнес-объектов (см. п.3), о примерах задания контекста см. п.7, подпункт 2.1)

3. Специфика VDB для бизнес-объектов

Бизнес-объект структурно древовиден, то есть имеет совсем не плоскую структуру. Б/о имеет ссылки на справочники и детализации, которые в свою очередь могут иметь ссылки на свои справочники и детализации. В связи с этим для бизнес-объекта в VDB генерируется не одна модель,  множество - по одной модели для класса бизнес-объекта каждой детализации. Именуются модели в соответствии с краткими именами классов бизнес-объектов, которые они представляют.

Как мы увидим в будущем, чтобы запросить данные какого-то одного документа с данными детализации/детализаций, конструируется SELECT-запрос, с конструкциями JOIN для "прицепления" данных детализаций к данным заголовка из других моделей.

Виртуальные таблицы для бизнес-объектов у нас имеют обязательные служебные поля.

Для каждой виртуальной таблицы б/о обязательны должны быть определены поля

contextSubjectUuid string OPTIONS (NAMEINSOURCE 'contextSubjectUuid'),

contextSubjectYear integer OPTIONS (NAMEINSOURCE 'contextSubjectYear'),

Они представляют собой проброс контекста планирования, конкретно - uuid субъекта планирования и контекстный год.

Помимо контекстных полей, для виртуальных таблиц представляющих детализации бизнес-объектов, для каждой должно присутствовать поле

parentUuid string OPTIONS (NAMEINSOURCE 'parentUuid'),

Это - uuid документа, который является вышестоящим для этого документа детализации. Нужно это поле для того, чтобы формировать запросы на данные мастер-детали с помощью join (см. п.7).

На всякий случай, уточню: указанные обязательные поля при автогенерации VDB по принципу п.1 - добавляются все автоматически, заботиться вам об этом не надо, но надо знать.

4. Доводка VDB после автогенерации

Teiid не переносит название "year" колонки виртуальной таблицы. По всей видимости, это является его зарезервированным словом. Переименовывайте такие колонки.

После генерации VDB может получиться, что в одной и той же таблице имеются поля с одинаковым названием (хоть и относящиеся к разным справочникам). Это вызовет ошибки во время развертывания VDB, которые будут читабельно выведены в server. log. По логу можно понять, какие колонки задублировались. Идём в файл VDB, переименовываем один из дублей на свой манер (в редком случае можно дубль удалить, если ТОЧНО известно, что эти колонки будут всегда иметь одинаковое значение. Но лучше не надо).

Но главная доводка требуется сгенерированным VDB для бизнес-объектов, где имеется КБК. На данный момент генератор VDB часто не добавляет в витрину для такого объекта поля наименований классификаторов (например, наименование ЦСР). Такие, отсутствующие поля - конечно если они требуются - придётся добавить руками по следующему принципу:

если есть поле кода ЦСР

csrClsId string OPTIONS (NAMEINSOURCE 'csr/clsId'),

то поле наименования ЦСР нужно задать так

csrName string OPTIONS(NAMEINSOURCE 'csr/object/name'),

И по такому же принципу для всех остальных необходимых классификаторов.

В принципе, такая же ситуация может возникнуть не только с КБК, но и с другими справочниками, но я привожу принцип доработки на примере КБК.

Технически, причина того что генератор VDB не создаёт некоторые описания полей справочника, такие как имя, или - вернее - создаёт их только для некоторых справочников, - заключается в структуре бизнес-объекта. Ссылка на справочник (например ClsCsrKey) содержит значения id, uuid, но не содержит значения name. С другой стороны, ссылка на классификатор РРО (ClsPayPromiseKey) содержит в том числе и name классификатора. Поэтому для ссылок, не содержащих необходимое значение, например name, требуется раскрытие ссылки через слово "object" в строке XPath, как описано выше.

5. Опции VDB (секции OPTIONS)

1) Опции описания поля

1.1) Для бизнес-объекта:

Имеем описание поля в модели VDB:

ownerName string OPTIONS (NAMEINSOURCE 'owner/name')

Здесь ownerName - имя поля в виртуальной таблице (в "выдаче"), string - тип значения. Дальше идут опции - это то, что не относится к DDL SQL, но нужно для настройки поля. В скобках приведена пара (имя опции 'значение').

NAMEINSOURCE - обязательная для каждого поля витринки опция, значение которой показывает откуда берется значение этого поля из исходных данных. Для бизнес-объектов в значении этой опции полностью поддерживается XPath по структуре бизнес-объекта. В нашем примере - в поле берется имя бюджета владельца документа.

Интересный пример, как вытащить в витринку суммы:

sum1 bigdecimal OPTIONS(NAMEINSOURCE 'sums[year=2016]/finalSum')

Здесь подтягивается итоговая сумма на 2016 год.

DENORMALIZE_BY - необязательная опция витрины бизнес-объекта. Нужна, чтобы представить бизнес-объект в более "регистровом" виде. Добавлена была изначально для сумм, чтобы можно было альтернативно разложить три суммы в три строчки итоговых данных. Чтобы это сделать на примере сумм, делается следующее:

для таблицы добавляется опция

"DENORMALIZE_BY" 'sums'

а в описание таблицы - поля

sum bigdecimal OPTIONS (NAMEINSOURCE 'sums/finalSum'),

ayear integer OPTIONS (NAMEINSOURCE 'sums/year')

И тогда, при наличии в записи в документе трех сумм, они будут выданы в результат, как в регистре - тремя строками, по годам. Такой вывод может быть удобнее в ряде задач, и не требует указания в VDB явно годов и периода планирования, как было показано выше.

PARENT_CLASS_NAME - на данный момент опция обязательна для витрин детализаций (в которых есть поле parentUuid). Возможно в будущем будет убрана. Должна иметь значение полного имени класса бизнес-объекта, владеющего этой детализацией. Например: для детализации "Суммы" в ОБАС это будет значение "ru. krista. planning. obas. model. Obas", а для детализации "Содержание заявки" - "ru. krista. planning. expends. model. AdjustmentDocument".

1.2) Для регистров:

Имеем такое описание поля:

ownerBudgetName string OPTIONS (NAMEINSOURCE 'owner. budget. name')

Всё очень похоже как и для бизнес-объектов, но значения NAMEINSOURCE пишутся не через слэш, а через точку, и именуют атрибуты hibernate-сущности, полностью так же как мы добавляем ключи в параметры группировки регистра.

В нашем примере - это поля имя бюджета владельца документа.

2) Опции описания таблицы

Эти опции пишутся после окончания описаний колонок виртуальной таблицы.

Простой пример для регистра:

OPTIONS("UPDATABLE" 'FALSE', "TARGET_SERVICE_NAME" 'ExpendsRegistryService');

Опция "UPDATABLE" у нас везде имеет значение 'FALSE', наши витринки все только для чтения.

Опция "TARGET_SERVICE_NAME" имеет значение, которые мы указали в качестве имени сервиса документа при автогенерации VDB (см. п.1).

Для бизнес-объектов, являющихся детализациями есть её одна опция. Пример:

OPTIONS("UPDATABLE" 'FALSE', "TARGET_SERVICE_NAME" 'AlterRequestService', "DETAIL_PATH" 'items');

Добавилась опция "DETAIL_PATH". Её значение показывает путь до детализации в заголовочном документе. Например в документе "Заявка" (AlterRequest) детализация "Содержание заявки" (AdjustmentItem) расположена по пути 'items' (смотреть - в структуру класса бизнес-объекта).

Все указанные опции являются обязательными для своих случаев.

6. Развертывание VDB

Готовый файлик *-vdb. xml устанавливается в систему по принципу деплоя обычных модулей типа war/jar, то есть копируется в папку standalone/deployments. После чего в логе можем наблюдать как он деплоится.

Ошибка при деплое VDB вида

ScriptEngineManager providers. next(): javax. script. ScriptEngineFactory: Provider n. script. javascript. RhinoScriptEngineFactory not found

является стандартной, незначимой. Смотреть нужно на последующие сообщения либо вида

TEIID50030 VDB AlterRequestService.1 model "AlterRequestMasterDetail" metadata loaded. End Time: 28.10.15 12:17

свидетельствующие об успешной установке очередной модели (много моделей в VDB - много и сообщений),

либо сообщения WARN (желтые), свидетельствующие об ошибке развертывания модели, имеют вид

TEIID50036 VDB AlterRequestService.1 model "AdjustmentSum" metadata failed to load. Reason:TEIID30386 org. teiid. api. exception. query. QueryParserException: TEIID31100 Parsing error: Encountered "'parentUuid'), [*]year[*] integer OPTIONS" at line 5, column 13.

после которого следует более детальное описание, что не так с моделью.

Отсюда тонкость: при деплое VDB, часть моделей может успешно установиться, а часть нет. Судя по всему, такая VDB считается успешно задеплоившейся и "удачные" модели будут работать. Не обольщайтесь появлению файлика c именем вида *-vdb. xml. deployed, всегда смотрите в лог!

Изменения в VDB файле можно делать прямо в папке деплоя, после сохранения изменений, он автоматически редеплоится в 99% случаев.

В оставшихся редких случаях бывает необходимо принудительно вызвать деплой, например маркерным файлом. dodeploy, опять же - смотрите в лог.

Внимание! Если у вас несколько VDB, которые зависят друг от друга (посредством секции import, см. п.8.2), то при передеплое той VDB от которой зависят, нужно передеплоить ту VDB, которая от неё зависит, иначе будет получена ошибка при попытке обращения к последней.

7. Запросы к VDB

Примечание: в запросах SELECT в секции FROM для Teiid пишутся не просто имена таблиц, а конструкция из имени модели и имени таблицы через точку. Т. к. у нас в сгенерированных VDB делается по одной модели на таблицу, обычно это выглядит как

FROM ExpendPlanRegistrySkeleton. ExpendPlanRegistrySkeleton...

1) Через что выполнять запросы

Технически, Teiid работает через JDBC драйвер. Для разработки и тестирования запросов был сделан простой сервелет, опубликованный по адресу http://localhost:8080/teiid-services/simplequery

На странице сервлета вводится имя VDB (то самое, которое записано в тэге <vdb name="AlterRequestService"...), имя пользователя, пароль и текст запроса. Авторизация осуществляется через JBoss, как и в самом Web Планировании. То есть на системе разработчика можно использовать system/masterkey.

По нажатии на кнопку "Выполнить" выведется время, затраченное на выполнение запроса, и его результаты в виде текста.

2) Типовое задание контекста/нескольких для одной таблицы

Задание контекста осуществляется передачей в запросе в строке WHERE значений uuid'а субъекта планирования и значения года планирования, т. к. единственный способ передавать любого рода параметры Teiid - это в составе запроса. Варианты использования - см. далее

2.1) Для регистров

Как было сказано ранее, специальных контекстных атрибутов в регистре не добавляется, он представляется в VDB "как есть". Типовая запись в регистр какого-либо документа сохраняет ссылку на субъект планирования и контекстный год в полях "owner. uuid" и "contextYear" - соответственно (здесь указываю имена этих атрибутов как они именуются с точки зрения регистра). Эти поля представлены в VDB полями "ownerUuid" и " contextYear". По этим полям и нужно писать ограничение в запросе, для выбора конкретного субъекта планирования/множества таких субъектов.

Пример (имя VDB = ExpendsRegistryService)

SELECT sourceDocDocCode, sourceDocDocName, ownerName, isMinor, subjectClsId, grbsClsId, fkrClsId, csrClsId, vrClsId, osguClsId, fundsTypeClsId, targetedFundsClsId, subsidyClsId, ppClsId, programActivitiesClsId, budgetClsId, sum, sourceDocUuid

FROM ExpendPlanRegistrySkeleton. ExpendPlanRegistrySkeleton

WHERE ((ownerUuid = '1323bb3a-8f98-41be-8e3c-07208d320d87') AND (contextYear = 2016)) OR ((ownerUuid = '0c5cc3b1-c9cf-4550-9aca-cc05b5c20d86') AND (contextYear = 2016))

В этом примере выборка ограничивается двумя контекстами планирования. Будут выбраны все данные обоих контекстов из регистра. Путём очевидных манипуляций можно как увеличить число покрываемых контекстов, так и убрать это ограничение вовсе.

Если требуются дополнительные атрибутные ограничения к этому запросу - они добавляются без премудростей, согласно синтаксису SQL.

2.2) Для бизнес-объекта

Для задания контекста для бизнес-объектов имеются специальные поля в каждой виртуальной таблице, представляющей каждый тип б/о: "contextSubjectUuid", "contextSubjectYear". Аналогично - это uuid субъекта планирования и год планирования.

Если мы хотим спросить данные например заявок из двух разных контекстов, запрос будет такой (имя VDB = AlterRequestService)

SELECT uuid, docCode, contextSubjectUuid, contextSubjectYear

FROM AlterRequest. AlterRequest

WHERE ((contextSubjectUuid = '1323bb3a-8f98-41be-8e3c-07208d320d87') AND (contextSubjectYear = 2016)) OR ((contextSubjectUuid = '0c5cc3b1-c9cf-4550-9aca-cc05b5c20d86') AND (contextSubjectYear = 2016))

Аналогично регистру мы здесь ограничились двумя контекстами.

Важно: в отличие от регистра, нельзя сделать запрос на данные бизнес-объекта вообще без указания контекстов, вследствие специфики хранения данных этих объектов. Должен быть задан хотя бы один контекст!

3) Типовой мастер-детальный запрос бизнес-объектов с заданием контекстов

Как говорилось выше, бизнес-объекты в представлении Teiid состоят из нескольких витрин, по одной для каждой детализации и одной для заголовка документа. Их нужно JOIN'ить.

Например мы хотим получить данные заявок с суммами, ограничиваясь двумя контекстами. То есть уже нужно запрашивать заголовки заявок по этим контекстам и содержание заявок по этим контекстам.

Пусть VDB заявок называется "AlterRequestService"

Запрос заголовков по контекстам отдельно выглядел бы так

SELECT c. uuid, c. contextSubjectUuid, c. contextSubjectYear, c. docCode, c. docName, c. ownerName

FROM AlterRequest. AlterRequest c

WHERE (((c. contextSubjectUuid = '1323bb3a-8f98-41be-8e3c-07208d320d87') AND (c. contextSubjectYear = 2016)) OR ((c. contextSubjectUuid = '0c5cc3b1-c9cf-4550-9aca-cc05b5c20d86') AND (c. contextSubjectYear = 2016)))

(состав колонок может быть изменен, алиас таблицы "c" добавлен для простоты построения JOIN'а ниже)

Запрос данных детализации по контекстам выглядел бы так

SELECT d. parentUuid, d. contextSubjectUuid, d. contextSubjectYear, bjectClsId, d. grbsClsId, d. fkrClsId, d. csrClsId, d. vrClsId, d. osguClsId, d. fundsTypeClsId, d. targetedFundsClsId, bsidyClsId, d. ppClsId, d. programActivitiesClsId, d. budgetClsId, m1, m2, m3

FROM AdjustmentItem. AdjustmentItem d

WHERE (((d. contextSubjectUuid = '1323bb3a-8f98-41be-8e3c-07208d320d87') AND (d. contextSubjectYear = 2016)) OR ((d. contextSubjectUuid = '0c5cc3b1-c9cf-4550-9aca-cc05b5c20d86') AND (d. contextSubjectYear = 2016)))

Как видно, у таблицы заголовка документа есть поле uuid, а у таблицы детализации - поле parentUuid. Это поля для сцепки.

Соединим запросы

SELECT c. uuid, c. docCode, c. docName, c. ownerName, bjectClsId, d. grbsClsId, d. fkrClsId, d. csrClsId, d. vrClsId, d. osguClsId, d. fundsTypeClsId, d. targetedFundsClsId, bsidyClsId, d. ppClsId, d. programActivitiesClsId, d. budgetClsId, m1, m2, m3, c. contextSubjectUuid, c. contextSubjectYear, d. contextSubjectUuid, d. contextSubjectYear

FROM AlterRequest. AlterRequest c

LEFT JOIN AdjustmentItem. AdjustmentItem d ON (c. uuid = d. parentUuid)

WHERE (((c. contextSubjectUuid = '1323bb3a-8f98-41be-8e3c-07208d320d87') AND (c. contextSubjectYear = 2016)) OR ((c. contextSubjectUuid = '0c5cc3b1-c9cf-4550-9aca-cc05b5c20d86') AND (c. contextSubjectYear = 2016)))

AND (((d. contextSubjectUuid = '1323bb3a-8f98-41be-8e3c-07208d320d87') AND (d. contextSubjectYear = 2016)) OR ((d. contextSubjectUuid = '0c5cc3b1-c9cf-4550-9aca-cc05b5c20d86') AND (d. contextSubjectYear = 2016)))

Вот и всё. Неудобство состоит в том, что контексты нужно писать для каждой таблицы, участвующей в JOIN. Обусловлено это собственно тем, что мы ограничены возможностями SQL. В будущем возможно будет разработан механизм, позволяющий задавать контекст один раз для таблицы заголовка.

4) Группировки

Допускается использование конструкции GROUP BY в запросе и агрегирующих функций. Всё это делается в соответствии с языком SQL, стоит только отметить на всякий случай, что группировка в запросе данных бизнес-объектов - обрабатывается процессором запросов Teiid уже в памяти, для чего он предварительно выбирает данные необходимых б/о. Тогда как группировка данных регистра производится самим регистром, Teiid в этом процессе участия не принимает.

8. Сохраненные запросы

Для упрощения, лучше типовые запросы данных документов, регистров, а так же типовые аналитические запросы - сохранять для последующего использования как SQL VIEW. Можно поместить их в VDB, относящуюся к предметно к тому блоку, к которому делается этот запрос, но можно и выделить в отдельную VDB.

1) Запросы сохраненные в одной VDB с источниками

Для типового мастер детального запроса к заявкам с двумя фиксированными контекстами (этот запрос мы рассматривали как основной выше), в той же VDB, где объявлены витрины для заявок, может быть добавлена следующая декларация

<model name="AlterRequestMasterDetail">

       <source name="AlterRequestMasterDetailSrc" translator-name="business-object" connection-jndi-name="java:/jndi-service-dispatcher-source"/>

       <metadata type="DDL"><![CDATA[

               CREATE VIEW AlterRequestMasterDetailFixedContext (

                       uuid string,

                       docCode string,

                       docName string,

                       ownerName string,

                       subjectClsId string,

                       grbsClsId string,

                       fkrClsId string,

                       csrClsId string,

                       vrClsId string,

                       osguClsId string,

                       fundsTypeClsId string,

                       targetedFundsClsId string,

                       subsidyClsId string,

                       ppClsId string,

                       programActivitiesClsId string,

                       budgetClsId string,

                       sum1 bigdecimal,

                       sum2 bigdecimal,

                       sum3 bigdecimal,

                       contextSubjectUuidCaption string,

                       contextSubjectYearCaption integer,

                       contextSubjectUuidDetail string,

                       contextSubjectYearDetail integer

               )

               AS SELECT c. uuid, c. docCode, c. docName, c. ownerName, bjectClsId, d. grbsClsId, d. fkrClsId, d. csrClsId, d. vrClsId, d. osguClsId, d. fundsTypeClsId, d. targetedFundsClsId, bsidyClsId, d. ppClsId, d. programActivitiesClsId, d. budgetClsId, m1, m2, m3, c. contextSubjectUuid, c. contextSubjectYear, d. contextSubjectUuid, d. contextSubjectYear

               FROM AlterRequest. AlterRequest c

               LEFT JOIN AdjustmentItem. AdjustmentItem d ON (c. uuid = d. parentUuid)

               WHERE (((c. contextSubjectUuid = '1323bb3a-8f98-41be-8e3c-07208d320d87') AND (c. contextSubjectYear = 2016)) OR ((c. contextSubjectUuid = '0c5cc3b1-c9cf-4550-9aca-cc05b5c20d86') AND (c. contextSubjectYear = 2016)))

               AND (((d. contextSubjectUuid = '1323bb3a-8f98-41be-8e3c-07208d320d87') AND (d. contextSubjectYear = 2016)) OR ((d. contextSubjectUuid = '0c5cc3b1-c9cf-4550-9aca-cc05b5c20d86') AND (d. contextSubjectYear = 2016)))

               ]]>

       </metadata>

</model>

После добавления такой декларации нет необходимости делать каждый раз запрос как в п.7, пп.3). Можно ограничиться таким запросом:

SELECT * FROM AlterRequestMasterDetail. AlterRequestMasterDetailFixedContext

добавив по необходимости атрибутные ограничения.

2) Запросы сохраненные в отдельной VDB

В общем-то логично аналитические запросы сохранять отдельно от источников, дабы не загромождать. Ничего сложного в этом нет, просто требуется дополнительная настройка.

Создадим новую VDB куда поместим VIEW, показанную выше (выборка документов Заявки с детализацией Содержание заявки по фиксированным контекстам).

Ключевой особенностью этой VDB будет то, что её модель ссылается на модели других VDB. Чтобы разрешить эту зависимость, в новую VDB добавляется строка

<import-vdb name="AlterRequestService" version="1" import-data-policies="true" />

Эта строка описывает, что текущая VDB имеет ссылку на другую VDB. Тогда она сможет использовать все витрины из импортированной VDB.

Полный код VDB с сохраненным запросом приведен ниже

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<vdb name="AlterRequestViews" version="1">

  <description>Описание</description>

  <property name="UseConnectorMetadata" value="true" />

       <import-vdb name="AlterRequestService" version="1" import-data-policies="true" />

       <model name="AlterRequestMasterDetailView">

               <source name="AlterRequestMasterDetailViewSrc" translator-name="business-object"

  connection-jndi-name="java:/jndi-service-dispatcher-source"/>

               <metadata type="DDL"><![CDATA[

                       CREATE VIEW AlterRequestMasterDetailFixedContext (

                               uuid string,

                               docCode string,

                               docName string,

                               ownerName string,

                               subjectClsId string,

                               grbsClsId string,

                               fkrClsId string,

                               csrClsId string,

                               vrClsId string,

                               osguClsId string,

                               fundsTypeClsId string,

                               targetedFundsClsId string,

                               subsidyClsId string,

                               ppClsId string,

                               programActivitiesClsId string,

                               budgetClsId string,

                               sum1 bigdecimal,

                               sum2 bigdecimal,

                               sum3 bigdecimal,

                               contextSubjectUuidCaption string,

                               contextSubjectYearCaption integer,

                               contextSubjectUuidDetail string,

                               contextSubjectYearDetail integer

                       ) AS

SELECT c. uuid, c. docCode, c. docName, c. ownerName, bjectClsId, d. grbsClsId, d. fkrClsId, d. csrClsId, d. vrClsId, d. osguClsId, d. fundsTypeClsId, d. targetedFundsClsId, bsidyClsId, d. ppClsId, d. programActivitiesClsId, d. budgetClsId, m1, m2, m3, c. contextSubjectUuid, c. contextSubjectYear, d. contextSubjectUuid, d. contextSubjectYear

FROM AlterRequest. AlterRequest c

LEFT JOIN AdjustmentItem. AdjustmentItem d ON (c. uuid = d. parentUuid)

WHERE (((c. contextSubjectUuid = '1323bb3a-8f98-41be-8e3c-07208d320d87') AND (c. contextSubjectYear = 2016)) OR ((c. contextSubjectUuid = '0c5cc3b1-c9cf-4550-9aca-cc05b5c20d86') AND (c. contextSubjectYear = 2016)))

AND (((d. contextSubjectUuid = '1323bb3a-8f98-41be-8e3c-07208d320d87') AND (d. contextSubjectYear = 2016)) OR ((d. contextSubjectUuid = '0c5cc3b1-c9cf-4550-9aca-cc05b5c20d86') AND (d. contextSubjectYear = 2016)))

               ]]>

               </metadata>

       </model>

</vdb>

9. Использование источников Teiid в отчетах BIRT

Поскольку с точки зрения потребителя, Teiid - это реляционная СУБД, к нему можно получить доступ через JDBC-драйвер.

Рассмотрим на примере VDB, приведенной выше в п.8.2.

Подключим шаблон BIRT к Teiid:

1) Должен быть запущен сервер приложений, на котором развернут Teiid и его VDB. Это не обязательно должен быть локально запущенный инстанс, но мы рассмотрим именно на примере локального.

2) Открываем BIRT Designer/Eclipse с установленным плагином BIRT.

3) Открываем существующий/создаём новый шаблон отчета.

4) Выбираем на панели следва "Data explorer".

5) Правой кнопкой мыши по "Data Sources" > "New Data Source".

6) В появившемся окне выбираем "JDBC Database Connection for Query Builder", нажимаем "Next"

7) В следующем окне выбираем "Generic JDBC", "Next"

8) Заполняем поля. В поле Database пишем "AlterRequestViews". В поле URL - "jdbc:teiid:AlterRequestViews@mm://localhost:31000". Этот URL содержит имя VDB, и настроен на локально развернутый сервер приложений. При обращении к удалённому серверу приложений вместо "localhost" потребуется вписать имя хоста, с сервером Teiid. Заполняем User name/Password. В нашем случае на тестовом сервере используем тестового пользователя "system" с паролем "mastekey".

В верхней строке "Drivers" если в выпадающем списке ещё нет Teiid JDBC driver, нажимаем плюсик.

На первой вкладке выбираем "Generic JDBC driver"

На второй вкладке нажимаем "Add JAR/Zip..." и добавляем показанные на рисунке модули, находящиеся по аналогичному пути в вашем локальном maven репозитории.

На третьей вкладке задаем свойства как показано на рисунке ниже.

Нажимаем "Ок".

Создав таким образом Data Source, нажимаем "Test connection". Если появилась ошибка, значит либо остановлен целевой сервер приложений, либо допущена ошибка в заполнении полей в этом пункте - см. текст ошибки.

Если всё хорошо - нажимаем "Finish". Соединение с Teiid создано.

9) Создадим Data set - представление конкретной сущности из Teiid. В панели "Data Explorer" (слева), нажмем правой кнопкой по узлу "Data Sets" > "New Data Set".

10) В появившемся окне выбираем созданный ранее Data Set. Нажимаем "Next".

11) В следующем окне либо вставляем ранее протестированный запрос к VDB, либо конструируем его следующим образом.

В средней секции кликаем правой кнопкой мыши, выбираем "Add table..."

В появившемся окне находим нужную витрину

Нажимаем "Ок".

Далее в этом окне с помощью GUI можно сконструировать SQL запрос, добавляя к SELECT колонки, ограничения, и т. д.

Закончив создание запроса, нажмите "Finish".

12) В следующем окне можно проверить работу созданного Data Set, выбрав слева окна "Preview results". Вы должны увидеть ожидаемую выборку из VDB, для которой конструировался запрос выше.

На запросы в Data Set распространяются те же ограничения, что и описанные ранее в этом документе в пп. 2-3.