summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/util
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2015-05-06 17:07:24 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2015-05-06 17:07:24 -0400
commit1b120563905e29f9769fd6d2ce39922d15cebf7f (patch)
treef987041976e8aa32b8f3e554cf1c50ba1fec55b2 /lib/sqlalchemy/util
parent5c852409219e18fb3d3b1403bfc872b3fe99f802 (diff)
downloadsqlalchemy-1b120563905e29f9769fd6d2ce39922d15cebf7f.tar.gz
- Fixed unexpected-use regression where in the odd case that the
primaryjoin of a relationship involved comparison to an unhashable type such as an HSTORE, lazy loads would fail due to a hash-oriented check on the statement parameters, modified in 1.0 as a result of :ticket:`3061` to use hashing and modified in :ticket:`3368` to occur in cases more common than "load on pending". The values are now checked for the ``__hash__`` attribute beforehand. fixes #3416
Diffstat (limited to 'lib/sqlalchemy/util')
-rw-r--r--lib/sqlalchemy/util/__init__.py2
-rw-r--r--lib/sqlalchemy/util/_collections.py13
2 files changed, 14 insertions, 1 deletions
diff --git a/lib/sqlalchemy/util/__init__.py b/lib/sqlalchemy/util/__init__.py
index d777d2e06..ed968f168 100644
--- a/lib/sqlalchemy/util/__init__.py
+++ b/lib/sqlalchemy/util/__init__.py
@@ -19,7 +19,7 @@ from ._collections import KeyedTuple, ImmutableContainer, immutabledict, \
OrderedSet, IdentitySet, OrderedIdentitySet, column_set, \
column_dict, ordered_column_set, populate_column_dict, unique_list, \
UniqueAppender, PopulateDict, EMPTY_SET, to_list, to_set, \
- to_column_set, update_copy, flatten_iterator, \
+ to_column_set, update_copy, flatten_iterator, has_intersection, \
LRUCache, ScopedRegistry, ThreadLocalRegistry, WeakSequence, \
coerce_generator_arg, lightweight_named_tuple
diff --git a/lib/sqlalchemy/util/_collections.py b/lib/sqlalchemy/util/_collections.py
index db2c21949..5c62ebed8 100644
--- a/lib/sqlalchemy/util/_collections.py
+++ b/lib/sqlalchemy/util/_collections.py
@@ -800,6 +800,19 @@ def to_list(x, default=None):
return list(x)
+def has_intersection(set_, iterable):
+ """return True if any items of set_ are present in iterable.
+
+ Goes through special effort to ensure __hash__ is not called
+ on items in iterable that don't support it.
+
+ """
+ # TODO: optimize, write in C, etc.
+ return bool(
+ set_.intersection([i for i in iterable if i.__hash__])
+ )
+
+
def to_set(x):
if x is None:
return set()