]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Add support for Azure authentication options
authorGord Thompson <gord@gordthompson.com>
Thu, 17 Sep 2020 16:32:31 +0000 (10:32 -0600)
committerGord Thompson <gord@gordthompson.com>
Fri, 18 Sep 2020 19:25:51 +0000 (13:25 -0600)
Fixes: #5592
Change-Id: I0688e5ea0fc6b01a0b72f397daea8f57a2ec0766
(cherry picked from commit dcd2be16b9c9a6a52b6bb7e144e31998b7cee631)

doc/build/changelog/unreleased_13/5592.rst [new file with mode: 0644]
lib/sqlalchemy/connectors/pyodbc.py
lib/sqlalchemy/dialects/mssql/pyodbc.py
test/dialect/mssql/test_engine.py

diff --git a/doc/build/changelog/unreleased_13/5592.rst b/doc/build/changelog/unreleased_13/5592.rst
new file mode 100644 (file)
index 0000000..294fadf
--- /dev/null
@@ -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.
index 57a1c54fb43c039dfe78d4bbb437752cfe94ffea..e49625147d683f4e0cffc759391e14c826278c0c 100644 (file)
@@ -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
index c198c37c779db06b5934469b031c43bac5c0bd05..22e20c14c063a6f76947592adbaaa04fe07e008e 100644 (file)
@@ -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.
 
index 8f9d8629c0dcaebdfccef1fe0c90bc8dbe2041dd..d99799a6a4dc22542fadde5401816bafd85bf5ad 100644 (file)
@@ -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(