denisenkom / pytds

Python DBAPI driver for MSSQL using pure Python TDS (Tabular Data Stream) protocol implementation
MIT License
192 stars 53 forks source link

Fail-over partner parameter doesn't quite work as expected #176

Open Wedge009 opened 6 hours ago

Wedge009 commented 6 hours ago

I appreciate this is a small project. My interest was piqued because this seems to be the only Python package I can find that claims to support SQL Server's 'fail-over partner' connection parameter. If I had a choice, I would likely avoid SQL Server altogether...

Giving python-tds a try (1.15.0 current at time of writing), I can get a connection once I negotiate its encryption specification (in contrast, I can use Trusted_Connection=yes in pyodbc and I don't have to manually install pyopenssl):

pytds.connect(dsn='<database server>', database='<database name>', failover_partner='<database mirror>', port=50433, cafile='<internal>.pem', use_sso=True)
<pytds.connection.NonMarsConnection object at 0x000001459A8134A0>

However, if the initial server given is the server that's unavailable, then I run into the same issue as what I get with pyodbc where it cannot specify a 'fail-over partner':

pytds.connect(dsn='<unavailable server>', database='<database name>', failover_partner='<available server>', port=50433, cafile='<internal>.pem', use_sso=True)
Traceback (most recent call last):
  File ".../venv/Lib/site-packages/pytds/utils.py", line 41, in exponential_backoff
    return work(try_time)
           ^^^^^^^^^^^^^^
  File ".../venv/Lib/site-packages/pytds/__init__.py", line 357, in attempt
    return _connect(
           ^^^^^^^^^
  File ".../venv/Lib/site-packages/pytds/__init__.py", line 453, in _connect
    route = tds_socket.login()
            ^^^^^^^^^^^^^^^^^^
  File ".../venv/Lib/site-packages/pytds/tds_socket.py", line 95, in login
    if not self._main_session.process_login_tokens():
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../venv/Lib/site-packages/pytds/tds_session.py", line 1571, in process_login_tokens
    self.process_token(marker)
  File ".../venv/Lib/site-packages/pytds/tds_session.py", line 1586, in process_token
    return handler(self)
           ^^^^^^^^^^^^^
  File ".../venv/Lib/site-packages/pytds/tds_session.py", line 1745, in <lambda>
    tds_base.TDS_DONE_TOKEN: lambda self: self.process_end(tds_base.TDS_DONE_TOKEN),
                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../venv/Lib/site-packages/pytds/tds_session.py", line 430, in process_end
    self.raise_db_exception()
  File ".../venv/Lib/site-packages/pytds/tds_session.py", line 176, in raise_db_exception
    raise ex
pytds.tds_base.OperationalError: ("The target database, '<database name>', is participating in an availability group and is currently not accessible for queries. Either data movement is suspended or the availability replica is not enabled for read access. To allow read-only access to this and other databases in the availability group, enable read access to one or more secondary availability replicas in the group.  For more information, see the ALTER AVAILABILITY GROUP statement in SQL Server Books Online.", None)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File ".../venv/Lib/site-packages/pytds/__init__.py", line 398, in connect
    return utils.exponential_backoff(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../venv/Lib/site-packages/pytds/utils.py", line 53, in exponential_backoff
    raise TimeoutError() from ex
TimeoutError

Specifically, the pytds.tds_base.OperationalError is the same as what I get with pyodbc.

Possibly related to #167.

Wedge009 commented 4 hours ago

Is this supposed to be resolved in #170 and we are just waiting for a new release?