summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql/expression.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2009-08-08 22:21:02 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2009-08-08 22:21:02 +0000
commita04da2a417726055da205bd604a1993eb4fd9887 (patch)
tree1b106d1a624599cdfdd62abcacbee8948b22da3c /lib/sqlalchemy/sql/expression.py
parentcbdccb7fd26da432ddf43ae1820656505acad37e (diff)
downloadsqlalchemy-a04da2a417726055da205bd604a1993eb4fd9887.tar.gz
- added **kw to ClauseElement.compare(), so that we can smarten up the "use_get" operation
- many-to-one relation to a joined-table subclass now uses get() for a simple load (known as the "use_get" condition), i.e. Related->Sub(Base), without the need to redefine the primaryjoin condition in terms of the base table. [ticket:1186] - specifying a foreign key with a declarative column, i.e. ForeignKey(MyRelatedClass.id) doesn't break the "use_get" condition from taking place [ticket:1492]
Diffstat (limited to 'lib/sqlalchemy/sql/expression.py')
-rw-r--r--lib/sqlalchemy/sql/expression.py56
1 files changed, 44 insertions, 12 deletions
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py
index 960fc0310..8c6877dbd 100644
--- a/lib/sqlalchemy/sql/expression.py
+++ b/lib/sqlalchemy/sql/expression.py
@@ -1101,11 +1101,15 @@ class ClauseElement(Visitable):
bind._convert_to_unique()
return cloned_traverse(self, {}, {'bindparam':visit_bindparam})
- def compare(self, other):
+ def compare(self, other, **kw):
"""Compare this ClauseElement to the given ClauseElement.
Subclasses should override the default behavior, which is a
straight identity comparison.
+
+ **kw are arguments consumed by subclass compare() methods and
+ may be used to modify the criteria for comparison.
+ (see :class:`ColumnElement`)
"""
return self is other
@@ -1697,6 +1701,34 @@ class ColumnElement(ClauseElement, _CompareMixin):
selectable.columns[name] = co
return co
+ def compare(self, other, use_proxies=False, equivalents=None, **kw):
+ """Compare this ColumnElement to another.
+
+ Special arguments understood:
+
+ :param use_proxies: when True, consider two columns that
+ share a common base column as equivalent (i.e. shares_lineage())
+
+ :param equivalents: a dictionary of columns as keys mapped to sets
+ of columns. If the given "other" column is present in this dictionary,
+ if any of the columns in the correponding set() pass the comparison
+ test, the result is True. This is used to expand the comparison to
+ other columns that may be known to be equivalent to this one via
+ foreign key or other criterion.
+
+ """
+ to_compare = (other, )
+ if equivalents and other in equivalents:
+ to_compare = equivalents[other].union(to_compare)
+
+ for oth in to_compare:
+ if use_proxies and self.shares_lineage(oth):
+ return True
+ elif oth is self:
+ return True
+ else:
+ return False
+
@util.memoized_property
def anon_label(self):
"""provides a constant 'anonymous label' for this ColumnElement.
@@ -2109,7 +2141,7 @@ class _BindParamClause(ColumnElement):
else:
return obj.type
- def compare(self, other):
+ def compare(self, other, **kw):
"""Compare this ``_BindParamClause`` to the given clause.
Since ``compare()`` is meant to compare statement syntax, this
@@ -2274,16 +2306,16 @@ class ClauseList(ClauseElement):
else:
return self
- def compare(self, other):
+ def compare(self, other, **kw):
"""Compare this ``ClauseList`` to the given ``ClauseList``,
including a comparison of all the clause items.
"""
if not isinstance(other, ClauseList) and len(self.clauses) == 1:
- return self.clauses[0].compare(other)
+ return self.clauses[0].compare(other, **kw)
elif isinstance(other, ClauseList) and len(self.clauses) == len(other.clauses):
for i in range(0, len(self.clauses)):
- if not self.clauses[i].compare(other.clauses[i]):
+ if not self.clauses[i].compare(other.clauses[i], **kw):
return False
else:
return self.operator == other.operator
@@ -2473,14 +2505,14 @@ class _UnaryExpression(ColumnElement):
def get_children(self, **kwargs):
return self.element,
- def compare(self, other):
+ def compare(self, other, **kw):
"""Compare this ``_UnaryExpression`` against the given ``ClauseElement``."""
return (
isinstance(other, _UnaryExpression) and
self.operator == other.operator and
self.modifier == other.modifier and
- self.element.compare(other.element)
+ self.element.compare(other.element, **kw)
)
def _negate(self):
@@ -2528,19 +2560,19 @@ class _BinaryExpression(ColumnElement):
def get_children(self, **kwargs):
return self.left, self.right
- def compare(self, other):
+ def compare(self, other, **kw):
"""Compare this ``_BinaryExpression`` against the given ``_BinaryExpression``."""
return (
isinstance(other, _BinaryExpression) and
self.operator == other.operator and
(
- self.left.compare(other.left) and
- self.right.compare(other.right) or
+ self.left.compare(other.left, **kw) and
+ self.right.compare(other.right, **kw) or
(
operators.is_commutative(self.operator) and
- self.left.compare(other.right) and
- self.right.compare(other.left)
+ self.left.compare(other.right, **kw) and
+ self.right.compare(other.left, **kw)
)
)
)