Release: 1.4.0b1 pre release | Release Date: unreleased

SQLAlchemy 1.4 Documentation

1.4 Changelog

1.4.0b1

no release date

orm

  • [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). See the migration notes linked below for further details.

    References: #4617

engine

  • [engine] [feature]

    The Table.autoload_with parameter now accepts an Inspector object directly, as well as any Engine or Connection as was the case before.

    References: #4755

  • [engine] [changed]

    Deprecated remaining engine-level introspection and utility methods including Engine.run_callable(), Engine.transaction(), Engine.table_names(), Engine.has_table(). The utility methods are superseded by modern context-manager patterns, and the table introspection tasks are suited by the Inspector object.

    References: #4755

  • [engine] [changed]

    The internal dialect method Dialect.reflecttable has been removed. A review of third party dialects has not found any making use of this method, as it was already documented as one that should not be used by external dialects. Additionally, the private Engine._run_visitor method is also removed.

    References: #4755

  • [engine] [changed]

    The long-deprecated Inspector.get_table_names.order_by parameter has been removed.

    References: #4755

  • [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

  • [engine] [change]

    The select() construct and related constructs now allow for duplication of column labels and columns themselves in the columns clause, mirroring exactly how column expressions were passed in. This allows the tuples returned by an executed result to match what was SELECTed for in the first place, which is how the ORM Query works, so this establishes better cross-compatibility between the two constructs. Additionally, it allows column-positioning-sensitive structures such as UNIONs (i.e. CompoundSelect) to be more intuitively constructed in those cases where a particular column might appear in more than one place. To support this change, the ColumnCollection has been revised to support duplicate columns as well as to allow integer index access.

    References: #4753

sql

  • [sql] [usecase]

    The Index.create() and Index.drop() methods now have a parameter Index.create.checkfirst, in the same way as that of Table and Sequence, which when enabled will cause the operation to detect if the index exists (or not) before performing a create or drop operation.

    References: #527

  • [sql] [bug]

    Reworked the ClauseElement.compare() methods in terms of a new visitor-based approach, and additionally added test coverage ensuring that all ClauseElement subclasses can be accurately compared against each other in terms of structure. Structural comparison capability is used to a small degree within the ORM currently, however it also may form the basis for new caching features.

    References: #4336

  • [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] [bug]

    The ORDER BY clause of a CompoundSelect, e.g. UNION, EXCEPT, etc. will not render the table name associated with a given column when applying CompoundSelect.order_by() in terms of a Table - bound column. Most databases require that the names in the ORDER BY clause be expressed as label names only which are matched to names in the first SELECT statement. The change is related to #4617 in that a previous workaround was to refer to the .c attribute of the CompoundSelect in order to get at a column that has no table name. As the subquery is now named, this change allows both the workaround to continue to work, as well as allows table-bound columns as well as the CompoundSelect.selected_columns collections to be usable in the CompoundSelect.order_by() method.

    References: #4617

  • [sql] [reflection]

    The “NO ACTION” keyword for foreign key “ON UPDATE” is now considered to be the default cascade for a foreign key on all supporting backends (SQlite, MySQL, PostgreSQL) and when detected is not included in the reflection dictionary; this is already the behavior for PostgreSQL and MySQL for all previous SQLAlchemy versions in any case. The “RESTRICT” keyword is positively stored when detected; PostgreSQL does report on this keyword, and MySQL as of version 8.0 does as well. On earlier MySQL versions, it is not reported by the database.

    References: #4741

  • [sql] [change]

    The “threadlocal” execution strategy, deprecated in 1.3, has been removed for 1.4, as well as the concept of “engine strategies” and the Engine.contextual_connect method. The “strategy=’mock’” keyword argument is still accepted for now with a deprecation warning; use create_mock_engine() instead for this use case.

    See also

    “threadlocal” engine strategy deprecated - from the 1.3 migration notes which discusses the rationale for deprecation.

    References: #4632

  • [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]

    As part of the SQLAlchemy 2.0 migration project, a conceptual change has been made to the role of the SelectBase class hierarchy, which is the root of all “SELECT” statement constructs, in that they no longer serve directly as FROM clauses, that is, they no longer subclass FromClause. For end users, the change mostly means that any placement of a select() construct in the FROM clause of another select() requires first that it be wrapped in a subquery first, which historically is through the use of the SelectBase.alias() method, and is now also available through the use of SelectBase.subquery(). This was usually a requirement in any case since several databases don’t accept unnamed SELECT subqueries in their FROM clause in any case.

    References: #4617

  • [sql] [change]

    Added a new Core class Subquery, which takes the place of Alias when creating named subqueries against a SelectBase object. Subquery acts in the same way as Alias and is produced from the SelectBase.subquery() method; for ease of use and backwards compatibility, the SelectBase.alias() method is synonymous with this new method.

    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

  • [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