SQLAlchemy version 0.7.2 is now available.
A lot has been going on leading up to this release, and there was actually a
bunch more I've wanted to do; but as we went about six weeks since the last
release we've accumulated at least twenty five bug fixes, and it's time for
them to go out. Work continues towards the next release.
This release features a relatively big change to the mechanics of joined and subquery
eager loading, which is that when invoked from a Query (as opposed to from a lazy load),
the eager loader will traverse the graph of objects fully regardless of collections and
attributes that are already loaded, populating any expired or not-yet-loaded attributes
all the way down the hierarchy. Previously it tried to save time by not descending into
already loaded subtrees. This is to better support the use case of using eager loading
in order to fully populate a tree, such that it can be detached and sent to a cache in a
fully loaded state. It is also behaviorally closer to the spirit of "I asked for X,
I should get X", i.e. if you say subqueryload(), you'll get your subquery no matter
what.
Other than that there were a *lot* of ORM fixes, most of which have been also applied to the
0.6 branch and will be in 0.6.9. Also some additional 0.6->0.7 regressions fixed, and
some fixes to the new "Mutable" extension including one which was kind of a show
stopper.
Download SQLAlchemy 0.7.2 at:
http://www.sqlalchemy.org/download.html
Changelog follows.
0.7.2
=====
- orm
- Feature enhancement: joined and subquery
loading will now traverse already-present related
objects and collections in search of unpopulated
attributes throughout the scope of the eager load
being defined, so that the eager loading that is
specified via mappings or query options
unconditionally takes place for the full depth,
populating whatever is not already populated.
Previously, this traversal would stop if a related
object or collection were already present leading
to inconsistent behavior (though would save on
loads/cycles for an already-loaded graph). For a
subqueryload, this means that the additional
SELECT statements emitted by subqueryload will
invoke unconditionally, no matter how much of the
existing graph is already present (hence the
controversy). The previous behavior of "stopping"
is still in effect when a query is the result of
an attribute-initiated lazyload, as otherwise an
"N+1" style of collection iteration can become
needlessly expensive when the same related object
is encountered repeatedly. There's also an
as-yet-not-public generative Query method
_with_invoke_all_eagers()
which selects old/new behavior [ticket:2213]
- A rework of "replacement traversal" within
the ORM as it alters selectables to be against
aliases of things (i.e. clause adaption) includes
a fix for multiply-nested any()/has() constructs
against a joined table structure. [ticket:2195]
- Fixed bug where query.join() + aliased=True
from a joined-inh structure to itself on
relationship() with join condition on the child
table would convert the lead entity into the
joined one inappropriately. [ticket:2234]
Also in 0.6.9.
- Fixed regression from 0.6 where Session.add()
against an object which contained None in a
collection would raise an internal exception.
Reverted this to 0.6's behavior which is to
accept the None but obviously nothing is
persisted. Ideally, collections with None
present or on append() should at least emit a
warning, which is being considered for 0.8.
[ticket:2205]
- Load of a deferred() attribute on an object
where row can't be located raises
ObjectDeletedError instead of failing later
on; improved the message in ObjectDeletedError
to include other conditions besides a simple
"delete". [ticket:2191]
- Fixed regression from 0.6 where a get history
operation on some relationship() based attributes
would fail when a lazyload would emit; this could
trigger within a flush() under certain conditions.
[ticket:2224] Thanks to the user who submitted
the great test for this.
- Fixed bug apparent only in Python 3 whereby
sorting of persistent + pending objects during
flush would produce an illegal comparison,
if the persistent object primary key
is not a single integer. [ticket:2228]
Also in 0.6.9
- Fixed bug whereby the source clause
used by query.join() would be inconsistent
if against a column expression that combined
multiple entities together. [ticket:2197]
Also in 0.6.9
- Fixed bug whereby if a mapped class
redefined __hash__() or __eq__() to something
non-standard, which is a supported use case
as SQLA should never consult these,
the methods would be consulted if the class
was part of a "composite" (i.e. non-single-entity)
result set. [ticket:2215]
Also in 0.6.9.
- Added public attribute ".validators" to
Mapper, an immutable dictionary view of
all attributes that have been decorated
with the @validates decorator.
[ticket:2240] courtesy Stefano Fontanelli
- Fixed subtle bug that caused SQL to blow
up if: column_property() against subquery +
joinedload + LIMIT + order by the column
property() occurred. [ticket:2188].
Also in 0.6.9
- The join condition produced by with_parent
as well as when using a "dynamic" relationship
against a parent will generate unique
bindparams, rather than incorrectly repeating
the same bindparam. [ticket:2207].
Also in 0.6.9.
- Added the same "columns-only" check to
mapper.polymorphic_on as used when
receiving user arguments to
relationship.order_by, foreign_keys,
remote_side, etc.
- Fixed bug whereby comparison of column
expression to a Query() would not call
as_scalar() on the underlying SELECT
statement to produce a scalar subquery,
in the way that occurs if you called
it on Query().subquery(). [ticket:2190]
- Fixed declarative bug where a class inheriting
from a superclass of the same name would fail
due to an unnecessary lookup of the name
in the _decl_class_registry. [ticket:2194]
- Repaired the "no statement condition"
assertion in Query which would attempt
to raise if a generative method were called
after from_statement() were called.
[ticket:2199]. Also in 0.6.9.
- sql
- Fixed two subtle bugs involving column
correspondence in a selectable,
one with the same labeled subquery repeated, the other
when the label has been "grouped" and
loses itself. Affects [ticket:2188].
- schema
- New feature: with_variant() method on
all types. Produces an instance of Variant(),
a special TypeDecorator which will select
the usage of a different type based on the
dialect in use. [ticket:2187]
- Added an informative error message when
ForeignKeyConstraint refers to a column name in
the parent that is not found. Also in 0.6.9.
- Fixed bug whereby adaptation of old append_ddl_listener()
function was passing unexpected **kw through
to the Table event. Table gets no kws, the MetaData
event in 0.6 would get "tables=somecollection",
this behavior is preserved. [ticket:2206]
- Fixed bug where "autoincrement" detection on
Table would fail if the type had no "affinity"
value, in particular this would occur when using
the UUID example on the site that uses TypeEngine
as the "impl".
- Added an improved repr() to TypeEngine objects
that will only display constructor args which
are positional or kwargs that deviate
from the default. [ticket:2209]
- engine
- Context manager provided by Connection.begin()
will issue rollback() if the commit() fails,
not just if an exception occurs.
- Use urllib.parse_qsl() in Python 2.6 and above,
no deprecation warning about cgi.parse_qsl()
[ticket:1682]
- Added mixin class sqlalchemy.ext.DontWrapMixin.
User-defined exceptions of this type are never
wrapped in StatementException when they
occur in the context of a statement
execution.
- StatementException wrapping will display the
original exception class in the message.
- Failures on connect which raise dbapi.Error
will forward the error to dialect.is_disconnect()
and set the "connection_invalidated" flag if
the dialect knows this to be a potentially
"retryable" condition. Only Oracle ORA-01033
implemented for now. [ticket:2201]
- sqlite
- SQLite dialect no longer strips quotes
off of reflected default value, allowing
a round trip CREATE TABLE to work.
This is consistent with other dialects
that also maintain the exact form of
the default. [ticket:2189]
- postgresql
- Added new "postgresql_ops" argument to
Index, allows specification of PostgreSQL
operator classes for indexed columns.
[ticket:2198] Courtesy Filip Zyzniewski.
- mysql
- Fixed OurSQL dialect to use ansi-neutral
quote symbol "'" for XA commands instead
of '"'. [ticket:2186]. Also in 0.6.9.
- mssql
- Adjusted the pyodbc dialect such that bound
values are passed as bytes and not unicode
if the "Easysoft" unix drivers are detected.
This is the same behavior as occurs with
FreeTDS. Easysoft appears to segfault
if Python unicodes are passed under
certain circumstances.
- oracle
- Added ORA-00028 to disconnect codes, use
cx_oracle _Error.code to get at the code,
[ticket:2200]. Also in 0.6.9.
- Added ORA-01033 to disconnect codes, which
can be caught during a connection
event. [ticket:2201]
- repaired the oracle.RAW type which did not
generate the correct DDL. [ticket:2220]
Also in 0.6.9.
- added CURRENT to reserved word list.
[ticket:2212] Also in 0.6.9.
-ext
- Fixed bug in the mutable extension whereby
if the same type were used twice in one
mapping, the attributes beyond the first
would not get instrumented.
- Fixed bug in the mutable extension whereby
if None or a non-corresponding type were set,
an error would be raised. None is now accepted
which assigns None to all attributes,
illegal values raise ValueError.
- examples
- Repaired the examples/versioning test runner
to not rely upon SQLAlchemy test libs,
nosetests must be run from within
examples/versioning to get around setup.cfg
breaking it.
- Tweak to examples/versioning to pick the
correct foreign key in a multi-level
inheritance situation.
- Fixed the attribute shard example to check
for bind param callable correctly in 0.7
style.
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en.