Skip to content

Conversation

@Masterchen09
Copy link
Contributor

When playing around with the OData API of the SAP Analytics Cloud to retrieve some stories, I have noticed that the nav method did not work with many to one relationships. The SAC API specifies such an relationship between a story and users (createdByUser, a story can be created only by one user, but a user can create many stories): Either you have to specify a key for the nav method or to use the get_entities method which both not works as the target entity is not a list of entities (the entity is returned directly and not in a results array) or as an invalid url is generated (the target entity is being indexed, which does not work as it is not an list).

I have tracked down this issue down to line 886 (and 1362) where the multiplicity for all roles is checked and when the multiplicity for one of the role is "*" the check fails. Here only the multiplicity of the "ToRole" should be checked as this role is the relevant role for the navigation.

Additionally when writing a test for this case I have found another issue: It is not possible to use the nav method with associations where both ends are of the same entity type. The logic for finding the navigation_entity_set in line 877-880 (and 1352-1359) is using the entity set name for finding the role in the association set: This does not work if both roles has the same entity set name. Here the method end_by_role method of the association set can be used to find the correct role (and then the correct navigation_entity_set).

@cla-assistant
Copy link

cla-assistant bot commented Aug 8, 2022

CLA assistant check
All committers have signed the CLA.

…ps and for associations with relationships to same entity
@Masterchen09 Masterchen09 force-pushed the fix-many-to-one-navigation branch from 98acc08 to 34825a9 Compare August 8, 2022 20:12
@phanak-sap
Copy link
Contributor

phanak-sap commented Aug 11, 2022

Hi @ Masterchen09
Thank you for not only uncovering more than one problem, but also providing fix for all of them.

If you want to improve small things, you can ammend the commit message (so it is not half-splitted), e.g. b678d0a, and update the changelog.md as well. I will look into the proper code review, but on first glance it looks good. I think after this PR merge I will immediately release 1.9.2 with this fix.

@phanak-sap phanak-sap self-requested a review August 11, 2022 09:36
Comment on lines -882 to -883
if not navigation_entity_set:
raise PyODataException(f'No association set for role {navigation_property.to_role}')
Copy link
Contributor

@phanak-sap phanak-sap Aug 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the bug is about "many to one relationships", why remove this exception rise? Even the second part of the PR description - "it is not possible to use the nav method with associations where both ends are of the same entity type." - as I understand it, the case that you would like to refer to something that does not exist at all is still valid.

The exception rise is removed multiple times, line 1358 (original).

As an example - consider metadata file, that is invalid, but forced to be parsed anyway - and then you can end easily with trying to access something which is not there at all.

It bothers me a bit that there is not a test that would start to fail by removing these lines - that for specific input we expect this exception to be thrown. But if such test existed, this PR would be IMHO backward-incompatible change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have removed this exception because the end_by_role method is raising a KeyError in case the end role was not found. I have thought about to handle the KeyError and raising the PyODataException, but this would be a bit redundant. However, due to the possible KeyError of end_by_role the navigation_entity_set can never be None (e.g. in case of an invalid metadata file) and the PyODataException would never be raised.

association_info.namespace)

navigation_entity_set = None
for end in association_set.end_roles:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was the for loop removed? Again, all tests are still passing, but this may be a problem of the test suite - that the loop was not covered so far, just simple cases around navigational properties.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The loop is not necessary (anymore) because the end_by_role method of the association_set is "looping" over the association_set.end_roles using the generator expression here:

return next((item for item in self._end_roles if item.role == end_role))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, that's true. And also, since now test metadata.xml contains multimple association sets ending to same end role (Customer), it is proven by tests.

Copy link
Contributor

@phanak-sap phanak-sap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All questions answered, all builds are passing, looking good.

Thanks for the good work.

@phanak-sap phanak-sap merged commit b6fdbb6 into SAP:master Aug 11, 2022
@Masterchen09 Masterchen09 deleted the fix-many-to-one-navigation branch August 11, 2022 18:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants