Comment 1 for bug 620508

Revision history for this message
Leonard Richardson (leonardr) wrote : Re: Slicing a ResultSet breaks subsequent len() calls.

OK, here is my real problem. 'foo' is a complex ResultSet.

>>> len(foo)
9
>>> tmp = foo[1:3]
>>> len(foo)
Traceback (most recent call last):
...
FeatureError: __contains__() does not yet support set expressions that combine ORDER BY with LIMIT/OFFSET

Here's the problem. When I slice the ResultSet, ResultSet.__getitem__ makes a copy of the ResultSet and configures the copy with the desired offset and limit. But the original and the copy share the same .select member. (This is an object from the storm.expr module.) When I call len(foo), ._select.limit and ._select.offset are populated for both the original and the copy.

When I call len() the second time. some code in _get_select() runs that looks like it should normalize the data.

        if self._select is not Undef:
            if self._order_by is not Undef:
                self._select.order_by = self._order_by
            if self._limit is not Undef: # XXX UNTESTED!
                self._select.limit = self._limit
            if self._offset is not Undef: # XXX UNTESTED!
                self._select.offset = self._offset
            return self._select

But it doesn't work in this case. This code only overrides .limit or .offset if the new value is not Undef. So if I slice the list again:

>>> tmp2 = foo[1:6]

The old .limit '2' will be replaced by '5' and I will get the correct slice. But when I call len(), the new limit is Undef, so the old value for .limit is left in place, and I get the FeatureError.

There are two solutions. Either change _get_select() to override a non-Undef value with Undef, or change the copy() operation to copy ._select.