Release: 1.4.0b1 pre release | Release Date: unreleased

SQLAlchemy 1.4 Documentation

1.4 Changelog


no release date


  • [orm] [bug]

    The internal attribute symbols NO_VALUE and NEVER_SET have been unified, as there was no meaningful difference between these two symbols, other than a few codepaths where they were differentiated in subtle and undocumented ways, these have been fixed.

    References: #4696

  • [orm] [bug]

    Accessing a collection-oriented attribute on a newly created object no longer mutates __dict__, but still returns an empty collection as has always been the case. This allows collection-oriented attributes to work consistently in comparison to scalar attributes which return None, but also don’t mutate __dict__. In order to accommodate for the collection being mutated, the same empty collection is returned each time once initially created, and when it is mutated (e.g. an item appended, added, etc.) it is then moved into __dict__. This removes the last of mutating side-effects on read-only attribute access within the ORM.

    References: #4519

  • [orm] [change]

    The condition where a pending object being flushed with an identity that already exists in the identity map has been adjusted to emit a warning, rather than throw a FlushError. The rationale is so that the flush will proceed and raise a IntegrityError instead, in the same way as if the existing object were not present in the identity map already. This helps with schemes that are uinsg the IntegrityError as a means of catching whether or not a row already exists in the table.

    References: #4662

  • [orm] [change]

    The ORM will now warn when asked to coerce a select() construct into a subquery implicitly. This occurs within places such as the Query.select_entity_from() and Query.select_from() methods as well as within the with_polymorphic() function. When a SelectBase (which is what’s produced by select()) or Query object is passed directly to these functions and others, the ORM is typically coercing them to be a subquery by calling the SelectBase.alias() method automatically (which is now superceded by the SelectBase.subquery method).  The historical reason is that most databases other than SQLite don't allow a SELECT of a SELECT without the inner SELECT being a named subuqery in any case; going forward, SQLAlchemy Core is moving towards no longer considering a SELECT statement that isn't inside a subquery to be a "FROM" clause, that is, an object that can be selected from, in the first place, as part of a larger change to unify the interfaces for :func:().select` and Query(). The change is intended to encourage code to make explicit those places where these subqueries have normally been implicitly created.

    References: #4617


  • [engine] [bug]

    The Connection object will now not clear a rolled-back transaction until the outermost transaction is explicitly rolled back. This is essentially the same behavior that the ORM Session has had for a long time, where an explicit call to .rollback() on all enclosing transactions is required for the transaction to logically clear, even though the DBAPI-level transaction has already been rolled back. The new behavior helps with situations such as the “ORM rollback test suite” pattern where the test suite rolls the transaction back within the ORM scope, but the test harness which seeks to control the scope of the transaction externally does not expect a new transaction to start implicitly.

    References: #4712


  • [sql] [bug]

    Registered function names based on GenericFunction are now retrieved in a case-insensitive fashion in all cases, removing the deprecation logic from 1.3 which temporarily allowed multiple GenericFunction objects to exist with differing cases. A GenericFunction that replaces another on the same name whether or not it’s case sensitive emits a warning before replacing the object.

    References: #4569, #4649

  • [sql] [change]

    The SelectBase.as_scalar() and Query.as_scalar() methods have been renamed to SelectBase.scalar_subquery() and Query.scalar_subquery(), respectively. The old names continue to exist within 1.4 series with a deprecation warning. In addition, the implicit coercion of SelectBase, Alias, and other SELECT oriented objects into scalar subqueries when evaluated in a column context is also deprecated, and emits a warning that the SelectBase.scalar_subquery() method should be called explicitly. This warning will in a later major release become an error, however the message will always be clear when SelectBase.scalar_subquery() needs to be invoked. The latter part of the change is for clarity and to reduce the implicit decisionmaking by the query coercion system.

    This change is part of the larger change to convert select() objects to no longer be directly part of the “from clause” class hierarchy, which also includes an overhaul of the clause coercion system.

    References: #4617

  • [sql] [change]

    Added new method SelectBase.subquery(), which creates a subquery that is essentially the same thing as what calling FromClause.alias() has always done, e.g. creates a named subquery. This method is intended to roughly mirror the same role as that of Query.subquery(). The SelectBase.alias() method is being kept for the time being as essentially the same function as that of SelectBase.subquery().

    References: #4617

  • [sql] [change]

    The “clause coercion” system, which is SQLAlchemy Core’s system of receiving arguments and resolving them into ClauseElement structures in order to build up SQL expression objects, has been rewritten from a series of ad-hoc functions to a fully consistent class-based system. This change is internal and should have no impact on end users other than more specific error messages when the wrong kind of argument is passed to an expression object, however the change is part of a larger set of changes involving the role and behavior of select() objects.

    References: #4617


  • [oracle] [change]

    The LIMIT / OFFSET scheme used in Oracle now makes use of named subqueries rather than unnamed subqueries when it transparently rewrites a SELECT statement to one that uses a subquery that includes ROWNUM. The change is part of a larger change where unnamed subqueries are no longer directly supported by Core, as well as to modernize the internal use of the select() construct within the Oracle dialect.

Previous: What’s New in SQLAlchemy 1.4? Next: 1.3 Changelog