summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/sql')
-rw-r--r--lib/sqlalchemy/sql/compiler.py42
-rw-r--r--lib/sqlalchemy/sql/naming.py43
-rw-r--r--lib/sqlalchemy/sql/schema.py37
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::