alf 0.9.0

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.
Files changed (94) hide show
  1. data/CHANGELOG.md +5 -0
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +42 -0
  4. data/LICENCE.md +22 -0
  5. data/Manifest.txt +15 -0
  6. data/README.md +769 -0
  7. data/Rakefile +23 -0
  8. data/TODO.md +26 -0
  9. data/alf.gemspec +191 -0
  10. data/alf.noespec +30 -0
  11. data/bin/alf +31 -0
  12. data/examples/autonum.alf +6 -0
  13. data/examples/cities.rash +4 -0
  14. data/examples/clip.alf +3 -0
  15. data/examples/compact.alf +2 -0
  16. data/examples/database.alf +6 -0
  17. data/examples/defaults.alf +3 -0
  18. data/examples/extend.alf +3 -0
  19. data/examples/group.alf +3 -0
  20. data/examples/intersect.alf +4 -0
  21. data/examples/join.alf +2 -0
  22. data/examples/minus.alf +8 -0
  23. data/examples/nest.alf +2 -0
  24. data/examples/nulls.rash +3 -0
  25. data/examples/parts.rash +6 -0
  26. data/examples/project.alf +2 -0
  27. data/examples/quota.alf +4 -0
  28. data/examples/rename.alf +3 -0
  29. data/examples/restrict.alf +2 -0
  30. data/examples/runall.sh +26 -0
  31. data/examples/schema.yaml +28 -0
  32. data/examples/sort.alf +4 -0
  33. data/examples/summarize.alf +16 -0
  34. data/examples/suppliers.rash +5 -0
  35. data/examples/supplies.rash +12 -0
  36. data/examples/ungroup.alf +4 -0
  37. data/examples/union.alf +3 -0
  38. data/examples/unnest.alf +4 -0
  39. data/examples/with.alf +23 -0
  40. data/lib/alf.rb +2984 -0
  41. data/lib/alf/loader.rb +1 -0
  42. data/lib/alf/renderer/text.rb +153 -0
  43. data/lib/alf/renderer/yaml.rb +22 -0
  44. data/lib/alf/version.rb +14 -0
  45. data/spec/aggregator_spec.rb +62 -0
  46. data/spec/alf_spec.rb +47 -0
  47. data/spec/assumptions_spec.rb +15 -0
  48. data/spec/environment/explicit_spec.rb +15 -0
  49. data/spec/environment/folder_spec.rb +30 -0
  50. data/spec/examples_spec.rb +26 -0
  51. data/spec/lispy_spec.rb +23 -0
  52. data/spec/operator/command_methods_spec.rb +38 -0
  53. data/spec/operator/non_relational/autonum_spec.rb +61 -0
  54. data/spec/operator/non_relational/clip_spec.rb +49 -0
  55. data/spec/operator/non_relational/compact/buffer_based.rb +30 -0
  56. data/spec/operator/non_relational/compact/sort_based_spec.rb +30 -0
  57. data/spec/operator/non_relational/compact_spec.rb +38 -0
  58. data/spec/operator/non_relational/defaults_spec.rb +55 -0
  59. data/spec/operator/non_relational/sort_spec.rb +66 -0
  60. data/spec/operator/relational/extend_spec.rb +34 -0
  61. data/spec/operator/relational/group_spec.rb +54 -0
  62. data/spec/operator/relational/intersect_spec.rb +58 -0
  63. data/spec/operator/relational/join/hash_based_spec.rb +63 -0
  64. data/spec/operator/relational/minus_spec.rb +56 -0
  65. data/spec/operator/relational/nest_spec.rb +32 -0
  66. data/spec/operator/relational/project_spec.rb +65 -0
  67. data/spec/operator/relational/quota_spec.rb +44 -0
  68. data/spec/operator/relational/rename_spec.rb +32 -0
  69. data/spec/operator/relational/restrict_spec.rb +56 -0
  70. data/spec/operator/relational/summarize/sort_based_spec.rb +31 -0
  71. data/spec/operator/relational/summarize_spec.rb +41 -0
  72. data/spec/operator/relational/ungroup_spec.rb +35 -0
  73. data/spec/operator/relational/union_spec.rb +35 -0
  74. data/spec/operator/relational/unnest_spec.rb +32 -0
  75. data/spec/reader/alf_file_spec.rb +15 -0
  76. data/spec/reader/input.rb +2 -0
  77. data/spec/reader/rash_spec.rb +31 -0
  78. data/spec/reader_spec.rb +27 -0
  79. data/spec/renderer/text/cell_spec.rb +34 -0
  80. data/spec/renderer/text/row_spec.rb +30 -0
  81. data/spec/renderer/text/table_spec.rb +39 -0
  82. data/spec/renderer_spec.rb +42 -0
  83. data/spec/spec_helper.rb +26 -0
  84. data/spec/tools/ordering_key_spec.rb +81 -0
  85. data/spec/tools/projection_key_spec.rb +83 -0
  86. data/spec/tools/tools_spec.rb +25 -0
  87. data/spec/tools/tuple_handle_spec.rb +78 -0
  88. data/tasks/debug_mail.rake +78 -0
  89. data/tasks/debug_mail.txt +13 -0
  90. data/tasks/gem.rake +68 -0
  91. data/tasks/spec_test.rake +79 -0
  92. data/tasks/unit_test.rake +77 -0
  93. data/tasks/yard.rake +51 -0
  94. metadata +282 -0
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator::Relational
4
+ describe Union do
5
+
6
+ let(:operator_class){ Union }
7
+ it_should_behave_like("An operator class")
8
+
9
+ let(:left) {[
10
+ {:city => 'London'},
11
+ {:city => 'Paris'},
12
+ {:city => 'Paris'}
13
+ ]}
14
+
15
+ let(:right) {[
16
+ {:city => 'Oslo'},
17
+ {:city => 'Paris'}
18
+ ]}
19
+
20
+ let(:operator){ Union.run([]) }
21
+ subject{ operator.to_a }
22
+
23
+ describe "when applied on non disjoint sets" do
24
+ before{ operator.datasets = [left, right] }
25
+ let(:expected){[
26
+ {:city => 'London'},
27
+ {:city => 'Paris'},
28
+ {:city => 'Oslo'}
29
+ ]}
30
+ it { should == expected }
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator::Relational
4
+ describe Unnest do
5
+
6
+ let(:operator_class){ Unnest }
7
+ it_should_behave_like("An operator class")
8
+
9
+ let(:input) {[
10
+ {:nested => {:a => "a", :b => "b"}, :c => "c"}
11
+ ]}
12
+
13
+ let(:expected) {[
14
+ {:a => "a", :b => "b", :c => "c"},
15
+ ]}
16
+
17
+ subject{ operator.to_a }
18
+
19
+ describe "when factored with commandline args" do
20
+ let(:operator){ Unnest.run(%w{-- nested}) }
21
+ before{ operator.pipe(input) }
22
+ it { should == expected }
23
+ end
24
+
25
+ describe "when factored with Lispy" do
26
+ let(:operator){ Lispy.unnest(input, :nested) }
27
+ it { should == expected }
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ describe Reader::AlfFile do
4
+
5
+ let(:io){ StringIO.new "(restrict :suppliers, lambda{status > 20})" }
6
+ let(:reader){ Reader::AlfFile.new(io, self) }
7
+ def dataset(name)
8
+ [{:status => 10},{:status => 30}]
9
+ end
10
+
11
+ subject{ reader.to_a }
12
+ it{ should == [{:status => 30}]}
13
+
14
+ end
15
+ end
@@ -0,0 +1,2 @@
1
+ {:id => 1}
2
+ {:id => 2}
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ describe Reader::Rash do
4
+
5
+ let(:lines){ [{:id => 1},{:id => 2}] }
6
+ let(:str) { lines.collect{|s| s.inspect}.join("\n") }
7
+ let(:io) { StringIO.new(str) }
8
+
9
+ describe "when called on a StringIO" do
10
+
11
+ let(:reader){ Reader::Rash.new(io) }
12
+
13
+ it "should be enumerable" do
14
+ reader.to_a.should == lines
15
+ end
16
+
17
+ end
18
+
19
+ describe "when called on a String" do
20
+
21
+ let(:file){ File.expand_path('../input.rb', __FILE__) }
22
+ let(:reader){ Reader::Rash.new(file) }
23
+
24
+ it "should be enumerable" do
25
+ reader.to_a.should == lines
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ describe Reader do
4
+
5
+ subject{ Reader }
6
+ it { should respond_to(:rash) }
7
+
8
+ describe "rash" do
9
+ subject{ Reader.rash($stdin) }
10
+ it{ should be_a(Reader::Rash) }
11
+ end
12
+
13
+ describe "reader" do
14
+
15
+ specify "when associated" do
16
+ r = Reader.reader('suppliers.rash')
17
+ r.should be_a(Reader::Rash)
18
+ end
19
+
20
+ specify "when not associated" do
21
+ lambda{ Reader.reader('.noone') }.should raise_error
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ class Renderer::Text
4
+ describe Cell do
5
+
6
+ let(:f){ Cell.new }
7
+
8
+ specify "text_rendering" do
9
+ Cell.new(100).text_rendering.should == "100"
10
+ Cell.new(:hello).text_rendering.should == ":hello"
11
+ Cell.new("hello").text_rendering.should == "hello"
12
+ Cell.new(10.0).text_rendering.should == "10.0000000"
13
+ Cell.new(10/3.0).text_rendering.should == "3.3333333"
14
+ Cell.new([]).text_rendering.should == "[]"
15
+ Cell.new([10/3.0, true]).text_rendering.should == "[3.3333333, true]"
16
+ end
17
+
18
+ specify "min_width" do
19
+ Cell.new("").min_width.should == 0
20
+ Cell.new(10/3.0).min_width.should == 9
21
+ Cell.new("12\n5345").min_width.should == 4
22
+ end
23
+
24
+ specify "rendering_lines" do
25
+ Cell.new("").rendering_lines.should == []
26
+ Cell.new(10/3.0).rendering_lines.should == ["3.3333333"]
27
+ Cell.new([10/3.0,true]).rendering_lines.should == ["[3.3333333, true]"]
28
+ Cell.new("abc").rendering_lines(5).should == ["abc "]
29
+ Cell.new(12).rendering_lines(5).should == [" 12"]
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ class Renderer::Text
4
+ describe Row do
5
+
6
+ let(:row){ Row.new(values) }
7
+
8
+ describe "when single values are used only" do
9
+
10
+ let(:values){ [ 10/3.0, true ] }
11
+ specify "rendering_lines" do
12
+ row.rendering_lines.should == ["| 3.3333333 | true |"]
13
+ row.rendering_lines([10,5]).should == ["| 3.3333333 | true |"]
14
+ end
15
+
16
+ end
17
+
18
+ describe "when multiple-line values are used" do
19
+
20
+ let(:values){ [ 10/3.0, [1, 2, 3] ] }
21
+
22
+ specify "rendering_lines" do
23
+ row.rendering_lines.should == ["| 3.3333333 | [1, 2, 3] |"]
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ class Renderer::Text
4
+ describe Table do
5
+
6
+ let(:columns){ [ :method, :total ] }
7
+ let(:table){ Table.new(records, columns) }
8
+
9
+ describe "on an empty table" do
10
+
11
+ let(:records){ [ ] }
12
+
13
+ specify "render" do
14
+ table.render.should == "+---------+--------+\n" +
15
+ "| :method | :total |\n" +
16
+ "+---------+--------+\n" +
17
+ "+---------+--------+\n"
18
+ end
19
+
20
+ end
21
+
22
+ describe "when single values are used only" do
23
+
24
+ let(:records){ [ [:by_x, 10.0], [:by_y, 2.0] ] }
25
+
26
+ specify "render" do
27
+ table.render.should == "+---------+------------+\n" +
28
+ "| :method | :total |\n" +
29
+ "+---------+------------+\n" +
30
+ "| :by_x | 10.0000000 |\n" +
31
+ "| :by_y | 2.0000000 |\n" +
32
+ "+---------+------------+\n"
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ describe Renderer do
4
+
5
+ subject{ Renderer }
6
+ it { should respond_to(:rash) }
7
+ it { should respond_to(:text) }
8
+
9
+ describe 'renderer' do
10
+ subject{ Renderer.renderer(:rash) }
11
+ it{ should be_a(Renderer) }
12
+ end
13
+
14
+ describe 'rash' do
15
+ subject{ Renderer.rash(input) }
16
+ let(:input){ [{:a => 1}] }
17
+ let(:output){ "" }
18
+ let(:expected){ "{:a=>1}\n" }
19
+ specify{
20
+ subject.should be_a(Renderer)
21
+ subject.execute(output).should == expected
22
+ }
23
+ end
24
+
25
+ describe 'text' do
26
+ subject{ Renderer.text(input) }
27
+ let(:input){ [{:a => 1}] }
28
+ let(:output){ "" }
29
+ let(:expected){ "+----+\n"\
30
+ "| :a |\n"\
31
+ "+----+\n"\
32
+ "| 1 |\n"\
33
+ "+----+\n"
34
+ }
35
+ specify{
36
+ subject.should be_a(Renderer)
37
+ subject.execute(output).should == expected
38
+ }
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,26 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'alf'
3
+
4
+ Alf::Lispy.extend(Alf::Lispy)
5
+
6
+ shared_examples_for "An operator class" do
7
+
8
+ it "should not have public set_args, _each and _prepare methods" do
9
+ operator_class.public_method_defined?(:set_args).should be_false
10
+ operator_class.public_method_defined?(:_each).should be_false
11
+ operator_class.public_method_defined?(:_prepare).should be_false
12
+ end
13
+
14
+ it "should have a public run method" do
15
+ operator_class.public_method_defined?(:run).should be_true
16
+ end
17
+
18
+ it "should have a public pipe method" do
19
+ operator_class.public_method_defined?(:pipe).should be_true
20
+ end
21
+
22
+ it "should have a public each method" do
23
+ operator_class.public_method_defined?(:each).should be_true
24
+ end
25
+
26
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Tools
4
+ describe OrderingKey do
5
+
6
+ describe "coerce" do
7
+
8
+ specify "when passed an doubly array" do
9
+ key = OrderingKey.coerce [[:a, :asc], [:b, :desc]]
10
+ key.attributes.should == [:a, :b]
11
+ key.order_of(:a).should == :asc
12
+ key.order_of(:b).should == :desc
13
+ end
14
+
15
+ specify "when passed a single array" do
16
+ key = OrderingKey.coerce [:a, :b]
17
+ key.attributes.should == [:a, :b]
18
+ key.order_of(:a).should == :asc
19
+ key.order_of(:b).should == :asc
20
+ end
21
+
22
+ specify "when passed an ordering key" do
23
+ key = OrderingKey.coerce [:a, :b]
24
+ key2 = OrderingKey.coerce key
25
+ key.should == key2
26
+ end
27
+
28
+ specify "when passed a projection key" do
29
+ pkey = ProjectionKey.new [:a, :b]
30
+ key = OrderingKey.coerce pkey
31
+ key.attributes.should == [:a, :b]
32
+ key.order_of(:a).should == :asc
33
+ key.order_of(:b).should == :asc
34
+ end
35
+
36
+ end # coerce
37
+
38
+ describe "compare" do
39
+
40
+ specify "when passed a single key" do
41
+ key = OrderingKey.coerce [:a]
42
+ key.compare({:a => 1}, {:a => 2}).should == -1
43
+ key.compare({:a => 1}, {:a => 1}).should == 0
44
+ key.compare({:a => 2}, {:a => 1}).should == 1
45
+ end
46
+
47
+ specify "when passed a single key with desc order" do
48
+ key = OrderingKey.coerce [[:a, :desc]]
49
+ key.compare({:a => 1}, {:a => 2}).should == 1
50
+ key.compare({:a => 1}, {:a => 1}).should == 0
51
+ key.compare({:a => 2}, {:a => 1}).should == -1
52
+ end
53
+
54
+ specify "when passed a double key" do
55
+ key = OrderingKey.coerce [[:a, :asc], [:b, :desc]]
56
+ key.compare({:a => 1, :b => 1}, {:a => 0, :b => 1}).should == 1
57
+ key.compare({:a => 1, :b => 1}, {:a => 1, :b => 2}).should == 1
58
+ key.compare({:a => 1, :b => 1}, {:a => 1, :b => 1}).should == 0
59
+ end
60
+
61
+ end
62
+
63
+ describe "+" do
64
+
65
+ specify "when passed another key" do
66
+ key = OrderingKey.coerce [:a]
67
+ key2 = key + OrderingKey.coerce([[:b, :desc]])
68
+ key2.ordering.should == [[:a, :asc], [:b, :desc]]
69
+ end
70
+
71
+ specify "when passed another array" do
72
+ key = OrderingKey.coerce [:a]
73
+ key2 = key + [[:b, :desc]]
74
+ key2.ordering.should == [[:a, :asc], [:b, :desc]]
75
+ end
76
+
77
+ end
78
+
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Tools
4
+ describe ProjectionKey do
5
+
6
+ describe "coerce" do
7
+
8
+ specify "when passed an array" do
9
+ key = ProjectionKey.coerce [:a, :b]
10
+ key.attributes.should == [:a, :b]
11
+ key.allbut.should == false
12
+ end
13
+
14
+ specify "when passed a ProjectionKey" do
15
+ key = ProjectionKey.coerce [:a, :b]
16
+ key2 = ProjectionKey.coerce key
17
+ key2.should == key
18
+ end
19
+
20
+ specify "when passed an OrderingKey" do
21
+ okey = OrderingKey.new [[:a, :asc], [:b, :asc]]
22
+ key = ProjectionKey.coerce(okey)
23
+ key.attributes.should == [:a, :b]
24
+ key.allbut.should == false
25
+ end
26
+
27
+ end
28
+
29
+ describe "to_ordering_key" do
30
+
31
+ specify "when passed an array" do
32
+ key = ProjectionKey.coerce [:a, :b]
33
+ okey = key.to_ordering_key
34
+ okey.attributes.should == [:a, :b]
35
+ okey.order_of(:a).should == :asc
36
+ okey.order_of(:b).should == :asc
37
+ end
38
+
39
+ end
40
+
41
+ describe "split" do
42
+
43
+ subject{ key.split(tuple) }
44
+
45
+ describe "when used without allbut" do
46
+ let(:key){ ProjectionKey.new [:a, :b] }
47
+ let(:tuple){ {:a => 1, :b => 2, :c => 3} }
48
+ let(:expected){ [{:a => 1, :b => 2}, {:c => 3}] }
49
+ it{ should == expected }
50
+ end
51
+
52
+ describe "when used with allbut" do
53
+ let(:key){ ProjectionKey.new [:a, :b], true }
54
+ let(:tuple){ {:a => 1, :b => 2, :c => 3} }
55
+ let(:expected){ [{:c => 3}, {:a => 1, :b => 2}] }
56
+ it{ should == expected }
57
+ end
58
+
59
+ end
60
+
61
+ describe "project" do
62
+
63
+ subject{ key.project(tuple) }
64
+
65
+ describe "when used without allbut" do
66
+ let(:key){ ProjectionKey.new [:a, :b] }
67
+ let(:tuple){ {:a => 1, :b => 2, :c => 3} }
68
+ let(:expected){ {:a => 1, :b => 2} }
69
+ it{ should == expected }
70
+ end
71
+
72
+ describe "when used with allbut" do
73
+ let(:key){ ProjectionKey.new [:a, :b], true }
74
+ let(:tuple){ {:a => 1, :b => 2, :c => 3} }
75
+ let(:expected){ {:c => 3} }
76
+ it{ should == expected }
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+ end
83
+ end