dibbler/sqlalchemy/dialects/mssql/pymssql.py

98 lines
3.1 KiB
Python
Raw Normal View History

2017-04-15 18:33:29 +02:00
# mssql/pymssql.py
# Copyright (C) 2005-2017 the SQLAlchemy authors and contributors
# <see AUTHORS file>
#
# This module is part of SQLAlchemy and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php
2010-05-07 19:33:49 +02:00
2017-04-15 18:33:29 +02:00
"""
.. dialect:: mssql+pymssql
:name: pymssql
:dbapi: pymssql
:connectstring: mssql+pymssql://<username>:<password>@<freetds_name>/?\
charset=utf8
:url: http://pymssql.org/
2010-05-07 19:33:49 +02:00
2017-04-15 18:33:29 +02:00
pymssql is a Python module that provides a Python DBAPI interface around
`FreeTDS <http://www.freetds.org/>`_. Compatible builds are available for
Linux, MacOSX and Windows platforms.
2010-05-07 19:33:49 +02:00
"""
2017-04-15 18:33:29 +02:00
from .base import MSDialect
from ... import types as sqltypes, util, processors
2010-05-07 19:33:49 +02:00
import re
2017-04-15 18:33:29 +02:00
2010-05-07 19:33:49 +02:00
class _MSNumeric_pymssql(sqltypes.Numeric):
def result_processor(self, dialect, type_):
if not self.asdecimal:
return processors.to_float
else:
return sqltypes.Numeric.result_processor(self, dialect, type_)
2017-04-15 18:33:29 +02:00
2010-05-07 19:33:49 +02:00
class MSDialect_pymssql(MSDialect):
supports_sane_rowcount = False
driver = 'pymssql'
2017-04-15 18:33:29 +02:00
2010-05-07 19:33:49 +02:00
colspecs = util.update_copy(
MSDialect.colspecs,
{
2017-04-15 18:33:29 +02:00
sqltypes.Numeric: _MSNumeric_pymssql,
sqltypes.Float: sqltypes.Float,
2010-05-07 19:33:49 +02:00
}
)
2017-04-15 18:33:29 +02:00
2010-05-07 19:33:49 +02:00
@classmethod
def dbapi(cls):
module = __import__('pymssql')
2017-04-15 18:33:29 +02:00
# pymmsql < 2.1.1 doesn't have a Binary method. we use string
2010-05-07 19:33:49 +02:00
client_ver = tuple(int(x) for x in module.__version__.split("."))
2017-04-15 18:33:29 +02:00
if client_ver < (2, 1, 1):
# TODO: monkeypatching here is less than ideal
module.Binary = lambda x: x if hasattr(x, 'decode') else str(x)
2010-05-07 19:33:49 +02:00
if client_ver < (1, ):
util.warn("The pymssql dialect expects at least "
2017-04-15 18:33:29 +02:00
"the 1.0 series of the pymssql DBAPI.")
2010-05-07 19:33:49 +02:00
return module
def __init__(self, **params):
super(MSDialect_pymssql, self).__init__(**params)
self.use_scope_identity = True
def _get_server_version_info(self, connection):
vers = connection.scalar("select @@version")
2017-04-15 18:33:29 +02:00
m = re.match(
r"Microsoft .*? - (\d+).(\d+).(\d+).(\d+)", vers)
2010-05-07 19:33:49 +02:00
if m:
return tuple(int(x) for x in m.group(1, 2, 3, 4))
else:
return None
def create_connect_args(self, url):
opts = url.translate_connect_args(username='user')
opts.update(url.query)
2017-04-15 18:33:29 +02:00
port = opts.pop('port', None)
if port and 'host' in opts:
opts['host'] = "%s:%s" % (opts['host'], port)
2010-05-07 19:33:49 +02:00
return [[], opts]
2017-04-15 18:33:29 +02:00
def is_disconnect(self, e, connection, cursor):
2010-05-07 19:33:49 +02:00
for msg in (
2017-04-15 18:33:29 +02:00
"Adaptive Server connection timed out",
"Net-Lib error during Connection reset by peer",
"message 20003", # connection timeout
2010-05-07 19:33:49 +02:00
"Error 10054",
"Not connected to any MS SQL server",
2017-04-15 18:33:29 +02:00
"Connection is closed",
"message 20006", # Write to the server failed
"message 20017", # Unexpected EOF from the server
2010-05-07 19:33:49 +02:00
):
if msg in str(e):
return True
else:
return False
2017-04-15 18:33:29 +02:00
dialect = MSDialect_pymssql