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,24 @@
1
+ module Alf
2
+ module Operator::Relational
3
+ class Extend < Alf::Operator()
4
+ include Operator::Relational, Operator::Transform
5
+
6
+ signature do |s|
7
+ s.argument :ext, TupleComputation, {}
8
+ end
9
+
10
+ protected
11
+
12
+ # (see Operator#_prepare)
13
+ def _prepare
14
+ @handle = TupleHandle.new
15
+ end
16
+
17
+ # (see Operator::Transform#_tuple2tuple)
18
+ def _tuple2tuple(tuple)
19
+ tuple.merge @ext.evaluate(@handle.set(tuple))
20
+ end
21
+
22
+ end # class Extend
23
+ end # module Operator::Relational
24
+ end # module Alf
@@ -0,0 +1,32 @@
1
+ module Alf
2
+ module Operator::Relational
3
+ class Group < Alf::Operator()
4
+ include Operator::Relational, Operator::Unary
5
+
6
+ signature do |s|
7
+ s.argument :attributes, AttrList, []
8
+ s.argument :as, AttrName, :group
9
+ s.option :allbut, Boolean, false, 'Group all but specified attributes?'
10
+ end
11
+
12
+ protected
13
+
14
+ # See Operator#_prepare
15
+ def _prepare
16
+ @index = Hash.new{|h,k| h[k] = Set.new}
17
+ each_input_tuple do |tuple|
18
+ key, rest = @attributes.split(tuple, !@allbut)
19
+ @index[key] << rest
20
+ end
21
+ end
22
+
23
+ # See Operator#_each
24
+ def _each
25
+ @index.each_pair do |k,v|
26
+ yield(k.merge(@as => Relation.coerce(v)))
27
+ end
28
+ end
29
+
30
+ end # class Group
31
+ end # module Operator::Relational
32
+ end # module Alf
@@ -0,0 +1,37 @@
1
+ module Alf
2
+ module Operator::Relational
3
+ class Intersect < Alf::Operator()
4
+ include Operator, Operator::Relational, Operator::Shortcut, Operator::Binary
5
+
6
+ signature do |s|
7
+ end
8
+
9
+ class HashBased
10
+ include Operator, Operator::Binary
11
+
12
+ protected
13
+
14
+ def _prepare
15
+ @index = Hash.new
16
+ right.each{|t| @index[t] = true}
17
+ end
18
+
19
+ def _each
20
+ left.each do |left_tuple|
21
+ yield(left_tuple) if @index.has_key?(left_tuple)
22
+ end
23
+ end
24
+
25
+ end
26
+
27
+ protected
28
+
29
+ # (see Shortcut#longexpr)
30
+ def longexpr
31
+ chain HashBased.new,
32
+ datasets
33
+ end
34
+
35
+ end # class Intersect
36
+ end # module Operator::Relational
37
+ end # module Alf
@@ -0,0 +1,106 @@
1
+ module Alf
2
+ module Operator::Relational
3
+ class Join < Alf::Operator()
4
+ include Operator::Relational, Operator::Shortcut, Operator::Binary
5
+
6
+ signature do |s|
7
+ end
8
+
9
+ #
10
+ # Performs a Join of two relations through a Hash buffer on the right
11
+ # one.
12
+ #
13
+ class HashBased
14
+ include Operator, Operator::Binary
15
+
16
+ #
17
+ # Implements a special Buffer for join-based relational operators.
18
+ #
19
+ # Example:
20
+ #
21
+ # buffer = Buffer::Join.new(...) # pass the right part of the join
22
+ # left.each do |left_tuple|
23
+ # key, rest = buffer.split(tuple)
24
+ # buffer.each(key) do |right_tuple|
25
+ # #
26
+ # # do whatever you want with left and right tuples
27
+ # #
28
+ # end
29
+ # end
30
+ #
31
+ class JoinBuffer
32
+ include Tools
33
+
34
+ #
35
+ # Creates a buffer instance with the right part of the join.
36
+ #
37
+ # @param [Iterator] enum a tuple iterator, right part of the join.
38
+ #
39
+ def initialize(enum)
40
+ @buffer = nil
41
+ @key = nil
42
+ @enum = enum
43
+ end
44
+
45
+ #
46
+ # Splits a left tuple according to the common key.
47
+ #
48
+ # @param [Hash] tuple a left tuple of the join
49
+ # @return [Array] an array of two elements, the key and the rest
50
+ # @see AttrList#split
51
+ #
52
+ def split(tuple)
53
+ _init(tuple) unless @key
54
+ @key.split(tuple)
55
+ end
56
+
57
+ #
58
+ # Yields each right tuple that matches a given key value.
59
+ #
60
+ # @param [Hash] key a tuple that matches elements of the common key
61
+ # (typically the first element returned by #split)
62
+ #
63
+ def each(key)
64
+ @buffer[key].each(&Proc.new) if @buffer.has_key?(key)
65
+ end
66
+
67
+ private
68
+
69
+ # Initialize the buffer with a right tuple
70
+ def _init(right)
71
+ @buffer = Hash.new{|h,k| h[k] = []}
72
+ @enum.each do |left|
73
+ @key ||= coerce(left.keys & right.keys, AttrList)
74
+ @buffer[@key.project(left)] << left
75
+ end
76
+ @key ||= coerce([], AttrList)
77
+ end
78
+
79
+ end # class JoinBuffer
80
+
81
+ protected
82
+
83
+ # (see Operator#_each)
84
+ def _each
85
+ buffer = JoinBuffer.new(right)
86
+ left.each do |left_tuple|
87
+ key, rest = buffer.split(left_tuple)
88
+ buffer.each(key) do |right|
89
+ yield(left_tuple.merge(right))
90
+ end
91
+ end
92
+ end
93
+
94
+ end
95
+
96
+ protected
97
+
98
+ # (see Shortcut#longexpr)
99
+ def longexpr
100
+ chain HashBased.new,
101
+ datasets
102
+ end
103
+
104
+ end # class Join
105
+ end # module Operator::Relational
106
+ end # module Alf
@@ -0,0 +1,45 @@
1
+ module Alf
2
+ module Operator::Relational
3
+ class Matching < Alf::Operator()
4
+ include Operator::Relational, Operator::Shortcut, Operator::Binary
5
+
6
+ signature do |s|
7
+ end
8
+
9
+ #
10
+ # Performs a Matching of two relations through a Hash buffer on the right
11
+ # one.
12
+ #
13
+ class HashBased
14
+ include Operator, Operator::Binary
15
+
16
+ # (see Operator#_each)
17
+ def _each
18
+ seen, key = nil, nil
19
+ left.each do |left_tuple|
20
+ seen ||= begin
21
+ h = Hash.new
22
+ right.each do |right_tuple|
23
+ key ||= coerce(left_tuple.keys & right_tuple.keys, AttrList)
24
+ h[key.project(right_tuple)] = true
25
+ end
26
+ key ||= coerce([], AttrList)
27
+ h
28
+ end
29
+ yield(left_tuple) if seen.has_key?(key.project(left_tuple))
30
+ end
31
+ end
32
+
33
+ end # class HashBased
34
+
35
+ protected
36
+
37
+ # (see Shortcut#longexpr)
38
+ def longexpr
39
+ chain HashBased.new,
40
+ datasets
41
+ end
42
+
43
+ end # class Matching
44
+ end # module Operator::Relational
45
+ end # module Alf
@@ -0,0 +1,37 @@
1
+ module Alf
2
+ module Operator::Relational
3
+ class Minus < Alf::Operator()
4
+ include Operator::Relational, Operator::Shortcut, Operator::Binary
5
+
6
+ signature do |s|
7
+ end
8
+
9
+ class HashBased
10
+ include Operator, Operator::Binary
11
+
12
+ protected
13
+
14
+ def _prepare
15
+ @index = Hash.new
16
+ right.each{|t| @index[t] = true}
17
+ end
18
+
19
+ def _each
20
+ left.each do |left_tuple|
21
+ yield(left_tuple) unless @index.has_key?(left_tuple)
22
+ end
23
+ end
24
+
25
+ end
26
+
27
+ protected
28
+
29
+ # (see Shortcut#longexpr)
30
+ def longexpr
31
+ chain HashBased.new,
32
+ datasets
33
+ end
34
+
35
+ end # class Minus
36
+ end # module Operator::Relational
37
+ end # module Alf
@@ -0,0 +1,45 @@
1
+ module Alf
2
+ module Operator::Relational
3
+ class NotMatching < Alf::Operator()
4
+ include Operator::Relational, Operator::Shortcut, Operator::Binary
5
+
6
+ signature do |s|
7
+ end
8
+
9
+ #
10
+ # Performs a NotMatching of two relations through a Hash buffer on the
11
+ # right one.
12
+ #
13
+ class HashBased
14
+ include Operator, Operator::Binary
15
+
16
+ # (see Operator#_each)
17
+ def _each
18
+ seen, key = nil, nil
19
+ left.each do |left_tuple|
20
+ seen ||= begin
21
+ h = Hash.new
22
+ right.each do |right_tuple|
23
+ key ||= coerce(left_tuple.keys & right_tuple.keys, AttrList)
24
+ h[key.project(right_tuple)] = true
25
+ end
26
+ key ||= coerce([], AttrList)
27
+ h
28
+ end
29
+ yield(left_tuple) unless seen.has_key?(key.project(left_tuple))
30
+ end
31
+ end
32
+
33
+ end # class HashBased
34
+
35
+ protected
36
+
37
+ # (see Shortcut#longexpr)
38
+ def longexpr
39
+ chain HashBased.new,
40
+ datasets
41
+ end
42
+
43
+ end # class NotMatching
44
+ end # module Operator::Relational
45
+ end # module Alf
@@ -0,0 +1,22 @@
1
+ module Alf
2
+ module Operator::Relational
3
+ class Project < Alf::Operator()
4
+ include Operator::Relational, Operator::Shortcut, Operator::Unary
5
+
6
+ signature do |s|
7
+ s.argument :attributes, AttrList, []
8
+ s.option :allbut, Boolean, false, 'Project all but specified attributes?'
9
+ end
10
+
11
+ protected
12
+
13
+ # (see Operator::Shortcut#longexpr)
14
+ def longexpr
15
+ chain Operator::NonRelational::Compact.new,
16
+ Operator::NonRelational::Clip.new(@attributes, {:allbut => @allbut}),
17
+ datasets
18
+ end
19
+
20
+ end # class Project
21
+ end # module Operator::Relational
22
+ end # module Alf
@@ -0,0 +1,51 @@
1
+ module Alf
2
+ module Operator::Relational
3
+ class Quota < Alf::Operator()
4
+ include Operator::Relational, Operator::Experimental,
5
+ Operator::Shortcut, Operator::Unary
6
+
7
+ signature do |s|
8
+ s.argument :by, AttrList, []
9
+ s.argument :order, Ordering, []
10
+ s.argument :summarization, Summarization, {}
11
+ end
12
+
13
+ class SortBased
14
+ include Operator, Operator::Cesure
15
+
16
+ def initialize(by, order, summarization)
17
+ @by, @order, @summarization = by, order, summarization
18
+ end
19
+
20
+ protected
21
+
22
+ # (see Operator::Cesure#project)
23
+ def project(tuple)
24
+ @by.project(tuple, false)
25
+ end
26
+
27
+ # (see Operator::Cesure#start_cesure)
28
+ def start_cesure(key, receiver)
29
+ @aggs = @summarization.least
30
+ end
31
+
32
+ # (see Operator::Cesure#accumulate_cesure)
33
+ def accumulate_cesure(tuple, receiver)
34
+ @aggs = @summarization.happens(@aggs, tuple)
35
+ receiver.call tuple.merge(@summarization.finalize(@aggs))
36
+ end
37
+
38
+ end # class SortBased
39
+
40
+ protected
41
+
42
+ def longexpr
43
+ sort_key = @by.to_ordering + @order
44
+ chain SortBased.new(@by, @order, @summarization),
45
+ Operator::NonRelational::Sort.new(sort_key),
46
+ datasets
47
+ end
48
+
49
+ end # class Quota
50
+ end # module Operator::Relational
51
+ end # module Alf
@@ -0,0 +1,55 @@
1
+ module Alf
2
+ module Operator::Relational
3
+ class Rank < Alf::Operator()
4
+ include Operator::Relational, Operator::Shortcut, Operator::Unary
5
+
6
+ signature do |s|
7
+ s.argument :order, Ordering, []
8
+ s.argument :as, AttrName, :rank
9
+ end
10
+
11
+ class SortBased
12
+ include Operator, Operator::Cesure
13
+
14
+ def initialize(order, as)
15
+ @by_key = AttrList.coerce(order)
16
+ @as = as
17
+ end
18
+
19
+ protected
20
+
21
+ # (see Operator::Cesure#project)
22
+ def project(tuple)
23
+ @by_key.project(tuple, false)
24
+ end
25
+
26
+ # (see Operator::Cesure#start_cesure)
27
+ def start_cesure(key, receiver)
28
+ @rank ||= 0
29
+ @last_block = 0
30
+ end
31
+
32
+ # (see Operator::Cesure#accumulate_cesure)
33
+ def accumulate_cesure(tuple, receiver)
34
+ receiver.call tuple.merge(@as => @rank)
35
+ @last_block += 1
36
+ end
37
+
38
+ # (see Operator::Cesure#flush_cesure)
39
+ def flush_cesure(key, receiver)
40
+ @rank += @last_block
41
+ end
42
+
43
+ end # class SortBased
44
+
45
+ protected
46
+
47
+ def longexpr
48
+ chain SortBased.new(@order, @as),
49
+ Operator::NonRelational::Sort.new(@order),
50
+ datasets
51
+ end
52
+
53
+ end # class Rank
54
+ end # module Operator::Relational
55
+ end # module Alf
@@ -0,0 +1,19 @@
1
+ module Alf
2
+ module Operator::Relational
3
+ class Rename < Alf::Operator()
4
+ include Operator::Relational, Operator::Transform
5
+
6
+ signature do |s|
7
+ s.argument :renaming, Renaming, {}
8
+ end
9
+
10
+ protected
11
+
12
+ # (see Operator::Transform#_tuple2tuple)
13
+ def _tuple2tuple(tuple)
14
+ @renaming.apply(tuple)
15
+ end
16
+
17
+ end # class Rename
18
+ end # module Operator::Relational
19
+ end # module Alf
@@ -0,0 +1,20 @@
1
+ module Alf
2
+ module Operator::Relational
3
+ class Restrict < Alf::Operator()
4
+ include Operator::Relational, Operator::Unary
5
+
6
+ signature do |s|
7
+ s.argument :predicate, TuplePredicate, "true"
8
+ end
9
+
10
+ protected
11
+
12
+ # (see Operator#_each)
13
+ def _each
14
+ handle = TupleHandle.new
15
+ each_input_tuple{|t| yield(t) if @predicate.evaluate(handle.set(t)) }
16
+ end
17
+
18
+ end # class Restrict
19
+ end # module Operator::Relational
20
+ end # module Alf
@@ -0,0 +1,83 @@
1
+ module Alf
2
+ module Operator::Relational
3
+ class Summarize < Alf::Operator()
4
+ include Operator::Relational, Operator::Shortcut, Operator::Unary
5
+
6
+ signature do |s|
7
+ s.argument :by, AttrList, []
8
+ s.argument :summarization, Summarization, {}
9
+ s.option :allbut, Boolean, false, "Summarize on all but specified attributes?"
10
+ end
11
+
12
+ # Summarizes according to a complete order
13
+ class SortBased
14
+ include Operator, Operator::Cesure
15
+
16
+ def initialize(by_key, allbut, summarization)
17
+ @by_key, @allbut, @summarization = by_key, allbut, summarization
18
+ end
19
+
20
+ protected
21
+
22
+ # (see Operator::Cesure#project)
23
+ def project(tuple)
24
+ @by_key.project(tuple, @allbut)
25
+ end
26
+
27
+ # (see Operator::Cesure#start_cesure)
28
+ def start_cesure(key, receiver)
29
+ @aggs = @summarization.least
30
+ end
31
+
32
+ # (see Operator::Cesure#accumulate_cesure)
33
+ def accumulate_cesure(tuple, receiver)
34
+ @aggs = @summarization.happens(@aggs, tuple)
35
+ end
36
+
37
+ # (see Operator::Cesure#flush_cesure)
38
+ def flush_cesure(key, receiver)
39
+ @aggs = @summarization.finalize(@aggs)
40
+ receiver.call key.merge(@aggs)
41
+ end
42
+
43
+ end # class SortBased
44
+
45
+ # Summarizes in-memory with a hash
46
+ class HashBased
47
+ include Operator, Operator::Relational, Operator::Unary
48
+
49
+ def initialize(by_key, allbut, summarization)
50
+ @by_key, @allbut, @summarization = by_key, allbut, summarization
51
+ end
52
+
53
+ protected
54
+
55
+ def _each
56
+ index = Hash.new{|h,k| @summarization.least}
57
+ each_input_tuple do |tuple|
58
+ key, rest = @by_key.split(tuple, @allbut)
59
+ index[key] = @summarization.happens(index[key], tuple)
60
+ end
61
+ index.each_pair do |key,aggs|
62
+ yield key.merge(@summarization.finalize(aggs))
63
+ end
64
+ end
65
+
66
+ end
67
+
68
+ protected
69
+
70
+ def longexpr
71
+ if @allbut
72
+ chain HashBased.new(@by, @allbut, @summarization),
73
+ datasets
74
+ else
75
+ chain SortBased.new(@by, @allbut, @summarization),
76
+ Operator::NonRelational::Sort.new(@by.to_ordering),
77
+ datasets
78
+ end
79
+ end
80
+
81
+ end # class Summarize
82
+ end # module Operator::Relational
83
+ end # module Alf
@@ -0,0 +1,25 @@
1
+ module Alf
2
+ module Operator::Relational
3
+ class Ungroup < Alf::Operator()
4
+ include Operator::Relational, Operator::Unary
5
+
6
+ signature do |s|
7
+ s.argument :attr, AttrName, :grouped
8
+ end
9
+
10
+ protected
11
+
12
+ # See Operator#_each
13
+ def _each
14
+ each_input_tuple do |tuple|
15
+ tuple = tuple.dup
16
+ subrel = tuple.delete(@attr)
17
+ subrel.each do |subtuple|
18
+ yield(tuple.merge(subtuple))
19
+ end
20
+ end
21
+ end
22
+
23
+ end # class Ungroup
24
+ end # module Operator::Relational
25
+ end # module Alf
@@ -0,0 +1,32 @@
1
+ module Alf
2
+ module Operator::Relational
3
+ class Union < Alf::Operator()
4
+ include Operator::Relational, Operator::Shortcut, Operator::Binary
5
+
6
+ signature do |s|
7
+ end
8
+
9
+ class DisjointBased
10
+ include Operator, Operator::Binary
11
+
12
+ protected
13
+
14
+ def _each
15
+ left.each(&Proc.new)
16
+ right.each(&Proc.new)
17
+ end
18
+
19
+ end
20
+
21
+ protected
22
+
23
+ # (see Shortcut#longexpr)
24
+ def longexpr
25
+ chain Operator::NonRelational::Compact.new,
26
+ DisjointBased.new,
27
+ datasets
28
+ end
29
+
30
+ end # class Union
31
+ end # module Operator::Relational
32
+ end # module Alf
@@ -0,0 +1,21 @@
1
+ module Alf
2
+ module Operator::Relational
3
+ class Unwrap < Alf::Operator()
4
+ include Operator::Relational, Operator::Transform
5
+
6
+ signature do |s|
7
+ s.argument :attr, AttrName, :wrapped
8
+ end
9
+
10
+ protected
11
+
12
+ # (see Operator::Transform#_tuple2tuple)
13
+ def _tuple2tuple(tuple)
14
+ tuple = tuple.dup
15
+ wrapped = tuple.delete(@attr) || {}
16
+ tuple.merge(wrapped)
17
+ end
18
+
19
+ end # class Unwrap
20
+ end # module Operator::Relational
21
+ end # module Alf
@@ -0,0 +1,22 @@
1
+ module Alf
2
+ module Operator::Relational
3
+ class Wrap < Alf::Operator()
4
+ include Operator::Relational, Operator::Transform
5
+
6
+ signature do |s|
7
+ s.argument :attributes, AttrList, []
8
+ s.argument :as, AttrName, :wrapped
9
+ end
10
+
11
+ protected
12
+
13
+ # (see Operator::Transform#_tuple2tuple)
14
+ def _tuple2tuple(tuple)
15
+ wrapped, others = @attributes.split(tuple)
16
+ others[@as] = wrapped
17
+ others
18
+ end
19
+
20
+ end # class Wrap
21
+ end # module Operator::Relational
22
+ end # module Alf