From: Mike Bayer Date: Mon, 15 Jun 2009 22:11:08 +0000 (+0000) Subject: split CHANGES into CHANGES and CHANGES_PRE_05, since I would like CHANGES to be viewa... X-Git-Tag: rel_0_5_5~17 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=44b6977cf4eab8e91ac617efd9bc37dbf86101b4;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git split CHANGES into CHANGES and CHANGES_PRE_05, since I would like CHANGES to be viewable in trac --- diff --git a/CHANGES b/CHANGES index 0259b1105d..638c5e356e 100644 --- a/CHANGES +++ b/CHANGES @@ -1748,4104 +1748,5 @@ full changes between 0.4/0.5. - 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() - expression operator and collate(, ) 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=", which - is set as the escape character using the syntax "x LIKE y - ESCAPE ''" [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==)), evaluate the actual - primary key value of at execution time so that - the autoflush step of the Query can complete, thereby - populating the PK value of in the case that - 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() 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. "'%' || " 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() 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 "_", - 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: - . - - 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 %%" 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] - - - ._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 , syntax - instead of LIMIT OFFSET 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 y) produces NOT (x 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== for scalar attributes, - Class.prop.contains() and Class.prop.any() 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=". When used - with "aliased=True", the id can be referenced by add_entity(cls, - id=) 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.(), 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[] [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 = -- 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().reset_joinpoint().\ - join(['a', 'c']).filter().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 .in_() (i.e. with no arguments) will return - "CASE WHEN ( 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. 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(=) -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. 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 [].", 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[]/row. - - 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. 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_...), 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..", - instance-level logging under "sqlalchemy...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 '(' 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 ". 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 diff --git a/CHANGES_PRE_05 b/CHANGES_PRE_05 new file mode 100644 index 0000000000..6291375d62 --- /dev/null +++ b/CHANGES_PRE_05 @@ -0,0 +1,4107 @@ +-*- 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() + expression operator and collate(, ) 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=", which + is set as the escape character using the syntax "x LIKE y + ESCAPE ''" [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==)), evaluate the actual + primary key value of at execution time so that + the autoflush step of the Query can complete, thereby + populating the PK value of in the case that + 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() 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. "'%' || " 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() 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 "_", + 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: + . + + 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 %%" 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] + + - ._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 , syntax + instead of LIMIT OFFSET 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 y) produces NOT (x 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== for scalar attributes, + Class.prop.contains() and Class.prop.any() 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=". When used + with "aliased=True", the id can be referenced by add_entity(cls, + id=) 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.(), 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[] [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 = +- 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().reset_joinpoint().\ + join(['a', 'c']).filter().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 .in_() (i.e. with no arguments) will return + "CASE WHEN ( 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. 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(=) -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. 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 [].", 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[]/row. + - 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. 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_...), 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..", + instance-level logging under "sqlalchemy...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 '(' 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 ". 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 + +