ConvertDataConnection
ConvertDataConnection - преобразующее загружающее соединение с данными, которое получает данные из другого загружающего соединения с данными и позволяет изменить структуру данных. Полный список селекторов для модификации структуры данных можно найти в статье справочника по синтаксису платформы WT, а здесь кратко познакомимся с часто используемыми.
Пример практического применения ConvertDataConnection рассматривается в Уроке 26. Работа с JSON на форме.
Работать будем с формой и запросами из раздела Подготовка.
Добавление новых полей
Частым случаем применения ConvertDataConnection является необходимость расширить набор полей исходного DataConnection. Например, добавить поля Added, Updated и Deleted, чтобы при редактировании записи на форме устанавливать статус, который проверять при сохранении изменений в базу данных.
Для этих целей используется селектор типа Value, который добавляет колонку с именем из атрибута Name
и типом данных из атрибута DataType
. Для каждой строки в ячейку новой колонки ставиться значение, указанное в качестве значения тэга. Изменить значения полей можно через set-проперти AddRow, AddRows, UpdateRow, UpdateRows, UpdateColumn и UpdateColumnCellsValues в команде типа ValueSetCommand.
<DataConnection Name="ClientConvertDataConnection" Type="ConvertDataConnection" Assembly="WorkflowServer">
<SourceDataConnection Name="ClientPrimaryGetDataConnection" />
<Fields>
<Field Name="ClientId" />
<Field Name="Title" />
<Field Name="CityId" />
<Field Name="Added" Type="Value" DataType="BooleanDataType">False</Field>
<Field Name="Updated" Type="Value" DataType="BooleanDataType">False</Field>
<Field Name="Deleted" Type="Value" DataType="BooleanDataType">False</Field>
</Fields>
</DataConnection>
Подстановка значений
Вторым по частоте использования является селектор типа Substitution, который добавляет колонку с именем из атрибута Name
, а значение для нее берет из матрицы подстановки по ключу из поля, указанному в атрибуте Field
.
<DataConnection Name="ClientConvertDataConnection" Type="ConvertDataConnection" Assembly="WorkflowServer">
<SourceDataConnection Name="ClientPrimaryGetDataConnection" />
<Fields>
<Field Name="ClientId" />
<Field Name="Title" />
<Field Name="CityId" />
<Field Name="CityTitle" Type="Substitution" Field="CityId">
<DataConnection SourceDataConnection="CityPrimaryGetDataConnection">
<Fields>
<Field Name="CityId" />
<Field Name="Title" />
</Fields>
</DataConnection>
</Field>
</Fields>
</DataConnection>
Подстановка сработает только при обновлении ConvertDataConnection, которое будет при загрузки формы и при обновлении источника данных, если не задан элемент ManualRefresh со значением True, а так же по команде типа DataConnectionRefreshCommand.
Поэтому при добавлении записи или редактировании колонки с ключом для подстановки нужно задавать значение
Замена подстрок
Бывают ситуации, когда в SQL-запросе формируется текстовая строка, в которой необходимо заменить подстроку. Например, в строку встраивается ключ, а на форме вместо ключа должно подставиться конкретное значение.
В качестве примера в запросе будем формировать строку из фамилии клиента и в круглых скобках указывать идентификатор города. На форме в ConvertDataConnection вместо идентификатора будем подставлять название города.
Скорректируем запрос TestClientSelectSqlQuery, добавив поле TitleWithCity:
<SqlQuery Name="TestClientSelectSqlQuery">
<Text>
SELECT
client_id AS "ClientId",
title AS "Title",
city_id AS "CityId",
archive AS "Archive",
title || ' (' || city_id || ')' AS "TitleWithCity"
FROM
template.client
ORDER BY client_id;
</Text>
</SqlQuery>
Добавим в ClientPrimaryGetDataConnection новое поле TitleWithCity, а затем переделаем ClientConvertDataConnection:
<DataConnection Name="ClientConvertDataConnection" Type="ConvertDataConnection" Assembly="WorkflowServer">
<SourceDataConnection Name="ClientPrimaryGetDataConnection" />
<Fields>
<Field Name="ClientId" />
<Field Name="TitleWithCity" Type="Replace">
<DataConnection SourceDataConnection="CityPrimaryGetDataConnection">
<Fields>
<Field Name="CityId" />
<Field Name="Title" />
</Fields>
</DataConnection>
</Field>
</Fields>
</DataConnection>
Для тэга <Field>
в атрибуте Name
укажем имя новой колонки, в которой будет происходить замена. А в качестве значения тэга <Field>
передадим соединение с данными со списком городов. Это соединение будет выступать матрицей замены, где первый столбец - ключ, по которому будет идти замена.
Укажем ClientConvertDataConnection в качестве источника данных в таблице ResultDatabaseTable, и скорректируем ее колонки.
Запустим форму, чтобы проверить результат:

