alf 0.9.3 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +255 -129
- data/Gemfile +31 -1
- data/Gemfile.lock +17 -20
- data/LICENCE.md +1 -1
- data/Manifest.txt +2 -0
- data/README.md +37 -43
- data/TODO.md +1 -1
- data/alf.gemspec +10 -7
- data/alf.noespec +24 -13
- data/bin/alf +2 -2
- data/doc/commands/exec.md +16 -0
- data/doc/commands/help.md +11 -0
- data/doc/commands/main.md +33 -0
- data/doc/commands/show.md +19 -0
- data/doc/operators/non_relational/autonum.md +23 -0
- data/doc/operators/non_relational/clip.md +31 -0
- data/doc/operators/non_relational/coerce.md +15 -0
- data/doc/operators/non_relational/compact.md +20 -0
- data/doc/operators/non_relational/defaults.md +32 -0
- data/doc/operators/non_relational/generator.md +20 -0
- data/doc/operators/non_relational/sort.md +24 -0
- data/doc/operators/relational/extend.md +18 -0
- data/doc/operators/relational/group.md +27 -0
- data/doc/operators/relational/intersect.md +13 -0
- data/doc/operators/relational/join.md +27 -0
- data/doc/operators/relational/matching.md +20 -0
- data/doc/operators/relational/minus.md +12 -0
- data/doc/operators/relational/not-matching.md +20 -0
- data/doc/operators/relational/project.md +28 -0
- data/doc/operators/relational/quota.md +21 -0
- data/doc/operators/relational/rank.md +27 -0
- data/doc/operators/relational/rename.md +17 -0
- data/doc/operators/relational/restrict.md +25 -0
- data/doc/operators/relational/summarize.md +25 -0
- data/doc/operators/relational/ungroup.md +20 -0
- data/doc/operators/relational/union.md +14 -0
- data/doc/operators/relational/unwrap.md +20 -0
- data/doc/operators/relational/wrap.md +24 -0
- data/examples/csv/suppliers.csv +6 -0
- data/examples/logs/access.log +1000 -0
- data/examples/logs/combined.alf +2 -0
- data/examples/logs/hits.alf +14 -0
- data/examples/logs/not_found.alf +7 -0
- data/examples/logs/robots-cheating.alf +11 -0
- data/examples/logs/robots.alf +8 -0
- data/examples/northwind/customers.csv +92 -0
- data/examples/northwind/northwind.db +0 -0
- data/examples/northwind/orders.csv +831 -0
- data/examples/operators/clip.alf +1 -1
- data/examples/operators/database.alf +5 -6
- data/examples/operators/defaults.alf +1 -1
- data/examples/operators/group.alf +1 -1
- data/examples/operators/project.alf +2 -1
- data/examples/operators/pseudo-with.alf +2 -2
- data/examples/operators/quota.alf +2 -2
- data/examples/operators/summarize.alf +2 -2
- data/lib/alf/aggregator/aggregators.rb +77 -0
- data/lib/alf/aggregator/base.rb +95 -0
- data/lib/alf/aggregator/class_methods.rb +57 -0
- data/lib/alf/buffer/sorted.rb +48 -0
- data/lib/alf/command/class_methods.rb +27 -0
- data/lib/alf/command/doc_manager.rb +72 -0
- data/lib/alf/command/exec.rb +12 -0
- data/lib/alf/command/help.rb +31 -0
- data/lib/alf/command/main.rb +146 -0
- data/lib/alf/command/show.rb +33 -0
- data/lib/alf/environment/base.rb +37 -0
- data/lib/alf/environment/class_methods.rb +93 -0
- data/lib/alf/environment/explicit.rb +38 -0
- data/lib/alf/environment/folder.rb +62 -0
- data/lib/alf/extra/csv.rb +104 -0
- data/lib/alf/extra/logs.rb +100 -0
- data/lib/alf/extra/sequel.rb +77 -0
- data/lib/alf/{yaml.rb → extra/yaml.rb} +0 -0
- data/lib/alf/extra.rb +5 -0
- data/lib/alf/iterator/base.rb +38 -0
- data/lib/alf/iterator/class_methods.rb +22 -0
- data/lib/alf/iterator/proxy.rb +33 -0
- data/lib/alf/lispy/instance_methods.rb +157 -0
- data/lib/alf/operator/base.rb +74 -0
- data/lib/alf/operator/binary.rb +32 -0
- data/lib/alf/operator/cesure.rb +45 -0
- data/lib/alf/operator/class_methods.rb +132 -0
- data/lib/alf/operator/experimental.rb +9 -0
- data/lib/alf/operator/non_relational/autonum.rb +24 -0
- data/lib/alf/operator/non_relational/clip.rb +20 -0
- data/lib/alf/operator/non_relational/coerce.rb +21 -0
- data/lib/alf/operator/non_relational/compact.rb +62 -0
- data/lib/alf/operator/non_relational/defaults.rb +25 -0
- data/lib/alf/operator/non_relational/generator.rb +38 -0
- data/lib/alf/operator/non_relational/sort.rb +23 -0
- data/lib/alf/operator/nullary.rb +20 -0
- data/lib/alf/operator/relational/extend.rb +24 -0
- data/lib/alf/operator/relational/group.rb +32 -0
- data/lib/alf/operator/relational/intersect.rb +37 -0
- data/lib/alf/operator/relational/join.rb +106 -0
- data/lib/alf/operator/relational/matching.rb +45 -0
- data/lib/alf/operator/relational/minus.rb +37 -0
- data/lib/alf/operator/relational/not_matching.rb +45 -0
- data/lib/alf/operator/relational/project.rb +22 -0
- data/lib/alf/operator/relational/quota.rb +51 -0
- data/lib/alf/operator/relational/rank.rb +55 -0
- data/lib/alf/operator/relational/rename.rb +19 -0
- data/lib/alf/operator/relational/restrict.rb +20 -0
- data/lib/alf/operator/relational/summarize.rb +83 -0
- data/lib/alf/operator/relational/ungroup.rb +25 -0
- data/lib/alf/operator/relational/union.rb +32 -0
- data/lib/alf/operator/relational/unwrap.rb +21 -0
- data/lib/alf/operator/relational/wrap.rb +22 -0
- data/lib/alf/operator/shortcut.rb +53 -0
- data/lib/alf/operator/signature.rb +262 -0
- data/lib/alf/operator/transform.rb +27 -0
- data/lib/alf/operator/unary.rb +38 -0
- data/lib/alf/reader/alf_file.rb +24 -0
- data/lib/alf/reader/base.rb +119 -0
- data/lib/alf/reader/class_methods.rb +82 -0
- data/lib/alf/reader/rash.rb +28 -0
- data/lib/alf/relation/class_methods.rb +37 -0
- data/lib/alf/relation/instance_methods.rb +127 -0
- data/lib/alf/renderer/base.rb +72 -0
- data/lib/alf/renderer/class_methods.rb +58 -0
- data/lib/alf/renderer/rash.rb +19 -0
- data/lib/alf/{text.rb → renderer/text.rb} +1 -1
- data/lib/alf/tools/coerce.rb +14 -0
- data/lib/alf/tools/miscellaneous.rb +77 -0
- data/lib/alf/tools/to_lispy.rb +99 -0
- data/lib/alf/tools/to_ruby_literal.rb +14 -0
- data/lib/alf/tools/tuple_handle.rb +50 -0
- data/lib/alf/types/attr_list.rb +56 -0
- data/lib/alf/types/attr_name.rb +28 -0
- data/lib/alf/types/boolean.rb +12 -0
- data/lib/alf/types/heading.rb +96 -0
- data/lib/alf/types/ordering.rb +93 -0
- data/lib/alf/types/renaming.rb +57 -0
- data/lib/alf/types/summarization.rb +76 -0
- data/lib/alf/types/tuple_computation.rb +61 -0
- data/lib/alf/types/tuple_expression.rb +61 -0
- data/lib/alf/types/tuple_predicate.rb +49 -0
- data/lib/alf/version.rb +2 -2
- data/lib/alf.rb +193 -3714
- data/spec/integration/__database__/group.alf +1 -1
- data/spec/integration/__database__/suppliers_csv.csv +6 -0
- data/spec/integration/command/alf/alf.db +0 -0
- data/spec/integration/command/alf/alf_env_sqlite.cmd +1 -0
- data/spec/integration/command/alf/alf_env_sqlite.stdout +9 -0
- data/spec/integration/command/alf/alf_help.cmd +1 -0
- data/spec/integration/command/alf/alf_help.stdout +67 -0
- data/spec/integration/command/autonum/autonum_0.cmd +1 -1
- data/spec/integration/command/coerce/coerce_1.cmd +1 -0
- data/spec/integration/command/coerce/coerce_1.stdout +5 -0
- data/spec/integration/command/defaults/defaults_0.cmd +1 -1
- data/spec/integration/command/defaults/defaults_0.stdout +9 -9
- data/spec/integration/command/defaults/defaults_2.cmd +1 -0
- data/spec/integration/command/defaults/defaults_2.stdout +9 -0
- data/spec/integration/command/generator/generator_1.cmd +1 -0
- data/spec/integration/command/generator/generator_1.stdout +10 -0
- data/spec/integration/command/generator/generator_2.cmd +1 -0
- data/spec/integration/command/generator/generator_2.stdout +5 -0
- data/spec/integration/command/generator/generator_3.cmd +1 -0
- data/spec/integration/command/generator/generator_3.stdout +5 -0
- data/spec/integration/command/group/group_0.cmd +1 -1
- data/spec/integration/command/group/group_1.cmd +1 -1
- data/spec/integration/command/help/help_1.cmd +1 -0
- data/spec/integration/command/help/help_1.stdout +22 -0
- data/spec/integration/command/quota/quota_0.cmd +1 -1
- data/spec/integration/command/rank/rank_1.cmd +1 -1
- data/spec/integration/command/rank/rank_1.stdout +10 -10
- data/spec/integration/command/rank/rank_2.cmd +1 -1
- data/spec/integration/command/rank/rank_2.stdout +10 -10
- data/spec/integration/command/rank/rank_3.cmd +1 -1
- data/spec/integration/command/rank/rank_3.stdout +10 -10
- data/spec/integration/command/rank/rank_4.cmd +1 -1
- data/spec/integration/command/rank/rank_5.cmd +1 -1
- data/spec/integration/command/show/show_csv.cmd +1 -0
- data/spec/integration/command/show/show_csv.stdout +6 -0
- data/spec/integration/command/show/show_rash_2.cmd +1 -1
- data/spec/integration/command/show/show_rash_2.stdout +5 -5
- data/spec/integration/command/sort/sort_0.cmd +1 -1
- data/spec/integration/command/sort/sort_1.cmd +1 -1
- data/spec/integration/command/sort/sort_1.stdout +2 -2
- data/spec/integration/command/sort/sort_2.cmd +1 -0
- data/spec/integration/command/sort/sort_2.stdout +9 -0
- data/spec/integration/command/sort/sort_3.cmd +1 -0
- data/spec/integration/command/sort/sort_3.stdout +9 -0
- data/spec/integration/command/summarize/summarize_0.cmd +1 -1
- data/spec/integration/command/ungroup/ungroup_0.cmd +1 -1
- data/spec/integration/command/wrap/wrap_0.cmd +1 -1
- data/spec/integration/semantics/test_project.alf +5 -6
- data/spec/integration/semantics/test_rank.alf +16 -16
- data/spec/integration/test_command.rb +17 -6
- data/spec/integration/test_examples.rb +1 -1
- data/spec/regression/logs/apache_combined.log +5 -0
- data/spec/regression/logs/test_path_attribute.rb +25 -0
- data/spec/regression/relation/test_relation_allbut_all.rb +14 -0
- data/spec/shared/an_operator_class.rb +10 -5
- data/spec/spec_helper.rb +1 -7
- data/spec/unit/assumptions/test_set.rb +64 -0
- data/spec/unit/command/doc_manager/dynamic.md +1 -0
- data/spec/unit/command/doc_manager/example.md +1 -0
- data/spec/unit/command/doc_manager/example_1.txt +11 -0
- data/spec/unit/command/doc_manager/static.md +1 -0
- data/spec/unit/command/doc_manager/test_call.rb +49 -0
- data/spec/unit/csv/input.csv +3 -0
- data/spec/unit/csv/test_reader.rb +66 -0
- data/spec/unit/csv/test_renderer.rb +73 -0
- data/spec/unit/lispy/test_relation.rb +37 -0
- data/spec/unit/lispy/test_run.rb +40 -0
- data/spec/unit/lispy/test_tuple.rb +36 -0
- data/spec/unit/logs/apache_combined.log +5 -0
- data/spec/unit/logs/postgresql.log +29 -0
- data/spec/unit/logs/test_reader.rb +56 -0
- data/spec/unit/operator/non_relational/compact/{buffer_based.rb → test_buffer_based.rb} +0 -0
- data/spec/unit/operator/non_relational/test_clip.rb +1 -1
- data/spec/unit/operator/non_relational/test_coerce.rb +35 -0
- data/spec/unit/operator/non_relational/test_defaults.rb +15 -2
- data/spec/unit/operator/non_relational/test_generator.rb +78 -0
- data/spec/unit/operator/relational/join/test_hash_based.rb +4 -4
- data/spec/unit/operator/relational/matching/test_hash_based.rb +6 -6
- data/spec/unit/operator/relational/not_matching/test_hash_based.rb +4 -4
- data/spec/unit/operator/relational/summarize/test_hash_based.rb +10 -6
- data/spec/unit/operator/relational/summarize/test_sort_based.rb +18 -7
- data/spec/unit/operator/relational/test_group.rb +8 -8
- data/spec/unit/operator/relational/test_intersect.rb +3 -3
- data/spec/unit/operator/relational/test_minus.rb +3 -3
- data/spec/unit/operator/relational/test_project.rb +12 -2
- data/spec/unit/operator/relational/test_quota.rb +5 -6
- data/spec/unit/operator/relational/test_summarize.rb +9 -11
- data/spec/unit/operator/relational/test_union.rb +1 -1
- data/spec/unit/operator/relational/test_wrap.rb +1 -1
- data/spec/unit/operator/signature/test_collect_on.rb +45 -0
- data/spec/unit/operator/signature/test_initialize.rb +17 -0
- data/spec/unit/operator/signature/test_install.rb +56 -0
- data/spec/unit/operator/signature/test_option_parser.rb +36 -0
- data/spec/unit/operator/signature/test_parse_args.rb +60 -0
- data/spec/unit/operator/signature/test_parse_argv.rb +87 -0
- data/spec/unit/operator/signature/test_to_lispy.rb +102 -0
- data/spec/unit/operator/signature/test_to_shell.rb +103 -0
- data/spec/unit/operator/test_non_relational.rb +3 -1
- data/spec/unit/relation/test_relops.rb +20 -15
- data/spec/unit/sequel/alf.db +0 -0
- data/spec/unit/sequel/test_environment.rb +54 -0
- data/spec/unit/test_aggregator.rb +32 -22
- data/spec/unit/test_environment.rb +5 -0
- data/spec/unit/test_lispy.rb +4 -0
- data/spec/unit/test_relation.rb +5 -0
- data/spec/unit/text/test_cell.rb +6 -6
- data/spec/unit/text/test_row.rb +3 -3
- data/spec/unit/text/test_table.rb +6 -6
- data/spec/unit/tools/test_coalesce.rb +15 -0
- data/spec/unit/tools/test_coerce.rb +10 -0
- data/spec/unit/tools/test_to_lispy.rb +138 -0
- data/spec/unit/tools/test_to_ruby_literal.rb +10 -0
- data/spec/unit/tools/test_tuple_handle.rb +1 -59
- data/spec/unit/types/test_attr_list.rb +106 -0
- data/spec/unit/types/test_attr_name.rb +52 -0
- data/spec/unit/{test_heading.rb → types/test_heading.rb} +10 -0
- data/spec/unit/types/test_ordering.rb +127 -0
- data/spec/unit/types/test_renaming.rb +55 -0
- data/spec/unit/types/test_summarization.rb +63 -0
- data/spec/unit/types/test_tuple_computation.rb +60 -0
- data/spec/unit/types/test_tuple_expression.rb +64 -0
- data/spec/unit/types/test_tuple_predicate.rb +79 -0
- data/tasks/debug_mail.rake +1 -1
- data/tasks/debug_mail.txt +5 -0
- data/tasks/gh-pages.rake +63 -0
- metadata +325 -52
- data/spec/unit/operator/test_command_methods.rb +0 -38
- data/spec/unit/tools/test_ordering_key.rb +0 -94
- data/spec/unit/tools/test_parse_commandline_args.rb +0 -47
- data/spec/unit/tools/test_projection_key.rb +0 -83
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
module Operator
|
4
|
+
describe Signature, "#parse_argv" do
|
5
|
+
|
6
|
+
let(:clazz){ Class.new(Object) }
|
7
|
+
let(:receiver){ clazz.new }
|
8
|
+
before{
|
9
|
+
signature.install
|
10
|
+
}
|
11
|
+
subject{
|
12
|
+
signature.parse_argv(argv, receiver)
|
13
|
+
}
|
14
|
+
|
15
|
+
describe "on a singleton signature with a AttrList" do
|
16
|
+
let(:signature){
|
17
|
+
Signature.new(clazz) do |s|
|
18
|
+
s.argument :proj, AttrList
|
19
|
+
end
|
20
|
+
}
|
21
|
+
let(:argv){ %w{-- hello world} }
|
22
|
+
specify{
|
23
|
+
subject.should eq([])
|
24
|
+
receiver.proj.should eq(AttrList.new([:hello, :world]))
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "on a singleton signature with a default" do
|
29
|
+
let(:signature){
|
30
|
+
Signature.new(clazz) do |s|
|
31
|
+
s.argument :attrname, AttrName, :autonum
|
32
|
+
end
|
33
|
+
}
|
34
|
+
let(:argv){ %w{} }
|
35
|
+
specify{
|
36
|
+
subject.should eq([])
|
37
|
+
receiver.attrname.should eq(:autonum)
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "On quota signature" do
|
42
|
+
let(:signature){
|
43
|
+
Signature.new(clazz) do |s|
|
44
|
+
s.argument :by, AttrList, []
|
45
|
+
s.argument :order, Ordering, []
|
46
|
+
s.argument :summarization, Summarization, {}
|
47
|
+
end
|
48
|
+
}
|
49
|
+
let(:argv){ %w|op1 -- a -- time -- time_sum sum{time} time_max max{time}| }
|
50
|
+
specify{
|
51
|
+
subject.should eq(["op1"])
|
52
|
+
receiver.by.should eq(AttrList.new([:a]))
|
53
|
+
receiver.order.should eq(Ordering.coerce([:time]))
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "When signature contains options" do
|
58
|
+
let(:signature){
|
59
|
+
Signature.new(clazz) do |s|
|
60
|
+
s.argument :by, AttrList, []
|
61
|
+
s.option :allbut, Boolean, false, "Allbut?"
|
62
|
+
end
|
63
|
+
}
|
64
|
+
|
65
|
+
describe "when options are specified" do
|
66
|
+
let(:argv){ %w{op1 --allbut -- a} }
|
67
|
+
specify{
|
68
|
+
subject.should eq(["op1"])
|
69
|
+
receiver.by.should eq(AttrList.new([:a]))
|
70
|
+
receiver.allbut.should eql(true)
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "when options are not specified" do
|
75
|
+
let(:argv){ %w{op1 -- a} }
|
76
|
+
specify{
|
77
|
+
subject.should eq(["op1"])
|
78
|
+
receiver.by.should eq(AttrList.new([:a]))
|
79
|
+
receiver.allbut.should eql(false)
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
module Operator
|
4
|
+
describe Signature, '#to_lispy' do
|
5
|
+
|
6
|
+
subject{ signature.to_lispy }
|
7
|
+
|
8
|
+
describe "on a nullary signature" do
|
9
|
+
let(:clazz){ Operator::NonRelational::Generator }
|
10
|
+
|
11
|
+
describe "on an empty signature" do
|
12
|
+
let(:signature){ Signature.new(clazz){|s|} }
|
13
|
+
it{ should eq("(generator)") }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "on an option-only signature" do
|
17
|
+
let(:signature){
|
18
|
+
Signature.new(clazz) do |s|
|
19
|
+
s.option :allbut, Boolean
|
20
|
+
end
|
21
|
+
}
|
22
|
+
it{ should eq("(generator {allbut: Boolean})") }
|
23
|
+
end
|
24
|
+
|
25
|
+
end # nullary signature
|
26
|
+
|
27
|
+
describe "on a monadic operator" do
|
28
|
+
let(:clazz){ Operator::NonRelational::Coerce }
|
29
|
+
|
30
|
+
describe "on an empty signature" do
|
31
|
+
let(:signature){ Signature.new(clazz){|s|} }
|
32
|
+
it{ should eq("(coerce operand)") }
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "on an option-only signature" do
|
36
|
+
let(:signature){
|
37
|
+
Signature.new(clazz) do |s|
|
38
|
+
s.option :allbut, Boolean
|
39
|
+
end
|
40
|
+
}
|
41
|
+
it{ should eq("(coerce operand, {allbut: Boolean})") }
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "on an option-only signature with multiple options" do
|
45
|
+
let(:signature){
|
46
|
+
Signature.new(clazz) do |s|
|
47
|
+
s.option :allbut, Boolean
|
48
|
+
s.option :newname, AttrName
|
49
|
+
end
|
50
|
+
}
|
51
|
+
it{ should eq("(coerce operand, {allbut: Boolean, newname: AttrName})") }
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "on a signature with one argument only" do
|
55
|
+
let(:signature){
|
56
|
+
Signature.new(clazz) do |s|
|
57
|
+
s.argument :by, AttrList
|
58
|
+
end
|
59
|
+
}
|
60
|
+
it{ should eq("(coerce operand, by:AttrList)") }
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "on a signature with multiple arguments" do
|
64
|
+
let(:signature){
|
65
|
+
Signature.new(clazz) do |s|
|
66
|
+
s.argument :by, AttrList
|
67
|
+
s.argument :order, Ordering
|
68
|
+
end
|
69
|
+
}
|
70
|
+
it{ should eq("(coerce operand, by:AttrList, order:Ordering)") }
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "on a full signature" do
|
74
|
+
let(:signature){
|
75
|
+
Signature.new(clazz) do |s|
|
76
|
+
s.argument :by, AttrList
|
77
|
+
s.argument :order, Ordering
|
78
|
+
s.option :allbut, Boolean
|
79
|
+
end
|
80
|
+
}
|
81
|
+
it{ should eq("(coerce operand, by:AttrList, order:Ordering, {allbut: Boolean})") }
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "on a dyadic operator" do
|
87
|
+
let(:clazz){ Operator::Relational::Join }
|
88
|
+
|
89
|
+
describe "on an option-only signature" do
|
90
|
+
let(:signature){
|
91
|
+
Signature.new(clazz) do |s|
|
92
|
+
s.option :allbut, Boolean
|
93
|
+
end
|
94
|
+
}
|
95
|
+
it{ should eq("(join left, right, {allbut: Boolean})") }
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
module Operator
|
4
|
+
describe Signature, '#to_shell' do
|
5
|
+
|
6
|
+
subject{ signature.to_shell }
|
7
|
+
|
8
|
+
describe "on a nullary signature" do
|
9
|
+
let(:clazz){ Operator::NonRelational::Generator }
|
10
|
+
|
11
|
+
describe "on an empty signature" do
|
12
|
+
let(:signature){ Signature.new(clazz){|s|} }
|
13
|
+
it{ should eq("alf generator") }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "on an option-only signature" do
|
17
|
+
let(:signature){
|
18
|
+
Signature.new(clazz) do |s|
|
19
|
+
s.option :allbut, Boolean
|
20
|
+
end
|
21
|
+
}
|
22
|
+
it{ should eq("alf generator [--allbut]") }
|
23
|
+
end
|
24
|
+
|
25
|
+
end # nullary signature
|
26
|
+
|
27
|
+
describe "on a monadic operator" do
|
28
|
+
let(:clazz){ Operator::NonRelational::Coerce }
|
29
|
+
|
30
|
+
describe "on an empty signature" do
|
31
|
+
let(:signature){ Signature.new(clazz){|s|} }
|
32
|
+
it{ should eq("alf coerce [OPERAND]") }
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "on an option-only signature" do
|
36
|
+
let(:signature){
|
37
|
+
Signature.new(clazz) do |s|
|
38
|
+
s.option :allbut, Boolean
|
39
|
+
end
|
40
|
+
}
|
41
|
+
it{ should eq("alf coerce [--allbut] [OPERAND]") }
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "on an option-only signature with multiple options" do
|
45
|
+
let(:signature){
|
46
|
+
Signature.new(clazz) do |s|
|
47
|
+
s.option :allbut, Boolean
|
48
|
+
s.option :newname, AttrName
|
49
|
+
end
|
50
|
+
}
|
51
|
+
it{ should eq("alf coerce [--allbut] [--newname=NEWNAME] [OPERAND]") }
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "on a signature with one argument only" do
|
55
|
+
let(:signature){
|
56
|
+
Signature.new(clazz) do |s|
|
57
|
+
s.argument :proj, AttrList
|
58
|
+
end
|
59
|
+
}
|
60
|
+
it{ should eq("alf coerce [OPERAND] -- PROJ") }
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "on a signature with multiple arguments" do
|
64
|
+
let(:signature){
|
65
|
+
Signature.new(clazz) do |s|
|
66
|
+
s.argument :proj, AttrList
|
67
|
+
s.argument :ordering, Ordering
|
68
|
+
end
|
69
|
+
}
|
70
|
+
it{ should eq("alf coerce [OPERAND] -- PROJ -- ORDERING") }
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "on a full signature" do
|
74
|
+
let(:signature){
|
75
|
+
Signature.new(clazz) do |s|
|
76
|
+
s.argument :proj, AttrList
|
77
|
+
s.argument :ordering, Ordering
|
78
|
+
s.option :allbut, Boolean
|
79
|
+
s.option :newname, AttrName
|
80
|
+
end
|
81
|
+
}
|
82
|
+
it{ should eq("alf coerce [--allbut] [--newname=NEWNAME] [OPERAND] -- PROJ -- ORDERING") }
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "on a dyadic operator" do
|
88
|
+
let(:clazz){ Operator::Relational::Join }
|
89
|
+
|
90
|
+
describe "on an option-only signature" do
|
91
|
+
let(:signature){
|
92
|
+
Signature.new(clazz) do |s|
|
93
|
+
s.option :allbut, Boolean
|
94
|
+
end
|
95
|
+
}
|
96
|
+
it{ should eq("alf join [--allbut] [LEFT] RIGHT") }
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -8,11 +8,13 @@ module Alf
|
|
8
8
|
x.sort{|m1,m2| m1.name.to_s <=> m2.name.to_s}.should == [
|
9
9
|
Alf::Operator::NonRelational::Autonum,
|
10
10
|
Alf::Operator::NonRelational::Clip,
|
11
|
+
Alf::Operator::NonRelational::Coerce,
|
11
12
|
Alf::Operator::NonRelational::Compact,
|
12
13
|
Alf::Operator::NonRelational::Defaults,
|
14
|
+
Alf::Operator::NonRelational::Generator,
|
13
15
|
Alf::Operator::NonRelational::Sort,
|
14
16
|
]
|
15
17
|
end
|
16
18
|
|
17
19
|
end
|
18
|
-
end
|
20
|
+
end
|
@@ -2,49 +2,54 @@ require 'spec_helper'
|
|
2
2
|
module Alf
|
3
3
|
describe Relation do
|
4
4
|
|
5
|
-
let(:rel1){
|
5
|
+
let(:rel1){Alf::Relation[
|
6
6
|
{:sid => 'S1'},
|
7
7
|
{:sid => 'S2'},
|
8
8
|
{:sid => 'S3'}
|
9
|
-
|
9
|
+
]}
|
10
10
|
|
11
|
-
let(:rel2){
|
11
|
+
let(:rel2){Alf::Relation[
|
12
12
|
{:sid => 'S5'},
|
13
13
|
{:sid => 'S2'}
|
14
|
-
|
14
|
+
]}
|
15
15
|
|
16
|
+
specify "project" do
|
17
|
+
rel1.project([]).should eq(Alf::Relation[{}])
|
18
|
+
rel1.project([:sid], :allbut => true).should eq(Alf::Relation[{}])
|
19
|
+
end
|
20
|
+
|
16
21
|
specify "allbut" do
|
17
|
-
rel1.allbut([:sid]).should
|
22
|
+
rel1.allbut([:sid]).should eq(Alf::Relation[{}])
|
18
23
|
end
|
19
24
|
|
20
25
|
specify "extend" do
|
21
|
-
rel1.extend(:x => lambda{ sid.downcase }).should ==
|
26
|
+
rel1.extend(:x => lambda{ sid.downcase }).should == Alf::Relation[
|
22
27
|
{:sid => 'S1', :x => 's1'},
|
23
28
|
{:sid => 'S2', :x => 's2'},
|
24
29
|
{:sid => 'S3', :x => 's3'}
|
25
|
-
|
30
|
+
]
|
26
31
|
end
|
27
32
|
|
28
33
|
specify "union" do
|
29
34
|
(rel1 + rel1).should == rel1
|
30
|
-
(rel1 + rel2).should ==
|
35
|
+
(rel1 + rel2).should == Alf::Relation[
|
31
36
|
{:sid => 'S1'},
|
32
37
|
{:sid => 'S3'},
|
33
38
|
{:sid => 'S2'},
|
34
39
|
{:sid => 'S5'}
|
35
|
-
|
40
|
+
]
|
36
41
|
end # coerce
|
37
42
|
|
38
43
|
specify "difference" do
|
39
|
-
(rel1 - rel1).should ==
|
40
|
-
(rel1 - rel2).should ==
|
44
|
+
(rel1 - rel1).should == Alf::Relation[]
|
45
|
+
(rel1 - rel2).should == Alf::Relation[
|
41
46
|
{:sid => 'S1'},
|
42
47
|
{:sid => 'S3'}
|
43
|
-
|
44
|
-
(rel2 - rel1).should ==
|
48
|
+
]
|
49
|
+
(rel2 - rel1).should == Alf::Relation[
|
45
50
|
{:sid => 'S5'}
|
46
|
-
|
51
|
+
]
|
47
52
|
end # coerce
|
48
53
|
|
49
54
|
end
|
50
|
-
end
|
55
|
+
end
|
Binary file
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fileutils'
|
3
|
+
require "sequel"
|
4
|
+
module Alf
|
5
|
+
describe Sequel::Environment do
|
6
|
+
|
7
|
+
let(:rel) {Alf::Relation[
|
8
|
+
{:sid => 'S1', :name => 'Smith', :status => 20, :city => 'London'},
|
9
|
+
{:sid => 'S2', :name => 'Jones', :status => 10, :city => 'Paris'},
|
10
|
+
{:sid => 'S3', :name => 'Blake', :status => 30, :city => 'Paris'},
|
11
|
+
{:sid => 'S4', :name => 'Clark', :status => 20, :city => 'London'},
|
12
|
+
{:sid => 'S5', :name => 'Adams', :status => 30, :city => 'Athens'}
|
13
|
+
]}
|
14
|
+
|
15
|
+
let(:file){ _("alf.db", __FILE__) }
|
16
|
+
let(:uri) { "sqlite://#{file}" }
|
17
|
+
let(:env) { Sequel::Environment.new(uri) }
|
18
|
+
|
19
|
+
before(:all){
|
20
|
+
unless File.exists?(file)
|
21
|
+
FileUtils.rm_rf file
|
22
|
+
db = ::Sequel.connect(uri)
|
23
|
+
db.create_table(:suppliers){
|
24
|
+
primary_key :sid
|
25
|
+
String :sid
|
26
|
+
String :name
|
27
|
+
Integer :status
|
28
|
+
String :city
|
29
|
+
}
|
30
|
+
rel.each{|tuple| db[:suppliers].insert(tuple)}
|
31
|
+
end
|
32
|
+
}
|
33
|
+
|
34
|
+
specify{
|
35
|
+
env.should be_a(Alf::Environment)
|
36
|
+
}
|
37
|
+
|
38
|
+
it "should serve iterators" do
|
39
|
+
env.dataset(:suppliers).should be_a(Alf::Iterator)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should be the correct relation" do
|
43
|
+
env.dataset(:suppliers).to_rel.should eq(rel)
|
44
|
+
end
|
45
|
+
|
46
|
+
specify ".recognizes?" do
|
47
|
+
Sequel::Environment.recognizes?([_("alf.db", __FILE__)]).should be_true
|
48
|
+
Sequel::Environment.recognizes?(["postgres://localhost/database"]).should be_true
|
49
|
+
Sequel::Environment.recognizes?(["nosuchone.db"]).should be_false
|
50
|
+
Sequel::Environment.recognizes?([nil]).should be_false
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -9,54 +9,64 @@ module Alf
|
|
9
9
|
{:a => 1, :sign => -1},
|
10
10
|
]}
|
11
11
|
|
12
|
+
it "should keep track of registered aggregators" do
|
13
|
+
Aggregator.aggregators.should_not be_empty
|
14
|
+
Aggregator.each do |agg|
|
15
|
+
agg.should be_a(Class)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
12
19
|
it "should behave correctly on count" do
|
13
|
-
Aggregator.count
|
20
|
+
Aggregator.count{a}.aggregate(input).should == 4
|
14
21
|
end
|
15
22
|
|
16
23
|
it "should behave correctly on sum" do
|
17
|
-
Aggregator.sum
|
24
|
+
Aggregator.sum{a}.aggregate(input).should == 7
|
18
25
|
end
|
19
26
|
|
20
27
|
it "should behave correctly on avg" do
|
21
|
-
Aggregator.avg
|
28
|
+
Aggregator.avg{a}.aggregate(input).should == 7.0 / 4.0
|
22
29
|
end
|
23
30
|
|
24
31
|
it "should behave correctly on min" do
|
25
|
-
Aggregator.min
|
32
|
+
Aggregator.min{a}.aggregate(input).should == 1
|
26
33
|
end
|
27
34
|
|
28
35
|
it "should behave correctly on max" do
|
29
|
-
Aggregator.max
|
36
|
+
Aggregator.max{a}.aggregate(input).should == 3
|
30
37
|
end
|
31
38
|
|
32
39
|
it "should behave correctly on concat" do
|
33
|
-
Aggregator.concat
|
34
|
-
Aggregator.concat(:
|
35
|
-
Aggregator.concat(:a, :before => "[", :after => "]").aggregate(input).should == "[1231]"
|
40
|
+
Aggregator.concat{a}.aggregate(input).should == "1231"
|
41
|
+
Aggregator.concat(:between => " "){ a }.aggregate(input).should == "1 2 3 1"
|
36
42
|
Aggregator.concat(:before => "[", :after => "]"){ a }.aggregate(input).should == "[1231]"
|
37
43
|
end
|
38
44
|
|
39
45
|
it "should behave correctly on collect" do
|
40
|
-
Aggregator.collect
|
46
|
+
Aggregator.collect{a}.aggregate(input).should == [1, 2, 3, 1]
|
41
47
|
Aggregator.collect{ {:a => a, :sign => sign} }.aggregate(input).should == input
|
42
48
|
end
|
43
49
|
|
44
|
-
it "should behave correctly on group" do
|
45
|
-
Aggregator.group(:a).aggregate(input).should == rel(
|
46
|
-
{:a => 1},
|
47
|
-
{:a => 2},
|
48
|
-
{:a => 3}
|
49
|
-
)
|
50
|
-
Aggregator.group(:a, :sign).aggregate(input).should == rel(
|
51
|
-
{:a => 1, :sign => -1},
|
52
|
-
{:a => 2, :sign => 1 },
|
53
|
-
{:a => 3, :sign => -1}
|
54
|
-
)
|
55
|
-
end
|
56
|
-
|
57
50
|
it "should allow specific tuple computations" do
|
58
51
|
Aggregator.sum{ 1.0 * a * sign }.aggregate(input).should == -3.0
|
59
52
|
end
|
53
|
+
|
54
|
+
describe "coerce" do
|
55
|
+
|
56
|
+
subject{ Aggregator.coerce(arg) }
|
57
|
+
|
58
|
+
describe "from an Aggregator" do
|
59
|
+
let(:arg){ Aggregator.sum{a} }
|
60
|
+
it{ should eq(arg) }
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "from a String" do
|
64
|
+
let(:arg){ "sum{a}" }
|
65
|
+
it{ should be_a(Aggregator::Sum) }
|
66
|
+
specify{ subject.aggregate(input).should eql(7) }
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
60
70
|
|
61
71
|
end
|
62
72
|
end
|
@@ -22,6 +22,11 @@ module Alf
|
|
22
22
|
env.should be_a(Environment::Folder)
|
23
23
|
end
|
24
24
|
|
25
|
+
it "should recognize a sqlite file" do
|
26
|
+
env = Environment.autodetect(_("sequel/alf.db", __FILE__))
|
27
|
+
env.should be_a(Sequel::Environment)
|
28
|
+
end
|
29
|
+
|
25
30
|
it "should raise an Argument when no match" do
|
26
31
|
lambda{ Environment.autodetect(12) }.should raise_error(ArgumentError)
|
27
32
|
end
|
data/spec/unit/test_lispy.rb
CHANGED
data/spec/unit/test_relation.rb
CHANGED
@@ -46,6 +46,11 @@ module Alf
|
|
46
46
|
it_should_behave_like "A value"
|
47
47
|
end
|
48
48
|
|
49
|
+
specify "different empty relations instances should be equal" do
|
50
|
+
Relation.new(Set.new).should eq(Relation.new(Set.new))
|
51
|
+
Relation[{}].should eq(Relation[{}])
|
52
|
+
end
|
53
|
+
|
49
54
|
describe "DUM" do
|
50
55
|
subject{ Relation::DUM }
|
51
56
|
it_should_behave_like "A value"
|
data/spec/unit/text/test_cell.rb
CHANGED
@@ -9,22 +9,22 @@ module Alf
|
|
9
9
|
Cell.new(100).text_rendering.should == "100"
|
10
10
|
Cell.new(:hello).text_rendering.should == ":hello"
|
11
11
|
Cell.new("hello").text_rendering.should == "hello"
|
12
|
-
Cell.new(10.0).text_rendering.should == "10.
|
13
|
-
Cell.new(10/3.0).text_rendering.should == "3.
|
12
|
+
Cell.new(10.0).text_rendering.should == "10.000"
|
13
|
+
Cell.new(10/3.0).text_rendering.should == "3.333"
|
14
14
|
Cell.new([]).text_rendering.should == "[]"
|
15
|
-
Cell.new([10/3.0, true]).text_rendering.should == "[3.
|
15
|
+
Cell.new([10/3.0, true]).text_rendering.should == "[3.333, true]"
|
16
16
|
end
|
17
17
|
|
18
18
|
specify "min_width" do
|
19
19
|
Cell.new("").min_width.should == 0
|
20
|
-
Cell.new(10/3.0).min_width.should ==
|
20
|
+
Cell.new(10/3.0).min_width.should == 5
|
21
21
|
Cell.new("12\n5345").min_width.should == 4
|
22
22
|
end
|
23
23
|
|
24
24
|
specify "rendering_lines" do
|
25
25
|
Cell.new("").rendering_lines.should == []
|
26
|
-
Cell.new(10/3.0).rendering_lines.should == ["3.
|
27
|
-
Cell.new([10/3.0,true]).rendering_lines.should == ["[3.
|
26
|
+
Cell.new(10/3.0).rendering_lines.should == ["3.333"]
|
27
|
+
Cell.new([10/3.0,true]).rendering_lines.should == ["[3.333, true]"]
|
28
28
|
Cell.new("abc").rendering_lines(5).should == ["abc "]
|
29
29
|
Cell.new(12).rendering_lines(5).should == [" 12"]
|
30
30
|
end
|
data/spec/unit/text/test_row.rb
CHANGED
@@ -9,8 +9,8 @@ module Alf
|
|
9
9
|
|
10
10
|
let(:values){ [ 10/3.0, true ] }
|
11
11
|
specify "rendering_lines" do
|
12
|
-
row.rendering_lines.should == ["| 3.
|
13
|
-
row.rendering_lines([10,5]).should == ["|
|
12
|
+
row.rendering_lines.should == ["| 3.333 | true |"]
|
13
|
+
row.rendering_lines([10,5]).should == ["| 3.333 | true |"]
|
14
14
|
end
|
15
15
|
|
16
16
|
end
|
@@ -20,7 +20,7 @@ module Alf
|
|
20
20
|
let(:values){ [ 10/3.0, [1, 2, 3] ] }
|
21
21
|
|
22
22
|
specify "rendering_lines" do
|
23
|
-
row.rendering_lines.should == ["| 3.
|
23
|
+
row.rendering_lines.should == ["| 3.333 | [1, 2, 3] |"]
|
24
24
|
end
|
25
25
|
|
26
26
|
end
|
@@ -24,12 +24,12 @@ module Alf
|
|
24
24
|
let(:records){ [ [:by_x, 10.0], [:by_y, 2.0] ] }
|
25
25
|
|
26
26
|
specify "render" do
|
27
|
-
table.render.should == "
|
28
|
-
"| :method | :total
|
29
|
-
"
|
30
|
-
"| :by_x | 10.
|
31
|
-
"| :by_y | 2.
|
32
|
-
"
|
27
|
+
table.render.should == "+---------+--------+\n" +
|
28
|
+
"| :method | :total |\n" +
|
29
|
+
"+---------+--------+\n" +
|
30
|
+
"| :by_x | 10.000 |\n" +
|
31
|
+
"| :by_y | 2.000 |\n" +
|
32
|
+
"+---------+--------+\n"
|
33
33
|
end
|
34
34
|
|
35
35
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
describe "Tools#coalesce" do
|
4
|
+
|
5
|
+
it "should support a varargs variant" do
|
6
|
+
Tools.coalesce(:a, nil, :b, :c).should eql(:a)
|
7
|
+
Tools.coalesce(nil, :a, nil, :b, :c).should eql(:a)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should support a block for costly computations" do
|
11
|
+
Tools.coalesce(nil){ :hello }.should eql(:hello)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|