]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Added a new feature :func:`.schema.conv`, the purpose of which is to
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 12 Mar 2014 21:33:03 +0000 (17:33 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 12 Mar 2014 21:33:03 +0000 (17:33 -0400)
mark a constraint name as already having had a naming convention applied.
This token will be used by Alembic migrations as of Alembic 0.6.4
in order to render constraints in migration scripts with names marked
as already having been subject to a naming convention.
re: #2991

doc/build/changelog/changelog_09.rst
doc/build/core/constraints.rst
lib/sqlalchemy/schema.py
lib/sqlalchemy/sql/naming.py

index 20a0b656d1310b75565ae247ee83e5e757d518c5..10879e2cafdbf00551dd9ed2c0cfd197b035bc6c 100644 (file)
 .. changelog::
     :version: 0.9.4
 
+    .. change::
+        :tags: feature, sql
+
+        Added a new feature :func:`.schema.conv`, the purpose of which is to
+        mark a constraint name as already having had a naming convention applied.
+        This token will be used by Alembic migrations as of Alembic 0.6.4
+        in order to render constraints in migration scripts with names marked
+        as already having been subject to a naming convention.
+
     .. change::
         :tags: bug, sql
 
index 3979631b0980f7715324e9a8d0e6f5c6f5063c8f..580fbc0b630317d1d85c0eac62f64aacfd139072 100644 (file)
@@ -459,6 +459,7 @@ Constraints API
     :members:
     :inherited-members:
 
+.. autofunction:: sqlalchemy.schema.conv
 
 .. _schema_indexes:
 
index 9e647e595292233464c020840c480858c3a42aaf..8556272a62904693433b39bf65ab24e7d8ac598a 100644 (file)
@@ -37,6 +37,9 @@ from .sql.schema import (
     )
 
 
+from .sql.naming import conv
+
+
 from .sql.ddl import (
     DDL,
     CreateTable,
index 3ba7f510599371db0b451a8de91c515ca36c17c6..1c5fae19330142a47621ff56a9b7f59643451da0 100644 (file)
@@ -16,13 +16,54 @@ from .. import exc
 from .elements import _truncated_label
 import re
 
+class conv(_truncated_label):
+    """Mark a string indicating that a name has already been converted
+    by a naming convention.
+
+    This is a string subclass that indicates a name that should not be
+    subject to any further naming conventions.
+
+    E.g. when we create a :class:`.Constraint` using a naming convention
+    as follows::
+
+        m = MetaData(naming_convention={"ck": "ck_%(table_name)s_%(constraint_name)s"})
+        t = Table('t', m, Column('x', Integer),
+                        CheckConstraint('x > 5', name='x5'))
+
+    The name of the above constraint will be rendered as ``"ck_t_x5"``.  That is,
+    the existing name ``x5`` is used in the naming convention as the ``constraint_name``
+    token.
+
+    In some situations, such as in migration scripts, we may be rendering
+    the above :class:`.CheckConstraint` with a name that's already been
+    converted.  In order to make sure the name isn't double-modified, the
+    new name is applied using the :func:`.schema.conv` marker.  We can
+    use this explicitly as follows::
+
+
+        m = MetaData(naming_convention={"ck": "ck_%(table_name)s_%(constraint_name)s"})
+        t = Table('t', m, Column('x', Integer),
+                        CheckConstraint('x > 5', name=conv('ck_t_x5')))
+
+    Where above, the :func:`.schema.conv` marker indicates that the constraint
+    name here is final, and the name will render as ``"ck_t_x5"`` and not
+    ``"ck_t_ck_t_x5"``
+
+    .. versionadded:: 0.9.4
+
+    .. seealso::
+
+        :ref:`constraint_naming_conventions`
+
+    """
+
 class ConventionDict(object):
     def __init__(self, const, table, convention):
         self.const = const
         self._is_fk = isinstance(const, ForeignKeyConstraint)
         self.table = table
         self.convention = convention
-        self._const_name = const._orig_name = getattr(const, '_orig_name', const.name)
+        self._const_name = const.name
 
     def _key_table_name(self):
         return self.table.name
@@ -41,9 +82,8 @@ class ConventionDict(object):
                     "%(constraint_name)s token requires that "
                     "constraint is explicitly named."
                 )
-        # they asked for a name that's derived from the existing
-        # name, so set the existing name to None
-        self.const.name = None
+        if not isinstance(self._const_name, conv):
+            self.const.name = None
         return self._const_name
 
     def _key_column_X_name(self, idx):
@@ -118,7 +158,7 @@ def _constraint_name(const, table):
         metadata = table.metadata
         convention = _get_convention(metadata.naming_convention, type(const))
         if convention is not None:
-            newname = _truncated_label(
+            newname = conv(
                         convention % ConventionDict(const, table, metadata.naming_convention)
                         )
             if const.name is None: