Incorrect behavior of join() on iterators was fixed

Due to the incorrect condition it code that limits
iterators even collections with known limit (lists etc.)
were converted to limiting iterators when there was
no upper length limit. As a result when join() method
was called without iterator limitation being configured
(for example through yaql.eval) it received its collection
arguments as iterators. Because iterators cannot be reset
and re-read again iterator for the inner iterator became
exhausted after the first item of the outer collection.

join() method was fixed to work correctly to memorize
inner iterator so that it could be re-read

Change-Id: I287d0d86b5461490ff32731c11a726174939753d
This commit is contained in:
Stan Lagun
2015-12-16 19:29:04 +03:00
parent bf28ac940e
commit 8f73db1a19
2 changed files with 9 additions and 9 deletions

View File

@@ -181,20 +181,19 @@ def get_memory_quota(engine):
def limit_iterable(iterable, limit_or_engine):
if isinstance(limit_or_engine, int):
count = limit_or_engine
max_count = limit_or_engine
else:
count = get_max_collection_size(limit_or_engine)
max_count = get_max_collection_size(limit_or_engine)
if count >= 0 and isinstance(iterable,
(SequenceType, MappingType, SetType)):
if len(iterable) > count:
raise exceptions.CollectionTooLargeException(count)
if isinstance(iterable, (SequenceType, MappingType, SetType)):
if 0 <= max_count < len(iterable):
raise exceptions.CollectionTooLargeException(max_count)
return iterable
def limiting_iterator():
for i, t in enumerate(iterable):
if 0 <= count <= i:
raise exceptions.CollectionTooLargeException(count)
if 0 <= max_count <= i:
raise exceptions.CollectionTooLargeException(max_count)
yield t
return limiting_iterator()

View File

@@ -371,7 +371,8 @@ def zip_longest(*collections, **kwargs):
@specs.parameter('collection2', yaqltypes.Iterable())
@specs.parameter('predicate', yaqltypes.Lambda())
@specs.parameter('selector', yaqltypes.Lambda())
def join(collection1, collection2, predicate, selector):
def join(engine, collection1, collection2, predicate, selector):
collection2 = utils.memorize(collection2, engine)
for self_item in collection1:
for other_item in collection2:
if predicate(self_item, other_item):