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: http://www.sqlalchemy.org/download.html 0.6.0 ===== - 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. [ticket:1754] - 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 changed. - 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). [ticket:1769] - 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. [ticket:1071] - 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 [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
