Skip to main content
Version: 7.0

CONSTRAINT statement

The CONSTRAINT statement creates a constraint.

Syntax​

CONSTRAINT [eventClause] constraintExpr [CHECKED [BY propertyId1, ..., propertyIdN]] MESSAGE messageExpr
[PROPERTIES outExpr1, ..., outExprM];

Description​

The CONSTRAINT statement creates a constraint. If the constraint is violated, the user will be shown the message defined in the statement.

Also, by using the CHECKED option you can use the constraint when showing dialogs for changing properties whose values may violate the constraint if changed. In this instance an additional filter will be set in the dialog so that, when the property value changes, the constraint is not violated. The filter is computed from the condition as written (before the automatic SET wrapping): for every offered value the condition is evaluated as if the property being changed had been set to that value for the object being edited, on top of the changes already made in the form's session, and the values for which the condition becomes non-NULL are hidden. The other parameters of the condition are bound to the object being edited; the PREV operator inside it reads the value before the session's changes, and a change operator compares the offered value with that previous value - so under such a condition the stored value of the property remains offered, and for an object whose previous value is NULL a condition on that previous value hides nothing. If it is necessary to limit the set of properties for which the above filtering will be performed, the list of properties can be specified after the keyword BY. The filter works only in these change dialogs; input mechanisms that offer values in some other way do not use it — there a violating value is rejected only when the constraint itself is checked.

info

Creating a constraint is pretty similar to the following statements:

constraintProperty = constraintExpr;
WHEN eventClause [=GROUP MAX constraintProperty(...)]() DO {
PRINT outConstraintPropertyForm MESSAGE NOWAIT;
CANCEL;
}

but it also has a number of advantages.

Parameters​

  • eventClause

    Event description block. Describes the event upon occurrence of which the created constraint will be checked. If omitted, the global APPLY event is used.

  • constraintExpr

    An expression whose value is a condition for the constraint being created. If the obtained property does not contain the PREV operator, the platform automatically wraps it into the SET operator.

  • propertyId1, ..., propertyIdN

    List of property IDs. When showing change dialog for each property in that list, options that violate the created constraint will be filtered.

  • messageExpr

    An expression whose value is shown as a message to the user when the set constraint is violated. It must have no parameters — for example, a string literal or a property without parameters.

  • outExpr1, ..., outExprM

    List of expressions over the parameters of the constraint condition whose values are displayed in a message to the user when the specified constraint is violated. If no list is specified, the properties matching the parameter classes of the constraint condition and belonging to property group System.id are selected.

Examples​

// balance not less than 0
CONSTRAINT balance(Sku s, Stock st) < 0 MESSAGE 'The balance cannot be negative for ' +
(GROUP CONCAT 'Product: ' + name(Sku ss) + ' Warehouse: ' + name(Stock sst), '\n' IF SET(balance(ss, sst) < 0) ORDER sst);

barcode = DATA STRING[15] (Sku);
// "emulation" security policy
CONSTRAINT DROPCHANGED(barcode(Sku s)) AND name(currentUser()) != 'admin'
MESSAGE 'Only the administrator is allowed to change the barcode for an already created product';

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] // a filter by available sku when selecting an item for an order line will be applied
MESSAGE 'In the order, a product unavailable to the user is selected for the selected customer';

CLASS Task;
CLASS Status;
allowed = DATA BOOLEAN (Status, Status); // from which status to which one the transition is allowed
status = DATA Status (Task);
// only the transitions allowed from the stored status: the status selection dialog offers the stored status
// and the statuses allowed from it, and all statuses for a task without a stored status
CONSTRAINT SETCHANGED(status(Task t)) AND PREV(status(t)) AND NOT allowed(PREV(status(t)), status(t))
CHECKED BY status[Task]
MESSAGE 'The status transition is not allowed';