Merge lp:~bjornt/storm/union-different-class-columns into lp:storm

Proposed by Björn Tillenius
Status: Merged
Approved by: Björn Tillenius
Approved revision: 472
Merged at revision: 472
Proposed branch: lp:~bjornt/storm/union-different-class-columns
Merge into: lp:storm
Diff against target: 66 lines (+29/-2)
2 files modified
storm/store.py (+19/-2)
tests/store/base.py (+10/-0)
To merge this branch: bzr merge lp:~bjornt/storm/union-different-class-columns
Reviewer Review Type Date Requested Status
Alberto Donato (community) Approve
Review via email: mp+256660@code.launchpad.net

Description of the change

Allow doing union of two result sets for different columns in different
model classes as long as the columns are of the same type.

To post a comment you must log in.
Revision history for this message
Alberto Donato (ack) wrote :

Nice, +1!

One docstring nitpick inline.

review: Approve
473. By Björn Tillenius

Add full stop.

474. By Björn Tillenius

Revert accidental change.

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-12-14 17:17:40 +0000
3+++ storm/store.py 2015-04-20 08:46:57 +0000
4@@ -37,6 +37,7 @@
5 from storm.exceptions import (
6 WrongStoreError, NotFlushedError, OrderLoopError, UnorderedError,
7 NotOneError, FeatureError, CompileError, LostObjectError, ClassInfoError)
8+from storm.properties import PropertyColumn
9 from storm import Undef
10 from storm.cache import Cache
11 from storm.event import EventSystem
12@@ -1706,7 +1707,12 @@
13 return columns, default_tables
14
15 def is_compatible(self, find_spec):
16- """Return True if this FindSpec is compatible with a second one."""
17+ """Return True if this FindSpec is compatible with a second one.
18+
19+ Two FindSpecs are considered compatible if either the find specs
20+ are identical (i.e. specifies the same classes and columns) or
21+ the find spec columns are of the same type.
22+ """
23 if self.is_tuple != find_spec.is_tuple:
24 return False
25 if len(self._cls_spec_info) != len(find_spec._cls_spec_info):
26@@ -1715,7 +1721,18 @@
27 self._cls_spec_info, find_spec._cls_spec_info):
28 if is_expr1 != is_expr2:
29 return False
30- if info1 is not info2:
31+ # If both infos are PropertyColumns, check whether they are
32+ # of the same type. Ideally we should check that the types as
33+ # defined in the database are the same, but checking the
34+ # variable class is easier and will work most of the time.
35+ if isinstance(info1, PropertyColumn):
36+ if not isinstance(info2, PropertyColumn):
37+ return False
38+ variable_class1 = info1.variable_factory().__class__
39+ variable_class2 = info2.variable_factory().__class__
40+ if variable_class1 is not variable_class2:
41+ return False
42+ elif info1 is not info2:
43 return False
44 return True
45
46
47=== modified file 'tests/store/base.py'
48--- tests/store/base.py 2013-06-28 08:13:08 +0000
49+++ tests/store/base.py 2015-04-20 08:46:57 +0000
50@@ -5572,6 +5572,16 @@
51 (30, "Title 10"),
52 ])
53
54+ def test_result_union_class_columns(self):
55+ """
56+ It's possible to do a union of two result sets on columns on
57+ different classes, as long as their variable classes are the
58+ same (e.g. both are IntVariables).
59+ """
60+ result1 = self.store.find(Foo.id, Foo.id == 10)
61+ result2 = self.store.find(Bar.foo_id, Bar.id == 200)
62+ self.assertEquals([10, 20], sorted(result1.union(result2)))
63+
64 def test_result_union_incompatible(self):
65 result1 = self.store.find(Foo, id=10)
66 result2 = self.store.find(Bar, id=100)

Subscribers

People subscribed via source and target branches

to status/vote changes: