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

Enable integration testing with postgres and check in failing test with secondary relationship #20

Merged
merged 9 commits into from
Sep 8, 2023

Conversation

mattalbr
Copy link
Contributor

I tried reasonably hard (~1 day) to fix the actual bug, but I don't understand sqlalchemy's relationship inspection well enough.

The local remote pairs on the Employee.departments.property is:

[(Column('e_id', Integer(), table=<employee>, primary_key=True, nullable=False), Column('employee_id', Integer(), ForeignKey('employee.e_id'), table=<employee_department_join_table>, primary_key=True, nullable=False)), (Column('d_id', Integer(), table=<department>, primary_key=True, nullable=False), Column('department_id', Integer(), ForeignKey('department.d_id'), table=<employee_department_join_table>, primary_key=True, nullable=False))]

So our strategy of filtering on in_(tuple([getattr(self, local.key) for local, _ in local_remote_pairs])) falls through.

local_columns more helpfully shows just e_id, so maybe there's a way we can join on the local entity and filter on that.

I think if we instead passed the key as only local_columns and changed the query to:

related_model = relationship.entity.entity
self_model = relationship.parent.entity
query = (
    select(
        related_model, self_model
    )
    .join(relationship.secondary, relationship.secondaryjoin)
    .join(self_model, relationship.primaryjoin)
    .filter(tuple_(*[column for column in relationship.local_columns]).in_(keys))
)

and changed our grouping to be on getattr(row[1], local.key)

it should work, but I'm not sure if there are corner cases with composite foreign keys, which my team doesn't use.

@mattalbr
Copy link
Contributor Author

Checks in the test that demonstrates #19

@mattalbr mattalbr requested review from patrick91 and erikwrede July 13, 2023 14:45
requirements.txt Outdated
sqlalchemy>=1.4
strawberry-graphql>=0.95
testing.postgresql>=1.3
Copy link
Member

Choose a reason for hiding this comment

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

didn't know about this 😊

I wonder if it might best to use github actions for that? or it is better to use this since it does work locally too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

At my company we run it locally with no problem, and isn't too heavy weight (test setup takes on the order of 1s)! Just need to have postgres installed on the device, which I'll add to our devcontainer once we have a devcontainer. testing.postgresql is basically just a convenient wrapper around postgres to make it easy (and performant) to use in tests. We also then use github actions to run a testing docker container, which of course has postgres installed.

Speaking of github actions, it appears none ran for this PR, so my money is on this library not having any CI/CD setup yet. It looks like strawberry core uses devcontainer and github actions, which is awesome because my company does the same so I'm familiar with both. In the next PR, I'm going to try to just copy over .devcontainer and .github from strawberiy-grpahql/strawberry, some config files from the root directory, make a few tweaks, and see if that'll get us CI/CD for ~free

Copy link
Member

Choose a reason for hiding this comment

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

ok! sounds good to me 😊

the strawberry devcontainer might not be up-to-date, I don't really use it personally :)

also we did migrate all our tests to nox, which makes it easier to test multiple dependencies 😊

Copy link
Member

@erikwrede erikwrede left a comment

Choose a reason for hiding this comment

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

Great first steps! 🚀
I believe in the long run we should really leverage SQLAlchemy's internals for relationship loading. All the edge cases are already covered there, and it will be less effort to adjust in the future. For reference:
https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/batching.py

requirements.txt Outdated
pytest-cov==3.0.0
sentinel==0.3.0
# Will sqlalchemy 2.0 work with create_engine(future=True) in unittets?
Copy link
Member

Choose a reason for hiding this comment

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

No, we need a parametrized conftest that dynamically creates session and engine based on SQLAlchemy version.

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

Comment on lines 42 to 60
@pytest.fixture
def engine(postgresql) -> Engine:
engine = sqlalchemy.create_engine(postgresql.url(), future=True)
yield engine
Copy link
Member

Choose a reason for hiding this comment

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

Can we make this fixture driver-agnostic? I'd prefer to have it so we can easily add sqlite and mysql. Especially sqlite is important for quickly running the tests. Postgres should not be required to develop locally on this library, but we should just provide the Postgres Pipeline in the repo.

Copy link
Member

Choose a reason for hiding this comment

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

/cc @patrick91 do you think we can get all the botberry pre release stuff in here without much effort?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What do you think of this @erikwrede? engine is now parameterized on DB type, and dynamically requests the appropriate fixture. For now, it's just postgresql but sqlite should be an easy add.

In the future, we might even be able to skip postgresql tests if postgresql isn't installed.

If you had a different idea about how to do this, I'm open!

@mattalbr
Copy link
Contributor Author

mattalbr commented Aug 4, 2023

Haven't lost track of this just got busy at work! Looking to pick it back up next week, thanks for the comments.

@mattalbr mattalbr requested a review from erikwrede August 8, 2023 18:48
@botberry
Copy link
Member

botberry commented Sep 8, 2023

Hi, thanks for contributing to Strawberry 🍓!

We noticed that this PR is missing a RELEASE.md file. We use that to automatically do releases here on GitHub and, most importantly, to PyPI!

So as soon as this PR is merged, a release will be made 🚀.

Here's an example of RELEASE.md:

Release type: patch

Description of the changes, ideally with some examples, if adding a new feature.

Release type can be one of patch, minor or major. We use semver, so make sure to pick the appropriate type. If in doubt feel free to ask :)

@codecov-commenter
Copy link

Welcome to Codecov 🎉

Once merged to your default branch, Codecov will compare your coverage reports and display the results in this comment.

Thanks for integrating Codecov - We've got you covered ☂️

@codspeed-hq
Copy link

codspeed-hq bot commented Sep 8, 2023

CodSpeed Performance Report

Merging #20 will not alter performance

Comparing mattalbr:secondary (2aabbfe) with main (8341ab5)

Summary

✅ 1 untouched benchmarks

@mattalbr mattalbr merged commit 2585016 into strawberry-graphql:main Sep 8, 2023
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.

5 participants