Merge lp:~allenap/storm/get-set-expr-columns into lp:storm

Proposed by Gavin Panella
Status: Work in progress
Proposed branch: lp:~allenap/storm/get-set-expr-columns
Merge into: lp:storm
Prerequisite: lp:~allenap/storm/value-columns-by-name
Diff against target: 75 lines (+35/-1)
3 files modified
storm/expr.py (+14/-0)
tests/expr.py (+10/-0)
tests/store/base.py (+11/-1)
To merge this branch: bzr merge lp:~allenap/storm/get-set-expr-columns
Reviewer Review Type Date Requested Status
James Henstridge Needs Fixing
Review via email: mp+23492@code.launchpad.net

Commit message

ResultSet.values() can now return values from set expressions.

Description of the change

Enables ResultSet.values() to operate on set expressions. It does this with a pass-through property, SetExpr.columns. An alternative implementation could be to deal specially with SetExprs in values() itself.

To post a comment you must log in.
Revision history for this message
James Henstridge (jamesh) wrote :

In most cases, I've used the replace_columns() helper in the store code where I need to fiddle with the column list for a query.

It'd probably be better to do the same in ResultSet.values(). The current code looks like it could leak changes outside of the method call, which could be problematic.

Secondly, I don't believe this patch will result in correct behaviour from ResultSet.values() for set expressions. Consider a table Foo containing the following data:

 id | name
 ---+------
 10 | value
 20 | value

And then do the following:

 result = store.find(Foo, id=10).union(store.find(Foo, id=20))
 print list(result.values(Foo.name))

This will print ['value'] when it should print ['value', 'value']. The result set clearly has two rows, but if we rewrite the column lists to Foo.name then the union will only give us one row.

review: Needs Fixing

Unmerged revisions

358. By Gavin Panella

Tests to show ResultSet.values() working on a set expression.

357. By Gavin Panella

Create a pass-through columns property on SetExpr.

356. By Gavin Panella

ResultSet.values() can now accept column names as well as columns themselves.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'storm/expr.py'
2--- storm/expr.py 2009-11-02 11:11:20 +0000
3+++ storm/expr.py 2010-04-22 15:57:27 +0000
4@@ -1136,6 +1136,20 @@
5 first.offset is Undef):
6 self.exprs = first.exprs + self.exprs[1:]
7
8+ def _get_columns(self):
9+ if len(self.exprs) > 0:
10+ # The find specs of all sub-expressions should be
11+ # compatible, so simply return the first.
12+ return self.exprs[0].columns
13+ else:
14+ return []
15+
16+ def _set_columns(self, columns):
17+ for expr in self.exprs:
18+ expr.columns = columns
19+
20+ columns = property(_get_columns, _set_columns)
21+
22
23 @compile.when(SetExpr)
24 def compile_set_expr(compile, expr, state):
25
26=== modified file 'tests/expr.py'
27--- tests/expr.py 2009-11-02 11:11:20 +0000
28+++ tests/expr.py 2010-04-22 15:57:27 +0000
29@@ -294,6 +294,16 @@
30 self.assertEquals(expr.expr, objects[0])
31 self.assertEquals(expr.name, objects[1])
32
33+ def test_set_expr_columns(self):
34+ select1 = Select((elem1, elem2))
35+ select2 = Select((elem2, elem1))
36+ expr = SetExpr(select1, select2)
37+ self.assertEquals((elem1, elem2), expr.columns)
38+ expr.columns = []
39+ self.assertEquals([], expr.columns)
40+ self.assertEquals([], select1.columns)
41+ self.assertEquals([], select2.columns)
42+
43 def test_union(self):
44 expr = Union(elem1, elem2, elem3)
45 self.assertEquals(expr.exprs, (elem1, elem2, elem3))
46
47=== modified file 'tests/store/base.py'
48--- tests/store/base.py 2010-04-22 15:57:27 +0000
49+++ tests/store/base.py 2010-04-22 15:57:27 +0000
50@@ -31,7 +31,7 @@
51 from storm.variables import PickleVariable
52 from storm.expr import (
53 Alias, And, Asc, Avg, Count, Desc, Eq, LeftJoin, Lower, Or, SQL, Select,
54- Sum)
55+ Sum, Union)
56 from storm.variables import Variable, UnicodeVariable, IntVariable
57 from storm.info import get_obj_info, ClassAlias
58 from storm.exceptions import *
59@@ -1047,6 +1047,16 @@
60 values = self.store.find(Foo).order_by(Foo.id)[1:2].values(Foo.id)
61 self.assertEquals(list(values), [20])
62
63+ def test_find_set_expr_values(self):
64+ result = self.store.find(Foo).union(self.store.find(Foo), all=True)
65+ values = result.values(Foo.id)
66+ self.assertEquals(sorted(values), [10, 10, 20, 20, 30, 30])
67+
68+ def test_find_set_expr_values_by_column_name(self):
69+ result = self.store.find(Foo).union(self.store.find(Foo), all=True)
70+ values = result.values('id')
71+ self.assertEquals(sorted(values), [10, 10, 20, 20, 30, 30])
72+
73 def test_find_remove(self):
74 self.store.find(Foo, Foo.id == 20).remove()
75 self.assertEquals(self.get_items(), [

Subscribers

People subscribed via source and target branches

to status/vote changes: