Feat/mssql python Add optional mssql-python backend, make pyodbc optional, and update docs / CI#681
Feat/mssql python Add optional mssql-python backend, make pyodbc optional, and update docs / CI#681axellpadilla wants to merge 5 commits into
Conversation
…d pyodbc backends
|
Ok, its a big change so will take a while to review, I can see a few issues I think so I'll find some time at start providing feedback. My main concern other than the actual code change is the install method for the adapter now changes as we have to specify the driver we want to use, that is a big change. This doesn't just affect us, DBT themselves will have the wrong install instructions. https://docs.getdbt.com/docs/local/connect-data-platform/mssql-setup?version=1.12#prerequisites |
Benjamin-Knight
left a comment
There was a problem hiding this comment.
Probably need some new tests as well but will look at those after these comments.
| "decimal.Decimal": "decimal", | ||
| } | ||
|
|
||
| MSSQL_PYTHON_UNSUPPORTED_AUTHENTICATIONS = { |
There was a problem hiding this comment.
You do not have MSI in this list, there is no MSI code in the new adapter connection handling, its only in get_pyodbc_attrs_before_credentials.
| getattr(mssql_python, "OperationalError", Exception), | ||
| ] | ||
|
|
||
| if _requires_pyodbc_backend(credentials): |
There was a problem hiding this comment.
This is inside a mssql python branch but states its pyodbc, I think the _requires_pyodbc_backend just needs renaming, I think this might have been an attempt to standardize logic between two branches but the same logic appears without the function on line 573 as well? Probably needs calling there as well?
| con_str = [f"SERVER={_build_server_arg(credentials)}"] | ||
| con_str.append(f"Database={credentials.database}") | ||
|
|
||
| assert credentials.authentication is not None |
There was a problem hiding this comment.
These assert statements, so here and L494-495 are not safe, if run in optimization mode they are dropped and these values could end up resolving to false or something unexpected, just raise a DBT exception of some kind.
| database: str | ||
| schema: str | ||
| driver: Optional[str] = None | ||
| host: str = "" |
There was a problem hiding this comment.
These string defaults do not look safe, previously not provided a value would cause a proper error before connection, now it will just try and use invalid blank strings.
| "pyodbc>=5.2.0", | ||
| ] | ||
| mssql = [ | ||
| "mssql-python>=1.1.0", |
There was a problem hiding this comment.
Why such an old version of the driver? We need at least 1.4.0 for the fixes to the datetime handling.
| pyodbc.InternalError, # not used according to docs, but defined in PEP-249 | ||
| pyodbc.OperationalError, | ||
| ] | ||
| mssql_python.pooling(enabled=False) |
There was a problem hiding this comment.
pyodbc uses pooling, why are we defaulting to no pooling on mssql_python?
| backend: | ||
| - pyodbc | ||
| - mssql-python | ||
| exclude: |
There was a problem hiding this comment.
pyodbc is still going to be the default for most users, at least to start, I do not think we should drop python version testing from pyodbc, I'm okay with the recent python versions only for the mssql-python, if you are changing driver you are likely on up to date python.
| application_name = f"dbt-{credentials.type}/{plugin_version}" | ||
| con_str.append(f"APP={application_name}") | ||
|
|
||
| try: |
There was a problem hiding this comment.
Don't think we need a try except around list appends?
|
|
||
|
|
||
| def _validate_pyodbc_requirements(credentials: SQLServerCredentials) -> None: | ||
| if not credentials.driver: |
There was a problem hiding this comment.
This would allow someone providing a driver value of "", we probably want something stronger like.
if credentials.driver is None or not credentials.driver.strip():
| assert "PWD={super-secret}" in con_str | ||
| assert "encrypt=Yes" in con_str | ||
| assert "TrustServerCertificate=Yes" in con_str | ||
| assert "APP=dbt-sqlserver/" not in con_str |
There was a problem hiding this comment.
Why are we testing that the APP value is no longer set? We set it in pyodbc and its useful when debugging server side, does the new driver not support it? Its a common connection string value? I can see we do not try and set it in the new driver connection code.
|
@Benjamin-Knight I'm moving this to v1.11, I'm more interested in the other patches for v1.10 and its true we will need more time holding the rc1 pending until dbt docs are updated |
This PR introduces the new optional mssql-python connection backend while keeping the legacy pyodbc ODBC path available as an explicit extra.
Key changes:
Why this change:
Testing: