summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-08-23 15:40:09 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2012-08-23 15:40:09 -0400
commit28bfc3d5dfdaae57a94f660959aaaeb83a5e2132 (patch)
tree43d42adce27ce2d606e8f1fae4849b722f0d8bd3
parent16d66d35644eaa6609fdc5c8f805314f7cf4d0fc (diff)
downloadsqlalchemy-28bfc3d5dfdaae57a94f660959aaaeb83a5e2132.tar.gz
- [feature] The before_cursor_execute event
fires off for so-called "_cursor_execute" events, which are usually special-case executions of primary-key bound sequences and default-generation SQL phrases that invoke separately when RETURNING is not used with INSERT. [ticket:2459]
-rw-r--r--CHANGES8
-rw-r--r--lib/sqlalchemy/engine/base.py72
-rw-r--r--lib/sqlalchemy/engine/default.py2
-rw-r--r--lib/sqlalchemy/event.py171
-rw-r--r--lib/sqlalchemy/events.py229
-rw-r--r--test/base/test_events.py226
-rw-r--r--test/engine/test_execute.py30
-rw-r--r--test/lib/profiles.txt200
-rw-r--r--test/sql/test_cte.py1
9 files changed, 699 insertions, 240 deletions
diff --git a/CHANGES b/CHANGES
index 59a0a839f..77d29ab2b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -303,6 +303,14 @@ underneath "0.7.xx".
Connection objects, not just Engine
objects. [ticket:2511]
+ - [feature] The before_cursor_execute event
+ fires off for so-called "_cursor_execute"
+ events, which are usually special-case
+ executions of primary-key bound sequences
+ and default-generation SQL
+ phrases that invoke separately when RETURNING
+ is not used with INSERT. [ticket:2459]
+
- [bug] Fixed bug whereby if a database restart
affected multiple connections, each
connection would individually invoke a new
diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py
index 83ed551af..bf3131994 100644
--- a/lib/sqlalchemy/engine/base.py
+++ b/lib/sqlalchemy/engine/base.py
@@ -63,7 +63,10 @@ class Connection(Connectable):
self.__invalid = False
if _dispatch:
self.dispatch = _dispatch
+ elif engine._has_events:
+ self.dispatch = self.dispatch._join(engine.dispatch)
self._has_events = _has_events or engine._has_events
+
self._echo = self.engine._should_log_info()
if _execution_options:
self._execution_options =\
@@ -429,7 +432,6 @@ class Connection(Connectable):
if self._has_events:
self.dispatch.begin(self)
- self.engine.dispatch.begin(self)
try:
self.engine.dialect.do_begin(self.connection)
@@ -440,7 +442,6 @@ class Connection(Connectable):
def _rollback_impl(self):
if self._has_events:
self.dispatch.rollback(self)
- self.engine.dispatch.rollback(self)
if self._still_open_and_connection_is_valid:
if self._echo:
@@ -457,7 +458,6 @@ class Connection(Connectable):
def _commit_impl(self):
if self._has_events:
self.dispatch.commit(self)
- self.engine.dispatch.commit(self)
if self._echo:
self.engine.logger.info("COMMIT")
@@ -471,7 +471,6 @@ class Connection(Connectable):
def _savepoint_impl(self, name=None):
if self._has_events:
self.dispatch.savepoint(self, name)
- self.engine.dispatch.savepoint(self, name)
if name is None:
self.__savepoint_seq += 1
@@ -483,7 +482,6 @@ class Connection(Connectable):
def _rollback_to_savepoint_impl(self, name, context):
if self._has_events:
self.dispatch.rollback_savepoint(self, name, context)
- self.engine.dispatch.rollback_savepoint(self, name, context)
if self._still_open_and_connection_is_valid:
self.engine.dialect.do_rollback_to_savepoint(self, name)
@@ -492,7 +490,6 @@ class Connection(Connectable):
def _release_savepoint_impl(self, name, context):
if self._has_events:
self.dispatch.release_savepoint(self, name, context)
- self.engine.dispatch.release_savepoint(self, name, context)
if self._still_open_and_connection_is_valid:
self.engine.dialect.do_release_savepoint(self, name)
@@ -501,7 +498,6 @@ class Connection(Connectable):
def _begin_twophase_impl(self, xid):
if self._has_events:
self.dispatch.begin_twophase(self, xid)
- self.engine.dispatch.begin_twophase(self, xid)
if self._still_open_and_connection_is_valid:
self.engine.dialect.do_begin_twophase(self, xid)
@@ -509,7 +505,6 @@ class Connection(Connectable):
def _prepare_twophase_impl(self, xid):
if self._has_events:
self.dispatch.prepare_twophase(self, xid)
- self.engine.dispatch.prepare_twophase(self, xid)
if self._still_open_and_connection_is_valid:
assert isinstance(self.__transaction, TwoPhaseTransaction)
@@ -518,7 +513,6 @@ class Connection(Connectable):
def _rollback_twophase_impl(self, xid, is_prepared):
if self._has_events:
self.dispatch.rollback_twophase(self, xid, is_prepared)
- self.engine.dispatch.rollback_twophase(self, xid, is_prepared)
if self._still_open_and_connection_is_valid:
assert isinstance(self.__transaction, TwoPhaseTransaction)
@@ -528,7 +522,6 @@ class Connection(Connectable):
def _commit_twophase_impl(self, xid, is_prepared):
if self._has_events:
self.dispatch.commit_twophase(self, xid, is_prepared)
- self.engine.dispatch.commit_twophase(self, xid, is_prepared)
if self._still_open_and_connection_is_valid:
assert isinstance(self.__transaction, TwoPhaseTransaction)
@@ -658,10 +651,7 @@ class Connection(Connectable):
"""Execute a schema.ColumnDefault object."""
if self._has_events:
- for fn in chain(
- self.dispatch.before_execute,
- self.engine.dispatch.before_execute
- ):
+ for fn in self.dispatch.before_execute:
default, multiparams, params = \
fn(self, default, multiparams, params)
@@ -685,8 +675,6 @@ class Connection(Connectable):
if self._has_events:
self.dispatch.after_execute(self,
default, multiparams, params, ret)
- self.engine.dispatch.after_execute(self,
- default, multiparams, params, ret)
return ret
@@ -694,10 +682,7 @@ class Connection(Connectable):
"""Execute a schema.DDL object."""
if self._has_events:
- for fn in chain(
- self.dispatch.before_execute,
- self.engine.dispatch.before_execute
- ):
+ for fn in self.dispatch.before_execute:
ddl, multiparams, params = \
fn(self, ddl, multiparams, params)
@@ -712,7 +697,7 @@ class Connection(Connectable):
compiled
)
if self._has_events:
- self.engine.dispatch.after_execute(self,
+ self.dispatch.after_execute(self,
ddl, multiparams, params, ret)
return ret
@@ -720,10 +705,7 @@ class Connection(Connectable):
"""Execute a sql.ClauseElement object."""
if self._has_events:
- for fn in chain(
- self.dispatch.before_execute,
- self.engine.dispatch.before_execute
- ):
+ for fn in self.dispatch.before_execute:
elem, multiparams, params = \
fn(self, elem, multiparams, params)
@@ -759,18 +741,13 @@ class Connection(Connectable):
if self._has_events:
self.dispatch.after_execute(self,
elem, multiparams, params, ret)
- self.engine.dispatch.after_execute(self,
- elem, multiparams, params, ret)
return ret
def _execute_compiled(self, compiled, multiparams, params):
"""Execute a sql.Compiled object."""
if self._has_events:
- for fn in chain(
- self.dispatch.before_execute,
- self.engine.dispatch.before_execute
- ):
+ for fn in self.dispatch.before_execute:
compiled, multiparams, params = \
fn(self, compiled, multiparams, params)
@@ -786,18 +763,13 @@ class Connection(Connectable):
if self._has_events:
self.dispatch.after_execute(self,
compiled, multiparams, params, ret)
- self.engine.dispatch.after_execute(self,
- compiled, multiparams, params, ret)
return ret
def _execute_text(self, statement, multiparams, params):
"""Execute a string SQL statement."""
if self._has_events:
- for fn in chain(
- self.dispatch.before_execute,
- self.engine.dispatch.before_execute
- ):
+ for fn in self.dispatch.before_execute:
statement, multiparams, params = \
fn(self, statement, multiparams, params)
@@ -813,8 +785,6 @@ class Connection(Connectable):
if self._has_events:
self.dispatch.after_execute(self,
statement, multiparams, params, ret)
- self.engine.dispatch.after_execute(self,
- statement, multiparams, params, ret)
return ret
def _execute_context(self, dialect, constructor,
@@ -847,10 +817,7 @@ class Connection(Connectable):
parameters = parameters[0]
if self._has_events:
- for fn in chain(
- self.dispatch.before_cursor_execute,
- self.engine.dispatch.before_cursor_execute
- ):
+ for fn in self.dispatch.before_cursor_execute:
statement, parameters = \
fn(self, cursor, statement, parameters,
context, context.executemany)
@@ -893,11 +860,6 @@ class Connection(Connectable):
parameters,
context,
context.executemany)
- self.engine.dispatch.after_cursor_execute(self, cursor,
- statement,
- parameters,
- context,
- context.executemany)
if context.compiled:
context.post_exec()
@@ -929,7 +891,7 @@ class Connection(Connectable):
return result
- def _cursor_execute(self, cursor, statement, parameters):
+ def _cursor_execute(self, cursor, statement, parameters, context=None):
"""Execute a statement + params on the given cursor.
Adds appropriate logging and exception handling.
@@ -940,6 +902,12 @@ class Connection(Connectable):
terminates at _execute_context().
"""
+ if self._has_events:
+ for fn in self.dispatch.before_cursor_execute:
+ statement, parameters = \
+ fn(self, cursor, statement, parameters,
+ context, context.executemany)
+
if self._echo:
self.engine.logger.info(statement)
self.engine.logger.info("%r", parameters)
@@ -1006,12 +974,6 @@ class Connection(Connectable):
parameters,
context,
e)
- self.engine.dispatch.dbapi_error(self,
- cursor,
- statement,
- parameters,
- context,
- e)
context.handle_dbapi_exception(e)
is_disconnect = isinstance(e, self.dialect.dbapi.Error) and \
diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py
index 8518cf0da..1c74dab43 100644
--- a/lib/sqlalchemy/engine/default.py
+++ b/lib/sqlalchemy/engine/default.py
@@ -597,7 +597,7 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
else:
default_params = {}
- conn._cursor_execute(self.cursor, stmt, default_params)
+ conn._cursor_execute(self.cursor, stmt, default_params, context=self)
r = self.cursor.fetchone()[0]
if type_ is not None:
# apply type post processors to the result
diff --git a/lib/sqlalchemy/event.py b/lib/sqlalchemy/event.py
index 8e9064cfc..ee4c0ad32 100644
--- a/lib/sqlalchemy/event.py
+++ b/lib/sqlalchemy/event.py
@@ -7,6 +7,7 @@
"""Base event API."""
from . import util, exc
+from itertools import chain
CANCEL = util.symbol('CANCEL')
NO_RETVAL = util.symbol('NO_RETVAL')
@@ -37,7 +38,7 @@ def listen(target, identifier, fn, *args, **kw):
tgt.dispatch._listen(tgt, identifier, fn, *args, **kw)
return
raise exc.InvalidRequestError("No such event '%s' for target '%s'" %
- (identifier,target))
+ (identifier, target))
def listens_for(target, identifier, *args, **kw):
"""Decorate a function as a listener for the given target + identifier.
@@ -69,7 +70,7 @@ def remove(target, identifier, fn):
"""
for evt_cls in _registrars[identifier]:
for tgt in evt_cls._accept_with(target):
- tgt.dispatch._remove(identifier, tgt, fn, *args, **kw)
+ tgt.dispatch._remove(identifier, tgt, fn)
return
_registrars = util.defaultdict(list)
@@ -112,6 +113,30 @@ class _Dispatch(object):
def __init__(self, _parent_cls):
self._parent_cls = _parent_cls
+ def _join(self, other):
+ """Create a 'join' of this :class:`._Dispatch` and another.
+
+ This new dispatcher will dispatch events to both
+ :class:`._Dispatch` objects.
+
+ Once constructed, the joined dispatch will respond to new events
+ added to this dispatcher, but may not be aware of events
+ added to the other dispatcher after creation of the join. This is
+ currently for performance reasons so that both dispatchers need
+ not be "evaluated" fully on each call.
+
+ """
+ if '_joined_dispatch_cls' not in self.__class__.__dict__:
+ cls = type(
+ "Joined%s" % self.__class__.__name__,
+ (_JoinedDispatcher, self.__class__), {}
+ )
+ for ls in _event_descriptors(self):
+ setattr(cls, ls.name, _JoinedDispatchDescriptor(ls.name))
+
+ self.__class__._joined_dispatch_cls = cls
+ return self._joined_dispatch_cls(self, other)
+
def __reduce__(self):
return _UnpickleDispatch(), (self._parent_cls, )
@@ -276,6 +301,7 @@ class _DispatchDescriptor(object):
obj.__dict__[self.__name__] = ret
return ret
+
class _EmptyListener(object):
"""Serves as a class-level interface to the events
served by a _DispatchDescriptor, when there are no
@@ -303,8 +329,9 @@ class _EmptyListener(object):
and returns it.
"""
- obj.__dict__[self.name] = result = _ListenerCollection(
- self.parent, obj._parent_cls)
+ result = _ListenerCollection(self.parent, obj._parent_cls)
+ if obj.__dict__[self.name] is self:
+ obj.__dict__[self.name] = result
return result
def _needs_modify(self, *args, **kw):
@@ -324,14 +351,47 @@ class _EmptyListener(object):
def __iter__(self):
return iter(self.parent_listeners)
- def __getitem__(self, index):
- return (self.parent_listeners)[index]
+ def __nonzero__(self):
+ return False
+
+class _CompoundListener(object):
+ _exec_once = False
+
+ def exec_once(self, *args, **kw):
+ """Execute this event, but only if it has not been
+ executed already for this collection."""
+
+ if not self._exec_once:
+ self(*args, **kw)
+ self._exec_once = True
+
+ # I'm not entirely thrilled about the overhead here,
+ # but this allows class-level listeners to be added
+ # at any point.
+ #
+ # In the absense of instance-level listeners,
+ # we stay with the _EmptyListener object when called
+ # at the instance level.
+
+ def __call__(self, *args, **kw):
+ """Execute this event."""
+
+ for fn in self.parent_listeners:
+ fn(*args, **kw)
+ for fn in self.listeners:
+ fn(*args, **kw)
+
+ def __len__(self):
+ return len(self.parent_listeners) + len(self.listeners)
+
+ def __iter__(self):
+ return chain(self.parent_listeners, self.listeners)
def __nonzero__(self):
- return bool(self.listeners)
+ return bool(self.listeners or self.parent_listeners)
-class _ListenerCollection(object):
+class _ListenerCollection(_CompoundListener):
"""Instance-level attributes on instances of :class:`._Dispatch`.
Represents a collection of listeners.
@@ -341,8 +401,6 @@ class _ListenerCollection(object):
"""
- _exec_once = False
-
def __init__(self, parent, target_cls):
if target_cls not in parent._clslevel:
parent.update_subclass(target_cls)
@@ -360,42 +418,6 @@ class _ListenerCollection(object):
"""
return self
- def exec_once(self, *args, **kw):
- """Execute this event, but only if it has not been
- executed already for this collection."""
-
- if not self._exec_once:
- self(*args, **kw)
- self._exec_once = True
-
- def __call__(self, *args, **kw):
- """Execute this event."""
-
- for fn in self.parent_listeners:
- fn(*args, **kw)
- for fn in self.listeners:
- fn(*args, **kw)
-
- # I'm not entirely thrilled about the overhead here,
- # but this allows class-level listeners to be added
- # at any point.
- #
- # In the absense of instance-level listeners,
- # we stay with the _EmptyListener object when called
- # at the instance level.
-
- def __len__(self):
- return len(self.parent_listeners + self.listeners)
-
- def __iter__(self):
- return iter(self.parent_listeners + self.listeners)
-
- def __getitem__(self, index):
- return (self.parent_listeners + self.listeners)[index]
-
- def __nonzero__(self):
- return bool(self.listeners or self.parent_listeners)
-
def _update(self, other, only_propagate=True):
"""Populate from the listeners in another :class:`_Dispatch`
object."""
@@ -430,6 +452,62 @@ class _ListenerCollection(object):
self.listeners[:] = []
self.propagate.clear()
+
+class _JoinedDispatcher(object):
+ """Represent a connection between two _Dispatch objects."""
+
+ def __init__(self, local, parent):
+ self.local = local
+ self.parent = parent
+ self._parent_cls = local._parent_cls
+
+
+class _JoinedDispatchDescriptor(object):
+ def __init__(self, name):
+ self.name = name
+
+ def __get__(self, obj, cls):
+ if obj is None:
+ return self
+ else:
+ obj.__dict__[self.name] = ret = _JoinedListener(
+ obj.parent, self.name,
+ getattr(obj.local, self.name)
+ )
+ return ret
+
+class _JoinedListener(_CompoundListener):
+ _exec_once = False
+ def __init__(self, parent, name, local):
+ self.parent = parent
+ self.name = name
+ self.local = local
+ self.parent_listeners = self.local
+
+ # fix .listeners for the parent. This means
+ # new events added to the parent won't be picked
+ # up here. Alternatively, the listeners can
+ # be via @property to just return getattr(self.parent, self.name)
+ # each time. less performant.
+ self.listeners = list(getattr(self.parent, self.name))
+
+ def for_modify(self, obj):
+ self.local = self.parent_listeners = self.local.for_modify(obj)
+ return self
+
+ def insert(self, obj, target, propagate):
+ self.local.insert(obj, target, propagate)
+
+ def append(self, obj, target, propagate):
+ self.local.append(obj, target, propagate)
+
+ def remove(self, obj, target):
+ self.local.remove(obj, target)
+
+ def clear(self):
+ raise NotImplementedError()
+
+
class dispatcher(object):
"""Descriptor used by target classes to
deliver the _Dispatch class at the class level
@@ -446,3 +524,4 @@ class dispatcher(object):
return self.dispatch_cls
obj.__dict__['dispatch'] = disp = self.dispatch_cls(cls)
return disp
+
diff --git a/lib/sqlalchemy/events.py b/lib/sqlalchemy/events.py
index 10717ee50..61392ea62 100644
--- a/lib/sqlalchemy/events.py
+++ b/lib/sqlalchemy/events.py
@@ -341,18 +341,56 @@ class ConnectionEvents(event.Events):
The methods here define the name of an event as well as the names of
members that are passed to listener functions.
- An event listener can be associated with any :class:`.Connectable`,
- such as an :class:`.Engine`, e.g.::
+ An event listener can be associated with any :class:`.Connectable`
+ class or instance, such as an :class:`.Engine`, e.g.::
from sqlalchemy import event, create_engine
- def before_execute(conn, clauseelement, multiparams, params):
- log.info("Received statement: %s" % clauseelement)
+ def before_cursor_execute(conn, cursor, statement, parameters, context,
+ executemany):
+ log.info("Received statement: %s" % statement)
engine = create_engine('postgresql://scott:tiger@localhost/test')
- event.listen(engine, "before_execute", before_execute)
+ event.listen(engine, "before_cursor_execute", before_cursor_execute)
- Some events allow modifiers to the :func:`.event.listen` function.
+ or with a specific :class:`.Connection`::
+
+ with engine.begin() as conn:
+ @event.listens_for(conn, 'before_cursor_execute')
+ def before_cursor_execute(conn, cursor, statement, parameters,
+ context, executemany):
+ log.info("Received statement: %s" % statement)
+
+ The :meth:`.before_execute` and :meth:`.before_cursor_execute`
+ events can also be established with the ``retval=True`` flag, which
+ allows modification of the statement and parameters to be sent
+ to the database. The :meth:`.before_cursor_execute` event is
+ particularly useful here to add ad-hoc string transformations, such
+ as comments, to all executions::
+
+ from sqlalchemy.engine import Engine
+ from sqlalchemy import event
+
+ @event.listens_for(Engine, "before_cursor_execute", retval=True)
+ def comment_sql_calls(conn, cursor, statement, parameters,
+ context, executemany):
+ statement = statement + " -- some comment"
+ return statement, parameters
+
+ .. note:: :class:`.ConnectionEvents` can be established on any
+ combination of :class:`.Engine`, :class:`.Connection`, as well
+ as instances of each of those classes. Events across all
+ four scopes will fire off for a given instance of
+ :class:`.Connection`. However, for performance reasons, the
+ :class:`.Connection` object determines at instantiation time
+ whether or not its parent :class:`.Engine` has event listeners
+ established. Event listeners added to the :class:`.Engine`
+ class or to an instance of :class:`.Engine` *after* the instantiation
+ of a dependent :class:`.Connection` instance will usually
+ *not* be available on that :class:`.Connection` instance. The newly
+ added listeners will instead take effect for :class:`.Connection`
+ instances created subsequent to those event listeners being
+ established on the parent :class:`.Engine` class or instance.
:param retval=False: Applies to the :meth:`.before_execute` and
:meth:`.before_cursor_execute` events only. When True, the
@@ -400,18 +438,107 @@ class ConnectionEvents(event.Events):
event.Events._listen(target, identifier, fn)
def before_execute(self, conn, clauseelement, multiparams, params):
- """Intercept high level execute() events."""
+ """Intercept high level execute() events, receiving uncompiled
+ SQL constructs and other objects prior to rendering into SQL.
+
+ This event is good for debugging SQL compilation issues as well
+ as early manipulation of the parameters being sent to the database,
+ as the parameter lists will be in a consistent format here.
+
+ This event can be optionally established with the ``retval=True``
+ flag. The ``clauseelement``, ``multiparams``, and ``params``
+ arguments should be returned as a three-tuple in this case::
+
+ @event.listens_for(Engine, "before_execute", retval=True)
+ def before_execute(conn, conn, clauseelement, multiparams, params):
+ # do something with clauseelement, multiparams, params
+ return clauseelement, multiparams, params
+
+ :param conn: :class:`.Connection` object
+ :param clauseelement: SQL expression construct, :class:`.Compiled`
+ instance, or string statement passed to :meth:`.Connection.execute`.
+ :param multiparams: Multiple parameter sets, a list of dictionaries.
+ :param params: Single parameter set, a single dictionary.
+
+ See also:
+
+ :meth:`.before_cursor_execute`
+
+ """
def after_execute(self, conn, clauseelement, multiparams, params, result):
- """Intercept high level execute() events."""
+ """Intercept high level execute() events after execute.
+
+
+ :param conn: :class:`.Connection` object
+ :param clauseelement: SQL expression construct, :class:`.Compiled`
+ instance, or string statement passed to :meth:`.Connection.execute`.
+ :param multiparams: Multiple parameter sets, a list of dictionaries.
+ :param params: Single parameter set, a single dictionary.
+ :param result: :class:`.ResultProxy` generated by the execution.
+
+ """
def before_cursor_execute(self, conn, cursor, statement,
parameters, context, executemany):
- """Intercept low-level cursor execute() events."""
+ """Intercept low-level cursor execute() events before execution,
+ receiving the string
+ SQL statement and DBAPI-specific parameter list to be invoked
+ against a cursor.
+
+ This event is a good choice for logging as well as late modifications
+ to the SQL string. It's less ideal for parameter modifications except
+ for those which are specific to a target backend.
+
+ This event can be optionally established with the ``retval=True``
+ flag. The ``statement`` and ``parameters`` arguments should be
+ returned as a two-tuple in this case::
+
+ @event.listens_for(Engine, "before_cursor_execute", retval=True)
+ def before_cursor_execute(conn, cursor, statement,
+ parameters, context, executemany):
+ # do something with statement, parameters
+ return statement, parameters
+
+ See the example at :class:`.ConnectionEvents`.
+
+ :param conn: :class:`.Connection` object
+ :param cursor: DBAPI cursor object
+ :param statement: string SQL statement
+ :param parameters: Dictionary, tuple, or list of parameters being
+ passed to the ``execute()`` or ``executemany()`` method of the
+ DBAPI ``cursor``. In some cases may be ``None``.
+ :param context: :class:`.ExecutionContext` object in use. May
+ be ``None``.
+ :param executemany: boolean, if ``True``, this is an ``executemany()``
+ call, if ``False``, this is an ``execute()`` call.
+
+ See also:
+
+ :meth:`.before_execute`
+
+ :meth:`.after_cursor_execute`
+
+ """
def after_cursor_execute(self, conn, cursor, statement,
parameters, context, executemany):
- """Intercept low-level cursor execute() events."""
+ """Intercept low-level cursor execute() events after execution.
+
+ :param conn: :class:`.Connection` object
+ :param cursor: DBAPI cursor object. Will have results pending
+ if the statement was a SELECT, but these should not be consumed
+ as they will be needed by the :class:`.ResultProxy`.
+ :param statement: string SQL statement
+ :param parameters: Dictionary, tuple, or list of parameters being
+ passed to the ``execute()`` or ``executemany()`` method of the
+ DBAPI ``cursor``. In some cases may be ``None``.
+ :param context: :class:`.ExecutionContext` object in use. May
+ be ``None``.
+ :param executemany: boolean, if ``True``, this is an ``executemany()``
+ call, if ``False``, this is an ``execute()`` call.
+
+ """
def dbapi_error(self, conn, cursor, statement, parameters,
context, exception):
@@ -439,37 +566,99 @@ class ConnectionEvents(event.Events):
exception is then wrapped in a SQLAlchemy DBAPI exception
wrapper and re-thrown.
+ :param conn: :class:`.Connection` object
+ :param cursor: DBAPI cursor object
+ :param statement: string SQL statement
+ :param parameters: Dictionary, tuple, or list of parameters being
+ passed to the ``execute()`` or ``executemany()`` method of the
+ DBAPI ``cursor``. In some cases may be ``None``.
+ :param context: :class:`.ExecutionContext` object in use. May
+ be ``None``.
+ :param exception: The **unwrapped** exception emitted directly from the
+ DBAPI. The class here is specific to the DBAPI module in use.
+
.. versionadded:: 0.7.7
"""
def begin(self, conn):
- """Intercept begin() events."""
+ """Intercept begin() events.
+
+ :param conn: :class:`.Connection` object
+
+ """
def rollback(self, conn):
- """Intercept rollback() events."""
+ """Intercept rollback() events.
+
+ :param conn: :class:`.Connection` object
+
+ """
def commit(self, conn):
- """Intercept commit() events."""
+ """Intercept commit() events.
+
+ :param conn: :class:`.Connection` object
+ """
def savepoint(self, conn, name=None):
- """Intercept savepoint() events."""
+ """Intercept savepoint() events.
+
+ :param conn: :class:`.Connection` object
+ :param name: specified name used for the savepoint.
+
+ """
def rollback_savepoint(self, conn, name, context):
- """Intercept rollback_savepoint() events."""
+ """Intercept rollback_savepoint() events.
+
+ :param conn: :class:`.Connection` object
+ :param name: specified name used for the savepoint.
+ :param context: :class:`.ExecutionContext` in use. May be ``None``.
+
+ """
def release_savepoint(self, conn, name, context):
- """Intercept release_savepoint() events."""
+ """Intercept release_savepoint() events.
+
+ :param conn: :class:`.Connection` object
+ :param name: specified name used for the savepoint.
+ :param context: :class:`.ExecutionContext` in use. May be ``None``.
+
+ """
def begin_twophase(self, conn, xid):
- """Intercept begin_twophase() events."""
+ """Intercept begin_twophase() events.
+
+ :param conn: :class:`.Connection` object
+ :param xid: two-phase XID identifier
+
+ """
def prepare_twophase(self, conn, xid):
- """Intercept prepare_twophase() events."""
+ """Intercept prepare_twophase() events.
+
+ :param conn: :class:`.Connection` object
+ :param xid: two-phase XID identifier
+ """
def rollback_twophase(self, conn, xid, is_prepared):
- """Intercept rollback_twophase() events."""
+ """Intercept rollback_twophase() events.
+
+ :param conn: :class:`.Connection` object
+ :param xid: two-phase XID identifier
+ :param is_prepared: boolean, indicates if
+ :meth:`.TwoPhaseTransaction.prepare` was called.
+
+ """
def commit_twophase(self, conn, xid, is_prepared):
- """Intercept commit_twophase() events."""
+ """Intercept commit_twophase() events.
+
+ :param conn: :class:`.Connection` object
+ :param xid: two-phase XID identifier
+ :param is_prepared: boolean, indicates if
+ :meth:`.TwoPhaseTransaction.prepare` was called.
+
+ """
diff --git a/test/base/test_events.py b/test/base/test_events.py
index 57c06c328..7ae05e6c3 100644
--- a/test/base/test_events.py
+++ b/test/base/test_events.py
@@ -5,7 +5,7 @@ from test.lib.testing import eq_, assert_raises, assert_raises_message, \
from sqlalchemy import event, exc, util
from test.lib import fixtures
-class TestEvents(fixtures.TestBase):
+class EventsTest(fixtures.TestBase):
"""Test class- and instance-level event registration."""
def setUp(self):
@@ -161,7 +161,7 @@ class TestEvents(fixtures.TestBase):
meth
)
-class TestClsLevelListen(fixtures.TestBase):
+class ClsLevelListenTest(fixtures.TestBase):
def tearDown(self):
@@ -242,7 +242,7 @@ class TestClsLevelListen(fixtures.TestBase):
assert handler2 not in s2.dispatch.event_one
-class TestAcceptTargets(fixtures.TestBase):
+class AcceptTargetsTest(fixtures.TestBase):
"""Test default target acceptance."""
def setUp(self):
@@ -313,7 +313,7 @@ class TestAcceptTargets(fixtures.TestBase):
[listen_two, listen_four]
)
-class TestCustomTargets(fixtures.TestBase):
+class CustomTargetsTest(fixtures.TestBase):
"""Test custom target acceptance."""
def setUp(self):
@@ -352,7 +352,7 @@ class TestCustomTargets(fixtures.TestBase):
listen, "event_one", self.Target
)
-class TestListenOverride(fixtures.TestBase):
+class ListenOverrideTest(fixtures.TestBase):
"""Test custom listen functions which change the listener function signature."""
def setUp(self):
@@ -398,7 +398,7 @@ class TestListenOverride(fixtures.TestBase):
]
)
-class TestPropagate(fixtures.TestBase):
+class PropagateTest(fixtures.TestBase):
def setUp(self):
class TargetEvents(event.Events):
def event_one(self, arg):
@@ -432,3 +432,217 @@ class TestPropagate(fixtures.TestBase):
t2.dispatch.event_one(t2, 1)
t2.dispatch.event_two(t2, 2)
eq_(result, [(t2, 1)])
+
+class JoinTest(fixtures.TestBase):
+ def setUp(self):
+ class TargetEvents(event.Events):
+ def event_one(self, target, arg):
+ pass
+
+ class BaseTarget(object):
+ dispatch = event.dispatcher(TargetEvents)
+
+ class TargetFactory(BaseTarget):
+ def create(self):
+ return TargetElement(self)
+
+ class TargetElement(BaseTarget):
+ def __init__(self, parent):
+ self.dispatch = self.dispatch._join(parent.dispatch)
+
+ def run_event(self, arg):
+ list(self.dispatch.event_one)
+ self.dispatch.event_one(self, arg)
+
+ self.BaseTarget = BaseTarget
+ self.TargetFactory = TargetFactory
+ self.TargetElement = TargetElement
+
+ def tearDown(self):
+ for cls in (self.TargetElement,
+ self.TargetFactory, self.BaseTarget):
+ if 'dispatch' in cls.__dict__:
+ event._remove_dispatcher(cls.__dict__['dispatch'].events)
+
+ def _listener(self):
+ canary = []
+ def listen(target, arg):
+ canary.append((target, arg))
+ return listen, canary
+
+ def test_neither(self):
+ element = self.TargetFactory().create()
+ element.run_event(1)
+ element.run_event(2)
+ element.run_event(3)
+
+ def test_parent_class_only(self):
+ _listener, canary = self._listener()
+
+ event.listen(self.TargetFactory, "event_one", _listener)
+
+ element = self.TargetFactory().create()
+ element.run_event(1)
+ element.run_event(2)
+ element.run_event(3)
+ eq_(
+ canary,
+ [(element, 1), (element, 2), (element, 3)]
+ )
+
+ def test_parent_class_child_class(self):
+ l1, c1 = self._listener()
+ l2, c2 = self._listener()
+
+ event.listen(self.TargetFactory, "event_one", l1)
+ event.listen(self.TargetElement, "event_one", l2)
+
+ element = self.TargetFactory().create()
+ element.run_event(1)
+ element.run_event(2)
+ element.run_event(3)
+ eq_(
+ c1,
+ [(element, 1), (element, 2), (element, 3)]
+ )
+ eq_(
+ c2,
+ [(element, 1), (element, 2), (element, 3)]
+ )
+
+ def test_parent_class_child_instance_apply_after(self):
+ l1, c1 = self._listener()
+ l2, c2 = self._listener()
+
+ event.listen(self.TargetFactory, "event_one", l1)
+ element = self.TargetFactory().create()
+
+ element.run_event(1)
+
+ event.listen(element, "event_one", l2)
+ element.run_event(2)
+ element.run_event(3)
+
+ eq_(
+ c1,
+ [(element, 1), (element, 2), (element, 3)]
+ )
+ eq_(
+ c2,
+ [(element, 2), (element, 3)]
+ )
+
+ def test_parent_class_child_instance_apply_before(self):
+ l1, c1 = self._listener()
+ l2, c2 = self._listener()
+
+ event.listen(self.TargetFactory, "event_one", l1)
+ element = self.TargetFactory().create()
+
+ event.listen(element, "event_one", l2)
+
+ element.run_event(1)
+ element.run_event(2)
+ element.run_event(3)
+
+ eq_(
+ c1,
+ [(element, 1), (element, 2), (element, 3)]
+ )
+ eq_(
+ c2,
+ [(element, 1), (element, 2), (element, 3)]
+ )
+
+ def test_parent_instance_child_class_apply_before(self):
+ l1, c1 = self._listener()
+ l2, c2 = self._listener()
+
+ event.listen(self.TargetElement, "event_one", l2)
+
+ factory = self.TargetFactory()
+ event.listen(factory, "event_one", l1)
+
+ element = factory.create()
+
+ element.run_event(1)
+ element.run_event(2)
+ element.run_event(3)
+
+ eq_(
+ c1,
+ [(element, 1), (element, 2), (element, 3)]
+ )
+ eq_(
+ c2,
+ [(element, 1), (element, 2), (element, 3)]
+ )
+
+ def test_parent_instance_child_class_apply_after(self):
+ l1, c1 = self._listener()
+ l2, c2 = self._listener()
+
+ event.listen(self.TargetElement, "event_one", l2)
+
+ factory = self.TargetFactory()
+ element = factory.create()
+
+ element.run_event(1)
+
+ event.listen(factory, "event_one", l1)
+
+ element.run_event(2)
+ element.run_event(3)
+
+ # c1 gets no events due to _JoinedListener
+ # fixing the "parent" at construction time.
+ # this can be changed to be "live" at the cost
+ # of performance.
+ eq_(
+ c1,
+ []
+ #(element, 2), (element, 3)]
+ )
+ eq_(
+ c2,
+ [(element, 1), (element, 2), (element, 3)]
+ )
+
+ def test_parent_instance_child_instance_apply_before(self):
+ l1, c1 = self._listener()
+ l2, c2 = self._listener()
+ factory = self.TargetFactory()
+
+ event.listen(factory, "event_one", l1)
+
+ element = factory.create()
+ event.listen(element, "event_one", l2)
+
+ element.run_event(1)
+ element.run_event(2)
+ element.run_event(3)
+
+ eq_(
+ c1,
+ [(element, 1), (element, 2), (element, 3)]
+ )
+ eq_(
+ c2,
+ [(element, 1), (element, 2), (element, 3)]
+ )
+
+ def test_parent_events_child_no_events(self):
+ l1, c1 = self._listener()
+ factory = self.TargetFactory()
+
+ event.listen(self.TargetElement, "event_one", l1)
+ element = factory.create()
+
+ element.run_event(1)
+ element.run_event(2)
+ element.run_event(3)
+
+ eq_(
+ c1,
+ [(element, 1), (element, 2), (element, 3)]
+ )
diff --git a/test/engine/test_execute.py b/test/engine/test_execute.py
index a23f8d05a..85b03e0e9 100644
--- a/test/engine/test_execute.py
+++ b/test/engine/test_execute.py
@@ -1,4 +1,5 @@
-from test.lib.testing import eq_, assert_raises, assert_raises_message, config
+from test.lib.testing import eq_, assert_raises, assert_raises_message, \
+ config, is_
import re
from test.lib.util import picklers
from sqlalchemy.interfaces import ConnectionProxy
@@ -1253,6 +1254,33 @@ class EngineEventsTest(fixtures.TestBase):
canary, ['execute', 'cursor_execute']
)
+ @testing.requires.sequences
+ @testing.provide_metadata
+ def test_cursor_execute(self):
+ canary = []
+ def tracker(name):
+ def go(conn, cursor, statement, parameters, context, executemany):
+ canary.append((statement, context))
+ return go
+ engine = engines.testing_engine()
+
+
+ t = Table('t', self.metadata,
+ Column('x', Integer, Sequence('t_id_seq'), primary_key=True),
+ implicit_returning=False
+ )
+ self.metadata.create_all(engine)
+ with engine.begin() as conn:
+ event.listen(conn, 'before_cursor_execute', tracker('cursor_execute'))
+ conn.execute(t.insert())
+ # we see the sequence pre-executed in the first call
+ assert "t_id_seq" in canary[0][0]
+ assert "INSERT" in canary[1][0]
+ # same context
+ is_(
+ canary[0][1], canary[1][1]
+ )
+
def test_transactional(self):
canary = []
def tracker(name):
diff --git a/test/lib/profiles.txt b/test/lib/profiles.txt
index 48e5caff9..d58d2ac38 100644
--- a/test/lib/profiles.txt
+++ b/test/lib/profiles.txt
@@ -21,28 +21,39 @@ test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_postgresql_psycopg2
test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_postgresql_psycopg2_nocextensions 62
test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_sqlite_pysqlite_cextensions 62
test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_sqlite_pysqlite_nocextensions 62
-test.aaa_profiling.test_compiler.CompileTest.test_insert 3.2_postgresql_psycopg2_nocextensions 68
-test.aaa_profiling.test_compiler.CompileTest.test_insert 3.2_sqlite_pysqlite_nocextensions 68
# TEST: test.aaa_profiling.test_compiler.CompileTest.test_select
-test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mysql_mysqldb_cextensions 133
-test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_postgresql_psycopg2_cextensions 133
-test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_postgresql_psycopg2_nocextensions 133
-test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_sqlite_pysqlite_cextensions 133
-test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_sqlite_pysqlite_nocextensions 133
-
-# TEST: test.aaa_profiling.test_compiler.CompileTest.test_select_second_time
-
-test.aaa_profiling.test_compiler.CompileTest.test_select_second_time 2.7_sqlite_pysqlite_nocextensions 133
+test.aaa_profiling.test_compiler.CompileTest.test_select 2.5_sqlite_pysqlite_nocextensions 134
+test.aaa_profiling.test_compiler.CompileTest.test_select 2.6_sqlite_pysqlite_nocextensions 135
+test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mysql_mysqldb_cextensions 135
+test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mysql_mysqldb_nocextensions 135
+test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_postgresql_psycopg2_cextensions 135
+test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_postgresql_psycopg2_nocextensions 135
+test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_sqlite_pysqlite_cextensions 135
+test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_sqlite_pysqlite_nocextensions 135
# TEST: test.aaa_profiling.test_compiler.CompileTest.test_update
+test.aaa_profiling.test_compiler.CompileTest.test_update 2.5_sqlite_pysqlite_nocextensions 65
+test.aaa_profiling.test_compiler.CompileTest.test_update 2.6_sqlite_pysqlite_nocextensions 65
+test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mysql_mysqldb_cextensions 65
+test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mysql_mysqldb_nocextensions 65
+test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_postgresql_psycopg2_cextensions 65
+test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_postgresql_psycopg2_nocextensions 65
test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_sqlite_pysqlite_cextensions 65
+test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_sqlite_pysqlite_nocextensions 65
# TEST: test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause
+test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.5_sqlite_pysqlite_nocextensions 129
+test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.6_sqlite_pysqlite_nocextensions 130
+test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mysql_mysqldb_cextensions 130
+test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mysql_mysqldb_nocextensions 130
+test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_postgresql_psycopg2_cextensions 130
+test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_postgresql_psycopg2_nocextensions 130
test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_sqlite_pysqlite_cextensions 130
+test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_sqlite_pysqlite_nocextensions 130
# TEST: test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity
@@ -54,47 +65,39 @@ test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_postgresql_psycopg2_nocextensions 17987
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_sqlite_pysqlite_cextensions 17987
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_sqlite_pysqlite_nocextensions 17987
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 3.2_postgresql_psycopg2_nocextensions 18987
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 3.2_sqlite_pysqlite_nocextensions 18987
# TEST: test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.5_sqlite_pysqlite_nocextensions 116038
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.6_sqlite_pysqlite_nocextensions 114788
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_mysql_mysqldb_cextensions 122288
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_mysql_mysqldb_nocextensions 125038
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_postgresql_psycopg2_cextensions 114788
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_postgresql_psycopg2_nocextensions 117538
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_sqlite_pysqlite_cextensions 113760
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_sqlite_pysqlite_nocextensions 116538
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.2_postgresql_psycopg2_nocextensions 121541
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.2_sqlite_pysqlite_nocextensions 121541
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.5_sqlite_pysqlite_nocextensions 116289
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.6_sqlite_pysqlite_nocextensions 116790
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_mysql_mysqldb_cextensions 122540
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_mysql_mysqldb_nocextensions 125290
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_postgresql_psycopg2_cextensions 115040
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_postgresql_psycopg2_nocextensions 117790
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_sqlite_pysqlite_cextensions 114040
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_sqlite_pysqlite_nocextensions 116790
# TEST: test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks
-test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.5_sqlite_pysqlite_nocextensions 19770
-test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.6_sqlite_pysqlite_nocextensions 18941
-test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_mysql_mysqldb_cextensions 19449
-test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_mysql_mysqldb_nocextensions 19709
-test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_postgresql_psycopg2_cextensions 18873
-test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_postgresql_psycopg2_nocextensions 19096
-test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_sqlite_pysqlite_cextensions 18885
-test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_sqlite_pysqlite_nocextensions 19117
-test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.2_postgresql_psycopg2_nocextensions 20217
-test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.2_sqlite_pysqlite_nocextensions 20274
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.5_sqlite_pysqlite_nocextensions 19852
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.6_sqlite_pysqlite_nocextensions 19217
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_mysql_mysqldb_cextensions 19491
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_mysql_mysqldb_nocextensions 19781
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_postgresql_psycopg2_cextensions 18878
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_postgresql_psycopg2_nocextensions 19168
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_sqlite_pysqlite_cextensions 18957
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_sqlite_pysqlite_nocextensions 19217
# TEST: test.aaa_profiling.test_orm.MergeTest.test_merge_load
-test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.5_sqlite_pysqlite_nocextensions 1132
-test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.6_sqlite_pysqlite_nocextensions 1113
-test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_mysql_mysqldb_cextensions 1295
-test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_mysql_mysqldb_nocextensions 1320
-test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_postgresql_psycopg2_cextensions 1154
-test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_postgresql_psycopg2_nocextensions 1179
-test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_sqlite_pysqlite_cextensions 1103
-test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_sqlite_pysqlite_nocextensions 1128
-test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.2_postgresql_psycopg2_nocextensions 1202
-test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.2_sqlite_pysqlite_nocextensions 1165
+test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.5_sqlite_pysqlite_nocextensions 1178
+test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.6_sqlite_pysqlite_nocextensions 1174
+test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_mysql_mysqldb_cextensions 1341
+test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_mysql_mysqldb_nocextensions 1366
+test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_postgresql_psycopg2_cextensions 1200
+test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_postgresql_psycopg2_nocextensions 1225
+test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_sqlite_pysqlite_cextensions 1149
+test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_sqlite_pysqlite_nocextensions 1174
# TEST: test.aaa_profiling.test_orm.MergeTest.test_merge_no_load
@@ -106,8 +109,6 @@ test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_postgresql_psycopg2
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_postgresql_psycopg2_nocextensions 98,16
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_sqlite_pysqlite_cextensions 98,16
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_sqlite_pysqlite_nocextensions 98,16
-test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 3.2_postgresql_psycopg2_nocextensions 103,17
-test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 3.2_sqlite_pysqlite_nocextensions 103,17
# TEST: test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect
@@ -119,8 +120,6 @@ test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.7_postgresql_psy
test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.7_postgresql_psycopg2_nocextensions 67
test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.7_sqlite_pysqlite_cextensions 67
test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.7_sqlite_pysqlite_nocextensions 67
-test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 3.2_postgresql_psycopg2_nocextensions 55
-test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 3.2_sqlite_pysqlite_nocextensions 55
# TEST: test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect
@@ -132,8 +131,6 @@ test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.7_postgresql_ps
test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.7_postgresql_psycopg2_nocextensions 29
test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.7_sqlite_pysqlite_cextensions 29
test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.7_sqlite_pysqlite_nocextensions 29
-test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 3.2_postgresql_psycopg2_nocextensions 23
-test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 3.2_sqlite_pysqlite_nocextensions 23
# TEST: test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect
@@ -145,8 +142,6 @@ test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.7_po
test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.7_postgresql_psycopg2_nocextensions 6
test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.7_sqlite_pysqlite_cextensions 6
test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.7_sqlite_pysqlite_nocextensions 6
-test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 3.2_postgresql_psycopg2_nocextensions 7
-test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 3.2_sqlite_pysqlite_nocextensions 7
# TEST: test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute
@@ -158,8 +153,6 @@ test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.7_postgresql_psycopg2_nocextensions 42
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.7_sqlite_pysqlite_cextensions 40
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.7_sqlite_pysqlite_nocextensions 42
-test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 3.2_postgresql_psycopg2_nocextensions 40
-test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 3.2_sqlite_pysqlite_nocextensions 40
# TEST: test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute
@@ -171,12 +164,13 @@ test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_postgresql_psycopg2_nocextensions 65
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_sqlite_pysqlite_cextensions 63
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_sqlite_pysqlite_nocextensions 65
-test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.2_postgresql_psycopg2_nocextensions 63
-test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.2_sqlite_pysqlite_nocextensions 63
# TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile
+test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.5_sqlite_pysqlite_nocextensions 14
+test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.6_sqlite_pysqlite_nocextensions 14
test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_mysql_mysqldb_cextensions 14
+test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_mysql_mysqldb_nocextensions 14
test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_postgresql_psycopg2_cextensions 14
test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_postgresql_psycopg2_nocextensions 14
test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_sqlite_pysqlite_cextensions 14
@@ -184,103 +178,87 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7
# TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_string
-test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.5_sqlite_pysqlite_nocextensions 14369
-test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.6_sqlite_pysqlite_nocextensions 14370
-test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_mysqldb_cextensions 408
-test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_mysqldb_nocextensions 14428
-test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_postgresql_psycopg2_cextensions 20394
-test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_postgresql_psycopg2_nocextensions 34414
-test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_sqlite_pysqlite_cextensions 350
-test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_sqlite_pysqlite_nocextensions 14370
-test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.2_postgresql_psycopg2_nocextensions 14382
-test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.2_sqlite_pysqlite_nocextensions 14353
+test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.5_sqlite_pysqlite_nocextensions 14413
+test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.6_sqlite_pysqlite_nocextensions 14414
+test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_mysqldb_cextensions 452
+test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_mysqldb_nocextensions 14472
+test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_postgresql_psycopg2_cextensions 20438
+test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_postgresql_psycopg2_nocextensions 34458
+test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_sqlite_pysqlite_cextensions 394
+test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_sqlite_pysqlite_nocextensions 14414
# TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_unicode
-test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.5_sqlite_pysqlite_nocextensions 14369
-test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.6_sqlite_pysqlite_nocextensions 14370
-test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_mysqldb_cextensions 408
-test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_mysqldb_nocextensions 44428
-test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_postgresql_psycopg2_cextensions 20394
-test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_postgresql_psycopg2_nocextensions 34414
-test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_sqlite_pysqlite_cextensions 350
-test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_sqlite_pysqlite_nocextensions 14370
-test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.2_postgresql_psycopg2_nocextensions 14382
-test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.2_sqlite_pysqlite_nocextensions 14353
+test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.5_sqlite_pysqlite_nocextensions 14413
+test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.6_sqlite_pysqlite_nocextensions 14414
+test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_mysqldb_cextensions 452
+test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_mysqldb_nocextensions 44472
+test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_postgresql_psycopg2_cextensions 20438
+test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_postgresql_psycopg2_nocextensions 34458
+test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_sqlite_pysqlite_cextensions 394
+test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_sqlite_pysqlite_nocextensions 14414
# TEST: test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_1a_populate
-test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_1a_populate 2.7_postgresql_psycopg2_cextensions 4915
-test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_1a_populate 2.7_postgresql_psycopg2_nocextensions 4959
-test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_1a_populate 3.2_postgresql_psycopg2_nocextensions 4707
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_1a_populate 2.7_postgresql_psycopg2_cextensions 5044
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_1a_populate 2.7_postgresql_psycopg2_nocextensions 5088
# TEST: test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_2_insert
test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_2_insert 2.7_postgresql_psycopg2_cextensions 247
test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_2_insert 2.7_postgresql_psycopg2_nocextensions 247
-test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_2_insert 3.2_postgresql_psycopg2_nocextensions 236
# TEST: test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_3_properties
-test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_3_properties 2.7_postgresql_psycopg2_cextensions 3302
-test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_3_properties 2.7_postgresql_psycopg2_nocextensions 3526
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_3_properties 2.7_postgresql_psycopg2_cextensions 3366
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_3_properties 2.7_postgresql_psycopg2_nocextensions 3590
# TEST: test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_4_expressions
-test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_4_expressions 2.7_postgresql_psycopg2_cextensions 10062
-test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_4_expressions 2.7_postgresql_psycopg2_nocextensions 11678
-test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_4_expressions 3.2_postgresql_psycopg2_nocextensions 10973
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_4_expressions 2.7_postgresql_psycopg2_cextensions 10366
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_4_expressions 2.7_postgresql_psycopg2_nocextensions 11982
# TEST: test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_5_aggregates
-test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_5_aggregates 2.7_postgresql_psycopg2_cextensions 998
-test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_5_aggregates 2.7_postgresql_psycopg2_nocextensions 1102
-test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_5_aggregates 3.2_postgresql_psycopg2_nocextensions 1076
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_5_aggregates 2.7_postgresql_psycopg2_cextensions 1005
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_5_aggregates 2.7_postgresql_psycopg2_nocextensions 1109
# TEST: test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_6_editing
-test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_6_editing 2.7_postgresql_psycopg2_cextensions 1654
-test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_6_editing 2.7_postgresql_psycopg2_nocextensions 1697
-test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_6_editing 3.2_postgresql_psycopg2_nocextensions 1600
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_6_editing 2.7_postgresql_psycopg2_cextensions 1736
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_6_editing 2.7_postgresql_psycopg2_nocextensions 1779
# TEST: test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_7_multiview
-test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_7_multiview 2.7_postgresql_psycopg2_cextensions 2154
-test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_7_multiview 2.7_postgresql_psycopg2_nocextensions 2384
-test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_7_multiview 3.2_postgresql_psycopg2_nocextensions 2365
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_7_multiview 2.7_postgresql_psycopg2_cextensions 2219
+test.aaa_profiling.test_zoomark.ZooMarkTest.test_profile_7_multiview 2.7_postgresql_psycopg2_nocextensions 2449
# TEST: test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_1a_populate
-test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_1a_populate 2.7_postgresql_psycopg2_cextensions 5842
-test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_1a_populate 2.7_postgresql_psycopg2_nocextensions 5968
-test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_1a_populate 3.2_postgresql_psycopg2_nocextensions 5981
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_1a_populate 2.7_postgresql_psycopg2_cextensions 5977
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_1a_populate 2.7_postgresql_psycopg2_nocextensions 6096
# TEST: test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_2_insert
-test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_2_insert 2.7_postgresql_psycopg2_cextensions 391
-test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_2_insert 2.7_postgresql_psycopg2_nocextensions 398
-test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_2_insert 3.2_postgresql_psycopg2_nocextensions 396
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_2_insert 2.7_postgresql_psycopg2_cextensions 392
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_2_insert 2.7_postgresql_psycopg2_nocextensions 399
# TEST: test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_3_properties
-test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_3_properties 2.7_postgresql_psycopg2_cextensions 5846
-test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_3_properties 2.7_postgresql_psycopg2_nocextensions 6078
-test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_3_properties 3.2_postgresql_psycopg2_nocextensions 6039
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_3_properties 2.7_postgresql_psycopg2_cextensions 6124
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_3_properties 2.7_postgresql_psycopg2_nocextensions 6356
# TEST: test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_4_expressions
-test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_4_expressions 2.7_postgresql_psycopg2_cextensions 17885
-test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_4_expressions 2.7_postgresql_psycopg2_nocextensions 19316
-test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_4_expressions 3.2_postgresql_psycopg2_nocextensions 19197
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_4_expressions 2.7_postgresql_psycopg2_cextensions 18140
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_4_expressions 2.7_postgresql_psycopg2_nocextensions 19571
# TEST: test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_5_aggregates
-test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_5_aggregates 2.7_postgresql_psycopg2_cextensions 1011
-test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_5_aggregates 2.7_postgresql_psycopg2_nocextensions 1107
-test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_5_aggregates 3.2_postgresql_psycopg2_nocextensions 1082
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_5_aggregates 2.7_postgresql_psycopg2_cextensions 1018
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_5_aggregates 2.7_postgresql_psycopg2_nocextensions 1114
# TEST: test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_6_editing
-test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_6_editing 2.7_postgresql_psycopg2_cextensions 2555
-test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_6_editing 2.7_postgresql_psycopg2_nocextensions 2618
-test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_6_editing 3.2_postgresql_psycopg2_nocextensions 2650
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_6_editing 2.7_postgresql_psycopg2_cextensions 2614
+test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_profile_6_editing 2.7_postgresql_psycopg2_nocextensions 2677
diff --git a/test/sql/test_cte.py b/test/sql/test_cte.py
index 59b347ccd..6360e278c 100644
--- a/test/sql/test_cte.py
+++ b/test/sql/test_cte.py
@@ -350,3 +350,4 @@ class CTETest(fixtures.TestBase, AssertsCompiledSQL):
checkpositional=('x', 'y'),
dialect=dialect
)
+