is_disconnect() method now. simpler design which also puts control of the ultimate "execute" call back into the hands of the dialects.
del keys['port']
return [[], keys]
- def get_disconnect_checker(self):
- def disconnect_checker(e):
- return isinstance(e, self.dbapi.DatabaseError) and "Error 10054" in str(e)
- return disconnect_checker
+ def is_disconnect(self, e):
+ return isinstance(e, self.dbapi.DatabaseError) and "Error 10054" in str(e)
## This code is leftover from the initial implementation, for reference
connectors.append ("TrustedConnection=Yes")
return [[";".join (connectors)], {}]
- def get_disconnect_checker(self):
- def disconnect_checker(e):
- return isinstance(e, self.dbapi.Error) and '[08S01]' in e.args[1]
- return disconnect_checker
+ def is_disconnect(self, e):
+ return isinstance(e, self.dbapi.Error) and '[08S01]' in e.args[1]
class MSSQLDialect_adodbapi(MSSQLDialect):
connectors.append("Integrated Security=SSPI")
return [[";".join (connectors)], {}]
- def get_disconnect_checker(self):
- def disconnect_checker(e):
- return isinstance(e, self.dbapi.adodbapi.DatabaseError) and "'connection failure'" in str(e)
- return disconnect_checker
+ def is_disconnect(self, e):
+ return isinstance(e, self.dbapi.adodbapi.DatabaseError) and "'connection failure'" in str(e)
dialect_mapping = {
'pymssql': MSSQLDialect_pymssql,
except:
pass
- def get_disconnect_checker(self):
- def disconnect_checker(e):
- return isinstance(e, self.dbapi.OperationalError) and e.args[0] in (2006, 2014)
- return disconnect_checker
-
+ def is_disconnect(self, e):
+ return isinstance(e, self.dbapi.OperationalError) and e.args[0] in (2006, 2014)
def get_default_schema_name(self):
if not hasattr(self, '_default_schema_name'):
cursor = connection.execute('''SELECT relname FROM pg_class WHERE relkind = 'S' AND relnamespace IN ( SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%%' AND nspname != 'information_schema' AND relname = %(seqname)s);''', {'seqname': sequence_name})
return bool(not not cursor.rowcount)
- def get_disconnect_checker(self):
- def disconnect_checker(e):
- if isinstance(e, self.dbapi.OperationalError):
- return 'closed the connection' in str(e) or 'connection not open' in str(e)
- elif isinstance(e, self.dbapi.InterfaceError):
- return 'connection already closed' in str(e)
- elif isinstance(e, self.dbapi.ProgrammingError):
- # yes, it really says "losed", not "closed"
- return "losed the connection unexpectedly" in str(e)
- else:
- return False
- return disconnect_checker
+ def is_disconnect(self, e):
+ if isinstance(e, self.dbapi.OperationalError):
+ return 'closed the connection' in str(e) or 'connection not open' in str(e)
+ elif isinstance(e, self.dbapi.InterfaceError):
+ return 'connection already closed' in str(e)
+ elif isinstance(e, self.dbapi.ProgrammingError):
+ # yes, it really says "losed", not "closed"
+ return "losed the connection unexpectedly" in str(e)
+ else:
+ return False
def reflecttable(self, connection, table):
if self.version == 2:
return clauseelement.compile(dialect=self, parameters=parameters)
- def get_disconnect_checker(self):
- """Return a callable that determines if an SQLError is caused by a database disconnection."""
-
- return lambda x: False
+ def is_disconnect(self, e):
+ """Return True if the given DBAPI error indicates an invalid connection"""
+ raise NotImplementedError()
class ExecutionContext(object):
try:
context.dialect.do_execute(context.cursor, context.statement, context.parameters, context=context)
except Exception, e:
+ if self.dialect.is_disconnect(e):
+ self.__connection.invalidate(e=e)
self._autorollback()
if self.__close_with_result:
self.close()
try:
context.dialect.do_executemany(context.cursor, context.statement, context.parameters, context=context)
except Exception, e:
+ if self.dialect.is_disconnect(e):
+ self.__connection.invalidate(e=e)
self._autorollback()
if self.__close_with_result:
self.close()
def defaultrunner(self, connection):
return base.DefaultRunner(connection)
+ def is_disconnect(self, e):
+ return False
+
def _set_paramstyle(self, style):
self._paramstyle = style
self._figure_paramstyle(style)
if tk in kwargs:
pool_args[k] = kwargs.pop(tk)
pool_args['use_threadlocal'] = self.pool_threadlocal()
- pool = poolclass(creator, disconnect_checker=dialect.get_disconnect_checker(), **pool_args)
+ pool = poolclass(creator, **pool_args)
else:
if isinstance(pool, poollib._DBProxy):
pool = pool.get_pool(*cargs, **cparams)
"""
def __init__(self, creator, recycle=-1, echo=None, use_threadlocal=False, auto_close_cursors=True,
- disallow_open_cursors=False, disconnect_checker=None):
+ disallow_open_cursors=False):
self.logger = logging.instance_logger(self)
self._threadconns = weakref.WeakValueDictionary()
self._creator = creator
self.auto_close_cursors = auto_close_cursors
self.disallow_open_cursors = disallow_open_cursors
self.echo = echo
- if disconnect_checker:
- self.disconnect_checker = disconnect_checker
- else:
- self.disconnect_checker = lambda x: False
echo = logging.echo_property()
def unique_connection(self):
self.__parent._cursors[self] = True
self.cursor = cursor
- def execute(self, *args, **kwargs):
- try:
- self.cursor.execute(*args, **kwargs)
- except Exception, e:
- if self.__parent._pool.disconnect_checker(e):
- self.invalidate(e=e)
- raise
-
- def executemany(self, *args, **kwargs):
- try:
- self.cursor.executemany(*args, **kwargs)
- except Exception, e:
- if self.__parent._pool.disconnect_checker(e):
- self.invalidate(e=e)
- raise
-
def invalidate(self, e=None):
self.__parent.invalidate(e=e)