edgedb-js icon indicating copy to clipboard operation
edgedb-js copied to clipboard

Infer cardinality when using an exclusive constraint on more than one property

Open smstromb opened this issue 3 years ago • 3 comments

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)
  }));

smstromb avatar Feb 23 '22 19:02 smstromb

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.

Sikarii avatar Feb 23 '22 19:02 Sikarii

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.

jaclarke avatar Feb 23 '22 20:02 jaclarke

I understand, thank you for the explanation.

smstromb avatar Feb 23 '22 20:02 smstromb