cubicweb #5503537 _may_be_shared_with too greedy / 'Unsupported' badly handled by _insert_snippet [open]

In some cases, a rql expression may add new constraints on a variable if shared with it, leading to a loss of solutions on the original request.

Changing the implementation of _may_be_shared_with by "return None" solve the problem.

Here is an attempt to explain the issue.

Given the following model:

class Org(EntityType):

class Event(EntityType):
    __permissions__ = {
        'read': (
            'X organized_by U',
            'X organized_by ORG, ORG is Org, ORG owned_by U'

    organized_by = SubjectRelation('Org', 'CWUser')

The following request should fail with an assertion fail in

Any X, X_ORG WHERE X is Event, X organized_by X_ORG

The error has 2 roots:

1/ because of _may_be_share_with(), X_ORG gets inserted in the 2nd expression. This ends up in a solution loss, detected in compute_solution(), which raises a Unsupported().

2/ Unsupported is caught in _insert_snippet, which is supposed to revert the insertion attempt. But it does not restore the solutions, leading to the assertion failure later.

A side-effect may happen if we fix 2 only: Some snippet may be completely lost, leading to an incorrect resulting request (ie missing some conditions).

The workaround is to make _may_be_shared_with() returns 'None' all the time. But we miss a potentially (it has not been evaluated) interesting optimisation by avoiding joins.

I do not think fixing 2/ is enough, because of the mentionned side-effect.

The right solution would be to evaluate, in _may_be_shared_with() itself, if the expression introduces new constraints that may restrict global solutions, in which case no sharing is done.

done in<not specified>
closed by<not specified>