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

WIP: feat: Add contains_exactly filter #391

Open
wants to merge 2 commits into
base: add-filters
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions examples/filters/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@


def create_app() -> FastAPI:
print("HERE")
init_db()
print("HERE?")
app = FastAPI()

app.mount("/graphql", GraphQLApp(schema, on_get=make_playground_handler()))
Expand Down
72 changes: 69 additions & 3 deletions graphene_sqlalchemy/filters.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import re
from typing import Any, Dict, List, Tuple, Type, TypeVar, Union

from sqlalchemy import and_, not_, or_
from sqlalchemy.orm import Query, aliased # , selectinload
from sqlalchemy import and_, func, not_, or_, select
from sqlalchemy.orm import Query, aliased, subqueryload # , selectinload

import graphene
from graphene.types.inputobjecttype import (
Expand Down Expand Up @@ -441,7 +441,73 @@
relationship_prop,
val: List[ScalarFilterInputType],
):
raise NotImplementedError
# working for sqlalchemy<1.4

# print("Contains exactly called: ", query, val)
# # Construct clauses from child_model_ids
# session = query.session
# child_model_ids = []
# for v in val:
# print("Contains exactly loop: ", v)

# # Always alias the model
# joined_model_alias = aliased(relationship_prop)

# subquery = session.query(joined_model_alias.id)
# subquery, _clauses = cls._meta.base_type_filter.execute_filters(
# subquery, v, model_alias=joined_model_alias
# )
# subquery_ids = [s_id[0] for s_id in subquery.filter(and_(*_clauses)).all()]
# child_model_ids.extend(subquery_ids)

# # Join the relationship onto the query
# joined_model_alias = aliased(relationship_prop)
# joined_field = field.of_type(joined_model_alias)
# query = query.join(joined_field)

# query = (
# query.filter(joined_model_alias.id.in_(child_model_ids))
# .group_by(parent_model)
# .having(func.count(str(field)) == len(child_model_ids))
# # TODO should filter on aliased field
# # .having(func.count(joined_field) == len(child_model_ids))
# )

# sqlalchemy 1.4 attempt

# do select()
# write down query without session
# main_query.subqueryload()
# use query.where() instead of query.filter()

# Always alias the model
joined_model_alias = aliased(relationship_prop)
subquery = select(joined_model_alias.id)
for v in val:
print("Contains exactly loop: ", v)

Check warning on line 487 in graphene_sqlalchemy/filters.py

View check run for this annotation

Codecov / codecov/patch

graphene_sqlalchemy/filters.py#L484-L487

Added lines #L484 - L487 were not covered by tests

subquery, _clauses = cls._meta.base_type_filter.execute_filters(

Check warning on line 489 in graphene_sqlalchemy/filters.py

View check run for this annotation

Codecov / codecov/patch

graphene_sqlalchemy/filters.py#L489

Added line #L489 was not covered by tests
subquery, v, model_alias=joined_model_alias
)
subquery = subquery.where(and_(*_clauses))

Check warning on line 492 in graphene_sqlalchemy/filters.py

View check run for this annotation

Codecov / codecov/patch

graphene_sqlalchemy/filters.py#L492

Added line #L492 was not covered by tests

print("HERE")

Check warning on line 494 in graphene_sqlalchemy/filters.py

View check run for this annotation

Codecov / codecov/patch

graphene_sqlalchemy/filters.py#L494

Added line #L494 was not covered by tests

print(subquery)

Check warning on line 496 in graphene_sqlalchemy/filters.py

View check run for this annotation

Codecov / codecov/patch

graphene_sqlalchemy/filters.py#L496

Added line #L496 was not covered by tests

joined_model_alias = aliased(relationship_prop)
joined_field = field.of_type(joined_model_alias)
query = query.join(joined_field)

Check warning on line 500 in graphene_sqlalchemy/filters.py

View check run for this annotation

Codecov / codecov/patch

graphene_sqlalchemy/filters.py#L498-L500

Added lines #L498 - L500 were not covered by tests

query = (

Check warning on line 502 in graphene_sqlalchemy/filters.py

View check run for this annotation

Codecov / codecov/patch

graphene_sqlalchemy/filters.py#L502

Added line #L502 was not covered by tests
select(parent_model)
.options(subqueryload(joined_model_alias.id))
.where(joined_model_alias.id.in_(subquery))
.group_by(parent_model)
.having(func.count(str(field)) == func.count(subquery))
)

return query, []

Check warning on line 510 in graphene_sqlalchemy/filters.py

View check run for this annotation

Codecov / codecov/patch

graphene_sqlalchemy/filters.py#L510

Added line #L510 was not covered by tests

@classmethod
def execute_filters(
Expand Down