Selecting field used in filter_single causes "cardinality MANY which does not match the expected cardinality ONE"
When selecting a link that was selected in filter_single you get a ResultCardinalityMismatchError: the query has cardinality MANY which does not match the expected cardinality ONE error.
Copying the edgeql query (i.e. .toEdgeQL()) and executing it directly does not error, so the issue appears to be with the query builder.
The query looks silly, but makes more sense when selecting the account initially from another exclusive constraint, or when the query is constructed from something like graphql
Code
e.select(e.Item, () => ({
filter_single: {
account: e.select(e.Account, () => ({ filter_single: { name: 'abc' } })),
key: 123
},
account: {
id: true,
name: true,
},
}).run(client);
Schema
module default {
type Account {
required name: str { constraint exclusive; }
}
type Item {
required account: Account;
requred key: int32;
constraint exclusive on ((.account, .key));
}
}
Error or desired behavior
ResultCardinalityMismatchError: the query has cardinality MANY which does not match the expected cardinality ONE
at RawConnection._parseErrorMessage (/***/node_modules/edgedb/dist/baseConn.js:333:21)
at RawConnection._executeFlow (/***/node_modules/edgedb/dist/baseConn.js:940:34)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at RawConnection.fetch (/***/node_modules/edgedb/dist/baseConn.js:992:17)
at ClientConnectionHolder.retryingFetch (/***/node_modules/edgedb/dist/baseClient.js:182:26)
at Client.querySingle (/***/node_modules/edgedb/dist/baseClient.js:509:20)
Workaround
Using e.assert_single and filter doesn't suffer from this issue
Versions (please complete the following information):
- OS:
- EdgeDB version (e.g.
2.0):3.2+bb17a05(same error in 3.1) - EdgeDB CLI version (e.g.
2.0):3.4.0+160d07d edgedb-jsversion (e.g.0.20.10;):1.3.4@edgedb/generateversion (e.g.0.0.7;):0.3.1- Typescript version:
5.1.3 - Node/Deno version:
18.12.1
We should be inferring the same cardinality as the EdgeQL compiler, which is the real bug here. We detect the cardinality of the query here as ONE (based on the use of filter_single), but for some reason the database is indicating that the cardinality ought to be MANY, and since we use querySingle on queries that we think ought to be EMPTY, ONE, and AT_MOST_ONE, we throw this error at query time.
It feels like the query ought to have a cardinality of ONE, so the real question here is why the server is responding with a MANY cardinality option here: is it a bug? If it is indeed MANY, we ought to detect this in the filter_single case and (ideally) make it a TypeScript compile-time error instead of a runtime error.