Skip to content

Fix distinct bug #290

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

Merged
merged 5 commits into from
Jun 5, 2018
Merged

Conversation

danyx23
Copy link
Contributor

@danyx23 danyx23 commented Oct 11, 2017

This adds a test case and fixes /issues/289. Please review and let me know if anythin should change, I'm not an expert in either graphql nor django :)

@spockNinja
Copy link
Contributor

@danyx23

This problem should be resolved by #194 or #224, which handles more than just the distinct being lost.

If you can verify that those fixes solve your problem, we can close this PR and it's corresponding issue.

Thanks!

@jussih
Copy link

jussih commented Oct 24, 2017

@spockNinja #194 or #224 do not fix this issue. Distinct and non-distinct querysets cannot be combined, assertion in Django prevents this.

Really needing distinct queries, I resorted to casting the qs to a list before returning it at the end of the resolver function. This prevents DjangoConnectionField from trying to merge it.

BTW what is the use case of enforced merge_querysets? It seems to basically do Model.objects.all() AND [resolved_iterable] which does nothing (except breaking distincts ;).

Copy link
Contributor

@spockNinja spockNinja left a comment

Choose a reason for hiding this comment

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

A few discussion points. Also, the new test is currently failing. See https://travis-ci.org/graphql-python/graphene-django/jobs/286635259#L744

@@ -90,6 +90,10 @@ def connection_resolver(cls, resolver, connection, default_manager, max_limit,
if isinstance(iterable, QuerySet):
if iterable is not default_manager:
default_queryset = maybe_queryset(default_manager)
if default_queryset.query.distinct and not iterable.query.distinct:
Copy link
Contributor

Choose a reason for hiding this comment

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

How about moving this logic into merge_querysets? Then any of the subclasses that use that will get this fix for free.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea, did that

@@ -90,6 +90,10 @@ def connection_resolver(cls, resolver, connection, default_manager, max_limit,
if isinstance(iterable, QuerySet):
if iterable is not default_manager:
default_queryset = maybe_queryset(default_manager)
if default_queryset.query.distinct and not iterable.query.distinct:
iterable = iterable.distinct()
Copy link
Contributor

Choose a reason for hiding this comment

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

How does this behave when the other distinct call had field args? (queryset.distinct('field_1', 'field_2'))

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 honestly have no idea. From my superficial understanding it should be fine :). Do I understand it correctly that this is only possible when using postgres backends?


result = schema.execute(query)
assert not result.errors
print(result.data)
Copy link
Contributor

Choose a reason for hiding this comment

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

Lets be sure to drop this print once the test is working.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Copy link
Member

Choose a reason for hiding this comment

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

the print is still there :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah sorry, missed your comment - thanks, will fix now!

@danyx23
Copy link
Contributor Author

danyx23 commented Dec 2, 2017

Updated the PR. The travis check seems to rebase this on top of master but my test was written against django-graphene 1.x (4 parameters to resolve functions). Is there a way to make travis test this against the 1.x branch and once everyone is fine with the PR we adapt it to 2.0 and merge an updated PR there? Or is the 1.x line no longer supported?

@spockNinja
Copy link
Contributor

Since this PR is merging into master, it will need to use the latest resolver signature. If you also want a PR to add this for an older version, you can target the PR against the tagged version instead of the master branch.

There also appears to be a merge conflict in fields.py.

Thanks a bunch for your work. Let's get those last things fixed up and I'll pass this on to the owner for a final review. 😄

@patrys
Copy link

patrys commented Feb 15, 2018

@danyx23 Are you still working on this? If not I'd be happy to pick it where you've left it and adapt it for the current master.

@jussih The default qs implementation returning model.objects.all() is an implementation detail of django-filters so unless you propose that we detect whether a queryset is filtered, I think there's no easy way to skip merging in the default case of unfiltered data.

@danyx23
Copy link
Contributor Author

danyx23 commented Feb 20, 2018

Ah damn, I totally forgot about this. Yes, I'll rebase against master and send an updated PR!

…d involving a query with inner join and distinct that is then filtered and would be combined with a filtered queryset that is not distinct.
@coveralls
Copy link

coveralls commented Feb 28, 2018

Coverage Status

Coverage decreased (-0.02%) to 94.562% when pulling c323406 on DouglasConnect:fix-distinct-bug into dbd3957 on graphql-python:master.

@danyx23
Copy link
Contributor Author

danyx23 commented Feb 28, 2018

Rebased against master, tests are green. Please let me know if you are happy for this to merge. (It's the first time I rebased a github PR, I should probably have created a new one to preserve the history of the old commits, sorry abou that)

@danyx23
Copy link
Contributor Author

danyx23 commented Mar 28, 2018

Do you mind merging this or do you consider it blocked because the coverage decreased by 0.08%?

class Query(graphene.ObjectType):
films = DjangoConnectionField(FilmType)

# def resolve_all_reporters_with_berlin_films(self, args, context, info):
Copy link
Member

Choose a reason for hiding this comment

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

sorry last one :) Is this needed?

I guess after resolving this @spockNinja or @syrusakbary can merge :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There might be a way to integrate it with the existing test suite but I didn't see a straightforward way to construct a query that would lead to one "half" of the resulting query being distinct and the other not. Doing it in this way keeps the addition localized to where it is needed. If you have a suggestion on how to integrate it with the existing model instead please let me know!

@syrusakbary
Copy link
Member

The PR looks good 👍 . Merging

@syrusakbary syrusakbary closed this Jun 5, 2018
@syrusakbary syrusakbary reopened this Jun 5, 2018
@syrusakbary syrusakbary merged commit 7563045 into graphql-python:master Jun 5, 2018
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.

DjangoConnectionField triggers django orm sql asserts with complex resolve + filtering
7 participants