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
@@ -0,0 +1,138 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ describe Tools, ".to_lispy" do
4
+
5
+ subject{ Tools.to_lispy(value) }
6
+
7
+ describe "on a Proxy" do
8
+ let(:value){ Iterator::Proxy.new(nil, :suppliers) }
9
+ it { should eq(":suppliers") }
10
+ end
11
+
12
+ describe "on an AttrName" do
13
+ let(:value){ :city }
14
+ it { should eq(":city") }
15
+ end
16
+
17
+ describe "on an AttrList" do
18
+ let(:value){ AttrList.new([:name, :city]) }
19
+ it { should eq("[:name, :city]") }
20
+ end
21
+
22
+ describe "on a Heading" do
23
+ let(:value){ Heading.new(:name => String) }
24
+ it { should eq("{:name => String}") }
25
+ end
26
+
27
+ describe "on an Ordering" do
28
+ let(:value){ Ordering.new([[:name, :asc], [:city, :desc]]) }
29
+ it { should eq("[[:name, :asc], [:city, :desc]]") }
30
+ end
31
+
32
+ describe "on a Renaming" do
33
+ let(:value){ Renaming.new(:old => :new) }
34
+ it { should eq("{:old => :new}") }
35
+ end
36
+
37
+ describe "on an Aggregation" do
38
+ let(:value){ Aggregator.coerce("sum{ qty*price }") }
39
+ it { should eq("sum{ qty*price }") }
40
+ end
41
+
42
+ describe "on a TupleExpression" do
43
+ let(:value){ TupleExpression.coerce(arg) }
44
+
45
+ describe "When built from a string" do
46
+ let(:arg){ "status.upcase" }
47
+ it{ should eq("->(){ status.upcase }")}
48
+ end
49
+
50
+ describe "When built from a symbol" do
51
+ let(:arg){ :status }
52
+ it{ should eq("->(){ status }")}
53
+ end
54
+
55
+ end # TupleExpression
56
+
57
+ describe "on a TuplePredicate" do
58
+ let(:value){ TuplePredicate.coerce(arg) }
59
+
60
+ describe "When built from a TupleExpression" do
61
+ let(:arg){ TupleExpression.coerce("status > 10") }
62
+ it{ should eq("->(){ status > 10 }")}
63
+ end
64
+
65
+ describe "When built from a boolean" do
66
+ let(:arg){ true }
67
+ it{ should eq("->(){ true }")}
68
+ end
69
+
70
+ describe "When built from a String" do
71
+ let(:arg){ "status > 10" }
72
+ it{ should eq("->(){ status > 10 }")}
73
+ end
74
+
75
+ describe "When built from a Hash" do
76
+ let(:arg){ {:status => 10} }
77
+ it{ should eq("->(){ (self.status == 10) }")}
78
+ end
79
+
80
+ describe "When built with a singleton Array" do
81
+ let(:arg){ ["status > 10"] }
82
+ it{ should eq("->(){ status > 10 }")}
83
+ end
84
+
85
+ describe "When built with a Hash-Array" do
86
+ let(:arg){ ["status", "10"] }
87
+ it{ should eq("->(){ (self.status == 10) }")}
88
+ end
89
+
90
+ describe "When built with a Hash-Array without coercion" do
91
+ let(:arg){ [:status, "10"] }
92
+ it{ should eq("->(){ (self.status == \"10\") }")}
93
+ end
94
+
95
+ end # TuplePredicate
96
+
97
+ describe "on a TupleComputation" do
98
+ let(:value){ TupleComputation.coerce(arg) }
99
+
100
+ describe "When built from a Hash" do
101
+ let(:arg){ {"upcased" => "status.upcase"} }
102
+ it{ should eq("{:upcased => ->(){ status.upcase }}")}
103
+ end
104
+
105
+ end # TupleComputation
106
+
107
+ describe "on a Summarization" do
108
+ let(:value){ Summarization.coerce(arg) }
109
+
110
+ describe "When built from an Array" do
111
+ let(:arg){ {"total" => "sum{ qty*price }"} }
112
+ it{ should eq("{:total => sum{ qty*price }}") }
113
+ end
114
+
115
+ end # Summarization
116
+
117
+ describe "on an nullary operator" do
118
+ let(:value){ Alf.lispy.run(%w{generator -- 10 -- id}) }
119
+ it { should eq("(generator 10, :id)") }
120
+ end
121
+
122
+ describe "on an monadic operator with an option" do
123
+ let(:value){ Alf.lispy.run(%w{project --allbut suppliers -- city}) }
124
+ it { should eq("(project :suppliers, [:city], {:allbut => true})") }
125
+ end
126
+
127
+ describe "on an monadic operator with default values for options" do
128
+ let(:value){ Alf.lispy.run(%w{project suppliers -- city}) }
129
+ it { should eq("(project :suppliers, [:city])") }
130
+ end
131
+
132
+ describe "on an dyadic operator without no args nor any option" do
133
+ let(:value){ Alf.lispy.run(%w{join suppliers cities}) }
134
+ it { should eq("(join :suppliers, :cities)") }
135
+ end
136
+
137
+ end
138
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ describe "Tools#to_ruby_literal" do
4
+
5
+ specify {
6
+ Tools.to_ruby_literal(12).should eql("12")
7
+ }
8
+
9
+ end
10
+ end
@@ -29,47 +29,7 @@ module Alf
29
29
  handle.set(:path => 1)
30
30
  handle.instance_eval{ path < 1 }.should be_false
31
31
  end
32
-
33
- describe "compile" do
34
-
35
- it "should return a Proc when passed a string" do
36
- TupleHandle.compile("true").should be_a(Proc)
37
- end
38
-
39
- it "should return the Proc when directly passed" do
40
- x = lambda{ true }
41
- TupleHandle.compile(x).should == x
42
- end
43
-
44
- it "should support an empty Hash" do
45
- pred = TupleHandle.compile({})
46
- pred.call.should be_true
47
- end
48
-
49
- it "should support a Hash" do
50
- pred = TupleHandle.compile({:status => 10})
51
- handle = TupleHandle.new
52
- handle.set({:status => 20}).evaluate(pred).should be_false
53
- handle.set({:status => 10}).evaluate(pred).should be_true
54
- end
55
-
56
- it "should support a Hash using keywords as attribute names" do
57
- pred = TupleHandle.compile({:when => 10})
58
- handle = TupleHandle.new
59
- handle.set({:when => 20}).evaluate(pred).should be_false
60
- handle.set({:when => 10}).evaluate(pred).should be_true
61
- end
62
-
63
- it "should support a Hash containing a Date" do
64
- today = Date.today
65
- pred = TupleHandle.compile({:at => today})
66
- handle = TupleHandle.new
67
- handle.set({:at => today}).evaluate(pred).should be_true
68
- handle.set({:at => today+1}).evaluate(pred).should be_false
69
- end
70
-
71
- end
72
-
32
+
73
33
  describe "evaluate" do
74
34
  before{ handle.set(:a => 1, :b => 2) }
75
35
 
@@ -85,24 +45,6 @@ module Alf
85
45
  handle.evaluate(lambda{ a }).should == 1
86
46
  end
87
47
 
88
- it "should allow a Hash" do
89
- handle.evaluate(:a => 1).should == true
90
- handle.evaluate(:a => 2).should == false
91
- handle.evaluate(:a => 1, :b => 1).should == false
92
- handle.evaluate(:a => 1, :b => 2).should == true
93
- end
94
-
95
- it "should allow an Array" do
96
- handle.evaluate([:a, 1]).should == true
97
- handle.evaluate([:a, 2]).should == false
98
- handle.evaluate([:a, 1, :b, 1]).should == false
99
- handle.evaluate([:a, 1, :b, 2]).should == true
100
- end
101
-
102
- it "should allow the result of compile" do
103
- handle.evaluate(TupleHandle.compile('a')).should == 1
104
- end
105
-
106
48
  end
107
49
 
108
50
  end
@@ -0,0 +1,106 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ describe AttrList do
4
+
5
+ describe "coerce" do
6
+
7
+ subject{ AttrList.coerce(arg) }
8
+
9
+ describe "when passed a AttrList" do
10
+ let(:arg){ [:a, :b] }
11
+ it{ should eq(AttrList.new(arg)) }
12
+ end
13
+
14
+ describe "when passed an array" do
15
+ let(:arg){ [:a, :b] }
16
+ specify{
17
+ subject.attributes.should eq([:a, :b])
18
+ }
19
+ end
20
+
21
+ describe "when passed an Ordering" do
22
+ let(:arg){ Ordering.new [[:a, :asc], [:b, :asc]] }
23
+ it{ should eq(AttrList.new([:a, :b])) }
24
+ end
25
+
26
+ end
27
+
28
+ describe "from_argv" do
29
+
30
+ subject{ AttrList.from_argv(argv) }
31
+
32
+ describe "on an empty array" do
33
+ let(:argv){ [] }
34
+ it{ should eq(AttrList.new([])) }
35
+ end
36
+
37
+ describe "on a singleton" do
38
+ let(:argv){ ["hello"] }
39
+ it{ should eq(AttrList.new([:hello])) }
40
+ end
41
+
42
+ describe "on multiple strings" do
43
+ let(:argv){ ["hello", "world"] }
44
+ it{ should eq(AttrList.new([:hello, :world])) }
45
+ end
46
+
47
+ end
48
+
49
+ describe "to_ordering" do
50
+
51
+ specify "when passed an array" do
52
+ key = AttrList.coerce [:a, :b]
53
+ okey = key.to_ordering
54
+ okey.attributes.should == [:a, :b]
55
+ okey.order_of(:a).should == :asc
56
+ okey.order_of(:b).should == :asc
57
+ end
58
+
59
+ end
60
+
61
+ describe "split" do
62
+
63
+ subject{ key.split(tuple, allbut) }
64
+
65
+ describe "when used without allbut" do
66
+ let(:key){ AttrList.new [:a, :b] }
67
+ let(:allbut){ false }
68
+ let(:tuple){ {:a => 1, :b => 2, :c => 3} }
69
+ let(:expected){ [{:a => 1, :b => 2}, {:c => 3}] }
70
+ it{ should == expected }
71
+ end
72
+
73
+ describe "when used with allbut" do
74
+ let(:key){ AttrList.new [:a, :b] }
75
+ let(:allbut){ true }
76
+ let(:tuple){ {:a => 1, :b => 2, :c => 3} }
77
+ let(:expected){ [{:c => 3}, {:a => 1, :b => 2}] }
78
+ it{ should == expected }
79
+ end
80
+
81
+ end
82
+
83
+ describe "project" do
84
+
85
+ subject{ key.project(tuple, allbut) }
86
+
87
+ describe "when used without allbut" do
88
+ let(:key){ AttrList.new [:a, :b] }
89
+ let(:allbut){ false }
90
+ let(:tuple){ {:a => 1, :b => 2, :c => 3} }
91
+ let(:expected){ {:a => 1, :b => 2} }
92
+ it{ should == expected }
93
+ end
94
+
95
+ describe "when used with allbut" do
96
+ let(:key){ AttrList.new [:a, :b] }
97
+ let(:allbut){ true }
98
+ let(:tuple){ {:a => 1, :b => 2, :c => 3} }
99
+ let(:expected){ {:c => 3} }
100
+ it{ should == expected }
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ describe AttrName do
4
+
5
+ it "should allow normal names" do
6
+ (AttrName === :city).should be_true
7
+ end
8
+
9
+ it "should allow underscores" do
10
+ (AttrName === :my_city).should be_true
11
+ end
12
+
13
+ it "should allow numbers" do
14
+ (AttrName === :city2).should be_true
15
+ end
16
+
17
+ it "should not allow strange attribute names" do
18
+ (AttrName === "$$$".to_sym).should be_false
19
+ end
20
+
21
+ describe "from_argv" do
22
+
23
+ subject{ AttrName.from_argv(argv, opts) }
24
+
25
+ describe "with a String" do
26
+ let(:argv){ %w{hello} }
27
+ let(:opts) {{}}
28
+ it{ should eq(:hello) }
29
+ end
30
+
31
+ describe "with nothing but a default" do
32
+ let(:argv){ %w{} }
33
+ let(:opts){ {:default => :hello} }
34
+ it{ should eq(:hello) }
35
+ end
36
+
37
+ describe "with nothing and no default" do
38
+ let(:argv){ %w{} }
39
+ let(:opts){ {} }
40
+ specify{ lambda{subject}.should raise_error(ArgumentError) }
41
+ end
42
+
43
+ describe "with more than one string" do
44
+ let(:argv){ %w{hello world} }
45
+ let(:opts){ {} }
46
+ specify{ lambda{subject}.should raise_error(ArgumentError) }
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+ end
@@ -6,6 +6,16 @@ module Alf
6
6
  let(:h1){ Heading.new(:name => String) }
7
7
  let(:h2){ Heading.new(:name => String, :price => Float) }
8
8
 
9
+ specify "coerce" do
10
+ Heading.coerce(:name => String).should eq(h1)
11
+ Heading.coerce([]).should eq(h0)
12
+ Heading.coerce(["name", "String"]).should eq(h1)
13
+ end
14
+
15
+ specify "from_argv" do
16
+ Heading.from_argv(["name", "String"]).should eq(h1)
17
+ end
18
+
9
19
  specify "cardinality" do
