]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Ensure autobegin occurs for attribute changes; Document autobegin
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 26 Apr 2021 13:50:50 +0000 (09:50 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 26 Apr 2021 16:17:46 +0000 (12:17 -0400)
The Session autobegin feature was not anticipated as having
any behavioral changes other than the event hook being called
at a different time, however as autobegin impacts the behavior
of the commit() and rollback() methods in that they can now
be no-ops in non-autocommit mode, document the behavior fully.

Fixed issue where the new :ref:`session_autobegin` behavior failed to
"autobegin" in the case where an existing persistent object has an
attribute change, which would then impact the behavior of
:meth:`_orm.Session.rollback` in that no snapshot was created to be rolled
back. The "attribute modify" mechanics have been updated to ensure
"autobegin", which does not perform any database work, does occur when
persistent attributes change in the same manner as when
:meth:`_orm.Session.add` is called. This is a regression as in 1.3, the
rollback() method always had a transaction to roll back and would expire
every time.

Fixes: #6360
Fixes: #6359
Change-Id: I69f231a206f49e3231275d23bbe2cafd4e2bf3ba

doc/build/changelog/migration_14.rst
doc/build/changelog/unreleased_14/6360.rst [new file with mode: 0644]
doc/build/orm/session_basics.rst
lib/sqlalchemy/orm/session.py
lib/sqlalchemy/orm/state.py
test/orm/test_session.py
test/profiles.txt

index 7cf1cc5942ce92fecd081942426a1c49454f2e75..1addfd15b8f6d5a2322f7ba888b4176b74d35cde 100644 (file)
@@ -2024,6 +2024,40 @@ as entity / column should work::
 Session features new "autobegin" behavior
 -----------------------------------------
 
+Previously, the :class:`.Session` in its default mode of ``autocommit=False``
+would internally begin a :class:`.SessionTransaction` object immediately
+on construction, and additionally would create a new one after each call to
+:meth:`.Session.rollback` or :meth:`.Session.commit`.
+
+The new behavior is that this :class:`.SessionTransaction` object is now
+created on demand only, when methods such as :meth:`.Session.add` or
+:meth:`.Session.execute` are called.    However it is also now possible
+to call :meth:`.Session.begin` explicitly in order to begin the transaction,
+even in ``autocommit=False`` mode, thus matching the behavior of the
+future-style :class:`_base.Connection`.
+
+The behavioral changes this indicates are:
+
+* The :class:`.Session` can now be in the state where no transaction is begun,
+  even in ``autocommit=False`` mode. Previously, this state was only available
+  in "autocommit" mode.
+* Within this state, the :meth:`.Session.commit` and :meth:`.Session.rollback`
+  methods are no-ops. Code that relies upon these methods to expire all objects
+  should make explicit use of either :meth:`.Session.begin` or
+  :meth:`.Session.expire_all` to suit their use case.
+* The :meth:`.SessionEvents.after_transaction_create` event hook is not emitted
+  immediately when the :class:`.Session` is created, or after a
+  :meth:`.Session.rollback` or :meth:`.Session.commit` completes.
+* The :meth:`.Session.close` method also does not imply implicit begin of a new
+  :class:`.SessionTransaction`.
+
+.. seealso::
+
+    :ref:`session_autobegin`
+
+Rationale
+^^^^^^^^^
+
 The :class:`.Session` object's default behavior of ``autocommit=False``
 historically has meant that there is always a :class:`.SessionTransaction`
 object in play, associated with the :class:`.Session` via the
@@ -2062,13 +2096,20 @@ when the :class:`.Session` has not yet created a  new
 :meth:`.Session.delete`, when  the :attr:`.Session.transaction` attribute is
 called upon, when the :meth:`.Session.flush` method has tasks to complete, etc.
 
+In addition, code which relies upon the :meth:`.Session.commit` or
+:meth:`.Session.rollback` method to unconditionally expire all objects can no
+longer do so. Code which needs to expire all objects when no change that has
+occurred should be calling :meth:`.Session.expire_all` for this case.
+
 Besides the change in when the :meth:`.SessionEvents.after_transaction_create`
-event is emitted, the change should have no other user-visible impact on the
-:class:`.Session` object's behavior; the :class:`.Session` will continue to have
-the behavior that it remains usable for new operations after :meth:`.Session.close`
-is called, and the sequencing of how the :class:`.Session` interacts with the
-:class:`_engine.Engine` and the database itself should also remain unaffected, since
-these operations were already operating in an on-demand fashion.
+event is emitted as well as the no-op nature of :meth:`.Session.commit` or
+:meth:`.Session.rollback`, the change should have no other user-visible impact
+on the :class:`.Session` object's behavior; the :class:`.Session` will continue
+to have the behavior that it remains usable for new operations after
+:meth:`.Session.close` is called, and the sequencing of how the
+:class:`.Session` interacts with the :class:`_engine.Engine` and the database
+itself should also remain unaffected, since these operations were already
+operating in an on-demand fashion.
 
 :ticket:`5074`
 
diff --git a/doc/build/changelog/unreleased_14/6360.rst b/doc/build/changelog/unreleased_14/6360.rst
new file mode 100644 (file)
index 0000000..880a799
--- /dev/null
@@ -0,0 +1,14 @@
+.. change::
+    :tags: bug, orm, regression
+    :tickets: 6360, 6359
+
+    Fixed issue where the new :ref:`session_autobegin` behavior failed to
+    "autobegin" in the case where an existing persistent object has an
+    attribute change, which would then impact the behavior of
+    :meth:`_orm.Session.rollback` in that no snapshot was created to be rolled
+    back. The "attribute modify" mechanics have been updated to ensure
+    "autobegin", which does not perform any database work, does occur when
+    persistent attributes change in the same manner as when
+    :meth:`_orm.Session.add` is called. This is a regression as in 1.3, the
+    rollback() method always had a transaction to roll back and would expire
+    every time.
index a5620ef6ec181776ed07e4297d50f5f36a2013ba..40c81f31c1243188bf10b6cff3b45bf31c9c2bcc 100644 (file)
@@ -81,6 +81,8 @@ persisted to the database.  If we were only issuing SELECT calls and did not
 need to write any changes, then the call to :meth:`_orm.Session.commit` would
 be unnecessary.
 
+.. _session_begin_commit_rollback_block:
+
 Framing out a begin / commit / rollback block
 -----------------------------------------------
 
@@ -95,6 +97,7 @@ expressed using a ``try: / except: / else:`` block such as::
 
     # verbose version of what a context manager will do
     with Session(engine) as session:
+        session.begin()
         try:
             session.add(some_object)
             session.add(some_other_object)
@@ -754,36 +757,98 @@ constructs support RETURNING as well.
   :ref:`orm_queryguide_selecting_text` - introduces the
   :meth:`_sql.Select.from_statement` method.
 
+.. _session_autobegin:
+
+Auto Begin
+----------
+
+.. versionadded:: 1.4
+
+  This section describes a behavior that is new in SQLAlchemy 1.4 and does
+  not apply to previous versions.  Further details on the "autobegin"
+  change are at :ref:`change_5074`.
+
+The :class:`_orm.Session` object features a behavior known as **autobegin**.
+This indicates that the :class:`_orm.Session` will internally consider itself
+to be in a "transactional" state as soon as any work is performed with the
+:class:`_orm.Session`, either involving modifications to the internal state of
+the :class:`_orm.Session` with regards to object state changes, or with
+operations that require database connectivity.
+
+When the :class:`_orm.Session` is first constructed, there's no transactional
+state present.   The transactional state is begun automatically, when
+a method such as :meth:`_orm.Session.add` or :meth:`_orm.Session.execute`
+is invoked, or similarly if a :class:`_orm.Query` is executed to return
+results (which ultimately uses :meth:`_orm.Session.execute`), or if
+an attribute is modified on a :term:`persistent` object.
+
+The transactional state can be checked by accessing the
+:meth:`_orm.Session.in_transaction` method, which returns ``True`` or ``False``
+indicating if the "autobegin" step has proceeded. While not normally needed,
+the :meth:`_orm.Session.get_transaction` method will return the actual
+:class:`_orm.SessionTransaction` object that represents this transactional
+state.
+
+The transactional state of the :class:`_orm.Session` may also be started
+explicitly, by invoking the :meth:`_orm.Session.begin` method.   When this
+method is called, the :class:`_orm.Session` is placed into the "transactional"
+state unconditionally.   :meth:`_orm.Session.begin` may be used as a context
+manager as described at :ref:`session_begin_commit_rollback_block`.
+
+.. versionchanged:: 1.4.12 - autobegin now correctly occurs if object
+   attributes are modified; previously this was not occurring.
+
+
 .. _session_committing:
 
 Committing
 ----------
 
 :meth:`~.Session.commit` is used to commit the current
-transaction. It always issues :meth:`~.Session.flush`
+transaction, if any.   When there is no transaction in place, the method
+passes silently.
+
+When :meth:`_orm.Session.commit` operates upon the current open transaction,
+it first always issues :meth:`~.Session.flush`
 beforehand to flush any remaining state to the database; this is independent
 of the "autoflush" setting.
 
-If the :class:`_orm.Session` does not currently have a transaction present,
-the method will silently pass, unless the legacy "autocommit" mode is enabled
-in which it will raise an error.
+Subsequent to that, :meth:`_orm.Session.commit` will then COMMIT the actual
+database transaction or transactions, if any, that are in place.
+
+Finally, all objects within the :class:`_orm.Session` are :term:`expired` as
+the transaction is closed out. This is so that when the instances are next
+accessed, either through attribute access or by them being present in the
+result of a SELECT, they receive the most recent state. This behavior may be
+controlled by the :paramref:`_orm.Session.expire_on_commit` flag, which may be
+set to ``False`` when this behavior is undesirable.
 
-Another behavior of :meth:`~.Session.commit` is that by
-default it expires the state of all instances present after the commit is
-complete. This is so that when the instances are next accessed, either through
-attribute access or by them being present in the result of a SELECT,
-they receive the most recent  state.   This behavior may be controlled
-by the :paramref:`_orm.Session.expire_on_commit` flag, which may be set
-to ``False`` when this behavior is undesirable.
+.. versionchanged:: 1.4
+
+    The :class:`_orm.Session` object now features deferred "begin" behavior, as
+    described in :ref:`autobegin <session_autobegin>`. If no transaction is
+    begun, methods like :meth:`_orm.Session.commit` and
+    :meth:`_orm.Session.rollback` have no effect.  This behavior would not
+    have been observed prior to 1.4 as under non-autocommit mode, a
+    transaction would always be implicitly present.
+
+.. seealso::
+
+    :ref:`session_autobegin`
 
 .. _session_rollback:
 
 Rolling Back
 ------------
 
-:meth:`~.Session.rollback` rolls back the current
-transaction. With a default configured session, the post-rollback state of the
-session is as follows:
+:meth:`~.Session.rollback` rolls back the current transaction, if any.
+When there is no transaction in place, the method passes silently.
+
+With a default configured session, the
+post-rollback state of the session, subsequent to a transaction having
+been begun either via :ref:`autobegin <session_autobegin>`
+or by calling the :meth:`_orm.Session.begin`
+method explicitly, is as follows:
 
   * All transactions are rolled back and all connections returned to the
     connection pool, unless the Session was bound directly to a Connection, in
@@ -797,22 +862,34 @@ session is as follows:
     their DELETE statement being rolled back. Note that if those objects were
     first :term:`pending` within the transaction, that operation takes precedence
     instead.
-  * All objects not expunged are fully expired.
+  * All objects not expunged are fully expired - this is regardless of the
+    :paramref:`_orm.Session.expire_on_commit` setting.
 
-With that state understood, the :class:`~sqlalchemy.orm.session.Session` may
+With that state understood, the :class:`_orm.Session` may
 safely continue usage after a rollback occurs.
 
-When a :meth:`~.Session.flush` fails, typically for
-reasons like primary key, foreign key, or "not nullable" constraint
-violations, a ROLLBACK is issued
+.. versionchanged:: 1.4
+
+    The :class:`_orm.Session` object now features deferred "begin" behavior, as
+    described in :ref:`autobegin <session_autobegin>`. If no transaction is
+    begun, methods like :meth:`_orm.Session.commit` and
+    :meth:`_orm.Session.rollback` have no effect.  This behavior would not
+    have been observed prior to 1.4 as under non-autocommit mode, a
+    transaction would always be implicitly present.
+
+When a :meth:`_orm.Session.flush` fails, typically for reasons like primary
+key, foreign key, or "not nullable" constraint violations, a ROLLBACK is issued
 automatically (it's currently not possible for a flush to continue after a
-partial failure).   However, the :class:`_orm.Session` goes into a state
-known as "inactive" at this point, and the calling application must
-always call the :meth:`_orm.Session.rollback` method explicitly so that
-the :class:`_orm.Session` can go back into a useable state (it can also
-be simply closed and discarded).   See the FAQ entry at
-:ref:`faq_session_rollback` for further discussion.
+partial failure). However, the :class:`_orm.Session` goes into a state known as
+"inactive" at this point, and the calling application must always call the
+:meth:`_orm.Session.rollback` method explicitly so that the
+:class:`_orm.Session` can go back into a useable state (it can also be simply
+closed and discarded). See the FAQ entry at :ref:`faq_session_rollback` for
+further discussion.
 
