summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2009-12-08 01:54:08 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2009-12-08 01:54:08 +0000
commit2305e22d6bde2161f5bee25514f0a8444cce8416 (patch)
tree54d183a1b92a4473636051554b0c1b28b73e2f98 /lib/sqlalchemy
parentacb2faedcd1502248e6db46228112133094dd3cf (diff)
downloadsqlalchemy-2305e22d6bde2161f5bee25514f0a8444cce8416.tar.gz
- backport of r6540
- The "use get" behavior of many-to-one relations, i.e. that a lazy load will fallback to the possibly cached query.get() value, now works across join conditions where the two compared types are not exactly the same class, but share the same "affinity" - i.e. Integer and SmallInteger. Also allows combinations of reflected and non-reflected types to work with 0.5 style type reflection, such as PGText/Text (note 0.6 reflects types as their generic versions). [ticket:1556] - types now support an "affinity comparison" operation, i.e. that an Integer/SmallInteger are "compatible", or a Text/String, PickleType/Binary, etc. Part of [ticket:1556].
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/orm/strategies.py1
-rw-r--r--lib/sqlalchemy/sql/expression.py15
-rw-r--r--lib/sqlalchemy/types.py17
3 files changed, 23 insertions, 10 deletions
diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py
index 68669a150..01af1de92 100644
--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -372,7 +372,6 @@ class LazyLoader(AbstractRelationLoader):
# determine if our "lazywhere" clause is the same as the mapper's
# get() clause. then we can just use mapper.get()
- #from sqlalchemy.orm import query
self.use_get = not self.uselist and self.mapper._get_clause[0].compare(self.__lazywhere)
if self.use_get:
self.logger.info("%s will use query.get() to optimize instance loads" % self)
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py
index 83897ef05..cf08ec195 100644
--- a/lib/sqlalchemy/sql/expression.py
+++ b/lib/sqlalchemy/sql/expression.py
@@ -2003,15 +2003,12 @@ class _BindParamClause(ColumnElement):
else:
return obj.type
- def compare(self, other):
- """Compare this ``_BindParamClause`` to the given clause.
-
- Since ``compare()`` is meant to compare statement syntax, this
- method returns True if the two ``_BindParamClauses`` have just
- the same type.
-
- """
- return isinstance(other, _BindParamClause) and other.type.__class__ == self.type.__class__ and self.value == other.value
+ def compare(self, other, **kw):
+ """Compare this ``_BindParamClause`` to the given clause."""
+
+ return isinstance(other, _BindParamClause) and \
+ self.type._compare_type_affinity(other.type) and \
+ self.value == other.value
def __getstate__(self):
"""execute a deferred value for serialization purposes."""
diff --git a/lib/sqlalchemy/types.py b/lib/sqlalchemy/types.py
index a03d6137d..8e6accdbf 100644
--- a/lib/sqlalchemy/types.py
+++ b/lib/sqlalchemy/types.py
@@ -81,6 +81,19 @@ class AbstractType(object):
By default, returns the operator unchanged.
"""
return op
+
+ @util.memoized_property
+ def _type_affinity(self):
+ """Return a rudimental 'affinity' value expressing the general class of type."""
+
+ for i, t in enumerate(self.__class__.__mro__):
+ if t is TypeEngine:
+ return self.__class__.__mro__[i - 1]
+ else:
+ return self.__class__
+
+ def _compare_type_affinity(self, other):
+ return self._type_affinity is other._type_affinity
def __repr__(self):
return "%s(%s)" % (
@@ -236,6 +249,10 @@ class TypeDecorator(AbstractType):
self._impl_dict[dialect] = tt
return tt
+ @util.memoized_property
+ def _type_affinity(self):
+ return self.impl._type_affinity
+
def load_dialect_impl(self, dialect):
"""Loads the dialect-specific implementation of this type.