[sqlalchemy] SQLAlchemy 0.6.0 released

Skip to first unread message

Michael Bayer

Apr 18, 2010, 8:02:09 PM4/18/10
to sqlalchemy
The first official 0.6 release of SQLAlchemy is now available.

0.6 includes a newly rewritten unit of work implementation originally slated for 0.7, but then as it went so well we decided on 0.6.1, and then because it continued to perform terrifically within several punishing environments we decided to go with 0.6.0. I'm very excited to have 0.6.0 out with the clean UOW system, as the old one was pretty much the last vestige of an earlier era for SQLAlchemy. As we come up on our 5th birthday, SQLAlchemy has grown and matured to a dramatic degree, thanks in large part to the very generous and supportive community who have pushed us to produce an ever more awesome product.

I hope everyone enjoys this release and don't hesitate to report any bugs on the wiki. Thanks for sticking around.

Changes for 0.6 below are relative to 0.6beta3. For a full overview of what 0.6 is about, see the "What's New?" document at http://www.sqlalchemy.org/trac/wiki/06Migration .

Download SQLAlchemy 0.6.0 at:



- orm
- Unit of work internals have been rewritten. Units of work
with large numbers of objects interdependent objects
can now be flushed without recursion overflows
as there is no longer reliance upon recursive calls
[ticket:1081]. The number of internal structures now stays
constant for a particular session state, regardless of
how many relationships are present on mappings. The flow
of events now corresponds to a linear list of steps,
generated by the mappers and relationships based on actual
work to be done, filtered through a single topological sort
for correct ordering. Flush actions are assembled using
far fewer steps and less memory. [ticket:1742]

- Along with the UOW rewrite, this also removes an issue
introduced in 0.6beta3 regarding topological cycle detection
for units of work with long dependency cycles. We now use
an algorithm written by Guido (thanks Guido!).

- one-to-many relationships now maintain a list of positive
parent-child associations within the flush, preventing
previous parents marked as deleted from cascading a
delete or NULL foreign key set on those child objects,
despite the end-user not removing the child from the old
association. [ticket:1764]

- A collection lazy load will switch off default
eagerloading on the reverse many-to-one side, since
that loading is by definition unnecessary. [ticket:1495]

- Session.refresh() now does an equivalent expire()
on the given instance first, so that the "refresh-expire"
cascade is propagated. Previously, refresh() was
not affected in any way by the presence of "refresh-expire"
cascade. This is a change in behavior versus that
of 0.6beta2, where the "lockmode" flag passed to refresh()
would cause a version check to occur. Since the instance
is first expired, refresh() always upgrades the object
to the most recent version.

- The 'refresh-expire' cascade, when reaching a pending object,
will expunge the object if the cascade also includes
"delete-orphan", or will simply detach it otherwise.

- id(obj) is no longer used internally within topological.py,
as the sorting functions now require hashable objects
only. [ticket:1756]

- The ORM will set the docstring of all generated descriptors
to None by default. This can be overridden using 'doc'
(or if using Sphinx, attribute docstrings work too).

- Added kw argument 'doc' to all mapper property callables
as well as Column(). Will assemble the string 'doc' as
the '__doc__' attribute on the descriptor.

- Usage of version_id_col on a backend that supports
cursor.rowcount for execute() but not executemany() now works
when a delete is issued (already worked for saves, since those
don't use executemany()). For a backend that doesn't support
cursor.rowcount at all, a warning is emitted the same
as with saves. [ticket:1761]

- The ORM now short-term caches the "compiled" form of
insert() and update() constructs when flushing lists of
objects of all the same class, thereby avoiding redundant
compilation per individual INSERT/UPDATE within an
individual flush() call.

- internal getattr(), setattr(), getcommitted() methods
on ColumnProperty, CompositeProperty, RelationshipProperty
have been underscored (i.e. are private), signature has

- engines
- The C extension now also works with DBAPIs which use custom
sequences as row (and not only tuples). [ticket:1757]

- sql
- Restored some bind-labeling logic from 0.5 which ensures
that tables with column names that overlap another column
of the form "<tablename>_<columnname>" won't produce
errors if column._label is used as a bind name during
an UPDATE. Test coverage which wasn't present in 0.5
has been added. [ticket:1755]

- somejoin.select(fold_equivalents=True) is no longer
deprecated, and will eventually be rolled into a more
comprehensive version of the feature for [ticket:1729].

- the Numeric type raises an *enormous* warning when expected
to convert floats to Decimal from a DBAPI that returns floats.
This includes SQLite, Sybase, MS-SQL. [ticket:1759]

- Fixed an error in expression typing which caused an endless
loop for expressions with two NULL types.

- Fixed bug in execution_options() feature whereby the existing
Transaction and other state information from the parent
connection would not be propagated to the sub-connection.

- Added new 'compiled_cache' execution option. A dictionary
where Compiled objects will be cached when the Connection
compiles a clause expression into a dialect- and parameter-
specific Compiled object. It is the user's responsibility to
manage the size of this dictionary, which will have keys
corresponding to the dialect, clause element, the column
names within the VALUES or SET clause of an INSERT or UPDATE,
as well as the "batch" mode for an INSERT or UPDATE statement.

- Added get_pk_constraint() to reflection.Inspector, similar
to get_primary_keys() except returns a dict that includes the
name of the constraint, for supported backends (PG so far).

- Table.create() and Table.drop() no longer apply metadata-
level create/drop events. [ticket:1771]

- ext
- the compiler extension now allows @compiles decorators
on base classes that extend to child classes, @compiles
decorators on child classes that aren't broken by a
@compiles decorator on the base class.

- Declarative will raise an informative error message
if a non-mapped class attribute is referenced in the
string-based relationship() arguments.

- Further reworked the "mixin" logic in declarative to
additionally allow __mapper_args__ as a @classproperty
on a mixin, such as to dynamically assign polymorphic_identity.

- postgresql
- Postgresql now reflects sequence names associated with
SERIAL columns correctly, after the name of of the sequence
has been changed. Thanks to Kumar McMillan for the patch.

- Repaired missing import in psycopg2._PGNumeric type when
unknown numeric is received.

- psycopg2/pg8000 dialects now aware of REAL[], FLOAT[],
DOUBLE_PRECISION[], NUMERIC[] return types without
raising an exception.

- Postgresql reflects the name of primary key constraints,
if one exists. [ticket:1769]

- oracle
- Now using cx_oracle output converters so that the
DBAPI returns natively the kinds of values we prefer:
- NUMBER values with positive precision + scale convert
to cx_oracle.STRING and then to Decimal. This
allows perfect precision for the Numeric type when
using cx_oracle. [ticket:1759]
- STRING/FIXED_CHAR now convert to unicode natively.
SQLAlchemy's String types then don't need to
apply any kind of conversions.

- firebird
- The functionality of result.rowcount can be disabled on a
per-engine basis by setting 'enable_rowcount=False'
on create_engine(). Normally, cursor.rowcount is called
after any UPDATE or DELETE statement unconditionally,
because the cursor is then closed and Firebird requires
an open cursor in order to get a rowcount. This
call is slightly expensive however so it can be disabled.
To re-enable on a per-execution basis, the
'enable_rowcount=True' execution option may be used.

- examples
- Updated attribute_shard.py example to use a more robust
method of searching a Query for binary expressions which
compare columns against literal values.

You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
To post to this group, send email to sqlal...@googlegroups.com.
To unsubscribe from this group, send email to sqlalchemy+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.

Domingo Aguilera

Apr 18, 2010, 10:22:10 PM4/18/10
to sqlalchemy
Congratulations Michael, keep it up!

Chris Withers

Apr 19, 2010, 5:21:44 AM4/19/10
to sqlal...@googlegroups.com
Michael Bayer wrote:
> The first official 0.6 release of SQLAlchemy is now available.

Yay! Congrats :-)


Simplistix - Content Management, Batch Processing & Python Consulting
- http://www.simplistix.co.uk

Diana Clarke

Apr 20, 2010, 9:12:36 AM4/20/10
to sqlal...@googlegroups.com
Yes, Congratulations & Thank-you!


On Sun, Apr 18, 2010 at 8:02 PM, Michael Bayer <mik...@zzzcomputing.com> wrote:
> The first official 0.6 release of SQLAlchemy is now available.

Gerry Reno

Apr 20, 2010, 10:27:29 AM4/20/10
to sqlalchemy
Congratulations Mike and contributors. This is an important milestone
in the evolution of SQLAlchemy. Thanks for all the hard work.

Reply all
Reply to author
0 new messages