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

FilterRestrictions & SortRestrictions on non-entity sets #2042

Closed
falbert-ptc opened this issue Jan 6, 2025 · 4 comments
Closed

FilterRestrictions & SortRestrictions on non-entity sets #2042

falbert-ptc opened this issue Jan 6, 2025 · 4 comments

Comments

@falbert-ptc
Copy link

Filter and Sort Restrictions annotations can only be applied to Entity Set or collection properties:
<Term Name="FilterRestrictions" Type="Capabilities.FilterRestrictionsType" Nullable="false" **AppliesTo="EntitySet Collection"**> <Annotation Term="Core.AppliesViaContainer" /> <Annotation Term="Core.Description" String="Restrictions on filter expressions" /> </Term>

Let's take the following use cases:

  1. Entity Type A has no entity set. It could be only available via one or more containment navigations or as a return type of a function or action. How do I flag that a given property on that entity type is never filterable or sortable ? Do I have to add a NavigationRestrictions annotation for each navigation property of that type ? What about when used as a return type in Functions ?
  2. Given the following type hierarchy: Entity Type B -> Entity Type C where Entity Type B has no entity set but Entity Type C does. How do I flag non-filterable properties from Entity Type B ?
  3. Given the following type hierarchy: Entity Type B -> Entity Type C where Entity Type C has no entity set but Entity Type B does. How do I flag non-filterable properties from Entity Type C ?
  4. Given the following type hierarchy: Entity Type B -> Entity Type C where both Entity Type C and Entity Type B have entity sets. Should non-filterable properties from Entity Type B be mentioned on Entity Set C ?

I have intentionally limited the use cases above to FilterRestrictions, but I have the same questions for SortRestrictions.

It seems to me it should be possible to apply the FilterRestrictions and SortRestrictions annotations for each Entity Type (and even Complex Type) to advertise to clients that some query options are not supported in certain situations. I understand there could be scenarios where specific entity sets have more or less restrictions, which the current model supports.

Any inputs would be greatly appreciated.

Thank you

@HeikoTheissen HeikoTheissen moved this to Open in OData TC Jan 7, 2025
@HeikoTheissen
Copy link
Contributor

HeikoTheissen commented Jan 9, 2025

The capability annotations are not meant to be used on entity types, but only on annotation targets that start with an entity container, or embedded in a container child (entity set, function or action import).

The idea behind this is that the same entity type can have different capabilities when it is addressed via different entity sets or containment navigation properties, or reused in different services via edmx:Include.

This has the following consequences for your questions:

  1. The annotation must be made on every containment navigation path where it applies. The return type of a function can be targeted as MySchema.MyEntityContainer/MyFunctionImport/$ReturnType. Additional addressings like MySchema.MyEntityContainer/MyEntitySet/MyFunction/$ReturnType are currently in discussion, see Should support annotations to bound actions/functions via path #393.
  2. Since they are inherited by entity type C, properties from entity type B can be targeted as MySchema.MyEntityContainer/EntitySetC/PropertyFromEntityTypeB.
  3. If entity type C has no entity set, there cannot be any capability annotations for it. Its properties can be annotated where they occur in members of entity set B that have the derived type, they are then targeted as MySchema.MyEntityContainer/EntitySetB/MySchema.EntityTypeC/PropertyFromEntityTypeC (the third segment is a type cast).
  4. Properties on entity set C do not inherit capabilities from entity set B, because capabilities are defined on entity sets whereas inheritance is between entity types. Such properties must therefore be targeted independently, via MySchema.MyEntityContainer/EntitySetB/PropertyFromEntityTypeC and MySchema.MyEntityContainer/EntitySetC/PropertyFromEntityTypeC.

I hope this answers your query.

@HeikoTheissen HeikoTheissen moved this from Open to Resolved in OData TC Jan 9, 2025
@falbert-ptc
Copy link
Author

Thank you, that helps clarify.

A couple follow up questions:

  1. Does that mean there currently is no way to address bound actions & functions in paths?
  2. For containment navigations, I'm not 100% sure I understand the meaning of this comment:

Using a property of NavigationPropertyRestriction in a NavigationRestrictions annotation is discouraged in favor of using an annotation with the corresponding term from this vocabulary and a target path starting with a container and ending in the NavigationProperty, unless the favored alternative is impossible because a dynamic expression requires an instance path whose evaluation starts at the target of the NavigationRestrictions annotation.

I'm not clear on what the annotations would look like. Is the below correct ?

<EntitySet Name="EntitySetB" EntityType="MySchema.EntityTypeB">
  <Annotation Term="Org.OData.Capabilities.V1.FilterRestrictions">
    <Record>
      <PropertyValue Property="NonFilterableProperties">
        <Collection>
          <PropertyPath>PropertyFromEntityTypeB</PropertyPath>
        </Collection>
      </PropertyValue>
    </Record>
  </Annotation>
  <Annotation Term="Org.OData.Capabilities.V1.NavigationRestrictions">
    <Record>
      <PropertyValue Property="RestrictedProperties">
        <Collection>
          <PropertyValue Property="NonFilterableProperties">
            <Collection>
              <PropertyPath>NavPropertyFromEntityTypeB/PropertyFromEntityTypeA</PropertyPath>
            </Collection>
        </PropertyValue>
        </Collection>
      </PropertyValue>
    </Record>
  </Annotation>
</EntitySet>

Thank you

@HeikoTheissen
Copy link
Contributor

  1. Does that mean there currently is no way to address bound actions & functions in paths?

Yes. The planned way to address this is described in #233.

  1. Is the below correct ?

Your first annotation is correct. The second annotation could be

<Annotation Term="Org.OData.Capabilities.V1.NavigationRestrictions">
  <Record>
    <PropertyValue Property="RestrictedProperties">
      <Collection>
        <Record>
          <PropertyValue Property="NavigationProperty"
            NavigationPropertyPath="NavPropertyFromEntityTypeB" />
          <PropertyValue Property="FilterRestrictions">
            <Record>
              <PropertyValue Property="NonFilterableProperties">
                <Collection>
                  <PropertyPath>NavPropertyFromEntityTypeB/PropertyFromEntityTypeA</PropertyPath>
                </Collection>
              </PropertyValue>
            </Record>
          </PropertyValue>
        </Record>
      </Collection>
    </PropertyValue>
  </Record>
</Annotation>

But the preferred (and more concise) way to annotate this is like in your first annotation, but with a navigation property path as target:

<Annotations Target="MySchema.MyContainer/EntitySetB/NavPropertyFromEntityTypeB">
  <Annotation Term="Org.OData.Capabilities.V1.FilterRestrictions">
    <Record>
      <PropertyValue Property="NonFilterableProperties">
        <Collection>
          <PropertyPath>PropertyFromEntityTypeA</PropertyPath>
        </Collection>
      </PropertyValue>
    </Record>
  </Annotation>
</Annotations>

@falbert-ptc
Copy link
Author

Thank you very much for the clarifications.
That helps a lot!

@github-project-automation github-project-automation bot moved this from Resolved to Closed in OData TC Jan 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Closed
Development

No branches or pull requests

2 participants