MassChange
- Класс
MassChange
- Поддерживает документацию
- да
- Поддерживает extras
- нет
MassChange (массовое изменение) — возможность применить однотипное изменение к различным элементам дерева проекта по условию. В дереве проекта хранятся в коллекции Mass changes в модуле приложения. На файловой системе хранятся по умолчанию в src/massChanges.yaml. Пример:
- select: Entity#messages Query roles: []
Данное массовое изменение выбирает все представления сущности messages и устанавливает им пустой список ролей.
Каждый элемент списка содержит селектор (select) и определение элемента. Для всех элементов, которые соответствуют селектору, производится переопределение указанных свойств точно так же, как в приложении кастомизируется элемент из модуля. В принципе селектор может соответствовать элементам разного типа, в некоторых случаях это сработает. Например:
- select: Entity#blahblah Query, Entity#blahblah Operation roles: []
Удалит все роли у всех представлений и операций сущности blahblah. Но лучше разносить подобное на отдельные селекторы.
Селектор пока может выбирать Query, Operation или Entity. Если селектор выбрал что-то другое, будет ошибка.
Содержание
- 1 Селекторы
- 2 Примеры
- 2.1 Изменение кода операций
- 2.2 Специальная операция для редактирования словарей
- 2.3 Удаление ролей для нескольких таблиц
- 2.4 Удаление ролей для всех операций по имени
- 2.5 Разрешить фильтровать словари всем
- 2.6 Администратору базы данных разрешить менять все словари
- 2.7 Добавить специальный запрос во все сущности кроме dummy
- 2.8 Добавить запрос Table definition в сущности, primary key которых не является dummy
Селекторы
Синтаксис селекторов похож на CSS. Спецсимволы обрабатываются в соответствии со стандартом CSS. Поддерживаются следующие возможности:
- Выбор по классу (аналог CSS type selector). Указывается просто название типа элементов. Пока поддерживаются Module, Entity, Query, Operation. Например:
Operation
- Такой селектор просто выберет все представления.
- Выбор по атрибуту (аналог CSS attribute value selectors). Поддерживаются формы
[attr=val], [attr^=val], [attr$=val], [attr*=val]
для точного совпадения значения, префикса, суффикса и подстроки. Список доступных атрибутов зависит от типа данных и обычно похож на список полей при сериализации в yaml. Например:
[name="messages"]
- Такой селектор выберет все элементы с именем messages.
- Выбор имени. Для сокращения предыдущий селектор можно написать так:
#messages
- Но при этом значение уже должно удовлетворять свойствам идентификатора, а не строки (например, нужно экранировать пробелы).
- Выбор типа. У Entity, Query и Operation бывает тип. Его можно выбрать через
[type="..."]
, но короче через точку:
.table
- Выберет все элементы с типом table. Доступные типы:
- Для Entity: table, dictionary, collection, genericCollection, metadata
- Для Query: 1D, 1D_unknown, 2D, static, custom, container, javascript
- Для Operation: java, sql, javafunction, js (=javascript), jsserver (=javascriptserver), dotnet, javadotnet
- Сложный селектор (CSS: compound selector). Несколько правил, написанных слитно. Выбирается элемент, удовлетворяющий всем правилам. Например:
Entity#messages
- Тут два правила: выбрать элементы по классу Entity (то есть сущности) и выбрать элементы с именем messages. В результате будет выбрана сущность с именем messages.
- Комбинатор-потомок (CSS: descendant combinator). Если перечислить несколько селекторов через пробел, будут выбраны элементы, удовлетворяющие последнему селектору, у которых есть родитель (не обязательно непосредственный), удовлетворяющий предпоследнему, и т. д. Например:
Entity#messages Query
- Выберет все представления сущности с именем messages. Другие CSS-комбинаторы (>, +, ~) не поддерживаются.
- Список селекторов (CSS: selector list). Можно перечислить через запятую несколько селекторов, тогда элемент будет выбран, если он подходит под любой из селекторов. Например:
Query, Operation
- Выберет все представления и все операции.
- Псевдокласс :not (CSS: negation). Выберет элементы, которые не удовлетворяют заданному в скобках селектору. Например:
Entity:not(.table)
- Выберет все сущности, тип которых не table.
- Псевдокласс :matches (CSS: matches). Выберет элементы, которые удовлетворяют хотя бы одному из заданных в скобках селекторов. Например:
Entity:matches(#users,#persons) Query
- Выберет все представления из сущностей с именами users и persons.
Примеры
Примеры старого SQL
-кода и соответствующего массового изменения:
Изменение кода операций
UPDATE operations SET code = 'com.beanexplorer.enterprise.operations.SilentEditOperation' WHERE code = 'com.beanexplorer.enterprise.operations.EditOperation' AND table_name != 'colorSchemes';
select: Entity:not(#colorSchemes) Operation[code="com.beanexplorer.enterprise.operations.EditOperation"] code: com.beanexplorer.enterprise.operations.SilentEditOperation
Специальная операция для редактирования словарей
UPDATE operations SET code = 'com.beanexplorer.ru.social.operations.DictionaryEdit' WHERE table_name IN ( SELECT name FROM entities WHERE type = 'dictionary' ) AND code = 'com.beanexplorer.enterprise.operations.EditOperation' AND name = 'Edit';
select: Entity.dictionary Operation#Edit[code="com.beanexplorer.enterprise.operations.EditOperation"] code: com.beanexplorer.ru.social.operations.DictionaryEdit
Удаление ролей для нескольких таблиц
DELETE FROM queries_per_role WHERE queryID IN ( SELECT q.ID FROM queries q WHERE q.name IN ( 'All records' ) AND q.table_name IN ( 'gpsDeviceTypes', 'gpsDevices' ) );
select: Entity:matches(#gpsDevices,#gpsDeviceTypes) Query[name="All records"] roles: []
Или
select: Entity[name^=gpsDevice] Query[name="All records"] roles: []
Удаление ролей для всех операций по имени
DELETE FROM operations_per_role WHERE operID IN ( SELECT o.ID FROM operations o WHERE o.name IN ( 'Explain Plan', 'Parent Record' ) );
select: Operation[name="Explain Plan"], Operation[name="Parent Record"] roles: []
Или
select: Operation:matches([name="Explain Plan"], [name="Parent Record"]) roles: []
Разрешить фильтровать словари всем
INSERT INTO operations_per_role SELECT o.ID, r.role_name FROM operations o, roles r WHERE o.table_name IN ( SELECT name FROM entities WHERE type = 'dictionary' ) AND o.name IN ( 'Filter' ) AND r.role_name IN ( r.role_name ) ;
select: Entity.dictionary Operation#Filter roles: '@AllRoles'
Администратору базы данных разрешить менять все словари
DELETE FROM operations_per_role WHERE role_name IN ( SELECT r.role_name FROM roles r WHERE r.role_name IN ( 'DbAdmin' ) ) AND operID IN ( SELECT o.ID FROM operations o WHERE o.table_name IN ( SELECT name FROM entities WHERE type='dictionary' AND origin IN ('ru.mfc') ) AND o.name in ( o.name ) ); INSERT INTO operations_per_role SELECT o.ID, r.role_name FROM operations o, roles r WHERE o.table_name IN ( SELECT name FROM entities WHERE type='dictionary' AND origin IN ('ru.mfc') ) AND o.name IN ( o.name ) AND r.role_name IN ( 'DbAdmin' ) ;
select: Module#ru\.mfc Entity.dictionary Operation roles: +DbAdmin
Добавить специальный запрос во все сущности кроме dummy
INSERT_INTO(queries) table_name, name, isInvisible, query ) SELECT name, 'Exchange: Modified Data', 'yes', _DBMS_CONCAT( 'SELECT * FROM ', name, '<if parameter="dateFrom"> WHERE modificationDate___ >= ''<parameter:dateFrom /> 00:00:00''</if>' ) FROM entities WHERE SUBSTRING(name,1,1) != '_';
select: Entity:not([name^=_]) queries: - 'Exchange: Modified Data': code: SELECT * FROM ${entity.getName()} <if parameter="dateFrom"> WHERE modificationDate___ >= '<parameter:dateFrom /> 00:00:00'</if> invisible: true
Добавить запрос Table definition в сущности, primary key которых не является dummy
-- add missing table defs in one powerful stroke ;-) INSERT INTO queries( table_name, name, query, type ) SELECT e.name, 'Table definition', ' ', '1D' FROM entities e WHERE e.primaryKeyColumn != '_dummy_' AND NOT EXISTS( SELECT 1 FROM queries q WHERE q.table_name = e.name AND q.name = 'Table definition' );
select: Entity:not([primaryKey="_dummy_"]) queries: - Table definition: {}