+ - Fixed bug whereby a non-"mutable" attribute modified event
+ which occurred on an object that was clean except for
+ preceding mutable attribute changes would fail to strongly
+ reference itself in the identity map. This would cause the
+ object to be garbage collected, losing track of any changes
+ that weren't previously saved in the "mutable changes"
+ - "innerjoin" flag doesn't take effect along the chain
+ of joinedload() joins if a previous join in that chain
+ is an outer join, thus allowing primary rows without
+ a referenced child row to be correctly returned
+ in results. [ticket:1954]
+ - Fixed bug regarding "subqueryload" strategy whereby
+ strategy would fail if the entity was an aliased()
+ construct. [ticket:1964]
+ - Fixed indexing of Query objects by -1. It was erroneously
+ transformed to the empty slice -1:0 that resulted in
+ IndexError. [ticket:1968]
+ - The mapper argument "primary_key" can be passed as a
+ single column as well as a list or tuple. [ticket:1971]
+ The documentation examples that illustrated it as a
+ scalar value have been changed to lists.
+ - Added active_history flag to relationship()
+ and column_property(), forces attribute events to
+ always load the "old" value, so that it's available to
+ attributes.get_history(). [ticket:1961]
+ - active_history flag also added to composite().
+ The flag has no effect in 0.6, but is instead
+ a placeholder flag for forwards compatibility,
+ as it will be needed in 0.7 for composites.
+ - Query.get() will raise if the number of params
+ in a composite key is too large, as well as too
+ - Backport of "optimized get" fix from 0.7,
+ improves the generation of joined-inheritance
+ "load expired row" behavior. [ticket:1992]
+ - Fixed operator precedence rules for multiple
+ chains of a single non-associative operator.
+ I.e. "x - (y - z)" will compile as "x - (y - z)"
+ and not "x - y - z". Also works with labels,
+ i.e. "x - (y - z).label('foo')"
+ - The 'info' attribute of Column is copied during
+ Column.copy(), i.e. as occurs when using columns
+ in declarative mixins. [ticket:1967]
+ - Added a bind processor for booleans which coerces
+ to int, for DBAPIs such as pymssql that naively call
+ - Fixed memory leak in C version of Decimal result
+ processor. [ticket:1978]
+ - Implemented sequence check capability for the C
+ version of RowProxy, as well as 2.7 style
+ "collections.Sequence" registration for RowProxy.
+ - Single element tuple expressions inside an IN clause
+ parenthesize correctly, also from [ticket:1984]
+ - Ensured every numeric, float, int code, scalar + array,
+ are recognized by psycopg2 and pg8000's "numeric"
+ base type. [ticket:1955]
+ - Added as_uuid=True flag to the UUID type, will receive
+ and return values as Python UUID() objects rather than
+ strings. Currently, the UUID type is only known to
+ work with psycopg2. [ticket:1956]
+ - Fixed bug whereby KeyError would occur with non-ENUM
+ supported PG versions after a pool dispose+recreate
+ would occur, [ticket:1989]
+ - Fixed error handling for Jython + zxjdbc, such that
+ has_table() property works again. Regression from
+ 0.6.3 (we don't have a Jython buildbot, sorry)
+ - The REFERENCES clause in a CREATE TABLE that includes
+ a remote schema to another table with the same schema
+ name now renders the remote name without
+ the schema clause, as required by SQLite. [ticket:1851]
+ - On the same theme, the REFERENCES clause in a CREATE TABLE
+ that includes a remote schema to a *different* schema
+ than that of the parent table doesn't render at all,
+ as cross-schema references do not appear to be supported.
+ - The cx_oracle "decimal detection" logic, which takes place
+ for for result set columns with ambiguous numeric characteristics,
+ now uses the decimal point character determined by the locale/
+ NLS_LANG setting, using an on-first-connect detection of
+ this character. cx_oracle 5.0.3 or greater is also required
+ when using a non-period-decimal-point NLS_LANG setting.
+ - An error is raised if __table_args__ is not in tuple
+ or dict format, and is not None. [ticket:1972]
+ - Added "map_to()" method to SqlSoup, which is a "master"
+ method which accepts explicit arguments for each aspect of
+ the selectable and mapping, including a base class per
+ - Mapped selectables used with the map(), with_labels(),
+ join() methods no longer put the given argument into the
+ internal "cache" dictionary. Particularly since the
+ join() and select() objects are created in the method
+ itself this was pretty much a pure memory leaking behavior.
+ - Added a new "lazyload" option "immediateload".
+ Issues the usual "lazy" load operation automatically
+ as the object is populated. The use case
+ here is when loading objects to be placed in
+ an offline cache, or otherwise used after
+ the session isn't available, and straight 'select'
+ loading, not 'joined' or 'subquery', is desired.
+ - New Query methods: query.label(name), query.as_scalar(),
+ return the query's statement as a scalar subquery
+ with /without label [ticket:1920];
+ query.with_entities(*ent), replaces the SELECT list of
+ the query with new entities.
+ Roughly equivalent to a generative form of query.values()
+ which accepts mapped entities as well as column
+ - Fixed recursion bug which could occur when moving
+ an object from one reference to another, with
+ backrefs involved, where the initiating parent
+ was a subclass (with its own mapper) of the
+ - Fixed a regression in 0.6.4 which occurred if you
+ passed an empty list to "include_properties" on
+ - Fixed labeling bug in Query whereby the NamedTuple
+ would mis-apply labels if any of the column
+ expressions were un-labeled.
+ - Patched a case where query.join() would adapt the
+ right side to the right side of the left's join
+ inappropriately [ticket:1925]
+ - Query.select_from() has been beefed up to help
+ ensure that a subsequent call to query.join()
+ will use the select_from() entity, assuming it's
+ a mapped entity and not a plain selectable,
+ as the default "left" side, not the first entity
+ in the Query object's list of entities.
+ - The exception raised by Session when it is used
+ subsequent to a subtransaction rollback (which is what
+ happens when a flush fails in autocommit=False mode) has
+ now been reworded (this is the "inactive due to a
+ rollback in a subtransaction" message). In particular,
+ if the rollback was due to an exception during flush(),
+ the message states this is the case, and reiterates the
+ string form of the original exception that occurred
+ during flush. If the session is closed due to explicit
+ usage of subtransactions (not very common), the message
+ just states this is the case.
+ - The exception raised by Mapper when repeated requests to
+ its initialization are made after initialization already
+ failed no longer assumes the "hasattr" case, since
+ there's other scenarios in which this message gets
+ emitted, and the message also does not compound onto
+ itself multiple times - you get the same message for
+ each attempt at usage. The misnomer "compiles" is being
+ traded out for "initialize".
+ - Fixed bug in query.update() where 'evaluate' or 'fetch'
+ expiration would fail if the column expression key was
+ a class attribute with a different keyname as the
+ actual column name. [ticket:1935]
+ - Added an assertion during flush which ensures
+ that no NULL-holding identity keys were generated
+ on "newly persistent" objects.
+ This can occur when user defined code inadvertently
+ triggers flushes on not-fully-loaded objects.
+ - lazy loads for relationship attributes now use
+ the current state, not the "committed" state,
+ of foreign and primary key attributes
+ when issuing SQL, if a flush is not in process.
+ Previously, only the database-committed state would
+ be used. In particular, this would cause a many-to-one
+ get()-on-lazyload operation to fail, as autoflush
+ is not triggered on these loads when the attributes are
+ determined and the "committed" state may not be
+ available. [ticket:1910]
+ - A new flag on relationship(), load_on_pending, allows
+ the lazy loader to fire off on pending objects without a
+ flush taking place, as well as a transient object that's
+ been manually "attached" to the session. Note that this
+ flag blocks attribute events from taking place when an
+ object is loaded, so backrefs aren't available until
+ after a flush. The flag is only intended for very
+ - Another new flag on relationship(), cascade_backrefs,
+ disables the "save-update" cascade when the event was
+ initiated on the "reverse" side of a bidirectional
+ relationship. This is a cleaner behavior so that
+ many-to-ones can be set on a transient object without
+ it getting sucked into the child object's session,
+ while still allowing the forward collection to
+ cascade. We *might* default this to False in 0.7.
+ - Slight improvement to the behavior of
+ "passive_updates=False" when placed only on the
+ many-to-one side of a relationship; documentation has
+ been clarified that passive_updates=False should really
+ be on the one-to-many side.
+ - Placing passive_deletes=True on a many-to-one emits
+ a warning, since you probably intended to put it on
+ - Fixed bug that would prevent "subqueryload" from
+ working correctly with single table inheritance
+ for a relationship from a subclass - the "where
+ type in (x, y, z)" only gets placed on the inside,
+ - When using from_self() with single table inheritance,
+ the "where type in (x, y, z)" is placed on the outside
+ of the query only, instead of repeatedly. May make
+ some more adjustments to this.
+ - scoped_session emits a warning when configure() is
+ called if a Session is already present (checks only the
+ current thread) [ticket:1924]
+ - reworked the internals of mapper.cascade_iterator() to
+ cut down method calls by about 9% in some circumstances.
+ - Fixed bug in TypeDecorator whereby the dialect-specific
+ type was getting pulled in to generate the DDL for a
+ given type, which didn't always return the correct result.
+ - TypeDecorator can now have a fully constructed type
+ specified as its "impl", in addition to a type class.
+ - TypeDecorator will now place itself as the resulting
+ type for a binary expression where the type coercion
+ rules would normally return its impl type - previously,
+ a copy of the impl type would be returned which would
+ have the TypeDecorator embedded into it as the "dialect"
+ impl, this was probably an unintentional way of achieving
+ - TypeDecorator.load_dialect_impl() returns "self.impl" by
+ default, i.e. not the dialect implementation type of
+ "self.impl". This to support compilation correctly.
+ Behavior can be user-overridden in exactly the same way
+ as before to the same effect.
+ - Added type_coerce(expr, type_) expression element.
+ Treats the given expression as the given type when evaluating
+ expressions and processing result rows, but does not
+ affect the generation of SQL, other than an anonymous
+ - Table.tometadata() now copies Index objects associated
+ with the Table as well.
+ - Table.tometadata() issues a warning if the given Table
+ is already present in the target MetaData - the existing
+ Table object is returned.
+ - An informative error message is raised if a Column
+ which has not yet been assigned a name, i.e. as in
+ declarative, is used in a context where it is
+ exported to the columns collection of an enclosing
+ select() construct, or if any construct involving
+ that column is compiled before its name is
+ - as_scalar(), label() can be called on a selectable
+ which contains a Column that is not yet named.
+ - Fixed recursion overflow which could occur when operating
+ with two expressions both of type "NullType", but
+ not the singleton NULLTYPE instance. [ticket:1907]
+ - @classproperty (soon/now @declared_attr) takes effect for
+ __mapper_args__, __table_args__, __tablename__ on
+ a base class that is not a mixin, as well as mixins.
+ - @classproperty 's official name/location for usage
+ with declarative is sqlalchemy.ext.declarative.declared_attr.
+ Same thing, but moving there since it is more of a
+ "marker" that's specific to declararative,
+ not just an attribute technique. [ticket:1915]
+ - Fixed bug whereby columns on a mixin wouldn't propagate
+ correctly to a single-table, or joined-table,
+ inheritance scheme where the attribute name is
+ different than that of the column. [ticket:1930],
+ - A mixin can now specify a column that overrides
+ a column of the same name associated with a superclass.
+ Thanks to Oystein Haaland.
+ - Fixed a regression in 0.6.4 whereby the change that
+ allowed cursor errors to be raised consistently broke
+ the result.lastrowid accessor. Test coverage has
+ been added for result.lastrowid. Note that lastrowid
+ is only supported by Pysqlite and some MySQL drivers,
+ so isn't super-useful in the general case.
+ - the logging message emitted by the engine when
+ a connection is first used is now "BEGIN (implicit)"
+ to emphasize that DBAPI has no explicit begin().
+ - added "views=True" option to metadata.reflect(),
+ will add the list of available views to those
+ being reflected. [ticket:1936]
+ - engine_from_config() now accepts 'debug' for
+ 'echo', 'echo_pool', 'force' for 'convert_unicode',
+ boolean values for 'use_native_unicode'.
+ - Added "as_tuple" flag to ARRAY type, returns results
+ as tuples instead of lists to allow hashing.
+ - Fixed bug which prevented "domain" built from a
+ custom type such as "enum" from being reflected.
+ - Fixed bug involving reflection of CURRENT_TIMESTAMP
+ default used with ON UPDATE clause, thanks to
+ Taavi Burns [ticket:1940]
+ - The implicit_retunring argument to create_engine()
+ is now honored regardless of detected version of
+ Oracle. Previously, the flag would be forced
+ to False if server version info was < 10.
+ - Fixed reflection bug which did not properly handle
+ reflection of unknown types. [ticket:1946]
+ - Fixed bug where aliasing of tables with "schema" would
+ fail to compile properly. [ticket:1943]
+ - Rewrote the reflection of indexes to use sys.
+ catalogs, so that column names of any configuration
+ (spaces, embedded commas, etc.) can be reflected.
+ Note that reflection of indexes requires SQL
+ Server 2005 or greater. [ticket:1770]
+ - mssql+pymssql dialect now honors the "port" portion
+ of the URL instead of discarding it. [ticket:1952]
+ - *Major* cleanup / modernization of the Informix
+ dialect for 0.6, courtesy Florian Apolloner.
+ - the NoseSQLAlchemyPlugin has been moved to a
+ new package "sqlalchemy_nose" which installs
+ along with "sqlalchemy". This so that the "nosetests"
+ script works as always but also allows the
+ --with-coverage option to turn on coverage before
+ SQLAlchemy modules are imported, allowing coverage
+ - CircularDependencyError now has .cycles and .edges
+ members, which are the set of elements involved in
+ one or more cycles, and the set of edges as 2-tuples.
+ - 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:"
+ - 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.
+ - 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,
+ - 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
+ - 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
+ - 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.
+ - 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
+ - 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
+ - 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
+ - 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
+ - Added basic math expression coercion for
+ 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].
+ - 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
+ - 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
+ - Connection.invalidate() can be called more than
+ once and subsequent calls do nothing.
+ - 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.
+ - 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
+ - Fixed "default schema" query to work with
+ - Fixed bug whereby a column default would fail to
+ reflect if the "default" keyword were lower case.
+ - Added ROWID type to the Oracle dialect, for those
+ cases where an explicit CAST might be needed.
+ - 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.
+ - 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.
+ - 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
+ - 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.
+ - Removed errant many-to-many load in unitofwork
+ which triggered unnecessarily on expired/unloaded
+ collections. This load now takes place only if
+ passive_updates is False and the parent primary
+ key has changed, or if passive_deletes is False
+ and a delete of the parent has occurred.
+ - Column-entities (i.e. query(Foo.id)) copy their
+ state more fully when queries are derived from
+ themselves + a selectable (i.e. from_self(),
+ union(), etc.), so that join() and such have the
+ correct state to work from. [ticket:1853]
+ - Fixed bug where Query.join() would fail if
+ querying a non-ORM column then joining without
+ an on clause when a FROM clause is already
+ present, now raises a checked exception the
+ same way it does when the clause is not
+ - Improved the check for an "unmapped class",
+ including the case where the superclass is mapped
+ but the subclass is not. Any attempts to access
+ cls._sa_class_manager.mapper now raise
+ UnmappedClassError(). [ticket:1142]
+ - Added "column_descriptions" accessor to Query,
+ returns a list of dictionaries containing
+ naming/typing information about the entities
+ the Query will return. Can be helpful for
+ building GUIs on top of ORM queries.
+ - The _extract_error_code() method now works
+ correctly with each MySQL dialect (
+ MySQL-python, OurSQL, MySQL-Connector-Python,
+ the reconnect logic would fail for OperationalError
+ conditions, however since MySQLdb and OurSQL
+ have their own reconnect feature, there was no
+ symptom for these drivers here unless one
+ watched the logs. [ticket:1848]
+ - More tweaks to cx_oracle Decimal handling.
+ "Ambiguous" numerics with no decimal place
+ are coerced to int at the connection handler
+ level. The advantage here is that ints
+ come back as ints without SQLA type
+ objects being involved and without needless
+ conversion to Decimal first.
+ Unfortunately, some exotic subquery cases
+ can even see different types between
+ individual result rows, so the Numeric
+ handler, when instructed to return Decimal,
+ can't take full advantage of "native decimal"
+ mode and must run isinstance() on every value
+ to check if its Decimal already. Reopen of
+ - Query.join() will check for a call of the
+ form query.join(target, clause_expression),
+ i.e. missing the tuple, and raise an informative
+ error message that this is the wrong calling form.
+ - Fixed bug regarding flushes on self-referential
+ bi-directional many-to-many relationships, where
+ two objects made to mutually reference each other
+ in one flush would fail to insert a row for both
+ sides. Regression from 0.5. [ticket:1824]
+ - the post_update feature of relationship() has been
+ reworked architecturally to integrate more closely
+ with the new 0.6 unit of work. The motivation
+ for the change is so that multiple "post update"
+ calls, each affecting different foreign key
+ columns of the same row, are executed in a single
+ UPDATE statement, rather than one UPDATE
+ statement per column per row. Multiple row
+ updates are also batched into executemany()s as
+ possible, while maintaining consistent row ordering.
+ - Query.statement, Query.subquery(), etc. now transfer
+ the values of bind parameters, i.e. those specified
+ by query.params(), into the resulting SQL expression.
+ Previously the values would not be transferred
+ and bind parameters would come out as None.
+ - Subquery-eager-loading now works with Query objects
+ which include params(), as well as get() Queries.
+ - Can now call make_transient() on an instance that
+ is referenced by parent objects via many-to-one,
+ without the parent's foreign key value getting
+ temporarily set to None - this was a function
+ of the "detect primary key switch" flush handler.
+ It now ignores objects that are no longer
+ in the "persistent" state, and the parent's
+ foreign key identifier is left unaffected.
+ - query.order_by() now accepts False, which cancels
+ any existing order_by() state on the Query, allowing
+ subsequent generative methods to be called which do
+ not support ORDER BY. This is not the same as the
+ already existing feature of passing None, which
+ suppresses any existing order_by() settings, including
+ those configured on the mapper. False will make it
+ as though order_by() was never called, while
+ None is an active setting.
+ - An instance which is moved to "transient", has
+ an incomplete or missing set of primary key
+ attributes, and contains expired attributes, will
+ raise an InvalidRequestError if an expired attribute
+ is accessed, instead of getting a recursion overflow.
+ - The make_transient() function is now in the generated
+ - make_transient() removes all "loader" callables from
+ the state being made transient, removing any
+ "expired" state - all unloaded attributes reset back
+ to undefined, None/empty on access.
+ - The warning emitted by the Unicode and String types
+ with convert_unicode=True no longer embeds the actual
+ value passed. This so that the Python warning
+ registry does not continue to grow in size, the warning
+ is emitted once as per the warning filter settings,
+ and large string values don't pollute the output.
+ - Fixed bug that would prevent overridden clause
+ compilation from working for "annotated" expression
+ elements, which are often generated by the ORM.
+ - The argument to "ESCAPE" of a LIKE operator or similar
+ is passed through render_literal_value(), which may
+ implement escaping of backslashes. [ticket:1400]
+ - Fixed bug in Enum type which blew away native_enum
+ flag when used with TypeDecorators or other adaption
+ - Inspector hits bind.connect() when invoked to ensure
+ initialize has been called. the internal name ".conn"
+ is changed to ".bind", since that's what it is.
+ - Modified the internals of "column annotation" such that
+ a custom Column subclass can safely override
+ _constructor to return Column, for the purposes of
+ making "configurational" column classes that aren't
+ involved in proxying, etc.
+ - Column.copy() takes along the "unique" attribute
+ among others, fixes [ticket:1829] regarding declarative
+ - render_literal_value() is overridden which escapes
+ backslashes, currently applies to the ESCAPE clause
+ of LIKE and similar expressions.
+ Ultimately this will have to detect the value of
+ "standard_conforming_strings" for full behavior.
+ - Won't generate "CREATE TYPE" / "DROP TYPE" if
+ using types.Enum on a PG version prior to 8.3 -
+ the supports_native_enum flag is fully
+ - MySQL dialect doesn't emit CAST() for MySQL version
+ detected < 4.0.2. This allows the unicode
+ check on connect to proceed. [ticket:1826]
+ - MySQL dialect now detects NO_BACKSLASH_ESCAPES sql
+ mode, in addition to ANSI_QUOTES.
+ - render_literal_value() is overridden which escapes
+ backslashes, currently applies to the ESCAPE clause
+ of LIKE and similar expressions. This behavior
+ is derived from detecting the value of
+ NO_BACKSLASH_ESCAPES. [ticket:1400]
+ - Fixed ora-8 compatibility flags such that they
+ don't cache a stale value from before the first
+ database connection actually occurs. [ticket:1819]
+ - Oracle's "native decimal" metadata begins to return
+ ambiguous typing information about numerics
+ when columns are embedded in subqueries as well
+ as when ROWNUM is consulted with subqueries, as we
+ do for limit/offset. We've added these ambiguous
+ conditions to the cx_oracle "convert to Decimal()"
+ handler, so that we receive numerics as Decimal
+ in more cases instead of as floats. These are
+ then converted, if requested, into Integer
+ or Float, or otherwise kept as the lossless
+ - If server_version_info is outside the usual
+ range of (8, ), (9, ), (10, ), a warning is emitted
+ which suggests checking that the FreeTDS version
+ configuration is using 7.0 or 8.0, not 4.2.
+ - Fixed incorrect signature in do_execute(), error
+ introduced in 0.6.1. [ticket:1823]
+ - Firebird dialect adds CHAR, VARCHAR types which
+ accept a "charset" flag, to support Firebird
+ "CHARACTER SET" clause. [ticket:1813]
+ - Added support for @classproperty to provide
+ any kind of schema/mapping construct from a
+ declarative mixin, including columns with foreign
+ keys, relationships, column_property, deferred.
+ This solves all such issues on declarative mixins.
+ An error is raised if any MapperProperty subclass
+ is specified on a mixin without using @classproperty.
+ [ticket:1751] [ticket:1796] [ticket:1805]
+ - a mixin class can now define a column that matches
+ one which is present on a __table__ defined on a
+ subclass. It cannot, however, define one that is
+ not present in the __table__, and the error message
+ here now works. [ticket:1821]
+ - The 'default' compiler is automatically copied over
+ when overriding the compilation of a built in
+ clause construct, so no KeyError is raised if the
+ user-defined compiler is specific to certain
+ backends and compilation for a different backend
+ is invoked. [ticket:1838]
+ - Added documentation for the Inspector. [ticket:1820]
+ - Fixed @memoized_property and @memoized_instancemethod
+ decorators so that Sphinx documentation picks up
+ these attributes and methods, such as
+ ResultProxy.inserted_primary_key. [ticket:1830]
+ - Fixed regression introduced in 0.6.0 involving improper
+ history accounting on mutable attributes. [ticket:1782]
+ - Fixed regression introduced in 0.6.0 unit of work refactor
+ that broke updates for bi-directional relationship()
+ with post_update=True. [ticket:1807]
+ - session.merge() will not expire attributes on the returned
+ instance if that instance is "pending". [ticket:1789]
+ - fixed __setstate__ method of CollectionAdapter to not
+ fail during deserialize where parent InstanceState not
+ yet unserialized. [ticket:1802]
+ - Added internal warning in case an instance without a
+ full PK happened to be expired and then was asked
+ to refresh. [ticket:1797]
+ - Added more aggressive caching to the mapper's usage of
+ UPDATE, INSERT, and DELETE expressions. Assuming the
+ statement has no per-object SQL expressions attached,
+ the expression objects are cached by the mapper after
+ the first create, and their compiled form is stored
+ persistently in a cache dictionary for the duration of
+ the related Engine. The cache is an LRUCache for the
+ rare case that a mapper receives an extremely
+ high number of different column patterns as UPDATEs.
+ - expr.in_() now accepts a text() construct as the argument.
+ Grouping parenthesis are added automatically, i.e. usage
+ is like `col.in_(text("select id from table"))`.
+ - Columns of _Binary type (i.e. LargeBinary, BLOB, etc.)
+ will coerce a "basestring" on the right side into a
+ _Binary as well so that required DBAPI processing
+ - Added table.add_is_dependent_on(othertable), allows manual
+ placement of dependency rules between two Table objects
+ for use within create_all(), drop_all(), sorted_tables.
+ - Fixed bug that prevented implicit RETURNING from functioning
+ properly with composite primary key that contained zeroes.
+ - Fixed errant space character when generating ADD CONSTRAINT
+ for a named UNIQUE constraint.
+ - Fixed "table" argument on constructor of ForeginKeyConstraint
+ - Fixed bug in connection pool cursor wrapper whereby if a
+ cursor threw an exception on close(), the logging of the
+ message would fail. [ticket:1786]
+ - the _make_proxy() method of ColumnClause and Column now use
+ self.__class__ to determine the class of object to be returned
+ instead of hardcoding to ColumnClause/Column, making it slightly
+ easier to produce specific subclasses of these which work in
+ alias/subquery situations.
+ - func.XXX() doesn't inadvertently resolve to non-Function
+ classes (e.g. fixes func.text()). [ticket:1798]
+ - Fixed building the C extensions on Python 2.4. [ticket:1781]
+ - Pool classes will reuse the same "pool_logging_name" setting
+ after a dispose() occurs.
+ - Engine gains an "execution_options" argument and
+ update_execution_options() method, which will apply to
+ all connections generated by this engine.
+ - func.sysdate() emits "SYSDATE()", i.e. with the ending
+ parenthesis, on MySQL. [ticket:1794]
+ - Fixed concatenation of constraints when "PRIMARY KEY"
+ constraint gets moved to column level due to SQLite
+ AUTOINCREMENT keyword being rendered. [ticket:1812]
+ - Added a check for cx_oracle versions lower than version 5,
+ in which case the incompatible "output type handler" won't
+ be used. This will impact decimal accuracy and some
+ unicode handling issues. [ticket:1775]
+ - Fixed use_ansi=False mode, which was producing broken
+ WHERE clauses in pretty much all cases. [ticket:1790]
+ - Re-established support for Oracle 8 with cx_oracle,
+ including that use_ansi is set to False automatically,
+ NVARCHAR2 and NCLOB are not rendered for Unicode,
+ "native unicode" check doesn't fail, cx_oracle
+ "native unicode" mode is disabled, VARCHAR() is emitted
+ with bytes count instead of char count. [ticket:1808]
+ - oracle_xe 5 doesn't accept a Python unicode object in
+ its connect string in normal Python 2.x mode - so we coerce
+ to str() directly. non-ascii characters aren't supported
+ in connect strings here since we don't know what encoding
+ we could use. [ticket:1670]
+ - FOR UPDATE is emitted in the syntactically correct position
+ when limit/offset is used, i.e. the ROWNUM subquery.
+ However, Oracle can't really handle FOR UPDATE with ORDER BY
+ or with subqueries, so its still not very usable, but at
+ least SQLA gets the SQL past the Oracle parser.
+ - Added a label to the query used within has_table() and
+ has_sequence() to work with older versions of Firebird
+ that don't provide labels for result columns. [ticket:1521]
+ - Added integer coercion to the "type_conv" attribute when
+ passed via query string, so that it is properly interpreted
+ by Kinterbasdb. [ticket:1779]
+ - Added 'connection shutdown' to the list of exception strings
+ which indicate a dropped connection. [ticket:1646]
+ - the SqlSoup constructor accepts a `base` argument which specifies
+ the base class to use for mapped classes, the default being
+ `object`. [ticket:1783]
+ - 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
+ - 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
+ - The C extension now also works with DBAPIs which use custom
+ sequences as row (and not only tuples). [ticket:1757]
+ - 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]
+ - 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 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
+ - Postgresql reflects the name of primary key constraints,
+ if one exists. [ticket:1769]
+ - 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.
+ - 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.
+ - Updated attribute_shard.py example to use a more robust
+ method of searching a Query for binary expressions which
+ compare columns against literal values.
+ - Major feature: Added new "subquery" loading capability to
+ relationship(). This is an eager loading option which
+ generates a second SELECT for each collection represented
+ in a query, across all parents at once. The query
+ re-issues the original end-user query wrapped in a subquery,
+ applies joins out to the target collection, and loads
+ all those collections fully in one result, similar to
+ "joined" eager loading but using all inner joins and not
+ re-fetching full parent rows repeatedly (as most DBAPIs seem
+ to do, even if columns are skipped). Subquery loading is
+ available at mapper config level using "lazy='subquery'" and
+ at the query options level using "subqueryload(props..)",
+ "subqueryload_all(props...)". [ticket:1675]
+ - To accomodate the fact that there are now two kinds of eager
+ loading available, the new names for eagerload() and
+ eagerload_all() are joinedload() and joinedload_all(). The
+ old names will remain as synonyms for the foreseeable future.
+ - The "lazy" flag on the relationship() function now accepts
+ a string argument for all kinds of loading: "select", "joined",