SQLAlchemy 0.6.4 is now available, with a significantly large number of enhancements and fixes.
A large focus of this release is on clarification and ease of use, including: - the largest documentation reorganization since we moved to Sphinx, with an emphasis on one-location-per-concept. no more jumping around to the "API Reference" to find things. - revamp of the error messages when dealing with primaryjoin issues, more forgiving behavior when it's clear what the user intent was - more warnings for known configurational mistakes with the ORM Other changes include: - an up to 90% call reduction within mapper.py when flushing highly polymorphic structures - Fixed psycopg2 isolation mode setting - lots of ORM / SQL / engine fixes I am always amazed at how fast CHANGES grows from the previous release, only around 6 weeks ago. Download SQLAlchemy 0.6.4 at: http://www.sqlalchemy.org/download.html 0.6.4 ===== - orm - The name ConcurrentModificationError has been changed to StaleDataError, and descriptive error messages have been revised to reflect exactly what the issue is. Both names will remain available for the forseeable future for schemes that may be specifying ConcurrentModificationError in an "except:" clause. - Added a mutex to the identity map which mutexes remove operations against iteration methods, which now pre-buffer before returning an iterable. This because asyncrhonous gc can remove items via the gc thread at any time. [ticket:1891] - The Session class is now present in sqlalchemy.orm.*. We're moving away from the usage of create_session(), which has non-standard defaults, for those situations where a one-step Session constructor is desired. Most users should stick with sessionmaker() for general use, however. - query.with_parent() now accepts transient objects and will use the non-persistent values of their pk/fk attributes in order to formulate the criterion. Docs are also clarified as to the purpose of with_parent(). - The include_properties and exclude_properties arguments to mapper() now accept Column objects as members in addition to strings. This so that same-named Column objects, such as those within a join(), can be disambiguated. - A warning is now emitted if a mapper is created against a join or other single selectable that includes multiple columns with the same name in its .c. collection, and those columns aren't explictly named as part of the same or separate attributes (or excluded). In 0.7 this warning will be an exception. Note that this warning is not emitted when the combination occurs as a result of inheritance, so that attributes still allow being overridden naturally. [ticket:1896]. In 0.7 this will be improved further. - The primary_key argument to mapper() can now specify a series of columns that are only a subset of the calculated "primary key" columns of the mapped selectable, without an error being raised. This helps for situations where a selectable's effective primary key is simpler than the number of columns in the selectable that are actually marked as "primary_key", such as a join against two tables on their primary key columns [ticket:1896]. - An object that's been deleted now gets a flag 'deleted', which prohibits the object from being re-add()ed to the session, as previously the object would live in the identity map silently until its attributes were accessed. The make_transient() function now resets this flag along with the "key" flag. - make_transient() can be safely called on an already transient instance. - a warning is emitted in mapper() if the polymorphic_on column is not present either in direct or derived form in the mapped selectable or in the with_polymorphic selectable, instead of silently ignoring it. Look for this to become an exception in 0.7. - Another pass through the series of error messages emitted when relationship() is configured with ambiguous arguments. The "foreign_keys" setting is no longer mentioned, as it is almost never needed and it is preferable users set up correct ForeignKey metadata, which is now the recommendation. If 'foreign_keys' is used and is incorrect, the message suggests the attribute is probably unnecessary. Docs for the attribute are beefed up. This because all confused relationship() users on the ML appear to be attempting to use foreign_keys due to the message, which only confuses them further since Table metadata is much clearer. - If the "secondary" table has no ForeignKey metadata and no foreign_keys is set, even though the user is passing screwed up information, it is assumed that primary/secondaryjoin expressions should consider only and all cols in "secondary" to be foreign. It's not possible with "secondary" for the foreign keys to be elsewhere in any case. A warning is now emitted instead of an error, and the mapping succeeds. [ticket:1877] - Moving an o2m object from one collection to another, or vice versa changing the referenced object by an m2o, where the foreign key is also a member of the primary key, will now be more carefully checked during flush if the change in value of the foreign key on the "many" side is the result of a change in the primary key of the "one" side, or if the "one" is just a different object. In one case, a cascade-capable DB would have cascaded the value already and we need to look at the "new" PK value to do an UPDATE, in the other we need to continue looking at the "old". We now look at the "old", assuming passive_updates=True, unless we know it was a PK switch that triggered the change. [ticket:1856] - The value of version_id_col can be changed manually, and this will result in an UPDATE of the row. Versioned UPDATEs and DELETEs now use the "committed" value of the version_id_col in the WHERE clause and not the pending changed value. The version generator is also bypassed if manual changes are present on the attribute. [ticket:1857] - Repaired the usage of merge() when used with concrete inheriting mappers. Such mappers frequently have so-called "concrete" attributes, which are subclass attributes that "disable" propagation from the parent - these needed to allow a merge() operation to pass through without effect. - Specifying a non-column based argument for column_mapped_collection, including string, text() etc., will raise an error message that specifically asks for a column element, no longer misleads with incorrect information about text() or literal(). [ticket:1863] - Similarly, for relationship(), foreign_keys, remote_side, order_by - all column-based expressions are enforced - lists of strings are explicitly disallowed since this is a very common error - Dynamic attributes don't support collection population - added an assertion for when set_committed_value() is called, as well as when joinedload() or subqueryload() options are applied to a dynamic attribute, instead of failure / silent failure. [ticket:1864] - Fixed bug whereby generating a Query derived from one which had the same column repeated with different label names, typically in some UNION situations, would fail to propagate the inner columns completely to the outer query. [ticket:1852] - object_session() raises the proper UnmappedInstanceError when presented with an unmapped instance. [ticket:1881] - Applied further memoizations to calculated Mapper properties, with significant (~90%) runtime mapper.py call count reduction in heavily polymorphic mapping configurations. - mapper _get_col_to_prop private method used by the versioning example is deprecated; now use mapper.get_property_by_column() which will remain the public method for this. - the versioning example works correctly now if versioning on a col that was formerly NULL. - sql - Calling execute() on an alias() construct is pending deprecation for 0.7, as it is not itself an "executable" construct. It currently "proxies" its inner element and is conditionally "executable" but this is not the kind of ambiguity we like these days. - The execute() and scalar() methods of ClauseElement are now moved appropriately to the Executable subclass. ClauseElement.execute()/ scalar() are still present and are pending deprecation in 0.7, but note these would always raise an error anyway if you were not an Executable (unless you were an alias(), see previous note). - Added basic math expression coercion for Numeric->Integer, so that resulting type is Numeric regardless of the direction of the expression. - Changed the scheme used to generate truncated "auto" index names when using the "index=True" flag on Column. The truncation only takes place with the auto-generated name, not one that is user-defined (an error would be raised instead), and the truncation scheme itself is now based on a fragment of an md5 hash of the identifier name, so that multiple indexes on columns with similar names still have unique names. [ticket:1855] - The generated index name also is based on a "max index name length" attribute which is separate from the "max identifier length" - this to appease MySQL who has a max length of 64 for index names, separate from their overall max length of 255. [ticket:1412] - the text() construct, if placed in a column oriented situation, will at least return NULLTYPE for its type instead of None, allowing it to be used a little more freely for ad-hoc column expressions than before. literal_column() is still the better choice, however. - Added full description of parent table/column, target table/column in error message raised when ForeignKey can't resolve target. - Fixed bug whereby replacing composite foreign key columns in a reflected table would cause an attempt to remove the reflected constraint from the table a second time, raising a KeyError. [ticket:1865] - the _Label construct, i.e. the one that is produced whenever you say somecol.label(), now counts itself in its "proxy_set" unioned with that of it's contained column's proxy set, instead of directly returning that of the contained column. This allows column correspondence operations which depend on the identity of the _Labels themselves to return the correct result - fixes ORM bug [ticket:1852]. - engine - Calling fetchone() or similar on a result that has already been exhausted, has been closed, or is not a result-returning result now raises ResourceClosedError, a subclass of InvalidRequestError, in all cases, regardless of backend. Previously, some DBAPIs would raise ProgrammingError (i.e. pysqlite), others would return None leading to downstream breakages (i.e. MySQL-python). - Fixed bug in Connection whereby if a "disconnect" event occurred in the "initialize" phase of the first connection pool connect, an AttributeError would be raised when the Connection would attempt to invalidate the DBAPI connection. [ticket:1894] - Connection, ResultProxy, as well as Session use ResourceClosedError for all "this connection/transaction/result is closed" types of errors. - Connection.invalidate() can be called more than once and subsequent calls do nothing. - declarative - if @classproperty is used with a regular class-bound mapper property attribute, it will be called to get the actual attribute value during initialization. Currently, there's no advantage to using @classproperty on a column or relationship attribute of a declarative class that isn't a mixin - evaluation is at the same time as if @classproperty weren't used. But here we at least allow it to function as expected. - Fixed bug where "Can't add additional column" message would display the wrong name. - postgresql - Fixed the psycopg2 dialect to use its set_isolation_level() method instead of relying upon the base "SET SESSION ISOLATION" command, as psycopg2 resets the isolation level on each new transaction otherwise. - mssql - Fixed "default schema" query to work with pymssql backend. - firebird - Fixed bug whereby a column default would fail to reflect if the "default" keyword were lower case. - oracle - Added ROWID type to the Oracle dialect, for those cases where an explicit CAST might be needed. [ticket:1879] - Oracle reflection of indexes has been tuned so that indexes which include some or all primary key columns, but not the same set of columns as that of the primary key, are reflected. Indexes which contain the identical columns as that of the primary key are skipped within reflection, as the index in that case is assumed to be the auto-generated primary key index. Previously, any index with PK columns present would be skipped. Thanks to Kent Bower for the patch. [ticket:1867] - Oracle now reflects the names of primary key constraints - also thanks to Kent Bower. [ticket:1868] - informix - Applied patches from [ticket:1904] to get basic Informix functionality up again. We rely upon end-user testing to ensure that Informix is working to some degree. - documentation - The docs have been reorganized such that the "API Reference" section is gone - all the docstrings from there which were public API are moved into the context of the main doc section that talks about it. Main docs divided into "SQLAlchemy Core" and "SQLAlchemy ORM" sections, mapper/relationship docs have been broken out. Lots of sections rewritten and/or reorganized. - examples - The beaker_caching example has been reorgnized such that the Session, cache manager, declarative_base are part of environment, and custom cache code is portable and now within "caching_query.py". This allows the example to be easier to "drop in" to existing projects. - the history_meta versioning recipe sets "unique=False" when copying columns, so that the versioning table handles multiple rows with repeating values. [ticket:1887] -- 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.
