alf 0.9.3 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (270) hide show
  1. data/CHANGELOG.md +255 -129
  2. data/Gemfile +31 -1
  3. data/Gemfile.lock +17 -20
  4. data/LICENCE.md +1 -1
  5. data/Manifest.txt +2 -0
  6. data/README.md +37 -43
  7. data/TODO.md +1 -1
  8. data/alf.gemspec +10 -7
  9. data/alf.noespec +24 -13
  10. data/bin/alf +2 -2
  11. data/doc/commands/exec.md +16 -0
  12. data/doc/commands/help.md +11 -0
  13. data/doc/commands/main.md +33 -0
  14. data/doc/commands/show.md +19 -0
  15. data/doc/operators/non_relational/autonum.md +23 -0
  16. data/doc/operators/non_relational/clip.md +31 -0
  17. data/doc/operators/non_relational/coerce.md +15 -0
  18. data/doc/operators/non_relational/compact.md +20 -0
  19. data/doc/operators/non_relational/defaults.md +32 -0
  20. data/doc/operators/non_relational/generator.md +20 -0
  21. data/doc/operators/non_relational/sort.md +24 -0
  22. data/doc/operators/relational/extend.md +18 -0
  23. data/doc/operators/relational/group.md +27 -0
  24. data/doc/operators/relational/intersect.md +13 -0
  25. data/doc/operators/relational/join.md +27 -0
  26. data/doc/operators/relational/matching.md +20 -0
  27. data/doc/operators/relational/minus.md +12 -0
  28. data/doc/operators/relational/not-matching.md +20 -0
  29. data/doc/operators/relational/project.md +28 -0
  30. data/doc/operators/relational/quota.md +21 -0
  31. data/doc/operators/relational/rank.md +27 -0
  32. data/doc/operators/relational/rename.md +17 -0
  33. data/doc/operators/relational/restrict.md +25 -0
  34. data/doc/operators/relational/summarize.md +25 -0
  35. data/doc/operators/relational/ungroup.md +20 -0
  36. data/doc/operators/relational/union.md +14 -0
  37. data/doc/operators/relational/unwrap.md +20 -0
  38. data/doc/operators/relational/wrap.md +24 -0
  39. data/examples/csv/suppliers.csv +6 -0
  40. data/examples/logs/access.log +1000 -0
  41. data/examples/logs/combined.alf +2 -0
  42. data/examples/logs/hits.alf +14 -0
  43. data/examples/logs/not_found.alf +7 -0
  44. data/examples/logs/robots-cheating.alf +11 -0
  45. data/examples/logs/robots.alf +8 -0
  46. data/examples/northwind/customers.csv +92 -0
  47. data/examples/northwind/northwind.db +0 -0
  48. data/examples/northwind/orders.csv +831 -0
  49. data/examples/operators/clip.alf +1 -1
  50. data/examples/operators/database.alf +5 -6
  51. data/examples/operators/defaults.alf +1 -1
  52. data/examples/operators/group.alf +1 -1
  53. data/examples/operators/project.alf +2 -1
  54. data/examples/operators/pseudo-with.alf +2 -2
  55. data/examples/operators/quota.alf +2 -2
  56. data/examples/operators/summarize.alf +2 -2
  57. data/lib/alf/aggregator/aggregators.rb +77 -0
  58. data/lib/alf/aggregator/base.rb +95 -0
  59. data/lib/alf/aggregator/class_methods.rb +57 -0
  60. data/lib/alf/buffer/sorted.rb +48 -0
  61. data/lib/alf/command/class_methods.rb +27 -0
  62. data/lib/alf/command/doc_manager.rb +72 -0
  63. data/lib/alf/command/exec.rb +12 -0
  64. data/lib/alf/command/help.rb +31 -0
  65. data/lib/alf/command/main.rb +146 -0
  66. data/lib/alf/command/show.rb +33 -0
  67. data/lib/alf/environment/base.rb +37 -0
  68. data/lib/alf/environment/class_methods.rb +93 -0
  69. data/lib/alf/environment/explicit.rb +38 -0
  70. data/lib/alf/environment/folder.rb +62 -0
  71. data/lib/alf/extra/csv.rb +104 -0
  72. data/lib/alf/extra/logs.rb +100 -0
  73. data/lib/alf/extra/sequel.rb +77 -0
  74. data/lib/alf/{yaml.rb → extra/yaml.rb} +0 -0
  75. data/lib/alf/extra.rb +5 -0
  76. data/lib/alf/iterator/base.rb +38 -0
  77. data/lib/alf/iterator/class_methods.rb +22 -0
  78. data/lib/alf/iterator/proxy.rb +33 -0
  79. data/lib/alf/lispy/instance_methods.rb +157 -0
  80. data/lib/alf/operator/base.rb +74 -0
  81. data/lib/alf/operator/binary.rb +32 -0
  82. data/lib/alf/operator/cesure.rb +45 -0
  83. data/lib/alf/operator/class_methods.rb +132 -0
  84. data/lib/alf/operator/experimental.rb +9 -0
  85. data/lib/alf/operator/non_relational/autonum.rb +24 -0
  86. data/lib/alf/operator/non_relational/clip.rb +20 -0
  87. data/lib/alf/operator/non_relational/coerce.rb +21 -0
  88. data/lib/alf/operator/non_relational/compact.rb +62 -0
  89. data/lib/alf/operator/non_relational/defaults.rb +25 -0
  90. data/lib/alf/operator/non_relational/generator.rb +38 -0
  91. data/lib/alf/operator/non_relational/sort.rb +23 -0
  92. data/lib/alf/operator/nullary.rb +20 -0
  93. data/lib/alf/operator/relational/extend.rb +24 -0
  94. data/lib/alf/operator/relational/group.rb +32 -0
  95. data/lib/alf/operator/relational/intersect.rb +37 -0
  96. data/lib/alf/operator/relational/join.rb +106 -0
  97. data/lib/alf/operator/relational/matching.rb +45 -0
  98. data/lib/alf/operator/relational/minus.rb +37 -0
  99. data/lib/alf/operator/relational/not_matching.rb +45 -0
  100. data/lib/alf/operator/relational/project.rb +22 -0
  101. data/lib/alf/operator/relational/quota.rb +51 -0
  102. data/lib/alf/operator/relational/rank.rb +55 -0
  103. data/lib/alf/operator/relational/rename.rb +19 -0
  104. data/lib/alf/operator/relational/restrict.rb +20 -0
  105. data/lib/alf/operator/relational/summarize.rb +83 -0
  106. data/lib/alf/operator/relational/ungroup.rb +25 -0
  107. data/lib/alf/operator/relational/union.rb +32 -0
  108. data/lib/alf/operator/relational/unwrap.rb +21 -0
  109. data/lib/alf/operator/relational/wrap.rb +22 -0
  110. data/lib/alf/operator/shortcut.rb +53 -0
  111. data/lib/alf/operator/signature.rb +262 -0
  112. data/lib/alf/operator/transform.rb +27 -0
  113. data/lib/alf/operator/unary.rb +38 -0
  114. data/lib/alf/reader/alf_file.rb +24 -0
  115. data/lib/alf/reader/base.rb +119 -0
  116. data/lib/alf/reader/class_methods.rb +82 -0
  117. data/lib/alf/reader/rash.rb +28 -0
  118. data/lib/alf/relation/class_methods.rb +37 -0
  119. data/lib/alf/relation/instance_methods.rb +127 -0
  120. data/lib/alf/renderer/base.rb +72 -0
  121. data/lib/alf/renderer/class_methods.rb +58 -0
  122. data/lib/alf/renderer/rash.rb +19 -0
  123. data/lib/alf/{text.rb → renderer/text.rb} +1 -1
  124. data/lib/alf/tools/coerce.rb +14 -0
  125. data/lib/alf/tools/miscellaneous.rb +77 -0
  126. data/lib/alf/tools/to_lispy.rb +99 -0
  127. data/lib/alf/tools/to_ruby_literal.rb +14 -0
  128. data/lib/alf/tools/tuple_handle.rb +50 -0
  129. data/lib/alf/types/attr_list.rb +56 -0
  130. data/lib/alf/types/attr_name.rb +28 -0
  131. data/lib/alf/types/boolean.rb +12 -0
  132. data/lib/alf/types/heading.rb +96 -0
  133. data/lib/alf/types/ordering.rb +93 -0
  134. data/lib/alf/types/renaming.rb +57 -0
  135. data/lib/alf/types/summarization.rb +76 -0
  136. data/lib/alf/types/tuple_computation.rb +61 -0
  137. data/lib/alf/types/tuple_expression.rb +61 -0
  138. data/lib/alf/types/tuple_predicate.rb +49 -0
  139. data/lib/alf/version.rb +2 -2
  140. data/lib/alf.rb +193 -3714
  141. data/spec/integration/__database__/group.alf +1 -1
  142. data/spec/integration/__database__/suppliers_csv.csv +6 -0
  143. data/spec/integration/command/alf/alf.db +0 -0
  144. data/spec/integration/command/alf/alf_env_sqlite.cmd +1 -0
  145. data/spec/integration/command/alf/alf_env_sqlite.stdout +9 -0
  146. data/spec/integration/command/alf/alf_help.cmd +1 -0
  147. data/spec/integration/command/alf/alf_help.stdout +67 -0
  148. data/spec/integration/command/autonum/autonum_0.cmd +1 -1
  149. data/spec/integration/command/coerce/coerce_1.cmd +1 -0
  150. data/spec/integration/command/coerce/coerce_1.stdout +5 -0
  151. data/spec/integration/command/defaults/defaults_0.cmd +1 -1
  152. data/spec/integration/command/defaults/defaults_0.stdout +9 -9
  153. data/spec/integration/command/defaults/defaults_2.cmd +1 -0
  154. data/spec/integration/command/defaults/defaults_2.stdout +9 -0
  155. data/spec/integration/command/generator/generator_1.cmd +1 -0
  156. data/spec/integration/command/generator/generator_1.stdout +10 -0
  157. data/spec/integration/command/generator/generator_2.cmd +1 -0
  158. data/spec/integration/command/generator/generator_2.stdout +5 -0
  159. data/spec/integration/command/generator/generator_3.cmd +1 -0
  160. data/spec/integration/command/generator/generator_3.stdout +5 -0
  161. data/spec/integration/command/group/group_0.cmd +1 -1
  162. data/spec/integration/command/group/group_1.cmd +1 -1
  163. data/spec/integration/command/help/help_1.cmd +1 -0
  164. data/spec/integration/command/help/help_1.stdout +22 -0
  165. data/spec/integration/command/quota/quota_0.cmd +1 -1
  166. data/spec/integration/command/rank/rank_1.cmd +1 -1
  167. data/spec/integration/command/rank/rank_1.stdout +10 -10
  168. data/spec/integration/command/rank/rank_2.cmd +1 -1
  169. data/spec/integration/command/rank/rank_2.stdout +10 -10
  170. data/spec/integration/command/rank/rank_3.cmd +1 -1
  171. data/spec/integration/command/rank/rank_3.stdout +10 -10
  172. data/spec/integration/command/rank/rank_4.cmd +1 -1
  173. data/spec/integration/command/rank/rank_5.cmd +1 -1
  174. data/spec/integration/command/show/show_csv.cmd +1 -0
  175. data/spec/integration/command/show/show_csv.stdout +6 -0
  176. data/spec/integration/command/show/show_rash_2.cmd +1 -1
  177. data/spec/integration/command/show/show_rash_2.stdout +5 -5
  178. data/spec/integration/command/sort/sort_0.cmd +1 -1
  179. data/spec/integration/command/sort/sort_1.cmd +1 -1
  180. data/spec/integration/command/sort/sort_1.stdout +2 -2
  181. data/spec/integration/command/sort/sort_2.cmd +1 -0
  182. data/spec/integration/command/sort/sort_2.stdout +9 -0
  183. data/spec/integration/command/sort/sort_3.cmd +1 -0
  184. data/spec/integration/command/sort/sort_3.stdout +9 -0
  185. data/spec/integration/command/summarize/summarize_0.cmd +1 -1
  186. data/spec/integration/command/ungroup/ungroup_0.cmd +1 -1
  187. data/spec/integration/command/wrap/wrap_0.cmd +1 -1
  188. data/spec/integration/semantics/test_project.alf +5 -6
  189. data/spec/integration/semantics/test_rank.alf +16 -16
  190. data/spec/integration/test_command.rb +17 -6
  191. data/spec/integration/test_examples.rb +1 -1
  192. data/spec/regression/logs/apache_combined.log +5 -0
  193. data/spec/regression/logs/test_path_attribute.rb +25 -0
  194. data/spec/regression/relation/test_relation_allbut_all.rb +14 -0
  195. data/spec/shared/an_operator_class.rb +10 -5
  196. data/spec/spec_helper.rb +1 -7
  197. data/spec/unit/assumptions/test_set.rb +64 -0
  198. data/spec/unit/command/doc_manager/dynamic.md +1 -0
  199. data/spec/unit/command/doc_manager/example.md +1 -0
  200. data/spec/unit/command/doc_manager/example_1.txt +11 -0
  201. data/spec/unit/command/doc_manager/static.md +1 -0
  202. data/spec/unit/command/doc_manager/test_call.rb +49 -0
  203. data/spec/unit/csv/input.csv +3 -0
  204. data/spec/unit/csv/test_reader.rb +66 -0
  205. data/spec/unit/csv/test_renderer.rb +73 -0
  206. data/spec/unit/lispy/test_relation.rb +37 -0
  207. data/spec/unit/lispy/test_run.rb +40 -0
  208. data/spec/unit/lispy/test_tuple.rb +36 -0
  209. data/spec/unit/logs/apache_combined.log +5 -0
  210. data/spec/unit/logs/postgresql.log +29 -0
  211. data/spec/unit/logs/test_reader.rb +56 -0
  212. data/spec/unit/operator/non_relational/compact/{buffer_based.rb → test_buffer_based.rb} +0 -0
  213. data/spec/unit/operator/non_relational/test_clip.rb +1 -1
  214. data/spec/unit/operator/non_relational/test_coerce.rb +35 -0
  215. data/spec/unit/operator/non_relational/test_defaults.rb +15 -2
  216. data/spec/unit/operator/non_relational/test_generator.rb +78 -0
  217. data/spec/unit/operator/relational/join/test_hash_based.rb +4 -4
  218. data/spec/unit/operator/relational/matching/test_hash_based.rb +6 -6
  219. data/spec/unit/operator/relational/not_matching/test_hash_based.rb +4 -4
  220. data/spec/unit/operator/relational/summarize/test_hash_based.rb +10 -6
  221. data/spec/unit/operator/relational/summarize/test_sort_based.rb +18 -7
  222. data/spec/unit/operator/relational/test_group.rb +8 -8
  223. data/spec/unit/operator/relational/test_intersect.rb +3 -3
  224. data/spec/unit/operator/relational/test_minus.rb +3 -3
  225. data/spec/unit/operator/relational/test_project.rb +12 -2
  226. data/spec/unit/operator/relational/test_quota.rb +5 -6
  227. data/spec/unit/operator/relational/test_summarize.rb +9 -11
  228. data/spec/unit/operator/relational/test_union.rb +1 -1
  229. data/spec/unit/operator/relational/test_wrap.rb +1 -1
  230. data/spec/unit/operator/signature/test_collect_on.rb +45 -0
  231. data/spec/unit/operator/signature/test_initialize.rb +17 -0
  232. data/spec/unit/operator/signature/test_install.rb +56 -0
  233. data/spec/unit/operator/signature/test_option_parser.rb +36 -0
  234. data/spec/unit/operator/signature/test_parse_args.rb +60 -0
  235. data/spec/unit/operator/signature/test_parse_argv.rb +87 -0
  236. data/spec/unit/operator/signature/test_to_lispy.rb +102 -0
  237. data/spec/unit/operator/signature/test_to_shell.rb +103 -0
  238. data/spec/unit/operator/test_non_relational.rb +3 -1
  239. data/spec/unit/relation/test_relops.rb +20 -15
  240. data/spec/unit/sequel/alf.db +0 -0
  241. data/spec/unit/sequel/test_environment.rb +54 -0
  242. data/spec/unit/test_aggregator.rb +32 -22
  243. data/spec/unit/test_environment.rb +5 -0
  244. data/spec/unit/test_lispy.rb +4 -0
  245. data/spec/unit/test_relation.rb +5 -0
  246. data/spec/unit/text/test_cell.rb +6 -6
  247. data/spec/unit/text/test_row.rb +3 -3
  248. data/spec/unit/text/test_table.rb +6 -6
  249. data/spec/unit/tools/test_coalesce.rb +15 -0
  250. data/spec/unit/tools/test_coerce.rb +10 -0
  251. data/spec/unit/tools/test_to_lispy.rb +138 -0
  252. data/spec/unit/tools/test_to_ruby_literal.rb +10 -0
  253. data/spec/unit/tools/test_tuple_handle.rb +1 -59
  254. data/spec/unit/types/test_attr_list.rb +106 -0
  255. data/spec/unit/types/test_attr_name.rb +52 -0
  256. data/spec/unit/{test_heading.rb → types/test_heading.rb} +10 -0
  257. data/spec/unit/types/test_ordering.rb +127 -0
  258. data/spec/unit/types/test_renaming.rb +55 -0
  259. data/spec/unit/types/test_summarization.rb +63 -0
  260. data/spec/unit/types/test_tuple_computation.rb +60 -0
  261. data/spec/unit/types/test_tuple_expression.rb +64 -0
  262. data/spec/unit/types/test_tuple_predicate.rb +79 -0
  263. data/tasks/debug_mail.rake +1 -1
  264. data/tasks/debug_mail.txt +5 -0
  265. data/tasks/gh-pages.rake +63 -0
  266. metadata +325 -52
  267. data/spec/unit/operator/test_command_methods.rb +0 -38
  268. data/spec/unit/tools/test_ordering_key.rb +0 -94
  269. data/spec/unit/tools/test_parse_commandline_args.rb +0 -47
  270. data/spec/unit/tools/test_projection_key.rb +0 -83
@@ -25,7 +25,7 @@ module Alf
25
25
  subject{ operator.to_a }
26
26
 
27
27
  describe "when applied on both candidate keys" do
28
- before{ operator.datasets = [suppliers, statuses] }
28
+ before{ operator.pipe [suppliers, statuses] }
29
29
  let(:expected){[
30
30
  {:sid => 'S1', :city => 'London', :status => 20},
31
31
  {:sid => 'S2', :city => 'Paris', :status => 10},
@@ -41,17 +41,17 @@ module Alf
41
41
  {:sid => 'S3', :city => 'Paris', :country => 'France'}
42
42
  ]}
43
43
  describe "on one way" do
44
- before{ operator.datasets = [suppliers, countries] }
44
+ before{ operator.pipe [suppliers, countries] }
45
45
  it { should == expected }
46
46
  end
47
47
  describe "on the other way around" do
48
- before{ operator.datasets = [countries, suppliers] }
48
+ before{ operator.pipe [countries, suppliers] }
49
49
  it { should == expected }
50
50
  end
51
51
  end
52
52
 
53
53
  describe "when no attributes are in common" do
54
- before{ operator.datasets = [statuses, countries] }
54
+ before{ operator.pipe [statuses, countries] }
55
55
  let(:expected){
56
56
  statuses.collect{|s| countries.collect{|c| c.merge(s)}}.flatten
57
57
  }
