]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- move some things that are features to the features
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 4 Oct 2014 23:10:23 +0000 (19:10 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 4 Oct 2014 23:10:23 +0000 (19:10 -0400)
doc/build/changelog/migration_10.rst

index 439ec4c6704bfe96a587c58d7064c98fe16c0754..b3e5f6f1521a40ed2918f49a18a700561caebc2b 100644 (file)
@@ -25,6 +25,141 @@ potentially backwards-incompatible changes.
 New Features
 ============
 
+.. _feature_3150:
+
+Improvements to declarative mixins, ``@declared_attr`` and related features
+----------------------------------------------------------------------------
+
+The declarative system in conjunction with :class:`.declared_attr` has been
+overhauled to support new capabilities.
+
+A function decorated with :class:`.declared_attr` is now called only **after**
+any mixin-based column copies are generated.  This means the function can
+call upon mixin-established columns and will receive a reference to the correct
+:class:`.Column` object::
+
+    class HasFooBar(object):
+        foobar = Column(Integer)
+
+        @declared_attr
+        def foobar_prop(cls):
+            return column_property('foobar: ' + cls.foobar)
+
+    class SomeClass(HasFooBar, Base):
+        __tablename__ = 'some_table'
+        id = Column(Integer, primary_key=True)
+
+Above, ``SomeClass.foobar_prop`` will be invoked against ``SomeClass``,
+and ``SomeClass.foobar`` will be the final :class:`.Column` object that is
+to be mapped to ``SomeClass``, as opposed to the non-copied object present
+directly on ``HasFooBar``, even though the columns aren't mapped yet.
+
+The :class:`.declared_attr` function now **memoizes** the value
+that's returned on a per-class basis, so that repeated calls to the same
+attribute will return the same value.  We can alter the example to illustrate
+this::
+
+    class HasFooBar(object):
+        @declared_attr
+        def foobar(cls):
+            return Column(Integer)
+
+        @declared_attr
+        def foobar_prop(cls):
+            return column_property('foobar: ' + cls.foobar)
+
+    class SomeClass(HasFooBar, Base):
+        __tablename__ = 'some_table'
+        id = Column(Integer, primary_key=True)
+
+Previously, ``SomeClass`` would be mapped with one particular copy of
+the ``foobar`` column, but the ``foobar_prop`` by calling upon ``foobar``
+a second time would produce a different column.   The value of
+``SomeClass.foobar`` is now memoized during declarative setup time, so that
+even before the attribute is mapped by the mapper, the interim column
+value will remain consistent no matter how many times the
+:class:`.declared_attr` is called upon.
+
+The two behaviors above should help considerably with declarative definition
+of many types of mapper properties that derive from other attributes, where
+the :class:`.declared_attr` function is called upon from other
+:class:`.declared_attr` functions locally present before the class is
+actually mapped.
+
+For a pretty slim edge case where one wishes to build a declarative mixin
+that establishes distinct columns per subclass, a new modifier
+:attr:`.declared_attr.cascading` is added.  With this modifier, the
+decorated function will be invoked individually for each class in the
+mapped inheritance hierarchy.  While this is already the behavior for
+special attributes such as ``__table_args__`` and ``__mapper_args__``,
+for columns and other properties the behavior by default assumes that attribute
+is affixed to the base class only, and just inherited from subclasses.
+With :attr:`.declared_attr.cascading`, individual behaviors can be
+applied::
+
+    class HasSomeAttribute(object):
+        @declared_attr.cascading
+        def some_id(cls):
+            if has_inherited_table(cls):
+                return Column(ForeignKey('myclass.id'), primary_key=True)
+            else:
+                return Column(Integer, primary_key=True)
+
+            return Column('id', Integer, primary_key=True)
+
+    class MyClass(HasSomeAttribute, Base):
+        ""
+        # ...
+
+    class MySubClass(MyClass):
+        ""
+        # ...
+
+.. seealso::
+
+    :ref:`mixin_inheritance_columns`
+
+Finally, the :class:`.AbstractConcreteBase` class has been reworked
+so that a relationship or other mapper property can be set up inline
+on the abstract base::
+
+    from sqlalchemy import Column, Integer, ForeignKey
+    from sqlalchemy.orm import relationship
+    from sqlalchemy.ext.declarative import (declarative_base, declared_attr,
+        AbstractConcreteBase)
+
+    Base = declarative_base()
+
+    class Something(Base):
+        __tablename__ = u'something'
+        id = Column(Integer, primary_key=True)
+
+
+    class Abstract(AbstractConcreteBase, Base):
+        id = Column(Integer, primary_key=True)
+
+        @declared_attr
+        def something_id(cls):
+            return Column(ForeignKey(Something.id))
+
+        @declared_attr
+        def something(cls):
+            return relationship(Something)
+
+
+    class Concrete(Abstract):
+        __tablename__ = u'cca'
+        __mapper_args__ = {'polymorphic_identity': 'cca', 'concrete': True}
+
+
+The above mapping will set up a table ``cca`` with both an ``id`` and
+a ``something_id`` column, and ``Concrete`` will also have a relationship
+``something``.  The new feature is that ``Abstract`` will also have an
+independently configured relationship ``something`` that builds against
+the polymorphic union of the base.
+
+:ticket:`3150` :ticket:`2670` :ticket:`3149` :ticket:`2952` :ticket:`3050`
+
 .. _feature_3034:
 
 Select/Query LIMIT / OFFSET may be specified as an arbitrary SQL expression
@@ -50,6 +185,84 @@ 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.
 
+.. _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`
+
+.. _feature_2891:
+
+Postgresql Dialect reflects Materialized Views, Foreign Tables
+--------------------------------------------------------------
+
+Changes are as follows:
+
+* the :class:`Table` construct with ``autoload=True`` will now match a name
+  that exists in the database as a materialized view or foriegn table.
+
+* :meth:`.Inspector.get_view_names` will return plain and materialized view
+  names.
+
+* :meth:`.Inspector.get_table_names` does **not** change for Postgresql, it
+  continues to return only the names of plain tables.
+
+* A new method :meth:`.PGInspector.get_foreign_table_names` is added which
+  will return the names of tables that are specifically marked as "foreign"
+  in the Postgresql schema tables.
+
+The change to reflection involves adding ``'m'`` and ``'f'`` to the list
+of qualifiers we use when querying ``pg_class.relkind``, but this change
+is new in 1.0.0 to avoid any backwards-incompatible surprises for those
+running 0.9 in production.
+
+:ticket:`2891`
+
+.. _feature_gh134:
+
+Postgresql FILTER keyword
+-------------------------
+
+The SQL standard FILTER keyword for aggregate functions is now supported
+by Postgresql as of 9.4.  SQLAlchemy allows this using
+:meth:`.FunctionElement.filter`::
+
+    func.count(1).filter(True)
+
+.. seealso::
+
+    :meth:`.FunctionElement.filter`
+
+    :class:`.FunctionFilter`
+
 .. _feature_3184:
 
 UniqueConstraint is now part of the Table reflection process
@@ -177,7 +390,6 @@ MacBookPro is 31 seconds on 0.9 and 26 seconds on 1.0, the extra time spent
 setting up very large memory buffers.
 
 
-
 .. _feature_3176:
 
 New KeyedTuple implementation dramatically faster
@@ -363,140 +575,6 @@ Renders::
 
 :ticket:`3177`
 
-.. _feature_3150:
-
-Improvements to declarative mixins, ``@declared_attr`` and related features
-----------------------------------------------------------------------------
-
-The declarative system in conjunction with :class:`.declared_attr` has been
-overhauled to support new capabilities.
-
-A function decorated with :class:`.declared_attr` is now called only **after**
-any mixin-based column copies are generated.  This means the function can
-call upon mixin-established columns and will receive a reference to the correct
-:class:`.Column` object::
-
-    class HasFooBar(object):
-        foobar = Column(Integer)
-
-        @declared_attr
-        def foobar_prop(cls):
-            return column_property('foobar: ' + cls.foobar)
-
-    class SomeClass(HasFooBar, Base):
-        __tablename__ = 'some_table'
-        id = Column(Integer, primary_key=True)
-
-Above, ``SomeClass.foobar_prop`` will be invoked against ``SomeClass``,
-and ``SomeClass.foobar`` will be the final :class:`.Column` object that is
-to be mapped to ``SomeClass``, as opposed to the non-copied object present
-directly on ``HasFooBar``, even though the columns aren't mapped yet.
-
-The :class:`.declared_attr` function now **memoizes** the value
-that's returned on a per-class basis, so that repeated calls to the same
-attribute will return the same value.  We can alter the example to illustrate
-this::
-
-    class HasFooBar(object):
-        @declared_attr
-        def foobar(cls):
-            return Column(Integer)
-
-        @declared_attr
-        def foobar_prop(cls):
-            return column_property('foobar: ' + cls.foobar)
-
-    class SomeClass(HasFooBar, Base):
-        __tablename__ = 'some_table'
-        id = Column(Integer, primary_key=True)
-
-Previously, ``SomeClass`` would be mapped with one particular copy of
-the ``foobar`` column, but the ``foobar_prop`` by calling upon ``foobar``
-a second time would produce a different column.   The value of
-``SomeClass.foobar`` is now memoized during declarative setup time, so that
-even before the attribute is mapped by the mapper, the interim column
-value will remain consistent no matter how many times the
-:class:`.declared_attr` is called upon.
-
-The two behaviors above should help considerably with declarative definition
-of many types of mapper properties that derive from other attributes, where
-the :class:`.declared_attr` function is called upon from other
-:class:`.declared_attr` functions locally present before the class is
-actually mapped.
-
-For a pretty slim edge case where one wishes to build a declarative mixin
-that establishes distinct columns per subclass, a new modifier
-:attr:`.declared_attr.cascading` is added.  With this modifier, the
-decorated function will be invoked individually for each class in the
-mapped inheritance hierarchy.  While this is already the behavior for
-special attributes such as ``__table_args__`` and ``__mapper_args__``,
-for columns and other properties the behavior by default assumes that attribute
-is affixed to the base class only, and just inherited from subclasses.
-With :attr:`.declared_attr.cascading`, individual behaviors can be
-applied::
-
-    class HasSomeAttribute(object):
-        @declared_attr.cascading
-        def some_id(cls):
-            if has_inherited_table(cls):
-                return Column(ForeignKey('myclass.id'), primary_key=True)
-            else:
-                return Column(Integer, primary_key=True)
-
-            return Column('id', Integer, primary_key=True)
-
-    class MyClass(HasSomeAttribute, Base):
-        ""
-        # ...
-
-    class MySubClass(MyClass):
-        ""
-        # ...
-
-.. seealso::
-
-    :ref:`mixin_inheritance_columns`
-
-Finally, the :class:`.AbstractConcreteBase` class has been reworked
-so that a relationship or other mapper property can be set up inline
-on the abstract base::
-
-    from sqlalchemy import Column, Integer, ForeignKey
-    from sqlalchemy.orm import relationship
-    from sqlalchemy.ext.declarative import (declarative_base, declared_attr,
-        AbstractConcreteBase)
-
-    Base = declarative_base()
-
-    class Something(Base):
-        __tablename__ = u'something'
-        id = Column(Integer, primary_key=True)
-
-
-    class Abstract(AbstractConcreteBase, Base):
-        id = Column(Integer, primary_key=True)
-
-        @declared_attr
-        def something_id(cls):
-            return Column(ForeignKey(Something.id))
-
-        @declared_attr
-        def something(cls):
-            return relationship(Something)
-
-
-    class Concrete(Abstract):
-        __tablename__ = u'cca'
-        __mapper_args__ = {'polymorphic_identity': 'cca', 'concrete': True}
-
-
-The above mapping will set up a table ``cca`` with both an ``id`` and
-a ``something_id`` column, and ``Concrete`` will also have a relationship
-``something``.  The new feature is that ``Abstract`` will also have an
-independently configured relationship ``something`` that builds against
-the polymorphic union of the base.
-
-:ticket:`3150` :ticket:`2670` :ticket:`3149` :ticket:`2952` :ticket:`3050`
 
 .. _bug_3188:
 
@@ -1021,84 +1099,6 @@ A :class:`.Table` can be set up for reflection by passing
 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`
-
-.. _feature_2891:
-
-Postgresql Dialect reflects Materialized Views, Foreign Tables
---------------------------------------------------------------
-
-Changes are as follows:
-
-* the :class:`Table` construct with ``autoload=True`` will now match a name
-  that exists in the database as a materialized view or foriegn table.
-
-* :meth:`.Inspector.get_view_names` will return plain and materialized view
-  names.
-
-* :meth:`.Inspector.get_table_names` does **not** change for Postgresql, it
-  continues to return only the names of plain tables.
-
-* A new method :meth:`.PGInspector.get_foreign_table_names` is added which
-  will return the names of tables that are specifically marked as "foreign"
-  in the Postgresql schema tables.
-
-The change to reflection involves adding ``'m'`` and ``'f'`` to the list
-of qualifiers we use when querying ``pg_class.relkind``, but this change
-is new in 1.0.0 to avoid any backwards-incompatible surprises for those
-running 0.9 in production.
-
-:ticket:`2891`
-
-.. _feature_gh134:
-
-Postgresql FILTER keyword
--------------------------
-
-The SQL standard FILTER keyword for aggregate functions is now supported
-by Postgresql as of 9.4.  SQLAlchemy allows this using
-:meth:`.FunctionElement.filter`::
-
-    func.count(1).filter(True)
-
-.. seealso::
-
-    :meth:`.FunctionElement.filter`
-
-    :class:`.FunctionFilter`
-
 
 MySQL internal "no such table" exceptions not passed to event handlers
 ----------------------------------------------------------------------