123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- # sqlalchemy/naming.py
- # Copyright (C) 2005-2017 the SQLAlchemy authors and contributors
- # <see AUTHORS file>
- #
- # This module is part of SQLAlchemy and is released under
- # the MIT License: http://www.opensource.org/licenses/mit-license.php
- """Establish constraint and index naming conventions.
- """
- from .schema import Constraint, ForeignKeyConstraint, PrimaryKeyConstraint, \
- UniqueConstraint, CheckConstraint, Index, Table, Column
- from .. import event, events
- from .. import exc
- from .elements import _truncated_label, _defer_name, _defer_none_name, conv
- import re
- 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.name
- def _key_table_name(self):
- return self.table.name
- def _column_X(self, idx):
- if self._is_fk:
- fk = self.const.elements[idx]
- return fk.parent
- else:
- return list(self.const.columns)[idx]
- def _key_constraint_name(self):
- if isinstance(self._const_name, (type(None), _defer_none_name)):
- raise exc.InvalidRequestError(
- "Naming convention including "
- "%(constraint_name)s token requires that "
- "constraint is explicitly named."
- )
- if not isinstance(self._const_name, conv):
- self.const.name = None
- return self._const_name
- def _key_column_X_name(self, idx):
- return self._column_X(idx).name
- def _key_column_X_label(self, idx):
- return self._column_X(idx)._label
- def _key_referred_table_name(self):
- fk = self.const.elements[0]
- refs = fk.target_fullname.split(".")
- if len(refs) == 3:
- refschema, reftable, refcol = refs
- else:
- reftable, refcol = refs
- return reftable
- 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
- def __getitem__(self, key):
- if key in self.convention:
- return self.convention[key](self.const, self.table)
- elif hasattr(self, '_key_%s' % key):
- return getattr(self, '_key_%s' % key)()
- else:
- col_template = re.match(r".*_?column_(\d+)_.+", 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)
- raise KeyError(key)
- _prefix_dict = {
- Index: "ix",
- PrimaryKeyConstraint: "pk",
- CheckConstraint: "ck",
- UniqueConstraint: "uq",
- ForeignKeyConstraint: "fk"
- }
- def _get_convention(dict_, key):
- for super_ in key.__mro__:
- if super_ in _prefix_dict and _prefix_dict[super_] in dict_:
- return dict_[_prefix_dict[super_]]
- elif super_ in dict_:
- return dict_[super_]
- else:
- return None
- def _constraint_name_for_table(const, table):
- metadata = table.metadata
- convention = _get_convention(metadata.naming_convention, type(const))
- if isinstance(const.name, conv):
- return const.name
- elif convention is not None and \
- not isinstance(const.name, conv) and \
- (
- const.name is None or
- "constraint_name" in convention or
- isinstance(const.name, _defer_name)):
- return conv(
- convention % ConventionDict(const, table,
- metadata.naming_convention)
- )
- elif isinstance(convention, _defer_none_name):
- return None
- @event.listens_for(Constraint, "after_parent_attach")
- @event.listens_for(Index, "after_parent_attach")
- def _constraint_name(const, table):
- if isinstance(table, Column):
- # for column-attached constraint, set another event
- # to link the column attached to the table as this constraint
- # associated with the table.
- event.listen(table, "after_parent_attach",
- lambda col, table: _constraint_name(const, table)
- )
- elif isinstance(table, Table):
- if isinstance(const.name, (conv, _defer_name)):
- return
- newname = _constraint_name_for_table(const, table)
- if newname is not None:
- const.name = newname
|