Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generalization of exclusive constraints #3089

Open
vpetrovykh opened this issue Oct 25, 2021 · 0 comments
Open

Generalization of exclusive constraints #3089

vpetrovykh opened this issue Oct 25, 2021 · 0 comments
Labels

Comments

@vpetrovykh
Copy link
Member

vpetrovykh commented Oct 25, 2021

We need a way to generalize exclusive constraints to refer to something other than each value subject to the constraint being != to all other values.

In large part this is motivated by #3088 and the practical need to have non-overlapping intervals. Currently the non-overlapping constraint cannot be expressed. However, even in the imagined future where we have the interval types and the standard library functions and operators to work with them it would still be impossible to express "this interval property must be non-overlapping with other objects".

The proposal is to use existing language features as much as possible to express the exclusive constraint in a way that would allow using more complex expressions as the basis for exclusion. The premise is that generally speaking, an exclusion constraint is a statement about some expression being true for all elements subject to the constraint.

The generalized variant would look something like this:

abstract constraint invariant() extending exclusive {
    using (
        all(__subject__ = __other__)
    );
};

The expression in the using block would have to be wrapped into all, indicating that what follows is in fact a condition that must be globally true. Inside the all argument we could use __other__ (referring to all other existing subjects of the constraints) to distinguish from __subject__. Not all expressions would be valid inside that, much like we currently don't allow long paths and non-immutable functions in all constraints. We could additionally allow top level and to combine multiple properties into a single exclusive constraint where a simple tuple exclusivity does not express what we want.

For example, consider a constraint like this:

abstract constraint invariant() extending exclusive {
    using (
        all(
            __subject__.name != __other__.name and
            __subject__.cohort = __other__.cohort and
        )
    );
};

Names have to be unique, but the cohort has to be the same (whatever it is). So we can have at most one cohort at any time, and within the objects that have a cohort specified, the names have to be unique, even if they aren't globally unique. This is meant to illustrate a situation which is inexpressible by the current less generic exclusive constraints and requires different operations to be performed on different constraint parts.

The operator and is a great way to indicate such composite constraints because it distributes over all (all(A and B) = all(A) and all(B)). It is probably not as useful to allow the use of any as an alternative way of expressing such rules mostly because and and any have a more complex interaction. At the end of the day it seems that we need to reduce the expression into a all(A and B and ...) format for Postgres and this task would be harder if we allowed any as an alternative way of specifying our exclusion constraints.

As far as parameters are concerned imagine if we could specify a constraint like this:

# Ensure that all constraint subjects are close to each other.
abstract constraint grouped(distance: float64) extending exclusive {
    using (
        all((__subject__ - __other__ ) ^ 2 < $distance ^ 2 )
    );
};

It might make more sense to use expression as the base constraint in the above examples, making exclusive defined like this:

abstract constraint exclusive() extending expression {
    using (
        all(__subject__ != __other__)
    );
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants