=======
CHANGES
=======
+
0.5beta4
========
+
- orm
- - The RowTuple object returned by Query(*cols) now
- features keynames which prefer mapped attribute
- names over column keys, column keys over
- column names, i.e.
- Query(Class.foo, Class.bar) will have names
- "foo" and "bar" even if those are not the names
- of the underlying Column objects. Direct
- Column objects such as Query(table.c.col) will
- return the "key" attribute of the Column.
-
- - Improved the determination of the FROM clause
- when placing SQL expressions in the query()
- list of entities. In particular scalar subqueries
- should not "leak" their inner FROM objects out
- into the enclosing query.
-
- - joins along a relation() from a mapped
- class to a mapped subclass, where the mapped
- subclass is configured with single table
- inheritance, will include an
- IN clause which limits the subtypes of the
- joined class to those requsted, within the
- ON clause of the join. This takes effect for
- eager load joins as well as query.join().
- Note that in some scenarios the IN clause will
- appear in the WHERE clause of the query
- as well since this discrimination has multiple
- trigger points.
-
- - Improved the behavior of query.join()
- when joining to joined-table inheritance
- subclasses, using explicit join criteria
- (i.e. not on a relation).
-
- - Fixed @on_reconsitute hook for subclasses
- which inherit from a base class.
- [ticket:1129]
-
- - The composite() property type now supports
- a __set_composite_values__() method on the composite
- class which is required if the class represents
- state using attribute names other than the
- column's keynames; default-generated values now
- get populated properly upon flush. Also,
- composites with attributes set to None compare
- correctly. [ticket:1132]
-
+ - The RowTuple object returned by Query(*cols) now features
+ keynames which prefer mapped attribute names over column keys,
+ column keys over column names, i.e. Query(Class.foo,
+ Class.bar) will have names "foo" and "bar" even if those are
+ not the names of the underlying Column objects. Direct Column
+ objects such as Query(table.c.col) will return the "key"
+ attribute of the Column.
+
+ - Improved the determination of the FROM clause when placing SQL
+ expressions in the query() list of entities. In particular
+ scalar subqueries should not "leak" their inner FROM objects
+ out into the enclosing query.
+
+ - joins along a relation() from a mapped class to a mapped
+ subclass, where the mapped subclass is configured with single
+ table inheritance, will include an IN clause which limits the
+ subtypes of the joined class to those requsted, within the ON
+ clause of the join. This takes effect for eager load joins as
+ well as query.join(). Note that in some scenarios the IN
+ clause will appear in the WHERE clause of the query as well
+ since this discrimination has multiple trigger points.
+
+ - Improved the behavior of query.join() when joining to
+ joined-table inheritance subclasses, using explicit join
+ criteria (i.e. not on a relation).
+
+ - Fixed @on_reconsitute hook for subclasses which inherit from a
+ base class. [ticket:1129]
+
+ - The composite() property type now supports a
+ __set_composite_values__() method on the composite class which
+ is required if the class represents state using attribute
+ names other than the column's keynames; default-generated
+ values now get populated properly upon flush. Also,
+ composites with attributes set to None compare correctly.
+ [ticket:1132]
+
- sql
- - Temporarily rolled back the "ORDER BY" enhancement
- from [ticket:1068]. This feature is on hold
- pending further development.
+ - Temporarily rolled back the "ORDER BY" enhancement from
+ [ticket:1068]. This feature is on hold pending further
+ development.
0.5beta3
========
- - 0.5beta3 includes all bugfixes listed under release
- "0.4.7".
+
+0.5beta3 includes all bugfixes listed under release "0.4.7".
- orm
- - The "entity_name" feature of SQLAlchemy mappers
- has been removed. For rationale, see
- http://tinyurl.com/6nm2ne
-
- - the "autoexpire" flag on Session, sessionmaker(),
- and scoped_session() has been renamed to
- "expire_on_commit". It does not affect
- the expiration behavior of rollback().
-
- - fixed endless loop bug which could occur
- within a mapper's deferred load of
- inherited attributes.
-
- - a legacy-support flag
- "_enable_transation_accounting" flag added
- to Session which when False, disables
- all transaction-level object accounting,
- including expire on rollback, expire
- on commit, new/deleted
- list maintenance, and autoflush on begin.
-
- - The 'cascade' parameter to relation() accepts None
- as a value, which is equivalent to no cascades.
-
- - A critical fix to dynamic relations allows the
- "modified" history to be properly cleared after
- a flush().
-
- - user-defined @properties on a class are detected
- and left in place during mapper initialization.
- This means that a table-bound column of the same
- name will not be mapped at all if a @property is
- in the way (and the column is not remapped to
- a different name), nor will an instrumented attribute
- from an inherited class be applied. The same
- rules apply for names excluded using the
- include_properties/exclude_properties collections.
-
- - Added a new SessionExtension hook called after_attach().
- This is called at the point of attachment for objects
- via add(), add_all(), delete(), and merge().
-
- - A mapper which inherits from another, when inheriting
- the columns of its inherited mapper, will use any
- reassigned property names specified in that inheriting
- mapper. Previously, if "Base" had reassigned "base_id"
- to the name "id", "SubBase(Base)" would still get
- an attribute called "base_id". This could be worked
- around by explicitly stating the column in each
- submapper as well but this is fairly unworkable
- and also impossible when using declarative [ticket:1111].
-
- - Fixed a series of potential race conditions in
- Session whereby asynchronous GC could remove unmodified,
- no longer referenced items from the session as they were
- present in a list of items to be processed, typically
- during session.expunge_all() and dependent methods.
-
- - Some improvements to the _CompileOnAttr mechanism which
- should reduce the probability of "Attribute x was
- not replaced during compile" warnings. (this generally
- applies to SQLA hackers, like Elixir devs).
-
- - Fixed bug whereby the "unsaved, pending instance"
- FlushError raised for a pending orphan would not take
- superclass mappers into account when generating
- the list of relations responsible for the error.
+ - The "entity_name" feature of SQLAlchemy mappers has been
+ removed. For rationale, see http://tinyurl.com/6nm2ne
+
+ - the "autoexpire" flag on Session, sessionmaker(), and
+ scoped_session() has been renamed to "expire_on_commit". It
+ does not affect the expiration behavior of rollback().
+
+ - fixed endless loop bug which could occur within a mapper's
+ deferred load of inherited attributes.
+
+ - a legacy-support flag "_enable_transation_accounting" flag
+ added to Session which when False, disables all
+ transaction-level object accounting, including expire on
+ rollback, expire on commit, new/deleted list maintenance, and
+ autoflush on begin.
+
+ - The 'cascade' parameter to relation() accepts None as a value,
+ which is equivalent to no cascades.
+
+ - A critical fix to dynamic relations allows the "modified"
+ history to be properly cleared after a flush().
+
+ - user-defined @properties on a class are detected and left in
+ place during mapper initialization. This means that a
+ table-bound column of the same name will not be mapped at all
+ if a @property is in the way (and the column is not remapped
+ to a different name), nor will an instrumented attribute from
+ an inherited class be applied. The same rules apply for names
+ excluded using the include_properties/exclude_properties
+ collections.
+
+ - Added a new SessionExtension hook called after_attach(). This
+ is called at the point of attachment for objects via add(),
+ add_all(), delete(), and merge().
+
+ - A mapper which inherits from another, when inheriting the
+ columns of its inherited mapper, will use any reassigned
+ property names specified in that inheriting mapper.
+ Previously, if "Base" had reassigned "base_id" to the name
+ "id", "SubBase(Base)" would still get an attribute called
+ "base_id". This could be worked around by explicitly stating
+ the column in each submapper as well but this is fairly
+ unworkable and also impossible when using declarative
+ [ticket:1111].
+
+ - Fixed a series of potential race conditions in Session whereby
+ asynchronous GC could remove unmodified, no longer referenced
+ items from the session as they were present in a list of items
+ to be processed, typically during session.expunge_all() and
+ dependent methods.
+
+ - Some improvements to the _CompileOnAttr mechanism which should
+ reduce the probability of "Attribute x was not replaced during
+ compile" warnings. (this generally applies to SQLA hackers,
+ like Elixir devs).
+
+ - Fixed bug whereby the "unsaved, pending instance" FlushError
+ raised for a pending orphan would not take superclass mappers
+ into account when generating the list of relations responsible
+ for the error.
- sql
- - func.count() with no arguments renders as COUNT(*),
- equivalent to func.count(text('*')).
-
- - simple label names in ORDER BY expressions render as
- themselves, and not as a re-statement of their
- corresponding expression. This feature is currently
- enabled only for SQLite, MySQL, and Postgres.
- It can be enabled on other dialects as each is shown
- to support this behavior. [ticket:1068]
-
+ - func.count() with no arguments renders as COUNT(*), equivalent
+ to func.count(text('*')).
+
+ - simple label names in ORDER BY expressions render as
+ themselves, and not as a re-statement of their corresponding
+ expression. This feature is currently enabled only for
+ SQLite, MySQL, and Postgres. It can be enabled on other
+ dialects as each is shown to support this
+ behavior. [ticket:1068]
+
- ext
- - Class-bound attributes sent as arguments to
- relation()'s remote_side and foreign_keys parameters
- are now accepted, allowing them to be used with declarative.
- Additionally fixed bugs involving order_by being
- specified as a class-bound attribute in conjunction
- with eager loading.
-
+ - Class-bound attributes sent as arguments to relation()'s
+ remote_side and foreign_keys parameters are now accepted,
+ allowing them to be used with declarative. Additionally fixed
+ bugs involving order_by being specified as a class-bound
+ attribute in conjunction with eager loading.
+
- declarative initialization of Columns adjusted so that
non-renamed columns initialize in the same way as a non
- declarative mapper. This allows an inheriting mapper
- to set up its same-named "id" columns in particular
- such that the parent "id" column is favored over the child
- column, reducing database round trips when this value
- is requested.
-
+ declarative mapper. This allows an inheriting mapper to set
+ up its same-named "id" columns in particular such that the
+ parent "id" column is favored over the child column, reducing
+ database round trips when this value is requested.
+
- mysql
- Quoting of MSEnum values for use in CREATE TABLE is now
optional & will be quoted on demand as required. (Quoting was
0.5beta2
========
- - 0.5beta2 includes some of the bugfixes listed under
- release "0.4.7".
+
+0.5beta2 includes some of the bugfixes listed under release "0.4.7".
- orm
- - In addition to expired attributes, deferred attributes
- also load if their data is present in the result set.
- [ticket:870]
-
- - session.refresh() raises an informative error message if
- the list of attributes does not include any column-based
+ - In addition to expired attributes, deferred attributes also
+ load if their data is present in the result set. [ticket:870]
+
+ - session.refresh() raises an informative error message if the
+ list of attributes does not include any column-based
attributes.
-
- - query() raises an informative error message if no columns
- or mappers are specified.
-
+
+ - query() raises an informative error message if no columns or
+ mappers are specified.
+
- lazy loaders now trigger autoflush before proceeding. This
- allows expire() of a collection or scalar relation to
- function properly in the context of autoflush.
-
+ allows expire() of a collection or scalar relation to function
+ properly in the context of autoflush.
+
- column_property() attributes which represent SQL expressions
- or columns that are not present in the mapped tables
- (such as those from views) are automatically expired
- after an INSERT or UPDATE, assuming they have not been
- locally modified, so that they are refreshed with the
- most recent data upon access. [ticket:887]
+ or columns that are not present in the mapped tables (such as
+ those from views) are automatically expired after an INSERT or
+ UPDATE, assuming they have not been locally modified, so that
+ they are refreshed with the most recent data upon access.
+ [ticket:887]
- - Fixed explicit, self-referential joins between two
- joined-table inheritance mappers when using
- query.join(cls, aliased=True). [ticket:1082]
+ - Fixed explicit, self-referential joins between two
+ joined-table inheritance mappers when using query.join(cls,
+ aliased=True). [ticket:1082]
- Fixed query.join() when used in conjunction with a
- columns-only clause and an SQL-expression
- ON clause in the join.
-
- - The "allow_column_override" flag from mapper() has
- been removed. This flag is virtually always misunderstood.
- Its specific functionality is available via the
+ columns-only clause and an SQL-expression ON clause in the
+ join.
+
+ - The "allow_column_override" flag from mapper() has been
+ removed. This flag is virtually always misunderstood. Its
+ specific functionality is available via the
include_properties/exclude_properties mapper arguments.
-
+
- Repaired `__str__()` method on Query. [ticket:1066]
- Session.bind gets used as a default even when table/mapper
specific binds are defined.
- schema
- - Added prefixes option to `Table` that accepts a list of
+ - Added prefixes option to `Table` that accepts a list of
strings to insert after CREATE in the CREATE TABLE statement.
[ticket:1075]
backends.
- sqlite
- - Modified SQLite's representation of "microseconds" to
- match the output of str(somedatetime), i.e. in that the
- microseconds are represented as fractional seconds in
- string format. This makes SQLA's SQLite date type
- compatible with datetimes that were saved directly
- using Pysqlite (which just calls str()).
+ - Modified SQLite's representation of "microseconds" to match
+ the output of str(somedatetime), i.e. in that the microseconds
+ are represented as fractional seconds in string format. This
+ makes SQLA's SQLite date type compatible with datetimes that
+ were saved directly using Pysqlite (which just calls str()).
Note that this is incompatible with the existing microseconds
values in a SQLA 0.4 generated SQLite database file.
-
+
To get the old behavior globally:
-
+
from sqlalchemy.databases.sqlite import DateTimeMixin
DateTimeMixin.__legacy_microseconds__ = True
-
+
To get the behavior on individual DateTime types:
-
+
t = sqlite.SLDateTime()
t.__legacy_microseconds__ = True
-
+
Then use "t" as the type on the Column.
-
+
[ticket:1090]
- SQLite Date, DateTime, and Time types only accept Python
datetime objects now, not strings. If you'd like to format
- dates as strings yourself with SQLite, use a String type.
- If you'd like them to return datetime objects anyway despite
- their accepting strings as input, make a TypeDecorator around
+ dates as strings yourself with SQLite, use a String type. If
+ you'd like them to return datetime objects anyway despite
+ their accepting strings as input, make a TypeDecorator around
String - SQLA doesn't encourage this pattern.
- extensions
- - Declarative supports a __table_args__ class variable, which
- is either a dictionary, or tuple of the form
- (arg1, arg2, ..., {kwarg1:value, ...}) which contains
- positional + kw arguments to be passed to the Table
- constructor. [ticket:1096]
-
+ - Declarative supports a __table_args__ class variable, which is
+ either a dictionary, or tuple of the form (arg1, arg2, ...,
+ {kwarg1:value, ...}) which contains positional + kw arguments
+ to be passed to the Table constructor. [ticket:1096]
+
0.5beta1
========
- - An ongoing document describing the changes from 0.4 to 0.5
- is at: http://www.sqlalchemy.org/trac/wiki/05Migration
- For this section, the list below primarily lists changes
- within the attribute instrumentation API and is only a
- small fraction of the full changes between 0.4/0.5.
+An ongoing document describing the changes from 0.4 to 0.5 is at:
+http://www.sqlalchemy.org/trac/wiki/05Migration
+
+For this section, the list below primarily lists changes within the
+attribute instrumentation API and is only a small fraction of the
+full changes between 0.4/0.5.
+-orm
- The "__init__" trigger/decorator added by mapper now attempts
to exactly mirror the argument signature of the original
__init__. The pass-through for '_sa_session' is no longer
that multiple contains() calls will not conflict
with each other [ticket:1058]
- - fixed bug preventing merge() from functioning in
+ - fixed bug preventing merge() from functioning in
conjunction with a comparable_property()
- the enable_typechecks=False setting on relation()
- now only allows subtypes with inheriting mappers.
+ now only allows subtypes with inheriting mappers.
Totally unrelated types, or subtypes not set up with
- mapper inheritance against the target mapper are
+ mapper inheritance against the target mapper are
still not allowed.
- - Added is_active flag to Sessions to detect when
+ - Added is_active flag to Sessions to detect when
a transaction is in progress [ticket:976]. This
- flag is always True with a "transactional"
+ flag is always True with a "transactional"
(in 0.5 a non-"autocommit") Session.
- sql
- Fixed bug when calling select([literal('foo')])
or select([bindparam('foo')]).
-
+
- schema
- create_all(), drop_all(), create(), drop() all raise
an error if the table name or schema name contains
long name cannot be explicitly dropped with
Index.drop(), similar to [ticket:571].
[ticket:820]
-
+
- postgres
- - Repaired server_side_cursors to properly detect
+ - Repaired server_side_cursors to properly detect
text() clauses.
- - Added PGCidr type. [ticket:1092]
+ - Added PGCidr type. [ticket:1092]
- mysql
- Added 'CALL' to the list of SQL keywords which return
in other owner namespaces with the same name do not
conflict [ticket:709]
- - Cursors now have "arraysize" set to 50 by default on
- them, the value of which is configurable using the
+ - Cursors now have "arraysize" set to 50 by default on
+ them, the value of which is configurable using the
"arraysize" argument to create_engine() with the
- Oracle dialect. This to account for cx_oracle's default
- setting of "1", which has the effect of many round trips
- being sent to Oracle. This actually works well in
- conjunction with BLOB/CLOB-bound cursors, of which
- there are any number available but only for the life of
- that row request (so BufferedColumnRow is still needed,
+ Oracle dialect. This to account for cx_oracle's default
+ setting of "1", which has the effect of many round trips
+ being sent to Oracle. This actually works well in
+ conjunction with BLOB/CLOB-bound cursors, of which
+ there are any number available but only for the life of
+ that row request (so BufferedColumnRow is still needed,
but less so). [ticket:1062]
- sqlite
- - add SLFloat type, which matches the SQLite REAL
+ - add SLFloat type, which matches the SQLite REAL
type affinity. Previously, only SLNumeric was provided
- which fulfills NUMERIC affinity, but that's not the
+ which fulfills NUMERIC affinity, but that's not the
same as REAL.
0.4.6
generation to handle placing bind params inside of
functions and other expressions. (partial progress
towards [ticket:610])
-
- - repaired single table inheritance such that you
+
+ - repaired single table inheritance such that you
can single-table inherit from a joined-table inherting
mapper without issue [ticket:1036].
-
+
- Fixed "concatenate tuple" bug which could occur with
Query.order_by() if clause adaption had taken place.
[ticket:1027]
-
+
- Removed ancient assertion that mapped selectables require
"alias names" - the mapper creates its own alias now if
none is present. Though in this case you need to use the
class, not the mapped selectable, as the source of column
attributes - so a warning is still issued.
- - fixes to the "exists" function involving inheritance (any(),
- has(), ~contains()); the full target join will be rendered
+ - fixes to the "exists" function involving inheritance (any(),
+ has(), ~contains()); the full target join will be rendered
into the EXISTS clause for relations that link to subclasses.
-
- - restored usage of append_result() extension method for primary
+
+ - restored usage of append_result() extension method for primary
query rows, when the extension is present and only a single-
entity result is being returned.
-
+
- Also re-established viewonly relation() configurations that
join across multiple tables.
-
+
- removed ancient assertion that mapped selectables require
"alias names" - the mapper creates its own alias now if
- none is present. Though in this case you need to use
+ none is present. Though in this case you need to use
the class, not the mapped selectable, as the source of
column attributes - so a warning is still issued.
-
+
- refined mapper._save_obj() which was unnecessarily calling
__ne__() on scalar values during flush [ticket:1015]
-
+
- added a feature to eager loading whereby subqueries set
as column_property() with explicit label names (which is not
necessary, btw) will have the label anonymized when
the instance is part of the eager join, to prevent
- conflicts with a subquery or column of the same name
+ conflicts with a subquery or column of the same name
on the parent object. [ticket:1019]
-
+
- set-based collections |=, -=, ^= and &= are stricter about
their operands and only operate on sets, frozensets or
subclasses of the collection type. Previously, they would
accept any duck-typed set.
-
+
- added an example dynamic_dict/dynamic_dict.py, illustrating
- a simple way to place dictionary behavior on top of
+ a simple way to place dictionary behavior on top of
a dynamic_loader.
- declarative extension
- Joined table inheritance mappers use a slightly relaxed
function to create the "inherit condition" to the parent
- table, so that other foreign keys to not-yet-declared
+ table, so that other foreign keys to not-yet-declared
Table objects don't trigger an error.
-
- - fixed reentrant mapper compile hang when
- a declared attribute is used within ForeignKey,
+
+ - fixed reentrant mapper compile hang when
+ a declared attribute is used within ForeignKey,
ie. ForeignKey(MyOtherClass.someattribute)
-
+
- sql
- Added COLLATE support via the .collate(<collation>)
expression operator and collate(<expr>, <collation>) sql
- Fixed bug with union() when applied to non-Table connected
select statements
- - improved behavior of text() expressions when used as
+ - improved behavior of text() expressions when used as
FROM clauses, such as select().select_from(text("sometext"))
[ticket:1014]
- Column.copy() respects the value of "autoincrement",
fixes usage with Migrate [ticket:1021]
-
+
- engines
- Pool listeners can now be provided as a dictionary of
callables or a (possibly partial) duck-type of
PoolListener, your choice.
-
- - added "rollback_returned" option to Pool which will
- disable the rollback() issued when connections are
+
+ - added "rollback_returned" option to Pool which will
+ disable the rollback() issued when connections are
returned. This flag is only safe to use with a database
which does not support transactions (i.e. MySQL/MyISAM).
- Added comparable_property(), adds query Comparator
behavior to regular, unmanaged Python properties
- - the functionality of query.with_polymorphic() has
- been added to mapper() as a configuration option.
+ - the functionality of query.with_polymorphic() has
+ been added to mapper() as a configuration option.
It's set via several forms:
with_polymorphic='*'
with_polymorphic=[mappers]
with_polymorphic=('*', selectable)
with_polymorphic=([mappers], selectable)
-
+
This controls the default polymorphic loading strategy
for inherited mappers. When a selectable is not given,
outer joins are created for all joined-table inheriting
mappers requested. Note that the auto-create of joins
is not compatible with concrete table inheritance.
- The existing select_table flag on mapper() is now
- deprecated and is synonymous with
+ The existing select_table flag on mapper() is now
+ deprecated and is synonymous with
with_polymorphic('*', select_table). Note that the
- underlying "guts" of select_table have been
+ underlying "guts" of select_table have been
completely removed and replaced with the newer,
- more flexible approach.
-
+ more flexible approach.
+
The new approach also automatically allows eager loads
to work for subclasses, if they are present, for
example
Engineers. A "with_polymorphic" Query option should be
introduced soon as well which would allow per-Query
control of with_polymorphic() on relations.
-
- - added two "experimental" features to Query,
+
+ - added two "experimental" features to Query,
"experimental" in that their specific name/behavior
is not carved in stone just yet: _values() and
_from_self(). We'd like feedback on these.
-
+
- _values(*columns) is given a list of column
expressions, and returns a new Query that only
returns those columns. When evaluated, the return
that "entity zero", i.e. the mapped class, is not
included in the results. This means it finally makes
sense to use group_by() and having() on Query, which
- have been sitting around uselessly until now.
-
+ have been sitting around uselessly until now.
+
A future change to this method may include that its
ability to join, filter and allow other options not
related to a "resultset" are removed, so the feedback
except that you can quickly create highly nested
queries that are less efficient, and we want feedback
on the naming choice.
-
+
- query.order_by() and query.group_by() will accept
- multiple arguments using *args (like select()
+ multiple arguments using *args (like select()
already does).
-
+
- Added some convenience descriptors to Query:
query.statement returns the full SELECT construct,
query.whereclause returns just the WHERE part of the
- Delete cascade with delete-orphan will delete orphans
whether or not it remains attached to its also-deleted
parent.
-
+
- delete-orphan casacde is properly detected on relations
that are present on superclasses when using inheritance.
ahead of the tablename in all column expressions as well
as when generating column labels. This prevents cross-
schema name collisions in all cases [ticket:999]
-
+
- can now allow selects which correlate all FROM clauses
and have no FROM themselves. These are typically
used in a scalar context, i.e. SELECT x, (SELECT x WHERE y)
FROM table. Requires explicit correlate() call.
-
+
- 'name' is no longer a required constructor argument for
Column(). It (and .key) may now be deferred until the
column is added to a Table.
- inheritance in declarative can be disabled when sending
"inherits=None" to __mapper_args__.
- - declarative_base() takes optional kwarg "mapper", which
+ - declarative_base() takes optional kwarg "mapper", which
is any callable/class/method that produces a mapper,
such as declarative_base(mapper=scopedsession.mapper).
This property can also be set on individual declarative
behavior than before which is why it's off by default.
- mssql
- - Reflected tables will now automatically load other tables
+ - Reflected tables will now automatically load other tables
which are referenced by Foreign keys in the auto-loaded
- table, [ticket:979].
+ table, [ticket:979].
- Added executemany check to skip identity fetch, [ticket:916].
- The proper error message is raised when trying to access
expired instance attributes with no session present
-
+
- dynamic_loader() / lazy="dynamic" now accepts and uses
the order_by parameter in the same way in which it works
with relation().
-
+
- Added expire_all() method to Session. Calls expire() for
all persistent instances. This is handy in conjunction
with...
new collection to a collection-based attribute which
already had pending changes would generate incorrect
history [ticket:922]
-
+
- fixed delete-orphan cascade bug whereby setting the
same object twice to a scalar attribute could log it
as an orphan [ticket:925]
-
+
- Fixed cascades on a += assignment to a list-based
relation.
-
+
- synonyms can now be created against props that don't
exist yet, which are later added via add_property().
This commonly includes backrefs. (i.e. you can make
- fixed bug which could occur with polymorphic "union"
mapper which falls back to "deferred" loading of
inheriting tables
-
+
- the "columns" collection on a mapper/mapped class
(i.e. 'c') is against the mapped table, not the
select_table in the case of polymorphic "union"
loading (this shouldn't be noticeable).
-
+
- ext
- '+', '*', '+=' and '*=' support for association
proxied lists.
- orm
- fixed fairly critical bug whereby the same instance could be listed
more than once in the unitofwork.new collection; most typically
- reproduced when using a combination of inheriting mappers and
+ reproduced when using a combination of inheriting mappers and
ScopedSession.mapper, as the multiple __init__ calls per instance
could save() the object with distinct _state objects
- added very rudimentary yielding iterator behavior to Query. Call
- query.yield_per(<number of rows>) and evaluate the Query in an
+ query.yield_per(<number of rows>) and evaluate the Query in an
iterative context; every collection of N rows will be packaged up
and yielded. Use this method with extreme caution since it does
not attempt to reconcile eagerly loaded collections across
reconnect after its underlying connection is invalidated, without
needing to connect() again from the engine. This allows an ORM session
bound to a single Connection to not need a reconnect.
- Open transactions on the Connection must be rolled back after an invalidation
+ Open transactions on the Connection must be rolled back after an invalidation
of the underlying connection else an error is raised. Also fixed
bug where disconnect detect was not being called for cursor(), rollback(),
or commit().
-
+
- added new flag to String and create_engine(),
assert_unicode=(True|False|'warn'|None). Defaults to `False` or `None` on
create_engine() and String, `'warn'` on the Unicode type. When `True`,
results in all unicode conversion operations raising an exception when a
non-unicode bytestring is passed as a bind parameter. 'warn' results
- in a warning. It is strongly advised that all unicode-aware applications
+ in a warning. It is strongly advised that all unicode-aware applications
make proper use of Python unicode objects (i.e. u'hello' and not 'hello')
so that data round trips accurately.
user code, except any code that might have been hardcoded against the generated
names. Generated bind params now have the form "<paramname>_<num>",
whereas before only the second bind of the same name would have this form.
-
+
- select().as_scalar() will raise an exception if the select does not have
exactly one expression in its columns clause.
-
+
- bindparam() objects themselves can be used as keys for execute(), i.e.
statement.execute({bind1:'foo', bind2:'bar'})
-
+
- added new methods to TypeDecorator, process_bind_param() and
process_result_value(), which automatically take advantage of the processing
of the underlying type. Ideal for using with Unicode or Pickletype.
- selectables (and others) will issue a warning when two columns in
their exported columns collection conflict based on name.
-
+
- tables with schemas can still be used in sqlite, firebird,
schema name just gets dropped [ticket:890]
- changed the various "literal" generation functions to use an anonymous
- bind parameter. not much changes here except their labels now look
+ bind parameter. not much changes here except their labels now look
like ":param_1", ":param_2" instead of ":literal"
-
+
- column labels in the form "tablename.columname", i.e. with a dot, are now
supported.
-
+
- from_obj keyword argument to select() can be a scalar or a list.
-
+
- orm
- - a major behavioral change to collection-based backrefs: they no
- longer trigger lazy loads ! "reverse" adds and removes
- are queued up and are merged with the collection when it is
+ - a major behavioral change to collection-based backrefs: they no
+ longer trigger lazy loads ! "reverse" adds and removes
+ are queued up and are merged with the collection when it is
actually read from and loaded; but do not trigger a load beforehand.
For users who have noticed this behavior, this should be much more
- convenient than using dynamic relations in some cases; for those who
+ convenient than using dynamic relations in some cases; for those who
have not, you might notice your apps using a lot fewer queries than
before in some situations. [ticket:871]
- inheriting mappers now inherit the MapperExtensions of their parent
mapper directly, so that all methods for a particular MapperExtension
- are called for subclasses as well. As always, any MapperExtension
+ are called for subclasses as well. As always, any MapperExtension
can return either EXT_CONTINUE to continue extension processing
or EXT_STOP to stop processing. The order of mapper resolution is:
<extensions declared on the classes mapper> <extensions declared on the
classes' parent mapper> <globally declared extensions>.
-
- Note that if you instantiate the same extension class separately
- and then apply it individually for two mappers in the same inheritance
+
+ Note that if you instantiate the same extension class separately
+ and then apply it individually for two mappers in the same inheritance
chain, the extension will be applied twice to the inheriting class,
and each method will be called twice.
-
+
To apply a mapper extension explicitly to each inheriting class but
- have each method called only once per operation, use the same
+ have each method called only once per operation, use the same
instance of the extension for both mappers.
[ticket:490]
- MapperExtension.before_update() and after_update() are now called
symmetrically; previously, an instance that had no modified column
- attributes (but had a relation() modification) could be called with
+ attributes (but had a relation() modification) could be called with
before_update() but not after_update() [ticket:907]
-
+
- columns which are missing from a Query's select statement
now get automatically deferred during load.
- - mapped classes which extend "object" and do not provide an
- __init__() method will now raise TypeError if non-empty *args
- or **kwargs are present at instance construction time (and are
- not consumed by any extensions such as the scoped_session mapper),
+ - mapped classes which extend "object" and do not provide an
+ __init__() method will now raise TypeError if non-empty *args
+ or **kwargs are present at instance construction time (and are
+ not consumed by any extensions such as the scoped_session mapper),
consistent with the behavior of normal Python classes [ticket:908]
-
+
- fixed Query bug when filter_by() compares a relation against None
[ticket:899]
-
+
- improved support for pickling of mapped entities. Per-instance
lazy/deferred/expired callables are now serializable so that
- they serialize and deserialize with _state.
-
+ they serialize and deserialize with _state.
+
- new synonym() behavior: an attribute will be placed on the mapped
class, if one does not exist already, in all cases. if a property
already exists on the class, the synonym will decorate the property
- Query.select_from() now replaces all existing FROM criterion with
the given argument; the previous behavior of constructing a list
- of FROM clauses was generally not useful as is required
+ of FROM clauses was generally not useful as is required
filter() calls to create join criterion, and new tables introduced
within filter() already add themselves to the FROM clause. The
- new behavior allows not just joins from the main table, but select
+ new behavior allows not just joins from the main table, but select
statements as well. Filter criterion, order bys, eager load
clauses will be "aliased" against the given statement.
-
+
- this month's refactoring of attribute instrumentation changes
the "copy-on-load" behavior we've had since midway through 0.3
with "copy-on-modify" in most cases. This takes a sizable chunk
of latency out of load operations and overall does less work
- as only attributes which are actually modified get their
+ as only attributes which are actually modified get their
"committed state" copied. Only "mutable scalar" attributes
- (i.e. a pickled object or other mutable item), the reason for
- the copy-on-load change in the first place, retain the old
+ (i.e. a pickled object or other mutable item), the reason for
+ the copy-on-load change in the first place, retain the old
behavior.
-
+
- a slight behavioral change to attributes is, del'ing an attribute
does *not* cause the lazyloader of that attribute to fire off again;
the "del" makes the effective value of the attribute "None". To
- re-trigger the "loader" for an attribute, use
+ re-trigger the "loader" for an attribute, use
session.expire(instance, [attrname]).
-
+
- query.filter(SomeClass.somechild == None), when comparing
a many-to-one property to None, properly generates "id IS NULL"
including that the NULL is on the right side.
- query.order_by() takes into account aliased joins, i.e.
query.join('orders', aliased=True).order_by(Order.id)
-
- - eagerload(), lazyload(), eagerload_all() take an optional
+
+ - eagerload(), lazyload(), eagerload_all() take an optional
second class-or-mapper argument, which will select the mapper
to apply the option towards. This can select among other
- mappers which were added using add_entity().
+ mappers which were added using add_entity().
- eagerloading will work with mappers added via add_entity().
-
+
- added "cascade delete" behavior to "dynamic" relations just like
that of regular relations. if passive_deletes flag (also just added)
- is not set, a delete of the parent item will trigger a full load of
+ is not set, a delete of the parent item will trigger a full load of
the child items so that they can be deleted or updated accordingly.
- also with dynamic, implemented correct count() behavior as well
as other helper methods.
-
+
- fix to cascades on polymorphic relations, such that cascades
- from an object to a polymorphic collection continue cascading
+ from an object to a polymorphic collection continue cascading
along the set of attributes specific to each element in the collection.
-
+
- query.get() and query.load() do not take existing filter or other
criterion into account; these methods *always* look up the given id
- in the database or return the current instance from the identity map,
+ in the database or return the current instance from the identity map,
disregarding any existing filter, join, group_by or other criterion
which has been configured. [ticket:893]
-
+
- added support for version_id_col in conjunction with inheriting mappers.
version_id_col is typically set on the base mapper in an inheritance
- relationship where it takes effect for all inheriting mappers.
+ relationship where it takes effect for all inheriting mappers.
[ticket:883]
-
+
- relaxed rules on column_property() expressions having labels; any
ColumnElement is accepted now, as the compiler auto-labels non-labeled
ColumnElements now. a selectable, like a select() statement, still
- fixed backref bug where you could not del instance.attr if attr
was None
-
+
- several ORM attributes have been removed or made private:
- mapper.get_attr_by_column(), mapper.set_attr_by_column(),
- mapper.pks_by_table, mapper.cascade_callable(),
+ mapper.get_attr_by_column(), mapper.set_attr_by_column(),
+ mapper.pks_by_table, mapper.cascade_callable(),
MapperProperty.cascade_callable(), mapper.canload(),
- mapper.save_obj(), mapper.delete_obj(), mapper._mapper_registry,
+ mapper.save_obj(), mapper.delete_obj(), mapper._mapper_registry,
attributes.AttributeManager
- Assigning an incompatible collection type to a relation attribute now
The MappedCollection uses this hook to ensure that incoming key/value
pairs are sane from the collection's perspective.
- - fixed endless loop issue when using lazy="dynamic" on both
+ - fixed endless loop issue when using lazy="dynamic" on both
sides of a bi-directional relationship [ticket:872]
- more fixes to the LIMIT/OFFSET aliasing applied with Query + eagerloads,
in this case when mapped against a select statement [ticket:904]
-
+
- fix to self-referential eager loading such that if the same mapped
instance appears in two or more distinct sets of columns in the same
result set, its eagerly loaded collection will be populated regardless
of whether or not all of the rows contain a set of "eager" columns for
that collection. this would also show up as a KeyError when fetching
results with join_depth turned on.
-
+
- fixed bug where Query would not apply a subquery to the SQL when LIMIT
- was used in conjunction with an inheriting mapper where the eager
+ was used in conjunction with an inheriting mapper where the eager
loader was only in the parent mapper.
-
+
- clarified the error message which occurs when you try to update()
an instance with the same identity key as an instance already present
in the session.
- - some clarifications and fixes to merge(instance, dont_load=True).
+ - some clarifications and fixes to merge(instance, dont_load=True).
fixed bug where lazy loaders were getting disabled on returned instances.
Also, we currently do not support merging an instance which has uncommitted
changes on it, in the case that dont_load=True is used....this will
- now raise an error. This is due to complexities in merging the
+ now raise an error. This is due to complexities in merging the
"committed state" of the given instance to correctly correspond to the
- newly copied instance, as well as other modified state.
- Since the use case for dont_load=True is caching, the given instances
+ newly copied instance, as well as other modified state.
+ Since the use case for dont_load=True is caching, the given instances
shouldn't have any uncommitted changes on them anyway.
We also copy the instances over without using any events now, so that
the 'dirty' list on the new session remains unaffected.
- fixed bug which could arise when using session.begin_nested() in conjunction
with more than one level deep of enclosing session.begin() statements
- - fixed session.refresh() with instance that has custom entity_name
+ - fixed session.refresh() with instance that has custom entity_name
[ticket:914]
-
+
- dialects
- - sqlite SLDate type will not erroneously render "microseconds" portion
+ - sqlite SLDate type will not erroneously render "microseconds" portion
of a datetime or time object.
-
+
- oracle
- added disconnect detection support for Oracle
- some cleanup to binary/raw types so that cx_oracle.LOB is detected
on an ad-hoc basis [ticket:902]
-
+
- MSSQL
- PyODBC no longer has a global "set nocount on".
- Fix non-identity integer PKs on autload [ticket:824]
- sql
- - the "shortname" keyword parameter on bindparam() has been
+ - the "shortname" keyword parameter on bindparam() has been
deprecated.
-
+
- Added contains operator (generates a "LIKE %<other>%" clause).
- - anonymous column expressions are automatically labeled.
+ - anonymous column expressions are automatically labeled.
e.g. select([x* 5]) produces "SELECT x * 5 AS anon_1".
This allows the labelname to be present in the cursor.description
which can then be appropriately matched to result-column processing
- rules. (we can't reliably use positional tracking for result-column
+ rules. (we can't reliably use positional tracking for result-column
matches since text() expressions may represent multiple columns).
-
- - operator overloading is now controlled by TypeEngine objects - the
+
+ - operator overloading is now controlled by TypeEngine objects - the
one built-in operator overload so far is String types overloading
'+' to be the string concatenation operator.
User-defined types can also define their own operator overloading
by overriding the adapt_operator(self, op) method.
-
+
- untyped bind parameters on the right side of a binary expression
will be assigned the type of the left side of the operation, to better
enable the appropriate bind parameter processing to take effect
[ticket:819]
-
+
- Removed regular expression step from most statement compilations.
Also fixes [ticket:833]
selectable expressions. On the SQL side this is represented by the
"corresponding_column()" method. This method is used heavily by the ORM
to "adapt" elements of an expression to similar, aliased expressions,
- as well as to target result set columns originally bound to a
+ as well as to target result set columns originally bound to a
table or selectable to an aliased, "corresponding" expression. The new
rewrite features completely consistent and accurate behavior.
- Added a field ("info") for storing arbitrary data on schema items
- [ticket:573]
+ [ticket:573]
- The "properties" collection on Connections has been renamed "info" to
match schema's writable collections. Access is still available via
- fix to compiled bind parameters to not mistakenly populate None
[ticket:853]
-
+
- <Engine|Connection>._execute_clauseelement becomes a public method
Connectable.execute_clauseelement
-
+
- orm
- - eager loading with LIMIT/OFFSET applied no longer adds the primary
+ - eager loading with LIMIT/OFFSET applied no longer adds the primary
table joined to a limited subquery of itself; the eager loads now
join directly to the subquery which also provides the primary table's
columns to the result set. This eliminates a JOIN from all eager loads
- session.refresh() and session.expire() now support an additional argument
"attribute_names", a list of individual attribute keynames to be refreshed
- or expired, allowing partial reloads of attributes on an already-loaded
+ or expired, allowing partial reloads of attributes on an already-loaded
instance. [ticket:802]
-
- - added op() operator to instrumented attributes; i.e.
+
+ - added op() operator to instrumented attributes; i.e.
User.name.op('ilike')('%somename%') [ticket:767]
-
+
- Mapped classes may now define __eq__, __hash__, and __nonzero__ methods
with arbitrary semantics. The orm now handles all mapped instances on
an identity-only basis. (e.g. 'is' vs '==') [ticket:676]
- the "properties" accessor on Mapper is removed; it now throws an informative
- exception explaining the usage of mapper.get_property() and
+ exception explaining the usage of mapper.get_property() and
mapper.iterate_properties
- added having() method to Query, applies HAVING to the generated statement
in the same way as filter() appends to the WHERE clause.
-
+
- The behavior of query.options() is now fully based on paths, i.e. an
option such as eagerload_all('x.y.z.y.x') will apply eagerloading to
only those paths, i.e. and not 'x.y.x'; eagerload('children.children')
- PickleType will compare using `==` when set up with mutable=False,
and not the `is` operator. To use `is` or any other comparator, send
in a custom comparison function using PickleType(comparator=my_custom_comparator).
-
+
- query doesn't throw an error if you use distinct() and an order_by()
containing UnaryExpressions (or other) together [ticket:848]
-
- - order_by() expressions from joined tables are properly added to columns
+
+ - order_by() expressions from joined tables are properly added to columns
clause when using distinct() [ticket:786]
-
+
- fixed error where Query.add_column() would not accept a class-bound
attribute as an argument; Query also raises an error if an invalid
argument was sent to add_column() (at instances() time) [ticket:858]
- added a little more checking for garbage-collection dereferences in
InstanceState.__cleanup() to reduce "gc ignored" errors on app
shutdown
-
+
- The session API has been solidified:
- It's an error to session.save() an object which is already
- Deferred column attributes no longer trigger a load operation when the
attribute is assigned to. In those cases, the newly assigned value
will be present in the flushes' UPDATE statement unconditionally.
-
+
- Fixed a truncation error when re-assigning a subset of a collection
(obj.relation = obj.relation[1:]) [ticket:834]
- fixed very hard-to-reproduce issue where by the FROM clause of Query
could get polluted by certain generative calls [ticket:852]
-
+
- dialects
-
+
- Added experimental support for MaxDB (versions >= 7.6.03.007 only).
- - oracle will now reflect "DATE" as an OracleDateTime column, not
+ - oracle will now reflect "DATE" as an OracleDateTime column, not
OracleDate
- added awareness of schema name in oracle table_names() function,
fixes metadata.reflect(schema='someschema') [ticket:847]
- MSSQL anonymous labels for selection of functions made deterministic
-
+
- sqlite will reflect "DECIMAL" as a numeric column.
- Made access dao detection more reliable [ticket:828]
- Added test coverage for unknown type reflection. Fixed sqlite/mysql
handling of type reflection for unknown types.
- - Added REAL for mysql dialect (for folks exploiting the
+ - Added REAL for mysql dialect (for folks exploiting the
REAL_AS_FLOAT sql mode).
- mysql Float, MSFloat and MSDouble constructed without arguments
0.4.0
-----
-- (see 0.4.0beta1 for the start of major changes against 0.3,
+- (see 0.4.0beta1 for the start of major changes against 0.3,
as well as http://www.sqlalchemy.org/trac/wiki/WhatsNewIn04 )
- Added initial Sybase support (mxODBC so far) [ticket:785]
- string-based query param parsing/config file parser understands
wider range of string values for booleans [ticket:817]
-
+
- backref remove object operation doesn't fail if the other-side
collection doesn't contain the item, supports noload collections
[ticket:813]
- removed __len__ from "dynamic" collection as it would require issuing
a SQL "count()" operation, thus forcing all list evaluations to issue
redundant SQL [ticket:818]
-
+
- inline optimizations added to locate_dirty() which can greatly speed up
repeated calls to flush(), as occurs with autoflush=True [ticket:816]
-
+
- The IdentifierPreprarer's _requires_quotes test is now regex based. Any
out-of-tree dialects that provide custom sets of legal_characters or
illegal_initial_characters will need to move to regexes or override
. FB now reflects Column's nullable property correctly.
- Fixed SQL compiler's awareness of top-level column labels as used
- in result-set processing; nested selects which contain the same column
+ in result-set processing; nested selects which contain the same column
names don't affect the result or conflict with result-column metadata.
- query.get() and related functions (like many-to-one lazyloading)
use compile-time-aliased bind parameter names, to prevent
- name conflicts with bind parameters that already exist in the
+ name conflicts with bind parameters that already exist in the
mapped selectable.
- Fixed three- and multi-level select and deferred inheritance loading
PostgreSQL 8.2+. [ticket:797]
- PG reflection, upon seeing the default schema name being used explicitly
- as the "schema" argument in a Table, will assume that this is the the
+ as the "schema" argument in a Table, will assume that this is the the
user's desired convention, and will explicitly set the "schema" argument
in foreign-key-related reflected tables, thus making them match only
with Table constructors that also use the explicit "schema" argument
- (even though its the default schema).
+ (even though its the default schema).
In other words, SA assumes the user is being consistent in this usage.
-
+
- fixed sqlite reflection of BOOL/BOOLEAN [ticket:808]
- Added support for UPDATE with LIMIT on mysql.
- fixed Oracle non-ansi join syntax
-- PickleType and Interval types (on db not supporting it natively) are now
+- PickleType and Interval types (on db not supporting it natively) are now
slightly faster.
-
+
- Added Float and Time types to Firebird (FBFloat and FBTime). Fixed
BLOB SUB_TYPE for TEXT and Binary types.
- [ticket:768] dont assume join criterion consists only of column objects
- - adjusted operator precedence of NOT to match '==' and others, so that
+ - adjusted operator precedence of NOT to match '==' and others, so that
~(x==y) produces NOT (x=y), which is compatible with MySQL < 5.0
(doesn't like "NOT x=y") [ticket:764]
-
+
- orm
- added a check for joining from A->B using join(), along two
- different m2m tables. this raises an error in 0.3 but is
+ different m2m tables. this raises an error in 0.3 but is
possible in 0.4 when aliases are used. [ticket:687]
- fixed small exception throw bug in Session.merge()
- - fixed bug where mapper, being linked to a join where one table had
+ - fixed bug where mapper, being linked to a join where one table had
no PK columns, would not detect that the joined table had no PK.
- fixed bugs in determining proper sync clauses from custom inherit
conditions [ticket:769]
- - backref remove object operation doesn't fail if the other-side
+ - backref remove object operation doesn't fail if the other-side
collection doesn't contain the item, supports noload collections
[ticket:813]
-
+
- engine
- fixed another occasional race condition which could occur
- added support for TIME columns (simulated using DATETIME) [ticket:679]
- - added support for BIGINT, MONEY, SMALLMONEY, UNIQUEIDENTIFIER and
+ - added support for BIGINT, MONEY, SMALLMONEY, UNIQUEIDENTIFIER and
SQL_VARIANT [ticket:721]
- index names are now quoted when dropping from reflected tables