+.. seealso::
+
+  :ref:`session_autobegin`
 
 
 Closing
@@ -840,6 +917,12 @@ that :meth:`_orm.Session.close` is called::
 
     # closes session automatically
 
+.. versionchanged:: 1.4
+
+    The :class:`_orm.Session` object features deferred "begin" behavior, as
+    described in :ref:`autobegin <session_autobegin>`. no longer immediately
+    begins a new transaction after the :meth:`_orm.Session.close` method is
+    called.
 
 .. _session_faq:
 
index d5f418b1cada348a953f028b7a438fa4fecaa343..a3ec360d00e0f4585bf8b8da1a4cc9b14a7a9e6a 100644 (file)
@@ -54,17 +54,14 @@ _sessions = weakref.WeakValueDictionary()
 """Weak-referencing dictionary of :class:`.Session` objects.
 """
 
+statelib._sessions = _sessions
+
 
 def _state_session(state):
     """Given an :class:`.InstanceState`, return the :class:`.Session`
     associated, if any.
     """
-    if state.session_id:
-        try:
-            return _sessions[state.session_id]
-        except KeyError:
-            pass
-    return None
+    return state.session
 
 
 class _SessionClassMethods(object):
@@ -1273,7 +1270,13 @@ class Session(_SessionClassMethods):
     )
     def begin(self, subtransactions=False, nested=False, _subtrans=False):
         """Begin a transaction, or nested transaction,
-        on this :class:`.Session`.
+        on this :class:`.Session`, if one is not already begun.
+
+        The :class:`_orm.Session` object features **autobegin** behavior,
+        so that normally it is not necessary to call the
+        :meth:`_orm.Session.begin`
+        method explicitly. However, it may be used in order to control
+        the scope of when the transactional state is begun.
 
         When used to begin the outermost transaction, an error is raised
         if this :class:`.Session` is already inside of a transaction.
@@ -1294,6 +1297,8 @@ class Session(_SessionClassMethods):
 
         .. seealso::
 
+            :ref:`session_autobegin`
+
             :ref:`unitofwork_transaction`
 
             :meth:`.Session.begin_nested`
index cda98b89083a026ed6636ee2195b9195b98f08c1..08390328e47dd9e2e343aa0a38676673739410be 100644 (file)
@@ -31,6 +31,10 @@ from .. import inspection
 from .. import util
 
 
+# late-populated by session.py
+_sessions = None
+
+
 @inspection._self_inspects
 class InstanceState(interfaces.InspectionAttrInfo):
     """tracks state information at the instance level.
@@ -247,7 +251,6 @@ class InstanceState(interfaces.InspectionAttrInfo):
             self._last_known_values[key] = NO_VALUE
 
     @property
-    @util.preload_module("sqlalchemy.orm.session")
     def session(self):
         """Return the owning :class:`.Session` for this instance,
         or ``None`` if none available.
@@ -260,7 +263,12 @@ class InstanceState(interfaces.InspectionAttrInfo):
         fully detached under normal circumstances.
 
         """
-        return util.preloaded.orm_session._state_session(self)
+        if self.session_id:
+            try:
+                return _sessions[self.session_id]
+            except KeyError:
+                pass
+        return None
 
     @property
     def object(self):
@@ -754,7 +762,10 @@ class InstanceState(interfaces.InspectionAttrInfo):
             self.modified = True
             instance_dict = self._instance_dict()
             if instance_dict:
+                has_modified = bool(instance_dict._modified)
                 instance_dict._modified.add(self)
+            else:
+                has_modified = False
 
             # only create _strong_obj link if attached
             # to a session
@@ -763,6 +774,20 @@ class InstanceState(interfaces.InspectionAttrInfo):
             if self.session_id:
                 self._strong_obj = inst
 
+                # if identity map already had modified objects,
+                # assume autobegin already occurred, else check
+                # for autobegin
+                if not has_modified:
+                    # inline of autobegin, to ensure session transaction
+                    # snapshot is established
+                    try:
+                        session = _sessions[self.session_id]
+                    except KeyError:
+                        pass
+                    else:
+                        if session._transaction is None:
+                            session._autobegin()
+
             if inst is None and attr:
                 raise orm_exc.ObjectDereferencedError(
                     "Can't emit change event for attribute '%s' - "
index 89d61c3ea1b673cca4eb0b1ea9ababe1bef5a884..d6cd83d6a2a348bf7f118626992a39619609acd4 100644 (file)
@@ -220,6 +220,81 @@ class TransScopingTest(_fixtures.FixtureTest):
             s.begin,
         )
 
+    @testing.combinations((True,), (False,), argnames="autocommit")
+    @testing.combinations((True,), (False,), argnames="begin")
+    @testing.combinations((True,), (False,), argnames="expire_on_commit")
+    @testing.combinations((True,), (False,), argnames="modify_unconditional")
+    @testing.combinations(
+        ("nothing",), ("modify",), ("add",), ("delete",), argnames="case_"
+    )
+    def test_autobegin_attr_change(
+        self, case_, autocommit, begin, modify_unconditional, expire_on_commit
+    ):
+        """test :ticket:`6360` """
+
+        User, users = self.classes.User, self.tables.users
+
+        mapper(User, users)
+
+        s = Session(
+            testing.db,
+            autocommit=autocommit,
+            expire_on_commit=expire_on_commit,
+        )
+
+        u = User(name="x")
+        u2 = User(name="d")
+        u3 = User(name="e")
+        s.add_all([u, u2, u3])
+
+        if autocommit:
+            s.flush()
+        else:
+            s.commit()
+
+        if begin:
+            s.begin()
+
+        if case_ == "add":
+            # this autobegins
+            s.add(User(name="q"))
+        elif case_ == "delete":
+            # this autobegins
+            s.delete(u2)
+        elif case_ == "modify":
+            # this autobegins
+            u3.name = "m"
+
+        if case_ == "nothing" and not begin:
+            assert not s._transaction
+            expect_expire = expire_on_commit
+        elif autocommit and not begin:
+            assert not s._transaction
+            expect_expire = expire_on_commit
+        else:
+            assert s._transaction
+            expect_expire = True
+
+        if modify_unconditional:
+            # this autobegins
+            u.name = "y"
+            expect_expire = True
+
+        if not expect_expire:
+            assert not s._transaction
+
+        # test is that state is consistent after rollback()
+        s.rollback()
+
+        if autocommit and not begin and modify_unconditional:
+            eq_(u.name, "y")
+        else:
+            if not expect_expire:
+                assert "name" in u.__dict__
+            else:
+                assert "name" not in u.__dict__
+            eq_(u.name, "x")
+
     @testing.requires.independent_connections
     @engines.close_open_connections
     def test_transaction(self):
