From: Gord Thompson Date: Thu, 17 Sep 2020 16:32:31 +0000 (-0600) Subject: Add support for Azure authentication options X-Git-Tag: rel_1_3_20~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a908d4e9af0593dd74e1c9ef7768cc546c68dbf3;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Add support for Azure authentication options Fixes: #5592 Change-Id: I0688e5ea0fc6b01a0b72f397daea8f57a2ec0766 (cherry picked from commit dcd2be16b9c9a6a52b6bb7e144e31998b7cee631) --- diff --git a/doc/build/changelog/unreleased_13/5592.rst b/doc/build/changelog/unreleased_13/5592.rst new file mode 100644 index 0000000000..294fadfffc --- /dev/null +++ b/doc/build/changelog/unreleased_13/5592.rst @@ -0,0 +1,8 @@ +.. change:: + :tags: bug, mssql + :tickets: 5592 + + Fixed issue where a SQLAlchemy connection URI for Azure DW with + ``authentication=ActiveDirectoryIntegrated`` (and no username+password) + was not constructing the ODBC connection string in a way that was + acceptable to the Azure DW instance. diff --git a/lib/sqlalchemy/connectors/pyodbc.py b/lib/sqlalchemy/connectors/pyodbc.py index 57a1c54fb4..e49625147d 100644 --- a/lib/sqlalchemy/connectors/pyodbc.py +++ b/lib/sqlalchemy/connectors/pyodbc.py @@ -95,9 +95,15 @@ class PyODBCConnector(Connector): user = keys.pop("user", None) if user: connectors.append("UID=%s" % user) - connectors.append("PWD=%s" % keys.pop("password", "")) + pwd = keys.pop("password", "") + if pwd: + connectors.append("PWD=%s" % pwd) else: - connectors.append("Trusted_Connection=Yes") + authentication = keys.pop("authentication", None) + if authentication: + connectors.append("Authentication=%s" % authentication) + else: + connectors.append("Trusted_Connection=Yes") # if set to 'Yes', the ODBC layer will try to automagically # convert textual data from your database encoding to your diff --git a/lib/sqlalchemy/dialects/mssql/pyodbc.py b/lib/sqlalchemy/dialects/mssql/pyodbc.py index c198c37c77..22e20c14c0 100644 --- a/lib/sqlalchemy/dialects/mssql/pyodbc.py +++ b/lib/sqlalchemy/dialects/mssql/pyodbc.py @@ -52,7 +52,8 @@ name must be URL encoded which means using plus signs for spaces:: Other keywords interpreted by the Pyodbc dialect to be passed to ``pyodbc.connect()`` in both the DSN and hostname cases include: -``odbc_autotranslate``, ``ansi``, ``unicode_results``, ``autocommit``. +``odbc_autotranslate``, ``ansi``, ``unicode_results``, ``autocommit``, +``authentication`` (e.g., ``authentication=ActiveDirectoryIntegrated``). Note that in order for the dialect to recognize these keywords (including the ``driver`` keyword above) they must be all lowercase. diff --git a/test/dialect/mssql/test_engine.py b/test/dialect/mssql/test_engine.py index 8f9d8629c0..d99799a6a4 100644 --- a/test/dialect/mssql/test_engine.py +++ b/test/dialect/mssql/test_engine.py @@ -158,6 +158,26 @@ class ParseConnectTest(fixtures.TestBase): True, ) + def test_pyodbc_extra_connect_azure(self): + # issue #5592 + dialect = pyodbc.dialect() + u = url.make_url( + "mssql+pyodbc://@server_name/db_name?" + "driver=ODBC+Driver+17+for+SQL+Server;" + "authentication=ActiveDirectoryIntegrated" + ) + connection = dialect.create_connect_args(u) + eq_(connection[1], {}) + eq_( + connection[0][0] + in ( + "DRIVER={ODBC Driver 17 for SQL Server};" + "Server=server_name;Database=db_name;" + "Authentication=ActiveDirectoryIntegrated", + ), + True, + ) + def test_pyodbc_odbc_connect(self): dialect = pyodbc.dialect() u = url.make_url(