@@ -25,33 +25,33 @@ module Alf
25
25
  subject{ operator.to_rel }
26
26
 
27
27
  describe "when applied on both candidate keys" do
28
- before{ operator.datasets = [suppliers, statuses] }
28
+ before{ operator.pipe [suppliers, statuses] }
29
29
  it { should eq(suppliers) }
30
30
  end
31
31
 
32
32
  describe "when applied on a typical foreign key" do
33
33
  describe "on one way" do
34
- before{ operator.datasets = [suppliers, countries] }
34
+ before{ operator.pipe [suppliers, countries] }
35
35
  it { should eq(suppliers) }
36
36
  end
37
37
  describe "on the other way around" do
38
- before{ operator.datasets = [countries, suppliers] }
38
+ before{ operator.pipe [countries, suppliers] }
39
39
  it { should eq(countries.restrict(lambda{ city != 'Bruxelles' })) }
40
40
  end
41
41
  end
42
42
 
43
43
  describe "when no attributes are in common" do
44
- before{ operator.datasets = [statuses, countries] }
44
+ before{ operator.pipe [statuses, countries] }
45
45
  it { should eq(statuses) }
46
46
  end
47
47
 
48
48
  describe "against DEE" do
49
- before{ operator.datasets = [suppliers, Relation::DEE] }
49
+ before{ operator.pipe [suppliers, Relation::DEE] }
50
50
  it { should eq(suppliers) }
51
51
  end
52
52
 
53
53
  describe "against DUM" do
54
- before{ operator.datasets = [suppliers, Relation::DUM] }
54
+ before{ operator.pipe [suppliers, Relation::DUM] }
55
55
  it { should eq(Relation::DUM) }
56
56
  end
57
57
 
@@ -13,22 +13,22 @@ module Alf
13
13
  subject{ operator.to_rel }
14
14
 
15
15
  describe "when applied on itself" do
16
- before{ operator.datasets = [suppliers, suppliers] }
16
+ before{ operator.pipe [suppliers, suppliers] }
17
17
  it { should eq(suppliers.minus(suppliers)) }
18
18
  end
19
19
 
20
20
  describe "when applied against a subset" do
21
- before{ operator.datasets = [suppliers, Alf::Relation[{:sid => 'S1'}]] }
21
+ before{ operator.pipe [suppliers, Alf::Relation[{:sid => 'S1'}]] }
22
22
  it { should eq(suppliers.restrict(lambda{ sid != 'S1' })) }
23
23
  end
24
24
 
25
25
  describe "against DEE" do
26
- before{ operator.datasets = [suppliers, Relation::DEE] }
26
+ before{ operator.pipe [suppliers, Relation::DEE] }
27
27
  it { should eq(Relation::DUM) }
28
28
  end
29
29
 
30
30
  describe "against DUM" do
31
- before{ operator.datasets = [suppliers, Relation::DUM] }
31
+ before{ operator.pipe [suppliers, Relation::DUM] }
32
32
  it { should eq(suppliers) }
33
33
  end
34
34
 
@@ -16,23 +16,27 @@ module Alf
16
16
  {:a => "via_reader", :time_sum => 6, :time_max => 4},
17
17
  ]}
18
18
 
19
- let(:aggs){{:time_sum => Aggregator.sum(:time),
20
- :time_max => Aggregator.max(:time)}}
21
- let(:operator){ Summarize::HashBased.new(by_key, aggs) }
19
+ let(:aggs){Summarization.new(
20
+ :time_sum => Aggregator.sum{ time },
21
+ :time_max => Aggregator.max{ time }
22
+ )}
23
+ let(:operator){ Summarize::HashBased.new(by_key, allbut, aggs) }
22
24
 
23
25
  before{ operator.pipe(input) }
24
26
  subject{ operator.to_a.sort{|t1,t2| t1[:a] <=> t2[:a]} }
25
27
 
26
28
  describe "when allbut is not set" do
27
- let(:by_key){ Tools::ProjectionKey.new([:a], false) }
29
+ let(:by_key){ AttrList.new([:a]) }
30
+ let(:allbut){ false }
28
31
  it { should == expected }
29
32
  end
30
33
 
31
34
  describe "when allbut is set" do
32
- let(:by_key){ Tools::ProjectionKey.new([:time], true) }
35
+ let(:by_key){ AttrList.new([:time]) }
36
+ let(:allbut){ true }
33
37
  it { should == expected }
34
38
  end
35
39
 
36
40
  end
37
41
  end
38
- end
42
+ end
@@ -16,16 +16,27 @@ module Alf
16
16
  {:a => "via_reader", :time_sum => 6, :time_max => 4},
17
17
  ]}
18
18
 
19
- let(:by_key){ Tools::ProjectionKey.new([:a],false) }
20
- let(:aggs){{:time_sum => Aggregator.sum(:time),
21
- :time_max => Aggregator.max(:time)}}
22
- let(:operator){ Summarize::SortBased.new(by_key, aggs) }
19
+ let(:aggs){Summarization.new(
20
+ :time_sum => Aggregator.sum{ time },
21
+ :time_max => Aggregator.max{ time }
22
+ )}
23
+ let(:operator){ Summarize::SortBased.new(by_key, allbut, aggs) }
23
24
 
24
25
  before{ operator.pipe(input) }
25
- subject{ operator.to_a }
26
+ subject{ operator.to_a.sort{|t1,t2| t1[:a] <=> t2[:a]} }
26
27
 
27
- it { should == expected }
28
+ describe "when allbut is not set" do
29
+ let(:by_key){ AttrList.new([:a]) }
30
+ let(:allbut){ false }
31
+ it { should == expected }
32
+ end
33
+
34
+ describe "when allbut is set" do
35
+ let(:by_key){ AttrList.new([:time]) }
36
+ let(:allbut){ true }
37
+ it { should == expected }
38
+ end
28
39
 
29
40
  end
30
41
  end
31
- end
42
+ end
@@ -13,9 +13,9 @@ module Alf
13
13
  ]}
14
14
 
15
15
  let(:expected) {[
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"})},
16
+ {:a => "via_method", :as => Alf::Relation[{:time => 1, :b => "b"},
17
+ {:time => 2, :b => "b"}]},
18
+ {:a => "via_reader", :as => Alf::Relation[{:time => 3, :b => "b"}]},
19
19
  ]}
20
20
 
21
21
  subject{ operator.to_a.sort{|k1,k2| k1[:a] <=> k2[:a]} }
@@ -23,7 +23,7 @@ module Alf
23
23
  describe "without --allbut" do
24
24
 
25
25
  describe "when factored with commandline args" do
26
- let(:operator){ Group.run(["--", "time", "b", "as"]) }
26
+ let(:operator){ Group.run(["--", "time", "b", "--", "as"]) }
27
27
  before{ operator.pipe(input) }
28
28
  it { should == expected }
29
29
  end
@@ -38,13 +38,13 @@ module Alf
38
38
  describe "with --allbut" do
39
39
 
40
40
  describe "when factored with commandline args" do
41
- let(:operator){ Group.run(["--","a", "as"]) }
42
- before{ operator.allbut = true; operator.pipe(input) }
41
+ let(:operator){ Group.run(["--allbut", "--","a", "--", "as"]) }
42
+ before{ operator.pipe(input) }
43
43
  it { should == expected }
44
44
  end
45
45
 
46
46
  describe "when factored with Lispy" do
47
- let(:operator){ Lispy.group(input, [:a], :as, true) }
47
+ let(:operator){ Lispy.group(input, [:a], :as, :allbut => true) }
48
48
  it { should == expected }
49
49
  end
50
50
 
@@ -52,4 +52,4 @@ module Alf
52
52
 
53
53
  end
54
54
  end
55
- end
55
+ end
@@ -26,12 +26,12 @@ module Alf
26
26
  subject{ operator.to_a }
27
27
 
28
28
  describe "when applied on the same operand twice" do
29
- before{ operator.datasets = [left, left] }
29
+ before{ operator.pipe [left, left] }
30
30
  it { should == left }
31
31
  end
32
32
 
33
33
  describe "when applied on operands sharing tuples" do
34
- before{ operator.datasets = [left, right] }
34
+ before{ operator.pipe [left, right] }
35
35
  let(:expected) {[
36
36
  {:sid => 'S1', :city => 'London'},
37
37
  {:sid => 'S2', :city => 'Paris'},
@@ -40,7 +40,7 @@ module Alf
40
40
  end
41
41
 
42
42
  describe "when applied on disjoint operands" do
43
- before{ operator.datasets = [left, disjoint] }
43
+ before{ operator.pipe [left, disjoint] }
44
44
  it { should be_empty }
45
45
  end
46
46
 
@@ -26,12 +26,12 @@ module Alf
26
26
  subject{ operator.to_a }
27
27
 
28
28
  describe "when applied on the same operand twice" do
29
- before{ operator.datasets = [left, left] }
29
+ before{ operator.pipe [left, left] }
30
30
  it { should be_empty }
31
31
  end
32
32
 
33
33
  describe "when applied on operands sharing tuples" do
34
- before{ operator.datasets = [left, right] }
34
+ before{ operator.pipe [left, right] }
35
35
  let(:expected) {[
36
36
  {:sid => 'S3', :city => 'Paris'}
37
37
  ]}
@@ -39,7 +39,7 @@ module Alf
39
39
  end
40
40
 
41
41
  describe "when applied on disjoint operands" do
42
- before{ operator.datasets = [left, disjoint] }
42
+ before{ operator.pipe [left, disjoint] }
43
43
  it { should == left }
44
44
  end
45
45
 
@@ -38,7 +38,12 @@ module Alf
38
38
  it { should == expected }
39
39
  end
40
40
 
41
- describe "and factored with Lispy" do
41
+ describe "and factored with Lispy#project" do
42
+ let(:operator){ Lispy.project(input, [:a], :allbut => true) }
43
+ it { should == expected }
44
+ end
45
+
46
+ describe "and factored with Lispy#allbut" do
42
47
  let(:operator){ Lispy.allbut(input, [:a]) }
43
48
  it { should == expected }
44
49
  end
@@ -58,8 +63,13 @@ module Alf
58
63
  it { should == [] }
59
64
  end
60
65
 
66
+ describe "when allbut is used" do
67
+ let(:operator){ Lispy.project(input, [:a, :b], :allbut => true) }
68
+ it { should == expected }
69
+ end
70
+
61
71
  end # all attributes projected
62
72
 
63
73
  end
64
74
  end
65
- end
75
+ end
@@ -25,20 +25,19 @@ module Alf
25
25
  subject{ operator.to_a }
26
26
 
27
27
  describe "When factored with commandline args" do
28
- let(:opts){ ['--by=a', "--order=time"] }
29
- let(:aggs){ ["time_sum", "sum(:time)", "time_max", "max(:time)"] }
30
- let(:operator){ Quota.run(opts + ["--"] + aggs) }
28
+ let(:aggs){ ["--", "a", "--", "time", "--", "time_sum", "sum{ time }", "time_max", "max{ time }"] }
29
+ let(:operator){ Quota.run(aggs) }
31
30
  before{ operator.pipe(input) }
32
31
  it { should == expected }
33
32
  end
34
33
 
35
34
  describe "When factored with Lispy" do
36
- let(:aggs){{:time_sum => Aggregator.sum(:time),
37
- :time_max => Aggregator.max(:time)}}
35
+ let(:aggs){{:time_sum => Aggregator.sum{ time },
36
+ :time_max => Aggregator.max{ time }}}
38
37
  let(:operator){ Lispy.quota(input, [:a], [:time], aggs) }
39
38
  it { should == expected }
40
39
  end
41
40
 
42
41
  end
43
42
  end
44
- end
43
+ end
@@ -19,18 +19,17 @@ module Alf
19
19
  {:a => "via_reader", :time_sum => 6, :time_max => 4, :time_avg => 6.0/2},
20
20
  ]}
21
21
 
22
- let(:aggs){{:time_sum => Aggregator.sum(:time),
23
- :time_max => Aggregator.max(:time),
24
- :time_avg => Aggregator.avg(:time)}}
22
+ let(:aggs){{:time_sum => Aggregator.sum{ time },
23
+ :time_max => Aggregator.max{ time },
24
+ :time_avg => Aggregator.avg{ time }}}
25
25
 
26
26
  subject{ operator.to_a.sort{|t1,t2| t1[:a] <=> t2[:a]} }
27
27
 
28
28
  describe "without allbut" do
29
29
 
30
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) }
31
+ let(:aggs){ ["--", "a", "--", "time_sum", "sum{ time }", "time_max", "max{ time }", "time_avg", "avg{ time }"] }
32
+ let(:operator){ Summarize.run(aggs) }
34
33
  before{ operator.pipe(input) }
35
34
  it { should == expected }
36
35
  end
@@ -45,15 +44,14 @@ module Alf
45
44
  describe "with allbut" do
46
45
 
47
46
  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) }
47
+ let(:aggs){ ["--allbut", "--", "time", "--", "time_sum", "sum{ time }", "time_max", "max{ time }", "time_avg", "avg{ time }"] }
48
+ let(:operator){ Summarize.run(aggs) }
51
49
  before{ operator.pipe(input) }
52
50
  it { should == expected }
53
51
  end
54
52
 
55
53
  describe "When factored with Lispy" do
56
- let(:operator){ Lispy.summarize(input, [:time], aggs, true) }
54
+ let(:operator){ Lispy.summarize(input, [:time], aggs, :allbut => true) }
57
55
  it { should == expected }
58
56
  end
59
57
 
@@ -61,4 +59,4 @@ module Alf
61
59
 
62
60
  end
63
61
  end
64
- end
62
+ end
@@ -21,7 +21,7 @@ module Alf
21
21
  subject{ operator.to_a }
22
22
 
23
23
  describe "when applied on non disjoint sets" do
