Инструкция CONSTRAINT
Инструкция CONSTRAINT - создание ограничения.
Синтаксис
CONSTRAINT [eventClause] constraintExpr [CHECKED [BY propertyId1, ..., propertyIdN]] MESSAGE messageExpr
[PROPERTIES outExpr1, ..., outExprM];
Описание
Инструкция CONSTRAINT создает ограничение. При нарушении ограничения пользователю будет выдано указанное в инструкции сообщение.
Также с помощью опции CHECKED можно использовать созданное ограничение при вызове диалогов изменения свойств, изменение значений которых может нарушить ограничение. В этом случае в диалоге будет устанавливаться дополнительный фильтр, таким образом, чтобы при изменении значения свойства не нарушить созданное ограничение. Фильтр вычисляется из условия в том виде, как оно записано (до автоматического заключения в SET): для каждого предлагаемого значения условие вычисляется так, как если бы изменяемое свойство уже было установлено в это значение для редактируемого объекта, поверх изменений, уже сделанных в сессии формы, и значения, при которых условие становится не NULL, скрываются. Остальные параметры условия связываются с редактируемым объектом; оператор PREV внутри него читает значение до изменений сессии, а оператор изменения сравнивает предлагаемое значение с этим предыдущим значением - поэтому при таком условии хранимое значение свойства остаётся предложенным, а для объекта, у которого предыдущее значение NULL, условие на это предыдущее значение ничего не скрывает. Если необходимо ограничить набор свойств, для которых будет выполняться указанная выше фильтрация, то список свойств может быть указан после ключевого слова BY. Фильтр действует только в этих диалогах изменения; механизмы ввода, предлагающие значения иным способом, его не используют — там нарушающее значение отклоняется только при самой проверке ограничения.
Создание ограничения во многом аналогично следующей инструкции:
constraintProperty = constraintExpr;
WHEN eventClause [=GROUP MAX constraintProperty(...)]() DO {
PRINT outConstraintPropertyForm MESSAGE NOWAIT;
CANCEL;
}
но при этом имеет ряд преимуществ.
Параметры
-
eventClauseБлок описания события. Описывает событие, при наступлении которого будет проверяться создаваемое ограничение. Если не указан, используется глобальное событие
APPLY. -
constraintExprВыражение, значение которого является условием создаваемого ограничения. Если полученное свойство не содержит внутри оператора
PREV, то платформа автоматически оборачивает его в операторSET. -
propertyId1, ..., propertyIdNСписок идентификаторов свойств. Для каждого перечисленного свойства в диалоге изменения свойства будет выполняться фильтрация вариантов, которые нарушают создаваемое ограничение.
-
messageExprВыражение, значение которого выдаётся в качестве сообщения пользователю, когда заданное ограничение нарушается. Не должно иметь параметров — например, строковый литерал или свойство без параметров.
-
outExpr1, ..., outExprMСписок выражений над параметрами условия ограничения, значения которых выдаются в сообщении пользователю, когда заданное ограничение нарушается. Если список не указывается, то выбираются свойства, подходящие по классам параметров к условию ограничения и принадлежащие группе свойств
System.id.
Примеры
// остаток не меньше 0
CONSTRAINT balance(Sku s, Stock st) < 0 MESSAGE 'Остаток не может быть отрицательным для ' +
(GROUP CONCAT 'Товар: ' + name(Sku ss) + ' Склад: ' + name(Stock sst), '\n' IF SET(balance(ss, sst) < 0) ORDER sst);
barcode = DATA STRING[15] (Sku);
// "эмуляция" политики безопасности
CONSTRAINT DROPCHANGED(barcode(Sku s)) AND name(currentUser()) != 'admin'
MESSAGE 'Изменять штрих-код для уже созданного товара разрешено только администратору';
sku = DATA Sku (OrderDetail);
in = DATA BOOLEAN (Sku, Customer);
CONSTRAINT sku(OrderDetail d) AND NOT in(sku(d), customer(order(d)))
CHECKED BY sku[OrderDetail] // будет применяться фильтр по доступным sku при выборе товара для строки заказа
MESSAGE 'В заказе выбран недоступный пользователю товар для выбранного покупателя';
CLASS Task;
CLASS Status;
allowed = DATA BOOLEAN (Status, Status); // из какого статуса в какой разрешён переход
status = DATA Status (Task);
// только разрешённые переходы из хранимого статуса: диалог выбора статуса предлагает хранимый статус
// и разрешённые из него статусы, а для задачи без хранимого статуса - все статусы
CONSTRAINT SETCHANGED(status(Task t)) AND PREV(status(t)) AND NOT allowed(PREV(status(t)), status(t))
CHECKED BY status[Task]
MESSAGE 'Переход в этот статус не разрешён';