10
20
  h0.cardinality.should eq(0)
11
21
  h1.cardinality.should eq(1)
@@ -0,0 +1,127 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ describe Ordering do
4
+
5
+ describe "coerce" do
6
+
7
+ specify "when passed an doubly array" do
8
+ key = Ordering.coerce [[:a, :asc], [:b, :desc]]
9
+ key.attributes.should == [:a, :b]
10
+ key.order_of(:a).should == :asc
11
+ key.order_of(:b).should == :desc
12
+ end
13
+
14
+ specify "when passed a single array" do
15
+ key = Ordering.coerce [:a, :b]
16
+ key.attributes.should == [:a, :b]
17
+ key.order_of(:a).should == :asc
18
+ key.order_of(:b).should == :asc
19
+ end
20
+
21
+ specify "when passed a single array of strings" do
22
+ key = Ordering.coerce ["a", "b"]
23
+ key.attributes.should == [:a, :b]
24
+ key.order_of(:a).should == :asc
25
+ key.order_of(:b).should == :asc
26
+ end
27
+
28
+ specify "when passed a single array with asc and desc (1)" do
29
+ key = Ordering.coerce [:a, :asc]
30
+ key.attributes.should == [:a]
31
+ key.order_of(:a).should == :asc
32
+ end
33
+
34
+ specify "when passed a single array with asc and desc (1)" do
35
+ key = Ordering.coerce [:a, :asc, :b, :desc]
36
+ key.attributes.should == [:a, :b]
37
+ key.order_of(:a).should == :asc
38
+ key.order_of(:b).should == :desc
39
+ end
40
+
41
+ specify "when passed a string array with asc and desc" do
42
+ key = Ordering.coerce ["a", "asc", "b", "desc"]
43
+ key.attributes.should == [:a, :b]
44
+ key.order_of(:a).should == :asc
45
+ key.order_of(:b).should == :desc
46
+ end
47
+
48
+ specify "when passed an ordering key" do
49
+ key = Ordering.coerce [:a, :b]
50
+ key2 = Ordering.coerce key
51
+ key.should == key2
52
+ end
53
+
54
+ specify "when passed a projection key" do
55
+ pkey = AttrList.new [:a, :b]
56
+ key = Ordering.coerce pkey
57
+ key.attributes.should == [:a, :b]
58
+ key.order_of(:a).should == :asc
59
+ key.order_of(:b).should == :asc
60
+ end
61
+
62
+ end # coerce
63
+
64
+ describe "from_argv" do
65
+
66
+ subject{ Ordering.from_argv(argv) }
67
+
68
+ describe "on an empty array" do
69
+ let(:argv){ [] }
70
+ it{ should eq(Ordering.new([])) }
71
+ end
72
+
73
+ describe "on a singleton" do
74
+ let(:argv){ ["hello"] }
75
+ it{ should eq(Ordering.new([[:hello, :asc]])) }
76
+ end
77
+
78
+ describe "on multiple strings" do
79
+ let(:argv){ ["hello", "asc", "world", "desc"] }
80
+ it{ should eq(Ordering.new([[:hello, :asc], [:world, :desc]])) }
81
+ end
82
+
83
+ end
84
+
85
+ describe "compare" do
86
+
87
+ specify "when passed a single key" do
88
+ key = Ordering.coerce [:a]
89
+ key.compare({:a => 1}, {:a => 2}).should == -1
90
+ key.compare({:a => 1}, {:a => 1}).should == 0
91
+ key.compare({:a => 2}, {:a => 1}).should == 1
92
+ end
93
+
94
+ specify "when passed a single key with desc order" do
95
+ key = Ordering.coerce [[:a, :desc]]
96
+ key.compare({:a => 1}, {:a => 2}).should == 1
97
+ key.compare({:a => 1}, {:a => 1}).should == 0
98
+ key.compare({:a => 2}, {:a => 1}).should == -1
99
+ end
100
+
101
+ specify "when passed a double key" do
102
+ key = Ordering.coerce [[:a, :asc], [:b, :desc]]
103
+ key.compare({:a => 1, :b => 1}, {:a => 0, :b => 1}).should == 1
104
+ key.compare({:a => 1, :b => 1}, {:a => 1, :b => 2}).should == 1
105
+ key.compare({:a => 1, :b => 1}, {:a => 1, :b => 1}).should == 0
106
+ end
107
+
108
+ end
109
+
110
+ describe "+" do
111
+
112
+ specify "when passed another key" do
113
+ key = Ordering.coerce [:a]
114
+ key2 = key + Ordering.coerce([[:b, :desc]])
115
+ key2.ordering.should == [[:a, :asc], [:b, :desc]]
116
+ end
117
+
118
+ specify "when passed another array" do
119
+ key = Ordering.coerce [:a]
120
+ key2 = key + [[:b, :desc]]
121
+ key2.ordering.should == [[:a, :asc], [:b, :desc]]
122
+ end
123
+
124
+ end
125
+
126
+ end
127
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ describe Renaming do
4
+
5
+ describe "coerce" do
6
+
7
+ subject{ Renaming.coerce(arg) }
8
+
9
+ describe "from a Renaming" do
10
+ let(:arg){ Renaming.new(:old => :new) }
11
+ it{ should eq(arg) }
12
+ end
13
+
14
+ describe "from a Hash" do
15
+ let(:arg){ {"old" => "new"} }
16
+ it{ should eq(Renaming.new(:old => :new)) }
17
+ end
18
+
19
+ describe "from an Array" do
20
+ let(:arg){ ["old", "new"] }
21
+ it{ should eq(Renaming.new(:old => :new)) }
22
+ end
23
+
24
+ end
25
+
26
+ describe "from_argv" do
27
+
28
+ subject{ Renaming.from_argv(argv) }
29
+
30
+ describe "from an empty Array" do
31
+ let(:argv){ [] }
32
+ it{ should eq(Renaming.new({})) }
33
+ end
34
+
35
+ describe "from an Array of two elements" do
36
+ let(:argv){ ["old", "new"] }
37
+ it{ should eq(Renaming.new(:old => :new)) }
38
+ end
39
+
40
+ describe "from an Array of four elements" do
41
+ let(:argv){ ["old", "new", "hello", "world"] }
42
+ it{ should eq(Renaming.new(:old => :new, :hello => :world)) }
43
+ end
44
+
45
+ end
46
+
47
+ describe "apply" do
48
+ let(:r){ Renaming.coerce(["old", "new"])}
49
+ specify{
50
+ r.apply(:old => :a, :other => :b).should eql(:new => :a, :other => :b)
51
+ }
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ describe Summarization do
4
+
5
+ describe "coerce" do
6
+
7
+ subject{ Summarization.coerce(arg) }
8
+
9
+ describe "from a Summarization" do
10
+ let(:arg){ Summarization.new(:s => Aggregator.sum{ qty }) }
11
+ it{ should eq(arg) }
12
+ end
13
+
14
+ describe "from a Hash" do
15
+ let(:arg){ { :s => "sum{ qty }", :m => Aggregator.max{ size } } }
16
+ it{ should be_a(Summarization) }
17
+ specify{
18
+ subject.aggregations.values.all?{|v|
19
+ v.is_a?(Aggregator)
20
+ }.should be_true
21
+ }
22
+ end
23
+
24
+ describe "from an Array" do
25
+ let(:arg){ ["s", "sum{ qty }", "m", "max{ size }"] }
26
+ it{ should be_a(Summarization) }
27
+ specify{
28
+ ([:s, :m] & subject.aggregations.keys).should eq([:s, :m])
29
+ subject.aggregations.values.all?{|v|
30
+ v.is_a?(Aggregator)
31
+ }.should be_true
32
+ }
33
+ end
34
+
35
+ end
36
+
37
+ describe "from_argv" do
38
+
39
+ subject{ Summarization.from_argv(argv) }
40
+
41
+ describe "from an Array" do
42
+ let(:argv){ ["s", "sum{ qty }", "m", "max{ size }"] }
43
+ it{ should be_a(Summarization) }
44
+ specify{
45
+ ([:s, :m] & subject.aggregations.keys).should eq([:s, :m])
46
+ subject.aggregations.values.all?{|v|
47
+ v.is_a?(Aggregator)
48
+ }.should be_true
49
+ }
50
+ end
51
+
52
+ end
53
+
54
+ specify "least -> happens -> finalize" do
55
+ summ = Summarization.coerce(["s", "sum{ qty }", "m", "max{ size }"])
56
+ (x = summ.least).should eql(:s => 0, :m => nil)
57
+ (x = summ.happens(x, :qty => 10, :size => 12)).should eq(:s => 10, :m => 12)
58
+ (x = summ.happens(x, :qty => 5, :size => 5)).should eq(:s => 15, :m => 12)
59
+ summ.finalize(x).should eq(:s => 15, :m => 12)
60
+ end
61
+
62
+ end
63
+ end