within the "name" field of logging messages instead of the default
hex identifier string. [ticket:1555]
+ - The visit_pool() method of Dialect is removed, and replaced with
+ on_connect(). This method returns a callable which receives
+ the raw DBAPI connection after each one is created. The callable
+ is assembled into a first_connect/connect pool listener by the
+ connection strategy if non-None. Provides a simpler interface
+ for dialects.
- metadata
- Added the ability to strip schema information when using
raise ImportError, "Unrecognized platform for mxODBC import"
return module
- def visit_pool(self, pool):
- def connect(conn, rec):
+ def on_connect(self):
+ def connect(conn):
conn.stringformat = self.dbapi.MIXED_STRINGFORMAT
conn.datetimeformat = self.dbapi.PYDATETIME_DATETIMEFORMAT
#conn.bindmethod = self.dbapi.BIND_USING_PYTHONTYPE
#conn.bindmethod = self.dbapi.BIND_USING_SQLTYPE
-
- pool.add_listener({'connect':connect})
+ return connect
def create_connect_args(self, url):
""" Return a tuple of *args,**kwargs for creating a connection.
if not self.supports_native_enum:
self.colspecs = self.colspecs.copy()
del self.colspecs[ENUM]
-
- def visit_pool(self, pool):
- if self.isolation_level is not None:
- class SetIsolationLevel(object):
- def __init__(self, isolation_level):
- self.isolation_level = isolation_level
-
- def connect(self, conn, rec):
- cursor = conn.cursor()
- cursor.execute("SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL %s"
- % self.isolation_level)
- cursor.execute("COMMIT")
- cursor.close()
- pool.add_listener(SetIsolationLevel(self.isolation_level))
+ def on_connect(self):
+ if self.isolation_level is not None:
+ def connect(conn):
+ cursor = conn.cursor()
+ cursor.execute("SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL %s"
+ % self.isolation_level)
+ cursor.execute("COMMIT")
+ cursor.close()
+ return connect
+ else:
+ return None
+
def do_begin_twophase(self, connection, xid):
self.do_begin(connection.connection)
psycopg = __import__('psycopg2')
return psycopg
- _unwrap_connection = None
-
- def visit_pool(self, pool):
+ def on_connect(self):
+ base_on_connect = super(PGDialect_psycopg2, self).on_connect()
if self.dbapi and self.use_native_unicode:
extensions = __import__('psycopg2.extensions').extensions
- def connect(conn, rec):
- if self._unwrap_connection:
- conn = self._unwrap_connection(conn)
- if conn is None:
- return
+ def connect(conn):
extensions.register_type(extensions.UNICODE, conn)
- pool.add_listener({'first_connect': connect, 'connect':connect})
- super(PGDialect_psycopg2, self).visit_pool(pool)
-
+ if base_on_connect:
+ base_on_connect(conn)
+ return connect
+ else:
+ return base_on_connect
+
def create_connect_args(self, url):
opts = url.translate_connect_args(username='user')
if 'port' in opts:
# hypothetical driver ?)
self.native_datetime = native_datetime
- def visit_pool(self, pool):
+ def on_connect(self):
if self.isolation_level is not None:
- class SetIsolationLevel(object):
- def __init__(self, isolation_level):
- if isolation_level == 'READ UNCOMMITTED':
- self.isolation_level = 1
- else:
- self.isolation_level = 0
-
- def connect(self, conn, rec):
- cursor = conn.cursor()
- cursor.execute("PRAGMA read_uncommitted = %d" % self.isolation_level)
- cursor.close()
- pool.add_listener(SetIsolationLevel(self.isolation_level))
-
+ if self.isolation_level == 'READ UNCOMMITTED':
+ isolation_level = 1
+ else:
+ isolation_level = 0
+
+ def connect(conn):
+ cursor = conn.cursor()
+ cursor.execute("PRAGMA read_uncommitted = %d" % isolation_level)
+ cursor.close()
+ return connect
+ else:
+ return None
+
def table_names(self, connection, schema):
if schema is not None:
qschema = self.identifier_preparer.quote_identifier(schema)
Given a :class:`~sqlalchemy.engine.url.URL` object, returns a tuple
consisting of a `*args`/`**kwargs` suitable to send directly
to the dbapi's connect function.
+
"""
raise NotImplementedError()
The returned result is cached *per dialect class* so can
contain no dialect-instance state.
+
"""
raise NotImplementedError()
Allows dialects to configure options based on server version info or
other properties.
+
+ The connection passed here is a SQLAlchemy Connection object,
+ with full capabilities.
+
+ The initalize() method of the base dialect should be called via
+ super().
+
"""
pass
properties from the database. If include_columns (a list or
set) is specified, limit the autoload to the given column
names.
+
+ The default implementation uses the
+ :class:`~sqlalchemy.engine.reflection.Inspector` interface to
+ provide the output, building upon the granular table/column/
+ constraint etc. methods of :class:`Dialect`.
+
"""
raise NotImplementedError()
raise NotImplementedError()
- def visit_pool(self, pool):
- """Executed after a pool is created."""
+ def on_connect(self):
+ """return a callable which sets up a newly created DBAPI connection.
+
+ The callable accepts a single argument "conn" which is the
+ DBAPI connection itself. It has no return value.
+
+ This is used to set dialect-wide per-connection options such as isolation
+ modes, unicode modes, etc.
+
+ If a callable is returned, it will be assembled into a pool listener
+ that receives the direct DBAPI connection, with all wrappers removed.
+
+ If None is returned, no listener will be generated.
+
+ """
+ return None
class ExecutionContext(object):
self.do_rollback(connection.connection)
+ def on_connect(self):
+ """return a callable which sets up a newly created DBAPI connection.
+
+ This is used to set dialect-wide per-connection options such as isolation
+ modes, unicode modes, etc.
+
+ If a callable is returned, it will be assembled into a pool listener
+ that receives the direct DBAPI connection, with all wrappers removed.
+
+ If None is returned, no listener will be generated.
+
+ """
+ return None
+
def _check_unicode_returns(self, connection):
# Py2K
if self.supports_unicode_statements:
engine = engineclass(pool, dialect, u, **engine_args)
if _initialize:
- dialect.visit_pool(pool)
-
+ do_on_connect = dialect.on_connect()
+ if do_on_connect:
+ def on_connect(conn, rec):
+ conn = getattr(conn, '_sqla_unwrap', conn)
+ if conn is None:
+ return
+ do_on_connect(conn)
+
+ pool.add_listener({'first_connect': on_connect, 'connect':on_connect})
+
def first_connect(conn, rec):
c = base.Connection(engine, connection=conn)
dialect.initialize(c)
else:
buffer.append(result)
return result
-
+
+ @property
+ def _sqla_unwrap(self):
+ return self._subject
+
def __getattribute__(self, key):
try:
return object.__getattribute__(self, key)
return self
else:
return result
-
+
+ @property
+ def _sqla_unwrap(self):
+ return None
+
def __getattribute__(self, key):
try:
return object.__getattribute__(self, key)
else:
return result
-def unwrap_connection(conn):
- if conn.__class__.__name__ == 'Recorder':
- return conn._subject
- elif conn.__class__.__name__ == 'Player':
- return None
- else:
- return conn
recorder = lambda: dbapi_session.recorder(creator())
engine = engines.testing_engine(options={'creator':recorder})
- engine.dialect._unwrap_connection = engines.unwrap_connection
metadata = MetaData(engine)
engine.connect()
player = lambda: dbapi_session.player()
engine = create_engine('postgresql:///', creator=player)
- engine.dialect._unwrap_connection = engines.unwrap_connection
metadata = MetaData(engine)
engine.connect()
creator = testing.db.pool._creator
recorder = lambda: dbapi_session.recorder(creator())
engine = engines.testing_engine(options={'creator':recorder})
- engine.dialect._unwrap_connection = engines.unwrap_connection
metadata = MetaData(engine)
session = sessionmaker()()
engine.connect()
player = lambda: dbapi_session.player()
engine = create_engine('postgresql:///', creator=player)
- engine.dialect._unwrap_connection = engines.unwrap_connection
metadata = MetaData(engine)
session = sessionmaker()()
engine.connect()