edgedb-js
edgedb-js copied to clipboard
Infer cardinality when using an exclusive constraint on more than one property
Given the following minimal schema:
type Person {
required property some_prop -> str;
required property some_other_prop -> str;
constraint exclusive on ( (.some_prop, .some_other_prop) );
}
I would expect the following query to infer Cardinality.AtMostOne:
const person = e.select(e.Person, (user) => ({
filter: e.op(
e.op(user.some_prop, '=', e.str('some value')),
'and',
e.op(user.some_other_prop, '=', e.str('some other value'))
)
}));
However, it infers Cardinality.Many. Furthermore, as an attempted work-around, adding a limit of 1 to the query does not appear to infer Cardinality.AtMostOne either. I'm not sure if this is a regression from https://github.com/edgedb/edgedb-js/pull/127
const person = e.select(e.Person, () => ({
// Setting the limit seems to have no effect on the inferred cardinality
limit: e.int64(1)
}));
From @colinhacks on Discord a week ago:
this is a known limitation — we skipped this initially because it's a pretty rare case and adds a fair bit of complexity to the inference infrastructure, but we'll look into it.
You can use assert_single() as a workaround, hope this helps for now.
Furthermore, as an attempted work-around, adding a limit of 1 to the query does not appear to infer Cardinality.AtMostOne either. I'm not sure if this is a regression from https://github.com/edgedb/edgedb-js/pull/127
At one point we did have cardinality inference on limit 1, but we realised that it could cause the cardinality inferred statically by typescript to go out of sync with the cardinality we track at runtime, so we had to remove it. Essentially when we see {limit: 1} at runtime we can't be sure whether typescript saw it as {limit: 1} or {limit: number}, and so whether to track the cardinality of the expression as AtMostOne or Many.
I understand, thank you for the explanation.