-
Notifications
You must be signed in to change notification settings - Fork 16.3k
Build correct SQLAlchemy URI in Teradata Hook #56305
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -22,8 +22,8 @@ | |||||||
| import re | ||||||||
| from typing import TYPE_CHECKING, Any | ||||||||
|
|
||||||||
| import sqlalchemy | ||||||||
| import teradatasql | ||||||||
| from sqlalchemy.engine import URL | ||||||||
| from teradatasql import TeradataConnection | ||||||||
|
|
||||||||
| from airflow.providers.common.sql.hooks.sql import DbApiHook | ||||||||
|
|
@@ -34,6 +34,7 @@ | |||||||
| except ImportError: | ||||||||
| from airflow.models.connection import Connection # type: ignore[assignment] | ||||||||
|
|
||||||||
| DEFAULT_DB_PORT = 1025 | ||||||||
| PARAM_TYPES = {bool, float, int, str} | ||||||||
|
|
||||||||
|
|
||||||||
|
|
@@ -166,7 +167,7 @@ def _get_conn_config_teradatasql(self) -> dict[str, Any]: | |||||||
| conn: Connection = self.get_connection(self.get_conn_id()) | ||||||||
| conn_config = { | ||||||||
| "host": conn.host or "localhost", | ||||||||
| "dbs_port": conn.port or "1025", | ||||||||
| "dbs_port": conn.port or DEFAULT_DB_PORT, | ||||||||
| "database": conn.schema or "", | ||||||||
| "user": conn.login or "dbc", | ||||||||
| "password": conn.password or "dbc", | ||||||||
|
|
@@ -195,12 +196,32 @@ def _get_conn_config_teradatasql(self) -> dict[str, Any]: | |||||||
|
|
||||||||
| return conn_config | ||||||||
|
|
||||||||
| def get_sqlalchemy_engine(self, engine_kwargs=None): | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is technically a breaking change. @eladkal do we need to do anything?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @sc250072 can you raise PR to re add the function to preserve backward compatibility and raise deprecation warning for it?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It will fall back to this method and return the same URL from sqlalchemy_url. But any case,
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Could you please clarify what you mean by a breaking change?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. one who uses older Teradata provider might break. (as this method has been removed and might be used), but if we're to bump major version. that should be fine |
||||||||
| """Return a connection object using sqlalchemy.""" | ||||||||
| conn: Connection = self.get_connection(self.get_conn_id()) | ||||||||
| link = f"teradatasql://{conn.login}:{conn.password}@{conn.host}" | ||||||||
| connection = sqlalchemy.create_engine(link) | ||||||||
| return connection | ||||||||
| @property | ||||||||
| def sqlalchemy_url(self) -> URL: | ||||||||
| """ | ||||||||
| Override to return a Sqlalchemy.engine.URL object from the Teradata connection. | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm a bit confused. override what to return the object?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
@Lee-W to return the sqlalchemy.engine.URL objectWill add the suggestion |
||||||||
|
|
||||||||
| :return: the extracted sqlalchemy.engine.URL object. | ||||||||
| """ | ||||||||
| connection = self.get_connection(self.get_conn_id()) | ||||||||
| # Adding only teradatasqlalchemy supported connection parameters. | ||||||||
| # https://pypi.org/project/teradatasqlalchemy/#ConnectionParameters | ||||||||
| url_kwargs = { | ||||||||
| "drivername": "teradatasql", | ||||||||
| "username": connection.login, | ||||||||
| "password": connection.password, | ||||||||
| "host": connection.host, | ||||||||
| "port": connection.port, | ||||||||
| } | ||||||||
|
|
||||||||
| if connection.schema: # Only include database if it's not None or empty | ||||||||
| url_kwargs["database"] = connection.schema | ||||||||
|
|
||||||||
| return URL.create(**url_kwargs) | ||||||||
|
|
||||||||
| def get_uri(self) -> str: | ||||||||
| """Override DbApiHook get_uri method for get_sqlalchemy_engine().""" | ||||||||
| return self.sqlalchemy_url.render_as_string() | ||||||||
|
|
||||||||
| @staticmethod | ||||||||
| def get_ui_field_behaviour() -> dict: | ||||||||
|
|
||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Probably could add a link to the doc that mentions 1025 as a comment above this line.