diff options
Diffstat (limited to 'lib/sqlalchemy/sql')
-rw-r--r-- | lib/sqlalchemy/sql/compiler.py | 42 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/naming.py | 43 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/schema.py | 37 |
3 files changed, 85 insertions, 37 deletions
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index 27ee4afc6..459e0ba2c 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -2621,17 +2621,7 @@ class DDLCompiler(Compiled): else: schema_name = None - ident = index.name - if isinstance(ident, elements._truncated_label): - max_ = self.dialect.max_index_name_length or \ - self.dialect.max_identifier_length - if len(ident) > max_: - ident = ident[0:max_ - 8] + \ - "_" + util.md5_hex(ident)[-4:] - else: - self.dialect.validate_identifier(ident) - - index_name = self.preparer.quote(ident) + index_name = self.preparer.format_index(index) if schema_name: index_name = schema_name + "." + index_name @@ -3162,11 +3152,31 @@ class IdentifierPreparer(object): if isinstance(constraint.name, elements._defer_name): name = naming._constraint_name_for_table( constraint, constraint.table) - if name: - return self.quote(name) - elif isinstance(constraint.name, elements._defer_none_name): - return None - return self.quote(constraint.name) + + if name is None: + if isinstance(constraint.name, elements._defer_none_name): + return None + else: + name = constraint.name + else: + name = constraint.name + + if isinstance(name, elements._truncated_label): + if constraint.__visit_name__ == 'index': + max_ = self.dialect.max_index_name_length or \ + self.dialect.max_identifier_length + else: + max_ = self.dialect.max_identifier_length + if len(name) > max_: + name = name[0:max_ - 8] + \ + "_" + util.md5_hex(name)[-4:] + else: + self.dialect.validate_identifier(name) + + return self.quote(name) + + def format_index(self, index): + return self.format_constraint(index) def format_table(self, table, use_schema=True, name=None): """Prepare a quoted table and schema name.""" diff --git a/lib/sqlalchemy/sql/naming.py b/lib/sqlalchemy/sql/naming.py index 533429333..0107ce724 100644 --- a/lib/sqlalchemy/sql/naming.py +++ b/lib/sqlalchemy/sql/naming.py @@ -48,6 +48,12 @@ class ConventionDict(object): self.const.name = None return self._const_name + def _key_column_X_key(self, idx): + # note this method was missing before + # [ticket:3989], meaning tokens like ``%(column_0_key)s`` weren't + # working even though documented. + return self._column_X(idx).key + def _key_column_X_name(self, idx): return self._column_X(idx).name @@ -65,12 +71,10 @@ class ConventionDict(object): def _key_referred_column_X_name(self, idx): fk = self.const.elements[idx] - refs = fk.target_fullname.split(".") - if len(refs) == 3: - refschema, reftable, refcol = refs - else: - reftable, refcol = refs - return refcol + # note that before [ticket:3989], this method was returning + # the specification for the :class:`.ForeignKey` itself, which normally + # would be using the ``.key`` of the column, not the name. + return fk.column.name def __getitem__(self, key): if key in self.convention: @@ -78,13 +82,30 @@ class ConventionDict(object): elif hasattr(self, '_key_%s' % key): return getattr(self, '_key_%s' % key)() else: - col_template = re.match(r".*_?column_(\d+)_.+", key) + col_template = re.match(r".*_?column_(\d+)(_?N)?_.+", key) if col_template: idx = col_template.group(1) - attr = "_key_" + key.replace(idx, "X") - idx = int(idx) - if hasattr(self, attr): - return getattr(self, attr)(idx) + multiples = col_template.group(2) + + if multiples: + if self._is_fk: + elems = self.const.elements + else: + elems = list(self.const.columns) + tokens = [] + for idx, elem in enumerate(elems): + attr = "_key_" + key.replace("0" + multiples, "X") + try: + tokens.append(getattr(self, attr)(idx)) + except AttributeError: + raise KeyError(key) + sep = "_" if multiples.startswith("_") else "" + return sep.join(tokens) + else: + attr = "_key_" + key.replace(idx, "X") + idx = int(idx) + if hasattr(self, attr): + return getattr(self, attr)(idx) raise KeyError(key) _prefix_dict = { diff --git a/lib/sqlalchemy/sql/schema.py b/lib/sqlalchemy/sql/schema.py index 88050b87e..e37c703eb 100644 --- a/lib/sqlalchemy/sql/schema.py +++ b/lib/sqlalchemy/sql/schema.py @@ -3654,15 +3654,29 @@ class MetaData(SchemaItem): * ``%(column_0_name)s`` - the name of the :class:`.Column` at index position "0" within the constraint. - * ``%(column_0_label)s`` - the label of the :class:`.Column` at - index position "0", e.g. :attr:`.Column.label` - - * ``%(column_0_key)s`` - the key of the :class:`.Column` at - index position "0", e.g. :attr:`.Column.key` - - * ``%(referred_column_0_name)s`` - the name of a :class:`.Column` - at index position "0" referenced by a - :class:`.ForeignKeyConstraint`. + * ``%(column_0N_name)s`` - the name of all :class:`.Column` + objects in order within the constraint, joined without a + separator. + + * ``%(column_0_N_name)s`` - the name of all :class:`.Column` + objects in order within the constraint, joined with an + underscore as a separator. + + * ``%(column_0_label)s``, ``%(column_0N_label)s``, + ``%(column_0_N_label)s`` - the label of either the zeroth + :class:`.Column` or all :class:`.Columns`, separated with + or without an underscore + + * ``%(column_0_key)s``, ``%(column_0N_key)s``, + ``%(column_0_N_key)s`` - the key of either the zeroth + :class:`.Column` or all :class:`.Columns`, separated with + or without an underscore + + * ``%(referred_column_0_name)s``, ``%(referred_column_0N_name)s`` + ``%(referred_column_0_N_name)s``, ``%(referred_column_0_key)s``, + ``%(referred_column_0N_key)s``, ... column tokens which + render the names/keys/labels of columns that are referenced + by a :class:`.ForeignKeyConstraint`. * ``%(constraint_name)s`` - a special key that refers to the existing name given to the constraint. When this key is @@ -3675,7 +3689,10 @@ class MetaData(SchemaItem): it along with a ``fn(constraint, table)`` callable to the naming_convention dictionary. - .. versionadded:: 0.9.2 + .. versionadded:: 1.3.0 - added new ``%(column_0N_name)s``, + ``%(column_0_N_name)s``, and related tokens that produce + concatenations of names, keys, or labels for all columns referred + to by a given constraint. .. seealso:: |