alf 0.9.3 → 0.10.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 (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