summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/schema.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/schema.py')
-rw-r--r--lib/sqlalchemy/schema.py83
1 files changed, 47 insertions, 36 deletions
diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py
index 5fa84063f..32ea2b5ee 100644
--- a/lib/sqlalchemy/schema.py
+++ b/lib/sqlalchemy/schema.py
@@ -769,13 +769,15 @@ class ForeignKey(SchemaItem):
__visit_name__ = 'foreign_key'
- def __init__(self, column, constraint=None, use_alter=False, name=None, onupdate=None, ondelete=None, deferrable=None, initially=None):
+ def __init__(self, column, constraint=None, use_alter=False, name=None, onupdate=None, ondelete=None, deferrable=None, initially=None, link_to_name=False):
"""
Construct a column-level FOREIGN KEY.
:param column: A single target column for the key relationship. A :class:`Column`
- object or a column name as a string: ``tablename.columnname`` or
- ``schema.tablename.columnname``.
+ object or a column name as a string: ``tablename.columnkey`` or
+ ``schema.tablename.columnkey``. ``columnkey`` is the ``key`` which has been assigned
+ to the column (defaults to the column name itself), unless ``link_to_name`` is ``True``
+ in which case the rendered name of the column is used.
:param constraint: Optional. A parent :class:`ForeignKeyConstraint` object. If not
supplied, a :class:`ForeignKeyConstraint` will be automatically created
@@ -797,7 +799,10 @@ class ForeignKey(SchemaItem):
:param initially: Optional string. If set, emit INITIALLY <value> when issuing DDL
for this constraint.
-
+
+ :param link_to_name: if True, the string name given in ``column`` is the rendered
+ name of the referenced column, not its locally assigned ``key``.
+
:param use_alter: If True, do not emit this key as part of the CREATE TABLE
definition. Instead, use ALTER TABLE after table creation to add
the key. Useful for circular dependencies.
@@ -812,6 +817,7 @@ class ForeignKey(SchemaItem):
self.ondelete = ondelete
self.deferrable = deferrable
self.initially = initially
+ self.link_to_name = link_to_name
def __repr__(self):
return "ForeignKey(%r)" % self._get_colspec()
@@ -877,21 +883,29 @@ class ForeignKey(SchemaItem):
"foreign key" % tname)
table = Table(tname, parenttable.metadata,
mustexist=True, schema=schema)
- try:
- if colname is None:
- # colname is None in the case that ForeignKey argument
- # was specified as table name only, in which case we
- # match the column name to the same column on the
- # parent.
- key = self.parent
- _column = table.c[self.parent.key]
- else:
- _column = table.c[colname]
- except KeyError, e:
+
+ _column = None
+ if colname is None:
+ # colname is None in the case that ForeignKey argument
+ # was specified as table name only, in which case we
+ # match the column name to the same column on the
+ # parent.
+ key = self.parent
+ _column = table.c.get(self.parent.key, None)
+ elif self.link_to_name:
+ key = colname
+ for c in table.c:
+ if c.name == colname:
+ _column = c
+ else:
+ key = colname
+ _column = table.c.get(colname, None)
+
+ if not _column:
raise exc.NoReferencedColumnError(
"Could not create ForeignKey '%s' on table '%s': "
"table '%s' has no column named '%s'" % (
- self._colspec, parenttable.name, table.name, str(e)))
+ self._colspec, parenttable.name, table.name, key))
elif hasattr(self._colspec, '__clause_element__'):
_column = self._colspec.__clause_element__()
@@ -1191,50 +1205,47 @@ class ForeignKeyConstraint(Constraint):
"""
__visit_name__ = 'foreign_key_constraint'
- def __init__(self, columns, refcolumns, name=None, onupdate=None, ondelete=None, use_alter=False, deferrable=None, initially=None):
+ def __init__(self, columns, refcolumns, name=None, onupdate=None, ondelete=None, use_alter=False, deferrable=None, initially=None, link_to_name=False):
"""Construct a composite-capable FOREIGN KEY.
- columns
- A sequence of local column names. The named columns must be defined
- and present in the parent Table.
+ :param columns: A sequence of local column names. The named columns must be defined
+ and present in the parent Table. The names should match the ``key`` given
+ to each column (defaults to the name) unless ``link_to_name`` is True.
- refcolumns
- A sequence of foreign column names or Column objects. The columns
+ :param refcolumns: A sequence of foreign column names or Column objects. The columns
must all be located within the same Table.
- name
- Optional, the in-database name of the key.
+ :param name: Optional, the in-database name of the key.
- onupdate
- Optional string. If set, emit ON UPDATE <value> when issuing DDL
+ :param onupdate: Optional string. If set, emit ON UPDATE <value> when issuing DDL
for this constraint. Typical values include CASCADE, DELETE and
RESTRICT.
- ondelete
- Optional string. If set, emit ON DELETE <value> when issuing DDL
+ :param ondelete: Optional string. If set, emit ON DELETE <value> when issuing DDL
for this constraint. Typical values include CASCADE, DELETE and
RESTRICT.
- deferrable
- Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when
+ :param deferrable: Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when
issuing DDL for this constraint.
- initially
- Optional string. If set, emit INITIALLY <value> when issuing DDL
+ :param initially: Optional string. If set, emit INITIALLY <value> when issuing DDL
for this constraint.
- use_alter
- If True, do not emit this key as part of the CREATE TABLE
+ :param link_to_name: if True, the string name given in ``column`` is the rendered
+ name of the referenced column, not its locally assigned ``key``.
+
+ :param use_alter: If True, do not emit this key as part of the CREATE TABLE
definition. Instead, use ALTER TABLE after table creation to add
the key. Useful for circular dependencies.
+
"""
-
super(ForeignKeyConstraint, self).__init__(name, deferrable, initially)
self.__colnames = columns
self.__refcolnames = refcolumns
self.elements = util.OrderedSet()
self.onupdate = onupdate
self.ondelete = ondelete
+ self.link_to_name = link_to_name
if self.name is None and use_alter:
raise exc.ArgumentError("Alterable ForeignKey/ForeignKeyConstraint requires a name")
self.use_alter = use_alter
@@ -1247,7 +1258,7 @@ class ForeignKeyConstraint(Constraint):
self.append_element(c, r)
def append_element(self, col, refcol):
- fk = ForeignKey(refcol, constraint=self, name=self.name, onupdate=self.onupdate, ondelete=self.ondelete, use_alter=self.use_alter)
+ fk = ForeignKey(refcol, constraint=self, name=self.name, onupdate=self.onupdate, ondelete=self.ondelete, use_alter=self.use_alter, link_to_name=self.link_to_name)
fk._set_parent(self.table.c[col])
self._append_fk(fk)