summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2011-02-09 15:06:32 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2011-02-09 15:06:32 -0500
commit6f16b8db6f08cefd68cdf251292316497eb849b3 (patch)
treedd86ad7eb16671bfec3ea091f2b0cfd5b6e18893 /lib/sqlalchemy
parentf473398f0170a00b0e760a7dba292087144c7e45 (diff)
downloadsqlalchemy-6f16b8db6f08cefd68cdf251292316497eb849b3.tar.gz
- add connection and cursor to is_disconnect(). We aren't using it yet,
but we'd like to. Most DBAPIs don't give us anything we can do with it. Some research was done on psycopg2 and it still seems like they give us no adequate method (tried connection.closed, cursor.closed, connection.status). mxodbc claims their .closed attribute will work (but I am skeptical). - remove beahvior in pool that auto-invalidated a connection when the cursor failed to create. That's not the pool's job. we need the conn for the error logic. Can't get any tests to fail, curious why that behavior was there, guess we'll find out (or not). - add support for psycopg2 version detection. even though we have no use for it yet... - adjust one of the reconnect tests to work with oracle's horrendously slow connect speed
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/connectors/mxodbc.py6
-rw-r--r--lib/sqlalchemy/connectors/pyodbc.py2
-rw-r--r--lib/sqlalchemy/connectors/zxJDBC.py2
-rw-r--r--lib/sqlalchemy/dialects/firebird/kinterbasdb.py2
-rw-r--r--lib/sqlalchemy/dialects/informix/informixdb.py2
-rw-r--r--lib/sqlalchemy/dialects/mssql/adodbapi.py2
-rw-r--r--lib/sqlalchemy/dialects/mssql/pymssql.py2
-rw-r--r--lib/sqlalchemy/dialects/mysql/base.py2
-rw-r--r--lib/sqlalchemy/dialects/mysql/mysqlconnector.py2
-rw-r--r--lib/sqlalchemy/dialects/mysql/oursql.py2
-rw-r--r--lib/sqlalchemy/dialects/oracle/cx_oracle.py2
-rw-r--r--lib/sqlalchemy/dialects/postgresql/pg8000.py2
-rw-r--r--lib/sqlalchemy/dialects/postgresql/psycopg2.py8
-rw-r--r--lib/sqlalchemy/dialects/postgresql/pypostgresql.py2
-rw-r--r--lib/sqlalchemy/dialects/sqlite/pysqlite.py2
-rw-r--r--lib/sqlalchemy/dialects/sybase/pysybase.py2
-rw-r--r--lib/sqlalchemy/engine/base.py4
-rw-r--r--lib/sqlalchemy/engine/default.py2
-rw-r--r--lib/sqlalchemy/pool.py6
19 files changed, 28 insertions, 26 deletions
diff --git a/lib/sqlalchemy/connectors/mxodbc.py b/lib/sqlalchemy/connectors/mxodbc.py
index f467234ca..5573dda40 100644
--- a/lib/sqlalchemy/connectors/mxodbc.py
+++ b/lib/sqlalchemy/connectors/mxodbc.py
@@ -106,9 +106,9 @@ class MxODBCConnector(Connector):
opts.pop('database', None)
return (args,), opts
- def is_disconnect(self, e):
- # eGenix recommends checking connection.closed here,
- # but how can we get a handle on the current connection?
+ def is_disconnect(self, e, connection, cursor):
+ # TODO: eGenix recommends checking connection.closed here
+ # Does that detect dropped connections ?
if isinstance(e, self.dbapi.ProgrammingError):
return "connection already closed" in str(e)
elif isinstance(e, self.dbapi.Error):
diff --git a/lib/sqlalchemy/connectors/pyodbc.py b/lib/sqlalchemy/connectors/pyodbc.py
index c66a8a8ae..3f6d6cb5f 100644
--- a/lib/sqlalchemy/connectors/pyodbc.py
+++ b/lib/sqlalchemy/connectors/pyodbc.py
@@ -81,7 +81,7 @@ class PyODBCConnector(Connector):
connectors.extend(['%s=%s' % (k,v) for k,v in keys.iteritems()])
return [[";".join (connectors)], connect_args]
- def is_disconnect(self, e):
+ def is_disconnect(self, e, connection, cursor):
if isinstance(e, self.dbapi.ProgrammingError):
return "The cursor's connection has been closed." in str(e) or \
'Attempt to use a closed connection.' in str(e)
diff --git a/lib/sqlalchemy/connectors/zxJDBC.py b/lib/sqlalchemy/connectors/zxJDBC.py
index a9ff5ec95..20bf9d9cf 100644
--- a/lib/sqlalchemy/connectors/zxJDBC.py
+++ b/lib/sqlalchemy/connectors/zxJDBC.py
@@ -46,7 +46,7 @@ class ZxJDBCConnector(Connector):
self.jdbc_driver_name],
opts]
- def is_disconnect(self, e):
+ def is_disconnect(self, e, connection, cursor):
if not isinstance(e, self.dbapi.ProgrammingError):
return False
e = str(e)
diff --git a/lib/sqlalchemy/dialects/firebird/kinterbasdb.py b/lib/sqlalchemy/dialects/firebird/kinterbasdb.py
index 216fec270..ebb7805ae 100644
--- a/lib/sqlalchemy/dialects/firebird/kinterbasdb.py
+++ b/lib/sqlalchemy/dialects/firebird/kinterbasdb.py
@@ -153,7 +153,7 @@ class FBDialect_kinterbasdb(FBDialect):
else:
return tuple([int(x) for x in m.group(1, 2, 3)] + ['interbase'])
- def is_disconnect(self, e):
+ def is_disconnect(self, e, connection, cursor):
if isinstance(e, (self.dbapi.OperationalError,
self.dbapi.ProgrammingError)):
msg = str(e)
diff --git a/lib/sqlalchemy/dialects/informix/informixdb.py b/lib/sqlalchemy/dialects/informix/informixdb.py
index c81983816..1b6833af7 100644
--- a/lib/sqlalchemy/dialects/informix/informixdb.py
+++ b/lib/sqlalchemy/dialects/informix/informixdb.py
@@ -62,7 +62,7 @@ class InformixDialect_informixdb(InformixDialect):
v = VERSION_RE.split(connection.connection.dbms_version)
return (int(v[1]), int(v[2]), v[3])
- def is_disconnect(self, e):
+ def is_disconnect(self, e, connection, cursor):
if isinstance(e, self.dbapi.OperationalError):
return 'closed the connection' in str(e) \
or 'connection not open' in str(e)
diff --git a/lib/sqlalchemy/dialects/mssql/adodbapi.py b/lib/sqlalchemy/dialects/mssql/adodbapi.py
index 355214d89..f2d945de2 100644
--- a/lib/sqlalchemy/dialects/mssql/adodbapi.py
+++ b/lib/sqlalchemy/dialects/mssql/adodbapi.py
@@ -62,7 +62,7 @@ class MSDialect_adodbapi(MSDialect):
connectors.append("Integrated Security=SSPI")
return [[";".join (connectors)], {}]
- def is_disconnect(self, e):
+ def is_disconnect(self, e, connection, cursor):
return isinstance(e, self.dbapi.adodbapi.DatabaseError) and \
"'connection failure'" in str(e)
diff --git a/lib/sqlalchemy/dialects/mssql/pymssql.py b/lib/sqlalchemy/dialects/mssql/pymssql.py
index 192e63366..8bc0ad95b 100644
--- a/lib/sqlalchemy/dialects/mssql/pymssql.py
+++ b/lib/sqlalchemy/dialects/mssql/pymssql.py
@@ -95,7 +95,7 @@ class MSDialect_pymssql(MSDialect):
opts['host'] = "%s:%s" % (opts['host'], port)
return [[], opts]
- def is_disconnect(self, e):
+ def is_disconnect(self, e, connection, cursor):
for msg in (
"Error 10054",
"Not connected to any MS SQL server",
diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py
index b495cc36e..882e13d2e 100644
--- a/lib/sqlalchemy/dialects/mysql/base.py
+++ b/lib/sqlalchemy/dialects/mysql/base.py
@@ -1711,7 +1711,7 @@ class MySQLDialect(default.DefaultDialect):
resultset = connection.execute("XA RECOVER")
return [row['data'][0:row['gtrid_length']] for row in resultset]
- def is_disconnect(self, e):
+ def is_disconnect(self, e, connection, cursor):
if isinstance(e, self.dbapi.OperationalError):
return self._extract_error_code(e) in \
(2006, 2013, 2014, 2045, 2055)
diff --git a/lib/sqlalchemy/dialects/mysql/mysqlconnector.py b/lib/sqlalchemy/dialects/mysql/mysqlconnector.py
index d3ec1f5cf..035ebe459 100644
--- a/lib/sqlalchemy/dialects/mysql/mysqlconnector.py
+++ b/lib/sqlalchemy/dialects/mysql/mysqlconnector.py
@@ -118,7 +118,7 @@ class MySQLDialect_mysqlconnector(MySQLDialect):
def _extract_error_code(self, exception):
return exception.errno
- def is_disconnect(self, e):
+ def is_disconnect(self, e, connection, cursor):
errnos = (2006, 2013, 2014, 2045, 2055, 2048)
exceptions = (self.dbapi.OperationalError,self.dbapi.InterfaceError)
if isinstance(e, exceptions):
diff --git a/lib/sqlalchemy/dialects/mysql/oursql.py b/lib/sqlalchemy/dialects/mysql/oursql.py
index d3ef839b1..8caa1eaec 100644
--- a/lib/sqlalchemy/dialects/mysql/oursql.py
+++ b/lib/sqlalchemy/dialects/mysql/oursql.py
@@ -195,7 +195,7 @@ class MySQLDialect_oursql(MySQLDialect):
execution_options(_oursql_plain_query=True),
table, charset, full_name)
- def is_disconnect(self, e):
+ def is_disconnect(self, e, connection, cursor):
if isinstance(e, self.dbapi.ProgrammingError):
return e.errno is None and 'cursor' not in e.args[1] and e.args[1].endswith('closed')
else:
diff --git a/lib/sqlalchemy/dialects/oracle/cx_oracle.py b/lib/sqlalchemy/dialects/oracle/cx_oracle.py
index bc1c87703..b00adcd63 100644
--- a/lib/sqlalchemy/dialects/oracle/cx_oracle.py
+++ b/lib/sqlalchemy/dialects/oracle/cx_oracle.py
@@ -680,7 +680,7 @@ class OracleDialect_cx_oracle(OracleDialect):
for x in connection.connection.version.split('.')
)
- def is_disconnect(self, e):
+ def is_disconnect(self, e, connection, cursor):
if isinstance(e, self.dbapi.InterfaceError):
return "not connected" in str(e)
else:
diff --git a/lib/sqlalchemy/dialects/postgresql/pg8000.py b/lib/sqlalchemy/dialects/postgresql/pg8000.py
index d3c2f1d50..c4f00eabe 100644
--- a/lib/sqlalchemy/dialects/postgresql/pg8000.py
+++ b/lib/sqlalchemy/dialects/postgresql/pg8000.py
@@ -108,7 +108,7 @@ class PGDialect_pg8000(PGDialect):
opts.update(url.query)
return ([], opts)
- def is_disconnect(self, e):
+ def is_disconnect(self, e, connection, cursor):
return "connection is closed" in str(e)
dialect = PGDialect_pg8000
diff --git a/lib/sqlalchemy/dialects/postgresql/psycopg2.py b/lib/sqlalchemy/dialects/postgresql/psycopg2.py
index 50ea9d437..10d6e0269 100644
--- a/lib/sqlalchemy/dialects/postgresql/psycopg2.py
+++ b/lib/sqlalchemy/dialects/postgresql/psycopg2.py
@@ -227,6 +227,7 @@ class PGDialect_psycopg2(PGDialect):
execution_ctx_cls = PGExecutionContext_psycopg2
statement_compiler = PGCompiler_psycopg2
preparer = PGIdentifierPreparer_psycopg2
+ psycopg2_version = (0, 0)
colspecs = util.update_copy(
PGDialect.colspecs,
@@ -243,6 +244,11 @@ class PGDialect_psycopg2(PGDialect):
self.server_side_cursors = server_side_cursors
self.use_native_unicode = use_native_unicode
self.supports_unicode_binds = use_native_unicode
+ if self.dbapi and hasattr(self.dbapi, '__version__'):
+ m = re.match(r'(\d+)\.(\d+)\.(\d+)?',
+ self.dbapi.__version__)
+ if m:
+ self.psycopg2_version = tuple(map(int, m.group(1, 2, 3)))
@classmethod
def dbapi(cls):
@@ -295,7 +301,7 @@ class PGDialect_psycopg2(PGDialect):
opts.update(url.query)
return ([], opts)
- def is_disconnect(self, e):
+ def is_disconnect(self, e, connection, cursor):
if isinstance(e, self.dbapi.OperationalError):
# these error messages from libpq: interfaces/libpq/fe-misc.c.
# TODO: these are sent through gettext in libpq and we can't
diff --git a/lib/sqlalchemy/dialects/postgresql/pypostgresql.py b/lib/sqlalchemy/dialects/postgresql/pypostgresql.py
index dd22fcb33..a137a6240 100644
--- a/lib/sqlalchemy/dialects/postgresql/pypostgresql.py
+++ b/lib/sqlalchemy/dialects/postgresql/pypostgresql.py
@@ -67,7 +67,7 @@ class PGDialect_pypostgresql(PGDialect):
opts.update(url.query)
return ([], opts)
- def is_disconnect(self, e):
+ def is_disconnect(self, e, connection, cursor):
return "connection is closed" in str(e)
dialect = PGDialect_pypostgresql
diff --git a/lib/sqlalchemy/dialects/sqlite/pysqlite.py b/lib/sqlalchemy/dialects/sqlite/pysqlite.py
index 14cfa93d9..646c5b86f 100644
--- a/lib/sqlalchemy/dialects/sqlite/pysqlite.py
+++ b/lib/sqlalchemy/dialects/sqlite/pysqlite.py
@@ -238,7 +238,7 @@ class SQLiteDialect_pysqlite(SQLiteDialect):
return ([filename], opts)
- def is_disconnect(self, e):
+ def is_disconnect(self, e, connection, cursor):
return isinstance(e, self.dbapi.ProgrammingError) and "Cannot operate on a closed database." in str(e)
dialect = SQLiteDialect_pysqlite
diff --git a/lib/sqlalchemy/dialects/sybase/pysybase.py b/lib/sqlalchemy/dialects/sybase/pysybase.py
index fed792817..e12cf07dd 100644
--- a/lib/sqlalchemy/dialects/sybase/pysybase.py
+++ b/lib/sqlalchemy/dialects/sybase/pysybase.py
@@ -87,7 +87,7 @@ class SybaseDialect_pysybase(SybaseDialect):
# (12, 5, 0, 0)
return (vers / 1000, vers % 1000 / 100, vers % 100 / 10, vers % 10)
- def is_disconnect(self, e):
+ def is_disconnect(self, e, connection, cursor):
if isinstance(e, (self.dbapi.OperationalError,
self.dbapi.ProgrammingError)):
msg = str(e)
diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py
index b78a30537..f6c974136 100644
--- a/lib/sqlalchemy/engine/base.py
+++ b/lib/sqlalchemy/engine/base.py
@@ -502,7 +502,7 @@ class Dialect(object):
raise NotImplementedError()
- def is_disconnect(self, e):
+ def is_disconnect(self, e, connection, cursor):
"""Return True if the given DB-API error indicates an invalid
connection"""
@@ -1518,7 +1518,7 @@ class Connection(Connectable):
if context:
context.handle_dbapi_exception(e)
- is_disconnect = self.dialect.is_disconnect(e)
+ is_disconnect = self.dialect.is_disconnect(e, self.__connection, cursor)
if is_disconnect:
self.invalidate(e)
self.engine.dispose()
diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py
index aa75a2853..e669b305e 100644
--- a/lib/sqlalchemy/engine/default.py
+++ b/lib/sqlalchemy/engine/default.py
@@ -324,7 +324,7 @@ class DefaultDialect(base.Dialect):
def do_execute(self, cursor, statement, parameters, context=None):
cursor.execute(statement, parameters)
- def is_disconnect(self, e):
+ def is_disconnect(self, e, connection, cursor):
return False
def reset_isolation_level(self, dbapi_conn):
diff --git a/lib/sqlalchemy/pool.py b/lib/sqlalchemy/pool.py
index 5150d282c..7201bccf3 100644
--- a/lib/sqlalchemy/pool.py
+++ b/lib/sqlalchemy/pool.py
@@ -425,11 +425,7 @@ class _ConnectionFairy(object):
self._close()
def cursor(self, *args, **kwargs):
- try:
- return self.connection.cursor(*args, **kwargs)
- except Exception, e:
- self.invalidate(e=e)
- raise
+ return self.connection.cursor(*args, **kwargs)
def __getattr__(self, key):
return getattr(self.connection, key)