24
- before{ operator.datasets = [left, right] }
24
+ before{ operator.pipe [left, right] }
25
25
  let(:expected){[
26
26
  {:city => 'London'},
27
27
  {:city => 'Paris'},
@@ -17,7 +17,7 @@ module Alf
17
17
  subject{ operator.to_a }
18
18
 
19
19
  describe "when factored with commandline args" do
20
- let(:operator){ Wrap.run(["--", "a", "b", "wraped"]) }
20
+ let(:operator){ Wrap.run(["--", "a", "b", "--", "wraped"]) }
21
21
  before{ operator.pipe(input) }
22
22
  it { should == expected }
23
23
  end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator
4
+ describe Signature, "#collect_on" do
5
+
6
+ subject{ op.class.signature.collect_on(op) }
7
+ let(:operands){ subject.first }
8
+ let(:arguments){ subject[1] }
9
+ let(:options){ subject[2] }
10
+
11
+ describe "on a nullary op" do
12
+ let(:op){ Alf.lispy.run %w{generator -- 10 -- id} }
13
+ it { should eq([[], [10, :id], {}]) }
14
+ end
15
+
16
+ describe "on a monadic op, with one arg" do
17
+ let(:op){ Alf.lispy.run %w{autonum suppliers -- id} }
18
+ specify{
19
+ operands.collect{|o| o.class}.should eq([Iterator::Proxy])
20
+ arguments.should eq([:id])
21
+ options.should eq({})
22
+ }
23
+ end
24
+
25
+ describe "on a monadic op, with one arg and an option" do
26
+ let(:op){ Alf.lispy.run %w{project --allbut suppliers -- name city} }
27
+ specify{
28
+ operands.collect{|o| o.class}.should eq([Iterator::Proxy])
29
+ arguments.should eq([AttrList.new([:name, :city])])
30
+ options.should eq({:allbut => true})
31
+ }
32
+ end
33
+
34
+ describe "on a dyadic op" do
35
+ let(:op){ Alf.lispy.run %w{join suppliers cities} }
36
+ specify{
37
+ operands.collect{|o| o.class}.should eq([Iterator::Proxy, Iterator::Proxy])
38
+ arguments.should eq([])
39
+ options.should eq({})
40
+ }
41
+ end
42
+
43
+ end
44
+ end # module Operator
45
+ end # module Alf
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator
4
+ describe Signature, '.initialize' do
5
+
6
+ it "should yield the signature" do
7
+ sig = Signature.new(nil){|s|
8
+ s.argument :name, AttrName, :autonum
9
+ s.option :allbut, Boolean, true, "Applies an allbut projection?"
10
+ }
11
+ sig.arguments.should eql([[:name, AttrName, :autonum, nil]])
12
+ sig.options.should eql([[:allbut, Boolean, true, "Applies an allbut projection?"]])
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator
4
+ describe Signature, '.install' do
5
+
6
+ let(:clazz){ Class.new(Object) }
7
+ subject{ signature.install }
8
+
9
+ describe "on an empty signature" do
10
+ let(:signature){ Signature.new(clazz) }
11
+ it{ should eq({}) }
12
+ specify{
13
+ lambda{ subject }.should_not raise_error
14
+ }
15
+ end
16
+
17
+ describe "on a non empty signature" do
18
+
19
+ let(:signature){
20
+ Signature.new(clazz) do |s|
21
+ s.argument :attrname, AttrName
22
+ s.argument :ordering, Ordering
23
+ s.option :allbut, Boolean, true
24
+ end
25
+ }
26
+
27
+ it{ should eq(:allbut => true) }
28
+
29
+ it "should have arguments installed as attr accessors" do
30
+ subject
31
+ inst = clazz.new
32
+ inst.should respond_to(:attrname)
33
+ inst.send(:"attrname=", :hello)
34
+ inst.attrname.should eq(:hello)
35
+ end
36
+
37
+ it "should have options installed as attr accessors" do
38
+ subject
39
+ inst = clazz.new
40
+ inst.should respond_to(:allbut)
41
+ inst.send(:"allbut=", true)
42
+ inst.allbut.should be_true
43
+ end
44
+
45
+ it "should apply auto-coercion" do
46
+ subject
47
+ inst = clazz.new
48
+ inst.send(:"allbut=", "true")
49
+ inst.allbut.should be_true
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator
4
+ describe Signature, '#option_parser' do
5
+
6
+ let(:clazz){ Class.new(Object) }
7
+ let(:signature){
8
+ Signature.new(clazz) do |s|
9
+ s.option :allbut, Boolean, true
10
+ s.option :name, AttrName, :autonum
11
+ end
12
+ }
13
+ let(:receiver){ clazz.new }
14
+ before{ signature.install }
15
+ subject{ signature.option_parser(receiver) }
16
+
17
+ specify "expected" do
18
+ opt = OptionParser.new
19
+ opt.on("--allbut"){ receiver.send(:allbut=,true) }
20
+ opt.on("--name=NAME"){|val| receiver.send(:name=,val) }
21
+ opt.parse!(["--allbut","--name=world"])
22
+ receiver.allbut.should be_true
23
+ receiver.name.should eq(:world)
24
+ end
25
+
26
+ it { should be_a(OptionParser) }
27
+
28
+ it "should install option values correctly" do
29
+ subject.parse!(["--allbut","--name=world"])
30
+ receiver.allbut.should be_true
31
+ receiver.name.should eq(:world)
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator
4
+ describe Signature, "#parse_args" do
5
+
6
+ let(:clazz){ Class.new(Object) }
7
+ let(:receiver){ clazz.new }
8
+ before{
9
+ signature.install
10
+ }
11
+ subject{
12
+ signature.parse_args(args, receiver)
13
+ receiver
14
+ }
15
+
16
+ describe "on a singleton signature with a AttrList" do
17
+ let(:signature){
18
+ Signature.new(clazz) do |s|
19
+ s.argument :proj, AttrList
20
+ end
21
+ }
22
+ let(:args){ [%w{hello world}] }
23
+ specify{
24
+ subject.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(:args){ [] }
35
+ specify{
36
+ subject.attrname.should eq(:autonum)
37
+ }
38
+ end
39
+
40
+ describe "on a signature with options" do
41
+ let(:signature){
42
+ Signature.new(clazz) do |s|
43
+ s.argument :key, AttrList, []
44
+ s.option :allbut, Boolean, false
45
+ end
46
+ }
47
+
48
+ describe "when no option is provided" do
49
+ let(:args){ [[:hello, :world]] }
50
+ specify{
51
+ subject.key.should eql(AttrList.new([:hello, :world]))
52
+ subject.allbut.should eql(false)
53
+ }
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+ end
60
+ end