From: Mike Bayer Date: Tue, 26 Aug 2014 18:44:50 +0000 (-0400) Subject: - updates to migration / changelog for 1.0 X-Git-Tag: rel_1_0_0b1~205^2~42 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f44a4b6437eb3d4340c6c0fa790bc4fa885085ea;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - updates to migration / changelog for 1.0 --- diff --git a/doc/build/changelog/changelog_10.rst b/doc/build/changelog/changelog_10.rst index bff3652c58..60a3331bf2 100644 --- a/doc/build/changelog/changelog_10.rst +++ b/doc/build/changelog/changelog_10.rst @@ -16,6 +16,12 @@ .. changelog:: :version: 1.0.0 + Version 1.0.0 is the first release of the 1.0 series. Many changes + described here are also present in the 0.9 and sometimes the 0.8 + series as well. For changes that are specific to 1.0 with an emphasis + on compatibility concerns, see :doc:`/changelog/migration_10`. + + .. change:: :tags: bug, orm :tickets: 3171 @@ -28,8 +34,8 @@ :tags: bug, sql :tickets: 3169 - The INSERT...FROM SELECT construct now implies ``inline=True`` - on :class:`.Insert`. This helps to fix a bug where an + Using :meth:`.Insert.from_select` now implies ``inline=True`` + on :func:`.insert`. This helps to fix a bug where an INSERT...FROM SELECT construct would inadvertently be compiled as "implicit returning" on supporting backends, which would cause breakage in the case of an INSERT that inserts zero rows @@ -88,8 +94,10 @@ statements can be batched; this will be invoked within flush to the degree that subsequent UPDATE statements for the same mapping and table involve the identical columns within the - VALUES clause, as well as that no VALUES-level SQL expressions - are embedded. + VALUES clause, that no SET-level SQL expressions + are embedded, and that the versioning requirements for the mapping + are compatible with the backend dialect's ability to return + a correct rowcount for an executemany operation. .. change:: :tags: engine, bug diff --git a/doc/build/changelog/migration_10.rst b/doc/build/changelog/migration_10.rst index cf81d41fdc..5124527c1f 100644 --- a/doc/build/changelog/migration_10.rst +++ b/doc/build/changelog/migration_10.rst @@ -8,7 +8,7 @@ What's New in SQLAlchemy 1.0? undergoing maintenance releases as of May, 2014, and SQLAlchemy version 1.0, as of yet unreleased. - Document last updated: May 23, 2014 + Document last updated: August 26, 2014 Introduction ============ @@ -32,6 +32,13 @@ Behavioral Changes - ORM Changes to attribute events and other operations regarding attributes that have no pre-existing value ------------------------------------------------------------------------------------------------------ +In this change, the default return value of ``None`` when accessing an object +is now returned dynamically on each access, rather than implicitly setting the +attribute's state with a special "set" operation when it is first accessed. +The visible result of this change is that ``obj.__dict__`` is not implicitly +modified on get, and there are also some minor behavioral changes +for :func:`.attributes.get_history` and related functions. + Given an object with no state:: >>> obj = Foo() @@ -90,25 +97,87 @@ attribute set operation on a many-to-one is received; previously, the "old" valu would be "None" if it had been not set otherwise; it now will send the value :data:`.orm.attributes.NEVER_SET`, which is a value that may be sent to an attribute listener now. This symbol may also be received when -calling on mapper utility functions such as :meth:`.Mapper.primary_key_from_state`; +calling on mapper utility functions such as :meth:`.Mapper.primary_key_from_instance`; if the primary key attributes have no setting at all, whereas the value would be ``None`` before, it will now be the :data:`.orm.attributes.NEVER_SET` symbol, and no change to the object's state occurs. :ticket:`3061` +query.update() with ``synchronize_session='evaluate'`` raises on multi-table update +----------------------------------------------------------------------------------- + +The "evaulator" for :meth:`.Query.update` won't work with multi-table +updates, and needs to be set to ``synchronize_session=False`` or +``synchronize_session='fetch'`` when multiple tables are present. +The new behavior is that an explicit exception is now raised, with a message +to change the synchronize setting. +This is upgraded from a warning emitted as of 0.9.7. + +:ticket:`3117` + +Resurrect Event has been Removed +-------------------------------- + +The "resurrect" ORM event has been removed entirely. This event ceased to +have any function since version 0.8 removed the older "mutable" system +from the unit of work. + + .. _behavioral_changes_core_10: Behavioral Changes - Core ========================= +.. _change_3163: + +Event listeners can not be added or removed from within that event's runner +--------------------------------------------------------------------------- + +Removal of an event listener from inside that same event itself would +modify the elements of a list during iteration, which would cause +still-attached event listeners to silently fail to fire. To prevent +this while still maintaining performance, the lists have been replaced +with ``collections.deque()``, which does not allow any additions or +removals during iteration, and instead raises ``RuntimeError``. + +:ticket:`3163` + +.. _change_3169: + +The INSERT...FROM SELECT construct now implies ``inline=True`` +-------------------------------------------------------------- + +Using :meth:`.Insert.from_select` now implies ``inline=True`` +on :func:`.insert`. This helps to fix a bug where an +INSERT...FROM SELECT construct would inadvertently be compiled +as "implicit returning" on supporting backends, which would +cause breakage in the case of an INSERT that inserts zero rows +(as implicit returning expects a row), as well as arbitrary +return data in the case of an INSERT that inserts multiple +rows (e.g. only the first row of many). +A similar change is also applied to an INSERT..VALUES +with multiple parameter sets; implicit RETURNING will no longer emit +for this statement either. As both of these constructs deal +with varible numbers of rows, the +:attr:`.ResultProxy.inserted_primary_key` accessor does not +apply. Previously, there was a documentation note that one +may prefer ``inline=True`` with INSERT..FROM SELECT as some databases +don't support returning and therefore can't do "implicit" returning, +but there's no reason an INSERT...FROM SELECT needs implicit returning +in any case. Regular explicit :meth:`.Insert.returning` should +be used to return variable numbers of result rows if inserted +data is needed. + +:ticket:`3169` + .. _change_3027: ``autoload_with`` now implies ``autoload=True`` ----------------------------------------------- -A :class:`.Table` can be set up for reflection by passing ``autoload_with`` -alone:: +A :class:`.Table` can be set up for reflection by passing +:paramref:`.Table.autoload_with` alone:: my_table = Table('my_table', metadata, autoload_with=some_engine) @@ -143,27 +212,28 @@ wishes to support the new feature should now call upon the ``._limit_clause`` and ``._offset_clause`` attributes to receive the full SQL expression, rather than the integer value. -.. _feature_get_enums: +Behavioral Improvements +======================= -New get_enums() method with Postgresql Dialect ----------------------------------------------- +.. _feature_updatemany: -The :func:`.inspect` method returns a :class:`.PGInspector` object in the -case of Postgresql, which includes a new :meth:`.PGInspector.get_enums` -method that returns information on all available ``ENUM`` types:: +UPDATE statements are now batched with executemany() in a flush +---------------------------------------------------------------- - from sqlalchemy import inspect, create_engine +UPDATE statements can now be batched within an ORM flush +into more performant executemany() call, similarly to how INSERT +statements can be batched; this will be invoked within flush +based on the following criteria: - engine = create_engine("postgresql+psycopg2://host/dbname") - insp = inspect(engine) - print(insp.get_enums()) +* two or more UPDATE statements in sequence involve the identical set of + columns to be modified. -.. seealso:: +* The statement has no embedded SQL expressions in the SET clause. - :meth:`.PGInspector.get_enums` +* The mapping does not use a :paramref:`~.orm.mapper.version_id_col`, or + the backend dialect supports a "sane" rowcount for an executemany() + operation; most DBAPIs support this correctly now. -Behavioral Improvements -======================= .. _feature_2963: @@ -172,12 +242,16 @@ Behavioral Improvements The :attr:`.InspectionAttr.info` collection is now available on every kind of object that one would retrieve from the :attr:`.Mapper.all_orm_descriptors` -collection:: +collection. This includes :class:`.hybrid_property` and :func:`.association_proxy`. +However, as these objects are class-bound descriptors, they must be accessed +**separately** from the class to which they are attached in order to get +at the attribute. Below this is illustared using the +:attr:`.Mapper.all_orm_descriptors` namespace:: class SomeObject(Base): # ... - @hybrid_property(self): + @hybrid_property def some_prop(self): return self.value + 5 @@ -195,6 +269,63 @@ as remaining ORM constructs such as :func:`.orm.synonym`. Dialect Changes =============== +.. _change_2051: + +New Postgresql Table options +----------------------------- + +Added support for PG table options TABLESPACE, ON COMMIT, +WITH(OUT) OIDS, and INHERITS, when rendering DDL via +the :class:`.Table` construct. + +.. seealso:: + + :ref:`postgresql_table_options` + +:ticket:`2051` + +.. _feature_get_enums: + +New get_enums() method with Postgresql Dialect +---------------------------------------------- + +The :func:`.inspect` method returns a :class:`.PGInspector` object in the +case of Postgresql, which includes a new :meth:`.PGInspector.get_enums` +method that returns information on all available ``ENUM`` types:: + + from sqlalchemy import inspect, create_engine + + engine = create_engine("postgresql+psycopg2://host/dbname") + insp = inspect(engine) + print(insp.get_enums()) + +.. seealso:: + + :meth:`.PGInspector.get_enums` + +MySQL internal "no such table" exceptions not passed to event handlers +---------------------------------------------------------------------- + +The MySQL dialect will now disable :meth:`.ConnectionEvents.handle_error` +events from firing for those statements which it uses internally +to detect if a table exists or not. This is achieved using an +execution option ``skip_user_error_events`` that disables the handle +error event for the scope of that execution. In this way, user code +that rewrites exceptions doesn't need to worry about the MySQL +dialect or other dialects that occasionally need to catch +SQLAlchemy specific exceptions. + + +Changed the default value of ``raise_on_warnings`` for MySQL-Connector +---------------------------------------------------------------------- + +Changed the default value of "raise_on_warnings" to False for +MySQL-Connector. This was set at True for some reason. The "buffered" +flag unfortunately must stay at True as MySQLconnector does not allow +a cursor to be closed unless all results are fully fetched. + +:ticket:`2515` + .. _change_2984: Drizzle Dialect is now an External Dialect diff --git a/doc/build/orm/internals.rst b/doc/build/orm/internals.rst index 0283f6cac8..78ec2fa8e3 100644 --- a/doc/build/orm/internals.rst +++ b/doc/build/orm/internals.rst @@ -27,7 +27,7 @@ sections, are listed here. :members: -.. autoclass:: sqlalchemy.orm.interfaces.InspectionAttr +.. autoclass:: sqlalchemy.orm.base.InspectionAttr :members: diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py index 39de0cf924..f1418f9035 100644 --- a/lib/sqlalchemy/dialects/postgresql/base.py +++ b/lib/sqlalchemy/dialects/postgresql/base.py @@ -417,7 +417,7 @@ of :class:`.PGInspector`, which offers additional methods:: .. autoclass:: PGInspector :members: -.. postgresql_table_options: +.. _postgresql_table_options: PostgreSQL Table Options -------------------------