alf 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +64 -0
- data/Gemfile.lock +4 -4
- data/README.md +257 -171
- data/TODO.md +4 -4
- data/alf.gemspec +3 -3
- data/alf.noespec +11 -6
- data/examples/pseudo-with.alf +7 -0
- data/examples/runall.sh +2 -2
- data/examples/unwrap.alf +4 -0
- data/examples/wrap.alf +2 -0
- data/lib/alf/relation.rb +118 -0
- data/lib/alf/version.rb +1 -1
- data/lib/alf.rb +320 -169
- data/spec/integration/src/test_minus.alf +5 -0
- data/spec/integration/src/test_project.alf +9 -0
- data/spec/{alf_spec.rb → integration/test_alf.rb} +8 -21
- data/spec/integration/test_alf_specs.rb +37 -0
- data/spec/{examples_spec.rb → integration/test_examples.rb} +1 -1
- data/spec/spec_helper.rb +19 -1
- data/spec/unit/environment/examples/suppliers.rash +5 -0
- data/spec/{environment/explicit_spec.rb → unit/environment/test_explicit.rb} +0 -0
- data/spec/{environment/folder_spec.rb → unit/environment/test_folder.rb} +1 -1
- data/spec/{operator → unit/operator}/non_relational/compact/buffer_based.rb +0 -0
- data/spec/{operator/non_relational/compact/sort_based_spec.rb → unit/operator/non_relational/compact/test_sort_based.rb} +0 -0
- data/spec/{operator/non_relational/autonum_spec.rb → unit/operator/non_relational/test_autonum.rb} +0 -0
- data/spec/{operator/non_relational/clip_spec.rb → unit/operator/non_relational/test_clip.rb} +0 -0
- data/spec/{operator/non_relational/compact_spec.rb → unit/operator/non_relational/test_compact.rb} +0 -0
- data/spec/{operator/non_relational/defaults_spec.rb → unit/operator/non_relational/test_defaults.rb} +0 -0
- data/spec/{operator/non_relational/sort_spec.rb → unit/operator/non_relational/test_sort.rb} +0 -0
- data/spec/{operator/relational/join/hash_based_spec.rb → unit/operator/relational/join/test_hash_based.rb} +0 -0
- data/spec/unit/operator/relational/summarize/test_hash_based.rb +38 -0
- data/spec/{operator/relational/summarize/sort_based_spec.rb → unit/operator/relational/summarize/test_sort_based.rb} +0 -0
- data/spec/{operator/relational/extend_spec.rb → unit/operator/relational/test_extend.rb} +0 -0
- data/spec/{operator/relational/group_spec.rb → unit/operator/relational/test_group.rb} +3 -2
- data/spec/{operator/relational/intersect_spec.rb → unit/operator/relational/test_intersect.rb} +0 -0
- data/spec/unit/operator/relational/test_join.rb +36 -0
- data/spec/{operator/relational/minus_spec.rb → unit/operator/relational/test_minus.rb} +0 -0
- data/spec/{operator/relational/project_spec.rb → unit/operator/relational/test_project.rb} +0 -0
- data/spec/{operator/relational/quota_spec.rb → unit/operator/relational/test_quota.rb} +0 -0
- data/spec/{operator/relational/rename_spec.rb → unit/operator/relational/test_rename.rb} +0 -0
- data/spec/{operator/relational/restrict_spec.rb → unit/operator/relational/test_restrict.rb} +0 -0
- data/spec/unit/operator/relational/test_summarize.rb +64 -0
- data/spec/{operator/relational/ungroup_spec.rb → unit/operator/relational/test_ungroup.rb} +0 -0
- data/spec/{operator/relational/union_spec.rb → unit/operator/relational/test_union.rb} +0 -0
- data/spec/{operator/relational/unnest_spec.rb → unit/operator/relational/test_unwrap.rb} +5 -5
- data/spec/{operator/relational/nest_spec.rb → unit/operator/relational/test_wrap.rb} +5 -5
- data/spec/{operator/command_methods_spec.rb → unit/operator/test_command_methods.rb} +0 -0
- data/spec/unit/operator/test_non_relational.rb +18 -0
- data/spec/unit/operator/test_relational.rb +27 -0
- data/spec/{reader → unit/reader}/input.rb +0 -0
- data/spec/unit/reader/test_alf_file.rb +27 -0
- data/spec/{reader/rash_spec.rb → unit/reader/test_rash.rb} +0 -0
- data/spec/unit/relation/test_coerce.rb +53 -0
- data/spec/unit/relation/test_inspect.rb +20 -0
- data/spec/unit/relation/test_relops.rb +46 -0
- data/spec/{renderer/text/cell_spec.rb → unit/renderer/text/test_cell.rb} +0 -0
- data/spec/{renderer/text/row_spec.rb → unit/renderer/text/test_row.rb} +0 -0
- data/spec/{renderer/text/table_spec.rb → unit/renderer/text/test_table.rb} +0 -0
- data/spec/{aggregator_spec.rb → unit/test_aggregator.rb} +6 -6
- data/spec/{assumptions_spec.rb → unit/test_assumptions.rb} +0 -0
- data/spec/{lispy_spec.rb → unit/test_lispy.rb} +0 -0
- data/spec/unit/test_operator.rb +16 -0
- data/spec/{reader_spec.rb → unit/test_reader.rb} +4 -0
- data/spec/unit/test_relation.rb +40 -0
- data/spec/{renderer_spec.rb → unit/test_renderer.rb} +0 -0
- data/spec/{tools/ordering_key_spec.rb → unit/tools/test_ordering_key.rb} +0 -0
- data/spec/{tools/projection_key_spec.rb → unit/tools/test_projection_key.rb} +0 -0
- data/spec/{tools/tools_spec.rb → unit/tools/test_tools.rb} +0 -0
- data/spec/{tools/tuple_handle_spec.rb → unit/tools/test_tuple_handle.rb} +0 -0
- data/tasks/clean.rake +3 -0
- data/tasks/spec_test.rake +1 -1
- metadata +143 -114
- data/examples/nest.alf +0 -2
- data/examples/unnest.alf +0 -4
- data/examples/with.alf +0 -23
- data/spec/operator/relational/summarize_spec.rb +0 -41
- data/spec/reader/alf_file_spec.rb +0 -15
@@ -18,30 +18,17 @@ describe Alf do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it "should allow compiling lispy expressions" do
|
21
|
-
lispy.compile{
|
21
|
+
lispy.compile {
|
22
22
|
(restrict :suppliers, lambda{ city == 'London'})
|
23
23
|
}.to_a.should == expected
|
24
24
|
end
|
25
|
-
|
26
|
-
it "should allow defining temporary expressions" do
|
27
|
-
lispy.compile{
|
28
|
-
with(:sup => (dataset :suppliers)) do
|
29
|
-
(restrict :sup, lambda{ city == 'London'})
|
30
|
-
end
|
31
|
-
}.to_a.should == expected
|
32
|
-
end
|
33
25
|
|
34
|
-
it "should allow
|
35
|
-
|
36
|
-
(restrict :suppliers, lambda{
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
41
|
-
projection.to_a.should == [
|
42
|
-
{:city => 'Paris'},
|
43
|
-
{:city => 'Athens'}
|
44
|
-
]
|
26
|
+
it "should allow evaluating lispy expressions" do
|
27
|
+
rel = lispy.evaluate {
|
28
|
+
(restrict :suppliers, lambda{ city == 'London'})
|
29
|
+
}
|
30
|
+
rel.should be_a(Alf::Relation)
|
31
|
+
rel.should eq(Alf::Relation.coerce(expected))
|
45
32
|
end
|
46
|
-
|
33
|
+
|
47
34
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe "Alf's integration tests" do
|
3
|
+
|
4
|
+
module Helpers
|
5
|
+
|
6
|
+
def rel_equal(x, y)
|
7
|
+
x.to_rel == y.to_rel
|
8
|
+
end
|
9
|
+
|
10
|
+
def specify(message, x)
|
11
|
+
raise message unless x
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
shared_examples_for "An integration file" do
|
17
|
+
|
18
|
+
let(:lispy){
|
19
|
+
lispy = Alf.lispy(Alf::Environment.examples)
|
20
|
+
lispy.ruby_extend(Helpers)
|
21
|
+
}
|
22
|
+
|
23
|
+
it "should work when executed with a Alf" do
|
24
|
+
lispy.compile(File.read(subject))
|
25
|
+
end
|
26
|
+
|
27
|
+
end # An example
|
28
|
+
|
29
|
+
|
30
|
+
Dir["#{File.expand_path('../src', __FILE__)}/**/*.alf"].each do |file|
|
31
|
+
describe file do
|
32
|
+
subject{ file }
|
33
|
+
it_should_behave_like "An integration file"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -15,7 +15,7 @@ module Alf
|
|
15
15
|
end # An example
|
16
16
|
|
17
17
|
|
18
|
-
Dir["#{File.expand_path('
|
18
|
+
Dir["#{File.expand_path('../../../examples', __FILE__)}/**/*.alf"].each do |file|
|
19
19
|
describe file do
|
20
20
|
subject{ file }
|
21
21
|
it_should_behave_like "An example"
|
data/spec/spec_helper.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
-
$LOAD_PATH.unshift File.expand_path('
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../../../lib', __FILE__)
|
2
2
|
require 'alf'
|
3
3
|
|
4
4
|
Alf::Lispy.extend(Alf::Lispy)
|
5
5
|
|
6
|
+
def rel(*args)
|
7
|
+
Alf::Relation.coerce(args)
|
8
|
+
end
|
9
|
+
|
6
10
|
shared_examples_for "An operator class" do
|
7
11
|
|
8
12
|
it "should not have public set_args, _each and _prepare methods" do
|
@@ -22,5 +26,19 @@ shared_examples_for "An operator class" do
|
|
22
26
|
it "should have a public each method" do
|
23
27
|
operator_class.public_method_defined?(:each).should be_true
|
24
28
|
end
|
29
|
+
|
30
|
+
it "should have a unary? class method" do
|
31
|
+
operator_class.should respond_to(:unary?)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should have a binary? class method" do
|
35
|
+
operator_class.should respond_to(:binary?)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should implement unary? and binary? accurately" do
|
39
|
+
operator_class.unary?.should_not eq(operator_class.binary?)
|
40
|
+
operator_class.unary?.should eq(operator_class.ancestors.include?(Alf::Operator::Unary))
|
41
|
+
operator_class.binary?.should eq(operator_class.ancestors.include?(Alf::Operator::Binary))
|
42
|
+
end
|
25
43
|
|
26
44
|
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
{:sid => 'S1', :name => 'Smith', :status => 20, :city => 'London'}
|
2
|
+
{:sid => 'S2', :name => 'Jones', :status => 10, :city => 'Paris'}
|
3
|
+
{:sid => 'S3', :name => 'Blake', :status => 30, :city => 'Paris'}
|
4
|
+
{:sid => 'S4', :name => 'Clark', :status => 20, :city => 'London'}
|
5
|
+
{:sid => 'S5', :name => 'Adams', :status => 30, :city => 'Athens'}
|
File without changes
|
File without changes
|
File without changes
|
data/spec/{operator/non_relational/autonum_spec.rb → unit/operator/non_relational/test_autonum.rb}
RENAMED
File without changes
|
data/spec/{operator/non_relational/clip_spec.rb → unit/operator/non_relational/test_clip.rb}
RENAMED
File without changes
|
data/spec/{operator/non_relational/compact_spec.rb → unit/operator/non_relational/test_compact.rb}
RENAMED
File without changes
|
data/spec/{operator/non_relational/defaults_spec.rb → unit/operator/non_relational/test_defaults.rb}
RENAMED
File without changes
|
data/spec/{operator/non_relational/sort_spec.rb → unit/operator/non_relational/test_sort.rb}
RENAMED
File without changes
|
File without changes
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
module Operator::Relational
|
4
|
+
describe Summarize::HashBased do
|
5
|
+
|
6
|
+
let(:input) {[
|
7
|
+
{:a => "via_method", :time => 1},
|
8
|
+
{:a => "via_reader", :time => 4},
|
9
|
+
{:a => "via_method", :time => 2},
|
10
|
+
{:a => "via_reader", :time => 2},
|
11
|
+
{:a => "via_method", :time => 1},
|
12
|
+
]}
|
13
|
+
|
14
|
+
let(:expected) {[
|
15
|
+
{:a => "via_method", :time_sum => 4, :time_max => 2},
|
16
|
+
{:a => "via_reader", :time_sum => 6, :time_max => 4},
|
17
|
+
]}
|
18
|
+
|
19
|
+
let(:aggs){{:time_sum => Aggregator.sum(:time),
|
20
|
+
:time_max => Aggregator.max(:time)}}
|
21
|
+
let(:operator){ Summarize::HashBased.new(by_key, aggs) }
|
22
|
+
|
23
|
+
before{ operator.pipe(input) }
|
24
|
+
subject{ operator.to_a.sort{|t1,t2| t1[:a] <=> t2[:a]} }
|
25
|
+
|
26
|
+
describe "when allbut is not set" do
|
27
|
+
let(:by_key){ Tools::ProjectionKey.new([:a], false) }
|
28
|
+
it { should == expected }
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "when allbut is set" do
|
32
|
+
let(:by_key){ Tools::ProjectionKey.new([:time], true) }
|
33
|
+
it { should == expected }
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
File without changes
|
File without changes
|
@@ -13,8 +13,9 @@ module Alf
|
|
13
13
|
]}
|
14
14
|
|
15
15
|
let(:expected) {[
|
16
|
-
{:a => "via_method", :as =>
|
17
|
-
|
16
|
+
{:a => "via_method", :as => rel({:time => 1, :b => "b"},
|
17
|
+
{:time => 2, :b => "b"})},
|
18
|
+
{:a => "via_reader", :as => rel({:time => 3, :b => "b"})},
|
18
19
|
]}
|
19
20
|
|
20
21
|
subject{ operator.to_a.sort{|k1,k2| k1[:a] <=> k2[:a]} }
|
data/spec/{operator/relational/intersect_spec.rb → unit/operator/relational/test_intersect.rb}
RENAMED
File without changes
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
module Operator::Relational
|
4
|
+
describe Join do
|
5
|
+
|
6
|
+
let(:suppliers){Relation.coerce [
|
7
|
+
{:sid => 'S1', :city => 'London'},
|
8
|
+
{:sid => 'S2', :city => 'Paris'},
|
9
|
+
{:sid => 'S3', :city => 'Paris'},
|
10
|
+
{:sid => 'S4', :city => 'London'},
|
11
|
+
{:sid => 'S5', :city => 'Athens'},
|
12
|
+
]}
|
13
|
+
|
14
|
+
describe "when applied to sub-relations" do
|
15
|
+
let(:suppliers_by_city){Relation.coerce(
|
16
|
+
Lispy.group(suppliers, [:sid], :suppliers)
|
17
|
+
)}
|
18
|
+
let(:s2_s3){Relation.coerce([
|
19
|
+
{:sid => 'S3'},
|
20
|
+
{:sid => 'S2'}
|
21
|
+
])}
|
22
|
+
let(:right){Relation.coerce([
|
23
|
+
{:suppliers => s2_s3, :hello => "world"}
|
24
|
+
])}
|
25
|
+
let(:expected){Relation.coerce([
|
26
|
+
{:suppliers => s2_s3, :hello => "world", :city => 'Paris'}
|
27
|
+
])}
|
28
|
+
subject{Relation.coerce(
|
29
|
+
Lispy.join(suppliers_by_city, right)
|
30
|
+
)}
|
31
|
+
it{ should == expected }
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/spec/{operator/relational/restrict_spec.rb → unit/operator/relational/test_restrict.rb}
RENAMED
File without changes
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
module Operator::Relational
|
4
|
+
describe Summarize do
|
5
|
+
|
6
|
+
let(:operator_class){ Summarize }
|
7
|
+
it_should_behave_like("An operator class")
|
8
|
+
|
9
|
+
let(:input) {[
|
10
|
+
{:a => "via_reader", :time => 2},
|
11
|
+
{:a => "via_method", :time => 1},
|
12
|
+
{:a => "via_method", :time => 2},
|
13
|
+
{:a => "via_reader", :time => 4},
|
14
|
+
{:a => "via_method", :time => 1},
|
15
|
+
]}
|
16
|
+
|
17
|
+
let(:expected) {[
|
18
|
+
{:a => "via_method", :time_sum => 4, :time_max => 2, :time_avg => 4.0/3},
|
19
|
+
{:a => "via_reader", :time_sum => 6, :time_max => 4, :time_avg => 6.0/2},
|
20
|
+
]}
|
21
|
+
|
22
|
+
let(:aggs){{:time_sum => Aggregator.sum(:time),
|
23
|
+
:time_max => Aggregator.max(:time),
|
24
|
+
:time_avg => Aggregator.avg(:time)}}
|
25
|
+
|
26
|
+
subject{ operator.to_a.sort{|t1,t2| t1[:a] <=> t2[:a]} }
|
27
|
+
|
28
|
+
describe "without allbut" do
|
29
|
+
|
30
|
+
describe "When factored with commandline args" do
|
31
|
+
let(:opts){ ["--by=a"] }
|
32
|
+
let(:aggs){ ["time_sum", "sum(:time)", "time_max", "max(:time)", "time_avg", "avg(:time)"] }
|
33
|
+
let(:operator){ Summarize.run(opts + ["--"] +aggs) }
|
34
|
+
before{ operator.pipe(input) }
|
35
|
+
it { should == expected }
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "When factored with Lispy" do
|
39
|
+
let(:operator){ Lispy.summarize(input, [:a], aggs) }
|
40
|
+
it { should == expected }
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "with allbut" do
|
46
|
+
|
47
|
+
describe "When factored with commandline args" do
|
48
|
+
let(:opts){ ["--by=time", "--allbut"] }
|
49
|
+
let(:aggs){ ["time_sum", "sum(:time)", "time_max", "max(:time)", "time_avg", "avg(:time)"] }
|
50
|
+
let(:operator){ Summarize.run(opts + ["--"] + aggs) }
|
51
|
+
before{ operator.pipe(input) }
|
52
|
+
it { should == expected }
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "When factored with Lispy" do
|
56
|
+
let(:operator){ Lispy.summarize(input, [:time], aggs, true) }
|
57
|
+
it { should == expected }
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
File without changes
|
File without changes
|
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
module Alf
|
3
3
|
module Operator::Relational
|
4
|
-
describe
|
4
|
+
describe Unwrap do
|
5
5
|
|
6
|
-
let(:operator_class){
|
6
|
+
let(:operator_class){ Unwrap }
|
7
7
|
it_should_behave_like("An operator class")
|
8
8
|
|
9
9
|
let(:input) {[
|
10
|
-
{:
|
10
|
+
{:wrapped => {:a => "a", :b => "b"}, :c => "c"}
|
11
11
|
]}
|
12
12
|
|
13
13
|
let(:expected) {[
|
@@ -17,13 +17,13 @@ module Alf
|
|
17
17
|
subject{ operator.to_a }
|
18
18
|
|
19
19
|
describe "when factored with commandline args" do
|
20
|
-
let(:operator){
|
20
|
+
let(:operator){ Unwrap.run(%w{-- wrapped}) }
|
21
21
|
before{ operator.pipe(input) }
|
22
22
|
it { should == expected }
|
23
23
|
end
|
24
24
|
|
25
25
|
describe "when factored with Lispy" do
|
26
|
-
let(:operator){ Lispy.
|
26
|
+
let(:operator){ Lispy.unwrap(input, :wrapped) }
|
27
27
|
it { should == expected }
|
28
28
|
end
|
29
29
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
module Alf
|
3
3
|
module Operator::Relational
|
4
|
-
describe
|
4
|
+
describe Wrap do
|
5
5
|
|
6
|
-
let(:operator_class){
|
6
|
+
let(:operator_class){ Wrap }
|
7
7
|
it_should_behave_like("An operator class")
|
8
8
|
|
9
9
|
let(:input) {[
|
@@ -11,19 +11,19 @@ module Alf
|
|
11
11
|
]}
|
12
12
|
|
13
13
|
let(:expected) {[
|
14
|
-
{:
|
14
|
+
{:wraped => {:a => "a", :b => "b"}, :c => "c"}
|
15
15
|
]}
|
16
16
|
|
17
17
|
subject{ operator.to_a }
|
18
18
|
|
19
19
|
describe "when factored with commandline args" do
|
20
|
-
let(:operator){
|
20
|
+
let(:operator){ Wrap.run(["--", "a", "b", "wraped"]) }
|
21
21
|
before{ operator.pipe(input) }
|
22
22
|
it { should == expected }
|
23
23
|
end
|
24
24
|
|
25
25
|
describe "when factored with Lispy" do
|
26
|
-
let(:operator){ Lispy.
|
26
|
+
let(:operator){ Lispy.wrap(input, [:a, :b], :wraped) }
|
27
27
|
it { should == expected }
|
28
28
|
end
|
29
29
|
|
File without changes
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
describe Operator::NonRelational do
|
4
|
+
|
5
|
+
specify "each" do
|
6
|
+
x = []
|
7
|
+
Operator::NonRelational.each{|m| x << m}
|
8
|
+
x.sort{|m1,m2| m1.name.to_s <=> m2.name.to_s}.should == [
|
9
|
+
Alf::Operator::NonRelational::Autonum,
|
10
|
+
Alf::Operator::NonRelational::Clip,
|
11
|
+
Alf::Operator::NonRelational::Compact,
|
12
|
+
Alf::Operator::NonRelational::Defaults,
|
13
|
+
Alf::Operator::NonRelational::Sort,
|
14
|
+
]
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
describe Operator::Relational do
|
4
|
+
|
5
|
+
specify "each" do
|
6
|
+
x = []
|
7
|
+
Operator::Relational.each{|m| x << m}
|
8
|
+
x.sort{|m1,m2| m1.name.to_s <=> m2.name.to_s}.should == [
|
9
|
+
Alf::Operator::Relational::Extend,
|
10
|
+
Alf::Operator::Relational::Group,
|
11
|
+
Alf::Operator::Relational::Intersect,
|
12
|
+
Alf::Operator::Relational::Join,
|
13
|
+
Alf::Operator::Relational::Minus,
|
14
|
+
Alf::Operator::Relational::Project,
|
15
|
+
Alf::Operator::Relational::Quota,
|
16
|
+
Alf::Operator::Relational::Rename,
|
17
|
+
Alf::Operator::Relational::Restrict,
|
18
|
+
Alf::Operator::Relational::Summarize,
|
19
|
+
Alf::Operator::Relational::Ungroup,
|
20
|
+
Alf::Operator::Relational::Union,
|
21
|
+
Alf::Operator::Relational::Unwrap,
|
22
|
+
Alf::Operator::Relational::Wrap,
|
23
|
+
]
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
File without changes
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
describe Reader::AlfFile do
|
4
|
+
|
5
|
+
let(:io){ StringIO.new(expr) }
|
6
|
+
def dataset(name)
|
7
|
+
[{:status => 10},{:status => 30}]
|
8
|
+
end
|
9
|
+
subject{ Reader::AlfFile.new(io, self).to_a }
|
10
|
+
|
11
|
+
describe "on pure functional expressions" do
|
12
|
+
let(:expr){ "(restrict :suppliers, lambda{status > 20})" }
|
13
|
+
it{ should == [{:status => 30}]}
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "on impure functional expressions" do
|
17
|
+
let(:expr){
|
18
|
+
<<-EOF
|
19
|
+
xxx = (restrict :suppliers, lambda{status > 20})
|
20
|
+
(extend xxx, :rev => lambda{ -status })
|
21
|
+
EOF
|
22
|
+
}
|
23
|
+
it{ should == [{:status => 30, :rev => -30}]}
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
File without changes
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
describe Relation do
|
4
|
+
|
5
|
+
let(:tuples_by_sid){[
|
6
|
+
{:sid => 'S1', :name => 'Smith', :status => 20, :city => 'London'},
|
7
|
+
{:sid => 'S2', :name => 'Jones', :status => 10, :city => 'Paris'},
|
8
|
+
{:sid => 'S3', :name => 'Blake', :status => 30, :city => 'Paris'}
|
9
|
+
]}
|
10
|
+
let(:rel){ Relation.new tuples_by_sid.to_set }
|
11
|
+
let(:tuples_by_name){ tuples_by_sid.sort{|t1,t2| t1[:name] <=> t2[:name]} }
|
12
|
+
|
13
|
+
describe "coerce" do
|
14
|
+
|
15
|
+
subject{ Relation.coerce(arg) }
|
16
|
+
|
17
|
+
describe "with a Relation" do
|
18
|
+
let(:arg){ rel }
|
19
|
+
it{ should be_a(Relation) }
|
20
|
+
it{ should == rel }
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "with a set of tuples" do
|
24
|
+
let(:arg){ tuples_by_name.to_set }
|
25
|
+
it{ should be_a(Relation) }
|
26
|
+
it{ should == rel }
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "with an array of tuples" do
|
30
|
+
let(:arg){ tuples_by_name }
|
31
|
+
it{ should be_a(Relation) }
|
32
|
+
it{ should == rel }
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "with an iterator" do
|
36
|
+
let(:arg){ Lispy.restrict(tuples_by_name, lambda{ true }) }
|
37
|
+
it{ should be_a(Relation) }
|
38
|
+
it{ should == rel }
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "with unrecognized arg" do
|
42
|
+
let(:arg){ nil }
|
43
|
+
specify{ lambda{ subject }.should raise_error(ArgumentError) }
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should be semi-aliased as []" do
|
47
|
+
Alf::Relation[*tuples_by_name].should == rel
|
48
|
+
end
|
49
|
+
|
50
|
+
end # coerce
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
describe Relation do
|
4
|
+
|
5
|
+
let(:rel){Relation.coerce([
|
6
|
+
{:sid => 'S1'},
|
7
|
+
{:sid => 'S2'},
|
8
|
+
{:sid => 'S3'}
|
9
|
+
])}
|
10
|
+
|
11
|
+
describe "inspect" do
|
12
|
+
|
13
|
+
it "should allows the litteral round-trip" do
|
14
|
+
Kernel.eval(rel.inspect).should == rel
|
15
|
+
end
|
16
|
+
|
17
|
+
end # coerce
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
describe Relation do
|
4
|
+
|
5
|
+
let(:rel1){rel(
|
6
|
+
{:sid => 'S1'},
|
7
|
+
{:sid => 'S2'},
|
8
|
+
{:sid => 'S3'}
|
9
|
+
)}
|
10
|
+
|
11
|
+
let(:rel2){rel(
|
12
|
+
{:sid => 'S5'},
|
13
|
+
{:sid => 'S2'}
|
14
|
+
)}
|
15
|
+
|
16
|
+
specify "extend" do
|
17
|
+
rel1.extend(:x => lambda{ sid.downcase }).should == rel(
|
18
|
+
{:sid => 'S1', :x => 's1'},
|
19
|
+
{:sid => 'S2', :x => 's2'},
|
20
|
+
{:sid => 'S3', :x => 's3'}
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
specify "union" do
|
25
|
+
(rel1 + rel1).should == rel1
|
26
|
+
(rel1 + rel2).should == rel(
|
27
|
+
{:sid => 'S1'},
|
28
|
+
{:sid => 'S3'},
|
29
|
+
{:sid => 'S2'},
|
30
|
+
{:sid => 'S5'}
|
31
|
+
)
|
32
|
+
end # coerce
|
33
|
+
|
34
|
+
specify "difference" do
|
35
|
+
(rel1 - rel1).should == rel()
|
36
|
+
(rel1 - rel2).should == rel(
|
37
|
+
{:sid => 'S1'},
|
38
|
+
{:sid => 'S3'}
|
39
|
+
)
|
40
|
+
(rel2 - rel1).should == rel(
|
41
|
+
{:sid => 'S5'}
|
42
|
+
)
|
43
|
+
end # coerce
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
@@ -42,16 +42,16 @@ module Alf
|
|
42
42
|
end
|
43
43
|
|
44
44
|
it "should behave correctly on group" do
|
45
|
-
Aggregator.group(:a).aggregate(input).should ==
|
45
|
+
Aggregator.group(:a).aggregate(input).should == rel(
|
46
46
|
{:a => 1},
|
47
47
|
{:a => 2},
|
48
|
-
{:a => 3}
|
49
|
-
|
50
|
-
Aggregator.group(:a, :sign).aggregate(input).should ==
|
48
|
+
{:a => 3}
|
49
|
+
)
|
50
|
+
Aggregator.group(:a, :sign).aggregate(input).should == rel(
|
51
51
|
{:a => 1, :sign => -1},
|
52
52
|
{:a => 2, :sign => 1 },
|
53
|
-
{:a => 3, :sign => -1}
|
54
|
-
|
53
|
+
{:a => 3, :sign => -1}
|
54
|
+
)
|
55
55
|
end
|
56
56
|
|
57
57
|
it "should allow specific tuple computations" do
|