- Added support for returning values from inserts (2.0+ only),
updates and deletes (2.1+ only).
-0.4.7
-=====
-- orm
- - The contains() operator when used with many-to-many
- will alias() the secondary (association) table so
- that multiple contains() calls will not conflict
- with each other [ticket:1058]
-
- - 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.
- Totally unrelated types, or subtypes not set up with
- mapper inheritance against the target mapper are
- still not allowed.
-
- - Added is_active flag to Sessions to detect when
- a transaction is in progress [ticket:976]. This
- 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
- more characters than that dialect's configured
- character limit. Some DB's can handle too-long
- table names during usage, and SQLA can handle this
- as well. But various reflection/
- checkfirst-during-create scenarios fail since we are
- looking for the name within the DB's catalog tables.
- [ticket:571]
-
- - The index name generated when you say "index=True"
- on a Column is truncated to the length appropriate
- for the dialect. Additionally, an Index with a too-
- long name cannot be explicitly dropped with
- Index.drop(), similar to [ticket:571].
- [ticket:820]
-
-- postgres
- - Repaired server_side_cursors to properly detect
- text() clauses.
-
- - Added PGCidr type. [ticket:1092]
-
-- mysql
- - Added 'CALL' to the list of SQL keywords which return
- result rows.
-
-- oracle
- - Oracle get_default_schema_name() "normalizes" the name
- before returning, meaning it returns a lower-case name
- when the identifier is detected as case insensitive.
-
- - creating/dropping tables takes schema name into account
- when searching for the existing table, so that tables
- 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
- "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,
- but less so). [ticket:1062]
-
-- sqlite
- - add SLFloat type, which matches the SQLite REAL
- type affinity. Previously, only SLNumeric was provided
- which fulfills NUMERIC affinity, but that's not the
- same as REAL.
-
-0.4.6
-=====
-- orm
- - Fix to the recent relation() refactoring which fixes
- exotic viewonly relations which join between local and
- remote table multiple times, with a common column shared
- between the joins.
-
- - Also re-established viewonly relation() configurations
- that join across multiple tables.
-
- - Added experimental relation() flag to help with
- primaryjoins across functions, etc.,
- _local_remote_pairs=[tuples]. This complements a complex
- primaryjoin condition allowing you to provide the
- individual column pairs which comprise the relation's
- local and remote sides. Also improved lazy load SQL
- generation to handle placing bind params inside of
- functions and other expressions. (partial progress
- towards [ticket:610])
-
- - 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
- into the EXISTS clause for relations that link to subclasses.
-
- - 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
- 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
- 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 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 objects don't trigger an error.
-
- - 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
- function.
-
- - Fixed bug with union() when applied to non-Table connected
- select statements
-
- - 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
- returned. This flag is only safe to use with a database
- which does not support transactions (i.e. MySQL/MyISAM).
-
-- ext
- - set-based association proxies |=, -=, ^= and &= are
- stricter about their operands and only operate on sets,
- frozensets or other association proxies. Previously, they
- would accept any duck-typed set.
-
-- mssql
- - Added "odbc_autotranslate" parameter to engine / dburi
- parameters. Any given string will be passed through to the
- ODBC connection string as:
-
- "AutoTranslate=%s" % odbc_autotranslate
-
- [ticket:1005]
-
- - Added "odbc_options" parameter to engine / dburi
- parameters. The given string is simply appended to the
- SQLAlchemy-generated odbc connection string.
-
- This should obviate the need of adding a myriad of ODBC
- options in the future.
-
-- firebird
- - Handle the "SUBSTRING(:string FROM :start FOR :length)"
- builtin.
-
-0.4.5
-=====
-- orm
- - A small change in behavior to session.merge() - existing
- objects are checked for based on primary key attributes, not
- necessarily _instance_key. So the widely requested
- capability, that:
-
- x = MyObject(id=1)
- x = sess.merge(x)
-
- will in fact load MyObject with id #1 from the database if
- present, is now available. merge() still copies the state
- of the given object to the persistent one, so an example
- like the above would typically have copied "None" from all
- attributes of "x" onto the persistent copy. These can be
- reverted using session.expire(x).
-
- - Also fixed behavior in merge() whereby collection elements
- present on the destination but not the merged collection
- were not being removed from the destination.
-
- - Added a more aggressive check for "uncompiled mappers",
- helps particularly with declarative layer [ticket:995]
-
- - The methodology behind "primaryjoin"/"secondaryjoin" has
- been refactored. Behavior should be slightly more
- intelligent, primarily in terms of error messages which
- have been pared down to be more readable. In a slight
- number of scenarios it can better resolve the correct
- foreign key than before.
-
- - 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.
-
- 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
- with_polymorphic('*', select_table). Note that the
- underlying "guts" of select_table have been
- completely removed and replaced with the newer,
- more flexible approach.
-
- The new approach also automatically allows eager loads
- to work for subclasses, if they are present, for
- example
- sess.query(Company).options(
- eagerload_all(
- [Company.employees.of_type(Engineer), 'machines']
- ))
- to load Company objects, their employees, and the
- 'machines' collection of employees who happen to be
- 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,
- "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
- value is a list of tuples just like when using
- add_column() or add_entity(), the only difference is
- 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.
-
- 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
- we're looking for is how people want to use
- _values()...i.e. at the very end, or do people prefer
- to continue generating after it's called.
-
- - _from_self() compiles the SELECT statement for the
- Query (minus any eager loaders), and returns a new
- Query that selects from that SELECT. So basically you
- can query from a Query without needing to extract the
- SELECT statement manually. This gives meaning to
- operations like query[3:5]._from_self().filter(some
- criterion). There's not much controversial here
- 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()
- already does).
-
- - Added some convenience descriptors to Query:
- query.statement returns the full SELECT construct,
- query.whereclause returns just the WHERE part of the
- SELECT construct.
-
- - Fixed/covered case when using a False/0 value as a
- polymorphic discriminator.
-
- - Fixed bug which was preventing synonym() attributes from
- being used with inheritance
-
- - Fixed SQL function truncation of trailing underscores
- [ticket:996]
-
- - When attributes are expired on a pending instance, an
- error will not be raised when the "refresh" action is
- triggered and no result is found.
-
- - Session.execute can now find binds from metadata
-
- - Adjusted the definition of "self-referential" to be any
- two mappers with a common parent (this affects whether or
- not aliased=True is required when joining with Query).
-
- - Made some fixes to the "from_joinpoint" argument to
- query.join() so that if the previous join was aliased and
- this one isn't, the join still happens successfully.
-
- - Assorted "cascade deletes" fixes:
- - Fixed "cascade delete" operation of dynamic relations,
- which had only been implemented for foreign-key
- nulling behavior in 0.4.2 and not actual cascading
- deletes [ticket:895]
-
- - Delete cascade without delete-orphan cascade on a
- many-to-one will not delete orphans which were
- disconnected from the parent before session.delete()
- is called on the parent (one-to-many already had
- this).
-
- - 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.
-
- - Fixed order_by calculation in Query to properly alias
- mapper-config'ed order_by when using select_from()
-
- - Refactored the diffing logic that kicks in when replacing
- one collection with another into collections.bulk_replace,
- useful to anyone building multi-level collections.
-
- - Cascade traversal algorithm converted from recursive to
- iterative to support deep object graphs.
-
-- sql
- - schema-qualified tables now will place the schemaname
- 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.
-
- - like(), ilike(), contains(), startswith(), endswith() take
- an optional keyword argument "escape=<somestring>", which
- is set as the escape character using the syntax "x LIKE y
- ESCAPE '<somestring>'" [ticket:993], [ticket:791]
-
- - random() is now a generic sql function and will compile to
- the database's random implementation, if any.
-
- - update().values() and insert().values() take keyword
- arguments.
-
- - Fixed an issue in select() regarding its generation of
- FROM clauses, in rare circumstances two clauses could be
- produced when one was intended to cancel out the other.
- Some ORM queries with lots of eager loads might have seen
- this symptom.
-
- - The case() function now also takes a dictionary as its
- whens parameter. It also interprets the "THEN"
- expressions as values by default, meaning case([(x==y,
- "foo")]) will interpret "foo" as a bound value, not a SQL
- expression. use text(expr) for literal SQL expressions in
- this case. For the criterion itself, these may be literal
- strings only if the "value" keyword is present, otherwise
- SA will force explicit usage of either text() or
- literal().
-
-- oracle
- - The "owner" keyword on Table is now deprecated, and is
- exactly synonymous with the "schema" keyword. Tables can
- now be reflected with alternate "owner" attributes,
- explicitly stated on the Table object or not using
- "schema".
-
- - All of the "magic" searching for synonyms, DBLINKs etc.
- during table reflection are disabled by default unless you
- specify "oracle_resolve_synonyms=True" on the Table
- object. Resolving synonyms necessarily leads to some
- messy guessing which we'd rather leave off by default.
- When the flag is set, tables and related tables will be
- resolved against synonyms in all cases, meaning if a
- synonym exists for a particular table, reflection will use
- it when reflecting related tables. This is stickier
- behavior than before which is why it's off by default.
-
-- declarative extension
- - The "synonym" function is now directly usable with
- "declarative". Pass in the decorated property using the
- "descriptor" keyword argument, e.g.: somekey =
- synonym('_somekey', descriptor=property(g, s))
-
- - The "deferred" function is usable with "declarative".
- Simplest usage is to declare deferred and Column together,
- e.g.: data = deferred(Column(Text))
-
- - Declarative also gained @synonym_for(...) and
- @comparable_using(...), front-ends for synonym and
- comparable_property.
-
- - Improvements to mapper compilation when using declarative;
- already-compiled mappers will still trigger compiles of
- other uncompiled mappers when used [ticket:995]
-
- - Declarative will complete setup for Columns lacking names,
- allows a more DRY syntax.
-
- class Foo(Base):
- __tablename__ = 'foos'
- id = Column(Integer, primary_key=True)
-
- - inheritance in declarative can be disabled when sending
- "inherits=None" to __mapper_args__.
-
- - 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
- classes using the "__mapper_cls__" property.
-
-- postgres
- - Got PG server side cursors back into shape, added fixed
- unit tests as part of the default test suite. Added
- better uniqueness to the cursor ID [ticket:1001]
-
-- oracle
- - The "owner" keyword on Table is now deprecated, and is
- exactly synonymous with the "schema" keyword. Tables can
- now be reflected with alternate "owner" attributes,
- explicitly stated on the Table object or not using
- "schema".
-
- - All of the "magic" searching for synonyms, DBLINKs etc.
- during table reflection are disabled by default unless you
- specify "oracle_resolve_synonyms=True" on the Table
- object. Resolving synonyms necessarily leads to some
- messy guessing which we'd rather leave off by default.
- When the flag is set, tables and related tables will be
- resolved against synonyms in all cases, meaning if a
- synonym exists for a particular table, reflection will use
- it when reflecting related tables. This is stickier
- behavior than before which is why it's off by default.
-
-- mssql
- - Reflected tables will now automatically load other tables
- which are referenced by Foreign keys in the auto-loaded
- table, [ticket:979].
-
- - Added executemany check to skip identity fetch, [ticket:916].
-
- - Added stubs for small date type, [ticket:884]
-
- - Added a new 'driver' keyword parameter for the pyodbc dialect.
- Will substitute into the ODBC connection string if given,
- defaults to 'SQL Server'.
-
- - Added a new 'max_identifier_length' keyword parameter for
- the pyodbc dialect.
-
- - Improvements to pyodbc + Unix. If you couldn't get that
- combination to work before, please try again.
-
-- mysql
- - The connection.info keys the dialect uses to cache server
- settings have changed and are now namespaced.
-
-0.4.4
-------
-- sql
- - Can again create aliases of selects against textual FROM
- clauses, [ticket:975]
-
- - The value of a bindparam() can be a callable, in which
- case it's evaluated at statement execution time to get the
- value.
-
- - Added exception wrapping/reconnect support to result set
- fetching. Reconnect works for those databases that raise
- a catchable data error during results (i.e. doesn't work
- on MySQL) [ticket:978]
-
- - Implemented two-phase API for "threadlocal" engine, via
- engine.begin_twophase(), engine.prepare() [ticket:936]
-
- - Fixed bug which was preventing UNIONS from being
- cloneable, [ticket:986]
-
- - Added "bind" keyword argument to insert(), update(),
- delete() and DDL(). The .bind property is now assignable
- on those statements as well as on select().
-
- - Insert statements can now be compiled with extra "prefix"
- words between INSERT and INTO, for vendor extensions like
- MySQL's INSERT IGNORE INTO table.
-
-- orm
- - any(), has(), contains(), ~contains(), attribute level ==
- and != now work properly with self-referential relations -
- the clause inside the EXISTS is aliased on the "remote"
- side to distinguish it from the parent table. This
- applies to single table self-referential as well as
- inheritance-based self-referential.
-
- - Repaired behavior of == and != operators at the relation()
- level when compared against NULL for one-to-one relations
- [ticket:985]
-
- - Fixed bug whereby session.expire() attributes were not
- loading on an polymorphically-mapped instance mapped by a
- select_table mapper.
-
- - Added query.with_polymorphic() - specifies a list of
- classes which descend from the base class, which will be
- added to the FROM clause of the query. Allows subclasses
- to be used within filter() criterion as well as eagerly
- loads the attributes of those subclasses.
-
- - Your cries have been heard: removing a pending item from
- an attribute or collection with delete-orphan expunges the
- item from the session; no FlushError is raised. Note that
- if you session.save()'ed the pending item explicitly, the
- attribute/collection removal still knocks it out.
-
- - session.refresh() and session.expire() raise an error when
- called on instances which are not persistent within the
- session
-
- - Fixed potential generative bug when the same Query was
- used to generate multiple Query objects using join().
-
- - Fixed bug which was introduced in 0.4.3, whereby loading
- an already-persistent instance mapped with joined table
- inheritance would trigger a useless "secondary" load from
- its joined table, when using the default "select"
- polymorphic_fetch. This was due to attributes being
- marked as expired during its first load and not getting
- unmarked from the previous "secondary" load. Attributes
- are now unexpired based on presence in __dict__ after any
- load or commit operation succeeds.
-
- - Deprecated Query methods apply_sum(), apply_max(),
- apply_min(), apply_avg(). Better methodologies are
- coming....
-
- - relation() can accept a callable for its first argument,
- which returns the class to be related. This is in place
- to assist declarative packages to define relations without
- classes yet being in place.
-
- - Added a new "higher level" operator called "of_type()":
- used in join() as well as with any() and has(), qualifies
- the subclass which will be used in filter criterion, e.g.:
-
- query.filter(Company.employees.of_type(Engineer).
- any(Engineer.name=='foo'))
-
- or
-
- query.join(Company.employees.of_type(Engineer)).
- filter(Engineer.name=='foo')
-
- - Preventive code against a potential lost-reference bug in
- flush().
-
- - Expressions used in filter(), filter_by() and others, when
- they make usage of a clause generated from a relation
- using the identity of a child object (e.g.,
- filter(Parent.child==<somechild>)), evaluate the actual
- primary key value of <somechild> at execution time so that
- the autoflush step of the Query can complete, thereby
- populating the PK value of <somechild> in the case that
- <somechild> was pending.
-
- - setting the relation()-level order by to a column in the
- many-to-many "secondary" table will now work with eager
- loading, previously the "order by" wasn't aliased against
- the secondary table's alias.
-
- - Synonyms riding on top of existing descriptors are now
- full proxies to those descriptors.
-
-- dialects
- - Invalid SQLite connection URLs now raise an error.
-
- - postgres TIMESTAMP renders correctly [ticket:981]
-
- - postgres PGArray is a "mutable" type by default; when used
- with the ORM, mutable-style equality/ copy-on-write
- techniques are used to test for changes.
-
-- extensions
- - a new super-small "declarative" extension has been added,
- which allows Table and mapper() configuration to take
- place inline underneath a class declaration. This
- extension differs from ActiveMapper and Elixir in that it
- does not redefine any SQLAlchemy semantics at all; literal
- Column, Table and relation() constructs are used to define
- the class behavior and table definition.
-
-0.4.3
-------
-- sql
- - Added "schema.DDL", an executable free-form DDL statement.
- DDLs can be executed in isolation or attached to Table or
- MetaData instances and executed automatically when those
- objects are created and/or dropped.
-
- - Table columns and constraints can be overridden on a an
- existing table (such as a table that was already reflected)
- using the 'useexisting=True' flag, which now takes into
- account the arguments passed along with it.
-
- - Added a callable-based DDL events interface, adds hooks
- before and after Tables and MetaData create and drop.
-
- - Added generative where(<criterion>) method to delete() and
- update() constructs which return a new object with criterion
- joined to existing criterion via AND, just like
- select().where().
-
- - Added "ilike()" operator to column operations. Compiles to
- ILIKE on postgres, lower(x) LIKE lower(y) on all
- others. [ticket:727]
-
- - Added "now()" as a generic function; on SQLite, Oracle
- and MSSQL compiles as "CURRENT_TIMESTAMP"; "now()" on
- all others. [ticket:943]
-
- - The startswith(), endswith(), and contains() operators now
- concatenate the wildcard operator with the given operand in
- SQL, i.e. "'%' || <bindparam>" in all cases, accept
- text('something') operands properly [ticket:962]
-
- - cast() accepts text('something') and other non-literal
- operands properly [ticket:962]
-
- - fixed bug in result proxy where anonymously generated
- column labels would not be accessible using their straight
- string name
-
- - Deferrable constraints can now be defined.
-
- - Added "autocommit=True" keyword argument to select() and
- text(), as well as generative autocommit() method on
- select(); for statements which modify the database through
- some user-defined means other than the usual INSERT/UPDATE/
- DELETE etc. This flag will enable "autocommit" behavior
- during execution if no transaction is in progress.
- [ticket:915]
-
- - The '.c.' attribute on a selectable now gets an entry for
- every column expression in its columns clause. Previously,
- "unnamed" columns like functions and CASE statements weren't
- getting put there. Now they will, using their full string
- representation if no 'name' is available.
-
- - a CompositeSelect, i.e. any union(), union_all(),
- intersect(), etc. now asserts that each selectable contains
- the same number of columns. This conforms to the
- corresponding SQL requirement.
-
- - The anonymous 'label' generated for otherwise unlabeled
- functions and expressions now propagates outwards at compile
- time for expressions like select([select([func.foo()])]).
-
- - Building on the above ideas, CompositeSelects now build up
- their ".c." collection based on the names present in the
- first selectable only; corresponding_column() now works
- fully for all embedded selectables.
-
- - Oracle and others properly encode SQL used for defaults like
- sequences, etc., even if no unicode idents are used since
- identifier preparer may return a cached unicode identifier.
-
- - Column and clause comparisons to datetime objects on the
- left hand side of the expression now work (d < table.c.col).
- (datetimes on the RHS have always worked, the LHS exception
- is a quirk of the datetime implementation.)
-
-- orm
- - Every Session.begin() must now be accompanied by a
- corresponding commit() or rollback() unless the session is
- closed with Session.close(). This also includes the begin()
- which is implicit to a session created with
- transactional=True. The biggest change introduced here is
- that when a Session created with transactional=True raises
- an exception during flush(), you must call
- Session.rollback() or Session.close() in order for that
- Session to continue after an exception.
-
- - Fixed merge() collection-doubling bug when merging transient
- entities with backref'ed collections. [ticket:961]
-
- - merge(dont_load=True) does not accept transient entities,
- this is in continuation with the fact that
- merge(dont_load=True) does not accept any "dirty" objects
- either.
-
- - Added standalone "query" class attribute generated by a
- scoped_session. This provides MyClass.query without using
- Session.mapper. Use via:
-
- MyClass.query = Session.query_property()
-
- - 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...
-
- - Instances which have been partially or fully expired will
- have their expired attributes populated during a regular
- Query operation which affects those objects, preventing a
- needless second SQL statement for each instance.
-
- - Dynamic relations, when referenced, create a strong
- reference to the parent object so that the query still has a
- parent to call against even if the parent is only created
- (and otherwise dereferenced) within the scope of a single
- expression. [ticket:938]
-
- - Added a mapper() flag "eager_defaults". When set to True,
- defaults that are generated during an INSERT or UPDATE
- operation are post-fetched immediately, instead of being
- deferred until later. This mimics the old 0.3 behavior.
-
- - query.join() can now accept class-mapped attributes as
- arguments. These can be used in place or in any combination
- with strings. In particular this allows construction of
- joins to subclasses on a polymorphic relation, i.e.:
-
- query(Company).join(['employees', Engineer.name])
-
- - query.join() can also accept tuples of attribute name/some
- selectable as arguments. This allows construction of joins
- *from* subclasses of a polymorphic relation, i.e.:
-
- query(Company).\
- join(
- [('employees', people.join(engineer)), Engineer.name]
- )
-
- - General improvements to the behavior of join() in
- conjunction with polymorphic mappers, i.e. joining from/to
- polymorphic mappers and properly applying aliases.
-
- - Fixed/improved behavior when a mapper determines the natural
- "primary key" of a mapped join, it will more effectively
- reduce columns which are equivalent via foreign key
- relation. This affects how many arguments need to be sent
- to query.get(), among other things. [ticket:933]
-
- - The lazy loader can now handle a join condition where the
- "bound" column (i.e. the one that gets the parent id sent as
- a bind parameter) appears more than once in the join
- condition. Specifically this allows the common task of a
- relation() which contains a parent-correlated subquery, such
- as "select only the most recent child item". [ticket:946]
-
- - Fixed bug in polymorphic inheritance where an incorrect
- exception is raised when base polymorphic_on column does not
- correspond to any columns within the local selectable of an
- inheriting mapper more than one level deep
-
- - Fixed bug in polymorphic inheritance which made it difficult
- to set a working "order_by" on a polymorphic mapper.
-
- - Fixed a rather expensive call in Query that was slowing down
- polymorphic queries.
-
- - "Passive defaults" and other "inline" defaults can now be
- loaded during a flush() call if needed; in particular, this
- allows constructing relations() where a foreign key column
- references a server-side-generated, non-primary-key
- column. [ticket:954]
-
- - Additional Session transaction fixes/changes:
- - Fixed bug with session transaction management: parent
- transactions weren't started on the connection when
- adding a connection to a nested transaction.
-
- - session.transaction now always refers to the innermost
- active transaction, even when commit/rollback are called
- directly on the session transaction object.
-
- - Two-phase transactions can now be prepared.
-
- - When preparing a two-phase transaction fails on one
- connection, all the connections are rolled back.
-
- - session.close() didn't close all transactions when
- nested transactions were used.
-
- - rollback() previously erroneously set the current
- transaction directly to the parent of the transaction
- that could be rolled back to. Now it rolls back the next
- transaction up that can handle it, but sets the current
- transaction to it's parent and inactivates the
- transactions in between. Inactive transactions can only
- be rolled back or closed, any other call results in an
- error.
-
- - autoflush for commit() wasn't flushing for simple
- subtransactions.
-
- - unitofwork flush didn't close the failed transaction
- when the session was not in a transaction and commiting
- the transaction failed.
-
- - Miscellaneous tickets: [ticket:940] [ticket:964]
-
-- general
- - Fixed a variety of hidden and some not-so-hidden
- compatibility issues for Python 2.3, thanks to new support
- for running the full test suite on 2.3.
-
- - Warnings are now issued as type exceptions.SAWarning.
-
-- dialects
- - Better support for schemas in SQLite (linked in by ATTACH
- DATABASE ... AS name). In some cases in the past, schema
- names were ommitted from generated SQL for SQLite. This is
- no longer the case.
-
- - table_names on SQLite now picks up temporary tables as well.
-
- - Auto-detect an unspecified MySQL ANSI_QUOTES mode during
- reflection operations, support for changing the mode
- midstream. Manual mode setting is still required if no
- reflection is used.
-
- - Fixed reflection of TIME columns on SQLite.
-
- - Finally added PGMacAddr type to postgres [ticket:580]
-
- - Reflect the sequence associated to a PK field (typically
- with a BEFORE INSERT trigger) under Firebird
-
- - Oracle assembles the correct columns in the result set
- column mapping when generating a LIMIT/OFFSET subquery,
- allows columns to map properly to result sets even if
- long-name truncation kicks in [ticket:941]
-
- - MSSQL now includes EXEC in the _is_select regexp, which
- should allow row-returning stored procedures to be used.
-
- - MSSQL now includes an experimental implementation of
- LIMIT/OFFSET using the ANSI SQL row_number() function, so it
- requires MSSQL-2005 or higher. To enable the feature, add
- "has_window_funcs" to the keyword arguments for connect, or
- add "?has_window_funcs=1" to your dburi query arguments.
-
-- ext
- - Changed ext.activemapper to use a non-transactional session
- for the objectstore.
-
- - Fixed output order of "['a'] + obj.proxied" binary operation
- on association-proxied lists.
-
-0.4.2p3
-------
-- general
- - sub version numbering scheme changed to suite
- setuptools version number rules; easy_install -u
- should now get this version over 0.4.2.
-
-- sql
- - Text type is properly exported now and does not
- raise a warning on DDL create; String types with no
- length only raise warnings during CREATE TABLE
- [ticket:912]
-
- - new UnicodeText type is added, to specify an
- encoded, unlengthed Text type
-
- - fixed bug in union() so that select() statements
- which don't derive from FromClause objects can be
- unioned
-
-- orm
- - fixed bug with session.dirty when using "mutable
- scalars" (such as PickleTypes)
-
- - added a more descriptive error message when flushing
- on a relation() that has non-locally-mapped columns
- in its primary or secondary join condition
-
-- dialects
- - Fixed reflection of mysql empty string column
- defaults.
-
-0.4.2b (0.4.2p2)
-------
-- sql
- - changed name of TEXT to Text since its a "generic"
- type; TEXT name is deprecated until 0.5. The
- "upgrading" behavior of String to Text when no
- length is present is also deprecated until 0.5; will
- issue a warning when used for CREATE TABLE
- statements (String with no length for SQL expression
- purposes is still fine) [ticket:912]
-
- - generative select.order_by(None) / group_by(None)
- was not managing to reset order by/group by
- criterion, fixed [ticket:924]
-
-- orm
- - suppressing *all* errors in
- InstanceState.__cleanup() now.
-
- - fixed an attribute history bug whereby assigning a
- 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
- synonyms for backrefs without worrying about the
- order of operations) [ticket:919]
-
- - 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.
-
-- dialects
- - mssql - narrowed down the test for "date"/"datetime"
- in MSDate/ MSDateTime subclasses so that incoming
- "datetime" objects don't get mis-interpreted as
- "date" objects and vice versa, [ticket:923]
-
-0.4.2a (0.4.2p1)
-------
-
-- 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
- 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
- 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
- result batch boundaries, nor will it behave nicely if the same
- instance occurs in more than one batch. This means that an eagerly
- loaded collection will get cleared out if it's referenced in more than
- one batch, and in all cases attributes will be overwritten on instances
- that occur in more than one batch.
-
- - Fixed in-place set mutation operators for set collections and association
- proxied sets. [ticket:920]
-
-- dialects
- - Fixed the missing call to subtype result processor for the PGArray
- type. [ticket:913]
-
-0.4.2
------
-- sql
- - generic functions ! we introduce a database of known SQL functions, such
- as current_timestamp, coalesce, and create explicit function objects
- representing them. These objects have constrained argument lists, are
- type aware, and can compile in a dialect-specific fashion. So saying
- func.char_length("foo", "bar") raises an error (too many args),
- func.coalesce(datetime.date(2007, 10, 5), datetime.date(2005, 10, 15))
- knows that its return type is a Date. We only have a few functions
- represented so far but will continue to add to the system [ticket:615]
-
- - auto-reconnect support improved; a Connection can now automatically
- 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
- 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
- make proper use of Python unicode objects (i.e. u'hello' and not 'hello')
- so that data round trips accurately.
-
- - generation of "unique" bind parameters has been simplified to use the same
- "unique identifier" mechanisms as everything else. This doesn't affect
- 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.
- TypeDecorator should now be the primary way to augment the behavior of any
- existing type including other TypeDecorator subclasses such as 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
- 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
- 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
- have not, you might notice your apps using a lot fewer queries than
- before in some situations. [ticket:871]
-
- - mutable primary key support is added. primary key columns can be
- changed freely, and the identity of the instance will change upon
- flush. In addition, update cascades of foreign key referents (primary
- key or not) along relations are supported, either in tandem with the
- database's ON UPDATE CASCADE (required for DB's like Postgres) or
- issued directly by the ORM in the form of UPDATE statements, by setting
- the flag "passive_cascades=False".
-
- - 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
- 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
- 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
- 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
- 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),
- 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.
-
- - 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
- with the appropriate comparison operators so that it can be used in in
- column expressions just like any other mapped attribute (i.e. usable in
- filter(), etc.) the "proxy=True" flag is deprecated and no longer means
- anything. Additionally, the flag "map_column=True" will automatically
- generate a ColumnProperty corresponding to the name of the synonym,
- i.e.: 'somename':synonym('_somename', map_column=True) will map the
- column named 'somename' to the attribute '_somename'. See the example
- in the mapper docs. [ticket:801]
-
- - 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
- 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
- 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
- "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
- 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
- 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
- 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().
-
- - 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
- 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
- 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,
- 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.
- [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
- requires conversion to ColumnElement via as_scalar() or label().
-
- - 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(),
- MapperProperty.cascade_callable(), mapper.canload(),
- mapper.save_obj(), mapper.delete_obj(), mapper._mapper_registry,
- attributes.AttributeManager
-
- - Assigning an incompatible collection type to a relation attribute now
- raises TypeError instead of sqlalchemy's ArgumentError.
-
- - Bulk assignment of a MappedCollection now raises an error if a key in the
- incoming dictionary does not match the key that the collection's keyfunc
- would use for that value. [ticket:886]
-
- - Custom collections can now specify a @converter method to translate
- objects used in "bulk" assignment into a stream of values, as in::
-
- obj.col = [newval1, newval2]
- # or
- obj.dictcol = {'foo': newval1, 'bar': newval2}
-
- 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
- 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
- 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).
- 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
- "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
- 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
- [ticket:914]
-
-- dialects
-
- - 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]
- - Better support for convert_unicode [ticket:839]
- - Less strict date conversion for pyodbc/adodbapi [ticket:842]
- - Schema-qualified tables / autoload [ticket:901]
-
- - Firebird backend
-
- - does properly reflect domains (partially fixing [ticket:410]) and
- PassiveDefaults
-
- - reverted to use default poolclass (was set to SingletonThreadPool in
- 0.4.0 [3562] for test purposes)
-
- - map func.length() to 'char_length' (easily overridable with the UDF
- 'strlen' on old versions of Firebird)
-
-
-0.4.1
------
-
-- sql
-
- - the "shortname" keyword parameter on bindparam() has been
- deprecated.
-
- - Added contains operator (generates a "LIKE %<other>%" clause).
-
- - 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
- matches since text() expressions may represent multiple columns).
-
- - 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]
-
- - Fixed empty (zero column) sqlite inserts, allowing inserts on
- autoincrementing single column tables.
-
- - Fixed expression translation of text() clauses; this repairs various
- ORM scenarios where literal text is used for SQL expressions
-
- - Removed ClauseParameters object; compiled.params returns a regular
- dictionary now, as well as result.last_inserted_params() /
- last_updated_params().
-
- - Fixed INSERT statements w.r.t. primary key columns that have
- SQL-expression based default generators on them; SQL expression
- executes inline as normal but will not trigger a "postfetch" condition
- for the column, for those DB's who provide it via cursor.lastrowid
-
- - func. objects can be pickled/unpickled [ticket:844]
-
- - rewrote and simplified the system used to "target" columns across
- 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
- 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]
-
- - The "properties" collection on Connections has been renamed "info" to
- match schema's writable collections. Access is still available via
- the "properties" name until 0.5.
-
- - fixed the close() method on Transaction when using strategy='threadlocal'
-
- - 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
- 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
- with LIMIT/OFFSET. [ticket:843]
-
- - 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
- instance. [ticket:802]
-
- - 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
- 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')
- applies only to exactly two-levels deep, etc. [ticket:777]
-
- - 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
- 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
- persistent [ticket:840]
-
- - It's an error to session.delete() an object which is *not*
- persistent.
-
- - session.update() and session.delete() raise an error when updating
- or deleting an instance that is already in the session with a
- different identity.
-
- - The session checks more carefully when determining "object X already
- in another session"; e.g. if you pickle a series of objects and
- unpickle (i.e. as in a Pylons HTTP session or similar), they can go
- into a new session without any conflict
-
- - merge() includes a keyword argument "dont_load=True". setting this
- flag will cause the merge operation to not load any data from the
- database in response to incoming detached objects, and will accept
- the incoming detached object as though it were already present in
- that session. Use this to merge detached objects from external
- caching systems into the session.
-
- - 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]
-
- - De-cruftified backref configuration code, backrefs which step on
- existing properties now raise an error [ticket:832]
-
- - Improved behavior of add_property() etc., fixed [ticket:831] involving
- synonym/deferred.
-
- - Fixed clear_mappers() behavior to better clean up after itself.
-
- - Fix to "row switch" behavior, i.e. when an INSERT/DELETE is combined
- into a single UPDATE; many-to-many relations on the parent object
- update properly. [ticket:841]
-
- - Fixed __hash__ for association proxy- these collections are unhashable,
- just like their mutable Python counterparts.
-
- - Added proxying of save_or_update, __contains__ and __iter__ methods for
- scoped sessions.
-
- - 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
- 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]
-
- - Renamed the Dialect attribute 'preexecute_sequences' to
- 'preexecute_pk_sequences'. An attribute porxy is in place for
- out-of-tree dialects using the old name.
-
- - 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
- REAL_AS_FLOAT sql mode).
-
- - mysql Float, MSFloat and MSDouble constructed without arguments
- now produce no-argument DDL, e.g.'FLOAT'.
-
-- misc
-
- - Removed unused util.hash().
-
-
-0.4.0
------
-
-- (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]
-
-- Added partial index support for PostgreSQL. Use the postgres_where keyword
- on the Index.
-
-- 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
- _requires_quotes.
-
-- Firebird has supports_sane_rowcount and supports_sane_multi_rowcount set
- to False due to ticket #370 (right way).
-
-- Improvements and fixes on Firebird reflection:
- . FBDialect now mimics OracleDialect, regarding case-sensitivity of TABLE and
- COLUMN names (see 'case_sensitive remotion' topic on this current file).
- . FBDialect.table_names() doesn't bring system tables (ticket:796).
- . 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
- 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
- mapped selectable.
-
-- Fixed three- and multi-level select and deferred inheritance loading
- (i.e. abc inheritance with no select_table), [ticket:795]
-
-- Ident passed to id_chooser in shard.py always a list.
-
-- The no-arg ResultProxy._row_processor() is now the class attribute
- `_process_row`.
-
-- Added support for returning values from inserts and updates for
- 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
- 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).
- 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.
-
-- null foreign key on a m2o doesn't trigger a lazyload [ticket:803]
-
-- oracle does not implicitly convert to unicode for non-typed result
- sets (i.e. when no TypeEngine/String/Unicode type is even being used;
- previously it was detecting DBAPI types and converting regardless).
- should fix [ticket:800]
-
-- fix to anonymous label generation of long table/column names [ticket:806]
-
-- Firebird dialect now uses SingletonThreadPool as poolclass.
-
-- Firebird now uses dialect.preparer to format sequences names
-
-- Fixed breakage with postgres and multiple two-phase transactions. Two-phase
- commits and and rollbacks didn't automatically end up with a new transaction
- as the usual dbapi commits/rollbacks do. [ticket:810]
-
-- Added an option to the _ScopedExt mapper extension to not automatically
- save new objects to session on object initialization.
-
-- fixed Oracle non-ansi join syntax
-
-- 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.
-
-- Changed the API for the in_ operator. in_() now accepts a single argument
- that is a sequence of values or a selectable. The old API of passing in
- values as varargs still works but is deprecated.
-
-
-0.4.0beta6
-----------
-
-- The Session identity map is now *weak referencing* by default, use
- weak_identity_map=False to use a regular dict. The weak dict we are using
- is customized to detect instances which are "dirty" and maintain a
- temporary strong reference to those instances until changes are flushed.
-
-- Mapper compilation has been reorganized such that most compilation occurs
- upon mapper construction. This allows us to have fewer calls to
- mapper.compile() and also to allow class-based properties to force a
- compilation (i.e. User.addresses == 7 will compile all mappers; this is
- [ticket:758]). The only caveat here is that an inheriting mapper now
- looks for its inherited mapper upon construction; so mappers within
- inheritance relationships need to be constructed in inheritance order
- (which should be the normal case anyway).
-
-- added "FETCH" to the keywords detected by Postgres to indicate a
- result-row holding statement (i.e. in addition to "SELECT").
-
-- Added full list of SQLite reserved keywords so that they get escaped
- properly.
-
-- Tightened up the relationship between the Query's generation of "eager
- load" aliases, and Query.instances() which actually grabs the eagerly
- loaded rows. If the aliases were not specifically generated for that
- statement by EagerLoader, the EagerLoader will not take effect when the
- rows are fetched. This prevents columns from being grabbed accidentally
- as being part of an eager load when they were not meant for such, which
- can happen with textual SQL as well as some inheritance situations. It's
- particularly important since the "anonymous aliasing" of columns uses
- simple integer counts now to generate labels.
-
-- Removed "parameters" argument from clauseelement.compile(), replaced with
- "column_keys". The parameters sent to execute() only interact with the
- insert/update statement compilation process in terms of the column names
- present but not the values for those columns. Produces more consistent
- execute/executemany behavior, simplifies things a bit internally.
-
-- Added 'comparator' keyword argument to PickleType. By default, "mutable"
- PickleType does a "deep compare" of objects using their dumps()
- representation. But this doesn't work for dictionaries. Pickled objects
- which provide an adequate __eq__() implementation can be set up with
- "PickleType(comparator=operator.eq)" [ticket:560]
-
-- Added session.is_modified(obj) method; performs the same "history"
- comparison operation as occurs within a flush operation; setting
- include_collections=False gives the same result as is used when the flush
- determines whether or not to issue an UPDATE for the instance's row.
-
-- Added "schema" argument to Sequence; use this with Postgres /Oracle when
- the sequence is located in an alternate schema. Implements part of
- [ticket:584], should fix [ticket:761].
-
-- Fixed reflection of the empty string for mysql enums.
-
-- Changed MySQL dialect to use the older LIMIT <offset>, <limit> syntax
- instead of LIMIT <l> OFFSET <o> for folks using 3.23. [ticket:794]
-
-- Added 'passive_deletes="all"' flag to relation(), disables all nulling-out
- of foreign key attributes during a flush where the parent object is
- deleted.
-
-- Column defaults and onupdates, executing inline, will add parenthesis for
- subqueries and other parenthesis-requiring expressions
-
-- The behavior of String/Unicode types regarding that they auto-convert to
- TEXT/CLOB when no length is present now occurs *only* for an exact type of
- String or Unicode with no arguments. If you use VARCHAR or NCHAR
- (subclasses of String/Unicode) with no length, they will be interpreted by
- the dialect as VARCHAR/NCHAR; no "magic" conversion happens there. This
- is less surprising behavior and in particular this helps Oracle keep
- string-based bind parameters as VARCHARs and not CLOBs [ticket:793].
-
-- Fixes to ShardedSession to work with deferred columns [ticket:771].
-
-- User-defined shard_chooser() function must accept "clause=None" argument;
- this is the ClauseElement passed to session.execute(statement) and can be
- used to determine correct shard id (since execute() doesn't take an
- instance.)
-
-- Adjusted operator precedence of NOT to match '==' and others, so that
- ~(x <operator> y) produces NOT (x <op> y), which is better compatible
- with older MySQL versions. [ticket:764]. This doesn't apply to "~(x==y)"
- as it does in 0.3 since ~(x==y) compiles to "x != y", but still applies
- to operators like BETWEEN.
-
-- Other tickets: [ticket:768], [ticket:728], [ticket:779], [ticket:757]
-
-0.4.0beta5
-----------
-
-- Connection pool fixes; the better performance of beta4 remains but fixes
- "connection overflow" and other bugs which were present (like
- [ticket:754]).
-
-- Fixed bugs in determining proper sync clauses from custom inherit
- conditions. [ticket:769]
-
-- Extended 'engine_from_config' coercion for QueuePool size / overflow.
- [ticket:763]
-
-- mysql views can be reflected again. [ticket:748]
-
-- AssociationProxy can now take custom getters and setters.
-
-- Fixed malfunctioning BETWEEN in orm queries.
-
-- Fixed OrderedProperties pickling [ticket:762]
-
-- SQL-expression defaults and sequences now execute "inline" for all
- non-primary key columns during an INSERT or UPDATE, and for all columns
- during an executemany()-style call. inline=True flag on any insert/update
- statement also forces the same behavior with a single execute().
- result.postfetch_cols() is a collection of columns for which the previous
- single insert or update statement contained a SQL-side default expression.
-
-- Fixed PG executemany() behavior, [ticket:759]
-
-- postgres reflects tables with autoincrement=False for primary key columns
- which have no defaults.
-
-- postgres no longer wraps executemany() with individual execute() calls,
- instead favoring performance. "rowcount"/"concurrency" checks with
- deleted items (which use executemany) are disabled with PG since psycopg2
- does not report proper rowcount for executemany().
-
-- Tickets fixed:
-
- - [ticket:742]
- - [ticket:748]
- - [ticket:760]
- - [ticket:762]
- - [ticket:763]
-
-0.4.0beta4
-----------
-
-- Tidied up what ends up in your namespace when you 'from sqlalchemy import *':
-
- - 'table' and 'column' are no longer imported. They remain available by
- direct reference (as in 'sql.table' and 'sql.column') or a glob import
- from the sql package. It was too easy to accidentally use a
- sql.expressions.table instead of schema.Table when just starting out
- with SQLAlchemy, likewise column.
-
- - Internal-ish classes like ClauseElement, FromClause, NullTypeEngine,
- etc., are also no longer imported into your namespace
-
- - The 'Smallinteger' compatiblity name (small i!) is no longer imported,
- but remains in schema.py for now. SmallInteger (big I!) is still
- imported.
-
-- The connection pool uses a "threadlocal" strategy internally to return
- the same connection already bound to a thread, for "contextual" connections;
- these are the connections used when you do a "connectionless" execution
- like insert().execute(). This is like a "partial" version of the
- "threadlocal" engine strategy but without the thread-local transaction part
- of it. We're hoping it reduces connection pool overhead as well as
- database usage. However, if it proves to impact stability in a negative way,
- we'll roll it right back.
-
-- Fix to bind param processing such that "False" values (like blank strings)
- still get processed/encoded.
-
-- Fix to select() "generative" behavior, such that calling column(),
- select_from(), correlate(), and with_prefix() does not modify the
- original select object [ticket:752]
-
-- Added a "legacy" adapter to types, such that user-defined TypeEngine
- and TypeDecorator classes which define convert_bind_param() and/or
- convert_result_value() will continue to function. Also supports
- calling the super() version of those methods.
-
-- Added session.prune(), trims away instances cached in a session that
- are no longer referenced elsewhere. (A utility for strong-ref
- identity maps).
-
-- Added close() method to Transaction. Closes out a transaction using
- rollback if it's the outermost transaction, otherwise just ends
- without affecting the outer transaction.
-
-- Transactional and non-transactional Session integrates better with
- bound connection; a close() will ensure that connection
- transactional state is the same as that which existed on it before
- being bound to the Session.
-
-- Modified SQL operator functions to be module-level operators,
- allowing SQL expressions to be pickleable. [ticket:735]
-
-- Small adjustment to mapper class.__init__ to allow for Py2.6
- object.__init__() behavior.
-
-- Fixed 'prefix' argument for select()
-
-- Connection.begin() no longer accepts nested=True, this logic is now
- all in begin_nested().
-
-- Fixes to new "dynamic" relation loader involving cascades
-
-- Tickets fixed:
-
- - [ticket:735]
- - [ticket:752]
-
-0.4.0beta3
-----------
-
-- SQL types optimization:
-
- - New performance tests show a combined mass-insert/mass-select test as
- having 68% fewer function calls than the same test run against 0.3.
-
- - General performance improvement of result set iteration is around 10-20%.
-
- - In types.AbstractType, convert_bind_param() and convert_result_value()
- have migrated to callable-returning bind_processor() and
- result_processor() methods. If no callable is returned, no pre/post
- processing function is called.
-
- - Hooks added throughout base/sql/defaults to optimize the calling of bind
- aram/result processors so that method call overhead is minimized.
-
- - Support added for executemany() scenarios such that unneeded "last row id"
- logic doesn't kick in, parameters aren't excessively traversed.
-
-- Added 'inherit_foreign_keys' arg to mapper().
-
-- Added support for string date passthrough in sqlite.
-
-- Tickets fixed:
-
- - [ticket:738]
- - [ticket:739]
- - [ticket:743]
- - [ticket:744]
-
-0.4.0beta2
-----------
-
-- mssql improvements.
-
-- oracle improvements.
-
-- Auto-commit after LOAD DATA INFILE for mysql.
-
-- A rudimental SessionExtension class has been added, allowing user-defined
- functionality to take place at flush(), commit(), and rollback() boundaries.
-
-- Added engine_from_config() function for helping to create_engine() from an
- .ini style config.
-
-- base_mapper() becomes a plain attribute.
-
-- session.execute() and scalar() can search for a Table with which to bind from
- using the given ClauseElement.
-
-- Session automatically extrapolates tables from mappers with binds, also uses
- base_mapper so that inheritance hierarchies bind automatically.
-
-- Moved ClauseVisitor traversal back to inlined non-recursive.
-
-- Tickets fixed:
-
- - [ticket:730]
- - [ticket:732]
- - [ticket:733]
- - [ticket:734]
-
-0.4.0beta1
-----------
-
-- orm
-
- - Speed! Along with recent speedups to ResultProxy, total number of function
- calls significantly reduced for large loads.
-
- - test/perf/masseagerload.py reports 0.4 as having the fewest number of
- function calls across all SA versions (0.1, 0.2, and 0.3).
-
- - New collection_class api and implementation [ticket:213]. Collections are
- now instrumented via decorations rather than proxying. You can now have
- collections that manage their own membership, and your class instance will
- be directly exposed on the relation property. The changes are transparent
- for most users.
-
- - InstrumentedList (as it was) is removed, and relation properties no
- longer have 'clear()', '.data', or any other added methods beyond those
- provided by the collection type. You are free, of course, to add them to
- a custom class.
-
- - __setitem__-like assignments now fire remove events for the existing
- value, if any.
-
- - dict-likes used as collection classes no longer need to change __iter__
- semantics- itervalues() is used by default instead. This is a backwards
- incompatible change.
-
- - Subclassing dict for a mapped collection is no longer needed in most
- cases. orm.collections provides canned implementations that key objects
- by a specified column or a custom function of your choice.
-
- - Collection assignment now requires a compatible type- assigning None to
- clear a collection or assigning a list to a dict collection will now
- raise an argument error.
-
- - AttributeExtension moved to interfaces, and .delete is now .remove The
- event method signature has also been swapped around.
-
- - Major overhaul for Query:
-
- - All selectXXX methods are deprecated. Generative methods are now the
- standard way to do things, i.e. filter(), filter_by(), all(), one(),
- etc. Deprecated methods are docstring'ed with their new replacements.
-
- - Class-level properties are now usable as query elements... no more
- '.c.'! "Class.c.propname" is now superceded by "Class.propname". All
- clause operators are supported, as well as higher level operators such
- as Class.prop==<some instance> for scalar attributes,
- Class.prop.contains(<some instance>) and Class.prop.any(<some
- expression>) for collection-based attributes (all are also
- negatable). Table-based column expressions as well as columns mounted
- on mapped classes via 'c' are of course still fully available and can be
- freely mixed with the new attributes. [ticket:643]
-
- - Removed ancient query.select_by_attributename() capability.
-
- - The aliasing logic used by eager loading has been generalized, so that
- it also adds full automatic aliasing support to Query. It's no longer
- necessary to create an explicit Alias to join to the same tables
- multiple times; *even for self-referential relationships*.
-
- - join() and outerjoin() take arguments "aliased=True". Yhis causes
- their joins to be built on aliased tables; subsequent calls to
- filter() and filter_by() will translate all table expressions (yes,
- real expressions using the original mapped Table) to be that of the
- Alias for the duration of that join() (i.e. until reset_joinpoint() or
- another join() is called).
-
- - join() and outerjoin() take arguments "id=<somestring>". When used
- with "aliased=True", the id can be referenced by add_entity(cls,
- id=<somestring>) so that you can select the joined instances even if
- they're from an alias.
-
- - join() and outerjoin() now work with self-referential relationships!
- Using "aliased=True", you can join as many levels deep as desired,
- i.e. query.join(['children', 'children'], aliased=True); filter
- criterion will be against the rightmost joined table
-
- - Added query.populate_existing(), marks the query to reload all
- attributes and collections of all instances touched in the query,
- including eagerly-loaded entities. [ticket:660]
-
- - Added eagerload_all(), allows eagerload_all('x.y.z') to specify eager
- loading of all properties in the given path.
-
- - Major overhaul for Session:
-
- - New function which "configures" a session called "sessionmaker()". Send
- various keyword arguments to this function once, returns a new class
- which creates a Session against that stereotype.
-
- - SessionTransaction removed from "public" API. You now can call begin()/
- commit()/rollback() on the Session itself.
-
- - Session also supports SAVEPOINT transactions; call begin_nested().
-
- - Session supports two-phase commit behavior when vertically or
- horizontally partitioning (i.e., using more than one engine). Use
- twophase=True.
-
- - Session flag "transactional=True" produces a session which always places
- itself into a transaction when first used. Upon commit(), rollback() or
- close(), the transaction ends; but begins again on the next usage.
-
- - Session supports "autoflush=True". This issues a flush() before each
- query. Use in conjunction with transactional, and you can just
- save()/update() and then query, the new objects will be there. Use
- commit() at the end (or flush() if non-transactional) to flush remaining
- changes.
-
- - New scoped_session() function replaces SessionContext and assignmapper.
- Builds onto "sessionmaker()" concept to produce a class whos Session()
- construction returns the thread-local session. Or, call all Session
- methods as class methods, i.e. Session.save(foo); Session.commit().
- just like the old "objectstore" days.
-
- - Added new "binds" argument to Session to support configuration of
- multiple binds with sessionmaker() function.
-
- - A rudimental SessionExtension class has been added, allowing
- user-defined functionality to take place at flush(), commit(), and
- rollback() boundaries.
-
- - Query-based relation()s available with dynamic_loader(). This is a
- *writable* collection (supporting append() and remove()) which is also a
- live Query object when accessed for reads. Ideal for dealing with very
- large collections where only partial loading is desired.
-
- - flush()-embedded inline INSERT/UPDATE expressions. Assign any SQL
- expression, like "sometable.c.column + 1", to an instance's attribute.
- Upon flush(), the mapper detects the expression and embeds it directly in
- the INSERT or UPDATE statement; the attribute gets deferred on the
- instance so it loads the new value the next time you access it.
-
- - A rudimental sharding (horizontal scaling) system is introduced. This
- system uses a modified Session which can distribute read and write
- operations among multiple databases, based on user-defined functions
- defining the "sharding strategy". Instances and their dependents can be
- distributed and queried among multiple databases based on attribute
- values, round-robin approaches or any other user-defined
- system. [ticket:618]
-
- - Eager loading has been enhanced to allow even more joins in more places.
- It now functions at any arbitrary depth along self-referential and
- cyclical structures. When loading cyclical structures, specify
- "join_depth" on relation() indicating how many times you'd like the table
- to join to itself; each level gets a distinct table alias. The alias
- names themselves are generated at compile time using a simple counting
- scheme now and are a lot easier on the eyes, as well as of course
- completely deterministic. [ticket:659]
-
- - Added composite column properties. This allows you to create a type which
- is represented by more than one column, when using the ORM. Objects of
- the new type are fully functional in query expressions, comparisons,
- query.get() clauses, etc. and act as though they are regular single-column
- scalars... except they're not! Use the function composite(cls, *columns)
- inside of the mapper's "properties" dict, and instances of cls will be
- created/mapped to a single attribute, comprised of the values correponding
- to *columns. [ticket:211]
-
- - Improved support for custom column_property() attributes which feature
- correlated subqueries, works better with eager loading now.
-
- - Primary key "collapse" behavior; the mapper will analyze all columns in
- its given selectable for primary key "equivalence", that is, columns which
- are equivalent via foreign key relationship or via an explicit
- inherit_condition. primarily for joined-table inheritance scenarios where
- different named PK columns in inheriting tables should "collapse" into a
- single-valued (or fewer-valued) primary key. Fixes things like
- [ticket:611].
-
- - Joined-table inheritance will now generate the primary key columns of all
- inherited classes against the root table of the join only. This implies
- that each row in the root table is distinct to a single instance. If for
- some rare reason this is not desireable, explicit primary_key settings on
- individual mappers will override it.
-
- - When "polymorphic" flags are used with joined-table or single-table
- inheritance, all identity keys are generated against the root class of the
- inheritance hierarchy; this allows query.get() to work polymorphically
- using the same caching semantics as a non-polymorphic get. Note that this
- currently does not work with concrete inheritance.
-
- - Secondary inheritance loading: polymorphic mappers can be constructed
- *without* a select_table argument. inheriting mappers whose tables were
- not represented in the initial load will issue a second SQL query
- immediately, once per instance (i.e. not very efficient for large lists),
- in order to load the remaining columns.
-
- - Secondary inheritance loading can also move its second query into a
- column-level "deferred" load, via the "polymorphic_fetch" argument, which
- can be set to 'select' or 'deferred'
-
- - It's now possible to map only a subset of available selectable columns
- onto mapper properties, using include_columns/exclude_columns.
- [ticket:696].
-
- - Added undefer_group() MapperOption, sets a set of "deferred" columns
- joined by a "group" to load as "undeferred".
-
- - Rewrite of the "deterministic alias name" logic to be part of the SQL
- layer, produces much simpler alias and label names more in the style of
- Hibernate
-
-- sql
-
- - Speed! Clause compilation as well as the mechanics of SQL constructs have
- been streamlined and simplified to a signficant degree, for a 20-30%
- improvement of the statement construction/compilation overhead of 0.3.
-
- - All "type" keyword arguments, such as those to bindparam(), column(),
- Column(), and func.<something>(), renamed to "type_". Those objects still
- name their "type" attribute as "type".
-
- - case_sensitive=(True|False) setting removed from schema items, since
- checking this state added a lot of method call overhead and there was no
- decent reason to ever set it to False. Table and column names which are
- all lower case will be treated as case-insenstive (yes we adjust for
- Oracle's UPPERCASE style too).
-
- - Transactions:
-
- - Added context manager (with statement) support for transactions.
- - Added support for two phase commit, works with mysql and postgres so far.
- - Added a subtransaction implementation that uses savepoints.
- - Added support for savepoints.
-
- - MetaData:
-
- - Tables can be reflected from the database en-masse without declaring
- them in advance. MetaData(engine, reflect=True) will load all tables
- present in the database, or use metadata.reflect() for finer control.
- - DynamicMetaData has been renamed to ThreadLocalMetaData
- - The ThreadLocalMetaData constructor now takes no arguments.
- - BoundMetaData has been removed- regular MetaData is equivalent
-
- - Numeric and Float types now have an "asdecimal" flag; defaults to True for
- Numeric, False for Float. When True, values are returned as
- decimal.Decimal objects; when False, values are returned as float(). The
- defaults of True/False are already the behavior for PG and MySQL's DBAPI
- modules. [ticket:646]
-
- - New SQL operator implementation which removes all hardcoded operators from
- expression structures and moves them into compilation; allows greater
- flexibility of operator compilation; for example, "+" compiles to "||"
- when used in a string context, or "concat(a,b)" on MySQL; whereas in a
- numeric context it compiles to "+". Fixes [ticket:475].
-
- - "Anonymous" alias and label names are now generated at SQL compilation
- time in a completely deterministic fashion... no more random hex IDs
-
- - Significant architectural overhaul to SQL elements (ClauseElement). All
- elements share a common "mutability" framework which allows a consistent
- approach to in-place modifications of elements as well as generative
- behavior. Improves stability of the ORM which makes heavy usage of
- mutations to SQL expressions.
-
- - select() and union()'s now have "generative" behavior. Methods like
- order_by() and group_by() return a *new* instance - the original instance
- is left unchanged. Non-generative methods remain as well.
-
- - The internals of select/union vastly simplified- all decision making
- regarding "is subquery" and "correlation" pushed to SQL generation phase.
- select() elements are now *never* mutated by their enclosing containers or
- by any dialect's compilation process [ticket:52] [ticket:569]
-
- - select(scalar=True) argument is deprecated; use select(..).as_scalar().
- The resulting object obeys the full "column" interface and plays better
- within expressions.
-
- - Added select().with_prefix('foo') allowing any set of keywords to be
- placed before the columns clause of the SELECT [ticket:504]
-
- - Added array slice support to row[<index>] [ticket:686]
-
- - Result sets make a better attempt at matching the DBAPI types present in
- cursor.description to the TypeEngine objects defined by the dialect, which
- are then used for result-processing. Note this only takes effect for
- textual SQL; constructed SQL statements always have an explicit type map.
-
- - Result sets from CRUD operations close their underlying cursor immediately
- and will also autoclose the connection if defined for the operation; this
- allows more efficient usage of connections for successive CRUD operations
- with less chance of "dangling connections".
-
- - Column defaults and onupdate Python functions (i.e. passed to
- ColumnDefault) may take zero or one arguments; the one argument is the
- ExecutionContext, from which you can call "context.parameters[someparam]"
- to access the other bind parameter values affixed to the statement
- [ticket:559]. The connection used for the execution is available as well
- so that you can pre-execute statements.
-
- - Added "explcit" create/drop/execute support for sequences (i.e. you can
- pass a "connectable" to each of those methods on Sequence).
-
- - Better quoting of identifiers when manipulating schemas.
-
- - Standardized the behavior for table reflection where types can't be
- located; NullType is substituted instead, warning is raised.
-
- - ColumnCollection (i.e. the 'c' attribute on tables) follows dictionary
- semantics for "__contains__" [ticket:606]
-
-- engines
-
- - Speed! The mechanics of result processing and bind parameter processing
- have been overhauled, streamlined and optimized to issue as little method
- calls as possible. Bench tests for mass INSERT and mass rowset iteration
- both show 0.4 to be over twice as fast as 0.3, using 68% fewer function
- calls.
-
- - You can now hook into the pool lifecycle and run SQL statements or other
- logic at new each DBAPI connection, pool check-out and check-in.
-
- - Connections gain a .properties collection, with contents scoped to the
- lifetime of the underlying DBAPI connection
-
- - Removed auto_close_cursors and disallow_open_cursors arguments from Pool;
- reduces overhead as cursors are normally closed by ResultProxy and
- Connection.
-
-- extensions
-
- - proxyengine is temporarily removed, pending an actually working
- replacement.
-
- - SelectResults has been replaced by Query. SelectResults /
- SelectResultsExt still exist but just return a slightly modified Query
- object for backwards-compatibility. join_to() method from SelectResults
- isn't present anymore, need to use join().
-
-- mysql
-
- - Table and column names loaded via reflection are now Unicode.
-
- - All standard column types are now supported, including SET.
-
- - Table reflection can now be performed in as little as one round-trip.
-
- - ANSI and ANSI_QUOTES sql modes are now supported.
-
- - Indexes are now reflected.
-
-- postgres
-
- - Added PGArray datatype for using postgres array datatypes.
-
-- oracle
-
- - Very rudimental support for OUT parameters added; use sql.outparam(name,
- type) to set up an OUT parameter, just like bindparam(); after execution,
- values are avaiable via result.out_parameters dictionary. [ticket:507]
-
-0.3.11
-------
-
-- sql
-
- - tweak DISTINCT precedence for clauses like
- `func.count(t.c.col.distinct())`
-
- - Fixed detection of internal '$' characters in :bind$params [ticket:719]
-
- - [ticket:768] dont assume join criterion consists only of column objects
-
- - 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
- 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
- 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
- collection doesn't contain the item, supports noload collections
- [ticket:813]
-
-- engine
-
- - fixed another occasional race condition which could occur
- when using pool with threadlocal setting
-
-- mysql
- - fixed specification of YEAR columns when generating schema
-
-- mssql
-
- - added support for TIME columns (simulated using DATETIME) [ticket:679]
-
- - added support for BIGINT, MONEY, SMALLMONEY, UNIQUEIDENTIFIER and
- SQL_VARIANT [ticket:721]
-
- - index names are now quoted when dropping from reflected tables
- [ticket:684]
-
- - can now specify a DSN for PyODBC, using a URI like mssql:///?dsn=bob
-
-- postgres
-
- - when reflecting tables from alternate schemas, the "default" placed upon
- the primary key, i.e. usually a sequence name, has the "schema" name
- unconditionally quoted, so that schema names which need quoting are fine.
- its slightly unnecessary for schema names which don't need quoting
- but not harmful.
-
-- sqlite
- - passthrough for stringified dates
-
-- firebird
- - supports_sane_rowcount() set to False due to ticket #370 (right way).
- - fixed reflection of Column's nullable property.
-
-- oracle
- - removed LONG_STRING, LONG_BINARY from "binary" types, so type objects
- don't try to read their values as LOB [ticket:622], [ticket:751]
-
-0.3.10
-- general
- - a new mutex that was added in 0.3.9 causes the pool_timeout
- feature to fail during a race condition; threads would
- raise TimeoutError immediately with no delay if many threads
- push the pool into overflow at the same time. this issue has been
- fixed.
-- sql
- - got connection-bound metadata to work with implicit execution
- - foreign key specs can have any chararcter in their identifiers
- [ticket:667]
- - added commutativity-awareness to binary clause comparisons to
- each other, improves ORM lazy load optimization [ticket:664]
-- orm
- - cleanup to connection-bound sessions, SessionTransaction
-- postgres
- - fixed max identifier length (63) [ticket:571]
-
-
-0.3.9
-- general
- - better error message for NoSuchColumnError [ticket:607]
- - finally figured out how to get setuptools version in, available
- as sqlalchemy.__version__ [ticket:428]
- - the various "engine" arguments, such as "engine", "connectable",
- "engine_or_url", "bind_to", etc. are all present, but deprecated.
- they all get replaced by the single term "bind". you also
- set the "bind" of MetaData using
- metadata.bind = <engine or connection>
-- ext
- - iteration over dict association proxies is now dict-like, not
- InstrumentedList-like (e.g. over keys instead of values)
- - association proxies no longer bind tightly to source collections
- [ticket:597], and are constructed with a thunk instead
- - added selectone_by() to assignmapper
-- orm
- - forwards-compatibility with 0.4: added one(), first(), and
- all() to Query. almost all Query functionality from 0.4 is
- present in 0.3.9 for forwards-compat purposes.
- - reset_joinpoint() really really works this time, promise ! lets
- you re-join from the root:
- query.join(['a', 'b']).filter(<crit>).reset_joinpoint().\
- join(['a', 'c']).filter(<some other crit>).all()
- in 0.4 all join() calls start from the "root"
- - added synchronization to the mapper() construction step, to avoid
- thread collisions when pre-existing mappers are compiling in a
- different thread [ticket:613]
- - a warning is issued by Mapper when two primary key columns of the
- same name are munged into a single attribute. this happens frequently
- when mapping to joins (or inheritance).
- - synonym() properties are fully supported by all Query joining/
- with_parent operations [ticket:598]
- - fixed very stupid bug when deleting items with many-to-many
- uselist=False relations
- - remember all that stuff about polymorphic_union ? for
- joined table inheritance ? Funny thing...
- You sort of don't need it for joined table inheritance, you
- can just string all the tables together via outerjoin().
- The UNION still applies if concrete tables are involved,
- though (since nothing to join them on).
- - small fix to eager loading to better work with eager loads
- to polymorphic mappers that are using a straight "outerjoin"
- clause
-- sql
- - ForeignKey to a table in a schema thats not the default schema
- requires the schema to be explicit; i.e. ForeignKey('alt_schema.users.id')
- - MetaData can now be constructed with an engine or url as the first
- argument, just like BoundMetaData
- - BoundMetaData is now deprecated, and MetaData is a direct substitute.
- - DynamicMetaData has been renamed to ThreadLocalMetaData. the
- DynamicMetaData name is deprecated and is an alias for ThreadLocalMetaData
- or a regular MetaData if threadlocal=False
- - composite primary key is represented as a non-keyed set to allow for
- composite keys consisting of cols with the same name; occurs within a
- Join. helps inheritance scenarios formulate correct PK.
- - improved ability to get the "correct" and most minimal set of primary key
- columns from a join, equating foreign keys and otherwise equated columns.
- this is also mostly to help inheritance scenarios formulate the best
- choice of primary key columns. [ticket:185]
- - added 'bind' argument to Sequence.create()/drop(), ColumnDefault.execute()
- - columns can be overridden in a reflected table with a "key"
- attribute different than the column's name, including for primary key
- columns [ticket:650]
- - fixed "ambiguous column" result detection, when dupe col names exist
- in a result [ticket:657]
- - some enhancements to "column targeting", the ability to match a column
- to a "corresponding" column in another selectable. this affects mostly
- ORM ability to map to complex joins
- - MetaData and all SchemaItems are safe to use with pickle. slow
- table reflections can be dumped into a pickled file to be reused later.
- Just reconnect the engine to the metadata after unpickling. [ticket:619]
- - added a mutex to QueuePool's "overflow" calculation to prevent a race
- condition that can bypass max_overflow
- - fixed grouping of compound selects to give correct results. will break
- on sqlite in some cases, but those cases were producing incorrect
- results anyway, sqlite doesn't support grouped compound selects
- [ticket:623]
- - fixed precedence of operators so that parenthesis are correctly applied
- [ticket:620]
- - calling <column>.in_() (i.e. with no arguments) will return
- "CASE WHEN (<column> IS NULL) THEN NULL ELSE 0 END = 1)", so that
- NULL or False is returned in all cases, rather than throwing an error
- [ticket:545]
- - fixed "where"/"from" criterion of select() to accept a unicode string
- in addition to regular string - both convert to text()
- - added standalone distinct() function in addition to column.distinct()
- [ticket:558]
- - result.last_inserted_ids() should return a list that is identically
- sized to the primary key constraint of the table. values that were
- "passively" created and not available via cursor.lastrowid will be None.
- - long-identifier detection fixed to use > rather than >= for
- max ident length [ticket:589]
- - fixed bug where selectable.corresponding_column(selectable.c.col)
- would not return selectable.c.col, if the selectable is a join
- of a table and another join involving the same table. messed
- up ORM decision making [ticket:593]
- - added Interval type to types.py [ticket:595]
-- mysql
- - fixed catching of some errors that imply a dropped connection [ticket:625]
- - fixed escaping of the modulo operator [ticket:624]
- - added 'fields' to reserved words [ticket:590]
- - various reflection enhancement/fixes
-- oracle
- - datetime fixes: got subsecond TIMESTAMP to work [ticket:604],
- added OracleDate which supports types.Date with only year/month/day
- - added dialect flag "auto_convert_lobs", defaults to True; will cause any
- LOB objects detected in a result set to be forced into OracleBinary
- so that the LOB is read() automatically, if no typemap was present
- (i.e., if a textual execute() was issued).
- - mod operator '%' produces MOD [ticket:624]
- - converts cx_oracle datetime objects to Python datetime.datetime when
- Python 2.3 used [ticket:542]
- - fixed unicode conversion in Oracle TEXT type
-- postgres
- - fixed escaping of the modulo operator [ticket:624]
- - added support for reflection of domains [ticket:570]
- - types which are missing during reflection resolve to Null type
- instead of raising an error
- - the fix in "schema" above fixes reflection of foreign keys from an
- alt-schema table to a public schema table
-- sqlite
- - rearranged dialect initialization so it has time to warn about pysqlite1
- being too old.
- - sqlite better handles datetime/date/time objects mixed and matched
- with various Date/Time/DateTime columns
- - string PK column inserts dont get overwritten with OID [ticket:603]
-- mssql
- - fix port option handling for pyodbc [ticket:634]
- - now able to reflect start and increment values for identity columns
- - preliminary support for using scope_identity() with pyodbc
-
-0.3.8
-- engines
- - added detach() to Connection, allows underlying DBAPI connection
- to be detached from its pool, closing on dereference/close()
- instead of being reused by the pool.
- - added invalidate() to Connection, immediately invalidates the
- Connection and its underlying DBAPI connection.
-- sql
- - _Label class overrides compare_self to return its ultimate
- object. meaning, if you say someexpr.label('foo') == 5, it
- produces the correct "someexpr == 5".
- - _Label propagates "_hide_froms()" so that scalar selects
- behave more properly with regards to FROM clause #574
- - fix to long name generation when using oid_column as an order by
- (oids used heavily in mapper queries)
- - significant speed improvement to ResultProxy, pre-caches
- TypeEngine dialect implementations and saves on function calls
- per column
- - parenthesis are applied to clauses via a new _Grouping
- construct. uses operator precedence to more intelligently apply
- parenthesis to clauses, provides cleaner nesting of clauses
- (doesnt mutate clauses placed in other clauses, i.e. no 'parens'
- flag)
- - added 'modifier' keyword, works like func.<foo> except does not
- add parenthesis. e.g. select([modifier.DISTINCT(...)]) etc.
- - removed "no group by's in a select thats part of a UNION"
- restriction [ticket:578]
-- orm
- - added reset_joinpoint() method to Query, moves the "join point"
- back to the starting mapper. 0.4 will change the behavior of
- join() to reset the "join point" in all cases so this is an
- interim method. for forwards compatibility, ensure joins across
- multiple relations are specified using a single join(), i.e.
- join(['a', 'b', 'c']).
- - fixed bug in query.instances() that wouldnt handle more than
- on additional mapper or one additional column.
- - "delete-orphan" no longer implies "delete". ongoing effort to
- separate the behavior of these two operations.
- - many-to-many relationships properly set the type of bind params
- for delete operations on the association table
- - many-to-many relationships check that the number of rows deleted
- from the association table by a delete operation matches the
- expected results
- - session.get() and session.load() propagate **kwargs through to
- query
- - fix to polymorphic query which allows the original
- polymorphic_union to be embedded into a correlated subquery
- [ticket:577]
- - fix to select_by(<propname>=<object instance>) -style joins in
- conjunction with many-to-many relationships, bug introduced in
- r2556
- - the "primary_key" argument to mapper() is propagated to the
- "polymorphic" mapper. primary key columns in this list get
- normalized to that of the mapper's local table.
- - restored logging of "lazy loading clause" under
- sa.orm.strategies logger, got removed in 0.3.7
- - improved support for eagerloading of properties off of mappers
- that are mapped to select() statements; i.e. eagerloader is
- better at locating the correct selectable with which to attach
- its LEFT OUTER JOIN.
-- mysql
- - Nearly all MySQL column types are now supported for declaration
- and reflection. Added NCHAR, NVARCHAR, VARBINARY, TINYBLOB,
- LONGBLOB, YEAR
- - The sqltypes.Binary passthrough now always builds a BLOB,
- avoiding problems with very old database versions
- - support for column-level CHARACTER SET and COLLATE declarations,
- as well as ASCII, UNICODE, NATIONAL and BINARY shorthand.
-- firebird
- - set max identifier length to 31
- - supports_sane_rowcount() set to False due to ticket #370.
- versioned_id_col feature wont work in FB.
- - some execution fixes
--extensions
- - new association proxy implementation, implementing complete
- proxies to list, dict and set-based relation collections
- - added orderinglist, a custom list class that synchronizes an
- object attribute with that object's position in the list
- - small fix to SelectResultsExt to not bypass itself during
- select().
- - added filter(), filter_by() to assignmapper
-
-0.3.7
-- engines
- - warnings module used for issuing warnings (instead of logging)
- - cleanup of DBAPI import strategies across all engines
- [ticket:480]
- - refactoring of engine internals which reduces complexity,
- number of codepaths; places more state inside of ExecutionContext
- to allow more dialect control of cursor handling, result sets.
- ResultProxy totally refactored and also has two versions of
- "buffered" result sets used for different purposes.
- - server side cursor support fully functional in postgres
- [ticket:514].
- - improved framework for auto-invalidation of connections that have
- lost their underlying database, via dialect-specific detection
- of exceptions corresponding to that database's disconnect
- related error messages. Additionally, when a "connection no
- longer open" condition is detected, the entire connection pool
- is discarded and replaced with a new instance. #516
- - the dialects within sqlalchemy.databases become a setuptools
- entry points. loading the built-in database dialects works the
- same as always, but if none found will fall back to trying
- pkg_resources to load an external module [ticket:521]
- - Engine contains a "url" attribute referencing the url.URL object
- used by create_engine().
-- sql:
- - keys() of result set columns are not lowercased, come back
- exactly as they're expressed in cursor.description. note this
- causes colnames to be all caps in oracle.
- - preliminary support for unicode table names, column names and
- SQL statements added, for databases which can support them.
- Works with sqlite and postgres so far. Mysql *mostly* works
- except the has_table() function does not work. Reflection
- works too.
- - the Unicode type is now a direct subclass of String, which now
- contains all the "convert_unicode" logic. This helps the variety
- of unicode situations that occur in db's such as MS-SQL to be
- better handled and allows subclassing of the Unicode datatype.
- [ticket:522]
- - ClauseElements can be used in in_() clauses now, such as bind
- parameters, etc. #476
- - reverse operators implemented for `CompareMixin` elements,
- allows expressions like "5 + somecolumn" etc. #474
- - the "where" criterion of an update() and delete() now correlates
- embedded select() statements against the table being updated or
- deleted. this works the same as nested select() statement
- correlation, and can be disabled via the correlate=False flag on
- the embedded select().
- - column labels are now generated in the compilation phase, which
- means their lengths are dialect-dependent. So on oracle a label
- that gets truncated to 30 chars will go out to 63 characters
- on postgres. Also, the true labelname is always attached as the
- accessor on the parent Selectable so theres no need to be aware
- of the "truncated" label names [ticket:512].
- - column label and bind param "truncation" also generate
- deterministic names now, based on their ordering within the
- full statement being compiled. this means the same statement
- will produce the same string across application restarts and
- allowing DB query plan caching to work better.
- - the "mini" column labels generated when using subqueries, which
- are to work around glitchy SQLite behavior that doesnt understand
- "foo.id" as equivalent to "id", are now only generated in the case
- that those named columns are selected from (part of [ticket:513])
- - the label() method on ColumnElement will properly propagate the
- TypeEngine of the base element out to the label, including a label()
- created from a scalar=True select() statement.
- - MS-SQL better detects when a query is a subquery and knows not to
- generate ORDER BY phrases for those [ticket:513]
- - fix for fetchmany() "size" argument being positional in most
- dbapis [ticket:505]
- - sending None as an argument to func.<something> will produce
- an argument of NULL
- - query strings in unicode URLs get keys encoded to ascii
- for **kwargs compat
- - slight tweak to raw execute() change to also support tuples
- for positional parameters, not just lists [ticket:523]
- - fix to case() construct to propagate the type of the first
- WHEN condition as the return type of the case statement
-- orm:
- - fixed critical issue when, after options(eagerload()) is used,
- the mapper would then always apply query "wrapping" behavior
- for all subsequent LIMIT/OFFSET/DISTINCT queries, even if no
- eager loading was applied on those subsequent queries.
- - added query.with_parent(someinstance) method. searches for
- target instance using lazy join criterion from parent instance.
- takes optional string "property" to isolate the desired relation.
- also adds static Query.query_from_parent(instance, property)
- version. [ticket:541]
- - improved query.XXX_by(someprop=someinstance) querying to use
- similar methodology to with_parent, i.e. using the "lazy" clause
- which prevents adding the remote instance's table to the SQL,
- thereby making more complex conditions possible [ticket:554]
- - added generative versions of aggregates, i.e. sum(), avg(), etc.
- to query. used via query.apply_max(), apply_sum(), etc.
- #552
- - fix to using distinct() or distinct=True in combination with
- join() and similar
- - corresponding to label/bindparam name generation, eager loaders
- generate deterministic names for the aliases they create using
- md5 hashes.
- - improved/fixed custom collection classes when giving it "set"/
- "sets.Set" classes or subclasses (was still looking for append()
- methods on them during lazy loads)
- - restored old "column_property()" ORM function (used to be called
- "column()") to force any column expression to be added as a property
- on a mapper, particularly those that aren't present in the mapped
- selectable. this allows "scalar expressions" of any kind to be
- added as relations (though they have issues with eager loads).
- - fix to many-to-many relationships targeting polymorphic mappers
- [ticket:533]
- - making progress with session.merge() as well as combining its
- usage with entity_name [ticket:543]
- - the usual adjustments to relationships between inheriting mappers,
- in this case establishing relation()s to subclass mappers where
- the join conditions come from the superclass' table
-- informix:
- - informix support added ! courtesy James Zhang, who put a ton
- of effort in.
-- sqlite:
- - removed silly behavior where sqlite would reflect UNIQUE indexes
- as part of the primary key (?!)
-- oracle:
- - small fix to allow successive compiles of the same SELECT object
- which features LIMIT/OFFSET. oracle dialect needs to modify
- the object to have ROW_NUMBER OVER and wasn't performing
- the full series of steps on successive compiles.
-- mysql
- - support for SSL arguments given as inline within URL query string,
- prefixed with "ssl_", courtesy terjeros@gmail.com.
- - mysql uses "DESCRIBE [<schemaname>].<tablename>", catching exceptions
- if table doesnt exist, in order to determine if a table exists.
- this supports unicode table names as well as schema names. tested
- with MySQL5 but should work with 4.1 series as well. (#557)
-- extensions
- - big fix to AssociationProxy so that multiple AssociationProxy
- objects can be associated with a single association collection.
- - assign_mapper names methods according to their keys (i.e. __name__)
- #551
-- mssql
- - pyodbc is now the preferred DB-API for MSSQL, and if no module is
- specifically requested, will be loaded first on a module probe.
-
- - The @@SCOPE_IDENTITY is now used instead of @@IDENTITY. This
- behavior may be overridden with the engine_connect
- "use_scope_identity" keyword parameter, which may also be specified
- in the dburi.
-
-
-
-0.3.6
-- sql:
- - bindparam() names are now repeatable! specify two
- distinct bindparam()s with the same name in a single statement,
- and the key will be shared. proper positional/named args translate
- at compile time. for the old behavior of "aliasing" bind parameters
- with conflicting names, specify "unique=True" - this option is
- still used internally for all the auto-genererated (value-based)
- bind parameters.
-
- - slightly better support for bind params as column clauses, either
- via bindparam() or via literal(), i.e. select([literal('foo')])
-
- - MetaData can bind to an engine either via "url" or "engine" kwargs
- to constructor, or by using connect() method. BoundMetaData is
- identical to MetaData except engine_or_url param is required.
- DynamicMetaData is the same and provides thread-local connections be
- default.
-
- - exists() becomes useable as a standalone selectable, not just in a
- WHERE clause, i.e. exists([columns], criterion).select()
-
- - correlated subqueries work inside of ORDER BY, GROUP BY
-
- - fixed function execution with explicit connections, i.e.
- conn.execute(func.dosomething())
-
- - use_labels flag on select() wont auto-create labels for literal text
- column elements, since we can make no assumptions about the text. to
- create labels for literal columns, you can say "somecol AS
- somelabel", or use literal_column("somecol").label("somelabel")
-
- - quoting wont occur for literal columns when they are "proxied" into
- the column collection for their selectable (is_literal flag is
- propagated). literal columns are specified via
- literal_column("somestring").
-
- - added "fold_equivalents" boolean argument to Join.select(), which
- removes 'duplicate' columns from the resulting column clause that
- are known to be equivalent based on the join condition. this is of
- great usage when constructing subqueries of joins which Postgres
- complains about if duplicate column names are present.
-
- - fixed use_alter flag on ForeignKeyConstraint [ticket:503]
-
- - fixed usage of 2.4-only "reversed" in topological.py [ticket:506]
-
- - for hackers, refactored the "visitor" system of ClauseElement and
- SchemaItem so that the traversal of items is controlled by the
- ClauseVisitor itself, using the method visitor.traverse(item).
- accept_visitor() methods can still be called directly but will not
- do any traversal of child items. ClauseElement/SchemaItem now have a
- configurable get_children() method to return the collection of child
- elements for each parent object. This allows the full traversal of
- items to be clear and unambiguous (as well as loggable), with an
- easy method of limiting a traversal (just pass flags which are
- picked up by appropriate get_children() methods). [ticket:501]
-
- - the "else_" parameter to the case statement now properly works when
- set to zero.
-
-- orm:
- - the full featureset of the SelectResults extension has been merged
- into a new set of methods available off of Query. These methods
- all provide "generative" behavior, whereby the Query is copied
- and a new one returned with additional criterion added.
- The new methods include:
-
- filter() - applies select criterion to the query
- filter_by() - applies "by"-style criterion to the query
- avg() - return the avg() function on the given column
- join() - join to a property (or across a list of properties)
- outerjoin() - like join() but uses LEFT OUTER JOIN
- limit()/offset() - apply LIMIT/OFFSET
- range-based access which applies limit/offset:
- session.query(Foo)[3:5]
- distinct() - apply DISTINCT
- list() - evaluate the criterion and return results
-
- no incompatible changes have been made to Query's API and no methods
- have been deprecated. Existing methods like select(), select_by(),
- get(), get_by() all execute the query at once and return results
- like they always did. join_to()/join_via() are still there although
- the generative join()/outerjoin() methods are easier to use.
-
- - the return value for multiple mappers used with instances() now
- returns a cartesian product of the requested list of mappers,
- represented as a list of tuples. this corresponds to the documented
- behavior. So that instances match up properly, the "uniquing" is
- disabled when this feature is used.
-
- - Query has add_entity() and add_column() generative methods. these
- will add the given mapper/class or ColumnElement to the query at
- compile time, and apply them to the instances() method. the user is
- responsible for constructing reasonable join conditions (otherwise
- you can get full cartesian products). result set is the list of
- tuples, non-uniqued.
-
- - strings and columns can also be sent to the *args of instances()
- where those exact result columns will be part of the result tuples.
-
- - a full select() construct can be passed to query.select() (which
- worked anyway), but also query.selectfirst(), query.selectone()
- which will be used as is (i.e. no query is compiled). works
- similarly to sending the results to instances().
-
- - eager loading will not "aliasize" "order by" clauses that were
- placed in the select statement by something other than the eager
- loader itself, to fix possibility of dupe columns as illustrated in
- [ticket:495]. however, this means you have to be more careful with
- the columns placed in the "order by" of Query.select(), that you
- have explicitly named them in your criterion (i.e. you cant rely on
- the eager loader adding them in for you)
-
- - added a handy multi-use "identity_key()" method to Session, allowing
- the generation of identity keys for primary key values, instances,
- and rows, courtesy Daniel Miller
-
- - many-to-many table will be properly handled even for operations that
- occur on the "backref" side of the operation [ticket:249]
-
- - added "refresh-expire" cascade [ticket:492]. allows refresh() and
- expire() calls to propagate along relationships.
-
- - more fixes to polymorphic relations, involving proper lazy-clause
- generation on many-to-one relationships to polymorphic mappers
- [ticket:493]. also fixes to detection of "direction", more specific
- targeting of columns that belong to the polymorphic union vs. those
- that dont.
-
- - some fixes to relationship calcs when using "viewonly=True" to pull
- in other tables into the join condition which arent parent of the
- relationship's parent/child mappings
-
- - flush fixes on cyclical-referential relationships that contain
- references to other instances outside of the cyclical chain, when
- some of the objects in the cycle are not actually part of the flush
-
- - put an aggressive check for "flushing object A with a collection of
- B's, but you put a C in the collection" error condition - **even if
- C is a subclass of B**, unless B's mapper loads polymorphically.
- Otherwise, the collection will later load a "B" which should be a
- "C" (since its not polymorphic) which breaks in bi-directional
- relationships (i.e. C has its A, but A's backref will lazyload it as
- a different instance of type "B") [ticket:500] This check is going
- to bite some of you who do this without issues, so the error message
- will also document a flag "enable_typechecks=False" to disable this
- checking. But be aware that bi-directional relationships in
- particular become fragile without this check.
-
-- extensions:
- - options() method on SelectResults now implemented "generatively"
- like the rest of the SelectResults methods [ticket:472]. But
- you're going to just use Query now anyway.
-
- - query() method is added by assignmapper. this helps with
- navigating to all the new generative methods on Query.
-
-- ms-sql:
- - removed seconds input on DATE column types (probably
- should remove the time altogether)
-
- - null values in float fields no longer raise errors
-
- - LIMIT with OFFSET now raises an error (MS-SQL has no OFFSET support)
-
- - added an facility to use the MSSQL type VARCHAR(max) instead of TEXT
- for large unsized string fields. Use the new "text_as_varchar" to
- turn it on. [ticket:509]
-
- - ORDER BY clauses without a LIMIT are now stripped in subqueries, as
- MS-SQL forbids this usage
-
- - cleanup of module importing code; specifiable DB-API module; more
- explicit ordering of module preferences. [ticket:480]
-
-- oracle:
- - got binary working for any size input ! cx_oracle works fine,
- it was my fault as BINARY was being passed and not BLOB for
- setinputsizes (also unit tests werent even setting input sizes).
-
- - also fixed CLOB read/write on a separate changeset.
-
- - auto_setinputsizes defaults to True for Oracle, fixed cases where
- it improperly propagated bad types.
-
-- mysql:
- - added a catchall **kwargs to MSString, to help reflection of
- obscure types (like "varchar() binary" in MS 4.0)
-
- - added explicit MSTimeStamp type which takes effect when using
- types.TIMESTAMP.
-
-
-0.3.5
-- sql:
- - the value of "case_sensitive" defaults to True now, regardless of the
- casing of the identifier, unless specifically set to False. this is
- because the object might be label'ed as something else which does
- contain mixed case, and propigating "case_sensitive=False" breaks that.
- Other fixes to quoting when using labels and "fake" column objects
- - added a "supports_execution()" method to ClauseElement, so that
- individual kinds of clauses can express if they are appropriate for
- executing...such as, you can execute a "select", but not a "Table" or a
- "Join".
- - fixed argument passing to straight textual execute() on engine,
- connection. can handle *args or a list instance for positional, **kwargs
- or a dict instance for named args, or a list of list or dicts to invoke
- executemany()
- - small fix to BoundMetaData to accept unicode or string URLs
- - fixed named PrimaryKeyConstraint generation [ticket:466] courtesy
- andrija at gmail
- - fixed generation of CHECK constraints on columns [ticket:464]
- - fixes to tometadata() operation to propagate Constraints at column and
- table level
-- oracle:
- - when returning "rowid" as the ORDER BY column or in use with ROW_NUMBER
- OVER, oracle dialect checks the selectable its being applied to and will
- switch to table PK if not applicable, i.e. for a UNION. checking for
- DISTINCT, GROUP BY (other places that rowid is invalid) still a TODO.
- allows polymorphic mappings to function, [ticket:436]
- - sequences on a non-pk column will properly fire off on INSERT
- - added PrefetchingResultProxy support to pre-fetch LOB columns when they
- are known to be present, fixes [ticket:435]
- - implemented reflection of tables based on synonyms, including across
- dblinks [ticket:379]
- - issues a log warning when a related table cant be reflected due to
- certain permission errors [ticket:363]
-- mysql:
- - fix to reflection on older DB's that might return array() type for
- "show variables like" statements
-- postgres:
- - better reflection of sequences for alternate-schema Tables [ticket:442]
- - sequences on a non-pk column will properly fire off on INSERT
- - added PGInterval type [ticket:460], PGInet type [ticket:444]
-- mssql:
- - preliminary support for pyodbc (Yay!) [ticket:419]
- - better support for NVARCHAR types added [ticket:298]
- - fix for commit logic on pymssql
- - fix for query.get() with schema [ticket:456]
- - fix for non-integer relationships [ticket:473]
- - DB-API module now selectable at run-time [ticket:419]
- - now passes many more unit tests [tickets:422, 481, 415]
- - better unittest compatibility with ANSI functions [ticket:479]
- - improved support for implicit sequence PK columns with auto-insert
- [ticket:415]
- - fix for blank password in adodbapi [ticket:371]
- - fixes to get unit tests working with pyodbc [ticket:481]
- - fix to auto_identity_insert on db-url query
- - added query_timeout to db-url query parms. currently works only for
- pymssql
- - tested with pymssql 0.8.0 (which is now LGPL)
-- orm bugs:
- - another refactoring to relationship calculation. Allows more accurate
- ORM behavior with relationships from/to/between mappers, particularly
- polymorphic mappers, also their usage with Query, SelectResults. tickets
- include [ticket:439], [ticket:441], [ticket:448].
- - removed deprecated method of specifying custom collections on classes;
- you must now use the "collection_class" option. the old way was
- beginning to produce conflicts when people used assign_mapper(), which
- now patches an "options" method, in conjunction with a relationship
- named "options". (relationships take precedence over monkeypatched
- assign_mapper methods).
- - extension() query option propagates to Mapper._instance() method so that
- all loading-related methods get called [ticket:454]
- - eager relation to an inheriting mapper wont fail if no rows returned for
- the relationship.
- - eager relation loading bug fixed for eager relation on multiple
- descendant classes [ticket:486]
- - fix for very large topological sorts, courtesy ants.aasma at gmail
- [ticket:423]
- - eager loading is slightly more strict about detecting "self-referential"
- relationships, specifically between polymorphic mappers. this results in
- an "eager degrade" to lazy loading.
- - improved support for complex queries embedded into "where" criterion for
- query.select() [ticket:449]
- - mapper options like eagerload(), lazyload(), deferred(), will work for
- "synonym()" relationships [ticket:485]
- - fixed bug where cascade operations incorrectly included deleted
- collection items in the cascade [ticket:445]
- - fixed relationship deletion error when one-to-many child item is moved
- to a new parent in a single unit of work [ticket:478]
- - fixed relationship deletion error where parent/child with a single
- column as PK/FK on the child would raise a "blank out the primary key"
- error, if manually deleted or "delete" cascade without "delete-orphan"
- was used
- - fix to deferred so that load operation doesnt mistakenly occur when only
- PK col attributes are set
-- orm enhancements:
- - implemented foreign_keys argument to mapper [ticket:385]. use in
- conjunction with primaryjoin/secondaryjoin arguments to specify/override
- foreign keys defined on the Table instance.
- - contains_eager('foo') automatically implies eagerload('foo')
- - added "alias" argument to contains_eager(). use it to specify the string
- name or Alias instance of an alias used in the query for the eagerly
- loaded child items. easier to use than "decorator"
- - added "contains_alias()" option for result set mapping to an alias of
- the mapped table
- - added support for py2.5 "with" statement with SessionTransaction
- [ticket:468]
-- extensions:
- - added distinct() method to SelectResults. generally should only make a
- difference when using count().
- - added options() method to SelectResults, equivalent to query.options()
- [ticket:472]
- - added optional __table_opts__ dictionary to ActiveMapper, will send kw
- options to Table objects [ticket:462]
- - added selectfirst(), selectfirst_by() to assign_mapper [ticket:467]
-
-0.3.4
-- general:
- - global "insure"->"ensure" change. in US english "insure" is actually
- largely interchangeable with "ensure" (so says the dictionary), so I'm not
- completely illiterate, but its definitely sub-optimal to "ensure" which is
- non-ambiguous.
-- sql:
- - added "fetchmany()" support to ResultProxy
- - added support for column "key" attribute to be useable in
- row[<key>]/row.<key>
- - changed "BooleanExpression" to subclass from "BinaryExpression", so that
- boolean expressions can also follow column-clause behaviors (i.e. label(),
- etc).
- - trailing underscores are trimmed from func.<xxx> calls, such as func.if_()
- - fix to correlation of subqueries when the column list of the select
- statement is constructed with individual calls to append_column(); this
- fixes an ORM bug whereby nested select statements were not getting
- correlated with the main select generated by the Query object.
- - another fix to subquery correlation so that a subquery which has only one
- FROM element will *not* correlate that single element, since at least one
- FROM element is required in a query.
- - default "timezone" setting is now False. this corresponds to Python's
- datetime behavior as well as Postgres' timestamp/time types (which is the
- only timezone-sensitive dialect at the moment) [ticket:414]
- - the "op()" function is now treated as an "operation", rather than a
- "comparison". the difference is, an operation produces a BinaryExpression
- from which further operations can occur whereas comparison produces the
- more restrictive BooleanExpression
- - trying to redefine a reflected primary key column as non-primary key raises
- an error
- - type system slightly modified to support TypeDecorators that can be
- overridden by the dialect (ok, thats not very clear, it allows the mssql
- tweak below to be possible)
-- mssql:
- - added an NVarchar type (produces NVARCHAR), also MSUnicode which provides
- Unicode-translation for the NVarchar regardless of dialect convert_unicode
- setting.
-- postgres:
- - fix to the initial checkfirst for tables to take current schema into
- account [ticket:424]
- - postgres has an optional "server_side_cursors=True" flag which will utilize
- server side cursors. these are appropriate for fetching only partial
- results and are necessary for working with very large unbounded result
- sets. While we'd like this to be the default behavior, different
- environments seem to have different results and the causes have not been
- isolated so we are leaving the feature off by default for now. Uses an
- apparently undocumented psycopg2 behavior recently discovered on the
- psycopg mailing list.
- - added "BIGSERIAL" support for postgres table with
- PGBigInteger/autoincrement
- - fixes to postgres reflection to better handle when schema names are
- present; thanks to jason (at) ncsmags.com [ticket:402]
-- mysql:
- - mysql is inconsistent with what kinds of quotes it uses in foreign keys
- during a SHOW CREATE TABLE, reflection updated to accomodate for all three
- styles [ticket:420]
- - mysql table create options work on a generic passthru now, i.e. Table(...,
- mysql_engine='InnoDB', mysql_collate="latin1_german2_ci",
- mysql_auto_increment="5", mysql_<somearg>...), helps [ticket:418]
-- firebird:
- - order of constraint creation puts primary key first before all other
- constraints; required for firebird, not a bad idea for others [ticket:408]
- - Firebird fix to autoload multifield foreign keys [ticket:409]
- - Firebird NUMERIC type properly handles a type without precision
- [ticket:409]
-- oracle:
- - *slight* support for binary, but still need to figure out how to insert
- reasonably large values (over 4K). requires auto_setinputsizes=True sent to
- create_engine(), rows must be fully fetched individually, etc.
-- orm:
- - poked the first hole in the can of worms: saying
- query.select_by(somerelationname=someinstance) will create the join of the
- primary key columns represented by "somerelationname"'s mapper to the
- actual primary key in "someinstance".
- - reworked how relations interact with "polymorphic" mappers, i.e. mappers
- that have a select_table as well as polymorphic flags. better determination
- of proper join conditions, interaction with user- defined join conditions,
- and support for self-referential polymorphic mappers.
- - related to polymorphic mapping relations, some deeper error checking when
- compiling relations, to detect an ambiguous "primaryjoin" in the case that
- both sides of the relationship have foreign key references in the primary
- join condition. also tightened down conditions used to locate "relation
- direction", associating the "foreignkey" of the relationship with the
- "primaryjoin"
- - a little bit of improvement to the concept of a "concrete" inheritance
- mapping, though that concept is not well fleshed out yet (added test case
- to support concrete mappers on top of a polymorphic base).
- - fix to "proxy=True" behavior on synonym()
- - fixed bug where delete-orphan basically didn't work with many-to-many
- relationships [ticket:427], backref presence generally hid the symptom
- - added a mutex to the mapper compilation step. ive been reluctant to add any
- kind of threading anything to SA but this is one spot that its its really
- needed since mappers are typically "global", and while their state does not
- change during normal operation, the initial compilation step does modify
- internal state significantly, and this step usually occurs not at
- module-level initialization time (unless you call compile()) but at
- first-request time
- - basic idea of "session.merge()" actually implemented. needs more testing.
- - added "compile_mappers()" function as a shortcut to compiling all mappers
- - fix to MapperExtension create_instance so that entity_name properly
- associated with new instance
- - speed enhancements to ORM object instantiation, eager loading of rows
- - invalid options sent to 'cascade' string will raise an exception
- [ticket:406]
- - fixed bug in mapper refresh/expire whereby eager loaders didnt properly
- re-populate item lists [ticket:407]
- - fix to post_update to ensure rows are updated even for non insert/delete
- scenarios [ticket:413]
- - added an error message if you actually try to modify primary key values on
- an entity and then flush it [ticket:412]
-- extensions
- - added "validate=False" argument to assign_mapper, if True will ensure that
- only mapped attributes are named [ticket:426]
- - assign_mapper gets "options", "instances" functions added (i.e.
- MyClass.instances())
-
-0.3.3
-- string-based FROM clauses fixed, i.e. select(..., from_obj=["sometext"])
-- fixes to passive_deletes flag, lazy=None (noload) flag
-- added example/docs for dealing with large collections
-- added object_session() method to sqlalchemy namespace
-- fixed QueuePool bug whereby its better able to reconnect to a database
-that was not reachable (thanks to Sébastien Lelong), also fixed dispose()
-method
-- patch that makes MySQL rowcount work correctly! [ticket:396]
-- fix to MySQL catch of 2006/2014 errors to properly re-raise OperationalError
-exception
-
-0.3.2
-- major connection pool bug fixed. fixes MySQL out of sync
-errors, will also prevent transactions getting rolled back
-accidentally in all DBs [ticket:387]
-- major speed enhancements vs. 0.3.1, to bring speed
-back to 0.2.8 levels
- - made conditional dozens of debug log calls that were
- time-intensive to generate log messages
- - fixed bug in cascade rules whereby the entire object graph
- could be unnecessarily cascaded on the save/update cascade
- - various speedups in attributes module
-- identity map in Session is by default *no longer weak referencing*.
-to have it be weak referencing, use create_session(weak_identity_map=True)
-fixes [ticket:388]
-- MySQL detects errors 2006 (server has gone away) and 2014
-(commands out of sync) and invalidates the connection on which it occured.
-- MySQL bool type fix: [ticket:307]
-- postgres reflection fixes: [ticket:349] [ticket:382]
-- added keywords for EXCEPT, INTERSECT, EXCEPT ALL, INTERSECT ALL
-[ticket:247]
-- assign_mapper in assignmapper extension returns the created mapper
-[changeset:2110]
-- added label() function to Select class, when scalar=True is used
-to create a scalar subquery
-i.e. "select x, y, (select max(foo) from table) AS foomax from table"
-- added onupdate and ondelete keyword arguments to ForeignKey; propagate
-to underlying ForeignKeyConstraint if present. (dont propagate in the
-other direction, however)
-- fix to session.update() to preserve "dirty" status of incoming object
-- sending a selectable to an IN via the in_() function no longer creates
-a "union" out of multiple selects; only one selectable to a the in_() function
-is allowed now (make a union yourself if union is needed)
-- improved support for disabling save-update cascade via cascade="none" etc.
-- added "remote_side" argument to relation(), used only with self-referential
-mappers to force the direction of the parent/child relationship. replaces
-the usage of the "foreignkey" parameter for "switching" the direction.
-"foreignkey" argument is deprecated for all uses and will eventually
-be replaced by an argument dedicated to ForeignKey specification on mappers.
-
-0.3.1
-- Engine/Pool:
- - some new Pool utility classes, updated docs
- - "use_threadlocal" on Pool defaults to False (same as create_engine)
- - fixed direct execution of Compiled objects
- - create_engine() reworked to be strict about incoming **kwargs. all keyword
-arguments must be consumed by one of the dialect, connection pool, and engine
-constructors, else a TypeError is thrown which describes the full set of
-invalid kwargs in relation to the selected dialect/pool/engine configuration.
-- Databases/Types:
- - MySQL catches exception on "describe" and reports as NoSuchTableError
- - further fixes to sqlite booleans, weren't working as defaults
- - fix to postgres sequence quoting when using schemas
-- ORM:
- - the "delete" cascade will load in all child objects, if they were not
-loaded already. this can be turned off (i.e. the old behavior) by setting
-passive_deletes=True on a relation().
- - adjustments to reworked eager query generation to not fail on circular
-eager-loaded relationships (like backrefs)
- - fixed bug where eagerload() (nor lazyload()) option didn't properly
-instruct the Query whether or not to use "nesting" when producing a
-LIMIT query.
- - fixed bug in circular dependency sorting at flush time; if object A
-contained a cyclical many-to-one relationship to object B, and object B
-was just attached to object A, *but* object B itself wasnt changed,
-the many-to-one synchronize of B's primary key attribute to A's foreign key
-attribute wouldnt occur. [ticket:360]
- - implemented from_obj argument for query.count, improves count function
-on selectresults [ticket:325]
- - added an assertion within the "cascade" step of ORM relationships to check
-that the class of object attached to a parent object is appropriate
-(i.e. if A.items stores B objects, raise an error if a C is appended to A.items)
- - new extension sqlalchemy.ext.associationproxy, provides transparent
-"association object" mappings. new example
-examples/association/proxied_association.py illustrates.
- - improvement to single table inheritance to load full hierarchies beneath
-the target class
- - fix to subtle condition in topological sort where a node could appear twice,
-for [ticket:362]
- - additional rework to topological sort, refactoring, for [ticket:365]
- - "delete-orphan" for a certain type can be set on more than one parent class;
-the instance is an "orphan" only if its not attached to *any* of those parents
-
-0.3.0
-- General:
- - logging is now implemented via standard python "logging" module.
- "echo" keyword parameters are still functional but set/unset
- log levels for their respective classes/instances. all logging
- can be controlled directly through the Python API by setting
- INFO and DEBUG levels for loggers in the "sqlalchemy" namespace.
- class-level logging is under "sqlalchemy.<module>.<classname>",
- instance-level logging under "sqlalchemy.<module>.<classname>.0x..<00-FF>".
- Test suite includes "--log-info" and "--log-debug" arguments
- which work independently of --verbose/--quiet. Logging added
- to orm to allow tracking of mapper configurations, row iteration.
- - the documentation-generation system has been overhauled to be
- much simpler in design and more integrated with Markdown
-- Specific Databases:
- - SQLite:
- - sqlite boolean datatype converts False/True to 0/1 by default
- - fixes to Date/Time (SLDate/SLTime) types; works as good as postgres
- now [ticket:335]
- - MS-SQL:
- - fixes bug 261 (table reflection broken for MS-SQL case-sensitive
- databases)
- - can now specify port for pymssql
- - introduces new "auto_identity_insert" option for auto-switching
- between "SET IDENTITY_INSERT" mode when values specified for IDENTITY columns
- - now supports multi-column foreign keys
- - fix to reflecting date/datetime columns
- - NCHAR and NVARCHAR type support added
- - Oracle:
- - Oracle has experimental support for cx_Oracle.TIMESTAMP, which requires
- a setinputsizes() call on the cursor that is now enabled via the
- 'auto_setinputsizes' flag to the oracle dialect.
- - Firebird:
- - aliases do not use "AS"
- - correctly raises NoSuchTableError when reflecting non-existent table
-- Schema:
- - a fair amount of cleanup to the schema package, removal of ambiguous
- methods, methods that are no longer needed. slightly more constrained
- useage, greater emphasis on explicitness
- - the "primary_key" attribute of Table and other selectables becomes
- a setlike ColumnCollection object; is ordered but not numerically
- indexed. a comparison clause between two pks that are derived from the
- same underlying tables (i.e. such as two Alias objects) can be generated
- via table1.primary_key==table2.primary_key
- - ForeignKey(Constraint) supports "use_alter=True", to create/drop a foreign key
- via ALTER. this allows circular foreign key relationships to be set up.
- - append_item() methods removed from Table and Column; preferably
- construct Table/Column/related objects inline, but if needed use
- append_column(), append_foreign_key(), append_constraint(), etc.
- - table.create() no longer returns the Table object, instead has no
- return value. the usual case is that tables are created via metadata,
- which is preferable since it will handle table dependencies.
- - added UniqueConstraint (goes at Table level), CheckConstraint
- (goes at Table or Column level).
- - index=False/unique=True on Column now creates a UniqueConstraint,
- index=True/unique=False creates a plain Index,
- index=True/unique=True on Column creates a unique Index. 'index'
- and 'unique' keyword arguments to column are now boolean only; for
- explcit names and groupings of indexes or unique constraints, use the
- UniqueConstraint/Index constructs explicitly.
- - added autoincrement=True to Column; will disable schema generation
- of SERIAL/AUTO_INCREMENT/identity seq for postgres/mysql/mssql if
- explicitly set to False
- - TypeEngine objects now have methods to deal with copying and comparing
- values of their specific type. Currently used by the ORM, see below.
- - fixed condition that occurred during reflection when a primary key
- column was explciitly overridden, where the PrimaryKeyConstraint would
- get both the reflected and the programmatic column doubled up
- - the "foreign_key" attribute on Column and ColumnElement in general
- is deprecated, in favor of the "foreign_keys" list/set-based attribute,
- which takes into account multiple foreign keys on one column.
- "foreign_key" will return the first element in the "foreign_keys" list/set
- or None if the list is empty.
-- Connections/Pooling/Execution:
- - connection pool tracks open cursors and automatically closes them
- if connection is returned to pool with cursors still opened. Can be
- affected by options which cause it to raise an error instead, or to
- do nothing. fixes issues with MySQL, others
- - fixed bug where Connection wouldnt lose its Transaction
- after commit/rollback
- - added scalar() method to ComposedSQLEngine, ResultProxy
- - ResultProxy will close() the underlying cursor when the ResultProxy
- itself is closed. this will auto-close cursors for ResultProxy objects
- that have had all their rows fetched (or had scalar() called).
- - ResultProxy.fetchall() internally uses DBAPI fetchall() for better efficiency,
- added to mapper iteration as well (courtesy Michael Twomey)
-- SQL Construction:
- - changed "for_update" parameter to accept False/True/"nowait"
- and "read", the latter two of which are interpreted only by
- Oracle and Mysql [ticket:292]
- - added extract() function to sql dialect
- (SELECT extract(field FROM expr))
- - BooleanExpression includes new "negate" argument to specify
- the appropriate negation operator if one is available.
- - calling a negation on an "IN" or "IS" clause will result in
- "NOT IN", "IS NOT" (as opposed to NOT (x IN y)).
- - Function objects know what to do in a FROM clause now. their
- behavior should be the same, except now you can also do things like
- select(['*'], from_obj=[func.my_function()]) to get multiple
- columns from the result, or even use sql.column() constructs to name the
- return columns [ticket:172]
-- ORM:
- - attribute tracking modified to be more intelligent about detecting
- changes, particularly with mutable types. TypeEngine objects now
- take a greater role in defining how to compare two scalar instances,
- including the addition of a MutableType mixin which is implemented by
- PickleType. unit-of-work now tracks the "dirty" list as an expression
- of all persistent objects where the attribute manager detects changes.
- The basic issue thats fixed is detecting changes on PickleType
- objects, but also generalizes type handling and "modified" object
- checking to be more complete and extensible.
- - a wide refactoring to "attribute loader" and "options" architectures.
- ColumnProperty and PropertyLoader define their loading behaivor via switchable
- "strategies", and MapperOptions no longer use mapper/property copying
- in order to function; they are instead propagated via QueryContext
- and SelectionContext objects at query/instances time.
- All of the internal copying of mappers and properties that was used to handle
- inheritance as well as options() has been removed; the structure
- of mappers and properties is much simpler than before and is clearly laid out
- in the new 'interfaces' module.
- - related to the mapper/property overhaul, internal refactoring to
- mapper instances() method to use a SelectionContext object to track
- state during the operation.
- SLIGHT API BREAKAGE: the append_result() and populate_instances()
- methods on MapperExtension have a slightly different method signature
- now as a result of the change; hoping that these methods are not
- in widespread use as of yet.
- - instances() method moved to Query now, backwards-compatible
- version remains on Mapper.
- - added contains_eager() MapperOption, used in conjunction with
- instances() to specify properties that should be eagerly loaded
- from the result set, using their plain column names by default, or translated
- given an custom row-translation function.
- - more rearrangements of unit-of-work commit scheme to better allow
- dependencies within circular flushes to work properly...updated
- task traversal/logging implementation
- - polymorphic mappers (i.e. using inheritance) now produces INSERT
- statements in order of tables across all inherited classes
- [ticket:321]
- - added an automatic "row switch" feature to mapping, which will
- detect a pending instance/deleted instance pair with the same
- identity key and convert the INSERT/DELETE to a single UPDATE
- - "association" mappings simplified to take advantage of
- automatic "row switch" feature
- - "custom list classes" is now implemented via the "collection_class"
- keyword argument to relation(). the old way still works but is
- deprecated [ticket:212]
- - added "viewonly" flag to relation(), allows construction of
- relations that have no effect on the flush() process.
- - added "lockmode" argument to base Query select/get functions,
- including "with_lockmode" function to get a Query copy that has
- a default locking mode. Will translate "read"/"update"
- arguments into a for_update argument on the select side.
- [ticket:292]
- - implemented "version check" logic in Query/Mapper, used
- when version_id_col is in effect and query.with_lockmode()
- is used to get() an instance thats already loaded
- - post_update behavior improved; does a better job at not
- updating too many rows, updates only required columns
- [ticket:208]
- - adjustments to eager loading so that its "eager chain" is
- kept separate from the normal mapper setup, thereby
- preventing conflicts with lazy loader operation, fixes
- [ticket:308]
- - fix to deferred group loading
- - session.flush() wont close a connection it opened [ticket:346]
- - added "batch=True" flag to mapper; if False, save_obj
- will fully save one object at a time including calls
- to before_XXXX and after_XXXX
- - added "column_prefix=None" argument to mapper; prepends the
- given string (typically '_') to column-based attributes automatically
- set up from the mapper's Table
- - specifying joins in the from_obj argument of query.select() will
- replace the main table of the query, if the table is somewhere within
- the given from_obj. this makes it possible to produce custom joins and
- outerjoins in queries without the main table getting added twice.
- [ticket:315]
- - eagerloading is adjusted to more thoughtfully attach its LEFT OUTER JOINs
- to the given query, looking for custom "FROM" clauses that may have
- already been set up.
- - added join_to and outerjoin_to transformative methods to SelectResults,
- to build up join/outerjoin conditions based on property names. also
- added select_from to explicitly set from_obj parameter.
- - removed "is_primary" flag from mapper.
-
-0.2.8
-- cleanup on connection methods + documentation. custom DBAPI
-arguments specified in query string, 'connect_args' argument
-to 'create_engine', or custom creation function via 'creator'
-function to 'create_engine'.
-- added "recycle" argument to Pool, is "pool_recycle" on create_engine,
-defaults to 3600 seconds; connections after this age will be closed and
-replaced with a new one, to handle db's that automatically close
-stale connections [ticket:274]
-- changed "invalidate" semantics with pooled connection; will
-instruct the underlying connection record to reconnect the next
-time its called. "invalidate" will also automatically be called
-if any error is thrown in the underlying call to connection.cursor().
-this will hopefully allow the connection pool to reconnect to a
-database that had been stopped and started without restarting
-the connecting application [ticket:121]
-- eesh ! the tutorial doctest was broken for quite some time.
-- add_property() method on mapper does a "compile all mappers"
-step in case the given property references a non-compiled mapper
-(as it did in the case of the tutorial !)
-- [ticket:277] check for pg sequence already existing before create
-- if a contextual session is established via MapperExtension.get_session
-(as it is using the sessioncontext plugin, etc), a lazy load operation
-will use that session by default if the parent object is not
-persistent with a session already.
-- lazy loads will not fire off for an object that does not have a
-database identity (why?
-see http://www.sqlalchemy.org/trac/wiki/WhyDontForeignKeysLoadData)
-- unit-of-work does a better check for "orphaned" objects that are
-part of a "delete-orphan" cascade, for certain conditions where the
-parent isnt available to cascade from.
-- mappers can tell if one of their objects is an "orphan" based
-on interactions with the attribute package. this check is based
-on a status flag maintained for each relationship
-when objects are attached and detached from each other.
-- it is now invalid to declare a self-referential relationship with
-"delete-orphan" (as the abovementioned check would make them impossible
-to save)
-- improved the check for objects being part of a session when the
-unit of work seeks to flush() them as part of a relationship..
-- [ticket:280] statement execution supports using the same BindParam
-object more than once in an expression; simplified handling of positional
-parameters. nice job by Bill Noon figuring out the basic idea.
-- postgres reflection moved to use pg_schema tables, can be overridden
-with use_information_schema=True argument to create_engine
-[ticket:60], [ticket:71]
-- added case_sensitive argument to MetaData, Table, Column, determines
-itself automatically based on if a parent schemaitem has a non-None
-setting for the flag, or if not, then whether the identifier name is all lower
-case or not. when set to True, quoting is applied to identifiers with mixed or
-uppercase identifiers. quoting is also applied automatically in all cases to
-identifiers that are known to be reserved words or contain other non-standard
-characters. various database dialects can override all of this behavior, but
-currently they are all using the default behavior. tested with postgres, mysql,
-sqlite, oracle. needs more testing with firebird, ms-sql. part of the ongoing
-work with [ticket:155]
-- unit tests updated to run without any pysqlite installed; pool
-test uses a mock DBAPI
-- urls support escaped characters in passwords [ticket:281]
-- added limit/offset to UNION queries (though not yet in oracle)
-- added "timezone=True" flag to DateTime and Time types. postgres
-so far will convert this to "TIME[STAMP] (WITH|WITHOUT) TIME ZONE",
-so that control over timezone presence is more controllable (psycopg2
-returns datetimes with tzinfo's if available, which can create confusion
-against datetimes that dont).
-- fix to using query.count() with distinct, **kwargs with SelectResults
-count() [ticket:287]
-- deregister Table from MetaData when autoload fails; [ticket:289]
-- import of py2.5s sqlite3 [ticket:293]
-- unicode fix for startswith()/endswith() [ticket:296]
-
-0.2.7
-- quoting facilities set up so that database-specific quoting can be
-turned on for individual table, schema, and column identifiers when
-used in all queries/creates/drops. Enabled via "quote=True" in
-Table or Column, as well as "quote_schema=True" in Table. Thanks to
-Aaron Spike for his excellent efforts.
-- assignmapper was setting is_primary=True, causing all sorts of mayhem
-by not raising an error when redundant mappers were set up, fixed
-- added allow_null_pks option to Mapper, allows rows where some
-primary key columns are null (i.e. when mapping to outer joins etc)
-- modifcation to unitofwork to not maintain ordering within the
-"new" list or within the UOWTask "objects" list; instead, new objects
-are tagged with an ordering identifier as they are registered as new
-with the session, and the INSERT statements are then sorted within the
-mapper save_obj. the INSERT ordering has basically been pushed all
-the way to the end of the flush cycle. that way the various sorts and
-organizations occuring within UOWTask (particularly the circular task
-sort) dont have to worry about maintaining order (which they werent anyway)
-- fixed reflection of foreign keys to autoload the referenced table
-if it was not loaded already
-- [ticket:256] - pass URL query string arguments to connect() function
-- [ticket:257] - oracle boolean type
-- custom primary/secondary join conditions in a relation *will* be propagated
-to backrefs by default. specifying a backref() will override this behavior.
-- better check for ambiguous join conditions in sql.Join; propagates to a
-better error message in PropertyLoader (i.e. relation()/backref()) for when
-the join condition can't be reasonably determined.
-- sqlite creates ForeignKeyConstraint objects properly upon table
-reflection.
-- adjustments to pool stemming from changes made for [ticket:224].
-overflow counter should only be decremented if the connection actually
-succeeded. added a test script to attempt testing this.
-- fixed mysql reflection of default values to be PassiveDefault
-- added reflected 'tinyint', 'mediumint' type to MS-SQL [ticket:263],
-[ticket:264]
-- SingletonThreadPool has a size and does a cleanup pass, so that
-only a given number of thread-local connections stay around (needed
-for sqlite applications that dispose of threads en masse)
-- fixed small pickle bug(s) with lazy loaders [ticket:265] [ticket:267]
-- fixed possible error in mysql reflection where certain versions
-return an array instead of string for SHOW CREATE TABLE call
-- fix to lazy loads when mapping to joins [changeset:1770]
-- all create()/drop() calls have a keyword argument of "connectable".
-"engine" is deprecated.
-- fixed ms-sql connect() to work with adodbapi
-- added "nowait" flag to Select()
-- inheritance check uses issubclass() instead of direct __mro__ check
-to make sure class A inherits from B, allowing mapper inheritance to more
-flexibly correspond to class inheritance [ticket:271]
-- SelectResults will use a subselect, when calling an aggregate (i.e.
-max, min, etc.) on a SelectResults that has an ORDER BY clause
-[ticket:252]
-- fixes to types so that database-specific types more easily used;
-fixes to mysql text types to work with this methodology
-[ticket:269]
-- some fixes to sqlite date type organization
-- added MSTinyInteger to MS-SQL [ticket:263]
-
-0.2.6
-- big overhaul to schema to allow truly composite primary and foreign
-key constraints, via new ForeignKeyConstraint and PrimaryKeyConstraint
-objects.
-Existing methods of primary/foreign key creation have not been changed
-but use these new objects behind the scenes. table creation
-and reflection is now more table oriented rather than column oriented.
-[ticket:76]
-- overhaul to MapperExtension calling scheme, wasnt working very well
-previously
-- tweaks to ActiveMapper, supports self-referential relationships
-- slight rearrangement to objectstore (in activemapper/threadlocal)
-so that the SessionContext is referenced by '.context' instead
-of subclassed directly.
-- activemapper will use threadlocal's objectstore if the mod is
-activated when activemapper is imported
-- small fix to URL regexp to allow filenames with '@' in them
-- fixes to Session expunge/update/etc...needs more cleanup.
-- select_table mappers *still* werent always compiling
-- fixed up Boolean datatype
-- added count()/count_by() to list of methods proxied by assignmapper;
-this also adds them to activemapper
-- connection exceptions wrapped in DBAPIError
-- ActiveMapper now supports autoloading column definitions from the
-database if you supply a __autoload__ = True attribute in your
-mapping inner-class. Currently this does not support reflecting
-any relationships.
-- deferred column load could screw up the connection status in
-a flush() under some circumstances, this was fixed
-- expunge() was not working with cascade, fixed.
-- potential endless loop in cascading operations fixed.
-- added "synonym()" function, applied to properties to have a
-propname the same as another, for the purposes of overriding props
-and allowing the original propname to be accessible in select_by().
-- fix to typing in clause construction which specifically helps
-type issues with polymorphic_union (CAST/ColumnClause propagates
-its type to proxy columns)
-- mapper compilation work ongoing, someday it'll work....moved
-around the initialization of MapperProperty objects to be after
-all mappers are created to better handle circular compilations.
-do_init() method is called on all properties now which are more
-aware of their "inherited" status if so.
-- eager loads explicitly disallowed on self-referential relationships, or
-relationships to an inheriting mapper (which is also self-referential)
-- reduced bind param size in query._get to appease the picky oracle
-[ticket:244]
-- added 'checkfirst' argument to table.create()/table.drop(), as
-well as table.exists() [ticket:234]
-- some other ongoing fixes to inheritance [ticket:245]
-- attribute/backref/orphan/history-tracking tweaks as usual...
-
-0.2.5
-- fixed endless loop bug in select_by(), if the traversal hit
-two mappers that referenced each other
-- upgraded all unittests to insert './lib/' into sys.path,
-working around new setuptools PYTHONPATH-killing behavior
-- further fixes with attributes/dependencies/etc....
-- improved error handling for when DynamicMetaData is not connected
-- MS-SQL support largely working (tested with pymssql)
-- ordering of UPDATE and DELETE statements within groups is now
-in order of primary key values, for more deterministic ordering
-- after_insert/delete/update mapper extensions now called per object,
-not per-object-per-table
-- further fixes/refactorings to mapper compilation
-
-0.2.4
-- try/except when the mapper sets init.__name__ on a mapped class,
-supports python 2.3
-- fixed bug where threadlocal engine would still autocommit
-despite a transaction in progress
-- lazy load and deferred load operations require the parent object
-to be in a Session to do the operation; whereas before the operation
-would just return a blank list or None, it now raises an exception.
-- Session.update() is slightly more lenient if the session to which
-the given object was formerly attached to was garbage collected;
-otherwise still requires you explicitly remove the instance from
-the previous Session.
-- fixes to mapper compilation, checking for more error conditions
-- small fix to eager loading combined with ordering/limit/offset
-- utterly remarkable: added a single space between 'CREATE TABLE'
-and '(<the rest of it>' since *thats how MySQL indicates a non-
-reserved word tablename.....* [ticket:206]
-- more fixes to inheritance, related to many-to-many relations
-properly saving
-- fixed bug when specifying explicit module to mysql dialect
-- when QueuePool times out it raises a TimeoutError instead of
-erroneously making another connection
-- Queue.Queue usage in pool has been replaced with a locally
-modified version (works in py2.3/2.4!) that uses a threading.RLock
-for a mutex. this is to fix a reported case where a ConnectionFairy's
-__del__() method got called within the Queue's get() method, which
-then returns its connection to the Queue via the the put() method,
-causing a reentrant hang unless threading.RLock is used.
-- postgres will not place SERIAL keyword on a primary key column
-if it has a foreign key constraint
-- cursor() method on ConnectionFairy allows db-specific extension
-arguments to be propagated [ticket:221]
-- lazy load bind params properly propagate column type [ticket:225]
-- new MySQL types: MSEnum, MSTinyText, MSMediumText, MSLongText, etc.
-more support for MS-specific length/precision params in numeric types
-patch courtesy Mike Bernson
-- some fixes to connection pool invalidate() [ticket:224]
-
-0.2.3
-- overhaul to mapper compilation to be deferred. this allows mappers
-to be constructed in any order, and their relationships to each
-other are compiled when the mappers are first used.
-- fixed a pretty big speed bottleneck in cascading behavior particularly
-when backrefs were in use
-- the attribute instrumentation module has been completely rewritten; its
-now a large degree simpler and clearer, slightly faster. the "history"
-of an attribute is no longer micromanaged with each change and is
-instead part of a "CommittedState" object created when the
-instance is first loaded. HistoryArraySet is gone, the behavior of
-list attributes is now more open ended (i.e. theyre not sets anymore).
-- py2.4 "set" construct used internally, falls back to sets.Set when
-"set" not available/ordering is needed.
-- fix to transaction control, so that repeated rollback() calls
-dont fail (was failing pretty badly when flush() would raise
-an exception in a larger try/except transaction block)
-- "foreignkey" argument to relation() can also be a list. fixed
-auto-foreignkey detection [ticket:151]
-- fixed bug where tables with schema names werent getting indexed in
-the MetaData object properly
-- fixed bug where Column with redefined "key" property wasnt getting
-type conversion happening in the ResultProxy [ticket:207]
-- fixed 'port' attribute of URL to be an integer if present
-- fixed old bug where if a many-to-many table mapped as "secondary"
-had extra columns, delete operations didnt work
-- bugfixes for mapping against UNION queries
-- fixed incorrect exception class thrown when no DB driver present
-- added NonExistentTable exception thrown when reflecting a table
-that doesnt exist [ticket:138]
-- small fix to ActiveMapper regarding one-to-one backrefs, other
-refactorings
-- overridden constructor in mapped classes gets __name__ and
-__doc__ from the original class
-- fixed small bug in selectresult.py regarding mapper extension
-[ticket:200]
-- small tweak to cascade_mappers, not very strongly supported
-function at the moment
-- some fixes to between(), column.between() to propagate typing
-information better [ticket:202]
-- if an object fails to be constructed, is not added to the
-session [ticket:203]
-- CAST function has been made into its own clause object with
-its own compilation function in ansicompiler; allows MySQL
-to silently ignore most CAST calls since MySQL
-seems to only support the standard CAST syntax with Date types.
-MySQL-compatible CAST support for strings, ints, etc. a TODO
-
-0.2.2
-- big improvements to polymorphic inheritance behavior, enabling it
-to work with adjacency list table structures [ticket:190]
-- major fixes and refactorings to inheritance relationships overall,
-more unit tests
-- fixed "echo_pool" flag on create_engine()
-- fix to docs, removed incorrect info that close() is unsafe to use
-with threadlocal strategy (its totally safe !)
-- create_engine() can take URLs as string or unicode [ticket:188]
-- firebird support partially completed;
-thanks to James Ralston and Brad Clements for their efforts.
-- Oracle url translation was broken, fixed, will feed host/port/sid
-into cx_oracle makedsn() if 'database' field is present, else uses
-straight TNS name from the 'host' field
-- fix to using unicode criterion for query.get()/query.load()
-- count() function on selectables now uses table primary key or
-first column instead of "1" for criterion, also uses label "rowcount"
-instead of "count".
-- got rudimental "mapping to multiple tables" functionality cleaned up,
-more correctly documented
-- restored global_connect() function, attaches to a DynamicMetaData
-instance called "default_metadata". leaving MetaData arg to Table
-out will use the default metadata.
-- fixes to session cascade behavior, entity_name propigation
-- reorganized unittests into subdirectories
-- more fixes to threadlocal connection nesting patterns
-
-0.2.1
-- "pool" argument to create_engine() properly propagates
-- fixes to URL, raises exception if not parsed, does not pass blank
-fields along to the DB connect string (a string such as
-user:host@/db was breaking on postgres)
-- small fixes to Mapper when it inserts and tries to get
-new primary key values back
-- rewrote half of TLEngine, the ComposedSQLEngine used with
-'strategy="threadlocal"'. it now properly implements engine.begin()/
-engine.commit(), which nest fully with connection.begin()/trans.commit().
-added about six unittests.
-- major "duh" in pool.Pool, forgot to put back the WeakValueDictionary.
-unittest which was supposed to check for this was also silently missing
-it. fixed unittest to ensure that ConnectionFairy properly falls out
-of scope.
-- placeholder dispose() method added to SingletonThreadPool, doesnt
-do anything yet
-- rollback() is automatically called when an exception is raised,
-but only if theres no transaction in process (i.e. works more like
-autocommit).
-- fixed exception raise in sqlite if no sqlite module present
-- added extra example detail for association object doc
-- Connection adds checks for already being closed
-
-0.2.0
-- overhaul to Engine system so that what was formerly the SQLEngine
-is now a ComposedSQLEngine which consists of a variety of components,
-including a Dialect, ConnectionProvider, etc. This impacted all the
-db modules as well as Session and Mapper.
-- create_engine now takes only RFC-1738-style strings:
-driver://user:password@host:port/database
-- total rewrite of connection-scoping methodology, Connection objects
-can now execute clause elements directly, added explicit "close" as
-well as support throughout Engine/ORM to handle closing properly,
-no longer relying upon __del__ internally to return connections
-to the pool [ticket:152].
-- overhaul to Session interface and scoping. uses hibernate-style
-methods, including query(class), save(), save_or_update(), etc.
-no threadlocal scope is installed by default. Provides a binding
-interface to specific Engines and/or Connections so that underlying
-Schema objects do not need to be bound to an Engine. Added a basic
-SessionTransaction object that can simplistically aggregate transactions
-across multiple engines.
-- overhaul to mapper's dependency and "cascade" behavior; dependency logic
-factored out of properties.py into a separate module "dependency.py".
-"cascade" behavior is now explicitly controllable, proper implementation
-of "delete", "delete-orphan", etc. dependency system can now determine at
-flush time if a child object has a parent or not so that it makes better
-decisions on how that child should be updated in the DB with regards to deletes.
-- overhaul to Schema to build upon MetaData object instead of an Engine.
-Entire SQL/Schema system can be used with no Engines whatsoever, executed
-solely by an explicit Connection object. the "bound" methodlogy exists via the
-BoundMetaData for schema objects. ProxyEngine is generally not needed
-anymore and is replaced by DynamicMetaData.
-- true polymorphic behavior implemented, fixes [ticket:167]
-- "oid" system has been totally moved into compile-time behavior;
-if they are used in an order_by where they are not available, the order_by
-doesnt get compiled, fixes [ticket:147]
-- overhaul to packaging; "mapping" is now "orm", "objectstore" is now
-"session", the old "objectstore" namespace gets loaded in via the
-"threadlocal" mod if used
-- mods now called in via "import <modname>". extensions favored over
-mods as mods are globally-monkeypatching
-- fix to add_property so that it propagates properties to inheriting
-mappers [ticket:154]
-- backrefs create themselves against primary mapper of its originating
-property, priamry/secondary join arguments can be specified to override.
-helps their usage with polymorphic mappers
-- "table exists" function has been implemented [ticket:31]
-- "create_all/drop_all" added to MetaData object [ticket:98]
-- improvements and fixes to topological sort algorithm, as well as more
-unit tests
-- tutorial page added to docs which also can be run with a custom doctest
-runner to ensure its properly working. docs generally overhauled to
-deal with new code patterns
-- many more fixes, refactorings.
-- migration guide is available on the Wiki at
-http://www.sqlalchemy.org/trac/wiki/02Migration
-
-0.1.7
-- some fixes to topological sort algorithm
-- added DISTINCT ON support to Postgres (just supply distinct=[col1,col2..])
-- added __mod__ (% operator) to sql expressions
-- "order_by" mapper property inherited from inheriting mapper
-- fix to column type used when mapper UPDATES/DELETEs
-- with convert_unicode=True, reflection was failing, has been fixed
-- types types types! still werent working....have to use TypeDecorator again :(
-- mysql binary type converts array output to buffer, fixes PickleType
-- fixed the attributes.py memory leak once and for all
-- unittests are qualified based on the databases that support each one
-- fixed bug where column defaults would clobber VALUES clause of insert objects
-- fixed bug where table def w/ schema name would force engine connection
-- fix for parenthesis to work correctly with subqueries in INSERT/UPDATE
-- HistoryArraySet gets extend() method
-- fixed lazyload support for other comparison operators besides =
-- lazyload fix where two comparisons in the join condition point to the
-samem column
-- added "construct_new" flag to mapper, will use __new__ to create instances
-instead of __init__ (standard in 0.2)
-- added selectresults.py to SVN, missed it last time
-- tweak to allow a many-to-many relationship from a table to itself via
-an association table
-- small fix to "translate_row" function used by polymorphic example
-- create_engine uses cgi.parse_qsl to read query string (out the window in 0.2)
-- tweaks to CAST operator
-- fixed function names LOCAL_TIME/LOCAL_TIMESTAMP -> LOCALTIME/LOCALTIMESTAMP
-- fixed order of ORDER BY/HAVING in compile
-
-0.1.6
-- support for MS-SQL added courtesy Rick Morrison, Runar Petursson
-- the latest SQLSoup from J. Ellis
-- ActiveMapper has preliminary support for inheritance (Jeff Watkins)
-- added a "mods" system which allows pluggable modules that modify/augment
-core functionality, using the function "install_mods(*modnames)".
-- added the first "mod", SelectResults, which modifies mapper selects to
-return generators that turn ranges into LIMIT/OFFSET queries (Jonas Borgstr?- factored out querying capabilities of Mapper into a separate Query object
-which is Session-centric. this improves the performance of mapper.using(session)
-and makes other things possible.
-- objectstore/Session refactored, the official way to save objects is now
-via the flush() method. The begin/commit functionality of Session is factored
-into LegacySession which is still established as the default behavior, until
-the 0.2 series.
-- types system is bound to an engine at query compile time, not schema
-construction time. this simplifies the types system as well as the ProxyEngine.
-- added 'version_id' keyword argument to mapper. this keyword should reference a
-Column object with type Integer, preferably non-nullable, which will be used on
-the mapped table to track version numbers. this number is incremented on each
-save operation and is specifed in the UPDATE/DELETE conditions so that it
-factors into the returned row count, which results in a ConcurrencyError if the
-value received is not the expected count.
-- added 'entity_name' keyword argument to mapper. a mapper is now associated
-with a class via the class object as well as an optional entity_name parameter,
-which is a string defaulting to None. any number of primary mappers can be
-created for a class, qualified by the entity name. instances of those classes
-will issue all of their load and save operations through their
-entity_name-qualified mapper, and maintain separate a identity in the identity
-map for an otherwise equilvalent object.
-- overhaul to the attributes system. code has been clarified, and also fixed to
-support proper polymorphic behavior on object attributes.
-- added "for_update" flag to Select objects
-- some fixes for backrefs
-- fix for postgres1 DateTime type
-- documentation pages mostly switched over to Markdown syntax
-
-0.1.5
-- added SQLSession concept to SQLEngine. this object keeps track of retrieving a
-connection from the connection pool as well as an in-progress transaction.
-methods push_session() and pop_session() added to SQLEngine which push/pop a new
-SQLSession onto the engine, allowing operation upon a second connection "nested"
-within the previous one, allowing nested transactions. Other tricks are sure to
-come later regarding SQLSession.
-- added nest_on argument to objectstore.Session. This is a single SQLEngine or
-list of engines for which push_session()/pop_session() will be called each time
-this Session becomes the active session (via objectstore.push_session() or
-equivalent). This allows a unit of work Session to take advantage of the nested
-transaction feature without explicitly calling push_session/pop_session on the
-engine.
-- factored apart objectstore/unitofwork to separate "Session scoping" from
-"uow commit heavy lifting"
-- added populate_instance() method to MapperExtension. allows an extension to
-modify the population of object attributes. this method can call the
-populate_instance() method on another mapper to proxy the attribute population
-from one mapper to another; some row translation logic is also built in to help
-with this.
-- fixed Oracle8-compatibility "use_ansi" flag which converts JOINs to
-comparisons with the = and (+) operators, passes basic unittests
-- tweaks to Oracle LIMIT/OFFSET support
-- Oracle reflection uses ALL_** views instead of USER_** to get larger
-list of stuff to reflect from
-- fixes to Oracle foreign key reflection [ticket:105]
-- objectstore.commit(obj1, obj2,...) adds an extra step to seek out private
-relations on properties and delete child objects, even though its not a global
-commit
-- lots and lots of fixes to mappers which use inheritance, strengthened the
-concept of relations on a mapper being made towards the "local" table for that
-mapper, not the tables it inherits. allows more complex compositional patterns
-to work with lazy/eager loading.
-- added support for mappers to inherit from others based on the same table,
-just specify the same table as that of both parent/child mapper.
-- some minor speed improvements to the attributes system with regards to
-instantiating and populating new objects.
-- fixed MySQL binary unit test
-- INSERTs can receive clause elements as VALUES arguments, not just literal
-values
-- support for calling multi-tokened functions, i.e. schema.mypkg.func()
-- added J. Ellis' SQLSoup module to extensions package
-- added "polymorphic" examples illustrating methods to load multiple object types
-from one mapper, the second of which uses the new populate_instance() method.
-small improvements to mapper, UNION construct to help the examples along
-- improvements/fixes to session.refresh()/session.expire() (which may have
-been called "invalidate" earlier..)
-- added session.expunge() which totally removes an object from the current
-session
-- added *args, **kwargs pass-thru to engine.transaction(func) allowing easier
-creation of transactionalizing decorator functions
-- added iterator interface to ResultProxy: "for row in result:..."
-- added assertion to tx = session.begin(); tx.rollback(); tx.begin(), i.e. cant
-use it after a rollback()
-- added date conversion on bind parameter fix to SQLite enabling dates to
-work with pysqlite1
-- improvements to subqueries to more intelligently construct their FROM
-clauses [ticket:116]
-- added PickleType to types.
-- fixed two bugs with column labels with regards to bind parameters: bind param
-keynames they are now generated from a column "label" in all relevant cases to
-take advantage of excess-name-length rules, and checks for a peculiar collision
-against a column named the same as "tablename_colname" added
-- major overhaul to unit of work documentation, other documentation sections.
-- fixed attributes bug where if an object is committed, its lazy-loaded list got
-blown away if it hadnt been loaded
-- added unique_connection() method to engine, connection pool to return a
-connection that is not part of the thread-local context or any current
-transaction
-- added invalidate() function to pooled connection. will remove the connection
-from the pool. still need work for engines to auto-reconnect to a stale DB
-though.
-- added distinct() function to column elements so you can do
-func.count(mycol.distinct())
-- added "always_refresh" flag to Mapper, creates a mapper that will always
-refresh the attributes of objects it gets/selects from the DB, overwriting any
-changes made.
-
-0.1.4
-- create_engine() now uses genericized parameters; host/hostname,
-db/dbname/database, password/passwd, etc. for all engine connections. makes
- engine URIs much more "universal"
-- added support for SELECT statements embedded into a column clause, using the
-flag "scalar=True"
-- another overhaul to EagerLoading when used in conjunction with mappers that
-inherit; improvements to eager loads figuring out their aliased queries
-correctly, also relations set up against a mapper with inherited mappers will
-create joins against the table that is specific to the mapper itself (i.e. and
-not any tables that are inherited/are further down the inheritance chain),
-this can be overridden by using custom primary/secondary joins.
-- added J.Ellis patch to mapper.py so that selectone() throws an exception
-if query returns more than one object row, selectfirst() to not throw the
-exception. also adds selectfirst_by (synonymous with get_by) and selectone_by
-- added onupdate parameter to Column, will exec SQL/python upon an update
-statement.Also adds "for_update=True" to all DefaultGenerator subclasses
-- added support for Oracle table reflection contributed by Andrija Zaric;
-still some bugs to work out regarding composite primary keys/dictionary selection
-- checked in an initial Firebird module, awaiting testing.
-- added sql.ClauseParameters dictionary object as the result for
-compiled.get_params(), does late-typeprocessing of bind parameters so
-that the original values are easier to access
-- more docs for indexes, column defaults, connection pooling, engine construction
-- overhaul to the construction of the types system. uses a simpler inheritance
-pattern so that any of the generic types can be easily subclassed, with no need
-for TypeDecorator.
-- added "convert_unicode=False" parameter to SQLEngine, will cause all String
-types to perform unicode encoding/decoding (makes Strings act like Unicodes)
-- added 'encoding="utf8"' parameter to engine. the given encoding will be
-used for all encode/decode calls within Unicode types as well as Strings
-when convert_unicode=True.
-- improved support for mapping against UNIONs, added polymorph.py example
-to illustrate multi-class mapping against a UNION
-- fix to SQLite LIMIT/OFFSET syntax
-- fix to Oracle LIMIT syntax
-- added backref() function, allows backreferences to have keyword arguments
-that will be passed to the backref.
-- Sequences and ColumnDefault objects can do execute()/scalar() standalone
-- SQL functions (i.e. func.foo()) can do execute()/scalar() standalone
-- fix to SQL functions so that the ANSI-standard functions, i.e. current_timestamp
-etc., do not specify parenthesis. all other functions do.
-- added settattr_clean and append_clean to SmartProperty, which set
-attributes without triggering a "dirty" event or any history. used as:
-myclass.prop1.setattr_clean(myobject, 'hi')
-- improved support to column defaults when used by mappers; mappers will pull
-pre-executed defaults from statement's executed bind parameters
-(pre-conversion) to populate them into a saved object's attributes; if any
-PassiveDefaults have fired off, will instead post-fetch the row from the DB to
-populate the object.
-- added 'get_session().invalidate(*obj)' method to objectstore, instances will
-refresh() themselves upon the next attribute access.
-- improvements to SQL func calls including an "engine" keyword argument so
-they can be execute()d or scalar()ed standalone, also added func accessor to
-SQLEngine
-- fix to MySQL4 custom table engines, i.e. TYPE instead of ENGINE
-- slightly enhanced logging, includes timestamps and a somewhat configurable
-formatting system, in lieu of a full-blown logging system
-- improvements to the ActiveMapper class from the TG gang, including
-many-to-many relationships
-- added Double and TinyInt support to mysql
-
-0.1.3
-- completed "post_update" feature, will add a second update statement before
-inserts and after deletes in order to reconcile a relationship without any
-dependencies being created; used when persisting two rows that are dependent
-on each other
-- completed mapper.using(session) function, localized per-object Session
-functionality; objects can be declared and manipulated as local to any
-user-defined Session
-- fix to Oracle "row_number over" clause with multiple tables
-- mapper.get() was not selecting multiple-keyed objects if the mapper's table was a join,
-such as in an inheritance relationship, this is fixed.
-- overhaul to sql/schema packages so that the sql package can run all on its own,
-producing selects, inserts, etc. without any engine dependencies. builds upon
-new TableClause/ColumnClause lexical objects. Schema's Table/Column objects
-are the "physical" subclasses of them. simplifies schema/sql relationship,
-extensions (like proxyengine), and speeds overall performance by a large margin.
-removes the entire getattr() behavior that plagued 0.1.1.
-- refactoring of how the mapper "synchronizes" data between two objects into a
-separate module, works better with properties attached to a mapper that has an
-additional inheritance relationship to one of the related tables, also the same
-methodology used to synchronize parent/child objects now used by mapper to
-synchronize between inherited and inheriting mappers.
-- made objectstore "check for out-of-identitymap" more aggressive, will perform the
-check when object attributes are modified or the object is deleted
-- Index object fully implemented, can be constructed standalone, or via
-"index" and "unique" arguments on Columns.
-- added "convert_unicode" flag to SQLEngine, will treat all String/CHAR types
-as Unicode types, with raw-byte/utf-8 translation on the bind parameter and
-result set side.
-- postgres maintains a list of ANSI functions that must have no parenthesis so
-function calls with no arguments work consistently
-- tables can be created with no engine specified. this will default their engine
-to a module-scoped "default engine" which is a ProxyEngine. this engine can
-be connected via the function "global_connect".
-- added "refresh(*obj)" method to objectstore / Session to reload the attributes of
-any set of objects from the database unconditionally
-
-0.1.2
-- fixed a recursive call in schema that was somehow running 994 times then returning
-normally. broke nothing, slowed down everything. thanks to jpellerin for finding this.
-
-0.1.1
-- small fix to Function class so that expressions with a func.foo() use the type of the
-Function object (i.e. the left side) as the type of the boolean expression, not the
-other side which is more of a moving target (changeset 1020).
-- creating self-referring mappers with backrefs slightly easier (but still not that easy -
-changeset 1019)
-- fixes to one-to-one mappings (changeset 1015)
-- psycopg1 date/time issue with None fixed (changeset 1005)
-- two issues related to postgres, which doesnt want to give you the "lastrowid"
-since oids are deprecated:
- * postgres database-side defaults that are on primary key cols *do* execute
-explicitly beforehand, even though thats not the idea of a PassiveDefault. this is
-because sequences on columns get reflected as PassiveDefaults, but need to be explicitly
-executed on a primary key col so we know what we just inserted.
- * if you did add a row that has a bunch of database-side defaults on it,
-and the PassiveDefault thing was working the old way, i.e. they just execute on
-the DB side, the "cant get the row back without an OID" exception that occurred
-also will not happen unless someone (usually the ORM) explicitly asks for it.
-- fixed a glitch with engine.execute_compiled where it was making a second
-ResultProxy that just got thrown away.
-- began to implement newer logic in object properities. you can now say
-myclass.attr.property, which will give you the PropertyLoader corresponding to that
-attribute, i.e. myclass.mapper.props['attr']
-- eager loading has been internally overhauled to use aliases at all times. more
-complicated chains of eager loads can now be created without any need for explicit
-"use aliases"-type instructions. EagerLoader code is also much simpler now.
-- a new somewhat experimental flag "use_update" added to relations, indicates that
-this relationship should be handled by a second UPDATE statement, either after a
-primary INSERT or before a primary DELETE. handles circular row dependencies.
-- added exceptions module, all raised exceptions (except for some
-KeyError/AttributeError exceptions) descend from these classes.
-- fix to date types with MySQL, returned timedelta converted to datetime.time
-- two-phase objectstore.commit operations (i.e. begin/commit) now return a
-transactional object (SessionTrans), to more clearly indicate transaction boundaries.
-- Index object with create/drop support added to schema
-- fix to postgres, where it will explicitly pre-execute a PassiveDefault on a table
-if it is a primary key column, pursuant to the ongoing "we cant get inserted rows
-back from postgres" issue
-- change to information_schema query that gets back postgres table defs, now
-uses explicit JOIN keyword, since one user had faster performance with 8.1
-- fix to engine.process_defaults so it works correctly with a table that has
-different column name/column keys (changset 982)
-- a column can only be attached to one table - this is now asserted
-- postgres time types descend from Time type
-- fix to alltests so that it runs types test (now named testtypes)
-- fix to Join object so that it correctly exports its foreign keys (cs 973)
-- creating relationships against mappers that use inheritance fixed (cs 973)
-
-0.1.0
-initial release
-
+For changes prior to 0.5, see CHANGES_PRE_05
--- /dev/null
+-*- coding: utf-8; fill-column: 68 -*-
+
+===============
+CHANGES PRE-0.5
+===============
+
+0.4.7
+=====
+- orm
+ - The contains() operator when used with many-to-many
+ will alias() the secondary (association) table so
+ that multiple contains() calls will not conflict
+ with each other [ticket:1058]
+
+ - 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.
+ Totally unrelated types, or subtypes not set up with
+ mapper inheritance against the target mapper are
+ still not allowed.
+
+ - Added is_active flag to Sessions to detect when
+ a transaction is in progress [ticket:976]. This
+ 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
+ more characters than that dialect's configured
+ character limit. Some DB's can handle too-long
+ table names during usage, and SQLA can handle this
+ as well. But various reflection/
+ checkfirst-during-create scenarios fail since we are
+ looking for the name within the DB's catalog tables.
+ [ticket:571]
+
+ - The index name generated when you say "index=True"
+ on a Column is truncated to the length appropriate
+ for the dialect. Additionally, an Index with a too-
+ long name cannot be explicitly dropped with
+ Index.drop(), similar to [ticket:571].
+ [ticket:820]
+
+- postgres
+ - Repaired server_side_cursors to properly detect
+ text() clauses.
+
+ - Added PGCidr type. [ticket:1092]
+
+- mysql
+ - Added 'CALL' to the list of SQL keywords which return
+ result rows.
+
+- oracle
+ - Oracle get_default_schema_name() "normalizes" the name
+ before returning, meaning it returns a lower-case name
+ when the identifier is detected as case insensitive.
+
+ - creating/dropping tables takes schema name into account
+ when searching for the existing table, so that tables
+ 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
+ "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,
+ but less so). [ticket:1062]
+
+- sqlite
+ - add SLFloat type, which matches the SQLite REAL
+ type affinity. Previously, only SLNumeric was provided
+ which fulfills NUMERIC affinity, but that's not the
+ same as REAL.
+
+0.4.6
+=====
+- orm
+ - Fix to the recent relation() refactoring which fixes
+ exotic viewonly relations which join between local and
+ remote table multiple times, with a common column shared
+ between the joins.
+
+ - Also re-established viewonly relation() configurations
+ that join across multiple tables.
+
+ - Added experimental relation() flag to help with
+ primaryjoins across functions, etc.,
+ _local_remote_pairs=[tuples]. This complements a complex
+ primaryjoin condition allowing you to provide the
+ individual column pairs which comprise the relation's
+ local and remote sides. Also improved lazy load SQL
+ generation to handle placing bind params inside of
+ functions and other expressions. (partial progress
+ towards [ticket:610])
+
+ - 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
+ into the EXISTS clause for relations that link to subclasses.
+
+ - 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
+ 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
+ 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 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 objects don't trigger an error.
+
+ - 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
+ function.
+
+ - Fixed bug with union() when applied to non-Table connected
+ select statements
+
+ - 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
+ returned. This flag is only safe to use with a database
+ which does not support transactions (i.e. MySQL/MyISAM).
+
+- ext
+ - set-based association proxies |=, -=, ^= and &= are
+ stricter about their operands and only operate on sets,
+ frozensets or other association proxies. Previously, they
+ would accept any duck-typed set.
+
+- mssql
+ - Added "odbc_autotranslate" parameter to engine / dburi
+ parameters. Any given string will be passed through to the
+ ODBC connection string as:
+
+ "AutoTranslate=%s" % odbc_autotranslate
+
+ [ticket:1005]
+
+ - Added "odbc_options" parameter to engine / dburi
+ parameters. The given string is simply appended to the
+ SQLAlchemy-generated odbc connection string.
+
+ This should obviate the need of adding a myriad of ODBC
+ options in the future.
+
+- firebird
+ - Handle the "SUBSTRING(:string FROM :start FOR :length)"
+ builtin.
+
+0.4.5
+=====
+- orm
+ - A small change in behavior to session.merge() - existing
+ objects are checked for based on primary key attributes, not
+ necessarily _instance_key. So the widely requested
+ capability, that:
+
+ x = MyObject(id=1)
+ x = sess.merge(x)
+
+ will in fact load MyObject with id #1 from the database if
+ present, is now available. merge() still copies the state
+ of the given object to the persistent one, so an example
+ like the above would typically have copied "None" from all
+ attributes of "x" onto the persistent copy. These can be
+ reverted using session.expire(x).
+
+ - Also fixed behavior in merge() whereby collection elements
+ present on the destination but not the merged collection
+ were not being removed from the destination.
+
+ - Added a more aggressive check for "uncompiled mappers",
+ helps particularly with declarative layer [ticket:995]
+
+ - The methodology behind "primaryjoin"/"secondaryjoin" has
+ been refactored. Behavior should be slightly more
+ intelligent, primarily in terms of error messages which
+ have been pared down to be more readable. In a slight
+ number of scenarios it can better resolve the correct
+ foreign key than before.
+
+ - 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.
+
+ 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
+ with_polymorphic('*', select_table). Note that the
+ underlying "guts" of select_table have been
+ completely removed and replaced with the newer,
+ more flexible approach.
+
+ The new approach also automatically allows eager loads
+ to work for subclasses, if they are present, for
+ example
+ sess.query(Company).options(
+ eagerload_all(
+ [Company.employees.of_type(Engineer), 'machines']
+ ))
+ to load Company objects, their employees, and the
+ 'machines' collection of employees who happen to be
+ 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,
+ "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
+ value is a list of tuples just like when using
+ add_column() or add_entity(), the only difference is
+ 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.
+
+ 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
+ we're looking for is how people want to use
+ _values()...i.e. at the very end, or do people prefer
+ to continue generating after it's called.
+
+ - _from_self() compiles the SELECT statement for the
+ Query (minus any eager loaders), and returns a new
+ Query that selects from that SELECT. So basically you
+ can query from a Query without needing to extract the
+ SELECT statement manually. This gives meaning to
+ operations like query[3:5]._from_self().filter(some
+ criterion). There's not much controversial here
+ 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()
+ already does).
+
+ - Added some convenience descriptors to Query:
+ query.statement returns the full SELECT construct,
+ query.whereclause returns just the WHERE part of the
+ SELECT construct.
+
+ - Fixed/covered case when using a False/0 value as a
+ polymorphic discriminator.
+
+ - Fixed bug which was preventing synonym() attributes from
+ being used with inheritance
+
+ - Fixed SQL function truncation of trailing underscores
+ [ticket:996]
+
+ - When attributes are expired on a pending instance, an
+ error will not be raised when the "refresh" action is
+ triggered and no result is found.
+
+ - Session.execute can now find binds from metadata
+
+ - Adjusted the definition of "self-referential" to be any
+ two mappers with a common parent (this affects whether or
+ not aliased=True is required when joining with Query).
+
+ - Made some fixes to the "from_joinpoint" argument to
+ query.join() so that if the previous join was aliased and
+ this one isn't, the join still happens successfully.
+
+ - Assorted "cascade deletes" fixes:
+ - Fixed "cascade delete" operation of dynamic relations,
+ which had only been implemented for foreign-key
+ nulling behavior in 0.4.2 and not actual cascading
+ deletes [ticket:895]
+
+ - Delete cascade without delete-orphan cascade on a
+ many-to-one will not delete orphans which were
+ disconnected from the parent before session.delete()
+ is called on the parent (one-to-many already had
+ this).
+
+ - 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.
+
+ - Fixed order_by calculation in Query to properly alias
+ mapper-config'ed order_by when using select_from()
+
+ - Refactored the diffing logic that kicks in when replacing
+ one collection with another into collections.bulk_replace,
+ useful to anyone building multi-level collections.
+
+ - Cascade traversal algorithm converted from recursive to
+ iterative to support deep object graphs.
+
+- sql
+ - schema-qualified tables now will place the schemaname
+ 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.
+
+ - like(), ilike(), contains(), startswith(), endswith() take
+ an optional keyword argument "escape=<somestring>", which
+ is set as the escape character using the syntax "x LIKE y
+ ESCAPE '<somestring>'" [ticket:993], [ticket:791]
+
+ - random() is now a generic sql function and will compile to
+ the database's random implementation, if any.
+
+ - update().values() and insert().values() take keyword
+ arguments.
+
+ - Fixed an issue in select() regarding its generation of
+ FROM clauses, in rare circumstances two clauses could be
+ produced when one was intended to cancel out the other.
+ Some ORM queries with lots of eager loads might have seen
+ this symptom.
+
+ - The case() function now also takes a dictionary as its
+ whens parameter. It also interprets the "THEN"
+ expressions as values by default, meaning case([(x==y,
+ "foo")]) will interpret "foo" as a bound value, not a SQL
+ expression. use text(expr) for literal SQL expressions in
+ this case. For the criterion itself, these may be literal
+ strings only if the "value" keyword is present, otherwise
+ SA will force explicit usage of either text() or
+ literal().
+
+- oracle
+ - The "owner" keyword on Table is now deprecated, and is
+ exactly synonymous with the "schema" keyword. Tables can
+ now be reflected with alternate "owner" attributes,
+ explicitly stated on the Table object or not using
+ "schema".
+
+ - All of the "magic" searching for synonyms, DBLINKs etc.
+ during table reflection are disabled by default unless you
+ specify "oracle_resolve_synonyms=True" on the Table
+ object. Resolving synonyms necessarily leads to some
+ messy guessing which we'd rather leave off by default.
+ When the flag is set, tables and related tables will be
+ resolved against synonyms in all cases, meaning if a
+ synonym exists for a particular table, reflection will use
+ it when reflecting related tables. This is stickier
+ behavior than before which is why it's off by default.
+
+- declarative extension
+ - The "synonym" function is now directly usable with
+ "declarative". Pass in the decorated property using the
+ "descriptor" keyword argument, e.g.: somekey =
+ synonym('_somekey', descriptor=property(g, s))
+
+ - The "deferred" function is usable with "declarative".
+ Simplest usage is to declare deferred and Column together,
+ e.g.: data = deferred(Column(Text))
+
+ - Declarative also gained @synonym_for(...) and
+ @comparable_using(...), front-ends for synonym and
+ comparable_property.
+
+ - Improvements to mapper compilation when using declarative;
+ already-compiled mappers will still trigger compiles of
+ other uncompiled mappers when used [ticket:995]
+
+ - Declarative will complete setup for Columns lacking names,
+ allows a more DRY syntax.
+
+ class Foo(Base):
+ __tablename__ = 'foos'
+ id = Column(Integer, primary_key=True)
+
+ - inheritance in declarative can be disabled when sending
+ "inherits=None" to __mapper_args__.
+
+ - 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
+ classes using the "__mapper_cls__" property.
+
+- postgres
+ - Got PG server side cursors back into shape, added fixed
+ unit tests as part of the default test suite. Added
+ better uniqueness to the cursor ID [ticket:1001]
+
+- oracle
+ - The "owner" keyword on Table is now deprecated, and is
+ exactly synonymous with the "schema" keyword. Tables can
+ now be reflected with alternate "owner" attributes,
+ explicitly stated on the Table object or not using
+ "schema".
+
+ - All of the "magic" searching for synonyms, DBLINKs etc.
+ during table reflection are disabled by default unless you
+ specify "oracle_resolve_synonyms=True" on the Table
+ object. Resolving synonyms necessarily leads to some
+ messy guessing which we'd rather leave off by default.
+ When the flag is set, tables and related tables will be
+ resolved against synonyms in all cases, meaning if a
+ synonym exists for a particular table, reflection will use
+ it when reflecting related tables. This is stickier
+ behavior than before which is why it's off by default.
+
+- mssql
+ - Reflected tables will now automatically load other tables
+ which are referenced by Foreign keys in the auto-loaded
+ table, [ticket:979].
+
+ - Added executemany check to skip identity fetch, [ticket:916].
+
+ - Added stubs for small date type, [ticket:884]
+
+ - Added a new 'driver' keyword parameter for the pyodbc dialect.
+ Will substitute into the ODBC connection string if given,
+ defaults to 'SQL Server'.
+
+ - Added a new 'max_identifier_length' keyword parameter for
+ the pyodbc dialect.
+
+ - Improvements to pyodbc + Unix. If you couldn't get that
+ combination to work before, please try again.
+
+- mysql
+ - The connection.info keys the dialect uses to cache server
+ settings have changed and are now namespaced.
+
+0.4.4
+------
+- sql
+ - Can again create aliases of selects against textual FROM
+ clauses, [ticket:975]
+
+ - The value of a bindparam() can be a callable, in which
+ case it's evaluated at statement execution time to get the
+ value.
+
+ - Added exception wrapping/reconnect support to result set
+ fetching. Reconnect works for those databases that raise
+ a catchable data error during results (i.e. doesn't work
+ on MySQL) [ticket:978]
+
+ - Implemented two-phase API for "threadlocal" engine, via
+ engine.begin_twophase(), engine.prepare() [ticket:936]
+
+ - Fixed bug which was preventing UNIONS from being
+ cloneable, [ticket:986]
+
+ - Added "bind" keyword argument to insert(), update(),
+ delete() and DDL(). The .bind property is now assignable
+ on those statements as well as on select().
+
+ - Insert statements can now be compiled with extra "prefix"
+ words between INSERT and INTO, for vendor extensions like
+ MySQL's INSERT IGNORE INTO table.
+
+- orm
+ - any(), has(), contains(), ~contains(), attribute level ==
+ and != now work properly with self-referential relations -
+ the clause inside the EXISTS is aliased on the "remote"
+ side to distinguish it from the parent table. This
+ applies to single table self-referential as well as
+ inheritance-based self-referential.
+
+ - Repaired behavior of == and != operators at the relation()
+ level when compared against NULL for one-to-one relations
+ [ticket:985]
+
+ - Fixed bug whereby session.expire() attributes were not
+ loading on an polymorphically-mapped instance mapped by a
+ select_table mapper.
+
+ - Added query.with_polymorphic() - specifies a list of
+ classes which descend from the base class, which will be
+ added to the FROM clause of the query. Allows subclasses
+ to be used within filter() criterion as well as eagerly
+ loads the attributes of those subclasses.
+
+ - Your cries have been heard: removing a pending item from
+ an attribute or collection with delete-orphan expunges the
+ item from the session; no FlushError is raised. Note that
+ if you session.save()'ed the pending item explicitly, the
+ attribute/collection removal still knocks it out.
+
+ - session.refresh() and session.expire() raise an error when
+ called on instances which are not persistent within the
+ session
+
+ - Fixed potential generative bug when the same Query was
+ used to generate multiple Query objects using join().
+
+ - Fixed bug which was introduced in 0.4.3, whereby loading
+ an already-persistent instance mapped with joined table
+ inheritance would trigger a useless "secondary" load from
+ its joined table, when using the default "select"
+ polymorphic_fetch. This was due to attributes being
+ marked as expired during its first load and not getting
+ unmarked from the previous "secondary" load. Attributes
+ are now unexpired based on presence in __dict__ after any
+ load or commit operation succeeds.
+
+ - Deprecated Query methods apply_sum(), apply_max(),
+ apply_min(), apply_avg(). Better methodologies are
+ coming....
+
+ - relation() can accept a callable for its first argument,
+ which returns the class to be related. This is in place
+ to assist declarative packages to define relations without
+ classes yet being in place.
+
+ - Added a new "higher level" operator called "of_type()":
+ used in join() as well as with any() and has(), qualifies
+ the subclass which will be used in filter criterion, e.g.:
+
+ query.filter(Company.employees.of_type(Engineer).
+ any(Engineer.name=='foo'))
+
+ or
+
+ query.join(Company.employees.of_type(Engineer)).
+ filter(Engineer.name=='foo')
+
+ - Preventive code against a potential lost-reference bug in
+ flush().
+
+ - Expressions used in filter(), filter_by() and others, when
+ they make usage of a clause generated from a relation
+ using the identity of a child object (e.g.,
+ filter(Parent.child==<somechild>)), evaluate the actual
+ primary key value of <somechild> at execution time so that
+ the autoflush step of the Query can complete, thereby
+ populating the PK value of <somechild> in the case that
+ <somechild> was pending.
+
+ - setting the relation()-level order by to a column in the
+ many-to-many "secondary" table will now work with eager
+ loading, previously the "order by" wasn't aliased against
+ the secondary table's alias.
+
+ - Synonyms riding on top of existing descriptors are now
+ full proxies to those descriptors.
+
+- dialects
+ - Invalid SQLite connection URLs now raise an error.
+
+ - postgres TIMESTAMP renders correctly [ticket:981]
+
+ - postgres PGArray is a "mutable" type by default; when used
+ with the ORM, mutable-style equality/ copy-on-write
+ techniques are used to test for changes.
+
+- extensions
+ - a new super-small "declarative" extension has been added,
+ which allows Table and mapper() configuration to take
+ place inline underneath a class declaration. This
+ extension differs from ActiveMapper and Elixir in that it
+ does not redefine any SQLAlchemy semantics at all; literal
+ Column, Table and relation() constructs are used to define
+ the class behavior and table definition.
+
+0.4.3
+------
+- sql
+ - Added "schema.DDL", an executable free-form DDL statement.
+ DDLs can be executed in isolation or attached to Table or
+ MetaData instances and executed automatically when those
+ objects are created and/or dropped.
+
+ - Table columns and constraints can be overridden on a an
+ existing table (such as a table that was already reflected)
+ using the 'useexisting=True' flag, which now takes into
+ account the arguments passed along with it.
+
+ - Added a callable-based DDL events interface, adds hooks
+ before and after Tables and MetaData create and drop.
+
+ - Added generative where(<criterion>) method to delete() and
+ update() constructs which return a new object with criterion
+ joined to existing criterion via AND, just like
+ select().where().
+
+ - Added "ilike()" operator to column operations. Compiles to
+ ILIKE on postgres, lower(x) LIKE lower(y) on all
+ others. [ticket:727]
+
+ - Added "now()" as a generic function; on SQLite, Oracle
+ and MSSQL compiles as "CURRENT_TIMESTAMP"; "now()" on
+ all others. [ticket:943]
+
+ - The startswith(), endswith(), and contains() operators now
+ concatenate the wildcard operator with the given operand in
+ SQL, i.e. "'%' || <bindparam>" in all cases, accept
+ text('something') operands properly [ticket:962]
+
+ - cast() accepts text('something') and other non-literal
+ operands properly [ticket:962]
+
+ - fixed bug in result proxy where anonymously generated
+ column labels would not be accessible using their straight
+ string name
+
+ - Deferrable constraints can now be defined.
+
+ - Added "autocommit=True" keyword argument to select() and
+ text(), as well as generative autocommit() method on
+ select(); for statements which modify the database through
+ some user-defined means other than the usual INSERT/UPDATE/
+ DELETE etc. This flag will enable "autocommit" behavior
+ during execution if no transaction is in progress.
+ [ticket:915]
+
+ - The '.c.' attribute on a selectable now gets an entry for
+ every column expression in its columns clause. Previously,
+ "unnamed" columns like functions and CASE statements weren't
+ getting put there. Now they will, using their full string
+ representation if no 'name' is available.
+
+ - a CompositeSelect, i.e. any union(), union_all(),
+ intersect(), etc. now asserts that each selectable contains
+ the same number of columns. This conforms to the
+ corresponding SQL requirement.
+
+ - The anonymous 'label' generated for otherwise unlabeled
+ functions and expressions now propagates outwards at compile
+ time for expressions like select([select([func.foo()])]).
+
+ - Building on the above ideas, CompositeSelects now build up
+ their ".c." collection based on the names present in the
+ first selectable only; corresponding_column() now works
+ fully for all embedded selectables.
+
+ - Oracle and others properly encode SQL used for defaults like
+ sequences, etc., even if no unicode idents are used since
+ identifier preparer may return a cached unicode identifier.
+
+ - Column and clause comparisons to datetime objects on the
+ left hand side of the expression now work (d < table.c.col).
+ (datetimes on the RHS have always worked, the LHS exception
+ is a quirk of the datetime implementation.)
+
+- orm
+ - Every Session.begin() must now be accompanied by a
+ corresponding commit() or rollback() unless the session is
+ closed with Session.close(). This also includes the begin()
+ which is implicit to a session created with
+ transactional=True. The biggest change introduced here is
+ that when a Session created with transactional=True raises
+ an exception during flush(), you must call
+ Session.rollback() or Session.close() in order for that
+ Session to continue after an exception.
+
+ - Fixed merge() collection-doubling bug when merging transient
+ entities with backref'ed collections. [ticket:961]
+
+ - merge(dont_load=True) does not accept transient entities,
+ this is in continuation with the fact that
+ merge(dont_load=True) does not accept any "dirty" objects
+ either.
+
+ - Added standalone "query" class attribute generated by a
+ scoped_session. This provides MyClass.query without using
+ Session.mapper. Use via:
+
+ MyClass.query = Session.query_property()
+
+ - 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...
+
+ - Instances which have been partially or fully expired will
+ have their expired attributes populated during a regular
+ Query operation which affects those objects, preventing a
+ needless second SQL statement for each instance.
+
+ - Dynamic relations, when referenced, create a strong
+ reference to the parent object so that the query still has a
+ parent to call against even if the parent is only created
+ (and otherwise dereferenced) within the scope of a single
+ expression. [ticket:938]
+
+ - Added a mapper() flag "eager_defaults". When set to True,
+ defaults that are generated during an INSERT or UPDATE
+ operation are post-fetched immediately, instead of being
+ deferred until later. This mimics the old 0.3 behavior.
+
+ - query.join() can now accept class-mapped attributes as
+ arguments. These can be used in place or in any combination
+ with strings. In particular this allows construction of
+ joins to subclasses on a polymorphic relation, i.e.:
+
+ query(Company).join(['employees', Engineer.name])
+
+ - query.join() can also accept tuples of attribute name/some
+ selectable as arguments. This allows construction of joins
+ *from* subclasses of a polymorphic relation, i.e.:
+
+ query(Company).\
+ join(
+ [('employees', people.join(engineer)), Engineer.name]
+ )
+
+ - General improvements to the behavior of join() in
+ conjunction with polymorphic mappers, i.e. joining from/to
+ polymorphic mappers and properly applying aliases.
+
+ - Fixed/improved behavior when a mapper determines the natural
+ "primary key" of a mapped join, it will more effectively
+ reduce columns which are equivalent via foreign key
+ relation. This affects how many arguments need to be sent
+ to query.get(), among other things. [ticket:933]
+
+ - The lazy loader can now handle a join condition where the
+ "bound" column (i.e. the one that gets the parent id sent as
+ a bind parameter) appears more than once in the join
+ condition. Specifically this allows the common task of a
+ relation() which contains a parent-correlated subquery, such
+ as "select only the most recent child item". [ticket:946]
+
+ - Fixed bug in polymorphic inheritance where an incorrect
+ exception is raised when base polymorphic_on column does not
+ correspond to any columns within the local selectable of an
+ inheriting mapper more than one level deep
+
+ - Fixed bug in polymorphic inheritance which made it difficult
+ to set a working "order_by" on a polymorphic mapper.
+
+ - Fixed a rather expensive call in Query that was slowing down
+ polymorphic queries.
+
+ - "Passive defaults" and other "inline" defaults can now be
+ loaded during a flush() call if needed; in particular, this
+ allows constructing relations() where a foreign key column
+ references a server-side-generated, non-primary-key
+ column. [ticket:954]
+
+ - Additional Session transaction fixes/changes:
+ - Fixed bug with session transaction management: parent
+ transactions weren't started on the connection when
+ adding a connection to a nested transaction.
+
+ - session.transaction now always refers to the innermost
+ active transaction, even when commit/rollback are called
+ directly on the session transaction object.
+
+ - Two-phase transactions can now be prepared.
+
+ - When preparing a two-phase transaction fails on one
+ connection, all the connections are rolled back.
+
+ - session.close() didn't close all transactions when
+ nested transactions were used.
+
+ - rollback() previously erroneously set the current
+ transaction directly to the parent of the transaction
+ that could be rolled back to. Now it rolls back the next
+ transaction up that can handle it, but sets the current
+ transaction to it's parent and inactivates the
+ transactions in between. Inactive transactions can only
+ be rolled back or closed, any other call results in an
+ error.
+
+ - autoflush for commit() wasn't flushing for simple
+ subtransactions.
+
+ - unitofwork flush didn't close the failed transaction
+ when the session was not in a transaction and commiting
+ the transaction failed.
+
+ - Miscellaneous tickets: [ticket:940] [ticket:964]
+
+- general
+ - Fixed a variety of hidden and some not-so-hidden
+ compatibility issues for Python 2.3, thanks to new support
+ for running the full test suite on 2.3.
+
+ - Warnings are now issued as type exceptions.SAWarning.
+
+- dialects
+ - Better support for schemas in SQLite (linked in by ATTACH
+ DATABASE ... AS name). In some cases in the past, schema
+ names were ommitted from generated SQL for SQLite. This is
+ no longer the case.
+
+ - table_names on SQLite now picks up temporary tables as well.
+
+ - Auto-detect an unspecified MySQL ANSI_QUOTES mode during
+ reflection operations, support for changing the mode
+ midstream. Manual mode setting is still required if no
+ reflection is used.
+
+ - Fixed reflection of TIME columns on SQLite.
+
+ - Finally added PGMacAddr type to postgres [ticket:580]
+
+ - Reflect the sequence associated to a PK field (typically
+ with a BEFORE INSERT trigger) under Firebird
+
+ - Oracle assembles the correct columns in the result set
+ column mapping when generating a LIMIT/OFFSET subquery,
+ allows columns to map properly to result sets even if
+ long-name truncation kicks in [ticket:941]
+
+ - MSSQL now includes EXEC in the _is_select regexp, which
+ should allow row-returning stored procedures to be used.
+
+ - MSSQL now includes an experimental implementation of
+ LIMIT/OFFSET using the ANSI SQL row_number() function, so it
+ requires MSSQL-2005 or higher. To enable the feature, add
+ "has_window_funcs" to the keyword arguments for connect, or
+ add "?has_window_funcs=1" to your dburi query arguments.
+
+- ext
+ - Changed ext.activemapper to use a non-transactional session
+ for the objectstore.
+
+ - Fixed output order of "['a'] + obj.proxied" binary operation
+ on association-proxied lists.
+
+0.4.2p3
+------
+- general
+ - sub version numbering scheme changed to suite
+ setuptools version number rules; easy_install -u
+ should now get this version over 0.4.2.
+
+- sql
+ - Text type is properly exported now and does not
+ raise a warning on DDL create; String types with no
+ length only raise warnings during CREATE TABLE
+ [ticket:912]
+
+ - new UnicodeText type is added, to specify an
+ encoded, unlengthed Text type
+
+ - fixed bug in union() so that select() statements
+ which don't derive from FromClause objects can be
+ unioned
+
+- orm
+ - fixed bug with session.dirty when using "mutable
+ scalars" (such as PickleTypes)
+
+ - added a more descriptive error message when flushing
+ on a relation() that has non-locally-mapped columns
+ in its primary or secondary join condition
+
+- dialects
+ - Fixed reflection of mysql empty string column
+ defaults.
+
+0.4.2b (0.4.2p2)
+------
+- sql
+ - changed name of TEXT to Text since its a "generic"
+ type; TEXT name is deprecated until 0.5. The
+ "upgrading" behavior of String to Text when no
+ length is present is also deprecated until 0.5; will
+ issue a warning when used for CREATE TABLE
+ statements (String with no length for SQL expression
+ purposes is still fine) [ticket:912]
+
+ - generative select.order_by(None) / group_by(None)
+ was not managing to reset order by/group by
+ criterion, fixed [ticket:924]
+
+- orm
+ - suppressing *all* errors in
+ InstanceState.__cleanup() now.
+
+ - fixed an attribute history bug whereby assigning a
+ 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
+ synonyms for backrefs without worrying about the
+ order of operations) [ticket:919]
+
+ - 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.
+
+- dialects
+ - mssql - narrowed down the test for "date"/"datetime"
+ in MSDate/ MSDateTime subclasses so that incoming
+ "datetime" objects don't get mis-interpreted as
+ "date" objects and vice versa, [ticket:923]
+
+0.4.2a (0.4.2p1)
+------
+
+- 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
+ 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
+ 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
+ result batch boundaries, nor will it behave nicely if the same
+ instance occurs in more than one batch. This means that an eagerly
+ loaded collection will get cleared out if it's referenced in more than
+ one batch, and in all cases attributes will be overwritten on instances
+ that occur in more than one batch.
+
+ - Fixed in-place set mutation operators for set collections and association
+ proxied sets. [ticket:920]
+
+- dialects
+ - Fixed the missing call to subtype result processor for the PGArray
+ type. [ticket:913]
+
+0.4.2
+-----
+- sql
+ - generic functions ! we introduce a database of known SQL functions, such
+ as current_timestamp, coalesce, and create explicit function objects
+ representing them. These objects have constrained argument lists, are
+ type aware, and can compile in a dialect-specific fashion. So saying
+ func.char_length("foo", "bar") raises an error (too many args),
+ func.coalesce(datetime.date(2007, 10, 5), datetime.date(2005, 10, 15))
+ knows that its return type is a Date. We only have a few functions
+ represented so far but will continue to add to the system [ticket:615]
+
+ - auto-reconnect support improved; a Connection can now automatically
+ 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
+ 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
+ make proper use of Python unicode objects (i.e. u'hello' and not 'hello')
+ so that data round trips accurately.
+
+ - generation of "unique" bind parameters has been simplified to use the same
+ "unique identifier" mechanisms as everything else. This doesn't affect
+ 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.
+ TypeDecorator should now be the primary way to augment the behavior of any
+ existing type including other TypeDecorator subclasses such as 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
+ 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
+ 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
+ have not, you might notice your apps using a lot fewer queries than
+ before in some situations. [ticket:871]
+
+ - mutable primary key support is added. primary key columns can be
+ changed freely, and the identity of the instance will change upon
+ flush. In addition, update cascades of foreign key referents (primary
+ key or not) along relations are supported, either in tandem with the
+ database's ON UPDATE CASCADE (required for DB's like Postgres) or
+ issued directly by the ORM in the form of UPDATE statements, by setting
+ the flag "passive_cascades=False".
+
+ - 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
+ 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
+ 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
+ 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
+ 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),
+ 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.
+
+ - 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
+ with the appropriate comparison operators so that it can be used in in
+ column expressions just like any other mapped attribute (i.e. usable in
+ filter(), etc.) the "proxy=True" flag is deprecated and no longer means
+ anything. Additionally, the flag "map_column=True" will automatically
+ generate a ColumnProperty corresponding to the name of the synonym,
+ i.e.: 'somename':synonym('_somename', map_column=True) will map the
+ column named 'somename' to the attribute '_somename'. See the example
+ in the mapper docs. [ticket:801]
+
+ - 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
+ 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
+ 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
+ "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
+ 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
+ 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
+ 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().
+
+ - 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
+ 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
+ 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,
+ 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.
+ [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
+ requires conversion to ColumnElement via as_scalar() or label().
+
+ - 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(),
+ MapperProperty.cascade_callable(), mapper.canload(),
+ mapper.save_obj(), mapper.delete_obj(), mapper._mapper_registry,
+ attributes.AttributeManager
+
+ - Assigning an incompatible collection type to a relation attribute now
+ raises TypeError instead of sqlalchemy's ArgumentError.
+
+ - Bulk assignment of a MappedCollection now raises an error if a key in the
+ incoming dictionary does not match the key that the collection's keyfunc
+ would use for that value. [ticket:886]
+
+ - Custom collections can now specify a @converter method to translate
+ objects used in "bulk" assignment into a stream of values, as in::
+
+ obj.col = [newval1, newval2]
+ # or
+ obj.dictcol = {'foo': newval1, 'bar': newval2}
+
+ 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
+ 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
+ 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).
+ 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
+ "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
+ 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
+ [ticket:914]
+
+- dialects
+
+ - 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]
+ - Better support for convert_unicode [ticket:839]
+ - Less strict date conversion for pyodbc/adodbapi [ticket:842]
+ - Schema-qualified tables / autoload [ticket:901]
+
+ - Firebird backend
+
+ - does properly reflect domains (partially fixing [ticket:410]) and
+ PassiveDefaults
+
+ - reverted to use default poolclass (was set to SingletonThreadPool in
+ 0.4.0 [3562] for test purposes)
+
+ - map func.length() to 'char_length' (easily overridable with the UDF
+ 'strlen' on old versions of Firebird)
+
+
+0.4.1
+-----
+
+- sql
+
+ - the "shortname" keyword parameter on bindparam() has been
+ deprecated.
+
+ - Added contains operator (generates a "LIKE %<other>%" clause).
+
+ - 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
+ matches since text() expressions may represent multiple columns).
+
+ - 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]
+
+ - Fixed empty (zero column) sqlite inserts, allowing inserts on
+ autoincrementing single column tables.
+
+ - Fixed expression translation of text() clauses; this repairs various
+ ORM scenarios where literal text is used for SQL expressions
+
+ - Removed ClauseParameters object; compiled.params returns a regular
+ dictionary now, as well as result.last_inserted_params() /
+ last_updated_params().
+
+ - Fixed INSERT statements w.r.t. primary key columns that have
+ SQL-expression based default generators on them; SQL expression
+ executes inline as normal but will not trigger a "postfetch" condition
+ for the column, for those DB's who provide it via cursor.lastrowid
+
+ - func. objects can be pickled/unpickled [ticket:844]
+
+ - rewrote and simplified the system used to "target" columns across
+ 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
+ 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]
+
+ - The "properties" collection on Connections has been renamed "info" to
+ match schema's writable collections. Access is still available via
+ the "properties" name until 0.5.
+
+ - fixed the close() method on Transaction when using strategy='threadlocal'
+
+ - 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
+ 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
+ with LIMIT/OFFSET. [ticket:843]
+
+ - 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
+ instance. [ticket:802]
+
+ - 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
+ 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')
+ applies only to exactly two-levels deep, etc. [ticket:777]
+
+ - 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
+ 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
+ persistent [ticket:840]
+
+ - It's an error to session.delete() an object which is *not*
+ persistent.
+
+ - session.update() and session.delete() raise an error when updating
+ or deleting an instance that is already in the session with a
+ different identity.
+
+ - The session checks more carefully when determining "object X already
+ in another session"; e.g. if you pickle a series of objects and
+ unpickle (i.e. as in a Pylons HTTP session or similar), they can go
+ into a new session without any conflict
+
+ - merge() includes a keyword argument "dont_load=True". setting this
+ flag will cause the merge operation to not load any data from the
+ database in response to incoming detached objects, and will accept
+ the incoming detached object as though it were already present in
+ that session. Use this to merge detached objects from external
+ caching systems into the session.
+
+ - 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]
+
+ - De-cruftified backref configuration code, backrefs which step on
+ existing properties now raise an error [ticket:832]
+
+ - Improved behavior of add_property() etc., fixed [ticket:831] involving
+ synonym/deferred.
+
+ - Fixed clear_mappers() behavior to better clean up after itself.
+
+ - Fix to "row switch" behavior, i.e. when an INSERT/DELETE is combined
+ into a single UPDATE; many-to-many relations on the parent object
+ update properly. [ticket:841]
+
+ - Fixed __hash__ for association proxy- these collections are unhashable,
+ just like their mutable Python counterparts.
+
+ - Added proxying of save_or_update, __contains__ and __iter__ methods for
+ scoped sessions.
+
+ - 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
+ 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]
+
+ - Renamed the Dialect attribute 'preexecute_sequences' to
+ 'preexecute_pk_sequences'. An attribute porxy is in place for
+ out-of-tree dialects using the old name.
+
+ - 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
+ REAL_AS_FLOAT sql mode).
+
+ - mysql Float, MSFloat and MSDouble constructed without arguments
+ now produce no-argument DDL, e.g.'FLOAT'.
+
+- misc
+
+ - Removed unused util.hash().
+
+
+0.4.0
+-----
+
+- (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]
+
+- Added partial index support for PostgreSQL. Use the postgres_where keyword
+ on the Index.
+
+- 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
+ _requires_quotes.
+
+- Firebird has supports_sane_rowcount and supports_sane_multi_rowcount set
+ to False due to ticket #370 (right way).
+
+- Improvements and fixes on Firebird reflection:
+ . FBDialect now mimics OracleDialect, regarding case-sensitivity of TABLE and
+ COLUMN names (see 'case_sensitive remotion' topic on this current file).
+ . FBDialect.table_names() doesn't bring system tables (ticket:796).
+ . 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
+ 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
+ mapped selectable.
+
+- Fixed three- and multi-level select and deferred inheritance loading
+ (i.e. abc inheritance with no select_table), [ticket:795]
+
+- Ident passed to id_chooser in shard.py always a list.
+
+- The no-arg ResultProxy._row_processor() is now the class attribute
+ `_process_row`.
+
+- Added support for returning values from inserts and updates for
+ 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
+ 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).
+ 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.
+
+- null foreign key on a m2o doesn't trigger a lazyload [ticket:803]
+
+- oracle does not implicitly convert to unicode for non-typed result
+ sets (i.e. when no TypeEngine/String/Unicode type is even being used;
+ previously it was detecting DBAPI types and converting regardless).
+ should fix [ticket:800]
+
+- fix to anonymous label generation of long table/column names [ticket:806]
+
+- Firebird dialect now uses SingletonThreadPool as poolclass.
+
+- Firebird now uses dialect.preparer to format sequences names
+
+- Fixed breakage with postgres and multiple two-phase transactions. Two-phase
+ commits and and rollbacks didn't automatically end up with a new transaction
+ as the usual dbapi commits/rollbacks do. [ticket:810]
+
+- Added an option to the _ScopedExt mapper extension to not automatically
+ save new objects to session on object initialization.
+
+- fixed Oracle non-ansi join syntax
+
+- 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.
+
+- Changed the API for the in_ operator. in_() now accepts a single argument
+ that is a sequence of values or a selectable. The old API of passing in
+ values as varargs still works but is deprecated.
+
+
+0.4.0beta6
+----------
+
+- The Session identity map is now *weak referencing* by default, use
+ weak_identity_map=False to use a regular dict. The weak dict we are using
+ is customized to detect instances which are "dirty" and maintain a
+ temporary strong reference to those instances until changes are flushed.
+
+- Mapper compilation has been reorganized such that most compilation occurs
+ upon mapper construction. This allows us to have fewer calls to
+ mapper.compile() and also to allow class-based properties to force a
+ compilation (i.e. User.addresses == 7 will compile all mappers; this is
+ [ticket:758]). The only caveat here is that an inheriting mapper now
+ looks for its inherited mapper upon construction; so mappers within
+ inheritance relationships need to be constructed in inheritance order
+ (which should be the normal case anyway).
+
+- added "FETCH" to the keywords detected by Postgres to indicate a
+ result-row holding statement (i.e. in addition to "SELECT").
+
+- Added full list of SQLite reserved keywords so that they get escaped
+ properly.
+
+- Tightened up the relationship between the Query's generation of "eager
+ load" aliases, and Query.instances() which actually grabs the eagerly
+ loaded rows. If the aliases were not specifically generated for that
+ statement by EagerLoader, the EagerLoader will not take effect when the
+ rows are fetched. This prevents columns from being grabbed accidentally
+ as being part of an eager load when they were not meant for such, which
+ can happen with textual SQL as well as some inheritance situations. It's
+ particularly important since the "anonymous aliasing" of columns uses
+ simple integer counts now to generate labels.
+
+- Removed "parameters" argument from clauseelement.compile(), replaced with
+ "column_keys". The parameters sent to execute() only interact with the
+ insert/update statement compilation process in terms of the column names
+ present but not the values for those columns. Produces more consistent
+ execute/executemany behavior, simplifies things a bit internally.
+
+- Added 'comparator' keyword argument to PickleType. By default, "mutable"
+ PickleType does a "deep compare" of objects using their dumps()
+ representation. But this doesn't work for dictionaries. Pickled objects
+ which provide an adequate __eq__() implementation can be set up with
+ "PickleType(comparator=operator.eq)" [ticket:560]
+
+- Added session.is_modified(obj) method; performs the same "history"
+ comparison operation as occurs within a flush operation; setting
+ include_collections=False gives the same result as is used when the flush
+ determines whether or not to issue an UPDATE for the instance's row.
+
+- Added "schema" argument to Sequence; use this with Postgres /Oracle when
+ the sequence is located in an alternate schema. Implements part of
+ [ticket:584], should fix [ticket:761].
+
+- Fixed reflection of the empty string for mysql enums.
+
+- Changed MySQL dialect to use the older LIMIT <offset>, <limit> syntax
+ instead of LIMIT <l> OFFSET <o> for folks using 3.23. [ticket:794]
+
+- Added 'passive_deletes="all"' flag to relation(), disables all nulling-out
+ of foreign key attributes during a flush where the parent object is
+ deleted.
+
+- Column defaults and onupdates, executing inline, will add parenthesis for
+ subqueries and other parenthesis-requiring expressions
+
+- The behavior of String/Unicode types regarding that they auto-convert to
+ TEXT/CLOB when no length is present now occurs *only* for an exact type of
+ String or Unicode with no arguments. If you use VARCHAR or NCHAR
+ (subclasses of String/Unicode) with no length, they will be interpreted by
+ the dialect as VARCHAR/NCHAR; no "magic" conversion happens there. This
+ is less surprising behavior and in particular this helps Oracle keep
+ string-based bind parameters as VARCHARs and not CLOBs [ticket:793].
+
+- Fixes to ShardedSession to work with deferred columns [ticket:771].
+
+- User-defined shard_chooser() function must accept "clause=None" argument;
+ this is the ClauseElement passed to session.execute(statement) and can be
+ used to determine correct shard id (since execute() doesn't take an
+ instance.)
+
+- Adjusted operator precedence of NOT to match '==' and others, so that
+ ~(x <operator> y) produces NOT (x <op> y), which is better compatible
+ with older MySQL versions. [ticket:764]. This doesn't apply to "~(x==y)"
+ as it does in 0.3 since ~(x==y) compiles to "x != y", but still applies
+ to operators like BETWEEN.
+
+- Other tickets: [ticket:768], [ticket:728], [ticket:779], [ticket:757]
+
+0.4.0beta5
+----------
+
+- Connection pool fixes; the better performance of beta4 remains but fixes
+ "connection overflow" and other bugs which were present (like
+ [ticket:754]).
+
+- Fixed bugs in determining proper sync clauses from custom inherit
+ conditions. [ticket:769]
+
+- Extended 'engine_from_config' coercion for QueuePool size / overflow.
+ [ticket:763]
+
+- mysql views can be reflected again. [ticket:748]
+
+- AssociationProxy can now take custom getters and setters.
+
+- Fixed malfunctioning BETWEEN in orm queries.
+
+- Fixed OrderedProperties pickling [ticket:762]
+
+- SQL-expression defaults and sequences now execute "inline" for all
+ non-primary key columns during an INSERT or UPDATE, and for all columns
+ during an executemany()-style call. inline=True flag on any insert/update
+ statement also forces the same behavior with a single execute().
+ result.postfetch_cols() is a collection of columns for which the previous
+ single insert or update statement contained a SQL-side default expression.
+
+- Fixed PG executemany() behavior, [ticket:759]
+
+- postgres reflects tables with autoincrement=False for primary key columns
+ which have no defaults.
+
+- postgres no longer wraps executemany() with individual execute() calls,
+ instead favoring performance. "rowcount"/"concurrency" checks with
+ deleted items (which use executemany) are disabled with PG since psycopg2
+ does not report proper rowcount for executemany().
+
+- Tickets fixed:
+
+ - [ticket:742]
+ - [ticket:748]
+ - [ticket:760]
+ - [ticket:762]
+ - [ticket:763]
+
+0.4.0beta4
+----------
+
+- Tidied up what ends up in your namespace when you 'from sqlalchemy import *':
+
+ - 'table' and 'column' are no longer imported. They remain available by
+ direct reference (as in 'sql.table' and 'sql.column') or a glob import
+ from the sql package. It was too easy to accidentally use a
+ sql.expressions.table instead of schema.Table when just starting out
+ with SQLAlchemy, likewise column.
+
+ - Internal-ish classes like ClauseElement, FromClause, NullTypeEngine,
+ etc., are also no longer imported into your namespace
+
+ - The 'Smallinteger' compatiblity name (small i!) is no longer imported,
+ but remains in schema.py for now. SmallInteger (big I!) is still
+ imported.
+
+- The connection pool uses a "threadlocal" strategy internally to return
+ the same connection already bound to a thread, for "contextual" connections;
+ these are the connections used when you do a "connectionless" execution
+ like insert().execute(). This is like a "partial" version of the
+ "threadlocal" engine strategy but without the thread-local transaction part
+ of it. We're hoping it reduces connection pool overhead as well as
+ database usage. However, if it proves to impact stability in a negative way,
+ we'll roll it right back.
+
+- Fix to bind param processing such that "False" values (like blank strings)
+ still get processed/encoded.
+
+- Fix to select() "generative" behavior, such that calling column(),
+ select_from(), correlate(), and with_prefix() does not modify the
+ original select object [ticket:752]
+
+- Added a "legacy" adapter to types, such that user-defined TypeEngine
+ and TypeDecorator classes which define convert_bind_param() and/or
+ convert_result_value() will continue to function. Also supports
+ calling the super() version of those methods.
+
+- Added session.prune(), trims away instances cached in a session that
+ are no longer referenced elsewhere. (A utility for strong-ref
+ identity maps).
+
+- Added close() method to Transaction. Closes out a transaction using
+ rollback if it's the outermost transaction, otherwise just ends
+ without affecting the outer transaction.
+
+- Transactional and non-transactional Session integrates better with
+ bound connection; a close() will ensure that connection
+ transactional state is the same as that which existed on it before
+ being bound to the Session.
+
+- Modified SQL operator functions to be module-level operators,
+ allowing SQL expressions to be pickleable. [ticket:735]
+
+- Small adjustment to mapper class.__init__ to allow for Py2.6
+ object.__init__() behavior.
+
+- Fixed 'prefix' argument for select()
+
+- Connection.begin() no longer accepts nested=True, this logic is now
+ all in begin_nested().
+
+- Fixes to new "dynamic" relation loader involving cascades
+
+- Tickets fixed:
+
+ - [ticket:735]
+ - [ticket:752]
+
+0.4.0beta3
+----------
+
+- SQL types optimization:
+
+ - New performance tests show a combined mass-insert/mass-select test as
+ having 68% fewer function calls than the same test run against 0.3.
+
+ - General performance improvement of result set iteration is around 10-20%.
+
+ - In types.AbstractType, convert_bind_param() and convert_result_value()
+ have migrated to callable-returning bind_processor() and
+ result_processor() methods. If no callable is returned, no pre/post
+ processing function is called.
+
+ - Hooks added throughout base/sql/defaults to optimize the calling of bind
+ aram/result processors so that method call overhead is minimized.
+
+ - Support added for executemany() scenarios such that unneeded "last row id"
+ logic doesn't kick in, parameters aren't excessively traversed.
+
+- Added 'inherit_foreign_keys' arg to mapper().
+
+- Added support for string date passthrough in sqlite.
+
+- Tickets fixed:
+
+ - [ticket:738]
+ - [ticket:739]
+ - [ticket:743]
+ - [ticket:744]
+
+0.4.0beta2
+----------
+
+- mssql improvements.
+
+- oracle improvements.
+
+- Auto-commit after LOAD DATA INFILE for mysql.
+
+- A rudimental SessionExtension class has been added, allowing user-defined
+ functionality to take place at flush(), commit(), and rollback() boundaries.
+
+- Added engine_from_config() function for helping to create_engine() from an
+ .ini style config.
+
+- base_mapper() becomes a plain attribute.
+
+- session.execute() and scalar() can search for a Table with which to bind from
+ using the given ClauseElement.
+
+- Session automatically extrapolates tables from mappers with binds, also uses
+ base_mapper so that inheritance hierarchies bind automatically.
+
+- Moved ClauseVisitor traversal back to inlined non-recursive.
+
+- Tickets fixed:
+
+ - [ticket:730]
+ - [ticket:732]
+ - [ticket:733]
+ - [ticket:734]
+
+0.4.0beta1
+----------
+
+- orm
+
+ - Speed! Along with recent speedups to ResultProxy, total number of function
+ calls significantly reduced for large loads.
+
+ - test/perf/masseagerload.py reports 0.4 as having the fewest number of
+ function calls across all SA versions (0.1, 0.2, and 0.3).
+
+ - New collection_class api and implementation [ticket:213]. Collections are
+ now instrumented via decorations rather than proxying. You can now have
+ collections that manage their own membership, and your class instance will
+ be directly exposed on the relation property. The changes are transparent
+ for most users.
+
+ - InstrumentedList (as it was) is removed, and relation properties no
+ longer have 'clear()', '.data', or any other added methods beyond those
+ provided by the collection type. You are free, of course, to add them to
+ a custom class.
+
+ - __setitem__-like assignments now fire remove events for the existing
+ value, if any.
+
+ - dict-likes used as collection classes no longer need to change __iter__
+ semantics- itervalues() is used by default instead. This is a backwards
+ incompatible change.
+
+ - Subclassing dict for a mapped collection is no longer needed in most
+ cases. orm.collections provides canned implementations that key objects
+ by a specified column or a custom function of your choice.
+
+ - Collection assignment now requires a compatible type- assigning None to
+ clear a collection or assigning a list to a dict collection will now
+ raise an argument error.
+
+ - AttributeExtension moved to interfaces, and .delete is now .remove The
+ event method signature has also been swapped around.
+
+ - Major overhaul for Query:
+
+ - All selectXXX methods are deprecated. Generative methods are now the
+ standard way to do things, i.e. filter(), filter_by(), all(), one(),
+ etc. Deprecated methods are docstring'ed with their new replacements.
+
+ - Class-level properties are now usable as query elements... no more
+ '.c.'! "Class.c.propname" is now superceded by "Class.propname". All
+ clause operators are supported, as well as higher level operators such
+ as Class.prop==<some instance> for scalar attributes,
+ Class.prop.contains(<some instance>) and Class.prop.any(<some
+ expression>) for collection-based attributes (all are also
+ negatable). Table-based column expressions as well as columns mounted
+ on mapped classes via 'c' are of course still fully available and can be
+ freely mixed with the new attributes. [ticket:643]
+
+ - Removed ancient query.select_by_attributename() capability.
+
+ - The aliasing logic used by eager loading has been generalized, so that
+ it also adds full automatic aliasing support to Query. It's no longer
+ necessary to create an explicit Alias to join to the same tables
+ multiple times; *even for self-referential relationships*.
+
+ - join() and outerjoin() take arguments "aliased=True". Yhis causes
+ their joins to be built on aliased tables; subsequent calls to
+ filter() and filter_by() will translate all table expressions (yes,
+ real expressions using the original mapped Table) to be that of the
+ Alias for the duration of that join() (i.e. until reset_joinpoint() or
+ another join() is called).
+
+ - join() and outerjoin() take arguments "id=<somestring>". When used
+ with "aliased=True", the id can be referenced by add_entity(cls,
+ id=<somestring>) so that you can select the joined instances even if
+ they're from an alias.
+
+ - join() and outerjoin() now work with self-referential relationships!
+ Using "aliased=True", you can join as many levels deep as desired,
+ i.e. query.join(['children', 'children'], aliased=True); filter
+ criterion will be against the rightmost joined table
+
+ - Added query.populate_existing(), marks the query to reload all
+ attributes and collections of all instances touched in the query,
+ including eagerly-loaded entities. [ticket:660]
+
+ - Added eagerload_all(), allows eagerload_all('x.y.z') to specify eager
+ loading of all properties in the given path.
+
+ - Major overhaul for Session:
+
+ - New function which "configures" a session called "sessionmaker()". Send
+ various keyword arguments to this function once, returns a new class
+ which creates a Session against that stereotype.
+
+ - SessionTransaction removed from "public" API. You now can call begin()/
+ commit()/rollback() on the Session itself.
+
+ - Session also supports SAVEPOINT transactions; call begin_nested().
+
+ - Session supports two-phase commit behavior when vertically or
+ horizontally partitioning (i.e., using more than one engine). Use
+ twophase=True.
+
+ - Session flag "transactional=True" produces a session which always places
+ itself into a transaction when first used. Upon commit(), rollback() or
+ close(), the transaction ends; but begins again on the next usage.
+
+ - Session supports "autoflush=True". This issues a flush() before each
+ query. Use in conjunction with transactional, and you can just
+ save()/update() and then query, the new objects will be there. Use
+ commit() at the end (or flush() if non-transactional) to flush remaining
+ changes.
+
+ - New scoped_session() function replaces SessionContext and assignmapper.
+ Builds onto "sessionmaker()" concept to produce a class whos Session()
+ construction returns the thread-local session. Or, call all Session
+ methods as class methods, i.e. Session.save(foo); Session.commit().
+ just like the old "objectstore" days.
+
+ - Added new "binds" argument to Session to support configuration of
+ multiple binds with sessionmaker() function.
+
+ - A rudimental SessionExtension class has been added, allowing
+ user-defined functionality to take place at flush(), commit(), and
+ rollback() boundaries.
+
+ - Query-based relation()s available with dynamic_loader(). This is a
+ *writable* collection (supporting append() and remove()) which is also a
+ live Query object when accessed for reads. Ideal for dealing with very
+ large collections where only partial loading is desired.
+
+ - flush()-embedded inline INSERT/UPDATE expressions. Assign any SQL
+ expression, like "sometable.c.column + 1", to an instance's attribute.
+ Upon flush(), the mapper detects the expression and embeds it directly in
+ the INSERT or UPDATE statement; the attribute gets deferred on the
+ instance so it loads the new value the next time you access it.
+
+ - A rudimental sharding (horizontal scaling) system is introduced. This
+ system uses a modified Session which can distribute read and write
+ operations among multiple databases, based on user-defined functions
+ defining the "sharding strategy". Instances and their dependents can be
+ distributed and queried among multiple databases based on attribute
+ values, round-robin approaches or any other user-defined
+ system. [ticket:618]
+
+ - Eager loading has been enhanced to allow even more joins in more places.
+ It now functions at any arbitrary depth along self-referential and
+ cyclical structures. When loading cyclical structures, specify
+ "join_depth" on relation() indicating how many times you'd like the table
+ to join to itself; each level gets a distinct table alias. The alias
+ names themselves are generated at compile time using a simple counting
+ scheme now and are a lot easier on the eyes, as well as of course
+ completely deterministic. [ticket:659]
+
+ - Added composite column properties. This allows you to create a type which
+ is represented by more than one column, when using the ORM. Objects of
+ the new type are fully functional in query expressions, comparisons,
+ query.get() clauses, etc. and act as though they are regular single-column
+ scalars... except they're not! Use the function composite(cls, *columns)
+ inside of the mapper's "properties" dict, and instances of cls will be
+ created/mapped to a single attribute, comprised of the values correponding
+ to *columns. [ticket:211]
+
+ - Improved support for custom column_property() attributes which feature
+ correlated subqueries, works better with eager loading now.
+
+ - Primary key "collapse" behavior; the mapper will analyze all columns in
+ its given selectable for primary key "equivalence", that is, columns which
+ are equivalent via foreign key relationship or via an explicit
+ inherit_condition. primarily for joined-table inheritance scenarios where
+ different named PK columns in inheriting tables should "collapse" into a
+ single-valued (or fewer-valued) primary key. Fixes things like
+ [ticket:611].
+
+ - Joined-table inheritance will now generate the primary key columns of all
+ inherited classes against the root table of the join only. This implies
+ that each row in the root table is distinct to a single instance. If for
+ some rare reason this is not desireable, explicit primary_key settings on
+ individual mappers will override it.
+
+ - When "polymorphic" flags are used with joined-table or single-table
+ inheritance, all identity keys are generated against the root class of the
+ inheritance hierarchy; this allows query.get() to work polymorphically
+ using the same caching semantics as a non-polymorphic get. Note that this
+ currently does not work with concrete inheritance.
+
+ - Secondary inheritance loading: polymorphic mappers can be constructed
+ *without* a select_table argument. inheriting mappers whose tables were
+ not represented in the initial load will issue a second SQL query
+ immediately, once per instance (i.e. not very efficient for large lists),
+ in order to load the remaining columns.
+
+ - Secondary inheritance loading can also move its second query into a
+ column-level "deferred" load, via the "polymorphic_fetch" argument, which
+ can be set to 'select' or 'deferred'
+
+ - It's now possible to map only a subset of available selectable columns
+ onto mapper properties, using include_columns/exclude_columns.
+ [ticket:696].
+
+ - Added undefer_group() MapperOption, sets a set of "deferred" columns
+ joined by a "group" to load as "undeferred".
+
+ - Rewrite of the "deterministic alias name" logic to be part of the SQL
+ layer, produces much simpler alias and label names more in the style of
+ Hibernate
+
+- sql
+
+ - Speed! Clause compilation as well as the mechanics of SQL constructs have
+ been streamlined and simplified to a signficant degree, for a 20-30%
+ improvement of the statement construction/compilation overhead of 0.3.
+
+ - All "type" keyword arguments, such as those to bindparam(), column(),
+ Column(), and func.<something>(), renamed to "type_". Those objects still
+ name their "type" attribute as "type".
+
+ - case_sensitive=(True|False) setting removed from schema items, since
+ checking this state added a lot of method call overhead and there was no
+ decent reason to ever set it to False. Table and column names which are
+ all lower case will be treated as case-insenstive (yes we adjust for
+ Oracle's UPPERCASE style too).
+
+ - Transactions:
+
+ - Added context manager (with statement) support for transactions.
+ - Added support for two phase commit, works with mysql and postgres so far.
+ - Added a subtransaction implementation that uses savepoints.
+ - Added support for savepoints.
+
+ - MetaData:
+
+ - Tables can be reflected from the database en-masse without declaring
+ them in advance. MetaData(engine, reflect=True) will load all tables
+ present in the database, or use metadata.reflect() for finer control.
+ - DynamicMetaData has been renamed to ThreadLocalMetaData
+ - The ThreadLocalMetaData constructor now takes no arguments.
+ - BoundMetaData has been removed- regular MetaData is equivalent
+
+ - Numeric and Float types now have an "asdecimal" flag; defaults to True for
+ Numeric, False for Float. When True, values are returned as
+ decimal.Decimal objects; when False, values are returned as float(). The
+ defaults of True/False are already the behavior for PG and MySQL's DBAPI
+ modules. [ticket:646]
+
+ - New SQL operator implementation which removes all hardcoded operators from
+ expression structures and moves them into compilation; allows greater
+ flexibility of operator compilation; for example, "+" compiles to "||"
+ when used in a string context, or "concat(a,b)" on MySQL; whereas in a
+ numeric context it compiles to "+". Fixes [ticket:475].
+
+ - "Anonymous" alias and label names are now generated at SQL compilation
+ time in a completely deterministic fashion... no more random hex IDs
+
+ - Significant architectural overhaul to SQL elements (ClauseElement). All
+ elements share a common "mutability" framework which allows a consistent
+ approach to in-place modifications of elements as well as generative
+ behavior. Improves stability of the ORM which makes heavy usage of
+ mutations to SQL expressions.
+
+ - select() and union()'s now have "generative" behavior. Methods like
+ order_by() and group_by() return a *new* instance - the original instance
+ is left unchanged. Non-generative methods remain as well.
+
+ - The internals of select/union vastly simplified- all decision making
+ regarding "is subquery" and "correlation" pushed to SQL generation phase.
+ select() elements are now *never* mutated by their enclosing containers or
+ by any dialect's compilation process [ticket:52] [ticket:569]
+
+ - select(scalar=True) argument is deprecated; use select(..).as_scalar().
+ The resulting object obeys the full "column" interface and plays better
+ within expressions.
+
+ - Added select().with_prefix('foo') allowing any set of keywords to be
+ placed before the columns clause of the SELECT [ticket:504]
+
+ - Added array slice support to row[<index>] [ticket:686]
+
+ - Result sets make a better attempt at matching the DBAPI types present in
+ cursor.description to the TypeEngine objects defined by the dialect, which
+ are then used for result-processing. Note this only takes effect for
+ textual SQL; constructed SQL statements always have an explicit type map.
+
+ - Result sets from CRUD operations close their underlying cursor immediately
+ and will also autoclose the connection if defined for the operation; this
+ allows more efficient usage of connections for successive CRUD operations
+ with less chance of "dangling connections".
+
+ - Column defaults and onupdate Python functions (i.e. passed to
+ ColumnDefault) may take zero or one arguments; the one argument is the
+ ExecutionContext, from which you can call "context.parameters[someparam]"
+ to access the other bind parameter values affixed to the statement
+ [ticket:559]. The connection used for the execution is available as well
+ so that you can pre-execute statements.
+
+ - Added "explcit" create/drop/execute support for sequences (i.e. you can
+ pass a "connectable" to each of those methods on Sequence).
+
+ - Better quoting of identifiers when manipulating schemas.
+
+ - Standardized the behavior for table reflection where types can't be
+ located; NullType is substituted instead, warning is raised.
+
+ - ColumnCollection (i.e. the 'c' attribute on tables) follows dictionary
+ semantics for "__contains__" [ticket:606]
+
+- engines
+
+ - Speed! The mechanics of result processing and bind parameter processing
+ have been overhauled, streamlined and optimized to issue as little method
+ calls as possible. Bench tests for mass INSERT and mass rowset iteration
+ both show 0.4 to be over twice as fast as 0.3, using 68% fewer function
+ calls.
+
+ - You can now hook into the pool lifecycle and run SQL statements or other
+ logic at new each DBAPI connection, pool check-out and check-in.
+
+ - Connections gain a .properties collection, with contents scoped to the
+ lifetime of the underlying DBAPI connection
+
+ - Removed auto_close_cursors and disallow_open_cursors arguments from Pool;
+ reduces overhead as cursors are normally closed by ResultProxy and
+ Connection.
+
+- extensions
+
+ - proxyengine is temporarily removed, pending an actually working
+ replacement.
+
+ - SelectResults has been replaced by Query. SelectResults /
+ SelectResultsExt still exist but just return a slightly modified Query
+ object for backwards-compatibility. join_to() method from SelectResults
+ isn't present anymore, need to use join().
+
+- mysql
+
+ - Table and column names loaded via reflection are now Unicode.
+
+ - All standard column types are now supported, including SET.
+
+ - Table reflection can now be performed in as little as one round-trip.
+
+ - ANSI and ANSI_QUOTES sql modes are now supported.
+
+ - Indexes are now reflected.
+
+- postgres
+
+ - Added PGArray datatype for using postgres array datatypes.
+
+- oracle
+
+ - Very rudimental support for OUT parameters added; use sql.outparam(name,
+ type) to set up an OUT parameter, just like bindparam(); after execution,
+ values are avaiable via result.out_parameters dictionary. [ticket:507]
+
+0.3.11
+------
+
+- sql
+
+ - tweak DISTINCT precedence for clauses like
+ `func.count(t.c.col.distinct())`
+
+ - Fixed detection of internal '$' characters in :bind$params [ticket:719]
+
+ - [ticket:768] dont assume join criterion consists only of column objects
+
+ - 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
+ 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
+ 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
+ collection doesn't contain the item, supports noload collections
+ [ticket:813]
+
+- engine
+
+ - fixed another occasional race condition which could occur
+ when using pool with threadlocal setting
+
+- mysql
+ - fixed specification of YEAR columns when generating schema
+
+- mssql
+
+ - added support for TIME columns (simulated using DATETIME) [ticket:679]
+
+ - added support for BIGINT, MONEY, SMALLMONEY, UNIQUEIDENTIFIER and
+ SQL_VARIANT [ticket:721]
+
+ - index names are now quoted when dropping from reflected tables
+ [ticket:684]
+
+ - can now specify a DSN for PyODBC, using a URI like mssql:///?dsn=bob
+
+- postgres
+
+ - when reflecting tables from alternate schemas, the "default" placed upon
+ the primary key, i.e. usually a sequence name, has the "schema" name
+ unconditionally quoted, so that schema names which need quoting are fine.
+ its slightly unnecessary for schema names which don't need quoting
+ but not harmful.
+
+- sqlite
+ - passthrough for stringified dates
+
+- firebird
+ - supports_sane_rowcount() set to False due to ticket #370 (right way).
+ - fixed reflection of Column's nullable property.
+
+- oracle
+ - removed LONG_STRING, LONG_BINARY from "binary" types, so type objects
+ don't try to read their values as LOB [ticket:622], [ticket:751]
+
+0.3.10
+- general
+ - a new mutex that was added in 0.3.9 causes the pool_timeout
+ feature to fail during a race condition; threads would
+ raise TimeoutError immediately with no delay if many threads
+ push the pool into overflow at the same time. this issue has been
+ fixed.
+- sql
+ - got connection-bound metadata to work with implicit execution
+ - foreign key specs can have any chararcter in their identifiers
+ [ticket:667]
+ - added commutativity-awareness to binary clause comparisons to
+ each other, improves ORM lazy load optimization [ticket:664]
+- orm
+ - cleanup to connection-bound sessions, SessionTransaction
+- postgres
+ - fixed max identifier length (63) [ticket:571]
+
+
+0.3.9
+- general
+ - better error message for NoSuchColumnError [ticket:607]
+ - finally figured out how to get setuptools version in, available
+ as sqlalchemy.__version__ [ticket:428]
+ - the various "engine" arguments, such as "engine", "connectable",
+ "engine_or_url", "bind_to", etc. are all present, but deprecated.
+ they all get replaced by the single term "bind". you also
+ set the "bind" of MetaData using
+ metadata.bind = <engine or connection>
+- ext
+ - iteration over dict association proxies is now dict-like, not
+ InstrumentedList-like (e.g. over keys instead of values)
+ - association proxies no longer bind tightly to source collections
+ [ticket:597], and are constructed with a thunk instead
+ - added selectone_by() to assignmapper
+- orm
+ - forwards-compatibility with 0.4: added one(), first(), and
+ all() to Query. almost all Query functionality from 0.4 is
+ present in 0.3.9 for forwards-compat purposes.
+ - reset_joinpoint() really really works this time, promise ! lets
+ you re-join from the root:
+ query.join(['a', 'b']).filter(<crit>).reset_joinpoint().\
+ join(['a', 'c']).filter(<some other crit>).all()
+ in 0.4 all join() calls start from the "root"
+ - added synchronization to the mapper() construction step, to avoid
+ thread collisions when pre-existing mappers are compiling in a
+ different thread [ticket:613]
+ - a warning is issued by Mapper when two primary key columns of the
+ same name are munged into a single attribute. this happens frequently
+ when mapping to joins (or inheritance).
+ - synonym() properties are fully supported by all Query joining/
+ with_parent operations [ticket:598]
+ - fixed very stupid bug when deleting items with many-to-many
+ uselist=False relations
+ - remember all that stuff about polymorphic_union ? for
+ joined table inheritance ? Funny thing...
+ You sort of don't need it for joined table inheritance, you
+ can just string all the tables together via outerjoin().
+ The UNION still applies if concrete tables are involved,
+ though (since nothing to join them on).
+ - small fix to eager loading to better work with eager loads
+ to polymorphic mappers that are using a straight "outerjoin"
+ clause
+- sql
+ - ForeignKey to a table in a schema thats not the default schema
+ requires the schema to be explicit; i.e. ForeignKey('alt_schema.users.id')
+ - MetaData can now be constructed with an engine or url as the first
+ argument, just like BoundMetaData
+ - BoundMetaData is now deprecated, and MetaData is a direct substitute.
+ - DynamicMetaData has been renamed to ThreadLocalMetaData. the
+ DynamicMetaData name is deprecated and is an alias for ThreadLocalMetaData
+ or a regular MetaData if threadlocal=False
+ - composite primary key is represented as a non-keyed set to allow for
+ composite keys consisting of cols with the same name; occurs within a
+ Join. helps inheritance scenarios formulate correct PK.
+ - improved ability to get the "correct" and most minimal set of primary key
+ columns from a join, equating foreign keys and otherwise equated columns.
+ this is also mostly to help inheritance scenarios formulate the best
+ choice of primary key columns. [ticket:185]
+ - added 'bind' argument to Sequence.create()/drop(), ColumnDefault.execute()
+ - columns can be overridden in a reflected table with a "key"
+ attribute different than the column's name, including for primary key
+ columns [ticket:650]
+ - fixed "ambiguous column" result detection, when dupe col names exist
+ in a result [ticket:657]
+ - some enhancements to "column targeting", the ability to match a column
+ to a "corresponding" column in another selectable. this affects mostly
+ ORM ability to map to complex joins
+ - MetaData and all SchemaItems are safe to use with pickle. slow
+ table reflections can be dumped into a pickled file to be reused later.
+ Just reconnect the engine to the metadata after unpickling. [ticket:619]
+ - added a mutex to QueuePool's "overflow" calculation to prevent a race
+ condition that can bypass max_overflow
+ - fixed grouping of compound selects to give correct results. will break
+ on sqlite in some cases, but those cases were producing incorrect
+ results anyway, sqlite doesn't support grouped compound selects
+ [ticket:623]
+ - fixed precedence of operators so that parenthesis are correctly applied
+ [ticket:620]
+ - calling <column>.in_() (i.e. with no arguments) will return
+ "CASE WHEN (<column> IS NULL) THEN NULL ELSE 0 END = 1)", so that
+ NULL or False is returned in all cases, rather than throwing an error
+ [ticket:545]
+ - fixed "where"/"from" criterion of select() to accept a unicode string
+ in addition to regular string - both convert to text()
+ - added standalone distinct() function in addition to column.distinct()
+ [ticket:558]
+ - result.last_inserted_ids() should return a list that is identically
+ sized to the primary key constraint of the table. values that were
+ "passively" created and not available via cursor.lastrowid will be None.
+ - long-identifier detection fixed to use > rather than >= for
+ max ident length [ticket:589]
+ - fixed bug where selectable.corresponding_column(selectable.c.col)
+ would not return selectable.c.col, if the selectable is a join
+ of a table and another join involving the same table. messed
+ up ORM decision making [ticket:593]
+ - added Interval type to types.py [ticket:595]
+- mysql
+ - fixed catching of some errors that imply a dropped connection [ticket:625]
+ - fixed escaping of the modulo operator [ticket:624]
+ - added 'fields' to reserved words [ticket:590]
+ - various reflection enhancement/fixes
+- oracle
+ - datetime fixes: got subsecond TIMESTAMP to work [ticket:604],
+ added OracleDate which supports types.Date with only year/month/day
+ - added dialect flag "auto_convert_lobs", defaults to True; will cause any
+ LOB objects detected in a result set to be forced into OracleBinary
+ so that the LOB is read() automatically, if no typemap was present
+ (i.e., if a textual execute() was issued).
+ - mod operator '%' produces MOD [ticket:624]
+ - converts cx_oracle datetime objects to Python datetime.datetime when
+ Python 2.3 used [ticket:542]
+ - fixed unicode conversion in Oracle TEXT type
+- postgres
+ - fixed escaping of the modulo operator [ticket:624]
+ - added support for reflection of domains [ticket:570]
+ - types which are missing during reflection resolve to Null type
+ instead of raising an error
+ - the fix in "schema" above fixes reflection of foreign keys from an
+ alt-schema table to a public schema table
+- sqlite
+ - rearranged dialect initialization so it has time to warn about pysqlite1
+ being too old.
+ - sqlite better handles datetime/date/time objects mixed and matched
+ with various Date/Time/DateTime columns
+ - string PK column inserts dont get overwritten with OID [ticket:603]
+- mssql
+ - fix port option handling for pyodbc [ticket:634]
+ - now able to reflect start and increment values for identity columns
+ - preliminary support for using scope_identity() with pyodbc
+
+0.3.8
+- engines
+ - added detach() to Connection, allows underlying DBAPI connection
+ to be detached from its pool, closing on dereference/close()
+ instead of being reused by the pool.
+ - added invalidate() to Connection, immediately invalidates the
+ Connection and its underlying DBAPI connection.
+- sql
+ - _Label class overrides compare_self to return its ultimate
+ object. meaning, if you say someexpr.label('foo') == 5, it
+ produces the correct "someexpr == 5".
+ - _Label propagates "_hide_froms()" so that scalar selects
+ behave more properly with regards to FROM clause #574
+ - fix to long name generation when using oid_column as an order by
+ (oids used heavily in mapper queries)
+ - significant speed improvement to ResultProxy, pre-caches
+ TypeEngine dialect implementations and saves on function calls
+ per column
+ - parenthesis are applied to clauses via a new _Grouping
+ construct. uses operator precedence to more intelligently apply
+ parenthesis to clauses, provides cleaner nesting of clauses
+ (doesnt mutate clauses placed in other clauses, i.e. no 'parens'
+ flag)
+ - added 'modifier' keyword, works like func.<foo> except does not
+ add parenthesis. e.g. select([modifier.DISTINCT(...)]) etc.
+ - removed "no group by's in a select thats part of a UNION"
+ restriction [ticket:578]
+- orm
+ - added reset_joinpoint() method to Query, moves the "join point"
+ back to the starting mapper. 0.4 will change the behavior of
+ join() to reset the "join point" in all cases so this is an
+ interim method. for forwards compatibility, ensure joins across
+ multiple relations are specified using a single join(), i.e.
+ join(['a', 'b', 'c']).
+ - fixed bug in query.instances() that wouldnt handle more than
+ on additional mapper or one additional column.
+ - "delete-orphan" no longer implies "delete". ongoing effort to
+ separate the behavior of these two operations.
+ - many-to-many relationships properly set the type of bind params
+ for delete operations on the association table
+ - many-to-many relationships check that the number of rows deleted
+ from the association table by a delete operation matches the
+ expected results
+ - session.get() and session.load() propagate **kwargs through to
+ query
+ - fix to polymorphic query which allows the original
+ polymorphic_union to be embedded into a correlated subquery
+ [ticket:577]
+ - fix to select_by(<propname>=<object instance>) -style joins in
+ conjunction with many-to-many relationships, bug introduced in
+ r2556
+ - the "primary_key" argument to mapper() is propagated to the
+ "polymorphic" mapper. primary key columns in this list get
+ normalized to that of the mapper's local table.
+ - restored logging of "lazy loading clause" under
+ sa.orm.strategies logger, got removed in 0.3.7
+ - improved support for eagerloading of properties off of mappers
+ that are mapped to select() statements; i.e. eagerloader is
+ better at locating the correct selectable with which to attach
+ its LEFT OUTER JOIN.
+- mysql
+ - Nearly all MySQL column types are now supported for declaration
+ and reflection. Added NCHAR, NVARCHAR, VARBINARY, TINYBLOB,
+ LONGBLOB, YEAR
+ - The sqltypes.Binary passthrough now always builds a BLOB,
+ avoiding problems with very old database versions
+ - support for column-level CHARACTER SET and COLLATE declarations,
+ as well as ASCII, UNICODE, NATIONAL and BINARY shorthand.
+- firebird
+ - set max identifier length to 31
+ - supports_sane_rowcount() set to False due to ticket #370.
+ versioned_id_col feature wont work in FB.
+ - some execution fixes
+-extensions
+ - new association proxy implementation, implementing complete
+ proxies to list, dict and set-based relation collections
+ - added orderinglist, a custom list class that synchronizes an
+ object attribute with that object's position in the list
+ - small fix to SelectResultsExt to not bypass itself during
+ select().
+ - added filter(), filter_by() to assignmapper
+
+0.3.7
+- engines
+ - warnings module used for issuing warnings (instead of logging)
+ - cleanup of DBAPI import strategies across all engines
+ [ticket:480]
+ - refactoring of engine internals which reduces complexity,
+ number of codepaths; places more state inside of ExecutionContext
+ to allow more dialect control of cursor handling, result sets.
+ ResultProxy totally refactored and also has two versions of
+ "buffered" result sets used for different purposes.
+ - server side cursor support fully functional in postgres
+ [ticket:514].
+ - improved framework for auto-invalidation of connections that have
+ lost their underlying database, via dialect-specific detection
+ of exceptions corresponding to that database's disconnect
+ related error messages. Additionally, when a "connection no
+ longer open" condition is detected, the entire connection pool
+ is discarded and replaced with a new instance. #516
+ - the dialects within sqlalchemy.databases become a setuptools
+ entry points. loading the built-in database dialects works the
+ same as always, but if none found will fall back to trying
+ pkg_resources to load an external module [ticket:521]
+ - Engine contains a "url" attribute referencing the url.URL object
+ used by create_engine().
+- sql:
+ - keys() of result set columns are not lowercased, come back
+ exactly as they're expressed in cursor.description. note this
+ causes colnames to be all caps in oracle.
+ - preliminary support for unicode table names, column names and
+ SQL statements added, for databases which can support them.
+ Works with sqlite and postgres so far. Mysql *mostly* works
+ except the has_table() function does not work. Reflection
+ works too.
+ - the Unicode type is now a direct subclass of String, which now
+ contains all the "convert_unicode" logic. This helps the variety
+ of unicode situations that occur in db's such as MS-SQL to be
+ better handled and allows subclassing of the Unicode datatype.
+ [ticket:522]
+ - ClauseElements can be used in in_() clauses now, such as bind
+ parameters, etc. #476
+ - reverse operators implemented for `CompareMixin` elements,
+ allows expressions like "5 + somecolumn" etc. #474
+ - the "where" criterion of an update() and delete() now correlates
+ embedded select() statements against the table being updated or
+ deleted. this works the same as nested select() statement
+ correlation, and can be disabled via the correlate=False flag on
+ the embedded select().
+ - column labels are now generated in the compilation phase, which
+ means their lengths are dialect-dependent. So on oracle a label
+ that gets truncated to 30 chars will go out to 63 characters
+ on postgres. Also, the true labelname is always attached as the
+ accessor on the parent Selectable so theres no need to be aware
+ of the "truncated" label names [ticket:512].
+ - column label and bind param "truncation" also generate
+ deterministic names now, based on their ordering within the
+ full statement being compiled. this means the same statement
+ will produce the same string across application restarts and
+ allowing DB query plan caching to work better.
+ - the "mini" column labels generated when using subqueries, which
+ are to work around glitchy SQLite behavior that doesnt understand
+ "foo.id" as equivalent to "id", are now only generated in the case
+ that those named columns are selected from (part of [ticket:513])
+ - the label() method on ColumnElement will properly propagate the
+ TypeEngine of the base element out to the label, including a label()
+ created from a scalar=True select() statement.
+ - MS-SQL better detects when a query is a subquery and knows not to
+ generate ORDER BY phrases for those [ticket:513]
+ - fix for fetchmany() "size" argument being positional in most
+ dbapis [ticket:505]
+ - sending None as an argument to func.<something> will produce
+ an argument of NULL
+ - query strings in unicode URLs get keys encoded to ascii
+ for **kwargs compat
+ - slight tweak to raw execute() change to also support tuples
+ for positional parameters, not just lists [ticket:523]
+ - fix to case() construct to propagate the type of the first
+ WHEN condition as the return type of the case statement
+- orm:
+ - fixed critical issue when, after options(eagerload()) is used,
+ the mapper would then always apply query "wrapping" behavior
+ for all subsequent LIMIT/OFFSET/DISTINCT queries, even if no
+ eager loading was applied on those subsequent queries.
+ - added query.with_parent(someinstance) method. searches for
+ target instance using lazy join criterion from parent instance.
+ takes optional string "property" to isolate the desired relation.
+ also adds static Query.query_from_parent(instance, property)
+ version. [ticket:541]
+ - improved query.XXX_by(someprop=someinstance) querying to use
+ similar methodology to with_parent, i.e. using the "lazy" clause
+ which prevents adding the remote instance's table to the SQL,
+ thereby making more complex conditions possible [ticket:554]
+ - added generative versions of aggregates, i.e. sum(), avg(), etc.
+ to query. used via query.apply_max(), apply_sum(), etc.
+ #552
+ - fix to using distinct() or distinct=True in combination with
+ join() and similar
+ - corresponding to label/bindparam name generation, eager loaders
+ generate deterministic names for the aliases they create using
+ md5 hashes.
+ - improved/fixed custom collection classes when giving it "set"/
+ "sets.Set" classes or subclasses (was still looking for append()
+ methods on them during lazy loads)
+ - restored old "column_property()" ORM function (used to be called
+ "column()") to force any column expression to be added as a property
+ on a mapper, particularly those that aren't present in the mapped
+ selectable. this allows "scalar expressions" of any kind to be
+ added as relations (though they have issues with eager loads).
+ - fix to many-to-many relationships targeting polymorphic mappers
+ [ticket:533]
+ - making progress with session.merge() as well as combining its
+ usage with entity_name [ticket:543]
+ - the usual adjustments to relationships between inheriting mappers,
+ in this case establishing relation()s to subclass mappers where
+ the join conditions come from the superclass' table
+- informix:
+ - informix support added ! courtesy James Zhang, who put a ton
+ of effort in.
+- sqlite:
+ - removed silly behavior where sqlite would reflect UNIQUE indexes
+ as part of the primary key (?!)
+- oracle:
+ - small fix to allow successive compiles of the same SELECT object
+ which features LIMIT/OFFSET. oracle dialect needs to modify
+ the object to have ROW_NUMBER OVER and wasn't performing
+ the full series of steps on successive compiles.
+- mysql
+ - support for SSL arguments given as inline within URL query string,
+ prefixed with "ssl_", courtesy terjeros@gmail.com.
+ - mysql uses "DESCRIBE [<schemaname>].<tablename>", catching exceptions
+ if table doesnt exist, in order to determine if a table exists.
+ this supports unicode table names as well as schema names. tested
+ with MySQL5 but should work with 4.1 series as well. (#557)
+- extensions
+ - big fix to AssociationProxy so that multiple AssociationProxy
+ objects can be associated with a single association collection.
+ - assign_mapper names methods according to their keys (i.e. __name__)
+ #551
+- mssql
+ - pyodbc is now the preferred DB-API for MSSQL, and if no module is
+ specifically requested, will be loaded first on a module probe.
+
+ - The @@SCOPE_IDENTITY is now used instead of @@IDENTITY. This
+ behavior may be overridden with the engine_connect
+ "use_scope_identity" keyword parameter, which may also be specified
+ in the dburi.
+
+
+
+0.3.6
+- sql:
+ - bindparam() names are now repeatable! specify two
+ distinct bindparam()s with the same name in a single statement,
+ and the key will be shared. proper positional/named args translate
+ at compile time. for the old behavior of "aliasing" bind parameters
+ with conflicting names, specify "unique=True" - this option is
+ still used internally for all the auto-genererated (value-based)
+ bind parameters.
+
+ - slightly better support for bind params as column clauses, either
+ via bindparam() or via literal(), i.e. select([literal('foo')])
+
+ - MetaData can bind to an engine either via "url" or "engine" kwargs
+ to constructor, or by using connect() method. BoundMetaData is
+ identical to MetaData except engine_or_url param is required.
+ DynamicMetaData is the same and provides thread-local connections be
+ default.
+
+ - exists() becomes useable as a standalone selectable, not just in a
+ WHERE clause, i.e. exists([columns], criterion).select()
+
+ - correlated subqueries work inside of ORDER BY, GROUP BY
+
+ - fixed function execution with explicit connections, i.e.
+ conn.execute(func.dosomething())
+
+ - use_labels flag on select() wont auto-create labels for literal text
+ column elements, since we can make no assumptions about the text. to
+ create labels for literal columns, you can say "somecol AS
+ somelabel", or use literal_column("somecol").label("somelabel")
+
+ - quoting wont occur for literal columns when they are "proxied" into
+ the column collection for their selectable (is_literal flag is
+ propagated). literal columns are specified via
+ literal_column("somestring").
+
+ - added "fold_equivalents" boolean argument to Join.select(), which
+ removes 'duplicate' columns from the resulting column clause that
+ are known to be equivalent based on the join condition. this is of
+ great usage when constructing subqueries of joins which Postgres
+ complains about if duplicate column names are present.
+
+ - fixed use_alter flag on ForeignKeyConstraint [ticket:503]
+
+ - fixed usage of 2.4-only "reversed" in topological.py [ticket:506]
+
+ - for hackers, refactored the "visitor" system of ClauseElement and
+ SchemaItem so that the traversal of items is controlled by the
+ ClauseVisitor itself, using the method visitor.traverse(item).
+ accept_visitor() methods can still be called directly but will not
+ do any traversal of child items. ClauseElement/SchemaItem now have a
+ configurable get_children() method to return the collection of child
+ elements for each parent object. This allows the full traversal of
+ items to be clear and unambiguous (as well as loggable), with an
+ easy method of limiting a traversal (just pass flags which are
+ picked up by appropriate get_children() methods). [ticket:501]
+
+ - the "else_" parameter to the case statement now properly works when
+ set to zero.
+
+- orm:
+ - the full featureset of the SelectResults extension has been merged
+ into a new set of methods available off of Query. These methods
+ all provide "generative" behavior, whereby the Query is copied
+ and a new one returned with additional criterion added.
+ The new methods include:
+
+ filter() - applies select criterion to the query
+ filter_by() - applies "by"-style criterion to the query
+ avg() - return the avg() function on the given column
+ join() - join to a property (or across a list of properties)
+ outerjoin() - like join() but uses LEFT OUTER JOIN
+ limit()/offset() - apply LIMIT/OFFSET
+ range-based access which applies limit/offset:
+ session.query(Foo)[3:5]
+ distinct() - apply DISTINCT
+ list() - evaluate the criterion and return results
+
+ no incompatible changes have been made to Query's API and no methods
+ have been deprecated. Existing methods like select(), select_by(),
+ get(), get_by() all execute the query at once and return results
+ like they always did. join_to()/join_via() are still there although
+ the generative join()/outerjoin() methods are easier to use.
+
+ - the return value for multiple mappers used with instances() now
+ returns a cartesian product of the requested list of mappers,
+ represented as a list of tuples. this corresponds to the documented
+ behavior. So that instances match up properly, the "uniquing" is
+ disabled when this feature is used.
+
+ - Query has add_entity() and add_column() generative methods. these
+ will add the given mapper/class or ColumnElement to the query at
+ compile time, and apply them to the instances() method. the user is
+ responsible for constructing reasonable join conditions (otherwise
+ you can get full cartesian products). result set is the list of
+ tuples, non-uniqued.
+
+ - strings and columns can also be sent to the *args of instances()
+ where those exact result columns will be part of the result tuples.
+
+ - a full select() construct can be passed to query.select() (which
+ worked anyway), but also query.selectfirst(), query.selectone()
+ which will be used as is (i.e. no query is compiled). works
+ similarly to sending the results to instances().
+
+ - eager loading will not "aliasize" "order by" clauses that were
+ placed in the select statement by something other than the eager
+ loader itself, to fix possibility of dupe columns as illustrated in
+ [ticket:495]. however, this means you have to be more careful with
+ the columns placed in the "order by" of Query.select(), that you
+ have explicitly named them in your criterion (i.e. you cant rely on
+ the eager loader adding them in for you)
+
+ - added a handy multi-use "identity_key()" method to Session, allowing
+ the generation of identity keys for primary key values, instances,
+ and rows, courtesy Daniel Miller
+
+ - many-to-many table will be properly handled even for operations that
+ occur on the "backref" side of the operation [ticket:249]
+
+ - added "refresh-expire" cascade [ticket:492]. allows refresh() and
+ expire() calls to propagate along relationships.
+
+ - more fixes to polymorphic relations, involving proper lazy-clause
+ generation on many-to-one relationships to polymorphic mappers
+ [ticket:493]. also fixes to detection of "direction", more specific
+ targeting of columns that belong to the polymorphic union vs. those
+ that dont.
+
+ - some fixes to relationship calcs when using "viewonly=True" to pull
+ in other tables into the join condition which arent parent of the
+ relationship's parent/child mappings
+
+ - flush fixes on cyclical-referential relationships that contain
+ references to other instances outside of the cyclical chain, when
+ some of the objects in the cycle are not actually part of the flush
+
+ - put an aggressive check for "flushing object A with a collection of
+ B's, but you put a C in the collection" error condition - **even if
+ C is a subclass of B**, unless B's mapper loads polymorphically.
+ Otherwise, the collection will later load a "B" which should be a
+ "C" (since its not polymorphic) which breaks in bi-directional
+ relationships (i.e. C has its A, but A's backref will lazyload it as
+ a different instance of type "B") [ticket:500] This check is going
+ to bite some of you who do this without issues, so the error message
+ will also document a flag "enable_typechecks=False" to disable this
+ checking. But be aware that bi-directional relationships in
+ particular become fragile without this check.
+
+- extensions:
+ - options() method on SelectResults now implemented "generatively"
+ like the rest of the SelectResults methods [ticket:472]. But
+ you're going to just use Query now anyway.
+
+ - query() method is added by assignmapper. this helps with
+ navigating to all the new generative methods on Query.
+
+- ms-sql:
+ - removed seconds input on DATE column types (probably
+ should remove the time altogether)
+
+ - null values in float fields no longer raise errors
+
+ - LIMIT with OFFSET now raises an error (MS-SQL has no OFFSET support)
+
+ - added an facility to use the MSSQL type VARCHAR(max) instead of TEXT
+ for large unsized string fields. Use the new "text_as_varchar" to
+ turn it on. [ticket:509]
+
+ - ORDER BY clauses without a LIMIT are now stripped in subqueries, as
+ MS-SQL forbids this usage
+
+ - cleanup of module importing code; specifiable DB-API module; more
+ explicit ordering of module preferences. [ticket:480]
+
+- oracle:
+ - got binary working for any size input ! cx_oracle works fine,
+ it was my fault as BINARY was being passed and not BLOB for
+ setinputsizes (also unit tests werent even setting input sizes).
+
+ - also fixed CLOB read/write on a separate changeset.
+
+ - auto_setinputsizes defaults to True for Oracle, fixed cases where
+ it improperly propagated bad types.
+
+- mysql:
+ - added a catchall **kwargs to MSString, to help reflection of
+ obscure types (like "varchar() binary" in MS 4.0)
+
+ - added explicit MSTimeStamp type which takes effect when using
+ types.TIMESTAMP.
+
+
+0.3.5
+- sql:
+ - the value of "case_sensitive" defaults to True now, regardless of the
+ casing of the identifier, unless specifically set to False. this is
+ because the object might be label'ed as something else which does
+ contain mixed case, and propigating "case_sensitive=False" breaks that.
+ Other fixes to quoting when using labels and "fake" column objects
+ - added a "supports_execution()" method to ClauseElement, so that
+ individual kinds of clauses can express if they are appropriate for
+ executing...such as, you can execute a "select", but not a "Table" or a
+ "Join".
+ - fixed argument passing to straight textual execute() on engine,
+ connection. can handle *args or a list instance for positional, **kwargs
+ or a dict instance for named args, or a list of list or dicts to invoke
+ executemany()
+ - small fix to BoundMetaData to accept unicode or string URLs
+ - fixed named PrimaryKeyConstraint generation [ticket:466] courtesy
+ andrija at gmail
+ - fixed generation of CHECK constraints on columns [ticket:464]
+ - fixes to tometadata() operation to propagate Constraints at column and
+ table level
+- oracle:
+ - when returning "rowid" as the ORDER BY column or in use with ROW_NUMBER
+ OVER, oracle dialect checks the selectable its being applied to and will
+ switch to table PK if not applicable, i.e. for a UNION. checking for
+ DISTINCT, GROUP BY (other places that rowid is invalid) still a TODO.
+ allows polymorphic mappings to function, [ticket:436]
+ - sequences on a non-pk column will properly fire off on INSERT
+ - added PrefetchingResultProxy support to pre-fetch LOB columns when they
+ are known to be present, fixes [ticket:435]
+ - implemented reflection of tables based on synonyms, including across
+ dblinks [ticket:379]
+ - issues a log warning when a related table cant be reflected due to
+ certain permission errors [ticket:363]
+- mysql:
+ - fix to reflection on older DB's that might return array() type for
+ "show variables like" statements
+- postgres:
+ - better reflection of sequences for alternate-schema Tables [ticket:442]
+ - sequences on a non-pk column will properly fire off on INSERT
+ - added PGInterval type [ticket:460], PGInet type [ticket:444]
+- mssql:
+ - preliminary support for pyodbc (Yay!) [ticket:419]
+ - better support for NVARCHAR types added [ticket:298]
+ - fix for commit logic on pymssql
+ - fix for query.get() with schema [ticket:456]
+ - fix for non-integer relationships [ticket:473]
+ - DB-API module now selectable at run-time [ticket:419]
+ - now passes many more unit tests [tickets:422, 481, 415]
+ - better unittest compatibility with ANSI functions [ticket:479]
+ - improved support for implicit sequence PK columns with auto-insert
+ [ticket:415]
+ - fix for blank password in adodbapi [ticket:371]
+ - fixes to get unit tests working with pyodbc [ticket:481]
+ - fix to auto_identity_insert on db-url query
+ - added query_timeout to db-url query parms. currently works only for
+ pymssql
+ - tested with pymssql 0.8.0 (which is now LGPL)
+- orm bugs:
+ - another refactoring to relationship calculation. Allows more accurate
+ ORM behavior with relationships from/to/between mappers, particularly
+ polymorphic mappers, also their usage with Query, SelectResults. tickets
+ include [ticket:439], [ticket:441], [ticket:448].
+ - removed deprecated method of specifying custom collections on classes;
+ you must now use the "collection_class" option. the old way was
+ beginning to produce conflicts when people used assign_mapper(), which
+ now patches an "options" method, in conjunction with a relationship
+ named "options". (relationships take precedence over monkeypatched
+ assign_mapper methods).
+ - extension() query option propagates to Mapper._instance() method so that
+ all loading-related methods get called [ticket:454]
+ - eager relation to an inheriting mapper wont fail if no rows returned for
+ the relationship.
+ - eager relation loading bug fixed for eager relation on multiple
+ descendant classes [ticket:486]
+ - fix for very large topological sorts, courtesy ants.aasma at gmail
+ [ticket:423]
+ - eager loading is slightly more strict about detecting "self-referential"
+ relationships, specifically between polymorphic mappers. this results in
+ an "eager degrade" to lazy loading.
+ - improved support for complex queries embedded into "where" criterion for
+ query.select() [ticket:449]
+ - mapper options like eagerload(), lazyload(), deferred(), will work for
+ "synonym()" relationships [ticket:485]
+ - fixed bug where cascade operations incorrectly included deleted
+ collection items in the cascade [ticket:445]
+ - fixed relationship deletion error when one-to-many child item is moved
+ to a new parent in a single unit of work [ticket:478]
+ - fixed relationship deletion error where parent/child with a single
+ column as PK/FK on the child would raise a "blank out the primary key"
+ error, if manually deleted or "delete" cascade without "delete-orphan"
+ was used
+ - fix to deferred so that load operation doesnt mistakenly occur when only
+ PK col attributes are set
+- orm enhancements:
+ - implemented foreign_keys argument to mapper [ticket:385]. use in
+ conjunction with primaryjoin/secondaryjoin arguments to specify/override
+ foreign keys defined on the Table instance.
+ - contains_eager('foo') automatically implies eagerload('foo')
+ - added "alias" argument to contains_eager(). use it to specify the string
+ name or Alias instance of an alias used in the query for the eagerly
+ loaded child items. easier to use than "decorator"
+ - added "contains_alias()" option for result set mapping to an alias of
+ the mapped table
+ - added support for py2.5 "with" statement with SessionTransaction
+ [ticket:468]
+- extensions:
+ - added distinct() method to SelectResults. generally should only make a
+ difference when using count().
+ - added options() method to SelectResults, equivalent to query.options()
+ [ticket:472]
+ - added optional __table_opts__ dictionary to ActiveMapper, will send kw
+ options to Table objects [ticket:462]
+ - added selectfirst(), selectfirst_by() to assign_mapper [ticket:467]
+
+0.3.4
+- general:
+ - global "insure"->"ensure" change. in US english "insure" is actually
+ largely interchangeable with "ensure" (so says the dictionary), so I'm not
+ completely illiterate, but its definitely sub-optimal to "ensure" which is
+ non-ambiguous.
+- sql:
+ - added "fetchmany()" support to ResultProxy
+ - added support for column "key" attribute to be useable in
+ row[<key>]/row.<key>
+ - changed "BooleanExpression" to subclass from "BinaryExpression", so that
+ boolean expressions can also follow column-clause behaviors (i.e. label(),
+ etc).
+ - trailing underscores are trimmed from func.<xxx> calls, such as func.if_()
+ - fix to correlation of subqueries when the column list of the select
+ statement is constructed with individual calls to append_column(); this
+ fixes an ORM bug whereby nested select statements were not getting
+ correlated with the main select generated by the Query object.
+ - another fix to subquery correlation so that a subquery which has only one
+ FROM element will *not* correlate that single element, since at least one
+ FROM element is required in a query.
+ - default "timezone" setting is now False. this corresponds to Python's
+ datetime behavior as well as Postgres' timestamp/time types (which is the
+ only timezone-sensitive dialect at the moment) [ticket:414]
+ - the "op()" function is now treated as an "operation", rather than a
+ "comparison". the difference is, an operation produces a BinaryExpression
+ from which further operations can occur whereas comparison produces the
+ more restrictive BooleanExpression
+ - trying to redefine a reflected primary key column as non-primary key raises
+ an error
+ - type system slightly modified to support TypeDecorators that can be
+ overridden by the dialect (ok, thats not very clear, it allows the mssql
+ tweak below to be possible)
+- mssql:
+ - added an NVarchar type (produces NVARCHAR), also MSUnicode which provides
+ Unicode-translation for the NVarchar regardless of dialect convert_unicode
+ setting.
+- postgres:
+ - fix to the initial checkfirst for tables to take current schema into
+ account [ticket:424]
+ - postgres has an optional "server_side_cursors=True" flag which will utilize
+ server side cursors. these are appropriate for fetching only partial
+ results and are necessary for working with very large unbounded result
+ sets. While we'd like this to be the default behavior, different
+ environments seem to have different results and the causes have not been
+ isolated so we are leaving the feature off by default for now. Uses an
+ apparently undocumented psycopg2 behavior recently discovered on the
+ psycopg mailing list.
+ - added "BIGSERIAL" support for postgres table with
+ PGBigInteger/autoincrement
+ - fixes to postgres reflection to better handle when schema names are
+ present; thanks to jason (at) ncsmags.com [ticket:402]
+- mysql:
+ - mysql is inconsistent with what kinds of quotes it uses in foreign keys
+ during a SHOW CREATE TABLE, reflection updated to accomodate for all three
+ styles [ticket:420]
+ - mysql table create options work on a generic passthru now, i.e. Table(...,
+ mysql_engine='InnoDB', mysql_collate="latin1_german2_ci",
+ mysql_auto_increment="5", mysql_<somearg>...), helps [ticket:418]
+- firebird:
+ - order of constraint creation puts primary key first before all other
+ constraints; required for firebird, not a bad idea for others [ticket:408]
+ - Firebird fix to autoload multifield foreign keys [ticket:409]
+ - Firebird NUMERIC type properly handles a type without precision
+ [ticket:409]
+- oracle:
+ - *slight* support for binary, but still need to figure out how to insert
+ reasonably large values (over 4K). requires auto_setinputsizes=True sent to
+ create_engine(), rows must be fully fetched individually, etc.
+- orm:
+ - poked the first hole in the can of worms: saying
+ query.select_by(somerelationname=someinstance) will create the join of the
+ primary key columns represented by "somerelationname"'s mapper to the
+ actual primary key in "someinstance".
+ - reworked how relations interact with "polymorphic" mappers, i.e. mappers
+ that have a select_table as well as polymorphic flags. better determination
+ of proper join conditions, interaction with user- defined join conditions,
+ and support for self-referential polymorphic mappers.
+ - related to polymorphic mapping relations, some deeper error checking when
+ compiling relations, to detect an ambiguous "primaryjoin" in the case that
+ both sides of the relationship have foreign key references in the primary
+ join condition. also tightened down conditions used to locate "relation
+ direction", associating the "foreignkey" of the relationship with the
+ "primaryjoin"
+ - a little bit of improvement to the concept of a "concrete" inheritance
+ mapping, though that concept is not well fleshed out yet (added test case
+ to support concrete mappers on top of a polymorphic base).
+ - fix to "proxy=True" behavior on synonym()
+ - fixed bug where delete-orphan basically didn't work with many-to-many
+ relationships [ticket:427], backref presence generally hid the symptom
+ - added a mutex to the mapper compilation step. ive been reluctant to add any
+ kind of threading anything to SA but this is one spot that its its really
+ needed since mappers are typically "global", and while their state does not
+ change during normal operation, the initial compilation step does modify
+ internal state significantly, and this step usually occurs not at
+ module-level initialization time (unless you call compile()) but at
+ first-request time
+ - basic idea of "session.merge()" actually implemented. needs more testing.
+ - added "compile_mappers()" function as a shortcut to compiling all mappers
+ - fix to MapperExtension create_instance so that entity_name properly
+ associated with new instance
+ - speed enhancements to ORM object instantiation, eager loading of rows
+ - invalid options sent to 'cascade' string will raise an exception
+ [ticket:406]
+ - fixed bug in mapper refresh/expire whereby eager loaders didnt properly
+ re-populate item lists [ticket:407]
+ - fix to post_update to ensure rows are updated even for non insert/delete
+ scenarios [ticket:413]
+ - added an error message if you actually try to modify primary key values on
+ an entity and then flush it [ticket:412]
+- extensions
+ - added "validate=False" argument to assign_mapper, if True will ensure that
+ only mapped attributes are named [ticket:426]
+ - assign_mapper gets "options", "instances" functions added (i.e.
+ MyClass.instances())
+
+0.3.3
+- string-based FROM clauses fixed, i.e. select(..., from_obj=["sometext"])
+- fixes to passive_deletes flag, lazy=None (noload) flag
+- added example/docs for dealing with large collections
+- added object_session() method to sqlalchemy namespace
+- fixed QueuePool bug whereby its better able to reconnect to a database
+that was not reachable (thanks to Sébastien Lelong), also fixed dispose()
+method
+- patch that makes MySQL rowcount work correctly! [ticket:396]
+- fix to MySQL catch of 2006/2014 errors to properly re-raise OperationalError
+exception
+
+0.3.2
+- major connection pool bug fixed. fixes MySQL out of sync
+errors, will also prevent transactions getting rolled back
+accidentally in all DBs [ticket:387]
+- major speed enhancements vs. 0.3.1, to bring speed
+back to 0.2.8 levels
+ - made conditional dozens of debug log calls that were
+ time-intensive to generate log messages
+ - fixed bug in cascade rules whereby the entire object graph
+ could be unnecessarily cascaded on the save/update cascade
+ - various speedups in attributes module
+- identity map in Session is by default *no longer weak referencing*.
+to have it be weak referencing, use create_session(weak_identity_map=True)
+fixes [ticket:388]
+- MySQL detects errors 2006 (server has gone away) and 2014
+(commands out of sync) and invalidates the connection on which it occured.
+- MySQL bool type fix: [ticket:307]
+- postgres reflection fixes: [ticket:349] [ticket:382]
+- added keywords for EXCEPT, INTERSECT, EXCEPT ALL, INTERSECT ALL
+[ticket:247]
+- assign_mapper in assignmapper extension returns the created mapper
+[changeset:2110]
+- added label() function to Select class, when scalar=True is used
+to create a scalar subquery
+i.e. "select x, y, (select max(foo) from table) AS foomax from table"
+- added onupdate and ondelete keyword arguments to ForeignKey; propagate
+to underlying ForeignKeyConstraint if present. (dont propagate in the
+other direction, however)
+- fix to session.update() to preserve "dirty" status of incoming object
+- sending a selectable to an IN via the in_() function no longer creates
+a "union" out of multiple selects; only one selectable to a the in_() function
+is allowed now (make a union yourself if union is needed)
+- improved support for disabling save-update cascade via cascade="none" etc.
+- added "remote_side" argument to relation(), used only with self-referential
+mappers to force the direction of the parent/child relationship. replaces
+the usage of the "foreignkey" parameter for "switching" the direction.
+"foreignkey" argument is deprecated for all uses and will eventually
+be replaced by an argument dedicated to ForeignKey specification on mappers.
+
+0.3.1
+- Engine/Pool:
+ - some new Pool utility classes, updated docs
+ - "use_threadlocal" on Pool defaults to False (same as create_engine)
+ - fixed direct execution of Compiled objects
+ - create_engine() reworked to be strict about incoming **kwargs. all keyword
+arguments must be consumed by one of the dialect, connection pool, and engine
+constructors, else a TypeError is thrown which describes the full set of
+invalid kwargs in relation to the selected dialect/pool/engine configuration.
+- Databases/Types:
+ - MySQL catches exception on "describe" and reports as NoSuchTableError
+ - further fixes to sqlite booleans, weren't working as defaults
+ - fix to postgres sequence quoting when using schemas
+- ORM:
+ - the "delete" cascade will load in all child objects, if they were not
+loaded already. this can be turned off (i.e. the old behavior) by setting
+passive_deletes=True on a relation().
+ - adjustments to reworked eager query generation to not fail on circular
+eager-loaded relationships (like backrefs)
+ - fixed bug where eagerload() (nor lazyload()) option didn't properly
+instruct the Query whether or not to use "nesting" when producing a
+LIMIT query.
+ - fixed bug in circular dependency sorting at flush time; if object A
+contained a cyclical many-to-one relationship to object B, and object B
+was just attached to object A, *but* object B itself wasnt changed,
+the many-to-one synchronize of B's primary key attribute to A's foreign key
+attribute wouldnt occur. [ticket:360]
+ - implemented from_obj argument for query.count, improves count function
+on selectresults [ticket:325]
+ - added an assertion within the "cascade" step of ORM relationships to check
+that the class of object attached to a parent object is appropriate
+(i.e. if A.items stores B objects, raise an error if a C is appended to A.items)
+ - new extension sqlalchemy.ext.associationproxy, provides transparent
+"association object" mappings. new example
+examples/association/proxied_association.py illustrates.
+ - improvement to single table inheritance to load full hierarchies beneath
+the target class
+ - fix to subtle condition in topological sort where a node could appear twice,
+for [ticket:362]
+ - additional rework to topological sort, refactoring, for [ticket:365]
+ - "delete-orphan" for a certain type can be set on more than one parent class;
+the instance is an "orphan" only if its not attached to *any* of those parents
+
+0.3.0
+- General:
+ - logging is now implemented via standard python "logging" module.
+ "echo" keyword parameters are still functional but set/unset
+ log levels for their respective classes/instances. all logging
+ can be controlled directly through the Python API by setting
+ INFO and DEBUG levels for loggers in the "sqlalchemy" namespace.
+ class-level logging is under "sqlalchemy.<module>.<classname>",
+ instance-level logging under "sqlalchemy.<module>.<classname>.0x..<00-FF>".
+ Test suite includes "--log-info" and "--log-debug" arguments
+ which work independently of --verbose/--quiet. Logging added
+ to orm to allow tracking of mapper configurations, row iteration.
+ - the documentation-generation system has been overhauled to be
+ much simpler in design and more integrated with Markdown
+- Specific Databases:
+ - SQLite:
+ - sqlite boolean datatype converts False/True to 0/1 by default
+ - fixes to Date/Time (SLDate/SLTime) types; works as good as postgres
+ now [ticket:335]
+ - MS-SQL:
+ - fixes bug 261 (table reflection broken for MS-SQL case-sensitive
+ databases)
+ - can now specify port for pymssql
+ - introduces new "auto_identity_insert" option for auto-switching
+ between "SET IDENTITY_INSERT" mode when values specified for IDENTITY columns
+ - now supports multi-column foreign keys
+ - fix to reflecting date/datetime columns
+ - NCHAR and NVARCHAR type support added
+ - Oracle:
+ - Oracle has experimental support for cx_Oracle.TIMESTAMP, which requires
+ a setinputsizes() call on the cursor that is now enabled via the
+ 'auto_setinputsizes' flag to the oracle dialect.
+ - Firebird:
+ - aliases do not use "AS"
+ - correctly raises NoSuchTableError when reflecting non-existent table
+- Schema:
+ - a fair amount of cleanup to the schema package, removal of ambiguous
+ methods, methods that are no longer needed. slightly more constrained
+ useage, greater emphasis on explicitness
+ - the "primary_key" attribute of Table and other selectables becomes
+ a setlike ColumnCollection object; is ordered but not numerically
+ indexed. a comparison clause between two pks that are derived from the
+ same underlying tables (i.e. such as two Alias objects) can be generated
+ via table1.primary_key==table2.primary_key
+ - ForeignKey(Constraint) supports "use_alter=True", to create/drop a foreign key
+ via ALTER. this allows circular foreign key relationships to be set up.
+ - append_item() methods removed from Table and Column; preferably
+ construct Table/Column/related objects inline, but if needed use
+ append_column(), append_foreign_key(), append_constraint(), etc.
+ - table.create() no longer returns the Table object, instead has no
+ return value. the usual case is that tables are created via metadata,
+ which is preferable since it will handle table dependencies.
+ - added UniqueConstraint (goes at Table level), CheckConstraint
+ (goes at Table or Column level).
+ - index=False/unique=True on Column now creates a UniqueConstraint,
+ index=True/unique=False creates a plain Index,
+ index=True/unique=True on Column creates a unique Index. 'index'
+ and 'unique' keyword arguments to column are now boolean only; for
+ explcit names and groupings of indexes or unique constraints, use the
+ UniqueConstraint/Index constructs explicitly.
+ - added autoincrement=True to Column; will disable schema generation
+ of SERIAL/AUTO_INCREMENT/identity seq for postgres/mysql/mssql if
+ explicitly set to False
+ - TypeEngine objects now have methods to deal with copying and comparing
+ values of their specific type. Currently used by the ORM, see below.
+ - fixed condition that occurred during reflection when a primary key
+ column was explciitly overridden, where the PrimaryKeyConstraint would
+ get both the reflected and the programmatic column doubled up
+ - the "foreign_key" attribute on Column and ColumnElement in general
+ is deprecated, in favor of the "foreign_keys" list/set-based attribute,
+ which takes into account multiple foreign keys on one column.
+ "foreign_key" will return the first element in the "foreign_keys" list/set
+ or None if the list is empty.
+- Connections/Pooling/Execution:
+ - connection pool tracks open cursors and automatically closes them
+ if connection is returned to pool with cursors still opened. Can be
+ affected by options which cause it to raise an error instead, or to
+ do nothing. fixes issues with MySQL, others
+ - fixed bug where Connection wouldnt lose its Transaction
+ after commit/rollback
+ - added scalar() method to ComposedSQLEngine, ResultProxy
+ - ResultProxy will close() the underlying cursor when the ResultProxy
+ itself is closed. this will auto-close cursors for ResultProxy objects
+ that have had all their rows fetched (or had scalar() called).
+ - ResultProxy.fetchall() internally uses DBAPI fetchall() for better efficiency,
+ added to mapper iteration as well (courtesy Michael Twomey)
+- SQL Construction:
+ - changed "for_update" parameter to accept False/True/"nowait"
+ and "read", the latter two of which are interpreted only by
+ Oracle and Mysql [ticket:292]
+ - added extract() function to sql dialect
+ (SELECT extract(field FROM expr))
+ - BooleanExpression includes new "negate" argument to specify
+ the appropriate negation operator if one is available.
+ - calling a negation on an "IN" or "IS" clause will result in
+ "NOT IN", "IS NOT" (as opposed to NOT (x IN y)).
+ - Function objects know what to do in a FROM clause now. their
+ behavior should be the same, except now you can also do things like
+ select(['*'], from_obj=[func.my_function()]) to get multiple
+ columns from the result, or even use sql.column() constructs to name the
+ return columns [ticket:172]
+- ORM:
+ - attribute tracking modified to be more intelligent about detecting
+ changes, particularly with mutable types. TypeEngine objects now
+ take a greater role in defining how to compare two scalar instances,
+ including the addition of a MutableType mixin which is implemented by
+ PickleType. unit-of-work now tracks the "dirty" list as an expression
+ of all persistent objects where the attribute manager detects changes.
+ The basic issue thats fixed is detecting changes on PickleType
+ objects, but also generalizes type handling and "modified" object
+ checking to be more complete and extensible.
+ - a wide refactoring to "attribute loader" and "options" architectures.
+ ColumnProperty and PropertyLoader define their loading behaivor via switchable
+ "strategies", and MapperOptions no longer use mapper/property copying
+ in order to function; they are instead propagated via QueryContext
+ and SelectionContext objects at query/instances time.
+ All of the internal copying of mappers and properties that was used to handle
+ inheritance as well as options() has been removed; the structure
+ of mappers and properties is much simpler than before and is clearly laid out
+ in the new 'interfaces' module.
+ - related to the mapper/property overhaul, internal refactoring to
+ mapper instances() method to use a SelectionContext object to track
+ state during the operation.
+ SLIGHT API BREAKAGE: the append_result() and populate_instances()
+ methods on MapperExtension have a slightly different method signature
+ now as a result of the change; hoping that these methods are not
+ in widespread use as of yet.
+ - instances() method moved to Query now, backwards-compatible
+ version remains on Mapper.
+ - added contains_eager() MapperOption, used in conjunction with
+ instances() to specify properties that should be eagerly loaded
+ from the result set, using their plain column names by default, or translated
+ given an custom row-translation function.
+ - more rearrangements of unit-of-work commit scheme to better allow
+ dependencies within circular flushes to work properly...updated
+ task traversal/logging implementation
+ - polymorphic mappers (i.e. using inheritance) now produces INSERT
+ statements in order of tables across all inherited classes
+ [ticket:321]
+ - added an automatic "row switch" feature to mapping, which will
+ detect a pending instance/deleted instance pair with the same
+ identity key and convert the INSERT/DELETE to a single UPDATE
+ - "association" mappings simplified to take advantage of
+ automatic "row switch" feature
+ - "custom list classes" is now implemented via the "collection_class"
+ keyword argument to relation(). the old way still works but is
+ deprecated [ticket:212]
+ - added "viewonly" flag to relation(), allows construction of
+ relations that have no effect on the flush() process.
+ - added "lockmode" argument to base Query select/get functions,
+ including "with_lockmode" function to get a Query copy that has
+ a default locking mode. Will translate "read"/"update"
+ arguments into a for_update argument on the select side.
+ [ticket:292]
+ - implemented "version check" logic in Query/Mapper, used
+ when version_id_col is in effect and query.with_lockmode()
+ is used to get() an instance thats already loaded
+ - post_update behavior improved; does a better job at not
+ updating too many rows, updates only required columns
+ [ticket:208]
+ - adjustments to eager loading so that its "eager chain" is
+ kept separate from the normal mapper setup, thereby
+ preventing conflicts with lazy loader operation, fixes
+ [ticket:308]
+ - fix to deferred group loading
+ - session.flush() wont close a connection it opened [ticket:346]
+ - added "batch=True" flag to mapper; if False, save_obj
+ will fully save one object at a time including calls
+ to before_XXXX and after_XXXX
+ - added "column_prefix=None" argument to mapper; prepends the
+ given string (typically '_') to column-based attributes automatically
+ set up from the mapper's Table
+ - specifying joins in the from_obj argument of query.select() will
+ replace the main table of the query, if the table is somewhere within
+ the given from_obj. this makes it possible to produce custom joins and
+ outerjoins in queries without the main table getting added twice.
+ [ticket:315]
+ - eagerloading is adjusted to more thoughtfully attach its LEFT OUTER JOINs
+ to the given query, looking for custom "FROM" clauses that may have
+ already been set up.
+ - added join_to and outerjoin_to transformative methods to SelectResults,
+ to build up join/outerjoin conditions based on property names. also
+ added select_from to explicitly set from_obj parameter.
+ - removed "is_primary" flag from mapper.
+
+0.2.8
+- cleanup on connection methods + documentation. custom DBAPI
+arguments specified in query string, 'connect_args' argument
+to 'create_engine', or custom creation function via 'creator'
+function to 'create_engine'.
+- added "recycle" argument to Pool, is "pool_recycle" on create_engine,
+defaults to 3600 seconds; connections after this age will be closed and
+replaced with a new one, to handle db's that automatically close
+stale connections [ticket:274]
+- changed "invalidate" semantics with pooled connection; will
+instruct the underlying connection record to reconnect the next
+time its called. "invalidate" will also automatically be called
+if any error is thrown in the underlying call to connection.cursor().
+this will hopefully allow the connection pool to reconnect to a
+database that had been stopped and started without restarting
+the connecting application [ticket:121]
+- eesh ! the tutorial doctest was broken for quite some time.
+- add_property() method on mapper does a "compile all mappers"
+step in case the given property references a non-compiled mapper
+(as it did in the case of the tutorial !)
+- [ticket:277] check for pg sequence already existing before create
+- if a contextual session is established via MapperExtension.get_session
+(as it is using the sessioncontext plugin, etc), a lazy load operation
+will use that session by default if the parent object is not
+persistent with a session already.
+- lazy loads will not fire off for an object that does not have a
+database identity (why?
+see http://www.sqlalchemy.org/trac/wiki/WhyDontForeignKeysLoadData)
+- unit-of-work does a better check for "orphaned" objects that are
+part of a "delete-orphan" cascade, for certain conditions where the
+parent isnt available to cascade from.
+- mappers can tell if one of their objects is an "orphan" based
+on interactions with the attribute package. this check is based
+on a status flag maintained for each relationship
+when objects are attached and detached from each other.
+- it is now invalid to declare a self-referential relationship with
+"delete-orphan" (as the abovementioned check would make them impossible
+to save)
+- improved the check for objects being part of a session when the
+unit of work seeks to flush() them as part of a relationship..
+- [ticket:280] statement execution supports using the same BindParam
+object more than once in an expression; simplified handling of positional
+parameters. nice job by Bill Noon figuring out the basic idea.
+- postgres reflection moved to use pg_schema tables, can be overridden
+with use_information_schema=True argument to create_engine
+[ticket:60], [ticket:71]
+- added case_sensitive argument to MetaData, Table, Column, determines
+itself automatically based on if a parent schemaitem has a non-None
+setting for the flag, or if not, then whether the identifier name is all lower
+case or not. when set to True, quoting is applied to identifiers with mixed or
+uppercase identifiers. quoting is also applied automatically in all cases to
+identifiers that are known to be reserved words or contain other non-standard
+characters. various database dialects can override all of this behavior, but
+currently they are all using the default behavior. tested with postgres, mysql,
+sqlite, oracle. needs more testing with firebird, ms-sql. part of the ongoing
+work with [ticket:155]
+- unit tests updated to run without any pysqlite installed; pool
+test uses a mock DBAPI
+- urls support escaped characters in passwords [ticket:281]
+- added limit/offset to UNION queries (though not yet in oracle)
+- added "timezone=True" flag to DateTime and Time types. postgres
+so far will convert this to "TIME[STAMP] (WITH|WITHOUT) TIME ZONE",
+so that control over timezone presence is more controllable (psycopg2
+returns datetimes with tzinfo's if available, which can create confusion
+against datetimes that dont).
+- fix to using query.count() with distinct, **kwargs with SelectResults
+count() [ticket:287]
+- deregister Table from MetaData when autoload fails; [ticket:289]
+- import of py2.5s sqlite3 [ticket:293]
+- unicode fix for startswith()/endswith() [ticket:296]
+
+0.2.7
+- quoting facilities set up so that database-specific quoting can be
+turned on for individual table, schema, and column identifiers when
+used in all queries/creates/drops. Enabled via "quote=True" in
+Table or Column, as well as "quote_schema=True" in Table. Thanks to
+Aaron Spike for his excellent efforts.
+- assignmapper was setting is_primary=True, causing all sorts of mayhem
+by not raising an error when redundant mappers were set up, fixed
+- added allow_null_pks option to Mapper, allows rows where some
+primary key columns are null (i.e. when mapping to outer joins etc)
+- modifcation to unitofwork to not maintain ordering within the
+"new" list or within the UOWTask "objects" list; instead, new objects
+are tagged with an ordering identifier as they are registered as new
+with the session, and the INSERT statements are then sorted within the
+mapper save_obj. the INSERT ordering has basically been pushed all
+the way to the end of the flush cycle. that way the various sorts and
+organizations occuring within UOWTask (particularly the circular task
+sort) dont have to worry about maintaining order (which they werent anyway)
+- fixed reflection of foreign keys to autoload the referenced table
+if it was not loaded already
+- [ticket:256] - pass URL query string arguments to connect() function
+- [ticket:257] - oracle boolean type
+- custom primary/secondary join conditions in a relation *will* be propagated
+to backrefs by default. specifying a backref() will override this behavior.
+- better check for ambiguous join conditions in sql.Join; propagates to a
+better error message in PropertyLoader (i.e. relation()/backref()) for when
+the join condition can't be reasonably determined.
+- sqlite creates ForeignKeyConstraint objects properly upon table
+reflection.
+- adjustments to pool stemming from changes made for [ticket:224].
+overflow counter should only be decremented if the connection actually
+succeeded. added a test script to attempt testing this.
+- fixed mysql reflection of default values to be PassiveDefault
+- added reflected 'tinyint', 'mediumint' type to MS-SQL [ticket:263],
+[ticket:264]
+- SingletonThreadPool has a size and does a cleanup pass, so that
+only a given number of thread-local connections stay around (needed
+for sqlite applications that dispose of threads en masse)
+- fixed small pickle bug(s) with lazy loaders [ticket:265] [ticket:267]
+- fixed possible error in mysql reflection where certain versions
+return an array instead of string for SHOW CREATE TABLE call
+- fix to lazy loads when mapping to joins [changeset:1770]
+- all create()/drop() calls have a keyword argument of "connectable".
+"engine" is deprecated.
+- fixed ms-sql connect() to work with adodbapi
+- added "nowait" flag to Select()
+- inheritance check uses issubclass() instead of direct __mro__ check
+to make sure class A inherits from B, allowing mapper inheritance to more
+flexibly correspond to class inheritance [ticket:271]
+- SelectResults will use a subselect, when calling an aggregate (i.e.
+max, min, etc.) on a SelectResults that has an ORDER BY clause
+[ticket:252]
+- fixes to types so that database-specific types more easily used;
+fixes to mysql text types to work with this methodology
+[ticket:269]
+- some fixes to sqlite date type organization
+- added MSTinyInteger to MS-SQL [ticket:263]
+
+0.2.6
+- big overhaul to schema to allow truly composite primary and foreign
+key constraints, via new ForeignKeyConstraint and PrimaryKeyConstraint
+objects.
+Existing methods of primary/foreign key creation have not been changed
+but use these new objects behind the scenes. table creation
+and reflection is now more table oriented rather than column oriented.
+[ticket:76]
+- overhaul to MapperExtension calling scheme, wasnt working very well
+previously
+- tweaks to ActiveMapper, supports self-referential relationships
+- slight rearrangement to objectstore (in activemapper/threadlocal)
+so that the SessionContext is referenced by '.context' instead
+of subclassed directly.
+- activemapper will use threadlocal's objectstore if the mod is
+activated when activemapper is imported
+- small fix to URL regexp to allow filenames with '@' in them
+- fixes to Session expunge/update/etc...needs more cleanup.
+- select_table mappers *still* werent always compiling
+- fixed up Boolean datatype
+- added count()/count_by() to list of methods proxied by assignmapper;
+this also adds them to activemapper
+- connection exceptions wrapped in DBAPIError
+- ActiveMapper now supports autoloading column definitions from the
+database if you supply a __autoload__ = True attribute in your
+mapping inner-class. Currently this does not support reflecting
+any relationships.
+- deferred column load could screw up the connection status in
+a flush() under some circumstances, this was fixed
+- expunge() was not working with cascade, fixed.
+- potential endless loop in cascading operations fixed.
+- added "synonym()" function, applied to properties to have a
+propname the same as another, for the purposes of overriding props
+and allowing the original propname to be accessible in select_by().
+- fix to typing in clause construction which specifically helps
+type issues with polymorphic_union (CAST/ColumnClause propagates
+its type to proxy columns)
+- mapper compilation work ongoing, someday it'll work....moved
+around the initialization of MapperProperty objects to be after
+all mappers are created to better handle circular compilations.
+do_init() method is called on all properties now which are more
+aware of their "inherited" status if so.
+- eager loads explicitly disallowed on self-referential relationships, or
+relationships to an inheriting mapper (which is also self-referential)
+- reduced bind param size in query._get to appease the picky oracle
+[ticket:244]
+- added 'checkfirst' argument to table.create()/table.drop(), as
+well as table.exists() [ticket:234]
+- some other ongoing fixes to inheritance [ticket:245]
+- attribute/backref/orphan/history-tracking tweaks as usual...
+
+0.2.5
+- fixed endless loop bug in select_by(), if the traversal hit
+two mappers that referenced each other
+- upgraded all unittests to insert './lib/' into sys.path,
+working around new setuptools PYTHONPATH-killing behavior
+- further fixes with attributes/dependencies/etc....
+- improved error handling for when DynamicMetaData is not connected
+- MS-SQL support largely working (tested with pymssql)
+- ordering of UPDATE and DELETE statements within groups is now
+in order of primary key values, for more deterministic ordering
+- after_insert/delete/update mapper extensions now called per object,
+not per-object-per-table
+- further fixes/refactorings to mapper compilation
+
+0.2.4
+- try/except when the mapper sets init.__name__ on a mapped class,
+supports python 2.3
+- fixed bug where threadlocal engine would still autocommit
+despite a transaction in progress
+- lazy load and deferred load operations require the parent object
+to be in a Session to do the operation; whereas before the operation
+would just return a blank list or None, it now raises an exception.
+- Session.update() is slightly more lenient if the session to which
+the given object was formerly attached to was garbage collected;
+otherwise still requires you explicitly remove the instance from
+the previous Session.
+- fixes to mapper compilation, checking for more error conditions
+- small fix to eager loading combined with ordering/limit/offset
+- utterly remarkable: added a single space between 'CREATE TABLE'
+and '(<the rest of it>' since *thats how MySQL indicates a non-
+reserved word tablename.....* [ticket:206]
+- more fixes to inheritance, related to many-to-many relations
+properly saving
+- fixed bug when specifying explicit module to mysql dialect
+- when QueuePool times out it raises a TimeoutError instead of
+erroneously making another connection
+- Queue.Queue usage in pool has been replaced with a locally
+modified version (works in py2.3/2.4!) that uses a threading.RLock
+for a mutex. this is to fix a reported case where a ConnectionFairy's
+__del__() method got called within the Queue's get() method, which
+then returns its connection to the Queue via the the put() method,
+causing a reentrant hang unless threading.RLock is used.
+- postgres will not place SERIAL keyword on a primary key column
+if it has a foreign key constraint
+- cursor() method on ConnectionFairy allows db-specific extension
+arguments to be propagated [ticket:221]
+- lazy load bind params properly propagate column type [ticket:225]
+- new MySQL types: MSEnum, MSTinyText, MSMediumText, MSLongText, etc.
+more support for MS-specific length/precision params in numeric types
+patch courtesy Mike Bernson
+- some fixes to connection pool invalidate() [ticket:224]
+
+0.2.3
+- overhaul to mapper compilation to be deferred. this allows mappers
+to be constructed in any order, and their relationships to each
+other are compiled when the mappers are first used.
+- fixed a pretty big speed bottleneck in cascading behavior particularly
+when backrefs were in use
+- the attribute instrumentation module has been completely rewritten; its
+now a large degree simpler and clearer, slightly faster. the "history"
+of an attribute is no longer micromanaged with each change and is
+instead part of a "CommittedState" object created when the
+instance is first loaded. HistoryArraySet is gone, the behavior of
+list attributes is now more open ended (i.e. theyre not sets anymore).
+- py2.4 "set" construct used internally, falls back to sets.Set when
+"set" not available/ordering is needed.
+- fix to transaction control, so that repeated rollback() calls
+dont fail (was failing pretty badly when flush() would raise
+an exception in a larger try/except transaction block)
+- "foreignkey" argument to relation() can also be a list. fixed
+auto-foreignkey detection [ticket:151]
+- fixed bug where tables with schema names werent getting indexed in
+the MetaData object properly
+- fixed bug where Column with redefined "key" property wasnt getting
+type conversion happening in the ResultProxy [ticket:207]
+- fixed 'port' attribute of URL to be an integer if present
+- fixed old bug where if a many-to-many table mapped as "secondary"
+had extra columns, delete operations didnt work
+- bugfixes for mapping against UNION queries
+- fixed incorrect exception class thrown when no DB driver present
+- added NonExistentTable exception thrown when reflecting a table
+that doesnt exist [ticket:138]
+- small fix to ActiveMapper regarding one-to-one backrefs, other
+refactorings
+- overridden constructor in mapped classes gets __name__ and
+__doc__ from the original class
+- fixed small bug in selectresult.py regarding mapper extension
+[ticket:200]
+- small tweak to cascade_mappers, not very strongly supported
+function at the moment
+- some fixes to between(), column.between() to propagate typing
+information better [ticket:202]
+- if an object fails to be constructed, is not added to the
+session [ticket:203]
+- CAST function has been made into its own clause object with
+its own compilation function in ansicompiler; allows MySQL
+to silently ignore most CAST calls since MySQL
+seems to only support the standard CAST syntax with Date types.
+MySQL-compatible CAST support for strings, ints, etc. a TODO
+
+0.2.2
+- big improvements to polymorphic inheritance behavior, enabling it
+to work with adjacency list table structures [ticket:190]
+- major fixes and refactorings to inheritance relationships overall,
+more unit tests
+- fixed "echo_pool" flag on create_engine()
+- fix to docs, removed incorrect info that close() is unsafe to use
+with threadlocal strategy (its totally safe !)
+- create_engine() can take URLs as string or unicode [ticket:188]
+- firebird support partially completed;
+thanks to James Ralston and Brad Clements for their efforts.
+- Oracle url translation was broken, fixed, will feed host/port/sid
+into cx_oracle makedsn() if 'database' field is present, else uses
+straight TNS name from the 'host' field
+- fix to using unicode criterion for query.get()/query.load()
+- count() function on selectables now uses table primary key or
+first column instead of "1" for criterion, also uses label "rowcount"
+instead of "count".
+- got rudimental "mapping to multiple tables" functionality cleaned up,
+more correctly documented
+- restored global_connect() function, attaches to a DynamicMetaData
+instance called "default_metadata". leaving MetaData arg to Table
+out will use the default metadata.
+- fixes to session cascade behavior, entity_name propigation
+- reorganized unittests into subdirectories
+- more fixes to threadlocal connection nesting patterns
+
+0.2.1
+- "pool" argument to create_engine() properly propagates
+- fixes to URL, raises exception if not parsed, does not pass blank
+fields along to the DB connect string (a string such as
+user:host@/db was breaking on postgres)
+- small fixes to Mapper when it inserts and tries to get
+new primary key values back
+- rewrote half of TLEngine, the ComposedSQLEngine used with
+'strategy="threadlocal"'. it now properly implements engine.begin()/
+engine.commit(), which nest fully with connection.begin()/trans.commit().
+added about six unittests.
+- major "duh" in pool.Pool, forgot to put back the WeakValueDictionary.
+unittest which was supposed to check for this was also silently missing
+it. fixed unittest to ensure that ConnectionFairy properly falls out
+of scope.
+- placeholder dispose() method added to SingletonThreadPool, doesnt
+do anything yet
+- rollback() is automatically called when an exception is raised,
+but only if theres no transaction in process (i.e. works more like
+autocommit).
+- fixed exception raise in sqlite if no sqlite module present
+- added extra example detail for association object doc
+- Connection adds checks for already being closed
+
+0.2.0
+- overhaul to Engine system so that what was formerly the SQLEngine
+is now a ComposedSQLEngine which consists of a variety of components,
+including a Dialect, ConnectionProvider, etc. This impacted all the
+db modules as well as Session and Mapper.
+- create_engine now takes only RFC-1738-style strings:
+driver://user:password@host:port/database
+- total rewrite of connection-scoping methodology, Connection objects
+can now execute clause elements directly, added explicit "close" as
+well as support throughout Engine/ORM to handle closing properly,
+no longer relying upon __del__ internally to return connections
+to the pool [ticket:152].
+- overhaul to Session interface and scoping. uses hibernate-style
+methods, including query(class), save(), save_or_update(), etc.
+no threadlocal scope is installed by default. Provides a binding
+interface to specific Engines and/or Connections so that underlying
+Schema objects do not need to be bound to an Engine. Added a basic
+SessionTransaction object that can simplistically aggregate transactions
+across multiple engines.
+- overhaul to mapper's dependency and "cascade" behavior; dependency logic
+factored out of properties.py into a separate module "dependency.py".
+"cascade" behavior is now explicitly controllable, proper implementation
+of "delete", "delete-orphan", etc. dependency system can now determine at
+flush time if a child object has a parent or not so that it makes better
+decisions on how that child should be updated in the DB with regards to deletes.
+- overhaul to Schema to build upon MetaData object instead of an Engine.
+Entire SQL/Schema system can be used with no Engines whatsoever, executed
+solely by an explicit Connection object. the "bound" methodlogy exists via the
+BoundMetaData for schema objects. ProxyEngine is generally not needed
+anymore and is replaced by DynamicMetaData.
+- true polymorphic behavior implemented, fixes [ticket:167]
+- "oid" system has been totally moved into compile-time behavior;
+if they are used in an order_by where they are not available, the order_by
+doesnt get compiled, fixes [ticket:147]
+- overhaul to packaging; "mapping" is now "orm", "objectstore" is now
+"session", the old "objectstore" namespace gets loaded in via the
+"threadlocal" mod if used
+- mods now called in via "import <modname>". extensions favored over
+mods as mods are globally-monkeypatching
+- fix to add_property so that it propagates properties to inheriting
+mappers [ticket:154]
+- backrefs create themselves against primary mapper of its originating
+property, priamry/secondary join arguments can be specified to override.
+helps their usage with polymorphic mappers
+- "table exists" function has been implemented [ticket:31]
+- "create_all/drop_all" added to MetaData object [ticket:98]
+- improvements and fixes to topological sort algorithm, as well as more
+unit tests
+- tutorial page added to docs which also can be run with a custom doctest
+runner to ensure its properly working. docs generally overhauled to
+deal with new code patterns
+- many more fixes, refactorings.
+- migration guide is available on the Wiki at
+http://www.sqlalchemy.org/trac/wiki/02Migration
+
+0.1.7
+- some fixes to topological sort algorithm
+- added DISTINCT ON support to Postgres (just supply distinct=[col1,col2..])
+- added __mod__ (% operator) to sql expressions
+- "order_by" mapper property inherited from inheriting mapper
+- fix to column type used when mapper UPDATES/DELETEs
+- with convert_unicode=True, reflection was failing, has been fixed
+- types types types! still werent working....have to use TypeDecorator again :(
+- mysql binary type converts array output to buffer, fixes PickleType
+- fixed the attributes.py memory leak once and for all
+- unittests are qualified based on the databases that support each one
+- fixed bug where column defaults would clobber VALUES clause of insert objects
+- fixed bug where table def w/ schema name would force engine connection
+- fix for parenthesis to work correctly with subqueries in INSERT/UPDATE
+- HistoryArraySet gets extend() method
+- fixed lazyload support for other comparison operators besides =
+- lazyload fix where two comparisons in the join condition point to the
+samem column
+- added "construct_new" flag to mapper, will use __new__ to create instances
+instead of __init__ (standard in 0.2)
+- added selectresults.py to SVN, missed it last time
+- tweak to allow a many-to-many relationship from a table to itself via
+an association table
+- small fix to "translate_row" function used by polymorphic example
+- create_engine uses cgi.parse_qsl to read query string (out the window in 0.2)
+- tweaks to CAST operator
+- fixed function names LOCAL_TIME/LOCAL_TIMESTAMP -> LOCALTIME/LOCALTIMESTAMP
+- fixed order of ORDER BY/HAVING in compile
+
+0.1.6
+- support for MS-SQL added courtesy Rick Morrison, Runar Petursson
+- the latest SQLSoup from J. Ellis
+- ActiveMapper has preliminary support for inheritance (Jeff Watkins)
+- added a "mods" system which allows pluggable modules that modify/augment
+core functionality, using the function "install_mods(*modnames)".
+- added the first "mod", SelectResults, which modifies mapper selects to
+return generators that turn ranges into LIMIT/OFFSET queries (Jonas Borgstr?- factored out querying capabilities of Mapper into a separate Query object
+which is Session-centric. this improves the performance of mapper.using(session)
+and makes other things possible.
+- objectstore/Session refactored, the official way to save objects is now
+via the flush() method. The begin/commit functionality of Session is factored
+into LegacySession which is still established as the default behavior, until
+the 0.2 series.
+- types system is bound to an engine at query compile time, not schema
+construction time. this simplifies the types system as well as the ProxyEngine.
+- added 'version_id' keyword argument to mapper. this keyword should reference a
+Column object with type Integer, preferably non-nullable, which will be used on
+the mapped table to track version numbers. this number is incremented on each
+save operation and is specifed in the UPDATE/DELETE conditions so that it
+factors into the returned row count, which results in a ConcurrencyError if the
+value received is not the expected count.
+- added 'entity_name' keyword argument to mapper. a mapper is now associated
+with a class via the class object as well as an optional entity_name parameter,
+which is a string defaulting to None. any number of primary mappers can be
+created for a class, qualified by the entity name. instances of those classes
+will issue all of their load and save operations through their
+entity_name-qualified mapper, and maintain separate a identity in the identity
+map for an otherwise equilvalent object.
+- overhaul to the attributes system. code has been clarified, and also fixed to
+support proper polymorphic behavior on object attributes.
+- added "for_update" flag to Select objects
+- some fixes for backrefs
+- fix for postgres1 DateTime type
+- documentation pages mostly switched over to Markdown syntax
+
+0.1.5
+- added SQLSession concept to SQLEngine. this object keeps track of retrieving a
+connection from the connection pool as well as an in-progress transaction.
+methods push_session() and pop_session() added to SQLEngine which push/pop a new
+SQLSession onto the engine, allowing operation upon a second connection "nested"
+within the previous one, allowing nested transactions. Other tricks are sure to
+come later regarding SQLSession.
+- added nest_on argument to objectstore.Session. This is a single SQLEngine or
+list of engines for which push_session()/pop_session() will be called each time
+this Session becomes the active session (via objectstore.push_session() or
+equivalent). This allows a unit of work Session to take advantage of the nested
+transaction feature without explicitly calling push_session/pop_session on the
+engine.
+- factored apart objectstore/unitofwork to separate "Session scoping" from
+"uow commit heavy lifting"
+- added populate_instance() method to MapperExtension. allows an extension to
+modify the population of object attributes. this method can call the
+populate_instance() method on another mapper to proxy the attribute population
+from one mapper to another; some row translation logic is also built in to help
+with this.
+- fixed Oracle8-compatibility "use_ansi" flag which converts JOINs to
+comparisons with the = and (+) operators, passes basic unittests
+- tweaks to Oracle LIMIT/OFFSET support
+- Oracle reflection uses ALL_** views instead of USER_** to get larger
+list of stuff to reflect from
+- fixes to Oracle foreign key reflection [ticket:105]
+- objectstore.commit(obj1, obj2,...) adds an extra step to seek out private
+relations on properties and delete child objects, even though its not a global
+commit
+- lots and lots of fixes to mappers which use inheritance, strengthened the
+concept of relations on a mapper being made towards the "local" table for that
+mapper, not the tables it inherits. allows more complex compositional patterns
+to work with lazy/eager loading.
+- added support for mappers to inherit from others based on the same table,
+just specify the same table as that of both parent/child mapper.
+- some minor speed improvements to the attributes system with regards to
+instantiating and populating new objects.
+- fixed MySQL binary unit test
+- INSERTs can receive clause elements as VALUES arguments, not just literal
+values
+- support for calling multi-tokened functions, i.e. schema.mypkg.func()
+- added J. Ellis' SQLSoup module to extensions package
+- added "polymorphic" examples illustrating methods to load multiple object types
+from one mapper, the second of which uses the new populate_instance() method.
+small improvements to mapper, UNION construct to help the examples along
+- improvements/fixes to session.refresh()/session.expire() (which may have
+been called "invalidate" earlier..)
+- added session.expunge() which totally removes an object from the current
+session
+- added *args, **kwargs pass-thru to engine.transaction(func) allowing easier
+creation of transactionalizing decorator functions
+- added iterator interface to ResultProxy: "for row in result:..."
+- added assertion to tx = session.begin(); tx.rollback(); tx.begin(), i.e. cant
+use it after a rollback()
+- added date conversion on bind parameter fix to SQLite enabling dates to
+work with pysqlite1
+- improvements to subqueries to more intelligently construct their FROM
+clauses [ticket:116]
+- added PickleType to types.
+- fixed two bugs with column labels with regards to bind parameters: bind param
+keynames they are now generated from a column "label" in all relevant cases to
+take advantage of excess-name-length rules, and checks for a peculiar collision
+against a column named the same as "tablename_colname" added
+- major overhaul to unit of work documentation, other documentation sections.
+- fixed attributes bug where if an object is committed, its lazy-loaded list got
+blown away if it hadnt been loaded
+- added unique_connection() method to engine, connection pool to return a
+connection that is not part of the thread-local context or any current
+transaction
+- added invalidate() function to pooled connection. will remove the connection
+from the pool. still need work for engines to auto-reconnect to a stale DB
+though.
+- added distinct() function to column elements so you can do
+func.count(mycol.distinct())
+- added "always_refresh" flag to Mapper, creates a mapper that will always
+refresh the attributes of objects it gets/selects from the DB, overwriting any
+changes made.
+
+0.1.4
+- create_engine() now uses genericized parameters; host/hostname,
+db/dbname/database, password/passwd, etc. for all engine connections. makes
+ engine URIs much more "universal"
+- added support for SELECT statements embedded into a column clause, using the
+flag "scalar=True"
+- another overhaul to EagerLoading when used in conjunction with mappers that
+inherit; improvements to eager loads figuring out their aliased queries
+correctly, also relations set up against a mapper with inherited mappers will
+create joins against the table that is specific to the mapper itself (i.e. and
+not any tables that are inherited/are further down the inheritance chain),
+this can be overridden by using custom primary/secondary joins.
+- added J.Ellis patch to mapper.py so that selectone() throws an exception
+if query returns more than one object row, selectfirst() to not throw the
+exception. also adds selectfirst_by (synonymous with get_by) and selectone_by
+- added onupdate parameter to Column, will exec SQL/python upon an update
+statement.Also adds "for_update=True" to all DefaultGenerator subclasses
+- added support for Oracle table reflection contributed by Andrija Zaric;
+still some bugs to work out regarding composite primary keys/dictionary selection
+- checked in an initial Firebird module, awaiting testing.
+- added sql.ClauseParameters dictionary object as the result for
+compiled.get_params(), does late-typeprocessing of bind parameters so
+that the original values are easier to access
+- more docs for indexes, column defaults, connection pooling, engine construction
+- overhaul to the construction of the types system. uses a simpler inheritance
+pattern so that any of the generic types can be easily subclassed, with no need
+for TypeDecorator.
+- added "convert_unicode=False" parameter to SQLEngine, will cause all String
+types to perform unicode encoding/decoding (makes Strings act like Unicodes)
+- added 'encoding="utf8"' parameter to engine. the given encoding will be
+used for all encode/decode calls within Unicode types as well as Strings
+when convert_unicode=True.
+- improved support for mapping against UNIONs, added polymorph.py example
+to illustrate multi-class mapping against a UNION
+- fix to SQLite LIMIT/OFFSET syntax
+- fix to Oracle LIMIT syntax
+- added backref() function, allows backreferences to have keyword arguments
+that will be passed to the backref.
+- Sequences and ColumnDefault objects can do execute()/scalar() standalone
+- SQL functions (i.e. func.foo()) can do execute()/scalar() standalone
+- fix to SQL functions so that the ANSI-standard functions, i.e. current_timestamp
+etc., do not specify parenthesis. all other functions do.
+- added settattr_clean and append_clean to SmartProperty, which set
+attributes without triggering a "dirty" event or any history. used as:
+myclass.prop1.setattr_clean(myobject, 'hi')
+- improved support to column defaults when used by mappers; mappers will pull
+pre-executed defaults from statement's executed bind parameters
+(pre-conversion) to populate them into a saved object's attributes; if any
+PassiveDefaults have fired off, will instead post-fetch the row from the DB to
+populate the object.
+- added 'get_session().invalidate(*obj)' method to objectstore, instances will
+refresh() themselves upon the next attribute access.
+- improvements to SQL func calls including an "engine" keyword argument so
+they can be execute()d or scalar()ed standalone, also added func accessor to
+SQLEngine
+- fix to MySQL4 custom table engines, i.e. TYPE instead of ENGINE
+- slightly enhanced logging, includes timestamps and a somewhat configurable
+formatting system, in lieu of a full-blown logging system
+- improvements to the ActiveMapper class from the TG gang, including
+many-to-many relationships
+- added Double and TinyInt support to mysql
+
+0.1.3
+- completed "post_update" feature, will add a second update statement before
+inserts and after deletes in order to reconcile a relationship without any
+dependencies being created; used when persisting two rows that are dependent
+on each other
+- completed mapper.using(session) function, localized per-object Session
+functionality; objects can be declared and manipulated as local to any
+user-defined Session
+- fix to Oracle "row_number over" clause with multiple tables
+- mapper.get() was not selecting multiple-keyed objects if the mapper's table was a join,
+such as in an inheritance relationship, this is fixed.
+- overhaul to sql/schema packages so that the sql package can run all on its own,
+producing selects, inserts, etc. without any engine dependencies. builds upon
+new TableClause/ColumnClause lexical objects. Schema's Table/Column objects
+are the "physical" subclasses of them. simplifies schema/sql relationship,
+extensions (like proxyengine), and speeds overall performance by a large margin.
+removes the entire getattr() behavior that plagued 0.1.1.
+- refactoring of how the mapper "synchronizes" data between two objects into a
+separate module, works better with properties attached to a mapper that has an
+additional inheritance relationship to one of the related tables, also the same
+methodology used to synchronize parent/child objects now used by mapper to
+synchronize between inherited and inheriting mappers.
+- made objectstore "check for out-of-identitymap" more aggressive, will perform the
+check when object attributes are modified or the object is deleted
+- Index object fully implemented, can be constructed standalone, or via
+"index" and "unique" arguments on Columns.
+- added "convert_unicode" flag to SQLEngine, will treat all String/CHAR types
+as Unicode types, with raw-byte/utf-8 translation on the bind parameter and
+result set side.
+- postgres maintains a list of ANSI functions that must have no parenthesis so
+function calls with no arguments work consistently
+- tables can be created with no engine specified. this will default their engine
+to a module-scoped "default engine" which is a ProxyEngine. this engine can
+be connected via the function "global_connect".
+- added "refresh(*obj)" method to objectstore / Session to reload the attributes of
+any set of objects from the database unconditionally
+
+0.1.2
+- fixed a recursive call in schema that was somehow running 994 times then returning
+normally. broke nothing, slowed down everything. thanks to jpellerin for finding this.
+
+0.1.1
+- small fix to Function class so that expressions with a func.foo() use the type of the
+Function object (i.e. the left side) as the type of the boolean expression, not the
+other side which is more of a moving target (changeset 1020).
+- creating self-referring mappers with backrefs slightly easier (but still not that easy -
+changeset 1019)
+- fixes to one-to-one mappings (changeset 1015)
+- psycopg1 date/time issue with None fixed (changeset 1005)
+- two issues related to postgres, which doesnt want to give you the "lastrowid"
+since oids are deprecated:
+ * postgres database-side defaults that are on primary key cols *do* execute
+explicitly beforehand, even though thats not the idea of a PassiveDefault. this is
+because sequences on columns get reflected as PassiveDefaults, but need to be explicitly
+executed on a primary key col so we know what we just inserted.
+ * if you did add a row that has a bunch of database-side defaults on it,
+and the PassiveDefault thing was working the old way, i.e. they just execute on
+the DB side, the "cant get the row back without an OID" exception that occurred
+also will not happen unless someone (usually the ORM) explicitly asks for it.
+- fixed a glitch with engine.execute_compiled where it was making a second
+ResultProxy that just got thrown away.
+- began to implement newer logic in object properities. you can now say
+myclass.attr.property, which will give you the PropertyLoader corresponding to that
+attribute, i.e. myclass.mapper.props['attr']
+- eager loading has been internally overhauled to use aliases at all times. more
+complicated chains of eager loads can now be created without any need for explicit
+"use aliases"-type instructions. EagerLoader code is also much simpler now.
+- a new somewhat experimental flag "use_update" added to relations, indicates that
+this relationship should be handled by a second UPDATE statement, either after a
+primary INSERT or before a primary DELETE. handles circular row dependencies.
+- added exceptions module, all raised exceptions (except for some
+KeyError/AttributeError exceptions) descend from these classes.
+- fix to date types with MySQL, returned timedelta converted to datetime.time
+- two-phase objectstore.commit operations (i.e. begin/commit) now return a
+transactional object (SessionTrans), to more clearly indicate transaction boundaries.
+- Index object with create/drop support added to schema
+- fix to postgres, where it will explicitly pre-execute a PassiveDefault on a table
+if it is a primary key column, pursuant to the ongoing "we cant get inserted rows
+back from postgres" issue
+- change to information_schema query that gets back postgres table defs, now
+uses explicit JOIN keyword, since one user had faster performance with 8.1
+- fix to engine.process_defaults so it works correctly with a table that has
+different column name/column keys (changset 982)
+- a column can only be attached to one table - this is now asserted
+- postgres time types descend from Time type
+- fix to alltests so that it runs types test (now named testtypes)
+- fix to Join object so that it correctly exports its foreign keys (cs 973)
+- creating relationships against mappers that use inheritance fixed (cs 973)
+
+0.1.0
+initial release
+
+