keso 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +23 -0
- data/Rakefile +44 -0
- data/VERSION +1 -0
- data/keso.gemspec +72 -0
- data/lib/keso.rb +8 -0
- data/lib/realvar.rb +12 -0
- data/lib/values/attribute.rb +44 -0
- data/lib/values/heading.rb +125 -0
- data/lib/values/immutable_hash.rb +112 -0
- data/lib/values/immutable_set.rb +151 -0
- data/lib/values/relation.rb +455 -0
- data/lib/values/tuple.rb +149 -0
- data/spec/attribute_spec.rb +61 -0
- data/spec/heading_spec.rb +125 -0
- data/spec/immutable_hash_spec.rb +200 -0
- data/spec/immutable_set_spec.rb +163 -0
- data/spec/relation_spec.rb +358 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/tuple_spec.rb +155 -0
- metadata +107 -0
@@ -0,0 +1,163 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
|
4
|
+
describe ImmutableSet do
|
5
|
+
describe :new do
|
6
|
+
it 'returns a new instance of ImmutableSet with the supplied values' do
|
7
|
+
ImmutableSet.new(:a).should be_instance_of ImmutableSet
|
8
|
+
ImmutableSet.new(:a).count.should eql(1)
|
9
|
+
|
10
|
+
ImmutableSet.new([:a,:b,:c,:a]).count.should eql(3)
|
11
|
+
ImmutableSet.new(ImmutableSet.new([:a,:b,:c,:a])).count.should eql(3)
|
12
|
+
|
13
|
+
ImmutableSet.new([:a,:b,:c,:a],[:z],[:y],:o).count.should eql(6)
|
14
|
+
ImmutableSet.new([:a,:b,:c,:a],[:z],[:y],ImmutableSet.new([:o])).count.should eql(6)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe :each do
|
19
|
+
it 'iterates over each value' do
|
20
|
+
ImmutableSet.new([:a,:b,:c]).each do |value|
|
21
|
+
[:a,:b,:c].should include value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe :count do
|
27
|
+
it 'returns the amount of items in the set' do
|
28
|
+
ImmutableSet.new([:a,:b,:c]).count.should eql(3)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe :size do
|
33
|
+
it 'returns the amount of items in the set' do
|
34
|
+
ImmutableSet.new([:a,:b,:c]).size.should eql(3)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe :include? do
|
39
|
+
it 'should be true when it contains the value' do
|
40
|
+
ImmutableSet.new([:a,:b,:c]).include?(:a).should be_true
|
41
|
+
ImmutableSet.new([:a,:b,:c]).include?(:z).should be_false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe :eql? do
|
46
|
+
it 'returns true if the two sets are equal' do
|
47
|
+
ImmutableSet.new([:a,:b,:c]).eql?(ImmutableSet.new([:a,:b,:c])).should be_true
|
48
|
+
ImmutableSet.new([:a,:b]).eql?(ImmutableSet.new([:a,:b,:c])).should be_false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe :hash do
|
53
|
+
it 'always returns the same value for two sets that are equal' do
|
54
|
+
ImmutableSet.new([:a,:b,:c]).hash.should eql(ImmutableSet.new([:a,:b,:c]).hash)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe :add do
|
59
|
+
it 'should result in a new set with the supplied value' do
|
60
|
+
ImmutableSet.new(:a).add(:b).add(:a).count.should eql(2)
|
61
|
+
ImmutableSet.new(:a).add([:b,:a,:c]).add(:a).count.should eql(3)
|
62
|
+
ImmutableSet.new(:a).add(ImmutableSet.new([:d])).add(:a).count.should eql(2)
|
63
|
+
|
64
|
+
ImmutableSet.new(:a).add(:b,:f).add(:a).count.should eql(3)
|
65
|
+
ImmutableSet.new(:a).add([:b,:a,:c]).add(:a,:ue).count.should eql(4)
|
66
|
+
ImmutableSet.new(:a).add(ImmutableSet.new([:d]),:htuneo).add(:a).count.should eql(3)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe :union do
|
71
|
+
it 'should result in a new set with the supplied value' do
|
72
|
+
ImmutableSet.new(:a).union(:b).union(:a).count.should eql(2)
|
73
|
+
ImmutableSet.new(:a).union([:b,:a,:c]).union(:a).count.should eql(3)
|
74
|
+
ImmutableSet.new(:a).union(ImmutableSet.new([:d])).union(:a).count.should eql(2)
|
75
|
+
|
76
|
+
ImmutableSet.new(:a).union(:b,:f).union(:a).count.should eql(3)
|
77
|
+
ImmutableSet.new(:a).union([:b,:a,:c]).union(:a,:ue).count.should eql(4)
|
78
|
+
ImmutableSet.new(:a).union(ImmutableSet.new([:d]),:htuneo).union(:a).count.should eql(3)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe :delete do
|
83
|
+
it 'should delete a value from the set' do
|
84
|
+
ImmutableSet.new(:a).add(:b).delete(:a).count.should eql(1)
|
85
|
+
ImmutableSet.new([:a,:b,:c,:e]).delete(ImmutableSet.new([:a,:b])).count.should eql(2)
|
86
|
+
ImmutableSet.new([:a,:b,:c,:e]).delete([:a,:b]).count.should eql(2)
|
87
|
+
|
88
|
+
ImmutableSet.new(:a).add(:b).delete(:a,:b).count.should eql(0)
|
89
|
+
ImmutableSet.new([:a,:b,:c,:e]).delete(ImmutableSet.new([:a,:b]),:c).count.should eql(1)
|
90
|
+
ImmutableSet.new([:a,:b,:c,:e]).delete([:a,:b],:e).count.should eql(1)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe :subset? do
|
95
|
+
it 'should return true when all values in the supplied set is also in the current set' do
|
96
|
+
|
97
|
+
ImmutableSet.new([:a,:b]).subset?(ImmutableSet.new([:a,:b,:c])).should be_true
|
98
|
+
ImmutableSet.new([:b,:c]).subset?(ImmutableSet.new([:a,:b,:c])).should be_true
|
99
|
+
ImmutableSet.new([:a,:b,:c]).subset?(ImmutableSet.new([:a,:b,:c])).should be_true
|
100
|
+
ImmutableSet.new([:a,:b,:c]).subset?(ImmutableSet.new([:b,:c,:gi])).should be_false
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe :proper_subset? do
|
106
|
+
it 'should return true when all values in the supplied set is also in the current set' do
|
107
|
+
|
108
|
+
ImmutableSet.new([:a,:b]).proper_subset?(ImmutableSet.new([:a,:b,:c])).should be_true
|
109
|
+
ImmutableSet.new([:b,:c]).proper_subset?(ImmutableSet.new([:a,:b,:c])).should be_true
|
110
|
+
ImmutableSet.new([:a,:b,:c]).proper_subset?(ImmutableSet.new([:a,:b,:c])).should be_false
|
111
|
+
ImmutableSet.new([:a,:b,:c]).proper_subset?(ImmutableSet.new([:b,:c,:gi])).should be_false
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe :proper_subset_of? do
|
117
|
+
it 'should return true when all values in the supplied set is also in the current set but they are not equal' do
|
118
|
+
|
119
|
+
ImmutableSet.new([:a,:b]).proper_subset_of?(ImmutableSet.new([:a,:b,:c])).should be_true
|
120
|
+
ImmutableSet.new([:b,:c]).proper_subset_of?(ImmutableSet.new([:a,:b,:c])).should be_true
|
121
|
+
ImmutableSet.new([:a,:b,:c]).proper_subset_of?(ImmutableSet.new([:a,:b,:c])).should be_false
|
122
|
+
ImmutableSet.new([:a,:b,:c]).proper_subset_of?(ImmutableSet.new([:b,:c,:gi])).should be_false
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe :superset? do
|
128
|
+
it 'should return true when all values in the supplied set is also in the current set but they are not equal' do
|
129
|
+
|
130
|
+
ImmutableSet.new([:a,:b,:c]).superset?(ImmutableSet.new([:a,:b])).should be_true
|
131
|
+
ImmutableSet.new([:a,:b,:c]).superset?(ImmutableSet.new([:b,:c])).should be_true
|
132
|
+
ImmutableSet.new([:a,:b,:c]).superset?(ImmutableSet.new([:a,:b,:c])).should be_true
|
133
|
+
ImmutableSet.new([:a,:b,:c]).superset?(ImmutableSet.new([:gi])).should be_false
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe :proper_superset? do
|
139
|
+
it 'should return true when all values in the supplied set is also in the current set' do
|
140
|
+
|
141
|
+
ImmutableSet.new([:a,:b,:c]).proper_superset?(ImmutableSet.new([:a,:b])).should be_true
|
142
|
+
ImmutableSet.new([:a,:b,:c]).proper_superset?(ImmutableSet.new([:b,:c])).should be_true
|
143
|
+
ImmutableSet.new([:a,:b,:c]).proper_superset?(ImmutableSet.new([:a,:b,:c])).should be_false
|
144
|
+
ImmutableSet.new([:a,:b,:c]).proper_superset?(ImmutableSet.new([:gi])).should be_false
|
145
|
+
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe :complement do
|
150
|
+
it 'should return a new set with set1 minues the values of set2' do
|
151
|
+
ImmutableSet.new([:a,:b,:c]).complement(ImmutableSet.new([:a,:b])).should eql(ImmutableSet.new([:c]))
|
152
|
+
ImmutableSet.new([:a,:b,:c]).complement(ImmutableSet.new([:a])).should eql(ImmutableSet.new([:c,:b]))
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
describe :intersect do
|
157
|
+
it 'should return a new set with the values that are fonud in both set1 and set2' do
|
158
|
+
ImmutableSet.new([:a,:b,:c]).intersect(ImmutableSet.new([:a,:b])).should eql(ImmutableSet.new([:a,:b]))
|
159
|
+
ImmutableSet.new([:a,:b,:c]).intersect(ImmutableSet.new([:a])).should eql(ImmutableSet.new([:a]))
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
@@ -0,0 +1,358 @@
|
|
1
|
+
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
3
|
+
|
4
|
+
describe Relation do
|
5
|
+
|
6
|
+
describe :count do
|
7
|
+
it 'returns the tupel count in the set' do
|
8
|
+
Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).count.should eql 1
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe :add do
|
13
|
+
it 'returns a new relation with the added tuple' do
|
14
|
+
Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30})).count.should eql 2
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'throws an exception as the supplied value is not a tuple' do
|
18
|
+
lambda { Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add("") }.should raise_error(ArgumentError)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'throws an exception as the supplied tuple is not of the same heading as the relation' do
|
22
|
+
lambda { Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:something => 'Emma',:age => 30})) }.should raise_error(ArgumentError)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'throws an exception as the relational value is of the wrong heading' do
|
26
|
+
|
27
|
+
person = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
28
|
+
person_with_length = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29,:length => 155})).add(Tuple.new({:name => 'Emma',:age => 30, :length => 135}))
|
29
|
+
|
30
|
+
company = Relation.new(Tuple.new({:name => 'Test AB',:employes => person}))
|
31
|
+
|
32
|
+
lambda { company = company.add(Tuple.new({:name => 'Nordea AB',:employes => person})) }.should_not raise_error(ArgumentError)
|
33
|
+
lambda { company = company.add(Tuple.new({:name => 'SEB AB',:employes => person_with_length})) }.should raise_error(ArgumentError)
|
34
|
+
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
describe :subset_of? do
|
41
|
+
it 'returns return true when the supplied value is a subset' do
|
42
|
+
a = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
43
|
+
Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).subset_of?(a).should be_true
|
44
|
+
Relation.new(Tuple.new({:name => 'Bjorn',:age => 30})).subset_of?(a).should be_false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# r1.proper_subset(r2) # boolean result
|
49
|
+
describe :proper_subset_of? do
|
50
|
+
it 'should return true when all values are also in the supplied set and they are not equal' do
|
51
|
+
a = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
52
|
+
Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).proper_subset_of?(a).should be_true
|
53
|
+
a.proper_subset_of?(a).should be_false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# r1.superset(r2) # boolean result
|
58
|
+
describe :superset_of? do
|
59
|
+
it 'should return true when all the tuples of the supplied set can be found in this set' do
|
60
|
+
a = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
61
|
+
a.superset_of?(Relation.new(Tuple.new({:name => 'Bjorn',:age => 29}))).should be_true
|
62
|
+
a.superset_of?(Relation.new(Tuple.new({:name => 'Bjor'}))).should be_false
|
63
|
+
a.superset_of?(a).should be_true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# r1.proper_superset(r2) # boolean result
|
68
|
+
describe :proper_superset_of? do
|
69
|
+
it 'should return true when all the tuples of the supplied set is also in this set but they are not equal' do
|
70
|
+
a = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
71
|
+
|
72
|
+
a.proper_superset_of?(Relation.new(Tuple.new({:name => 'Bjorn',:age => 29}))).should be_true
|
73
|
+
a.proper_superset_of?(Relation.new(Tuple.new({:name => 'Bjor'}))).should be_false
|
74
|
+
a.proper_superset_of?(a).should be_false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# r1.union(r2) # r1 + r2, set result
|
79
|
+
describe :union do
|
80
|
+
it 'returns a new relation with the tuples of both' do
|
81
|
+
a = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
82
|
+
b = Relation.new(Tuple.new({:name => 'Frida',:age => 25})).add(Tuple.new({:name => 'Marianna',:age => 32}))
|
83
|
+
|
84
|
+
c = Relation.new(Tuple.new({:name => 'Frida',:age => 25})).add(Tuple.new({:name => 'Marianna',:age => 32})).add(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
85
|
+
|
86
|
+
a.union(b).should eql(c)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe :eql? do
|
91
|
+
it 'returns true when two relations have the same value' do
|
92
|
+
a = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
93
|
+
b = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
94
|
+
a.should eql b
|
95
|
+
|
96
|
+
|
97
|
+
r1 = Relation.new(Tuple.new({:name => 'Bjorn', :person_ids => Relation.new(Tuple.new({:person_id => 12})).add(Tuple.new({:person_id => 119}))}))
|
98
|
+
r2 = Relation.new(Tuple.new({:name => 'Bjorn', :person_ids => Relation.new(Tuple.new({:person_id => 12})).add(Tuple.new({:person_id => 119}))}))
|
99
|
+
r1.should eql(r2)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe :== do
|
104
|
+
it 'returns true when two relations have the same value' do
|
105
|
+
a = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
106
|
+
b = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
107
|
+
(a == b).should be_true
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe :hash do
|
112
|
+
it 'should return the same hash for the same value' do
|
113
|
+
a = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
114
|
+
b = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
115
|
+
a.hash.should eql b.hash
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# r1.intersect(r2) # all in r1 that is also in r2, set result
|
120
|
+
describe :intersect do
|
121
|
+
it 'should return a new relation all the tuples that are found in both' do
|
122
|
+
a = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
123
|
+
b = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Frida',:age => 25}))
|
124
|
+
|
125
|
+
a.intersect(b).should eql(Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})))
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should throw an exception as the realtions are not of the same headings' do
|
129
|
+
a = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29}))
|
130
|
+
b = Relation.new(Tuple.new({:name => 'Bjorn'}))
|
131
|
+
|
132
|
+
lambda { a.intersect(b) }.should raise_error(ArgumentError)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# r1.complement(r2) # r1 - r2, set result
|
137
|
+
describe :complement do
|
138
|
+
it 'should return a new relation that has all the tuples that where not in r2' do
|
139
|
+
a = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
140
|
+
b = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Frida',:age => 25}))
|
141
|
+
|
142
|
+
a.complement(b).should eql(Relation.new(Tuple.new({:name => 'Emma',:age => 30})))
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'should throw an exception with the text ""Not of the same heading""' do
|
146
|
+
a = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29}))
|
147
|
+
b = Relation.new(Tuple.new({:name => 'Bjorn'}))
|
148
|
+
|
149
|
+
lambda { a.complement(b) }.should raise_error(ArgumentError)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# r1.project_all_but('Name','age') # results in a relation with all attributes exepct the supplied ones, set result
|
154
|
+
describe :project_all_but do
|
155
|
+
it 'should return a new relation with all but the supplied columns' do
|
156
|
+
Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30})).project_all_but(:name).should eql(Relation.new(Tuple.new({:age => 30})).add(Tuple.new({:age => 29})))
|
157
|
+
Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30})).project_all_but(:name,:age).should eql(Relation.new())
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
|
162
|
+
# r1.project('Name','age') # results in a relation of only the supplied attributes, set result
|
163
|
+
describe :project do
|
164
|
+
it 'should return with a new relation with only the attributes named in the argument' do
|
165
|
+
Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30})).project(:name).should eql(Relation.new(Tuple.new({:name => 'Bjorn'})).add(Tuple.new({:name => 'Emma'})))
|
166
|
+
Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30})).project(:name,:age).should eql(Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30})))
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'should throw an exception as the attribue name is not in the relation' do
|
170
|
+
lambda { Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30})).project(:names) }.should raise_error(ArgumentError)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# r1.rename('Name','PersonName') # changes the attribute name from "Name" to "PersonName", set result
|
175
|
+
describe :rename do
|
176
|
+
it 'should change the name of a tuple' do
|
177
|
+
Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30})).rename(:name,:new_name).should eql(Relation.new(Tuple.new({:new_name => 'Bjorn',:age => 29})).add(Tuple.new({:new_name => 'Emma',:age => 30})))
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should throw an exception ' do
|
181
|
+
lambda { Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30})).rename(:old_name,:new_name) }.should raise_error(ArgumentError)
|
182
|
+
lambda { Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30})).rename(:name,:age) }.should raise_error(ArgumentError)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
describe :new do
|
188
|
+
|
189
|
+
it 'should accept a relation as a type' do
|
190
|
+
|
191
|
+
persons = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
192
|
+
|
193
|
+
Relation.new(Tuple.new({:name => 'Test AB',:employes => persons})).each do |tuple|
|
194
|
+
tuple.employes.should eql(Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30})))
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
describe :each do
|
201
|
+
it 'iterates over all the tuples and executes the given block' do
|
202
|
+
|
203
|
+
names = {}
|
204
|
+
|
205
|
+
Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30})).each do |tuple|
|
206
|
+
names[tuple[:name]] = tuple[:name]
|
207
|
+
end
|
208
|
+
|
209
|
+
names['Bjorn'].should_not be_nil
|
210
|
+
names['Emma'].should_not be_nil
|
211
|
+
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
# r1.select do |r| r.age = 18 end
|
216
|
+
describe :select do
|
217
|
+
it 'should return only the tuples with age 29' do
|
218
|
+
result = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30})).select do |tuple|
|
219
|
+
tuple.age == 29
|
220
|
+
end
|
221
|
+
|
222
|
+
result.should eql(Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})))
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'should return only the tuples with age greater than 18' do
|
226
|
+
result = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30})).select do |tuple|
|
227
|
+
tuple.age > 18
|
228
|
+
end
|
229
|
+
|
230
|
+
result.should eql(Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30})))
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
# r1.join(r2) do |tupel| ... end
|
235
|
+
describe :join do
|
236
|
+
it 'returns a new relation that is the result of join r1 with r2' do
|
237
|
+
r1 = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
238
|
+
r2 = Relation.new(Tuple.new({:name => 'Bjorn',:length => 185})).add(Tuple.new({:name => 'Emma',:length => 115})).rename(:name,:name2)
|
239
|
+
|
240
|
+
result = r1.join(r2) do |tupel|
|
241
|
+
tupel.name == tupel.name2
|
242
|
+
end
|
243
|
+
|
244
|
+
r3 = Relation.new(Tuple.new({:name => 'Bjorn',:name2 => 'Bjorn',:length => 185,:age => 29})).add(Tuple.new({:name => 'Emma',:name2 => 'Emma',:length => 115, :age => 30}))
|
245
|
+
|
246
|
+
result.count.should eql(r3.count)
|
247
|
+
result.heading.should eql(r3.heading)
|
248
|
+
result.should eql(r3)
|
249
|
+
|
250
|
+
end
|
251
|
+
|
252
|
+
it 'returns a new relation that is the result of join r1 with r2' do
|
253
|
+
r1 = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
254
|
+
r2 = Relation.new(Tuple.new({:name => 'Bjorn',:length => 185})).add(Tuple.new({:name => 'Emma',:length => 115})).rename(:name,:name2)
|
255
|
+
|
256
|
+
result = r1.join(r2) do |tupel|
|
257
|
+
tupel.name != tupel.name2
|
258
|
+
end
|
259
|
+
|
260
|
+
r3 = Relation.new(Tuple.new({:name => 'Bjorn',:name2 => 'Emma',:length => 115,:age => 29})).add(Tuple.new({:name => 'Emma',:name2 => 'Bjorn',:length => 185, :age => 30}))
|
261
|
+
|
262
|
+
result.count.should eql(r3.count)
|
263
|
+
result.heading.should eql(r3.heading)
|
264
|
+
result.should eql(r3)
|
265
|
+
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
|
270
|
+
# r1.cartesian_product(r2) # new relation with r1 * r2 tuples with all attributes of r1 and r2, set result
|
271
|
+
describe :cartesian_product do
|
272
|
+
it 'should return a new relation' do
|
273
|
+
r1 = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
274
|
+
r2 = Relation.new(Tuple.new({:name => 'Bjorn',:length => 185})).add(Tuple.new({:name => 'Emma',:length => 115})).rename(:name,:name2)
|
275
|
+
|
276
|
+
result = r1.cartesian_product(r2)
|
277
|
+
|
278
|
+
r3 = Relation.new(Tuple.new({:name => 'Bjorn',:name2 => 'Emma',:length => 115,:age => 29})).add(Tuple.new({:name => 'Emma',:name2 => 'Bjorn',:length => 185, :age => 30})).add(Tuple.new({:name => 'Bjorn',:name2 => 'Bjorn',:length => 185,:age => 29})).add(Tuple.new({:name => 'Emma',:name2 => 'Emma',:length => 115, :age => 30}))
|
279
|
+
|
280
|
+
result.count.should eql(r3.count)
|
281
|
+
result.heading.should eql(r3.heading)
|
282
|
+
result.should eql(r3)
|
283
|
+
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
# r1.natrual_join(r2) # cartesian_product with a selection based on equal attributes having to have equal value, set result
|
288
|
+
describe :natrual_join do
|
289
|
+
it 'returns a new relation that is the result of join r1 with r2' do
|
290
|
+
r1 = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
291
|
+
r2 = Relation.new(Tuple.new({:name => 'Bjorn',:length => 185})).add(Tuple.new({:name => 'Emma',:length => 115}))
|
292
|
+
|
293
|
+
result = r1.natrual_join(r2)
|
294
|
+
|
295
|
+
r3 = Relation.new(Tuple.new({:name => 'Bjorn',:length => 185,:age => 29})).add(Tuple.new({:name => 'Emma',:length => 115, :age => 30}))
|
296
|
+
|
297
|
+
result.count.should eql(r3.count)
|
298
|
+
result.heading.should eql(r3.heading)
|
299
|
+
result.should eql(r3)
|
300
|
+
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
|
305
|
+
# r1.group
|
306
|
+
# r1.project('Name','Age').group(['Age'],'Names') # results in a new relation as r{'Age' => integer, 'Names' => r{'Name' => String}}
|
307
|
+
describe :group do
|
308
|
+
it 'should return a new relatino with a relational value for the columns that was not supplied with the supplied name' do
|
309
|
+
|
310
|
+
r1 = Relation.new(Tuple.new({:name => 'Bjorn', :person_id => 12})).add(Tuple.new({:name => 'Bjorn', :person_id => 119}))
|
311
|
+
r2 = Relation.new(Tuple.new({:name => 'Bjorn', :person_ids => Relation.new(Tuple.new({:person_id => 12})).add(Tuple.new({:person_id => 119}))}))
|
312
|
+
|
313
|
+
r1.group([:name],:person_ids).should eql(r2)
|
314
|
+
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
|
319
|
+
# r1.ungroup
|
320
|
+
# r1.project('Name','Age').group(['Age'],'Names').ungroup('Names'[,{'Name' => 'New_name'}]) # results in a new relation as r{'Age' => integer, 'Name' => String}
|
321
|
+
describe :ungroup do
|
322
|
+
it 'should return a new relation with the person_ids relational value expended into its container relation' do
|
323
|
+
|
324
|
+
r1 = Relation.new(Tuple.new({:name => 'Bjorn', :person_id => 12})).add(Tuple.new({:name => 'Bjorn', :person_id => 119}))
|
325
|
+
r2 = Relation.new(Tuple.new({:name => 'Bjorn', :person_ids => Relation.new(Tuple.new({:person_id => 12})).add(Tuple.new({:person_id => 119}))}))
|
326
|
+
|
327
|
+
r2.ungroup(:person_ids).should eql(r1)
|
328
|
+
|
329
|
+
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
# r1.summarize(:name) do |tuples,new_tuple|
|
334
|
+
# new_tuple.add('avrange_age',avg(tuples,'age'))
|
335
|
+
# new_tuple.add('max_age',max(tuples,'age'))
|
336
|
+
# new_tuple.add('min_age',min(tuples,'age'))
|
337
|
+
# new_tuple.add('median_age',median(tuples,'age'))
|
338
|
+
# end
|
339
|
+
describe :summarize do
|
340
|
+
it 'returns a new relation with new columns' do
|
341
|
+
|
342
|
+
r1 = Relation.new(Tuple.new({:name => 'Bjorn', :person_id => 12})).add(Tuple.new({:name => 'Bjorn', :person_id => 119})).add(Tuple.new({:name => 'Marianna', :person_id => 9}))
|
343
|
+
r2 = Relation.new(Tuple.new({:name => 'Bjorn', :count => 2})).add(Tuple.new({:name => 'Marianna', :count => 1}))
|
344
|
+
|
345
|
+
r3 = r1.summarize(:name) do |tuple,relation|
|
346
|
+
tuple.add(:count => relation.count)
|
347
|
+
end
|
348
|
+
|
349
|
+
r3.should eql(r2)
|
350
|
+
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
|
355
|
+
|
356
|
+
end
|
357
|
+
|
358
|
+
|