1.4.0b2
Released: February 3, 2021
general
- [general] [bug] Fixed a SQLite source file that had non-ascii characters inside of its
docstring without a source encoding, introduced within the "INSERT..ON
CONFLICT" feature, which would cause failures under Python 2.
platform
-
[platform] [performance] Adjusted some elements related to internal class production at import time
which added significant latency to the time spent to import the library vs.
that of 1.3. The time is now about 20-30% slower than 1.3 instead of
200%.References: #5681
orm
-
[orm] [usecase] Added
_orm.ORMExecuteState.bind_mapper
and
_orm.ORMExecuteState.all_mappers
accessors to
_orm.ORMExecuteState
event object, so that handlers can respond to
the target mapper and/or mapped class or classes involved in an ORM
statement execution. -
[orm] [usecase] [asyncio] Added
_asyncio.AsyncSession.scalar()
,
_asyncio.AsyncSession.get()
as well as support for
_orm.sessionmaker.begin()
to work as an async context manager with
_asyncio.AsyncSession
. Also added
_asyncio.AsyncSession.in_transaction()
accessor. -
[orm] [changed] Mapper "configuration", which occurs within the
_orm.configure_mappers()
function, is now organized to be on a
per-registry basis. This allows for example the mappers within a certain
declarative base to be configured, but not those of another base that is
also present in memory. The goal is to provide a means of reducing
application startup time by only running the "configure" process for sets
of mappers that are needed. This also adds the
_orm.registry.configure()
method that will run configure for the
mappers local in a particular registry only.References: #5897
-
[orm] [bug] Added a comprehensive check and an informative error message for the case
where a mapped class, or a string mapped class name, is passed to
_orm.relationship.secondary
. This is an extremely common error
which warrants a clear message.Additionally, added a new rule to the class registry resolution such that
with regards to the_orm.relationship.secondary
parameter, if a
mapped class and its table are of the identical string name, the
Table
will be favored when resolving this parameter. In all
other cases, the class continues to be favored if a class and table
share the identical name.This change is also backported to: 1.3.21
References: #5774
-
[orm] [bug] Fixed bug involving the
restore_load_context
option of ORM events such
as_ormevent.InstanceEvents.load()
such that the flag would not be
carried along to subclasses which were mapped after the event handler were
first established.This change is also backported to: 1.3.21
References: #5737
-
[orm] [bug] [regression] Fixed issue in new
_orm.Session
similar to that of the
_engine.Connection
where the new "autobegin" logic could be
tripped into a re-entrant (recursive) state if SQL were executed within the
SessionEvents.after_transaction_create()
event hook.References: #5845
-
[orm] [bug] [unitofwork] Improved the unit of work topological sorting system such that the
toplogical sort is now deterministic based on the sorting of the input set,
which itself is now sorted at the level of mappers, so that the same inputs
of affected mappers should produce the same output every time, among
mappers / tables that don't have any dependency on each other. This further
reduces the chance of deadlocks as can be observed in a flush that UPDATEs
among multiple, unrelated tables such that row locks are generated.References: #5735
-
[orm] [bug] Fixed regression where the
Bundle.single_entity
flag would
take effect for aBundle
even though it were not set.
Additionally, this flag is legacy as it only makes sense for the
_orm.Query
object and not 2.0 style execution. a deprecation
warning is emitted when used with new-style execution.References: #5702
-
[orm] [bug] Fixed regression where creating an
_orm.aliased
construct against
a plain selectable and including a name would raise an assertionerror.References: #5750
-
[orm] [bug] Related to the fixes for the lambda criteria system within Core, within the
ORM implemented a variety of fixes for the
_orm.with_loader_criteria()
feature as well as the
_orm.SessionEvents.do_orm_execute()
event handler that is often
used in conjunction [ticket:5760]:- fixed issue where `_orm.with_loader_criteria()` function would fail if the given entity or base included non-mapped mixins in its descending class hierarchy [ticket:5766] - The `_orm.with_loader_criteria()` feature is now unconditionally disabled for the case of ORM "refresh" operations, including loads of deferred or expired column attributes as well as for explicit operations like `_orm.Session.refresh()`. These loads are necessarily based on primary key identity where addiional WHERE criteria is never appropriate. [ticket:5762] - Added new attribute `_orm.ORMExecuteState.is_column_load` to indicate that a `_orm.SessionEvents.do_orm_execute()` handler that a particular operation is a primary-key-directed column attribute load, where additional criteria should not be added. The `_orm.with_loader_criteria()` function as above ignores these in any case now. [ticket:5761] - Fixed issue where the `_orm.ORMExecuteState.is_relationship_load` attribute would not be set correctly for many lazy loads as well as all selectinloads. The flag is essential in order to test if options should be added to statements or if they would already have been propagated via relationship loads. [ticket:5764]
-
[orm] [bug] Fixed 1.4 regression where the use of
_orm.Query.having()
in
conjunction with queries with internally adapted SQL elements (common in
inheritance scenarios) would fail due to an incorrect function call. Pull
request courtesy esoh.References: #5781
-
[orm] [bug] Fixed an issue where the API to create a custom executable SQL construct
using thesqlalchemy.ext.compiles
extension according to the
documentation that's been up for many years would no longer function if
onlyExecutable, ClauseElement
were used as the base classes,
additional classes were needed if wanting to use
_orm.Session.execute()
. This has been resolved so that those extra
classes aren't needed. -
[orm] [bug] [regression] Fixed ORM unit of work regression where an errant "assert primary_key"
statement interferes with primary key generation sequences that don't
actually consider the columns in the table to use a real primary key
constraint, instead using_orm.mapper.primary_key
to establish
certain columns as "primary".References: #5867
orm declarative
-
[orm] [declarative] [feature] Added an alternate resolution scheme to Declarative that will extract the
SQLAlchemy column or mapped property from the "metadata" dictionary of a
dataclasses.Field object. This allows full declarative mappings to be
combined with dataclass fields.References: #5745
engine
-
[engine] [feature] Dialect-specific constructs such as
_postgresql.Insert.on_conflict_do_update()
can now stringify in-place
without the need to specify an explicit dialect object. The constructs,
when called upon forstr()
,print()
, etc. now have internal
direction to call upon their appropriate dialect rather than the
"default"dialect which doesn't know how to stringify these. The approach
is also adapted to generic schema-level create/drop such as
_schema.AddConstraint
, which will adapt its stringify dialect to
one indicated by the element within it, such as the
_postgresql.ExcludeConstraint
object. -
[engine] [feature] Added new execution option
_engine.Connection.execution_options.logging_token
. This option
will add an additional per-message token to log messages generated by the
_engine.Connection
as it executes statements. This token is not
part of the logger name itself (that part can be affected using the
existing_sa.create_engine.logging_name
parameter), so is
appropriate for ad-hoc connection use without the side effect of creating
many new loggers. The option can be set at the level of
_engine.Connection
or_engine.Engine
.References: #5911
-
[engine] [bug] [sqlite] Fixed bug in the 2.0 "future" version of
Engine
where emitting
SQL during theEngineEvents.begin()
event hook would cause a
re-entrant (recursive) condition due to autobegin, affecting among other
things the recipe documented for SQLite to allow for savepoints and
serializable isolation support.References: #5845
-
[engine] [bug] [oracle] [postgresql] Adjusted the "setinputsizes" logic relied upon by the cx_Oracle, asyncpg
and pg8000 dialects to support aTypeDecorator
that includes
an override theTypeDecorator.get_dbapi_type()
method. -
[engine] [bug] Added the "future" keyword to the list of words that are known by the
_sa.engine_from_config()
function, so that the values "true" and
"false" may be configured as "boolean" values when using a key such
assqlalchemy.future = true
orsqlalchemy.future = false
.
sql
-
[sql] [feature] Implemented support for "table valued functions" along with additional
syntaxes supported by PostgreSQL, one of the most commonly requested
features. Table valued functions are SQL functions that return lists of
values or rows, and are prevalent in PostgreSQL in the area of JSON
functions, where the "table value" is commonly referred towards as the
"record" datatype. Table valued functions are also supported by Oracle and
SQL Server.Features added include:
- the `_functions.FunctionElement.table_valued()` modifier that creates a table-like selectable object from a SQL function - A `_sql.TableValuedAlias` construct that renders a SQL function as a named table - Support for PostgreSQL's special "derived column" syntax that includes column names and sometimes datatypes, such as for the `json_to_recordset` function, using the `_sql.TableValuedAlias.render_derived()` method. - Support for PostgreSQL's "WITH ORDINALITY" construct using the `_functions.FunctionElement.table_valued.with_ordinality` parameter - Support for selection FROM a SQL function as column-valued scalar, a syntax supported by PostgreSQL and Oracle, via the `_functions.FunctionElement.column_valued()` method - A way to SELECT a single column from a table-valued expression without using a FROM clause via the `_functions.FunctionElement.scalar_table_valued()` method.
References: #3566
-
[sql] [usecase] Multiple calls to "returning", e.g.
_sql.Insert.returning()
,
may now be chained to add new columns to the RETURNING clause.References: #5695
-
[sql] [usecase] Added
_sql.Select.outerjoin_from()
method to complement
_sql.Select.join_from()
. -
[sql] [usecase] Adjusted the "literal_binds" feature of
_sql.Compiler
to render
NULL for a bound parameter that hasNone
as the value, either
explicitly passed or omitted. The previous error message "bind parameter
without a renderable value" is removed, and a missing orNone
value
will now render NULL in all cases. Previously, rendering of NULL was
starting to happen for DML statements due to internal refactorings, but was
not explicitly part of test coverage, which it now is.While no error is raised, when the context is within that of a column
comparison, and the operator is not "IS"/"IS NOT", a warning is emitted
that this is not generally useful from a SQL perspective.References: #5888
-
[sql] [bug] Fixed issue in new
_sql.Select.join()
method where chaining from the
current JOIN wasn't looking at the right state, causing an expression like
"FROM a JOIN b , b JOIN c " rather than
"FROM a JOIN b JOIN c ".References: #5858
-
[sql] [bug] Deprecation warnings are emitted under "SQLALCHEMY_WARN_20" mode when
passing a plain string to_orm.Session.execute()
.References: #5754
-
[sql] [bug] [orm] A wide variety of fixes to the "lambda SQL" feature introduced at
engine_lambda_caching
have been implemented based on user feedback,
with an emphasis on its use within the_orm.with_loader_criteria()
feature where it is most prominently used [ticket:5760]:- fixed issue where boolean True/False values referred towards in the closure variables of the lambda would cause failures [ticket:5763] - Repaired a non-working detection for Python functions embedded in the lambda that produce bound values; this case is likely not supportable so raises an informative error, where the function should be invoked outside the lambda itself. New documentation has been added to further detail this behavior. [ticket:5770] - The lambda system by default now rejects the use of non-SQL elements within the closure variables of the lambda entirely, where the error suggests the two options of either explicitly ignoring closure variables that are not SQL parameters, or specifying a specific set of values to be considered as part of the cache key based on hash value. This critically prevents the lambda system from assuming that arbitrary objects within the lambda's closure are appropriate for caching while also refusing to ignore them by default, preventing the case where their state might not be constant and have an impact on the SQL construct produced. The error message is comprehensive and new documentation has been added to further detail this behavior. [ticket:5765] - Fixed support for the edge case where an `in_()` expression against a list of SQL elements, such as `_sql.literal()` objects, would fail to be accommodated correctly. [ticket:5768]
-
[sql] [bug] [mysql] [postgresql] [sqlite] An informative error message is now raised for a selected set of DML
methods (currently all part of_dml.Insert
constructs) if they are
called a second time, which would implicitly cancel out the previous
setting. The methods altered include:
_sqlite.Insert.on_conflict_do_update
,
_sqlite.Insert.on_conflict_do_nothing
(SQLite),
_postgresql.Insert.on_conflict_do_update
,
_postgresql.Insert.on_conflict_do_nothing
(PostgreSQL),
_mysql.Insert.on_duplicate_key_update
(MySQL)References: #5169
-
[sql] [bug] Fixed issue in new
_sql.Values
construct where passing tuples of
objects would fall back to per-value type detection rather than making use
of the_schema.Column
objects passed directly to
_sql.Values
that tells SQLAlchemy what the expected type is. This
would lead to issues for objects such as enumerations and numpy strings
that are not actually necessary since the expected type is given.References: #5785
-
[sql] [bug] Fixed issue where a
RemovedIn20Warning
would erroneously emit
when the.bind
attribute were accessed internally on objects,
particularly when stringifying a SQL construct.References: #5717
-
[sql] [bug] Properly render
cycle=False
andorder=False
asNO CYCLE
and
NO ORDER
in_sql.Sequence
and_sql.Identity
objects.References: #5722
-
[sql] Replace
_orm.Query.with_labels()
and
_sql.GenerativeSelect.apply_labels()
with explicit getters and
setters_sql.GenerativeSelect.get_label_style()
and
_sql.GenerativeSelect.set_label_style()
to accommodate the three
supported label styles: :data:_sql.LABEL_STYLE_DISAMBIGUATE_ONLY
,
:data:_sql.LABEL_STYLE_TABLENAME_PLUS_COL
, and
:data:_sql.LABEL_STYLE_NONE
.Unknown interpreted text role "data".
Unknown interpreted text role "data".
Unknown interpreted text role "data".
In addition, for Core and "future style" ORM queries,
LABEL_STYLE_DISAMBIGUATE_ONLY
is now the default label style. This
style differs from the existing "no labels" style in that labeling is
applied in the case of column name conflicts; withLABEL_STYLE_NONE
, a
duplicate column name is not accessible via name in any case.For cases where labeling is significant, namely that the
.c
collection
of a subquery is able to refer to all columns unambiguously, the behavior
ofLABEL_STYLE_DISAMBIGUATE_ONLY
is now sufficient for all
SQLAlchemy features across Core and ORM which involve this behavior.
Result set rows since SQLAlchemy 1.0 are usually aligned with column
constructs positionally.For legacy ORM queries using
_query.Query
, the table-plus-column
names labeling style applied byLABEL_STYLE_TABLENAME_PLUS_COL
continues to be used so that existing test suites and logging facilities
see no change in behavior by default.References: #4757
schema
-
[schema] [feature] Added
_types.TypeEngine.as_generic()
to map dialect-specific types,
such assqlalchemy.dialects.mysql.INTEGER
, with the "best match"
generic SQLAlchemy type, in this case_types.Integer
. Pull
request courtesy Andrew Hannigan.References: #5659
-
[schema] [usecase] The
_events.DDLEvents.column_reflect()
event may now be applied to a
_schema.MetaData
object where it will take effect for the
_schema.Table
objects local to that collection.References: #5712
-
[schema] [usecase] Added parameters
_ddl.CreateTable.if_not_exists
,
_ddl.CreateIndex.if_not_exists
,
_ddl.DropTable.if_exists
and
_ddl.DropIndex.if_exists
to the_ddl.CreateTable
,
_ddl.DropTable
,_ddl.CreateIndex
and
_ddl.DropIndex
constructs which result in "IF NOT EXISTS" / "IF
EXISTS" DDL being added to the CREATE/DROP. These phrases are not accepted
by all databases and the operation will fail on a database that does not
support it as there is no similarly compatible fallback within the scope of
a single DDL statement. Pull request courtesy Ramon Williams.References: #2843
-
[schema] [changed] Altered the behavior of the
_schema.Identity
construct such that
when applied to a_schema.Column
, it will automatically imply that
the value of_sql.Column.nullable
should default toFalse
,
in a similar manner as when the_sql.Column.primary_key
parameter is set toTrue
. This matches the default behavior of all
supporting databases whereIDENTITY
impliesNOT NULL
. The
PostgreSQL backend is the only one that supports addingNULL
to an
IDENTITY
column, which is here supported by passing aTrue
value
for the_sql.Column.nullable
parameter at the same time.References: #5775
asyncio
-
[asyncio] [usecase] The
AsyncEngine
,AsyncConnection
and
AsyncTransaction
objects may be compared using Python==
or
!=
, which will compare the two given objects based on the "sync" object
they are proxying towards. This is useful as there are cases particularly
forAsyncTransaction
where multiple instances of
AsyncTransaction
can be proxying towards the same sync
_engine.Transaction
, and are actually equivalent. The
AsyncConnection.get_transaction()
method will currently return a new
proxyingAsyncTransaction
each time as the
AsyncTransaction
is not otherwise statefully associated with its
originatingAsyncConnection
. -
[asyncio] [bug] Adjusted the greenlet integration, which provides support for Python asyncio
in SQLAlchemy, to accommodate for the handling of Pythoncontextvars
(introduced in Python 3.7) forgreenlet
versions greater than 0.4.17.
Greenlet version 0.4.17 added automatic handling of contextvars in a
backwards-incompatible way; we've coordinated with the greenlet authors to
add a preferred API for this in versions subsequent to 0.4.17 which is now
supported by SQLAlchemy's greenlet integration. For greenlet versions prior
to 0.4.17 no behavioral change is needed, version 0.4.17 itself is blocked
from the dependencies.References: #5615
-
[asyncio] [bug] Implemented "connection-binding" for
AsyncSession
, the ability to
pass anAsyncConnection
to create anAsyncSession
.
Previously, this use case was not implemented and would use the associated
engine when the connection were passed. This fixes the issue where the
"join a session to an external transaction" use case would not work
correctly for theAsyncSession
. Additionally, added methods
AsyncConnection.in_transaction()
,
AsyncConnection.in_nested_transaction()
,
AsyncConnection.get_transaction()
,
AsyncConnection.get_nested_transaction()
and
AsyncConnection.info
attribute.References: #5811
-
[asyncio] [bug] Fixed bug in asyncio connection pool where
asyncio.TimeoutError
would
be raised rather thanexc.TimeoutError
. Also repaired the
_sa.create_engine.pool_timeout
parameter set to zero when using
the async engine, which previously would ignore the timeout and block
rather than timing out immediately as is the behavior with regular
QueuePool
.References: #5827
-
[asyncio] [bug] [pool] When using an asyncio engine, the connection pool will now detach and
discard a pooled connection that is was not explicitly closed/returned to
the pool when its tracking object is garbage collected, emitting a warning
that the connection was not properly closed. As this operation occurs
during Python gc finalizers, it's not safe to run any IO operations upon
the connection including transaction rollback or connection close as this
will often be outside of the event loop.The
AsyncAdaptedQueue
used by default on async dpapis
should instantiate a queue only when it's first used
to avoid binding it to a possibly wrong event loop.References: #5823
-
[asyncio] The SQLAlchemy async mode now detects and raises an informative
error when an non asyncio compatible :term:DBAPI
is used.
Using a standardDBAPI
with async SQLAlchemy will cause
it to block like any sync call, interrupting the executing asyncio
loop.Unknown interpreted text role "term".
postgresql
-
[postgresql] [usecase] Added new parameter
_postgresql.ExcludeConstraint.ops
to the
_postgresql.ExcludeConstraint
object, to support operator class
specification with this constraint. Pull request courtesy Alon Menczer.This change is also backported to: 1.3.21
References: #5604
-
[postgresql] [usecase] Added a read/write
.autocommit
attribute to the DBAPI-adaptation layer
for the asyncpg dialect. This so that when working with DBAPI-specific
schemes that need to use "autocommit" directly with the DBAPI connection,
the same.autocommit
attribute which works with both psycopg2 as well
as pg8000 is available. -
[postgresql] [changed] Fixed issue where the psycopg2 dialect would silently pass the
use_native_unicode=False
flag without actually having any effect under
Python 3, as the psycopg2 DBAPI uses Unicode unconditionally under Python
3. This usage now raises an_exc.ArgumentError
when used under
Python 3. Added test support for Python 2. -
[postgresql] [performance] Enhanced the performance of the asyncpg dialect by caching the asyncpg
PreparedStatement objects on a per-connection basis. For a test case that
makes use of the same statement on a set of pooled connections this appears
to grant a 10-20% speed improvement. The cache size is adjustable and may
also be disabled. -
[postgresql] [bug] [mysql] Fixed regression introduced in 1.3.2 for the PostgreSQL dialect, also
copied out to the MySQL dialect's feature in 1.3.18, where usage of a non
_schema.Table
construct such as_sql.text()
as the argument
to_sql.Select.with_for_update.of
would fail to be accommodated
correctly within the PostgreSQL or MySQL compilers.This change is also backported to: 1.3.21
References: #5729
-
[postgresql] [bug] Fixed a small regression where the query for "show
standard_conforming_strings" upon initialization would be emitted even if
the server version info were detected as less than version 8.2, previously
it would only occur for server version 8.2 or greater. The query fails on
Amazon Redshift which reports a PG server version older than this value.References: #5698
-
[postgresql] [bug] Established support for
_schema.Column
objects as well as ORM
instrumented attributes as keys in theset_
dictionary passed to the
_postgresql.Insert.on_conflict_do_update()
and
_sqlite.Insert.on_conflict_do_update()
methods, which match to the
_schema.Column
objects in the.c
collection of the target
_schema.Table
. Previously, only string column names were
expected; a column expression would be assumed to be an out-of-table
expression that would render fully along with a warning.References: #5722
-
[postgresql] [bug] [asyncio] Fixed bug in asyncpg dialect where a failure during a "commit" or less
likely a "rollback" should cancel the entire transaction; it's no longer
possible to emit rollback. Previously the connection would continue to
await a rollback that could not succeed as asyncpg would reject it.References: #5824
mysql
-
[mysql] [feature] Added support for the aiomysql driver when using the asyncio SQLAlchemy
extension.References: #5747
-
[mysql] [bug] [reflection] Fixed issue where reflecting a server default on MariaDB only that
contained a decimal point in the value would fail to be reflected
correctly, leading towards a reflected table that lacked any server
default.This change is also backported to: 1.3.21
References: #5744
sqlite
-
[sqlite] [usecase] Implemented INSERT... ON CONFLICT clause for SQLite. Pull request courtesy
Ramon Williams.References: #4010
-
[sqlite] [bug] Use python
re.search()
instead ofre.match()
as the operation
used by theColumn.regexp_match()
method when using sqlite.
This matches the behavior of regular expressions on other databases
as well as that of well-known SQLite plugins.References: #5699
mssql
-
[mssql] [bug] [datatypes] [mysql] Decimal accuracy and behavior has been improved when extracting floating
point and/or decimal values from JSON strings using the
_sql.sqltypes.JSON.Comparator.as_float()
method, when the numeric
value inside of the JSON string has many significant digits; previously,
MySQL backends would truncate values with many significant digits and SQL
Server backends would raise an exception due to a DECIMAL cast with
insufficient significant digits. Both backends now use a FLOAT-compatible
approach that does not hardcode significant digits for floating point
values. For precision numerics, a new method
_sql.sqltypes.JSON.Comparator.as_numeric()
has been added which
accepts arguments for precision and scale, and will return values as Python
Decimal
objects with no floating point conversion assuming the DBAPI
supports it (all but pysqlite).References: #5788
oracle
-
[oracle] [bug] Fixed regression which occured due to #5755 which implemented
isolation level support for Oracle. It has been reported that many Oracle
accounts don't actually have permission to query thev$transaction
view so this feature has been altered to gracefully fallback when it fails
upon database connect, where the dialect will assume "READ COMMITTED" is
the default isolation level as was the case prior to SQLAlchemy 1.3.21.
However, explicit use of the_engine.Connection.get_isolation_level()
method must now necessarily raise an exception, as Oracle databases with
this restriction explicitly disallow the user from reading the current
isolation level.This change is also backported to: 1.3.22
References: #5784
-
[oracle] [bug] Oracle two-phase transactions at a rudimentary level are now no longer
deprecated. After receiving support from cx_Oracle devs we can provide for
basic xid + begin/prepare support with some limitations, which will work
more fully in an upcoming release of cx_Oracle. Two phase "recovery" is not
currently supported.References: #5884
-
[oracle] [bug] The Oracle dialect now uses
select sys_context( 'userenv', 'current_schema' ) from dual
to get
the default schema name, rather thanSELECT USER FROM DUAL
, to
accommodate for changes to the session-local schema name under Oracle.References: #5716
misc
-
[usecase] [pool] [tests] Improve documentation and add test for sub-second pool timeouts.
Pull request courtesy Jordan Pittier.References: #5582
-
[usecase] [pool] The internal mechanics of the engine connection routine has been altered
such that it's now guaranteed that a user-defined event handler for the
_pool.PoolEvents.connect()
handler, when established using
insert=True
, will allow an event handler to run that is definitely
invoked before any dialect-specific initialization starts up, most
notably when it does things like detect default schema name.
Previously, this would occur in most cases but not unconditionally.
A new example is added to the schema documentation illustrating how to
establish the "default schema name" within an on-connect event. -
[bug] [reflection] Fixed bug where the now-deprecated
autoload
parameter was being called
internally within the reflection routines when a related table were
reflected.References: #5684
-
[bug] [pool] Fixed regression where a connection pool event specified with a keyword,
most notablyinsert=True
, would be lost when the event were set up.
This would prevent startup events that need to fire before dialect-level
events from working correctly.References: #5708
-
[bug] [pool] [pypy] Fixed issue where connection pool would not return connections to the pool
or otherwise be finalized upon garbage collection under pypy if the checked
out connection fell out of scope without being closed. This is a long
standing issue due to pypy's difference in GC behavior that does not call
weakref finalizers if they are relative to another object that is also
being garbage collected. A strong reference to the related record is now
maintained so that the weakref has a strong-referenced "base" to trigger
off of.References: #5842