summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-06-21 15:39:48 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2012-06-21 15:39:48 -0400
commit2272f30af435c5283157724bbb16fb0a573159ce (patch)
treea74af95302914877bbc3a81f23cca15bdec1d731
parent81eefb2f13a9c854e1dcd924550d0c36553e930a (diff)
downloadsqlalchemy-2272f30af435c5283157724bbb16fb0a573159ce.tar.gz
- [feature] Added "MATCH" clause to ForeignKey,
ForeignKeyConstraint, courtesy Ryan Kelly. [ticket:2502]
-rw-r--r--CHANGES4
-rw-r--r--lib/sqlalchemy/schema.py24
-rw-r--r--lib/sqlalchemy/sql/compiler.py7
-rw-r--r--test/sql/test_constraints.py21
4 files changed, 50 insertions, 6 deletions
diff --git a/CHANGES b/CHANGES
index 757972a75..7e59d638a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -199,6 +199,10 @@ underneath "0.7.xx".
that aren't in the target table is now an exception.
[ticket:2415]
+ - [feature] Added "MATCH" clause to ForeignKey,
+ ForeignKeyConstraint, courtesy Ryan Kelly.
+ [ticket:2502]
+
- [feature] select() features a correlate_except()
method, auto correlates all selectables except those
passed.
diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py
index 231da7d03..d50b8af2a 100644
--- a/lib/sqlalchemy/schema.py
+++ b/lib/sqlalchemy/schema.py
@@ -1191,7 +1191,7 @@ class ForeignKey(SchemaItem):
def __init__(self, column, _constraint=None, use_alter=False, name=None,
onupdate=None, ondelete=None, deferrable=None,
schema=None,
- initially=None, link_to_name=False):
+ initially=None, link_to_name=False, match=None):
"""
Construct a column-level FOREIGN KEY.
@@ -1236,6 +1236,10 @@ class ForeignKey(SchemaItem):
generated/dropped externally from the CREATE TABLE/ DROP TABLE
statement. See that classes' constructor for details.
+ :param match: Optional string. If set, emit MATCH <value> when issuing
+ DDL for this constraint. Typical values include SIMPLE, PARTIAL
+ and FULL.
+
"""
self._colspec = column
@@ -1255,6 +1259,7 @@ class ForeignKey(SchemaItem):
self.deferrable = deferrable
self.initially = initially
self.link_to_name = link_to_name
+ self.match = match
def __repr__(self):
return "ForeignKey(%r)" % self._get_colspec()
@@ -1283,7 +1288,8 @@ class ForeignKey(SchemaItem):
ondelete=self.ondelete,
deferrable=self.deferrable,
initially=self.initially,
- link_to_name=self.link_to_name
+ link_to_name=self.link_to_name,
+ match=self.match
)
fk.dispatch._update(self.dispatch)
return fk
@@ -1445,6 +1451,7 @@ class ForeignKey(SchemaItem):
[], [], use_alter=self.use_alter, name=self.name,
onupdate=self.onupdate, ondelete=self.ondelete,
deferrable=self.deferrable, initially=self.initially,
+ match=self.match,
)
self.constraint._elements[self.parent] = self
self.constraint._set_parent_with_dispatch(table)
@@ -2031,7 +2038,7 @@ class ForeignKeyConstraint(Constraint):
def __init__(self, columns, refcolumns, name=None, onupdate=None,
ondelete=None, deferrable=None, initially=None, use_alter=False,
- link_to_name=False, table=None):
+ link_to_name=False, match=None, table=None):
"""Construct a composite-capable FOREIGN KEY.
:param columns: A sequence of local column names. The named columns
@@ -2072,6 +2079,10 @@ class ForeignKeyConstraint(Constraint):
This is normally used to generate/drop constraints on objects that
are mutually dependent on each other.
+ :param match: Optional string. If set, emit MATCH <value> when issuing
+ DDL for this constraint. Typical values include SIMPLE, PARTIAL
+ and FULL.
+
"""
super(ForeignKeyConstraint, self).\
__init__(name, deferrable, initially)
@@ -2082,6 +2093,7 @@ class ForeignKeyConstraint(Constraint):
if self.name is None and use_alter:
raise exc.ArgumentError("Alterable Constraint requires a name")
self.use_alter = use_alter
+ self.match = match
self._elements = util.OrderedDict()
@@ -2097,7 +2109,8 @@ class ForeignKeyConstraint(Constraint):
onupdate=self.onupdate,
ondelete=self.ondelete,
use_alter=self.use_alter,
- link_to_name=self.link_to_name
+ link_to_name=self.link_to_name,
+ match=self.match
)
if table is not None:
@@ -2153,7 +2166,8 @@ class ForeignKeyConstraint(Constraint):
use_alter=self.use_alter,
deferrable=self.deferrable,
initially=self.initially,
- link_to_name=self.link_to_name
+ link_to_name=self.link_to_name,
+ match=self.match
)
fkc.dispatch._update(self.dispatch)
return fkc
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index fd7e7d773..8a8c773f8 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -1726,6 +1726,7 @@ class DDLCompiler(engine.Compiled):
', '.join(preparer.quote(f.column.name, f.column.quote)
for f in constraint._elements.values())
)
+ text += self.define_constraint_match(constraint)
text += self.define_constraint_cascades(constraint)
text += self.define_constraint_deferrability(constraint)
return text
@@ -1765,6 +1766,12 @@ class DDLCompiler(engine.Compiled):
text += " INITIALLY %s" % constraint.initially
return text
+ def define_constraint_match(self, constraint):
+ text = ""
+ if constraint.match is not None:
+ text += " MATCH %s" % constraint.match
+ return text
+
class GenericTypeCompiler(engine.TypeCompiler):
def visit_CHAR(self, type_):
diff --git a/test/sql/test_constraints.py b/test/sql/test_constraints.py
index 546a14ca2..fcc6c085e 100644
--- a/test/sql/test_constraints.py
+++ b/test/sql/test_constraints.py
@@ -355,6 +355,25 @@ class ConstraintCompilationTest(fixtures.TestBase, AssertsCompiledSQL):
"(a) DEFERRABLE INITIALLY DEFERRED)",
)
+ def test_fk_match_clause(self):
+ t = Table('tbl', MetaData(),
+ Column('a', Integer),
+ Column('b', Integer,
+ ForeignKey('tbl.a', match="SIMPLE")))
+
+ self.assert_compile(
+ schema.CreateTable(t),
+ "CREATE TABLE tbl (a INTEGER, b INTEGER, "
+ "FOREIGN KEY(b) REFERENCES tbl "
+ "(a) MATCH SIMPLE)",
+ )
+
+ self.assert_compile(
+ schema.AddConstraint(list(t.foreign_keys)[0].constraint),
+ "ALTER TABLE tbl ADD FOREIGN KEY(b) "
+ "REFERENCES tbl (a) MATCH SIMPLE"
+ )
+
def test_deferrable_unique(self):
factory = lambda **kw: UniqueConstraint('b', **kw)
self._test_deferrable(factory)
@@ -554,4 +573,4 @@ class ConstraintCompilationTest(fixtures.TestBase, AssertsCompiledSQL):
)
c = CheckConstraint(t.c.a > t2.c.b)
assert c not in t.constraints
- assert c not in t2.constraints \ No newline at end of file
+ assert c not in t2.constraints