index 1a271596d182ee9c74ac945a2f4a550eff18a115..e31bda76632f953b9c079ab0a874c4465461dcc0 100644 (file)
@@ -1,15 +1,15 @@
 # /home/classic/dev/sqlalchemy/test/profiles.txt
 # This file is written out on a per-environment basis.
-# For each test in aaa_profiling, the corresponding function and
+# For each test in aaa_profiling, the corresponding function and 
 # environment is located within this file.  If it doesn't exist,
 # the test is skipped.
-# If a callcount does exist, it is compared to what we received.
+# If a callcount does exist, it is compared to what we received. 
 # assertions are raised if the counts do not match.
-#
-# To add a new callcount test, apply the function_call_count
-# decorator and re-run the tests using the --write-profiles
+# 
+# To add a new callcount test, apply the function_call_count 
+# decorator and re-run the tests using the --write-profiles 
 # option - this file will be rewritten including the new count.
-#
+# 
 
 # TEST: test.aaa_profiling.test_compiler.CompileTest.test_insert
 
@@ -237,102 +237,102 @@ test.aaa_profiling.test_misc.EnumTest.test_create_enum_from_pep_435_w_expensive_
 
 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation
 
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 47205
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 58405
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 47305
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 58505
 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 50805
 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 63005
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 50905
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 63005
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 51105
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 63205
 
 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation
 
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 46005
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 57205
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 46105
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 57305
 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 50105
 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 62305
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 49705
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 61805
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 49905
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 62005
 
 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations
 
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 45305
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 54005
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 45405
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 54105
 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 48505
 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 58205
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 48405
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 58005
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 48605
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 58205
 
 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations
 
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 44505
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 53205
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 44605
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 53305
 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 47705
 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 57405
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 47605
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 57205
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 47805
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 57405
 
 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle
 
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 43305
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 47005
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 43405
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 47105
 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 46005
 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 50705
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 45805
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 50405
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 46005
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 50605
 
 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations
 
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 45305
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 54005
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 45405
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 54105
 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 48505
 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 58205
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 48405
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 58005
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 48605
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 58205
 
 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations
 
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 44505
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 53205
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 44605
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 53305
 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 47705
 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 57405
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 47605
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 57205
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 47805
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 57405
 
 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations
 
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 29205
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 31805
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 29305
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 31905
 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 32305
 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 35305
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 32005
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 34905
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 32205
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 35105
 
 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations
 
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 28405
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 31005
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 28505
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 31105
 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 31505
 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 34505
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 31205
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 34105
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 31405
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 34305
 
 # TEST: test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set
 
-test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 3567
-test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 3567
+test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 3327
+test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 3327
 test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 3688
 test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 3688
-test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 3688
-test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 3688
+test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 3448
+test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 3448
 
 # TEST: test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove
 
-test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 5626
-test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 5626
+test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 5226
+test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 5226
 test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 5828
 test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 5828
-test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 5828
-test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 5828
+test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 5428
+test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 5428
 
 # TEST: test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_key_bound_branching
 
@@ -354,21 +354,21 @@ test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_unbound_branching
 
 # TEST: test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline
 
-test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 15199
-test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 26212
+test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 15200
+test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 26213
 test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 15115
 test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 27133
-test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 15229
-test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 27246
+test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 15231
+test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 27248
 
 # TEST: test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols
 
-test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 21341
-test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 26354
+test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 21342
+test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 26355
 test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 21371
 test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 27389
-test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 21378
-test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 27395
+test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 21380
+test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 27397
 
 # TEST: test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased
 
@@ -390,75 +390,75 @@ test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_plain x86_64_linux_cpy
 
 # TEST: test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d
 
-test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 95638
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 95438
 test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 95788
 test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 102054
 test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 102204
 test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 103239
-test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 103389
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 103189
 
 # TEST: test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased
 
-test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 93688
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 93488
 test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 93838
 test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 100404
 test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 100569
 test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 101589
-test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 101739
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 101539
 
 # TEST: test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query
 
-test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 472614
-test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 474456
+test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 472719
+test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 474566
 test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 505420
 test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 507262
-test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 504380
-test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 506222
+test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 504580
+test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 506422
 
 # TEST: test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results
 
-test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 408605
-test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 426205
+test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 400805
+test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 417205
 test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 395087
 test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 414201
-test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 415105
-test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 433605
+test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 405405
+test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 423905
 
 # TEST: test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity
 
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 19986
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 19986
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 20985
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 20985
 test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 20986
 test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 20986
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 20986
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 20986
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 21985
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 21985
 
 # 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 x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 90562
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 93130
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 91562
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 94090
 test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 84836
 test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 89106
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 94242
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 98273
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 95295
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 99326
 
 # 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 x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 20899
-test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 21353
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 20867
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 21321
 test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 21185
 test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 21784
-test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 21763
-test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 22331
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 21749
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 22317
 
 # TEST: test.aaa_profiling.test_orm.MergeTest.test_merge_load
 
-test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 1374
-test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 1408
+test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 1378
+test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 1412
 test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 1391
 test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 1438
-test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 1446
-test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 1491
+test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 1452
+test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 1497
 
 # TEST: test.aaa_profiling.test_orm.MergeTest.test_merge_no_load
 
@@ -471,30 +471,30 @@ test.aaa_profiling.test_orm.MergeTest.test_merge_no_load x86_64_linux_cpython_3.
 
 # TEST: test.aaa_profiling.test_orm.QueryTest.test_query_cols
 
-test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 5597
-test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 6357
+test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 5607
+test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 6367
 test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 5763
 test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 6563
-test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 5925
-test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 6715
+test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 5945
+test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 6735
 
 # TEST: test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results
 
-test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 244405
-test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 261205
+test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 247005
+test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 263605
 test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 246134
 test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 264752
-test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 255605
-test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 273705
+test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 258205
+test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 276505
 
 # TEST: test.aaa_profiling.test_orm.SessionTest.test_expire_lots
 
-test.aaa_profiling.test_orm.SessionTest.test_expire_lots x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 1169
-test.aaa_profiling.test_orm.SessionTest.test_expire_lots x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 1138
+test.aaa_profiling.test_orm.SessionTest.test_expire_lots x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_cextensions 1158
+test.aaa_profiling.test_orm.SessionTest.test_expire_lots x86_64_linux_cpython_2.7_sqlite_pysqlite_dbapiunicode_nocextensions 1133
 test.aaa_profiling.test_orm.SessionTest.test_expire_lots x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_cextensions 1253
 test.aaa_profiling.test_orm.SessionTest.test_expire_lots x86_64_linux_cpython_3.8_sqlite_pysqlite_dbapiunicode_nocextensions 1267
-test.aaa_profiling.test_orm.SessionTest.test_expire_lots x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 1255
-test.aaa_profiling.test_orm.SessionTest.test_expire_lots x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 1252
+test.aaa_profiling.test_orm.SessionTest.test_expire_lots x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_cextensions 1283
+test.aaa_profiling.test_orm.SessionTest.test_expire_lots x86_64_linux_cpython_3.9_sqlite_pysqlite_dbapiunicode_nocextensions 1247
 
 # TEST: test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect