Skip to content

SQLAlchemy 2.0 Compatibility #307

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 2 commits into from
Jan 6, 2023

Conversation

mathiasritter
Copy link
Member

@mathiasritter mathiasritter commented Dec 22, 2022

Description

In the do_execute function of SQLAlchemy dialect, an if statement was accessing context.should_autocommit. This property has been removed in SQLAlchemy 2.0.

To fix, the if statement can simply be removed as it is no longer needed. See #291 for more details.

Resolves #291

Non-technical explanation

The current dialect is incompatible with SQLAlchemy version 2.0. This change makes the dialect compatible.

Release notes

( ) This is not user-visible or docs only and no release notes are required.
( ) Release notes are required, please propose a release note for me.
(x) Release notes are required, with the following suggested text:

* Add support for SQLAlchemy 2.0. ({issue}`291`)

@cla-bot
Copy link

cla-bot bot commented Dec 22, 2022

Thank you for your pull request and welcome to our community. We could not parse the GitHub identity of the following contributors: mritter31.
This is most likely caused by a git client misconfiguration; please make sure to:

  1. check if your git client is configured with an email to sign commits git config --list | grep email
  2. If not, set it up using git config --global user.email email@example.com
  3. Make sure that the git commit email is configured in your GitHub account settings, see https://github.com/settings/emails

Copy link
Contributor

@mdesmet mdesmet left a comment

Choose a reason for hiding this comment

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

Can you also add an integration test on the sqlalchemy beta version?

See

- { python: "3.11", trino: "latest", sqlalchemy: "~=1.3.0" }

@mathiasritter
Copy link
Member Author

Thanks @mdesmet, that was what I was looking for.

Unfortunately, the tests for 2.0 are failing because of an issue in sqlalchemy-utils library. That issue has been fixed since October, but they haven't released a new version since July...
See: kvesteri/sqlalchemy-utils#666

@hashhar
Copy link
Member

hashhar commented Dec 23, 2022

We're using that library only in tests if I remember correctly - can we remove that dependency with some alternative code? It's used in two tests - just to verify whether sqla.inspect(engine).get_table_names(schema) returns only tables and whether sqla.inspect(engine).get_view_names(schema) only returns views.

Would those tests still work if we directly executed CREATE VIEW on the underlying connection instead of going via SQLA?

@mathiasritter
Copy link
Member Author

@hashhar They have just released a new version of sqlalchemy-utils that fixed the issue 😄 got some other issues now though, that I will look into later.

@mathiasritter mathiasritter force-pushed the feature/sqlalchemy-2 branch 3 times, most recently from b9b17b0 to 5934726 Compare January 3, 2023 10:56
@mathiasritter mathiasritter requested a review from mdesmet January 3, 2023 10:58
@mathiasritter mathiasritter force-pushed the feature/sqlalchemy-2 branch 6 times, most recently from 5e3fc8c to d5a33aa Compare January 3, 2023 12:22
@@ -156,7 +156,7 @@ def _get_columns(self, connection: Connection, table_name: str, schema: str = No
ORDER BY "ordinal_position" ASC
"""
).strip()
res = connection.execute(sql.text(query), schema=schema, table=table_name)
res = connection.execute(sql.text(query), {"schema": schema, "table": table_name})
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this change required for sqlalchemy 2.0.0?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes

Copy link
Member Author

Choose a reason for hiding this comment

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

@@ -351,7 +355,8 @@ def test_get_table_comment(trino_connection):
engine, conn = trino_connection

if not engine.dialect.has_schema(conn, "test"):
engine.execute(sqla.schema.CreateSchema("test"))
with engine.begin() as connection:
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this change required for sqlalchemy 2.0.0?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes

Copy link
Member Author

Choose a reason for hiding this comment

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

@mathiasritter mathiasritter force-pushed the feature/sqlalchemy-2 branch 2 times, most recently from 1a3f263 to 701cc72 Compare January 3, 2023 16:42
@mathiasritter mathiasritter requested a review from mdesmet January 3, 2023 16:44
@mdesmet
Copy link
Contributor

mdesmet commented Jan 4, 2023

@hashhar : PTAL

@@ -421,10 +428,10 @@ def test_get_view_names(trino_connection, schema):
)
metadata.create_all(engine)
view_name = schema_name + ".test_get_view_names"
conn.execute(f"CREATE VIEW {view_name} AS SELECT * FROM test_table")
conn.execute(sqla.text(f"CREATE VIEW {view_name} AS SELECT * FROM test_table"))
Copy link
Member

Choose a reason for hiding this comment

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

This conn object is a dbapi connection (see fixture trino_connection) so why do we need this sqla.text here?

Copy link
Member Author

@mathiasritter mathiasritter Jan 4, 2023

Choose a reason for hiding this comment

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

The conn object is a SQLAlchemy Connection instance:

@pytest.fixture
def trino_connection(run_trino, request):
_, host, port = run_trino
engine = sqla.create_engine(f"trino://test@{host}:{port}/{request.param}",
connect_args={"source": "test", "max_attempts": 1})
yield engine, engine.connect()

SQLAlchemy 2.0 requires this raw statement to be wrapped into text.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, 🤦 - should've seen what class the fixture is coming from. Thanks.

Copy link
Member

@hashhar hashhar left a comment

Choose a reason for hiding this comment

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

LGTM % comments

@cla-bot
Copy link

cla-bot bot commented Jan 4, 2023

Thank you for your pull request and welcome to our community. We could not parse the GitHub identity of the following contributors: Mathias Ritter.
This is most likely caused by a git client misconfiguration; please make sure to:

  1. check if your git client is configured with an email to sign commits git config --list | grep email
  2. If not, set it up using git config --global user.email email@example.com
  3. Make sure that the git commit email is configured in your GitHub account settings, see https://github.com/settings/emails

@cla-bot cla-bot bot removed the cla-signed label Jan 4, 2023
The following changes are for compatibility with SQLAlchemy 2.0, while mainting compatibility with versions >= 1.3.

In the Connection.execute function, query parameters may no longer be passed as keyword arguments.
Parameters can be passed in a dicionary instead.

Engine.execute was removed.
Statements can only be executed on the Connection object, which can be obtained via Engine.begin() or Engine.connect().

RowProxy is no longer a “proxy”; is now called Row and behaves like an enhanced named tuple.
In order to access rows, just use row.column instead of row["column"].

Raw SQL statements must be wrapped into a TextClause by calling text(...), imported from sqlalchemy.
In the do_execute function of SQLAlchemy dialect, an if statement was accessing context.should_autocommit.
This property has been removed in SQLAlchemy 2.0.
To fix, the if statement can simply be removed as it is no longer needed.
@hashhar
Copy link
Member

hashhar commented Jan 4, 2023

LGTM. @mathiasritter I assume you've sent the CLA already (and it matches the email you use in your commits)? If not please do. If sent already I'll take care of it.

@mathiasritter
Copy link
Member Author

@hashhar Yes I’ve already sent it

@hashhar hashhar merged commit d7ed5e1 into trinodb:master Jan 6, 2023
@hashhar hashhar mentioned this pull request Jan 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

SQLAlchemy 2.0 Compatibility
4 participants