7.7 Arbitrary Constraints

Occasionally, %mandatory, %prohibit and %size are just not flexible enough. We might, for instance, want to ensure that if a field is present, then it must have a certain relationship to other fields. Or we might want to stipulate that under certain conditions only, a record contains a particular field.

To this end, recutils provides a way for arbitrary field constraints to be defined. These permit restrictions on the presence and/or value of fields, based upon the value or presence of other fields within that record. This is done using the %constraint special field. Its usage is:

%constraint: expr

where expr is a selection expression (see Selection Expressions). When a constraint is present in a record set it means that all the records of that type must satisfy the selection expression, i.e. the evaluation of the expression with the record returns 1. Otherwise an integrity error is raised.

Consider for example a record type Task featuring two fields of type date called Start and End. We can use a constraint in the record set to specify that the task cannot start after it finishes:

%rec: Task
%type: Start,End date
%constraint: Start << End

The “implies” operator => is especially useful when defining constraints, since it can be used to specify conditional constraints, i.e. constraints applying only in certain records. For example, we could specify that if a task is closed then it must have an End date in the following way:

%rec: Task
%type: Start,End date
%constraint: Start << End
%constraint: Status = 'CLOSED' => #End

It is acceptable to declare several constraints in the same record set.