From 690f484f5c172cbef735fe5050bd562c41d7f746 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 20 Oct 2012 18:28:02 -0400 Subject: [PATCH] - move all CHANGES files into the sphinx docs. this is rudimental now but puts the changelog in a more data driven format, so that we can begin linking version directives with them as well as with migration documents, once those are also moved into sphinx. --- CHANGES | 6699 +------------------------- CHANGES_PRE_06 | 6343 ------------------------ doc/build/builder/__init__.py | 3 +- doc/build/builder/changelog.py | 268 ++ doc/build/builder/dialect_info.py | 2 - doc/build/changelog/changelog_01.rst | 975 ++++ doc/build/changelog/changelog_02.rst | 1187 +++++ doc/build/changelog/changelog_03.rst | 2928 +++++++++++ doc/build/changelog/changelog_04.rst | 4198 ++++++++++++++++ doc/build/changelog/changelog_05.rst | 3775 +++++++++++++++ doc/build/changelog/changelog_06.rst | 4762 ++++++++++++++++++ doc/build/changelog/changelog_07.rst | 4435 +++++++++++++++++ doc/build/changelog/changelog_08.rst | 1298 +++++ doc/build/changelog/index.rst | 35 + doc/build/contents.rst | 1 + doc/build/index.rst | 3 +- 16 files changed, 23872 insertions(+), 13040 deletions(-) delete mode 100644 CHANGES_PRE_06 create mode 100644 doc/build/builder/changelog.py create mode 100644 doc/build/changelog/changelog_01.rst create mode 100644 doc/build/changelog/changelog_02.rst create mode 100644 doc/build/changelog/changelog_03.rst create mode 100644 doc/build/changelog/changelog_04.rst create mode 100644 doc/build/changelog/changelog_05.rst create mode 100644 doc/build/changelog/changelog_06.rst create mode 100644 doc/build/changelog/changelog_07.rst create mode 100644 doc/build/changelog/changelog_08.rst create mode 100644 doc/build/changelog/index.rst diff --git a/CHANGES b/CHANGES index f1301ba281..dbf3779046 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6703 +1,16 @@ --*- coding: utf-8; fill-column: 68 -*- - -======= -CHANGES -======= - -0.8.0b1 -======= -Changes noted below are specific to version 0.8. -For changes that are in both 0.7 and 0.8, see below -underneath "0.7.xx". - -- general - - SQLAlchemy 0.8 now targets Python 2.5 and - above. Python 2.4 is no longer supported. - - - [removed] The "sqlalchemy.exceptions" - synonym for "sqlalchemy.exc" is removed - fully. [ticket:2433] - -- orm - - [removed] The legacy "mutable" system of the - ORM, including the MutableType class as well - as the mutable=True flag on PickleType - and postgresql.ARRAY has been removed. - In-place mutations are detected by the ORM - using the sqlalchemy.ext.mutable extension, - introduced in 0.7. The removal of MutableType - and associated constructs removes a great - deal of complexity from SQLAlchemy's internals. - The approach performed poorly as it would incur - a scan of the full contents of the Session - when in use. [ticket:2442] - - - [moved] The InstrumentationManager interface - and the entire related system of alternate - class implementation is now moved out - to sqlalchemy.ext.instrumentation. This is - a seldom used system that adds significant - complexity and overhead to the mechanics of - class instrumentation. The new architecture - allows it to remain unused until - InstrumentationManager is actually imported, - at which point it is bootstrapped into - the core. - - - [feature] Major rewrite of relationship() - internals now allow join conditions which - include columns pointing to themselves - within composite foreign keys. A new - API for very specialized primaryjoin conditions - is added, allowing conditions based on - SQL functions, CAST, etc. to be handled - by placing the annotation functions - remote() and foreign() inline within the - expression when necessary. Previous recipes - using the semi-private _local_remote_pairs - approach can be upgraded to this new - approach. [ticket:1401] - - - [bug] ORM will perform extra effort to determine - that an FK dependency between two tables is - not significant during flush if the tables - are related via joined inheritance and the FK - dependency is not part of the inherit_condition, - saves the user a use_alter directive. - [ticket:2527] - - - [feature] New standalone function with_polymorphic() - provides the functionality of query.with_polymorphic() - in a standalone form. It can be applied to any - entity within a query, including as the target - of a join in place of the "of_type()" modifier. - [ticket:2333] - - - [feature] The of_type() construct on attributes - now accepts aliased() class constructs as well - as with_polymorphic constructs, and works with - query.join(), any(), has(), and also - eager loaders subqueryload(), joinedload(), - contains_eager() - [ticket:2438] [ticket:1106] - - - [feature] Improvements to event listening for - mapped classes allows that unmapped classes - can be specified for instance- and mapper-events. - The established events will be automatically - set up on subclasses of that class when the - propagate=True flag is passed, and the - events will be set up for that class itself - if and when it is ultimately mapped. - [ticket:2585] - - - [bug] The instrumentation events class_instrument(), - class_uninstrument(), and attribute_instrument() - will now fire off only for descendant classes - of the class assigned to listen(). Previously, - an event listener would be assigned to listen - for all classes in all cases regardless of the - "target" argument passed. [ticket:2590] - - - [bug] with_polymorphic() produces JOINs - in the correct order and with correct inheriting - tables in the case of sending multi-level - subclasses in an arbitrary order or with - intermediary classes missing. [ticket:1900] - - - [feature] The "deferred declarative - reflection" system has been moved into the - declarative extension itself, using the - new DeferredReflection class. This - class is now tested with both single - and joined table inheritance use cases. - [ticket:2485] - - - [feature] Added new core function "inspect()", - which serves as a generic gateway to - introspection into mappers, objects, - others. The Mapper and InstanceState - objects have been enhanced with a public - API that allows inspection of mapped - attributes, including filters for column-bound - or relationship-bound properties, inspection - of current object state, history of - attributes, etc. [ticket:2208] - - - [feature] Calling rollback() within a - session.begin_nested() will now only expire - those objects that had net changes within the - scope of that transaction, that is objects which - were dirty or were modified on a flush. This - allows the typical use case for begin_nested(), - that of altering a small subset of objects, to - leave in place the data from the larger enclosing - set of objects that weren't modified in - that sub-transaction. [ticket:2452] - - - [feature] Added utility feature - Session.enable_relationship_loading(), - supersedes relationship.load_on_pending. - Both features should be avoided, however. - [ticket:2372] - - - [feature] Added support for .info dictionary argument to - column_property(), relationship(), composite(). - All MapperProperty classes have an auto-creating .info - dict available overall. - - - [feature] Adding/removing None from a mapped collection - now generates attribute events. Previously, a None - append would be ignored in some cases. Related - to [ticket:2229]. - - - [feature] The presence of None in a mapped collection - now raises an error during flush. Previously, - None values in collections would be silently ignored. - [ticket:2229] - - - [feature] The Query.update() method is now - more lenient as to the table - being updated. Plain Table objects are better - supported now, and additional a joined-inheritance - subclass may be used with update(); the subclass - table will be the target of the update, - and if the parent table is referenced in the - WHERE clause, the compiler will call upon - UPDATE..FROM syntax as allowed by the dialect - to satisfy the WHERE clause. MySQL's multi-table - update feature is also supported if columns - are specified by object in the "values" dicitionary. - PG's DELETE..USING is also not available - in Core yet. - - - [feature] New session events after_transaction_create - and after_transaction_end - allows tracking of new SessionTransaction objects. - If the object is inspected, can be used to determine - when a session first becomes active and when - it deactivates. - - - [feature] The Query can now load entity/scalar-mixed - "tuple" rows that contain - types which aren't hashable, by setting the flag - "hashable=False" on the corresponding TypeEngine object - in use. Custom types that return unhashable types - (typically lists) can set this flag to False. - [ticket:2592] - - - [bug] Improvements to joined/subquery eager - loading dealing with chains of subclass entities - sharing a common base, with no specific "join depth" - provided. Will chain out to - each subclass mapper individually before detecting - a "cycle", rather than considering the base class - to be the source of the "cycle". [ticket:2481] - - - [bug] The "passive" flag on Session.is_modified() - no longer has any effect. is_modified() in - all cases looks only at local in-memory - modified flags and will not emit any - SQL or invoke loader callables/initializers. - [ticket:2320] - - - [bug] The warning emitted when using - delete-orphan cascade with one-to-many - or many-to-many without single-parent=True - is now an error. The ORM - would fail to function subsequent to this - warning in any case. [ticket:2405] - - - [bug] Lazy loads emitted within flush events - such as before_flush(), before_update(), - etc. will now function as they would - within non-event code, regarding consideration - of the PK/FK values used in the lazy-emitted - query. Previously, - special flags would be established that - would cause lazy loads to load related items - based on the "previous" value of the - parent PK/FK values specifically when called - upon within a flush; the signal to load - in this way is now localized to where the - unit of work actually needs to load that - way. Note that the UOW does - sometimes load these collections before - the before_update() event is called, - so the usage of "passive_updates" or not - can affect whether or not a collection will - represent the "old" or "new" data, when - accessed within a flush event, based - on when the lazy load was emitted. - The change is backwards incompatible in - the exceedingly small chance that - user event code depended on the old - behavior. [ticket:2350] - - - [feature] Query now "auto correlates" by - default in the same way as select() does. - Previously, a Query used as a subquery - in another would require the correlate() - method be called explicitly in order to - correlate a table on the inside to the - outside. As always, correlate(None) - disables correlation. [ticket:2179] - - - [feature] The after_attach event is now - emitted after the object is established - in Session.new or Session.identity_map - upon Session.add(), Session.merge(), - etc., so that the object is represented - in these collections when the event - is called. Added before_attach - event to accommodate use cases that - need autoflush w pre-attached object. - [ticket:2464] - - - [feature] The Session will produce warnings - when unsupported methods are used inside the - "execute" portion of the flush. These are - the familiar methods add(), delete(), etc. - as well as collection and related-object - manipulations, as called within mapper-level - flush events - like after_insert(), after_update(), etc. - It's been prominently documented for a long - time that SQLAlchemy cannot guarantee - results when the Session is manipulated within - the execution of the flush plan, - however users are still doing it, so now - there's a warning. Maybe someday the Session - will be enhanced to support these operations - inside of the flush, but for now, results - can't be guaranteed. - - - [bug] Continuing [ticket:2566] regarding extra - state post-flush due to event listeners; - any states that are marked as "dirty" from an - attribute perspective, usually via column-attribute - set events within after_insert(), after_update(), - etc., will get the "history" flag reset - in all cases, instead of only those instances - that were part of the flush. This has the effect - that this "dirty" state doesn't carry over - after the flush and won't result in UPDATE - statements. A warning is emitted to this - effect; the set_committed_state() - method can be used to assign attributes on objects - without producing history events. [ticket:2582] - - - [feature] ORM entities can be passed - to the core select() construct as well - as to the select_from(), - correlate(), and correlate_except() - methods of select(), where they will be unwrapped - into selectables. [ticket:2245] - - - [feature] Some support for auto-rendering of a - relationship join condition based on the mapped - attribute, with usage of core SQL constructs. - E.g. select([SomeClass]).where(SomeClass.somerelationship) - would render SELECT from "someclass" and use the - primaryjoin of "somerelationship" as the WHERE - clause. This changes the previous meaning - of "SomeClass.somerelationship" when used in a - core SQL context; previously, it would "resolve" - to the parent selectable, which wasn't generally - useful. Also works with query.filter(). - Related to [ticket:2245]. - - - [feature] The registry of classes - in declarative_base() is now a - WeakValueDictionary. So subclasses of - "Base" that are dereferenced will be - garbage collected, *if they are not - referred to by any other mappers/superclass - mappers*. See the next note for this ticket. - [ticket:2526] - - - [feature] Conflicts between columns on - single-inheritance declarative subclasses, - with or without using a mixin, can be resolved - using a new @declared_attr usage described - in the documentation. [ticket:2472] - - - [feature] declared_attr can now be used - on non-mixin classes, even though this is generally - only useful for single-inheritance subclass - column conflict resolution. [ticket:2472] - - - [feature] declared_attr can now be used with - attributes that are not Column or MapperProperty; - including any user-defined value as well - as association proxy objects. [ticket:2517] - - - [bug] Fixed a disconnect that slowly evolved - between a @declared_attr Column and a - directly-defined Column on a mixin. In both - cases, the Column will be applied to the - declared class' table, but not to that of a - joined inheritance subclass. Previously, - the directly-defined Column would be placed - on both the base and the sub table, which isn't - typically what's desired. [ticket:2565] - - - [feature] *Very limited* support for - inheriting mappers to be GC'ed when the - class itself is deferenced. The mapper - must not have its own table (i.e. - single table inh only) without polymorphic - attributes in place. - This allows for the use case of - creating a temporary subclass of a declarative - mapped class, with no table or mapping - directives of its own, to be garbage collected - when dereferenced by a unit test. - [ticket:2526] - - - [feature] Declarative now maintains a registry - of classes by string name as well as by full - module-qualified name. Multiple classes with the - same name can now be looked up based on a module-qualified - string within relationship(). Simple class name - lookups where more than one class shares the same - name now raises an informative error message. - [ticket:2338] - - - [feature] Can now provide class-bound attributes - that override columns which are of any - non-ORM type, not just descriptors. - [ticket:2535] - - - [feature] Added with_labels and - reduce_columns keyword arguments to - Query.subquery(), to provide two alternate - strategies for producing queries with uniquely- - named columns. [ticket:1729]. - - - [feature] A warning is emitted when a reference - to an instrumented collection is no longer - associated with the parent class due to - expiration/attribute refresh/collection - replacement, but an append - or remove operation is received on the - now-detached collection. [ticket:2476] - - - [bug] Declarative can now propagate a column - declared on a single-table inheritance subclass - up to the parent class' table, when the parent - class is itself mapped to a join() or select() - statement, directly or via joined inheritance, - and not just a Table. [ticket:2549] - - - [bug] An error is emitted when uselist=False - is combined with a "dynamic" loader. - This is a warning in 0.7.9. - - - [removed] Deprecated identifiers removed: - - * allow_null_pks mapper() argument - (use allow_partial_pks) - - * _get_col_to_prop() mapper method - (use get_property_by_column()) - - * dont_load argument to Session.merge() - (use load=True) - - * sqlalchemy.orm.shard module - (use sqlalchemy.ext.horizontal_shard) - -- engine - - [feature] Connection event listeners can - now be associated with individual - Connection objects, not just Engine - objects. [ticket:2511] - - - [feature] The before_cursor_execute event - fires off for so-called "_cursor_execute" - events, which are usually special-case - executions of primary-key bound sequences - and default-generation SQL - phrases that invoke separately when RETURNING - is not used with INSERT. [ticket:2459] - - - [feature] The libraries used by the test suite - have been moved around a bit so that they are - part of the SQLAlchemy install again. In addition, - a new suite of tests is present in the - new sqlalchemy.testing.suite package. This is - an under-development system that hopes to provide - a universal testing suite for external dialects. - Dialects which are maintained outside of SQLAlchemy - can use the new test fixture as the framework - for their own tests, and will get for free a - "compliance" suite of dialect-focused tests, - including an improved "requirements" system - where specific capabilities and features can - be enabled or disabled for testing. - - - [bug] The Inspector.get_table_names() - order_by="foreign_key" feature now sorts - tables by dependee first, to be consistent - with util.sort_tables and metadata.sorted_tables. - - - [bug] Fixed bug whereby if a database restart - affected multiple connections, each - connection would individually invoke a new - disposal of the pool, even though only - one disposal is needed. [ticket:2522] - - - [feature] Added a new system - for registration of new dialects in-process - without using an entrypoint. See the - docs for "Registering New Dialects". - [ticket:2462] - - - [feature] The "required" flag is set to - True by default, if not passed explicitly, - on bindparam() if the "value" or "callable" - parameters are not passed. - This will cause statement execution to check - for the parameter being present in the final - collection of bound parameters, rather than - implicitly assigning None. [ticket:2556] - - - [feature] Various API tweaks to the "dialect" - API to better support highly specialized - systems such as the Akiban database, including - more hooks to allow an execution context to - access type processors. - - - [bug] The names of the columns on the - .c. attribute of a select().apply_labels() - is now based on _ instead - of _, for those columns - that have a distinctly named .key. - [ticket:2397] - - - [feature] Inspector.get_primary_keys() is - deprecated; use Inspector.get_pk_constraint(). - Courtesy Diana Clarke. [ticket:2422] - - - [bug] The autoload_replace flag on Table, - when False, will cause any reflected foreign key - constraints which refer to already-declared - columns to be skipped, assuming that the - in-Python declared column will take over - the task of specifying in-Python ForeignKey - or ForeignKeyConstraint declarations. - - - [bug] The ResultProxy methods inserted_primary_key, - last_updated_params(), last_inserted_params(), - postfetch_cols(), prefetch_cols() all - assert that the given statement is a compiled - construct, and is an insert() or update() - statement as is appropriate, else - raise InvalidRequestError. [ticket:2498] - - - [feature] New C extension module "utils" has - been added for additional function speedups - as we have time to implement. - - - ResultProxy.last_inserted_ids is removed, - replaced by inserted_primary_key. - -- sql - - [feature] Major rework of operator system - in Core, to allow redefinition of existing - operators as well as addition of new operators - at the type level. New types can be created - from existing ones which add or redefine - operations that are exported out to column - expressions, in a similar manner to how the - ORM has allowed comparator_factory. The new - architecture moves this capability into the - Core so that it is consistently usable in - all cases, propagating cleanly using existing - type propagation behavior. [ticket:2547] - - - [feature] To complement [ticket:2547], types - can now provide "bind expressions" and - "column expressions" which allow compile-time - injection of SQL expressions into statements - on a per-column or per-bind level. This is - to suit the use case of a type which needs - to augment bind- and result- behavior at the - SQL level, as opposed to in the Python level. - Allows for schemes like transparent encryption/ - decryption, usage of Postgis functions, etc. - [ticket:1534] - - - [feature] The Core oeprator system now includes - the `getitem` operator, i.e. the bracket - operator in Python. This is used at first - to provide index and slice behavior to the - Postgresql ARRAY type, and also provides a hook - for end-user definition of custom __getitem__ - schemes which can be applied at the type - level as well as within ORM-level custom - operator schemes. `lshift` (<<) - and `rshift` (>>) are also supported as - optional operators. - - Note that this change has the effect that - descriptor-based __getitem__ schemes used by - the ORM in conjunction with synonym() or other - "descriptor-wrapped" schemes will need - to start using a custom comparator in order - to maintain this behavior. - - - [feature] Revised the rules used to determine - the operator precedence for the user-defined - operator, i.e. that granted using the ``op()`` - method. Previously, the smallest precedence - was applied in all cases, now the default - precedence is zero, lower than all operators - except "comma" (such as, used in the argument - list of a ``func`` call) and "AS", and is - also customizable via the "precedence" argument - on the ``op()`` method. [ticket:2537] - - - [feature] Added "collation" parameter to all - String types. When present, renders as - COLLATE . This to support the - COLLATE keyword now supported by several - databases including MySQL, SQLite, and Postgresql. - [ticket:2276] - - - [change] The Text() type renders the length - given to it, if a length was specified. - - - [feature] Custom unary operators can now be - used by combining operators.custom_op() with - UnaryExpression(). - - - [bug] A tweak to column precedence which moves the - "concat" and "match" operators to be the same as - that of "is", "like", and others; this helps with - parenthesization rendering when used in conjunction - with "IS". [ticket:2564] - - - [feature] Enhanced GenericFunction and func.* - to allow for user-defined GenericFunction - subclasses to be available via the func.* - namespace automatically by classname, - optionally using a package name, as well - as with the ability to have the rendered - name different from the identified name - in func.*. - - - [feature] The cast() and extract() constructs - will now be produced via the func.* accessor - as well, as users naturally try to access these - names from func.* they might as well do - what's expected, even though the returned - object is not a FunctionElement. - [ticket:2562] - - - [changed] Most classes in expression.sql - are no longer preceded with an underscore, - i.e. Label, SelectBase, Generative, CompareMixin. - _BindParamClause is also renamed to - BindParameter. The old underscore names for - these classes will remain available as synonyms - for the foreseeable future. - - - [feature] The Inspector object can now be - acquired using the new inspect() service, - part of [ticket:2208] - - - [feature] The column_reflect event now - accepts the Inspector object as the first - argument, preceding "table". Code which - uses the 0.7 version of this very new - event will need modification to add the - "inspector" object as the first argument. - [ticket:2418] - - - [feature] The behavior of column targeting - in result sets is now case sensitive by - default. SQLAlchemy for many years would - run a case-insensitive conversion on these values, - probably to alleviate early case sensitivity - issues with dialects like Oracle and - Firebird. These issues have been more cleanly - solved in more modern versions so the performance - hit of calling lower() on identifiers is removed. - The case insensitive comparisons can be re-enabled - by setting "case_insensitive=False" on - create_engine(). [ticket:2423] - - - [bug] Applying a column expression to a select - statement using a label with or without other - modifying constructs will no longer "target" that - expression to the underlying Column; this affects - ORM operations that rely upon Column targeting - in order to retrieve results. That is, a query - like query(User.id, User.id.label('foo')) will now - track the value of each "User.id" expression separately - instead of munging them together. It is not expected - that any users will be impacted by this; however, - a usage that uses select() in conjunction with - query.from_statement() and attempts to load fully - composed ORM entities may not function as expected - if the select() named Column objects with arbitrary - .label() names, as these will no longer target to - the Column objects mapped by that entity. - [ticket:2591] - - - [feature] The "unconsumed column names" warning emitted - when keys are present in insert.values() or update.values() - that aren't in the target table is now an exception. - [ticket:2415] - - - [feature] Added "MATCH" clause to ForeignKey, - ForeignKeyConstraint, courtesy Ryan Kelly. - [ticket:2502] - - - [feature] Added support for DELETE and UPDATE from - an alias of a table, which would assumedly - be related to itself elsewhere in the query, - courtesy Ryan Kelly. [ticket:2507] - - - [feature] select() features a correlate_except() - method, auto correlates all selectables except those - passed. - - - [feature] The prefix_with() method is now available - on each of select(), insert(), update(), delete(), - all with the same API, accepting multiple - prefix calls, as well as a "dialect name" so that - the prefix can be limited to one kind of dialect. - [ticket:2431] - - - [feature] Added reduce_columns() method - to select() construct, replaces columns inline - using the util.reduce_columns utility function - to remove equivalent columns. reduce_columns() - also adds "with_only_synonyms" to limit the - reduction just to those columns which have the same - name. The deprecated fold_equivalents() feature is - removed [ticket:1729]. - - - [feature] Reworked the startswith(), endswith(), - contains() operators to do a better job with - negation (NOT LIKE), and also to assemble them - at compilation time so that their rendered SQL - can be altered, such as in the case for Firebird - STARTING WITH [ticket:2470] - - - [feature] Added a hook to the system of rendering - CREATE TABLE that provides access to the render for each - Column individually, by constructing a @compiles - function against the new schema.CreateColumn - construct. [ticket:2463] - - - [feature] "scalar" selects now have a WHERE method - to help with generative building. Also slight adjustment - regarding how SS "correlates" columns; the new methodology - no longer applies meaning to the underlying - Table column being selected. This improves - some fairly esoteric situations, and the logic - that was there didn't seem to have any purpose. - - - [bug] Fixes to the interpretation of the - Column "default" parameter as a callable - to not pass ExecutionContext into a keyword - argument parameter. [ticket:2520] - - - [bug] All of UniqueConstraint, ForeignKeyConstraint, - CheckConstraint, and PrimaryKeyConstraint will - attach themselves to their parent table automatically - when they refer to a Table-bound Column object directly - (i.e. not just string column name), and refer to - one and only one Table. Prior to 0.8 this behavior - occurred for UniqueConstraint and PrimaryKeyConstraint, - but not ForeignKeyConstraint or CheckConstraint. - [ticket:2410] - - - [bug] TypeDecorator now includes a generic repr() - that works in terms of the "impl" type by default. - This is a behavioral change for those TypeDecorator - classes that specify a custom __init__ method; those - types will need to re-define __repr__() if they need - __repr__() to provide a faithful constructor representation. - [ticket:2594] - - - [bug] column.label(None) now produces an - anonymous label, instead of returning the - column object itself, consistent with the behavior - of label(column, None). [ticket:2168] - - - [feature] An explicit error is raised when - a ForeignKeyConstraint() that was - constructed to refer to multiple remote tables - is first used. [ticket:2455] - -- access - - [feature] the MS Access dialect has been - moved to its own project on Bitbucket, - taking advantage of the new SQLAlchemy - dialect compliance suite. The dialect is - still in very rough shape and probably not - ready for general use yet, however - it does have *extremely* rudimental - functionality now. - https://bitbucket.org/zzzeek/sqlalchemy-access - -- maxdb - - [moved] The MaxDB dialect, which hasn't been - functional for several years, is - moved out to a pending bitbucket project, - https://bitbucket.org/zzzeek/sqlalchemy-maxdb. - - -- sqlite - - [feature] the SQLite date and time types - have been overhauled to support a more open - ended format for input and output, using - name based format strings and regexps. A - new argument "microseconds" also provides - the option to omit the "microseconds" - portion of timestamps. Thanks to - Nathan Wright for the work and tests on - this. [ticket:2363] - -- mssql - - [feature] SQL Server dialect can be given - database-qualified schema names, - i.e. "schema='mydatabase.dbo'"; reflection - operations will detect this, split the schema - among the "." to get the owner separately, - and emit a "USE mydatabase" statement before - reflecting targets within the "dbo" owner; - the existing database returned from - DB_NAME() is then restored. - - - [bug] removed legacy behavior whereby - a column comparison to a scalar SELECT via - == would coerce to an IN with the SQL server - dialect. This is implicit - behavior which fails in other scenarios - so is removed. Code which relies on this - needs to be modified to use column.in_(select) - explicitly. [ticket:2277] - - - [feature] updated support for the mxodbc - driver; mxodbc 3.2.1 is recommended for full - compatibility. - -- postgresql - - - [feature] postgresql.ARRAY features an optional - "dimension" argument, will assign a specific - number of dimensions to the array which will - render in DDL as ARRAY[][]..., also improves - performance of bind/result processing. - [ticket:2441] - - - [feature] postgresql.ARRAY now supports - indexing and slicing. The Python [] operator - is available on all SQL expressions that are - of type ARRAY; integer or simple slices can be - passed. The slices can also be used on the - assignment side in the SET clause of an UPDATE - statement by passing them into Update.values(); - see the docs for examples. - - - [feature] Added new "array literal" construct - postgresql.array(). Basically a "tuple" that - renders as ARRAY[1,2,3]. - - - [feature] Added support for the Postgresql ONLY - keyword, which can appear corresponding to a - table in a SELECT, UPDATE, or DELETE statement. - The phrase is established using with_hint(). - Courtesy Ryan Kelly [ticket:2506] - - - [feature] The "ischema_names" dictionary of the - Postgresql dialect is "unofficially" customizable. - Meaning, new types such as PostGIS types can - be added into this dictionary, and the PG type - reflection code should be able to handle simple - types with variable numbers of arguments. - The functionality here is "unofficial" for - three reasons: - - 1. this is not an "official" API. Ideally - an "official" API would allow custom type-handling - callables at the dialect or global level - in a generic way. - 2. This is only implemented for the PG dialect, - in particular because PG has broad support - for custom types vs. other database backends. - A real API would be implemented at the - default dialect level. - 3. The reflection code here is only tested against - simple types and probably has issues with more - compositional types. - - patch courtesy Éric Lemoine. - -- firebird - - [feature] The "startswith()" operator renders - as "STARTING WITH", "~startswith()" renders - as "NOT STARTING WITH", using FB's more efficient - operator. [ticket:2470] - - - [bug] CompileError is raised when VARCHAR with - no length is attempted to be emitted, same - way as MySQL. [ticket:2505] - - - [bug] Firebird now uses strict "ansi bind rules" - so that bound parameters don't render in the - columns clause of a statement - they render - literally instead. - - - [bug] Support for passing datetime as date when - using the DateTime type with Firebird; other - dialects support this. - - - [feature] An experimental dialect for the fdb - driver is added, but is untested as I cannot - get the fdb package to build. [ticket:2504] - -- mysql - - [bug] Dialect no longer emits expensive server - collations query, as well as server casing, - on first connect. These functions are still - available as semi-private. [ticket:2404] - - - [feature] Added TIME type to mysql dialect, - accepts "fst" argument which is the new - "fractional seconds" specifier for recent - MySQL versions. The datatype will interpret - a microseconds portion received from the driver, - however note that at this time most/all MySQL - DBAPIs do not support returning this value. - [ticket:2534] - -- oracle - - [bug] Quoting information is now passed along - from a Column with quote=True when generating - a same-named bound parameter to the bindparam() - object, as is the case in generated INSERT and UPDATE - statements, so that unknown reserved names can - be fully supported. [ticket:2437] - - - [feature] The types of columns excluded from the - setinputsizes() set can be customized by sending - a list of string DBAPI type names to exclude, - using the exclude_setinputsizes dialect parameter. - This list was previously fixed. The list also - now defaults to STRING, UNICODE, removing - CLOB, NCLOB from the list. [ticket:2561] - - - [bug] The CreateIndex construct in Oracle - will now schema-qualify the name of the index - to be that of the parent table. Previously this - name was omitted which apparently creates the - index in the default schema, rather than that - of the table. - -- extensions - - [removed] The SQLSoup extension is removed from - SQLAlchemy, and is now an external project. - See http://pypi.python.org/pypi/sqlsoup . - [ticket:2262] - -0.7.7 - 0.7.xx -============== -0.8 development begins during 0.7.7 development. -All relevant bug fixes -and features listed below from version 0.7.7 on -are also present in 0.8. - -0.7.10 -====== -- orm - - [bug] Fixed Session accounting bug whereby replacing - a deleted object in the identity map with another - object of the same primary key would raise a - "conflicting state" error on rollback(), - if the replaced primary key were established either - via non-unitofwork-established INSERT statement - or by primary key switch of another instance. - [ticket:2583] - -- oracle - - [bug] changed the list of cx_oracle types that are - excluded from the setinputsizes() step to only include - STRING and UNICODE; CLOB and NCLOB are removed. This - is to work around cx_oracle behavior which is broken - for the executemany() call. In 0.8, this same change - is applied however it is also configurable via the - exclude_setinputsizes argument. [ticket:2561] - -- mysql - - [feature] Added "raise_on_warnings" flag to OurSQL - dialect. [ticket:2523] - - - [feature] Added "read_timeout" flag to MySQLdb - dialect. [ticket:2554] - -0.7.9 -===== -- orm - - [bug] Fixed bug mostly local to new - AbstractConcreteBase helper where the "type" - attribute from the superclass would not - be overridden on the subclass to produce the - "reserved for base" error message, instead placing - a do-nothing attribute there. This was inconsistent - vs. using ConcreteBase as well as all the behavior - of classical concrete mappings, where the "type" - column from the polymorphic base would be explicitly - disabled on subclasses, unless overridden - explicitly. - - - [bug] A warning is emitted when lazy='dynamic' - is combined with uselist=False. This is an - exception raise in 0.8. - - - [bug] Fixed bug whereby user error in related-object - assignment could cause recursion overflow if the - assignment triggered a backref of the same name - as a bi-directional attribute on the incorrect - class to the same target. An informative - error is raised now. - - - [bug] Fixed bug where incorrect type information - would be passed when the ORM would bind the - "version" column, when using the "version" feature. - Tests courtesy Daniel Miller. [ticket:2539] - - - [bug] Extra logic has been added to the "flush" - that occurs within Session.commit(), such that the - extra state added by an after_flush() or - after_flush_postexec() hook is also flushed in a - subsequent flush, before the "commit" completes. - Subsequent calls to flush() will continue until - the after_flush hooks stop adding new state. - An "overflow" counter of 100 is also in place, - in the event of a broken after_flush() hook - adding new content each time. [ticket:2566] - -- sql - - [bug] Fixed the DropIndex construct to support - an Index associated with a Table in a remote - schema. [ticket:2571] - - - [bug] Fixed bug in over() construct whereby - passing an empty list for either partition_by - or order_by, as opposed to None, would fail - to generate correctly. - Courtesy Gunnlaugur Þór Briem. - [ticket:2574] - - - [bug] Fixed CTE bug whereby positional - bound parameters present in the CTEs themselves - would corrupt the overall ordering of - bound parameters. This primarily - affected SQL Server as the platform with - positional binds + CTE support. - [ticket:2521] - - - [bug] Fixed more un-intuitivenesses in CTEs - which prevented referring to a CTE in a union - of itself without it being aliased. - CTEs now render uniquely - on name, rendering the outermost CTE of a given - name only - all other references are rendered - just as the name. This even includes other - CTE/SELECTs that refer to different versions - of the same CTE object, such as a SELECT - or a UNION ALL of that SELECT. We are - somewhat loosening the usual link between object - identity and lexical identity in this case. - A true name conflict between two unrelated - CTEs now raises an error. - - - [bug] quoting is applied to the column names - inside the WITH RECURSIVE clause of a - common table expression according to the - quoting rules for the originating Column. - [ticket:2512] - - - [bug] Fixed regression introduced in 0.7.6 - whereby the FROM list of a SELECT statement - could be incorrect in certain "clone+replace" - scenarios. [ticket:2518] - - - [bug] Fixed bug whereby usage of a UNION - or similar inside of an embedded subquery - would interfere with result-column targeting, - in the case that a result-column had the same - ultimate name as a name inside the embedded - UNION. [ticket:2552] - - - [bug] Fixed a regression since 0.6 regarding - result-row targeting. It should be possible - to use a select() statement with string - based columns in it, that is - select(['id', 'name']).select_from('mytable'), - and have this statement be targetable by - Column objects with those names; this is the - mechanism by which - query(MyClass).from_statement(some_statement) - works. At some point the specific case of - using select(['id']), which is equivalent to - select([literal_column('id')]), stopped working - here, so this has been re-instated and of - course tested. [ticket:2558] - - - [bug] Added missing operators is_(), isnot() - to the ColumnOperators base, so that these long-available - operators are present as methods like all - the other operators. [ticket:2544] - - - [bug] When the primary key column of a Table - is replaced, such as via extend_existing, - the "auto increment" column used by insert() - constructs is reset. Previously it would - remain referring to the previous primary - key column. [ticket:2525] - -- engine - - [bug] Fixed bug whereby - a disconnect detect + dispose that occurs - when the QueuePool has threads waiting - for connections would leave those - threads waiting for the duration of - the timeout on the old pool (or indefinitely - if timeout was disabled). The fix - now notifies those waiters with a special - exception case and has them move onto - the new pool. [ticket:2522] - - - [feature] Dramatic improvement in memory - usage of the event system; instance-level - collections are no longer created for a - particular type of event until - instance-level listeners are established - for that event. [ticket:2516] - - - [bug] Added gaerdbms import to mysql/__init__.py, - the absense of which was preventing the new - GAE dialect from being loaded. [ticket:2529] - - - [bug] Fixed cextension bug whereby the - "ambiguous column error" would fail to - function properly if the given index were - a Column object and not a string. - Note there are still some column-targeting - issues here which are fixed in 0.8. - [ticket:2553] - - - [bug] Fixed the repr() of Enum to include - the "name" and "native_enum" flags. Helps - Alembic autogenerate. - -- sqlite - - [bug] Adjusted a very old bugfix which attempted - to work around a SQLite issue that itself was - "fixed" as of sqlite 3.6.14, regarding quotes - surrounding a table name when using - the "foreign_key_list" pragma. The fix has been - adjusted to not interfere with quotes that - are *actually in the name* of a column or table, - to as much a degree as possible; sqlite still - doesn't return the correct result for foreign_key_list() - if the target table actually has quotes surrounding - its name, as *part* of its name (i.e. """mytable"""). - [ticket:2568] - - - [bug] Adjusted column default reflection code to - convert non-string values to string, to accommodate - old SQLite versions that don't deliver - default info as a string. [ticket:2265] - - - [feature] Added support for the localtimestamp() - SQL function implemented in SQLite, courtesy - Richard Mitchell. - -- postgresql - - [bug] Columns in reflected primary key constraint - are now returned in the order in which the constraint - itself defines them, rather than how the table - orders them. Courtesy Gunnlaugur Þór Briem. - [ticket:2531]. - - - [bug] Added 'terminating connection' to the list - of messages we use to detect a disconnect with PG, which - appears to be present in some versions when the server - is restarted. [ticket:2570] - -- mysql - - [bug] Updated mysqlconnector interface to use - updated "client flag" and "charset" APIs, - courtesy David McNelis. - -- mssql - - [bug] Fixed compiler bug whereby using a correlated - subquery within an ORDER BY would fail to render correctly - if the stament also used LIMIT/OFFSET, due to mis-rendering - within the ROW_NUMBER() OVER clause. Fix courtesy - sayap [ticket:2538] - - - [bug] Fixed compiler bug whereby a given - select() would be modified if it had an "offset" - attribute, causing the construct to not compile - correctly a second time. [ticket:2545] - - - [bug] Fixed bug where reflection of primary key constraint - would double up columns if the same constraint/table - existed in multiple schemas. - -0.7.8 -===== -- orm - - [bug] Fixed bug whereby subqueryload() from - a polymorphic mapping to a target would incur - a new invocation of the query for each - distinct class encountered in the polymorphic - result. [ticket:2480] - - - [bug] Fixed bug in declarative - whereby the precedence of columns - in a joined-table, composite - column (typically for id) would fail to - be correct if the columns contained - names distinct from their attribute - names. This would cause things like - primaryjoin conditions made against the - entity attributes to be incorrect. Related - to [ticket:1892] as this was supposed - to be part of that, this is [ticket:2491]. - - - [feature] The 'objects' argument to - flush() is no longer deprecated, as some - valid use cases have been identified. - - - [bug] Fixed identity_key() function which - was not accepting a scalar argument - for the identity. [ticket:2508]. - - - [bug] Fixed bug whereby populate_existing - option would not propagate to subquery - eager loaders. [ticket:2497]. - -- sql - - [bug] added BIGINT to types.__all__, - BIGINT, BINARY, VARBINARY to sqlalchemy - module namespace, plus test to ensure - this breakage doesn't occur again. - [ticket:2499] - - - [bug] Repaired common table expression - rendering to function correctly when the - SELECT statement contains UNION or other - compound expressions, courtesy btbuilder. - [ticket:2490] - - - [bug] Fixed bug whereby append_column() - wouldn't function correctly on a cloned - select() construct, courtesy - Gunnlaugur Þór Briem. [ticket:2482] - -- engine - - [bug] Fixed memory leak in C version of - result proxy whereby DBAPIs which don't deliver - pure Python tuples for result rows would - fail to decrement refcounts correctly. - The most prominently affected DBAPI - is pyodbc. [ticket:2489] - - - [bug] Fixed bug affecting Py3K whereby - string positional parameters passed to - engine/connection execute() would fail to be - interpreted correctly, due to __iter__ - being present on Py3K string. - [ticket:2503]. - -- postgresql - - [bug] removed unnecessary table clause when - reflecting enums, [ticket:2510]. Courtesy - Gunnlaugur Þór Briem. - -- oracle - - [bug] Added ROWID to oracle.*, [ticket:2483] - -- mysql - - [feature] Added a new dialect for Google App - Engine. Courtesy Richie Foreman. [ticket:2484] - - -0.7.7 -===== -- orm - - [bug] Fixed issue in unit of work - whereby setting a non-None self-referential - many-to-one relationship to None - would fail to persist the change if the - former value was not already loaded. - [ticket:2477]. - - - [feature] Added prefix_with() method - to Query, calls upon select().prefix_with() - to allow placement of MySQL SELECT - directives in statements. Courtesy - Diana Clarke [ticket:2443] - - - [bug] Fixed bug in 0.7.6 introduced by - [ticket:2409] whereby column_mapped_collection - used against columns that were mapped as - joins or other indirect selectables - would fail to function. - - - [feature] Added new flag to @validates - include_removes. When True, collection - remove and attribute del events - will also be sent to the validation function, - which accepts an additional argument - "is_remove" when this flag is used. - - - [bug] Fixed bug whereby polymorphic_on - column that's not otherwise mapped on the - class would be incorrectly included - in a merge() operation, raising an error. - [ticket:2449] - - - [bug] Fixed bug in expression annotation - mechanics which could lead to incorrect - rendering of SELECT statements with aliases - and joins, particularly when using - column_property(). [ticket:2453] - - - [bug] Fixed bug which would prevent - OrderingList from being pickleable - [ticket:2454]. Courtesy Jeff Dairiki - - - [bug] Fixed bug in relationship comparisons - whereby calling unimplemented methods like - SomeClass.somerelationship.like() would - produce a recursion overflow, instead - of NotImplementedError. - -- sql - - [bug] Removed warning when Index is created - with no columns; while this might not be what - the user intended, it is a valid use case - as an Index could be a placeholder for just an - index of a certain name. - - - [feature] Added new connection event - dbapi_error(). Is called for all DBAPI-level - errors passing the original DBAPI exception - before SQLAlchemy modifies the state - of the cursor. - - - [bug] If conn.begin() fails when calling - "with engine.begin()", the newly acquired - Connection is closed explicitly before - propagating the exception onward normally. - - - [bug] Add BINARY, VARBINARY to types.__all__, - [ticket:2474] - -- mssql - - [feature] Added interim create_engine flag - supports_unicode_binds to PyODBC dialect, - to force whether or not the dialect - passes Python unicode literals to PyODBC - or not. - - - [bug] Repaired the use_scope_identity - create_engine() flag when using the pyodbc - dialect. Previously this flag would be - ignored if set to False. When set to False, - you'll get "SELECT @@identity" after each - INSERT to get at the last inserted ID, - for those tables which have "implicit_returning" - set to False. - - - [bug] UPDATE..FROM syntax with SQL Server - requires that the updated table be present - in the FROM clause when an alias of that - table is also present in the FROM clause. - The updated table is now always present - in the FROM, when FROM is present - in the first place. Courtesy sayap. - [ticket:2468] - -- postgresql - - [feature] Added new for_update/with_lockmode() - options for Postgresql: for_update="read"/ - with_lockmode("read"), - for_update="read_nowait"/ - with_lockmode("read_nowait"). - These emit "FOR SHARE" and "FOR SHARE NOWAIT", - respectively. Courtesy Diana Clarke - [ticket:2445] - - - [bug] removed unnecessary table clause - when reflecting domains, [ticket:2473] - -- mysql - - [bug] Fixed bug whereby column name inside - of "KEY" clause for autoincrement composite - column with InnoDB would double quote a - name that's a reserved word. Courtesy Jeff - Dairiki. [ticket:2460] - - - [bug] Fixed bug whereby get_view_names() for - "information_schema" schema would fail - to retrieve views marked as "SYSTEM VIEW". - courtesy Matthew Turland. - - - [bug] Fixed bug whereby if cast() is used - on a SQL expression whose type is not supported - by cast() and therefore CAST isn't rendered by - the dialect, the order of evaluation could change - if the casted expression required that it be - grouped; grouping is now applied to those - expressions. [ticket:2467] - -- sqlite - - - [feature] Added SQLite execution option - "sqlite_raw_colnames=True", will bypass - attempts to remove "." from column names - returned by SQLite cursor.description. - [ticket:2475] - -0.7.6 ===== -- orm - - [bug] Fixed event registration bug - which would primarily show up as - events not being registered with - sessionmaker() instances created - after the event was associated - with the Session class. [ticket:2424] - - - [bug] Fixed bug whereby a primaryjoin - condition with a "literal" in it would - raise an error on compile with certain - kinds of deeply nested expressions - which also needed to render the same - bound parameter name more than once. - [ticket:2425] - - - [feature] Added "no_autoflush" context - manager to Session, used with with: - will temporarily disable autoflush. - - - [feature] Added cte() method to Query, - invokes common table expression support - from the Core (see below). [ticket:1859] - - - [bug] Removed the check for number of - rows affected when doing a multi-delete - against mapped objects. If an ON DELETE - CASCADE exists between two rows, we can't - get an accurate rowcount from the DBAPI; - this particular count is not supported - on most DBAPIs in any case, MySQLdb - is the notable case where it is. - [ticket:2403] - - - [bug] Fixed bug whereby objects using - attribute_mapped_collection or - column_mapped_collection could not be - pickled. [ticket:2409] - - - [bug] Fixed bug whereby MappedCollection - would not get the appropriate collection - instrumentation if it were only used - in a custom subclass that used - @collection.internally_instrumented. - [ticket:2406] - - - [bug] Fixed bug whereby SQL adaption mechanics - would fail in a very nested scenario involving - joined-inheritance, joinedload(), limit(), and a - derived function in the columns clause. - [ticket:2419] - - - [bug] Fixed the repr() for CascadeOptions to - include refresh-expire. Also reworked - CascadeOptions to be a . - [ticket:2417] - - - [feature] Added the ability to query for - Table-bound column names when using - query(sometable).filter_by(colname=value). - [ticket:2400] - - - [bug] Improved the "declarative reflection" - example to support single-table inheritance, - multiple calls to prepare(), tables that - are present in alternate schemas, - establishing only a subset of classes - as reflected. - - - [bug] Scaled back the test applied within - flush() to check for UPDATE against partially - NULL PK within one table to only actually - happen if there's really an UPDATE to occur. - [ticket:2390] - - - [bug] Fixed bug whereby if a method name - conflicted with a column name, a - TypeError would be raised when the mapper - tried to inspect the __get__() method - on the method object. [ticket:2352] - -- sql - - [bug] Fixed memory leak in core which would - occur when C extensions were used with - particular types of result fetches, - in particular when orm query.count() - were called. [ticket:2427] - - - [bug] Fixed issue whereby attribute-based - column access on a row would raise - AttributeError with non-C version, - NoSuchColumnError with C version. Now - raises AttributeError in both cases. - [ticket:2398] - - - [feature] Added support for SQL standard - common table expressions (CTE), allowing - SELECT objects as the CTE source (DML - not yet supported). This is invoked via - the cte() method on any select() construct. - [ticket:1859] - - - [bug] Added support for using the .key - of a Column as a string identifier in a - result set row. The .key is currently - listed as an "alternate" name for a column, - and is superseded by the name of a column - which has that key value as its regular name. - For the next major release - of SQLAlchemy we may reverse this precedence - so that .key takes precedence, but this - is not decided on yet. [ticket:2392] - - - [bug] A warning is emitted when a not-present - column is stated in the values() clause - of an insert() or update() construct. - Will move to an exception in 0.8. - [ticket:2413] - - - [bug] A significant change to how labeling - is applied to columns in SELECT statements - allows "truncated" labels, that is label names - that are generated in Python which exceed - the maximum identifier length (note this is - configurable via label_length on create_engine()), - to be properly referenced when rendered inside - of a subquery, as well as to be present - in a result set row using their original - in-Python names. [ticket:2396] - - - [bug] Fixed bug in new "autoload_replace" flag - which would fail to preserve the primary - key constraint of the reflected table. - [ticket:2402] - - - [bug] Index will raise when arguments passed - cannot be interpreted as columns or expressions. - Will warn when Index is created - with no columns at all. [ticket:2380] - -- engine - - [feature] Added "no_parameters=True" execution - option for connections. If no parameters - are present, will pass the statement - as cursor.execute(statement), thereby invoking - the DBAPIs behavior when no parameter collection - is present; for psycopg2 and mysql-python, this - means not interpreting % signs in the string. - This only occurs with this option, and not - just if the param list is blank, as otherwise - this would produce inconsistent behavior - of SQL expressions that normally escape percent - signs (and while compiling, can't know ahead of - time if parameters will be present in - some cases). [ticket:2407] - - - [bug] Added execution_options() call to - MockConnection (i.e., that used with - strategy="mock") which acts as a pass through - for arguments. - - - [feature] Added pool_reset_on_return argument - to create_engine, allows control over - "connection return" behavior. Also added - new arguments 'rollback', 'commit', None - to pool.reset_on_return to allow more control - over connection return activity. [ticket:2378] - - - [feature] Added some decent context managers - to Engine, Connection: - - with engine.begin() as conn: - - - and: - - with engine.connect() as conn: - - - Both close out the connection when done, - commit or rollback transaction with errors - on engine.begin(). - -- sqlite - - [bug] Fixed bug in C extensions whereby - string format would not be applied to a - Numeric value returned as integer; this - affected primarily SQLite which does - not maintain numeric scale settings. - [ticket:2432] - -- mssql - - [feature] Added support for MSSQL INSERT, - UPDATE, and DELETE table hints, using - new with_hint() method on UpdateBase. - [ticket:2430] - -- mysql - - [feature] Added support for MySQL index and - primary key constraint types - (i.e. USING) via new mysql_using parameter - to Index and PrimaryKeyConstraint, - courtesy Diana Clarke. [ticket:2386] - - - [feature] Added support for the "isolation_level" - parameter to all MySQL dialects. Thanks - to mu_mind for the patch here. [ticket:2394] - -- oracle - - [feature] Added a new create_engine() flag - coerce_to_decimal=False, disables the precision - numeric handling which can add lots of overhead - by converting all numeric values to - Decimal. [ticket:2399] - - - [bug] Added missing compilation support for - LONG [ticket:2401] - - - [bug] Added 'LEVEL' to the list of reserved - words for Oracle. [ticket:2435] - -- examples - - [bug] Altered _params_from_query() function - in Beaker example to pull bindparams from the - fully compiled statement, as a quick means - to get everything including subqueries in the - columns clause, etc. - -0.7.5 (January 28, 2012) +MOVED ===== -- orm - - [bug] Fixed issue where modified session state - established after a failed flush would be committed - as part of the subsequent transaction that - begins automatically after manual call - to rollback(). The state of the session is - checked within rollback(), and if new state - is present, a warning is emitted and - restore_snapshot() is called a second time, - discarding those changes. [ticket:2389] - - - [bug] Fixed regression from 0.7.4 whereby - using an already instrumented column from a - superclass as "polymorphic_on" failed to resolve - the underlying Column. [ticket:2345] - - - [bug] Raise an exception if xyzload_all() is - used inappropriately with two non-connected - relationships. [ticket:2370] - - - [feature] Added "class_registry" argument to - declarative_base(). Allows two or more declarative - bases to share the same registry of class names. - - - [feature] query.filter() accepts multiple - criteria which will join via AND, i.e. - query.filter(x==y, z>q, ...) - - - [feature] Added new capability to relationship - loader options to allow "default" loader strategies. - Pass '*' to any of joinedload(), lazyload(), - subqueryload(), or noload() and that becomes the - loader strategy used for all relationships, - except for those explicitly stated in the - Query. Thanks to up-and-coming contributor - Kent Bower for an exhaustive and well - written test suite ! [ticket:2351] - - - [bug] Fixed bug whereby event.listen(SomeClass) - forced an entirely unnecessary compile of the - mapper, making events very hard to set up - at module import time (nobody noticed this ??) - [ticket:2367] - - - [bug] Fixed bug whereby hybrid_property didn't - work as a kw arg in any(), has(). - - - Fixed regression from 0.6 whereby if - "load_on_pending" relationship() flag were used - where a non-"get()" lazy clause needed to be - emitted on a pending object, it would fail - to load. - - - [bug] ensure pickleability of all ORM exceptions - for multiprocessing compatibility. [ticket:2371] - - - [bug] implemented standard "can't set attribute" / - "can't delete attribute" AttributeError when - setattr/delattr used on a hybrid that doesn't - define fset or fdel. [ticket:2353] - - - [bug] Fixed bug where unpickled object didn't - have enough of its state set up to work - correctly within the unpickle() event established - by the mutable object extension, if the object - needed ORM attribute access within - __eq__() or similar. [ticket:2362] - - - [bug] Fixed bug where "merge" cascade could - mis-interpret an unloaded attribute, if the - load_on_pending flag were used with - relationship(). Thanks to Kent Bower - for tests. [ticket:2374] - - - [feature] New declarative reflection example - added, illustrates how best to mix table reflection - with declarative as well as uses some new features - from [ticket:2356]. - -- sql - - [feature] New reflection feature "autoload_replace"; - when set to False on Table, the Table can be autoloaded - without existing columns being replaced. Allows - more flexible chains of Table construction/reflection - to be constructed, including that it helps with - combining Declarative with table reflection. - See the new example on the wiki. [ticket:2356] - - - [bug] Improved the API for add_column() such that - if the same column is added to its own table, - an error is not raised and the constraints - don't get doubled up. Also helps with some - reflection/declarative patterns. [ticket:2356] - - - [feature] Added "false()" and "true()" expression - constructs to sqlalchemy.sql namespace, though - not part of __all__ as of yet. - - - [feature] Dialect-specific compilers now raise - CompileException for all type/statement compilation - issues, instead of InvalidRequestError or ArgumentError. - The DDL for CREATE TABLE will re-raise - CompileExceptions to include table/column information - for the problematic column. [ticket:2361] - - - [bug] Fixed issue where the "required" exception - would not be raised for bindparam() with required=True, - if the statement were given no parameters at all. - [ticket:2381] - -- engine - - [bug] Added __reduce__ to StatementError, - DBAPIError, column errors so that exceptions - are pickleable, as when using multiprocessing. - However, not - all DBAPIs support this yet, such as - psycopg2. [ticket:2371] - - - [bug] Improved error messages when a non-string - or invalid string is passed to any of the - date/time processors used by SQLite, including - C and Python versions. [ticket:2382] - - - [bug] Fixed bug whereby a table-bound Column - object named "_" which matched a column - labeled as "_" could match - inappropriately when targeting in a result - set row. [ticket:2377] - - - [bug] Fixed bug in "mock" strategy whereby - correct DDL visit method wasn't called, resulting - in "CREATE/DROP SEQUENCE" statements being - duplicated [ticket:2384] - -- sqlite - - [bug] the "name" of an FK constraint in SQLite - is reflected as "None", not "0" or other - integer value [ticket:2364]. - SQLite does not appear to support constraint - naming in any case. - - - [bug] sql.false() and sql.true() compile to - 0 and 1, respectively in sqlite [ticket:2368] - - - [bug] removed an erroneous "raise" in the - SQLite dialect when getting table names - and view names, where logic is in place - to fall back to an older version of - SQLite that doesn't have the - "sqlite_temp_master" table. - -- mysql - - [bug] fixed regexp that filters out warnings - for non-reflected "PARTITION" directives, - thanks to George Reilly [ticket:2376] - -- mssql - - [bug] Adjusted the regexp used in the - mssql.TIME type to ensure only six digits - are received for the "microseconds" portion - of the value, which is expected by - Python's datetime.time(). Note that - support for sending microseconds doesn't - seem to be possible yet with pyodbc - at least. [ticket:2340] - - - [bug] Dropped the "30 char" limit on pymssql, - based on reports that it's doing things - better these days. pymssql hasn't been - well tested and as the DBAPI is in flux - it's still not clear what the status - is on this driver and how SQLAlchemy's - implementation should adapt. [ticket:2347] - -- oracle - - [bug] Added ORA-03135 to the never ending - list of oracle "connection lost" errors - [ticket:2388] - -- core - - [bug] Changed LRUCache, used by the mapper - to cache INSERT/UPDATE/DELETE statements, - to use an incrementing counter instead - of a timestamp to track entries, for greater - reliability versus using time.time(), which - can cause test failures on some platforms. - [ticket:2379] - - - [bug] Added a boolean check for the "finalize" - function within the pool connection proxy's - weakref callback before calling it, so that a - warning isn't emitted that this function is None - when the application is exiting and gc has - removed the function from the module before the - weakref callback was invoked. [ticket:2383] - -- Py3K - - [bug] Fixed inappropriate usage of util.py3k - flag and renamed it to util.py3k_warning, since - this flag is intended to detect the -3 flag - series of import restrictions only. - [ticket:2348] - -- examples - - [feature] Simplified the versioning example - a bit to use a declarative mixin as well - as an event listener, instead of a metaclass + - SessionExtension. [ticket:2313] - - - [bug] Fixed large_collection.py to close the - session before dropping tables. [ticket:2346] - -0.7.4 (December 9, 2011) -===== -- orm - - [bug] Fixed backref behavior when "popping" the - value off of a many-to-one in response to - a removal from a stale one-to-many - the operation - is skipped, since the many-to-one has since - been updated. [ticket:2315] - - - [bug] After some years of not doing this, added - more granularity to the "is X a parent of Y" - functionality, which is used when determining - if the FK on "Y" needs to be "nulled out" as well - as if "Y" should be deleted with delete-orphan - cascade. The test now takes into account the - Python identity of the parent as well its identity - key, to see if the last known parent of Y is - definitely X. If a decision - can't be made, a StaleDataError is raised. The - conditions where this error is raised are fairly - rare, requiring that the previous parent was - garbage collected, and previously - could very well inappropriately update/delete - a record that's since moved onto a new parent, - though there may be some cases where - "silent success" occurred previously that will now - raise in the face of ambiguity. - Expiring "Y" resets the "parent" tracker, meaning - X.remove(Y) could then end up deleting Y even - if X is stale, but this is the same behavior - as before; it's advised to expire X also in that - case. [ticket:2264] - - - [bug] fixed inappropriate evaluation of user-mapped - object in a boolean context within query.get() - [ticket:2310]. Also in 0.6.9. - - - [bug] Added missing comma to PASSIVE_RETURN_NEVER_SET - symbol [ticket:2304] - - - [bug] Cls.column.collate("some collation") now - works. [ticket:1776] Also in 0.6.9 - - - [bug] the value of a composite attribute is now - expired after an insert or update operation, instead - of regenerated in place. This ensures that a - column value which is expired within a flush - will be loaded first, before the composite - is regenerated using that value. [ticket:2309] - - - [bug] The fix in [ticket:2309] also emits the - "refresh" event when the composite value is - loaded on access, even if all column - values were already present, as is appropriate. - This fixes the "mutable" extension which relies - upon the "load" event to ensure the _parents - dictionary is up to date, fixes [ticket:2308]. - Thanks to Scott Torborg for the test case here. - - - [bug] Fixed bug whereby a subclass of a subclass - using concrete inheritance in conjunction with - the new ConcreteBase or AbstractConcreteBase - would fail to apply the subclasses deeper than - one level to the "polymorphic loader" of each - base [ticket:2312] - - - [bug] Fixed bug whereby a subclass of a subclass - using the new AbstractConcreteBase would fail - to acquire the correct "base_mapper" attribute - when the "base" mapper was generated, thereby - causing failures later on. [ticket:2312] - - - [bug] Fixed bug whereby column_property() created - against ORM-level column could be treated as - a distinct entity when producing certain - kinds of joined-inh joins. [ticket:2316] - - - [bug] Fixed the error formatting raised when - a tuple is inadvertently passed to session.query() - [ticket:2297]. Also in 0.6.9. - - - [bug] Calls to query.join() to a single-table - inheritance subclass are now tracked, and - are used to eliminate the additional WHERE.. - IN criterion normally tacked on with single - table inheritance, since the join should - accommodate it. This allows OUTER JOIN - to a single table subclass to produce - the correct results, and overall will produce - fewer WHERE criterion when dealing with - single table inheritance joins. - [ticket:2328] - - - [bug] __table_args__ can now be passed as - an empty tuple as well as an empty dict. - [ticket:2339]. Thanks to Fayaz Yusuf Khan - for the patch. - - - [bug] Updated warning message when setting - delete-orphan without delete to no longer - refer to 0.6, as we never got around to - upgrading this to an exception. Ideally - this might be better as an exception but - it's not critical either way. [ticket:2325] - - - [feature] polymorphic_on now accepts many - new kinds of values: - - - standalone expressions that aren't - otherwise mapped - - column_property() objects - - string names of any column_property() - or attribute name of a mapped Column - - The docs include an example using - the case() construct, which is likely to be - a common constructed used here. - [ticket:2345] and part of [ticket:2238] - - Standalone expressions in polymorphic_on - propagate to single-table inheritance - subclasses so that they are used in the - WHERE /JOIN clause to limit rows to that - subclass as is the usual behavior. - - - [feature] IdentitySet supports the - operator - as the same as difference(), handy when dealing - with Session.dirty etc. [ticket:2301] - - - [feature] Added new value for Column autoincrement - called "ignore_fk", can be used to force autoincrement - on a column that's still part of a ForeignKeyConstraint. - New example in the relationship docs illustrates - its use. - - - [bug] Fixed bug in get_history() when referring - to a composite attribute that has no value; - added coverage for get_history() regarding - composites which is otherwise just a userland - function. - -- sql - - [bug] related to [ticket:2316], made some - adjustments to the change from [ticket:2261] - regarding the "from" list on a select(). The - _froms collection is no longer memoized, as this - simplifies various use cases and removes the - need for a "warning" if a column is attached - to a table after it was already used in an - expression - the select() construct will now - always produce the correct expression. - There's probably no real-world - performance hit here; select() objects are - almost always made ad-hoc, and systems that - wish to optimize the re-use of a select() - would be using the "compiled_cache" feature. - A hit which would occur when calling select.bind - has been reduced, but the vast majority - of users shouldn't be using "bound metadata" - anyway :). - - - [feature] The update() construct can now accommodate - multiple tables in the WHERE clause, which will - render an "UPDATE..FROM" construct, recognized by - Postgresql and MSSQL. When compiled on MySQL, - will instead generate "UPDATE t1, t2, ..". MySQL - additionally can render against multiple tables in the - SET clause, if Column objects are used as keys - in the "values" parameter or generative method. - [ticket:2166] [ticket:1944] - - - [feature] Added accessor to types called "python_type", - returns the rudimentary Python type object - for a particular TypeEngine instance, if known, - else raises NotImplementedError. [ticket:77] - - - [bug] further tweak to the fix from [ticket:2261], - so that generative methods work a bit better - off of cloned (this is almost a non-use case though). - In particular this allows with_only_columns() - to behave more consistently. Added additional - documentation to with_only_columns() to clarify - expected behavior, which changed as a result - of [ticket:2261]. [ticket:2319] - -- engine - - [bug] Fixed bug whereby transaction.rollback() - would throw an error on an invalidated - connection if the transaction were a - two-phase or savepoint transaction. - For plain transactions, rollback() is a no-op - if the connection is invalidated, so while - it wasn't 100% clear if it should be a no-op, - at least now the interface is consistent. - [ticket:2317] - -- schema - - [feature] Added new support for remote "schemas": - - MetaData() accepts "schema" and "quote_schema" - arguments, which will be applied to the same-named - arguments of a Table - or Sequence which leaves these at their default - of ``None``. - - Sequence accepts "quote_schema" argument - - tometadata() for Table will use the "schema" - of the incoming MetaData for the new Table - if the schema argument is explicitly "None" - - Added CreateSchema and DropSchema DDL - constructs - these accept just the string - name of a schema and a "quote" flag. - - When using default "schema" with MetaData, - ForeignKey will also assume the "default" schema - when locating remote table. This allows the "schema" - argument on MetaData to be applied to any - set of Table objects that otherwise don't have - a "schema". - - a "has_schema" method has been implemented - on dialect, but only works on Postgresql so far. - Courtesy Manlio Perillo, [ticket:1679] - - - [feature] The "extend_existing" flag on Table - now allows for the reflection process to take - effect for a Table object that's already been - defined; when autoload=True and extend_existing=True - are both set, the full set of columns will be - reflected from the Table which will then - *overwrite* those columns already present, - rather than no activity occurring. Columns that - are present directly in the autoload run - will be used as always, however. - [ticket:1410] - - - [bug] Fixed bug whereby TypeDecorator would - return a stale value for _type_affinity, when - using a TypeDecorator that "switches" types, - like the CHAR/UUID type. - - - [bug] Fixed bug whereby "order_by='foreign_key'" - option to Inspector.get_table_names - wasn't implementing the sort properly, replaced - with the existing sort algorithm - - - [bug] the "name" of a column-level CHECK constraint, - if present, is now rendered in the CREATE TABLE - statement using "CONSTRAINT CHECK ". - [ticket:2305] - -- pyodbc - - [bug] pyodbc-based dialects now parse the - pyodbc accurately as far as observed - pyodbc strings, including such gems - as "py3-3.0.1-beta4" [ticket:2318] - -- postgresql - - [bug] Postgresql dialect memoizes that an ENUM of a - particular name was processed - during a create/drop sequence. This allows - a create/drop sequence to work without any - calls to "checkfirst", and also means with - "checkfirst" turned on it only needs to - check for the ENUM once. [ticket:2311] - - - [feature] Added create_type constructor argument - to pg.ENUM. When False, no CREATE/DROP or - checking for the type will be performed as part - of a table create/drop event; only the - create()/drop)() methods called directly - will do this. Helps with Alembic "offline" - scripts. - -- mssql - - [feature] lifted the restriction on SAVEPOINT - for SQL Server. All tests pass using it, - it's not known if there are deeper issues - however. [ticket:822] - - - [bug] repaired the with_hint() feature which - wasn't implemented correctly on MSSQL - - usually used for the "WITH (NOLOCK)" hint - (which you shouldn't be using anyway ! - use snapshot isolation instead :) ) - [ticket:2336] - - - [bug] use new pyodbc version detection for - _need_decimal_fix option, [ticket:2318] - - - [bug] don't cast "table name" as NVARCHAR - on SQL Server 2000. Still mostly in the dark - what incantations are needed to make PyODBC - work fully with FreeTDS 0.91 here, however. - [ticket:2343] - - - [bug] Decode incoming values when retrieving - list of index names and the names of columns - within those indexes. [ticket:2269] - -- mysql - - [bug] Unicode adjustments allow latest pymysql - (post 0.4) to pass 100% on Python 2. - -- ext - - [feature] Added an example to the hybrid docs - of a "transformer" - a hybrid that returns a - query-transforming callable in combination - with a custom comparator. Uses a new method - on Query called with_transformation(). The use - case here is fairly experimental, but only - adds one line of code to Query. - - - [bug] the @compiles decorator raises an - informative error message when no "default" - compilation handler is present, rather - than KeyError. - -- examples - - [bug] Fixed bug in history_meta.py example where - the "unique" flag was not removed from a - single-table-inheritance subclass which - generates columns to put up onto the base. - -0.7.3 -===== -- general - - Adjusted the "importlater" mechanism, which is - used internally to resolve import cycles, - such that the usage of __import__ is completed - when the import of sqlalchemy or sqlalchemy.orm - is done, thereby avoiding any usage of __import__ - after the application starts new threads, - fixes [ticket:2279]. Also in 0.6.9. - -- orm - - Improved query.join() such that the "left" side - can more flexibly be a non-ORM selectable, - such as a subquery. A selectable placed - in select_from() will now be used as the left - side, favored over implicit usage - of a mapped entity. - If the join still fails based on lack of - foreign keys, the error message includes - this detail. Thanks to brianrhude - on IRC for the test case. [ticket:2298] - - - Added after_soft_rollback() Session event. This - event fires unconditionally whenever rollback() - is called, regardless of if an actual DBAPI - level rollback occurred. This event - is specifically designed to allow operations - with the Session to proceed after a rollback - when the Session.is_active is True. - [ticket:2241] - - - added "adapt_on_names" boolean flag to orm.aliased() - construct. Allows an aliased() construct - to link the ORM entity to a selectable that contains - aggregates or other derived forms of a particular - attribute, provided the name is the same as that - of the entity mapped column. - - - Added new flag expire_on_flush=False to column_property(), - marks those properties that would otherwise be considered - to be "readonly", i.e. derived from SQL expressions, - to retain their value after a flush has occurred, including - if the parent object itself was involved in an update. - - - Enhanced the instrumentation in the ORM to support - Py3K's new argument style of "required kw arguments", - i.e. fn(a, b, *, c, d), fn(a, b, *args, c, d). - Argument signatures of mapped object's __init__ - method will be preserved, including required kw rules. - [ticket:2237] - - - Fixed bug in unit of work whereby detection of - "cycles" among classes in highly interlinked patterns - would not produce a deterministic - result; thereby sometimes missing some nodes that - should be considered cycles and causing further - issues down the road. Note this bug is in 0.6 - also; not backported at the moment. - [ticket:2282] - - - Fixed a variety of synonym()-related regressions - from 0.6: - - making a synonym against a synonym now works. - - synonyms made against a relationship() can - be passed to query.join(), options sent - to query.options(), passed by name - to query.with_parent(). - - - Fixed bug whereby mapper.order_by attribute would - be ignored in the "inner" query within a - subquery eager load. [ticket:2287]. - Also in 0.6.9. - - - Identity map .discard() uses dict.pop(,None) - internally instead of "del" to avoid KeyError/warning - during a non-determinate gc teardown [ticket:2267] - - - Fixed regression in new composite rewrite where - deferred=True option failed due to missing - import [ticket:2253] - - - Reinstated "comparator_factory" argument to - composite(), removed when 0.7 was released. - [ticket:2248] - - - Fixed bug in query.join() which would occur - in a complex multiple-overlapping path scenario, - where the same table could be joined to - twice. Thanks *much* to Dave Vitek - for the excellent fix here. [ticket:2247] - - - Query will convert an OFFSET of zero when - slicing into None, so that needless OFFSET - clauses are not invoked. - - - Repaired edge case where mapper would fail - to fully update internal state when a relationship - on a new mapper would establish a backref on the - first mapper. - - - Fixed bug whereby if __eq__() was - redefined, a relationship many-to-one lazyload - would hit the __eq__() and fail. [ticket:2260] - Does not apply to 0.6.9. - - - Calling class_mapper() and passing in an object - that is not a "type" (i.e. a class that could - potentially be mapped) now raises an informative - ArgumentError, rather than UnmappedClassError. - [ticket:2196] - - - New event hook, MapperEvents.after_configured(). - Called after a configure() step has completed and - mappers were in fact affected. Theoretically this - event is called once per application, unless new mappings - are constructed after existing ones have been used - already. - - - When an open Session is garbage collected, the objects - within it which remain are considered detached again - when they are add()-ed to a new Session. - This is accomplished by an extra check that the previous - "session_key" doesn't actually exist among the pool - of Sessions. [ticket:2281] - - - New declarative features: - - __declare_last__() method, establishes an event - listener for the class method that will be called - when mappers are completed with the final "configure" - step. - - __abstract__ flag. The class will not be mapped - at all when this flag is present on the class. - - New helper classes ConcreteBase, AbstractConcreteBase. - Allow concrete mappings using declarative which automatically - set up the "polymorphic_union" when the "configure" - mapper step is invoked. - - The mapper itself has semi-private methods that allow - the "with_polymorphic" selectable to be assigned - to the mapper after it has already been configured. - [ticket:2239] - - - Declarative will warn when a subclass' base uses - @declared_attr for a regular column - this attribute - does not propagate to subclasses. [ticket:2283] - - - The integer "id" used to link a mapped instance with - its owning Session is now generated by a sequence - generation function rather than id(Session), to - eliminate the possibility of recycled id() values - causing an incorrect result, no need to check that - object actually in the session. [ticket:2280] - --sql - - Behavioral improvement: empty - conjunctions such as and_() and or_() will be - flattened in the context of an enclosing conjunction, - i.e. and_(x, or_()) will produce 'X' and not 'X AND - ()'. [ticket:2257]. - - - Fixed bug regarding calculation of "from" list - for a select() element. The "from" calc is now - delayed, so that if the construct uses a Column - object that is not yet attached to a Table, - but is later associated with a Table, it generates - SQL using the table as a FROM. This change - impacted fairly deeply the mechanics of how - the FROM list as well as the "correlates" collection - is calculated, as some "clause adaption" schemes - (these are used very heavily in the ORM) - were relying upon the fact that the "froms" - collection would typically be cached before the - adaption completed. The rework allows it - such that the "froms" collection can be cleared - and re-generated at any time. [ticket:2261] - - - Fixed bug whereby with_only_columns() method of - Select would fail if a selectable were passed. - [ticket:2270]. Also in 0.6.9. - -- schema - - Modified Column.copy() to use _constructor(), - which defaults to self.__class__, in order to - create the new object. This allows easier support - of subclassing Column. [ticket:2284] - - - Added a slightly nicer __repr__() to SchemaItem - classes. Note the repr here can't fully support - the "repr is the constructor" idea since schema - items can be very deeply nested/cyclical, have - late initialization of some things, etc. - [ticket:2223] - -- engine - - The recreate() method in all pool classes uses - self.__class__ to get at the type of pool - to produce, in the case of subclassing. Note - there's no usual need to subclass pools. - [ticket:2254] - - - Improvement to multi-param statement logging, - long lists of bound parameter sets will be - compressed with an informative indicator - of the compression taking place. Exception - messages use the same improved formatting. - [ticket:2243] - - - Added optional "sa_pool_key" argument to - pool.manage(dbapi).connect() so that serialization - of args is not necessary. - - - The entry point resolution supported by - create_engine() now supports resolution of - individual DBAPI drivers on top of a built-in - or entry point-resolved dialect, using the - standard '+' notation - it's converted to - a '.' before being resolved as an entry - point. [ticket:2286] - - - Added an exception catch + warning for the - "return unicode detection" step within connect, - allows databases that crash on NVARCHAR to - continue initializing, assuming no NVARCHAR - type implemented. [ticket:2299] - -- types - - Extra keyword arguments to the base Float - type beyond "precision" and "asdecimal" are ignored; - added a deprecation warning here and additional - docs, related to [ticket:2258] - -- sqlite - - Ensured that the same ValueError is raised for - illegal date/time/datetime string parsed from - the database regardless of whether C - extensions are in use or not. - -- postgresql - - Added "postgresql_using" argument to Index(), produces - USING clause to specify index implementation for - PG. [ticket:2290]. Thanks to Ryan P. Kelly for - the patch. - - - Added client_encoding parameter to create_engine() - when the postgresql+psycopg2 dialect is used; - calls the psycopg2 set_client_encoding() method - with the value upon connect. [ticket:1839] - - - Fixed bug related to [ticket:2141] whereby the - same modified index behavior in PG 9 affected - primary key reflection on a renamed column. - [ticket:2291]. Also in 0.6.9. - - - Reflection functions for Table, Sequence no longer - case insensitive. Names can be differ only in case - and will be correctly distinguished. [ticket:2256] - - - Use an atomic counter as the "random number" - source for server side cursor names; - conflicts have been reported in rare cases. - - - Narrowed the assumption made when reflecting - a foreign-key referenced table with schema in - the current search path; an explicit schema will - be applied to the referenced table only if - it actually matches that of the referencing table, - which also has an explicit schema. Previously - it was assumed that "current" schema was synonymous - with the full search_path. [ticket:2249] - -- mysql - - a CREATE TABLE will put the COLLATE option - after CHARSET, which appears to be part of - MySQL's arbitrary rules regarding if it will actually - work or not. [ticket:2225] Also in 0.6.9. - - - Added mysql_length parameter to Index construct, - specifies "length" for indexes. [ticket:2293] - -- mssql - - Changes to attempt support of FreeTDS 0.91 with - Pyodbc. This includes that string binds are sent as - Python unicode objects when FreeTDS 0.91 is detected, - and a CAST(? AS NVARCHAR) is used when we detect - for a table. However, I'd continue - to characterize Pyodbc + FreeTDS 0.91 behavior as - pretty crappy, there are still many queries such - as used in reflection which cause a core dump on - Linux, and it is not really usable at all - on OSX, MemoryErrors abound and just plain broken - unicode support. [ticket:2273] - - - The behavior of =/!= when comparing a scalar select - to a value will no longer produce IN/NOT IN as of 0.8; - this behavior is a little too heavy handed (use in_() if - you want to emit IN) and now emits a deprecation warning. - To get the 0.8 behavior immediately and remove the warning, - a compiler recipe is given at - http://www.sqlalchemy.org/docs/07/dialects/mssql.html#scalar-select-comparisons - to override the behavior of visit_binary(). - [ticket:2277] - - - "0" is accepted as an argument for limit() which - will produce "TOP 0". [ticket:2222] - -- oracle - - Fixed ReturningResultProxy for zxjdbc dialect. - [ticket:2272]. Regression from 0.6. - - - The String type now generates VARCHAR2 on Oracle - which is recommended as the default VARCHAR. - Added an explicit VARCHAR2 and NVARCHAR2 to the Oracle - dialect as well. Using NVARCHAR still generates - "NVARCHAR2" - there is no "NVARCHAR" on Oracle - - this remains a slight breakage of the "uppercase types - always give exactly that" policy. VARCHAR still - generates "VARCHAR", keeping with the policy. If - Oracle were to ever define "VARCHAR" as something - different as they claim (IMHO this will never happen), - the type would be available. [ticket:2252] - -- ext - - SQLSoup will not be included in version 0.8 - of SQLAlchemy; while useful, we would like to - keep SQLAlchemy itself focused on one ORM - usage paradigm. SQLSoup will hopefully - soon be superseded by a third party - project. [ticket:2262] - - - Added local_attr, remote_attr, attr accessors - to AssociationProxy, providing quick access - to the proxied attributes at the class - level. [ticket:2236] - - - Changed the update() method on association proxy - dictionary to use a duck typing approach, i.e. - checks for "keys", to discern between update({}) - and update((a, b)). Previously, passing a - dictionary that had tuples as keys would be misinterpreted - as a sequence. [ticket:2275] - -- examples - - Adjusted dictlike-polymorphic.py example - to apply the CAST such that it works on - PG, other databases. [ticket:2266] - Also in 0.6.9. - -0.7.2 -===== -- orm - - Feature enhancement: joined and subquery - loading will now traverse already-present related - objects and collections in search of unpopulated - attributes throughout the scope of the eager load - being defined, so that the eager loading that is - specified via mappings or query options - unconditionally takes place for the full depth, - populating whatever is not already populated. - Previously, this traversal would stop if a related - object or collection were already present leading - to inconsistent behavior (though would save on - loads/cycles for an already-loaded graph). For a - subqueryload, this means that the additional - SELECT statements emitted by subqueryload will - invoke unconditionally, no matter how much of the - existing graph is already present (hence the - controversy). The previous behavior of "stopping" - is still in effect when a query is the result of - an attribute-initiated lazyload, as otherwise an - "N+1" style of collection iteration can become - needlessly expensive when the same related object - is encountered repeatedly. There's also an - as-yet-not-public generative Query method - _with_invoke_all_eagers() - which selects old/new behavior [ticket:2213] - - - A rework of "replacement traversal" within - the ORM as it alters selectables to be against - aliases of things (i.e. clause adaption) includes - a fix for multiply-nested any()/has() constructs - against a joined table structure. [ticket:2195] - - - Fixed bug where query.join() + aliased=True - from a joined-inh structure to itself on - relationship() with join condition on the child - table would convert the lead entity into the - joined one inappropriately. [ticket:2234] - Also in 0.6.9. - - - Fixed regression from 0.6 where Session.add() - against an object which contained None in a - collection would raise an internal exception. - Reverted this to 0.6's behavior which is to - accept the None but obviously nothing is - persisted. Ideally, collections with None - present or on append() should at least emit a - warning, which is being considered for 0.8. - [ticket:2205] - - - Load of a deferred() attribute on an object - where row can't be located raises - ObjectDeletedError instead of failing later - on; improved the message in ObjectDeletedError - to include other conditions besides a simple - "delete". [ticket:2191] - - - Fixed regression from 0.6 where a get history - operation on some relationship() based attributes - would fail when a lazyload would emit; this could - trigger within a flush() under certain conditions. - [ticket:2224] Thanks to the user who submitted - the great test for this. - - - Fixed bug apparent only in Python 3 whereby - sorting of persistent + pending objects during - flush would produce an illegal comparison, - if the persistent object primary key - is not a single integer. [ticket:2228] - Also in 0.6.9 - - - Fixed bug whereby the source clause - used by query.join() would be inconsistent - if against a column expression that combined - multiple entities together. [ticket:2197] - Also in 0.6.9 - - - Fixed bug whereby if a mapped class - redefined __hash__() or __eq__() to something - non-standard, which is a supported use case - as SQLA should never consult these, - the methods would be consulted if the class - was part of a "composite" (i.e. non-single-entity) - result set. [ticket:2215] - Also in 0.6.9. - - - Added public attribute ".validators" to - Mapper, an immutable dictionary view of - all attributes that have been decorated - with the @validates decorator. - [ticket:2240] courtesy Stefano Fontanelli - - - Fixed subtle bug that caused SQL to blow - up if: column_property() against subquery + - joinedload + LIMIT + order by the column - property() occurred. [ticket:2188]. - Also in 0.6.9 - - - The join condition produced by with_parent - as well as when using a "dynamic" relationship - against a parent will generate unique - bindparams, rather than incorrectly repeating - the same bindparam. [ticket:2207]. - Also in 0.6.9. - - - Added the same "columns-only" check to - mapper.polymorphic_on as used when - receiving user arguments to - relationship.order_by, foreign_keys, - remote_side, etc. - - - Fixed bug whereby comparison of column - expression to a Query() would not call - as_scalar() on the underlying SELECT - statement to produce a scalar subquery, - in the way that occurs if you called - it on Query().subquery(). [ticket:2190] - - - Fixed declarative bug where a class inheriting - from a superclass of the same name would fail - due to an unnecessary lookup of the name - in the _decl_class_registry. [ticket:2194] - - - Repaired the "no statement condition" - assertion in Query which would attempt - to raise if a generative method were called - after from_statement() were called. - [ticket:2199]. Also in 0.6.9. - -- sql - - Fixed two subtle bugs involving column - correspondence in a selectable, - one with the same labeled subquery repeated, the other - when the label has been "grouped" and - loses itself. Affects [ticket:2188]. - -- schema - - New feature: with_variant() method on - all types. Produces an instance of Variant(), - a special TypeDecorator which will select - the usage of a different type based on the - dialect in use. [ticket:2187] - - - Added an informative error message when - ForeignKeyConstraint refers to a column name in - the parent that is not found. Also in 0.6.9. - - - Fixed bug whereby adaptation of old append_ddl_listener() - function was passing unexpected **kw through - to the Table event. Table gets no kws, the MetaData - event in 0.6 would get "tables=somecollection", - this behavior is preserved. [ticket:2206] - - - Fixed bug where "autoincrement" detection on - Table would fail if the type had no "affinity" - value, in particular this would occur when using - the UUID example on the site that uses TypeEngine - as the "impl". - - - Added an improved repr() to TypeEngine objects - that will only display constructor args which - are positional or kwargs that deviate - from the default. [ticket:2209] - -- engine - - Context manager provided by Connection.begin() - will issue rollback() if the commit() fails, - not just if an exception occurs. - - - Use urllib.parse_qsl() in Python 2.6 and above, - no deprecation warning about cgi.parse_qsl() - [ticket:1682] - - - Added mixin class sqlalchemy.ext.DontWrapMixin. - User-defined exceptions of this type are never - wrapped in StatementException when they - occur in the context of a statement - execution. - - - StatementException wrapping will display the - original exception class in the message. - - - Failures on connect which raise dbapi.Error - will forward the error to dialect.is_disconnect() - and set the "connection_invalidated" flag if - the dialect knows this to be a potentially - "retryable" condition. Only Oracle ORA-01033 - implemented for now. [ticket:2201] - -- sqlite - - SQLite dialect no longer strips quotes - off of reflected default value, allowing - a round trip CREATE TABLE to work. - This is consistent with other dialects - that also maintain the exact form of - the default. [ticket:2189] - -- postgresql - - Added new "postgresql_ops" argument to - Index, allows specification of PostgreSQL - operator classes for indexed columns. - [ticket:2198] Courtesy Filip Zyzniewski. - -- mysql - - Fixed OurSQL dialect to use ansi-neutral - quote symbol "'" for XA commands instead - of '"'. [ticket:2186]. Also in 0.6.9. - -- mssql - - Adjusted the pyodbc dialect such that bound - values are passed as bytes and not unicode - if the "Easysoft" unix drivers are detected. - This is the same behavior as occurs with - FreeTDS. Easysoft appears to segfault - if Python unicodes are passed under - certain circumstances. - -- oracle - - Added ORA-00028 to disconnect codes, use - cx_oracle _Error.code to get at the code, - [ticket:2200]. Also in 0.6.9. - - - Added ORA-01033 to disconnect codes, which - can be caught during a connection - event. [ticket:2201] - - - repaired the oracle.RAW type which did not - generate the correct DDL. [ticket:2220] - Also in 0.6.9. - - - added CURRENT to reserved word list. - [ticket:2212] Also in 0.6.9. - --ext - - Fixed bug in the mutable extension whereby - if the same type were used twice in one - mapping, the attributes beyond the first - would not get instrumented. - - - Fixed bug in the mutable extension whereby - if None or a non-corresponding type were set, - an error would be raised. None is now accepted - which assigns None to all attributes, - illegal values raise ValueError. - -- examples - - Repaired the examples/versioning test runner - to not rely upon SQLAlchemy test libs, - nosetests must be run from within - examples/versioning to get around setup.cfg - breaking it. - - - Tweak to examples/versioning to pick the - correct foreign key in a multi-level - inheritance situation. - - - Fixed the attribute shard example to check - for bind param callable correctly in 0.7 - style. - -0.7.1 -===== -- general - - Added a workaround for Python bug 7511 where - failure of C extension build does not - raise an appropriate exception on Windows 64 - bit + VC express [ticket:2184] - -- orm - - "delete-orphan" cascade is now allowed on - self-referential relationships - this since - SQLA 0.7 no longer enforces "parent with no - child" at the ORM level; this check is left - up to foreign key nullability. - Related to [ticket:1912] - - - Repaired new "mutable" extension to propagate - events to subclasses correctly; don't - create multiple event listeners for - subclasses either. [ticket:2180] - - - Modify the text of the message which occurs - when the "identity" key isn't detected on - flush, to include the common cause that - the Column isn't set up to detect - auto-increment correctly; [ticket:2170]. - Also in 0.6.8. - - - Fixed bug where transaction-level "deleted" - collection wouldn't be cleared of expunged - states, raising an error if they later - became transient [ticket:2182]. - Also in 0.6.8. - -- sql - - Fixed bug whereby metadata.reflect(bind) - would close a Connection passed as a - bind argument. Regression from 0.6. - - - Streamlined the process by which a Select - determines what's in it's '.c' collection. - Behaves identically, except that a - raw ClauseList() passed to select([]) - (which is not a documented case anyway) will - now be expanded into its individual column - elements instead of being ignored. - -- engine - - Deprecate schema/SQL-oriented methods on - Connection/Engine that were never well known - and are redundant: reflecttable(), create(), - drop(), text(), engine.func - - - Adjusted the __contains__() method of - a RowProxy result row such that no exception - throw is generated internally; - NoSuchColumnError() also will generate its - message regardless of whether or not the column - construct can be coerced to a string. - [ticket:2178]. Also in 0.6.8. - -- sqlite - - Accept None from cursor.fetchone() when - "PRAGMA read_uncommitted" is called to determine - current isolation mode at connect time and - default to SERIALIZABLE; this to support SQLite - versions pre-3.3.0 that did not have this - feature. [ticket:2173] - -- postgresql - - Some unit test fixes regarding numeric arrays, - MATCH operator. A potential floating-point - inaccuracy issue was fixed, and certain tests - of the MATCH operator only execute within an - EN-oriented locale for now. [ticket:2175]. - Also in 0.6.8. - -- mysql - - Unit tests pass 100% on MySQL installed - on windows. - - - Removed the "adjust casing" step that would - fail when reflecting a table on MySQL - on windows with a mixed case name. After some - experimenting with a windows MySQL server, it's - been determined that this step wasn't really - helping the situation much; MySQL does not return - FK names with proper casing on non-windows - platforms either, and removing the step at - least allows the reflection to act more like - it does on other OSes. A warning here - has been considered but its difficult to - determine under what conditions such a warning - can be raised, so punted on that for now - - added some docs instead. [ticket:2181] - - - supports_sane_rowcount will be set to False - if using MySQLdb and the DBAPI doesn't provide - the constants.CLIENT module. - -0.7.0 -======= -- This section documents those changes from 0.7b4 - to 0.7.0. For an overview of what's new in - SQLAlchemy 0.7, see - http://www.sqlalchemy.org/trac/wiki/07Migration - -- orm - - Fixed regression introduced in 0.7b4 (!) whereby - query.options(someoption("nonexistent name")) would - fail to raise an error. Also added additional - error catching for cases where the option would - try to build off a column-based element, further - fixed up some of the error messages tailored - in [ticket:2069] - - - query.count() emits "count(*)" instead of - "count(1)". [ticket:2162] - - - Fine tuning of Query clause adaptation when - from_self(), union(), or other "select from - myself" operation, such that plain SQL expression - elements added to filter(), order_by() etc. - which are present in the nested "from myself" - query *will* be adapted in the same way an ORM - expression element will, since these - elements are otherwise not easily accessible. - [ticket:2155] - - - Fixed bug where determination of "self referential" - relationship would fail with no workaround - for joined-inh subclass related to itself, - or joined-inh subclass related to a subclass - of that with no cols in the sub-sub class - in the join condition. [ticket:2149] - Also in 0.6.8. - - - mapper() will ignore non-configured foreign keys - to unrelated tables when determining inherit - condition between parent and child class, - but will raise as usual for unresolved - columns and table names regarding the inherited - table. This is an enhanced generalization of - behavior that was already applied to declarative - previously. [ticket:2153] 0.6.8 has a more - conservative version of this which doesn't - fundamentally alter how join conditions - are determined. - - - It is an error to call query.get() when the - given entity is not a single, full class - entity or mapper (i.e. a column). This is - a deprecation warning in 0.6.8. - [ticket:2144] - - - Fixed a potential KeyError which under some - circumstances could occur with the identity - map, part of [ticket:2148] - - - added Query.with_session() method, switches - Query to use a different session. - - - horizontal shard query should use execution - options per connection as per [ticket:2131] - - - a non_primary mapper will inherit the _identity_class - of the primary mapper. This so that a non_primary - established against a class that's normally in an - inheritance mapping will produce results that are - identity-map compatible with that of the primary - mapper [ticket:2151] (also in 0.6.8) - - - Fixed the error message emitted for "can't - execute syncrule for destination column 'q'; - mapper 'X' does not map this column" to - reference the correct mapper. [ticket:2163]. - Also in 0.6.8. - - - polymorphic_union() gets a "cast_nulls" option, - disables the usage of CAST when it renders - the labeled NULL columns. [ticket:1502] - - - polymorphic_union() renders the columns in their - original table order, as according to the first - table/selectable in the list of polymorphic - unions in which they appear. (which is itself - an unordered mapping unless you pass an OrderedDict). - - - Fixed bug whereby mapper mapped to an anonymous - alias would fail if logging were used, due to - unescaped % sign in the alias name. [ticket:2171] - Also in 0.6.8. - -- sql - - Fixed bug whereby nesting a label of a select() - with another label in it would produce incorrect - exported columns. Among other things this would - break an ORM column_property() mapping against - another column_property(). [ticket:2167]. - Also in 0.6.8 - - - Changed the handling in determination of join - conditions such that foreign key errors are - only considered between the two given tables. - That is, t1.join(t2) will report FK errors - that involve 't1' or 't2', but anything - involving 't3' will be skipped. This affects - join(), as well as ORM relationship and - inherit condition logic. - - - Some improvements to error handling inside - of the execute procedure to ensure auto-close - connections are really closed when very - unusual DBAPI errors occur. - - - metadata.reflect() and reflection.Inspector() - had some reliance on GC to close connections - which were internally procured, fixed this. - - - Added explicit check for when Column .name - is assigned as blank string [ticket:2140] - - - Fixed bug whereby if FetchedValue was passed - to column server_onupdate, it would not - have its parent "column" assigned, added - test coverage for all column default assignment - patterns. [ticket:2147] also in 0.6.8 - -- postgresql - - Fixed the psycopg2_version parsing in the - psycopg2 dialect. - - - Fixed bug affecting PG 9 whereby index reflection - would fail if against a column whose name - had changed. [ticket:2141]. Also in 0.6.8. - -- mssql - - Fixed bug in MSSQL dialect whereby the aliasing - applied to a schema-qualified table would leak - into enclosing select statements [ticket:2169]. - Also in 0.6.8. - -- documentation - - Removed the usage of the "collections.MutableMapping" - abc from the ext.mutable docs as it was being used - incorrectly and makes the example more difficult - to understand in any case. [ticket:2152] - -- examples - - removed the ancient "polymorphic association" - examples and replaced with an updated set of - examples that use declarative mixins, - "generic_associations". Each presents an alternative - table layout. - -- ext - - Fixed bugs in sqlalchemy.ext.mutable extension where - `None` was not appropriately handled, replacement - events were not appropriately handled. - [ticket:2143] - -0.7.0b4 -======= -- general - - Changes to the format of CHANGES, this file. - The format changes have been applied to - the 0.7 releases. - - - The "-declarative" changes will now be listed - directly under the "-orm" section, as these - are closely related. - - - The 0.5 series changes have been moved to - the file CHANGES_PRE_06 which replaces - CHANGES_PRE_05. - - - The changelog for 0.6.7 and subsequent within - the 0.6 series is now listed only in the - CHANGES file within the 0.6 branch. - In the 0.7 CHANGES file (i.e. this file), all the - 0.6 changes are listed inline within the 0.7 - section in which they were also applied - (since all 0.6 changes are in 0.7 as well). - Changes that apply to an 0.6 version here - are noted as are if any differences in - implementation/behavior are present. - -- orm - - Some fixes to "evaulate" and "fetch" evaluation - when query.update(), query.delete() are called. - The retrieval of records is done after autoflush - in all cases, and before update/delete is - emitted, guarding against unflushed data present - as well as expired objects failing during - the evaluation. [ticket:2122] - - - Reworded the exception raised when a flush - is attempted of a subclass that is not polymorphic - against the supertype. [ticket:2063] - - - Still more wording adjustments when a query option - can't find the target entity. Explain that the - path must be from one of the root entities. - - - Some fixes to the state handling regarding - backrefs, typically when autoflush=False, where - the back-referenced collection wouldn't - properly handle add/removes with no net - change. Thanks to Richard Murri for the - test case + patch. [ticket:2123] - (also in 0.6.7). - - - Added checks inside the UOW to detect the unusual - condition of being asked to UPDATE or DELETE - on a primary key value that contains NULL - in it. [ticket:2127] - - - Some refinements to attribute history. More - changes are pending possibly in 0.8, but - for now history has been modified such that - scalar history doesn't have a "side effect" - of populating None for a non-present value. - This allows a slightly better ability to - distinguish between a None set and no actual - change, affects [ticket:2127] as well. - - - a "having" clause would be copied from the - inside to the outside query if from_self() - were used; in particular this would break - an 0.7 style count() query [ticket:2130]. - (also in 0.6.7) - - - the Query.execution_options() method now passes - those options to the Connection rather than - the SELECT statement, so that all available - options including isolation level and - compiled cache may be used. [ticket:2131] - -- sql - - The "compiled_cache" execution option now raises - an error when passed to a SELECT statement - rather than a Connection. Previously it was - being ignored entirely. We may look into - having this option work on a per-statement - level at some point. [ticket:2131] - - - Restored the "catchall" constructor on the base - TypeEngine class, with a deprecation warning. - This so that code which does something like - Integer(11) still succeeds. - - - Fixed regression whereby MetaData() coming - back from unpickling did not keep track of - new things it keeps track of now, i.e. - collection of Sequence objects, list - of schema names. [ticket:2104] - - - The limit/offset keywords to select() as well - as the value passed to select.limit()/offset() - will be coerced to integer. [ticket:2116] - (also in 0.6.7) - - - fixed bug where "from" clause gathering from an - over() clause would be an itertools.chain() and - not a list, causing "can only concatenate list" - TypeError when combined with other clauses. - - - Fixed incorrect usage of "," in over() clause - being placed between the "partition" and "order by" - clauses. [ticket:2134] - - - Before/after attach events for PrimaryKeyConstraint - now function, tests added for before/after events - on all constraint types. [ticket:2105] - - - Added explicit true()/false() constructs to expression - lib - coercion rules will intercept "False"/"True" - into these constructs. In 0.6, the constructs were - typically converted straight to string, which was - no longer accepted in 0.7. [ticket:2117] - -- engine - - The C extension is now enabled by default on CPython - 2.x with a fallback to pure python if it fails to - compile. [ticket:2129] - -- schema - - The 'useexisting' flag on Table has been superceded - by a new pair of flags 'keep_existing' and - 'extend_existing'. 'extend_existing' is equivalent - to 'useexisting' - the existing Table is returned, - and additional constructor elements are added. - With 'keep_existing', the existing Table is returned, - but additional constructor elements are not added - - these elements are only applied when the Table - is newly created. [ticket:2109] - -- types - - REAL has been added to the core types. Supported - by Postgresql, SQL Server, MySQL, SQLite. Note - that the SQL Server and MySQL versions, which - add extra arguments, are also still available - from those dialects. [ticket:2081] - --event - - Added @event.listens_for() decorator, given - target + event name, applies the decorated - function as a listener. [ticket:2106] - -- pool - - AssertionPool now stores the traceback indicating - where the currently checked out connection was - acquired; this traceback is reported within - the assertion raised upon a second concurrent - checkout; courtesy Gunnlaugur Briem - [ticket:2103] - - - The "pool.manage" feature doesn't use pickle - anymore to hash the arguments for each pool. - -- sqlite - - Fixed bug where reflection of foreign key - created as "REFERENCES " without - col name would fail. [ticket:2115] - (also in 0.6.7) - -- postgresql - - Psycopg2 for Python 3 is now supported. - - - Fixed support for precision numerics when using - pg8000. [ticket:2132] - -- oracle - - Using column names that would require quotes - for the column itself or for a name-generated - bind parameter, such as names with special - characters, underscores, non-ascii characters, - now properly translate bind parameter keys when - talking to cx_oracle. [ticket:2100] (Also - in 0.6.7) - - - Oracle dialect adds use_binds_for_limits=False - create_engine() flag, will render the LIMIT/OFFSET - values inline instead of as binds, reported to - modify the execution plan used by Oracle. - [ticket:2116] (Also in 0.6.7) - -- documentation - - Documented SQLite DATE/TIME/DATETIME types. - [ticket:2029] (also in 0.6.7) - - - Fixed mutable extension docs to show the - correct type-association methods. - [ticket:2118] - -0.7.0b3 -======= -- general - - Lots of fixes to unit tests when run under Pypy - (courtesy Alex Gaynor). - -- orm - - Changed the underlying approach to query.count(). - query.count() is now in all cases exactly: - - query. - from_self(func.count(literal_column('1'))). - scalar() - - That is, "select count(1) from ()". - This produces a subquery in all cases, but - vastly simplifies all the guessing count() - tried to do previously, which would still - fail in many scenarios particularly when - joined table inheritance and other joins - were involved. If the subquery produced - for an otherwise very simple count is really - an issue, use query(func.count()) as an - optimization. [ticket:2093] - - - some changes to the identity map regarding - rare weakref callbacks during iterations. - The mutex has been removed as it apparently - can cause a reentrant (i.e. in one thread) deadlock, - perhaps when gc collects objects at the point of - iteration in order to gain more memory. It is hoped - that "dictionary changed during iteration" will - be exceedingly rare as iteration methods internally - acquire the full list of objects in a single values() - call. Note 0.6.7 has a more conservative fix here - which still keeps the mutex in place. [ticket:2087] - - - A tweak to the unit of work causes it to order - the flush along relationship() dependencies even if - the given objects don't have any inter-attribute - references in memory, which was the behavior in - 0.5 and earlier, so a flush of Parent/Child with - only foreign key/primary key set will succeed. - This while still maintaining 0.6 and above's not - generating a ton of useless internal dependency - structures within the flush that don't correspond - to state actually within the current flush. - [ticket:2082] - - - Improvements to the error messages emitted when - querying against column-only entities in conjunction - with (typically incorrectly) using loader options, - where the parent entity is not fully present. - [ticket:2069] - - - Fixed bug in query.options() whereby a path - applied to a lazyload using string keys could - overlap a same named attribute on the wrong - entity. Note 0.6.7 has a more conservative fix - to this. [ticket:2098] - -- declarative - - Arguments in __mapper_args__ that aren't "hashable" - aren't mistaken for always-hashable, possibly-column - arguments. [ticket:2091] (also in 0.6.7) - -- sql - - Added a fully descriptive error message for the - case where Column is subclassed and _make_proxy() - fails to make a copy due to TypeError on the - constructor. The method _constructor should - be implemented in this case. - - - Added new event "column_reflect" for Table objects. - Receives the info dictionary about a Column before - the object is generated within reflection, and allows - modification to the dictionary for control over - most aspects of the resulting Column including - key, name, type, info dictionary. [ticket:2095] - - - To help with the "column_reflect" event being used - with specific Table objects instead of all instances - of Table, listeners can be added to a Table object - inline with its construction using a new argument - "listeners", a list of tuples of the form - (, ), which are applied to the Table - before the reflection process begins. - - - Added new generic function "next_value()", accepts - a Sequence object as its argument and renders the - appropriate "next value" generation string on the - target platform, if supported. Also provides - ".next_value()" method on Sequence itself. - [ticket:2085] - - - func.next_value() or other SQL expression can - be embedded directly into an insert() construct, - and if implicit or explicit "returning" is used - in conjunction with a primary key column, - the newly generated value will be present in - result.inserted_primary_key. [ticket:2084] - - - Added accessors to ResultProxy "returns_rows", - "is_insert" [ticket:2089] (also in 0.6.7) - -- engine - - Fixed AssertionPool regression bug. [ticket:2097] - - - Changed exception raised to ArgumentError when an - invalid dialect is specified. [ticket:2060] - -- postgresql - - Added RESERVED_WORDS for postgresql dialect. [ticket:2092] - (also in 0.6.7) - - - Fixed the BIT type to allow a "length" parameter, "varying" - parameter. Reflection also fixed. [ticket:2073] - (also in 0.6.7) - -- mssql - - Rewrote the query used to get the definition of a view, - typically when using the Inspector interface, to - use sys.sql_modules instead of the information schema, - thereby allowing views definitions longer than 4000 - characters to be fully returned. [ticket:2071] - (also in 0.6.7) - -- firebird - - The "implicit_returning" flag on create_engine() is - honored if set to False. [ticket:2083] (also in 0.6.7) - -- informix - - - Added RESERVED_WORDS informix dialect. [ticket:2092] - (also in 0.6.7) - -- ext - - The horizontal_shard ShardedSession class accepts the common - Session argument "query_cls" as a constructor argument, - to enable further subclassing of ShardedQuery. - [ticket:2090] (also in 0.6.7) - -- examples - - Updated the association, association proxy examples - to use declarative, added a new example - dict_of_sets_with_default.py, a "pushing the envelope" - example of association proxy. - - - The Beaker caching example allows a "query_cls" argument - to the query_callable() function. [ticket:2090] - (also in 0.6.7) - -0.7.0b2 -======== -- orm - - Fixed bug whereby Session.merge() would call the - load() event with one too few arguments. - [ticket:2053] - - - Added logic which prevents the generation of - events from a MapperExtension or SessionExtension - from generating do-nothing events for all the methods - not overridden. [ticket:2052] - -- declarative - - Fixed regression whereby composite() with - Column objects placed inline would fail - to initialize. The Column objects can now - be inline with the composite() or external - and pulled in via name or object ref. - [ticket:2058] - - - Fix error message referencing old @classproperty - name to reference @declared_attr [ticket:2061] - (also in 0.6.7) - - - the dictionary at the end of the __table_args__ - tuple is now optional. [ticket:1468] - -- sql - - Renamed the EngineEvents event class to - ConnectionEvents. As these classes are never - accessed directly by end-user code, this strictly - is a documentation change for end users. Also - simplified how events get linked to engines - and connections internally. [ticket:2059] - - - The Sequence() construct, when passed a MetaData() - object via its 'metadata' argument, will be - included in CREATE/DROP statements within - metadata.create_all() and metadata.drop_all(), - including "checkfirst" logic. [ticket:2055] - - - The Column.references() method now returns True - if it has a foreign key referencing the - given column exactly, not just it's parent - table. [ticket:2064] - -- postgresql - - Fixed regression from 0.6 where SMALLINT and - BIGINT types would both generate SERIAL - on an integer PK column, instead of - SMALLINT and BIGSERIAL [ticket:2065] - -- ext - - Association proxy now has correct behavior for - any(), has(), and contains() when proxying - a many-to-one scalar attribute to a one-to-many - collection (i.e. the reverse of the 'typical' - association proxy use case) [ticket:2054] - -- examples - - Beaker example now takes into account 'limit' - and 'offset', bind params within embedded - FROM clauses (like when you use union() or - from_self()) when generating a cache key. - -0.7.0b1 -======= -- Detailed descriptions of each change below are - described at: - http://www.sqlalchemy.org/trac/wiki/07Migration - -- general - - New event system, supercedes all extensions, listeners, - etc. [ticket:1902] - - - Logging enhancements - [ticket:1926] - - - Setup no longer installs a Nose plugin - [ticket:1949] - - - The "sqlalchemy.exceptions" alias in sys.modules - has been removed. Base SQLA exceptions are - available via "from sqlalchemy import exc". - The "exceptions" alias for "exc" remains in - "sqlalchemy" for now, it's just not patched into - sys.modules. - -- orm - - More succinct form of query.join(target, onclause) - [ticket:1923] - - - Hybrid Attributes, implements/supercedes synonym() - [ticket:1903] - - - Rewrite of composites [ticket:2008] - - - Mutation Event Extension, supercedes "mutable=True" - - - PickleType and ARRAY mutability turned off by default - [ticket:1980] - - - Simplified polymorphic_on assignment - [ticket:1895] - - - Flushing of Orphans that have no parent is allowed - [ticket:1912] - - - Adjusted flush accounting step to occur before - the commit in the case of autocommit=True. This allows - autocommit=True to work appropriately with - expire_on_commit=True, and also allows post-flush session - hooks to operate in the same transactional context - as when autocommit=False. [ticket:2041] - - - Warnings generated when collection members, scalar referents - not part of the flush - [ticket:1973] - - - Non-`Table`-derived constructs can be mapped - [ticket:1876] - - - Tuple label names in Query Improved - [ticket:1942] - - - Mapped column attributes reference the most specific - column first - [ticket:1892] - - - Mapping to joins with two or more same-named columns - requires explicit declaration - [ticket:1896] - - - Mapper requires that polymorphic_on column be present - in the mapped selectable - [ticket:1875] - - - compile_mappers() renamed configure_mappers(), simplified - configuration internals - [ticket:1966] - - - the aliased() function, if passed a SQL FromClause element - (i.e. not a mapped class), will return element.alias() - instead of raising an error on AliasedClass. [ticket:2018] - - - Session.merge() will check the version id of the incoming - state against that of the database, assuming the mapping - uses version ids and incoming state has a version_id - assigned, and raise StaleDataError if they don't - match. [ticket:2027] - - - Session.connection(), Session.execute() accept 'bind', - to allow execute/connection operations to participate - in the open transaction of an engine explicitly. - [ticket:1996] - - - Query.join(), Query.outerjoin(), eagerload(), - eagerload_all(), others no longer allow lists - of attributes as arguments (i.e. option([x, y, z]) - form, deprecated since 0.5) - - - ScopedSession.mapper is removed (deprecated since 0.5). - - - Horizontal shard query places 'shard_id' in - context.attributes where it's accessible by the - "load()" event. [ticket:2031] - - - A single contains_eager() call across - multiple entities will indicate all collections - along that path should load, instead of requiring - distinct contains_eager() calls for each endpoint - (which was never correctly documented). - [ticket:2032] - - - The "name" field used in orm.aliased() now renders - in the resulting SQL statement. - - - Session weak_instance_dict=False is deprecated. - [ticket:1473] - - - An exception is raised in the unusual case that an - append or similar event on a collection occurs after - the parent object has been dereferenced, which - prevents the parent from being marked as "dirty" - in the session. Was a warning in 0.6.6. - [ticket:2046] - - - Query.distinct() now accepts column expressions - as *args, interpreted by the Postgresql dialect - as DISTINCT ON (). [ticket:1069] - - - Additional tuning to "many-to-one" relationship - loads during a flush(). A change in version 0.6.6 - ([ticket:2002]) required that more "unnecessary" m2o - loads during a flush could occur. Extra loading modes have - been added so that the SQL emitted in this - specific use case is trimmed back, while still - retrieving the information the flush needs in order - to not miss anything. [ticket:2049] - - - the value of "passive" as passed to - attributes.get_history() should be one of the - constants defined in the attributes package. Sending - True or False is deprecated. - - - Added a `name` argument to `Query.subquery()`, to allow - a fixed name to be assigned to the alias object. - [ticket:2030] (also in 0.6.7) - - - A warning is emitted when a joined-table inheriting mapper - has no primary keys on the locally mapped table - (but has pks on the superclass table). [ticket:2019] - (also in 0.6.7) - - - Fixed bug where "middle" class in a polymorphic hierarchy - would have no 'polymorphic_on' column if it didn't also - specify a 'polymorphic_identity', leading to strange - errors upon refresh, wrong class loaded when querying - from that target. Also emits the correct WHERE criterion - when using single table inheritance. [ticket:2038] - (also in 0.6.7) - - - Fixed bug where a column with a SQL or server side default - that was excluded from a mapping with include_properties - or exclude_properties would result in UnmappedColumnError. - [ticket:1995] (also in 0.6.7) - - - A warning is emitted in the unusual case that an - append or similar event on a collection occurs after - the parent object has been dereferenced, which - prevents the parent from being marked as "dirty" - in the session. This will be an exception in 0.7. - [ticket:2046] (also in 0.6.7) - -- declarative - - Added an explicit check for the case that the name - 'metadata' is used for a column attribute on a - declarative class. [ticket:2050] (also in 0.6.7) - -- sql - - Added over() function, method to FunctionElement - classes, produces the _Over() construct which - in turn generates "window functions", i.e. - " OVER (PARTITION BY , - ORDER BY )". - [ticket:1844] - - - LIMIT/OFFSET clauses now use bind parameters - [ticket:805] - - - select.distinct() now accepts column expressions - as *args, interpreted by the Postgresql dialect - as DISTINCT ON (). Note this was already - available via passing a list to the `distinct` - keyword argument to select(). [ticket:1069] - - - select.prefix_with() accepts multiple expressions - (i.e. *expr), 'prefix' keyword argument to select() - accepts a list or tuple. - - - Passing a string to the `distinct` keyword argument - of `select()` for the purpose of emitting special - MySQL keywords (DISTINCTROW etc.) is deprecated - - use `prefix_with()` for this. - - - TypeDecorator works with primary key columns - [ticket:2005] [ticket:2006] - - - DDL() constructs now escape percent signs - [ticket:1897] - - - Table.c / MetaData.tables refined a bit, don't allow direct - mutation [ticket:1893] [ticket:1917] - - - Callables passed to `bindparam()` don't get evaluated - [ticket:1950] - - - types.type_map is now private, types._type_map - [ticket:1870] - - - Non-public Pool methods underscored - [ticket:1982] - - - Added NULLS FIRST and NULLS LAST support. It's implemented - as an extension to the asc() and desc() operators, called - nullsfirst() and nullslast(). [ticket:723] - - - The Index() construct can be created inline with a Table - definition, using strings as column names, as an alternative - to the creation of the index outside of the Table. - - - execution_options() on Connection accepts - "isolation_level" argument, sets transaction isolation - level for that connection only until returned to the - connection pool, for thsoe backends which support it - (SQLite, Postgresql) [ticket:2001] - - - A TypeDecorator of Integer can be used with a primary key - column, and the "autoincrement" feature of various dialects - as well as the "sqlite_autoincrement" flag will honor - the underlying database type as being Integer-based. - [ticket:2005] - - - Established consistency when server_default is present - on an Integer PK column. SQLA doesn't pre-fetch these, - nor do they come back in cursor.lastrowid (DBAPI). - Ensured all backends consistently return None - in result.inserted_primary_key for these. Regarding - reflection for this case, reflection of an int PK col - with a server_default sets the "autoincrement" flag to False, - except in the case of a PG SERIAL col where we detected a - sequence default. [ticket:2020] [ticket:2021] - - - Result-row processors are applied to pre-executed SQL - defaults, as well as cursor.lastrowid, when determining - the contents of result.inserted_primary_key. - [ticket:2006] - - - Bind parameters present in the "columns clause" of a select - are now auto-labeled like other "anonymous" clauses, - which among other things allows their "type" to be meaningful - when the row is fetched, as in result row processors. - - - TypeDecorator is present in the "sqlalchemy" import space. - - - Non-DBAPI errors which occur in the scope of an `execute()` - call are now wrapped in sqlalchemy.exc.StatementError, - and the text of the SQL statement and repr() of params - is included. This makes it easier to identify statement - executions which fail before the DBAPI becomes - involved. [ticket:2015] - - - The concept of associating a ".bind" directly with a - ClauseElement has been explicitly moved to Executable, - i.e. the mixin that describes ClauseElements which represent - engine-executable constructs. This change is an improvement - to internal organization and is unlikely to affect any - real-world usage. [ticket:2048] - - - Column.copy(), as used in table.tometadata(), copies the - 'doc' attribute. [ticket:2028] (also in 0.6.7) - - - Added some defs to the resultproxy.c extension so that - the extension compiles and runs on Python 2.4. - [ticket:2023] (also in 0.6.7) - - - The compiler extension now supports overriding the default - compilation of expression._BindParamClause including that - the auto-generated binds within the VALUES/SET clause - of an insert()/update() statement will also use the new - compilation rules. [ticket:2042] (also in 0.6.7) - --sqlite - - SQLite dialect now uses `NullPool` for file-based databases - [ticket:1921] - - - The path given as the location of a sqlite database is now - normalized via os.path.abspath(), so that directory changes - within the process don't affect the ultimate location - of a relative file path. [ticket:2036] - -- postgresql - - When explicit sequence execution derives the name - of the auto-generated sequence of a SERIAL column, - which currently only occurs if implicit_returning=False, - now accommodates if the table + column name is greater - than 63 characters using the same logic Postgresql uses. - [ticket:1083] (also in 0.6.7) - - - Added an additional libpq message to the list of "disconnect" - exceptions, "could not receive data from server" - [ticket:2044] (also in 0.6.7) - -- mssql - - the String/Unicode types, and their counterparts VARCHAR/ - NVARCHAR, emit "max" as the length when no length is - specified, so that the default length, normally '1' - as per SQL server documentation, is instead - 'unbounded'. This also occurs for the VARBINARY type. - [ticket:1833]. - - This behavior makes these types more closely compatible - with Postgresql's VARCHAR type which is similarly unbounded - when no length is specified. - -- mysql - - New DBAPI support for pymysql, a pure Python port - of MySQL-python. [ticket:1991] - - - oursql dialect accepts the same "ssl" arguments in - create_engine() as that of MySQLdb. [ticket:2047] - (also in 0.6.7) - -- firebird - - Some adjustments so that Interbase is supported as well. - FB/Interbase version idents are parsed into a structure - such as (8, 1, 1, 'interbase') or (2, 1, 588, 'firebird') - so they can be distinguished. [ticket:1885] - -- drizzle - - New dialect for Drizzle, a MySQL variant. Uses MySQL-python - for the DBAPI. [ticket:2003] - -0.6.7 - 0.6.xx -============== - -Changes which apply to 0.6.7 and subsequent versions of 0.6 -are listed in the CHANGES file within the 0.6 branch. All -those changes which are also in the 0.7 series (which is typically -all of them) are listed inline within the 0.7 changes above, -those which apply to an 0.6 release are noted. - -0.6.6 -===== -- orm - - Fixed bug whereby a non-"mutable" attribute modified event - which occurred on an object that was clean except for - preceding mutable attribute changes would fail to strongly - reference itself in the identity map. This would cause the - object to be garbage collected, losing track of any changes - that weren't previously saved in the "mutable changes" - dictionary. - - - Fixed bug whereby "passive_deletes='all'" wasn't passing - the correct symbols to lazy loaders during flush, thereby - causing an unwarranted load. [ticket:2013] - - - Fixed bug which prevented composite mapped - attributes from being used on a mapped select statement. - [ticket:1997]. Note the workings of composite are slated to - change significantly in 0.7. - - - active_history flag also added to composite(). - The flag has no effect in 0.6, but is instead - a placeholder flag for forwards compatibility, - as it applies in 0.7 for composites. - [ticket:1976] - - - Fixed uow bug whereby expired objects passed to - Session.delete() would not have unloaded references - or collections taken into account when deleting - objects, despite passive_deletes remaining at - its default of False. [ticket:2002] - - - A warning is emitted when version_id_col is specified - on an inheriting mapper when the inherited mapper - already has one, if those column expressions are not - the same. [ticket:1987] - - - "innerjoin" flag doesn't take effect along the chain - of joinedload() joins if a previous join in that chain - is an outer join, thus allowing primary rows without - a referenced child row to be correctly returned - in results. [ticket:1954] - - - Fixed bug regarding "subqueryload" strategy whereby - strategy would fail if the entity was an aliased() - construct. [ticket:1964] - - - Fixed bug regarding "subqueryload" strategy whereby - the join would fail if using a multi-level load - of the form from A->joined-subclass->C [ticket:2014] - - - Fixed indexing of Query objects by -1. It was erroneously - transformed to the empty slice -1:0 that resulted in - IndexError. [ticket:1968] - - - The mapper argument "primary_key" can be passed as a - single column as well as a list or tuple. [ticket:1971] - The documentation examples that illustrated it as a - scalar value have been changed to lists. - - - Added active_history flag to relationship() - and column_property(), forces attribute events to - always load the "old" value, so that it's available to - attributes.get_history(). [ticket:1961] - - - Query.get() will raise if the number of params - in a composite key is too large, as well as too - small. [ticket:1977] - - - Backport of "optimized get" fix from 0.7, - improves the generation of joined-inheritance - "load expired row" behavior. [ticket:1992] - - - A little more verbiage to the "primaryjoin" error, - in an unusual condition that the join condition - "works" for viewonly but doesn't work for non-viewonly, - and foreign_keys wasn't used - adds "foreign_keys" to - the suggestion. Also add "foreign_keys" to the - suggestion for the generic "direction" error. - -- sql - - Fixed operator precedence rules for multiple - chains of a single non-associative operator. - I.e. "x - (y - z)" will compile as "x - (y - z)" - and not "x - y - z". Also works with labels, - i.e. "x - (y - z).label('foo')" - [ticket:1984] - - - The 'info' attribute of Column is copied during - Column.copy(), i.e. as occurs when using columns - in declarative mixins. [ticket:1967] - - - Added a bind processor for booleans which coerces - to int, for DBAPIs such as pymssql that naively call - str() on values. - - - CheckConstraint will copy its 'initially', 'deferrable', - and '_create_rule' attributes within a copy()/tometadata() - [ticket:2000] - -- engine - - The "unicode warning" against non-unicode bind data - is now raised only when the - Unicode type is used explictly; not when - convert_unicode=True is used on the engine - or String type. - - - Fixed memory leak in C version of Decimal result - processor. [ticket:1978] - - - Implemented sequence check capability for the C - version of RowProxy, as well as 2.7 style - "collections.Sequence" registration for RowProxy. - [ticket:1871] - - - Threadlocal engine methods rollback(), commit(), - prepare() won't raise if no transaction is in progress; - this was a regression introduced in 0.6. [ticket:1998] - - - Threadlocal engine returns itself upon begin(), - begin_nested(); engine then implements contextmanager - methods to allow the "with" statement. [ticket:2004] - -- postgresql - - Single element tuple expressions inside an IN clause - parenthesize correctly, also from [ticket:1984] - - - Ensured every numeric, float, int code, scalar + array, - are recognized by psycopg2 and pg8000's "numeric" - base type. [ticket:1955] - - - Added as_uuid=True flag to the UUID type, will receive - and return values as Python UUID() objects rather than - strings. Currently, the UUID type is only known to - work with psycopg2. [ticket:1956] - - - Fixed bug whereby KeyError would occur with non-ENUM - supported PG versions after a pool dispose+recreate - would occur, [ticket:1989] - -- mysql - - Fixed error handling for Jython + zxjdbc, such that - has_table() property works again. Regression from - 0.6.3 (we don't have a Jython buildbot, sorry) - [ticket:1960] - -- sqlite - - The REFERENCES clause in a CREATE TABLE that includes - a remote schema to another table with the same schema - name now renders the remote name without - the schema clause, as required by SQLite. [ticket:1851] - - - On the same theme, the REFERENCES clause in a CREATE TABLE - that includes a remote schema to a *different* schema - than that of the parent table doesn't render at all, - as cross-schema references do not appear to be supported. - -- mssql - - The rewrite of index reflection in [ticket:1770] was - unfortunately not tested correctly, and returned incorrect - results. This regression is now fixed. - -- oracle - - The cx_oracle "decimal detection" logic, which takes place - for for result set columns with ambiguous numeric characteristics, - now uses the decimal point character determined by the locale/ - NLS_LANG setting, using an on-first-connect detection of - this character. cx_oracle 5.0.3 or greater is also required - when using a non-period-decimal-point NLS_LANG setting. - [ticket:1953]. - -- firebird - - Firebird numeric type now checks for Decimal explicitly, - lets float() pass right through, thereby allowing - special values such as float('inf'). [ticket:2012] - -- declarative - - An error is raised if __table_args__ is not in tuple - or dict format, and is not None. [ticket:1972] - -- sqlsoup - - Added "map_to()" method to SqlSoup, which is a "master" - method which accepts explicit arguments for each aspect of - the selectable and mapping, including a base class per - mapping. [ticket:1975] - - - Mapped selectables used with the map(), with_labels(), - join() methods no longer put the given argument into the - internal "cache" dictionary. Particularly since the - join() and select() objects are created in the method - itself this was pretty much a pure memory leaking behavior. - -- examples - - The versioning example now supports detection of changes - in an associated relationship(). - -0.6.5 -===== -- orm - - Added a new "lazyload" option "immediateload". - Issues the usual "lazy" load operation automatically - as the object is populated. The use case - here is when loading objects to be placed in - an offline cache, or otherwise used after - the session isn't available, and straight 'select' - loading, not 'joined' or 'subquery', is desired. - [ticket:1914] - - - New Query methods: query.label(name), query.as_scalar(), - return the query's statement as a scalar subquery - with /without label [ticket:1920]; - query.with_entities(*ent), replaces the SELECT list of - the query with new entities. - Roughly equivalent to a generative form of query.values() - which accepts mapped entities as well as column - expressions. - - - Fixed recursion bug which could occur when moving - an object from one reference to another, with - backrefs involved, where the initiating parent - was a subclass (with its own mapper) of the - previous parent. - - - Fixed a regression in 0.6.4 which occurred if you - passed an empty list to "include_properties" on - mapper() [ticket:1918] - - - Fixed labeling bug in Query whereby the NamedTuple - would mis-apply labels if any of the column - expressions were un-labeled. - - - Patched a case where query.join() would adapt the - right side to the right side of the left's join - inappropriately [ticket:1925] - - - Query.select_from() has been beefed up to help - ensure that a subsequent call to query.join() - will use the select_from() entity, assuming it's - a mapped entity and not a plain selectable, - as the default "left" side, not the first entity - in the Query object's list of entities. - - - The exception raised by Session when it is used - subsequent to a subtransaction rollback (which is what - happens when a flush fails in autocommit=False mode) has - now been reworded (this is the "inactive due to a - rollback in a subtransaction" message). In particular, - if the rollback was due to an exception during flush(), - the message states this is the case, and reiterates the - string form of the original exception that occurred - during flush. If the session is closed due to explicit - usage of subtransactions (not very common), the message - just states this is the case. - - - The exception raised by Mapper when repeated requests to - its initialization are made after initialization already - failed no longer assumes the "hasattr" case, since - there's other scenarios in which this message gets - emitted, and the message also does not compound onto - itself multiple times - you get the same message for - each attempt at usage. The misnomer "compiles" is being - traded out for "initialize". - - - Fixed bug in query.update() where 'evaluate' or 'fetch' - expiration would fail if the column expression key was - a class attribute with a different keyname as the - actual column name. [ticket:1935] - - - Added an assertion during flush which ensures - that no NULL-holding identity keys were generated - on "newly persistent" objects. - This can occur when user defined code inadvertently - triggers flushes on not-fully-loaded objects. - - - lazy loads for relationship attributes now use - the current state, not the "committed" state, - of foreign and primary key attributes - when issuing SQL, if a flush is not in process. - Previously, only the database-committed state would - be used. In particular, this would cause a many-to-one - get()-on-lazyload operation to fail, as autoflush - is not triggered on these loads when the attributes are - determined and the "committed" state may not be - available. [ticket:1910] - - - A new flag on relationship(), load_on_pending, allows - the lazy loader to fire off on pending objects without a - flush taking place, as well as a transient object that's - been manually "attached" to the session. Note that this - flag blocks attribute events from taking place when an - object is loaded, so backrefs aren't available until - after a flush. The flag is only intended for very - specific use cases. - - - Another new flag on relationship(), cascade_backrefs, - disables the "save-update" cascade when the event was - initiated on the "reverse" side of a bidirectional - relationship. This is a cleaner behavior so that - many-to-ones can be set on a transient object without - it getting sucked into the child object's session, - while still allowing the forward collection to - cascade. We *might* default this to False in 0.7. - - - Slight improvement to the behavior of - "passive_updates=False" when placed only on the - many-to-one side of a relationship; documentation has - been clarified that passive_updates=False should really - be on the one-to-many side. - - - Placing passive_deletes=True on a many-to-one emits - a warning, since you probably intended to put it on - the one-to-many side. - - - Fixed bug that would prevent "subqueryload" from - working correctly with single table inheritance - for a relationship from a subclass - the "where - type in (x, y, z)" only gets placed on the inside, - instead of repeatedly. - - - When using from_self() with single table inheritance, - the "where type in (x, y, z)" is placed on the outside - of the query only, instead of repeatedly. May make - some more adjustments to this. - - - scoped_session emits a warning when configure() is - called if a Session is already present (checks only the - current thread) [ticket:1924] - - - reworked the internals of mapper.cascade_iterator() to - cut down method calls by about 9% in some circumstances. - [ticket:1932] - -- sql - - Fixed bug in TypeDecorator whereby the dialect-specific - type was getting pulled in to generate the DDL for a - given type, which didn't always return the correct result. - - - TypeDecorator can now have a fully constructed type - specified as its "impl", in addition to a type class. - - - TypeDecorator will now place itself as the resulting - type for a binary expression where the type coercion - rules would normally return its impl type - previously, - a copy of the impl type would be returned which would - have the TypeDecorator embedded into it as the "dialect" - impl, this was probably an unintentional way of achieving - the desired effect. - - - TypeDecorator.load_dialect_impl() returns "self.impl" by - default, i.e. not the dialect implementation type of - "self.impl". This to support compilation correctly. - Behavior can be user-overridden in exactly the same way - as before to the same effect. - - - Added type_coerce(expr, type_) expression element. - Treats the given expression as the given type when evaluating - expressions and processing result rows, but does not - affect the generation of SQL, other than an anonymous - label. - - - Table.tometadata() now copies Index objects associated - with the Table as well. - - - Table.tometadata() issues a warning if the given Table - is already present in the target MetaData - the existing - Table object is returned. - - - An informative error message is raised if a Column - which has not yet been assigned a name, i.e. as in - declarative, is used in a context where it is - exported to the columns collection of an enclosing - select() construct, or if any construct involving - that column is compiled before its name is - assigned. - - - as_scalar(), label() can be called on a selectable - which contains a Column that is not yet named. - [ticket:1862] - - - Fixed recursion overflow which could occur when operating - with two expressions both of type "NullType", but - not the singleton NULLTYPE instance. [ticket:1907] - -- declarative - - @classproperty (soon/now @declared_attr) takes effect for - __mapper_args__, __table_args__, __tablename__ on - a base class that is not a mixin, as well as mixins. - [ticket:1922] - - - @classproperty 's official name/location for usage - with declarative is sqlalchemy.ext.declarative.declared_attr. - Same thing, but moving there since it is more of a - "marker" that's specific to declararative, - not just an attribute technique. [ticket:1915] - - - Fixed bug whereby columns on a mixin wouldn't propagate - correctly to a single-table, or joined-table, - inheritance scheme where the attribute name is - different than that of the column. [ticket:1930], - [ticket:1931]. - - - A mixin can now specify a column that overrides - a column of the same name associated with a superclass. - Thanks to Oystein Haaland. - -- engine - - - Fixed a regression in 0.6.4 whereby the change that - allowed cursor errors to be raised consistently broke - the result.lastrowid accessor. Test coverage has - been added for result.lastrowid. Note that lastrowid - is only supported by Pysqlite and some MySQL drivers, - so isn't super-useful in the general case. - - - the logging message emitted by the engine when - a connection is first used is now "BEGIN (implicit)" - to emphasize that DBAPI has no explicit begin(). - - - added "views=True" option to metadata.reflect(), - will add the list of available views to those - being reflected. [ticket:1936] - - - engine_from_config() now accepts 'debug' for - 'echo', 'echo_pool', 'force' for 'convert_unicode', - boolean values for 'use_native_unicode'. - [ticket:1899] - -- postgresql - - Added "as_tuple" flag to ARRAY type, returns results - as tuples instead of lists to allow hashing. - - - Fixed bug which prevented "domain" built from a - custom type such as "enum" from being reflected. - [ticket:1933] - -- mysql - - Fixed bug involving reflection of CURRENT_TIMESTAMP - default used with ON UPDATE clause, thanks to - Taavi Burns [ticket:1940] - -- oracle - - The implicit_retunring argument to create_engine() - is now honored regardless of detected version of - Oracle. Previously, the flag would be forced - to False if server version info was < 10. - [ticket:1878] - -- mssql - - Fixed reflection bug which did not properly handle - reflection of unknown types. [ticket:1946] - - - Fixed bug where aliasing of tables with "schema" would - fail to compile properly. [ticket:1943] - - - Rewrote the reflection of indexes to use sys. - catalogs, so that column names of any configuration - (spaces, embedded commas, etc.) can be reflected. - Note that reflection of indexes requires SQL - Server 2005 or greater. [ticket:1770] - - - mssql+pymssql dialect now honors the "port" portion - of the URL instead of discarding it. [ticket:1952] - -- informix - - *Major* cleanup / modernization of the Informix - dialect for 0.6, courtesy Florian Apolloner. - [ticket:1906] - -- tests - - the NoseSQLAlchemyPlugin has been moved to a - new package "sqlalchemy_nose" which installs - along with "sqlalchemy". This so that the "nosetests" - script works as always but also allows the - --with-coverage option to turn on coverage before - SQLAlchemy modules are imported, allowing coverage - to work correctly. - -- misc - - CircularDependencyError now has .cycles and .edges - members, which are the set of elements involved in - one or more cycles, and the set of edges as 2-tuples. - [ticket:1890] - -0.6.4 -===== -- orm - - The name ConcurrentModificationError has been - changed to StaleDataError, and descriptive - error messages have been revised to reflect - exactly what the issue is. Both names will - remain available for the forseeable future - for schemes that may be specifying - ConcurrentModificationError in an "except:" - clause. - - - Added a mutex to the identity map which mutexes - remove operations against iteration methods, - which now pre-buffer before returning an - iterable. This because asyncrhonous gc - can remove items via the gc thread at any time. - [ticket:1891] - - - The Session class is now present in sqlalchemy.orm.*. - We're moving away from the usage of create_session(), - which has non-standard defaults, for those situations - where a one-step Session constructor is desired. Most - users should stick with sessionmaker() for general use, - however. - - - query.with_parent() now accepts transient objects - and will use the non-persistent values of their pk/fk - attributes in order to formulate the criterion. - Docs are also clarified as to the purpose of with_parent(). - - - The include_properties and exclude_properties arguments - to mapper() now accept Column objects as members in - addition to strings. This so that same-named Column - objects, such as those within a join(), can be - disambiguated. - - - A warning is now emitted if a mapper is created against a - join or other single selectable that includes multiple - columns with the same name in its .c. collection, - and those columns aren't explictly named as part of - the same or separate attributes (or excluded). - In 0.7 this warning will be an exception. Note that - this warning is not emitted when the combination occurs - as a result of inheritance, so that attributes - still allow being overridden naturally. - [ticket:1896]. In 0.7 this will be improved further. - - - The primary_key argument to mapper() can now specify - a series of columns that are only a subset of - the calculated "primary key" columns of the mapped - selectable, without an error being raised. This - helps for situations where a selectable's effective - primary key is simpler than the number of columns - in the selectable that are actually marked as - "primary_key", such as a join against two - tables on their primary key columns [ticket:1896]. - - - An object that's been deleted now gets a flag - 'deleted', which prohibits the object from - being re-add()ed to the session, as previously - the object would live in the identity map - silently until its attributes were accessed. - The make_transient() function now resets this - flag along with the "key" flag. - - - make_transient() can be safely called on an - already transient instance. - - - a warning is emitted in mapper() if the polymorphic_on - column is not present either in direct or derived - form in the mapped selectable or in the - with_polymorphic selectable, instead of silently - ignoring it. Look for this to become an - exception in 0.7. - - - Another pass through the series of error messages - emitted when relationship() is configured with - ambiguous arguments. The "foreign_keys" - setting is no longer mentioned, as it is almost - never needed and it is preferable users set up - correct ForeignKey metadata, which is now the - recommendation. If 'foreign_keys' - is used and is incorrect, the message suggests - the attribute is probably unnecessary. Docs - for the attribute are beefed up. This - because all confused relationship() users on the - ML appear to be attempting to use foreign_keys - due to the message, which only confuses them - further since Table metadata is much clearer. - - - If the "secondary" table has no ForeignKey metadata - and no foreign_keys is set, even though the - user is passing screwed up information, it is assumed - that primary/secondaryjoin expressions should - consider only and all cols in "secondary" to be - foreign. It's not possible with "secondary" for - the foreign keys to be elsewhere in any case. - A warning is now emitted instead of an error, - and the mapping succeeds. [ticket:1877] - - - Moving an o2m object from one collection to - another, or vice versa changing the referenced - object by an m2o, where the foreign key is also a - member of the primary key, will now be more - carefully checked during flush if the change in - value of the foreign key on the "many" side is the - result of a change in the primary key of the "one" - side, or if the "one" is just a different object. - In one case, a cascade-capable DB would have - cascaded the value already and we need to look at - the "new" PK value to do an UPDATE, in the other we - need to continue looking at the "old". We now look - at the "old", assuming passive_updates=True, - unless we know it was a PK switch that - triggered the change. [ticket:1856] - - - The value of version_id_col can be changed - manually, and this will result in an UPDATE - of the row. Versioned UPDATEs and DELETEs - now use the "committed" value of the - version_id_col in the WHERE clause and - not the pending changed value. The - version generator is also bypassed if - manual changes are present on the attribute. - [ticket:1857] - - - Repaired the usage of merge() when used with - concrete inheriting mappers. Such mappers frequently - have so-called "concrete" attributes, which are - subclass attributes that "disable" propagation from - the parent - these needed to allow a merge() - operation to pass through without effect. - - - Specifying a non-column based argument - for column_mapped_collection, including string, - text() etc., will raise an error message that - specifically asks for a column element, no longer - misleads with incorrect information about - text() or literal(). [ticket:1863] - - - Similarly, for relationship(), foreign_keys, - remote_side, order_by - all column-based - expressions are enforced - lists of strings - are explicitly disallowed since this is a - very common error - - - Dynamic attributes don't support collection - population - added an assertion for when - set_committed_value() is called, as well as - when joinedload() or subqueryload() options - are applied to a dynamic attribute, instead - of failure / silent failure. [ticket:1864] - - - Fixed bug whereby generating a Query derived - from one which had the same column repeated - with different label names, typically - in some UNION situations, would fail to - propagate the inner columns completely to - the outer query. [ticket:1852] - - - object_session() raises the proper - UnmappedInstanceError when presented with an - unmapped instance. [ticket:1881] - - - Applied further memoizations to calculated Mapper - properties, with significant (~90%) runtime mapper.py - call count reduction in heavily polymorphic mapping - configurations. - - - mapper _get_col_to_prop private method used - by the versioning example is deprecated; - now use mapper.get_property_by_column() which - will remain the public method for this. - - - the versioning example works correctly now - if versioning on a col that was formerly - NULL. - -- sql - - Calling execute() on an alias() construct is pending - deprecation for 0.7, as it is not itself an - "executable" construct. It currently "proxies" its - inner element and is conditionally "executable" but - this is not the kind of ambiguity we like these days. - - - The execute() and scalar() methods of ClauseElement - are now moved appropriately to the Executable - subclass. ClauseElement.execute()/ scalar() are still - present and are pending deprecation in 0.7, but note - these would always raise an error anyway if you were - not an Executable (unless you were an alias(), see - previous note). - - - Added basic math expression coercion for - Numeric->Integer, - so that resulting type is Numeric regardless - of the direction of the expression. - - - Changed the scheme used to generate truncated - "auto" index names when using the "index=True" - flag on Column. The truncation only takes - place with the auto-generated name, not one - that is user-defined (an error would be - raised instead), and the truncation scheme - itself is now based on a fragment of an md5 - hash of the identifier name, so that multiple - indexes on columns with similar names still - have unique names. [ticket:1855] - - - The generated index name also is based on - a "max index name length" attribute which is - separate from the "max identifier length" - - this to appease MySQL who has a max length - of 64 for index names, separate from their - overall max length of 255. [ticket:1412] - - - the text() construct, if placed in a column - oriented situation, will at least return NULLTYPE - for its type instead of None, allowing it to - be used a little more freely for ad-hoc column - expressions than before. literal_column() - is still the better choice, however. - - - Added full description of parent table/column, - target table/column in error message raised when - ForeignKey can't resolve target. - - - Fixed bug whereby replacing composite foreign key - columns in a reflected table would cause an attempt - to remove the reflected constraint from the table - a second time, raising a KeyError. [ticket:1865] - - - the _Label construct, i.e. the one that is produced - whenever you say somecol.label(), now counts itself - in its "proxy_set" unioned with that of it's - contained column's proxy set, instead of - directly returning that of the contained column. - This allows column correspondence - operations which depend on the identity of the - _Labels themselves to return the correct result - - fixes ORM bug [ticket:1852]. - -- engine - - - Calling fetchone() or similar on a result that - has already been exhausted, has been closed, - or is not a result-returning result now - raises ResourceClosedError, a subclass of - InvalidRequestError, in all cases, regardless - of backend. Previously, some DBAPIs would - raise ProgrammingError (i.e. pysqlite), others - would return None leading to downstream breakages - (i.e. MySQL-python). - - - Fixed bug in Connection whereby if a "disconnect" - event occurred in the "initialize" phase of the - first connection pool connect, an AttributeError - would be raised when the Connection would attempt - to invalidate the DBAPI connection. [ticket:1894] - - - Connection, ResultProxy, as well as Session use - ResourceClosedError for all "this - connection/transaction/result is closed" types of - errors. - - - Connection.invalidate() can be called more than - once and subsequent calls do nothing. - -- declarative - - if @classproperty is used with a regular class-bound - mapper property attribute, it will be called to get the - actual attribute value during initialization. Currently, - there's no advantage to using @classproperty on a column - or relationship attribute of a declarative class that - isn't a mixin - evaluation is at the same time as if - @classproperty weren't used. But here we at least allow - it to function as expected. - - - Fixed bug where "Can't add additional column" message - would display the wrong name. - -- postgresql - - Fixed the psycopg2 dialect to use its - set_isolation_level() method instead of relying - upon the base "SET SESSION ISOLATION" command, - as psycopg2 resets the isolation level on each new - transaction otherwise. - -- mssql - - Fixed "default schema" query to work with - pymssql backend. - -- firebird - - Fixed bug whereby a column default would fail to - reflect if the "default" keyword were lower case. - -- oracle - - Added ROWID type to the Oracle dialect, for those - cases where an explicit CAST might be needed. - [ticket:1879] - - - Oracle reflection of indexes has been tuned so - that indexes which include some or all primary - key columns, but not the same set of columns - as that of the primary key, are reflected. - Indexes which contain the identical columns - as that of the primary key are skipped within - reflection, as the index in that case is assumed - to be the auto-generated primary key index. - Previously, any index with PK columns present - would be skipped. Thanks to Kent Bower - for the patch. [ticket:1867] - - - Oracle now reflects the names of primary key - constraints - also thanks to Kent Bower. - [ticket:1868] - -- informix - - Applied patches from [ticket:1904] to get - basic Informix functionality up again. We - rely upon end-user testing to ensure that - Informix is working to some degree. - -- documentation - - The docs have been reorganized such that the "API - Reference" section is gone - all the docstrings from - there which were public API are moved into the - context of the main doc section that talks about it. - Main docs divided into "SQLAlchemy Core" and - "SQLAlchemy ORM" sections, mapper/relationship docs - have been broken out. Lots of sections rewritten - and/or reorganized. - -- examples - - The beaker_caching example has been reorgnized - such that the Session, cache manager, - declarative_base are part of environment, and - custom cache code is portable and now within - "caching_query.py". This allows the example to - be easier to "drop in" to existing projects. - - - the history_meta versioning recipe sets "unique=False" - when copying columns, so that the versioning - table handles multiple rows with repeating values. - [ticket:1887] - -0.6.3 -===== -- orm - - Removed errant many-to-many load in unitofwork - which triggered unnecessarily on expired/unloaded - collections. This load now takes place only if - passive_updates is False and the parent primary - key has changed, or if passive_deletes is False - and a delete of the parent has occurred. - [ticket:1845] - - - Column-entities (i.e. query(Foo.id)) copy their - state more fully when queries are derived from - themselves + a selectable (i.e. from_self(), - union(), etc.), so that join() and such have the - correct state to work from. [ticket:1853] - - - Fixed bug where Query.join() would fail if - querying a non-ORM column then joining without - an on clause when a FROM clause is already - present, now raises a checked exception the - same way it does when the clause is not - present. [ticket:1853] - - - Improved the check for an "unmapped class", - including the case where the superclass is mapped - but the subclass is not. Any attempts to access - cls._sa_class_manager.mapper now raise - UnmappedClassError(). [ticket:1142] - - - Added "column_descriptions" accessor to Query, - returns a list of dictionaries containing - naming/typing information about the entities - the Query will return. Can be helpful for - building GUIs on top of ORM queries. - -- mysql - - - The _extract_error_code() method now works - correctly with each MySQL dialect ( - MySQL-python, OurSQL, MySQL-Connector-Python, - PyODBC). Previously, - the reconnect logic would fail for OperationalError - conditions, however since MySQLdb and OurSQL - have their own reconnect feature, there was no - symptom for these drivers here unless one - watched the logs. [ticket:1848] - -- oracle - - More tweaks to cx_oracle Decimal handling. - "Ambiguous" numerics with no decimal place - are coerced to int at the connection handler - level. The advantage here is that ints - come back as ints without SQLA type - objects being involved and without needless - conversion to Decimal first. - - Unfortunately, some exotic subquery cases - can even see different types between - individual result rows, so the Numeric - handler, when instructed to return Decimal, - can't take full advantage of "native decimal" - mode and must run isinstance() on every value - to check if its Decimal already. Reopen of - [ticket:1840] - -0.6.2 -===== -- orm - - Query.join() will check for a call of the - form query.join(target, clause_expression), - i.e. missing the tuple, and raise an informative - error message that this is the wrong calling form. - - - Fixed bug regarding flushes on self-referential - bi-directional many-to-many relationships, where - two objects made to mutually reference each other - in one flush would fail to insert a row for both - sides. Regression from 0.5. [ticket:1824] - - - the post_update feature of relationship() has been - reworked architecturally to integrate more closely - with the new 0.6 unit of work. The motivation - for the change is so that multiple "post update" - calls, each affecting different foreign key - columns of the same row, are executed in a single - UPDATE statement, rather than one UPDATE - statement per column per row. Multiple row - updates are also batched into executemany()s as - possible, while maintaining consistent row ordering. - - - Query.statement, Query.subquery(), etc. now transfer - the values of bind parameters, i.e. those specified - by query.params(), into the resulting SQL expression. - Previously the values would not be transferred - and bind parameters would come out as None. - - - Subquery-eager-loading now works with Query objects - which include params(), as well as get() Queries. - - - Can now call make_transient() on an instance that - is referenced by parent objects via many-to-one, - without the parent's foreign key value getting - temporarily set to None - this was a function - of the "detect primary key switch" flush handler. - It now ignores objects that are no longer - in the "persistent" state, and the parent's - foreign key identifier is left unaffected. - - - query.order_by() now accepts False, which cancels - any existing order_by() state on the Query, allowing - subsequent generative methods to be called which do - not support ORDER BY. This is not the same as the - already existing feature of passing None, which - suppresses any existing order_by() settings, including - those configured on the mapper. False will make it - as though order_by() was never called, while - None is an active setting. - - - An instance which is moved to "transient", has - an incomplete or missing set of primary key - attributes, and contains expired attributes, will - raise an InvalidRequestError if an expired attribute - is accessed, instead of getting a recursion overflow. - - - The make_transient() function is now in the generated - documentation. - - - make_transient() removes all "loader" callables from - the state being made transient, removing any - "expired" state - all unloaded attributes reset back - to undefined, None/empty on access. - -- sql - - The warning emitted by the Unicode and String types - with convert_unicode=True no longer embeds the actual - value passed. This so that the Python warning - registry does not continue to grow in size, the warning - is emitted once as per the warning filter settings, - and large string values don't pollute the output. - [ticket:1822] - - - Fixed bug that would prevent overridden clause - compilation from working for "annotated" expression - elements, which are often generated by the ORM. - - - The argument to "ESCAPE" of a LIKE operator or similar - is passed through render_literal_value(), which may - implement escaping of backslashes. [ticket:1400] - - - Fixed bug in Enum type which blew away native_enum - flag when used with TypeDecorators or other adaption - scenarios. - - - Inspector hits bind.connect() when invoked to ensure - initialize has been called. the internal name ".conn" - is changed to ".bind", since that's what it is. - - - Modified the internals of "column annotation" such that - a custom Column subclass can safely override - _constructor to return Column, for the purposes of - making "configurational" column classes that aren't - involved in proxying, etc. - - - Column.copy() takes along the "unique" attribute - among others, fixes [ticket:1829] regarding declarative - mixins - -- postgresql - - render_literal_value() is overridden which escapes - backslashes, currently applies to the ESCAPE clause - of LIKE and similar expressions. - Ultimately this will have to detect the value of - "standard_conforming_strings" for full behavior. - [ticket:1400] - - - Won't generate "CREATE TYPE" / "DROP TYPE" if - using types.Enum on a PG version prior to 8.3 - - the supports_native_enum flag is fully - honored. [ticket:1836] - -- mysql - - MySQL dialect doesn't emit CAST() for MySQL version - detected < 4.0.2. This allows the unicode - check on connect to proceed. [ticket:1826] - - - MySQL dialect now detects NO_BACKSLASH_ESCAPES sql - mode, in addition to ANSI_QUOTES. - - - render_literal_value() is overridden which escapes - backslashes, currently applies to the ESCAPE clause - of LIKE and similar expressions. This behavior - is derived from detecting the value of - NO_BACKSLASH_ESCAPES. [ticket:1400] - -- oracle: - - Fixed ora-8 compatibility flags such that they - don't cache a stale value from before the first - database connection actually occurs. [ticket:1819] - - - Oracle's "native decimal" metadata begins to return - ambiguous typing information about numerics - when columns are embedded in subqueries as well - as when ROWNUM is consulted with subqueries, as we - do for limit/offset. We've added these ambiguous - conditions to the cx_oracle "convert to Decimal()" - handler, so that we receive numerics as Decimal - in more cases instead of as floats. These are - then converted, if requested, into Integer - or Float, or otherwise kept as the lossless - Decimal [ticket:1840]. - -- mssql - - If server_version_info is outside the usual - range of (8, ), (9, ), (10, ), a warning is emitted - which suggests checking that the FreeTDS version - configuration is using 7.0 or 8.0, not 4.2. - [ticket:1825] - -- firebird - - Fixed incorrect signature in do_execute(), error - introduced in 0.6.1. [ticket:1823] - - - Firebird dialect adds CHAR, VARCHAR types which - accept a "charset" flag, to support Firebird - "CHARACTER SET" clause. [ticket:1813] - -- declarative - - Added support for @classproperty to provide - any kind of schema/mapping construct from a - declarative mixin, including columns with foreign - keys, relationships, column_property, deferred. - This solves all such issues on declarative mixins. - An error is raised if any MapperProperty subclass - is specified on a mixin without using @classproperty. - [ticket:1751] [ticket:1796] [ticket:1805] - - - a mixin class can now define a column that matches - one which is present on a __table__ defined on a - subclass. It cannot, however, define one that is - not present in the __table__, and the error message - here now works. [ticket:1821] - -- compiler extension - - The 'default' compiler is automatically copied over - when overriding the compilation of a built in - clause construct, so no KeyError is raised if the - user-defined compiler is specific to certain - backends and compilation for a different backend - is invoked. [ticket:1838] - -- documentation - - Added documentation for the Inspector. [ticket:1820] - - - Fixed @memoized_property and @memoized_instancemethod - decorators so that Sphinx documentation picks up - these attributes and methods, such as - ResultProxy.inserted_primary_key. [ticket:1830] - - -0.6.1 -===== -- orm - - Fixed regression introduced in 0.6.0 involving improper - history accounting on mutable attributes. [ticket:1782] - - - Fixed regression introduced in 0.6.0 unit of work refactor - that broke updates for bi-directional relationship() - with post_update=True. [ticket:1807] - - - session.merge() will not expire attributes on the returned - instance if that instance is "pending". [ticket:1789] - - - fixed __setstate__ method of CollectionAdapter to not - fail during deserialize where parent InstanceState not - yet unserialized. [ticket:1802] - - - Added internal warning in case an instance without a - full PK happened to be expired and then was asked - to refresh. [ticket:1797] - - - Added more aggressive caching to the mapper's usage of - UPDATE, INSERT, and DELETE expressions. Assuming the - statement has no per-object SQL expressions attached, - the expression objects are cached by the mapper after - the first create, and their compiled form is stored - persistently in a cache dictionary for the duration of - the related Engine. The cache is an LRUCache for the - rare case that a mapper receives an extremely - high number of different column patterns as UPDATEs. - -- sql - - expr.in_() now accepts a text() construct as the argument. - Grouping parenthesis are added automatically, i.e. usage - is like `col.in_(text("select id from table"))`. - [ticket:1793] - - - Columns of _Binary type (i.e. LargeBinary, BLOB, etc.) - will coerce a "basestring" on the right side into a - _Binary as well so that required DBAPI processing - takes place. - - - Added table.add_is_dependent_on(othertable), allows manual - placement of dependency rules between two Table objects - for use within create_all(), drop_all(), sorted_tables. - [ticket:1801] - - - Fixed bug that prevented implicit RETURNING from functioning - properly with composite primary key that contained zeroes. - [ticket:1778] - - - Fixed errant space character when generating ADD CONSTRAINT - for a named UNIQUE constraint. - - - Fixed "table" argument on constructor of ForeginKeyConstraint - [ticket:1571] - - - Fixed bug in connection pool cursor wrapper whereby if a - cursor threw an exception on close(), the logging of the - message would fail. [ticket:1786] - - - the _make_proxy() method of ColumnClause and Column now use - self.__class__ to determine the class of object to be returned - instead of hardcoding to ColumnClause/Column, making it slightly - easier to produce specific subclasses of these which work in - alias/subquery situations. - - - func.XXX() doesn't inadvertently resolve to non-Function - classes (e.g. fixes func.text()). [ticket:1798] - -- engines - - Fixed building the C extensions on Python 2.4. [ticket:1781] - - - Pool classes will reuse the same "pool_logging_name" setting - after a dispose() occurs. - - - Engine gains an "execution_options" argument and - update_execution_options() method, which will apply to - all connections generated by this engine. - -- mysql - - func.sysdate() emits "SYSDATE()", i.e. with the ending - parenthesis, on MySQL. [ticket:1794] - -- sqlite - - Fixed concatenation of constraints when "PRIMARY KEY" - constraint gets moved to column level due to SQLite - AUTOINCREMENT keyword being rendered. [ticket:1812] - -- oracle - - Added a check for cx_oracle versions lower than version 5, - in which case the incompatible "output type handler" won't - be used. This will impact decimal accuracy and some - unicode handling issues. [ticket:1775] - - - Fixed use_ansi=False mode, which was producing broken - WHERE clauses in pretty much all cases. [ticket:1790] - - - Re-established support for Oracle 8 with cx_oracle, - including that use_ansi is set to False automatically, - NVARCHAR2 and NCLOB are not rendered for Unicode, - "native unicode" check doesn't fail, cx_oracle - "native unicode" mode is disabled, VARCHAR() is emitted - with bytes count instead of char count. [ticket:1808] - - - oracle_xe 5 doesn't accept a Python unicode object in - its connect string in normal Python 2.x mode - so we coerce - to str() directly. non-ascii characters aren't supported - in connect strings here since we don't know what encoding - we could use. [ticket:1670] - - - FOR UPDATE is emitted in the syntactically correct position - when limit/offset is used, i.e. the ROWNUM subquery. - However, Oracle can't really handle FOR UPDATE with ORDER BY - or with subqueries, so its still not very usable, but at - least SQLA gets the SQL past the Oracle parser. - [ticket:1815] - -- firebird - - Added a label to the query used within has_table() and - has_sequence() to work with older versions of Firebird - that don't provide labels for result columns. [ticket:1521] - - - Added integer coercion to the "type_conv" attribute when - passed via query string, so that it is properly interpreted - by Kinterbasdb. [ticket:1779] - - - Added 'connection shutdown' to the list of exception strings - which indicate a dropped connection. [ticket:1646] - -- sqlsoup - - the SqlSoup constructor accepts a `base` argument which specifies - the base class to use for mapped classes, the default being - `object`. [ticket:1783] - -0.6.0 -===== - -- orm - - Unit of work internals have been rewritten. Units of work - with large numbers of objects interdependent objects - can now be flushed without recursion overflows - as there is no longer reliance upon recursive calls - [ticket:1081]. The number of internal structures now stays - constant for a particular session state, regardless of - how many relationships are present on mappings. The flow - of events now corresponds to a linear list of steps, - generated by the mappers and relationships based on actual - work to be done, filtered through a single topological sort - for correct ordering. Flush actions are assembled using - far fewer steps and less memory. [ticket:1742] - - - Along with the UOW rewrite, this also removes an issue - introduced in 0.6beta3 regarding topological cycle detection - for units of work with long dependency cycles. We now use - an algorithm written by Guido (thanks Guido!). - - - one-to-many relationships now maintain a list of positive - parent-child associations within the flush, preventing - previous parents marked as deleted from cascading a - delete or NULL foreign key set on those child objects, - despite the end-user not removing the child from the old - association. [ticket:1764] - - - A collection lazy load will switch off default - eagerloading on the reverse many-to-one side, since - that loading is by definition unnecessary. [ticket:1495] - - - Session.refresh() now does an equivalent expire() - on the given instance first, so that the "refresh-expire" - cascade is propagated. Previously, refresh() was - not affected in any way by the presence of "refresh-expire" - cascade. This is a change in behavior versus that - of 0.6beta2, where the "lockmode" flag passed to refresh() - would cause a version check to occur. Since the instance - is first expired, refresh() always upgrades the object - to the most recent version. - - - The 'refresh-expire' cascade, when reaching a pending object, - will expunge the object if the cascade also includes - "delete-orphan", or will simply detach it otherwise. - [ticket:1754] - - - id(obj) is no longer used internally within topological.py, - as the sorting functions now require hashable objects - only. [ticket:1756] - - - The ORM will set the docstring of all generated descriptors - to None by default. This can be overridden using 'doc' - (or if using Sphinx, attribute docstrings work too). - - - Added kw argument 'doc' to all mapper property callables - as well as Column(). Will assemble the string 'doc' as - the '__doc__' attribute on the descriptor. - - - Usage of version_id_col on a backend that supports - cursor.rowcount for execute() but not executemany() now works - when a delete is issued (already worked for saves, since those - don't use executemany()). For a backend that doesn't support - cursor.rowcount at all, a warning is emitted the same - as with saves. [ticket:1761] - - - The ORM now short-term caches the "compiled" form of - insert() and update() constructs when flushing lists of - objects of all the same class, thereby avoiding redundant - compilation per individual INSERT/UPDATE within an - individual flush() call. - - - internal getattr(), setattr(), getcommitted() methods - on ColumnProperty, CompositeProperty, RelationshipProperty - have been underscored (i.e. are private), signature has - changed. - -- engines - - The C extension now also works with DBAPIs which use custom - sequences as row (and not only tuples). [ticket:1757] - -- sql - - Restored some bind-labeling logic from 0.5 which ensures - that tables with column names that overlap another column - of the form "_" won't produce - errors if column._label is used as a bind name during - an UPDATE. Test coverage which wasn't present in 0.5 - has been added. [ticket:1755] - - - somejoin.select(fold_equivalents=True) is no longer - deprecated, and will eventually be rolled into a more - comprehensive version of the feature for [ticket:1729]. - - - the Numeric type raises an *enormous* warning when expected - to convert floats to Decimal from a DBAPI that returns floats. - This includes SQLite, Sybase, MS-SQL. [ticket:1759] - - - Fixed an error in expression typing which caused an endless - loop for expressions with two NULL types. - - - Fixed bug in execution_options() feature whereby the existing - Transaction and other state information from the parent - connection would not be propagated to the sub-connection. - - - Added new 'compiled_cache' execution option. A dictionary - where Compiled objects will be cached when the Connection - compiles a clause expression into a dialect- and parameter- - specific Compiled object. It is the user's responsibility to - manage the size of this dictionary, which will have keys - corresponding to the dialect, clause element, the column - names within the VALUES or SET clause of an INSERT or UPDATE, - as well as the "batch" mode for an INSERT or UPDATE statement. - - - Added get_pk_constraint() to reflection.Inspector, similar - to get_primary_keys() except returns a dict that includes the - name of the constraint, for supported backends (PG so far). - [ticket:1769] - - - Table.create() and Table.drop() no longer apply metadata- - level create/drop events. [ticket:1771] - -- ext - - the compiler extension now allows @compiles decorators - on base classes that extend to child classes, @compiles - decorators on child classes that aren't broken by a - @compiles decorator on the base class. - - - Declarative will raise an informative error message - if a non-mapped class attribute is referenced in the - string-based relationship() arguments. - - - Further reworked the "mixin" logic in declarative to - additionally allow __mapper_args__ as a @classproperty - on a mixin, such as to dynamically assign polymorphic_identity. - -- postgresql - - Postgresql now reflects sequence names associated with - SERIAL columns correctly, after the name of of the sequence - has been changed. Thanks to Kumar McMillan for the patch. - [ticket:1071] - - - Repaired missing import in psycopg2._PGNumeric type when - unknown numeric is received. - - - psycopg2/pg8000 dialects now aware of REAL[], FLOAT[], - DOUBLE_PRECISION[], NUMERIC[] return types without - raising an exception. - - - Postgresql reflects the name of primary key constraints, - if one exists. [ticket:1769] - -- oracle - - Now using cx_oracle output converters so that the - DBAPI returns natively the kinds of values we prefer: - - NUMBER values with positive precision + scale convert - to cx_oracle.STRING and then to Decimal. This - allows perfect precision for the Numeric type when - using cx_oracle. [ticket:1759] - - STRING/FIXED_CHAR now convert to unicode natively. - SQLAlchemy's String types then don't need to - apply any kind of conversions. - -- firebird - - The functionality of result.rowcount can be disabled on a - per-engine basis by setting 'enable_rowcount=False' - on create_engine(). Normally, cursor.rowcount is called - after any UPDATE or DELETE statement unconditionally, - because the cursor is then closed and Firebird requires - an open cursor in order to get a rowcount. This - call is slightly expensive however so it can be disabled. - To re-enable on a per-execution basis, the - 'enable_rowcount=True' execution option may be used. - -- examples - - Updated attribute_shard.py example to use a more robust - method of searching a Query for binary expressions which - compare columns against literal values. - -0.6beta3 -======== - -- orm - - Major feature: Added new "subquery" loading capability to - relationship(). This is an eager loading option which - generates a second SELECT for each collection represented - in a query, across all parents at once. The query - re-issues the original end-user query wrapped in a subquery, - applies joins out to the target collection, and loads - all those collections fully in one result, similar to - "joined" eager loading but using all inner joins and not - re-fetching full parent rows repeatedly (as most DBAPIs seem - to do, even if columns are skipped). Subquery loading is - available at mapper config level using "lazy='subquery'" and - at the query options level using "subqueryload(props..)", - "subqueryload_all(props...)". [ticket:1675] - - - To accomodate the fact that there are now two kinds of eager - loading available, the new names for eagerload() and - eagerload_all() are joinedload() and joinedload_all(). The - old names will remain as synonyms for the foreseeable future. - - - The "lazy" flag on the relationship() function now accepts - a string argument for all kinds of loading: "select", "joined", - "subquery", "noload" and "dynamic", where the default is now - "select". The old values of True/ - False/None still retain their usual meanings and will remain - as synonyms for the foreseeable future. - - - Added with_hint() method to Query() construct. This calls - directly down to select().with_hint() and also accepts - entities as well as tables and aliases. See with_hint() in the - SQL section below. [ticket:921] - - - Fixed bug in Query whereby calling q.join(prop).from_self(...). - join(prop) would fail to render the second join outside the - subquery, when joining on the same criterion as was on the - inside. - - - Fixed bug in Query whereby the usage of aliased() constructs - would fail if the underlying table (but not the actual alias) - were referenced inside the subquery generated by - q.from_self() or q.select_from(). - - - Fixed bug which affected all eagerload() and similar options - such that "remote" eager loads, i.e. eagerloads off of a lazy - load such as query(A).options(eagerload(A.b, B.c)) - wouldn't eagerload anything, but using eagerload("b.c") would - work fine. - - - Query gains an add_columns(*columns) method which is a multi- - version of add_column(col). add_column(col) is future - deprecated. - - - Query.join() will detect if the end result will be - "FROM A JOIN A", and will raise an error if so. - - - Query.join(Cls.propname, from_joinpoint=True) will check more - carefully that "Cls" is compatible with the current joinpoint, - and act the same way as Query.join("propname", from_joinpoint=True) - in that regard. - -- sql - - Added with_hint() method to select() construct. Specify - a table/alias, hint text, and optional dialect name, and - "hints" will be rendered in the appropriate place in the - statement. Works for Oracle, Sybase, MySQL. [ticket:921] - - - Fixed bug introduced in 0.6beta2 where column labels would - render inside of column expressions already assigned a label. - [ticket:1747] - -- postgresql - - The psycopg2 dialect will log NOTICE messages via the - "sqlalchemy.dialects.postgresql" logger name. - [ticket:877] - - - the TIME and TIMESTAMP types are now availble from the - postgresql dialect directly, which add the PG-specific - argument 'precision' to both. 'precision' and - 'timezone' are correctly reflected for both TIME and - TIMEZONE types. [ticket:997] - -- mysql - - No longer guessing that TINYINT(1) should be BOOLEAN - when reflecting - TINYINT(1) is returned. Use Boolean/ - BOOLEAN in table definition to get boolean conversion - behavior. [ticket:1752] - -- oracle - - The Oracle dialect will issue VARCHAR type definitions - using character counts, i.e. VARCHAR2(50 CHAR), so that - the column is sized in terms of characters and not bytes. - Column reflection of character types will also use - ALL_TAB_COLUMNS.CHAR_LENGTH instead of - ALL_TAB_COLUMNS.DATA_LENGTH. Both of these behaviors take - effect when the server version is 9 or higher - for - version 8, the old behaviors are used. [ticket:1744] - -- declarative - - Using a mixin won't break if the mixin implements an - unpredictable __getattribute__(), i.e. Zope interfaces. - [ticket:1746] - - - Using @classdecorator and similar on mixins to define - __tablename__, __table_args__, etc. now works if - the method references attributes on the ultimate - subclass. [ticket:1749] - - - relationships and columns with foreign keys aren't - allowed on declarative mixins, sorry. [ticket:1751] - -- ext - - The sqlalchemy.orm.shard module now becomes an extension, - sqlalchemy.ext.horizontal_shard. The old import - works with a deprecation warning. - -0.6beta2 -======== - -- py3k - - Improved the installation/test setup regarding Python 3, - now that Distribute runs on Py3k. distribute_setup.py - is now included. See README.py3k for Python 3 installation/ - testing instructions. - -- orm - - The official name for the relation() function is now - relationship(), to eliminate confusion over the relational - algebra term. relation() however will remain available - in equal capacity for the foreseeable future. [ticket:1740] - - - Added "version_id_generator" argument to Mapper, this is a - callable that, given the current value of the "version_id_col", - returns the next version number. Can be used for alternate - versioning schemes such as uuid, timestamps. [ticket:1692] - - - added "lockmode" kw argument to Session.refresh(), will - pass through the string value to Query the same as - in with_lockmode(), will also do version check for a - version_id_col-enabled mapping. - - - Fixed bug whereby calling query(A).join(A.bs).add_entity(B) - in a joined inheritance scenario would double-add B as a - target and produce an invalid query. [ticket:1188] - - - Fixed bug in session.rollback() which involved not removing - formerly "pending" objects from the session before - re-integrating "deleted" objects, typically occured with - natural primary keys. If there was a primary key conflict - between them, the attach of the deleted would fail - internally. The formerly "pending" objects are now expunged - first. [ticket:1674] - - - Removed a lot of logging that nobody really cares about, - logging that remains will respond to live changes in the - log level. No significant overhead is added. [ticket:1719] - - - Fixed bug in session.merge() which prevented dict-like - collections from merging. - - - session.merge() works with relations that specifically - don't include "merge" in their cascade options - the target - is ignored completely. - - - session.merge() will not expire existing scalar attributes - on an existing target if the target has a value for that - attribute, even if the incoming merged doesn't have - a value for the attribute. This prevents unnecessary loads - on existing items. Will still mark the attr as expired - if the destination doesn't have the attr, though, which - fulfills some contracts of deferred cols. [ticket:1681] - - - The "allow_null_pks" flag is now called "allow_partial_pks", - defaults to True, acts like it did in 0.5 again. Except, - it also is implemented within merge() such that a SELECT - won't be issued for an incoming instance with partially - NULL primary key if the flag is False. [ticket:1680] - - - Fixed bug in 0.6-reworked "many-to-one" optimizations - such that a many-to-one that is against a non-primary key - column on the remote table (i.e. foreign key against a - UNIQUE column) will pull the "old" value in from the - database during a change, since if it's in the session - we will need it for proper history/backref accounting, - and we can't pull from the local identity map on a - non-primary key column. [ticket:1737] - - - fixed internal error which would occur if calling has() - or similar complex expression on a single-table inheritance - relation(). [ticket:1731] - - - query.one() no longer applies LIMIT to the query, this to - ensure that it fully counts all object identities present - in the result, even in the case where joins may conceal - multiple identities for two or more rows. As a bonus, - one() can now also be called with a query that issued - from_statement() to start with since it no longer modifies - the query. [ticket:1688] - - - query.get() now returns None if queried for an identifier - that is present in the identity map with a different class - than the one requested, i.e. when using polymorphic loading. - [ticket:1727] - - - A major fix in query.join(), when the "on" clause is an - attribute of an aliased() construct, but there is already - an existing join made out to a compatible target, query properly - joins to the right aliased() construct instead of sticking - onto the right side of the existing join. [ticket:1706] - - - Slight improvement to the fix for [ticket:1362] to not issue - needless updates of the primary key column during a so-called - "row switch" operation, i.e. add + delete of two objects - with the same PK. - - - Now uses sqlalchemy.orm.exc.DetachedInstanceError when an - attribute load or refresh action fails due to object - being detached from any Session. UnboundExecutionError - is specific to engines bound to sessions and statements. - - - Query called in the context of an expression will render - disambiguating labels in all cases. Note that this does - not apply to the existing .statement and .subquery() - accessor/method, which still honors the .with_labels() - setting that defaults to False. - - - Query.union() retains disambiguating labels within the - returned statement, thus avoiding various SQL composition - errors which can result from column name conflicts. - [ticket:1676] - - - Fixed bug in attribute history that inadvertently invoked - __eq__ on mapped instances. - - - Some internal streamlining of object loading grants a - small speedup for large results, estimates are around - 10-15%. Gave the "state" internals a good solid - cleanup with less complexity, datamembers, - method calls, blank dictionary creates. - - - Documentation clarification for query.delete() - [ticket:1689] - - - Fixed cascade bug in many-to-one relation() when attribute - was set to None, introduced in r6711 (cascade deleted - items into session during add()). - - - Calling query.order_by() or query.distinct() before calling - query.select_from(), query.with_polymorphic(), or - query.from_statement() raises an exception now instead of - silently dropping those criterion. [ticket:1736] - - - query.scalar() now raises an exception if more than one - row is returned. All other behavior remains the same. - [ticket:1735] - - - Fixed bug which caused "row switch" logic, that is an - INSERT and DELETE replaced by an UPDATE, to fail when - version_id_col was in use. [ticket:1692] - -- sql - - join() will now simulate a NATURAL JOIN by default. Meaning, - if the left side is a join, it will attempt to join the right - side to the rightmost side of the left first, and not raise - any exceptions about ambiguous join conditions if successful - even if there are further join targets across the rest of - the left. [ticket:1714] - - - The most common result processors conversion function were - moved to the new "processors" module. Dialect authors are - encouraged to use those functions whenever they correspond - to their needs instead of implementing custom ones. - - - SchemaType and subclasses Boolean, Enum are now serializable, - including their ddl listener and other event callables. - [ticket:1694] [ticket:1698] - - - Some platforms will now interpret certain literal values - as non-bind parameters, rendered literally into the SQL - statement. This to support strict SQL-92 rules that are - enforced by some platforms including MS-SQL and Sybase. - In this model, bind parameters aren't allowed in the - columns clause of a SELECT, nor are certain ambiguous - expressions like "?=?". When this mode is enabled, the base - compiler will render the binds as inline literals, but only across - strings and numeric values. Other types such as dates - will raise an error, unless the dialect subclass defines - a literal rendering function for those. The bind parameter - must have an embedded literal value already or an error - is raised (i.e. won't work with straight bindparam('x')). - Dialects can also expand upon the areas where binds are not - accepted, such as within argument lists of functions - (which don't work on MS-SQL when native SQL binding is used). - - - Added "unicode_errors" parameter to String, Unicode, etc. - Behaves like the 'errors' keyword argument to - the standard library's string.decode() functions. This flag - requires that `convert_unicode` is set to `"force"` - otherwise, - SQLAlchemy is not guaranteed to handle the task of unicode - conversion. Note that this flag adds significant performance - overhead to row-fetching operations for backends that already - return unicode objects natively (which most DBAPIs do). This - flag should only be used as an absolute last resort for reading - strings from a column with varied or corrupted encodings, - which only applies to databases that accept invalid encodings - in the first place (i.e. MySQL. *not* PG, Sqlite, etc.) - - - Added math negation operator support, -x. - - - FunctionElement subclasses are now directly executable the - same way any func.foo() construct is, with automatic - SELECT being applied when passed to execute(). - - - The "type" and "bind" keyword arguments of a func.foo() - construct are now local to "func." constructs and are - not part of the FunctionElement base class, allowing - a "type" to be handled in a custom constructor or - class-level variable. - - - Restored the keys() method to ResultProxy. - - - The type/expression system now does a more complete job - of determining the return type from an expression - as well as the adaptation of the Python operator into - a SQL operator, based on the full left/right/operator - of the given expression. In particular - the date/time/interval system created for Postgresql - EXTRACT in [ticket:1647] has now been generalized into - the type system. The previous behavior which often - occured of an expression "column + literal" forcing - the type of "literal" to be the same as that of "column" - will now usually not occur - the type of - "literal" is first derived from the Python type of the - literal, assuming standard native Python types + date - types, before falling back to that of the known type - on the other side of the expression. If the - "fallback" type is compatible (i.e. CHAR from String), - the literal side will use that. TypeDecorator - types override this by default to coerce the "literal" - side unconditionally, which can be changed by implementing - the coerce_compared_value() method. Also part of - [ticket:1683]. - - - Made sqlalchemy.sql.expressions.Executable part of public - API, used for any expression construct that can be sent to - execute(). FunctionElement now inherits Executable so that - it gains execution_options(), which are also propagated - to the select() that's generated within execute(). - Executable in turn subclasses _Generative which marks - any ClauseElement that supports the @_generative - decorator - these may also become "public" for the benefit - of the compiler extension at some point. - - - A change to the solution for [ticket:1579] - an end-user - defined bind parameter name that directly conflicts with - a column-named bind generated directly from the SET or - VALUES clause of an update/insert generates a compile error. - This reduces call counts and eliminates some cases where - undesirable name conflicts could still occur. - - - Column() requires a type if it has no foreign keys (this is - not new). An error is now raised if a Column() has no type - and no foreign keys. [ticket:1705] - - - the "scale" argument of the Numeric() type is honored when - coercing a returned floating point value into a string - on its way to Decimal - this allows accuracy to function - on SQLite, MySQL. [ticket:1717] - - - the copy() method of Column now copies over uninitialized - "on table attach" events. Helps with the new declarative - "mixin" capability. - -- engines - - Added an optional C extension to speed up the sql layer by - reimplementing RowProxy and the most common result processors. - The actual speedups will depend heavily on your DBAPI and - the mix of datatypes used in your tables, and can vary from - a 30% improvement to more than 200%. It also provides a modest - (~15-20%) indirect improvement to ORM speed for large queries. - Note that it is *not* built/installed by default. - See README for installation instructions. - - - the execution sequence pulls all rowcount/last inserted ID - info from the cursor before commit() is called on the - DBAPI connection in an "autocommit" scenario. This helps - mxodbc with rowcount and is probably a good idea overall. - - - Opened up logging a bit such that isEnabledFor() is called - more often, so that changes to the log level for engine/pool - will be reflected on next connect. This adds a small - amount of method call overhead. It's negligible and will make - life a lot easier for all those situations when logging - just happens to be configured after create_engine() is called. - [ticket:1719] - - - The assert_unicode flag is deprecated. SQLAlchemy will raise - a warning in all cases where it is asked to encode a non-unicode - Python string, as well as when a Unicode or UnicodeType type - is explicitly passed a bytestring. The String type will do nothing - for DBAPIs that already accept Python unicode objects. - - - Bind parameters are sent as a tuple instead of a list. Some - backend drivers will not accept bind parameters as a list. - - - threadlocal engine wasn't properly closing the connection - upon close() - fixed that. - - - Transaction object doesn't rollback or commit if it isn't - "active", allows more accurate nesting of begin/rollback/commit. - - - Python unicode objects as binds result in the Unicode type, - not string, thus eliminating a certain class of unicode errors - on drivers that don't support unicode binds. - - - Added "logging_name" argument to create_engine(), Pool() constructor - as well as "pool_logging_name" argument to create_engine() which - filters down to that of Pool. Issues the given string name - within the "name" field of logging messages instead of the default - hex identifier string. [ticket:1555] - - - The visit_pool() method of Dialect is removed, and replaced with - connect(). This method returns a callable which receives - the raw DBAPI connection after each one is created. The callable - is assembled into a first_connect/connect pool listener by the - connection strategy if non-None. Provides a simpler interface - for dialects. - - - StaticPool now initializes, disposes and recreates without - opening a new connection - the connection is only opened when - first requested. dispose() also works on AssertionPool now. - [ticket:1728] - -- metadata - - Added the ability to strip schema information when using - "tometadata" by passing "schema=None" as an argument. If schema - is not specified then the table's schema is retained. - [ticket: 1673] - -- declarative - - DeclarativeMeta exclusively uses cls.__dict__ (not dict_) - as the source of class information; _as_declarative exclusively - uses the dict_ passed to it as the source of class information - (which when using DeclarativeMeta is cls.__dict__). This should - in theory make it easier for custom metaclasses to modify - the state passed into _as_declarative. - - - declarative now accepts mixin classes directly, as a means - to provide common functional and column-based elements on - all subclasses, as well as a means to propagate a fixed - set of __table_args__ or __mapper_args__ to subclasses. - For custom combinations of __table_args__/__mapper_args__ from - an inherited mixin to local, descriptors can now be used. - New details are all up in the Declarative documentation. - Thanks to Chris Withers for putting up with my strife - on this. [ticket:1707] - - - the __mapper_args__ dict is copied when propagating to a subclass, - and is taken straight off the class __dict__ to avoid any - propagation from the parent. mapper inheritance already - propagates the things you want from the parent mapper. - [ticket:1393] - - - An exception is raised when a single-table subclass specifies - a column that is already present on the base class. - [ticket:1732] - -- mysql - - Fixed reflection bug whereby when COLLATE was present, - nullable flag and server defaults would not be reflected. - [ticket:1655] - - - Fixed reflection of TINYINT(1) "boolean" columns defined with - integer flags like UNSIGNED. - - - Further fixes for the mysql-connector dialect. [ticket:1668] - - - Composite PK table on InnoDB where the "autoincrement" column - isn't first will emit an explicit "KEY" phrase within - CREATE TABLE thereby avoiding errors, [ticket:1496] - - - Added reflection/create table support for a wide range - of MySQL keywords. [ticket:1634] - - - Fixed import error which could occur reflecting tables on - a Windows host [ticket:1580] - -- mssql - - Re-established support for the pymssql dialect. - - - Various fixes for implicit returning, reflection, - etc. - the MS-SQL dialects aren't quite complete - in 0.6 yet (but are close) - - - Added basic support for mxODBC [ticket:1710]. - - - Removed the text_as_varchar option. - -- oracle - - "out" parameters require a type that is supported by - cx_oracle. An error will be raised if no cx_oracle - type can be found. - - - Oracle 'DATE' now does not perform any result processing, - as the DATE type in Oracle stores full date+time objects, - that's what you'll get. Note that the generic types.Date - type *will* still call value.date() on incoming values, - however. When reflecting a table, the reflected type - will be 'DATE'. - - - Added preliminary support for Oracle's WITH_UNICODE - mode. At the very least this establishes initial - support for cx_Oracle with Python 3. When WITH_UNICODE - mode is used in Python 2.xx, a large and scary warning - is emitted asking that the user seriously consider - the usage of this difficult mode of operation. - [ticket:1670] - - - The except_() method now renders as MINUS on Oracle, - which is more or less equivalent on that platform. - [ticket:1712] - - - Added support for rendering and reflecting - TIMESTAMP WITH TIME ZONE, i.e. TIMESTAMP(timezone=True). - [ticket:651] - - - Oracle INTERVAL type can now be reflected. - -- sqlite - - Added "native_datetime=True" flag to create_engine(). - This will cause the DATE and TIMESTAMP types to skip - all bind parameter and result row processing, under - the assumption that PARSE_DECLTYPES has been enabled - on the connection. Note that this is not entirely - compatible with the "func.current_date()", which - will be returned as a string. [ticket:1685] - -- sybase - - Implemented a preliminary working dialect for Sybase, - with sub-implementations for Python-Sybase as well - as Pyodbc. Handles table - creates/drops and basic round trip functionality. - Does not yet include reflection or comprehensive - support of unicode/special expressions/etc. - -- examples - - Changed the beaker cache example a bit to have a separate - RelationCache option for lazyload caching. This object - does a lookup among any number of potential attributes - more efficiently by grouping several into a common structure. - Both FromCache and RelationCache are simpler individually. - -- documentation - - Major cleanup work in the docs to link class, function, and - method names into the API docs. [ticket:1700/1702/1703] - -0.6beta1 -======== -- Major Release - - For the full set of feature descriptions, see - http://www.sqlalchemy.org/trac/wiki/06Migration . - This document is a work in progress. - - - All bug fixes and feature enhancements from the most - recent 0.5 version and below are also included within 0.6. - - - Platforms targeted now include Python 2.4/2.5/2.6, Python - 3.1, Jython2.5. - -- orm - - Changes to query.update() and query.delete(): - - the 'expire' option on query.update() has been renamed to - 'fetch', thus matching that of query.delete(). - 'expire' is deprecated and issues a warning. - - - query.update() and query.delete() both default to - 'evaluate' for the synchronize strategy. - - - the 'synchronize' strategy for update() and delete() - raises an error on failure. There is no implicit fallback - onto "fetch". Failure of evaluation is based on the - structure of criteria, so success/failure is deterministic - based on code structure. - - - Enhancements on many-to-one relations: - - many-to-one relations now fire off a lazyload in fewer - cases, including in most cases will not fetch the "old" - value when a new one is replaced. - - - many-to-one relation to a joined-table subclass now uses - get() for a simple load (known as the "use_get" - condition), i.e. Related->Sub(Base), without the need to - redefine the primaryjoin condition in terms of the base - table. [ticket:1186] - - - specifying a foreign key with a declarative column, i.e. - ForeignKey(MyRelatedClass.id) doesn't break the "use_get" - condition from taking place [ticket:1492] - - - relation(), eagerload(), and eagerload_all() now feature - an option called "innerjoin". Specify `True` or `False` to - control whether an eager join is constructed as an INNER - or OUTER join. Default is `False` as always. The mapper - options will override whichever setting is specified on - relation(). Should generally be set for many-to-one, not - nullable foreign key relations to allow improved join - performance. [ticket:1544] - - - the behavior of eagerloading such that the main query is - wrapped in a subquery when LIMIT/OFFSET are present now - makes an exception for the case when all eager loads are - many-to-one joins. In those cases, the eager joins are - against the parent table directly along with the - limit/offset without the extra overhead of a subquery, - since a many-to-one join does not add rows to the result. - - - Enhancements / Changes on Session.merge(): - - the "dont_load=True" flag on Session.merge() is deprecated - and is now "load=False". - - - Session.merge() is performance optimized, using half the - call counts for "load=False" mode compared to 0.5 and - significantly fewer SQL queries in the case of collections - for "load=True" mode. - - - merge() will not issue a needless merge of attributes if the - given instance is the same instance which is already present. - - - merge() now also merges the "options" associated with a given - state, i.e. those passed through query.options() which follow - along with an instance, such as options to eagerly- or - lazyily- load various attributes. This is essential for - the construction of highly integrated caching schemes. This - is a subtle behavioral change vs. 0.5. - - - A bug was fixed regarding the serialization of the "loader - path" present on an instance's state, which is also necessary - when combining the usage of merge() with serialized state - and associated options that should be preserved. - - - The all new merge() is showcased in a new comprehensive - example of how to integrate Beaker with SQLAlchemy. See - the notes in the "examples" note below. - - - Primary key values can now be changed on a joined-table inheritance - object, and ON UPDATE CASCADE will be taken into account when - the flush happens. Set the new "passive_updates" flag to False - on mapper() when using SQLite or MySQL/MyISAM. [ticket:1362] - - - flush() now detects when a primary key column was updated by - an ON UPDATE CASCADE operation from another primary key, and - can then locate the row for a subsequent UPDATE on the new PK - value. This occurs when a relation() is there to establish - the relationship as well as passive_updates=True. [ticket:1671] - - - the "save-update" cascade will now cascade the pending *removed* - values from a scalar or collection attribute into the new session - during an add() operation. This so that the flush() operation - will also delete or modify rows of those disconnected items. - - - Using a "dynamic" loader with a "secondary" table now produces - a query where the "secondary" table is *not* aliased. This - allows the secondary Table object to be used in the "order_by" - attribute of the relation(), and also allows it to be used - in filter criterion against the dynamic relation. - [ticket:1531] - - - relation() with uselist=False will emit a warning when - an eager or lazy load locates more than one valid value for - the row. This may be due to primaryjoin/secondaryjoin - conditions which aren't appropriate for an eager LEFT OUTER - JOIN or for other conditions. [ticket:1643] - - - an explicit check occurs when a synonym() is used with - map_column=True, when a ColumnProperty (deferred or otherwise) - exists separately in the properties dictionary sent to mapper - with the same keyname. Instead of silently replacing - the existing property (and possible options on that property), - an error is raised. [ticket:1633] - - - a "dynamic" loader sets up its query criterion at construction - time so that the actual query is returned from non-cloning - accessors like "statement". - - - the "named tuple" objects returned when iterating a - Query() are now pickleable. - - - mapping to a select() construct now requires that you - make an alias() out of it distinctly. This to eliminate - confusion over such issues as [ticket:1542] - - - query.join() has been reworked to provide more consistent - behavior and more flexibility (includes [ticket:1537]) - - - query.select_from() accepts multiple clauses to produce - multiple comma separated entries within the FROM clause. - Useful when selecting from multiple-homed join() clauses. - - - query.select_from() also accepts mapped classes, aliased() - constructs, and mappers as arguments. In particular this - helps when querying from multiple joined-table classes to ensure - the full join gets rendered. - - - query.get() can be used with a mapping to an outer join - where one or more of the primary key values are None. - [ticket:1135] - - - query.from_self(), query.union(), others which do a - "SELECT * from (SELECT...)" type of nesting will do - a better job translating column expressions within the subquery - to the columns clause of the outer query. This is - potentially backwards incompatible with 0.5, in that this - may break queries with literal expressions that do not have labels - applied (i.e. literal('foo'), etc.) - [ticket:1568] - - - relation primaryjoin and secondaryjoin now check that they - are column-expressions, not just clause elements. this prohibits - things like FROM expressions being placed there directly. - [ticket:1622] - - - `expression.null()` is fully understood the same way - None is when comparing an object/collection-referencing - attribute within query.filter(), filter_by(), etc. - [ticket:1415] - - - added "make_transient()" helper function which transforms a - persistent/ detached instance into a transient one (i.e. - deletes the instance_key and removes from any session.) - [ticket:1052] - - - the allow_null_pks flag on mapper() is deprecated, and - the feature is turned "on" by default. This means that - a row which has a non-null value for any of its primary key - columns will be considered an identity. The need for this - scenario typically only occurs when mapping to an outer join. - [ticket:1339] - - - the mechanics of "backref" have been fully merged into the - finer grained "back_populates" system, and take place entirely - within the _generate_backref() method of RelationProperty. This - makes the initialization procedure of RelationProperty - simpler and allows easier propagation of settings (such as from - subclasses of RelationProperty) into the reverse reference. - The internal BackRef() is gone and backref() returns a plain - tuple that is understood by RelationProperty. - - - The version_id_col feature on mapper() will raise a warning when - used with dialects that don't support "rowcount" adequately. - [ticket:1569] - - - added "execution_options()" to Query, to so options can be - passed to the resulting statement. Currently only - Select-statements have these options, and the only option - used is "stream_results", and the only dialect which knows - "stream_results" is psycopg2. - - - Query.yield_per() will set the "stream_results" statement - option automatically. - - - Deprecated or removed: - * 'allow_null_pks' flag on mapper() is deprecated. It does - nothing now and the setting is "on" in all cases. - * 'transactional' flag on sessionmaker() and others is - removed. Use 'autocommit=True' to indicate 'transactional=False'. - * 'polymorphic_fetch' argument on mapper() is removed. - Loading can be controlled using the 'with_polymorphic' - option. - * 'select_table' argument on mapper() is removed. Use - 'with_polymorphic=("*", )' for this - functionality. - * 'proxy' argument on synonym() is removed. This flag - did nothing throughout 0.5, as the "proxy generation" - behavior is now automatic. - * Passing a single list of elements to eagerload(), - eagerload_all(), contains_eager(), lazyload(), - defer(), and undefer() instead of multiple positional - *args is deprecated. - * Passing a single list of elements to query.order_by(), - query.group_by(), query.join(), or query.outerjoin() - instead of multiple positional *args is deprecated. - * query.iterate_instances() is removed. Use query.instances(). - * Query.query_from_parent() is removed. Use the - sqlalchemy.orm.with_parent() function to produce a - "parent" clause, or alternatively query.with_parent(). - * query._from_self() is removed, use query.from_self() - instead. - * the "comparator" argument to composite() is removed. - Use "comparator_factory". - * RelationProperty._get_join() is removed. - * the 'echo_uow' flag on Session is removed. Use - logging on the "sqlalchemy.orm.unitofwork" name. - * session.clear() is removed. use session.expunge_all(). - * session.save(), session.update(), session.save_or_update() - are removed. Use session.add() and session.add_all(). - * the "objects" flag on session.flush() remains deprecated. - * the "dont_load=True" flag on session.merge() is deprecated - in favor of "load=False". - * ScopedSession.mapper remains deprecated. See the - usage recipe at - http://www.sqlalchemy.org/trac/wiki/UsageRecipes/SessionAwareMapper - * passing an InstanceState (internal SQLAlchemy state object) to - attributes.init_collection() or attributes.get_history() is - deprecated. These functions are public API and normally - expect a regular mapped object instance. - * the 'engine' parameter to declarative_base() is removed. - Use the 'bind' keyword argument. - -- sql - - - the "autocommit" flag on select() and text() as well - as select().autocommit() are deprecated - now call - .execution_options(autocommit=True) on either of those - constructs, also available directly on Connection and orm.Query. - - - the autoincrement flag on column now indicates the column - which should be linked to cursor.lastrowid, if that method - is used. See the API docs for details. - - - an executemany() now requires that all bound parameter - sets require that all keys are present which are - present in the first bound parameter set. The structure - and behavior of an insert/update statement is very much - determined by the first parameter set, including which - defaults are going to fire off, and a minimum of - guesswork is performed with all the rest so that performance - is not impacted. For this reason defaults would otherwise - silently "fail" for missing parameters, so this is now guarded - against. [ticket:1566] - - - returning() support is native to insert(), update(), - delete(). Implementations of varying levels of - functionality exist for Postgresql, Firebird, MSSQL and - Oracle. returning() can be called explicitly with column - expressions which are then returned in the resultset, - usually via fetchone() or first(). - - insert() constructs will also use RETURNING implicitly to - get newly generated primary key values, if the database - version in use supports it (a version number check is - performed). This occurs if no end-user returning() was - specified. - - - union(), intersect(), except() and other "compound" types - of statements have more consistent behavior w.r.t. - parenthesizing. Each compound element embedded within - another will now be grouped with parenthesis - previously, - the first compound element in the list would not be grouped, - as SQLite doesn't like a statement to start with - parenthesis. However, Postgresql in particular has - precedence rules regarding INTERSECT, and it is - more consistent for parenthesis to be applied equally - to all sub-elements. So now, the workaround for SQLite - is also what the workaround for PG was previously - - when nesting compound elements, the first one usually needs - ".alias().select()" called on it to wrap it inside - of a subquery. [ticket:1665] - - - insert() and update() constructs can now embed bindparam() - objects using names that match the keys of columns. These - bind parameters will circumvent the usual route to those - keys showing up in the VALUES or SET clause of the generated - SQL. [ticket:1579] - - - the Binary type now returns data as a Python string - (or a "bytes" type in Python 3), instead of the built- - in "buffer" type. This allows symmetric round trips - of binary data. [ticket:1524] - - - Added a tuple_() construct, allows sets of expressions - to be compared to another set, typically with IN against - composite primary keys or similar. Also accepts an - IN with multiple columns. The "scalar select can - have only one column" error message is removed - will - rely upon the database to report problems with - col mismatch. - - - User-defined "default" and "onupdate" callables which - accept a context should now call upon - "context.current_parameters" to get at the dictionary - of bind parameters currently being processed. This - dict is available in the same way regardless of - single-execute or executemany-style statement execution. - - - multi-part schema names, i.e. with dots such as - "dbo.master", are now rendered in select() labels - with underscores for dots, i.e. "dbo_master_table_column". - This is a "friendly" label that behaves better - in result sets. [ticket:1428] - - - removed needless "counter" behavior with select() - labelnames that match a column name in the table, - i.e. generates "tablename_id" for "id", instead of - "tablename_id_1" in an attempt to avoid naming - conflicts, when the table has a column actually - named "tablename_id" - this is because - the labeling logic is always applied to all columns - so a naming conflict will never occur. - - - calling expr.in_([]), i.e. with an empty list, emits a warning - before issuing the usual "expr != expr" clause. The - "expr != expr" can be very expensive, and it's preferred - that the user not issue in_() if the list is empty, - instead simply not querying, or modifying the criterion - as appropriate for more complex situations. - [ticket:1628] - - - Added "execution_options()" to select()/text(), which set the - default options for the Connection. See the note in "engines". - - - Deprecated or removed: - * "scalar" flag on select() is removed, use - select.as_scalar(). - * "shortname" attribute on bindparam() is removed. - * postgres_returning, firebird_returning flags on - insert(), update(), delete() are deprecated, use - the new returning() method. - * fold_equivalents flag on join is deprecated (will remain - until [ticket:1131] is implemented) - -- engines - - transaction isolation level may be specified with - create_engine(... isolation_level="..."); available on - postgresql and sqlite. [ticket:443] - - - Connection has execution_options(), generative method - which accepts keywords that affect how the statement - is executed w.r.t. the DBAPI. Currently supports - "stream_results", causes psycopg2 to use a server - side cursor for that statement, as well as - "autocommit", which is the new location for the "autocommit" - option from select() and text(). select() and - text() also have .execution_options() as well as - ORM Query(). - - - fixed the import for entrypoint-driven dialects to - not rely upon silly tb_info trick to determine import - error status. [ticket:1630] - - - added first() method to ResultProxy, returns first row and - closes result set immediately. - - - RowProxy objects are now pickleable, i.e. the object returned - by result.fetchone(), result.fetchall() etc. - - - RowProxy no longer has a close() method, as the row no longer - maintains a reference to the parent. Call close() on - the parent ResultProxy instead, or use autoclose. - - - ResultProxy internals have been overhauled to greatly reduce - method call counts when fetching columns. Can provide a large - speed improvement (up to more than 100%) when fetching large - result sets. The improvement is larger when fetching columns - that have no type-level processing applied and when using - results as tuples (instead of as dictionaries). Many - thanks to Elixir's Gaëtan de Menten for this dramatic - improvement ! [ticket:1586] - - - Databases which rely upon postfetch of "last inserted id" - to get at a generated sequence value (i.e. MySQL, MS-SQL) - now work correctly when there is a composite primary key - where the "autoincrement" column is not the first primary - key column in the table. - - - the last_inserted_ids() method has been renamed to the - descriptor "inserted_primary_key". - - - setting echo=False on create_engine() now sets the loglevel - to WARN instead of NOTSET. This so that logging can be - disabled for a particular engine even if logging - for "sqlalchemy.engine" is enabled overall. Note that the - default setting of "echo" is `None`. [ticket:1554] - - - ConnectionProxy now has wrapper methods for all transaction - lifecycle events, including begin(), rollback(), commit() - begin_nested(), begin_prepared(), prepare(), release_savepoint(), - etc. - - - Connection pool logging now uses both INFO and DEBUG - log levels for logging. INFO is for major events such - as invalidated connections, DEBUG for all the acquire/return - logging. `echo_pool` can be False, None, True or "debug" - the same way as `echo` works. - - - All pyodbc-dialects now support extra pyodbc-specific - kw arguments 'ansi', 'unicode_results', 'autocommit'. - [ticket:1621] - - - the "threadlocal" engine has been rewritten and simplified - and now supports SAVEPOINT operations. - - - deprecated or removed - * result.last_inserted_ids() is deprecated. Use - result.inserted_primary_key - * dialect.get_default_schema_name(connection) is now - public via dialect.default_schema_name. - * the "connection" argument from engine.transaction() and - engine.run_callable() is removed - Connection itself - now has those methods. All four methods accept - *args and **kwargs which are passed to the given callable, - as well as the operating connection. - -- schema - - the `__contains__()` method of `MetaData` now accepts - strings or `Table` objects as arguments. If given - a `Table`, the argument is converted to `table.key` first, - i.e. "[schemaname.]" [ticket:1541] - - - deprecated MetaData.connect() and - ThreadLocalMetaData.connect() have been removed - send - the "bind" attribute to bind a metadata. - - - deprecated metadata.table_iterator() method removed (use - sorted_tables) - - - deprecated PassiveDefault - use DefaultClause. - - - the "metadata" argument is removed from DefaultGenerator - and subclasses, but remains locally present on Sequence, - which is a standalone construct in DDL. - - - Removed public mutability from Index and Constraint - objects: - - ForeignKeyConstraint.append_element() - - Index.append_column() - - UniqueConstraint.append_column() - - PrimaryKeyConstraint.add() - - PrimaryKeyConstraint.remove() - These should be constructed declaratively (i.e. in one - construction). - - - The "start" and "increment" attributes on Sequence now - generate "START WITH" and "INCREMENT BY" by default, - on Oracle and Postgresql. Firebird doesn't support - these keywords right now. [ticket:1545] - - - UniqueConstraint, Index, PrimaryKeyConstraint all accept - lists of column names or column objects as arguments. - - - Other removed things: - - Table.key (no idea what this was for) - - Table.primary_key is not assignable - use - table.append_constraint(PrimaryKeyConstraint(...)) - - Column.bind (get via column.table.bind) - - Column.metadata (get via column.table.metadata) - - Column.sequence (use column.default) - - ForeignKey(constraint=some_parent) (is now private _constraint) - - - The use_alter flag on ForeignKey is now a shortcut option - for operations that can be hand-constructed using the - DDL() event system. A side effect of this refactor is - that ForeignKeyConstraint objects with use_alter=True - will *not* be emitted on SQLite, which does not support - ALTER for foreign keys. - - - ForeignKey and ForeignKeyConstraint objects now correctly - copy() all their public keyword arguments. [ticket:1605] - -- Reflection/Inspection - - Table reflection has been expanded and generalized into - a new API called "sqlalchemy.engine.reflection.Inspector". - The Inspector object provides fine-grained information about - a wide variety of schema information, with room for expansion, - including table names, column names, view definitions, sequences, - indexes, etc. - - - Views are now reflectable as ordinary Table objects. The same - Table constructor is used, with the caveat that "effective" - primary and foreign key constraints aren't part of the reflection - results; these have to be specified explicitly if desired. - - - The existing autoload=True system now uses Inspector underneath - so that each dialect need only return "raw" data about tables - and other objects - Inspector is the single place that information - is compiled into Table objects so that consistency is at a maximum. - -- DDL - - the DDL system has been greatly expanded. the DDL() class - now extends the more generic DDLElement(), which forms the basis - of many new constructs: - - - CreateTable() - - DropTable() - - AddConstraint() - - DropConstraint() - - CreateIndex() - - DropIndex() - - CreateSequence() - - DropSequence() - - These support "on" and "execute-at()" just like plain DDL() - does. User-defined DDLElement subclasses can be created and - linked to a compiler using the sqlalchemy.ext.compiler extension. - - - The signature of the "on" callable passed to DDL() and - DDLElement() is revised as follows: - - "ddl" - the DDLElement object itself. - "event" - the string event name. - "target" - previously "schema_item", the Table or - MetaData object triggering the event. - "connection" - the Connection object in use for the operation. - **kw - keyword arguments. In the case of MetaData before/after - create/drop, the list of Table objects for which - CREATE/DROP DDL is to be issued is passed as the kw - argument "tables". This is necessary for metadata-level - DDL that is dependent on the presence of specific tables. - - - the "schema_item" attribute of DDL has been renamed to - "target". - -- dialect refactor - - Dialect modules are now broken into database dialects - plus DBAPI implementations. Connect URLs are now - preferred to be specified using dialect+driver://..., - i.e. "mysql+mysqldb://scott:tiger@localhost/test". See - the 0.6 documentation for examples. - - - the setuptools entrypoint for external dialects is now - called "sqlalchemy.dialects". - - - the "owner" keyword argument is removed from Table. Use - "schema" to represent any namespaces to be prepended to - the table name. - - - server_version_info becomes a static attribute. - - - dialects receive an initialize() event on initial - connection to determine connection properties. - - - dialects receive a visit_pool event have an opportunity - to establish pool listeners. - - - cached TypeEngine classes are cached per-dialect class - instead of per-dialect. - - - new UserDefinedType should be used as a base class for - new types, which preserves the 0.5 behavior of - get_col_spec(). - - - The result_processor() method of all type classes now - accepts a second argument "coltype", which is the DBAPI - type argument from cursor.description. This argument - can help some types decide on the most efficient processing - of result values. - - - Deprecated Dialect.get_params() removed. - - - Dialect.get_rowcount() has been renamed to a descriptor - "rowcount", and calls cursor.rowcount directly. Dialects - which need to hardwire a rowcount in for certain calls - should override the method to provide different behavior. - - - DefaultRunner and subclasses have been removed. The job - of this object has been simplified and moved into - ExecutionContext. Dialects which support sequences should - add a `fire_sequence()` method to their execution context - implementation. [ticket:1566] - - - Functions and operators generated by the compiler now use - (almost) regular dispatch functions of the form - "visit_" and "visit__fn" to provide - customed processing. This replaces the need to copy the - "functions" and "operators" dictionaries in compiler - subclasses with straightforward visitor methods, and also - allows compiler subclasses complete control over - rendering, as the full _Function or _BinaryExpression - object is passed in. - -- postgresql - - New dialects: pg8000, zxjdbc, and pypostgresql - on py3k. - - - The "postgres" dialect is now named "postgresql" ! - Connection strings look like: - - postgresql://scott:tiger@localhost/test - postgresql+pg8000://scott:tiger@localhost/test - - The "postgres" name remains for backwards compatiblity - in the following ways: - - - There is a "postgres.py" dummy dialect which - allows old URLs to work, i.e. - postgres://scott:tiger@localhost/test - - - The "postgres" name can be imported from the old - "databases" module, i.e. "from - sqlalchemy.databases import postgres" as well as - "dialects", "from sqlalchemy.dialects.postgres - import base as pg", will send a deprecation - warning. - - - Special expression arguments are now named - "postgresql_returning" and "postgresql_where", but - the older "postgres_returning" and - "postgres_where" names still work with a - deprecation warning. - - - "postgresql_where" now accepts SQL expressions which - can also include literals, which will be quoted as needed. - - - The psycopg2 dialect now uses psycopg2's "unicode extension" - on all new connections, which allows all String/Text/etc. - types to skip the need to post-process bytestrings into - unicode (an expensive step due to its volume). Other - dialects which return unicode natively (pg8000, zxjdbc) - also skip unicode post-processing. - - - Added new ENUM type, which exists as a schema-level - construct and extends the generic Enum type. Automatically - associates itself with tables and their parent metadata - to issue the appropriate CREATE TYPE/DROP TYPE - commands as needed, supports unicode labels, supports - reflection. [ticket:1511] - - - INTERVAL supports an optional "precision" argument - corresponding to the argument that PG accepts. - - - using new dialect.initialize() feature to set up - version-dependent behavior. - - - somewhat better support for % signs in table/column names; - psycopg2 can't handle a bind parameter name of - %(foobar)s however and SQLA doesn't want to add overhead - just to treat that one non-existent use case. - [ticket:1279] - - - Inserting NULL into a primary key + foreign key column - will allow the "not null constraint" error to raise, - not an attempt to execute a nonexistent "col_id_seq" - sequence. [ticket:1516] - - - autoincrement SELECT statements, i.e. those which - select from a procedure that modifies rows, now work - with server-side cursor mode (the named cursor isn't - used for such statements.) - - - postgresql dialect can properly detect pg "devel" version - strings, i.e. "8.5devel" [ticket:1636] - - - The psycopg2 now respects the statement option - "stream_results". This option overrides the connection setting - "server_side_cursors". If true, server side cursors will be - used for the statement. If false, they will not be used, even - if "server_side_cursors" is true on the - connection. [ticket:1619] - -- mysql - - New dialects: oursql, a new native dialect, - MySQL Connector/Python, a native Python port of MySQLdb, - and of course zxjdbc on Jython. - - - VARCHAR/NVARCHAR will not render without a length, raises - an error before passing to MySQL. Doesn't impact - CAST since VARCHAR is not allowed in MySQL CAST anyway, - the dialect renders CHAR/NCHAR in those cases. - - - all the _detect_XXX() functions now run once underneath - dialect.initialize() - - - somewhat better support for % signs in table/column names; - MySQLdb can't handle % signs in SQL when executemany() is used, - and SQLA doesn't want to add overhead just to treat that one - non-existent use case. [ticket:1279] - - - the BINARY and MSBinary types now generate "BINARY" in all - cases. Omitting the "length" parameter will generate - "BINARY" with no length. Use BLOB to generate an unlengthed - binary column. - - - the "quoting='quoted'" argument to MSEnum/ENUM is deprecated. - It's best to rely upon the automatic quoting. - - - ENUM now subclasses the new generic Enum type, and also handles - unicode values implicitly, if the given labelnames are unicode - objects. - - - a column of type TIMESTAMP now defaults to NULL if - "nullable=False" is not passed to Column(), and no default - is present. This is now consistent with all other types, - and in the case of TIMESTAMP explictly renders "NULL" - due to MySQL's "switching" of default nullability - for TIMESTAMP columns. [ticket:1539] - -- oracle - - unit tests pass 100% with cx_oracle ! - - - support for cx_Oracle's "native unicode" mode which does - not require NLS_LANG to be set. Use the latest 5.0.2 or - later of cx_oracle. - - - an NCLOB type is added to the base types. - - - use_ansi=False won't leak into the FROM/WHERE clause of - a statement that's selecting from a subquery that also - uses JOIN/OUTERJOIN. - - - added native INTERVAL type to the dialect. This supports - only the DAY TO SECOND interval type so far due to lack - of support in cx_oracle for YEAR TO MONTH. [ticket:1467] - - - usage of the CHAR type results in cx_oracle's - FIXED_CHAR dbapi type being bound to statements. - - - the Oracle dialect now features NUMBER which intends - to act justlike Oracle's NUMBER type. It is the primary - numeric type returned by table reflection and attempts - to return Decimal()/float/int based on the precision/scale - parameters. [ticket:885] - - - func.char_length is a generic function for LENGTH - - - ForeignKey() which includes onupdate= will emit a - warning, not emit ON UPDATE CASCADE which is unsupported - by oracle - - - the keys() method of RowProxy() now returns the result - column names *normalized* to be SQLAlchemy case - insensitive names. This means they will be lower case for - case insensitive names, whereas the DBAPI would normally - return them as UPPERCASE names. This allows row keys() to - be compatible with further SQLAlchemy operations. - - - using new dialect.initialize() feature to set up - version-dependent behavior. - - - using types.BigInteger with Oracle will generate - NUMBER(19) [ticket:1125] - - - "case sensitivity" feature will detect an all-lowercase - case-sensitive column name during reflect and add - "quote=True" to the generated Column, so that proper - quoting is maintained. - -- firebird - - the keys() method of RowProxy() now returns the result - column names *normalized* to be SQLAlchemy case - insensitive names. This means they will be lower case for - case insensitive names, whereas the DBAPI would normally - return them as UPPERCASE names. This allows row keys() to - be compatible with further SQLAlchemy operations. - - - using new dialect.initialize() feature to set up - version-dependent behavior. - - - "case sensitivity" feature will detect an all-lowercase - case-sensitive column name during reflect and add - "quote=True" to the generated Column, so that proper - quoting is maintained. - -- mssql - - MSSQL + Pyodbc + FreeTDS now works for the most part, - with possible exceptions regarding binary data as well as - unicode schema identifiers. - - the "has_window_funcs" flag is removed. LIMIT/OFFSET - usage will use ROW NUMBER as always, and if on an older - version of SQL Server, the operation fails. The behavior - is exactly the same except the error is raised by SQL - server instead of the dialect, and no flag setting is - required to enable it. - - the "auto_identity_insert" flag is removed. This feature - always takes effect when an INSERT statement overrides a - column that is known to have a sequence on it. As with - "has_window_funcs", if the underlying driver doesn't - support this, then you can't do this operation in any - case, so there's no point in having a flag. - - using new dialect.initialize() feature to set up - version-dependent behavior. - - removed references to sequence which is no longer used. - implicit identities in mssql work the same as implicit - sequences on any other dialects. Explicit sequences are - enabled through the use of "default=Sequence()". See - the MSSQL dialect documentation for more information. - -- sqlite - - DATE, TIME and DATETIME types can now take optional storage_format - and regexp argument. storage_format can be used to store those types - using a custom string format. regexp allows to use a custom regular - expression to match string values from the database. - - Time and DateTime types now use by a default a stricter regular - expression to match strings from the database. Use the regexp - argument if you are using data stored in a legacy format. - - __legacy_microseconds__ on SQLite Time and DateTime types is not - supported anymore. You should use the storage_format argument - instead. - - Date, Time and DateTime types are now stricter in what they accept as - bind parameters: Date type only accepts date objects (and datetime - ones, because they inherit from date), Time only accepts time - objects, and DateTime only accepts date and datetime objects. - - Table() supports a keyword argument "sqlite_autoincrement", which - applies the SQLite keyword "AUTOINCREMENT" to the single integer - primary key column when generating DDL. Will prevent generation of - a separate PRIMARY KEY constraint. [ticket:1016] - -- new dialects - - postgresql+pg8000 - - postgresql+pypostgresql (partial) - - postgresql+zxjdbc - - mysql+pyodbc - - mysql+zxjdbc - -- types - - The construction of types within dialects has been totally - overhauled. Dialects now define publically available types - as UPPERCASE names exclusively, and internal implementation - types using underscore identifiers (i.e. are private). - The system by which types are expressed in SQL and DDL - has been moved to the compiler system. This has the - effect that there are much fewer type objects within - most dialects. A detailed document on this architecture - for dialect authors is in - lib/sqlalchemy/dialects/type_migration_guidelines.txt . - - - Types no longer make any guesses as to default - parameters. In particular, Numeric, Float, NUMERIC, - FLOAT, DECIMAL don't generate any length or scale unless - specified. - - - types.Binary is renamed to types.LargeBinary, it only - produces BLOB, BYTEA, or a similar "long binary" type. - New base BINARY and VARBINARY - types have been added to access these MySQL/MS-SQL specific - types in an agnostic way [ticket:1664]. - - - String/Text/Unicode types now skip the unicode() check - on each result column value if the dialect has - detected the DBAPI as returning Python unicode objects - natively. This check is issued on first connect - using "SELECT CAST 'some text' AS VARCHAR(10)" or - equivalent, then checking if the returned object - is a Python unicode. This allows vast performance - increases for native-unicode DBAPIs, including - pysqlite/sqlite3, psycopg2, and pg8000. - - - Most types result processors have been checked for possible speed - improvements. Specifically, the following generic types have been - optimized, resulting in varying speed improvements: - Unicode, PickleType, Interval, TypeDecorator, Binary. - Also the following dbapi-specific implementations have been improved: - Time, Date and DateTime on Sqlite, ARRAY on Postgresql, - Time on MySQL, Numeric(as_decimal=False) on MySQL, oursql and - pypostgresql, DateTime on cx_oracle and LOB-based types on cx_oracle. - - - Reflection of types now returns the exact UPPERCASE - type within types.py, or the UPPERCASE type within - the dialect itself if the type is not a standard SQL - type. This means reflection now returns more accurate - information about reflected types. - - - Added a new Enum generic type. Enum is a schema-aware object - to support databases which require specific DDL in order to - use enum or equivalent; in the case of PG it handles the - details of `CREATE TYPE`, and on other databases without - native enum support will by generate VARCHAR + an inline CHECK - constraint to enforce the enum. - [ticket:1109] [ticket:1511] - - - The Interval type includes a "native" flag which controls - if native INTERVAL types (postgresql + oracle) are selected - if available, or not. "day_precision" and "second_precision" - arguments are also added which propagate as appropriately - to these native types. Related to [ticket:1467]. - - - The Boolean type, when used on a backend that doesn't - have native boolean support, will generate a CHECK - constraint "col IN (0, 1)" along with the int/smallint- - based column type. This can be switched off if - desired with create_constraint=False. - Note that MySQL has no native boolean *or* CHECK constraint - support so this feature isn't available on that platform. - [ticket:1589] - - - PickleType now uses == for comparison of values when - mutable=True, unless the "comparator" argument with a - comparsion function is specified to the type. Objects - being pickled will be compared based on identity (which - defeats the purpose of mutable=True) if __eq__() is not - overridden or a comparison function is not provided. - - - The default "precision" and "scale" arguments of Numeric - and Float have been removed and now default to None. - NUMERIC and FLOAT will be rendered with no numeric - arguments by default unless these values are provided. - - - AbstractType.get_search_list() is removed - the games - that was used for are no longer necessary. - - - Added a generic BigInteger type, compiles to - BIGINT or NUMBER(19). [ticket:1125] - --ext - - sqlsoup has been overhauled to explicitly support an 0.5 style - session, using autocommit=False, autoflush=True. Default - behavior of SQLSoup now requires the usual usage of commit() - and rollback(), which have been added to its interface. An - explcit Session or scoped_session can be passed to the - constructor, allowing these arguments to be overridden. - - sqlsoup db..update() and delete() now call - query(cls).update() and delete(), respectively. +Please see: - - sqlsoup now has execute() and connection(), which call upon - the Session methods of those names, ensuring that the bind is - in terms of the SqlSoup object's bind. + /doc/changelog/index.html - - sqlsoup objects no longer have the 'query' attribute - it's - not needed for sqlsoup's usage paradigm and it gets in the - way of a column that is actually named 'query'. +or - - The signature of the proxy_factory callable passed to - association_proxy is now (lazy_collection, creator, - value_attr, association_proxy), adding a fourth argument - that is the parent AssociationProxy argument. Allows - serializability and subclassing of the built in collections. - [ticket:1259] + http://www.sqlalchemy.org/docs/latest/changelog/ - - association_proxy now has basic comparator methods .any(), - .has(), .contains(), ==, !=, thanks to Scott Torborg. - [ticket:1372] +for an index of all changelogs. -- examples - - The "query_cache" examples have been removed, and are replaced - with a fully comprehensive approach that combines the usage of - Beaker with SQLAlchemy. New query options are used to indicate - the caching characteristics of a particular Query, which - can also be invoked deep within an object graph when lazily - loading related objects. See /examples/beaker_caching/README. -For changes prior to 0.6, see CHANGES_PRE_06 diff --git a/CHANGES_PRE_06 b/CHANGES_PRE_06 deleted file mode 100644 index fe0c36b46d..0000000000 --- a/CHANGES_PRE_06 +++ /dev/null @@ -1,6343 +0,0 @@ --*- coding: utf-8; fill-column: 68 -*- - -=============== -CHANGES PRE-0.6 -=============== - -0.5.9 -===== -- sql - - Fixed erroneous self_group() call in expression package. - [ticket:1661] - -0.5.8 -===== -- sql - - The copy() method on Column now supports uninitialized, - unnamed Column objects. This allows easy creation of - declarative helpers which place common columns on multiple - subclasses. - - - Default generators like Sequence() translate correctly - across a copy() operation. - - - Sequence() and other DefaultGenerator objects are accepted - as the value for the "default" and "onupdate" keyword - arguments of Column, in addition to being accepted - positionally. - - - Fixed a column arithmetic bug that affected column - correspondence for cloned selectables which contain - free-standing column expressions. This bug is - generally only noticeable when exercising newer - ORM behavior only availble in 0.6 via [ticket:1568], - but is more correct at the SQL expression level - as well. [ticket:1617] - -- postgresql - - The extract() function, which was slightly improved in - 0.5.7, needed a lot more work to generate the correct - typecast (the typecasts appear to be necessary in PG's - EXTRACT quite a lot of the time). The typecast is - now generated using a rule dictionary based - on PG's documentation for date/time/interval arithmetic. - It also accepts text() constructs again, which was broken - in 0.5.7. [ticket:1647] - -- firebird - - Recognize more errors as disconnections. [ticket:1646] - -0.5.7 -===== -- orm - - contains_eager() now works with the automatically - generated subquery that results when you say - "query(Parent).join(Parent.somejoinedsubclass)", i.e. - when Parent joins to a joined-table-inheritance subclass. - Previously contains_eager() would erroneously add the - subclass table to the query separately producing a - cartesian product. An example is in the ticket - description. [ticket:1543] - - - query.options() now only propagate to loaded objects - for potential further sub-loads only for options where - such behavior is relevant, keeping - various unserializable options like those generated - by contains_eager() out of individual instance states. - [ticket:1553] - - - Session.execute() now locates table- and - mapper-specific binds based on a passed - in expression which is an insert()/update()/delete() - construct. [ticket:1054] - - - Session.merge() now properly overwrites a many-to-one or - uselist=False attribute to None if the attribute - is also None in the given object to be merged. - - - Fixed a needless select which would occur when merging - transient objects that contained a null primary key - identifier. [ticket:1618] - - - Mutable collection passed to the "extension" attribute - of relation(), column_property() etc. will not be mutated - or shared among multiple instrumentation calls, preventing - duplicate extensions, such as backref populators, - from being inserted into the list. - [ticket:1585] - - - Fixed the call to get_committed_value() on CompositeProperty. - [ticket:1504] - - - Fixed bug where Query would crash if a join() with no clear - "left" side were called when a non-mapped column entity - appeared in the columns list. [ticket:1602] - - - Fixed bug whereby composite columns wouldn't load properly - when configured on a joined-table subclass, introduced in - version 0.5.6 as a result of the fix for [ticket:1480]. - [ticket:1616] thx to Scott Torborg. - - - The "use get" behavior of many-to-one relations, i.e. that a - lazy load will fallback to the possibly cached query.get() - value, now works across join conditions where the two compared - types are not exactly the same class, but share the same - "affinity" - i.e. Integer and SmallInteger. Also allows - combinations of reflected and non-reflected types to work - with 0.5 style type reflection, such as PGText/Text (note 0.6 - reflects types as their generic versions). [ticket:1556] - - - Fixed bug in query.update() when passing Cls.attribute - as keys in the value dict and using synchronize_session='expire' - ('fetch' in 0.6). [ticket:1436] - -- sql - - Fixed bug in two-phase transaction whereby commit() method - didn't set the full state which allows subsequent close() - call to succeed. [ticket:1603] - - - Fixed the "numeric" paramstyle, which apparently is the - default paramstyle used by Informixdb. - - - Repeat expressions in the columns clause of a select - are deduped based on the identity of each clause element, - not the actual string. This allows positional - elements to render correctly even if they all render - identically, such as "qmark" style bind parameters. - [ticket:1574] - - - The cursor associated with connection pool connections - (i.e. _CursorFairy) now proxies `__iter__()` to the - underlying cursor correctly. [ticket:1632] - - - types now support an "affinity comparison" operation, i.e. - that an Integer/SmallInteger are "compatible", or - a Text/String, PickleType/Binary, etc. Part of - [ticket:1556]. - - - Fixed bug preventing alias() of an alias() from being - cloned or adapted (occurs frequently in ORM operations). - [ticket:1641] - -- sqlite - - sqlite dialect properly generates CREATE INDEX for a table - that is in an alternate schema. [ticket:1439] - -- postgresql - - Added support for reflecting the DOUBLE PRECISION type, - via a new postgres.PGDoublePrecision object. - This is postgresql.DOUBLE_PRECISION in 0.6. - [ticket:1085] - - - Added support for reflecting the INTERVAL YEAR TO MONTH - and INTERVAL DAY TO SECOND syntaxes of the INTERVAL - type. [ticket:460] - - - Corrected the "has_sequence" query to take current schema, - or explicit sequence-stated schema, into account. - [ticket:1576] - - - Fixed the behavior of extract() to apply operator - precedence rules to the "::" operator when applying - the "timestamp" cast - ensures proper parenthesization. - [ticket:1611] - -- mssql - - Changed the name of TrustedConnection to - Trusted_Connection when constructing pyodbc connect - arguments [ticket:1561] - -- oracle - - The "table_names" dialect function, used by MetaData - .reflect(), omits "index overflow tables", a system - table generated by Oracle when "index only tables" - with overflow are used. These tables aren't accessible - via SQL and can't be reflected. [ticket:1637] - -- ext - - A column can be added to a joined-table declarative - superclass after the class has been constructed - (i.e. via class-level attribute assignment), and - the column will be propagated down to - subclasses. [ticket:1570] This is the reverse - situation as that of [ticket:1523], fixed in 0.5.6. - - - Fixed a slight inaccuracy in the sharding example. - Comparing equivalence of columns in the ORM is best - accomplished using col1.shares_lineage(col2). - [ticket:1491] - - - Removed unused `load()` method from ShardedQuery. - [ticket:1606] - -0.5.6 -===== -- orm - - Fixed bug whereby inheritance discriminator part of a - composite primary key would fail on updates. - Continuation of [ticket:1300]. - - - Fixed bug which disallowed one side of a many-to-many - bidirectional reference to declare itself as "viewonly" - [ticket:1507] - - - Added an assertion that prevents a @validates function - or other AttributeExtension from loading an unloaded - collection such that internal state may be corrupted. - [ticket:1526] - - - Fixed bug which prevented two entities from mutually - replacing each other's primary key values within a single - flush() for some orderings of operations. [ticket:1519] - - - Fixed an obscure issue whereby a joined-table subclass - with a self-referential eager load on the base class - would populate the related object's "subclass" table with - data from the "subclass" table of the parent. - [ticket:1485] - - - relations() now have greater ability to be "overridden", - meaning a subclass that explicitly specifies a relation() - overriding that of the parent class will be honored - during a flush. This is currently to support - many-to-many relations from concrete inheritance setups. - Outside of that use case, YMMV. [ticket:1477] - - - Squeezed a few more unnecessary "lazy loads" out of - relation(). When a collection is mutated, many-to-one - backrefs on the other side will not fire off to load - the "old" value, unless "single_parent=True" is set. - A direct assignment of a many-to-one still loads - the "old" value in order to update backref collections - on that value, which may be present in the session - already, thus maintaining the 0.5 behavioral contract. - [ticket:1483] - - - Fixed bug whereby a load/refresh of joined table - inheritance attributes which were based on - column_property() or similar would fail to evaluate. - [ticket:1480] - - - Improved support for MapperProperty objects overriding - that of an inherited mapper for non-concrete - inheritance setups - attribute extensions won't randomly - collide with each other. [ticket:1488] - - - UPDATE and DELETE do not support ORDER BY, LIMIT, OFFSET, - etc. in standard SQL. Query.update() and Query.delete() - now raise an exception if any of limit(), offset(), - order_by(), group_by(), or distinct() have been - called. [ticket:1487] - - - Added AttributeExtension to sqlalchemy.orm.__all__ - - - Improved error message when query() is called with - a non-SQL /entity expression. [ticket:1476] - - - Using False or 0 as a polymorphic discriminator now - works on the base class as well as a subclass. - [ticket:1440] - - - Added enable_assertions(False) to Query which disables - the usual assertions for expected state - used - by Query subclasses to engineer custom state. - [ticket:1424]. See - http://www.sqlalchemy.org/trac/wiki/UsageRecipes/PreFilteredQuery - for an example. - - - Fixed recursion issue which occured if a mapped object's - `__len__()` or `__nonzero__()` method resulted in state - changes. [ticket:1501] - - - Fixed incorrect exception raise in - Weak/StrongIdentityMap.add() - [ticket:1506] - - - Fixed the error message for "could not find a FROM clause" - in query.join() which would fail to issue correctly - if the query was against a pure SQL construct. - [ticket:1522] - - - Fixed a somewhat hypothetical issue which would result - in the wrong primary key being calculated for a mapper - using the old polymorphic_union function - but this - is old stuff. [ticket:1486] - -- sql - - Fixed column.copy() to copy defaults and onupdates. - [ticket:1373] - - - Fixed a bug in extract() introduced in 0.5.4 whereby - the string "field" argument was getting treated as a - ClauseElement, causing various errors within more - complex SQL transformations. - - - Unary expressions such as DISTINCT propagate their - type handling to result sets, allowing conversions like - unicode and such to take place. [ticket:1420] - - - Fixed bug in Table and Column whereby passing empty - dict for "info" argument would raise an exception. - [ticket:1482] - -- oracle - - Backported 0.6 fix for Oracle alias names not getting - truncated. [ticket:1309] - -- ext - - The collection proxies produced by associationproxy are now - pickleable. A user-defined proxy_factory however - is still not pickleable unless it defines __getstate__ - and __setstate__. [ticket:1446] - - - Declarative will raise an informative exception if - __table_args__ is passed as a tuple with no dict argument. - Improved documentation. [ticket:1468] - - - Table objects declared in the MetaData can now be used - in string expressions sent to primaryjoin/secondaryjoin/ - secondary - the name is pulled from the MetaData of the - declarative base. [ticket:1527] - - - A column can be added to a joined-table subclass after - the class has been constructed (i.e. via class-level - attribute assignment). The column is added to the underlying - Table as always, but now the mapper will rebuild its - "join" to include the new column, instead of raising - an error about "no such column, use column_property() - instead". [ticket:1523] - -- test - - Added examples into the test suite so they get exercised - regularly and cleaned up a couple deprecation warnings. - - -0.5.5 -======= -- general - - unit tests have been migrated from unittest to nose. See - README.unittests for information on how to run the tests. - [ticket:970] - -- orm - - The "foreign_keys" argument of relation() will now propagate - automatically to the backref in the same way that primaryjoin - and secondaryjoin do. For the extremely rare use case where - the backref of a relation() has intentionally different - "foreign_keys" configured, both sides now need to be - configured explicity (if they do in fact require this setting, - see the next note...). - - - ...the only known (and really, really rare) use case where a - different foreign_keys setting was used on the - forwards/backwards side, a composite foreign key that - partially points to its own columns, has been enhanced such - that the fk->itself aspect of the relation won't be used to - determine relation direction. - - - Session.mapper is now *deprecated*. - - Call session.add() if you'd like a free-standing object to be - part of your session. Otherwise, a DIY version of - Session.mapper is now documented at - http://www.sqlalchemy.org/trac/wiki/UsageRecipes/SessionAwareMapper - The method will remain deprecated throughout 0.6. - - - Fixed Query being able to join() from individual columns of a - joined-table subclass entity, i.e. query(SubClass.foo, - SubcClass.bar).join(). In most cases, an error - "Could not find a FROM clause to join from" would be - raised. In a few others, the result would be returned in terms - of the base class rather than the subclass - so applications - which relied on this erroneous result need to be - adjusted. [ticket:1431] - - - Fixed a bug involving contains_eager(), which would apply - itself to a secondary (i.e. lazy) load in a particular rare - case, producing cartesian products. improved the targeting of - query.options() on secondary loads overall [ticket:1461]. - - - Fixed bug introduced in 0.5.4 whereby Composite types fail - when default-holding columns are flushed. - - - Fixed another 0.5.4 bug whereby mutable attributes - (i.e. PickleType) wouldn't be deserialized correctly when the - whole object was serialized. [ticket:1426] - - - Fixed bug whereby session.is_modified() would raise an - exception if any synonyms were in use. - - - Fixed potential memory leak whereby previously pickled objects - placed back in a session would not be fully garbage collected - unless the Session were explicitly closed out. - - - Fixed bug whereby list-based attributes, like pickletype and - PGArray, failed to be merged() properly. - - - Repaired non-working attributes.set_committed_value function. - - - Trimmed the pickle format for InstanceState which should - further reduce the memory footprint of pickled instances. The - format should be backwards compatible with that of 0.5.4 and - previous. - - - sqlalchemy.orm.join and sqlalchemy.orm.outerjoin are now - added to __all__ in sqlalchemy.orm.*. [ticket:1463] - - - Fixed bug where Query exception raise would fail when - a too-short composite primary key value were passed to - get(). [ticket:1458] - -- sql - - Removed an obscure feature of execute() (including connection, - engine, Session) whereby a bindparam() construct can be sent - as a key to the params dictionary. This usage is undocumented - and is at the core of an issue whereby the bindparam() object - created implicitly by a text() construct may have the same - hash value as a string placed in the params dictionary and may - result in an inappropriate match when computing the final bind - parameters. Internal checks for this condition would add - significant latency to the critical task of parameter - rendering, so the behavior is removed. This is a backwards - incompatible change for any application that may have been - using this feature, however the feature has never been - documented. - -- engine/pool - - Implemented recreate() for StaticPool. - - -0.5.4p2 -======= - -- sql - - Repaired the printing of SQL exceptions which are not - based on parameters or are not executemany() style. - -- postgresql - - Deprecated the hardcoded TIMESTAMP function, which when - used as func.TIMESTAMP(value) would render "TIMESTAMP value". - This breaks on some platforms as PostgreSQL doesn't allow - bind parameters to be used in this context. The hard-coded - uppercase is also inappropriate and there's lots of other - PG casts that we'd need to support. So instead, use - text constructs i.e. select(["timestamp '12/05/09'"]). - - -0.5.4p1 -======= - -- orm - - Fixed an attribute error introduced in 0.5.4 which would - occur when merge() was used with an incomplete object. - -0.5.4 -===== - -- orm - - Significant performance enhancements regarding Sessions/flush() - in conjunction with large mapper graphs, large numbers of - objects: - - - Removed all* O(N) scanning behavior from the flush() process, - i.e. operations that were scanning the full session, - including an extremely expensive one that was erroneously - assuming primary key values were changing when this - was not the case. - - * one edge case remains which may invoke a full scan, - if an existing primary key attribute is modified - to a new value. - - - The Session's "weak referencing" behavior is now *full* - - no strong references whatsoever are made to a mapped object - or related items/collections in its __dict__. Backrefs and - other cycles in objects no longer affect the Session's ability - to lose all references to unmodified objects. Objects with - pending changes still are maintained strongly until flush. - [ticket:1398] - - The implementation also improves performance by moving - the "resurrection" process of garbage collected items - to only be relevant for mappings that map "mutable" - attributes (i.e. PickleType, composite attrs). This removes - overhead from the gc process and simplifies internal - behavior. - - If a "mutable" attribute change is the sole change on an object - which is then dereferenced, the mapper will not have access to - other attribute state when the UPDATE is issued. This may present - itself differently to some MapperExtensions. - - The change also affects the internal attribute API, but not - the AttributeExtension interface nor any of the publically - documented attribute functions. - - - The unit of work no longer genererates a graph of "dependency" - processors for the full graph of mappers during flush(), instead - creating such processors only for those mappers which represent - objects with pending changes. This saves a tremendous number - of method calls in the context of a large interconnected - graph of mappers. - - - Cached a wasteful "table sort" operation that previously - occured multiple times per flush, also removing significant - method call count from flush(). - - - Other redundant behaviors have been simplified in - mapper._save_obj(). - - - Modified query_cls on DynamicAttributeImpl to accept a full - mixin version of the AppenderQuery, which allows subclassing - the AppenderMixin. - - - The "polymorphic discriminator" column may be part of a - primary key, and it will be populated with the correct - discriminator value. [ticket:1300] - - - Fixed the evaluator not being able to evaluate IS NULL clauses. - - - Fixed the "set collection" function on "dynamic" relations to - initiate events correctly. Previously a collection could only - be assigned to a pending parent instance, otherwise modified - events would not be fired correctly. Set collection is now - compatible with merge(), fixes [ticket:1352]. - - - Allowed pickling of PropertyOption objects constructed with - instrumented descriptors; previously, pickle errors would occur - when pickling an object which was loaded with a descriptor-based - option, such as query.options(eagerload(MyClass.foo)). - - - Lazy loader will not use get() if the "lazy load" SQL clause - matches the clause used by get(), but contains some parameters - hardcoded. Previously the lazy strategy would fail with the - get(). Ideally get() would be used with the hardcoded - parameters but this would require further development. - [ticket:1357] - - - MapperOptions and other state associated with query.options() - is no longer bundled within callables associated with each - lazy/deferred-loading attribute during a load. - The options are now associated with the instance's - state object just once when it's populated. This removes - the need in most cases for per-instance/attribute loader - objects, improving load speed and memory overhead for - individual instances. [ticket:1391] - - - Fixed another location where autoflush was interfering - with session.merge(). autoflush is disabled completely - for the duration of merge() now. [ticket:1360] - - - Fixed bug which prevented "mutable primary key" dependency - logic from functioning properly on a one-to-one - relation(). [ticket:1406] - - - Fixed bug in relation(), introduced in 0.5.3, - whereby a self referential relation - from a base class to a joined-table subclass would - not configure correctly. - - - Fixed obscure mapper compilation issue when inheriting - mappers are used which would result in un-initialized - attributes. - - - Fixed documentation for session weak_identity_map - - the default value is True, indicating a weak - referencing map in use. - - - Fixed a unit of work issue whereby the foreign - key attribute on an item contained within a collection - owned by an object being deleted would not be set to - None if the relation() was self-referential. [ticket:1376] - - - Fixed Query.update() and Query.delete() failures with eagerloaded - relations. [ticket:1378] - - - It is now an error to specify both columns of a binary primaryjoin - condition in the foreign_keys or remote_side collection. Whereas - previously it was just nonsensical, but would succeed in a - non-deterministic way. - -- schema - - Added a quote_schema() method to the IdentifierPreparer class - so that dialects can override how schemas get handled. This - enables the MSSQL dialect to treat schemas as multipart - identifiers, such as 'database.owner'. [ticket: 594, 1341] - -- sql - - Back-ported the "compiler" extension from SQLA 0.6. This - is a standardized interface which allows the creation of custom - ClauseElement subclasses and compilers. In particular it's - handy as an alternative to text() when you'd like to - build a construct that has database-specific compilations. - See the extension docs for details. - - - Exception messages are truncated when the list of bound - parameters is larger than 10, preventing enormous - multi-page exceptions from filling up screens and logfiles - for large executemany() statements. [ticket:1413] - - - ``sqlalchemy.extract()`` is now dialect sensitive and can - extract components of timestamps idiomatically across the - supported databases, including SQLite. - - - Fixed __repr__() and other _get_colspec() methods on - ForeignKey constructed from __clause_element__() style - construct (i.e. declarative columns). [ticket:1353] - -- mysql - - Reflecting a FOREIGN KEY construct will take into account - a dotted schema.tablename combination, if the foreign key - references a table in a remote schema. [ticket:1405] - -- mssql - - Modified how savepoint logic works to prevent it from - stepping on non-savepoint oriented routines. Savepoint - support is still very experimental. - - - Added in reserved words for MSSQL that covers version 2008 - and all prior versions. [ticket:1310] - - - Corrected problem with information schema not working with a - binary collation based database. Cleaned up information schema - since it is only used by mssql now. [ticket:1343] - -- sqlite - - Corrected the SLBoolean type so that it properly treats only 1 - as True. [ticket:1402] - - - Corrected the float type so that it correctly maps to a - SLFloat type when being reflected. [ticket:1273] - -- extensions - - - Fixed adding of deferred or other column properties to a - declarative class. [ticket:1379] - -0.5.3 -===== -- orm - - The "objects" argument to session.flush() is deprecated. - State which represents the linkage between a parent and - child object does not support "flushed" status on - one side of the link and not the other, so supporting - this operation leads to misleading results. - [ticket:1315] - - - Query now implements __clause_element__() which produces - its selectable, which means a Query instance can be accepted - in many SQL expressions, including col.in_(query), - union(query1, query2), select([foo]).select_from(query), - etc. - - - Query.join() can now construct multiple FROM clauses, if - needed. Such as, query(A, B).join(A.x).join(B.y) - might say SELECT A.*, B.* FROM A JOIN X, B JOIN Y. - Eager loading can also tack its joins onto those - multiple FROM clauses. [ticket:1337] - - - Fixed bug in dynamic_loader() where append/remove events - after construction time were not being propagated to the - UOW to pick up on flush(). [ticket:1347] - - - Fixed bug where column_prefix wasn't being checked before - not mapping an attribute that already had class-level - name present. - - - a session.expire() on a particular collection attribute - will clear any pending backref additions as well, so that - the next access correctly returns only what was present - in the database. Presents some degree of a workaround for - [ticket:1315], although we are considering removing the - flush([objects]) feature altogether. - - - Session.scalar() now converts raw SQL strings to text() - the same way Session.execute() does and accepts same - alternative **kw args. - - - improvements to the "determine direction" logic of - relation() such that the direction of tricky situations - like mapper(A.join(B)) -> relation-> mapper(B) can be - determined. - - - When flushing partial sets of objects using session.flush([somelist]), - pending objects which remain pending after the operation won't - inadvertently be added as persistent. [ticket:1306] - - - Added "post_configure_attribute" method to InstrumentationManager, - so that the "listen_for_events.py" example works again. - [ticket:1314] - - - a forward and complementing backwards reference which are both - of the same direction, i.e. ONETOMANY or MANYTOONE, - is now detected, and an error message is raised. - Saves crazy CircularDependencyErrors later on. - - - Fixed bugs in Query regarding simultaneous selection of - multiple joined-table inheritance entities with common base - classes: - - - previously the adaption applied to "B" on - "A JOIN B" would be erroneously partially applied - to "A". - - - comparisons on relations (i.e. A.related==someb) - were not getting adapted when they should. - - - Other filterings, like - query(A).join(A.bs).filter(B.foo=='bar'), were erroneously - adapting "B.foo" as though it were an "A". - - - Fixed adaptation of EXISTS clauses via any(), has(), etc. - in conjunction with an aliased object on the left and - of_type() on the right. [ticket:1325] - - - Added an attribute helper method ``set_committed_value`` in - sqlalchemy.orm.attributes. Given an object, attribute name, - and value, will set the value on the object as part of its - "committed" state, i.e. state that is understood to have - been loaded from the database. Helps with the creation of - homegrown collection loaders and such. - - - Query won't fail with weakref error when a non-mapper/class - instrumented descriptor is passed, raises - "Invalid column expession". - - - Query.group_by() properly takes into account aliasing applied - to the FROM clause, such as with select_from(), using - with_polymorphic(), or using from_self(). - -- sql - - An alias() of a select() will convert to a "scalar subquery" - when used in an unambiguously scalar context, i.e. it's used - in a comparison operation. This applies to - the ORM when using query.subquery() as well. - - - Fixed missing _label attribute on Function object, others - when used in a select() with use_labels (such as when used - in an ORM column_property()). [ticket:1302] - - - anonymous alias names now truncate down to the max length - allowed by the dialect. More significant on DBs like - Oracle with very small character limits. [ticket:1309] - - - the __selectable__() interface has been replaced entirely - by __clause_element__(). - - - The per-dialect cache used by TypeEngine to cache - dialect-specific types is now a WeakKeyDictionary. - This to prevent dialect objects from - being referenced forever for an application that - creates an arbitrarily large number of engines - or dialects. There is a small performance penalty - which will be resolved in 0.6. [ticket:1299] - -- sqlite - - Fixed SQLite reflection methods so that non-present - cursor.description, which triggers an auto-cursor - close, will be detected so that no results doesn't - fail on recent versions of pysqlite which raise - an error when fetchone() called with no rows present. - -- postgresql - - Index reflection won't fail when an index with - multiple expressions is encountered. - - - Added PGUuid and PGBit types to - sqlalchemy.databases.postgres. [ticket:1327] - - - Refection of unknown PG types won't crash when those - types are specified within a domain. [ticket:1327] - -- mssql - - Preliminary support for pymssql 1.0.1 - - - Corrected issue on mssql where max_identifier_length was - not being respected. - -- extensions - - - Fixed a recursive pickling issue in serializer, triggered - by an EXISTS or other embedded FROM construct. - - - Declarative locates the "inherits" class using a search - through __bases__, to skip over mixins that are local - to subclasses. - - - Declarative figures out joined-table inheritance primary join - condition even if "inherits" mapper argument is given - explicitly. - - - Declarative will properly interpret the "foreign_keys" argument - on a backref() if it's a string. - - - Declarative will accept a table-bound column as a property - when used in conjunction with __table__, if the column is already - present in __table__. The column will be remapped to the given - key the same way as when added to the mapper() properties dict. - -0.5.2 -====== - -- orm - - Further refined 0.5.1's warning about delete-orphan cascade - placed on a many-to-many relation. First, the bad news: - the warning will apply to both many-to-many as well as - many-to-one relations. This is necessary since in both - cases, SQLA does not scan the full set of potential parents - when determining "orphan" status - for a persistent object - it only detects an in-python de-association event to establish - the object as an "orphan". Next, the good news: to support - one-to-one via a foreign key or assocation table, or to - support one-to-many via an association table, a new flag - single_parent=True may be set which indicates objects - linked to the relation are only meant to have a single parent. - The relation will raise an error if multiple parent-association - events occur within Python. - - - Adjusted the attribute instrumentation change from 0.5.1 to - fully establish instrumentation for subclasses where the mapper - was created after the superclass had already been fully - instrumented. [ticket:1292] - - - Fixed bug in delete-orphan cascade whereby two one-to-one - relations from two different parent classes to the same target - class would prematurely expunge the instance. - - - Fixed an eager loading bug whereby self-referential eager - loading would prevent other eager loads, self referential or not, - from joining to the parent JOIN properly. Thanks to Alex K - for creating a great test case. - - - session.expire() and related methods will not expire() unloaded - deferred attributes. This prevents them from being needlessly - loaded when the instance is refreshed. - - - query.join()/outerjoin() will now properly join an aliased() - construct to the existing left side, even if query.from_self() - or query.select_from(someselectable) has been called. - [ticket:1293] - -- sql - - Further fixes to the "percent signs and spaces in column/table - names" functionality. [ticket:1284] - -- mssql - - Restored convert_unicode handling. Results were being passed - on through without conversion. [ticket:1291] - - - Really fixing the decimal handling this time. [ticket:1282]. - - - Modified table reflection code to use only kwargs when - constructing tables. [Ticket:1289] - -0.5.1 -======== - -- orm - - Removed an internal join cache which could potentially leak - memory when issuing query.join() repeatedly to ad-hoc - selectables. - - - The "clear()", "save()", "update()", "save_or_update()" - Session methods have been deprecated, replaced by - "expunge_all()" and "add()". "expunge_all()" has also - been added to ScopedSession. - - - Modernized the "no mapped table" exception and added a more - explicit __table__/__tablename__ exception to declarative. - - - Concrete inheriting mappers now instrument attributes which - are inherited from the superclass, but are not defined for - the concrete mapper itself, with an InstrumentedAttribute that - issues a descriptive error when accessed. [ticket:1237] - - - Added a new `relation()` keyword `back_populates`. This - allows configuation of backreferences using explicit - relations. [ticket:781] This is required when creating - bidirectional relations between a hierarchy of concrete - mappers and another class. [ticket:1237] - - - Test coverage added for `relation()` objects specified on - concrete mappers. [ticket:1237] - - - Query.from_self() as well as query.subquery() both disable - the rendering of eager joins inside the subquery produced. - The "disable all eager joins" feature is available publically - via a new query.enable_eagerloads() generative. [ticket:1276] - - - Added a rudimental series of set operations to Query that - receive Query objects as arguments, including union(), - union_all(), intersect(), except_(), insertsect_all(), - except_all(). See the API documentation for - Query.union() for examples. - - - Fixed bug that prevented Query.join() and eagerloads from - attaching to a query that selected from a union or aliased union. - - - A short documentation example added for bidirectional - relations specified on concrete mappers. [ticket:1237] - - - Mappers now instrument class attributes upon construction - with the final InstrumentedAttribute object which remains - persistent. The `_CompileOnAttr`/`__getattribute__()` - methodology has been removed. The net effect is that - Column-based mapped class attributes can now be used fully - at the class level without invoking a mapper compilation - operation, greatly simplifying typical usage patterns - within declarative. [ticket:1269] - - - ColumnProperty (and front-end helpers such as ``deferred``) no - longer ignores unknown **keyword arguments. - - - Fixed a bug with the unitofwork's "row switch" mechanism, - i.e. the conversion of INSERT/DELETE into an UPDATE, when - combined with joined-table inheritance and an object - which contained no defined values for the child table where - an UPDATE with no SET clause would be rendered. - - - Using delete-orphan on a many-to-many relation is deprecated. - This produces misleading or erroneous results since SQLA does - not retrieve the full list of "parents" for m2m. To get delete-orphan - behavior with an m2m table, use an explcit association class - so that the individual association row is treated as a parent. - [ticket:1281] - - - delete-orphan cascade always requires delete cascade. Specifying - delete-orphan without delete now raises a deprecation warning. - [ticket:1281] - -- sql - - Improved the methodology to handling percent signs in column - names from [ticket:1256]. Added more tests. MySQL and - PostgreSQL dialects still do not issue correct CREATE TABLE - statements for identifiers with percent signs in them. - -- schema - - Index now accepts column-oriented InstrumentedAttributes - (i.e. column-based mapped class attributes) as column - arguments. [ticket:1214] - - - Column with no name (as in declarative) won't raise a - NoneType error when it's string output is requsted - (such as in a stack trace). - - - Fixed bug when overriding a Column with a ForeignKey - on a reflected table, where derived columns (i.e. the - "virtual" columns of a select, etc.) would inadvertently - call upon schema-level cleanup logic intended only - for the original column. [ticket:1278] - -- declarative - - Can now specify Column objects on subclasses which have no - table of their own (i.e. use single table inheritance). - The columns will be appended to the base table, but only - mapped by the subclass. - - - For both joined and single inheriting subclasses, the subclass - will only map those columns which are already mapped on the - superclass and those explicit on the subclass. Other - columns that are present on the `Table` will be excluded - from the mapping by default, which can be disabled - by passing a blank `exclude_properties` collection to the - `__mapper_args__`. This is so that single-inheriting - classes which define their own columns are the only classes - to map those columns. The effect is actually a more organized - mapping than you'd normally get with explicit `mapper()` - calls unless you set up the `exclude_properties` arguments - explicitly. - - - It's an error to add new Column objects to a declarative class - that specified an existing table using __table__. - -- mysql - - Added the missing keywords from MySQL 4.1 so they get escaped - properly. - -- mssql - - Corrected handling of large decimal values with more robust - tests. Removed string manipulation on floats. [ticket:1280] - - - Modified the do_begin handling in mssql to use the Cursor not - the Connection so it is DBAPI compatible. - - - Corrected SAVEPOINT support on adodbapi by changing the - handling of savepoint_release, which is unsupported on mssql. - -0.5.0 -======== - -- new features -- general - - Documentation has been converted to Sphinx. In particular, - the generated API documentation has been constructed into a - full blown "API Reference" section which organizes editorial - documentation combined with generated docstrings. Cross - linking between sections and API docs are vastly improved, a - javascript-powered search feature is provided, and a full - index of all classes, functions and members is provided. - - - setup.py now imports setuptools only optionally. If not - present, distutils is used. The new "pip" installer is - recommended over easy_install as it installs in a more - simplified way. - - - added an extremely basic illustration of a PostGIS integration - to the examples folder. - -- orm - - Query.with_polymorphic() now accepts a third argument - "discriminator" which will replace the value of - mapper.polymorphic_on for that query. Mappers themselves no - longer require polymorphic_on to be set, even if the mapper - has a polymorphic_identity. When not set, the mapper will - load non-polymorphically by default. Together, these two - features allow a non-polymorphic concrete inheritance setup to - use polymorphic loading on a per-query basis, since concrete - setups are prone to many issues when used polymorphically in - all cases. - - - dynamic_loader accepts a query_class= to customize the Query - classes used for both the dynamic collection and the queries - built from it. - - - query.order_by() accepts None which will remove any pending - order_by state from the query, as well as cancel out any - mapper/relation configured ordering. This is primarily useful - for overriding the ordering specified on a dynamic_loader(). - [ticket:1079] - -- sql - - RowProxy objects can be used in place of dictionary arguments - sent to connection.execute() and friends. [ticket:935] - -- dialect - - Added a new description_encoding attribute on the dialect that - is used for encoding the column name when processing the - metadata. This usually defaults to utf-8. - -- mssql - - Added in a new MSGenericBinary type. This maps to the Binary - type so it can implement the specialized behavior of treating - length specified types as fixed-width Binary types and - non-length types as an unbound variable length Binary type. - - - Added in new types: MSVarBinary and MSImage. [ticket:1249] - - - Added in the MSReal, MSNText, MSSmallDateTime, MSTime, - MSDateTimeOffset, and MSDateTime2 types - -- sqlite - - Table reflection now stores the actual DefaultClause value for - the column. [ticket:1266] - -- bugfixes, behavioral changes -- general -- orm - - Exceptions raised during compile_mappers() are now preserved - to provide "sticky behavior" - if a hasattr() call on a - pre-compiled mapped attribute triggers a failing compile and - suppresses the exception, subsequent compilation is blocked - and the exception will be reiterated on the next compile() - call. This issue occurs frequently when using declarative. - - - property.of_type() is now recognized on a single-table - inheriting target, when used in the context of - prop.of_type(..).any()/has(), as well as - query.join(prop.of_type(...)). - - - query.join() raises an error when the target of the join - doesn't match the property-based attribute - while it's - unlikely anyone is doing this, the SQLAlchemy author was - guilty of this particular loosey-goosey behavior. - - - Fixed bug when using weak_instance_map=False where modified - events would not be intercepted for a flush(). [ticket:1272] - - - Fixed some deep "column correspondence" issues which could - impact a Query made against a selectable containing multiple - versions of the same table, as well as unions and similar - which contained the same table columns in different column - positions at different levels. [ticket:1268] - - - Custom comparator classes used in conjunction with - column_property(), relation() etc. can define new comparison - methods on the Comparator, which will become available via - __getattr__() on the InstrumentedAttribute. In the case of - synonym() or comparable_property(), attributes are resolved - first on the user-defined descriptor, then on the user-defined - comparator. - - - Added ScopedSession.is_active accessor. [ticket:976] - - - Can pass mapped attributes and column objects as keys to - query.update({}). [ticket:1262] - - - Mapped attributes passed to the values() of an expression - level insert() or update() will use the keys of the mapped - columns, not that of the mapped attribute. - - - Corrected problem with Query.delete() and Query.update() not - working properly with bind parameters. [ticket:1242] - - - Query.select_from(), from_statement() ensure that the given - argument is a FromClause, or Text/Select/Union, respectively. - - - Query() can be passed a "composite" attribute as a column - expression and it will be expanded. Somewhat related to - [ticket:1253]. - - - Query() is a little more robust when passed various column - expressions such as strings, clauselists, text() constructs - (which may mean it just raises an error more nicely). - - - first() works as expected with Query.from_statement(). - - - Fixed bug introduced in 0.5rc4 involving eager loading not - functioning for properties which were added to a mapper - post-compile using add_property() or equivalent. - - - Fixed bug where many-to-many relation() with viewonly=True - would not correctly reference the link between - secondary->remote. - - - Duplicate items in a list-based collection will be maintained - when issuing INSERTs to a "secondary" table in a many-to-many - relation. Assuming the m2m table has a unique or primary key - constraint on it, this will raise the expected constraint - violation instead of silently dropping the duplicate - entries. Note that the old behavior remains for a one-to-many - relation since collection entries in that case don't result in - INSERT statements and SQLA doesn't manually police - collections. [ticket:1232] - - - Query.add_column() can accept FromClause objects in the same - manner as session.query() can. - - - Comparison of many-to-one relation to NULL is properly - converted to IS NOT NULL based on not_(). - - - Extra checks added to ensure explicit - primaryjoin/secondaryjoin are ClauseElement instances, to - prevent more confusing errors later on. [ticket:1087] - - - Improved mapper() check for non-class classes. [ticket:1236] - - - comparator_factory argument is now documented and supported by - all MapperProperty types, including column_property(), - relation(), backref(), and synonym() [ticket:5051]. - - - Changed the name of PropertyLoader to RelationProperty, to be - consistent with all the other names. PropertyLoader is still - present as a synonym. - - - fixed "double iter()" call causing bus errors in shard API, - removed errant result.close() left over from the 0.4 - version. [ticket:1099] [ticket:1228] - - - made Session.merge cascades not trigger autoflush. Fixes - merged instances getting prematurely inserted with missing - values. - - - Two fixes to help prevent out-of-band columns from being - rendered in polymorphic_union inheritance scenarios (which - then causes extra tables to be rendered in the FROM clause - causing cartesian products): - - - improvements to "column adaption" for a->b->c inheritance - situations to better locate columns that are related to - one another via multiple levels of indirection, rather - than rendering the non-adapted column. - - - the "polymorphic discriminator" column is only rendered - for the actual mapper being queried against. The column - won't be "pulled in" from a subclass or superclass mapper - since it's not needed. - - - Fixed shard_id argument on ShardedSession.execute(). - [ticket:1072] - -- sql - - Columns can again contain percent signs within their - names. [ticket:1256] - - - sqlalchemy.sql.expression.Function is now a public class. It - can be subclassed to provide user-defined SQL functions in an - imperative style, including with pre-established behaviors. - The postgis.py example illustrates one usage of this. - - - PickleType now favors == comparison by default, if the - incoming object (such as a dict) implements __eq__(). If the - object does not implement __eq__() and mutable=True, a - deprecation warning is raised. - - - Fixed the import weirdness in sqlalchemy.sql to not export - __names__ [ticket:1215]. - - - Using the same ForeignKey object repeatedly raises an error - instead of silently failing later. [ticket:1238] - - - Added NotImplementedError for params() method on - Insert/Update/Delete constructs. These items currently don't - support this functionality, which also would be a little - misleading compared to values(). - - - Reflected foreign keys will properly locate their referenced - column, even if the column was given a "key" attribute - different from the reflected name. This is achieved via a new - flag on ForeignKey/ForeignKeyConstraint called "link_to_name", - if True means the given name is the referred-to column's name, - not its assigned key. [ticket:650] - - - select() can accept a ClauseList as a column in the same way - as a Table or other selectable and the interior expressions - will be used as column elements. [ticket:1253] - - - the "passive" flag on session.is_modified() is correctly - propagated to the attribute manager. - - - union() and union_all() will not whack any order_by() that has - been applied to the select()s inside. If you union() a - select() with order_by() (presumably to support LIMIT/OFFSET), - you should also call self_group() on it to apply parenthesis. - -- engine/pool - - - Connection.invalidate() checks for closed status to avoid - attribute errors. [ticket:1246] - - - NullPool supports reconnect on failure behavior. - [ticket:1094] - - - Added a mutex for the initial pool creation when using - pool.manage(dbapi). This prevents a minor case of "dogpile" - behavior which would otherwise occur upon a heavy load - startup. [ticket:799] - - - _execute_clauseelement() goes back to being a private method. - Subclassing Connection is not needed now that ConnectionProxy - is available. - -- documentation - - Tickets [ticket:1200] [ticket:1149]. - - - Added note about create_session() defaults. - - - Added section about metadata.reflect(). - - - Updated `TypeDecorator` section. - - - Rewrote the "threadlocal" strategy section of the docs due to - recent confusion over this feature. - - - Removed badly out of date 'polymorphic_fetch' and - 'select_table' docs from inheritance, reworked the second half - of "joined table inheritance". - - - Documented `comparator_factory` kwarg, added new doc section - "Custom Comparators". - -- mssql - - Refactored the Date/Time types. The ``smalldatetime`` data - type no longer truncates to a date only, and will now be - mapped to the MSSmallDateTime type. [ticket:1254] - - - Corrected an issue with Numerics to accept an int. - - - Mapped ``char_length`` to the ``LEN()`` function. - - - If an ``INSERT`` includes a subselect the ``INSERT`` is - converted from an ``INSERT INTO VALUES`` construct to a - ``INSERT INTO SELECT`` construct. - - - If the column is part of a ``primary_key`` it will be ``NOT - NULL`` since MSSQL doesn't allow ``NULL`` in primary_key - columns. - - - ``MSBinary`` now returns a ``BINARY`` instead of an - ``IMAGE``. This is a backwards incompatible change in that - ``BINARY`` is a fixed length data type whereas ``IMAGE`` is a - variable length data type. [ticket:1249] - - - ``get_default_schema_name`` is now reflected from the database - based on the user's default schema. This only works with MSSQL - 2005 and later. [ticket:1258] - - - Added collation support through the use of a new collation - argument. This is supported on the following types: char, - nchar, varchar, nvarchar, text, ntext. [ticket:1248] - - - Changes to the connection string parameters favor DSN as the - default specification for pyodbc. See the mssql.py docstring - for detailed usage instructions. - - - Added experimental support of savepoints. It currently does - not work fully with sessions. - - - Support for three levels of column nullability: NULL, NOT - NULL, and the database's configured default. The default - Column configuration (nullable=True) will now generate NULL in - the DDL. Previously no specification was emitted and the - database default would take effect (usually NULL, but not - always). To explicitly request the database default, - configure columns with nullable=None and no specification will - be emitted in DDL. This is backwards incompatible - behavior. [ticket:1243] - -- postgres - - "%" signs in text() constructs are automatically escaped to - "%%". Because of the backwards incompatible nature of this - change, a warning is emitted if '%%' is detected in the - string. [ticket:1267] - - - Calling alias.execute() in conjunction with - server_side_cursors won't raise AttributeError. - - - Added Index reflection support to PostgreSQL, using a great - patch we long neglected, submitted by Ken - Kuhlman. [ticket:714] - -- oracle - - Adjusted the format of create_xid() to repair two-phase - commit. We now have field reports of Oracle two-phase commit - working properly with this change. - - - Added OracleNVarchar type, produces NVARCHAR2, and also - subclasses Unicode so that convert_unicode=True by default. - NVARCHAR2 reflects into this type automatically so these - columns pass unicode on a reflected table with no explicit - convert_unicode=True flags. [ticket:1233] - - - Fixed bug which was preventing out params of certain types - from being received; thanks a ton to huddlej at wwu.edu ! - [ticket:1265] - -- mysql - - "%" signs in text() constructs are automatically escaped to - "%%". Because of the backwards incompatible nature of this - change, a warning is emitted if '%%' is detected in the - string. - - - Fixed bug in exception raise when FK columns not present - during reflection. [ticket:1241] - - - Fixed bug involving reflection of a remote-schema table with a - foreign key ref to another table in that schema. - -- associationproxy - - The association proxy properties are make themselves available - at the class level, e.g. MyClass.aproxy. Previously this - evaluated to None. - -- declarative - - The full list of arguments accepted as string by backref() - includes 'primaryjoin', 'secondaryjoin', 'secondary', - 'foreign_keys', 'remote_side', 'order_by'. - -0.5.0rc4 -======== -- features -- orm - - Query.count() has been enhanced to do the "right thing" in a - wider variety of cases. It can now count multiple-entity - queries, as well as column-based queries. Note that this means - if you say query(A, B).count() without any joining criterion, - it's going to count the cartesian product of A*B. Any query - which is against column-based entities will automatically - issue "SELECT count(1) FROM (SELECT...)" so that the real - rowcount is returned, meaning a query such as - query(func.count(A.name)).count() will return a value of one, - since that query would return one row. - - - Lots of performance tuning. A rough guesstimate over various - ORM operations places it 10% faster over 0.5.0rc3, 25-30% over - 0.4.8. - -- bugfixes and behavioral changes -- general: - - global "propigate"->"propagate" change. - -- orm - - Adjustments to the enhanced garbage collection on - InstanceState to better guard against errors due to lost - state. - - - Query.get() returns a more informative error message when - executed against multiple entities. [ticket:1220] - - - Restored NotImplementedError on Cls.relation.in_() - [ticket:1140] [ticket:1221] - - - Fixed PendingDeprecationWarning involving order_by parameter - on relation(). [ticket:1226] - -- sql - - Removed the 'properties' attribute of the Connection object, - Connection.info should be used. - - - Restored "active rowcount" fetch before ResultProxy autocloses - the cursor. This was removed in 0.5rc3. - - - Rearranged the `load_dialect_impl()` method in `TypeDecorator` - such that it will take effect even if the user-defined - `TypeDecorator` uses another `TypeDecorator` as its impl. - -- access - - Added support for Currency type. - - - Functions were not return their result. [ticket:1017] - - - Corrected problem with joins. Access only support LEFT OUTER - or INNER not just JOIN by itself. [ticket:1017] - -- mssql - - Lots of cleanup and fixes to correct problems with limit and - offset. - - - Correct situation where subqueries as part of a binary - expression need to be translated to use the IN and NOT IN - syntax. - - - Fixed E Notation issue that prevented the ability to insert - decimal values less than 1E-6. [ticket:1216] - - - Corrected problems with reflection when dealing with schemas, - particularly when those schemas are the default - schema. [ticket:1217] - - - Corrected problem with casting a zero length item to a - varchar. It now correctly adjusts the CAST. - -- ext - - Can now use a custom "inherit_condition" in __mapper_args__ - when using declarative. - - - fixed string-based "remote_side", "order_by" and others not - propagating correctly when used in backref(). - -0.5.0rc3 -======== -- features -- orm - - Added two new hooks to SessionExtension: after_bulk_delete() - and after_bulk_update(). after_bulk_delete() is called after - a bulk delete() operation on a query. after_bulk_update() is - called after a bulk update() operation on a query. - -- sql - - SQL compiler optimizations and complexity reduction. The call - count for compiling a typical select() construct is 20% less - versus 0.5.0rc2. - - - Dialects can now generate label names of adjustable - length. Pass in the argument "label_length=" to - create_engine() to adjust how many characters max will be - present in dynamically generated column labels, i.e. - "somecolumn AS somelabel". Any value less than 6 will result - in a label of minimal size, consisting of an underscore and a - numeric counter. The compiler uses the value of - dialect.max_identifier_length as a default. [ticket:1211] - -- ext - - Added a new extension sqlalchemy.ext.serializer. Provides - Serializer/Deserializer "classes" which mirror - Pickle/Unpickle, as well as dumps() and loads(). This - serializer implements an "external object" pickler which keeps - key context-sensitive objects, including engines, sessions, - metadata, Tables/Columns, and mappers, outside of the pickle - stream, and can later restore the pickle using any - engine/metadata/session provider. This is used not for - pickling regular object instances, which are pickleable - without any special logic, but for pickling expression objects - and full Query objects, such that all mapper/engine/session - dependencies can be restored at unpickle time. - -- oracle - - Wrote a docstring for Oracle dialect. Apparently that Ohloh - "few source code comments" label is starting to sting :). - - - Removed FIRST_ROWS() optimize flag when using LIMIT/OFFSET, - can be reenabled with optimize_limits=True create_engine() - flag. [ticket:536] - -- bugfixes and behavioral changes -- orm - - "not equals" comparisons of simple many-to-one relation to an - instance will not drop into an EXISTS clause and will compare - foreign key columns instead. - - - Removed not-really-working use cases of comparing a collection - to an iterable. Use contains() to test for collection - membership. - - - Improved the behavior of aliased() objects such that they more - accurately adapt the expressions generated, which helps - particularly with self-referential comparisons. [ticket:1171] - - - Fixed bug involving primaryjoin/secondaryjoin conditions - constructed from class-bound attributes (as often occurs when - using declarative), which later would be inappropriately - aliased by Query, particularly with the various EXISTS based - comparators. - - - Fixed bug when using multiple query.join() with an - aliased-bound descriptor which would lose the left alias. - - - Improved weakref identity map memory management to no longer - require mutexing, resurrects garbage collected instance on a - lazy basis for an InstanceState with pending changes. - - - InstanceState object now removes circular references to itself - upon disposal to keep it outside of cyclic garbage collection. - - - relation() won't hide unrelated ForeignKey errors inside of - the "please specify primaryjoin" message when determining join - condition. - - - Fixed bug in Query involving order_by() in conjunction with - multiple aliases of the same class (will add tests in - [ticket:1218]) - - - When using Query.join() with an explicit clause for the ON - clause, the clause will be aliased in terms of the left side - of the join, allowing scenarios like query(Source). - from_self().join((Dest, Source.id==Dest.source_id)) to work - properly. - - - polymorphic_union() function respects the "key" of each Column - if they differ from the column's name. - - - Repaired support for "passive-deletes" on a many-to-one - relation() with "delete" cascade. [ticket:1183] - - - Fixed bug in composite types which prevented a primary-key - composite type from being mutated [ticket:1213]. - - - Added more granularity to internal attribute access, such that - cascade and flush operations will not initialize unloaded - attributes and collections, leaving them intact for a - lazy-load later on. Backref events still initialize attrbutes - and collections for pending instances. [ticket:1202] - -- sql - - Simplified the check for ResultProxy "autoclose without - results" to be based solely on presence of - cursor.description. All the regexp-based guessing about - statements returning rows has been removed [ticket:1212]. - - - Direct execution of a union() construct will properly set up - result-row processing. [ticket:1194] - - - The internal notion of an "OID" or "ROWID" column has been - removed. It's basically not used by any dialect, and the - possibility of its usage with psycopg2's cursor.lastrowid is - basically gone now that INSERT..RETURNING is available. - - - Removed "default_order_by()" method on all FromClause objects. - - - Repaired the table.tometadata() method so that a passed-in - schema argument is propagated to ForeignKey constructs. - - - Slightly changed behavior of IN operator for comparing to - empty collections. Now results in inequality comparison - against self. More portable, but breaks with stored procedures - that aren't pure functions. - -- oracle - - Setting the auto_convert_lobs to False on create_engine() will - also instruct the OracleBinary type to return the cx_oracle - LOB object unchanged. - -- mysql - - Fixed foreign key reflection in the edge case where a Table's - explicit schema= is the same as the schema (database) the - connection is attached to. - - - No longer expects include_columns in table reflection to be - lower case. - -- ext - - Fixed bug preventing declarative-bound "column" objects from - being used in column_mapped_collection(). [ticket:1174] - -- misc - - util.flatten_iterator() func doesn't interpret strings with - __iter__() methods as iterators, such as in pypy - [ticket:1077]. - -0.5.0rc2 -======== -- orm - - Fixed bug involving read/write relation()s that contain - literal or other non-column expressions within their - primaryjoin condition equated to a foreign key column. - - - "non-batch" mode in mapper(), a feature which allows mapper - extension methods to be called as each instance is - updated/inserted, now honors the insert order of the objects - given. - - - Fixed RLock-related bug in mapper which could deadlock upon - reentrant mapper compile() calls, something that occurs when - using declarative constructs inside of ForeignKey objects. - - - ScopedSession.query_property now accepts a query_cls factory, - overriding the session's configured query_cls. - - - Fixed shared state bug interfering with ScopedSession.mapper's - ability to apply default __init__ implementations on object - subclasses. - - - Fixed up slices on Query (i.e. query[x:y]) to work properly - for zero length slices, slices with None on either end. - [ticket:1177] - - - Added an example illustrating Celko's "nested sets" as a - SQLA mapping. - - - contains_eager() with an alias argument works even when - the alias is embedded in a SELECT, as when sent to the - Query via query.select_from(). - - - contains_eager() usage is now compatible with a Query that - also contains a regular eager load and limit/offset, in that - the columns are added to the Query-generated subquery. - [ticket:1180] - - - session.execute() will execute a Sequence object passed to - it (regression from 0.4). - - - Removed the "raiseerror" keyword argument from object_mapper() - and class_mapper(). These functions raise in all cases - if the given class/instance is not mapped. - - - Fixed session.transaction.commit() on a autocommit=False - session not starting a new transaction. - - - Some adjustments to Session.identity_map's weak referencing - behavior to reduce asynchronous GC side effects. - - - Adjustment to Session's post-flush accounting of newly - "clean" objects to better protect against operating on - objects as they're asynchronously gc'ed. [ticket:1182] - -- sql - - column.in_(someselect) can now be used as a columns-clause - expression without the subquery bleeding into the FROM clause - [ticket:1074] - -- sqlite - - Overhauled SQLite date/time bind/result processing to use - regular expressions and format strings, rather than - strptime/strftime, to generically support pre-1900 dates, - dates with microseconds. [ticket:968] - - - String's (and Unicode's, UnicodeText's, etc.) convert_unicode - logic disabled in the sqlite dialect, to adjust for pysqlite - 2.5.0's new requirement that only Python unicode objects are - accepted; - http://itsystementwicklung.de/pipermail/list-pysqlite/2008-March/000018.html - -- mysql - - Temporary tables are now reflectable. - -- oracle - - Oracle will detect string-based statements which contain - comments at the front before a SELECT as SELECT statements. - [ticket:1187] - -0.5.0rc1 -======== - -- orm - - Query now has delete() and update(values) methods. This allows - to perform bulk deletes/updates with the Query object. - - - The RowTuple object returned by Query(*cols) now features - keynames which prefer mapped attribute names over column keys, - column keys over column names, i.e. Query(Class.foo, - Class.bar) will have names "foo" and "bar" even if those are - not the names of the underlying Column objects. Direct Column - objects such as Query(table.c.col) will return the "key" - attribute of the Column. - - - Added scalar() and value() methods to Query, each return a - single scalar value. scalar() takes no arguments and is - roughly equivalent to first()[0], value() - takes a single column expression and is roughly equivalent to - values(expr).next()[0]. - - - Improved the determination of the FROM clause when placing SQL - expressions in the query() list of entities. In particular - scalar subqueries should not "leak" their inner FROM objects - out into the enclosing query. - - - Joins along a relation() from a mapped class to a mapped - subclass, where the mapped subclass is configured with single - table inheritance, will include an IN clause which limits the - subtypes of the joined class to those requested, within the ON - clause of the join. This takes effect for eager load joins as - well as query.join(). Note that in some scenarios the IN - clause will appear in the WHERE clause of the query as well - since this discrimination has multiple trigger points. - - - AttributeExtension has been refined such that the event - is fired before the mutation actually occurs. Additionally, - the append() and set() methods must now return the given value, - which is used as the value to be used in the mutation operation. - This allows creation of validating AttributeListeners which - raise before the action actually occurs, and which can change - the given value into something else before its used. - - - column_property(), composite_property(), and relation() now - accept a single or list of AttributeExtensions using the - "extension" keyword argument. - - - query.order_by().get() silently drops the "ORDER BY" from - the query issued by GET but does not raise an exception. - - - Added a Validator AttributeExtension, as well as a - @validates decorator which is used in a similar fashion - as @reconstructor, and marks a method as validating - one or more mapped attributes. - - - class.someprop.in_() raises NotImplementedError pending the - implementation of "in_" for relation [ticket:1140] - - - Fixed primary key update for many-to-many collections where - the collection had not been loaded yet [ticket:1127] - - - Fixed bug whereby deferred() columns with a group in conjunction - with an otherwise unrelated synonym() would produce - an AttributeError during deferred load. - - - The before_flush() hook on SessionExtension takes place before - the list of new/dirty/deleted is calculated for the final - time, allowing routines within before_flush() to further - change the state of the Session before the flush proceeds. - [ticket:1128] - - - The "extension" argument to Session and others can now - optionally be a list, supporting events sent to multiple - SessionExtension instances. Session places SessionExtensions - in Session.extensions. - - - Reentrant calls to flush() raise an error. This also serves - as a rudimentary, but not foolproof, check against concurrent - calls to Session.flush(). - - - Improved the behavior of query.join() when joining to - joined-table inheritance subclasses, using explicit join - criteria (i.e. not on a relation). - - - @orm.attributes.reconstitute and - MapperExtension.reconstitute have been renamed to - @orm.reconstructor and MapperExtension.reconstruct_instance - - - Fixed @reconstructor hook for subclasses which inherit from a - base class. [ticket:1129] - - - The composite() property type now supports a - __set_composite_values__() method on the composite class which - is required if the class represents state using attribute - names other than the column's keynames; default-generated - values now get populated properly upon flush. Also, - composites with attributes set to None compare correctly. - [ticket:1132] - - - The 3-tuple of iterables returned by attributes.get_history() - may now be a mix of lists and tuples. (Previously members - were always lists.) - - - Fixed bug whereby changing a primary key attribute on an - entity where the attribute's previous value had been expired - would produce an error upon flush(). [ticket:1151] - - - Fixed custom instrumentation bug whereby get_instance_dict() - was not called for newly constructed instances not loaded - by the ORM. - - - Session.delete() adds the given object to the session if - not already present. This was a regression bug from 0.4. - [ticket:1150] - - - The `echo_uow` flag on `Session` is deprecated, and unit-of-work - logging is now application-level only, not per-session level. - - - Removed conflicting `contains()` operator from - `InstrumentedAttribute` which didn't accept `escape` kwaarg - [ticket:1153]. - -- declarative - - Fixed bug whereby mapper couldn't initialize if a composite - primary key referenced another table that was not defined - yet. [ticket:1161] - - - Fixed exception throw which would occur when string-based - primaryjoin condition was used in conjunction with backref. - -- schema - - Added "sorted_tables" accessor to MetaData, which returns - Table objects sorted in order of dependency as a list. - This deprecates the MetaData.table_iterator() method. - The "reverse=False" keyword argument has also been - removed from util.sort_tables(); use the Python - 'reversed' function to reverse the results. - [ticket:1033] - - - The 'length' argument to all Numeric types has been renamed - to 'scale'. 'length' is deprecated and is still accepted - with a warning. - - - Dropped 0.3-compatibility for user defined types - (convert_result_value, convert_bind_param). - -- sql - - Temporarily rolled back the "ORDER BY" enhancement from - [ticket:1068]. This feature is on hold pending further - development. - - - The exists() construct won't "export" its contained list - of elements as FROM clauses, allowing them to be used more - effectively in the columns clause of a SELECT. - - - and_() and or_() now generate a ColumnElement, allowing - boolean expressions as result columns, i.e. - select([and_(1, 0)]). [ticket:798] - - - Bind params now subclass ColumnElement which allows them to be - selectable by orm.query (they already had most ColumnElement - semantics). - - - Added select_from() method to exists() construct, which becomes - more and more compatible with a regular select(). - - - Added func.min(), func.max(), func.sum() as "generic functions", - which basically allows for their return type to be determined - automatically. Helps with dates on SQLite, decimal types, - others. [ticket:1160] - - - added decimal.Decimal as an "auto-detect" type; bind parameters - and generic functions will set their type to Numeric when a - Decimal is used. - -- mysql - - The 'length' argument to MSInteger, MSBigInteger, MSTinyInteger, - MSSmallInteger and MSYear has been renamed to 'display_width'. - - - Added MSMediumInteger type [ticket:1146]. - - - the function func.utc_timestamp() compiles to UTC_TIMESTAMP, without - the parenthesis, which seem to get in the way when using in - conjunction with executemany(). - -- oracle - - limit/offset no longer uses ROW NUMBER OVER to limit rows, - and instead uses subqueries in conjunction with a special - Oracle optimization comment. Allows LIMIT/OFFSET to work - in conjunction with DISTINCT. [ticket:536] - - has_sequence() now takes the current "schema" argument into - account [ticket:1155] - - added BFILE to reflected type names [ticket:1121] - -0.5beta3 -======== - -0.5beta3 includes all bugfixes listed under release "0.4.7". - -- orm - - The "entity_name" feature of SQLAlchemy mappers has been - removed. For rationale, see http://tinyurl.com/6nm2ne - - - the "autoexpire" flag on Session, sessionmaker(), and - scoped_session() has been renamed to "expire_on_commit". It - does not affect the expiration behavior of rollback(). - - - fixed endless loop bug which could occur within a mapper's - deferred load of inherited attributes. - - - a legacy-support flag "_enable_transaction_accounting" flag - added to Session which when False, disables all - transaction-level object accounting, including expire on - rollback, expire on commit, new/deleted list maintenance, and - autoflush on begin. - - - The 'cascade' parameter to relation() accepts None as a value, - which is equivalent to no cascades. - - - A critical fix to dynamic relations allows the "modified" - history to be properly cleared after a flush(). - - - user-defined @properties on a class are detected and left in - place during mapper initialization. This means that a - table-bound column of the same name will not be mapped at all - if a @property is in the way (and the column is not remapped - to a different name), nor will an instrumented attribute from - an inherited class be applied. The same rules apply for names - excluded using the include_properties/exclude_properties - collections. - - - Added a new SessionExtension hook called after_attach(). This - is called at the point of attachment for objects via add(), - add_all(), delete(), and merge(). - - - A mapper which inherits from another, when inheriting the - columns of its inherited mapper, will use any reassigned - property names specified in that inheriting mapper. - Previously, if "Base" had reassigned "base_id" to the name - "id", "SubBase(Base)" would still get an attribute called - "base_id". This could be worked around by explicitly stating - the column in each submapper as well but this is fairly - unworkable and also impossible when using declarative - [ticket:1111]. - - - Fixed a series of potential race conditions in Session whereby - asynchronous GC could remove unmodified, no longer referenced - items from the session as they were present in a list of items - to be processed, typically during session.expunge_all() and - dependent methods. - - - Some improvements to the _CompileOnAttr mechanism which should - reduce the probability of "Attribute x was not replaced during - compile" warnings. (this generally applies to SQLA hackers, - like Elixir devs). - - - Fixed bug whereby the "unsaved, pending instance" FlushError - raised for a pending orphan would not take superclass mappers - into account when generating the list of relations responsible - for the error. - -- sql - - func.count() with no arguments renders as COUNT(*), equivalent - to func.count(text('*')). - - - simple label names in ORDER BY expressions render as - themselves, and not as a re-statement of their corresponding - expression. This feature is currently enabled only for - SQLite, MySQL, and PostgreSQL. It can be enabled on other - dialects as each is shown to support this - behavior. [ticket:1068] - -- ext - - Class-bound attributes sent as arguments to relation()'s - remote_side and foreign_keys parameters are now accepted, - allowing them to be used with declarative. Additionally fixed - bugs involving order_by being specified as a class-bound - attribute in conjunction with eager loading. - - - declarative initialization of Columns adjusted so that - non-renamed columns initialize in the same way as a non - declarative mapper. This allows an inheriting mapper to set - up its same-named "id" columns in particular such that the - parent "id" column is favored over the child column, reducing - database round trips when this value is requested. - -- mysql - - Quoting of MSEnum values for use in CREATE TABLE is now - optional & will be quoted on demand as required. (Quoting was - always optional for use with existing tables.) [ticket:1110] - -0.5beta2 -======== - -0.5beta2 includes some of the bugfixes listed under release "0.4.7". - -- orm - - In addition to expired attributes, deferred attributes also - load if their data is present in the result set. [ticket:870] - - - session.refresh() raises an informative error message if the - list of attributes does not include any column-based - attributes. - - - query() raises an informative error message if no columns or - mappers are specified. - - - lazy loaders now trigger autoflush before proceeding. This - allows expire() of a collection or scalar relation to function - properly in the context of autoflush. - - - column_property() attributes which represent SQL expressions - or columns that are not present in the mapped tables (such as - those from views) are automatically expired after an INSERT or - UPDATE, assuming they have not been locally modified, so that - they are refreshed with the most recent data upon access. - [ticket:887] - - - Fixed explicit, self-referential joins between two - joined-table inheritance mappers when using query.join(cls, - aliased=True). [ticket:1082] - - - Fixed query.join() when used in conjunction with a - columns-only clause and an SQL-expression ON clause in the - join. - - - The "allow_column_override" flag from mapper() has been - removed. This flag is virtually always misunderstood. Its - specific functionality is available via the - include_properties/exclude_properties mapper arguments. - - - Repaired `__str__()` method on Query. [ticket:1066] - - - Session.bind gets used as a default even when table/mapper - specific binds are defined. - -- schema - - Added prefixes option to `Table` that accepts a list of - strings to insert after CREATE in the CREATE TABLE statement. - [ticket:1075] - - - Unicode, UnicodeText types now set "assert_unicode" and - "convert_unicode" by default, but accept overriding - **kwargs for these values. - -- sql - - Added new match() operator that performs a full-text search. - Supported on PostgreSQL, SQLite, MySQL, MS-SQL, and Oracle - backends. - -- sqlite - - Modified SQLite's representation of "microseconds" to match - the output of str(somedatetime), i.e. in that the microseconds - are represented as fractional seconds in string format. This - makes SQLA's SQLite date type compatible with datetimes that - were saved directly using Pysqlite (which just calls str()). - Note that this is incompatible with the existing microseconds - values in a SQLA 0.4 generated SQLite database file. - - To get the old behavior globally: - - from sqlalchemy.databases.sqlite import DateTimeMixin - DateTimeMixin.__legacy_microseconds__ = True - - To get the behavior on individual DateTime types: - - t = sqlite.SLDateTime() - t.__legacy_microseconds__ = True - - Then use "t" as the type on the Column. - - [ticket:1090] - - - SQLite Date, DateTime, and Time types only accept Python - datetime objects now, not strings. If you'd like to format - dates as strings yourself with SQLite, use a String type. If - you'd like them to return datetime objects anyway despite - their accepting strings as input, make a TypeDecorator around - String - SQLA doesn't encourage this pattern. - -- extensions - - Declarative supports a __table_args__ class variable, which is - either a dictionary, or tuple of the form (arg1, arg2, ..., - {kwarg1:value, ...}) which contains positional + kw arguments - to be passed to the Table constructor. [ticket:1096] - -0.5beta1 -======== - -An ongoing document describing the changes from 0.4 to 0.5 is at: -http://www.sqlalchemy.org/trac/wiki/05Migration - -For this section, the list below primarily lists changes within the -attribute instrumentation API and is only a small fraction of the -full changes between 0.4/0.5. - --orm - - The "__init__" trigger/decorator added by mapper now attempts - to exactly mirror the argument signature of the original - __init__. The pass-through for '_sa_session' is no longer - implicit- you must allow for this keyword argument in your - constructor. - - - ClassState is renamed to ClassManager. - - - Classes may supply their own InstrumentationManager by - providing a __sa_instrumentation_manager__ property. - - - Custom instrumentation may use any mechanism to associate a - ClassManager with a class and an InstanceState with an - instance. Attributes on those objects are still the default - association mechanism used by SQLAlchemy's native - instrumentation. - - - Moved entity_name, _sa_session_id, and _instance_key from the - instance object to the instance state. These values are still - available in the old way, which is now deprecated, using - descriptors attached to the class. A deprecation warning will - be issued when accessed. - - - The _prepare_instrumentation alias for prepare_instrumentation - has been removed. - - - sqlalchemy.exceptions has been renamed to sqlalchemy.exc. The - module may be imported under either name. - - - ORM-related exceptions are now defined in sqlalchemy.orm.exc. - ConcurrentModificationError, FlushError, and - UnmappedColumnError compatibility aliases are installed in - sqlalchemy.exc during the import of sqlalchemy.orm. - - - sqlalchemy.logging has been renamed to sqlalchemy.log. - - - The transitional sqlalchemy.log.SADeprecationWarning alias for - the warning's definition in sqlalchemy.exc has been removed. - - - exc.AssertionError has been removed and usage replaced with - Python's built-in AssertionError. - - - The behavior of MapperExtensions attached to multiple, - entity_name= primary mappers for a single class has been - altered. The first mapper() defined for a class is the only - mapper eligible for the MapperExtension 'instrument_class', - 'init_instance' and 'init_failed' events. This is backwards - incompatible; previously the extensions of last mapper defined - would receive these events. - -- firebird - - Added support for returning values from inserts (2.0+ only), - updates and deletes (2.1+ only). - -0.4.9 (unreleased) -================== - -- general: - - global "propigate"->"propagate" change. - -- orm - - polymorphic_union() function respects the "key" of each - Column if they differ from the column's name. - - - Fixed 0.4-only bug preventing composite columns - from working properly with inheriting mappers - [ticket:1199] - - - Fixed RLock-related bug in mapper which could deadlock upon - reentrant mapper compile() calls, something that occurs when - using declarative constructs inside of ForeignKey objects. - Ported from 0.5. - - - Fixed bug in composite types which prevented a primary-key - composite type from being mutated [ticket:1213]. - - - Added ScopedSession.is_active accessor. [ticket:976] - - - Class-bound accessor can be used as the argument to - relation() order_by. [ticket:939] - - - Fixed shard_id argument on ShardedSession.execute(). - [ticket:1072] - -- sql - - Connection.invalidate() checks for closed status - to avoid attribute errors. [ticket:1246] - - - NullPool supports reconnect on failure behavior. - [ticket:1094] - - - The per-dialect cache used by TypeEngine to cache - dialect-specific types is now a WeakKeyDictionary. - This to prevent dialect objects from - being referenced forever for an application that - creates an arbitrarily large number of engines - or dialects. There is a small performance penalty - which will be resolved in 0.6. [ticket:1299] - --sqlite - - Fixed SQLite reflection methods so that non-present - cursor.description, which triggers an auto-cursor - close, will be detected so that no results doesn't - fail on recent versions of pysqlite which raise - an error when fetchone() called with no rows present. - -- postgres - - Added Index reflection support to Postgres, using a - great patch we long neglected, submitted by - Ken Kuhlman. [ticket:714] - -- mysql - - Fixed bug in exception raise when FK columns not present - during reflection. [ticket:1241] - -- oracle - - Fixed bug which was preventing out params of certain types - from being received; thanks a ton to huddlej at wwu.edu ! - [ticket:1265] - -0.4.8 -===== -- orm - - Fixed bug regarding inherit_condition passed - with "A=B" versus "B=A" leading to errors - [ticket:1039] - - - Changes made to new, dirty and deleted - collections in - SessionExtension.before_flush() will take - effect for that flush. - - - Added label() method to InstrumentedAttribute - to establish forwards compatibility with 0.5. - -- sql - - column.in_(someselect) can now be used as - a columns-clause expression without the subquery - bleeding into the FROM clause [ticket:1074] - -- mysql - - Added MSMediumInteger type [ticket:1146]. - -- sqlite - - Supplied a custom strftime() function which - handles dates before 1900. [ticket:968] - - - String's (and Unicode's, UnicodeText's, etc.) - convert_unicode logic disabled in the sqlite dialect, - to adjust for pysqlite 2.5.0's new requirement that - only Python unicode objects are accepted; - http://itsystementwicklung.de/pipermail/list-pysqlite/2008-March/000018.html - -- oracle - - has_sequence() now takes schema name into account - [ticket:1155] - - added BFILE to the list of reflected types - [ticket:1121] - -0.4.7p1 -===== -- orm - - Added "add()" and "add_all()" to scoped_session - methods. Workaround for 0.4.7: - - from sqlalchemy.orm.scoping import ScopedSession,\ - instrument - setattr( - ScopedSession, "add", instrument("add")) - setattr( - ScopedSession, "add_all", instrument("add_all")) - - - Fixed non-2.3 compatible usage of set() and generator - expression within relation(). - -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 - - diff --git a/doc/build/builder/__init__.py b/doc/build/builder/__init__.py index 0e29e69c46..f3ea8b93ae 100644 --- a/doc/build/builder/__init__.py +++ b/doc/build/builder/__init__.py @@ -1,6 +1,6 @@ -from . import autodoc_mods, dialect_info, sqlformatter, mako +from . import autodoc_mods, dialect_info, sqlformatter, mako, changelog def setup(app): app.add_config_value('release_date', "", True) @@ -10,3 +10,4 @@ def setup(app): autodoc_mods.setup(app) dialect_info.setup(app) sqlformatter.setup(app) + changelog.setup(app) diff --git a/doc/build/builder/changelog.py b/doc/build/builder/changelog.py new file mode 100644 index 0000000000..16126f4ffb --- /dev/null +++ b/doc/build/builder/changelog.py @@ -0,0 +1,268 @@ +import re +from sphinx.util.compat import Directive +from docutils.statemachine import StringList +from docutils import nodes +import textwrap +import itertools +import collections + +def _comma_list(text): + return re.split(r"\s*,\s*", text.strip()) + +def _parse_content(content): + d = {} + d['text'] = [] + idx = 0 + for line in content: + idx += 1 + m = re.match(r' *\:(.+?)\:(?: +(.+))?', line) + if m: + attrname, value = m.group(1, 2) + d[attrname] = value or '' + else: + break + d["text"] = content[idx:] + return d + +def _ticketurl(ticket): + return "http://www.sqlalchemy.org/trac/ticket/%s" % ticket + +class EnvDirective(object): + @property + def env(self): + return self.state.document.settings.env + +class ChangeLogDirective(EnvDirective, Directive): + has_content = True + + type_ = "change" + + sections = _comma_list("general, orm, orm declarative, orm querying, \ + orm configuration, engine, sql, \ + schema, \ + postgresql, mysql, sqlite, mssql, oracle, firebird, misc") + + subsections = ["feature", "bug", "moved", "changed", "removed", ""] + + + def _organize_by_section(self, changes): + compound_sections = [(s, s.split(" ")) for s in + self.sections if " " in s] + + bysection = collections.defaultdict(list) + for rec in changes: + subsection = rec['tags'].intersection(self.subsections) + if subsection: + subsection = subsection.pop() + else: + subsection = "" + + for compound, comp_words in compound_sections: + if rec['tags'].issuperset(comp_words): + bysection[(compound, subsection)].append(rec) + break + + intersect = rec['tags'].intersection(self.sections) + if intersect: + bysection[(intersect.pop(), subsection)].append(rec) + continue + + bysection[('misc', subsection)].append(rec) + return bysection + + @classmethod + def changes(cls, env): + return env.temp_data['ChangeLogDirective_%s_changes' % cls.type_] + + def _setup_run(self): + self.env.temp_data['ChangeLogDirective_%s_changes' % self.type_] = [] + self._parsed_content = _parse_content(self.content) + + p = nodes.paragraph('', '',) + self.state.nested_parse(self.content[1:], 0, p) + + def run(self): + self._setup_run() + changes = self.changes(self.env) + output = [] + + version = self._parsed_content.get('version', '') + id_prefix = "%s-%s" % (self.type_, version) + topsection = self._run_top(id_prefix) + output.append(topsection) + + bysection = self._organize_by_section(changes) + + counter = itertools.count() + + for section in self.sections: + sec, append_sec = self._section(section, id_prefix) + + for cat in self.subsections: + for rec in bysection[(section, cat)]: + rec["id"] = "%s-%s" % (id_prefix, next(counter)) + + self._render_rec(rec, section, cat, append_sec) + + if append_sec.children: + topsection.append(sec) + + return output + + def _section(self, section, id_prefix): + bullets = nodes.bullet_list() + sec = nodes.section('', + nodes.title(section, section), + bullets, + ids=["%s-%s" % (id_prefix, section.replace(" ", "-"))] + ) + return sec, bullets + + def _run_top(self, id_prefix): + version = self._parsed_content.get('version', '') + topsection = nodes.section('', + nodes.title(version, version), + ids=[id_prefix] + ) + + if self._parsed_content.get("released"): + topsection.append(nodes.Text("Released: %s" % self._parsed_content['released'])) + else: + topsection.append(nodes.Text("no release date")) + return topsection + + def _render_rec(self, rec, section, cat, append_sec): + para = rec['node'].deepcopy() + insert_ticket = nodes.paragraph('') + para.append(insert_ticket) + + for i, ticket in enumerate(rec['tickets']): + if i > 0: + insert_ticket.append(nodes.Text(", ", ", ")) + else: + insert_ticket.append(nodes.Text(" ", " ")) + insert_ticket.append( + nodes.reference('', '', + nodes.Text("#%s" % ticket, "#%s" % ticket), + refuri=_ticketurl(ticket) + ) + ) + + if cat or rec['tags']: + #tag_node = nodes.strong('', + # "[" + cat + "] " + # ) + tag_node = nodes.strong('', + " ".join("[%s]" % t for t + in + [cat] + + list(rec['tags'].difference([cat])) + if t + ) + " " + ) + para.children[0].insert(0, tag_node) + + append_sec.append( + nodes.list_item('', + nodes.target('', '', ids=[rec['id']]), + para + ) + ) + + +class MigrationLogDirective(ChangeLogDirective): + type_ = "migration" + + sections = _comma_list("New Features, Behavioral Changes, Removed") + + subsections = _comma_list("general, orm, orm declarative, orm querying, \ + orm configuration, engine, sql, \ + postgresql, mysql, sqlite") + + def _run_top(self, id_prefix): + version = self._parsed_content.get('version', '') + title = "What's new in %s?" % version + topsection = nodes.section('', + nodes.title(title, title), + ids=[id_prefix] + ) + if "released" in self._parsed_content: + topsection.append(nodes.Text("Released: %s" % self._parsed_content['released'])) + return topsection + + def _section(self, section, id_prefix): + sec = nodes.section('', + nodes.title(section, section), + ids=["%s-%s" % (id_prefix, section.replace(" ", "-"))] + ) + return sec, sec + + def _render_rec(self, rec, section, cat, append_sec): + para = rec['node'].deepcopy() + + insert_ticket = nodes.paragraph('') + para.append(insert_ticket) + + for i, ticket in enumerate(rec['tickets']): + if i > 0: + insert_ticket.append(nodes.Text(", ", ", ")) + else: + insert_ticket.append(nodes.Text(" ", " ")) + insert_ticket.append( + nodes.reference('', '', + nodes.Text("#%s" % ticket, "#%s" % ticket), + refuri=_ticketurl(ticket) + ) + ) + + append_sec.append( + nodes.section('', + nodes.title(rec['title'], rec['title']), + para, + ids=[rec['id']] + ) + ) + + + +class ChangeDirective(EnvDirective, Directive): + has_content = True + + type_ = "change" + parent_cls = ChangeLogDirective + + def run(self): + content = _parse_content(self.content) + p = nodes.paragraph('', '',) + rec = { + 'tags': set(_comma_list(content.get('tags', ''))).difference(['']), + 'tickets': set(_comma_list(content.get('tickets', ''))).difference(['']), + 'node': p, + 'type': self.type_, + "title": content.get("title", None) + } + + if "declarative" in rec['tags']: + rec['tags'].add("orm") + + self.state.nested_parse(content['text'], 0, p) + self.parent_cls.changes(self.env).append(rec) + + return [] + +class MigrationDirective(ChangeDirective): + type_ = "migration" + parent_cls = MigrationLogDirective + + +def _rst2sphinx(text): + return StringList( + [line.strip() for line in textwrap.dedent(text).split("\n")] + ) + +def setup(app): + app.add_directive('changelog', ChangeLogDirective) + app.add_directive('migrationlog', MigrationLogDirective) + app.add_directive('migration', MigrationDirective) + app.add_directive('change', ChangeDirective) + diff --git a/doc/build/builder/dialect_info.py b/doc/build/builder/dialect_info.py index 454f26f4ef..22e3fb0859 100644 --- a/doc/build/builder/dialect_info.py +++ b/doc/build/builder/dialect_info.py @@ -91,8 +91,6 @@ class DialectDirective(Directive): if "connectstring" in content: - # TODO: wish I knew how to just embed RST here and parse it into - # nodes sec = nodes.section( '', nodes.title("Connecting", "Connecting"), diff --git a/doc/build/changelog/changelog_01.rst b/doc/build/changelog/changelog_01.rst new file mode 100644 index 0000000000..156599a13e --- /dev/null +++ b/doc/build/changelog/changelog_01.rst @@ -0,0 +1,975 @@ + +============== +0.1 Changelog +============== + + +.. changelog:: + :version: 0.1.7 + :released: Fri May 05 2006 + + .. change:: + :tags: + :tickets: + + some fixes to topological sort algorithm + + .. change:: + :tags: + :tickets: + + added DISTINCT ON support to Postgres (just supply distinct=[col1,col2..]) + + .. change:: + :tags: + :tickets: + + added __mod__ (% operator) to sql expressions + + .. change:: + :tags: + :tickets: + + "order_by" mapper property inherited from inheriting mapper + + .. change:: + :tags: + :tickets: + + fix to column type used when mapper UPDATES/DELETEs + + .. change:: + :tags: + :tickets: + + with convert_unicode=True, reflection was failing, has been fixed + + .. change:: + :tags: + :tickets: + + types types types! still werent working....have to use TypeDecorator again :( + + .. change:: + :tags: + :tickets: + + mysql binary type converts array output to buffer, fixes PickleType + + .. change:: + :tags: + :tickets: + + fixed the attributes.py memory leak once and for all + + .. change:: + :tags: + :tickets: + + unittests are qualified based on the databases that support each one + + .. change:: + :tags: + :tickets: + + fixed bug where column defaults would clobber VALUES clause of insert objects + + .. change:: + :tags: + :tickets: + + fixed bug where table def w/ schema name would force engine connection + + .. change:: + :tags: + :tickets: + + fix for parenthesis to work correctly with subqueries in INSERT/UPDATE + + .. change:: + :tags: + :tickets: + + HistoryArraySet gets extend() method + + .. change:: + :tags: + :tickets: + + fixed lazyload support for other comparison operators besides = + + .. change:: + :tags: + :tickets: + + lazyload fix where two comparisons in the join condition point to the + samem column + + .. change:: + :tags: + :tickets: + + added "construct_new" flag to mapper, will use __new__ to create instances + instead of __init__ (standard in 0.2) + + .. change:: + :tags: + :tickets: + + added selectresults.py to SVN, missed it last time + + .. change:: + :tags: + :tickets: + + tweak to allow a many-to-many relationship from a table to itself via + an association table + + .. change:: + :tags: + :tickets: + + small fix to "translate_row" function used by polymorphic example + + .. change:: + :tags: + :tickets: + + create_engine uses cgi.parse_qsl to read query string (out the window in 0.2) + + .. change:: + :tags: + :tickets: + + tweaks to CAST operator + + .. change:: + :tags: + :tickets: + + fixed function names LOCAL_TIME/LOCAL_TIMESTAMP -> LOCALTIME/LOCALTIMESTAMP + + .. change:: + :tags: + :tickets: + + fixed order of ORDER BY/HAVING in compile + +.. changelog:: + :version: 0.1.6 + :released: Wed Apr 12 2006 + + .. change:: + :tags: + :tickets: + + support for MS-SQL added courtesy Rick Morrison, Runar Petursson + + .. change:: + :tags: + :tickets: + + the latest SQLSoup from J. Ellis + + .. change:: + :tags: + :tickets: + + ActiveMapper has preliminary support for inheritance (Jeff Watkins) + + .. change:: + :tags: + :tickets: + + added a "mods" system which allows pluggable modules that modify/augment + core functionality, using the function "install_mods(*modnames)". + + .. change:: + :tags: + :tickets: + + added the first "mod", SelectResults, which modifies mapper selects to + return generators that turn ranges into LIMIT/OFFSET queries + (Jonas Borgstr? + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + overhaul to the attributes system. code has been clarified, and also fixed to + support proper polymorphic behavior on object attributes. + + .. change:: + :tags: + :tickets: + + added "for_update" flag to Select objects + + .. change:: + :tags: + :tickets: + + some fixes for backrefs + + .. change:: + :tags: + :tickets: + + fix for postgres1 DateTime type + + .. change:: + :tags: + :tickets: + + documentation pages mostly switched over to Markdown syntax + +.. changelog:: + :version: 0.1.5 + :released: Mon Mar 27 2006 + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + factored apart objectstore/unitofwork to separate "Session scoping" from + "uow commit heavy lifting" + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + fixed Oracle8-compatibility "use_ansi" flag which converts JOINs to + comparisons with the = and (+) operators, passes basic unittests + + .. change:: + :tags: + :tickets: + + tweaks to Oracle LIMIT/OFFSET support + + .. change:: + :tags: + :tickets: + + Oracle reflection uses ALL_** views instead of USER_** to get larger + list of stuff to reflect from + + .. change:: + :tags: + :tickets: 105 + + fixes to Oracle foreign key reflection + + .. change:: + :tags: + :tickets: + + 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 + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + some minor speed improvements to the attributes system with regards to + instantiating and populating new objects. + + .. change:: + :tags: + :tickets: + + fixed MySQL binary unit test + + .. change:: + :tags: + :tickets: + + INSERTs can receive clause elements as VALUES arguments, not just literal + values + + .. change:: + :tags: + :tickets: + + support for calling multi-tokened functions, i.e. schema.mypkg.func() + + .. change:: + :tags: + :tickets: + + added J. Ellis' SQLSoup module to extensions package + + .. change:: + :tags: + :tickets: + + 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 + + .. change:: + :tags: + :tickets: + + improvements/fixes to session.refresh()/session.expire() (which may have + been called "invalidate" earlier..) + + .. change:: + :tags: + :tickets: + + added session.expunge() which totally removes an object from the current + session + + .. change:: + :tags: + :tickets: + + added *args, **kwargs pass-thru to engine.transaction(func) allowing easier + creation of transactionalizing decorator functions + + .. change:: + :tags: + :tickets: + + added iterator interface to ResultProxy: "for row in result:..." + + .. change:: + :tags: + :tickets: + + added assertion to tx = session.begin(); tx.rollback(); tx.begin(), i.e. cant + use it after a rollback() + + .. change:: + :tags: + :tickets: + + added date conversion on bind parameter fix to SQLite enabling dates to + work with pysqlite1 + + .. change:: + :tags: + :tickets: 116 + + improvements to subqueries to more intelligently construct their FROM + clauses + + .. change:: + :tags: + :tickets: + + added PickleType to types. + + .. change:: + :tags: + :tickets: + + 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 + + .. change:: + :tags: + :tickets: + + major overhaul to unit of work documentation, other documentation sections. + + .. change:: + :tags: + :tickets: + + fixed attributes bug where if an object is committed, its lazy-loaded list got + blown away if it hadnt been loaded + + .. change:: + :tags: + :tickets: + + 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 + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + added distinct() function to column elements so you can do + func.count(mycol.distinct()) + + .. change:: + :tags: + :tickets: + + 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. + +.. changelog:: + :version: 0.1.4 + :released: Mon Mar 13 2006 + + .. change:: + :tags: + :tickets: + + create_engine() now uses genericized parameters; host/hostname, + db/dbname/database, password/passwd, etc. for all engine connections. makes + engine URIs much more "universal" + + .. change:: + :tags: + :tickets: + + added support for SELECT statements embedded into a column clause, using the + flag "scalar=True" + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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 + + .. change:: + :tags: + :tickets: + + added onupdate parameter to Column, will exec SQL/python upon an update + statement.Also adds "for_update=True" to all DefaultGenerator subclasses + + .. change:: + :tags: + :tickets: + + added support for Oracle table reflection contributed by Andrija Zaric; + still some bugs to work out regarding composite primary keys/dictionary selection + + .. change:: + :tags: + :tickets: + + checked in an initial Firebird module, awaiting testing. + + .. change:: + :tags: + :tickets: + + 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 + + .. change:: + :tags: + :tickets: + + more docs for indexes, column defaults, connection pooling, engine construction + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + added "convert_unicode=False" parameter to SQLEngine, will cause all String + types to perform unicode encoding/decoding (makes Strings act like Unicodes) + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + improved support for mapping against UNIONs, added polymorph.py example + to illustrate multi-class mapping against a UNION + + .. change:: + :tags: + :tickets: + + fix to SQLite LIMIT/OFFSET syntax + + .. change:: + :tags: + :tickets: + + fix to Oracle LIMIT syntax + + .. change:: + :tags: + :tickets: + + added backref() function, allows backreferences to have keyword arguments + that will be passed to the backref. + + .. change:: + :tags: + :tickets: + + Sequences and ColumnDefault objects can do execute()/scalar() standalone + + .. change:: + :tags: + :tickets: + + SQL functions (i.e. func.foo()) can do execute()/scalar() standalone + + .. change:: + :tags: + :tickets: + + fix to SQL functions so that the ANSI-standard functions, i.e. current_timestamp + etc., do not specify parenthesis. all other functions do. + + .. change:: + :tags: + :tickets: + + 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') + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + added 'get_session().invalidate(*obj)' method to objectstore, instances will + refresh() themselves upon the next attribute access. + + .. change:: + :tags: + :tickets: + + 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 + + .. change:: + :tags: + :tickets: + + fix to MySQL4 custom table engines, i.e. TYPE instead of ENGINE + + .. change:: + :tags: + :tickets: + + slightly enhanced logging, includes timestamps and a somewhat configurable + formatting system, in lieu of a full-blown logging system + + .. change:: + :tags: + :tickets: + + improvements to the ActiveMapper class from the TG gang, including + many-to-many relationships + + .. change:: + :tags: + :tickets: + + added Double and TinyInt support to mysql + +.. changelog:: + :version: 0.1.3 + :released: Thu Mar 02 2006 + + .. change:: + :tags: + :tickets: + + 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 + + .. change:: + :tags: + :tickets: + + completed mapper.using(session) function, localized per-object Session + functionality; objects can be declared and manipulated as local to any + user-defined Session + + .. change:: + :tags: + :tickets: + + fix to Oracle "row_number over" clause with multiple tables + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + made objectstore "check for out-of-identitymap" more aggressive, will perform the + check when object attributes are modified or the object is deleted + + .. change:: + :tags: + :tickets: + + Index object fully implemented, can be constructed standalone, or via + "index" and "unique" arguments on Columns. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + postgres maintains a list of ANSI functions that must have no parenthesis so + function calls with no arguments work consistently + + .. change:: + :tags: + :tickets: + + 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". + + .. change:: + :tags: + :tickets: + + added "refresh(*obj)" method to objectstore / Session to reload the attributes of + any set of objects from the database unconditionally + +.. changelog:: + :version: 0.1.2 + :released: Fri Feb 24 2006 + + .. change:: + :tags: + :tickets: + + 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. + +.. changelog:: + :version: 0.1.1 + :released: Thu Feb 23 2006 + + .. change:: + :tags: + :tickets: + + 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). + + .. change:: + :tags: + :tickets: + + creating self-referring mappers with backrefs slightly easier (but still not that easy - + changeset 1019) + + .. change:: + :tags: + :tickets: + + fixes to one-to-one mappings (changeset 1015) + + .. change:: + :tags: + :tickets: + + psycopg1 date/time issue with None fixed (changeset 1005) + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + fixed a glitch with engine.execute_compiled where it was making a second + ResultProxy that just got thrown away. + + .. change:: + :tags: + :tickets: + + 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'] + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + added exceptions module, all raised exceptions (except for some + KeyError/AttributeError exceptions) descend from these classes. + + .. change:: + :tags: + :tickets: + + fix to date types with MySQL, returned timedelta converted to datetime.time + + .. change:: + :tags: + :tickets: + + two-phase objectstore.commit operations (i.e. begin/commit) now return a + transactional object (SessionTrans), to more clearly indicate transaction boundaries. + + .. change:: + :tags: + :tickets: + + Index object with create/drop support added to schema + + .. change:: + :tags: + :tickets: + + 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:: + :tags: + :tickets: + + 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 + + .. change:: + :tags: + :tickets: + + fix to engine.process_defaults so it works correctly with a table that has + different column name/column keys (changset 982) + + .. change:: + :tags: + :tickets: + + a column can only be attached to one table - this is now asserted + + .. change:: + :tags: + :tickets: + + postgres time types descend from Time type + + .. change:: + :tags: + :tickets: + + fix to alltests so that it runs types test (now named testtypes) + + .. change:: + :tags: + :tickets: + + fix to Join object so that it correctly exports its foreign keys (cs 973) + + .. change:: + :tags: + :tickets: + + creating relationships against mappers that use inheritance fixed (cs 973) diff --git a/doc/build/changelog/changelog_02.rst b/doc/build/changelog/changelog_02.rst new file mode 100644 index 0000000000..3053659a85 --- /dev/null +++ b/doc/build/changelog/changelog_02.rst @@ -0,0 +1,1187 @@ + +============== +0.2 Changelog +============== + + +.. changelog:: + :version: 0.2.8 + :released: Tue Sep 05 2006 + + .. change:: + :tags: + :tickets: + + 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'. + + .. change:: + :tags: + :tickets: 274 + + 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 + + .. change:: + :tags: + :tickets: 121 + + 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 + + .. change:: + :tags: + :tickets: + + eesh ! the tutorial doctest was broken for quite some time. + + .. change:: + :tags: + :tickets: + + 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 !) + + .. change:: + :tags: + :tickets: 277 + + check for pg sequence already existing before create + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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) + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + it is now invalid to declare a self-referential relationship with + "delete-orphan" (as the abovementioned check would make them impossible + to save) + + .. change:: + :tags: + :tickets: + + improved the check for objects being part of a session when the + unit of work seeks to flush() them as part of a relationship.. + + .. change:: + :tags: + :tickets: 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. + + .. change:: + :tags: + :tickets: 60, 71 + + postgres reflection moved to use pg_schema tables, can be overridden + with use_information_schema=True argument to create_engine. + + .. change:: + :tags: + :tickets: 155 + + 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 + + .. change:: + :tags: + :tickets: + + unit tests updated to run without any pysqlite installed; pool + test uses a mock DBAPI + + .. change:: + :tags: + :tickets: 281 + + urls support escaped characters in passwords + + .. change:: + :tags: + :tickets: + + added limit/offset to UNION queries (though not yet in oracle) + + .. change:: + :tags: + :tickets: + + 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). + + .. change:: + :tags: + :tickets: 287 + + fix to using query.count() with distinct, **kwargs with SelectResults + count() + + .. change:: + :tags: + :tickets: 289 + + deregister Table from MetaData when autoload fails; + + .. change:: + :tags: + :tickets: 293 + + import of py2.5s sqlite3 + + .. change:: + :tags: + :tickets: 296 + + unicode fix for startswith()/endswith() + +.. changelog:: + :version: 0.2.7 + :released: Sat Aug 12 2006 + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + assignmapper was setting is_primary=True, causing all sorts of mayhem + by not raising an error when redundant mappers were set up, fixed + + .. change:: + :tags: + :tickets: + + added allow_null_pks option to Mapper, allows rows where some + primary key columns are null (i.e. when mapping to outer joins etc) + + .. change:: + :tags: + :tickets: + + 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) + + .. change:: + :tags: + :tickets: + + fixed reflection of foreign keys to autoload the referenced table + if it was not loaded already + + .. change:: + :tags: + :tickets: 256 + + - pass URL query string arguments to connect() function + + .. change:: + :tags: + :tickets: 257 + + - oracle boolean type + + .. change:: + :tags: + :tickets: + + custom primary/secondary join conditions in a relation *will* be propagated + to backrefs by default. specifying a backref() will override this behavior. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + sqlite creates ForeignKeyConstraint objects properly upon table + reflection. + + .. change:: + :tags: + :tickets: 224 + + adjustments to pool stemming from changes made for. + overflow counter should only be decremented if the connection actually + succeeded. added a test script to attempt testing this. + + .. change:: + :tags: + :tickets: + + fixed mysql reflection of default values to be PassiveDefault + + .. change:: + :tags: + :tickets: 263, 264 + + added reflected 'tinyint', 'mediumint' type to MS-SQL. + + .. change:: + :tags: + :tickets: + + 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) + + .. change:: + :tags: + :tickets: 267, 265 + + fixed small pickle bug(s) with lazy loaders + + .. change:: + :tags: + :tickets: + + fixed possible error in mysql reflection where certain versions + return an array instead of string for SHOW CREATE TABLE call + + .. change:: + :tags: + :tickets: 1770 + + fix to lazy loads when mapping to joins + + .. change:: + :tags: + :tickets: + + all create()/drop() calls have a keyword argument of "connectable". + "engine" is deprecated. + + .. change:: + :tags: + :tickets: + + fixed ms-sql connect() to work with adodbapi + + .. change:: + :tags: + :tickets: + + added "nowait" flag to Select() + + .. change:: + :tags: + :tickets: 271 + + 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 + + .. change:: + :tags: + :tickets: 252 + + SelectResults will use a subselect, when calling an aggregate (i.e. + max, min, etc.) on a SelectResults that has an ORDER BY clause + + .. change:: + :tags: + :tickets: 269 + + fixes to types so that database-specific types more easily used; + fixes to mysql text types to work with this methodology + + .. change:: + :tags: + :tickets: + + some fixes to sqlite date type organization + + .. change:: + :tags: + :tickets: 263 + + added MSTinyInteger to MS-SQL + +.. changelog:: + :version: 0.2.6 + :released: Thu Jul 20 2006 + + .. change:: + :tags: + :tickets: 76 + + 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. + + .. change:: + :tags: + :tickets: + + overhaul to MapperExtension calling scheme, wasnt working very well + previously + + .. change:: + :tags: + :tickets: + + tweaks to ActiveMapper, supports self-referential relationships + + .. change:: + :tags: + :tickets: + + slight rearrangement to objectstore (in activemapper/threadlocal) + so that the SessionContext is referenced by '.context' instead + of subclassed directly. + + .. change:: + :tags: + :tickets: + + activemapper will use threadlocal's objectstore if the mod is + activated when activemapper is imported + + .. change:: + :tags: + :tickets: + + small fix to URL regexp to allow filenames with '@' in them + + .. change:: + :tags: + :tickets: + + fixes to Session expunge/update/etc...needs more cleanup. + + .. change:: + :tags: + :tickets: + + select_table mappers *still* werent always compiling + + .. change:: + :tags: + :tickets: + + fixed up Boolean datatype + + .. change:: + :tags: + :tickets: + + added count()/count_by() to list of methods proxied by assignmapper; + this also adds them to activemapper + + .. change:: + :tags: + :tickets: + + connection exceptions wrapped in DBAPIError + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + deferred column load could screw up the connection status in + a flush() under some circumstances, this was fixed + + .. change:: + :tags: + :tickets: + + expunge() was not working with cascade, fixed. + + .. change:: + :tags: + :tickets: + + potential endless loop in cascading operations fixed. + + .. change:: + :tags: + :tickets: + + 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(). + + .. change:: + :tags: + :tickets: + + fix to typing in clause construction which specifically helps + type issues with polymorphic_union (CAST/ColumnClause propagates + its type to proxy columns) + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + eager loads explicitly disallowed on self-referential relationships, or + relationships to an inheriting mapper (which is also self-referential) + + .. change:: + :tags: + :tickets: 244 + + reduced bind param size in query._get to appease the picky oracle + + .. change:: + :tags: + :tickets: 234 + + added 'checkfirst' argument to table.create()/table.drop(), as + well as table.exists() + + .. change:: + :tags: + :tickets: 245 + + some other ongoing fixes to inheritance + + .. change:: + :tags: + :tickets: + + attribute/backref/orphan/history-tracking tweaks as usual... + +.. changelog:: + :version: 0.2.5 + :released: Sat Jul 08 2006 + + .. change:: + :tags: + :tickets: + + fixed endless loop bug in select_by(), if the traversal hit + two mappers that referenced each other + + .. change:: + :tags: + :tickets: + + upgraded all unittests to insert './lib/' into sys.path, + working around new setuptools PYTHONPATH-killing behavior + + .. change:: + :tags: + :tickets: + + further fixes with attributes/dependencies/etc.... + + .. change:: + :tags: + :tickets: + + improved error handling for when DynamicMetaData is not connected + + .. change:: + :tags: + :tickets: + + MS-SQL support largely working (tested with pymssql) + + .. change:: + :tags: + :tickets: + + ordering of UPDATE and DELETE statements within groups is now + in order of primary key values, for more deterministic ordering + + .. change:: + :tags: + :tickets: + + after_insert/delete/update mapper extensions now called per object, + not per-object-per-table + + .. change:: + :tags: + :tickets: + + further fixes/refactorings to mapper compilation + +.. changelog:: + :version: 0.2.4 + :released: Tue Jun 27 2006 + + .. change:: + :tags: + :tickets: + + try/except when the mapper sets init.__name__ on a mapped class, + supports python 2.3 + + .. change:: + :tags: + :tickets: + + fixed bug where threadlocal engine would still autocommit + despite a transaction in progress + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + fixes to mapper compilation, checking for more error conditions + + .. change:: + :tags: + :tickets: + + small fix to eager loading combined with ordering/limit/offset + + .. change:: + :tags: + :tickets: 206 + + utterly remarkable: added a single space between 'CREATE TABLE' + and '(' since *thats how MySQL indicates a non- + reserved word tablename.....* + + .. change:: + :tags: + :tickets: + + more fixes to inheritance, related to many-to-many relations + properly saving + + .. change:: + :tags: + :tickets: + + fixed bug when specifying explicit module to mysql dialect + + .. change:: + :tags: + :tickets: + + when QueuePool times out it raises a TimeoutError instead of + erroneously making another connection + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + postgres will not place SERIAL keyword on a primary key column + if it has a foreign key constraint + + .. change:: + :tags: + :tickets: 221 + + cursor() method on ConnectionFairy allows db-specific extension + arguments to be propagated + + .. change:: + :tags: + :tickets: 225 + + lazy load bind params properly propagate column type + + .. change:: + :tags: + :tickets: + + new MySQL types: MSEnum, MSTinyText, MSMediumText, MSLongText, etc. + more support for MS-specific length/precision params in numeric types + patch courtesy Mike Bernson + + .. change:: + :tags: + :tickets: 224 + + some fixes to connection pool invalidate() + +.. changelog:: + :version: 0.2.3 + :released: Sat Jun 17 2006 + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + fixed a pretty big speed bottleneck in cascading behavior particularly + when backrefs were in use + + .. change:: + :tags: + :tickets: + + 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). + + .. change:: + :tags: + :tickets: + + py2.4 "set" construct used internally, falls back to sets.Set when + "set" not available/ordering is needed. + + .. change:: + :tags: + :tickets: + + 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) + + .. change:: + :tags: + :tickets: 151 + + "foreignkey" argument to relation() can also be a list. fixed + auto-foreignkey detection + + .. change:: + :tags: + :tickets: + + fixed bug where tables with schema names werent getting indexed in + the MetaData object properly + + .. change:: + :tags: + :tickets: 207 + + fixed bug where Column with redefined "key" property wasnt getting + type conversion happening in the ResultProxy + + .. change:: + :tags: + :tickets: + + fixed 'port' attribute of URL to be an integer if present + + .. change:: + :tags: + :tickets: + + fixed old bug where if a many-to-many table mapped as "secondary" + had extra columns, delete operations didnt work + + .. change:: + :tags: + :tickets: + + bugfixes for mapping against UNION queries + + .. change:: + :tags: + :tickets: + + fixed incorrect exception class thrown when no DB driver present + + .. change:: + :tags: + :tickets: 138 + + added NonExistentTable exception thrown when reflecting a table + that doesnt exist + + .. change:: + :tags: + :tickets: + + small fix to ActiveMapper regarding one-to-one backrefs, other + refactorings + + .. change:: + :tags: + :tickets: + + overridden constructor in mapped classes gets __name__ and + __doc__ from the original class + + .. change:: + :tags: + :tickets: 200 + + fixed small bug in selectresult.py regarding mapper extension + + .. change:: + :tags: + :tickets: + + small tweak to cascade_mappers, not very strongly supported + function at the moment + + .. change:: + :tags: + :tickets: 202 + + some fixes to between(), column.between() to propagate typing + information better + + .. change:: + :tags: + :tickets: 203 + + if an object fails to be constructed, is not added to the + session + + .. change:: + :tags: + :tickets: + + 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 + +.. changelog:: + :version: 0.2.2 + :released: Mon Jun 05 2006 + + .. change:: + :tags: + :tickets: 190 + + big improvements to polymorphic inheritance behavior, enabling it + to work with adjacency list table structures + + .. change:: + :tags: + :tickets: + + major fixes and refactorings to inheritance relationships overall, + more unit tests + + .. change:: + :tags: + :tickets: + + fixed "echo_pool" flag on create_engine() + + .. change:: + :tags: + :tickets: + + fix to docs, removed incorrect info that close() is unsafe to use + with threadlocal strategy (its totally safe !) + + .. change:: + :tags: + :tickets: 188 + + create_engine() can take URLs as string or unicode + + .. change:: + :tags: + :tickets: + + firebird support partially completed; + thanks to James Ralston and Brad Clements for their efforts. + + .. change:: + :tags: + :tickets: + + 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 + + .. change:: + :tags: + :tickets: + + fix to using unicode criterion for query.get()/query.load() + + .. change:: + :tags: + :tickets: + + count() function on selectables now uses table primary key or + first column instead of "1" for criterion, also uses label "rowcount" + instead of "count". + + .. change:: + :tags: + :tickets: + + got rudimental "mapping to multiple tables" functionality cleaned up, + more correctly documented + + .. change:: + :tags: + :tickets: + + restored global_connect() function, attaches to a DynamicMetaData + instance called "default_metadata". leaving MetaData arg to Table + out will use the default metadata. + + .. change:: + :tags: + :tickets: + + fixes to session cascade behavior, entity_name propigation + + .. change:: + :tags: + :tickets: + + reorganized unittests into subdirectories + + .. change:: + :tags: + :tickets: + + more fixes to threadlocal connection nesting patterns + +.. changelog:: + :version: 0.2.1 + :released: Mon May 29 2006 + + .. change:: + :tags: + :tickets: + + "pool" argument to create_engine() properly propagates + + .. change:: + :tags: + :tickets: + + 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) + + .. change:: + :tags: + :tickets: + + small fixes to Mapper when it inserts and tries to get + new primary key values back + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + placeholder dispose() method added to SingletonThreadPool, doesnt + do anything yet + + .. change:: + :tags: + :tickets: + + rollback() is automatically called when an exception is raised, + but only if theres no transaction in process (i.e. works more like + autocommit). + + .. change:: + :tags: + :tickets: + + fixed exception raise in sqlite if no sqlite module present + + .. change:: + :tags: + :tickets: + + added extra example detail for association object doc + + .. change:: + :tags: + :tickets: + + Connection adds checks for already being closed + +.. changelog:: + :version: 0.2.0 + :released: Sat May 27 2006 + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + create_engine now takes only RFC-1738-style strings: + driver://user:password@host:port/database + + .. change:: + :tags: + :tickets: 152 + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: 167 + + true polymorphic behavior implemented, fixes + + .. change:: + :tags: + :tickets: 147 + + "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 + + .. change:: + :tags: + :tickets: + + overhaul to packaging; "mapping" is now "orm", "objectstore" is now + "session", the old "objectstore" namespace gets loaded in via the + "threadlocal" mod if used + + .. change:: + :tags: + :tickets: + + mods now called in via "import ". extensions favored over + mods as mods are globally-monkeypatching + + .. change:: + :tags: + :tickets: 154 + + fix to add_property so that it propagates properties to inheriting + mappers + + .. change:: + :tags: + :tickets: + + 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 + + .. change:: + :tags: + :tickets: 31 + + "table exists" function has been implemented + + .. change:: + :tags: + :tickets: 98 + + "create_all/drop_all" added to MetaData object + + .. change:: + :tags: + :tickets: + + improvements and fixes to topological sort algorithm, as well as more + unit tests + + .. change:: + :tags: + :tickets: + + 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 + + .. change:: + :tags: + :tickets: + + many more fixes, refactorings. + + .. change:: + :tags: + :tickets: + + migration guide is available on the Wiki at + http://www.sqlalchemy.org/trac/wiki/02Migration diff --git a/doc/build/changelog/changelog_03.rst b/doc/build/changelog/changelog_03.rst new file mode 100644 index 0000000000..c1944c705b --- /dev/null +++ b/doc/build/changelog/changelog_03.rst @@ -0,0 +1,2928 @@ + +============== +0.3 Changelog +============== + + +.. changelog:: + :version: 0.3.11 + :released: Sun Oct 14 2007 + + .. change:: + :tags: sql + :tickets: + + tweak DISTINCT precedence for clauses like + `func.count(t.c.col.distinct())` + + .. change:: + :tags: sql + :tickets: 719 + + Fixed detection of internal '$' characters in :bind$params + + .. change:: + :tags: sql + :tickets: 768 + + dont assume join criterion consists only of column objects + + .. change:: + :tags: sql + :tickets: 764 + + 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") + + .. change:: + :tags: orm + :tickets: 687 + + 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. + + .. change:: + :tags: orm + :tickets: + + fixed small exception throw bug in Session.merge() + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: 769 + + fixed bugs in determining proper sync clauses from custom inherit + conditions + + .. change:: + :tags: orm + :tickets: 813 + + backref remove object operation doesn't fail if the other-side + collection doesn't contain the item, supports noload collections + + .. change:: + :tags: engine + :tickets: + + fixed another occasional race condition which could occur + when using pool with threadlocal setting + + .. change:: + :tags: mysql + :tickets: + + fixed specification of YEAR columns when generating schema + + .. change:: + :tags: mssql + :tickets: 679 + + added support for TIME columns (simulated using DATETIME) + + .. change:: + :tags: mssql + :tickets: 721 + + added support for BIGINT, MONEY, SMALLMONEY, UNIQUEIDENTIFIER and + SQL_VARIANT + + .. change:: + :tags: mssql + :tickets: 684 + + index names are now quoted when dropping from reflected tables + + .. change:: + :tags: mssql + :tickets: + + can now specify a DSN for PyODBC, using a URI like mssql:///?dsn=bob + + .. change:: + :tags: postgres + :tickets: + + 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. + + .. change:: + :tags: sqlite + :tickets: + + passthrough for stringified dates + + .. change:: + :tags: firebird + :tickets: + + supports_sane_rowcount() set to False due to ticket #370 (right way). + + .. change:: + :tags: firebird + :tickets: + + fixed reflection of Column's nullable property. + + .. change:: + :tags: oracle + :tickets: 622, 751 + + removed LONG_STRING, LONG_BINARY from "binary" types, so type objects + don't try to read their values as LOB. + +.. changelog:: + :version: 0.3.10 + :released: Fri Jul 20 2007 + + .. change:: + :tags: general + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + got connection-bound metadata to work with implicit execution + + .. change:: + :tags: sql + :tickets: 667 + + foreign key specs can have any chararcter in their identifiers + + .. change:: + :tags: sql + :tickets: 664 + + added commutativity-awareness to binary clause comparisons to + each other, improves ORM lazy load optimization + + .. change:: + :tags: orm + :tickets: + + cleanup to connection-bound sessions, SessionTransaction + + .. change:: + :tags: postgres + :tickets: 571 + + fixed max identifier length (63) + +.. changelog:: + :version: 0.3.9 + :released: Sun Jul 15 2007 + + .. change:: + :tags: general + :tickets: 607 + + better error message for NoSuchColumnError + + .. change:: + :tags: general + :tickets: 428 + + finally figured out how to get setuptools version in, available + as sqlalchemy.__version__ + + .. change:: + :tags: general + :tickets: + + 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 = + + .. change:: + :tags: ext + :tickets: + + iteration over dict association proxies is now dict-like, not + InstrumentedList-like (e.g. over keys instead of values) + + .. change:: + :tags: ext + :tickets: 597 + + association proxies no longer bind tightly to source collections, and are constructed with a thunk instead + + .. change:: + :tags: ext + :tickets: + + added selectone_by() to assignmapper + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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" + + .. change:: + :tags: orm + :tickets: 613 + + added synchronization to the mapper() construction step, to avoid + thread collisions when pre-existing mappers are compiling in a + different thread + + .. change:: + :tags: orm + :tickets: + + 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). + + .. change:: + :tags: orm + :tickets: 598 + + synonym() properties are fully supported by all Query joining/ + with_parent operations + + .. change:: + :tags: orm + :tickets: + + fixed very stupid bug when deleting items with many-to-many + uselist=False relations + + .. change:: + :tags: orm + :tickets: + + 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). + + .. change:: + :tags: orm + :tickets: + + small fix to eager loading to better work with eager loads + to polymorphic mappers that are using a straight "outerjoin" + clause + + .. change:: + :tags: sql + :tickets: + + 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') + + .. change:: + :tags: sql + :tickets: + + MetaData can now be constructed with an engine or url as the first + argument, just like BoundMetaData + + .. change:: + :tags: sql + :tickets: + + BoundMetaData is now deprecated, and MetaData is a direct substitute. + + .. change:: + :tags: sql + :tickets: + + DynamicMetaData has been renamed to ThreadLocalMetaData. the + DynamicMetaData name is deprecated and is an alias for ThreadLocalMetaData + or a regular MetaData if threadlocal=False + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: 185 + + 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. + + .. change:: + :tags: sql + :tickets: + + added 'bind' argument to Sequence.create()/drop(), ColumnDefault.execute() + + .. change:: + :tags: sql + :tickets: 650 + + columns can be overridden in a reflected table with a "key" + attribute different than the column's name, including for primary key + columns + + .. change:: + :tags: sql + :tickets: 657 + + fixed "ambiguous column" result detection, when dupe col names exist + in a result + + .. change:: + :tags: sql + :tickets: + + 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 + + .. change:: + :tags: sql + :tickets: 619 + + 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. + + .. change:: + :tags: sql + :tickets: + + added a mutex to QueuePool's "overflow" calculation to prevent a race + condition that can bypass max_overflow + + .. change:: + :tags: sql + :tickets: 623 + + 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 + + .. change:: + :tags: sql + :tickets: 620 + + fixed precedence of operators so that parenthesis are correctly applied + + .. change:: + :tags: sql + :tickets: 545 + + 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 + + .. change:: + :tags: sql + :tickets: + + fixed "where"/"from" criterion of select() to accept a unicode string + in addition to regular string - both convert to text() + + .. change:: + :tags: sql + :tickets: 558 + + added standalone distinct() function in addition to column.distinct() + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: 589 + + long-identifier detection fixed to use > rather than >= for + max ident length + + .. change:: + :tags: sql + :tickets: 593 + + 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 + + .. change:: + :tags: sql + :tickets: 595 + + added Interval type to types.py + + .. change:: + :tags: mysql + :tickets: 625 + + fixed catching of some errors that imply a dropped connection + + .. change:: + :tags: mysql + :tickets: 624 + + fixed escaping of the modulo operator + + .. change:: + :tags: mysql + :tickets: 590 + + added 'fields' to reserved words + + .. change:: + :tags: mysql + :tickets: + + various reflection enhancement/fixes + + .. change:: + :tags: oracle + :tickets: 604 + + datetime fixes: got subsecond TIMESTAMP to work, + added OracleDate which supports types.Date with only year/month/day + + .. change:: + :tags: oracle + :tickets: + + 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). + + .. change:: + :tags: oracle + :tickets: 624 + + mod operator '%' produces MOD + + .. change:: + :tags: oracle + :tickets: 542 + + converts cx_oracle datetime objects to Python datetime.datetime when + Python 2.3 used + + .. change:: + :tags: oracle + :tickets: + + fixed unicode conversion in Oracle TEXT type + + .. change:: + :tags: postgres + :tickets: 624 + + fixed escaping of the modulo operator + + .. change:: + :tags: postgres + :tickets: 570 + + added support for reflection of domains + + .. change:: + :tags: postgres + :tickets: + + types which are missing during reflection resolve to Null type + instead of raising an error + + .. change:: + :tags: postgres + :tickets: + + the fix in "schema" above fixes reflection of foreign keys from an + alt-schema table to a public schema table + + .. change:: + :tags: sqlite + :tickets: + + rearranged dialect initialization so it has time to warn about pysqlite1 + being too old. + + .. change:: + :tags: sqlite + :tickets: + + sqlite better handles datetime/date/time objects mixed and matched + with various Date/Time/DateTime columns + + .. change:: + :tags: sqlite + :tickets: 603 + + string PK column inserts dont get overwritten with OID + + .. change:: + :tags: mssql + :tickets: 634 + + fix port option handling for pyodbc + + .. change:: + :tags: mssql + :tickets: + + now able to reflect start and increment values for identity columns + + .. change:: + :tags: mssql + :tickets: + + preliminary support for using scope_identity() with pyodbc + +.. changelog:: + :version: 0.3.8 + :released: Sat Jun 02 2007 + + .. change:: + :tags: engines + :tickets: + + 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. + + .. change:: + :tags: engines + :tickets: + + added invalidate() to Connection, immediately invalidates the + Connection and its underlying DBAPI connection. + + .. change:: + :tags: sql + :tickets: + + _Label class overrides compare_self to return its ultimate + object. meaning, if you say someexpr.label('foo') == 5, it + produces the correct "someexpr == 5". + + .. change:: + :tags: sql + :tickets: + + _Label propagates "_hide_froms()" so that scalar selects + behave more properly with regards to FROM clause #574 + + .. change:: + :tags: sql + :tickets: + + fix to long name generation when using oid_column as an order by + (oids used heavily in mapper queries) + + .. change:: + :tags: sql + :tickets: + + significant speed improvement to ResultProxy, pre-caches + TypeEngine dialect implementations and saves on function calls + per column + + .. change:: + :tags: sql + :tickets: + + 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) + + .. change:: + :tags: sql + :tickets: + + added 'modifier' keyword, works like func. except does not + add parenthesis. e.g. select([modifier.DISTINCT(...)]) etc. + + .. change:: + :tags: sql + :tickets: 578 + + removed "no group by's in a select thats part of a UNION" + restriction + + .. change:: + :tags: orm + :tickets: + + 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']). + + .. change:: + :tags: orm + :tickets: + + fixed bug in query.instances() that wouldnt handle more than + on additional mapper or one additional column. + + .. change:: + :tags: orm + :tickets: + + "delete-orphan" no longer implies "delete". ongoing effort to + separate the behavior of these two operations. + + .. change:: + :tags: orm + :tickets: + + many-to-many relationships properly set the type of bind params + for delete operations on the association table + + .. change:: + :tags: orm + :tickets: + + many-to-many relationships check that the number of rows deleted + from the association table by a delete operation matches the + expected results + + .. change:: + :tags: orm + :tickets: + + session.get() and session.load() propagate **kwargs through to + query + + .. change:: + :tags: orm + :tickets: 577 + + fix to polymorphic query which allows the original + polymorphic_union to be embedded into a correlated subquery + + .. change:: + :tags: orm + :tickets: + + fix to select_by(=) -style joins in + conjunction with many-to-many relationships, bug introduced in + r2556 + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + restored logging of "lazy loading clause" under + sa.orm.strategies logger, got removed in 0.3.7 + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: mysql + :tickets: + + Nearly all MySQL column types are now supported for declaration + and reflection. Added NCHAR, NVARCHAR, VARBINARY, TINYBLOB, + LONGBLOB, YEAR + + .. change:: + :tags: mysql + :tickets: + + The sqltypes.Binary passthrough now always builds a BLOB, + avoiding problems with very old database versions + + .. change:: + :tags: mysql + :tickets: + + support for column-level CHARACTER SET and COLLATE declarations, + as well as ASCII, UNICODE, NATIONAL and BINARY shorthand. + + .. change:: + :tags: firebird + :tickets: + + set max identifier length to 31 + + .. change:: + :tags: firebird + :tickets: + + supports_sane_rowcount() set to False due to ticket #370. + versioned_id_col feature wont work in FB. + + .. change:: + :tags: firebird + :tickets: + + some execution fixes + + .. change:: + :tags: firebird + :tickets: + + new association proxy implementation, implementing complete + proxies to list, dict and set-based relation collections + + .. change:: + :tags: firebird + :tickets: + + added orderinglist, a custom list class that synchronizes an + object attribute with that object's position in the list + + .. change:: + :tags: firebird + :tickets: + + small fix to SelectResultsExt to not bypass itself during + select(). + + .. change:: + :tags: firebird + :tickets: + + added filter(), filter_by() to assignmapper + +.. changelog:: + :version: 0.3.7 + :released: Sun Apr 29 2007 + + .. change:: + :tags: engines + :tickets: + + warnings module used for issuing warnings (instead of logging) + + .. change:: + :tags: engines + :tickets: 480 + + cleanup of DBAPI import strategies across all engines + + .. change:: + :tags: engines + :tickets: + + 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. + + .. change:: + :tags: engines + :tickets: 514 + + server side cursor support fully functional in postgres. + + .. change:: + :tags: engines + :tickets: + + 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 + + .. change:: + :tags: engines + :tickets: 521 + + 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 + + .. change:: + :tags: engines + :tickets: + + Engine contains a "url" attribute referencing the url.URL object + used by create_engine(). + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: 522 + + 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. + + .. change:: + :tags: sql + :tickets: + + ClauseElements can be used in in_() clauses now, such as bind + parameters, etc. #476 + + .. change:: + :tags: sql + :tickets: + + reverse operators implemented for `CompareMixin` elements, + allows expressions like "5 + somecolumn" etc. #474 + + .. change:: + :tags: sql + :tickets: + + 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(). + + .. change:: + :tags: sql + :tickets: 512 + + 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. + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: 513 + + 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) + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: 513 + + MS-SQL better detects when a query is a subquery and knows not to + generate ORDER BY phrases for those + + .. change:: + :tags: sql + :tickets: 505 + + fix for fetchmany() "size" argument being positional in most + dbapis + + .. change:: + :tags: sql + :tickets: + + sending None as an argument to func. will produce + an argument of NULL + + .. change:: + :tags: sql + :tickets: + + query strings in unicode URLs get keys encoded to ascii + for **kwargs compat + + .. change:: + :tags: sql + :tickets: 523 + + slight tweak to raw execute() change to also support tuples + for positional parameters, not just lists + + .. change:: + :tags: sql + :tickets: + + fix to case() construct to propagate the type of the first + WHEN condition as the return type of the case statement + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: 541 + + 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. + + .. change:: + :tags: orm + :tickets: 554 + + 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 + + .. change:: + :tags: orm + :tickets: + + added generative versions of aggregates, i.e. sum(), avg(), etc. + to query. used via query.apply_max(), apply_sum(), etc. + #552 + + .. change:: + :tags: orm + :tickets: + + fix to using distinct() or distinct=True in combination with + join() and similar + + .. change:: + :tags: orm + :tickets: + + corresponding to label/bindparam name generation, eager loaders + generate deterministic names for the aliases they create using + md5 hashes. + + .. change:: + :tags: orm + :tickets: + + 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) + + .. change:: + :tags: orm + :tickets: + + 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). + + .. change:: + :tags: orm + :tickets: 533 + + fix to many-to-many relationships targeting polymorphic mappers + + .. change:: + :tags: orm + :tickets: 543 + + making progress with session.merge() as well as combining its + usage with entity_name + + .. change:: + :tags: orm + :tickets: + + 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 + + .. change:: + :tags: informix + :tickets: + + informix support added ! courtesy James Zhang, who put a ton + of effort in. + + .. change:: + :tags: sqlite + :tickets: + + removed silly behavior where sqlite would reflect UNIQUE indexes + as part of the primary key (?!) + + .. change:: + :tags: oracle + :tickets: + + 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. + + .. change:: + :tags: mysql + :tickets: + + support for SSL arguments given as inline within URL query string, + prefixed with "ssl_", courtesy terjeros@gmail.com. + + .. change:: + :tags: , mysql + :tickets: + + 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) + + .. change:: + :tags: extensions + :tickets: + + big fix to AssociationProxy so that multiple AssociationProxy + objects can be associated with a single association collection. + + .. change:: + :tags: extensions + :tickets: + + assign_mapper names methods according to their keys (i.e. __name__) + #551 + + .. change:: + :tags: mssql + :tickets: + + pyodbc is now the preferred DB-API for MSSQL, and if no module is + specifically requested, will be loaded first on a module probe. + + .. change:: + :tags: mssql + :tickets: + + 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. + +.. changelog:: + :version: 0.3.6 + :released: Fri Mar 23 2007 + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + slightly better support for bind params as column clauses, either + via bindparam() or via literal(), i.e. select([literal('foo')]) + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + exists() becomes useable as a standalone selectable, not just in a + WHERE clause, i.e. exists([columns], criterion).select() + + .. change:: + :tags: sql + :tickets: + + correlated subqueries work inside of ORDER BY, GROUP BY + + .. change:: + :tags: sql + :tickets: + + fixed function execution with explicit connections, i.e. + conn.execute(func.dosomething()) + + .. change:: + :tags: sql + :tickets: + + 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") + + .. change:: + :tags: sql + :tickets: + + 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"). + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: 503 + + fixed use_alter flag on ForeignKeyConstraint + + .. change:: + :tags: sql + :tickets: 506 + + fixed usage of 2.4-only "reversed" in topological.py + + .. change:: + :tags: sql + :tickets: 501 + + 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). + + .. change:: + :tags: sql + :tickets: + + the "else_" parameter to the case statement now properly works when + set to zero. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + strings and columns can also be sent to the *args of instances() + where those exact result columns will be part of the result tuples. + + .. change:: + :tags: orm + :tickets: + + 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(). + + .. change:: + :tags: orm + :tickets: 495 + + 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. 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) + + .. change:: + :tags: orm + :tickets: + + 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 + + .. change:: + :tags: orm + :tickets: 249 + + many-to-many table will be properly handled even for operations that + occur on the "backref" side of the operation + + .. change:: + :tags: orm + :tickets: 492 + + added "refresh-expire" cascade. allows refresh() and + expire() calls to propagate along relationships. + + .. change:: + :tags: orm + :tickets: 493 + + more fixes to polymorphic relations, involving proper lazy-clause + generation on many-to-one relationships to polymorphic mappers. also fixes to detection of "direction", more specific + targeting of columns that belong to the polymorphic union vs. those + that dont. + + .. change:: + :tags: orm + :tickets: + + 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 + + .. change:: + :tags: orm + :tickets: + + 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 + + .. change:: + :tags: orm + :tickets: 500 + + 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") 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. + + .. change:: + :tags: extensions + :tickets: 472 + + options() method on SelectResults now implemented "generatively" + like the rest of the SelectResults methods. But + you're going to just use Query now anyway. + + .. change:: + :tags: extensions + :tickets: + + query() method is added by assignmapper. this helps with + navigating to all the new generative methods on Query. + + .. change:: + :tags: ms-sql + :tickets: + + removed seconds input on DATE column types (probably + should remove the time altogether) + + .. change:: + :tags: ms-sql + :tickets: + + null values in float fields no longer raise errors + + .. change:: + :tags: ms-sql + :tickets: + + LIMIT with OFFSET now raises an error (MS-SQL has no OFFSET support) + + .. change:: + :tags: ms-sql + :tickets: 509 + + 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. + + .. change:: + :tags: ms-sql + :tickets: + + ORDER BY clauses without a LIMIT are now stripped in subqueries, as + MS-SQL forbids this usage + + .. change:: + :tags: ms-sql + :tickets: 480 + + cleanup of module importing code; specifiable DB-API module; more + explicit ordering of module preferences. + + .. change:: + :tags: oracle + :tickets: + + 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). + + .. change:: + :tags: oracle + :tickets: + + also fixed CLOB read/write on a separate changeset. + + .. change:: + :tags: oracle + :tickets: + + auto_setinputsizes defaults to True for Oracle, fixed cases where + it improperly propagated bad types. + + .. change:: + :tags: mysql + :tickets: + + added a catchall **kwargs to MSString, to help reflection of + obscure types (like "varchar() binary" in MS 4.0) + + .. change:: + :tags: mysql + :tickets: + + added explicit MSTimeStamp type which takes effect when using + types.TIMESTAMP. + +.. changelog:: + :version: 0.3.5 + :released: Thu Feb 22 2007 + + .. change:: + :tags: sql + :tickets: + + 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 + + .. change:: + :tags: sql + :tickets: + + 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". + + .. change:: + :tags: sql + :tickets: + + 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() + + .. change:: + :tags: sql + :tickets: + + small fix to BoundMetaData to accept unicode or string URLs + + .. change:: + :tags: sql + :tickets: 466 + + fixed named PrimaryKeyConstraint generation courtesy + andrija at gmail + + .. change:: + :tags: sql + :tickets: 464 + + fixed generation of CHECK constraints on columns + + .. change:: + :tags: sql + :tickets: + + fixes to tometadata() operation to propagate Constraints at column and + table level + + .. change:: + :tags: oracle + :tickets: 436 + + 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. + + .. change:: + :tags: oracle + :tickets: + + sequences on a non-pk column will properly fire off on INSERT + + .. change:: + :tags: oracle + :tickets: 435 + + added PrefetchingResultProxy support to pre-fetch LOB columns when they + are known to be present, fixes + + .. change:: + :tags: oracle + :tickets: 379 + + implemented reflection of tables based on synonyms, including across + dblinks + + .. change:: + :tags: oracle + :tickets: 363 + + issues a log warning when a related table cant be reflected due to + certain permission errors + + .. change:: + :tags: mysql + :tickets: + + fix to reflection on older DB's that might return array() type for + "show variables like" statements + + .. change:: + :tags: postgres + :tickets: 442 + + better reflection of sequences for alternate-schema Tables + + .. change:: + :tags: postgres + :tickets: + + sequences on a non-pk column will properly fire off on INSERT + + .. change:: + :tags: postgres + :tickets: 460, 444 + + added PGInterval type, PGInet type + + .. change:: + :tags: mssql + :tickets: 419 + + preliminary support for pyodbc (Yay!) + + .. change:: + :tags: mssql + :tickets: 298 + + better support for NVARCHAR types added + + .. change:: + :tags: mssql + :tickets: + + fix for commit logic on pymssql + + .. change:: + :tags: mssql + :tickets: 456 + + fix for query.get() with schema + + .. change:: + :tags: mssql + :tickets: 473 + + fix for non-integer relationships + + .. change:: + :tags: mssql + :tickets: 419 + + DB-API module now selectable at run-time + + .. change:: + :tags: tickets:422, 481, 415, mssql + :tickets: + + now passes many more unit tests + + .. change:: + :tags: mssql + :tickets: 479 + + better unittest compatibility with ANSI functions + + .. change:: + :tags: mssql + :tickets: 415 + + improved support for implicit sequence PK columns with auto-insert + + .. change:: + :tags: mssql + :tickets: 371 + + fix for blank password in adodbapi + + .. change:: + :tags: mssql + :tickets: 481 + + fixes to get unit tests working with pyodbc + + .. change:: + :tags: mssql + :tickets: + + fix to auto_identity_insert on db-url query + + .. change:: + :tags: mssql + :tickets: + + added query_timeout to db-url query parms. currently works only for + pymssql + + .. change:: + :tags: mssql + :tickets: + + tested with pymssql 0.8.0 (which is now LGPL) + + .. change:: + :tags: orm, bugs + :tickets: 441, 448, 439 + + 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,,. + + .. change:: + :tags: orm, bugs + :tickets: + + 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). + + .. change:: + :tags: orm, bugs + :tickets: 454 + + extension() query option propagates to Mapper._instance() method so that + all loading-related methods get called + + .. change:: + :tags: orm, bugs + :tickets: + + eager relation to an inheriting mapper wont fail if no rows returned for + the relationship. + + .. change:: + :tags: orm, bugs + :tickets: 486 + + eager relation loading bug fixed for eager relation on multiple + descendant classes + + .. change:: + :tags: orm, bugs + :tickets: 423 + + fix for very large topological sorts, courtesy ants.aasma at gmail + + .. change:: + :tags: orm, bugs + :tickets: + + eager loading is slightly more strict about detecting "self-referential" + relationships, specifically between polymorphic mappers. this results in + an "eager degrade" to lazy loading. + + .. change:: + :tags: orm, bugs + :tickets: 449 + + improved support for complex queries embedded into "where" criterion for + query.select() + + .. change:: + :tags: orm, bugs + :tickets: 485 + + mapper options like eagerload(), lazyload(), deferred(), will work for + "synonym()" relationships + + .. change:: + :tags: orm, bugs + :tickets: 445 + + fixed bug where cascade operations incorrectly included deleted + collection items in the cascade + + .. change:: + :tags: orm, bugs + :tickets: 478 + + fixed relationship deletion error when one-to-many child item is moved + to a new parent in a single unit of work + + .. change:: + :tags: orm, bugs + :tickets: + + 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 + + .. change:: + :tags: orm, bugs + :tickets: + + fix to deferred so that load operation doesnt mistakenly occur when only + PK col attributes are set + + .. change:: + :tags: orm, enhancements + :tickets: 385 + + implemented foreign_keys argument to mapper. use in + conjunction with primaryjoin/secondaryjoin arguments to specify/override + foreign keys defined on the Table instance. + + .. change:: + :tags: orm, enhancements + :tickets: + + contains_eager('foo') automatically implies eagerload('foo') + + .. change:: + :tags: orm, enhancements + :tickets: + + 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" + + .. change:: + :tags: orm, enhancements + :tickets: + + added "contains_alias()" option for result set mapping to an alias of + the mapped table + + .. change:: + :tags: orm, enhancements + :tickets: 468 + + added support for py2.5 "with" statement with SessionTransaction + + .. change:: + :tags: extensions + :tickets: + + added distinct() method to SelectResults. generally should only make a + difference when using count(). + + .. change:: + :tags: extensions + :tickets: 472 + + added options() method to SelectResults, equivalent to query.options() + + .. change:: + :tags: extensions + :tickets: 462 + + added optional __table_opts__ dictionary to ActiveMapper, will send kw + options to Table objects + + .. change:: + :tags: extensions + :tickets: 467 + + added selectfirst(), selectfirst_by() to assign_mapper + +.. changelog:: + :version: 0.3.4 + :released: Tue Jan 23 2007 + + .. change:: + :tags: general + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + added "fetchmany()" support to ResultProxy + + .. change:: + :tags: sql + :tickets: + + added support for column "key" attribute to be useable in + row[]/row. + + .. change:: + :tags: sql + :tickets: + + changed "BooleanExpression" to subclass from "BinaryExpression", so that + boolean expressions can also follow column-clause behaviors (i.e. label(), + etc). + + .. change:: + :tags: sql + :tickets: + + trailing underscores are trimmed from func. calls, such as func.if_() + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: 414 + + 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) + + .. change:: + :tags: sql + :tickets: + + 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 + + .. change:: + :tags: sql + :tickets: + + trying to redefine a reflected primary key column as non-primary key raises + an error + + .. change:: + :tags: sql + :tickets: + + 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) + + .. change:: + :tags: mssql + :tickets: + + added an NVarchar type (produces NVARCHAR), also MSUnicode which provides + Unicode-translation for the NVarchar regardless of dialect convert_unicode + setting. + + .. change:: + :tags: postgres + :tickets: 424 + + fix to the initial checkfirst for tables to take current schema into + account + + .. change:: + :tags: postgres + :tickets: + + 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. + + .. change:: + :tags: postgres + :tickets: + + added "BIGSERIAL" support for postgres table with + PGBigInteger/autoincrement + + .. change:: + :tags: postgres + :tickets: 402 + + fixes to postgres reflection to better handle when schema names are + present; thanks to jason (at) ncsmags.com + + .. change:: + :tags: mysql + :tickets: 420 + + 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 + + .. change:: + :tags: mysql + :tickets: 418 + + 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 + + .. change:: + :tags: firebird + :tickets: 408 + + order of constraint creation puts primary key first before all other + constraints; required for firebird, not a bad idea for others + + .. change:: + :tags: firebird + :tickets: 409 + + Firebird fix to autoload multifield foreign keys + + .. change:: + :tags: firebird + :tickets: 409 + + Firebird NUMERIC type properly handles a type without precision + + .. change:: + :tags: oracle + :tickets: + + *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. + + .. change:: + :tags: orm + :tickets: + + 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". + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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" + + .. change:: + :tags: orm + :tickets: + + 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). + + .. change:: + :tags: orm + :tickets: + + fix to "proxy=True" behavior on synonym() + + .. change:: + :tags: orm + :tickets: 427 + + fixed bug where delete-orphan basically didn't work with many-to-many + relationships, backref presence generally hid the symptom + + .. change:: + :tags: orm + :tickets: + + 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 + + .. change:: + :tags: orm + :tickets: + + basic idea of "session.merge()" actually implemented. needs more testing. + + .. change:: + :tags: orm + :tickets: + + added "compile_mappers()" function as a shortcut to compiling all mappers + + .. change:: + :tags: orm + :tickets: + + fix to MapperExtension create_instance so that entity_name properly + associated with new instance + + .. change:: + :tags: orm + :tickets: + + speed enhancements to ORM object instantiation, eager loading of rows + + .. change:: + :tags: orm + :tickets: 406 + + invalid options sent to 'cascade' string will raise an exception + + .. change:: + :tags: orm + :tickets: 407 + + fixed bug in mapper refresh/expire whereby eager loaders didnt properly + re-populate item lists + + .. change:: + :tags: orm + :tickets: 413 + + fix to post_update to ensure rows are updated even for non insert/delete + scenarios + + .. change:: + :tags: orm + :tickets: 412 + + added an error message if you actually try to modify primary key values on + an entity and then flush it + + .. change:: + :tags: extensions + :tickets: 426 + + added "validate=False" argument to assign_mapper, if True will ensure that + only mapped attributes are named + + .. change:: + :tags: extensions + :tickets: + + assign_mapper gets "options", "instances" functions added (i.e. + MyClass.instances()) + +.. changelog:: + :version: 0.3.3 + :released: Fri Dec 15 2006 + + .. change:: + :tags: + :tickets: + + string-based FROM clauses fixed, i.e. select(..., from_obj=["sometext"]) + + .. change:: + :tags: + :tickets: + + fixes to passive_deletes flag, lazy=None (noload) flag + + .. change:: + :tags: + :tickets: + + added example/docs for dealing with large collections + + .. change:: + :tags: + :tickets: + + added object_session() method to sqlalchemy namespace + + .. change:: + :tags: + :tickets: + + 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 + + .. change:: + :tags: + :tickets: 396 + + patch that makes MySQL rowcount work correctly! + + .. change:: + :tags: + :tickets: + + fix to MySQL catch of 2006/2014 errors to properly re-raise OperationalError + exception + +.. changelog:: + :version: 0.3.2 + :released: Sun Dec 10 2006 + + .. change:: + :tags: + :tickets: 387 + + major connection pool bug fixed. fixes MySQL out of sync + errors, will also prevent transactions getting rolled back + accidentally in all DBs + + .. change:: + :tags: + :tickets: + + major speed enhancements vs. 0.3.1, to bring speed + back to 0.2.8 levels + + .. change:: + :tags: + :tickets: + + made conditional dozens of debug log calls that were + time-intensive to generate log messages + + .. change:: + :tags: + :tickets: + + fixed bug in cascade rules whereby the entire object graph + could be unnecessarily cascaded on the save/update cascade + + .. change:: + :tags: + :tickets: + + various speedups in attributes module + + .. change:: + :tags: + :tickets: 388 + + 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 + + .. change:: + :tags: + :tickets: + + MySQL detects errors 2006 (server has gone away) and 2014 + (commands out of sync) and invalidates the connection on which it occured. + + .. change:: + :tags: + :tickets: 307 + + MySQL bool type fix: + + .. change:: + :tags: + :tickets: 382, 349 + + postgres reflection fixes: + + .. change:: + :tags: + :tickets: 247 + + added keywords for EXCEPT, INTERSECT, EXCEPT ALL, INTERSECT ALL + + .. change:: + :tags: + :tickets: 2110 + + assign_mapper in assignmapper extension returns the created mapper + + .. change:: + :tags: + :tickets: + + 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" + + .. change:: + :tags: + :tickets: + + added onupdate and ondelete keyword arguments to ForeignKey; propagate + to underlying ForeignKeyConstraint if present. (dont propagate in the + other direction, however) + + .. change:: + :tags: + :tickets: + + fix to session.update() to preserve "dirty" status of incoming object + + .. change:: + :tags: + :tickets: + + 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) + + .. change:: + :tags: + :tickets: + + improved support for disabling save-update cascade via cascade="none" etc. + + .. change:: + :tags: + :tickets: + + 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. + +.. changelog:: + :version: 0.3.1 + :released: Mon Nov 13 2006 + + .. change:: + :tags: engine/pool + :tickets: + + some new Pool utility classes, updated docs + + .. change:: + :tags: engine/pool + :tickets: + + "use_threadlocal" on Pool defaults to False (same as create_engine) + + .. change:: + :tags: engine/pool + :tickets: + + fixed direct execution of Compiled objects + + .. change:: + :tags: engine/pool + :tickets: + + 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. + + .. change:: + :tags: databases/types + :tickets: + + MySQL catches exception on "describe" and reports as NoSuchTableError + + .. change:: + :tags: databases/types + :tickets: + + further fixes to sqlite booleans, weren't working as defaults + + .. change:: + :tags: databases/types + :tickets: + + fix to postgres sequence quoting when using schemas + + .. change:: + :tags: orm + :tickets: + + 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(). + + .. change:: + :tags: orm + :tickets: + + adjustments to reworked eager query generation to not fail on circular + eager-loaded relationships (like backrefs) + + .. change:: + :tags: orm + :tickets: + + fixed bug where eagerload() (nor lazyload()) option didn't properly + instruct the Query whether or not to use "nesting" when producing a + LIMIT query. + + .. change:: + :tags: orm + :tickets: 360 + + 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. + + .. change:: + :tags: orm + :tickets: 325 + + implemented from_obj argument for query.count, improves count function + on selectresults + + .. change:: + :tags: orm + :tickets: + + 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) + + .. change:: + :tags: orm + :tickets: + + new extension sqlalchemy.ext.associationproxy, provides transparent + "association object" mappings. new example + examples/association/proxied_association.py illustrates. + + .. change:: + :tags: orm + :tickets: + + improvement to single table inheritance to load full hierarchies beneath + the target class + + .. change:: + :tags: orm + :tickets: 362 + + fix to subtle condition in topological sort where a node could appear twice, + for + + .. change:: + :tags: orm + :tickets: 365 + + additional rework to topological sort, refactoring, for + + .. change:: + :tags: orm + :tickets: + + "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 + +.. changelog:: + :version: 0.3.0 + :released: Sun Oct 22 2006 + + .. change:: + :tags: general + :tickets: + + 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. + + .. change:: + :tags: general + :tickets: + + the documentation-generation system has been overhauled to be + much simpler in design and more integrated with Markdown + + .. change:: + :tags: sqlite + :tickets: + + sqlite boolean datatype converts False/True to 0/1 by default + + .. change:: + :tags: sqlite + :tickets: 335 + + fixes to Date/Time (SLDate/SLTime) types; works as good as postgres + now + + .. change:: + :tags: ms-sql + :tickets: + + fixes bug 261 (table reflection broken for MS-SQL case-sensitive + databases) + + .. change:: + :tags: ms-sql + :tickets: + + can now specify port for pymssql + + .. change:: + :tags: ms-sql + :tickets: + + introduces new "auto_identity_insert" option for auto-switching + between "SET IDENTITY_INSERT" mode when values specified for IDENTITY columns + + .. change:: + :tags: ms-sql + :tickets: + + now supports multi-column foreign keys + + .. change:: + :tags: ms-sql + :tickets: + + fix to reflecting date/datetime columns + + .. change:: + :tags: ms-sql + :tickets: + + NCHAR and NVARCHAR type support added + + .. change:: + :tags: oracle + :tickets: + + 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. + + .. change:: + :tags: firebird + :tickets: + + aliases do not use "AS" + + .. change:: + :tags: firebird + :tickets: + + correctly raises NoSuchTableError when reflecting non-existent table + + .. change:: + :tags: schema + :tickets: + + 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 + + .. change:: + :tags: schema + :tickets: + + 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 + + .. change:: + :tags: schema + :tickets: + + ForeignKey(Constraint) supports "use_alter=True", to create/drop a foreign key + via ALTER. this allows circular foreign key relationships to be set up. + + .. change:: + :tags: schema + :tickets: + + 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. + + .. change:: + :tags: schema + :tickets: + + 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. + + .. change:: + :tags: schema + :tickets: + + added UniqueConstraint (goes at Table level), CheckConstraint + (goes at Table or Column level). + + .. change:: + :tags: schema + :tickets: + + 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. + + .. change:: + :tags: schema + :tickets: + + added autoincrement=True to Column; will disable schema generation + of SERIAL/AUTO_INCREMENT/identity seq for postgres/mysql/mssql if + explicitly set to False + + .. change:: + :tags: schema + :tickets: + + TypeEngine objects now have methods to deal with copying and comparing + values of their specific type. Currently used by the ORM, see below. + + .. change:: + :tags: schema + :tickets: + + 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 + + .. change:: + :tags: schema + :tickets: + + 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. + + .. change:: + :tags: connections/pooling/execution + :tickets: + + 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 + + .. change:: + :tags: connections/pooling/execution + :tickets: + + fixed bug where Connection wouldnt lose its Transaction + after commit/rollback + + .. change:: + :tags: connections/pooling/execution + :tickets: + + added scalar() method to ComposedSQLEngine, ResultProxy + + .. change:: + :tags: connections/pooling/execution + :tickets: + + 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). + + .. change:: + :tags: connections/pooling/execution + :tickets: + + ResultProxy.fetchall() internally uses DBAPI fetchall() for better efficiency, + added to mapper iteration as well (courtesy Michael Twomey) + + .. change:: + :tags: construction, sql + :tickets: 292 + + changed "for_update" parameter to accept False/True/"nowait" + and "read", the latter two of which are interpreted only by + Oracle and Mysql + + .. change:: + :tags: construction, sql + :tickets: + + added extract() function to sql dialect + (SELECT extract(field FROM expr)) + + .. change:: + :tags: construction, sql + :tickets: + + BooleanExpression includes new "negate" argument to specify + the appropriate negation operator if one is available. + + .. change:: + :tags: construction, sql + :tickets: + + calling a negation on an "IN" or "IS" clause will result in + "NOT IN", "IS NOT" (as opposed to NOT (x IN y)). + + .. change:: + :tags: construction, sql + :tickets: 172 + + 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 + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + instances() method moved to Query now, backwards-compatible + version remains on Mapper. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + more rearrangements of unit-of-work commit scheme to better allow + dependencies within circular flushes to work properly...updated + task traversal/logging implementation + + .. change:: + :tags: orm + :tickets: 321 + + polymorphic mappers (i.e. using inheritance) now produces INSERT + statements in order of tables across all inherited classes + + .. change:: + :tags: orm + :tickets: + + 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 + + .. change:: + :tags: orm + :tickets: + + "association" mappings simplified to take advantage of + automatic "row switch" feature + + .. change:: + :tags: orm + :tickets: 212 + + "custom list classes" is now implemented via the "collection_class" + keyword argument to relation(). the old way still works but is + deprecated + + .. change:: + :tags: orm + :tickets: + + added "viewonly" flag to relation(), allows construction of + relations that have no effect on the flush() process. + + .. change:: + :tags: orm + :tickets: 292 + + 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. + + .. change:: + :tags: orm + :tickets: + + 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 + + .. change:: + :tags: orm + :tickets: 208 + + post_update behavior improved; does a better job at not + updating too many rows, updates only required columns + + .. change:: + :tags: orm + :tickets: 308 + + 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 + + .. change:: + :tags: orm + :tickets: + + fix to deferred group loading + + .. change:: + :tags: orm + :tickets: 346 + + session.flush() wont close a connection it opened + + .. change:: + :tags: orm + :tickets: + + 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 + + .. change:: + :tags: orm + :tickets: + + added "column_prefix=None" argument to mapper; prepends the + given string (typically '_') to column-based attributes automatically + set up from the mapper's Table + + .. change:: + :tags: orm + :tickets: 315 + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + removed "is_primary" flag from mapper. diff --git a/doc/build/changelog/changelog_04.rst b/doc/build/changelog/changelog_04.rst new file mode 100644 index 0000000000..37b424df7b --- /dev/null +++ b/doc/build/changelog/changelog_04.rst @@ -0,0 +1,4198 @@ + +============== +0.4 Changelog +============== + + +.. changelog:: + :version: 0.4.8 + :released: Sun Oct 12 2008 + + .. change:: + :tags: orm + :tickets: 1039 + + Fixed bug regarding inherit_condition passed + with "A=B" versus "B=A" leading to errors + + .. change:: + :tags: orm + :tickets: + + Changes made to new, dirty and deleted + collections in + SessionExtension.before_flush() will take + effect for that flush. + + .. change:: + :tags: orm + :tickets: + + Added label() method to InstrumentedAttribute + to establish forwards compatibility with 0.5. + + .. change:: + :tags: sql + :tickets: 1074 + + column.in_(someselect) can now be used as + a columns-clause expression without the subquery + bleeding into the FROM clause + + .. change:: + :tags: mysql + :tickets: 1146 + + Added MSMediumInteger type. + + .. change:: + :tags: sqlite + :tickets: 968 + + Supplied a custom strftime() function which + handles dates before 1900. + + .. change:: + :tags: sqlite + :tickets: + + String's (and Unicode's, UnicodeText's, etc.) + convert_unicode logic disabled in the sqlite dialect, + to adjust for pysqlite 2.5.0's new requirement that + only Python unicode objects are accepted; + http://itsystementwicklung.de/pipermail/list-pysqlite/2008-March/000018.html + + .. change:: + :tags: oracle + :tickets: 1155 + + has_sequence() now takes schema name into account + + .. change:: + :tags: oracle + :tickets: 1121 + + added BFILE to the list of reflected types + +.. changelog:: + :version: 0.4.7p1 + :released: Thu Jul 31 2008 + + .. change:: + :tags: orm + :tickets: + + Added "add()" and "add_all()" to scoped_session + methods. Workaround for 0.4.7: + + from sqlalchemy.orm.scoping import ScopedSession,\ + instrument + setattr( + ScopedSession, "add", instrument("add")) + setattr( + ScopedSession, "add_all", instrument("add_all")) + + .. change:: + :tags: orm + :tickets: + + Fixed non-2.3 compatible usage of set() and generator + expression within relation(). + +.. changelog:: + :version: 0.4.7 + :released: Sat Jul 26 2008 + + .. change:: + :tags: orm + :tickets: 1058 + + 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 + + .. change:: + :tags: orm + :tickets: + + fixed bug preventing merge() from functioning in + conjunction with a comparable_property() + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: 976 + + Added is_active flag to Sessions to detect when + a transaction is in progress. This + flag is always True with a "transactional" + (in 0.5 a non-"autocommit") Session. + + .. change:: + :tags: sql + :tickets: + + Fixed bug when calling select([literal('foo')]) + or select([bindparam('foo')]). + + .. change:: + :tags: schema + :tickets: 571 + + 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. + + .. change:: + :tags: schema + :tickets: 571, 820 + + 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. + + .. change:: + :tags: postgres + :tickets: + + Repaired server_side_cursors to properly detect + text() clauses. + + .. change:: + :tags: postgres + :tickets: 1092 + + Added PGCidr type. + + .. change:: + :tags: mysql + :tickets: + + Added 'CALL' to the list of SQL keywords which return + result rows. + + .. change:: + :tags: oracle + :tickets: + + 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. + + .. change:: + :tags: oracle + :tickets: 709 + + 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 + + .. change:: + :tags: oracle + :tickets: 1062 + + 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). + + .. change:: + :tags: oracle + :tickets: + + 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. + +.. changelog:: + :version: 0.4.6 + :released: Sat May 10 2008 + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + Also re-established viewonly relation() configurations + that join across multiple tables. + + .. change:: + :tags: orm + :tickets: 610 + + 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) + + .. change:: + :tags: orm + :tickets: 1036 + + repaired single table inheritance such that you + can single-table inherit from a joined-table inherting + mapper without issue. + + .. change:: + :tags: orm + :tickets: 1027 + + Fixed "concatenate tuple" bug which could occur with + Query.order_by() if clause adaption had taken place. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + Also re-established viewonly relation() configurations that + join across multiple tables. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: 1015 + + refined mapper._save_obj() which was unnecessarily calling + __ne__() on scalar values during flush + + .. change:: + :tags: orm + :tickets: 1019 + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + added an example dynamic_dict/dynamic_dict.py, illustrating + a simple way to place dictionary behavior on top of + a dynamic_loader. + + .. change:: + :tags: declarative, extension + :tickets: + + 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. + + .. change:: + :tags: declarative, extension + :tickets: + + fixed reentrant mapper compile hang when + a declared attribute is used within ForeignKey, + ie. ForeignKey(MyOtherClass.someattribute) + + .. change:: + :tags: sql + :tickets: + + Added COLLATE support via the .collate() + expression operator and collate(, ) sql + function. + + .. change:: + :tags: sql + :tickets: + + Fixed bug with union() when applied to non-Table connected + select statements + + .. change:: + :tags: sql + :tickets: 1014 + + improved behavior of text() expressions when used as + FROM clauses, such as select().select_from(text("sometext")) + + .. change:: + :tags: sql + :tickets: 1021 + + Column.copy() respects the value of "autoincrement", + fixes usage with Migrate + + .. change:: + :tags: engines + :tickets: + + Pool listeners can now be provided as a dictionary of + callables or a (possibly partial) duck-type of + PoolListener, your choice. + + .. change:: + :tags: engines + :tickets: + + 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). + + .. change:: + :tags: ext + :tickets: + + 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. + + .. change:: + :tags: mssql + :tickets: 1005 + + 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 + + .. change:: + :tags: mssql + :tickets: + + 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. + + .. change:: + :tags: firebird + :tickets: + + Handle the "SUBSTRING(:string FROM :start FOR :length)" + builtin. + +.. changelog:: + :version: 0.4.5 + :released: Fri Apr 04 2008 + + .. change:: + :tags: orm + :tickets: + + 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). + + .. change:: + :tags: orm + :tickets: + + Also fixed behavior in merge() whereby collection elements + present on the destination but not the merged collection + were not being removed from the destination. + + .. change:: + :tags: orm + :tickets: 995 + + Added a more aggressive check for "uncompiled mappers", + helps particularly with declarative layer + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + Added comparable_property(), adds query Comparator + behavior to regular, unmanaged Python properties + + .. change:: + :tags: orm, Company.employees.of_type(Engineer), 'machines' + :tickets: + + 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( + + )) + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + query.order_by() and query.group_by() will accept + multiple arguments using *args (like select() + already does). + + .. change:: + :tags: orm + :tickets: + + Added some convenience descriptors to Query: + query.statement returns the full SELECT construct, + query.whereclause returns just the WHERE part of the + SELECT construct. + + .. change:: + :tags: orm + :tickets: + + Fixed/covered case when using a False/0 value as a + polymorphic discriminator. + + .. change:: + :tags: orm + :tickets: + + Fixed bug which was preventing synonym() attributes from + being used with inheritance + + .. change:: + :tags: orm + :tickets: 996 + + Fixed SQL function truncation of trailing underscores + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + Session.execute can now find binds from metadata + + .. change:: + :tags: orm + :tickets: + + 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). + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: 895 + + 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 + + - 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. + + .. change:: + :tags: orm + :tickets: + + Fixed order_by calculation in Query to properly alias + mapper-config'ed order_by when using select_from() + + .. change:: + :tags: orm + :tickets: + + Refactored the diffing logic that kicks in when replacing + one collection with another into collections.bulk_replace, + useful to anyone building multi-level collections. + + .. change:: + :tags: orm + :tickets: + + Cascade traversal algorithm converted from recursive to + iterative to support deep object graphs. + + .. change:: + :tags: sql + :tickets: 999 + + 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 + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + '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. + + .. change:: + :tags: sql + :tickets: 791, 993 + + 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 ''". + + .. change:: + :tags: sql + :tickets: + + random() is now a generic sql function and will compile to + the database's random implementation, if any. + + .. change:: + :tags: sql + :tickets: + + update().values() and insert().values() take keyword + arguments. + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + 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(). + + .. change:: + :tags: oracle + :tickets: + + 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". + + .. change:: + :tags: oracle + :tickets: + + 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. + + .. change:: + :tags: declarative, extension + :tickets: + + 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)) + + .. change:: + :tags: declarative, extension + :tickets: + + The "deferred" function is usable with "declarative". + Simplest usage is to declare deferred and Column together, + e.g.: data = deferred(Column(Text)) + + .. change:: + :tags: declarative, extension + :tickets: + + Declarative also gained @synonym_for(...) and + @comparable_using(...), front-ends for synonym and + comparable_property. + + .. change:: + :tags: declarative, extension + :tickets: 995 + + Improvements to mapper compilation when using declarative; + already-compiled mappers will still trigger compiles of + other uncompiled mappers when used + + .. change:: + :tags: declarative, extension + :tickets: + + Declarative will complete setup for Columns lacking names, + allows a more DRY syntax. + + class Foo(Base): + __tablename__ = 'foos' + id = Column(Integer, primary_key=True) + + .. change:: + :tags: declarative, extension + :tickets: + + inheritance in declarative can be disabled when sending + "inherits=None" to __mapper_args__. + + .. change:: + :tags: declarative, extension + :tickets: + + 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. + + .. change:: + :tags: postgres + :tickets: 1001 + + 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 + + .. change:: + :tags: oracle + :tickets: + + 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". + + .. change:: + :tags: oracle + :tickets: + + 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. + + .. change:: + :tags: mssql + :tickets: 979 + + Reflected tables will now automatically load other tables + which are referenced by Foreign keys in the auto-loaded + table,. + + .. change:: + :tags: mssql + :tickets: 916 + + Added executemany check to skip identity fetch,. + + .. change:: + :tags: mssql + :tickets: 884 + + Added stubs for small date type. + + .. change:: + :tags: mssql + :tickets: + + Added a new 'driver' keyword parameter for the pyodbc dialect. + Will substitute into the ODBC connection string if given, + defaults to 'SQL Server'. + + .. change:: + :tags: mssql + :tickets: + + Added a new 'max_identifier_length' keyword parameter for + the pyodbc dialect. + + .. change:: + :tags: mssql + :tickets: + + Improvements to pyodbc + Unix. If you couldn't get that + combination to work before, please try again. + + .. change:: + :tags: mysql + :tickets: + + The connection.info keys the dialect uses to cache server + settings have changed and are now namespaced. + +.. changelog:: + :version: 0.4.4 + :released: Wed Mar 12 2008 + + .. change:: + :tags: sql + :tickets: 975 + + Can again create aliases of selects against textual FROM + clauses. + + .. change:: + :tags: sql + :tickets: + + The value of a bindparam() can be a callable, in which + case it's evaluated at statement execution time to get the + value. + + .. change:: + :tags: sql + :tickets: 978 + + 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) + + .. change:: + :tags: sql + :tickets: 936 + + Implemented two-phase API for "threadlocal" engine, via + engine.begin_twophase(), engine.prepare() + + .. change:: + :tags: sql + :tickets: 986 + + Fixed bug which was preventing UNIONS from being + cloneable. + + .. change:: + :tags: sql + :tickets: + + Added "bind" keyword argument to insert(), update(), + delete() and DDL(). The .bind property is now assignable + on those statements as well as on select(). + + .. change:: + :tags: sql + :tickets: + + Insert statements can now be compiled with extra "prefix" + words between INSERT and INTO, for vendor extensions like + MySQL's INSERT IGNORE INTO table. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: 985 + + Repaired behavior of == and != operators at the relation() + level when compared against NULL for one-to-one relations + + .. change:: + :tags: orm + :tickets: + + Fixed bug whereby session.expire() attributes were not + loading on an polymorphically-mapped instance mapped by a + select_table mapper. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + session.refresh() and session.expire() raise an error when + called on instances which are not persistent within the + session + + .. change:: + :tags: orm + :tickets: + + Fixed potential generative bug when the same Query was + used to generate multiple Query objects using join(). + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + Deprecated Query methods apply_sum(), apply_max(), + apply_min(), apply_avg(). Better methodologies are + coming.... + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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') + + .. change:: + :tags: orm + :tickets: + + Preventive code against a potential lost-reference bug in + flush(). + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + Synonyms riding on top of existing descriptors are now + full proxies to those descriptors. + + .. change:: + :tags: dialects + :tickets: + + Invalid SQLite connection URLs now raise an error. + + .. change:: + :tags: dialects + :tickets: 981 + + postgres TIMESTAMP renders correctly + + .. change:: + :tags: dialects + :tickets: + + 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. + + .. change:: + :tags: extensions + :tickets: + + 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. + +.. changelog:: + :version: 0.4.3 + :released: Thu Feb 14 2008 + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + Added a callable-based DDL events interface, adds hooks + before and after Tables and MetaData create and drop. + + .. change:: + :tags: sql + :tickets: + + 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(). + + .. change:: + :tags: sql + :tickets: 727 + + Added "ilike()" operator to column operations. Compiles to + ILIKE on postgres, lower(x) LIKE lower(y) on all + others. + + .. change:: + :tags: sql + :tickets: 943 + + Added "now()" as a generic function; on SQLite, Oracle + and MSSQL compiles as "CURRENT_TIMESTAMP"; "now()" on + all others. + + .. change:: + :tags: sql + :tickets: 962 + + 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 + + .. change:: + :tags: sql + :tickets: 962 + + cast() accepts text('something') and other non-literal + operands properly + + .. change:: + :tags: sql + :tickets: + + fixed bug in result proxy where anonymously generated + column labels would not be accessible using their straight + string name + + .. change:: + :tags: sql + :tickets: + + Deferrable constraints can now be defined. + + .. change:: + :tags: sql + :tickets: 915 + + 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. + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + The anonymous 'label' generated for otherwise unlabeled + functions and expressions now propagates outwards at compile + time for expressions like select([select([func.foo()])]). + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + 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.) + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: 961 + + Fixed merge() collection-doubling bug when merging transient + entities with backref'ed collections. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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() + + .. change:: + :tags: orm + :tickets: + + The proper error message is raised when trying to access + expired instance attributes with no session present + + .. change:: + :tags: orm + :tickets: + + dynamic_loader() / lazy="dynamic" now accepts and uses + the order_by parameter in the same way in which it works + with relation(). + + .. change:: + :tags: orm + :tickets: + + Added expire_all() method to Session. Calls expire() for + all persistent instances. This is handy in conjunction + with... + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: 938 + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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]) + + .. change:: + :tags: orm, ('employees', people.join(engineer)), Engineer.name + :tickets: + + 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( + + ) + + .. change:: + :tags: orm + :tickets: + + General improvements to the behavior of join() in + conjunction with polymorphic mappers, i.e. joining from/to + polymorphic mappers and properly applying aliases. + + .. change:: + :tags: orm + :tickets: 933 + + 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. + + .. change:: + :tags: orm + :tickets: 946 + + 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". + + .. change:: + :tags: orm + :tickets: + + 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 + + .. change:: + :tags: orm + :tickets: + + Fixed bug in polymorphic inheritance which made it difficult + to set a working "order_by" on a polymorphic mapper. + + .. change:: + :tags: orm + :tickets: + + Fixed a rather expensive call in Query that was slowing down + polymorphic queries. + + .. change:: + :tags: orm + :tickets: 954 + + "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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: 964, 940 + + Miscellaneous tickets: + + .. change:: + :tags: general + :tickets: + + 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. + + .. change:: + :tags: general + :tickets: + + Warnings are now issued as type exceptions.SAWarning. + + .. change:: + :tags: dialects + :tickets: + + 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. + + .. change:: + :tags: dialects + :tickets: + + table_names on SQLite now picks up temporary tables as well. + + .. change:: + :tags: dialects + :tickets: + + 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. + + .. change:: + :tags: dialects + :tickets: + + Fixed reflection of TIME columns on SQLite. + + .. change:: + :tags: dialects + :tickets: 580 + + Finally added PGMacAddr type to postgres + + .. change:: + :tags: dialects + :tickets: + + Reflect the sequence associated to a PK field (typically + with a BEFORE INSERT trigger) under Firebird + + .. change:: + :tags: dialects + :tickets: 941 + + 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 + + .. change:: + :tags: dialects + :tickets: + + MSSQL now includes EXEC in the _is_select regexp, which + should allow row-returning stored procedures to be used. + + .. change:: + :tags: dialects + :tickets: + + 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. + + .. change:: + :tags: ext + :tickets: + + Changed ext.activemapper to use a non-transactional session + for the objectstore. + + .. change:: + :tags: ext + :tickets: + + Fixed output order of "['a'] + obj.proxied" binary operation + on association-proxied lists. + +.. changelog:: + :version: 0.4.2p3 + :released: Wed Jan 09 2008 + + .. change:: + :tags: general + :tickets: + + sub version numbering scheme changed to suite + setuptools version number rules; easy_install -u + should now get this version over 0.4.2. + + .. change:: + :tags: sql + :tickets: 912 + + 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 + + .. change:: + :tags: sql + :tickets: + + new UnicodeText type is added, to specify an + encoded, unlengthed Text type + + .. change:: + :tags: sql + :tickets: + + fixed bug in union() so that select() statements + which don't derive from FromClause objects can be + unioned + + .. change:: + :tags: orm + :tickets: + + fixed bug with session.dirty when using "mutable + scalars" (such as PickleTypes) + + .. change:: + :tags: orm + :tickets: + + added a more descriptive error message when flushing + on a relation() that has non-locally-mapped columns + in its primary or secondary join condition + + .. change:: + :tags: dialects + :tickets: + + Fixed reflection of mysql empty string column + defaults. + + .. change:: + :tags: sql + :tickets: 912 + + 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) + + .. change:: + :tags: sql + :tickets: 924 + + generative select.order_by(None) / group_by(None) + was not managing to reset order by/group by + criterion, fixed + + .. change:: + :tags: orm + :tickets: + + suppressing *all* errors in + InstanceState.__cleanup() now. + + .. change:: + :tags: orm + :tickets: 922 + + fixed an attribute history bug whereby assigning a + new collection to a collection-based attribute which + already had pending changes would generate incorrect + history + + .. change:: + :tags: orm + :tickets: 925 + + fixed delete-orphan cascade bug whereby setting the + same object twice to a scalar attribute could log it + as an orphan + + .. change:: + :tags: orm + :tickets: + + Fixed cascades on a += assignment to a list-based + relation. + + .. change:: + :tags: orm + :tickets: 919 + + 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) + + .. change:: + :tags: orm + :tickets: + + fixed bug which could occur with polymorphic "union" + mapper which falls back to "deferred" loading of + inheriting tables + + .. change:: + :tags: orm + :tickets: + + 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). + + .. change:: + :tags: ext + :tickets: + + '+', '*', '+=' and '*=' support for association + proxied lists. + + .. change:: + :tags: dialects + :tickets: 923 + + 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. + + .. change:: + :tags: orm + :tickets: + + 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 + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: 920 + + Fixed in-place set mutation operators for set collections and association + proxied sets. + + .. change:: + :tags: dialects + :tickets: 913 + + Fixed the missing call to subtype result processor for the PGArray + type. + +.. changelog:: + :version: 0.4.2 + :released: Wed Jan 02 2008 + + .. change:: + :tags: sql + :tickets: 615 + + 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 + + .. change:: + :tags: sql + :tickets: + + 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(). + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + select().as_scalar() will raise an exception if the select does not have + exactly one expression in its columns clause. + + .. change:: + :tags: sql + :tickets: + + bindparam() objects themselves can be used as keys for execute(), i.e. + statement.execute({bind1:'foo', bind2:'bar'}) + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + selectables (and others) will issue a warning when two columns in + their exported columns collection conflict based on name. + + .. change:: + :tags: sql + :tickets: 890 + + tables with schemas can still be used in sqlite, firebird, + schema name just gets dropped + + .. change:: + :tags: sql + :tickets: + + 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" + + .. change:: + :tags: sql + :tickets: + + column labels in the form "tablename.columname", i.e. with a dot, are now + supported. + + .. change:: + :tags: sql + :tickets: + + from_obj keyword argument to select() can be a scalar or a list. + + .. change:: + :tags: orm + :tickets: 871 + + 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. + + .. change:: + :tags: orm + :tickets: + + 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". + + .. change:: + :tags: orm + :tickets: 490 + + 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. + + .. change:: + :tags: orm + :tickets: 907 + + 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() + + .. change:: + :tags: orm + :tickets: + + columns which are missing from a Query's select statement + now get automatically deferred during load. + + .. change:: + :tags: orm + :tickets: 908 + + 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 + + .. change:: + :tags: orm + :tickets: 899 + + fixed Query bug when filter_by() compares a relation against None + + .. change:: + :tags: orm + :tickets: + + improved support for pickling of mapped entities. Per-instance + lazy/deferred/expired callables are now serializable so that + they serialize and deserialize with _state. + + .. change:: + :tags: orm + :tickets: 801 + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: attrname, orm + :tickets: + + 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,). + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + query.order_by() takes into account aliased joins, i.e. + query.join('orders', aliased=True).order_by(Order.id) + + .. change:: + :tags: orm + :tickets: + + 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(). + + .. change:: + :tags: orm + :tickets: + + eagerloading will work with mappers added via add_entity(). + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + also with dynamic, implemented correct count() behavior as well + as other helper methods. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: 893 + + 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. + + .. change:: + :tags: orm + :tickets: 883 + + 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. + + .. change:: + :tags: orm + :tickets: + + 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(). + + .. change:: + :tags: orm + :tickets: + + fixed backref bug where you could not del instance.attr if attr + was None + + .. change:: + :tags: orm + :tickets: + + 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 + + .. change:: + :tags: orm + :tickets: + + Assigning an incompatible collection type to a relation attribute now + raises TypeError instead of sqlalchemy's ArgumentError. + + .. change:: + :tags: orm + :tickets: 886 + + 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. + + .. change:: + :tags: orm, newval1, newval2 + :tickets: + + Custom collections can now specify a @converter method to translate + objects used in "bulk" assignment into a stream of values, as in:: + + obj.col = + # 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. + + .. change:: + :tags: orm + :tickets: 872 + + fixed endless loop issue when using lazy="dynamic" on both + sides of a bi-directional relationship + + .. change:: + :tags: orm + :tickets: 904 + + more fixes to the LIMIT/OFFSET aliasing applied with Query + eagerloads, + in this case when mapped against a select statement + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + fixed bug which could arise when using session.begin_nested() in conjunction + with more than one level deep of enclosing session.begin() statements + + .. change:: + :tags: orm + :tickets: 914 + + fixed session.refresh() with instance that has custom entity_name + + .. change:: + :tags: dialects + :tickets: + + sqlite SLDate type will not erroneously render "microseconds" portion + of a datetime or time object. + + .. change:: + :tags: dialects + :tickets: 902 + + 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 + + .. change:: + :tags: dialects + :tickets: 824, 839, 842, 901 + + MSSQL + - PyODBC no longer has a global "set nocount on". + - Fix non-identity integer PKs on autload + - Better support for convert_unicode + - Less strict date conversion for pyodbc/adodbapi + - Schema-qualified tables / autoload + + .. change:: + :tags: firebird, backend + :tickets: 410 + + does properly reflect domains (partially fixing) and + PassiveDefaults + + .. change:: + :tags: 3562, firebird, backend + :tickets: + + reverted to use default poolclass (was set to SingletonThreadPool in + 0.4.0 for test purposes) + + .. change:: + :tags: firebird, backend + :tickets: + + map func.length() to 'char_length' (easily overridable with the UDF + 'strlen' on old versions of Firebird) + +.. changelog:: + :version: 0.4.1 + :released: Sun Nov 18 2007 + + .. change:: + :tags: sql + :tickets: + + the "shortname" keyword parameter on bindparam() has been + deprecated. + + .. change:: + :tags: sql + :tickets: + + Added contains operator (generates a "LIKE %%" clause). + + .. change:: + :tags: sql + :tickets: + + 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). + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: 819 + + 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 + + .. change:: + :tags: sql + :tickets: 833 + + Removed regular expression step from most statement compilations. + Also fixes + + .. change:: + :tags: sql + :tickets: + + Fixed empty (zero column) sqlite inserts, allowing inserts on + autoincrementing single column tables. + + .. change:: + :tags: sql + :tickets: + + Fixed expression translation of text() clauses; this repairs various + ORM scenarios where literal text is used for SQL expressions + + .. change:: + :tags: sql + :tickets: + + Removed ClauseParameters object; compiled.params returns a regular + dictionary now, as well as result.last_inserted_params() / + last_updated_params(). + + .. change:: + :tags: sql + :tickets: + + 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 + + .. change:: + :tags: sql + :tickets: 844 + + func. objects can be pickled/unpickled + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: 573 + + Added a field ("info") for storing arbitrary data on schema items + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + fixed the close() method on Transaction when using strategy='threadlocal' + + .. change:: + :tags: sql + :tickets: 853 + + fix to compiled bind parameters to not mistakenly populate None + + .. change:: + :tags: sql + :tickets: + + ._execute_clauseelement becomes a public method + Connectable.execute_clauseelement + + .. change:: + :tags: orm + :tickets: 843 + + 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. + + .. change:: + :tags: orm + :tickets: 802 + + 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. + + .. change:: + :tags: orm + :tickets: 767 + + added op() operator to instrumented attributes; i.e. + User.name.op('ilike')('%somename%') + + .. change:: + :tags: orm + :tickets: 676 + + 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 '==') + + .. change:: + :tags: orm + :tickets: + + the "properties" accessor on Mapper is removed; it now throws an informative + exception explaining the usage of mapper.get_property() and + mapper.iterate_properties + + .. change:: + :tags: orm + :tickets: + + added having() method to Query, applies HAVING to the generated statement + in the same way as filter() appends to the WHERE clause. + + .. change:: + :tags: orm + :tickets: 777 + + 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. + + .. change:: + :tags: orm + :tickets: + + 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). + + .. change:: + :tags: orm + :tickets: 848 + + query doesn't throw an error if you use distinct() and an order_by() + containing UnaryExpressions (or other) together + + .. change:: + :tags: orm + :tickets: 786 + + order_by() expressions from joined tables are properly added to columns + clause when using distinct() + + .. change:: + :tags: orm + :tickets: 858 + + 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) + + .. change:: + :tags: orm + :tickets: + + added a little more checking for garbage-collection dereferences in + InstanceState.__cleanup() to reduce "gc ignored" errors on app + shutdown + + .. change:: + :tags: orm + :tickets: + + The session API has been solidified: + + .. change:: + :tags: orm + :tickets: 840 + + It's an error to session.save() an object which is already + persistent + + .. change:: + :tags: orm + :tickets: + + It's an error to session.delete() an object which is *not* + persistent. + + .. change:: + :tags: orm + :tickets: + + session.update() and session.delete() raise an error when updating + or deleting an instance that is already in the session with a + different identity. + + .. change:: + :tags: orm + :tickets: + + 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 + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: 834 + + Fixed a truncation error when re-assigning a subset of a collection + (obj.relation = obj.relation[1:]) + + .. change:: + :tags: orm + :tickets: 832 + + De-cruftified backref configuration code, backrefs which step on + existing properties now raise an error + + .. change:: + :tags: orm + :tickets: 831 + + Improved behavior of add_property() etc., fixed involving + synonym/deferred. + + .. change:: + :tags: orm + :tickets: + + Fixed clear_mappers() behavior to better clean up after itself. + + .. change:: + :tags: orm + :tickets: 841 + + 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. + + .. change:: + :tags: orm + :tickets: + + Fixed __hash__ for association proxy- these collections are unhashable, + just like their mutable Python counterparts. + + .. change:: + :tags: orm + :tickets: + + Added proxying of save_or_update, __contains__ and __iter__ methods for + scoped sessions. + + .. change:: + :tags: orm + :tickets: 852 + + fixed very hard-to-reproduce issue where by the FROM clause of Query + could get polluted by certain generative calls + + .. change:: + :tags: dialects + :tickets: + + Added experimental support for MaxDB (versions >= 7.6.03.007 only). + + .. change:: + :tags: dialects + :tickets: + + oracle will now reflect "DATE" as an OracleDateTime column, not + OracleDate + + .. change:: + :tags: dialects + :tickets: 847 + + added awareness of schema name in oracle table_names() function, + fixes metadata.reflect(schema='someschema') + + .. change:: + :tags: dialects + :tickets: + + MSSQL anonymous labels for selection of functions made deterministic + + .. change:: + :tags: dialects + :tickets: + + sqlite will reflect "DECIMAL" as a numeric column. + + .. change:: + :tags: dialects + :tickets: 828 + + Made access dao detection more reliable + + .. change:: + :tags: dialects + :tickets: + + 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. + + .. change:: + :tags: dialects + :tickets: + + Added test coverage for unknown type reflection. Fixed sqlite/mysql + handling of type reflection for unknown types. + + .. change:: + :tags: dialects + :tickets: + + Added REAL for mysql dialect (for folks exploiting the + REAL_AS_FLOAT sql mode). + + .. change:: + :tags: dialects + :tickets: + + mysql Float, MSFloat and MSDouble constructed without arguments + now produce no-argument DDL, e.g.'FLOAT'. + + .. change:: + :tags: misc + :tickets: + + Removed unused util.hash(). + +.. changelog:: + :version: 0.4.0 + :released: Wed Oct 17 2007 + + .. change:: + :tags: + :tickets: + + (see 0.4.0beta1 for the start of major changes against 0.3, + as well as http://www.sqlalchemy.org/trac/wiki/WhatsNewIn04 ) + + .. change:: + :tags: + :tickets: 785 + + Added initial Sybase support (mxODBC so far) + + .. change:: + :tags: + :tickets: + + Added partial index support for PostgreSQL. Use the postgres_where keyword + on the Index. + + .. change:: + :tags: + :tickets: 817 + + string-based query param parsing/config file parser understands + wider range of string values for booleans + + .. change:: + :tags: + :tickets: 813 + + backref remove object operation doesn't fail if the other-side + collection doesn't contain the item, supports noload collections + + .. change:: + :tags: + :tickets: 818 + + removed __len__ from "dynamic" collection as it would require issuing + a SQL "count()" operation, thus forcing all list evaluations to issue + redundant SQL + + .. change:: + :tags: + :tickets: 816 + + inline optimizations added to locate_dirty() which can greatly speed up + repeated calls to flush(), as occurs with autoflush=True + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + Firebird has supports_sane_rowcount and supports_sane_multi_rowcount set + to False due to ticket #370 (right way). + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: 795 + + Fixed three- and multi-level select and deferred inheritance loading + (i.e. abc inheritance with no select_table). + + .. change:: + :tags: + :tickets: + + Ident passed to id_chooser in shard.py always a list. + + .. change:: + :tags: + :tickets: + + The no-arg ResultProxy._row_processor() is now the class attribute + `_process_row`. + + .. change:: + :tags: + :tickets: 797 + + Added support for returning values from inserts and updates for + PostgreSQL 8.2+. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: 808 + + fixed sqlite reflection of BOOL/BOOLEAN + + .. change:: + :tags: + :tickets: + + Added support for UPDATE with LIMIT on mysql. + + .. change:: + :tags: + :tickets: 803 + + null foreign key on a m2o doesn't trigger a lazyload + + .. change:: + :tags: + :tickets: 800 + + 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 + + .. change:: + :tags: + :tickets: 806 + + fix to anonymous label generation of long table/column names + + .. change:: + :tags: + :tickets: + + Firebird dialect now uses SingletonThreadPool as poolclass. + + .. change:: + :tags: + :tickets: + + Firebird now uses dialect.preparer to format sequences names + + .. change:: + :tags: + :tickets: 810 + + 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. + + .. change:: + :tags: + :tickets: + + Added an option to the _ScopedExt mapper extension to not automatically + save new objects to session on object initialization. + + .. change:: + :tags: + :tickets: + + fixed Oracle non-ansi join syntax + + .. change:: + :tags: + :tickets: + + PickleType and Interval types (on db not supporting it natively) are now + slightly faster. + + .. change:: + :tags: + :tickets: + + Added Float and Time types to Firebird (FBFloat and FBTime). Fixed + BLOB SUB_TYPE for TEXT and Binary types. + + .. change:: + :tags: + :tickets: + + 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. + +.. changelog:: + :version: 0.4.0beta6 + :released: Thu Sep 27 2007 + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: 758 + + 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). 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). + + .. change:: + :tags: + :tickets: + + added "FETCH" to the keywords detected by Postgres to indicate a + result-row holding statement (i.e. in addition to "SELECT"). + + .. change:: + :tags: + :tickets: + + Added full list of SQLite reserved keywords so that they get escaped + properly. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: 560 + + 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)" + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: 584, 761 + + Added "schema" argument to Sequence; use this with Postgres /Oracle when + the sequence is located in an alternate schema. Implements part of, should fix. + + .. change:: + :tags: + :tickets: + + Fixed reflection of the empty string for mysql enums. + + .. change:: + :tags: + :tickets: 794 + + Changed MySQL dialect to use the older LIMIT , syntax + instead of LIMIT OFFSET for folks using 3.23. + + .. change:: + :tags: + :tickets: + + Added 'passive_deletes="all"' flag to relation(), disables all nulling-out + of foreign key attributes during a flush where the parent object is + deleted. + + .. change:: + :tags: + :tickets: + + Column defaults and onupdates, executing inline, will add parenthesis for + subqueries and other parenthesis-requiring expressions + + .. change:: + :tags: + :tickets: 793 + + 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. + + .. change:: + :tags: + :tickets: 771 + + Fixes to ShardedSession to work with deferred columns. + + .. change:: + :tags: + :tickets: + + 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.) + + .. change:: + :tags: + :tickets: 764 + + 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.. 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. + + .. change:: + :tags: + :tickets: 757, 768, 779, 728 + + Other tickets:,,. + +.. changelog:: + :version: 0.4.0beta5 + :released: + + .. change:: + :tags: + :tickets: 754 + + Connection pool fixes; the better performance of beta4 remains but fixes + "connection overflow" and other bugs which were present (like). + + .. change:: + :tags: + :tickets: 769 + + Fixed bugs in determining proper sync clauses from custom inherit + conditions. + + .. change:: + :tags: + :tickets: 763 + + Extended 'engine_from_config' coercion for QueuePool size / overflow. + + .. change:: + :tags: + :tickets: 748 + + mysql views can be reflected again. + + .. change:: + :tags: + :tickets: + + AssociationProxy can now take custom getters and setters. + + .. change:: + :tags: + :tickets: + + Fixed malfunctioning BETWEEN in orm queries. + + .. change:: + :tags: + :tickets: 762 + + Fixed OrderedProperties pickling + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: 759 + + Fixed PG executemany() behavior. + + .. change:: + :tags: + :tickets: + + postgres reflects tables with autoincrement=False for primary key columns + which have no defaults. + + .. change:: + :tags: + :tickets: + + 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(). + + .. change:: + :tags: tickets, fixed + :tickets: 742 + + + + .. change:: + :tags: tickets, fixed + :tickets: 748 + + + + .. change:: + :tags: tickets, fixed + :tickets: 760 + + + + .. change:: + :tags: tickets, fixed + :tickets: 762 + + + + .. change:: + :tags: tickets, fixed + :tickets: 763 + + + +.. changelog:: + :version: 0.4.0beta4 + :released: Wed Aug 22 2007 + + .. change:: + :tags: + :tickets: + + Tidied up what ends up in your namespace when you 'from sqlalchemy import *': + + .. change:: + :tags: + :tickets: + + '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. + + .. change:: + :tags: + :tickets: + + Internal-ish classes like ClauseElement, FromClause, NullTypeEngine, + etc., are also no longer imported into your namespace + + .. change:: + :tags: + :tickets: + + The 'Smallinteger' compatiblity name (small i!) is no longer imported, + but remains in schema.py for now. SmallInteger (big I!) is still + imported. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + Fix to bind param processing such that "False" values (like blank strings) + still get processed/encoded. + + .. change:: + :tags: + :tickets: 752 + + Fix to select() "generative" behavior, such that calling column(), + select_from(), correlate(), and with_prefix() does not modify the + original select object + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + Added session.prune(), trims away instances cached in a session that + are no longer referenced elsewhere. (A utility for strong-ref + identity maps). + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: 735 + + Modified SQL operator functions to be module-level operators, + allowing SQL expressions to be pickleable. + + .. change:: + :tags: + :tickets: + + Small adjustment to mapper class.__init__ to allow for Py2.6 + object.__init__() behavior. + + .. change:: + :tags: + :tickets: + + Fixed 'prefix' argument for select() + + .. change:: + :tags: + :tickets: + + Connection.begin() no longer accepts nested=True, this logic is now + all in begin_nested(). + + .. change:: + :tags: + :tickets: + + Fixes to new "dynamic" relation loader involving cascades + + .. change:: + :tags: tickets, fixed + :tickets: 735 + + + + .. change:: + :tags: tickets, fixed + :tickets: 752 + + + +.. changelog:: + :version: 0.4.0beta3 + :released: Thu Aug 16 2007 + + .. change:: + :tags: + :tickets: + + SQL types optimization: + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + General performance improvement of result set iteration is around 10-20%. + + .. change:: + :tags: + :tickets: + + 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. + + .. change:: + :tags: + :tickets: + + Hooks added throughout base/sql/defaults to optimize the calling of bind + aram/result processors so that method call overhead is minimized. + + .. change:: + :tags: + :tickets: + + Support added for executemany() scenarios such that unneeded "last row id" + logic doesn't kick in, parameters aren't excessively traversed. + + .. change:: + :tags: + :tickets: + + Added 'inherit_foreign_keys' arg to mapper(). + + .. change:: + :tags: + :tickets: + + Added support for string date passthrough in sqlite. + + .. change:: + :tags: tickets, fixed + :tickets: 738 + + + + .. change:: + :tags: tickets, fixed + :tickets: 739 + + + + .. change:: + :tags: tickets, fixed + :tickets: 743 + + + + .. change:: + :tags: tickets, fixed + :tickets: 744 + + + +.. changelog:: + :version: 0.4.0beta2 + :released: Tue Aug 14 2007 + + .. change:: + :tags: oracle, improvements. + :tickets: + + Auto-commit after LOAD DATA INFILE for mysql. + + .. change:: + :tags: oracle, improvements. + :tickets: + + A rudimental SessionExtension class has been added, allowing user-defined + functionality to take place at flush(), commit(), and rollback() boundaries. + + .. change:: + :tags: oracle, improvements. + :tickets: + + Added engine_from_config() function for helping to create_engine() from an + .ini style config. + + .. change:: + :tags: oracle, improvements. + :tickets: + + base_mapper() becomes a plain attribute. + + .. change:: + :tags: oracle, improvements. + :tickets: + + session.execute() and scalar() can search for a Table with which to bind from + using the given ClauseElement. + + .. change:: + :tags: oracle, improvements. + :tickets: + + Session automatically extrapolates tables from mappers with binds, also uses + base_mapper so that inheritance hierarchies bind automatically. + + .. change:: + :tags: oracle, improvements. + :tickets: + + Moved ClauseVisitor traversal back to inlined non-recursive. + + .. change:: + :tags: tickets, fixed + :tickets: 730 + + + + .. change:: + :tags: tickets, fixed + :tickets: 732 + + + + .. change:: + :tags: tickets, fixed + :tickets: 733 + + + + .. change:: + :tags: tickets, fixed + :tickets: 734 + + + +.. changelog:: + :version: 0.4.0beta1 + :released: Sun Aug 12 2007 + + .. change:: + :tags: orm + :tickets: + + Speed! Along with recent speedups to ResultProxy, total number of function + calls significantly reduced for large loads. + + .. change:: + :tags: orm + :tickets: + + 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). + + .. change:: + :tags: orm + :tickets: 213 + + New collection_class api and implementation. 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + __setitem__-like assignments now fire remove events for the existing + value, if any. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + AttributeExtension moved to interfaces, and .delete is now .remove The + event method signature has also been swapped around. + + .. change:: + :tags: orm + :tickets: + + Major overhaul for Query: + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: 643 + + 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. + + .. change:: + :tags: orm + :tickets: + + Removed ancient query.select_by_attributename() capability. + + .. change:: + :tags: orm + :tickets: + + 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 + + .. change:: + :tags: orm + :tickets: 660 + + Added query.populate_existing(), marks the query to reload all + attributes and collections of all instances touched in the query, + including eagerly-loaded entities. + + .. change:: + :tags: orm + :tickets: + + Added eagerload_all(), allows eagerload_all('x.y.z') to specify eager + loading of all properties in the given path. + + .. change:: + :tags: orm + :tickets: + + Major overhaul for Session: + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + SessionTransaction removed from "public" API. You now can call begin()/ + commit()/rollback() on the Session itself. + + .. change:: + :tags: orm + :tickets: + + Session also supports SAVEPOINT transactions; call begin_nested(). + + .. change:: + :tags: orm + :tickets: + + Session supports two-phase commit behavior when vertically or + horizontally partitioning (i.e., using more than one engine). Use + twophase=True. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + Added new "binds" argument to Session to support configuration of + multiple binds with sessionmaker() function. + + .. change:: + :tags: orm + :tickets: + + A rudimental SessionExtension class has been added, allowing + user-defined functionality to take place at flush(), commit(), and + rollback() boundaries. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: 618 + + 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. + + .. change:: + :tags: orm + :tickets: 659 + + 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. + + .. change:: + :tags: orm + :tickets: 211 + + 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. + + .. change:: + :tags: orm + :tickets: + + Improved support for custom column_property() attributes which feature + correlated subqueries, works better with eager loading now. + + .. change:: + :tags: orm + :tickets: 611 + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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. + + .. change:: + :tags: orm + :tickets: + + 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' + + .. change:: + :tags: orm + :tickets: 696 + + It's now possible to map only a subset of available selectable columns + onto mapper properties, using include_columns/exclude_columns.. + + .. change:: + :tags: orm + :tickets: + + Added undefer_group() MapperOption, sets a set of "deferred" columns + joined by a "group" to load as "undeferred". + + .. change:: + :tags: orm + :tickets: + + 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 + + .. change:: + :tags: sql + :tickets: + + 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. + + .. change:: + :tags: sql + :tickets: + + 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". + + .. change:: + :tags: sql + :tickets: + + 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). + + .. change:: + :tags: transactions + :tickets: + + Added context manager (with statement) support for transactions. + + .. change:: + :tags: transactions + :tickets: + + Added support for two phase commit, works with mysql and postgres so far. + + .. change:: + :tags: transactions + :tickets: + + Added a subtransaction implementation that uses savepoints. + + .. change:: + :tags: transactions + :tickets: + + Added support for savepoints. + + .. change:: + :tags: metadata + :tickets: + + 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. + + .. change:: + :tags: metadata + :tickets: + + DynamicMetaData has been renamed to ThreadLocalMetaData + + .. change:: + :tags: metadata + :tickets: + + The ThreadLocalMetaData constructor now takes no arguments. + + .. change:: + :tags: metadata + :tickets: + + BoundMetaData has been removed- regular MetaData is equivalent + + .. change:: + :tags: metadata + :tickets: 646 + + 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. + + .. change:: + :tags: metadata + :tickets: 475 + + 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. + + .. change:: + :tags: metadata + :tickets: + + "Anonymous" alias and label names are now generated at SQL compilation + time in a completely deterministic fashion... no more random hex IDs + + .. change:: + :tags: metadata + :tickets: + + 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. + + .. change:: + :tags: metadata + :tickets: + + 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. + + .. change:: + :tags: metadata + :tickets: 569, 52 + + 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 + + .. change:: + :tags: metadata + :tickets: + + select(scalar=True) argument is deprecated; use select(..).as_scalar(). + The resulting object obeys the full "column" interface and plays better + within expressions. + + .. change:: + :tags: metadata + :tickets: 504 + + Added select().with_prefix('foo') allowing any set of keywords to be + placed before the columns clause of the SELECT + + .. change:: + :tags: metadata + :tickets: 686 + + Added array slice support to row[] + + .. change:: + :tags: metadata + :tickets: + + 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. + + .. change:: + :tags: metadata + :tickets: + + 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". + + .. change:: + :tags: metadata + :tickets: 559 + + 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. The connection used for the execution is available as well + so that you can pre-execute statements. + + .. change:: + :tags: metadata + :tickets: + + Added "explcit" create/drop/execute support for sequences (i.e. you can + pass a "connectable" to each of those methods on Sequence). + + .. change:: + :tags: metadata + :tickets: + + Better quoting of identifiers when manipulating schemas. + + .. change:: + :tags: metadata + :tickets: + + Standardized the behavior for table reflection where types can't be + located; NullType is substituted instead, warning is raised. + + .. change:: + :tags: metadata + :tickets: 606 + + ColumnCollection (i.e. the 'c' attribute on tables) follows dictionary + semantics for "__contains__" + + .. change:: + :tags: engines + :tickets: + + 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. + + .. change:: + :tags: engines + :tickets: + + 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. + + .. change:: + :tags: engines + :tickets: + + Connections gain a .properties collection, with contents scoped to the + lifetime of the underlying DBAPI connection + + .. change:: + :tags: engines + :tickets: + + Removed auto_close_cursors and disallow_open_cursors arguments from Pool; + reduces overhead as cursors are normally closed by ResultProxy and + Connection. + + .. change:: + :tags: extensions + :tickets: + + proxyengine is temporarily removed, pending an actually working + replacement. + + .. change:: + :tags: extensions + :tickets: + + 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(). + + .. change:: + :tags: mysql + :tickets: + + Table and column names loaded via reflection are now Unicode. + + .. change:: + :tags: mysql + :tickets: + + All standard column types are now supported, including SET. + + .. change:: + :tags: mysql + :tickets: + + Table reflection can now be performed in as little as one round-trip. + + .. change:: + :tags: mysql + :tickets: + + ANSI and ANSI_QUOTES sql modes are now supported. + + .. change:: + :tags: mysql + :tickets: + + Indexes are now reflected. + + .. change:: + :tags: postgres + :tickets: + + Added PGArray datatype for using postgres array datatypes. + + .. change:: + :tags: oracle + :tickets: 507 + + 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. diff --git a/doc/build/changelog/changelog_05.rst b/doc/build/changelog/changelog_05.rst new file mode 100644 index 0000000000..a02a67fcfa --- /dev/null +++ b/doc/build/changelog/changelog_05.rst @@ -0,0 +1,3775 @@ + +============== +0.5 Changelog +============== + + +.. changelog:: + :version: 0.5.9 + :released: + + .. change:: + :tags: sql + :tickets: 1661 + + Fixed erroneous self_group() call in expression package. + +.. changelog:: + :version: 0.5.8 + :released: Sat Jan 16 2010 + + .. change:: + :tags: sql + :tickets: + + The copy() method on Column now supports uninitialized, + unnamed Column objects. This allows easy creation of + declarative helpers which place common columns on multiple + subclasses. + + .. change:: + :tags: sql + :tickets: + + Default generators like Sequence() translate correctly + across a copy() operation. + + .. change:: + :tags: sql + :tickets: + + Sequence() and other DefaultGenerator objects are accepted + as the value for the "default" and "onupdate" keyword + arguments of Column, in addition to being accepted + positionally. + + .. change:: + :tags: sql + :tickets: 1568, 1617 + + Fixed a column arithmetic bug that affected column + correspondence for cloned selectables which contain + free-standing column expressions. This bug is + generally only noticeable when exercising newer + ORM behavior only availble in 0.6 via, + but is more correct at the SQL expression level + as well. + + .. change:: + :tags: postgresql + :tickets: 1647 + + The extract() function, which was slightly improved in + 0.5.7, needed a lot more work to generate the correct + typecast (the typecasts appear to be necessary in PG's + EXTRACT quite a lot of the time). The typecast is + now generated using a rule dictionary based + on PG's documentation for date/time/interval arithmetic. + It also accepts text() constructs again, which was broken + in 0.5.7. + + .. change:: + :tags: firebird + :tickets: 1646 + + Recognize more errors as disconnections. + +.. changelog:: + :version: 0.5.7 + :released: Sat Dec 26 2009 + + .. change:: + :tags: orm + :tickets: 1543 + + contains_eager() now works with the automatically + generated subquery that results when you say + "query(Parent).join(Parent.somejoinedsubclass)", i.e. + when Parent joins to a joined-table-inheritance subclass. + Previously contains_eager() would erroneously add the + subclass table to the query separately producing a + cartesian product. An example is in the ticket + description. + + .. change:: + :tags: orm + :tickets: 1553 + + query.options() now only propagate to loaded objects + for potential further sub-loads only for options where + such behavior is relevant, keeping + various unserializable options like those generated + by contains_eager() out of individual instance states. + + .. change:: + :tags: orm + :tickets: 1054 + + Session.execute() now locates table- and + mapper-specific binds based on a passed + in expression which is an insert()/update()/delete() + construct. + + .. change:: + :tags: orm + :tickets: + + Session.merge() now properly overwrites a many-to-one or + uselist=False attribute to None if the attribute + is also None in the given object to be merged. + + .. change:: + :tags: orm + :tickets: 1618 + + Fixed a needless select which would occur when merging + transient objects that contained a null primary key + identifier. + + .. change:: + :tags: orm + :tickets: 1585 + + Mutable collection passed to the "extension" attribute + of relation(), column_property() etc. will not be mutated + or shared among multiple instrumentation calls, preventing + duplicate extensions, such as backref populators, + from being inserted into the list. + + .. change:: + :tags: orm + :tickets: 1504 + + Fixed the call to get_committed_value() on CompositeProperty. + + .. change:: + :tags: orm + :tickets: 1602 + + Fixed bug where Query would crash if a join() with no clear + "left" side were called when a non-mapped column entity + appeared in the columns list. + + .. change:: + :tags: orm + :tickets: 1616, 1480 + + Fixed bug whereby composite columns wouldn't load properly + when configured on a joined-table subclass, introduced in + version 0.5.6 as a result of the fix for. thx to Scott Torborg. + + .. change:: + :tags: orm + :tickets: 1556 + + The "use get" behavior of many-to-one relations, i.e. that a + lazy load will fallback to the possibly cached query.get() + value, now works across join conditions where the two compared + types are not exactly the same class, but share the same + "affinity" - i.e. Integer and SmallInteger. Also allows + combinations of reflected and non-reflected types to work + with 0.5 style type reflection, such as PGText/Text (note 0.6 + reflects types as their generic versions). + + .. change:: + :tags: orm + :tickets: 1436 + + Fixed bug in query.update() when passing Cls.attribute + as keys in the value dict and using synchronize_session='expire' + ('fetch' in 0.6). + + .. change:: + :tags: sql + :tickets: 1603 + + Fixed bug in two-phase transaction whereby commit() method + didn't set the full state which allows subsequent close() + call to succeed. + + .. change:: + :tags: sql + :tickets: + + Fixed the "numeric" paramstyle, which apparently is the + default paramstyle used by Informixdb. + + .. change:: + :tags: sql + :tickets: 1574 + + Repeat expressions in the columns clause of a select + are deduped based on the identity of each clause element, + not the actual string. This allows positional + elements to render correctly even if they all render + identically, such as "qmark" style bind parameters. + + .. change:: + :tags: sql + :tickets: 1632 + + The cursor associated with connection pool connections + (i.e. _CursorFairy) now proxies `__iter__()` to the + underlying cursor correctly. + + .. change:: + :tags: sql + :tickets: 1556 + + types now support an "affinity comparison" operation, i.e. + that an Integer/SmallInteger are "compatible", or + a Text/String, PickleType/Binary, etc. Part of. + + .. change:: + :tags: sql + :tickets: 1641 + + Fixed bug preventing alias() of an alias() from being + cloned or adapted (occurs frequently in ORM operations). + + .. change:: + :tags: sqlite + :tickets: 1439 + + sqlite dialect properly generates CREATE INDEX for a table + that is in an alternate schema. + + .. change:: + :tags: postgresql + :tickets: 1085 + + Added support for reflecting the DOUBLE PRECISION type, + via a new postgres.PGDoublePrecision object. + This is postgresql.DOUBLE_PRECISION in 0.6. + + .. change:: + :tags: postgresql + :tickets: 460 + + Added support for reflecting the INTERVAL YEAR TO MONTH + and INTERVAL DAY TO SECOND syntaxes of the INTERVAL + type. + + .. change:: + :tags: postgresql + :tickets: 1576 + + Corrected the "has_sequence" query to take current schema, + or explicit sequence-stated schema, into account. + + .. change:: + :tags: postgresql + :tickets: 1611 + + Fixed the behavior of extract() to apply operator + precedence rules to the "::" operator when applying + the "timestamp" cast - ensures proper parenthesization. + + .. change:: + :tags: mssql + :tickets: 1561 + + Changed the name of TrustedConnection to + Trusted_Connection when constructing pyodbc connect + arguments + + .. change:: + :tags: oracle + :tickets: 1637 + + The "table_names" dialect function, used by MetaData + .reflect(), omits "index overflow tables", a system + table generated by Oracle when "index only tables" + with overflow are used. These tables aren't accessible + via SQL and can't be reflected. + + .. change:: + :tags: ext + :tickets: 1570, 1523 + + A column can be added to a joined-table declarative + superclass after the class has been constructed + (i.e. via class-level attribute assignment), and + the column will be propagated down to + subclasses. This is the reverse + situation as that of, fixed in 0.5.6. + + .. change:: + :tags: ext + :tickets: 1491 + + Fixed a slight inaccuracy in the sharding example. + Comparing equivalence of columns in the ORM is best + accomplished using col1.shares_lineage(col2). + + .. change:: + :tags: ext + :tickets: 1606 + + Removed unused `load()` method from ShardedQuery. + +.. changelog:: + :version: 0.5.6 + :released: Sat Sep 12 2009 + + .. change:: + :tags: orm + :tickets: 1300 + + Fixed bug whereby inheritance discriminator part of a + composite primary key would fail on updates. + Continuation of. + + .. change:: + :tags: orm + :tickets: 1507 + + Fixed bug which disallowed one side of a many-to-many + bidirectional reference to declare itself as "viewonly" + + .. change:: + :tags: orm + :tickets: 1526 + + Added an assertion that prevents a @validates function + or other AttributeExtension from loading an unloaded + collection such that internal state may be corrupted. + + .. change:: + :tags: orm + :tickets: 1519 + + Fixed bug which prevented two entities from mutually + replacing each other's primary key values within a single + flush() for some orderings of operations. + + .. change:: + :tags: orm + :tickets: 1485 + + Fixed an obscure issue whereby a joined-table subclass + with a self-referential eager load on the base class + would populate the related object's "subclass" table with + data from the "subclass" table of the parent. + + .. change:: + :tags: orm + :tickets: 1477 + + relations() now have greater ability to be "overridden", + meaning a subclass that explicitly specifies a relation() + overriding that of the parent class will be honored + during a flush. This is currently to support + many-to-many relations from concrete inheritance setups. + Outside of that use case, YMMV. + + .. change:: + :tags: orm + :tickets: 1483 + + Squeezed a few more unnecessary "lazy loads" out of + relation(). When a collection is mutated, many-to-one + backrefs on the other side will not fire off to load + the "old" value, unless "single_parent=True" is set. + A direct assignment of a many-to-one still loads + the "old" value in order to update backref collections + on that value, which may be present in the session + already, thus maintaining the 0.5 behavioral contract. + + .. change:: + :tags: orm + :tickets: 1480 + + Fixed bug whereby a load/refresh of joined table + inheritance attributes which were based on + column_property() or similar would fail to evaluate. + + .. change:: + :tags: orm + :tickets: 1488 + + Improved support for MapperProperty objects overriding + that of an inherited mapper for non-concrete + inheritance setups - attribute extensions won't randomly + collide with each other. + + .. change:: + :tags: orm + :tickets: 1487 + + UPDATE and DELETE do not support ORDER BY, LIMIT, OFFSET, + etc. in standard SQL. Query.update() and Query.delete() + now raise an exception if any of limit(), offset(), + order_by(), group_by(), or distinct() have been + called. + + .. change:: + :tags: orm + :tickets: + + Added AttributeExtension to sqlalchemy.orm.__all__ + + .. change:: + :tags: orm + :tickets: 1476 + + Improved error message when query() is called with + a non-SQL /entity expression. + + .. change:: + :tags: orm + :tickets: 1440 + + Using False or 0 as a polymorphic discriminator now + works on the base class as well as a subclass. + + .. change:: + :tags: orm + :tickets: 1424 + + Added enable_assertions(False) to Query which disables + the usual assertions for expected state - used + by Query subclasses to engineer custom state.. See + http://www.sqlalchemy.org/trac/wiki/UsageRecipes/PreFilteredQuery + for an example. + + .. change:: + :tags: orm + :tickets: 1501 + + Fixed recursion issue which occured if a mapped object's + `__len__()` or `__nonzero__()` method resulted in state + changes. + + .. change:: + :tags: orm + :tickets: 1506 + + Fixed incorrect exception raise in + Weak/StrongIdentityMap.add() + + .. change:: + :tags: orm + :tickets: 1522 + + Fixed the error message for "could not find a FROM clause" + in query.join() which would fail to issue correctly + if the query was against a pure SQL construct. + + .. change:: + :tags: orm + :tickets: 1486 + + Fixed a somewhat hypothetical issue which would result + in the wrong primary key being calculated for a mapper + using the old polymorphic_union function - but this + is old stuff. + + .. change:: + :tags: sql + :tickets: 1373 + + Fixed column.copy() to copy defaults and onupdates. + + .. change:: + :tags: sql + :tickets: + + Fixed a bug in extract() introduced in 0.5.4 whereby + the string "field" argument was getting treated as a + ClauseElement, causing various errors within more + complex SQL transformations. + + .. change:: + :tags: sql + :tickets: 1420 + + Unary expressions such as DISTINCT propagate their + type handling to result sets, allowing conversions like + unicode and such to take place. + + .. change:: + :tags: sql + :tickets: 1482 + + Fixed bug in Table and Column whereby passing empty + dict for "info" argument would raise an exception. + + .. change:: + :tags: oracle + :tickets: 1309 + + Backported 0.6 fix for Oracle alias names not getting + truncated. + + .. change:: + :tags: ext + :tickets: 1446 + + The collection proxies produced by associationproxy are now + pickleable. A user-defined proxy_factory however + is still not pickleable unless it defines __getstate__ + and __setstate__. + + .. change:: + :tags: ext + :tickets: 1468 + + Declarative will raise an informative exception if + __table_args__ is passed as a tuple with no dict argument. + Improved documentation. + + .. change:: + :tags: ext + :tickets: 1527 + + Table objects declared in the MetaData can now be used + in string expressions sent to primaryjoin/secondaryjoin/ + secondary - the name is pulled from the MetaData of the + declarative base. + + .. change:: + :tags: ext + :tickets: 1523 + + A column can be added to a joined-table subclass after + the class has been constructed (i.e. via class-level + attribute assignment). The column is added to the underlying + Table as always, but now the mapper will rebuild its + "join" to include the new column, instead of raising + an error about "no such column, use column_property() + instead". + + .. change:: + :tags: test + :tickets: + + Added examples into the test suite so they get exercised + regularly and cleaned up a couple deprecation warnings. + +.. changelog:: + :version: 0.5.5 + :released: Mon Jul 13 2009 + + .. change:: + :tags: general + :tickets: 970 + + unit tests have been migrated from unittest to nose. See + README.unittests for information on how to run the tests. + + .. change:: + :tags: orm + :tickets: + + The "foreign_keys" argument of relation() will now propagate + automatically to the backref in the same way that primaryjoin + and secondaryjoin do. For the extremely rare use case where + the backref of a relation() has intentionally different + "foreign_keys" configured, both sides now need to be + configured explicity (if they do in fact require this setting, + see the next note...). + + .. change:: + :tags: orm + :tickets: + + ...the only known (and really, really rare) use case where a + different foreign_keys setting was used on the + forwards/backwards side, a composite foreign key that + partially points to its own columns, has been enhanced such + that the fk->itself aspect of the relation won't be used to + determine relation direction. + + .. change:: + :tags: orm + :tickets: + + Session.mapper is now *deprecated*. + + Call session.add() if you'd like a free-standing object to be + part of your session. Otherwise, a DIY version of + Session.mapper is now documented at + http://www.sqlalchemy.org/trac/wiki/UsageRecipes/SessionAwareMapper + The method will remain deprecated throughout 0.6. + + .. change:: + :tags: orm + :tickets: 1431 + + Fixed Query being able to join() from individual columns of a + joined-table subclass entity, i.e. query(SubClass.foo, + SubcClass.bar).join(). In most cases, an error + "Could not find a FROM clause to join from" would be + raised. In a few others, the result would be returned in terms + of the base class rather than the subclass - so applications + which relied on this erroneous result need to be + adjusted. + + .. change:: + :tags: orm + :tickets: 1461 + + Fixed a bug involving contains_eager(), which would apply + itself to a secondary (i.e. lazy) load in a particular rare + case, producing cartesian products. improved the targeting of + query.options() on secondary loads overall. + + .. change:: + :tags: orm + :tickets: + + Fixed bug introduced in 0.5.4 whereby Composite types fail + when default-holding columns are flushed. + + .. change:: + :tags: orm + :tickets: 1426 + + Fixed another 0.5.4 bug whereby mutable attributes + (i.e. PickleType) wouldn't be deserialized correctly when the + whole object was serialized. + + .. change:: + :tags: orm + :tickets: + + Fixed bug whereby session.is_modified() would raise an + exception if any synonyms were in use. + + .. change:: + :tags: orm + :tickets: + + Fixed potential memory leak whereby previously pickled objects + placed back in a session would not be fully garbage collected + unless the Session were explicitly closed out. + + .. change:: + :tags: orm + :tickets: + + Fixed bug whereby list-based attributes, like pickletype and + PGArray, failed to be merged() properly. + + .. change:: + :tags: orm + :tickets: + + Repaired non-working attributes.set_committed_value function. + + .. change:: + :tags: orm + :tickets: + + Trimmed the pickle format for InstanceState which should + further reduce the memory footprint of pickled instances. The + format should be backwards compatible with that of 0.5.4 and + previous. + + .. change:: + :tags: orm + :tickets: 1463 + + sqlalchemy.orm.join and sqlalchemy.orm.outerjoin are now + added to __all__ in sqlalchemy.orm.*. + + .. change:: + :tags: orm + :tickets: 1458 + + Fixed bug where Query exception raise would fail when + a too-short composite primary key value were passed to + get(). + + .. change:: + :tags: sql + :tickets: + + Removed an obscure feature of execute() (including connection, + engine, Session) whereby a bindparam() construct can be sent + as a key to the params dictionary. This usage is undocumented + and is at the core of an issue whereby the bindparam() object + created implicitly by a text() construct may have the same + hash value as a string placed in the params dictionary and may + result in an inappropriate match when computing the final bind + parameters. Internal checks for this condition would add + significant latency to the critical task of parameter + rendering, so the behavior is removed. This is a backwards + incompatible change for any application that may have been + using this feature, however the feature has never been + documented. + + .. change:: + :tags: engine/pool + :tickets: + + Implemented recreate() for StaticPool. + +.. changelog:: + :version: 0.5.4p2 + :released: Tue May 26 2009 + + .. change:: + :tags: sql + :tickets: + + Repaired the printing of SQL exceptions which are not + based on parameters or are not executemany() style. + + .. change:: + :tags: postgresql + :tickets: + + Deprecated the hardcoded TIMESTAMP function, which when + used as func.TIMESTAMP(value) would render "TIMESTAMP value". + This breaks on some platforms as PostgreSQL doesn't allow + bind parameters to be used in this context. The hard-coded + uppercase is also inappropriate and there's lots of other + PG casts that we'd need to support. So instead, use + text constructs i.e. select(["timestamp '12/05/09'"]). + +.. changelog:: + :version: 0.5.4p1 + :released: Mon May 18 2009 + + .. change:: + :tags: orm + :tickets: + + Fixed an attribute error introduced in 0.5.4 which would + occur when merge() was used with an incomplete object. + +.. changelog:: + :version: 0.5.4 + :released: Sun May 17 2009 + + .. change:: + :tags: orm + :tickets: 1398 + + Significant performance enhancements regarding Sessions/flush() + in conjunction with large mapper graphs, large numbers of + objects: + + - Removed all* O(N) scanning behavior from the flush() process, + i.e. operations that were scanning the full session, + including an extremely expensive one that was erroneously + assuming primary key values were changing when this + was not the case. + + * one edge case remains which may invoke a full scan, + if an existing primary key attribute is modified + to a new value. + + - The Session's "weak referencing" behavior is now *full* - + no strong references whatsoever are made to a mapped object + or related items/collections in its __dict__. Backrefs and + other cycles in objects no longer affect the Session's ability + to lose all references to unmodified objects. Objects with + pending changes still are maintained strongly until flush. + + + The implementation also improves performance by moving + the "resurrection" process of garbage collected items + to only be relevant for mappings that map "mutable" + attributes (i.e. PickleType, composite attrs). This removes + overhead from the gc process and simplifies internal + behavior. + + If a "mutable" attribute change is the sole change on an object + which is then dereferenced, the mapper will not have access to + other attribute state when the UPDATE is issued. This may present + itself differently to some MapperExtensions. + + The change also affects the internal attribute API, but not + the AttributeExtension interface nor any of the publically + documented attribute functions. + + - The unit of work no longer genererates a graph of "dependency" + processors for the full graph of mappers during flush(), instead + creating such processors only for those mappers which represent + objects with pending changes. This saves a tremendous number + of method calls in the context of a large interconnected + graph of mappers. + + - Cached a wasteful "table sort" operation that previously + occured multiple times per flush, also removing significant + method call count from flush(). + + - Other redundant behaviors have been simplified in + mapper._save_obj(). + + .. change:: + :tags: orm + :tickets: + + Modified query_cls on DynamicAttributeImpl to accept a full + mixin version of the AppenderQuery, which allows subclassing + the AppenderMixin. + + .. change:: + :tags: orm + :tickets: 1300 + + The "polymorphic discriminator" column may be part of a + primary key, and it will be populated with the correct + discriminator value. + + .. change:: + :tags: orm + :tickets: + + Fixed the evaluator not being able to evaluate IS NULL clauses. + + .. change:: + :tags: orm + :tickets: 1352 + + Fixed the "set collection" function on "dynamic" relations to + initiate events correctly. Previously a collection could only + be assigned to a pending parent instance, otherwise modified + events would not be fired correctly. Set collection is now + compatible with merge(), fixes. + + .. change:: + :tags: orm + :tickets: + + Allowed pickling of PropertyOption objects constructed with + instrumented descriptors; previously, pickle errors would occur + when pickling an object which was loaded with a descriptor-based + option, such as query.options(eagerload(MyClass.foo)). + + .. change:: + :tags: orm + :tickets: 1357 + + Lazy loader will not use get() if the "lazy load" SQL clause + matches the clause used by get(), but contains some parameters + hardcoded. Previously the lazy strategy would fail with the + get(). Ideally get() would be used with the hardcoded + parameters but this would require further development. + + .. change:: + :tags: orm + :tickets: 1391 + + MapperOptions and other state associated with query.options() + is no longer bundled within callables associated with each + lazy/deferred-loading attribute during a load. + The options are now associated with the instance's + state object just once when it's populated. This removes + the need in most cases for per-instance/attribute loader + objects, improving load speed and memory overhead for + individual instances. + + .. change:: + :tags: orm + :tickets: 1360 + + Fixed another location where autoflush was interfering + with session.merge(). autoflush is disabled completely + for the duration of merge() now. + + .. change:: + :tags: orm + :tickets: 1406 + + Fixed bug which prevented "mutable primary key" dependency + logic from functioning properly on a one-to-one + relation(). + + .. change:: + :tags: orm + :tickets: + + Fixed bug in relation(), introduced in 0.5.3, + whereby a self referential relation + from a base class to a joined-table subclass would + not configure correctly. + + .. change:: + :tags: orm + :tickets: + + Fixed obscure mapper compilation issue when inheriting + mappers are used which would result in un-initialized + attributes. + + .. change:: + :tags: orm + :tickets: + + Fixed documentation for session weak_identity_map - + the default value is True, indicating a weak + referencing map in use. + + .. change:: + :tags: orm + :tickets: 1376 + + Fixed a unit of work issue whereby the foreign + key attribute on an item contained within a collection + owned by an object being deleted would not be set to + None if the relation() was self-referential. + + .. change:: + :tags: orm + :tickets: 1378 + + Fixed Query.update() and Query.delete() failures with eagerloaded + relations. + + .. change:: + :tags: orm + :tickets: + + It is now an error to specify both columns of a binary primaryjoin + condition in the foreign_keys or remote_side collection. Whereas + previously it was just nonsensical, but would succeed in a + non-deterministic way. + + .. change:: + :tags: ticket: 594, 1341, schema + :tickets: + + Added a quote_schema() method to the IdentifierPreparer class + so that dialects can override how schemas get handled. This + enables the MSSQL dialect to treat schemas as multipart + identifiers, such as 'database.owner'. + + .. change:: + :tags: sql + :tickets: + + Back-ported the "compiler" extension from SQLA 0.6. This + is a standardized interface which allows the creation of custom + ClauseElement subclasses and compilers. In particular it's + handy as an alternative to text() when you'd like to + build a construct that has database-specific compilations. + See the extension docs for details. + + .. change:: + :tags: sql + :tickets: 1413 + + Exception messages are truncated when the list of bound + parameters is larger than 10, preventing enormous + multi-page exceptions from filling up screens and logfiles + for large executemany() statements. + + .. change:: + :tags: sql + :tickets: + + ``sqlalchemy.extract()`` is now dialect sensitive and can + extract components of timestamps idiomatically across the + supported databases, including SQLite. + + .. change:: + :tags: sql + :tickets: 1353 + + Fixed __repr__() and other _get_colspec() methods on + ForeignKey constructed from __clause_element__() style + construct (i.e. declarative columns). + + .. change:: + :tags: mysql + :tickets: 1405 + + Reflecting a FOREIGN KEY construct will take into account + a dotted schema.tablename combination, if the foreign key + references a table in a remote schema. + + .. change:: + :tags: mssql + :tickets: + + Modified how savepoint logic works to prevent it from + stepping on non-savepoint oriented routines. Savepoint + support is still very experimental. + + .. change:: + :tags: mssql + :tickets: 1310 + + Added in reserved words for MSSQL that covers version 2008 + and all prior versions. + + .. change:: + :tags: mssql + :tickets: 1343 + + Corrected problem with information schema not working with a + binary collation based database. Cleaned up information schema + since it is only used by mssql now. + + .. change:: + :tags: sqlite + :tickets: 1402 + + Corrected the SLBoolean type so that it properly treats only 1 + as True. + + .. change:: + :tags: sqlite + :tickets: 1273 + + Corrected the float type so that it correctly maps to a + SLFloat type when being reflected. + + .. change:: + :tags: extensions + :tickets: 1379 + + Fixed adding of deferred or other column properties to a + declarative class. + +.. changelog:: + :version: 0.5.3 + :released: Tue Mar 24 2009 + + .. change:: + :tags: orm + :tickets: 1315 + + The "objects" argument to session.flush() is deprecated. + State which represents the linkage between a parent and + child object does not support "flushed" status on + one side of the link and not the other, so supporting + this operation leads to misleading results. + + .. change:: + :tags: orm + :tickets: + + Query now implements __clause_element__() which produces + its selectable, which means a Query instance can be accepted + in many SQL expressions, including col.in_(query), + union(query1, query2), select([foo]).select_from(query), + etc. + + .. change:: + :tags: orm + :tickets: 1337 + + Query.join() can now construct multiple FROM clauses, if + needed. Such as, query(A, B).join(A.x).join(B.y) + might say SELECT A.*, B.* FROM A JOIN X, B JOIN Y. + Eager loading can also tack its joins onto those + multiple FROM clauses. + + .. change:: + :tags: orm + :tickets: 1347 + + Fixed bug in dynamic_loader() where append/remove events + after construction time were not being propagated to the + UOW to pick up on flush(). + + .. change:: + :tags: orm + :tickets: + + Fixed bug where column_prefix wasn't being checked before + not mapping an attribute that already had class-level + name present. + + .. change:: + :tags: orm + :tickets: 1315 + + a session.expire() on a particular collection attribute + will clear any pending backref additions as well, so that + the next access correctly returns only what was present + in the database. Presents some degree of a workaround for, although we are considering removing the + flush([objects]) feature altogether. + + .. change:: + :tags: orm + :tickets: + + Session.scalar() now converts raw SQL strings to text() + the same way Session.execute() does and accepts same + alternative **kw args. + + .. change:: + :tags: orm + :tickets: + + improvements to the "determine direction" logic of + relation() such that the direction of tricky situations + like mapper(A.join(B)) -> relation-> mapper(B) can be + determined. + + .. change:: + :tags: orm + :tickets: 1306 + + When flushing partial sets of objects using session.flush([somelist]), + pending objects which remain pending after the operation won't + inadvertently be added as persistent. + + .. change:: + :tags: orm + :tickets: 1314 + + Added "post_configure_attribute" method to InstrumentationManager, + so that the "listen_for_events.py" example works again. + + .. change:: + :tags: orm + :tickets: + + a forward and complementing backwards reference which are both + of the same direction, i.e. ONETOMANY or MANYTOONE, + is now detected, and an error message is raised. + Saves crazy CircularDependencyErrors later on. + + .. change:: + :tags: orm + :tickets: + + Fixed bugs in Query regarding simultaneous selection of + multiple joined-table inheritance entities with common base + classes: + + - previously the adaption applied to "B" on + "A JOIN B" would be erroneously partially applied + to "A". + + - comparisons on relations (i.e. A.related==someb) + were not getting adapted when they should. + + - Other filterings, like + query(A).join(A.bs).filter(B.foo=='bar'), were erroneously + adapting "B.foo" as though it were an "A". + + .. change:: + :tags: orm + :tickets: 1325 + + Fixed adaptation of EXISTS clauses via any(), has(), etc. + in conjunction with an aliased object on the left and + of_type() on the right. + + .. change:: + :tags: orm + :tickets: + + Added an attribute helper method ``set_committed_value`` in + sqlalchemy.orm.attributes. Given an object, attribute name, + and value, will set the value on the object as part of its + "committed" state, i.e. state that is understood to have + been loaded from the database. Helps with the creation of + homegrown collection loaders and such. + + .. change:: + :tags: orm + :tickets: + + Query won't fail with weakref error when a non-mapper/class + instrumented descriptor is passed, raises + "Invalid column expession". + + .. change:: + :tags: orm + :tickets: + + Query.group_by() properly takes into account aliasing applied + to the FROM clause, such as with select_from(), using + with_polymorphic(), or using from_self(). + + .. change:: + :tags: sql + :tickets: + + An alias() of a select() will convert to a "scalar subquery" + when used in an unambiguously scalar context, i.e. it's used + in a comparison operation. This applies to + the ORM when using query.subquery() as well. + + .. change:: + :tags: sql + :tickets: 1302 + + Fixed missing _label attribute on Function object, others + when used in a select() with use_labels (such as when used + in an ORM column_property()). + + .. change:: + :tags: sql + :tickets: 1309 + + anonymous alias names now truncate down to the max length + allowed by the dialect. More significant on DBs like + Oracle with very small character limits. + + .. change:: + :tags: sql + :tickets: + + the __selectable__() interface has been replaced entirely + by __clause_element__(). + + .. change:: + :tags: sql + :tickets: 1299 + + The per-dialect cache used by TypeEngine to cache + dialect-specific types is now a WeakKeyDictionary. + This to prevent dialect objects from + being referenced forever for an application that + creates an arbitrarily large number of engines + or dialects. There is a small performance penalty + which will be resolved in 0.6. + + .. change:: + :tags: sqlite + :tickets: + + Fixed SQLite reflection methods so that non-present + cursor.description, which triggers an auto-cursor + close, will be detected so that no results doesn't + fail on recent versions of pysqlite which raise + an error when fetchone() called with no rows present. + + .. change:: + :tags: postgresql + :tickets: + + Index reflection won't fail when an index with + multiple expressions is encountered. + + .. change:: + :tags: postgresql + :tickets: 1327 + + Added PGUuid and PGBit types to + sqlalchemy.databases.postgres. + + .. change:: + :tags: postgresql + :tickets: 1327 + + Refection of unknown PG types won't crash when those + types are specified within a domain. + + .. change:: + :tags: mssql + :tickets: + + Preliminary support for pymssql 1.0.1 + + .. change:: + :tags: mssql + :tickets: + + Corrected issue on mssql where max_identifier_length was + not being respected. + + .. change:: + :tags: extensions + :tickets: + + Fixed a recursive pickling issue in serializer, triggered + by an EXISTS or other embedded FROM construct. + + .. change:: + :tags: extensions + :tickets: + + Declarative locates the "inherits" class using a search + through __bases__, to skip over mixins that are local + to subclasses. + + .. change:: + :tags: extensions + :tickets: + + Declarative figures out joined-table inheritance primary join + condition even if "inherits" mapper argument is given + explicitly. + + .. change:: + :tags: extensions + :tickets: + + Declarative will properly interpret the "foreign_keys" argument + on a backref() if it's a string. + + .. change:: + :tags: extensions + :tickets: + + Declarative will accept a table-bound column as a property + when used in conjunction with __table__, if the column is already + present in __table__. The column will be remapped to the given + key the same way as when added to the mapper() properties dict. + +.. changelog:: + :version: 0.5.2 + :released: Sat Jan 24 2009 + + .. change:: + :tags: orm + :tickets: + + Further refined 0.5.1's warning about delete-orphan cascade + placed on a many-to-many relation. First, the bad news: + the warning will apply to both many-to-many as well as + many-to-one relations. This is necessary since in both + cases, SQLA does not scan the full set of potential parents + when determining "orphan" status - for a persistent object + it only detects an in-python de-association event to establish + the object as an "orphan". Next, the good news: to support + one-to-one via a foreign key or assocation table, or to + support one-to-many via an association table, a new flag + single_parent=True may be set which indicates objects + linked to the relation are only meant to have a single parent. + The relation will raise an error if multiple parent-association + events occur within Python. + + .. change:: + :tags: orm + :tickets: 1292 + + Adjusted the attribute instrumentation change from 0.5.1 to + fully establish instrumentation for subclasses where the mapper + was created after the superclass had already been fully + instrumented. + + .. change:: + :tags: orm + :tickets: + + Fixed bug in delete-orphan cascade whereby two one-to-one + relations from two different parent classes to the same target + class would prematurely expunge the instance. + + .. change:: + :tags: orm + :tickets: + + Fixed an eager loading bug whereby self-referential eager + loading would prevent other eager loads, self referential or not, + from joining to the parent JOIN properly. Thanks to Alex K + for creating a great test case. + + .. change:: + :tags: orm + :tickets: + + session.expire() and related methods will not expire() unloaded + deferred attributes. This prevents them from being needlessly + loaded when the instance is refreshed. + + .. change:: + :tags: orm + :tickets: 1293 + + query.join()/outerjoin() will now properly join an aliased() + construct to the existing left side, even if query.from_self() + or query.select_from(someselectable) has been called. + + .. change:: + :tags: sql + :tickets: 1284 + + Further fixes to the "percent signs and spaces in column/table + names" functionality. + + .. change:: + :tags: mssql + :tickets: 1291 + + Restored convert_unicode handling. Results were being passed + on through without conversion. + + .. change:: + :tags: mssql + :tickets: 1282 + + Really fixing the decimal handling this time.. + + .. change:: + :tags: Ticket:1289, mssql + :tickets: + + Modified table reflection code to use only kwargs when + constructing tables. + +.. changelog:: + :version: 0.5.1 + :released: Sat Jan 17 2009 + + .. change:: + :tags: orm + :tickets: + + Removed an internal join cache which could potentially leak + memory when issuing query.join() repeatedly to ad-hoc + selectables. + + .. change:: + :tags: orm + :tickets: + + The "clear()", "save()", "update()", "save_or_update()" + Session methods have been deprecated, replaced by + "expunge_all()" and "add()". "expunge_all()" has also + been added to ScopedSession. + + .. change:: + :tags: orm + :tickets: + + Modernized the "no mapped table" exception and added a more + explicit __table__/__tablename__ exception to declarative. + + .. change:: + :tags: orm + :tickets: 1237 + + Concrete inheriting mappers now instrument attributes which + are inherited from the superclass, but are not defined for + the concrete mapper itself, with an InstrumentedAttribute that + issues a descriptive error when accessed. + + .. change:: + :tags: orm + :tickets: 1237, 781 + + Added a new `relation()` keyword `back_populates`. This + allows configuation of backreferences using explicit + relations. This is required when creating + bidirectional relations between a hierarchy of concrete + mappers and another class. + + .. change:: + :tags: orm + :tickets: 1237 + + Test coverage added for `relation()` objects specified on + concrete mappers. + + .. change:: + :tags: orm + :tickets: 1276 + + Query.from_self() as well as query.subquery() both disable + the rendering of eager joins inside the subquery produced. + The "disable all eager joins" feature is available publically + via a new query.enable_eagerloads() generative. + + .. change:: + :tags: orm + :tickets: + + Added a rudimental series of set operations to Query that + receive Query objects as arguments, including union(), + union_all(), intersect(), except_(), insertsect_all(), + except_all(). See the API documentation for + Query.union() for examples. + + .. change:: + :tags: orm + :tickets: + + Fixed bug that prevented Query.join() and eagerloads from + attaching to a query that selected from a union or aliased union. + + .. change:: + :tags: orm + :tickets: 1237 + + A short documentation example added for bidirectional + relations specified on concrete mappers. + + .. change:: + :tags: orm + :tickets: 1269 + + Mappers now instrument class attributes upon construction + with the final InstrumentedAttribute object which remains + persistent. The `_CompileOnAttr`/`__getattribute__()` + methodology has been removed. The net effect is that + Column-based mapped class attributes can now be used fully + at the class level without invoking a mapper compilation + operation, greatly simplifying typical usage patterns + within declarative. + + .. change:: + :tags: orm + :tickets: + + ColumnProperty (and front-end helpers such as ``deferred``) no + longer ignores unknown **keyword arguments. + + .. change:: + :tags: orm + :tickets: + + Fixed a bug with the unitofwork's "row switch" mechanism, + i.e. the conversion of INSERT/DELETE into an UPDATE, when + combined with joined-table inheritance and an object + which contained no defined values for the child table where + an UPDATE with no SET clause would be rendered. + + .. change:: + :tags: orm + :tickets: 1281 + + Using delete-orphan on a many-to-many relation is deprecated. + This produces misleading or erroneous results since SQLA does + not retrieve the full list of "parents" for m2m. To get delete-orphan + behavior with an m2m table, use an explcit association class + so that the individual association row is treated as a parent. + + .. change:: + :tags: orm + :tickets: 1281 + + delete-orphan cascade always requires delete cascade. Specifying + delete-orphan without delete now raises a deprecation warning. + + .. change:: + :tags: sql + :tickets: 1256 + + Improved the methodology to handling percent signs in column + names from. Added more tests. MySQL and + PostgreSQL dialects still do not issue correct CREATE TABLE + statements for identifiers with percent signs in them. + + .. change:: + :tags: schema + :tickets: 1214 + + Index now accepts column-oriented InstrumentedAttributes + (i.e. column-based mapped class attributes) as column + arguments. + + .. change:: + :tags: schema + :tickets: + + Column with no name (as in declarative) won't raise a + NoneType error when it's string output is requsted + (such as in a stack trace). + + .. change:: + :tags: schema + :tickets: 1278 + + Fixed bug when overriding a Column with a ForeignKey + on a reflected table, where derived columns (i.e. the + "virtual" columns of a select, etc.) would inadvertently + call upon schema-level cleanup logic intended only + for the original column. + + .. change:: + :tags: declarative + :tickets: + + Can now specify Column objects on subclasses which have no + table of their own (i.e. use single table inheritance). + The columns will be appended to the base table, but only + mapped by the subclass. + + .. change:: + :tags: declarative + :tickets: + + For both joined and single inheriting subclasses, the subclass + will only map those columns which are already mapped on the + superclass and those explicit on the subclass. Other + columns that are present on the `Table` will be excluded + from the mapping by default, which can be disabled + by passing a blank `exclude_properties` collection to the + `__mapper_args__`. This is so that single-inheriting + classes which define their own columns are the only classes + to map those columns. The effect is actually a more organized + mapping than you'd normally get with explicit `mapper()` + calls unless you set up the `exclude_properties` arguments + explicitly. + + .. change:: + :tags: declarative + :tickets: + + It's an error to add new Column objects to a declarative class + that specified an existing table using __table__. + + .. change:: + :tags: mysql + :tickets: + + Added the missing keywords from MySQL 4.1 so they get escaped + properly. + + .. change:: + :tags: mssql + :tickets: 1280 + + Corrected handling of large decimal values with more robust + tests. Removed string manipulation on floats. + + .. change:: + :tags: mssql + :tickets: + + Modified the do_begin handling in mssql to use the Cursor not + the Connection so it is DBAPI compatible. + + .. change:: + :tags: mssql + :tickets: + + Corrected SAVEPOINT support on adodbapi by changing the + handling of savepoint_release, which is unsupported on mssql. + +.. changelog:: + :version: 0.5.0 + :released: Tue Jan 06 2009 + + .. change:: + :tags: general + :tickets: + + Documentation has been converted to Sphinx. In particular, + the generated API documentation has been constructed into a + full blown "API Reference" section which organizes editorial + documentation combined with generated docstrings. Cross + linking between sections and API docs are vastly improved, a + javascript-powered search feature is provided, and a full + index of all classes, functions and members is provided. + + .. change:: + :tags: general + :tickets: + + setup.py now imports setuptools only optionally. If not + present, distutils is used. The new "pip" installer is + recommended over easy_install as it installs in a more + simplified way. + + .. change:: + :tags: general + :tickets: + + added an extremely basic illustration of a PostGIS integration + to the examples folder. + + .. change:: + :tags: orm + :tickets: + + Query.with_polymorphic() now accepts a third argument + "discriminator" which will replace the value of + mapper.polymorphic_on for that query. Mappers themselves no + longer require polymorphic_on to be set, even if the mapper + has a polymorphic_identity. When not set, the mapper will + load non-polymorphically by default. Together, these two + features allow a non-polymorphic concrete inheritance setup to + use polymorphic loading on a per-query basis, since concrete + setups are prone to many issues when used polymorphically in + all cases. + + .. change:: + :tags: orm + :tickets: + + dynamic_loader accepts a query_class= to customize the Query + classes used for both the dynamic collection and the queries + built from it. + + .. change:: + :tags: orm + :tickets: 1079 + + query.order_by() accepts None which will remove any pending + order_by state from the query, as well as cancel out any + mapper/relation configured ordering. This is primarily useful + for overriding the ordering specified on a dynamic_loader(). + + .. change:: + :tags: sql + :tickets: 935 + + RowProxy objects can be used in place of dictionary arguments + sent to connection.execute() and friends. + + .. change:: + :tags: dialect + :tickets: + + Added a new description_encoding attribute on the dialect that + is used for encoding the column name when processing the + metadata. This usually defaults to utf-8. + + .. change:: + :tags: mssql + :tickets: + + Added in a new MSGenericBinary type. This maps to the Binary + type so it can implement the specialized behavior of treating + length specified types as fixed-width Binary types and + non-length types as an unbound variable length Binary type. + + .. change:: + :tags: mssql + :tickets: 1249 + + Added in new types: MSVarBinary and MSImage. + + .. change:: + :tags: mssql + :tickets: + + Added in the MSReal, MSNText, MSSmallDateTime, MSTime, + MSDateTimeOffset, and MSDateTime2 types + + .. change:: + :tags: sqlite + :tickets: 1266 + + Table reflection now stores the actual DefaultClause value for + the column. + + .. change:: + :tags: sqlite + :tickets: + + bugfixes, behavioral changes + + .. change:: + :tags: orm + :tickets: + + Exceptions raised during compile_mappers() are now preserved + to provide "sticky behavior" - if a hasattr() call on a + pre-compiled mapped attribute triggers a failing compile and + suppresses the exception, subsequent compilation is blocked + and the exception will be reiterated on the next compile() + call. This issue occurs frequently when using declarative. + + .. change:: + :tags: orm + :tickets: + + property.of_type() is now recognized on a single-table + inheriting target, when used in the context of + prop.of_type(..).any()/has(), as well as + query.join(prop.of_type(...)). + + .. change:: + :tags: orm + :tickets: + + query.join() raises an error when the target of the join + doesn't match the property-based attribute - while it's + unlikely anyone is doing this, the SQLAlchemy author was + guilty of this particular loosey-goosey behavior. + + .. change:: + :tags: orm + :tickets: 1272 + + Fixed bug when using weak_instance_map=False where modified + events would not be intercepted for a flush(). + + .. change:: + :tags: orm + :tickets: 1268 + + Fixed some deep "column correspondence" issues which could + impact a Query made against a selectable containing multiple + versions of the same table, as well as unions and similar + which contained the same table columns in different column + positions at different levels. + + .. change:: + :tags: orm + :tickets: + + Custom comparator classes used in conjunction with + column_property(), relation() etc. can define new comparison + methods on the Comparator, which will become available via + __getattr__() on the InstrumentedAttribute. In the case of + synonym() or comparable_property(), attributes are resolved + first on the user-defined descriptor, then on the user-defined + comparator. + + .. change:: + :tags: orm + :tickets: 976 + + Added ScopedSession.is_active accessor. + + .. change:: + :tags: orm + :tickets: 1262 + + Can pass mapped attributes and column objects as keys to + query.update({}). + + .. change:: + :tags: orm + :tickets: + + Mapped attributes passed to the values() of an expression + level insert() or update() will use the keys of the mapped + columns, not that of the mapped attribute. + + .. change:: + :tags: orm + :tickets: 1242 + + Corrected problem with Query.delete() and Query.update() not + working properly with bind parameters. + + .. change:: + :tags: orm + :tickets: + + Query.select_from(), from_statement() ensure that the given + argument is a FromClause, or Text/Select/Union, respectively. + + .. change:: + :tags: orm + :tickets: 1253 + + Query() can be passed a "composite" attribute as a column + expression and it will be expanded. Somewhat related to. + + .. change:: + :tags: orm + :tickets: + + Query() is a little more robust when passed various column + expressions such as strings, clauselists, text() constructs + (which may mean it just raises an error more nicely). + + .. change:: + :tags: orm + :tickets: + + first() works as expected with Query.from_statement(). + + .. change:: + :tags: orm + :tickets: + + Fixed bug introduced in 0.5rc4 involving eager loading not + functioning for properties which were added to a mapper + post-compile using add_property() or equivalent. + + .. change:: + :tags: orm + :tickets: + + Fixed bug where many-to-many relation() with viewonly=True + would not correctly reference the link between + secondary->remote. + + .. change:: + :tags: orm + :tickets: 1232 + + Duplicate items in a list-based collection will be maintained + when issuing INSERTs to a "secondary" table in a many-to-many + relation. Assuming the m2m table has a unique or primary key + constraint on it, this will raise the expected constraint + violation instead of silently dropping the duplicate + entries. Note that the old behavior remains for a one-to-many + relation since collection entries in that case don't result in + INSERT statements and SQLA doesn't manually police + collections. + + .. change:: + :tags: orm + :tickets: + + Query.add_column() can accept FromClause objects in the same + manner as session.query() can. + + .. change:: + :tags: orm + :tickets: + + Comparison of many-to-one relation to NULL is properly + converted to IS NOT NULL based on not_(). + + .. change:: + :tags: orm + :tickets: 1087 + + Extra checks added to ensure explicit + primaryjoin/secondaryjoin are ClauseElement instances, to + prevent more confusing errors later on. + + .. change:: + :tags: orm + :tickets: 1236 + + Improved mapper() check for non-class classes. + + .. change:: + :tags: orm + :tickets: 5051 + + comparator_factory argument is now documented and supported by + all MapperProperty types, including column_property(), + relation(), backref(), and synonym(). + + .. change:: + :tags: orm + :tickets: + + Changed the name of PropertyLoader to RelationProperty, to be + consistent with all the other names. PropertyLoader is still + present as a synonym. + + .. change:: + :tags: orm + :tickets: 1099, 1228 + + fixed "double iter()" call causing bus errors in shard API, + removed errant result.close() left over from the 0.4 + version. + + .. change:: + :tags: orm + :tickets: + + made Session.merge cascades not trigger autoflush. Fixes + merged instances getting prematurely inserted with missing + values. + + .. change:: + :tags: orm + :tickets: + + Two fixes to help prevent out-of-band columns from being + rendered in polymorphic_union inheritance scenarios (which + then causes extra tables to be rendered in the FROM clause + causing cartesian products): + + - improvements to "column adaption" for a->b->c inheritance + situations to better locate columns that are related to + one another via multiple levels of indirection, rather + than rendering the non-adapted column. + + - the "polymorphic discriminator" column is only rendered + for the actual mapper being queried against. The column + won't be "pulled in" from a subclass or superclass mapper + since it's not needed. + + .. change:: + :tags: orm + :tickets: 1072 + + Fixed shard_id argument on ShardedSession.execute(). + + .. change:: + :tags: sql + :tickets: 1256 + + Columns can again contain percent signs within their + names. + + .. change:: + :tags: sql + :tickets: + + sqlalchemy.sql.expression.Function is now a public class. It + can be subclassed to provide user-defined SQL functions in an + imperative style, including with pre-established behaviors. + The postgis.py example illustrates one usage of this. + + .. change:: + :tags: sql + :tickets: + + PickleType now favors == comparison by default, if the + incoming object (such as a dict) implements __eq__(). If the + object does not implement __eq__() and mutable=True, a + deprecation warning is raised. + + .. change:: + :tags: sql + :tickets: 1215 + + Fixed the import weirdness in sqlalchemy.sql to not export + __names__. + + .. change:: + :tags: sql + :tickets: 1238 + + Using the same ForeignKey object repeatedly raises an error + instead of silently failing later. + + .. change:: + :tags: sql + :tickets: + + Added NotImplementedError for params() method on + Insert/Update/Delete constructs. These items currently don't + support this functionality, which also would be a little + misleading compared to values(). + + .. change:: + :tags: sql + :tickets: 650 + + Reflected foreign keys will properly locate their referenced + column, even if the column was given a "key" attribute + different from the reflected name. This is achieved via a new + flag on ForeignKey/ForeignKeyConstraint called "link_to_name", + if True means the given name is the referred-to column's name, + not its assigned key. + + .. change:: + :tags: sql + :tickets: 1253 + + select() can accept a ClauseList as a column in the same way + as a Table or other selectable and the interior expressions + will be used as column elements. + + .. change:: + :tags: sql + :tickets: + + the "passive" flag on session.is_modified() is correctly + propagated to the attribute manager. + + .. change:: + :tags: sql + :tickets: + + union() and union_all() will not whack any order_by() that has + been applied to the select()s inside. If you union() a + select() with order_by() (presumably to support LIMIT/OFFSET), + you should also call self_group() on it to apply parenthesis. + + .. change:: + :tags: engine/pool + :tickets: 1246 + + Connection.invalidate() checks for closed status to avoid + attribute errors. + + .. change:: + :tags: engine/pool + :tickets: 1094 + + NullPool supports reconnect on failure behavior. + + .. change:: + :tags: engine/pool + :tickets: 799 + + Added a mutex for the initial pool creation when using + pool.manage(dbapi). This prevents a minor case of "dogpile" + behavior which would otherwise occur upon a heavy load + startup. + + .. change:: + :tags: engine/pool + :tickets: + + _execute_clauseelement() goes back to being a private method. + Subclassing Connection is not needed now that ConnectionProxy + is available. + + .. change:: + :tags: documentation + :tickets: 1149, 1200 + + Tickets. + + .. change:: + :tags: documentation + :tickets: + + Added note about create_session() defaults. + + .. change:: + :tags: documentation + :tickets: + + Added section about metadata.reflect(). + + .. change:: + :tags: documentation + :tickets: + + Updated `TypeDecorator` section. + + .. change:: + :tags: documentation + :tickets: + + Rewrote the "threadlocal" strategy section of the docs due to + recent confusion over this feature. + + .. change:: + :tags: documentation + :tickets: + + Removed badly out of date 'polymorphic_fetch' and + 'select_table' docs from inheritance, reworked the second half + of "joined table inheritance". + + .. change:: + :tags: documentation + :tickets: + + Documented `comparator_factory` kwarg, added new doc section + "Custom Comparators". + + .. change:: + :tags: mssql + :tickets: 1254 + + Refactored the Date/Time types. The ``smalldatetime`` data + type no longer truncates to a date only, and will now be + mapped to the MSSmallDateTime type. + + .. change:: + :tags: mssql + :tickets: + + Corrected an issue with Numerics to accept an int. + + .. change:: + :tags: mssql + :tickets: + + Mapped ``char_length`` to the ``LEN()`` function. + + .. change:: + :tags: mssql + :tickets: + + If an ``INSERT`` includes a subselect the ``INSERT`` is + converted from an ``INSERT INTO VALUES`` construct to a + ``INSERT INTO SELECT`` construct. + + .. change:: + :tags: mssql + :tickets: + + If the column is part of a ``primary_key`` it will be ``NOT + NULL`` since MSSQL doesn't allow ``NULL`` in primary_key + columns. + + .. change:: + :tags: mssql + :tickets: 1249 + + ``MSBinary`` now returns a ``BINARY`` instead of an + ``IMAGE``. This is a backwards incompatible change in that + ``BINARY`` is a fixed length data type whereas ``IMAGE`` is a + variable length data type. + + .. change:: + :tags: mssql + :tickets: 1258 + + ``get_default_schema_name`` is now reflected from the database + based on the user's default schema. This only works with MSSQL + 2005 and later. + + .. change:: + :tags: mssql + :tickets: 1248 + + Added collation support through the use of a new collation + argument. This is supported on the following types: char, + nchar, varchar, nvarchar, text, ntext. + + .. change:: + :tags: mssql + :tickets: + + Changes to the connection string parameters favor DSN as the + default specification for pyodbc. See the mssql.py docstring + for detailed usage instructions. + + .. change:: + :tags: mssql + :tickets: + + Added experimental support of savepoints. It currently does + not work fully with sessions. + + .. change:: + :tags: mssql + :tickets: 1243 + + Support for three levels of column nullability: NULL, NOT + NULL, and the database's configured default. The default + Column configuration (nullable=True) will now generate NULL in + the DDL. Previously no specification was emitted and the + database default would take effect (usually NULL, but not + always). To explicitly request the database default, + configure columns with nullable=None and no specification will + be emitted in DDL. This is backwards incompatible + behavior. + + .. change:: + :tags: postgres + :tickets: 1267 + + "%" signs in text() constructs are automatically escaped to + "%%". Because of the backwards incompatible nature of this + change, a warning is emitted if '%%' is detected in the + string. + + .. change:: + :tags: postgres + :tickets: + + Calling alias.execute() in conjunction with + server_side_cursors won't raise AttributeError. + + .. change:: + :tags: postgres + :tickets: 714 + + Added Index reflection support to PostgreSQL, using a great + patch we long neglected, submitted by Ken + Kuhlman. + + .. change:: + :tags: oracle + :tickets: + + Adjusted the format of create_xid() to repair two-phase + commit. We now have field reports of Oracle two-phase commit + working properly with this change. + + .. change:: + :tags: oracle + :tickets: 1233 + + Added OracleNVarchar type, produces NVARCHAR2, and also + subclasses Unicode so that convert_unicode=True by default. + NVARCHAR2 reflects into this type automatically so these + columns pass unicode on a reflected table with no explicit + convert_unicode=True flags. + + .. change:: + :tags: oracle + :tickets: 1265 + + Fixed bug which was preventing out params of certain types + from being received; thanks a ton to huddlej at wwu.edu ! + + .. change:: + :tags: mysql + :tickets: + + "%" signs in text() constructs are automatically escaped to + "%%". Because of the backwards incompatible nature of this + change, a warning is emitted if '%%' is detected in the + string. + + .. change:: + :tags: mysql + :tickets: 1241 + + Fixed bug in exception raise when FK columns not present + during reflection. + + .. change:: + :tags: mysql + :tickets: + + Fixed bug involving reflection of a remote-schema table with a + foreign key ref to another table in that schema. + + .. change:: + :tags: associationproxy + :tickets: + + The association proxy properties are make themselves available + at the class level, e.g. MyClass.aproxy. Previously this + evaluated to None. + + .. change:: + :tags: declarative + :tickets: + + The full list of arguments accepted as string by backref() + includes 'primaryjoin', 'secondaryjoin', 'secondary', + 'foreign_keys', 'remote_side', 'order_by'. + +.. changelog:: + :version: 0.5.0rc4 + :released: Fri Nov 14 2008 + + .. change:: + :tags: orm + :tickets: + + Query.count() has been enhanced to do the "right thing" in a + wider variety of cases. It can now count multiple-entity + queries, as well as column-based queries. Note that this means + if you say query(A, B).count() without any joining criterion, + it's going to count the cartesian product of A*B. Any query + which is against column-based entities will automatically + issue "SELECT count(1) FROM (SELECT...)" so that the real + rowcount is returned, meaning a query such as + query(func.count(A.name)).count() will return a value of one, + since that query would return one row. + + .. change:: + :tags: orm + :tickets: + + Lots of performance tuning. A rough guesstimate over various + ORM operations places it 10% faster over 0.5.0rc3, 25-30% over + 0.4.8. + + .. change:: + :tags: orm + :tickets: + + bugfixes and behavioral changes + + .. change:: + :tags: general + :tickets: + + global "propigate"->"propagate" change. + + .. change:: + :tags: orm + :tickets: + + Adjustments to the enhanced garbage collection on + InstanceState to better guard against errors due to lost + state. + + .. change:: + :tags: orm + :tickets: 1220 + + Query.get() returns a more informative error message when + executed against multiple entities. + + .. change:: + :tags: orm + :tickets: 1140, 1221 + + Restored NotImplementedError on Cls.relation.in_() + + .. change:: + :tags: orm + :tickets: 1226 + + Fixed PendingDeprecationWarning involving order_by parameter + on relation(). + + .. change:: + :tags: sql + :tickets: + + Removed the 'properties' attribute of the Connection object, + Connection.info should be used. + + .. change:: + :tags: sql + :tickets: + + Restored "active rowcount" fetch before ResultProxy autocloses + the cursor. This was removed in 0.5rc3. + + .. change:: + :tags: sql + :tickets: + + Rearranged the `load_dialect_impl()` method in `TypeDecorator` + such that it will take effect even if the user-defined + `TypeDecorator` uses another `TypeDecorator` as its impl. + + .. change:: + :tags: access + :tickets: + + Added support for Currency type. + + .. change:: + :tags: access + :tickets: 1017 + + Functions were not return their result. + + .. change:: + :tags: access + :tickets: 1017 + + Corrected problem with joins. Access only support LEFT OUTER + or INNER not just JOIN by itself. + + .. change:: + :tags: mssql + :tickets: + + Lots of cleanup and fixes to correct problems with limit and + offset. + + .. change:: + :tags: mssql + :tickets: + + Correct situation where subqueries as part of a binary + expression need to be translated to use the IN and NOT IN + syntax. + + .. change:: + :tags: mssql + :tickets: 1216 + + Fixed E Notation issue that prevented the ability to insert + decimal values less than 1E-6. + + .. change:: + :tags: mssql + :tickets: 1217 + + Corrected problems with reflection when dealing with schemas, + particularly when those schemas are the default + schema. + + .. change:: + :tags: mssql + :tickets: + + Corrected problem with casting a zero length item to a + varchar. It now correctly adjusts the CAST. + + .. change:: + :tags: ext + :tickets: + + Can now use a custom "inherit_condition" in __mapper_args__ + when using declarative. + + .. change:: + :tags: ext + :tickets: + + fixed string-based "remote_side", "order_by" and others not + propagating correctly when used in backref(). + +.. changelog:: + :version: 0.5.0rc3 + :released: Fri Nov 07 2008 + + .. change:: + :tags: orm + :tickets: + + Added two new hooks to SessionExtension: after_bulk_delete() + and after_bulk_update(). after_bulk_delete() is called after + a bulk delete() operation on a query. after_bulk_update() is + called after a bulk update() operation on a query. + + .. change:: + :tags: sql + :tickets: + + SQL compiler optimizations and complexity reduction. The call + count for compiling a typical select() construct is 20% less + versus 0.5.0rc2. + + .. change:: + :tags: sql + :tickets: 1211 + + Dialects can now generate label names of adjustable + length. Pass in the argument "label_length=" to + create_engine() to adjust how many characters max will be + present in dynamically generated column labels, i.e. + "somecolumn AS somelabel". Any value less than 6 will result + in a label of minimal size, consisting of an underscore and a + numeric counter. The compiler uses the value of + dialect.max_identifier_length as a default. + + .. change:: + :tags: ext + :tickets: + + Added a new extension sqlalchemy.ext.serializer. Provides + Serializer/Deserializer "classes" which mirror + Pickle/Unpickle, as well as dumps() and loads(). This + serializer implements an "external object" pickler which keeps + key context-sensitive objects, including engines, sessions, + metadata, Tables/Columns, and mappers, outside of the pickle + stream, and can later restore the pickle using any + engine/metadata/session provider. This is used not for + pickling regular object instances, which are pickleable + without any special logic, but for pickling expression objects + and full Query objects, such that all mapper/engine/session + dependencies can be restored at unpickle time. + + .. change:: + :tags: oracle + :tickets: + + Wrote a docstring for Oracle dialect. Apparently that Ohloh + "few source code comments" label is starting to sting :). + + .. change:: + :tags: oracle + :tickets: 536 + + Removed FIRST_ROWS() optimize flag when using LIMIT/OFFSET, + can be reenabled with optimize_limits=True create_engine() + flag. + + .. change:: + :tags: oracle + :tickets: + + bugfixes and behavioral changes + + .. change:: + :tags: orm + :tickets: + + "not equals" comparisons of simple many-to-one relation to an + instance will not drop into an EXISTS clause and will compare + foreign key columns instead. + + .. change:: + :tags: orm + :tickets: + + Removed not-really-working use cases of comparing a collection + to an iterable. Use contains() to test for collection + membership. + + .. change:: + :tags: orm + :tickets: 1171 + + Improved the behavior of aliased() objects such that they more + accurately adapt the expressions generated, which helps + particularly with self-referential comparisons. + + .. change:: + :tags: orm + :tickets: + + Fixed bug involving primaryjoin/secondaryjoin conditions + constructed from class-bound attributes (as often occurs when + using declarative), which later would be inappropriately + aliased by Query, particularly with the various EXISTS based + comparators. + + .. change:: + :tags: orm + :tickets: + + Fixed bug when using multiple query.join() with an + aliased-bound descriptor which would lose the left alias. + + .. change:: + :tags: orm + :tickets: + + Improved weakref identity map memory management to no longer + require mutexing, resurrects garbage collected instance on a + lazy basis for an InstanceState with pending changes. + + .. change:: + :tags: orm + :tickets: + + InstanceState object now removes circular references to itself + upon disposal to keep it outside of cyclic garbage collection. + + .. change:: + :tags: orm + :tickets: + + relation() won't hide unrelated ForeignKey errors inside of + the "please specify primaryjoin" message when determining join + condition. + + .. change:: + :tags: orm + :tickets: 1218 + + Fixed bug in Query involving order_by() in conjunction with + multiple aliases of the same class (will add tests in) + + .. change:: + :tags: orm + :tickets: + + When using Query.join() with an explicit clause for the ON + clause, the clause will be aliased in terms of the left side + of the join, allowing scenarios like query(Source). + from_self().join((Dest, Source.id==Dest.source_id)) to work + properly. + + .. change:: + :tags: orm + :tickets: + + polymorphic_union() function respects the "key" of each Column + if they differ from the column's name. + + .. change:: + :tags: orm + :tickets: 1183 + + Repaired support for "passive-deletes" on a many-to-one + relation() with "delete" cascade. + + .. change:: + :tags: orm + :tickets: 1213 + + Fixed bug in composite types which prevented a primary-key + composite type from being mutated. + + .. change:: + :tags: orm + :tickets: 1202 + + Added more granularity to internal attribute access, such that + cascade and flush operations will not initialize unloaded + attributes and collections, leaving them intact for a + lazy-load later on. Backref events still initialize attrbutes + and collections for pending instances. + + .. change:: + :tags: sql + :tickets: 1212 + + Simplified the check for ResultProxy "autoclose without + results" to be based solely on presence of + cursor.description. All the regexp-based guessing about + statements returning rows has been removed. + + .. change:: + :tags: sql + :tickets: 1194 + + Direct execution of a union() construct will properly set up + result-row processing. + + .. change:: + :tags: sql + :tickets: + + The internal notion of an "OID" or "ROWID" column has been + removed. It's basically not used by any dialect, and the + possibility of its usage with psycopg2's cursor.lastrowid is + basically gone now that INSERT..RETURNING is available. + + .. change:: + :tags: sql + :tickets: + + Removed "default_order_by()" method on all FromClause objects. + + .. change:: + :tags: sql + :tickets: + + Repaired the table.tometadata() method so that a passed-in + schema argument is propagated to ForeignKey constructs. + + .. change:: + :tags: sql + :tickets: + + Slightly changed behavior of IN operator for comparing to + empty collections. Now results in inequality comparison + against self. More portable, but breaks with stored procedures + that aren't pure functions. + + .. change:: + :tags: oracle + :tickets: + + Setting the auto_convert_lobs to False on create_engine() will + also instruct the OracleBinary type to return the cx_oracle + LOB object unchanged. + + .. change:: + :tags: mysql + :tickets: + + Fixed foreign key reflection in the edge case where a Table's + explicit schema= is the same as the schema (database) the + connection is attached to. + + .. change:: + :tags: mysql + :tickets: + + No longer expects include_columns in table reflection to be + lower case. + + .. change:: + :tags: ext + :tickets: 1174 + + Fixed bug preventing declarative-bound "column" objects from + being used in column_mapped_collection(). + + .. change:: + :tags: misc + :tickets: 1077 + + util.flatten_iterator() func doesn't interpret strings with + __iter__() methods as iterators, such as in pypy. + +.. changelog:: + :version: 0.5.0rc2 + :released: Sun Oct 12 2008 + + .. change:: + :tags: orm + :tickets: + + Fixed bug involving read/write relation()s that contain + literal or other non-column expressions within their + primaryjoin condition equated to a foreign key column. + + .. change:: + :tags: orm + :tickets: + + "non-batch" mode in mapper(), a feature which allows mapper + extension methods to be called as each instance is + updated/inserted, now honors the insert order of the objects + given. + + .. change:: + :tags: orm + :tickets: + + Fixed RLock-related bug in mapper which could deadlock upon + reentrant mapper compile() calls, something that occurs when + using declarative constructs inside of ForeignKey objects. + + .. change:: + :tags: orm + :tickets: + + ScopedSession.query_property now accepts a query_cls factory, + overriding the session's configured query_cls. + + .. change:: + :tags: orm + :tickets: + + Fixed shared state bug interfering with ScopedSession.mapper's + ability to apply default __init__ implementations on object + subclasses. + + .. change:: + :tags: orm + :tickets: 1177 + + Fixed up slices on Query (i.e. query[x:y]) to work properly + for zero length slices, slices with None on either end. + + .. change:: + :tags: orm + :tickets: + + Added an example illustrating Celko's "nested sets" as a + SQLA mapping. + + .. change:: + :tags: orm + :tickets: + + contains_eager() with an alias argument works even when + the alias is embedded in a SELECT, as when sent to the + Query via query.select_from(). + + .. change:: + :tags: orm + :tickets: 1180 + + contains_eager() usage is now compatible with a Query that + also contains a regular eager load and limit/offset, in that + the columns are added to the Query-generated subquery. + + .. change:: + :tags: orm + :tickets: + + session.execute() will execute a Sequence object passed to + it (regression from 0.4). + + .. change:: + :tags: orm + :tickets: + + Removed the "raiseerror" keyword argument from object_mapper() + and class_mapper(). These functions raise in all cases + if the given class/instance is not mapped. + + .. change:: + :tags: orm + :tickets: + + Fixed session.transaction.commit() on a autocommit=False + session not starting a new transaction. + + .. change:: + :tags: orm + :tickets: + + Some adjustments to Session.identity_map's weak referencing + behavior to reduce asynchronous GC side effects. + + .. change:: + :tags: orm + :tickets: 1182 + + Adjustment to Session's post-flush accounting of newly + "clean" objects to better protect against operating on + objects as they're asynchronously gc'ed. + + .. change:: + :tags: sql + :tickets: 1074 + + column.in_(someselect) can now be used as a columns-clause + expression without the subquery bleeding into the FROM clause + + .. change:: + :tags: sqlite + :tickets: 968 + + Overhauled SQLite date/time bind/result processing to use + regular expressions and format strings, rather than + strptime/strftime, to generically support pre-1900 dates, + dates with microseconds. + + .. change:: + :tags: sqlite + :tickets: + + String's (and Unicode's, UnicodeText's, etc.) convert_unicode + logic disabled in the sqlite dialect, to adjust for pysqlite + 2.5.0's new requirement that only Python unicode objects are + accepted; + http://itsystementwicklung.de/pipermail/list-pysqlite/2008-March/000018.html + + .. change:: + :tags: mysql + :tickets: + + Temporary tables are now reflectable. + + .. change:: + :tags: oracle + :tickets: 1187 + + Oracle will detect string-based statements which contain + comments at the front before a SELECT as SELECT statements. + +.. changelog:: + :version: 0.5.0rc1 + :released: Thu Sep 11 2008 + + .. change:: + :tags: orm + :tickets: + + Query now has delete() and update(values) methods. This allows + to perform bulk deletes/updates with the Query object. + + .. change:: + :tags: orm + :tickets: + + The RowTuple object returned by Query(*cols) now features + keynames which prefer mapped attribute names over column keys, + column keys over column names, i.e. Query(Class.foo, + Class.bar) will have names "foo" and "bar" even if those are + not the names of the underlying Column objects. Direct Column + objects such as Query(table.c.col) will return the "key" + attribute of the Column. + + .. change:: + :tags: orm + :tickets: + + Added scalar() and value() methods to Query, each return a + single scalar value. scalar() takes no arguments and is + roughly equivalent to first()[0], value() + takes a single column expression and is roughly equivalent to + values(expr).next()[0]. + + .. change:: + :tags: orm + :tickets: + + Improved the determination of the FROM clause when placing SQL + expressions in the query() list of entities. In particular + scalar subqueries should not "leak" their inner FROM objects + out into the enclosing query. + + .. change:: + :tags: orm + :tickets: + + Joins along a relation() from a mapped class to a mapped + subclass, where the mapped subclass is configured with single + table inheritance, will include an IN clause which limits the + subtypes of the joined class to those requested, within the ON + clause of the join. This takes effect for eager load joins as + well as query.join(). Note that in some scenarios the IN + clause will appear in the WHERE clause of the query as well + since this discrimination has multiple trigger points. + + .. change:: + :tags: orm + :tickets: + + AttributeExtension has been refined such that the event + is fired before the mutation actually occurs. Additionally, + the append() and set() methods must now return the given value, + which is used as the value to be used in the mutation operation. + This allows creation of validating AttributeListeners which + raise before the action actually occurs, and which can change + the given value into something else before its used. + + .. change:: + :tags: orm + :tickets: + + column_property(), composite_property(), and relation() now + accept a single or list of AttributeExtensions using the + "extension" keyword argument. + + .. change:: + :tags: orm + :tickets: + + query.order_by().get() silently drops the "ORDER BY" from + the query issued by GET but does not raise an exception. + + .. change:: + :tags: orm + :tickets: + + Added a Validator AttributeExtension, as well as a + @validates decorator which is used in a similar fashion + as @reconstructor, and marks a method as validating + one or more mapped attributes. + + .. change:: + :tags: orm + :tickets: 1140 + + class.someprop.in_() raises NotImplementedError pending the + implementation of "in_" for relation + + .. change:: + :tags: orm + :tickets: 1127 + + Fixed primary key update for many-to-many collections where + the collection had not been loaded yet + + .. change:: + :tags: orm + :tickets: + + Fixed bug whereby deferred() columns with a group in conjunction + with an otherwise unrelated synonym() would produce + an AttributeError during deferred load. + + .. change:: + :tags: orm + :tickets: 1128 + + The before_flush() hook on SessionExtension takes place before + the list of new/dirty/deleted is calculated for the final + time, allowing routines within before_flush() to further + change the state of the Session before the flush proceeds. + + .. change:: + :tags: orm + :tickets: + + The "extension" argument to Session and others can now + optionally be a list, supporting events sent to multiple + SessionExtension instances. Session places SessionExtensions + in Session.extensions. + + .. change:: + :tags: orm + :tickets: + + Reentrant calls to flush() raise an error. This also serves + as a rudimentary, but not foolproof, check against concurrent + calls to Session.flush(). + + .. change:: + :tags: orm + :tickets: + + Improved the behavior of query.join() when joining to + joined-table inheritance subclasses, using explicit join + criteria (i.e. not on a relation). + + .. change:: + :tags: orm + :tickets: + + @orm.attributes.reconstitute and + MapperExtension.reconstitute have been renamed to + @orm.reconstructor and MapperExtension.reconstruct_instance + + .. change:: + :tags: orm + :tickets: 1129 + + Fixed @reconstructor hook for subclasses which inherit from a + base class. + + .. change:: + :tags: orm + :tickets: 1132 + + The composite() property type now supports a + __set_composite_values__() method on the composite class which + is required if the class represents state using attribute + names other than the column's keynames; default-generated + values now get populated properly upon flush. Also, + composites with attributes set to None compare correctly. + + .. change:: + :tags: orm + :tickets: + + The 3-tuple of iterables returned by attributes.get_history() + may now be a mix of lists and tuples. (Previously members + were always lists.) + + .. change:: + :tags: orm + :tickets: 1151 + + Fixed bug whereby changing a primary key attribute on an + entity where the attribute's previous value had been expired + would produce an error upon flush(). + + .. change:: + :tags: orm + :tickets: + + Fixed custom instrumentation bug whereby get_instance_dict() + was not called for newly constructed instances not loaded + by the ORM. + + .. change:: + :tags: orm + :tickets: 1150 + + Session.delete() adds the given object to the session if + not already present. This was a regression bug from 0.4. + + .. change:: + :tags: orm + :tickets: + + The `echo_uow` flag on `Session` is deprecated, and unit-of-work + logging is now application-level only, not per-session level. + + .. change:: + :tags: orm + :tickets: 1153 + + Removed conflicting `contains()` operator from + `InstrumentedAttribute` which didn't accept `escape` kwaarg. + + .. change:: + :tags: declarative + :tickets: 1161 + + Fixed bug whereby mapper couldn't initialize if a composite + primary key referenced another table that was not defined + yet. + + .. change:: + :tags: declarative + :tickets: + + Fixed exception throw which would occur when string-based + primaryjoin condition was used in conjunction with backref. + + .. change:: + :tags: schema + :tickets: 1033 + + Added "sorted_tables" accessor to MetaData, which returns + Table objects sorted in order of dependency as a list. + This deprecates the MetaData.table_iterator() method. + The "reverse=False" keyword argument has also been + removed from util.sort_tables(); use the Python + 'reversed' function to reverse the results. + + .. change:: + :tags: schema + :tickets: + + The 'length' argument to all Numeric types has been renamed + to 'scale'. 'length' is deprecated and is still accepted + with a warning. + + .. change:: + :tags: schema + :tickets: + + Dropped 0.3-compatibility for user defined types + (convert_result_value, convert_bind_param). + + .. change:: + :tags: sql + :tickets: 1068 + + Temporarily rolled back the "ORDER BY" enhancement from. This feature is on hold pending further + development. + + .. change:: + :tags: sql + :tickets: + + The exists() construct won't "export" its contained list + of elements as FROM clauses, allowing them to be used more + effectively in the columns clause of a SELECT. + + .. change:: + :tags: sql + :tickets: 798 + + and_() and or_() now generate a ColumnElement, allowing + boolean expressions as result columns, i.e. + select([and_(1, 0)]). + + .. change:: + :tags: sql + :tickets: + + Bind params now subclass ColumnElement which allows them to be + selectable by orm.query (they already had most ColumnElement + semantics). + + .. change:: + :tags: sql + :tickets: + + Added select_from() method to exists() construct, which becomes + more and more compatible with a regular select(). + + .. change:: + :tags: sql + :tickets: 1160 + + Added func.min(), func.max(), func.sum() as "generic functions", + which basically allows for their return type to be determined + automatically. Helps with dates on SQLite, decimal types, + others. + + .. change:: + :tags: sql + :tickets: + + added decimal.Decimal as an "auto-detect" type; bind parameters + and generic functions will set their type to Numeric when a + Decimal is used. + + .. change:: + :tags: mysql + :tickets: + + The 'length' argument to MSInteger, MSBigInteger, MSTinyInteger, + MSSmallInteger and MSYear has been renamed to 'display_width'. + + .. change:: + :tags: mysql + :tickets: 1146 + + Added MSMediumInteger type. + + .. change:: + :tags: mysql + :tickets: + + the function func.utc_timestamp() compiles to UTC_TIMESTAMP, without + the parenthesis, which seem to get in the way when using in + conjunction with executemany(). + + .. change:: + :tags: oracle + :tickets: 536 + + limit/offset no longer uses ROW NUMBER OVER to limit rows, + and instead uses subqueries in conjunction with a special + Oracle optimization comment. Allows LIMIT/OFFSET to work + in conjunction with DISTINCT. + + .. change:: + :tags: oracle + :tickets: 1155 + + has_sequence() now takes the current "schema" argument into + account + + .. change:: + :tags: oracle + :tickets: 1121 + + added BFILE to reflected type names + +.. changelog:: + :version: 0.5beta3 + :released: Mon Aug 04 2008 + + .. change:: + :tags: orm + :tickets: + + The "entity_name" feature of SQLAlchemy mappers has been + removed. For rationale, see http://tinyurl.com/6nm2ne + + .. change:: + :tags: orm + :tickets: + + the "autoexpire" flag on Session, sessionmaker(), and + scoped_session() has been renamed to "expire_on_commit". It + does not affect the expiration behavior of rollback(). + + .. change:: + :tags: orm + :tickets: + + fixed endless loop bug which could occur within a mapper's + deferred load of inherited attributes. + + .. change:: + :tags: orm + :tickets: + + a legacy-support flag "_enable_transaction_accounting" flag + added to Session which when False, disables all + transaction-level object accounting, including expire on + rollback, expire on commit, new/deleted list maintenance, and + autoflush on begin. + + .. change:: + :tags: orm + :tickets: + + The 'cascade' parameter to relation() accepts None as a value, + which is equivalent to no cascades. + + .. change:: + :tags: orm + :tickets: + + A critical fix to dynamic relations allows the "modified" + history to be properly cleared after a flush(). + + .. change:: + :tags: orm + :tickets: + + user-defined @properties on a class are detected and left in + place during mapper initialization. This means that a + table-bound column of the same name will not be mapped at all + if a @property is in the way (and the column is not remapped + to a different name), nor will an instrumented attribute from + an inherited class be applied. The same rules apply for names + excluded using the include_properties/exclude_properties + collections. + + .. change:: + :tags: orm + :tickets: + + Added a new SessionExtension hook called after_attach(). This + is called at the point of attachment for objects via add(), + add_all(), delete(), and merge(). + + .. change:: + :tags: orm + :tickets: 1111 + + A mapper which inherits from another, when inheriting the + columns of its inherited mapper, will use any reassigned + property names specified in that inheriting mapper. + Previously, if "Base" had reassigned "base_id" to the name + "id", "SubBase(Base)" would still get an attribute called + "base_id". This could be worked around by explicitly stating + the column in each submapper as well but this is fairly + unworkable and also impossible when using declarative. + + .. change:: + :tags: orm + :tickets: + + Fixed a series of potential race conditions in Session whereby + asynchronous GC could remove unmodified, no longer referenced + items from the session as they were present in a list of items + to be processed, typically during session.expunge_all() and + dependent methods. + + .. change:: + :tags: orm + :tickets: + + Some improvements to the _CompileOnAttr mechanism which should + reduce the probability of "Attribute x was not replaced during + compile" warnings. (this generally applies to SQLA hackers, + like Elixir devs). + + .. change:: + :tags: orm + :tickets: + + Fixed bug whereby the "unsaved, pending instance" FlushError + raised for a pending orphan would not take superclass mappers + into account when generating the list of relations responsible + for the error. + + .. change:: + :tags: sql + :tickets: + + func.count() with no arguments renders as COUNT(*), equivalent + to func.count(text('*')). + + .. change:: + :tags: sql + :tickets: 1068 + + simple label names in ORDER BY expressions render as + themselves, and not as a re-statement of their corresponding + expression. This feature is currently enabled only for + SQLite, MySQL, and PostgreSQL. It can be enabled on other + dialects as each is shown to support this + behavior. + + .. change:: + :tags: ext + :tickets: + + Class-bound attributes sent as arguments to relation()'s + remote_side and foreign_keys parameters are now accepted, + allowing them to be used with declarative. Additionally fixed + bugs involving order_by being specified as a class-bound + attribute in conjunction with eager loading. + + .. change:: + :tags: ext + :tickets: + + declarative initialization of Columns adjusted so that + non-renamed columns initialize in the same way as a non + declarative mapper. This allows an inheriting mapper to set + up its same-named "id" columns in particular such that the + parent "id" column is favored over the child column, reducing + database round trips when this value is requested. + + .. change:: + :tags: mysql + :tickets: 1110 + + Quoting of MSEnum values for use in CREATE TABLE is now + optional & will be quoted on demand as required. (Quoting was + always optional for use with existing tables.) + +.. changelog:: + :version: 0.5beta2 + :released: Mon Jul 14 2008 + + .. change:: + :tags: orm + :tickets: 870 + + In addition to expired attributes, deferred attributes also + load if their data is present in the result set. + + .. change:: + :tags: orm + :tickets: + + session.refresh() raises an informative error message if the + list of attributes does not include any column-based + attributes. + + .. change:: + :tags: orm + :tickets: + + query() raises an informative error message if no columns or + mappers are specified. + + .. change:: + :tags: orm + :tickets: + + lazy loaders now trigger autoflush before proceeding. This + allows expire() of a collection or scalar relation to function + properly in the context of autoflush. + + .. change:: + :tags: orm + :tickets: 887 + + column_property() attributes which represent SQL expressions + or columns that are not present in the mapped tables (such as + those from views) are automatically expired after an INSERT or + UPDATE, assuming they have not been locally modified, so that + they are refreshed with the most recent data upon access. + + .. change:: + :tags: orm + :tickets: 1082 + + Fixed explicit, self-referential joins between two + joined-table inheritance mappers when using query.join(cls, + aliased=True). + + .. change:: + :tags: orm + :tickets: + + Fixed query.join() when used in conjunction with a + columns-only clause and an SQL-expression ON clause in the + join. + + .. change:: + :tags: orm + :tickets: + + The "allow_column_override" flag from mapper() has been + removed. This flag is virtually always misunderstood. Its + specific functionality is available via the + include_properties/exclude_properties mapper arguments. + + .. change:: + :tags: orm + :tickets: 1066 + + Repaired `__str__()` method on Query. + + .. change:: + :tags: orm + :tickets: + + Session.bind gets used as a default even when table/mapper + specific binds are defined. + + .. change:: + :tags: schema + :tickets: 1075 + + Added prefixes option to `Table` that accepts a list of + strings to insert after CREATE in the CREATE TABLE statement. + + .. change:: + :tags: schema + :tickets: + + Unicode, UnicodeText types now set "assert_unicode" and + "convert_unicode" by default, but accept overriding + **kwargs for these values. + + .. change:: + :tags: sql + :tickets: + + Added new match() operator that performs a full-text search. + Supported on PostgreSQL, SQLite, MySQL, MS-SQL, and Oracle + backends. + + .. change:: + :tags: sqlite + :tickets: 1090 + + Modified SQLite's representation of "microseconds" to match + the output of str(somedatetime), i.e. in that the microseconds + are represented as fractional seconds in string format. This + makes SQLA's SQLite date type compatible with datetimes that + were saved directly using Pysqlite (which just calls str()). + Note that this is incompatible with the existing microseconds + values in a SQLA 0.4 generated SQLite database file. + + To get the old behavior globally: + + from sqlalchemy.databases.sqlite import DateTimeMixin + DateTimeMixin.__legacy_microseconds__ = True + + To get the behavior on individual DateTime types: + + t = sqlite.SLDateTime() + t.__legacy_microseconds__ = True + + Then use "t" as the type on the Column. + + .. change:: + :tags: sqlite + :tickets: + + SQLite Date, DateTime, and Time types only accept Python + datetime objects now, not strings. If you'd like to format + dates as strings yourself with SQLite, use a String type. If + you'd like them to return datetime objects anyway despite + their accepting strings as input, make a TypeDecorator around + String - SQLA doesn't encourage this pattern. + + .. change:: + :tags: extensions + :tickets: 1096 + + Declarative supports a __table_args__ class variable, which is + either a dictionary, or tuple of the form (arg1, arg2, ..., + {kwarg1:value, ...}) which contains positional + kw arguments + to be passed to the Table constructor. + +.. changelog:: + :version: 0.5beta1 + :released: Thu Jun 12 2008 + + .. change:: + :tags: + :tickets: + + The "__init__" trigger/decorator added by mapper now attempts + to exactly mirror the argument signature of the original + __init__. The pass-through for '_sa_session' is no longer + implicit- you must allow for this keyword argument in your + constructor. + + .. change:: + :tags: + :tickets: + + ClassState is renamed to ClassManager. + + .. change:: + :tags: + :tickets: + + Classes may supply their own InstrumentationManager by + providing a __sa_instrumentation_manager__ property. + + .. change:: + :tags: + :tickets: + + Custom instrumentation may use any mechanism to associate a + ClassManager with a class and an InstanceState with an + instance. Attributes on those objects are still the default + association mechanism used by SQLAlchemy's native + instrumentation. + + .. change:: + :tags: + :tickets: + + Moved entity_name, _sa_session_id, and _instance_key from the + instance object to the instance state. These values are still + available in the old way, which is now deprecated, using + descriptors attached to the class. A deprecation warning will + be issued when accessed. + + .. change:: + :tags: + :tickets: + + The _prepare_instrumentation alias for prepare_instrumentation + has been removed. + + .. change:: + :tags: + :tickets: + + sqlalchemy.exceptions has been renamed to sqlalchemy.exc. The + module may be imported under either name. + + .. change:: + :tags: + :tickets: + + ORM-related exceptions are now defined in sqlalchemy.orm.exc. + ConcurrentModificationError, FlushError, and + UnmappedColumnError compatibility aliases are installed in + sqlalchemy.exc during the import of sqlalchemy.orm. + + .. change:: + :tags: + :tickets: + + sqlalchemy.logging has been renamed to sqlalchemy.log. + + .. change:: + :tags: + :tickets: + + The transitional sqlalchemy.log.SADeprecationWarning alias for + the warning's definition in sqlalchemy.exc has been removed. + + .. change:: + :tags: + :tickets: + + exc.AssertionError has been removed and usage replaced with + Python's built-in AssertionError. + + .. change:: + :tags: + :tickets: + + The behavior of MapperExtensions attached to multiple, + entity_name= primary mappers for a single class has been + altered. The first mapper() defined for a class is the only + mapper eligible for the MapperExtension 'instrument_class', + 'init_instance' and 'init_failed' events. This is backwards + incompatible; previously the extensions of last mapper defined + would receive these events. + + .. change:: + :tags: firebird + :tickets: + + Added support for returning values from inserts (2.0+ only), + updates and deletes (2.1+ only). + + .. change:: + :tags: general + :tickets: + + global "propigate"->"propagate" change. + + .. change:: + :tags: orm + :tickets: + + polymorphic_union() function respects the "key" of each + Column if they differ from the column's name. + + .. change:: + :tags: orm + :tickets: 1199 + + Fixed 0.4-only bug preventing composite columns + from working properly with inheriting mappers + + .. change:: + :tags: orm + :tickets: + + Fixed RLock-related bug in mapper which could deadlock upon + reentrant mapper compile() calls, something that occurs when + using declarative constructs inside of ForeignKey objects. + Ported from 0.5. + + .. change:: + :tags: orm + :tickets: 1213 + + Fixed bug in composite types which prevented a primary-key + composite type from being mutated. + + .. change:: + :tags: orm + :tickets: 976 + + Added ScopedSession.is_active accessor. + + .. change:: + :tags: orm + :tickets: 939 + + Class-bound accessor can be used as the argument to + relation() order_by. + + .. change:: + :tags: orm + :tickets: 1072 + + Fixed shard_id argument on ShardedSession.execute(). + + .. change:: + :tags: sql + :tickets: 1246 + + Connection.invalidate() checks for closed status + to avoid attribute errors. + + .. change:: + :tags: sql + :tickets: 1094 + + NullPool supports reconnect on failure behavior. + + .. change:: + :tags: sql + :tickets: 1299 + + The per-dialect cache used by TypeEngine to cache + dialect-specific types is now a WeakKeyDictionary. + This to prevent dialect objects from + being referenced forever for an application that + creates an arbitrarily large number of engines + or dialects. There is a small performance penalty + which will be resolved in 0.6. + + .. change:: + :tags: sql + :tickets: + + Fixed SQLite reflection methods so that non-present + cursor.description, which triggers an auto-cursor + close, will be detected so that no results doesn't + fail on recent versions of pysqlite which raise + an error when fetchone() called with no rows present. + + .. change:: + :tags: postgres + :tickets: 714 + + Added Index reflection support to Postgres, using a + great patch we long neglected, submitted by + Ken Kuhlman. + + .. change:: + :tags: mysql + :tickets: 1241 + + Fixed bug in exception raise when FK columns not present + during reflection. + + .. change:: + :tags: oracle + :tickets: 1265 + + Fixed bug which was preventing out params of certain types + from being received; thanks a ton to huddlej at wwu.edu ! diff --git a/doc/build/changelog/changelog_06.rst b/doc/build/changelog/changelog_06.rst new file mode 100644 index 0000000000..83f316f539 --- /dev/null +++ b/doc/build/changelog/changelog_06.rst @@ -0,0 +1,4762 @@ + +============== +0.6 Changelog +============== + + +.. changelog:: + :version: 0.6.6 + :released: Sat Jan 08 2011 + + .. change:: + :tags: orm + :tickets: + + Fixed bug whereby a non-"mutable" attribute modified event + which occurred on an object that was clean except for + preceding mutable attribute changes would fail to strongly + reference itself in the identity map. This would cause the + object to be garbage collected, losing track of any changes + that weren't previously saved in the "mutable changes" + dictionary. + + .. change:: + :tags: orm + :tickets: 2013 + + Fixed bug whereby "passive_deletes='all'" wasn't passing + the correct symbols to lazy loaders during flush, thereby + causing an unwarranted load. + + .. change:: + :tags: orm + :tickets: 1997 + + Fixed bug which prevented composite mapped + attributes from being used on a mapped select statement.. Note the workings of composite are slated to + change significantly in 0.7. + + .. change:: + :tags: orm + :tickets: 1976 + + active_history flag also added to composite(). + The flag has no effect in 0.6, but is instead + a placeholder flag for forwards compatibility, + as it applies in 0.7 for composites. + + .. change:: + :tags: orm + :tickets: 2002 + + Fixed uow bug whereby expired objects passed to + Session.delete() would not have unloaded references + or collections taken into account when deleting + objects, despite passive_deletes remaining at + its default of False. + + .. change:: + :tags: orm + :tickets: 1987 + + A warning is emitted when version_id_col is specified + on an inheriting mapper when the inherited mapper + already has one, if those column expressions are not + the same. + + .. change:: + :tags: orm + :tickets: 1954 + + "innerjoin" flag doesn't take effect along the chain + of joinedload() joins if a previous join in that chain + is an outer join, thus allowing primary rows without + a referenced child row to be correctly returned + in results. + + .. change:: + :tags: orm + :tickets: 1964 + + Fixed bug regarding "subqueryload" strategy whereby + strategy would fail if the entity was an aliased() + construct. + + .. change:: + :tags: orm + :tickets: 2014 + + Fixed bug regarding "subqueryload" strategy whereby + the join would fail if using a multi-level load + of the form from A->joined-subclass->C + + .. change:: + :tags: orm + :tickets: 1968 + + Fixed indexing of Query objects by -1. It was erroneously + transformed to the empty slice -1:0 that resulted in + IndexError. + + .. change:: + :tags: orm + :tickets: 1971 + + The mapper argument "primary_key" can be passed as a + single column as well as a list or tuple. + The documentation examples that illustrated it as a + scalar value have been changed to lists. + + .. change:: + :tags: orm + :tickets: 1961 + + Added active_history flag to relationship() + and column_property(), forces attribute events to + always load the "old" value, so that it's available to + attributes.get_history(). + + .. change:: + :tags: orm + :tickets: 1977 + + Query.get() will raise if the number of params + in a composite key is too large, as well as too + small. + + .. change:: + :tags: orm + :tickets: 1992 + + Backport of "optimized get" fix from 0.7, + improves the generation of joined-inheritance + "load expired row" behavior. + + .. change:: + :tags: orm + :tickets: + + A little more verbiage to the "primaryjoin" error, + in an unusual condition that the join condition + "works" for viewonly but doesn't work for non-viewonly, + and foreign_keys wasn't used - adds "foreign_keys" to + the suggestion. Also add "foreign_keys" to the + suggestion for the generic "direction" error. + + .. change:: + :tags: sql + :tickets: 1984 + + Fixed operator precedence rules for multiple + chains of a single non-associative operator. + I.e. "x - (y - z)" will compile as "x - (y - z)" + and not "x - y - z". Also works with labels, + i.e. "x - (y - z).label('foo')" + + .. change:: + :tags: sql + :tickets: 1967 + + The 'info' attribute of Column is copied during + Column.copy(), i.e. as occurs when using columns + in declarative mixins. + + .. change:: + :tags: sql + :tickets: + + Added a bind processor for booleans which coerces + to int, for DBAPIs such as pymssql that naively call + str() on values. + + .. change:: + :tags: sql + :tickets: 2000 + + CheckConstraint will copy its 'initially', 'deferrable', + and '_create_rule' attributes within a copy()/tometadata() + + .. change:: + :tags: engine + :tickets: + + The "unicode warning" against non-unicode bind data + is now raised only when the + Unicode type is used explictly; not when + convert_unicode=True is used on the engine + or String type. + + .. change:: + :tags: engine + :tickets: 1978 + + Fixed memory leak in C version of Decimal result + processor. + + .. change:: + :tags: engine + :tickets: 1871 + + Implemented sequence check capability for the C + version of RowProxy, as well as 2.7 style + "collections.Sequence" registration for RowProxy. + + .. change:: + :tags: engine + :tickets: 1998 + + Threadlocal engine methods rollback(), commit(), + prepare() won't raise if no transaction is in progress; + this was a regression introduced in 0.6. + + .. change:: + :tags: engine + :tickets: 2004 + + Threadlocal engine returns itself upon begin(), + begin_nested(); engine then implements contextmanager + methods to allow the "with" statement. + + .. change:: + :tags: postgresql + :tickets: 1984 + + Single element tuple expressions inside an IN clause + parenthesize correctly, also from + + .. change:: + :tags: postgresql + :tickets: 1955 + + Ensured every numeric, float, int code, scalar + array, + are recognized by psycopg2 and pg8000's "numeric" + base type. + + .. change:: + :tags: postgresql + :tickets: 1956 + + Added as_uuid=True flag to the UUID type, will receive + and return values as Python UUID() objects rather than + strings. Currently, the UUID type is only known to + work with psycopg2. + + .. change:: + :tags: postgresql + :tickets: 1989 + + Fixed bug whereby KeyError would occur with non-ENUM + supported PG versions after a pool dispose+recreate + would occur. + + .. change:: + :tags: mysql + :tickets: 1960 + + Fixed error handling for Jython + zxjdbc, such that + has_table() property works again. Regression from + 0.6.3 (we don't have a Jython buildbot, sorry) + + .. change:: + :tags: sqlite + :tickets: 1851 + + The REFERENCES clause in a CREATE TABLE that includes + a remote schema to another table with the same schema + name now renders the remote name without + the schema clause, as required by SQLite. + + .. change:: + :tags: sqlite + :tickets: + + On the same theme, the REFERENCES clause in a CREATE TABLE + that includes a remote schema to a *different* schema + than that of the parent table doesn't render at all, + as cross-schema references do not appear to be supported. + + .. change:: + :tags: mssql + :tickets: 1770 + + The rewrite of index reflection in was + unfortunately not tested correctly, and returned incorrect + results. This regression is now fixed. + + .. change:: + :tags: oracle + :tickets: 1953 + + The cx_oracle "decimal detection" logic, which takes place + for for result set columns with ambiguous numeric characteristics, + now uses the decimal point character determined by the locale/ + NLS_LANG setting, using an on-first-connect detection of + this character. cx_oracle 5.0.3 or greater is also required + when using a non-period-decimal-point NLS_LANG setting.. + + .. change:: + :tags: firebird + :tickets: 2012 + + Firebird numeric type now checks for Decimal explicitly, + lets float() pass right through, thereby allowing + special values such as float('inf'). + + .. change:: + :tags: declarative + :tickets: 1972 + + An error is raised if __table_args__ is not in tuple + or dict format, and is not None. + + .. change:: + :tags: sqlsoup + :tickets: 1975 + + Added "map_to()" method to SqlSoup, which is a "master" + method which accepts explicit arguments for each aspect of + the selectable and mapping, including a base class per + mapping. + + .. change:: + :tags: sqlsoup + :tickets: + + Mapped selectables used with the map(), with_labels(), + join() methods no longer put the given argument into the + internal "cache" dictionary. Particularly since the + join() and select() objects are created in the method + itself this was pretty much a pure memory leaking behavior. + + .. change:: + :tags: examples + :tickets: + + The versioning example now supports detection of changes + in an associated relationship(). + +.. changelog:: + :version: 0.6.5 + :released: Sun Oct 24 2010 + + .. change:: + :tags: orm + :tickets: 1914 + + Added a new "lazyload" option "immediateload". + Issues the usual "lazy" load operation automatically + as the object is populated. The use case + here is when loading objects to be placed in + an offline cache, or otherwise used after + the session isn't available, and straight 'select' + loading, not 'joined' or 'subquery', is desired. + + .. change:: + :tags: orm + :tickets: 1920 + + New Query methods: query.label(name), query.as_scalar(), + return the query's statement as a scalar subquery + with /without label; + query.with_entities(*ent), replaces the SELECT list of + the query with new entities. + Roughly equivalent to a generative form of query.values() + which accepts mapped entities as well as column + expressions. + + .. change:: + :tags: orm + :tickets: + + Fixed recursion bug which could occur when moving + an object from one reference to another, with + backrefs involved, where the initiating parent + was a subclass (with its own mapper) of the + previous parent. + + .. change:: + :tags: orm + :tickets: 1918 + + Fixed a regression in 0.6.4 which occurred if you + passed an empty list to "include_properties" on + mapper() + + .. change:: + :tags: orm + :tickets: + + Fixed labeling bug in Query whereby the NamedTuple + would mis-apply labels if any of the column + expressions were un-labeled. + + .. change:: + :tags: orm + :tickets: 1925 + + Patched a case where query.join() would adapt the + right side to the right side of the left's join + inappropriately + + .. change:: + :tags: orm + :tickets: + + Query.select_from() has been beefed up to help + ensure that a subsequent call to query.join() + will use the select_from() entity, assuming it's + a mapped entity and not a plain selectable, + as the default "left" side, not the first entity + in the Query object's list of entities. + + .. change:: + :tags: orm + :tickets: + + The exception raised by Session when it is used + subsequent to a subtransaction rollback (which is what + happens when a flush fails in autocommit=False mode) has + now been reworded (this is the "inactive due to a + rollback in a subtransaction" message). In particular, + if the rollback was due to an exception during flush(), + the message states this is the case, and reiterates the + string form of the original exception that occurred + during flush. If the session is closed due to explicit + usage of subtransactions (not very common), the message + just states this is the case. + + .. change:: + :tags: orm + :tickets: + + The exception raised by Mapper when repeated requests to + its initialization are made after initialization already + failed no longer assumes the "hasattr" case, since + there's other scenarios in which this message gets + emitted, and the message also does not compound onto + itself multiple times - you get the same message for + each attempt at usage. The misnomer "compiles" is being + traded out for "initialize". + + .. change:: + :tags: orm + :tickets: 1935 + + Fixed bug in query.update() where 'evaluate' or 'fetch' + expiration would fail if the column expression key was + a class attribute with a different keyname as the + actual column name. + + .. change:: + :tags: orm + :tickets: + + Added an assertion during flush which ensures + that no NULL-holding identity keys were generated + on "newly persistent" objects. + This can occur when user defined code inadvertently + triggers flushes on not-fully-loaded objects. + + .. change:: + :tags: orm + :tickets: 1910 + + lazy loads for relationship attributes now use + the current state, not the "committed" state, + of foreign and primary key attributes + when issuing SQL, if a flush is not in process. + Previously, only the database-committed state would + be used. In particular, this would cause a many-to-one + get()-on-lazyload operation to fail, as autoflush + is not triggered on these loads when the attributes are + determined and the "committed" state may not be + available. + + .. change:: + :tags: orm + :tickets: + + A new flag on relationship(), load_on_pending, allows + the lazy loader to fire off on pending objects without a + flush taking place, as well as a transient object that's + been manually "attached" to the session. Note that this + flag blocks attribute events from taking place when an + object is loaded, so backrefs aren't available until + after a flush. The flag is only intended for very + specific use cases. + + .. change:: + :tags: orm + :tickets: + + Another new flag on relationship(), cascade_backrefs, + disables the "save-update" cascade when the event was + initiated on the "reverse" side of a bidirectional + relationship. This is a cleaner behavior so that + many-to-ones can be set on a transient object without + it getting sucked into the child object's session, + while still allowing the forward collection to + cascade. We *might* default this to False in 0.7. + + .. change:: + :tags: orm + :tickets: + + Slight improvement to the behavior of + "passive_updates=False" when placed only on the + many-to-one side of a relationship; documentation has + been clarified that passive_updates=False should really + be on the one-to-many side. + + .. change:: + :tags: orm + :tickets: + + Placing passive_deletes=True on a many-to-one emits + a warning, since you probably intended to put it on + the one-to-many side. + + .. change:: + :tags: orm + :tickets: + + Fixed bug that would prevent "subqueryload" from + working correctly with single table inheritance + for a relationship from a subclass - the "where + type in (x, y, z)" only gets placed on the inside, + instead of repeatedly. + + .. change:: + :tags: orm + :tickets: + + When using from_self() with single table inheritance, + the "where type in (x, y, z)" is placed on the outside + of the query only, instead of repeatedly. May make + some more adjustments to this. + + .. change:: + :tags: orm + :tickets: 1924 + + scoped_session emits a warning when configure() is + called if a Session is already present (checks only the + current thread) + + .. change:: + :tags: orm + :tickets: 1932 + + reworked the internals of mapper.cascade_iterator() to + cut down method calls by about 9% in some circumstances. + + .. change:: + :tags: sql + :tickets: + + Fixed bug in TypeDecorator whereby the dialect-specific + type was getting pulled in to generate the DDL for a + given type, which didn't always return the correct result. + + .. change:: + :tags: sql + :tickets: + + TypeDecorator can now have a fully constructed type + specified as its "impl", in addition to a type class. + + .. change:: + :tags: sql + :tickets: + + TypeDecorator will now place itself as the resulting + type for a binary expression where the type coercion + rules would normally return its impl type - previously, + a copy of the impl type would be returned which would + have the TypeDecorator embedded into it as the "dialect" + impl, this was probably an unintentional way of achieving + the desired effect. + + .. change:: + :tags: sql + :tickets: + + TypeDecorator.load_dialect_impl() returns "self.impl" by + default, i.e. not the dialect implementation type of + "self.impl". This to support compilation correctly. + Behavior can be user-overridden in exactly the same way + as before to the same effect. + + .. change:: + :tags: sql + :tickets: + + Added type_coerce(expr, type_) expression element. + Treats the given expression as the given type when evaluating + expressions and processing result rows, but does not + affect the generation of SQL, other than an anonymous + label. + + .. change:: + :tags: sql + :tickets: + + Table.tometadata() now copies Index objects associated + with the Table as well. + + .. change:: + :tags: sql + :tickets: + + Table.tometadata() issues a warning if the given Table + is already present in the target MetaData - the existing + Table object is returned. + + .. change:: + :tags: sql + :tickets: + + An informative error message is raised if a Column + which has not yet been assigned a name, i.e. as in + declarative, is used in a context where it is + exported to the columns collection of an enclosing + select() construct, or if any construct involving + that column is compiled before its name is + assigned. + + .. change:: + :tags: sql + :tickets: 1862 + + as_scalar(), label() can be called on a selectable + which contains a Column that is not yet named. + + .. change:: + :tags: sql + :tickets: 1907 + + Fixed recursion overflow which could occur when operating + with two expressions both of type "NullType", but + not the singleton NULLTYPE instance. + + .. change:: + :tags: declarative + :tickets: 1922 + + @classproperty (soon/now @declared_attr) takes effect for + __mapper_args__, __table_args__, __tablename__ on + a base class that is not a mixin, as well as mixins. + + .. change:: + :tags: declarative + :tickets: 1915 + + @classproperty 's official name/location for usage + with declarative is sqlalchemy.ext.declarative.declared_attr. + Same thing, but moving there since it is more of a + "marker" that's specific to declararative, + not just an attribute technique. + + .. change:: + :tags: declarative + :tickets: 1931, 1930 + + Fixed bug whereby columns on a mixin wouldn't propagate + correctly to a single-table, or joined-table, + inheritance scheme where the attribute name is + different than that of the column.,. + + .. change:: + :tags: declarative + :tickets: + + A mixin can now specify a column that overrides + a column of the same name associated with a superclass. + Thanks to Oystein Haaland. + + .. change:: + :tags: engine + :tickets: + + Fixed a regression in 0.6.4 whereby the change that + allowed cursor errors to be raised consistently broke + the result.lastrowid accessor. Test coverage has + been added for result.lastrowid. Note that lastrowid + is only supported by Pysqlite and some MySQL drivers, + so isn't super-useful in the general case. + + .. change:: + :tags: engine + :tickets: + + the logging message emitted by the engine when + a connection is first used is now "BEGIN (implicit)" + to emphasize that DBAPI has no explicit begin(). + + .. change:: + :tags: engine + :tickets: 1936 + + added "views=True" option to metadata.reflect(), + will add the list of available views to those + being reflected. + + .. change:: + :tags: engine + :tickets: 1899 + + engine_from_config() now accepts 'debug' for + 'echo', 'echo_pool', 'force' for 'convert_unicode', + boolean values for 'use_native_unicode'. + + .. change:: + :tags: postgresql + :tickets: + + Added "as_tuple" flag to ARRAY type, returns results + as tuples instead of lists to allow hashing. + + .. change:: + :tags: postgresql + :tickets: 1933 + + Fixed bug which prevented "domain" built from a + custom type such as "enum" from being reflected. + + .. change:: + :tags: mysql + :tickets: 1940 + + Fixed bug involving reflection of CURRENT_TIMESTAMP + default used with ON UPDATE clause, thanks to + Taavi Burns + + .. change:: + :tags: oracle + :tickets: 1878 + + The implicit_retunring argument to create_engine() + is now honored regardless of detected version of + Oracle. Previously, the flag would be forced + to False if server version info was < 10. + + .. change:: + :tags: mssql + :tickets: 1946 + + Fixed reflection bug which did not properly handle + reflection of unknown types. + + .. change:: + :tags: mssql + :tickets: 1943 + + Fixed bug where aliasing of tables with "schema" would + fail to compile properly. + + .. change:: + :tags: mssql + :tickets: 1770 + + Rewrote the reflection of indexes to use sys. + catalogs, so that column names of any configuration + (spaces, embedded commas, etc.) can be reflected. + Note that reflection of indexes requires SQL + Server 2005 or greater. + + .. change:: + :tags: mssql + :tickets: 1952 + + mssql+pymssql dialect now honors the "port" portion + of the URL instead of discarding it. + + .. change:: + :tags: informix + :tickets: 1906 + + *Major* cleanup / modernization of the Informix + dialect for 0.6, courtesy Florian Apolloner. + + .. change:: + :tags: tests + :tickets: + + the NoseSQLAlchemyPlugin has been moved to a + new package "sqlalchemy_nose" which installs + along with "sqlalchemy". This so that the "nosetests" + script works as always but also allows the + --with-coverage option to turn on coverage before + SQLAlchemy modules are imported, allowing coverage + to work correctly. + + .. change:: + :tags: misc + :tickets: 1890 + + CircularDependencyError now has .cycles and .edges + members, which are the set of elements involved in + one or more cycles, and the set of edges as 2-tuples. + +.. changelog:: + :version: 0.6.4 + :released: Tue Sep 07 2010 + + .. change:: + :tags: orm + :tickets: + + The name ConcurrentModificationError has been + changed to StaleDataError, and descriptive + error messages have been revised to reflect + exactly what the issue is. Both names will + remain available for the forseeable future + for schemes that may be specifying + ConcurrentModificationError in an "except:" + clause. + + .. change:: + :tags: orm + :tickets: 1891 + + Added a mutex to the identity map which mutexes + remove operations against iteration methods, + which now pre-buffer before returning an + iterable. This because asyncrhonous gc + can remove items via the gc thread at any time. + + .. change:: + :tags: orm + :tickets: + + The Session class is now present in sqlalchemy.orm.*. + We're moving away from the usage of create_session(), + which has non-standard defaults, for those situations + where a one-step Session constructor is desired. Most + users should stick with sessionmaker() for general use, + however. + + .. change:: + :tags: orm + :tickets: + + query.with_parent() now accepts transient objects + and will use the non-persistent values of their pk/fk + attributes in order to formulate the criterion. + Docs are also clarified as to the purpose of with_parent(). + + .. change:: + :tags: orm + :tickets: + + The include_properties and exclude_properties arguments + to mapper() now accept Column objects as members in + addition to strings. This so that same-named Column + objects, such as those within a join(), can be + disambiguated. + + .. change:: + :tags: orm + :tickets: 1896 + + A warning is now emitted if a mapper is created against a + join or other single selectable that includes multiple + columns with the same name in its .c. collection, + and those columns aren't explictly named as part of + the same or separate attributes (or excluded). + In 0.7 this warning will be an exception. Note that + this warning is not emitted when the combination occurs + as a result of inheritance, so that attributes + still allow being overridden naturally.. In 0.7 this will be improved further. + + .. change:: + :tags: orm + :tickets: 1896 + + The primary_key argument to mapper() can now specify + a series of columns that are only a subset of + the calculated "primary key" columns of the mapped + selectable, without an error being raised. This + helps for situations where a selectable's effective + primary key is simpler than the number of columns + in the selectable that are actually marked as + "primary_key", such as a join against two + tables on their primary key columns. + + .. change:: + :tags: orm + :tickets: + + An object that's been deleted now gets a flag + 'deleted', which prohibits the object from + being re-add()ed to the session, as previously + the object would live in the identity map + silently until its attributes were accessed. + The make_transient() function now resets this + flag along with the "key" flag. + + .. change:: + :tags: orm + :tickets: + + make_transient() can be safely called on an + already transient instance. + + .. change:: + :tags: orm + :tickets: + + a warning is emitted in mapper() if the polymorphic_on + column is not present either in direct or derived + form in the mapped selectable or in the + with_polymorphic selectable, instead of silently + ignoring it. Look for this to become an + exception in 0.7. + + .. change:: + :tags: orm + :tickets: + + Another pass through the series of error messages + emitted when relationship() is configured with + ambiguous arguments. The "foreign_keys" + setting is no longer mentioned, as it is almost + never needed and it is preferable users set up + correct ForeignKey metadata, which is now the + recommendation. If 'foreign_keys' + is used and is incorrect, the message suggests + the attribute is probably unnecessary. Docs + for the attribute are beefed up. This + because all confused relationship() users on the + ML appear to be attempting to use foreign_keys + due to the message, which only confuses them + further since Table metadata is much clearer. + + .. change:: + :tags: orm + :tickets: 1877 + + If the "secondary" table has no ForeignKey metadata + and no foreign_keys is set, even though the + user is passing screwed up information, it is assumed + that primary/secondaryjoin expressions should + consider only and all cols in "secondary" to be + foreign. It's not possible with "secondary" for + the foreign keys to be elsewhere in any case. + A warning is now emitted instead of an error, + and the mapping succeeds. + + .. change:: + :tags: orm + :tickets: 1856 + + Moving an o2m object from one collection to + another, or vice versa changing the referenced + object by an m2o, where the foreign key is also a + member of the primary key, will now be more + carefully checked during flush if the change in + value of the foreign key on the "many" side is the + result of a change in the primary key of the "one" + side, or if the "one" is just a different object. + In one case, a cascade-capable DB would have + cascaded the value already and we need to look at + the "new" PK value to do an UPDATE, in the other we + need to continue looking at the "old". We now look + at the "old", assuming passive_updates=True, + unless we know it was a PK switch that + triggered the change. + + .. change:: + :tags: orm + :tickets: 1857 + + The value of version_id_col can be changed + manually, and this will result in an UPDATE + of the row. Versioned UPDATEs and DELETEs + now use the "committed" value of the + version_id_col in the WHERE clause and + not the pending changed value. The + version generator is also bypassed if + manual changes are present on the attribute. + + .. change:: + :tags: orm + :tickets: + + Repaired the usage of merge() when used with + concrete inheriting mappers. Such mappers frequently + have so-called "concrete" attributes, which are + subclass attributes that "disable" propagation from + the parent - these needed to allow a merge() + operation to pass through without effect. + + .. change:: + :tags: orm + :tickets: 1863 + + Specifying a non-column based argument + for column_mapped_collection, including string, + text() etc., will raise an error message that + specifically asks for a column element, no longer + misleads with incorrect information about + text() or literal(). + + .. change:: + :tags: orm + :tickets: + + Similarly, for relationship(), foreign_keys, + remote_side, order_by - all column-based + expressions are enforced - lists of strings + are explicitly disallowed since this is a + very common error + + .. change:: + :tags: orm + :tickets: 1864 + + Dynamic attributes don't support collection + population - added an assertion for when + set_committed_value() is called, as well as + when joinedload() or subqueryload() options + are applied to a dynamic attribute, instead + of failure / silent failure. + + .. change:: + :tags: orm + :tickets: 1852 + + Fixed bug whereby generating a Query derived + from one which had the same column repeated + with different label names, typically + in some UNION situations, would fail to + propagate the inner columns completely to + the outer query. + + .. change:: + :tags: orm + :tickets: 1881 + + object_session() raises the proper + UnmappedInstanceError when presented with an + unmapped instance. + + .. change:: + :tags: orm + :tickets: + + Applied further memoizations to calculated Mapper + properties, with significant (~90%) runtime mapper.py + call count reduction in heavily polymorphic mapping + configurations. + + .. change:: + :tags: orm + :tickets: + + mapper _get_col_to_prop private method used + by the versioning example is deprecated; + now use mapper.get_property_by_column() which + will remain the public method for this. + + .. change:: + :tags: orm + :tickets: + + the versioning example works correctly now + if versioning on a col that was formerly + NULL. + + .. change:: + :tags: sql + :tickets: + + Calling execute() on an alias() construct is pending + deprecation for 0.7, as it is not itself an + "executable" construct. It currently "proxies" its + inner element and is conditionally "executable" but + this is not the kind of ambiguity we like these days. + + .. change:: + :tags: sql + :tickets: + + The execute() and scalar() methods of ClauseElement + are now moved appropriately to the Executable + subclass. ClauseElement.execute()/ scalar() are still + present and are pending deprecation in 0.7, but note + these would always raise an error anyway if you were + not an Executable (unless you were an alias(), see + previous note). + + .. change:: + :tags: sql + :tickets: + + Added basic math expression coercion for + Numeric->Integer, + so that resulting type is Numeric regardless + of the direction of the expression. + + .. change:: + :tags: sql + :tickets: 1855 + + Changed the scheme used to generate truncated + "auto" index names when using the "index=True" + flag on Column. The truncation only takes + place with the auto-generated name, not one + that is user-defined (an error would be + raised instead), and the truncation scheme + itself is now based on a fragment of an md5 + hash of the identifier name, so that multiple + indexes on columns with similar names still + have unique names. + + .. change:: + :tags: sql + :tickets: 1412 + + The generated index name also is based on + a "max index name length" attribute which is + separate from the "max identifier length" - + this to appease MySQL who has a max length + of 64 for index names, separate from their + overall max length of 255. + + .. change:: + :tags: sql + :tickets: + + the text() construct, if placed in a column + oriented situation, will at least return NULLTYPE + for its type instead of None, allowing it to + be used a little more freely for ad-hoc column + expressions than before. literal_column() + is still the better choice, however. + + .. change:: + :tags: sql + :tickets: + + Added full description of parent table/column, + target table/column in error message raised when + ForeignKey can't resolve target. + + .. change:: + :tags: sql + :tickets: 1865 + + Fixed bug whereby replacing composite foreign key + columns in a reflected table would cause an attempt + to remove the reflected constraint from the table + a second time, raising a KeyError. + + .. change:: + :tags: sql + :tickets: + + the _Label construct, i.e. the one that is produced + whenever you say somecol.label(), now counts itself + in its "proxy_set" unioned with that of it's + contained column's proxy set, instead of + directly returning that of the contained column. + This allows column correspondence + operations which depend on the identity of the + _Labels themselves to return the correct result + + .. change:: + :tags: sql + :tickets: 1852 + + fixes ORM bug. + + .. change:: + :tags: engine + :tickets: + + Calling fetchone() or similar on a result that + has already been exhausted, has been closed, + or is not a result-returning result now + raises ResourceClosedError, a subclass of + InvalidRequestError, in all cases, regardless + of backend. Previously, some DBAPIs would + raise ProgrammingError (i.e. pysqlite), others + would return None leading to downstream breakages + (i.e. MySQL-python). + + .. change:: + :tags: engine + :tickets: 1894 + + Fixed bug in Connection whereby if a "disconnect" + event occurred in the "initialize" phase of the + first connection pool connect, an AttributeError + would be raised when the Connection would attempt + to invalidate the DBAPI connection. + + .. change:: + :tags: engine + :tickets: + + Connection, ResultProxy, as well as Session use + ResourceClosedError for all "this + connection/transaction/result is closed" types of + errors. + + .. change:: + :tags: engine + :tickets: + + Connection.invalidate() can be called more than + once and subsequent calls do nothing. + + .. change:: + :tags: declarative + :tickets: + + if @classproperty is used with a regular class-bound + mapper property attribute, it will be called to get the + actual attribute value during initialization. Currently, + there's no advantage to using @classproperty on a column + or relationship attribute of a declarative class that + isn't a mixin - evaluation is at the same time as if + @classproperty weren't used. But here we at least allow + it to function as expected. + + .. change:: + :tags: declarative + :tickets: + + Fixed bug where "Can't add additional column" message + would display the wrong name. + + .. change:: + :tags: postgresql + :tickets: + + Fixed the psycopg2 dialect to use its + set_isolation_level() method instead of relying + upon the base "SET SESSION ISOLATION" command, + as psycopg2 resets the isolation level on each new + transaction otherwise. + + .. change:: + :tags: mssql + :tickets: + + Fixed "default schema" query to work with + pymssql backend. + + .. change:: + :tags: firebird + :tickets: + + Fixed bug whereby a column default would fail to + reflect if the "default" keyword were lower case. + + .. change:: + :tags: oracle + :tickets: 1879 + + Added ROWID type to the Oracle dialect, for those + cases where an explicit CAST might be needed. + + .. change:: + :tags: oracle + :tickets: 1867 + + Oracle reflection of indexes has been tuned so + that indexes which include some or all primary + key columns, but not the same set of columns + as that of the primary key, are reflected. + Indexes which contain the identical columns + as that of the primary key are skipped within + reflection, as the index in that case is assumed + to be the auto-generated primary key index. + Previously, any index with PK columns present + would be skipped. Thanks to Kent Bower + for the patch. + + .. change:: + :tags: oracle + :tickets: 1868 + + Oracle now reflects the names of primary key + constraints - also thanks to Kent Bower. + + .. change:: + :tags: informix + :tickets: 1904 + + Applied patches from to get + basic Informix functionality up again. We + rely upon end-user testing to ensure that + Informix is working to some degree. + + .. change:: + :tags: documentation + :tickets: + + The docs have been reorganized such that the "API + Reference" section is gone - all the docstrings from + there which were public API are moved into the + context of the main doc section that talks about it. + Main docs divided into "SQLAlchemy Core" and + "SQLAlchemy ORM" sections, mapper/relationship docs + have been broken out. Lots of sections rewritten + and/or reorganized. + + .. change:: + :tags: examples + :tickets: + + The beaker_caching example has been reorgnized + such that the Session, cache manager, + declarative_base are part of environment, and + custom cache code is portable and now within + "caching_query.py". This allows the example to + be easier to "drop in" to existing projects. + + .. change:: + :tags: examples + :tickets: 1887 + + the history_meta versioning recipe sets "unique=False" + when copying columns, so that the versioning + table handles multiple rows with repeating values. + +.. changelog:: + :version: 0.6.3 + :released: Thu Jul 15 2010 + + .. change:: + :tags: orm + :tickets: 1845 + + Removed errant many-to-many load in unitofwork + which triggered unnecessarily on expired/unloaded + collections. This load now takes place only if + passive_updates is False and the parent primary + key has changed, or if passive_deletes is False + and a delete of the parent has occurred. + + .. change:: + :tags: orm + :tickets: 1853 + + Column-entities (i.e. query(Foo.id)) copy their + state more fully when queries are derived from + themselves + a selectable (i.e. from_self(), + union(), etc.), so that join() and such have the + correct state to work from. + + .. change:: + :tags: orm + :tickets: 1853 + + Fixed bug where Query.join() would fail if + querying a non-ORM column then joining without + an on clause when a FROM clause is already + present, now raises a checked exception the + same way it does when the clause is not + present. + + .. change:: + :tags: orm + :tickets: 1142 + + Improved the check for an "unmapped class", + including the case where the superclass is mapped + but the subclass is not. Any attempts to access + cls._sa_class_manager.mapper now raise + UnmappedClassError(). + + .. change:: + :tags: orm + :tickets: + + Added "column_descriptions" accessor to Query, + returns a list of dictionaries containing + naming/typing information about the entities + the Query will return. Can be helpful for + building GUIs on top of ORM queries. + + .. change:: + :tags: mysql + :tickets: 1848 + + The _extract_error_code() method now works + correctly with each MySQL dialect ( + MySQL-python, OurSQL, MySQL-Connector-Python, + PyODBC). Previously, + the reconnect logic would fail for OperationalError + conditions, however since MySQLdb and OurSQL + have their own reconnect feature, there was no + symptom for these drivers here unless one + watched the logs. + + .. change:: + :tags: oracle + :tickets: 1840 + + More tweaks to cx_oracle Decimal handling. + "Ambiguous" numerics with no decimal place + are coerced to int at the connection handler + level. The advantage here is that ints + come back as ints without SQLA type + objects being involved and without needless + conversion to Decimal first. + + Unfortunately, some exotic subquery cases + can even see different types between + individual result rows, so the Numeric + handler, when instructed to return Decimal, + can't take full advantage of "native decimal" + mode and must run isinstance() on every value + to check if its Decimal already. Reopen of + +.. changelog:: + :version: 0.6.2 + :released: Tue Jul 06 2010 + + .. change:: + :tags: orm + :tickets: + + Query.join() will check for a call of the + form query.join(target, clause_expression), + i.e. missing the tuple, and raise an informative + error message that this is the wrong calling form. + + .. change:: + :tags: orm + :tickets: 1824 + + Fixed bug regarding flushes on self-referential + bi-directional many-to-many relationships, where + two objects made to mutually reference each other + in one flush would fail to insert a row for both + sides. Regression from 0.5. + + .. change:: + :tags: orm + :tickets: + + the post_update feature of relationship() has been + reworked architecturally to integrate more closely + with the new 0.6 unit of work. The motivation + for the change is so that multiple "post update" + calls, each affecting different foreign key + columns of the same row, are executed in a single + UPDATE statement, rather than one UPDATE + statement per column per row. Multiple row + updates are also batched into executemany()s as + possible, while maintaining consistent row ordering. + + .. change:: + :tags: orm + :tickets: + + Query.statement, Query.subquery(), etc. now transfer + the values of bind parameters, i.e. those specified + by query.params(), into the resulting SQL expression. + Previously the values would not be transferred + and bind parameters would come out as None. + + .. change:: + :tags: orm + :tickets: + + Subquery-eager-loading now works with Query objects + which include params(), as well as get() Queries. + + .. change:: + :tags: orm + :tickets: + + Can now call make_transient() on an instance that + is referenced by parent objects via many-to-one, + without the parent's foreign key value getting + temporarily set to None - this was a function + of the "detect primary key switch" flush handler. + It now ignores objects that are no longer + in the "persistent" state, and the parent's + foreign key identifier is left unaffected. + + .. change:: + :tags: orm + :tickets: + + query.order_by() now accepts False, which cancels + any existing order_by() state on the Query, allowing + subsequent generative methods to be called which do + not support ORDER BY. This is not the same as the + already existing feature of passing None, which + suppresses any existing order_by() settings, including + those configured on the mapper. False will make it + as though order_by() was never called, while + None is an active setting. + + .. change:: + :tags: orm + :tickets: + + An instance which is moved to "transient", has + an incomplete or missing set of primary key + attributes, and contains expired attributes, will + raise an InvalidRequestError if an expired attribute + is accessed, instead of getting a recursion overflow. + + .. change:: + :tags: orm + :tickets: + + The make_transient() function is now in the generated + documentation. + + .. change:: + :tags: orm + :tickets: + + make_transient() removes all "loader" callables from + the state being made transient, removing any + "expired" state - all unloaded attributes reset back + to undefined, None/empty on access. + + .. change:: + :tags: sql + :tickets: 1822 + + The warning emitted by the Unicode and String types + with convert_unicode=True no longer embeds the actual + value passed. This so that the Python warning + registry does not continue to grow in size, the warning + is emitted once as per the warning filter settings, + and large string values don't pollute the output. + + .. change:: + :tags: sql + :tickets: + + Fixed bug that would prevent overridden clause + compilation from working for "annotated" expression + elements, which are often generated by the ORM. + + .. change:: + :tags: sql + :tickets: 1400 + + The argument to "ESCAPE" of a LIKE operator or similar + is passed through render_literal_value(), which may + implement escaping of backslashes. + + .. change:: + :tags: sql + :tickets: + + Fixed bug in Enum type which blew away native_enum + flag when used with TypeDecorators or other adaption + scenarios. + + .. change:: + :tags: sql + :tickets: + + Inspector hits bind.connect() when invoked to ensure + initialize has been called. the internal name ".conn" + is changed to ".bind", since that's what it is. + + .. change:: + :tags: sql + :tickets: + + Modified the internals of "column annotation" such that + a custom Column subclass can safely override + _constructor to return Column, for the purposes of + making "configurational" column classes that aren't + involved in proxying, etc. + + .. change:: + :tags: sql + :tickets: 1829 + + Column.copy() takes along the "unique" attribute + among others, fixes regarding declarative + mixins + + .. change:: + :tags: postgresql + :tickets: 1400 + + render_literal_value() is overridden which escapes + backslashes, currently applies to the ESCAPE clause + of LIKE and similar expressions. + Ultimately this will have to detect the value of + "standard_conforming_strings" for full behavior. + + .. change:: + :tags: postgresql + :tickets: 1836 + + Won't generate "CREATE TYPE" / "DROP TYPE" if + using types.Enum on a PG version prior to 8.3 - + the supports_native_enum flag is fully + honored. + + .. change:: + :tags: mysql + :tickets: 1826 + + MySQL dialect doesn't emit CAST() for MySQL version + detected < 4.0.2. This allows the unicode + check on connect to proceed. + + .. change:: + :tags: mysql + :tickets: + + MySQL dialect now detects NO_BACKSLASH_ESCAPES sql + mode, in addition to ANSI_QUOTES. + + .. change:: + :tags: mysql + :tickets: 1400 + + render_literal_value() is overridden which escapes + backslashes, currently applies to the ESCAPE clause + of LIKE and similar expressions. This behavior + is derived from detecting the value of + NO_BACKSLASH_ESCAPES. + + .. change:: + :tags: oracle + :tickets: 1819 + + Fixed ora-8 compatibility flags such that they + don't cache a stale value from before the first + database connection actually occurs. + + .. change:: + :tags: oracle + :tickets: 1840 + + Oracle's "native decimal" metadata begins to return + ambiguous typing information about numerics + when columns are embedded in subqueries as well + as when ROWNUM is consulted with subqueries, as we + do for limit/offset. We've added these ambiguous + conditions to the cx_oracle "convert to Decimal()" + handler, so that we receive numerics as Decimal + in more cases instead of as floats. These are + then converted, if requested, into Integer + or Float, or otherwise kept as the lossless + Decimal. + + .. change:: + :tags: mssql + :tickets: 1825 + + If server_version_info is outside the usual + range of (8, ), (9, ), (10, ), a warning is emitted + which suggests checking that the FreeTDS version + configuration is using 7.0 or 8.0, not 4.2. + + .. change:: + :tags: firebird + :tickets: 1823 + + Fixed incorrect signature in do_execute(), error + introduced in 0.6.1. + + .. change:: + :tags: firebird + :tickets: 1813 + + Firebird dialect adds CHAR, VARCHAR types which + accept a "charset" flag, to support Firebird + "CHARACTER SET" clause. + + .. change:: + :tags: declarative + :tickets: 1805, 1796, 1751 + + Added support for @classproperty to provide + any kind of schema/mapping construct from a + declarative mixin, including columns with foreign + keys, relationships, column_property, deferred. + This solves all such issues on declarative mixins. + An error is raised if any MapperProperty subclass + is specified on a mixin without using @classproperty. + + .. change:: + :tags: declarative + :tickets: 1821 + + a mixin class can now define a column that matches + one which is present on a __table__ defined on a + subclass. It cannot, however, define one that is + not present in the __table__, and the error message + here now works. + + .. change:: + :tags: extension, compiler + :tickets: 1838 + + The 'default' compiler is automatically copied over + when overriding the compilation of a built in + clause construct, so no KeyError is raised if the + user-defined compiler is specific to certain + backends and compilation for a different backend + is invoked. + + .. change:: + :tags: documentation + :tickets: 1820 + + Added documentation for the Inspector. + + .. change:: + :tags: documentation + :tickets: 1830 + + Fixed @memoized_property and @memoized_instancemethod + decorators so that Sphinx documentation picks up + these attributes and methods, such as + ResultProxy.inserted_primary_key. + +.. changelog:: + :version: 0.6.1 + :released: Mon May 31 2010 + + .. change:: + :tags: orm + :tickets: 1782 + + Fixed regression introduced in 0.6.0 involving improper + history accounting on mutable attributes. + + .. change:: + :tags: orm + :tickets: 1807 + + Fixed regression introduced in 0.6.0 unit of work refactor + that broke updates for bi-directional relationship() + with post_update=True. + + .. change:: + :tags: orm + :tickets: 1789 + + session.merge() will not expire attributes on the returned + instance if that instance is "pending". + + .. change:: + :tags: orm + :tickets: 1802 + + fixed __setstate__ method of CollectionAdapter to not + fail during deserialize where parent InstanceState not + yet unserialized. + + .. change:: + :tags: orm + :tickets: 1797 + + Added internal warning in case an instance without a + full PK happened to be expired and then was asked + to refresh. + + .. change:: + :tags: orm + :tickets: + + Added more aggressive caching to the mapper's usage of + UPDATE, INSERT, and DELETE expressions. Assuming the + statement has no per-object SQL expressions attached, + the expression objects are cached by the mapper after + the first create, and their compiled form is stored + persistently in a cache dictionary for the duration of + the related Engine. The cache is an LRUCache for the + rare case that a mapper receives an extremely + high number of different column patterns as UPDATEs. + + .. change:: + :tags: sql + :tickets: 1793 + + expr.in_() now accepts a text() construct as the argument. + Grouping parenthesis are added automatically, i.e. usage + is like `col.in_(text("select id from table"))`. + + .. change:: + :tags: sql + :tickets: + + Columns of _Binary type (i.e. LargeBinary, BLOB, etc.) + will coerce a "basestring" on the right side into a + _Binary as well so that required DBAPI processing + takes place. + + .. change:: + :tags: sql + :tickets: 1801 + + Added table.add_is_dependent_on(othertable), allows manual + placement of dependency rules between two Table objects + for use within create_all(), drop_all(), sorted_tables. + + .. change:: + :tags: sql + :tickets: 1778 + + Fixed bug that prevented implicit RETURNING from functioning + properly with composite primary key that contained zeroes. + + .. change:: + :tags: sql + :tickets: + + Fixed errant space character when generating ADD CONSTRAINT + for a named UNIQUE constraint. + + .. change:: + :tags: sql + :tickets: 1571 + + Fixed "table" argument on constructor of ForeginKeyConstraint + + .. change:: + :tags: sql + :tickets: 1786 + + Fixed bug in connection pool cursor wrapper whereby if a + cursor threw an exception on close(), the logging of the + message would fail. + + .. change:: + :tags: sql + :tickets: + + the _make_proxy() method of ColumnClause and Column now use + self.__class__ to determine the class of object to be returned + instead of hardcoding to ColumnClause/Column, making it slightly + easier to produce specific subclasses of these which work in + alias/subquery situations. + + .. change:: + :tags: sql + :tickets: 1798 + + func.XXX() doesn't inadvertently resolve to non-Function + classes (e.g. fixes func.text()). + + .. change:: + :tags: engines + :tickets: 1781 + + Fixed building the C extensions on Python 2.4. + + .. change:: + :tags: engines + :tickets: + + Pool classes will reuse the same "pool_logging_name" setting + after a dispose() occurs. + + .. change:: + :tags: engines + :tickets: + + Engine gains an "execution_options" argument and + update_execution_options() method, which will apply to + all connections generated by this engine. + + .. change:: + :tags: mysql + :tickets: 1794 + + func.sysdate() emits "SYSDATE()", i.e. with the ending + parenthesis, on MySQL. + + .. change:: + :tags: sqlite + :tickets: 1812 + + Fixed concatenation of constraints when "PRIMARY KEY" + constraint gets moved to column level due to SQLite + AUTOINCREMENT keyword being rendered. + + .. change:: + :tags: oracle + :tickets: 1775 + + Added a check for cx_oracle versions lower than version 5, + in which case the incompatible "output type handler" won't + be used. This will impact decimal accuracy and some + unicode handling issues. + + .. change:: + :tags: oracle + :tickets: 1790 + + Fixed use_ansi=False mode, which was producing broken + WHERE clauses in pretty much all cases. + + .. change:: + :tags: oracle + :tickets: 1808 + + Re-established support for Oracle 8 with cx_oracle, + including that use_ansi is set to False automatically, + NVARCHAR2 and NCLOB are not rendered for Unicode, + "native unicode" check doesn't fail, cx_oracle + "native unicode" mode is disabled, VARCHAR() is emitted + with bytes count instead of char count. + + .. change:: + :tags: oracle + :tickets: 1670 + + oracle_xe 5 doesn't accept a Python unicode object in + its connect string in normal Python 2.x mode - so we coerce + to str() directly. non-ascii characters aren't supported + in connect strings here since we don't know what encoding + we could use. + + .. change:: + :tags: oracle + :tickets: 1815 + + FOR UPDATE is emitted in the syntactically correct position + when limit/offset is used, i.e. the ROWNUM subquery. + However, Oracle can't really handle FOR UPDATE with ORDER BY + or with subqueries, so its still not very usable, but at + least SQLA gets the SQL past the Oracle parser. + + .. change:: + :tags: firebird + :tickets: 1521 + + Added a label to the query used within has_table() and + has_sequence() to work with older versions of Firebird + that don't provide labels for result columns. + + .. change:: + :tags: firebird + :tickets: 1779 + + Added integer coercion to the "type_conv" attribute when + passed via query string, so that it is properly interpreted + by Kinterbasdb. + + .. change:: + :tags: firebird + :tickets: 1646 + + Added 'connection shutdown' to the list of exception strings + which indicate a dropped connection. + + .. change:: + :tags: sqlsoup + :tickets: 1783 + + the SqlSoup constructor accepts a `base` argument which specifies + the base class to use for mapped classes, the default being + `object`. + +.. changelog:: + :version: 0.6.0 + :released: Sun Apr 18 2010 + + .. change:: + :tags: orm + :tickets: 1742, 1081 + + Unit of work internals have been rewritten. Units of work + with large numbers of objects interdependent objects + can now be flushed without recursion overflows + as there is no longer reliance upon recursive calls. The number of internal structures now stays + constant for a particular session state, regardless of + how many relationships are present on mappings. The flow + of events now corresponds to a linear list of steps, + generated by the mappers and relationships based on actual + work to be done, filtered through a single topological sort + for correct ordering. Flush actions are assembled using + far fewer steps and less memory. + + .. change:: + :tags: orm + :tickets: + + Along with the UOW rewrite, this also removes an issue + introduced in 0.6beta3 regarding topological cycle detection + for units of work with long dependency cycles. We now use + an algorithm written by Guido (thanks Guido!). + + .. change:: + :tags: orm + :tickets: 1764 + + one-to-many relationships now maintain a list of positive + parent-child associations within the flush, preventing + previous parents marked as deleted from cascading a + delete or NULL foreign key set on those child objects, + despite the end-user not removing the child from the old + association. + + .. change:: + :tags: orm + :tickets: 1495 + + A collection lazy load will switch off default + eagerloading on the reverse many-to-one side, since + that loading is by definition unnecessary. + + .. change:: + :tags: orm + :tickets: + + Session.refresh() now does an equivalent expire() + on the given instance first, so that the "refresh-expire" + cascade is propagated. Previously, refresh() was + not affected in any way by the presence of "refresh-expire" + cascade. This is a change in behavior versus that + of 0.6beta2, where the "lockmode" flag passed to refresh() + would cause a version check to occur. Since the instance + is first expired, refresh() always upgrades the object + to the most recent version. + + .. change:: + :tags: orm + :tickets: 1754 + + The 'refresh-expire' cascade, when reaching a pending object, + will expunge the object if the cascade also includes + "delete-orphan", or will simply detach it otherwise. + + .. change:: + :tags: orm + :tickets: 1756 + + id(obj) is no longer used internally within topological.py, + as the sorting functions now require hashable objects + only. + + .. change:: + :tags: orm + :tickets: + + The ORM will set the docstring of all generated descriptors + to None by default. This can be overridden using 'doc' + (or if using Sphinx, attribute docstrings work too). + + .. change:: + :tags: orm + :tickets: + + Added kw argument 'doc' to all mapper property callables + as well as Column(). Will assemble the string 'doc' as + the '__doc__' attribute on the descriptor. + + .. change:: + :tags: orm + :tickets: 1761 + + Usage of version_id_col on a backend that supports + cursor.rowcount for execute() but not executemany() now works + when a delete is issued (already worked for saves, since those + don't use executemany()). For a backend that doesn't support + cursor.rowcount at all, a warning is emitted the same + as with saves. + + .. change:: + :tags: orm + :tickets: + + The ORM now short-term caches the "compiled" form of + insert() and update() constructs when flushing lists of + objects of all the same class, thereby avoiding redundant + compilation per individual INSERT/UPDATE within an + individual flush() call. + + .. change:: + :tags: orm + :tickets: + + internal getattr(), setattr(), getcommitted() methods + on ColumnProperty, CompositeProperty, RelationshipProperty + have been underscored (i.e. are private), signature has + changed. + + .. change:: + :tags: engines + :tickets: 1757 + + The C extension now also works with DBAPIs which use custom + sequences as row (and not only tuples). + + .. change:: + :tags: sql + :tickets: 1755 + + Restored some bind-labeling logic from 0.5 which ensures + that tables with column names that overlap another column + of the form "_" won't produce + errors if column._label is used as a bind name during + an UPDATE. Test coverage which wasn't present in 0.5 + has been added. + + .. change:: + :tags: sql + :tickets: 1729 + + somejoin.select(fold_equivalents=True) is no longer + deprecated, and will eventually be rolled into a more + comprehensive version of the feature for. + + .. change:: + :tags: sql + :tickets: 1759 + + the Numeric type raises an *enormous* warning when expected + to convert floats to Decimal from a DBAPI that returns floats. + This includes SQLite, Sybase, MS-SQL. + + .. change:: + :tags: sql + :tickets: + + Fixed an error in expression typing which caused an endless + loop for expressions with two NULL types. + + .. change:: + :tags: sql + :tickets: + + Fixed bug in execution_options() feature whereby the existing + Transaction and other state information from the parent + connection would not be propagated to the sub-connection. + + .. change:: + :tags: sql + :tickets: + + Added new 'compiled_cache' execution option. A dictionary + where Compiled objects will be cached when the Connection + compiles a clause expression into a dialect- and parameter- + specific Compiled object. It is the user's responsibility to + manage the size of this dictionary, which will have keys + corresponding to the dialect, clause element, the column + names within the VALUES or SET clause of an INSERT or UPDATE, + as well as the "batch" mode for an INSERT or UPDATE statement. + + .. change:: + :tags: sql + :tickets: 1769 + + Added get_pk_constraint() to reflection.Inspector, similar + to get_primary_keys() except returns a dict that includes the + name of the constraint, for supported backends (PG so far). + + .. change:: + :tags: sql + :tickets: 1771 + + Table.create() and Table.drop() no longer apply metadata- + level create/drop events. + + .. change:: + :tags: ext + :tickets: + + the compiler extension now allows @compiles decorators + on base classes that extend to child classes, @compiles + decorators on child classes that aren't broken by a + @compiles decorator on the base class. + + .. change:: + :tags: ext + :tickets: + + Declarative will raise an informative error message + if a non-mapped class attribute is referenced in the + string-based relationship() arguments. + + .. change:: + :tags: ext + :tickets: + + Further reworked the "mixin" logic in declarative to + additionally allow __mapper_args__ as a @classproperty + on a mixin, such as to dynamically assign polymorphic_identity. + + .. change:: + :tags: postgresql + :tickets: 1071 + + Postgresql now reflects sequence names associated with + SERIAL columns correctly, after the name of of the sequence + has been changed. Thanks to Kumar McMillan for the patch. + + .. change:: + :tags: postgresql + :tickets: + + Repaired missing import in psycopg2._PGNumeric type when + unknown numeric is received. + + .. change:: + :tags: postgresql + :tickets: + + psycopg2/pg8000 dialects now aware of REAL[], FLOAT[], + DOUBLE_PRECISION[], NUMERIC[] return types without + raising an exception. + + .. change:: + :tags: postgresql + :tickets: 1769 + + Postgresql reflects the name of primary key constraints, + if one exists. + + .. change:: + :tags: oracle + :tickets: + + Now using cx_oracle output converters so that the + DBAPI returns natively the kinds of values we prefer: + + .. change:: + :tags: oracle + :tickets: 1759 + + NUMBER values with positive precision + scale convert + to cx_oracle.STRING and then to Decimal. This + allows perfect precision for the Numeric type when + using cx_oracle. + + .. change:: + :tags: oracle + :tickets: + + STRING/FIXED_CHAR now convert to unicode natively. + SQLAlchemy's String types then don't need to + apply any kind of conversions. + + .. change:: + :tags: firebird + :tickets: + + The functionality of result.rowcount can be disabled on a + per-engine basis by setting 'enable_rowcount=False' + on create_engine(). Normally, cursor.rowcount is called + after any UPDATE or DELETE statement unconditionally, + because the cursor is then closed and Firebird requires + an open cursor in order to get a rowcount. This + call is slightly expensive however so it can be disabled. + To re-enable on a per-execution basis, the + 'enable_rowcount=True' execution option may be used. + + .. change:: + :tags: examples + :tickets: + + Updated attribute_shard.py example to use a more robust + method of searching a Query for binary expressions which + compare columns against literal values. + +.. changelog:: + :version: 0.6beta3 + :released: Sun Mar 28 2010 + + .. change:: + :tags: orm + :tickets: 1675 + + Major feature: Added new "subquery" loading capability to + relationship(). This is an eager loading option which + generates a second SELECT for each collection represented + in a query, across all parents at once. The query + re-issues the original end-user query wrapped in a subquery, + applies joins out to the target collection, and loads + all those collections fully in one result, similar to + "joined" eager loading but using all inner joins and not + re-fetching full parent rows repeatedly (as most DBAPIs seem + to do, even if columns are skipped). Subquery loading is + available at mapper config level using "lazy='subquery'" and + at the query options level using "subqueryload(props..)", + "subqueryload_all(props...)". + + .. change:: + :tags: orm + :tickets: + + To accomodate the fact that there are now two kinds of eager + loading available, the new names for eagerload() and + eagerload_all() are joinedload() and joinedload_all(). The + old names will remain as synonyms for the foreseeable future. + + .. change:: + :tags: orm + :tickets: + + The "lazy" flag on the relationship() function now accepts + a string argument for all kinds of loading: "select", "joined", + "subquery", "noload" and "dynamic", where the default is now + "select". The old values of True/ + False/None still retain their usual meanings and will remain + as synonyms for the foreseeable future. + + .. change:: + :tags: orm + :tickets: 921 + + Added with_hint() method to Query() construct. This calls + directly down to select().with_hint() and also accepts + entities as well as tables and aliases. See with_hint() in the + SQL section below. + + .. change:: + :tags: orm + :tickets: + + Fixed bug in Query whereby calling q.join(prop).from_self(...). + join(prop) would fail to render the second join outside the + subquery, when joining on the same criterion as was on the + inside. + + .. change:: + :tags: orm + :tickets: + + Fixed bug in Query whereby the usage of aliased() constructs + would fail if the underlying table (but not the actual alias) + were referenced inside the subquery generated by + q.from_self() or q.select_from(). + + .. change:: + :tags: orm + :tickets: + + Fixed bug which affected all eagerload() and similar options + such that "remote" eager loads, i.e. eagerloads off of a lazy + load such as query(A).options(eagerload(A.b, B.c)) + wouldn't eagerload anything, but using eagerload("b.c") would + work fine. + + .. change:: + :tags: orm + :tickets: + + Query gains an add_columns(*columns) method which is a multi- + version of add_column(col). add_column(col) is future + deprecated. + + .. change:: + :tags: orm + :tickets: + + Query.join() will detect if the end result will be + "FROM A JOIN A", and will raise an error if so. + + .. change:: + :tags: orm + :tickets: + + Query.join(Cls.propname, from_joinpoint=True) will check more + carefully that "Cls" is compatible with the current joinpoint, + and act the same way as Query.join("propname", from_joinpoint=True) + in that regard. + + .. change:: + :tags: sql + :tickets: 921 + + Added with_hint() method to select() construct. Specify + a table/alias, hint text, and optional dialect name, and + "hints" will be rendered in the appropriate place in the + statement. Works for Oracle, Sybase, MySQL. + + .. change:: + :tags: sql + :tickets: 1747 + + Fixed bug introduced in 0.6beta2 where column labels would + render inside of column expressions already assigned a label. + + .. change:: + :tags: postgresql + :tickets: 877 + + The psycopg2 dialect will log NOTICE messages via the + "sqlalchemy.dialects.postgresql" logger name. + + .. change:: + :tags: postgresql + :tickets: 997 + + the TIME and TIMESTAMP types are now availble from the + postgresql dialect directly, which add the PG-specific + argument 'precision' to both. 'precision' and + 'timezone' are correctly reflected for both TIME and + TIMEZONE types. + + .. change:: + :tags: mysql + :tickets: 1752 + + No longer guessing that TINYINT(1) should be BOOLEAN + when reflecting - TINYINT(1) is returned. Use Boolean/ + BOOLEAN in table definition to get boolean conversion + behavior. + + .. change:: + :tags: oracle + :tickets: 1744 + + The Oracle dialect will issue VARCHAR type definitions + using character counts, i.e. VARCHAR2(50 CHAR), so that + the column is sized in terms of characters and not bytes. + Column reflection of character types will also use + ALL_TAB_COLUMNS.CHAR_LENGTH instead of + ALL_TAB_COLUMNS.DATA_LENGTH. Both of these behaviors take + effect when the server version is 9 or higher - for + version 8, the old behaviors are used. + + .. change:: + :tags: declarative + :tickets: 1746 + + Using a mixin won't break if the mixin implements an + unpredictable __getattribute__(), i.e. Zope interfaces. + + .. change:: + :tags: declarative + :tickets: 1749 + + Using @classdecorator and similar on mixins to define + __tablename__, __table_args__, etc. now works if + the method references attributes on the ultimate + subclass. + + .. change:: + :tags: declarative + :tickets: 1751 + + relationships and columns with foreign keys aren't + allowed on declarative mixins, sorry. + + .. change:: + :tags: ext + :tickets: + + The sqlalchemy.orm.shard module now becomes an extension, + sqlalchemy.ext.horizontal_shard. The old import + works with a deprecation warning. + +.. changelog:: + :version: 0.6beta2 + :released: Sat Mar 20 2010 + + .. change:: + :tags: py3k + :tickets: + + Improved the installation/test setup regarding Python 3, + now that Distribute runs on Py3k. distribute_setup.py + is now included. See README.py3k for Python 3 installation/ + testing instructions. + + .. change:: + :tags: orm + :tickets: 1740 + + The official name for the relation() function is now + relationship(), to eliminate confusion over the relational + algebra term. relation() however will remain available + in equal capacity for the foreseeable future. + + .. change:: + :tags: orm + :tickets: 1692 + + Added "version_id_generator" argument to Mapper, this is a + callable that, given the current value of the "version_id_col", + returns the next version number. Can be used for alternate + versioning schemes such as uuid, timestamps. + + .. change:: + :tags: orm + :tickets: + + added "lockmode" kw argument to Session.refresh(), will + pass through the string value to Query the same as + in with_lockmode(), will also do version check for a + version_id_col-enabled mapping. + + .. change:: + :tags: orm + :tickets: 1188 + + Fixed bug whereby calling query(A).join(A.bs).add_entity(B) + in a joined inheritance scenario would double-add B as a + target and produce an invalid query. + + .. change:: + :tags: orm + :tickets: 1674 + + Fixed bug in session.rollback() which involved not removing + formerly "pending" objects from the session before + re-integrating "deleted" objects, typically occured with + natural primary keys. If there was a primary key conflict + between them, the attach of the deleted would fail + internally. The formerly "pending" objects are now expunged + first. + + .. change:: + :tags: orm + :tickets: 1719 + + Removed a lot of logging that nobody really cares about, + logging that remains will respond to live changes in the + log level. No significant overhead is added. + + .. change:: + :tags: orm + :tickets: + + Fixed bug in session.merge() which prevented dict-like + collections from merging. + + .. change:: + :tags: orm + :tickets: + + session.merge() works with relations that specifically + don't include "merge" in their cascade options - the target + is ignored completely. + + .. change:: + :tags: orm + :tickets: 1681 + + session.merge() will not expire existing scalar attributes + on an existing target if the target has a value for that + attribute, even if the incoming merged doesn't have + a value for the attribute. This prevents unnecessary loads + on existing items. Will still mark the attr as expired + if the destination doesn't have the attr, though, which + fulfills some contracts of deferred cols. + + .. change:: + :tags: orm + :tickets: 1680 + + The "allow_null_pks" flag is now called "allow_partial_pks", + defaults to True, acts like it did in 0.5 again. Except, + it also is implemented within merge() such that a SELECT + won't be issued for an incoming instance with partially + NULL primary key if the flag is False. + + .. change:: + :tags: orm + :tickets: 1737 + + Fixed bug in 0.6-reworked "many-to-one" optimizations + such that a many-to-one that is against a non-primary key + column on the remote table (i.e. foreign key against a + UNIQUE column) will pull the "old" value in from the + database during a change, since if it's in the session + we will need it for proper history/backref accounting, + and we can't pull from the local identity map on a + non-primary key column. + + .. change:: + :tags: orm + :tickets: 1731 + + fixed internal error which would occur if calling has() + or similar complex expression on a single-table inheritance + relation(). + + .. change:: + :tags: orm + :tickets: 1688 + + query.one() no longer applies LIMIT to the query, this to + ensure that it fully counts all object identities present + in the result, even in the case where joins may conceal + multiple identities for two or more rows. As a bonus, + one() can now also be called with a query that issued + from_statement() to start with since it no longer modifies + the query. + + .. change:: + :tags: orm + :tickets: 1727 + + query.get() now returns None if queried for an identifier + that is present in the identity map with a different class + than the one requested, i.e. when using polymorphic loading. + + .. change:: + :tags: orm + :tickets: 1706 + + A major fix in query.join(), when the "on" clause is an + attribute of an aliased() construct, but there is already + an existing join made out to a compatible target, query properly + joins to the right aliased() construct instead of sticking + onto the right side of the existing join. + + .. change:: + :tags: orm + :tickets: 1362 + + Slight improvement to the fix for to not issue + needless updates of the primary key column during a so-called + "row switch" operation, i.e. add + delete of two objects + with the same PK. + + .. change:: + :tags: orm + :tickets: + + Now uses sqlalchemy.orm.exc.DetachedInstanceError when an + attribute load or refresh action fails due to object + being detached from any Session. UnboundExecutionError + is specific to engines bound to sessions and statements. + + .. change:: + :tags: orm + :tickets: + + Query called in the context of an expression will render + disambiguating labels in all cases. Note that this does + not apply to the existing .statement and .subquery() + accessor/method, which still honors the .with_labels() + setting that defaults to False. + + .. change:: + :tags: orm + :tickets: 1676 + + Query.union() retains disambiguating labels within the + returned statement, thus avoiding various SQL composition + errors which can result from column name conflicts. + + .. change:: + :tags: orm + :tickets: + + Fixed bug in attribute history that inadvertently invoked + __eq__ on mapped instances. + + .. change:: + :tags: orm + :tickets: + + Some internal streamlining of object loading grants a + small speedup for large results, estimates are around + 10-15%. Gave the "state" internals a good solid + cleanup with less complexity, datamembers, + method calls, blank dictionary creates. + + .. change:: + :tags: orm + :tickets: 1689 + + Documentation clarification for query.delete() + + .. change:: + :tags: orm + :tickets: + + Fixed cascade bug in many-to-one relation() when attribute + was set to None, introduced in r6711 (cascade deleted + items into session during add()). + + .. change:: + :tags: orm + :tickets: 1736 + + Calling query.order_by() or query.distinct() before calling + query.select_from(), query.with_polymorphic(), or + query.from_statement() raises an exception now instead of + silently dropping those criterion. + + .. change:: + :tags: orm + :tickets: 1735 + + query.scalar() now raises an exception if more than one + row is returned. All other behavior remains the same. + + .. change:: + :tags: orm + :tickets: 1692 + + Fixed bug which caused "row switch" logic, that is an + INSERT and DELETE replaced by an UPDATE, to fail when + version_id_col was in use. + + .. change:: + :tags: sql + :tickets: 1714 + + join() will now simulate a NATURAL JOIN by default. Meaning, + if the left side is a join, it will attempt to join the right + side to the rightmost side of the left first, and not raise + any exceptions about ambiguous join conditions if successful + even if there are further join targets across the rest of + the left. + + .. change:: + :tags: sql + :tickets: + + The most common result processors conversion function were + moved to the new "processors" module. Dialect authors are + encouraged to use those functions whenever they correspond + to their needs instead of implementing custom ones. + + .. change:: + :tags: sql + :tickets: 1694, 1698 + + SchemaType and subclasses Boolean, Enum are now serializable, + including their ddl listener and other event callables. + + .. change:: + :tags: sql + :tickets: + + Some platforms will now interpret certain literal values + as non-bind parameters, rendered literally into the SQL + statement. This to support strict SQL-92 rules that are + enforced by some platforms including MS-SQL and Sybase. + In this model, bind parameters aren't allowed in the + columns clause of a SELECT, nor are certain ambiguous + expressions like "?=?". When this mode is enabled, the base + compiler will render the binds as inline literals, but only across + strings and numeric values. Other types such as dates + will raise an error, unless the dialect subclass defines + a literal rendering function for those. The bind parameter + must have an embedded literal value already or an error + is raised (i.e. won't work with straight bindparam('x')). + Dialects can also expand upon the areas where binds are not + accepted, such as within argument lists of functions + (which don't work on MS-SQL when native SQL binding is used). + + .. change:: + :tags: sql + :tickets: + + Added "unicode_errors" parameter to String, Unicode, etc. + Behaves like the 'errors' keyword argument to + the standard library's string.decode() functions. This flag + requires that `convert_unicode` is set to `"force"` - otherwise, + SQLAlchemy is not guaranteed to handle the task of unicode + conversion. Note that this flag adds significant performance + overhead to row-fetching operations for backends that already + return unicode objects natively (which most DBAPIs do). This + flag should only be used as an absolute last resort for reading + strings from a column with varied or corrupted encodings, + which only applies to databases that accept invalid encodings + in the first place (i.e. MySQL. *not* PG, Sqlite, etc.) + + .. change:: + :tags: sql + :tickets: + + Added math negation operator support, -x. + + .. change:: + :tags: sql + :tickets: + + FunctionElement subclasses are now directly executable the + same way any func.foo() construct is, with automatic + SELECT being applied when passed to execute(). + + .. change:: + :tags: sql + :tickets: + + The "type" and "bind" keyword arguments of a func.foo() + construct are now local to "func." constructs and are + not part of the FunctionElement base class, allowing + a "type" to be handled in a custom constructor or + class-level variable. + + .. change:: + :tags: sql + :tickets: + + Restored the keys() method to ResultProxy. + + .. change:: + :tags: sql + :tickets: 1647, 1683 + + The type/expression system now does a more complete job + of determining the return type from an expression + as well as the adaptation of the Python operator into + a SQL operator, based on the full left/right/operator + of the given expression. In particular + the date/time/interval system created for Postgresql + EXTRACT in has now been generalized into + the type system. The previous behavior which often + occured of an expression "column + literal" forcing + the type of "literal" to be the same as that of "column" + will now usually not occur - the type of + "literal" is first derived from the Python type of the + literal, assuming standard native Python types + date + types, before falling back to that of the known type + on the other side of the expression. If the + "fallback" type is compatible (i.e. CHAR from String), + the literal side will use that. TypeDecorator + types override this by default to coerce the "literal" + side unconditionally, which can be changed by implementing + the coerce_compared_value() method. Also part of. + + .. change:: + :tags: sql + :tickets: + + Made sqlalchemy.sql.expressions.Executable part of public + API, used for any expression construct that can be sent to + execute(). FunctionElement now inherits Executable so that + it gains execution_options(), which are also propagated + to the select() that's generated within execute(). + Executable in turn subclasses _Generative which marks + any ClauseElement that supports the @_generative + decorator - these may also become "public" for the benefit + of the compiler extension at some point. + + .. change:: + :tags: sql + :tickets: 1579 + + A change to the solution for - an end-user + defined bind parameter name that directly conflicts with + a column-named bind generated directly from the SET or + VALUES clause of an update/insert generates a compile error. + This reduces call counts and eliminates some cases where + undesirable name conflicts could still occur. + + .. change:: + :tags: sql + :tickets: 1705 + + Column() requires a type if it has no foreign keys (this is + not new). An error is now raised if a Column() has no type + and no foreign keys. + + .. change:: + :tags: sql + :tickets: 1717 + + the "scale" argument of the Numeric() type is honored when + coercing a returned floating point value into a string + on its way to Decimal - this allows accuracy to function + on SQLite, MySQL. + + .. change:: + :tags: sql + :tickets: + + the copy() method of Column now copies over uninitialized + "on table attach" events. Helps with the new declarative + "mixin" capability. + + .. change:: + :tags: engines + :tickets: + + Added an optional C extension to speed up the sql layer by + reimplementing RowProxy and the most common result processors. + The actual speedups will depend heavily on your DBAPI and + the mix of datatypes used in your tables, and can vary from + a 30% improvement to more than 200%. It also provides a modest + (~15-20%) indirect improvement to ORM speed for large queries. + Note that it is *not* built/installed by default. + See README for installation instructions. + + .. change:: + :tags: engines + :tickets: + + the execution sequence pulls all rowcount/last inserted ID + info from the cursor before commit() is called on the + DBAPI connection in an "autocommit" scenario. This helps + mxodbc with rowcount and is probably a good idea overall. + + .. change:: + :tags: engines + :tickets: 1719 + + Opened up logging a bit such that isEnabledFor() is called + more often, so that changes to the log level for engine/pool + will be reflected on next connect. This adds a small + amount of method call overhead. It's negligible and will make + life a lot easier for all those situations when logging + just happens to be configured after create_engine() is called. + + .. change:: + :tags: engines + :tickets: + + The assert_unicode flag is deprecated. SQLAlchemy will raise + a warning in all cases where it is asked to encode a non-unicode + Python string, as well as when a Unicode or UnicodeType type + is explicitly passed a bytestring. The String type will do nothing + for DBAPIs that already accept Python unicode objects. + + .. change:: + :tags: engines + :tickets: + + Bind parameters are sent as a tuple instead of a list. Some + backend drivers will not accept bind parameters as a list. + + .. change:: + :tags: engines + :tickets: + + threadlocal engine wasn't properly closing the connection + upon close() - fixed that. + + .. change:: + :tags: engines + :tickets: + + Transaction object doesn't rollback or commit if it isn't + "active", allows more accurate nesting of begin/rollback/commit. + + .. change:: + :tags: engines + :tickets: + + Python unicode objects as binds result in the Unicode type, + not string, thus eliminating a certain class of unicode errors + on drivers that don't support unicode binds. + + .. change:: + :tags: engines + :tickets: 1555 + + Added "logging_name" argument to create_engine(), Pool() constructor + as well as "pool_logging_name" argument to create_engine() which + filters down to that of Pool. Issues the given string name + within the "name" field of logging messages instead of the default + hex identifier string. + + .. change:: + :tags: engines + :tickets: + + The visit_pool() method of Dialect is removed, and replaced with + connect(). This method returns a callable which receives + the raw DBAPI connection after each one is created. The callable + is assembled into a first_connect/connect pool listener by the + connection strategy if non-None. Provides a simpler interface + for dialects. + + .. change:: + :tags: engines + :tickets: 1728 + + StaticPool now initializes, disposes and recreates without + opening a new connection - the connection is only opened when + first requested. dispose() also works on AssertionPool now. + + .. change:: + :tags: ticket: 1673, metadata + :tickets: + + Added the ability to strip schema information when using + "tometadata" by passing "schema=None" as an argument. If schema + is not specified then the table's schema is retained. + + .. change:: + :tags: declarative + :tickets: + + DeclarativeMeta exclusively uses cls.__dict__ (not dict_) + as the source of class information; _as_declarative exclusively + uses the dict_ passed to it as the source of class information + (which when using DeclarativeMeta is cls.__dict__). This should + in theory make it easier for custom metaclasses to modify + the state passed into _as_declarative. + + .. change:: + :tags: declarative + :tickets: 1707 + + declarative now accepts mixin classes directly, as a means + to provide common functional and column-based elements on + all subclasses, as well as a means to propagate a fixed + set of __table_args__ or __mapper_args__ to subclasses. + For custom combinations of __table_args__/__mapper_args__ from + an inherited mixin to local, descriptors can now be used. + New details are all up in the Declarative documentation. + Thanks to Chris Withers for putting up with my strife + on this. + + .. change:: + :tags: declarative + :tickets: 1393 + + the __mapper_args__ dict is copied when propagating to a subclass, + and is taken straight off the class __dict__ to avoid any + propagation from the parent. mapper inheritance already + propagates the things you want from the parent mapper. + + .. change:: + :tags: declarative + :tickets: 1732 + + An exception is raised when a single-table subclass specifies + a column that is already present on the base class. + + .. change:: + :tags: mysql + :tickets: 1655 + + Fixed reflection bug whereby when COLLATE was present, + nullable flag and server defaults would not be reflected. + + .. change:: + :tags: mysql + :tickets: + + Fixed reflection of TINYINT(1) "boolean" columns defined with + integer flags like UNSIGNED. + + .. change:: + :tags: mysql + :tickets: 1668 + + Further fixes for the mysql-connector dialect. + + .. change:: + :tags: mysql + :tickets: 1496 + + Composite PK table on InnoDB where the "autoincrement" column + isn't first will emit an explicit "KEY" phrase within + CREATE TABLE thereby avoiding errors. + + .. change:: + :tags: mysql + :tickets: 1634 + + Added reflection/create table support for a wide range + of MySQL keywords. + + .. change:: + :tags: mysql + :tickets: 1580 + + Fixed import error which could occur reflecting tables on + a Windows host + + .. change:: + :tags: mssql + :tickets: + + Re-established support for the pymssql dialect. + + .. change:: + :tags: mssql + :tickets: + + Various fixes for implicit returning, reflection, + etc. - the MS-SQL dialects aren't quite complete + in 0.6 yet (but are close) + + .. change:: + :tags: mssql + :tickets: 1710 + + Added basic support for mxODBC. + + .. change:: + :tags: mssql + :tickets: + + Removed the text_as_varchar option. + + .. change:: + :tags: oracle + :tickets: + + "out" parameters require a type that is supported by + cx_oracle. An error will be raised if no cx_oracle + type can be found. + + .. change:: + :tags: oracle + :tickets: + + Oracle 'DATE' now does not perform any result processing, + as the DATE type in Oracle stores full date+time objects, + that's what you'll get. Note that the generic types.Date + type *will* still call value.date() on incoming values, + however. When reflecting a table, the reflected type + will be 'DATE'. + + .. change:: + :tags: oracle + :tickets: 1670 + + Added preliminary support for Oracle's WITH_UNICODE + mode. At the very least this establishes initial + support for cx_Oracle with Python 3. When WITH_UNICODE + mode is used in Python 2.xx, a large and scary warning + is emitted asking that the user seriously consider + the usage of this difficult mode of operation. + + .. change:: + :tags: oracle + :tickets: 1712 + + The except_() method now renders as MINUS on Oracle, + which is more or less equivalent on that platform. + + .. change:: + :tags: oracle + :tickets: 651 + + Added support for rendering and reflecting + TIMESTAMP WITH TIME ZONE, i.e. TIMESTAMP(timezone=True). + + .. change:: + :tags: oracle + :tickets: + + Oracle INTERVAL type can now be reflected. + + .. change:: + :tags: sqlite + :tickets: 1685 + + Added "native_datetime=True" flag to create_engine(). + This will cause the DATE and TIMESTAMP types to skip + all bind parameter and result row processing, under + the assumption that PARSE_DECLTYPES has been enabled + on the connection. Note that this is not entirely + compatible with the "func.current_date()", which + will be returned as a string. + + .. change:: + :tags: sybase + :tickets: + + Implemented a preliminary working dialect for Sybase, + with sub-implementations for Python-Sybase as well + as Pyodbc. Handles table + creates/drops and basic round trip functionality. + Does not yet include reflection or comprehensive + support of unicode/special expressions/etc. + + .. change:: + :tags: examples + :tickets: + + Changed the beaker cache example a bit to have a separate + RelationCache option for lazyload caching. This object + does a lookup among any number of potential attributes + more efficiently by grouping several into a common structure. + Both FromCache and RelationCache are simpler individually. + + .. change:: + :tags: documentation + :tickets: 1700 + + Major cleanup work in the docs to link class, function, and + method names into the API docs. + +.. changelog:: + :version: 0.6beta1 + :released: Wed Feb 03 2010 + + .. change:: + :tags: Release, Major + :tickets: + + For the full set of feature descriptions, see + http://www.sqlalchemy.org/trac/wiki/06Migration . + This document is a work in progress. + + .. change:: + :tags: Release, Major + :tickets: + + All bug fixes and feature enhancements from the most + recent 0.5 version and below are also included within 0.6. + + .. change:: + :tags: Release, Major + :tickets: + + Platforms targeted now include Python 2.4/2.5/2.6, Python + 3.1, Jython2.5. + + .. change:: + :tags: orm + :tickets: + + Changes to query.update() and query.delete(): + - the 'expire' option on query.update() has been renamed to + 'fetch', thus matching that of query.delete(). + 'expire' is deprecated and issues a warning. + + - query.update() and query.delete() both default to + 'evaluate' for the synchronize strategy. + + - the 'synchronize' strategy for update() and delete() + raises an error on failure. There is no implicit fallback + onto "fetch". Failure of evaluation is based on the + structure of criteria, so success/failure is deterministic + based on code structure. + + .. change:: + :tags: orm + :tickets: 1186, 1492, 1544 + + Enhancements on many-to-one relations: + - many-to-one relations now fire off a lazyload in fewer + cases, including in most cases will not fetch the "old" + value when a new one is replaced. + + - many-to-one relation to a joined-table subclass now uses + get() for a simple load (known as the "use_get" + condition), i.e. Related->Sub(Base), without the need to + redefine the primaryjoin condition in terms of the base + table. + + - specifying a foreign key with a declarative column, i.e. + ForeignKey(MyRelatedClass.id) doesn't break the "use_get" + condition from taking place + + - relation(), eagerload(), and eagerload_all() now feature + an option called "innerjoin". Specify `True` or `False` to + control whether an eager join is constructed as an INNER + or OUTER join. Default is `False` as always. The mapper + options will override whichever setting is specified on + relation(). Should generally be set for many-to-one, not + nullable foreign key relations to allow improved join + performance. + + - the behavior of eagerloading such that the main query is + wrapped in a subquery when LIMIT/OFFSET are present now + makes an exception for the case when all eager loads are + many-to-one joins. In those cases, the eager joins are + against the parent table directly along with the + limit/offset without the extra overhead of a subquery, + since a many-to-one join does not add rows to the result. + + .. change:: + :tags: orm + :tickets: + + Enhancements / Changes on Session.merge(): + + .. change:: + :tags: orm + :tickets: + + the "dont_load=True" flag on Session.merge() is deprecated + and is now "load=False". + + .. change:: + :tags: orm + :tickets: + + Session.merge() is performance optimized, using half the + call counts for "load=False" mode compared to 0.5 and + significantly fewer SQL queries in the case of collections + for "load=True" mode. + + .. change:: + :tags: orm + :tickets: + + merge() will not issue a needless merge of attributes if the + given instance is the same instance which is already present. + + .. change:: + :tags: orm + :tickets: + + merge() now also merges the "options" associated with a given + state, i.e. those passed through query.options() which follow + along with an instance, such as options to eagerly- or + lazyily- load various attributes. This is essential for + the construction of highly integrated caching schemes. This + is a subtle behavioral change vs. 0.5. + + .. change:: + :tags: orm + :tickets: + + A bug was fixed regarding the serialization of the "loader + path" present on an instance's state, which is also necessary + when combining the usage of merge() with serialized state + and associated options that should be preserved. + + .. change:: + :tags: orm + :tickets: + + The all new merge() is showcased in a new comprehensive + example of how to integrate Beaker with SQLAlchemy. See + the notes in the "examples" note below. + + .. change:: + :tags: orm + :tickets: 1362 + + Primary key values can now be changed on a joined-table inheritance + object, and ON UPDATE CASCADE will be taken into account when + the flush happens. Set the new "passive_updates" flag to False + on mapper() when using SQLite or MySQL/MyISAM. + + .. change:: + :tags: orm + :tickets: 1671 + + flush() now detects when a primary key column was updated by + an ON UPDATE CASCADE operation from another primary key, and + can then locate the row for a subsequent UPDATE on the new PK + value. This occurs when a relation() is there to establish + the relationship as well as passive_updates=True. + + .. change:: + :tags: orm + :tickets: + + the "save-update" cascade will now cascade the pending *removed* + values from a scalar or collection attribute into the new session + during an add() operation. This so that the flush() operation + will also delete or modify rows of those disconnected items. + + .. change:: + :tags: orm + :tickets: 1531 + + Using a "dynamic" loader with a "secondary" table now produces + a query where the "secondary" table is *not* aliased. This + allows the secondary Table object to be used in the "order_by" + attribute of the relation(), and also allows it to be used + in filter criterion against the dynamic relation. + + .. change:: + :tags: orm + :tickets: 1643 + + relation() with uselist=False will emit a warning when + an eager or lazy load locates more than one valid value for + the row. This may be due to primaryjoin/secondaryjoin + conditions which aren't appropriate for an eager LEFT OUTER + JOIN or for other conditions. + + .. change:: + :tags: orm + :tickets: 1633 + + an explicit check occurs when a synonym() is used with + map_column=True, when a ColumnProperty (deferred or otherwise) + exists separately in the properties dictionary sent to mapper + with the same keyname. Instead of silently replacing + the existing property (and possible options on that property), + an error is raised. + + .. change:: + :tags: orm + :tickets: + + a "dynamic" loader sets up its query criterion at construction + time so that the actual query is returned from non-cloning + accessors like "statement". + + .. change:: + :tags: orm + :tickets: + + the "named tuple" objects returned when iterating a + Query() are now pickleable. + + .. change:: + :tags: orm + :tickets: 1542 + + mapping to a select() construct now requires that you + make an alias() out of it distinctly. This to eliminate + confusion over such issues as + + .. change:: + :tags: orm + :tickets: 1537 + + query.join() has been reworked to provide more consistent + behavior and more flexibility (includes) + + .. change:: + :tags: orm + :tickets: + + query.select_from() accepts multiple clauses to produce + multiple comma separated entries within the FROM clause. + Useful when selecting from multiple-homed join() clauses. + + .. change:: + :tags: orm + :tickets: + + query.select_from() also accepts mapped classes, aliased() + constructs, and mappers as arguments. In particular this + helps when querying from multiple joined-table classes to ensure + the full join gets rendered. + + .. change:: + :tags: orm + :tickets: 1135 + + query.get() can be used with a mapping to an outer join + where one or more of the primary key values are None. + + .. change:: + :tags: orm + :tickets: 1568 + + query.from_self(), query.union(), others which do a + "SELECT * from (SELECT...)" type of nesting will do + a better job translating column expressions within the subquery + to the columns clause of the outer query. This is + potentially backwards incompatible with 0.5, in that this + may break queries with literal expressions that do not have labels + applied (i.e. literal('foo'), etc.) + + .. change:: + :tags: orm + :tickets: 1622 + + relation primaryjoin and secondaryjoin now check that they + are column-expressions, not just clause elements. this prohibits + things like FROM expressions being placed there directly. + + .. change:: + :tags: orm + :tickets: 1415 + + `expression.null()` is fully understood the same way + None is when comparing an object/collection-referencing + attribute within query.filter(), filter_by(), etc. + + .. change:: + :tags: orm + :tickets: 1052 + + added "make_transient()" helper function which transforms a + persistent/ detached instance into a transient one (i.e. + deletes the instance_key and removes from any session.) + + .. change:: + :tags: orm + :tickets: 1339 + + the allow_null_pks flag on mapper() is deprecated, and + the feature is turned "on" by default. This means that + a row which has a non-null value for any of its primary key + columns will be considered an identity. The need for this + scenario typically only occurs when mapping to an outer join. + + .. change:: + :tags: orm + :tickets: + + the mechanics of "backref" have been fully merged into the + finer grained "back_populates" system, and take place entirely + within the _generate_backref() method of RelationProperty. This + makes the initialization procedure of RelationProperty + simpler and allows easier propagation of settings (such as from + subclasses of RelationProperty) into the reverse reference. + The internal BackRef() is gone and backref() returns a plain + tuple that is understood by RelationProperty. + + .. change:: + :tags: orm + :tickets: 1569 + + The version_id_col feature on mapper() will raise a warning when + used with dialects that don't support "rowcount" adequately. + + .. change:: + :tags: orm + :tickets: + + added "execution_options()" to Query, to so options can be + passed to the resulting statement. Currently only + Select-statements have these options, and the only option + used is "stream_results", and the only dialect which knows + "stream_results" is psycopg2. + + .. change:: + :tags: orm + :tickets: + + Query.yield_per() will set the "stream_results" statement + option automatically. + + .. change:: + :tags: orm + :tickets: + + Deprecated or removed: + * 'allow_null_pks' flag on mapper() is deprecated. It does + nothing now and the setting is "on" in all cases. + * 'transactional' flag on sessionmaker() and others is + removed. Use 'autocommit=True' to indicate 'transactional=False'. + * 'polymorphic_fetch' argument on mapper() is removed. + Loading can be controlled using the 'with_polymorphic' + option. + * 'select_table' argument on mapper() is removed. Use + 'with_polymorphic=("*", )' for this + functionality. + * 'proxy' argument on synonym() is removed. This flag + did nothing throughout 0.5, as the "proxy generation" + behavior is now automatic. + * Passing a single list of elements to eagerload(), + eagerload_all(), contains_eager(), lazyload(), + defer(), and undefer() instead of multiple positional + *args is deprecated. + * Passing a single list of elements to query.order_by(), + query.group_by(), query.join(), or query.outerjoin() + instead of multiple positional *args is deprecated. + * query.iterate_instances() is removed. Use query.instances(). + * Query.query_from_parent() is removed. Use the + sqlalchemy.orm.with_parent() function to produce a + "parent" clause, or alternatively query.with_parent(). + * query._from_self() is removed, use query.from_self() + instead. + * the "comparator" argument to composite() is removed. + Use "comparator_factory". + * RelationProperty._get_join() is removed. + * the 'echo_uow' flag on Session is removed. Use + logging on the "sqlalchemy.orm.unitofwork" name. + * session.clear() is removed. use session.expunge_all(). + * session.save(), session.update(), session.save_or_update() + are removed. Use session.add() and session.add_all(). + * the "objects" flag on session.flush() remains deprecated. + * the "dont_load=True" flag on session.merge() is deprecated + in favor of "load=False". + * ScopedSession.mapper remains deprecated. See the + usage recipe at + http://www.sqlalchemy.org/trac/wiki/UsageRecipes/SessionAwareMapper + * passing an InstanceState (internal SQLAlchemy state object) to + attributes.init_collection() or attributes.get_history() is + deprecated. These functions are public API and normally + expect a regular mapped object instance. + * the 'engine' parameter to declarative_base() is removed. + Use the 'bind' keyword argument. + + .. change:: + :tags: sql + :tickets: + + the "autocommit" flag on select() and text() as well + as select().autocommit() are deprecated - now call + .execution_options(autocommit=True) on either of those + constructs, also available directly on Connection and orm.Query. + + .. change:: + :tags: sql + :tickets: + + the autoincrement flag on column now indicates the column + which should be linked to cursor.lastrowid, if that method + is used. See the API docs for details. + + .. change:: + :tags: sql + :tickets: 1566 + + an executemany() now requires that all bound parameter + sets require that all keys are present which are + present in the first bound parameter set. The structure + and behavior of an insert/update statement is very much + determined by the first parameter set, including which + defaults are going to fire off, and a minimum of + guesswork is performed with all the rest so that performance + is not impacted. For this reason defaults would otherwise + silently "fail" for missing parameters, so this is now guarded + against. + + .. change:: + :tags: sql + :tickets: + + returning() support is native to insert(), update(), + delete(). Implementations of varying levels of + functionality exist for Postgresql, Firebird, MSSQL and + Oracle. returning() can be called explicitly with column + expressions which are then returned in the resultset, + usually via fetchone() or first(). + + insert() constructs will also use RETURNING implicitly to + get newly generated primary key values, if the database + version in use supports it (a version number check is + performed). This occurs if no end-user returning() was + specified. + + .. change:: + :tags: sql + :tickets: 1665 + + union(), intersect(), except() and other "compound" types + of statements have more consistent behavior w.r.t. + parenthesizing. Each compound element embedded within + another will now be grouped with parenthesis - previously, + the first compound element in the list would not be grouped, + as SQLite doesn't like a statement to start with + parenthesis. However, Postgresql in particular has + precedence rules regarding INTERSECT, and it is + more consistent for parenthesis to be applied equally + to all sub-elements. So now, the workaround for SQLite + is also what the workaround for PG was previously - + when nesting compound elements, the first one usually needs + ".alias().select()" called on it to wrap it inside + of a subquery. + + .. change:: + :tags: sql + :tickets: 1579 + + insert() and update() constructs can now embed bindparam() + objects using names that match the keys of columns. These + bind parameters will circumvent the usual route to those + keys showing up in the VALUES or SET clause of the generated + SQL. + + .. change:: + :tags: sql + :tickets: 1524 + + the Binary type now returns data as a Python string + (or a "bytes" type in Python 3), instead of the built- + in "buffer" type. This allows symmetric round trips + of binary data. + + .. change:: + :tags: sql + :tickets: + + Added a tuple_() construct, allows sets of expressions + to be compared to another set, typically with IN against + composite primary keys or similar. Also accepts an + IN with multiple columns. The "scalar select can + have only one column" error message is removed - will + rely upon the database to report problems with + col mismatch. + + .. change:: + :tags: sql + :tickets: + + User-defined "default" and "onupdate" callables which + accept a context should now call upon + "context.current_parameters" to get at the dictionary + of bind parameters currently being processed. This + dict is available in the same way regardless of + single-execute or executemany-style statement execution. + + .. change:: + :tags: sql + :tickets: 1428 + + multi-part schema names, i.e. with dots such as + "dbo.master", are now rendered in select() labels + with underscores for dots, i.e. "dbo_master_table_column". + This is a "friendly" label that behaves better + in result sets. + + .. change:: + :tags: sql + :tickets: + + removed needless "counter" behavior with select() + labelnames that match a column name in the table, + i.e. generates "tablename_id" for "id", instead of + "tablename_id_1" in an attempt to avoid naming + conflicts, when the table has a column actually + named "tablename_id" - this is because + the labeling logic is always applied to all columns + so a naming conflict will never occur. + + .. change:: + :tags: sql + :tickets: 1628 + + calling expr.in_([]), i.e. with an empty list, emits a warning + before issuing the usual "expr != expr" clause. The + "expr != expr" can be very expensive, and it's preferred + that the user not issue in_() if the list is empty, + instead simply not querying, or modifying the criterion + as appropriate for more complex situations. + + .. change:: + :tags: sql + :tickets: + + Added "execution_options()" to select()/text(), which set the + default options for the Connection. See the note in "engines". + + .. change:: + :tags: sql + :tickets: 1131 + + Deprecated or removed: + * "scalar" flag on select() is removed, use + select.as_scalar(). + * "shortname" attribute on bindparam() is removed. + * postgres_returning, firebird_returning flags on + insert(), update(), delete() are deprecated, use + the new returning() method. + * fold_equivalents flag on join is deprecated (will remain + until is implemented) + + .. change:: + :tags: engines + :tickets: 443 + + transaction isolation level may be specified with + create_engine(... isolation_level="..."); available on + postgresql and sqlite. + + .. change:: + :tags: engines + :tickets: + + Connection has execution_options(), generative method + which accepts keywords that affect how the statement + is executed w.r.t. the DBAPI. Currently supports + "stream_results", causes psycopg2 to use a server + side cursor for that statement, as well as + "autocommit", which is the new location for the "autocommit" + option from select() and text(). select() and + text() also have .execution_options() as well as + ORM Query(). + + .. change:: + :tags: engines + :tickets: 1630 + + fixed the import for entrypoint-driven dialects to + not rely upon silly tb_info trick to determine import + error status. + + .. change:: + :tags: engines + :tickets: + + added first() method to ResultProxy, returns first row and + closes result set immediately. + + .. change:: + :tags: engines + :tickets: + + RowProxy objects are now pickleable, i.e. the object returned + by result.fetchone(), result.fetchall() etc. + + .. change:: + :tags: engines + :tickets: + + RowProxy no longer has a close() method, as the row no longer + maintains a reference to the parent. Call close() on + the parent ResultProxy instead, or use autoclose. + + .. change:: + :tags: engines + :tickets: 1586 + + ResultProxy internals have been overhauled to greatly reduce + method call counts when fetching columns. Can provide a large + speed improvement (up to more than 100%) when fetching large + result sets. The improvement is larger when fetching columns + that have no type-level processing applied and when using + results as tuples (instead of as dictionaries). Many + thanks to Elixir's Gaëtan de Menten for this dramatic + improvement ! + + .. change:: + :tags: engines + :tickets: + + Databases which rely upon postfetch of "last inserted id" + to get at a generated sequence value (i.e. MySQL, MS-SQL) + now work correctly when there is a composite primary key + where the "autoincrement" column is not the first primary + key column in the table. + + .. change:: + :tags: engines + :tickets: + + the last_inserted_ids() method has been renamed to the + descriptor "inserted_primary_key". + + .. change:: + :tags: engines + :tickets: 1554 + + setting echo=False on create_engine() now sets the loglevel + to WARN instead of NOTSET. This so that logging can be + disabled for a particular engine even if logging + for "sqlalchemy.engine" is enabled overall. Note that the + default setting of "echo" is `None`. + + .. change:: + :tags: engines + :tickets: + + ConnectionProxy now has wrapper methods for all transaction + lifecycle events, including begin(), rollback(), commit() + begin_nested(), begin_prepared(), prepare(), release_savepoint(), + etc. + + .. change:: + :tags: engines + :tickets: + + Connection pool logging now uses both INFO and DEBUG + log levels for logging. INFO is for major events such + as invalidated connections, DEBUG for all the acquire/return + logging. `echo_pool` can be False, None, True or "debug" + the same way as `echo` works. + + .. change:: + :tags: engines + :tickets: 1621 + + All pyodbc-dialects now support extra pyodbc-specific + kw arguments 'ansi', 'unicode_results', 'autocommit'. + + .. change:: + :tags: engines + :tickets: + + the "threadlocal" engine has been rewritten and simplified + and now supports SAVEPOINT operations. + + .. change:: + :tags: engines + :tickets: + + deprecated or removed + * result.last_inserted_ids() is deprecated. Use + result.inserted_primary_key + * dialect.get_default_schema_name(connection) is now + public via dialect.default_schema_name. + * the "connection" argument from engine.transaction() and + engine.run_callable() is removed - Connection itself + now has those methods. All four methods accept + *args and **kwargs which are passed to the given callable, + as well as the operating connection. + + .. change:: + :tags: schema + :tickets: 1541 + + the `__contains__()` method of `MetaData` now accepts + strings or `Table` objects as arguments. If given + a `Table`, the argument is converted to `table.key` first, + i.e. "[schemaname.]" + + .. change:: + :tags: schema + :tickets: + + deprecated MetaData.connect() and + ThreadLocalMetaData.connect() have been removed - send + the "bind" attribute to bind a metadata. + + .. change:: + :tags: schema + :tickets: + + deprecated metadata.table_iterator() method removed (use + sorted_tables) + + .. change:: + :tags: schema + :tickets: + + deprecated PassiveDefault - use DefaultClause. + + .. change:: + :tags: schema + :tickets: + + the "metadata" argument is removed from DefaultGenerator + and subclasses, but remains locally present on Sequence, + which is a standalone construct in DDL. + + .. change:: + :tags: schema + :tickets: + + Removed public mutability from Index and Constraint + objects: + - ForeignKeyConstraint.append_element() + - Index.append_column() + - UniqueConstraint.append_column() + - PrimaryKeyConstraint.add() + - PrimaryKeyConstraint.remove() + These should be constructed declaratively (i.e. in one + construction). + + .. change:: + :tags: schema + :tickets: 1545 + + The "start" and "increment" attributes on Sequence now + generate "START WITH" and "INCREMENT BY" by default, + on Oracle and Postgresql. Firebird doesn't support + these keywords right now. + + .. change:: + :tags: schema + :tickets: + + UniqueConstraint, Index, PrimaryKeyConstraint all accept + lists of column names or column objects as arguments. + + .. change:: + :tags: schema + :tickets: + + Other removed things: + - Table.key (no idea what this was for) + - Table.primary_key is not assignable - use + table.append_constraint(PrimaryKeyConstraint(...)) + - Column.bind (get via column.table.bind) + - Column.metadata (get via column.table.metadata) + - Column.sequence (use column.default) + - ForeignKey(constraint=some_parent) (is now private _constraint) + + .. change:: + :tags: schema + :tickets: + + The use_alter flag on ForeignKey is now a shortcut option + for operations that can be hand-constructed using the + DDL() event system. A side effect of this refactor is + that ForeignKeyConstraint objects with use_alter=True + will *not* be emitted on SQLite, which does not support + ALTER for foreign keys. + + .. change:: + :tags: schema + :tickets: 1605 + + ForeignKey and ForeignKeyConstraint objects now correctly + copy() all their public keyword arguments. + + .. change:: + :tags: Reflection/Inspection + :tickets: + + Table reflection has been expanded and generalized into + a new API called "sqlalchemy.engine.reflection.Inspector". + The Inspector object provides fine-grained information about + a wide variety of schema information, with room for expansion, + including table names, column names, view definitions, sequences, + indexes, etc. + + .. change:: + :tags: Reflection/Inspection + :tickets: + + Views are now reflectable as ordinary Table objects. The same + Table constructor is used, with the caveat that "effective" + primary and foreign key constraints aren't part of the reflection + results; these have to be specified explicitly if desired. + + .. change:: + :tags: Reflection/Inspection + :tickets: + + The existing autoload=True system now uses Inspector underneath + so that each dialect need only return "raw" data about tables + and other objects - Inspector is the single place that information + is compiled into Table objects so that consistency is at a maximum. + + .. change:: + :tags: DDL + :tickets: + + the DDL system has been greatly expanded. the DDL() class + now extends the more generic DDLElement(), which forms the basis + of many new constructs: + + - CreateTable() + - DropTable() + - AddConstraint() + - DropConstraint() + - CreateIndex() + - DropIndex() + - CreateSequence() + - DropSequence() + + These support "on" and "execute-at()" just like plain DDL() + does. User-defined DDLElement subclasses can be created and + linked to a compiler using the sqlalchemy.ext.compiler extension. + + .. change:: + :tags: DDL + :tickets: + + The signature of the "on" callable passed to DDL() and + DDLElement() is revised as follows: + + "ddl" - the DDLElement object itself. + "event" - the string event name. + "target" - previously "schema_item", the Table or + MetaData object triggering the event. + "connection" - the Connection object in use for the operation. + **kw - keyword arguments. In the case of MetaData before/after + create/drop, the list of Table objects for which + CREATE/DROP DDL is to be issued is passed as the kw + argument "tables". This is necessary for metadata-level + DDL that is dependent on the presence of specific tables. + + - the "schema_item" attribute of DDL has been renamed to + "target". + + .. change:: + :tags: dialect, refactor + :tickets: + + Dialect modules are now broken into database dialects + plus DBAPI implementations. Connect URLs are now + preferred to be specified using dialect+driver://..., + i.e. "mysql+mysqldb://scott:tiger@localhost/test". See + the 0.6 documentation for examples. + + .. change:: + :tags: dialect, refactor + :tickets: + + the setuptools entrypoint for external dialects is now + called "sqlalchemy.dialects". + + .. change:: + :tags: dialect, refactor + :tickets: + + the "owner" keyword argument is removed from Table. Use + "schema" to represent any namespaces to be prepended to + the table name. + + .. change:: + :tags: dialect, refactor + :tickets: + + server_version_info becomes a static attribute. + + .. change:: + :tags: dialect, refactor + :tickets: + + dialects receive an initialize() event on initial + connection to determine connection properties. + + .. change:: + :tags: dialect, refactor + :tickets: + + dialects receive a visit_pool event have an opportunity + to establish pool listeners. + + .. change:: + :tags: dialect, refactor + :tickets: + + cached TypeEngine classes are cached per-dialect class + instead of per-dialect. + + .. change:: + :tags: dialect, refactor + :tickets: + + new UserDefinedType should be used as a base class for + new types, which preserves the 0.5 behavior of + get_col_spec(). + + .. change:: + :tags: dialect, refactor + :tickets: + + The result_processor() method of all type classes now + accepts a second argument "coltype", which is the DBAPI + type argument from cursor.description. This argument + can help some types decide on the most efficient processing + of result values. + + .. change:: + :tags: dialect, refactor + :tickets: + + Deprecated Dialect.get_params() removed. + + .. change:: + :tags: dialect, refactor + :tickets: + + Dialect.get_rowcount() has been renamed to a descriptor + "rowcount", and calls cursor.rowcount directly. Dialects + which need to hardwire a rowcount in for certain calls + should override the method to provide different behavior. + + .. change:: + :tags: dialect, refactor + :tickets: 1566 + + DefaultRunner and subclasses have been removed. The job + of this object has been simplified and moved into + ExecutionContext. Dialects which support sequences should + add a `fire_sequence()` method to their execution context + implementation. + + .. change:: + :tags: dialect, refactor + :tickets: + + Functions and operators generated by the compiler now use + (almost) regular dispatch functions of the form + "visit_" and "visit__fn" to provide + customed processing. This replaces the need to copy the + "functions" and "operators" dictionaries in compiler + subclasses with straightforward visitor methods, and also + allows compiler subclasses complete control over + rendering, as the full _Function or _BinaryExpression + object is passed in. + + .. change:: + :tags: postgresql + :tickets: + + New dialects: pg8000, zxjdbc, and pypostgresql + on py3k. + + .. change:: + :tags: postgresql + :tickets: + + The "postgres" dialect is now named "postgresql" ! + Connection strings look like: + + postgresql://scott:tiger@localhost/test + postgresql+pg8000://scott:tiger@localhost/test + + The "postgres" name remains for backwards compatiblity + in the following ways: + + - There is a "postgres.py" dummy dialect which + allows old URLs to work, i.e. + postgres://scott:tiger@localhost/test + + - The "postgres" name can be imported from the old + "databases" module, i.e. "from + sqlalchemy.databases import postgres" as well as + "dialects", "from sqlalchemy.dialects.postgres + import base as pg", will send a deprecation + warning. + + - Special expression arguments are now named + "postgresql_returning" and "postgresql_where", but + the older "postgres_returning" and + "postgres_where" names still work with a + deprecation warning. + + .. change:: + :tags: postgresql + :tickets: + + "postgresql_where" now accepts SQL expressions which + can also include literals, which will be quoted as needed. + + .. change:: + :tags: postgresql + :tickets: + + The psycopg2 dialect now uses psycopg2's "unicode extension" + on all new connections, which allows all String/Text/etc. + types to skip the need to post-process bytestrings into + unicode (an expensive step due to its volume). Other + dialects which return unicode natively (pg8000, zxjdbc) + also skip unicode post-processing. + + .. change:: + :tags: postgresql + :tickets: 1511 + + Added new ENUM type, which exists as a schema-level + construct and extends the generic Enum type. Automatically + associates itself with tables and their parent metadata + to issue the appropriate CREATE TYPE/DROP TYPE + commands as needed, supports unicode labels, supports + reflection. + + .. change:: + :tags: postgresql + :tickets: + + INTERVAL supports an optional "precision" argument + corresponding to the argument that PG accepts. + + .. change:: + :tags: postgresql + :tickets: + + using new dialect.initialize() feature to set up + version-dependent behavior. + + .. change:: + :tags: postgresql + :tickets: 1279 + + somewhat better support for % signs in table/column names; + psycopg2 can't handle a bind parameter name of + %(foobar)s however and SQLA doesn't want to add overhead + just to treat that one non-existent use case. + + .. change:: + :tags: postgresql + :tickets: 1516 + + Inserting NULL into a primary key + foreign key column + will allow the "not null constraint" error to raise, + not an attempt to execute a nonexistent "col_id_seq" + sequence. + + .. change:: + :tags: postgresql + :tickets: + + autoincrement SELECT statements, i.e. those which + select from a procedure that modifies rows, now work + with server-side cursor mode (the named cursor isn't + used for such statements.) + + .. change:: + :tags: postgresql + :tickets: 1636 + + postgresql dialect can properly detect pg "devel" version + strings, i.e. "8.5devel" + + .. change:: + :tags: postgresql + :tickets: 1619 + + The psycopg2 now respects the statement option + "stream_results". This option overrides the connection setting + "server_side_cursors". If true, server side cursors will be + used for the statement. If false, they will not be used, even + if "server_side_cursors" is true on the + connection. + + .. change:: + :tags: mysql + :tickets: + + New dialects: oursql, a new native dialect, + MySQL Connector/Python, a native Python port of MySQLdb, + and of course zxjdbc on Jython. + + .. change:: + :tags: mysql + :tickets: + + VARCHAR/NVARCHAR will not render without a length, raises + an error before passing to MySQL. Doesn't impact + CAST since VARCHAR is not allowed in MySQL CAST anyway, + the dialect renders CHAR/NCHAR in those cases. + + .. change:: + :tags: mysql + :tickets: + + all the _detect_XXX() functions now run once underneath + dialect.initialize() + + .. change:: + :tags: mysql + :tickets: 1279 + + somewhat better support for % signs in table/column names; + MySQLdb can't handle % signs in SQL when executemany() is used, + and SQLA doesn't want to add overhead just to treat that one + non-existent use case. + + .. change:: + :tags: mysql + :tickets: + + the BINARY and MSBinary types now generate "BINARY" in all + cases. Omitting the "length" parameter will generate + "BINARY" with no length. Use BLOB to generate an unlengthed + binary column. + + .. change:: + :tags: mysql + :tickets: + + the "quoting='quoted'" argument to MSEnum/ENUM is deprecated. + It's best to rely upon the automatic quoting. + + .. change:: + :tags: mysql + :tickets: + + ENUM now subclasses the new generic Enum type, and also handles + unicode values implicitly, if the given labelnames are unicode + objects. + + .. change:: + :tags: mysql + :tickets: 1539 + + a column of type TIMESTAMP now defaults to NULL if + "nullable=False" is not passed to Column(), and no default + is present. This is now consistent with all other types, + and in the case of TIMESTAMP explictly renders "NULL" + due to MySQL's "switching" of default nullability + for TIMESTAMP columns. + + .. change:: + :tags: oracle + :tickets: + + unit tests pass 100% with cx_oracle ! + + .. change:: + :tags: oracle + :tickets: + + support for cx_Oracle's "native unicode" mode which does + not require NLS_LANG to be set. Use the latest 5.0.2 or + later of cx_oracle. + + .. change:: + :tags: oracle + :tickets: + + an NCLOB type is added to the base types. + + .. change:: + :tags: oracle + :tickets: + + use_ansi=False won't leak into the FROM/WHERE clause of + a statement that's selecting from a subquery that also + uses JOIN/OUTERJOIN. + + .. change:: + :tags: oracle + :tickets: 1467 + + added native INTERVAL type to the dialect. This supports + only the DAY TO SECOND interval type so far due to lack + of support in cx_oracle for YEAR TO MONTH. + + .. change:: + :tags: oracle + :tickets: + + usage of the CHAR type results in cx_oracle's + FIXED_CHAR dbapi type being bound to statements. + + .. change:: + :tags: oracle + :tickets: 885 + + the Oracle dialect now features NUMBER which intends + to act justlike Oracle's NUMBER type. It is the primary + numeric type returned by table reflection and attempts + to return Decimal()/float/int based on the precision/scale + parameters. + + .. change:: + :tags: oracle + :tickets: + + func.char_length is a generic function for LENGTH + + .. change:: + :tags: oracle + :tickets: + + ForeignKey() which includes onupdate= will emit a + warning, not emit ON UPDATE CASCADE which is unsupported + by oracle + + .. change:: + :tags: oracle + :tickets: + + the keys() method of RowProxy() now returns the result + column names *normalized* to be SQLAlchemy case + insensitive names. This means they will be lower case for + case insensitive names, whereas the DBAPI would normally + return them as UPPERCASE names. This allows row keys() to + be compatible with further SQLAlchemy operations. + + .. change:: + :tags: oracle + :tickets: + + using new dialect.initialize() feature to set up + version-dependent behavior. + + .. change:: + :tags: oracle + :tickets: 1125 + + using types.BigInteger with Oracle will generate + NUMBER(19) + + .. change:: + :tags: oracle + :tickets: + + "case sensitivity" feature will detect an all-lowercase + case-sensitive column name during reflect and add + "quote=True" to the generated Column, so that proper + quoting is maintained. + + .. change:: + :tags: firebird + :tickets: + + the keys() method of RowProxy() now returns the result + column names *normalized* to be SQLAlchemy case + insensitive names. This means they will be lower case for + case insensitive names, whereas the DBAPI would normally + return them as UPPERCASE names. This allows row keys() to + be compatible with further SQLAlchemy operations. + + .. change:: + :tags: firebird + :tickets: + + using new dialect.initialize() feature to set up + version-dependent behavior. + + .. change:: + :tags: firebird + :tickets: + + "case sensitivity" feature will detect an all-lowercase + case-sensitive column name during reflect and add + "quote=True" to the generated Column, so that proper + quoting is maintained. + + .. change:: + :tags: mssql + :tickets: + + MSSQL + Pyodbc + FreeTDS now works for the most part, + with possible exceptions regarding binary data as well as + unicode schema identifiers. + + .. change:: + :tags: mssql + :tickets: + + the "has_window_funcs" flag is removed. LIMIT/OFFSET + usage will use ROW NUMBER as always, and if on an older + version of SQL Server, the operation fails. The behavior + is exactly the same except the error is raised by SQL + server instead of the dialect, and no flag setting is + required to enable it. + + .. change:: + :tags: mssql + :tickets: + + the "auto_identity_insert" flag is removed. This feature + always takes effect when an INSERT statement overrides a + column that is known to have a sequence on it. As with + "has_window_funcs", if the underlying driver doesn't + support this, then you can't do this operation in any + case, so there's no point in having a flag. + + .. change:: + :tags: mssql + :tickets: + + using new dialect.initialize() feature to set up + version-dependent behavior. + + .. change:: + :tags: mssql + :tickets: + + removed references to sequence which is no longer used. + implicit identities in mssql work the same as implicit + sequences on any other dialects. Explicit sequences are + enabled through the use of "default=Sequence()". See + the MSSQL dialect documentation for more information. + + .. change:: + :tags: sqlite + :tickets: + + DATE, TIME and DATETIME types can now take optional storage_format + and regexp argument. storage_format can be used to store those types + using a custom string format. regexp allows to use a custom regular + expression to match string values from the database. + + .. change:: + :tags: sqlite + :tickets: + + Time and DateTime types now use by a default a stricter regular + expression to match strings from the database. Use the regexp + argument if you are using data stored in a legacy format. + + .. change:: + :tags: sqlite + :tickets: + + __legacy_microseconds__ on SQLite Time and DateTime types is not + supported anymore. You should use the storage_format argument + instead. + + .. change:: + :tags: sqlite + :tickets: + + Date, Time and DateTime types are now stricter in what they accept as + bind parameters: Date type only accepts date objects (and datetime + ones, because they inherit from date), Time only accepts time + objects, and DateTime only accepts date and datetime objects. + + .. change:: + :tags: sqlite + :tickets: 1016 + + Table() supports a keyword argument "sqlite_autoincrement", which + applies the SQLite keyword "AUTOINCREMENT" to the single integer + primary key column when generating DDL. Will prevent generation of + a separate PRIMARY KEY constraint. + + .. change:: + :tags: types + :tickets: + + The construction of types within dialects has been totally + overhauled. Dialects now define publically available types + as UPPERCASE names exclusively, and internal implementation + types using underscore identifiers (i.e. are private). + The system by which types are expressed in SQL and DDL + has been moved to the compiler system. This has the + effect that there are much fewer type objects within + most dialects. A detailed document on this architecture + for dialect authors is in + lib/sqlalchemy/dialects/type_migration_guidelines.txt . + + .. change:: + :tags: types + :tickets: + + Types no longer make any guesses as to default + parameters. In particular, Numeric, Float, NUMERIC, + FLOAT, DECIMAL don't generate any length or scale unless + specified. + + .. change:: + :tags: types + :tickets: 1664 + + types.Binary is renamed to types.LargeBinary, it only + produces BLOB, BYTEA, or a similar "long binary" type. + New base BINARY and VARBINARY + types have been added to access these MySQL/MS-SQL specific + types in an agnostic way. + + .. change:: + :tags: types + :tickets: + + String/Text/Unicode types now skip the unicode() check + on each result column value if the dialect has + detected the DBAPI as returning Python unicode objects + natively. This check is issued on first connect + using "SELECT CAST 'some text' AS VARCHAR(10)" or + equivalent, then checking if the returned object + is a Python unicode. This allows vast performance + increases for native-unicode DBAPIs, including + pysqlite/sqlite3, psycopg2, and pg8000. + + .. change:: + :tags: types + :tickets: + + Most types result processors have been checked for possible speed + improvements. Specifically, the following generic types have been + optimized, resulting in varying speed improvements: + Unicode, PickleType, Interval, TypeDecorator, Binary. + Also the following dbapi-specific implementations have been improved: + Time, Date and DateTime on Sqlite, ARRAY on Postgresql, + Time on MySQL, Numeric(as_decimal=False) on MySQL, oursql and + pypostgresql, DateTime on cx_oracle and LOB-based types on cx_oracle. + + .. change:: + :tags: types + :tickets: + + Reflection of types now returns the exact UPPERCASE + type within types.py, or the UPPERCASE type within + the dialect itself if the type is not a standard SQL + type. This means reflection now returns more accurate + information about reflected types. + + .. change:: + :tags: types + :tickets: 1511, 1109 + + Added a new Enum generic type. Enum is a schema-aware object + to support databases which require specific DDL in order to + use enum or equivalent; in the case of PG it handles the + details of `CREATE TYPE`, and on other databases without + native enum support will by generate VARCHAR + an inline CHECK + constraint to enforce the enum. + + .. change:: + :tags: types + :tickets: 1467 + + The Interval type includes a "native" flag which controls + if native INTERVAL types (postgresql + oracle) are selected + if available, or not. "day_precision" and "second_precision" + arguments are also added which propagate as appropriately + to these native types. Related to. + + .. change:: + :tags: types + :tickets: 1589 + + The Boolean type, when used on a backend that doesn't + have native boolean support, will generate a CHECK + constraint "col IN (0, 1)" along with the int/smallint- + based column type. This can be switched off if + desired with create_constraint=False. + Note that MySQL has no native boolean *or* CHECK constraint + support so this feature isn't available on that platform. + + .. change:: + :tags: types + :tickets: + + PickleType now uses == for comparison of values when + mutable=True, unless the "comparator" argument with a + comparsion function is specified to the type. Objects + being pickled will be compared based on identity (which + defeats the purpose of mutable=True) if __eq__() is not + overridden or a comparison function is not provided. + + .. change:: + :tags: types + :tickets: + + The default "precision" and "scale" arguments of Numeric + and Float have been removed and now default to None. + NUMERIC and FLOAT will be rendered with no numeric + arguments by default unless these values are provided. + + .. change:: + :tags: types + :tickets: + + AbstractType.get_search_list() is removed - the games + that was used for are no longer necessary. + + .. change:: + :tags: types + :tickets: 1125 + + Added a generic BigInteger type, compiles to + BIGINT or NUMBER(19). + + .. change:: + :tags: types + :tickets: + + sqlsoup has been overhauled to explicitly support an 0.5 style + session, using autocommit=False, autoflush=True. Default + behavior of SQLSoup now requires the usual usage of commit() + and rollback(), which have been added to its interface. An + explcit Session or scoped_session can be passed to the + constructor, allowing these arguments to be overridden. + + .. change:: + :tags: types + :tickets: + + sqlsoup db..update() and delete() now call + query(cls).update() and delete(), respectively. + + .. change:: + :tags: types + :tickets: + + sqlsoup now has execute() and connection(), which call upon + the Session methods of those names, ensuring that the bind is + in terms of the SqlSoup object's bind. + + .. change:: + :tags: types + :tickets: + + sqlsoup objects no longer have the 'query' attribute - it's + not needed for sqlsoup's usage paradigm and it gets in the + way of a column that is actually named 'query'. + + .. change:: + :tags: types + :tickets: 1259 + + The signature of the proxy_factory callable passed to + association_proxy is now (lazy_collection, creator, + value_attr, association_proxy), adding a fourth argument + that is the parent AssociationProxy argument. Allows + serializability and subclassing of the built in collections. + + .. change:: + :tags: types + :tickets: 1372 + + association_proxy now has basic comparator methods .any(), + .has(), .contains(), ==, !=, thanks to Scott Torborg. + + .. change:: + :tags: examples + :tickets: + + The "query_cache" examples have been removed, and are replaced + with a fully comprehensive approach that combines the usage of + Beaker with SQLAlchemy. New query options are used to indicate + the caching characteristics of a particular Query, which + can also be invoked deep within an object graph when lazily + loading related objects. See /examples/beaker_caching/README. diff --git a/doc/build/changelog/changelog_07.rst b/doc/build/changelog/changelog_07.rst new file mode 100644 index 0000000000..8029339a2f --- /dev/null +++ b/doc/build/changelog/changelog_07.rst @@ -0,0 +1,4435 @@ + +============== +0.7 Changelog +============== + + +.. changelog:: + :version: 0.7.10 + :released: + + .. change:: + :tags: orm, bug + :tickets: 2583 + + Fixed Session accounting bug whereby replacing + a deleted object in the identity map with another + object of the same primary key would raise a + "conflicting state" error on rollback(), + if the replaced primary key were established either + via non-unitofwork-established INSERT statement + or by primary key switch of another instance. + + .. change:: + :tags: oracle, bug + :tickets: 2561 + + changed the list of cx_oracle types that are + excluded from the setinputsizes() step to only include + STRING and UNICODE; CLOB and NCLOB are removed. This + is to work around cx_oracle behavior which is broken + for the executemany() call. In 0.8, this same change + is applied however it is also configurable via the + exclude_setinputsizes argument. + + .. change:: + :tags: feature, mysql + :tickets: 2523 + + Added "raise_on_warnings" flag to OurSQL + dialect. + + .. change:: + :tags: feature, mysql + :tickets: 2554 + + Added "read_timeout" flag to MySQLdb + dialect. + +.. changelog:: + :version: 0.7.9 + :released: Mon Oct 01 2012 + + .. change:: + :tags: orm, bug + :tickets: + + Fixed bug mostly local to new + AbstractConcreteBase helper where the "type" + attribute from the superclass would not + be overridden on the subclass to produce the + "reserved for base" error message, instead placing + a do-nothing attribute there. This was inconsistent + vs. using ConcreteBase as well as all the behavior + of classical concrete mappings, where the "type" + column from the polymorphic base would be explicitly + disabled on subclasses, unless overridden + explicitly. + + .. change:: + :tags: orm, bug + :tickets: + + A warning is emitted when lazy='dynamic' + is combined with uselist=False. This is an + exception raise in 0.8. + + .. change:: + :tags: orm, bug + :tickets: + + Fixed bug whereby user error in related-object + assignment could cause recursion overflow if the + assignment triggered a backref of the same name + as a bi-directional attribute on the incorrect + class to the same target. An informative + error is raised now. + + .. change:: + :tags: orm, bug + :tickets: 2539 + + Fixed bug where incorrect type information + would be passed when the ORM would bind the + "version" column, when using the "version" feature. + Tests courtesy Daniel Miller. + + .. change:: + :tags: orm, bug + :tickets: 2566 + + Extra logic has been added to the "flush" + that occurs within Session.commit(), such that the + extra state added by an after_flush() or + after_flush_postexec() hook is also flushed in a + subsequent flush, before the "commit" completes. + Subsequent calls to flush() will continue until + the after_flush hooks stop adding new state. + An "overflow" counter of 100 is also in place, + in the event of a broken after_flush() hook + adding new content each time. + + .. change:: + :tags: bug, sql + :tickets: 2571 + + Fixed the DropIndex construct to support + an Index associated with a Table in a remote + schema. + + .. change:: + :tags: bug, sql + :tickets: 2574 + + Fixed bug in over() construct whereby + passing an empty list for either partition_by + or order_by, as opposed to None, would fail + to generate correctly. + Courtesy Gunnlaugur Þór Briem. + + .. change:: + :tags: bug, sql + :tickets: 2521 + + Fixed CTE bug whereby positional + bound parameters present in the CTEs themselves + would corrupt the overall ordering of + bound parameters. This primarily + affected SQL Server as the platform with + positional binds + CTE support. + + .. change:: + :tags: bug, sql + :tickets: + + Fixed more un-intuitivenesses in CTEs + which prevented referring to a CTE in a union + of itself without it being aliased. + CTEs now render uniquely + on name, rendering the outermost CTE of a given + name only - all other references are rendered + just as the name. This even includes other + CTE/SELECTs that refer to different versions + of the same CTE object, such as a SELECT + or a UNION ALL of that SELECT. We are + somewhat loosening the usual link between object + identity and lexical identity in this case. + A true name conflict between two unrelated + CTEs now raises an error. + + .. change:: + :tags: bug, sql + :tickets: 2512 + + quoting is applied to the column names + inside the WITH RECURSIVE clause of a + common table expression according to the + quoting rules for the originating Column. + + .. change:: + :tags: bug, sql + :tickets: 2518 + + Fixed regression introduced in 0.7.6 + whereby the FROM list of a SELECT statement + could be incorrect in certain "clone+replace" + scenarios. + + .. change:: + :tags: bug, sql + :tickets: 2552 + + Fixed bug whereby usage of a UNION + or similar inside of an embedded subquery + would interfere with result-column targeting, + in the case that a result-column had the same + ultimate name as a name inside the embedded + UNION. + + .. change:: + :tags: bug, sql + :tickets: 2558 + + Fixed a regression since 0.6 regarding + result-row targeting. It should be possible + to use a select() statement with string + based columns in it, that is + select(['id', 'name']).select_from('mytable'), + and have this statement be targetable by + Column objects with those names; this is the + mechanism by which + query(MyClass).from_statement(some_statement) + works. At some point the specific case of + using select(['id']), which is equivalent to + select([literal_column('id')]), stopped working + here, so this has been re-instated and of + course tested. + + .. change:: + :tags: bug, sql + :tickets: 2544 + + Added missing operators is_(), isnot() + to the ColumnOperators base, so that these long-available + operators are present as methods like all + the other operators. + + .. change:: + :tags: bug, sql + :tickets: 2525 + + When the primary key column of a Table + is replaced, such as via extend_existing, + the "auto increment" column used by insert() + constructs is reset. Previously it would + remain referring to the previous primary + key column. + + .. change:: + :tags: engine, bug + :tickets: 2522 + + Fixed bug whereby + a disconnect detect + dispose that occurs + when the QueuePool has threads waiting + for connections would leave those + threads waiting for the duration of + the timeout on the old pool (or indefinitely + if timeout was disabled). The fix + now notifies those waiters with a special + exception case and has them move onto + the new pool. + + .. change:: + :tags: engine, feature + :tickets: 2516 + + Dramatic improvement in memory + usage of the event system; instance-level + collections are no longer created for a + particular type of event until + instance-level listeners are established + for that event. + + .. change:: + :tags: engine, bug + :tickets: 2529 + + Added gaerdbms import to mysql/__init__.py, + the absense of which was preventing the new + GAE dialect from being loaded. + + .. change:: + :tags: engine, bug + :tickets: 2553 + + Fixed cextension bug whereby the + "ambiguous column error" would fail to + function properly if the given index were + a Column object and not a string. + Note there are still some column-targeting + issues here which are fixed in 0.8. + + .. change:: + :tags: engine, bug + :tickets: + + Fixed the repr() of Enum to include + the "name" and "native_enum" flags. Helps + Alembic autogenerate. + + .. change:: + :tags: sqlite, bug + :tickets: 2568 + + Adjusted a very old bugfix which attempted + to work around a SQLite issue that itself was + "fixed" as of sqlite 3.6.14, regarding quotes + surrounding a table name when using + the "foreign_key_list" pragma. The fix has been + adjusted to not interfere with quotes that + are *actually in the name* of a column or table, + to as much a degree as possible; sqlite still + doesn't return the correct result for foreign_key_list() + if the target table actually has quotes surrounding + its name, as *part* of its name (i.e. """mytable"""). + + .. change:: + :tags: sqlite, bug + :tickets: 2265 + + Adjusted column default reflection code to + convert non-string values to string, to accommodate + old SQLite versions that don't deliver + default info as a string. + + .. change:: + :tags: sqlite, feature + :tickets: + + Added support for the localtimestamp() + SQL function implemented in SQLite, courtesy + Richard Mitchell. + + .. change:: + :tags: postgresql, bug + :tickets: 2531 + + Columns in reflected primary key constraint + are now returned in the order in which the constraint + itself defines them, rather than how the table + orders them. Courtesy Gunnlaugur Þór Briem.. + + .. change:: + :tags: postgresql, bug + :tickets: 2570 + + Added 'terminating connection' to the list + of messages we use to detect a disconnect with PG, which + appears to be present in some versions when the server + is restarted. + + .. change:: + :tags: bug, mysql + :tickets: + + Updated mysqlconnector interface to use + updated "client flag" and "charset" APIs, + courtesy David McNelis. + + .. change:: + :tags: mssql, bug + :tickets: 2538 + + Fixed compiler bug whereby using a correlated + subquery within an ORDER BY would fail to render correctly + if the stament also used LIMIT/OFFSET, due to mis-rendering + within the ROW_NUMBER() OVER clause. Fix courtesy + sayap + + .. change:: + :tags: mssql, bug + :tickets: 2545 + + Fixed compiler bug whereby a given + select() would be modified if it had an "offset" + attribute, causing the construct to not compile + correctly a second time. + + .. change:: + :tags: mssql, bug + :tickets: + + Fixed bug where reflection of primary key constraint + would double up columns if the same constraint/table + existed in multiple schemas. + +.. changelog:: + :version: 0.7.8 + :released: Sat Jun 16 2012 + + .. change:: + :tags: orm, bug + :tickets: 2480 + + Fixed bug whereby subqueryload() from + a polymorphic mapping to a target would incur + a new invocation of the query for each + distinct class encountered in the polymorphic + result. + + .. change:: + :tags: orm, bug + :tickets: 2491, 1892 + + Fixed bug in declarative + whereby the precedence of columns + in a joined-table, composite + column (typically for id) would fail to + be correct if the columns contained + names distinct from their attribute + names. This would cause things like + primaryjoin conditions made against the + entity attributes to be incorrect. Related + to as this was supposed + to be part of that, this is. + + .. change:: + :tags: orm, feature + :tickets: + + The 'objects' argument to + flush() is no longer deprecated, as some + valid use cases have been identified. + + .. change:: + :tags: orm, bug + :tickets: 2508 + + Fixed identity_key() function which + was not accepting a scalar argument + for the identity. . + + .. change:: + :tags: orm, bug + :tickets: 2497 + + Fixed bug whereby populate_existing + option would not propagate to subquery + eager loaders. . + + .. change:: + :tags: bug, sql + :tickets: 2499 + + added BIGINT to types.__all__, + BIGINT, BINARY, VARBINARY to sqlalchemy + module namespace, plus test to ensure + this breakage doesn't occur again. + + .. change:: + :tags: bug, sql + :tickets: 2490 + + Repaired common table expression + rendering to function correctly when the + SELECT statement contains UNION or other + compound expressions, courtesy btbuilder. + + .. change:: + :tags: bug, sql + :tickets: 2482 + + Fixed bug whereby append_column() + wouldn't function correctly on a cloned + select() construct, courtesy + Gunnlaugur Þór Briem. + + .. change:: + :tags: engine, bug + :tickets: 2489 + + Fixed memory leak in C version of + result proxy whereby DBAPIs which don't deliver + pure Python tuples for result rows would + fail to decrement refcounts correctly. + The most prominently affected DBAPI + is pyodbc. + + .. change:: + :tags: engine, bug + :tickets: 2503 + + Fixed bug affecting Py3K whereby + string positional parameters passed to + engine/connection execute() would fail to be + interpreted correctly, due to __iter__ + being present on Py3K string.. + + .. change:: + :tags: postgresql, bug + :tickets: 2510 + + removed unnecessary table clause when + reflecting enums,. Courtesy + Gunnlaugur Þór Briem. + + .. change:: + :tags: oracle, bug + :tickets: 2483 + + Added ROWID to oracle.*. + + .. change:: + :tags: feature, mysql + :tickets: 2484 + + Added a new dialect for Google App + Engine. Courtesy Richie Foreman. + +.. changelog:: + :version: 0.7.7 + :released: Sat May 05 2012 + + .. change:: + :tags: orm, bug + :tickets: 2477 + + Fixed issue in unit of work + whereby setting a non-None self-referential + many-to-one relationship to None + would fail to persist the change if the + former value was not already loaded.. + + .. change:: + :tags: orm, feature + :tickets: 2443 + + Added prefix_with() method + to Query, calls upon select().prefix_with() + to allow placement of MySQL SELECT + directives in statements. Courtesy + Diana Clarke + + .. change:: + :tags: orm, bug + :tickets: 2409 + + Fixed bug in 0.7.6 introduced by whereby column_mapped_collection + used against columns that were mapped as + joins or other indirect selectables + would fail to function. + + .. change:: + :tags: orm, feature + :tickets: + + Added new flag to @validates + include_removes. When True, collection + remove and attribute del events + will also be sent to the validation function, + which accepts an additional argument + "is_remove" when this flag is used. + + .. change:: + :tags: orm, bug + :tickets: 2449 + + Fixed bug whereby polymorphic_on + column that's not otherwise mapped on the + class would be incorrectly included + in a merge() operation, raising an error. + + .. change:: + :tags: orm, bug + :tickets: 2453 + + Fixed bug in expression annotation + mechanics which could lead to incorrect + rendering of SELECT statements with aliases + and joins, particularly when using + column_property(). + + .. change:: + :tags: orm, bug + :tickets: 2454 + + Fixed bug which would prevent + OrderingList from being pickleable. Courtesy Jeff Dairiki + + .. change:: + :tags: orm, bug + :tickets: + + Fixed bug in relationship comparisons + whereby calling unimplemented methods like + SomeClass.somerelationship.like() would + produce a recursion overflow, instead + of NotImplementedError. + + .. change:: + :tags: bug, sql + :tickets: + + Removed warning when Index is created + with no columns; while this might not be what + the user intended, it is a valid use case + as an Index could be a placeholder for just an + index of a certain name. + + .. change:: + :tags: feature, sql + :tickets: + + Added new connection event + dbapi_error(). Is called for all DBAPI-level + errors passing the original DBAPI exception + before SQLAlchemy modifies the state + of the cursor. + + .. change:: + :tags: bug, sql + :tickets: + + If conn.begin() fails when calling + "with engine.begin()", the newly acquired + Connection is closed explicitly before + propagating the exception onward normally. + + .. change:: + :tags: bug, sql + :tickets: 2474 + + Add BINARY, VARBINARY to types.__all__. + + .. change:: + :tags: mssql, feature + :tickets: + + Added interim create_engine flag + supports_unicode_binds to PyODBC dialect, + to force whether or not the dialect + passes Python unicode literals to PyODBC + or not. + + .. change:: + :tags: mssql, bug + :tickets: + + Repaired the use_scope_identity + create_engine() flag when using the pyodbc + dialect. Previously this flag would be + ignored if set to False. When set to False, + you'll get "SELECT @@identity" after each + INSERT to get at the last inserted ID, + for those tables which have "implicit_returning" + set to False. + + .. change:: + :tags: mssql, bug + :tickets: 2468 + + UPDATE..FROM syntax with SQL Server + requires that the updated table be present + in the FROM clause when an alias of that + table is also present in the FROM clause. + The updated table is now always present + in the FROM, when FROM is present + in the first place. Courtesy sayap. + + .. change:: + :tags: postgresql, feature + :tickets: 2445 + + Added new for_update/with_lockmode() + options for Postgresql: for_update="read"/ + with_lockmode("read"), + for_update="read_nowait"/ + with_lockmode("read_nowait"). + These emit "FOR SHARE" and "FOR SHARE NOWAIT", + respectively. Courtesy Diana Clarke + + .. change:: + :tags: postgresql, bug + :tickets: 2473 + + removed unnecessary table clause + when reflecting domains. + + .. change:: + :tags: bug, mysql + :tickets: 2460 + + Fixed bug whereby column name inside + of "KEY" clause for autoincrement composite + column with InnoDB would double quote a + name that's a reserved word. Courtesy Jeff + Dairiki. + + .. change:: + :tags: bug, mysql + :tickets: + + Fixed bug whereby get_view_names() for + "information_schema" schema would fail + to retrieve views marked as "SYSTEM VIEW". + courtesy Matthew Turland. + + .. change:: + :tags: bug, mysql + :tickets: 2467 + + Fixed bug whereby if cast() is used + on a SQL expression whose type is not supported + by cast() and therefore CAST isn't rendered by + the dialect, the order of evaluation could change + if the casted expression required that it be + grouped; grouping is now applied to those + expressions. + + .. change:: + :tags: sqlite, feature + :tickets: 2475 + + Added SQLite execution option + "sqlite_raw_colnames=True", will bypass + attempts to remove "." from column names + returned by SQLite cursor.description. + +.. changelog:: + :version: 0.7.6 + :released: Wed Mar 14 2012 + + .. change:: + :tags: orm, bug + :tickets: 2424 + + Fixed event registration bug + which would primarily show up as + events not being registered with + sessionmaker() instances created + after the event was associated + with the Session class. + + .. change:: + :tags: orm, bug + :tickets: 2425 + + Fixed bug whereby a primaryjoin + condition with a "literal" in it would + raise an error on compile with certain + kinds of deeply nested expressions + which also needed to render the same + bound parameter name more than once. + + .. change:: + :tags: orm, feature + :tickets: + + Added "no_autoflush" context + manager to Session, used with with: + will temporarily disable autoflush. + + .. change:: + :tags: orm, feature + :tickets: 1859 + + Added cte() method to Query, + invokes common table expression support + from the Core (see below). + + .. change:: + :tags: orm, bug + :tickets: 2403 + + Removed the check for number of + rows affected when doing a multi-delete + against mapped objects. If an ON DELETE + CASCADE exists between two rows, we can't + get an accurate rowcount from the DBAPI; + this particular count is not supported + on most DBAPIs in any case, MySQLdb + is the notable case where it is. + + .. change:: + :tags: orm, bug + :tickets: 2409 + + Fixed bug whereby objects using + attribute_mapped_collection or + column_mapped_collection could not be + pickled. + + .. change:: + :tags: orm, bug + :tickets: 2406 + + Fixed bug whereby MappedCollection + would not get the appropriate collection + instrumentation if it were only used + in a custom subclass that used + @collection.internally_instrumented. + + .. change:: + :tags: orm, bug + :tickets: 2419 + + Fixed bug whereby SQL adaption mechanics + would fail in a very nested scenario involving + joined-inheritance, joinedload(), limit(), and a + derived function in the columns clause. + + .. change:: + :tags: orm, bug + :tickets: 2417 + + Fixed the repr() for CascadeOptions to + include refresh-expire. Also reworked + CascadeOptions to be a . + + .. change:: + :tags: orm, feature + :tickets: 2400 + + Added the ability to query for + Table-bound column names when using + query(sometable).filter_by(colname=value). + + .. change:: + :tags: orm, bug + :tickets: + + Improved the "declarative reflection" + example to support single-table inheritance, + multiple calls to prepare(), tables that + are present in alternate schemas, + establishing only a subset of classes + as reflected. + + .. change:: + :tags: orm, bug + :tickets: 2390 + + Scaled back the test applied within + flush() to check for UPDATE against partially + NULL PK within one table to only actually + happen if there's really an UPDATE to occur. + + .. change:: + :tags: orm, bug + :tickets: 2352 + + Fixed bug whereby if a method name + conflicted with a column name, a + TypeError would be raised when the mapper + tried to inspect the __get__() method + on the method object. + + .. change:: + :tags: bug, sql + :tickets: 2427 + + Fixed memory leak in core which would + occur when C extensions were used with + particular types of result fetches, + in particular when orm query.count() + were called. + + .. change:: + :tags: bug, sql + :tickets: 2398 + + Fixed issue whereby attribute-based + column access on a row would raise + AttributeError with non-C version, + NoSuchColumnError with C version. Now + raises AttributeError in both cases. + + .. change:: + :tags: feature, sql + :tickets: 1859 + + Added support for SQL standard + common table expressions (CTE), allowing + SELECT objects as the CTE source (DML + not yet supported). This is invoked via + the cte() method on any select() construct. + + .. change:: + :tags: bug, sql + :tickets: 2392 + + Added support for using the .key + of a Column as a string identifier in a + result set row. The .key is currently + listed as an "alternate" name for a column, + and is superseded by the name of a column + which has that key value as its regular name. + For the next major release + of SQLAlchemy we may reverse this precedence + so that .key takes precedence, but this + is not decided on yet. + + .. change:: + :tags: bug, sql + :tickets: 2413 + + A warning is emitted when a not-present + column is stated in the values() clause + of an insert() or update() construct. + Will move to an exception in 0.8. + + .. change:: + :tags: bug, sql + :tickets: 2396 + + A significant change to how labeling + is applied to columns in SELECT statements + allows "truncated" labels, that is label names + that are generated in Python which exceed + the maximum identifier length (note this is + configurable via label_length on create_engine()), + to be properly referenced when rendered inside + of a subquery, as well as to be present + in a result set row using their original + in-Python names. + + .. change:: + :tags: bug, sql + :tickets: 2402 + + Fixed bug in new "autoload_replace" flag + which would fail to preserve the primary + key constraint of the reflected table. + + .. change:: + :tags: bug, sql + :tickets: 2380 + + Index will raise when arguments passed + cannot be interpreted as columns or expressions. + Will warn when Index is created + with no columns at all. + + .. change:: + :tags: engine, feature + :tickets: 2407 + + Added "no_parameters=True" execution + option for connections. If no parameters + are present, will pass the statement + as cursor.execute(statement), thereby invoking + the DBAPIs behavior when no parameter collection + is present; for psycopg2 and mysql-python, this + means not interpreting % signs in the string. + This only occurs with this option, and not + just if the param list is blank, as otherwise + this would produce inconsistent behavior + of SQL expressions that normally escape percent + signs (and while compiling, can't know ahead of + time if parameters will be present in + some cases). + + .. change:: + :tags: engine, bug + :tickets: + + Added execution_options() call to + MockConnection (i.e., that used with + strategy="mock") which acts as a pass through + for arguments. + + .. change:: + :tags: engine, feature + :tickets: 2378 + + Added pool_reset_on_return argument + to create_engine, allows control over + "connection return" behavior. Also added + new arguments 'rollback', 'commit', None + to pool.reset_on_return to allow more control + over connection return activity. + + .. change:: + :tags: engine, feature + :tickets: + + Added some decent context managers + to Engine, Connection: + + with engine.begin() as conn: + + + and: + + with engine.connect() as conn: + + + Both close out the connection when done, + commit or rollback transaction with errors + on engine.begin(). + + .. change:: + :tags: sqlite, bug + :tickets: 2432 + + Fixed bug in C extensions whereby + string format would not be applied to a + Numeric value returned as integer; this + affected primarily SQLite which does + not maintain numeric scale settings. + + .. change:: + :tags: mssql, feature + :tickets: 2430 + + Added support for MSSQL INSERT, + UPDATE, and DELETE table hints, using + new with_hint() method on UpdateBase. + + .. change:: + :tags: feature, mysql + :tickets: 2386 + + Added support for MySQL index and + primary key constraint types + (i.e. USING) via new mysql_using parameter + to Index and PrimaryKeyConstraint, + courtesy Diana Clarke. + + .. change:: + :tags: feature, mysql + :tickets: 2394 + + Added support for the "isolation_level" + parameter to all MySQL dialects. Thanks + to mu_mind for the patch here. + + .. change:: + :tags: oracle, feature + :tickets: 2399 + + Added a new create_engine() flag + coerce_to_decimal=False, disables the precision + numeric handling which can add lots of overhead + by converting all numeric values to + Decimal. + + .. change:: + :tags: oracle, bug + :tickets: 2401 + + Added missing compilation support for + LONG + + .. change:: + :tags: oracle, bug + :tickets: 2435 + + Added 'LEVEL' to the list of reserved + words for Oracle. + + .. change:: + :tags: examples, bug + :tickets: + + Altered _params_from_query() function + in Beaker example to pull bindparams from the + fully compiled statement, as a quick means + to get everything including subqueries in the + columns clause, etc. + + .. change:: + :tags: orm, bug + :tickets: 2389 + + Fixed issue where modified session state + established after a failed flush would be committed + as part of the subsequent transaction that + begins automatically after manual call + to rollback(). The state of the session is + checked within rollback(), and if new state + is present, a warning is emitted and + restore_snapshot() is called a second time, + discarding those changes. + + .. change:: + :tags: orm, bug + :tickets: 2345 + + Fixed regression from 0.7.4 whereby + using an already instrumented column from a + superclass as "polymorphic_on" failed to resolve + the underlying Column. + + .. change:: + :tags: orm, bug + :tickets: 2370 + + Raise an exception if xyzload_all() is + used inappropriately with two non-connected + relationships. + + .. change:: + :tags: orm, feature + :tickets: + + Added "class_registry" argument to + declarative_base(). Allows two or more declarative + bases to share the same registry of class names. + + .. change:: + :tags: orm, feature + :tickets: + + query.filter() accepts multiple + criteria which will join via AND, i.e. + query.filter(x==y, z>q, ...) + + .. change:: + :tags: orm, feature + :tickets: 2351 + + Added new capability to relationship + loader options to allow "default" loader strategies. + Pass '*' to any of joinedload(), lazyload(), + subqueryload(), or noload() and that becomes the + loader strategy used for all relationships, + except for those explicitly stated in the + Query. Thanks to up-and-coming contributor + Kent Bower for an exhaustive and well + written test suite ! + + .. change:: + :tags: orm, bug + :tickets: 2367 + + Fixed bug whereby event.listen(SomeClass) + forced an entirely unnecessary compile of the + mapper, making events very hard to set up + at module import time (nobody noticed this ??) + + .. change:: + :tags: orm, bug + :tickets: + + Fixed bug whereby hybrid_property didn't + work as a kw arg in any(), has(). + + .. change:: + :tags: orm + :tickets: + + Fixed regression from 0.6 whereby if + "load_on_pending" relationship() flag were used + where a non-"get()" lazy clause needed to be + emitted on a pending object, it would fail + to load. + + .. change:: + :tags: orm, bug + :tickets: 2371 + + ensure pickleability of all ORM exceptions + for multiprocessing compatibility. + + .. change:: + :tags: orm, bug + :tickets: 2353 + + implemented standard "can't set attribute" / + "can't delete attribute" AttributeError when + setattr/delattr used on a hybrid that doesn't + define fset or fdel. + + .. change:: + :tags: orm, bug + :tickets: 2362 + + Fixed bug where unpickled object didn't + have enough of its state set up to work + correctly within the unpickle() event established + by the mutable object extension, if the object + needed ORM attribute access within + __eq__() or similar. + + .. change:: + :tags: orm, bug + :tickets: 2374 + + Fixed bug where "merge" cascade could + mis-interpret an unloaded attribute, if the + load_on_pending flag were used with + relationship(). Thanks to Kent Bower + for tests. + + .. change:: + :tags: orm, feature + :tickets: 2356 + + New declarative reflection example + added, illustrates how best to mix table reflection + with declarative as well as uses some new features + from. + + .. change:: + :tags: feature, sql + :tickets: 2356 + + New reflection feature "autoload_replace"; + when set to False on Table, the Table can be autoloaded + without existing columns being replaced. Allows + more flexible chains of Table construction/reflection + to be constructed, including that it helps with + combining Declarative with table reflection. + See the new example on the wiki. + + .. change:: + :tags: bug, sql + :tickets: 2356 + + Improved the API for add_column() such that + if the same column is added to its own table, + an error is not raised and the constraints + don't get doubled up. Also helps with some + reflection/declarative patterns. + + .. change:: + :tags: feature, sql + :tickets: + + Added "false()" and "true()" expression + constructs to sqlalchemy.sql namespace, though + not part of __all__ as of yet. + + .. change:: + :tags: feature, sql + :tickets: 2361 + + Dialect-specific compilers now raise + CompileException for all type/statement compilation + issues, instead of InvalidRequestError or ArgumentError. + The DDL for CREATE TABLE will re-raise + CompileExceptions to include table/column information + for the problematic column. + + .. change:: + :tags: bug, sql + :tickets: 2381 + + Fixed issue where the "required" exception + would not be raised for bindparam() with required=True, + if the statement were given no parameters at all. + + .. change:: + :tags: engine, bug + :tickets: 2371 + + Added __reduce__ to StatementError, + DBAPIError, column errors so that exceptions + are pickleable, as when using multiprocessing. + However, not + all DBAPIs support this yet, such as + psycopg2. + + .. change:: + :tags: engine, bug + :tickets: 2382 + + Improved error messages when a non-string + or invalid string is passed to any of the + date/time processors used by SQLite, including + C and Python versions. + + .. change:: + :tags: engine, bug + :tickets: 2377 + + Fixed bug whereby a table-bound Column + object named "_" which matched a column + labeled as "_" could match + inappropriately when targeting in a result + set row. + + .. change:: + :tags: engine, bug + :tickets: 2384 + + Fixed bug in "mock" strategy whereby + correct DDL visit method wasn't called, resulting + in "CREATE/DROP SEQUENCE" statements being + duplicated + + .. change:: + :tags: sqlite, bug + :tickets: 2364 + + the "name" of an FK constraint in SQLite + is reflected as "None", not "0" or other + integer value. + SQLite does not appear to support constraint + naming in any case. + + .. change:: + :tags: sqlite, bug + :tickets: 2368 + + sql.false() and sql.true() compile to + 0 and 1, respectively in sqlite + + .. change:: + :tags: sqlite, bug + :tickets: + + removed an erroneous "raise" in the + SQLite dialect when getting table names + and view names, where logic is in place + to fall back to an older version of + SQLite that doesn't have the + "sqlite_temp_master" table. + + .. change:: + :tags: bug, mysql + :tickets: 2376 + + fixed regexp that filters out warnings + for non-reflected "PARTITION" directives, + thanks to George Reilly + + .. change:: + :tags: mssql, bug + :tickets: 2340 + + Adjusted the regexp used in the + mssql.TIME type to ensure only six digits + are received for the "microseconds" portion + of the value, which is expected by + Python's datetime.time(). Note that + support for sending microseconds doesn't + seem to be possible yet with pyodbc + at least. + + .. change:: + :tags: mssql, bug + :tickets: 2347 + + Dropped the "30 char" limit on pymssql, + based on reports that it's doing things + better these days. pymssql hasn't been + well tested and as the DBAPI is in flux + it's still not clear what the status + is on this driver and how SQLAlchemy's + implementation should adapt. + + .. change:: + :tags: oracle, bug + :tickets: 2388 + + Added ORA-03135 to the never ending + list of oracle "connection lost" errors + + .. change:: + :tags: core, bug + :tickets: 2379 + + Changed LRUCache, used by the mapper + to cache INSERT/UPDATE/DELETE statements, + to use an incrementing counter instead + of a timestamp to track entries, for greater + reliability versus using time.time(), which + can cause test failures on some platforms. + + .. change:: + :tags: core, bug + :tickets: 2383 + + Added a boolean check for the "finalize" + function within the pool connection proxy's + weakref callback before calling it, so that a + warning isn't emitted that this function is None + when the application is exiting and gc has + removed the function from the module before the + weakref callback was invoked. + + .. change:: + :tags: bug, Py3K + :tickets: 2348 + + Fixed inappropriate usage of util.py3k + flag and renamed it to util.py3k_warning, since + this flag is intended to detect the -3 flag + series of import restrictions only. + + .. change:: + :tags: examples, feature + :tickets: 2313 + + Simplified the versioning example + a bit to use a declarative mixin as well + as an event listener, instead of a metaclass + + SessionExtension. + + .. change:: + :tags: examples, bug + :tickets: 2346 + + Fixed large_collection.py to close the + session before dropping tables. + + .. change:: + :tags: orm, bug + :tickets: 2315 + + Fixed backref behavior when "popping" the + value off of a many-to-one in response to + a removal from a stale one-to-many - the operation + is skipped, since the many-to-one has since + been updated. + + .. change:: + :tags: orm, bug + :tickets: 2264 + + After some years of not doing this, added + more granularity to the "is X a parent of Y" + functionality, which is used when determining + if the FK on "Y" needs to be "nulled out" as well + as if "Y" should be deleted with delete-orphan + cascade. The test now takes into account the + Python identity of the parent as well its identity + key, to see if the last known parent of Y is + definitely X. If a decision + can't be made, a StaleDataError is raised. The + conditions where this error is raised are fairly + rare, requiring that the previous parent was + garbage collected, and previously + could very well inappropriately update/delete + a record that's since moved onto a new parent, + though there may be some cases where + "silent success" occurred previously that will now + raise in the face of ambiguity. + Expiring "Y" resets the "parent" tracker, meaning + X.remove(Y) could then end up deleting Y even + if X is stale, but this is the same behavior + as before; it's advised to expire X also in that + case. + + .. change:: + :tags: orm, bug + :tickets: 2310 + + fixed inappropriate evaluation of user-mapped + object in a boolean context within query.get(). Also in 0.6.9. + + .. change:: + :tags: orm, bug + :tickets: 2304 + + Added missing comma to PASSIVE_RETURN_NEVER_SET + symbol + + .. change:: + :tags: orm, bug + :tickets: 1776 + + Cls.column.collate("some collation") now + works. Also in 0.6.9 + + .. change:: + :tags: orm, bug + :tickets: 2309 + + the value of a composite attribute is now + expired after an insert or update operation, instead + of regenerated in place. This ensures that a + column value which is expired within a flush + will be loaded first, before the composite + is regenerated using that value. + + .. change:: + :tags: orm, bug + :tickets: 2309, 2308 + + The fix in also emits the + "refresh" event when the composite value is + loaded on access, even if all column + values were already present, as is appropriate. + This fixes the "mutable" extension which relies + upon the "load" event to ensure the _parents + dictionary is up to date, fixes. + Thanks to Scott Torborg for the test case here. + + .. change:: + :tags: orm, bug + :tickets: 2312 + + Fixed bug whereby a subclass of a subclass + using concrete inheritance in conjunction with + the new ConcreteBase or AbstractConcreteBase + would fail to apply the subclasses deeper than + one level to the "polymorphic loader" of each + base + + .. change:: + :tags: orm, bug + :tickets: 2312 + + Fixed bug whereby a subclass of a subclass + using the new AbstractConcreteBase would fail + to acquire the correct "base_mapper" attribute + when the "base" mapper was generated, thereby + causing failures later on. + + .. change:: + :tags: orm, bug + :tickets: 2316 + + Fixed bug whereby column_property() created + against ORM-level column could be treated as + a distinct entity when producing certain + kinds of joined-inh joins. + + .. change:: + :tags: orm, bug + :tickets: 2297 + + Fixed the error formatting raised when + a tuple is inadvertently passed to session.query(). Also in 0.6.9. + + .. change:: + :tags: orm, bug + :tickets: 2328 + + Calls to query.join() to a single-table + inheritance subclass are now tracked, and + are used to eliminate the additional WHERE.. + IN criterion normally tacked on with single + table inheritance, since the join should + accommodate it. This allows OUTER JOIN + to a single table subclass to produce + the correct results, and overall will produce + fewer WHERE criterion when dealing with + single table inheritance joins. + + .. change:: + :tags: orm, bug + :tickets: 2339 + + __table_args__ can now be passed as + an empty tuple as well as an empty dict.. Thanks to Fayaz Yusuf Khan + for the patch. + + .. change:: + :tags: orm, bug + :tickets: 2325 + + Updated warning message when setting + delete-orphan without delete to no longer + refer to 0.6, as we never got around to + upgrading this to an exception. Ideally + this might be better as an exception but + it's not critical either way. + + .. change:: + :tags: orm, feature + :tickets: 2345, 2238 + + polymorphic_on now accepts many + new kinds of values: + + - standalone expressions that aren't + otherwise mapped + - column_property() objects + - string names of any column_property() + or attribute name of a mapped Column + + The docs include an example using + the case() construct, which is likely to be + a common constructed used here. and part of + + Standalone expressions in polymorphic_on + propagate to single-table inheritance + subclasses so that they are used in the + WHERE /JOIN clause to limit rows to that + subclass as is the usual behavior. + + .. change:: + :tags: orm, feature + :tickets: 2301 + + IdentitySet supports the - operator + as the same as difference(), handy when dealing + with Session.dirty etc. + + .. change:: + :tags: orm, feature + :tickets: + + Added new value for Column autoincrement + called "ignore_fk", can be used to force autoincrement + on a column that's still part of a ForeignKeyConstraint. + New example in the relationship docs illustrates + its use. + + .. change:: + :tags: orm, bug + :tickets: + + Fixed bug in get_history() when referring + to a composite attribute that has no value; + added coverage for get_history() regarding + composites which is otherwise just a userland + function. + + .. change:: + :tags: bug, sql + :tickets: 2316, 2261 + + related to, made some + adjustments to the change from + regarding the "from" list on a select(). The + _froms collection is no longer memoized, as this + simplifies various use cases and removes the + need for a "warning" if a column is attached + to a table after it was already used in an + expression - the select() construct will now + always produce the correct expression. + There's probably no real-world + performance hit here; select() objects are + almost always made ad-hoc, and systems that + wish to optimize the re-use of a select() + would be using the "compiled_cache" feature. + A hit which would occur when calling select.bind + has been reduced, but the vast majority + of users shouldn't be using "bound metadata" + anyway :). + + .. change:: + :tags: feature, sql + :tickets: 2166, 1944 + + The update() construct can now accommodate + multiple tables in the WHERE clause, which will + render an "UPDATE..FROM" construct, recognized by + Postgresql and MSSQL. When compiled on MySQL, + will instead generate "UPDATE t1, t2, ..". MySQL + additionally can render against multiple tables in the + SET clause, if Column objects are used as keys + in the "values" parameter or generative method. + + .. change:: + :tags: feature, sql + :tickets: 77 + + Added accessor to types called "python_type", + returns the rudimentary Python type object + for a particular TypeEngine instance, if known, + else raises NotImplementedError. + + .. change:: + :tags: bug, sql + :tickets: 2261, 2319 + + further tweak to the fix from, + so that generative methods work a bit better + off of cloned (this is almost a non-use case though). + In particular this allows with_only_columns() + to behave more consistently. Added additional + documentation to with_only_columns() to clarify + expected behavior, which changed as a result + of. + + .. change:: + :tags: engine, bug + :tickets: 2317 + + Fixed bug whereby transaction.rollback() + would throw an error on an invalidated + connection if the transaction were a + two-phase or savepoint transaction. + For plain transactions, rollback() is a no-op + if the connection is invalidated, so while + it wasn't 100% clear if it should be a no-op, + at least now the interface is consistent. + + .. change:: + :tags: feature, schema + :tickets: + + Added new support for remote "schemas": + + .. change:: + :tags: schema + :tickets: + + MetaData() accepts "schema" and "quote_schema" + arguments, which will be applied to the same-named + arguments of a Table + or Sequence which leaves these at their default + of ``None``. + + .. change:: + :tags: schema + :tickets: + + Sequence accepts "quote_schema" argument + + .. change:: + :tags: schema + :tickets: + + tometadata() for Table will use the "schema" + of the incoming MetaData for the new Table + if the schema argument is explicitly "None" + + .. change:: + :tags: schema + :tickets: + + Added CreateSchema and DropSchema DDL + constructs - these accept just the string + name of a schema and a "quote" flag. + + .. change:: + :tags: schema + :tickets: + + When using default "schema" with MetaData, + ForeignKey will also assume the "default" schema + when locating remote table. This allows the "schema" + argument on MetaData to be applied to any + set of Table objects that otherwise don't have + a "schema". + + .. change:: + :tags: schema + :tickets: 1679 + + a "has_schema" method has been implemented + on dialect, but only works on Postgresql so far. + Courtesy Manlio Perillo. + + .. change:: + :tags: feature, schema + :tickets: 1410 + + The "extend_existing" flag on Table + now allows for the reflection process to take + effect for a Table object that's already been + defined; when autoload=True and extend_existing=True + are both set, the full set of columns will be + reflected from the Table which will then + *overwrite* those columns already present, + rather than no activity occurring. Columns that + are present directly in the autoload run + will be used as always, however. + + .. change:: + :tags: bug, schema + :tickets: + + Fixed bug whereby TypeDecorator would + return a stale value for _type_affinity, when + using a TypeDecorator that "switches" types, + like the CHAR/UUID type. + + .. change:: + :tags: bug, schema + :tickets: + + Fixed bug whereby "order_by='foreign_key'" + option to Inspector.get_table_names + wasn't implementing the sort properly, replaced + with the existing sort algorithm + + .. change:: + :tags: bug, schema + :tickets: 2305 + + the "name" of a column-level CHECK constraint, + if present, is now rendered in the CREATE TABLE + statement using "CONSTRAINT CHECK ". + + .. change:: + :tags: pyodbc, bug + :tickets: 2318 + + pyodbc-based dialects now parse the + pyodbc accurately as far as observed + pyodbc strings, including such gems + as "py3-3.0.1-beta4" + + .. change:: + :tags: postgresql, bug + :tickets: 2311 + + Postgresql dialect memoizes that an ENUM of a + particular name was processed + during a create/drop sequence. This allows + a create/drop sequence to work without any + calls to "checkfirst", and also means with + "checkfirst" turned on it only needs to + check for the ENUM once. + + .. change:: + :tags: postgresql, feature + :tickets: + + Added create_type constructor argument + to pg.ENUM. When False, no CREATE/DROP or + checking for the type will be performed as part + of a table create/drop event; only the + create()/drop)() methods called directly + will do this. Helps with Alembic "offline" + scripts. + + .. change:: + :tags: mssql, feature + :tickets: 822 + + lifted the restriction on SAVEPOINT + for SQL Server. All tests pass using it, + it's not known if there are deeper issues + however. + + .. change:: + :tags: mssql, bug + :tickets: 2336 + + repaired the with_hint() feature which + wasn't implemented correctly on MSSQL - + usually used for the "WITH (NOLOCK)" hint + (which you shouldn't be using anyway ! + use snapshot isolation instead :) ) + + .. change:: + :tags: mssql, bug + :tickets: 2318 + + use new pyodbc version detection for + _need_decimal_fix option. + + .. change:: + :tags: mssql, bug + :tickets: 2343 + + don't cast "table name" as NVARCHAR + on SQL Server 2000. Still mostly in the dark + what incantations are needed to make PyODBC + work fully with FreeTDS 0.91 here, however. + + .. change:: + :tags: mssql, bug + :tickets: 2269 + + Decode incoming values when retrieving + list of index names and the names of columns + within those indexes. + + .. change:: + :tags: bug, mysql + :tickets: + + Unicode adjustments allow latest pymysql + (post 0.4) to pass 100% on Python 2. + + .. change:: + :tags: ext, feature + :tickets: + + Added an example to the hybrid docs + of a "transformer" - a hybrid that returns a + query-transforming callable in combination + with a custom comparator. Uses a new method + on Query called with_transformation(). The use + case here is fairly experimental, but only + adds one line of code to Query. + + .. change:: + :tags: ext, bug + :tickets: + + the @compiles decorator raises an + informative error message when no "default" + compilation handler is present, rather + than KeyError. + + .. change:: + :tags: examples, bug + :tickets: + + Fixed bug in history_meta.py example where + the "unique" flag was not removed from a + single-table-inheritance subclass which + generates columns to put up onto the base. + +.. changelog:: + :version: 0.7.3 + :released: Sun Oct 16 2011 + + .. change:: + :tags: general + :tickets: 2279 + + Adjusted the "importlater" mechanism, which is + used internally to resolve import cycles, + such that the usage of __import__ is completed + when the import of sqlalchemy or sqlalchemy.orm + is done, thereby avoiding any usage of __import__ + after the application starts new threads, + fixes. Also in 0.6.9. + + .. change:: + :tags: orm + :tickets: 2298 + + Improved query.join() such that the "left" side + can more flexibly be a non-ORM selectable, + such as a subquery. A selectable placed + in select_from() will now be used as the left + side, favored over implicit usage + of a mapped entity. + If the join still fails based on lack of + foreign keys, the error message includes + this detail. Thanks to brianrhude + on IRC for the test case. + + .. change:: + :tags: orm + :tickets: 2241 + + Added after_soft_rollback() Session event. This + event fires unconditionally whenever rollback() + is called, regardless of if an actual DBAPI + level rollback occurred. This event + is specifically designed to allow operations + with the Session to proceed after a rollback + when the Session.is_active is True. + + .. change:: + :tags: orm + :tickets: + + added "adapt_on_names" boolean flag to orm.aliased() + construct. Allows an aliased() construct + to link the ORM entity to a selectable that contains + aggregates or other derived forms of a particular + attribute, provided the name is the same as that + of the entity mapped column. + + .. change:: + :tags: orm + :tickets: + + Added new flag expire_on_flush=False to column_property(), + marks those properties that would otherwise be considered + to be "readonly", i.e. derived from SQL expressions, + to retain their value after a flush has occurred, including + if the parent object itself was involved in an update. + + .. change:: + :tags: orm + :tickets: 2237 + + Enhanced the instrumentation in the ORM to support + Py3K's new argument style of "required kw arguments", + i.e. fn(a, b, *, c, d), fn(a, b, *args, c, d). + Argument signatures of mapped object's __init__ + method will be preserved, including required kw rules. + + .. change:: + :tags: orm + :tickets: 2282 + + Fixed bug in unit of work whereby detection of + "cycles" among classes in highly interlinked patterns + would not produce a deterministic + result; thereby sometimes missing some nodes that + should be considered cycles and causing further + issues down the road. Note this bug is in 0.6 + also; not backported at the moment. + + .. change:: + :tags: orm + :tickets: + + Fixed a variety of synonym()-related regressions + from 0.6: + - making a synonym against a synonym now works. + - synonyms made against a relationship() can + be passed to query.join(), options sent + to query.options(), passed by name + to query.with_parent(). + + .. change:: + :tags: orm + :tickets: 2287 + + Fixed bug whereby mapper.order_by attribute would + be ignored in the "inner" query within a + subquery eager load. . + Also in 0.6.9. + + .. change:: + :tags: orm + :tickets: 2267 + + Identity map .discard() uses dict.pop(,None) + internally instead of "del" to avoid KeyError/warning + during a non-determinate gc teardown + + .. change:: + :tags: orm + :tickets: 2253 + + Fixed regression in new composite rewrite where + deferred=True option failed due to missing + import + + .. change:: + :tags: orm + :tickets: 2248 + + Reinstated "comparator_factory" argument to + composite(), removed when 0.7 was released. + + .. change:: + :tags: orm + :tickets: 2247 + + Fixed bug in query.join() which would occur + in a complex multiple-overlapping path scenario, + where the same table could be joined to + twice. Thanks *much* to Dave Vitek + for the excellent fix here. + + .. change:: + :tags: orm + :tickets: + + Query will convert an OFFSET of zero when + slicing into None, so that needless OFFSET + clauses are not invoked. + + .. change:: + :tags: orm + :tickets: + + Repaired edge case where mapper would fail + to fully update internal state when a relationship + on a new mapper would establish a backref on the + first mapper. + + .. change:: + :tags: orm + :tickets: 2260 + + Fixed bug whereby if __eq__() was + redefined, a relationship many-to-one lazyload + would hit the __eq__() and fail. + Does not apply to 0.6.9. + + .. change:: + :tags: orm + :tickets: 2196 + + Calling class_mapper() and passing in an object + that is not a "type" (i.e. a class that could + potentially be mapped) now raises an informative + ArgumentError, rather than UnmappedClassError. + + .. change:: + :tags: orm + :tickets: + + New event hook, MapperEvents.after_configured(). + Called after a configure() step has completed and + mappers were in fact affected. Theoretically this + event is called once per application, unless new mappings + are constructed after existing ones have been used + already. + + .. change:: + :tags: orm + :tickets: 2281 + + When an open Session is garbage collected, the objects + within it which remain are considered detached again + when they are add()-ed to a new Session. + This is accomplished by an extra check that the previous + "session_key" doesn't actually exist among the pool + of Sessions. + + .. change:: + :tags: orm + :tickets: 2239 + + New declarative features: + - __declare_last__() method, establishes an event + listener for the class method that will be called + when mappers are completed with the final "configure" + step. + - __abstract__ flag. The class will not be mapped + at all when this flag is present on the class. + - New helper classes ConcreteBase, AbstractConcreteBase. + Allow concrete mappings using declarative which automatically + set up the "polymorphic_union" when the "configure" + mapper step is invoked. + - The mapper itself has semi-private methods that allow + the "with_polymorphic" selectable to be assigned + to the mapper after it has already been configured. + + .. change:: + :tags: orm + :tickets: 2283 + + Declarative will warn when a subclass' base uses + @declared_attr for a regular column - this attribute + does not propagate to subclasses. + + .. change:: + :tags: orm + :tickets: 2280 + + The integer "id" used to link a mapped instance with + its owning Session is now generated by a sequence + generation function rather than id(Session), to + eliminate the possibility of recycled id() values + causing an incorrect result, no need to check that + object actually in the session. + + .. change:: + :tags: orm + :tickets: 2257 + + Behavioral improvement: empty + conjunctions such as and_() and or_() will be + flattened in the context of an enclosing conjunction, + i.e. and_(x, or_()) will produce 'X' and not 'X AND + ()'.. + + .. change:: + :tags: orm + :tickets: 2261 + + Fixed bug regarding calculation of "from" list + for a select() element. The "from" calc is now + delayed, so that if the construct uses a Column + object that is not yet attached to a Table, + but is later associated with a Table, it generates + SQL using the table as a FROM. This change + impacted fairly deeply the mechanics of how + the FROM list as well as the "correlates" collection + is calculated, as some "clause adaption" schemes + (these are used very heavily in the ORM) + were relying upon the fact that the "froms" + collection would typically be cached before the + adaption completed. The rework allows it + such that the "froms" collection can be cleared + and re-generated at any time. + + .. change:: + :tags: orm + :tickets: 2270 + + Fixed bug whereby with_only_columns() method of + Select would fail if a selectable were passed.. Also in 0.6.9. + + .. change:: + :tags: schema + :tickets: 2284 + + Modified Column.copy() to use _constructor(), + which defaults to self.__class__, in order to + create the new object. This allows easier support + of subclassing Column. + + .. change:: + :tags: schema + :tickets: 2223 + + Added a slightly nicer __repr__() to SchemaItem + classes. Note the repr here can't fully support + the "repr is the constructor" idea since schema + items can be very deeply nested/cyclical, have + late initialization of some things, etc. + + .. change:: + :tags: engine + :tickets: 2254 + + The recreate() method in all pool classes uses + self.__class__ to get at the type of pool + to produce, in the case of subclassing. Note + there's no usual need to subclass pools. + + .. change:: + :tags: engine + :tickets: 2243 + + Improvement to multi-param statement logging, + long lists of bound parameter sets will be + compressed with an informative indicator + of the compression taking place. Exception + messages use the same improved formatting. + + .. change:: + :tags: engine + :tickets: + + Added optional "sa_pool_key" argument to + pool.manage(dbapi).connect() so that serialization + of args is not necessary. + + .. change:: + :tags: engine + :tickets: 2286 + + The entry point resolution supported by + create_engine() now supports resolution of + individual DBAPI drivers on top of a built-in + or entry point-resolved dialect, using the + standard '+' notation - it's converted to + a '.' before being resolved as an entry + point. + + .. change:: + :tags: engine + :tickets: 2299 + + Added an exception catch + warning for the + "return unicode detection" step within connect, + allows databases that crash on NVARCHAR to + continue initializing, assuming no NVARCHAR + type implemented. + + .. change:: + :tags: types + :tickets: 2258 + + Extra keyword arguments to the base Float + type beyond "precision" and "asdecimal" are ignored; + added a deprecation warning here and additional + docs, related to + + .. change:: + :tags: sqlite + :tickets: + + Ensured that the same ValueError is raised for + illegal date/time/datetime string parsed from + the database regardless of whether C + extensions are in use or not. + + .. change:: + :tags: postgresql + :tickets: 2290 + + Added "postgresql_using" argument to Index(), produces + USING clause to specify index implementation for + PG. . Thanks to Ryan P. Kelly for + the patch. + + .. change:: + :tags: postgresql + :tickets: 1839 + + Added client_encoding parameter to create_engine() + when the postgresql+psycopg2 dialect is used; + calls the psycopg2 set_client_encoding() method + with the value upon connect. + + .. change:: + :tags: postgresql + :tickets: 2291, 2141 + + Fixed bug related to whereby the + same modified index behavior in PG 9 affected + primary key reflection on a renamed column.. Also in 0.6.9. + + .. change:: + :tags: postgresql + :tickets: 2256 + + Reflection functions for Table, Sequence no longer + case insensitive. Names can be differ only in case + and will be correctly distinguished. + + .. change:: + :tags: postgresql + :tickets: + + Use an atomic counter as the "random number" + source for server side cursor names; + conflicts have been reported in rare cases. + + .. change:: + :tags: postgresql + :tickets: 2249 + + Narrowed the assumption made when reflecting + a foreign-key referenced table with schema in + the current search path; an explicit schema will + be applied to the referenced table only if + it actually matches that of the referencing table, + which also has an explicit schema. Previously + it was assumed that "current" schema was synonymous + with the full search_path. + + .. change:: + :tags: mysql + :tickets: 2225 + + a CREATE TABLE will put the COLLATE option + after CHARSET, which appears to be part of + MySQL's arbitrary rules regarding if it will actually + work or not. Also in 0.6.9. + + .. change:: + :tags: mysql + :tickets: 2293 + + Added mysql_length parameter to Index construct, + specifies "length" for indexes. + + .. change:: + :tags: mssql + :tickets: 2273 + + Changes to attempt support of FreeTDS 0.91 with + Pyodbc. This includes that string binds are sent as + Python unicode objects when FreeTDS 0.91 is detected, + and a CAST(? AS NVARCHAR) is used when we detect + for a table. However, I'd continue + to characterize Pyodbc + FreeTDS 0.91 behavior as + pretty crappy, there are still many queries such + as used in reflection which cause a core dump on + Linux, and it is not really usable at all + on OSX, MemoryErrors abound and just plain broken + unicode support. + + .. change:: + :tags: mssql + :tickets: 2277 + + The behavior of =/!= when comparing a scalar select + to a value will no longer produce IN/NOT IN as of 0.8; + this behavior is a little too heavy handed (use in_() if + you want to emit IN) and now emits a deprecation warning. + To get the 0.8 behavior immediately and remove the warning, + a compiler recipe is given at + http://www.sqlalchemy.org/docs/07/dialects/mssql.html#scalar-select-comparisons + to override the behavior of visit_binary(). + + .. change:: + :tags: mssql + :tickets: 2222 + + "0" is accepted as an argument for limit() which + will produce "TOP 0". + + .. change:: + :tags: oracle + :tickets: 2272 + + Fixed ReturningResultProxy for zxjdbc dialect.. Regression from 0.6. + + .. change:: + :tags: oracle + :tickets: 2252 + + The String type now generates VARCHAR2 on Oracle + which is recommended as the default VARCHAR. + Added an explicit VARCHAR2 and NVARCHAR2 to the Oracle + dialect as well. Using NVARCHAR still generates + "NVARCHAR2" - there is no "NVARCHAR" on Oracle - + this remains a slight breakage of the "uppercase types + always give exactly that" policy. VARCHAR still + generates "VARCHAR", keeping with the policy. If + Oracle were to ever define "VARCHAR" as something + different as they claim (IMHO this will never happen), + the type would be available. + + .. change:: + :tags: ext + :tickets: 2262 + + SQLSoup will not be included in version 0.8 + of SQLAlchemy; while useful, we would like to + keep SQLAlchemy itself focused on one ORM + usage paradigm. SQLSoup will hopefully + soon be superseded by a third party + project. + + .. change:: + :tags: ext + :tickets: 2236 + + Added local_attr, remote_attr, attr accessors + to AssociationProxy, providing quick access + to the proxied attributes at the class + level. + + .. change:: + :tags: ext + :tickets: 2275 + + Changed the update() method on association proxy + dictionary to use a duck typing approach, i.e. + checks for "keys", to discern between update({}) + and update((a, b)). Previously, passing a + dictionary that had tuples as keys would be misinterpreted + as a sequence. + + .. change:: + :tags: examples + :tickets: 2266 + + Adjusted dictlike-polymorphic.py example + to apply the CAST such that it works on + PG, other databases. + Also in 0.6.9. + +.. changelog:: + :version: 0.7.2 + :released: Sun Jul 31 2011 + + .. change:: + :tags: orm + :tickets: 2213 + + Feature enhancement: joined and subquery + loading will now traverse already-present related + objects and collections in search of unpopulated + attributes throughout the scope of the eager load + being defined, so that the eager loading that is + specified via mappings or query options + unconditionally takes place for the full depth, + populating whatever is not already populated. + Previously, this traversal would stop if a related + object or collection were already present leading + to inconsistent behavior (though would save on + loads/cycles for an already-loaded graph). For a + subqueryload, this means that the additional + SELECT statements emitted by subqueryload will + invoke unconditionally, no matter how much of the + existing graph is already present (hence the + controversy). The previous behavior of "stopping" + is still in effect when a query is the result of + an attribute-initiated lazyload, as otherwise an + "N+1" style of collection iteration can become + needlessly expensive when the same related object + is encountered repeatedly. There's also an + as-yet-not-public generative Query method + _with_invoke_all_eagers() + which selects old/new behavior + + .. change:: + :tags: orm + :tickets: 2195 + + A rework of "replacement traversal" within + the ORM as it alters selectables to be against + aliases of things (i.e. clause adaption) includes + a fix for multiply-nested any()/has() constructs + against a joined table structure. + + .. change:: + :tags: orm + :tickets: 2234 + + Fixed bug where query.join() + aliased=True + from a joined-inh structure to itself on + relationship() with join condition on the child + table would convert the lead entity into the + joined one inappropriately. + Also in 0.6.9. + + .. change:: + :tags: orm + :tickets: 2205 + + Fixed regression from 0.6 where Session.add() + against an object which contained None in a + collection would raise an internal exception. + Reverted this to 0.6's behavior which is to + accept the None but obviously nothing is + persisted. Ideally, collections with None + present or on append() should at least emit a + warning, which is being considered for 0.8. + + .. change:: + :tags: orm + :tickets: 2191 + + Load of a deferred() attribute on an object + where row can't be located raises + ObjectDeletedError instead of failing later + on; improved the message in ObjectDeletedError + to include other conditions besides a simple + "delete". + + .. change:: + :tags: orm + :tickets: 2224 + + Fixed regression from 0.6 where a get history + operation on some relationship() based attributes + would fail when a lazyload would emit; this could + trigger within a flush() under certain conditions. Thanks to the user who submitted + the great test for this. + + .. change:: + :tags: orm + :tickets: 2228 + + Fixed bug apparent only in Python 3 whereby + sorting of persistent + pending objects during + flush would produce an illegal comparison, + if the persistent object primary key + is not a single integer. + Also in 0.6.9 + + .. change:: + :tags: orm + :tickets: 2197 + + Fixed bug whereby the source clause + used by query.join() would be inconsistent + if against a column expression that combined + multiple entities together. + Also in 0.6.9 + + .. change:: + :tags: orm + :tickets: 2215 + + Fixed bug whereby if a mapped class + redefined __hash__() or __eq__() to something + non-standard, which is a supported use case + as SQLA should never consult these, + the methods would be consulted if the class + was part of a "composite" (i.e. non-single-entity) + result set. + Also in 0.6.9. + + .. change:: + :tags: orm + :tickets: 2240 + + Added public attribute ".validators" to + Mapper, an immutable dictionary view of + all attributes that have been decorated + with the @validates decorator. courtesy Stefano Fontanelli + + .. change:: + :tags: orm + :tickets: 2188 + + Fixed subtle bug that caused SQL to blow + up if: column_property() against subquery + + joinedload + LIMIT + order by the column + property() occurred. . + Also in 0.6.9 + + .. change:: + :tags: orm + :tickets: 2207 + + The join condition produced by with_parent + as well as when using a "dynamic" relationship + against a parent will generate unique + bindparams, rather than incorrectly repeating + the same bindparam. . + Also in 0.6.9. + + .. change:: + :tags: orm + :tickets: + + Added the same "columns-only" check to + mapper.polymorphic_on as used when + receiving user arguments to + relationship.order_by, foreign_keys, + remote_side, etc. + + .. change:: + :tags: orm + :tickets: 2190 + + Fixed bug whereby comparison of column + expression to a Query() would not call + as_scalar() on the underlying SELECT + statement to produce a scalar subquery, + in the way that occurs if you called + it on Query().subquery(). + + .. change:: + :tags: orm + :tickets: 2194 + + Fixed declarative bug where a class inheriting + from a superclass of the same name would fail + due to an unnecessary lookup of the name + in the _decl_class_registry. + + .. change:: + :tags: orm + :tickets: 2199 + + Repaired the "no statement condition" + assertion in Query which would attempt + to raise if a generative method were called + after from_statement() were called.. Also in 0.6.9. + + .. change:: + :tags: sql + :tickets: 2188 + + Fixed two subtle bugs involving column + correspondence in a selectable, + one with the same labeled subquery repeated, the other + when the label has been "grouped" and + loses itself. Affects. + + .. change:: + :tags: schema + :tickets: 2187 + + New feature: with_variant() method on + all types. Produces an instance of Variant(), + a special TypeDecorator which will select + the usage of a different type based on the + dialect in use. + + .. change:: + :tags: schema + :tickets: + + Added an informative error message when + ForeignKeyConstraint refers to a column name in + the parent that is not found. Also in 0.6.9. + + .. change:: + :tags: schema + :tickets: 2206 + + Fixed bug whereby adaptation of old append_ddl_listener() + function was passing unexpected **kw through + to the Table event. Table gets no kws, the MetaData + event in 0.6 would get "tables=somecollection", + this behavior is preserved. + + .. change:: + :tags: schema + :tickets: + + Fixed bug where "autoincrement" detection on + Table would fail if the type had no "affinity" + value, in particular this would occur when using + the UUID example on the site that uses TypeEngine + as the "impl". + + .. change:: + :tags: schema + :tickets: 2209 + + Added an improved repr() to TypeEngine objects + that will only display constructor args which + are positional or kwargs that deviate + from the default. + + .. change:: + :tags: engine + :tickets: + + Context manager provided by Connection.begin() + will issue rollback() if the commit() fails, + not just if an exception occurs. + + .. change:: + :tags: engine + :tickets: 1682 + + Use urllib.parse_qsl() in Python 2.6 and above, + no deprecation warning about cgi.parse_qsl() + + .. change:: + :tags: engine + :tickets: + + Added mixin class sqlalchemy.ext.DontWrapMixin. + User-defined exceptions of this type are never + wrapped in StatementException when they + occur in the context of a statement + execution. + + .. change:: + :tags: engine + :tickets: + + StatementException wrapping will display the + original exception class in the message. + + .. change:: + :tags: engine + :tickets: 2201 + + Failures on connect which raise dbapi.Error + will forward the error to dialect.is_disconnect() + and set the "connection_invalidated" flag if + the dialect knows this to be a potentially + "retryable" condition. Only Oracle ORA-01033 + implemented for now. + + .. change:: + :tags: sqlite + :tickets: 2189 + + SQLite dialect no longer strips quotes + off of reflected default value, allowing + a round trip CREATE TABLE to work. + This is consistent with other dialects + that also maintain the exact form of + the default. + + .. change:: + :tags: postgresql + :tickets: 2198 + + Added new "postgresql_ops" argument to + Index, allows specification of PostgreSQL + operator classes for indexed columns. Courtesy Filip Zyzniewski. + + .. change:: + :tags: mysql + :tickets: 2186 + + Fixed OurSQL dialect to use ansi-neutral + quote symbol "'" for XA commands instead + of '"'. . Also in 0.6.9. + + .. change:: + :tags: mssql + :tickets: + + Adjusted the pyodbc dialect such that bound + values are passed as bytes and not unicode + if the "Easysoft" unix drivers are detected. + This is the same behavior as occurs with + FreeTDS. Easysoft appears to segfault + if Python unicodes are passed under + certain circumstances. + + .. change:: + :tags: oracle + :tickets: 2200 + + Added ORA-00028 to disconnect codes, use + cx_oracle _Error.code to get at the code,. Also in 0.6.9. + + .. change:: + :tags: oracle + :tickets: 2201 + + Added ORA-01033 to disconnect codes, which + can be caught during a connection + event. + + .. change:: + :tags: oracle + :tickets: 2220 + + repaired the oracle.RAW type which did not + generate the correct DDL. + Also in 0.6.9. + + .. change:: + :tags: oracle + :tickets: 2212 + + added CURRENT to reserved word list. Also in 0.6.9. + + .. change:: + :tags: ext + :tickets: + + Fixed bug in the mutable extension whereby + if the same type were used twice in one + mapping, the attributes beyond the first + would not get instrumented. + + .. change:: + :tags: ext + :tickets: + + Fixed bug in the mutable extension whereby + if None or a non-corresponding type were set, + an error would be raised. None is now accepted + which assigns None to all attributes, + illegal values raise ValueError. + + .. change:: + :tags: examples + :tickets: + + Repaired the examples/versioning test runner + to not rely upon SQLAlchemy test libs, + nosetests must be run from within + examples/versioning to get around setup.cfg + breaking it. + + .. change:: + :tags: examples + :tickets: + + Tweak to examples/versioning to pick the + correct foreign key in a multi-level + inheritance situation. + + .. change:: + :tags: examples + :tickets: + + Fixed the attribute shard example to check + for bind param callable correctly in 0.7 + style. + +.. changelog:: + :version: 0.7.1 + :released: Sun Jun 05 2011 + + .. change:: + :tags: general + :tickets: 2184 + + Added a workaround for Python bug 7511 where + failure of C extension build does not + raise an appropriate exception on Windows 64 + bit + VC express + + .. change:: + :tags: orm + :tickets: 1912 + + "delete-orphan" cascade is now allowed on + self-referential relationships - this since + SQLA 0.7 no longer enforces "parent with no + child" at the ORM level; this check is left + up to foreign key nullability. + Related to + + .. change:: + :tags: orm + :tickets: 2180 + + Repaired new "mutable" extension to propagate + events to subclasses correctly; don't + create multiple event listeners for + subclasses either. + + .. change:: + :tags: orm + :tickets: 2170 + + Modify the text of the message which occurs + when the "identity" key isn't detected on + flush, to include the common cause that + the Column isn't set up to detect + auto-increment correctly;. + Also in 0.6.8. + + .. change:: + :tags: orm + :tickets: 2182 + + Fixed bug where transaction-level "deleted" + collection wouldn't be cleared of expunged + states, raising an error if they later + became transient. + Also in 0.6.8. + + .. change:: + :tags: sql + :tickets: + + Fixed bug whereby metadata.reflect(bind) + would close a Connection passed as a + bind argument. Regression from 0.6. + + .. change:: + :tags: sql + :tickets: + + Streamlined the process by which a Select + determines what's in it's '.c' collection. + Behaves identically, except that a + raw ClauseList() passed to select([]) + (which is not a documented case anyway) will + now be expanded into its individual column + elements instead of being ignored. + + .. change:: + :tags: engine + :tickets: + + Deprecate schema/SQL-oriented methods on + Connection/Engine that were never well known + and are redundant: reflecttable(), create(), + drop(), text(), engine.func + + .. change:: + :tags: engine + :tickets: 2178 + + Adjusted the __contains__() method of + a RowProxy result row such that no exception + throw is generated internally; + NoSuchColumnError() also will generate its + message regardless of whether or not the column + construct can be coerced to a string.. Also in 0.6.8. + + .. change:: + :tags: sqlite + :tickets: 2173 + + Accept None from cursor.fetchone() when + "PRAGMA read_uncommitted" is called to determine + current isolation mode at connect time and + default to SERIALIZABLE; this to support SQLite + versions pre-3.3.0 that did not have this + feature. + + .. change:: + :tags: postgresql + :tickets: 2175 + + Some unit test fixes regarding numeric arrays, + MATCH operator. A potential floating-point + inaccuracy issue was fixed, and certain tests + of the MATCH operator only execute within an + EN-oriented locale for now. . + Also in 0.6.8. + + .. change:: + :tags: mysql + :tickets: + + Unit tests pass 100% on MySQL installed + on windows. + + .. change:: + :tags: mysql + :tickets: 2181 + + Removed the "adjust casing" step that would + fail when reflecting a table on MySQL + on windows with a mixed case name. After some + experimenting with a windows MySQL server, it's + been determined that this step wasn't really + helping the situation much; MySQL does not return + FK names with proper casing on non-windows + platforms either, and removing the step at + least allows the reflection to act more like + it does on other OSes. A warning here + has been considered but its difficult to + determine under what conditions such a warning + can be raised, so punted on that for now - + added some docs instead. + + .. change:: + :tags: mysql + :tickets: + + supports_sane_rowcount will be set to False + if using MySQLdb and the DBAPI doesn't provide + the constants.CLIENT module. + +.. changelog:: + :version: 0.7.0 + :released: Fri May 20 2011 + + .. change:: + :tags: mysql + :tickets: + + This section documents those changes from 0.7b4 + to 0.7.0. For an overview of what's new in + SQLAlchemy 0.7, see + http://www.sqlalchemy.org/trac/wiki/07Migration + + .. change:: + :tags: orm + :tickets: 2069 + + Fixed regression introduced in 0.7b4 (!) whereby + query.options(someoption("nonexistent name")) would + fail to raise an error. Also added additional + error catching for cases where the option would + try to build off a column-based element, further + fixed up some of the error messages tailored + in + + .. change:: + :tags: orm + :tickets: 2162 + + query.count() emits "count(*)" instead of + "count(1)". + + .. change:: + :tags: orm + :tickets: 2155 + + Fine tuning of Query clause adaptation when + from_self(), union(), or other "select from + myself" operation, such that plain SQL expression + elements added to filter(), order_by() etc. + which are present in the nested "from myself" + query *will* be adapted in the same way an ORM + expression element will, since these + elements are otherwise not easily accessible. + + .. change:: + :tags: orm + :tickets: 2149 + + Fixed bug where determination of "self referential" + relationship would fail with no workaround + for joined-inh subclass related to itself, + or joined-inh subclass related to a subclass + of that with no cols in the sub-sub class + in the join condition. + Also in 0.6.8. + + .. change:: + :tags: orm + :tickets: 2153 + + mapper() will ignore non-configured foreign keys + to unrelated tables when determining inherit + condition between parent and child class, + but will raise as usual for unresolved + columns and table names regarding the inherited + table. This is an enhanced generalization of + behavior that was already applied to declarative + previously. 0.6.8 has a more + conservative version of this which doesn't + fundamentally alter how join conditions + are determined. + + .. change:: + :tags: orm + :tickets: 2144 + + It is an error to call query.get() when the + given entity is not a single, full class + entity or mapper (i.e. a column). This is + a deprecation warning in 0.6.8. + + .. change:: + :tags: orm + :tickets: 2148 + + Fixed a potential KeyError which under some + circumstances could occur with the identity + map, part of + + .. change:: + :tags: orm + :tickets: + + added Query.with_session() method, switches + Query to use a different session. + + .. change:: + :tags: orm + :tickets: 2131 + + horizontal shard query should use execution + options per connection as per + + .. change:: + :tags: orm + :tickets: 2151 + + a non_primary mapper will inherit the _identity_class + of the primary mapper. This so that a non_primary + established against a class that's normally in an + inheritance mapping will produce results that are + identity-map compatible with that of the primary + mapper (also in 0.6.8) + + .. change:: + :tags: orm + :tickets: 2163 + + Fixed the error message emitted for "can't + execute syncrule for destination column 'q'; + mapper 'X' does not map this column" to + reference the correct mapper. . + Also in 0.6.8. + + .. change:: + :tags: orm + :tickets: 1502 + + polymorphic_union() gets a "cast_nulls" option, + disables the usage of CAST when it renders + the labeled NULL columns. + + .. change:: + :tags: orm + :tickets: + + polymorphic_union() renders the columns in their + original table order, as according to the first + table/selectable in the list of polymorphic + unions in which they appear. (which is itself + an unordered mapping unless you pass an OrderedDict). + + .. change:: + :tags: orm + :tickets: 2171 + + Fixed bug whereby mapper mapped to an anonymous + alias would fail if logging were used, due to + unescaped % sign in the alias name. + Also in 0.6.8. + + .. change:: + :tags: sql + :tickets: 2167 + + Fixed bug whereby nesting a label of a select() + with another label in it would produce incorrect + exported columns. Among other things this would + break an ORM column_property() mapping against + another column_property(). . + Also in 0.6.8 + + .. change:: + :tags: sql + :tickets: + + Changed the handling in determination of join + conditions such that foreign key errors are + only considered between the two given tables. + That is, t1.join(t2) will report FK errors + that involve 't1' or 't2', but anything + involving 't3' will be skipped. This affects + join(), as well as ORM relationship and + inherit condition logic. + + .. change:: + :tags: sql + :tickets: + + Some improvements to error handling inside + of the execute procedure to ensure auto-close + connections are really closed when very + unusual DBAPI errors occur. + + .. change:: + :tags: sql + :tickets: + + metadata.reflect() and reflection.Inspector() + had some reliance on GC to close connections + which were internally procured, fixed this. + + .. change:: + :tags: sql + :tickets: 2140 + + Added explicit check for when Column .name + is assigned as blank string + + .. change:: + :tags: sql + :tickets: 2147 + + Fixed bug whereby if FetchedValue was passed + to column server_onupdate, it would not + have its parent "column" assigned, added + test coverage for all column default assignment + patterns. also in 0.6.8 + + .. change:: + :tags: postgresql + :tickets: + + Fixed the psycopg2_version parsing in the + psycopg2 dialect. + + .. change:: + :tags: postgresql + :tickets: 2141 + + Fixed bug affecting PG 9 whereby index reflection + would fail if against a column whose name + had changed. . Also in 0.6.8. + + .. change:: + :tags: mssql + :tickets: 2169 + + Fixed bug in MSSQL dialect whereby the aliasing + applied to a schema-qualified table would leak + into enclosing select statements. + Also in 0.6.8. + + .. change:: + :tags: documentation + :tickets: 2152 + + Removed the usage of the "collections.MutableMapping" + abc from the ext.mutable docs as it was being used + incorrectly and makes the example more difficult + to understand in any case. + + .. change:: + :tags: examples + :tickets: + + removed the ancient "polymorphic association" + examples and replaced with an updated set of + examples that use declarative mixins, + "generic_associations". Each presents an alternative + table layout. + + .. change:: + :tags: ext + :tickets: 2143 + + Fixed bugs in sqlalchemy.ext.mutable extension where + `None` was not appropriately handled, replacement + events were not appropriately handled. + +.. changelog:: + :version: 0.7.0b4 + :released: Sun Apr 17 2011 + + .. change:: + :tags: general + :tickets: + + Changes to the format of CHANGES, this file. + The format changes have been applied to + the 0.7 releases. + + .. change:: + :tags: general + :tickets: + + The "-declarative" changes will now be listed + directly under the "-orm" section, as these + are closely related. + + .. change:: + :tags: general + :tickets: + + The 0.5 series changes have been moved to + the file CHANGES_PRE_06 which replaces + CHANGES_PRE_05. + + .. change:: + :tags: general + :tickets: + + The changelog for 0.6.7 and subsequent within + the 0.6 series is now listed only in the + CHANGES file within the 0.6 branch. + In the 0.7 CHANGES file (i.e. this file), all the + 0.6 changes are listed inline within the 0.7 + section in which they were also applied + (since all 0.6 changes are in 0.7 as well). + Changes that apply to an 0.6 version here + are noted as are if any differences in + implementation/behavior are present. + + .. change:: + :tags: orm + :tickets: 2122 + + Some fixes to "evaulate" and "fetch" evaluation + when query.update(), query.delete() are called. + The retrieval of records is done after autoflush + in all cases, and before update/delete is + emitted, guarding against unflushed data present + as well as expired objects failing during + the evaluation. + + .. change:: + :tags: orm + :tickets: 2063 + + Reworded the exception raised when a flush + is attempted of a subclass that is not polymorphic + against the supertype. + + .. change:: + :tags: orm + :tickets: + + Still more wording adjustments when a query option + can't find the target entity. Explain that the + path must be from one of the root entities. + + .. change:: + :tags: orm + :tickets: 2123 + + Some fixes to the state handling regarding + backrefs, typically when autoflush=False, where + the back-referenced collection wouldn't + properly handle add/removes with no net + change. Thanks to Richard Murri for the + test case + patch. + (also in 0.6.7). + + .. change:: + :tags: orm + :tickets: 2127 + + Added checks inside the UOW to detect the unusual + condition of being asked to UPDATE or DELETE + on a primary key value that contains NULL + in it. + + .. change:: + :tags: orm + :tickets: 2127 + + Some refinements to attribute history. More + changes are pending possibly in 0.8, but + for now history has been modified such that + scalar history doesn't have a "side effect" + of populating None for a non-present value. + This allows a slightly better ability to + distinguish between a None set and no actual + change, affects as well. + + .. change:: + :tags: orm + :tickets: 2130 + + a "having" clause would be copied from the + inside to the outside query if from_self() + were used; in particular this would break + an 0.7 style count() query. + (also in 0.6.7) + + .. change:: + :tags: orm + :tickets: 2131 + + the Query.execution_options() method now passes + those options to the Connection rather than + the SELECT statement, so that all available + options including isolation level and + compiled cache may be used. + + .. change:: + :tags: sql + :tickets: 2131 + + The "compiled_cache" execution option now raises + an error when passed to a SELECT statement + rather than a Connection. Previously it was + being ignored entirely. We may look into + having this option work on a per-statement + level at some point. + + .. change:: + :tags: sql + :tickets: + + Restored the "catchall" constructor on the base + TypeEngine class, with a deprecation warning. + This so that code which does something like + Integer(11) still succeeds. + + .. change:: + :tags: sql + :tickets: 2104 + + Fixed regression whereby MetaData() coming + back from unpickling did not keep track of + new things it keeps track of now, i.e. + collection of Sequence objects, list + of schema names. + + .. change:: + :tags: sql + :tickets: 2116 + + The limit/offset keywords to select() as well + as the value passed to select.limit()/offset() + will be coerced to integer. + (also in 0.6.7) + + .. change:: + :tags: sql + :tickets: + + fixed bug where "from" clause gathering from an + over() clause would be an itertools.chain() and + not a list, causing "can only concatenate list" + TypeError when combined with other clauses. + + .. change:: + :tags: sql + :tickets: 2134 + + Fixed incorrect usage of "," in over() clause + being placed between the "partition" and "order by" + clauses. + + .. change:: + :tags: sql + :tickets: 2105 + + Before/after attach events for PrimaryKeyConstraint + now function, tests added for before/after events + on all constraint types. + + .. change:: + :tags: sql + :tickets: 2117 + + Added explicit true()/false() constructs to expression + lib - coercion rules will intercept "False"/"True" + into these constructs. In 0.6, the constructs were + typically converted straight to string, which was + no longer accepted in 0.7. + + .. change:: + :tags: engine + :tickets: 2129 + + The C extension is now enabled by default on CPython + 2.x with a fallback to pure python if it fails to + compile. + + .. change:: + :tags: schema + :tickets: 2109 + + The 'useexisting' flag on Table has been superceded + by a new pair of flags 'keep_existing' and + 'extend_existing'. 'extend_existing' is equivalent + to 'useexisting' - the existing Table is returned, + and additional constructor elements are added. + With 'keep_existing', the existing Table is returned, + but additional constructor elements are not added - + these elements are only applied when the Table + is newly created. + + .. change:: + :tags: types + :tickets: 2081 + + REAL has been added to the core types. Supported + by Postgresql, SQL Server, MySQL, SQLite. Note + that the SQL Server and MySQL versions, which + add extra arguments, are also still available + from those dialects. + + .. change:: + :tags: types + :tickets: 2106 + + Added @event.listens_for() decorator, given + target + event name, applies the decorated + function as a listener. + + .. change:: + :tags: pool + :tickets: 2103 + + AssertionPool now stores the traceback indicating + where the currently checked out connection was + acquired; this traceback is reported within + the assertion raised upon a second concurrent + checkout; courtesy Gunnlaugur Briem + + .. change:: + :tags: pool + :tickets: + + The "pool.manage" feature doesn't use pickle + anymore to hash the arguments for each pool. + + .. change:: + :tags: sqlite + :tickets: 2115 + + Fixed bug where reflection of foreign key + created as "REFERENCES " without + col name would fail. + (also in 0.6.7) + + .. change:: + :tags: postgresql + :tickets: + + Psycopg2 for Python 3 is now supported. + + .. change:: + :tags: postgresql + :tickets: 2132 + + Fixed support for precision numerics when using + pg8000. + + .. change:: + :tags: oracle + :tickets: 2100 + + Using column names that would require quotes + for the column itself or for a name-generated + bind parameter, such as names with special + characters, underscores, non-ascii characters, + now properly translate bind parameter keys when + talking to cx_oracle. (Also + in 0.6.7) + + .. change:: + :tags: oracle + :tickets: 2116 + + Oracle dialect adds use_binds_for_limits=False + create_engine() flag, will render the LIMIT/OFFSET + values inline instead of as binds, reported to + modify the execution plan used by Oracle. (Also in 0.6.7) + + .. change:: + :tags: documentation + :tickets: 2029 + + Documented SQLite DATE/TIME/DATETIME types. (also in 0.6.7) + + .. change:: + :tags: documentation + :tickets: 2118 + + Fixed mutable extension docs to show the + correct type-association methods. + +.. changelog:: + :version: 0.7.0b3 + :released: Sun Mar 20 2011 + + .. change:: + :tags: general + :tickets: + + Lots of fixes to unit tests when run under Pypy + (courtesy Alex Gaynor). + + .. change:: + :tags: orm + :tickets: 2093 + + Changed the underlying approach to query.count(). + query.count() is now in all cases exactly: + + query. + from_self(func.count(literal_column('1'))). + scalar() + + That is, "select count(1) from ()". + This produces a subquery in all cases, but + vastly simplifies all the guessing count() + tried to do previously, which would still + fail in many scenarios particularly when + joined table inheritance and other joins + were involved. If the subquery produced + for an otherwise very simple count is really + an issue, use query(func.count()) as an + optimization. + + .. change:: + :tags: orm + :tickets: 2087 + + some changes to the identity map regarding + rare weakref callbacks during iterations. + The mutex has been removed as it apparently + can cause a reentrant (i.e. in one thread) deadlock, + perhaps when gc collects objects at the point of + iteration in order to gain more memory. It is hoped + that "dictionary changed during iteration" will + be exceedingly rare as iteration methods internally + acquire the full list of objects in a single values() + call. Note 0.6.7 has a more conservative fix here + which still keeps the mutex in place. + + .. change:: + :tags: orm + :tickets: 2082 + + A tweak to the unit of work causes it to order + the flush along relationship() dependencies even if + the given objects don't have any inter-attribute + references in memory, which was the behavior in + 0.5 and earlier, so a flush of Parent/Child with + only foreign key/primary key set will succeed. + This while still maintaining 0.6 and above's not + generating a ton of useless internal dependency + structures within the flush that don't correspond + to state actually within the current flush. + + .. change:: + :tags: orm + :tickets: 2069 + + Improvements to the error messages emitted when + querying against column-only entities in conjunction + with (typically incorrectly) using loader options, + where the parent entity is not fully present. + + .. change:: + :tags: orm + :tickets: 2098 + + Fixed bug in query.options() whereby a path + applied to a lazyload using string keys could + overlap a same named attribute on the wrong + entity. Note 0.6.7 has a more conservative fix + to this. + + .. change:: + :tags: declarative + :tickets: 2091 + + Arguments in __mapper_args__ that aren't "hashable" + aren't mistaken for always-hashable, possibly-column + arguments. (also in 0.6.7) + + .. change:: + :tags: sql + :tickets: + + Added a fully descriptive error message for the + case where Column is subclassed and _make_proxy() + fails to make a copy due to TypeError on the + constructor. The method _constructor should + be implemented in this case. + + .. change:: + :tags: sql + :tickets: 2095 + + Added new event "column_reflect" for Table objects. + Receives the info dictionary about a Column before + the object is generated within reflection, and allows + modification to the dictionary for control over + most aspects of the resulting Column including + key, name, type, info dictionary. + + .. change:: + :tags: sql + :tickets: + + To help with the "column_reflect" event being used + with specific Table objects instead of all instances + of Table, listeners can be added to a Table object + inline with its construction using a new argument + "listeners", a list of tuples of the form + (, ), which are applied to the Table + before the reflection process begins. + + .. change:: + :tags: sql + :tickets: 2085 + + Added new generic function "next_value()", accepts + a Sequence object as its argument and renders the + appropriate "next value" generation string on the + target platform, if supported. Also provides + ".next_value()" method on Sequence itself. + + .. change:: + :tags: sql + :tickets: 2084 + + func.next_value() or other SQL expression can + be embedded directly into an insert() construct, + and if implicit or explicit "returning" is used + in conjunction with a primary key column, + the newly generated value will be present in + result.inserted_primary_key. + + .. change:: + :tags: sql + :tickets: 2089 + + Added accessors to ResultProxy "returns_rows", + "is_insert" (also in 0.6.7) + + .. change:: + :tags: engine + :tickets: 2097 + + Fixed AssertionPool regression bug. + + .. change:: + :tags: engine + :tickets: 2060 + + Changed exception raised to ArgumentError when an + invalid dialect is specified. + + .. change:: + :tags: postgresql + :tickets: 2092 + + Added RESERVED_WORDS for postgresql dialect. + (also in 0.6.7) + + .. change:: + :tags: postgresql + :tickets: 2073 + + Fixed the BIT type to allow a "length" parameter, "varying" + parameter. Reflection also fixed. + (also in 0.6.7) + + .. change:: + :tags: mssql + :tickets: 2071 + + Rewrote the query used to get the definition of a view, + typically when using the Inspector interface, to + use sys.sql_modules instead of the information schema, + thereby allowing views definitions longer than 4000 + characters to be fully returned. + (also in 0.6.7) + + .. change:: + :tags: firebird + :tickets: 2083 + + The "implicit_returning" flag on create_engine() is + honored if set to False. (also in 0.6.7) + + .. change:: + :tags: informix + :tickets: 2092 + + Added RESERVED_WORDS informix dialect. + (also in 0.6.7) + + .. change:: + :tags: ext + :tickets: 2090 + + The horizontal_shard ShardedSession class accepts the common + Session argument "query_cls" as a constructor argument, + to enable further subclassing of ShardedQuery. (also in 0.6.7) + + .. change:: + :tags: examples + :tickets: + + Updated the association, association proxy examples + to use declarative, added a new example + dict_of_sets_with_default.py, a "pushing the envelope" + example of association proxy. + + .. change:: + :tags: examples + :tickets: 2090 + + The Beaker caching example allows a "query_cls" argument + to the query_callable() function. + (also in 0.6.7) + +.. changelog:: + :version: 0.7.0b2 + :released: Sat Feb 19 2011 + + .. change:: + :tags: orm + :tickets: 2053 + + Fixed bug whereby Session.merge() would call the + load() event with one too few arguments. + + .. change:: + :tags: orm + :tickets: 2052 + + Added logic which prevents the generation of + events from a MapperExtension or SessionExtension + from generating do-nothing events for all the methods + not overridden. + + .. change:: + :tags: declarative + :tickets: 2058 + + Fixed regression whereby composite() with + Column objects placed inline would fail + to initialize. The Column objects can now + be inline with the composite() or external + and pulled in via name or object ref. + + .. change:: + :tags: declarative + :tickets: 2061 + + Fix error message referencing old @classproperty + name to reference @declared_attr + (also in 0.6.7) + + .. change:: + :tags: declarative + :tickets: 1468 + + the dictionary at the end of the __table_args__ + tuple is now optional. + + .. change:: + :tags: sql + :tickets: 2059 + + Renamed the EngineEvents event class to + ConnectionEvents. As these classes are never + accessed directly by end-user code, this strictly + is a documentation change for end users. Also + simplified how events get linked to engines + and connections internally. + + .. change:: + :tags: sql + :tickets: 2055 + + The Sequence() construct, when passed a MetaData() + object via its 'metadata' argument, will be + included in CREATE/DROP statements within + metadata.create_all() and metadata.drop_all(), + including "checkfirst" logic. + + .. change:: + :tags: sql + :tickets: 2064 + + The Column.references() method now returns True + if it has a foreign key referencing the + given column exactly, not just it's parent + table. + + .. change:: + :tags: postgresql + :tickets: 2065 + + Fixed regression from 0.6 where SMALLINT and + BIGINT types would both generate SERIAL + on an integer PK column, instead of + SMALLINT and BIGSERIAL + + .. change:: + :tags: ext + :tickets: 2054 + + Association proxy now has correct behavior for + any(), has(), and contains() when proxying + a many-to-one scalar attribute to a one-to-many + collection (i.e. the reverse of the 'typical' + association proxy use case) + + .. change:: + :tags: examples + :tickets: + + Beaker example now takes into account 'limit' + and 'offset', bind params within embedded + FROM clauses (like when you use union() or + from_self()) when generating a cache key. + +.. changelog:: + :version: 0.7.0b1 + :released: Sat Feb 12 2011 + + .. change:: + :tags: examples + :tickets: + + Detailed descriptions of each change below are + described at: + http://www.sqlalchemy.org/trac/wiki/07Migration + + .. change:: + :tags: general + :tickets: 1902 + + New event system, supercedes all extensions, listeners, + etc. + + .. change:: + :tags: general + :tickets: 1926 + + Logging enhancements + + .. change:: + :tags: general + :tickets: 1949 + + Setup no longer installs a Nose plugin + + .. change:: + :tags: general + :tickets: + + The "sqlalchemy.exceptions" alias in sys.modules + has been removed. Base SQLA exceptions are + available via "from sqlalchemy import exc". + The "exceptions" alias for "exc" remains in + "sqlalchemy" for now, it's just not patched into + sys.modules. + + .. change:: + :tags: orm + :tickets: 1923 + + More succinct form of query.join(target, onclause) + + .. change:: + :tags: orm + :tickets: 1903 + + Hybrid Attributes, implements/supercedes synonym() + + .. change:: + :tags: orm + :tickets: 2008 + + Rewrite of composites + + .. change:: + :tags: orm + :tickets: + + Mutation Event Extension, supercedes "mutable=True" + + .. change:: + :tags: orm + :tickets: 1980 + + PickleType and ARRAY mutability turned off by default + + .. change:: + :tags: orm + :tickets: 1895 + + Simplified polymorphic_on assignment + + .. change:: + :tags: orm + :tickets: 1912 + + Flushing of Orphans that have no parent is allowed + + .. change:: + :tags: orm + :tickets: 2041 + + Adjusted flush accounting step to occur before + the commit in the case of autocommit=True. This allows + autocommit=True to work appropriately with + expire_on_commit=True, and also allows post-flush session + hooks to operate in the same transactional context + as when autocommit=False. + + .. change:: + :tags: orm + :tickets: 1973 + + Warnings generated when collection members, scalar referents + not part of the flush + + .. change:: + :tags: orm + :tickets: 1876 + + Non-`Table`-derived constructs can be mapped + + .. change:: + :tags: orm + :tickets: 1942 + + Tuple label names in Query Improved + + .. change:: + :tags: orm + :tickets: 1892 + + Mapped column attributes reference the most specific + column first + + .. change:: + :tags: orm + :tickets: 1896 + + Mapping to joins with two or more same-named columns + requires explicit declaration + + .. change:: + :tags: orm + :tickets: 1875 + + Mapper requires that polymorphic_on column be present + in the mapped selectable + + .. change:: + :tags: orm + :tickets: 1966 + + compile_mappers() renamed configure_mappers(), simplified + configuration internals + + .. change:: + :tags: orm + :tickets: 2018 + + the aliased() function, if passed a SQL FromClause element + (i.e. not a mapped class), will return element.alias() + instead of raising an error on AliasedClass. + + .. change:: + :tags: orm + :tickets: 2027 + + Session.merge() will check the version id of the incoming + state against that of the database, assuming the mapping + uses version ids and incoming state has a version_id + assigned, and raise StaleDataError if they don't + match. + + .. change:: + :tags: orm + :tickets: 1996 + + Session.connection(), Session.execute() accept 'bind', + to allow execute/connection operations to participate + in the open transaction of an engine explicitly. + + .. change:: + :tags: orm + :tickets: + + Query.join(), Query.outerjoin(), eagerload(), + eagerload_all(), others no longer allow lists + of attributes as arguments (i.e. option([x, y, z]) + form, deprecated since 0.5) + + .. change:: + :tags: orm + :tickets: + + ScopedSession.mapper is removed (deprecated since 0.5). + + .. change:: + :tags: orm + :tickets: 2031 + + Horizontal shard query places 'shard_id' in + context.attributes where it's accessible by the + "load()" event. + + .. change:: + :tags: orm + :tickets: 2032 + + A single contains_eager() call across + multiple entities will indicate all collections + along that path should load, instead of requiring + distinct contains_eager() calls for each endpoint + (which was never correctly documented). + + .. change:: + :tags: orm + :tickets: + + The "name" field used in orm.aliased() now renders + in the resulting SQL statement. + + .. change:: + :tags: orm + :tickets: 1473 + + Session weak_instance_dict=False is deprecated. + + .. change:: + :tags: orm + :tickets: 2046 + + An exception is raised in the unusual case that an + append or similar event on a collection occurs after + the parent object has been dereferenced, which + prevents the parent from being marked as "dirty" + in the session. Was a warning in 0.6.6. + + .. change:: + :tags: orm + :tickets: 1069 + + Query.distinct() now accepts column expressions + as *args, interpreted by the Postgresql dialect + as DISTINCT ON (). + + .. change:: + :tags: orm + :tickets: 2049 + + Additional tuning to "many-to-one" relationship + loads during a flush(). A change in version 0.6.6 + ([ticket:2002]) required that more "unnecessary" m2o + loads during a flush could occur. Extra loading modes have + been added so that the SQL emitted in this + specific use case is trimmed back, while still + retrieving the information the flush needs in order + to not miss anything. + + .. change:: + :tags: orm + :tickets: + + the value of "passive" as passed to + attributes.get_history() should be one of the + constants defined in the attributes package. Sending + True or False is deprecated. + + .. change:: + :tags: orm + :tickets: 2030 + + Added a `name` argument to `Query.subquery()`, to allow + a fixed name to be assigned to the alias object. (also in 0.6.7) + + .. change:: + :tags: orm + :tickets: 2019 + + A warning is emitted when a joined-table inheriting mapper + has no primary keys on the locally mapped table + (but has pks on the superclass table). + (also in 0.6.7) + + .. change:: + :tags: orm + :tickets: 2038 + + Fixed bug where "middle" class in a polymorphic hierarchy + would have no 'polymorphic_on' column if it didn't also + specify a 'polymorphic_identity', leading to strange + errors upon refresh, wrong class loaded when querying + from that target. Also emits the correct WHERE criterion + when using single table inheritance. + (also in 0.6.7) + + .. change:: + :tags: orm + :tickets: 1995 + + Fixed bug where a column with a SQL or server side default + that was excluded from a mapping with include_properties + or exclude_properties would result in UnmappedColumnError. (also in 0.6.7) + + .. change:: + :tags: orm + :tickets: 2046 + + A warning is emitted in the unusual case that an + append or similar event on a collection occurs after + the parent object has been dereferenced, which + prevents the parent from being marked as "dirty" + in the session. This will be an exception in 0.7. (also in 0.6.7) + + .. change:: + :tags: declarative + :tickets: 2050 + + Added an explicit check for the case that the name + 'metadata' is used for a column attribute on a + declarative class. (also in 0.6.7) + + .. change:: + :tags: sql + :tickets: 1844 + + Added over() function, method to FunctionElement + classes, produces the _Over() construct which + in turn generates "window functions", i.e. + " OVER (PARTITION BY , + ORDER BY )". + + .. change:: + :tags: sql + :tickets: 805 + + LIMIT/OFFSET clauses now use bind parameters + + .. change:: + :tags: sql + :tickets: 1069 + + select.distinct() now accepts column expressions + as *args, interpreted by the Postgresql dialect + as DISTINCT ON (). Note this was already + available via passing a list to the `distinct` + keyword argument to select(). + + .. change:: + :tags: sql + :tickets: + + select.prefix_with() accepts multiple expressions + (i.e. *expr), 'prefix' keyword argument to select() + accepts a list or tuple. + + .. change:: + :tags: sql + :tickets: + + Passing a string to the `distinct` keyword argument + of `select()` for the purpose of emitting special + MySQL keywords (DISTINCTROW etc.) is deprecated - + use `prefix_with()` for this. + + .. change:: + :tags: sql + :tickets: 2006, 2005 + + TypeDecorator works with primary key columns + + .. change:: + :tags: sql + :tickets: 1897 + + DDL() constructs now escape percent signs + + .. change:: + :tags: sql + :tickets: 1917, 1893 + + Table.c / MetaData.tables refined a bit, don't allow direct + mutation + + .. change:: + :tags: sql + :tickets: 1950 + + Callables passed to `bindparam()` don't get evaluated + + .. change:: + :tags: sql + :tickets: 1870 + + types.type_map is now private, types._type_map + + .. change:: + :tags: sql + :tickets: 1982 + + Non-public Pool methods underscored + + .. change:: + :tags: sql + :tickets: 723 + + Added NULLS FIRST and NULLS LAST support. It's implemented + as an extension to the asc() and desc() operators, called + nullsfirst() and nullslast(). + + .. change:: + :tags: sql + :tickets: + + The Index() construct can be created inline with a Table + definition, using strings as column names, as an alternative + to the creation of the index outside of the Table. + + .. change:: + :tags: sql + :tickets: 2001 + + execution_options() on Connection accepts + "isolation_level" argument, sets transaction isolation + level for that connection only until returned to the + connection pool, for thsoe backends which support it + (SQLite, Postgresql) + + .. change:: + :tags: sql + :tickets: 2005 + + A TypeDecorator of Integer can be used with a primary key + column, and the "autoincrement" feature of various dialects + as well as the "sqlite_autoincrement" flag will honor + the underlying database type as being Integer-based. + + .. change:: + :tags: sql + :tickets: 2020, 2021 + + Established consistency when server_default is present + on an Integer PK column. SQLA doesn't pre-fetch these, + nor do they come back in cursor.lastrowid (DBAPI). + Ensured all backends consistently return None + in result.inserted_primary_key for these. Regarding + reflection for this case, reflection of an int PK col + with a server_default sets the "autoincrement" flag to False, + except in the case of a PG SERIAL col where we detected a + sequence default. + + .. change:: + :tags: sql + :tickets: 2006 + + Result-row processors are applied to pre-executed SQL + defaults, as well as cursor.lastrowid, when determining + the contents of result.inserted_primary_key. + + .. change:: + :tags: sql + :tickets: + + Bind parameters present in the "columns clause" of a select + are now auto-labeled like other "anonymous" clauses, + which among other things allows their "type" to be meaningful + when the row is fetched, as in result row processors. + + .. change:: + :tags: sql + :tickets: + + TypeDecorator is present in the "sqlalchemy" import space. + + .. change:: + :tags: sql + :tickets: 2015 + + Non-DBAPI errors which occur in the scope of an `execute()` + call are now wrapped in sqlalchemy.exc.StatementError, + and the text of the SQL statement and repr() of params + is included. This makes it easier to identify statement + executions which fail before the DBAPI becomes + involved. + + .. change:: + :tags: sql + :tickets: 2048 + + The concept of associating a ".bind" directly with a + ClauseElement has been explicitly moved to Executable, + i.e. the mixin that describes ClauseElements which represent + engine-executable constructs. This change is an improvement + to internal organization and is unlikely to affect any + real-world usage. + + .. change:: + :tags: sql + :tickets: 2028 + + Column.copy(), as used in table.tometadata(), copies the + 'doc' attribute. (also in 0.6.7) + + .. change:: + :tags: sql + :tickets: 2023 + + Added some defs to the resultproxy.c extension so that + the extension compiles and runs on Python 2.4. (also in 0.6.7) + + .. change:: + :tags: sql + :tickets: 2042 + + The compiler extension now supports overriding the default + compilation of expression._BindParamClause including that + the auto-generated binds within the VALUES/SET clause + of an insert()/update() statement will also use the new + compilation rules. (also in 0.6.7) + + .. change:: + :tags: sql + :tickets: 1921 + + SQLite dialect now uses `NullPool` for file-based databases + + .. change:: + :tags: sql + :tickets: 2036 + + The path given as the location of a sqlite database is now + normalized via os.path.abspath(), so that directory changes + within the process don't affect the ultimate location + of a relative file path. + + .. change:: + :tags: postgresql + :tickets: 1083 + + When explicit sequence execution derives the name + of the auto-generated sequence of a SERIAL column, + which currently only occurs if implicit_returning=False, + now accommodates if the table + column name is greater + than 63 characters using the same logic Postgresql uses. (also in 0.6.7) + + .. change:: + :tags: postgresql + :tickets: 2044 + + Added an additional libpq message to the list of "disconnect" + exceptions, "could not receive data from server" (also in 0.6.7) + + .. change:: + :tags: mssql + :tickets: 1833 + + the String/Unicode types, and their counterparts VARCHAR/ + NVARCHAR, emit "max" as the length when no length is + specified, so that the default length, normally '1' + as per SQL server documentation, is instead + 'unbounded'. This also occurs for the VARBINARY type.. + + This behavior makes these types more closely compatible + with Postgresql's VARCHAR type which is similarly unbounded + when no length is specified. + + .. change:: + :tags: mysql + :tickets: 1991 + + New DBAPI support for pymysql, a pure Python port + of MySQL-python. + + .. change:: + :tags: mysql + :tickets: 2047 + + oursql dialect accepts the same "ssl" arguments in + create_engine() as that of MySQLdb. + (also in 0.6.7) + + .. change:: + :tags: firebird + :tickets: 1885 + + Some adjustments so that Interbase is supported as well. + FB/Interbase version idents are parsed into a structure + such as (8, 1, 1, 'interbase') or (2, 1, 588, 'firebird') + so they can be distinguished. + + .. change:: + :tags: drizzle + :tickets: 2003 + + New dialect for Drizzle, a MySQL variant. Uses MySQL-python + for the DBAPI. diff --git a/doc/build/changelog/changelog_08.rst b/doc/build/changelog/changelog_08.rst new file mode 100644 index 0000000000..a093ffb482 --- /dev/null +++ b/doc/build/changelog/changelog_08.rst @@ -0,0 +1,1298 @@ + +============== +0.8 Changelog +============== + + +.. changelog:: + :version: 0.8.0b1 + :released: + + .. change:: + :tags: general + :tickets: + + SQLAlchemy 0.8 now targets Python 2.5 and + above. Python 2.4 is no longer supported. + + .. change:: + :tags: removed, general + :tickets: 2433 + + The "sqlalchemy.exceptions" + synonym for "sqlalchemy.exc" is removed + fully. + + .. change:: + :tags: removed, orm + :tickets: 2442 + + The legacy "mutable" system of the + ORM, including the MutableType class as well + as the mutable=True flag on PickleType + and postgresql.ARRAY has been removed. + In-place mutations are detected by the ORM + using the sqlalchemy.ext.mutable extension, + introduced in 0.7. The removal of MutableType + and associated constructs removes a great + deal of complexity from SQLAlchemy's internals. + The approach performed poorly as it would incur + a scan of the full contents of the Session + when in use. + + .. change:: + :tags: orm, moved + :tickets: + + The InstrumentationManager interface + and the entire related system of alternate + class implementation is now moved out + to sqlalchemy.ext.instrumentation. This is + a seldom used system that adds significant + complexity and overhead to the mechanics of + class instrumentation. The new architecture + allows it to remain unused until + InstrumentationManager is actually imported, + at which point it is bootstrapped into + the core. + + .. change:: + :tags: orm, feature + :tickets: 1401 + + Major rewrite of relationship() + internals now allow join conditions which + include columns pointing to themselves + within composite foreign keys. A new + API for very specialized primaryjoin conditions + is added, allowing conditions based on + SQL functions, CAST, etc. to be handled + by placing the annotation functions + remote() and foreign() inline within the + expression when necessary. Previous recipes + using the semi-private _local_remote_pairs + approach can be upgraded to this new + approach. + + .. change:: + :tags: orm, bug + :tickets: 2527 + + ORM will perform extra effort to determine + that an FK dependency between two tables is + not significant during flush if the tables + are related via joined inheritance and the FK + dependency is not part of the inherit_condition, + saves the user a use_alter directive. + + .. change:: + :tags: orm, feature + :tickets: 2333 + + New standalone function with_polymorphic() + provides the functionality of query.with_polymorphic() + in a standalone form. It can be applied to any + entity within a query, including as the target + of a join in place of the "of_type()" modifier. + + .. change:: + :tags: orm, feature + :tickets: 1106, 2438 + + The of_type() construct on attributes + now accepts aliased() class constructs as well + as with_polymorphic constructs, and works with + query.join(), any(), has(), and also + eager loaders subqueryload(), joinedload(), + contains_eager() + + .. change:: + :tags: orm, feature + :tickets: 2585 + + Improvements to event listening for + mapped classes allows that unmapped classes + can be specified for instance- and mapper-events. + The established events will be automatically + set up on subclasses of that class when the + propagate=True flag is passed, and the + events will be set up for that class itself + if and when it is ultimately mapped. + + .. change:: + :tags: orm, bug + :tickets: 2590 + + The instrumentation events class_instrument(), + class_uninstrument(), and attribute_instrument() + will now fire off only for descendant classes + of the class assigned to listen(). Previously, + an event listener would be assigned to listen + for all classes in all cases regardless of the + "target" argument passed. + + .. change:: + :tags: orm, bug + :tickets: 1900 + + with_polymorphic() produces JOINs + in the correct order and with correct inheriting + tables in the case of sending multi-level + subclasses in an arbitrary order or with + intermediary classes missing. + + .. change:: + :tags: orm, feature + :tickets: 2485 + + The "deferred declarative + reflection" system has been moved into the + declarative extension itself, using the + new DeferredReflection class. This + class is now tested with both single + and joined table inheritance use cases. + + .. change:: + :tags: orm, feature + :tickets: 2208 + + Added new core function "inspect()", + which serves as a generic gateway to + introspection into mappers, objects, + others. The Mapper and InstanceState + objects have been enhanced with a public + API that allows inspection of mapped + attributes, including filters for column-bound + or relationship-bound properties, inspection + of current object state, history of + attributes, etc. + + .. change:: + :tags: orm, feature + :tickets: 2452 + + Calling rollback() within a + session.begin_nested() will now only expire + those objects that had net changes within the + scope of that transaction, that is objects which + were dirty or were modified on a flush. This + allows the typical use case for begin_nested(), + that of altering a small subset of objects, to + leave in place the data from the larger enclosing + set of objects that weren't modified in + that sub-transaction. + + .. change:: + :tags: orm, feature + :tickets: 2372 + + Added utility feature + Session.enable_relationship_loading(), + supersedes relationship.load_on_pending. + Both features should be avoided, however. + + .. change:: + :tags: orm, feature + :tickets: + + Added support for .info dictionary argument to + column_property(), relationship(), composite(). + All MapperProperty classes have an auto-creating .info + dict available overall. + + .. change:: + :tags: orm, feature + :tickets: 2229 + + Adding/removing None from a mapped collection + now generates attribute events. Previously, a None + append would be ignored in some cases. Related + to. + + .. change:: + :tags: orm, feature + :tickets: 2229 + + The presence of None in a mapped collection + now raises an error during flush. Previously, + None values in collections would be silently ignored. + + .. change:: + :tags: orm, feature + :tickets: + + The Query.update() method is now + more lenient as to the table + being updated. Plain Table objects are better + supported now, and additional a joined-inheritance + subclass may be used with update(); the subclass + table will be the target of the update, + and if the parent table is referenced in the + WHERE clause, the compiler will call upon + UPDATE..FROM syntax as allowed by the dialect + to satisfy the WHERE clause. MySQL's multi-table + update feature is also supported if columns + are specified by object in the "values" dicitionary. + PG's DELETE..USING is also not available + in Core yet. + + .. change:: + :tags: orm, feature + :tickets: + + New session events after_transaction_create + and after_transaction_end + allows tracking of new SessionTransaction objects. + If the object is inspected, can be used to determine + when a session first becomes active and when + it deactivates. + + .. change:: + :tags: orm, feature + :tickets: 2592 + + The Query can now load entity/scalar-mixed + "tuple" rows that contain + types which aren't hashable, by setting the flag + "hashable=False" on the corresponding TypeEngine object + in use. Custom types that return unhashable types + (typically lists) can set this flag to False. + + .. change:: + :tags: orm, bug + :tickets: 2481 + + Improvements to joined/subquery eager + loading dealing with chains of subclass entities + sharing a common base, with no specific "join depth" + provided. Will chain out to + each subclass mapper individually before detecting + a "cycle", rather than considering the base class + to be the source of the "cycle". + + .. change:: + :tags: orm, bug + :tickets: 2320 + + The "passive" flag on Session.is_modified() + no longer has any effect. is_modified() in + all cases looks only at local in-memory + modified flags and will not emit any + SQL or invoke loader callables/initializers. + + .. change:: + :tags: orm, bug + :tickets: 2405 + + The warning emitted when using + delete-orphan cascade with one-to-many + or many-to-many without single-parent=True + is now an error. The ORM + would fail to function subsequent to this + warning in any case. + + .. change:: + :tags: orm, bug + :tickets: 2350 + + Lazy loads emitted within flush events + such as before_flush(), before_update(), + etc. will now function as they would + within non-event code, regarding consideration + of the PK/FK values used in the lazy-emitted + query. Previously, + special flags would be established that + would cause lazy loads to load related items + based on the "previous" value of the + parent PK/FK values specifically when called + upon within a flush; the signal to load + in this way is now localized to where the + unit of work actually needs to load that + way. Note that the UOW does + sometimes load these collections before + the before_update() event is called, + so the usage of "passive_updates" or not + can affect whether or not a collection will + represent the "old" or "new" data, when + accessed within a flush event, based + on when the lazy load was emitted. + The change is backwards incompatible in + the exceedingly small chance that + user event code depended on the old + behavior. + + .. change:: + :tags: orm, feature + :tickets: 2179 + + Query now "auto correlates" by + default in the same way as select() does. + Previously, a Query used as a subquery + in another would require the correlate() + method be called explicitly in order to + correlate a table on the inside to the + outside. As always, correlate(None) + disables correlation. + + .. change:: + :tags: orm, feature + :tickets: 2464 + + The after_attach event is now + emitted after the object is established + in Session.new or Session.identity_map + upon Session.add(), Session.merge(), + etc., so that the object is represented + in these collections when the event + is called. Added before_attach + event to accommodate use cases that + need autoflush w pre-attached object. + + .. change:: + :tags: orm, feature + :tickets: + + The Session will produce warnings + when unsupported methods are used inside the + "execute" portion of the flush. These are + the familiar methods add(), delete(), etc. + as well as collection and related-object + manipulations, as called within mapper-level + flush events + like after_insert(), after_update(), etc. + It's been prominently documented for a long + time that SQLAlchemy cannot guarantee + results when the Session is manipulated within + the execution of the flush plan, + however users are still doing it, so now + there's a warning. Maybe someday the Session + will be enhanced to support these operations + inside of the flush, but for now, results + can't be guaranteed. + + .. change:: + :tags: orm, bug + :tickets: 2582, 2566 + + Continuing regarding extra + state post-flush due to event listeners; + any states that are marked as "dirty" from an + attribute perspective, usually via column-attribute + set events within after_insert(), after_update(), + etc., will get the "history" flag reset + in all cases, instead of only those instances + that were part of the flush. This has the effect + that this "dirty" state doesn't carry over + after the flush and won't result in UPDATE + statements. A warning is emitted to this + effect; the set_committed_state() + method can be used to assign attributes on objects + without producing history events. + + .. change:: + :tags: orm, feature + :tickets: 2245 + + ORM entities can be passed + to the core select() construct as well + as to the select_from(), + correlate(), and correlate_except() + methods of select(), where they will be unwrapped + into selectables. + + .. change:: + :tags: orm, feature + :tickets: 2245 + + Some support for auto-rendering of a + relationship join condition based on the mapped + attribute, with usage of core SQL constructs. + E.g. select([SomeClass]).where(SomeClass.somerelationship) + would render SELECT from "someclass" and use the + primaryjoin of "somerelationship" as the WHERE + clause. This changes the previous meaning + of "SomeClass.somerelationship" when used in a + core SQL context; previously, it would "resolve" + to the parent selectable, which wasn't generally + useful. Also works with query.filter(). + Related to. + + .. change:: + :tags: orm, feature + :tickets: 2526 + + The registry of classes + in declarative_base() is now a + WeakValueDictionary. So subclasses of + "Base" that are dereferenced will be + garbage collected, *if they are not + referred to by any other mappers/superclass + mappers*. See the next note for this ticket. + + .. change:: + :tags: orm, feature + :tickets: 2472 + + Conflicts between columns on + single-inheritance declarative subclasses, + with or without using a mixin, can be resolved + using a new @declared_attr usage described + in the documentation. + + .. change:: + :tags: orm, feature + :tickets: 2472 + + declared_attr can now be used + on non-mixin classes, even though this is generally + only useful for single-inheritance subclass + column conflict resolution. + + .. change:: + :tags: orm, feature + :tickets: 2517 + + declared_attr can now be used with + attributes that are not Column or MapperProperty; + including any user-defined value as well + as association proxy objects. + + .. change:: + :tags: orm, bug + :tickets: 2565 + + Fixed a disconnect that slowly evolved + between a @declared_attr Column and a + directly-defined Column on a mixin. In both + cases, the Column will be applied to the + declared class' table, but not to that of a + joined inheritance subclass. Previously, + the directly-defined Column would be placed + on both the base and the sub table, which isn't + typically what's desired. + + .. change:: + :tags: orm, feature + :tickets: 2526 + + *Very limited* support for + inheriting mappers to be GC'ed when the + class itself is deferenced. The mapper + must not have its own table (i.e. + single table inh only) without polymorphic + attributes in place. + This allows for the use case of + creating a temporary subclass of a declarative + mapped class, with no table or mapping + directives of its own, to be garbage collected + when dereferenced by a unit test. + + .. change:: + :tags: orm, feature + :tickets: 2338 + + Declarative now maintains a registry + of classes by string name as well as by full + module-qualified name. Multiple classes with the + same name can now be looked up based on a module-qualified + string within relationship(). Simple class name + lookups where more than one class shares the same + name now raises an informative error message. + + .. change:: + :tags: orm, feature + :tickets: 2535 + + Can now provide class-bound attributes + that override columns which are of any + non-ORM type, not just descriptors. + + .. change:: + :tags: orm, feature + :tickets: 1729 + + Added with_labels and + reduce_columns keyword arguments to + Query.subquery(), to provide two alternate + strategies for producing queries with uniquely- + named columns. . + + .. change:: + :tags: orm, feature + :tickets: 2476 + + A warning is emitted when a reference + to an instrumented collection is no longer + associated with the parent class due to + expiration/attribute refresh/collection + replacement, but an append + or remove operation is received on the + now-detached collection. + + .. change:: + :tags: orm, bug + :tickets: 2549 + + Declarative can now propagate a column + declared on a single-table inheritance subclass + up to the parent class' table, when the parent + class is itself mapped to a join() or select() + statement, directly or via joined inheritance, + and not just a Table. + + .. change:: + :tags: orm, bug + :tickets: + + An error is emitted when uselist=False + is combined with a "dynamic" loader. + This is a warning in 0.7.9. + + .. change:: + :tags: removed, orm + :tickets: + + Deprecated identifiers removed: + + * allow_null_pks mapper() argument + (use allow_partial_pks) + + * _get_col_to_prop() mapper method + (use get_property_by_column()) + + * dont_load argument to Session.merge() + (use load=True) + + * sqlalchemy.orm.shard module + (use sqlalchemy.ext.horizontal_shard) + + .. change:: + :tags: engine, feature + :tickets: 2511 + + Connection event listeners can + now be associated with individual + Connection objects, not just Engine + objects. + + .. change:: + :tags: engine, feature + :tickets: 2459 + + The before_cursor_execute event + fires off for so-called "_cursor_execute" + events, which are usually special-case + executions of primary-key bound sequences + and default-generation SQL + phrases that invoke separately when RETURNING + is not used with INSERT. + + .. change:: + :tags: engine, feature + :tickets: + + The libraries used by the test suite + have been moved around a bit so that they are + part of the SQLAlchemy install again. In addition, + a new suite of tests is present in the + new sqlalchemy.testing.suite package. This is + an under-development system that hopes to provide + a universal testing suite for external dialects. + Dialects which are maintained outside of SQLAlchemy + can use the new test fixture as the framework + for their own tests, and will get for free a + "compliance" suite of dialect-focused tests, + including an improved "requirements" system + where specific capabilities and features can + be enabled or disabled for testing. + + .. change:: + :tags: engine, bug + :tickets: + + The Inspector.get_table_names() + order_by="foreign_key" feature now sorts + tables by dependee first, to be consistent + with util.sort_tables and metadata.sorted_tables. + + .. change:: + :tags: engine, bug + :tickets: 2522 + + Fixed bug whereby if a database restart + affected multiple connections, each + connection would individually invoke a new + disposal of the pool, even though only + one disposal is needed. + + .. change:: + :tags: engine, feature + :tickets: 2462 + + Added a new system + for registration of new dialects in-process + without using an entrypoint. See the + docs for "Registering New Dialects". + + .. change:: + :tags: engine, feature + :tickets: 2556 + + The "required" flag is set to + True by default, if not passed explicitly, + on bindparam() if the "value" or "callable" + parameters are not passed. + This will cause statement execution to check + for the parameter being present in the final + collection of bound parameters, rather than + implicitly assigning None. + + .. change:: + :tags: engine, feature + :tickets: + + Various API tweaks to the "dialect" + API to better support highly specialized + systems such as the Akiban database, including + more hooks to allow an execution context to + access type processors. + + .. change:: + :tags: engine, bug + :tickets: 2397 + + The names of the columns on the + .c. attribute of a select().apply_labels() + is now based on _ instead + of _, for those columns + that have a distinctly named .key. + + .. change:: + :tags: engine, feature + :tickets: 2422 + + Inspector.get_primary_keys() is + deprecated; use Inspector.get_pk_constraint(). + Courtesy Diana Clarke. + + .. change:: + :tags: engine, bug + :tickets: + + The autoload_replace flag on Table, + when False, will cause any reflected foreign key + constraints which refer to already-declared + columns to be skipped, assuming that the + in-Python declared column will take over + the task of specifying in-Python ForeignKey + or ForeignKeyConstraint declarations. + + .. change:: + :tags: engine, bug + :tickets: 2498 + + The ResultProxy methods inserted_primary_key, + last_updated_params(), last_inserted_params(), + postfetch_cols(), prefetch_cols() all + assert that the given statement is a compiled + construct, and is an insert() or update() + statement as is appropriate, else + raise InvalidRequestError. + + .. change:: + :tags: engine, feature + :tickets: + + New C extension module "utils" has + been added for additional function speedups + as we have time to implement. + + .. change:: + :tags: engine + :tickets: + + ResultProxy.last_inserted_ids is removed, + replaced by inserted_primary_key. + + .. change:: + :tags: feature, sql + :tickets: 2547 + + Major rework of operator system + in Core, to allow redefinition of existing + operators as well as addition of new operators + at the type level. New types can be created + from existing ones which add or redefine + operations that are exported out to column + expressions, in a similar manner to how the + ORM has allowed comparator_factory. The new + architecture moves this capability into the + Core so that it is consistently usable in + all cases, propagating cleanly using existing + type propagation behavior. + + .. change:: + :tags: feature, sql + :tickets: 1534, 2547 + + To complement, types + can now provide "bind expressions" and + "column expressions" which allow compile-time + injection of SQL expressions into statements + on a per-column or per-bind level. This is + to suit the use case of a type which needs + to augment bind- and result- behavior at the + SQL level, as opposed to in the Python level. + Allows for schemes like transparent encryption/ + decryption, usage of Postgis functions, etc. + + .. change:: + :tags: feature, sql + :tickets: + + The Core oeprator system now includes + the `getitem` operator, i.e. the bracket + operator in Python. This is used at first + to provide index and slice behavior to the + Postgresql ARRAY type, and also provides a hook + for end-user definition of custom __getitem__ + schemes which can be applied at the type + level as well as within ORM-level custom + operator schemes. `lshift` (<<) + and `rshift` (>>) are also supported as + optional operators. + + Note that this change has the effect that + descriptor-based __getitem__ schemes used by + the ORM in conjunction with synonym() or other + "descriptor-wrapped" schemes will need + to start using a custom comparator in order + to maintain this behavior. + + .. change:: + :tags: feature, sql + :tickets: 2537 + + Revised the rules used to determine + the operator precedence for the user-defined + operator, i.e. that granted using the ``op()`` + method. Previously, the smallest precedence + was applied in all cases, now the default + precedence is zero, lower than all operators + except "comma" (such as, used in the argument + list of a ``func`` call) and "AS", and is + also customizable via the "precedence" argument + on the ``op()`` method. + + .. change:: + :tags: feature, sql + :tickets: 2276 + + Added "collation" parameter to all + String types. When present, renders as + COLLATE . This to support the + COLLATE keyword now supported by several + databases including MySQL, SQLite, and Postgresql. + + .. change:: + :tags: change, sql + :tickets: + + The Text() type renders the length + given to it, if a length was specified. + + .. change:: + :tags: feature, sql + :tickets: + + Custom unary operators can now be + used by combining operators.custom_op() with + UnaryExpression(). + + .. change:: + :tags: bug, sql + :tickets: 2564 + + A tweak to column precedence which moves the + "concat" and "match" operators to be the same as + that of "is", "like", and others; this helps with + parenthesization rendering when used in conjunction + with "IS". + + .. change:: + :tags: feature, sql + :tickets: + + Enhanced GenericFunction and func.* + to allow for user-defined GenericFunction + subclasses to be available via the func.* + namespace automatically by classname, + optionally using a package name, as well + as with the ability to have the rendered + name different from the identified name + in func.*. + + .. change:: + :tags: feature, sql + :tickets: 2562 + + The cast() and extract() constructs + will now be produced via the func.* accessor + as well, as users naturally try to access these + names from func.* they might as well do + what's expected, even though the returned + object is not a FunctionElement. + + .. change:: + :tags: changed, sql + :tickets: + + Most classes in expression.sql + are no longer preceded with an underscore, + i.e. Label, SelectBase, Generative, CompareMixin. + _BindParamClause is also renamed to + BindParameter. The old underscore names for + these classes will remain available as synonyms + for the foreseeable future. + + .. change:: + :tags: feature, sql + :tickets: 2208 + + The Inspector object can now be + acquired using the new inspect() service, + part of + + .. change:: + :tags: feature, sql + :tickets: 2418 + + The column_reflect event now + accepts the Inspector object as the first + argument, preceding "table". Code which + uses the 0.7 version of this very new + event will need modification to add the + "inspector" object as the first argument. + + .. change:: + :tags: feature, sql + :tickets: 2423 + + The behavior of column targeting + in result sets is now case sensitive by + default. SQLAlchemy for many years would + run a case-insensitive conversion on these values, + probably to alleviate early case sensitivity + issues with dialects like Oracle and + Firebird. These issues have been more cleanly + solved in more modern versions so the performance + hit of calling lower() on identifiers is removed. + The case insensitive comparisons can be re-enabled + by setting "case_insensitive=False" on + create_engine(). + + .. change:: + :tags: bug, sql + :tickets: 2591 + + Applying a column expression to a select + statement using a label with or without other + modifying constructs will no longer "target" that + expression to the underlying Column; this affects + ORM operations that rely upon Column targeting + in order to retrieve results. That is, a query + like query(User.id, User.id.label('foo')) will now + track the value of each "User.id" expression separately + instead of munging them together. It is not expected + that any users will be impacted by this; however, + a usage that uses select() in conjunction with + query.from_statement() and attempts to load fully + composed ORM entities may not function as expected + if the select() named Column objects with arbitrary + .label() names, as these will no longer target to + the Column objects mapped by that entity. + + .. change:: + :tags: feature, sql + :tickets: 2415 + + The "unconsumed column names" warning emitted + when keys are present in insert.values() or update.values() + that aren't in the target table is now an exception. + + .. change:: + :tags: feature, sql + :tickets: 2502 + + Added "MATCH" clause to ForeignKey, + ForeignKeyConstraint, courtesy Ryan Kelly. + + .. change:: + :tags: feature, sql + :tickets: 2507 + + Added support for DELETE and UPDATE from + an alias of a table, which would assumedly + be related to itself elsewhere in the query, + courtesy Ryan Kelly. + + .. change:: + :tags: feature, sql + :tickets: + + select() features a correlate_except() + method, auto correlates all selectables except those + passed. + + .. change:: + :tags: feature, sql + :tickets: 2431 + + The prefix_with() method is now available + on each of select(), insert(), update(), delete(), + all with the same API, accepting multiple + prefix calls, as well as a "dialect name" so that + the prefix can be limited to one kind of dialect. + + .. change:: + :tags: feature, sql + :tickets: 1729 + + Added reduce_columns() method + to select() construct, replaces columns inline + using the util.reduce_columns utility function + to remove equivalent columns. reduce_columns() + also adds "with_only_synonyms" to limit the + reduction just to those columns which have the same + name. The deprecated fold_equivalents() feature is + removed. + + .. change:: + :tags: feature, sql + :tickets: 2470 + + Reworked the startswith(), endswith(), + contains() operators to do a better job with + negation (NOT LIKE), and also to assemble them + at compilation time so that their rendered SQL + can be altered, such as in the case for Firebird + STARTING WITH + + .. change:: + :tags: feature, sql + :tickets: 2463 + + Added a hook to the system of rendering + CREATE TABLE that provides access to the render for each + Column individually, by constructing a @compiles + function against the new schema.CreateColumn + construct. + + .. change:: + :tags: feature, sql + :tickets: + + "scalar" selects now have a WHERE method + to help with generative building. Also slight adjustment + regarding how SS "correlates" columns; the new methodology + no longer applies meaning to the underlying + Table column being selected. This improves + some fairly esoteric situations, and the logic + that was there didn't seem to have any purpose. + + .. change:: + :tags: bug, sql + :tickets: 2520 + + Fixes to the interpretation of the + Column "default" parameter as a callable + to not pass ExecutionContext into a keyword + argument parameter. + + .. change:: + :tags: bug, sql + :tickets: 2410 + + All of UniqueConstraint, ForeignKeyConstraint, + CheckConstraint, and PrimaryKeyConstraint will + attach themselves to their parent table automatically + when they refer to a Table-bound Column object directly + (i.e. not just string column name), and refer to + one and only one Table. Prior to 0.8 this behavior + occurred for UniqueConstraint and PrimaryKeyConstraint, + but not ForeignKeyConstraint or CheckConstraint. + + .. change:: + :tags: bug, sql + :tickets: 2594 + + TypeDecorator now includes a generic repr() + that works in terms of the "impl" type by default. + This is a behavioral change for those TypeDecorator + classes that specify a custom __init__ method; those + types will need to re-define __repr__() if they need + __repr__() to provide a faithful constructor representation. + + .. change:: + :tags: bug, sql + :tickets: 2168 + + column.label(None) now produces an + anonymous label, instead of returning the + column object itself, consistent with the behavior + of label(column, None). + + .. change:: + :tags: feature, sql + :tickets: 2455 + + An explicit error is raised when + a ForeignKeyConstraint() that was + constructed to refer to multiple remote tables + is first used. + + .. change:: + :tags: access, feature + :tickets: + + the MS Access dialect has been + moved to its own project on Bitbucket, + taking advantage of the new SQLAlchemy + dialect compliance suite. The dialect is + still in very rough shape and probably not + ready for general use yet, however + it does have *extremely* rudimental + functionality now. + https://bitbucket.org/zzzeek/sqlalchemy-access + + .. change:: + :tags: maxdb, moved + :tickets: + + The MaxDB dialect, which hasn't been + functional for several years, is + moved out to a pending bitbucket project, + https://bitbucket.org/zzzeek/sqlalchemy-maxdb. + + .. change:: + :tags: sqlite, feature + :tickets: 2363 + + the SQLite date and time types + have been overhauled to support a more open + ended format for input and output, using + name based format strings and regexps. A + new argument "microseconds" also provides + the option to omit the "microseconds" + portion of timestamps. Thanks to + Nathan Wright for the work and tests on + this. + + .. change:: + :tags: mssql, feature + :tickets: + + SQL Server dialect can be given + database-qualified schema names, + i.e. "schema='mydatabase.dbo'"; reflection + operations will detect this, split the schema + among the "." to get the owner separately, + and emit a "USE mydatabase" statement before + reflecting targets within the "dbo" owner; + the existing database returned from + DB_NAME() is then restored. + + .. change:: + :tags: mssql, bug + :tickets: 2277 + + removed legacy behavior whereby + a column comparison to a scalar SELECT via + == would coerce to an IN with the SQL server + dialect. This is implicit + behavior which fails in other scenarios + so is removed. Code which relies on this + needs to be modified to use column.in_(select) + explicitly. + + .. change:: + :tags: mssql, feature + :tickets: + + updated support for the mxodbc + driver; mxodbc 3.2.1 is recommended for full + compatibility. + + .. change:: + :tags: postgresql, feature + :tickets: 2441 + + postgresql.ARRAY features an optional + "dimension" argument, will assign a specific + number of dimensions to the array which will + render in DDL as ARRAY[][]..., also improves + performance of bind/result processing. + + .. change:: + :tags: postgresql, feature + :tickets: + + postgresql.ARRAY now supports + indexing and slicing. The Python [] operator + is available on all SQL expressions that are + of type ARRAY; integer or simple slices can be + passed. The slices can also be used on the + assignment side in the SET clause of an UPDATE + statement by passing them into Update.values(); + see the docs for examples. + + .. change:: + :tags: postgresql, feature + :tickets: + + Added new "array literal" construct + postgresql.array(). Basically a "tuple" that + renders as ARRAY[1,2,3]. + + .. change:: + :tags: postgresql, feature + :tickets: 2506 + + Added support for the Postgresql ONLY + keyword, which can appear corresponding to a + table in a SELECT, UPDATE, or DELETE statement. + The phrase is established using with_hint(). + Courtesy Ryan Kelly + + .. change:: + :tags: postgresql, feature + :tickets: + + The "ischema_names" dictionary of the + Postgresql dialect is "unofficially" customizable. + Meaning, new types such as PostGIS types can + be added into this dictionary, and the PG type + reflection code should be able to handle simple + types with variable numbers of arguments. + The functionality here is "unofficial" for + three reasons: + + 1. this is not an "official" API. Ideally + an "official" API would allow custom type-handling + callables at the dialect or global level + in a generic way. + 2. This is only implemented for the PG dialect, + in particular because PG has broad support + for custom types vs. other database backends. + A real API would be implemented at the + default dialect level. + 3. The reflection code here is only tested against + simple types and probably has issues with more + compositional types. + + patch courtesy Éric Lemoine. + + .. change:: + :tags: firebird, feature + :tickets: 2470 + + The "startswith()" operator renders + as "STARTING WITH", "~startswith()" renders + as "NOT STARTING WITH", using FB's more efficient + operator. + + .. change:: + :tags: firebird, bug + :tickets: 2505 + + CompileError is raised when VARCHAR with + no length is attempted to be emitted, same + way as MySQL. + + .. change:: + :tags: firebird, bug + :tickets: + + Firebird now uses strict "ansi bind rules" + so that bound parameters don't render in the + columns clause of a statement - they render + literally instead. + + .. change:: + :tags: firebird, bug + :tickets: + + Support for passing datetime as date when + using the DateTime type with Firebird; other + dialects support this. + + .. change:: + :tags: firebird, feature + :tickets: 2504 + + An experimental dialect for the fdb + driver is added, but is untested as I cannot + get the fdb package to build. + + .. change:: + :tags: bug, mysql + :tickets: 2404 + + Dialect no longer emits expensive server + collations query, as well as server casing, + on first connect. These functions are still + available as semi-private. + + .. change:: + :tags: feature, mysql + :tickets: 2534 + + Added TIME type to mysql dialect, + accepts "fst" argument which is the new + "fractional seconds" specifier for recent + MySQL versions. The datatype will interpret + a microseconds portion received from the driver, + however note that at this time most/all MySQL + DBAPIs do not support returning this value. + + .. change:: + :tags: oracle, bug + :tickets: 2437 + + Quoting information is now passed along + from a Column with quote=True when generating + a same-named bound parameter to the bindparam() + object, as is the case in generated INSERT and UPDATE + statements, so that unknown reserved names can + be fully supported. + + .. change:: + :tags: oracle, feature + :tickets: 2561 + + The types of columns excluded from the + setinputsizes() set can be customized by sending + a list of string DBAPI type names to exclude, + using the exclude_setinputsizes dialect parameter. + This list was previously fixed. The list also + now defaults to STRING, UNICODE, removing + CLOB, NCLOB from the list. + + .. change:: + :tags: oracle, bug + :tickets: + + The CreateIndex construct in Oracle + will now schema-qualify the name of the index + to be that of the parent table. Previously this + name was omitted which apparently creates the + index in the default schema, rather than that + of the table. + + .. change:: + :tags: removed, extensions + :tickets: 2262 + + The SQLSoup extension is removed from + SQLAlchemy, and is now an external project. + See http://pypi.python.org/pypi/sqlsoup . diff --git a/doc/build/changelog/index.rst b/doc/build/changelog/index.rst new file mode 100644 index 0000000000..29a473d26d --- /dev/null +++ b/doc/build/changelog/index.rst @@ -0,0 +1,35 @@ +.. _changelog_toplevel: + +Changes and Migration +===================== + +Migration Guides +---------------- + +SQLAlchemy migration guides are currently available on the wiki. + +* `Version 0.8 `_ + +* `Version 0.7 `_ + +* `Version 0.6 `_ + +* `Version 0.5 `_ + +Change logs +----------- + +SQLAlchemy changelogs are now available within the main documentation. + +.. toctree:: + :maxdepth: 2 + + changelog_08 + changelog_07 + changelog_06 + changelog_05 + changelog_04 + changelog_03 + changelog_02 + changelog_01 + diff --git a/doc/build/contents.rst b/doc/build/contents.rst index dcd9171de8..df80e9b79f 100644 --- a/doc/build/contents.rst +++ b/doc/build/contents.rst @@ -13,6 +13,7 @@ documentation, see :ref:`index_toplevel`. orm/index core/index dialects/index + changelog/index Indices and tables ------------------ diff --git a/doc/build/index.rst b/doc/build/index.rst index 01e62a4209..121fc05b38 100644 --- a/doc/build/index.rst +++ b/doc/build/index.rst @@ -11,7 +11,8 @@ A high level view and getting set up. :ref:`Overview ` | :ref:`Installation Guide ` | -:ref:`Migration from 0.7 ` +:ref:`Migration from 0.7 ` | +:ref:`Changelog catalog ` SQLAlchemy ORM ============== -- 2.47.3