Форматирование строки
Бывает необходимость собрать текстовую строку, содержащую данные из других полей той же строки соединения с данными. Для этого используется селектор типа Format. В качестве значения тэга ожидается строка-шаблон, с указанием в фигурных скобках {}
имен полей исходного соединения с данными, которые будут источниками значений.
Скорректируем запрос TestClientSelectSqlQuery, добавив поле CityTitle:
<SqlQuery Name="TestClientSelectSqlQuery">
<Text>
SELECT
client.client_id AS "ClientId",
client.title AS "Title",
client.city_id AS "CityId",
client.archive AS "Archive",
city.title AS "CityTitle"
FROM
template.client
LEFT JOIN template.city USING(city_id)
ORDER BY client_id;
</Text>
</SqlQuery>
Добавим в ClientPrimaryGetDataConnection новое поле CityTitle, а затем переделаем ClientConvertDataConnection:
<DataConnection Name="ClientConvertDataConnection" Type="ConvertDataConnection" Assembly="WorkflowServer">
<SourceDataConnection Name="ClientPrimaryGetDataConnection" />
<Fields>
<Field Name="ClientId" />
<Field Name="ClientTitle" Type="Format">{Title} ({CityTitle})</Field>
</Fields>
</DataConnection>
Укажем его в качестве источника данных в таблице ResultDatabaseTable, и скорректируем ее колонки.
Запустим форму, чтобы проверить результат:

Сложные шаблоны
Для форматирования строки по шаблону существует еще один селектор типа TemplateFormat, который позволяет использовать в шаблоне условные операторы.
Давайте рассмотрим пример, добавления в имя клиента постфикса (арх.), если запись находится в архиве:
<DataConnection Name="ClientConvertDataConnection" Type="ConvertDataConnection" Assembly="WorkflowServer">
<SourceDataConnection Name="ClientPrimaryGetDataConnection" />
<Fields>
<Field Name="ClientId" />
<Field Name="Title" Type="TemplateFormat">{{Title}}{{if Archive}} (арх.){{end}}</Field>
<Field Name="Archive" />
</Fields>
</DataConnection>
Укажем его в качестве источника данных в таблице ResultDatabaseTable, и скорректируем ее колонки.
Запустим форму, чтобы проверить результат:

Вложенные массивы
Для обработки вложенных массивов используется селектор типа Action, который поддерживает операций по работе с массивами, перечисленные в статье Array.
Скорректируем запрос TestClientSelectSqlQuery, добавив поля с вложенными массивами:
<SqlQuery Name="TestClientSelectSqlQuery">
<Text>
WITH _material AS (
SELECT
O.client_id,
array_agg(M.title) AS materials,
array_agg(OP.quantity * OP.unit_price) AS total_price
FROM
template.order_position OP
LEFT JOIN template.order O USING(order_id)
LEFT JOIN template.material M USING(material_id)
LEFT JOIN template.material_category MC USING(material_category_id)
LEFT JOIN template.unit U USING(unit_id)
GROUP BY O.client_id
)
SELECT
C.client_id AS "ClientId",
C.title AS "Title",
C.city_id AS "CityId",
C.archive AS "Archive",
M.materials AS "Materials",
M.total_price AS "TotalPrice"
FROM
template.client C
LEFT JOIN _material M USING(client_id)
ORDER BY client_id;
</Text>
</SqlQuery>
Результат выполнения этого запроса будет иметь вид:

Добавим в ClientPrimaryGetDataConnection новые поля Materials и TotalPrice, а затем переделаем ClientConvertDataConnection:
<DataConnection Name="ClientConvertDataConnection" Type="ConvertDataConnection" Assembly="WorkflowServer">
<SourceDataConnection Name="ClientPrimaryGetDataConnection" />
<Fields>
<Field Name="ClientId" />
<Field Name="Title" />
<Field Name="MaterialsAction" Type="Action" Field="Materials">
<StringJoin Separator=", " />
</Field>
<Field Name="TotalPriceAction" Type="Action" Field="TotalPrice">
<Sum Type="DecimalDataType" />
</Field>
</Fields>
</DataConnection>
Укажем его в качестве источника данных в таблице ResultDatabaseTable, и скорректируем ее колонки.
Запустим форму, чтобы проверить результат:

Last updated