Merge lp:~radix/storm/count-limited-union into lp:storm

Proposed by Christopher Armstrong
Status: Merged
Approved by: Thomas Herve
Approved revision: 455
Merged at revision: 454
Proposed branch: lp:~radix/storm/count-limited-union
Merge into: lp:storm
Diff against target: 56 lines (+34/-1)
2 files modified
storm/store.py (+5/-1)
tests/store/base.py (+29/-0)
To merge this branch: bzr merge lp:~radix/storm/count-limited-union
Reviewer Review Type Date Requested Status
Thomas Herve (community) Approve
Review via email: mp+139825@code.launchpad.net

Description of the change

Can someone explain to me what this branch breaks?

I have some code that I would love to be able to do a result1.union(result2).order_by(c).config(limit=n).count() in, but there's an arbitrary restriction preventing it from working. Given the comment, it sounds like there's some case in which it might not be supported, but the simple case I have works just fine if I remove the assertion.

By the way, the error message it raised was really confusing; it looks like replace_columns assumes it's only being called in a __contains__ code path, when it's also called elsewhere.

To post a comment you must log in.
Revision history for this message
Thomas Herve (therve) wrote :

The message is definitely outdated, by only mentioning __contains__, but it seems to me that's it's still valid: the order_by value is not passed along, so it can't be used by the new expression? Your test doesn't check that as there is only one value.

lp:~radix/storm/count-limited-union updated
455. By Christopher Armstrong

try a different strategy for avoiding the error.

Revision history for this message
Christopher Armstrong (radix) wrote :

The ordering doesn't matter for this case. I've talked to therve a bit and have changed the strategy used in the branch a bit to be a bit more explicit and less far-reaching.

Revision history for this message
Thomas Herve (therve) wrote :

It looks good to me. Maybe add another test for another aggregation function to make sure everything is fine. +1!

review: Approve
lp:~radix/storm/count-limited-union updated
456. By Christopher Armstrong

add a test for avg() as well, to ensure the fix works for all aggregates.

Revision history for this message
Christopher Armstrong (radix) wrote :

Done. I'm not a storm committer, can someone take care of merging this?

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'storm/store.py'
2--- storm/store.py 2012-06-12 10:00:51 +0000
3+++ storm/store.py 2012-12-18 21:23:38 +0000
4@@ -1244,7 +1244,11 @@
5 alias = Alias(expr, "_expr")
6 columns.append(alias)
7 aggregate = aggregate_func(alias)
8- subquery = replace_columns(self._get_select(), columns)
9+ # Ordering probably doesn't matter for any aggregates, and since
10+ # replace_columns() blows up on an ordered query, we'll drop it.
11+ select = self._get_select()
12+ select.order_by = Undef
13+ subquery = replace_columns(select, columns)
14 select = Select(aggregate, tables=Alias(subquery, "_tmp"))
15 result = self._store._connection.execute(select)
16 value = result.get_one()[0]
17
18=== modified file 'tests/store/base.py'
19--- tests/store/base.py 2012-04-06 08:19:07 +0000
20+++ tests/store/base.py 2012-12-18 21:23:38 +0000
21@@ -5583,6 +5583,35 @@
22
23 self.assertEquals(result3.count(), 2)
24
25+ def test_result_union_limit_count(self):
26+ """
27+ It's possible to count the result of a union that is limited.
28+ """
29+ result1 = self.store.find(Foo, id=30)
30+ result2 = self.store.find(Foo, id=30)
31+
32+ result3 = result1.union(result2, all=True)
33+ result3.order_by(Foo.id)
34+ result3.config(limit=1)
35+
36+ self.assertEquals(result3.count(), 1)
37+ self.assertEquals(result3.count(Foo.id), 1)
38+
39+ def test_result_union_limit_avg(self):
40+ """
41+ It's possible to average the result of a union that is limited.
42+ """
43+ result1 = self.store.find(Foo, id=10)
44+ result2 = self.store.find(Foo, id=30)
45+
46+ result3 = result1.union(result2, all=True)
47+ result3.order_by(Foo.id)
48+ result3.config(limit=1)
49+
50+ # Since 30 was left off because of the limit, the only result will be
51+ # 10, and the average of that is 10.
52+ self.assertEquals(result3.avg(Foo.id), 10)
53+
54 def test_result_difference(self):
55 if self.__class__.__name__.startswith("MySQL"):
56 return

Subscribers

People subscribed via source and target branches

to status/vote changes: