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.
- data/CHANGELOG.md +255 -129
- data/Gemfile +31 -1
- data/Gemfile.lock +17 -20
- data/LICENCE.md +1 -1
- data/Manifest.txt +2 -0
- data/README.md +37 -43
- data/TODO.md +1 -1
- data/alf.gemspec +10 -7
- data/alf.noespec +24 -13
- data/bin/alf +2 -2
- data/doc/commands/exec.md +16 -0
- data/doc/commands/help.md +11 -0
- data/doc/commands/main.md +33 -0
- data/doc/commands/show.md +19 -0
- data/doc/operators/non_relational/autonum.md +23 -0
- data/doc/operators/non_relational/clip.md +31 -0
- data/doc/operators/non_relational/coerce.md +15 -0
- data/doc/operators/non_relational/compact.md +20 -0
- data/doc/operators/non_relational/defaults.md +32 -0
- data/doc/operators/non_relational/generator.md +20 -0
- data/doc/operators/non_relational/sort.md +24 -0
- data/doc/operators/relational/extend.md +18 -0
- data/doc/operators/relational/group.md +27 -0
- data/doc/operators/relational/intersect.md +13 -0
- data/doc/operators/relational/join.md +27 -0
- data/doc/operators/relational/matching.md +20 -0
- data/doc/operators/relational/minus.md +12 -0
- data/doc/operators/relational/not-matching.md +20 -0
- data/doc/operators/relational/project.md +28 -0
- data/doc/operators/relational/quota.md +21 -0
- data/doc/operators/relational/rank.md +27 -0
- data/doc/operators/relational/rename.md +17 -0
- data/doc/operators/relational/restrict.md +25 -0
- data/doc/operators/relational/summarize.md +25 -0
- data/doc/operators/relational/ungroup.md +20 -0
- data/doc/operators/relational/union.md +14 -0
- data/doc/operators/relational/unwrap.md +20 -0
- data/doc/operators/relational/wrap.md +24 -0
- data/examples/csv/suppliers.csv +6 -0
- data/examples/logs/access.log +1000 -0
- data/examples/logs/combined.alf +2 -0
- data/examples/logs/hits.alf +14 -0
- data/examples/logs/not_found.alf +7 -0
- data/examples/logs/robots-cheating.alf +11 -0
- data/examples/logs/robots.alf +8 -0
- data/examples/northwind/customers.csv +92 -0
- data/examples/northwind/northwind.db +0 -0
- data/examples/northwind/orders.csv +831 -0
- data/examples/operators/clip.alf +1 -1
- data/examples/operators/database.alf +5 -6
- data/examples/operators/defaults.alf +1 -1
- data/examples/operators/group.alf +1 -1
- data/examples/operators/project.alf +2 -1
- data/examples/operators/pseudo-with.alf +2 -2
- data/examples/operators/quota.alf +2 -2
- data/examples/operators/summarize.alf +2 -2
- data/lib/alf/aggregator/aggregators.rb +77 -0
- data/lib/alf/aggregator/base.rb +95 -0
- data/lib/alf/aggregator/class_methods.rb +57 -0
- data/lib/alf/buffer/sorted.rb +48 -0
- data/lib/alf/command/class_methods.rb +27 -0
- data/lib/alf/command/doc_manager.rb +72 -0
- data/lib/alf/command/exec.rb +12 -0
- data/lib/alf/command/help.rb +31 -0
- data/lib/alf/command/main.rb +146 -0
- data/lib/alf/command/show.rb +33 -0
- data/lib/alf/environment/base.rb +37 -0
- data/lib/alf/environment/class_methods.rb +93 -0
- data/lib/alf/environment/explicit.rb +38 -0
- data/lib/alf/environment/folder.rb +62 -0
- data/lib/alf/extra/csv.rb +104 -0
- data/lib/alf/extra/logs.rb +100 -0
- data/lib/alf/extra/sequel.rb +77 -0
- data/lib/alf/{yaml.rb → extra/yaml.rb} +0 -0
- data/lib/alf/extra.rb +5 -0
- data/lib/alf/iterator/base.rb +38 -0
- data/lib/alf/iterator/class_methods.rb +22 -0
- data/lib/alf/iterator/proxy.rb +33 -0
- data/lib/alf/lispy/instance_methods.rb +157 -0
- data/lib/alf/operator/base.rb +74 -0
- data/lib/alf/operator/binary.rb +32 -0
- data/lib/alf/operator/cesure.rb +45 -0
- data/lib/alf/operator/class_methods.rb +132 -0
- data/lib/alf/operator/experimental.rb +9 -0
- data/lib/alf/operator/non_relational/autonum.rb +24 -0
- data/lib/alf/operator/non_relational/clip.rb +20 -0
- data/lib/alf/operator/non_relational/coerce.rb +21 -0
- data/lib/alf/operator/non_relational/compact.rb +62 -0
- data/lib/alf/operator/non_relational/defaults.rb +25 -0
- data/lib/alf/operator/non_relational/generator.rb +38 -0
- data/lib/alf/operator/non_relational/sort.rb +23 -0
- data/lib/alf/operator/nullary.rb +20 -0
- data/lib/alf/operator/relational/extend.rb +24 -0
- data/lib/alf/operator/relational/group.rb +32 -0
- data/lib/alf/operator/relational/intersect.rb +37 -0
- data/lib/alf/operator/relational/join.rb +106 -0
- data/lib/alf/operator/relational/matching.rb +45 -0
- data/lib/alf/operator/relational/minus.rb +37 -0
- data/lib/alf/operator/relational/not_matching.rb +45 -0
- data/lib/alf/operator/relational/project.rb +22 -0
- data/lib/alf/operator/relational/quota.rb +51 -0
- data/lib/alf/operator/relational/rank.rb +55 -0
- data/lib/alf/operator/relational/rename.rb +19 -0
- data/lib/alf/operator/relational/restrict.rb +20 -0
- data/lib/alf/operator/relational/summarize.rb +83 -0
- data/lib/alf/operator/relational/ungroup.rb +25 -0
- data/lib/alf/operator/relational/union.rb +32 -0
- data/lib/alf/operator/relational/unwrap.rb +21 -0
- data/lib/alf/operator/relational/wrap.rb +22 -0
- data/lib/alf/operator/shortcut.rb +53 -0
- data/lib/alf/operator/signature.rb +262 -0
- data/lib/alf/operator/transform.rb +27 -0
- data/lib/alf/operator/unary.rb +38 -0
- data/lib/alf/reader/alf_file.rb +24 -0
- data/lib/alf/reader/base.rb +119 -0
- data/lib/alf/reader/class_methods.rb +82 -0
- data/lib/alf/reader/rash.rb +28 -0
- data/lib/alf/relation/class_methods.rb +37 -0
- data/lib/alf/relation/instance_methods.rb +127 -0
- data/lib/alf/renderer/base.rb +72 -0
- data/lib/alf/renderer/class_methods.rb +58 -0
- data/lib/alf/renderer/rash.rb +19 -0
- data/lib/alf/{text.rb → renderer/text.rb} +1 -1
- data/lib/alf/tools/coerce.rb +14 -0
- data/lib/alf/tools/miscellaneous.rb +77 -0
- data/lib/alf/tools/to_lispy.rb +99 -0
- data/lib/alf/tools/to_ruby_literal.rb +14 -0
- data/lib/alf/tools/tuple_handle.rb +50 -0
- data/lib/alf/types/attr_list.rb +56 -0
- data/lib/alf/types/attr_name.rb +28 -0
- data/lib/alf/types/boolean.rb +12 -0
- data/lib/alf/types/heading.rb +96 -0
- data/lib/alf/types/ordering.rb +93 -0
- data/lib/alf/types/renaming.rb +57 -0
- data/lib/alf/types/summarization.rb +76 -0
- data/lib/alf/types/tuple_computation.rb +61 -0
- data/lib/alf/types/tuple_expression.rb +61 -0
- data/lib/alf/types/tuple_predicate.rb +49 -0
- data/lib/alf/version.rb +2 -2
- data/lib/alf.rb +193 -3714
- data/spec/integration/__database__/group.alf +1 -1
- data/spec/integration/__database__/suppliers_csv.csv +6 -0
- data/spec/integration/command/alf/alf.db +0 -0
- data/spec/integration/command/alf/alf_env_sqlite.cmd +1 -0
- data/spec/integration/command/alf/alf_env_sqlite.stdout +9 -0
- data/spec/integration/command/alf/alf_help.cmd +1 -0
- data/spec/integration/command/alf/alf_help.stdout +67 -0
- data/spec/integration/command/autonum/autonum_0.cmd +1 -1
- data/spec/integration/command/coerce/coerce_1.cmd +1 -0
- data/spec/integration/command/coerce/coerce_1.stdout +5 -0
- data/spec/integration/command/defaults/defaults_0.cmd +1 -1
- data/spec/integration/command/defaults/defaults_0.stdout +9 -9
- data/spec/integration/command/defaults/defaults_2.cmd +1 -0
- data/spec/integration/command/defaults/defaults_2.stdout +9 -0
- data/spec/integration/command/generator/generator_1.cmd +1 -0
- data/spec/integration/command/generator/generator_1.stdout +10 -0
- data/spec/integration/command/generator/generator_2.cmd +1 -0
- data/spec/integration/command/generator/generator_2.stdout +5 -0
- data/spec/integration/command/generator/generator_3.cmd +1 -0
- data/spec/integration/command/generator/generator_3.stdout +5 -0
- data/spec/integration/command/group/group_0.cmd +1 -1
- data/spec/integration/command/group/group_1.cmd +1 -1
- data/spec/integration/command/help/help_1.cmd +1 -0
- data/spec/integration/command/help/help_1.stdout +22 -0
- data/spec/integration/command/quota/quota_0.cmd +1 -1
- data/spec/integration/command/rank/rank_1.cmd +1 -1
- data/spec/integration/command/rank/rank_1.stdout +10 -10
- data/spec/integration/command/rank/rank_2.cmd +1 -1
- data/spec/integration/command/rank/rank_2.stdout +10 -10
- data/spec/integration/command/rank/rank_3.cmd +1 -1
- data/spec/integration/command/rank/rank_3.stdout +10 -10
- data/spec/integration/command/rank/rank_4.cmd +1 -1
- data/spec/integration/command/rank/rank_5.cmd +1 -1
- data/spec/integration/command/show/show_csv.cmd +1 -0
- data/spec/integration/command/show/show_csv.stdout +6 -0
- data/spec/integration/command/show/show_rash_2.cmd +1 -1
- data/spec/integration/command/show/show_rash_2.stdout +5 -5
- data/spec/integration/command/sort/sort_0.cmd +1 -1
- data/spec/integration/command/sort/sort_1.cmd +1 -1
- data/spec/integration/command/sort/sort_1.stdout +2 -2
- data/spec/integration/command/sort/sort_2.cmd +1 -0
- data/spec/integration/command/sort/sort_2.stdout +9 -0
- data/spec/integration/command/sort/sort_3.cmd +1 -0
- data/spec/integration/command/sort/sort_3.stdout +9 -0
- data/spec/integration/command/summarize/summarize_0.cmd +1 -1
- data/spec/integration/command/ungroup/ungroup_0.cmd +1 -1
- data/spec/integration/command/wrap/wrap_0.cmd +1 -1
- data/spec/integration/semantics/test_project.alf +5 -6
- data/spec/integration/semantics/test_rank.alf +16 -16
- data/spec/integration/test_command.rb +17 -6
- data/spec/integration/test_examples.rb +1 -1
- data/spec/regression/logs/apache_combined.log +5 -0
- data/spec/regression/logs/test_path_attribute.rb +25 -0
- data/spec/regression/relation/test_relation_allbut_all.rb +14 -0
- data/spec/shared/an_operator_class.rb +10 -5
- data/spec/spec_helper.rb +1 -7
- data/spec/unit/assumptions/test_set.rb +64 -0
- data/spec/unit/command/doc_manager/dynamic.md +1 -0
- data/spec/unit/command/doc_manager/example.md +1 -0
- data/spec/unit/command/doc_manager/example_1.txt +11 -0
- data/spec/unit/command/doc_manager/static.md +1 -0
- data/spec/unit/command/doc_manager/test_call.rb +49 -0
- data/spec/unit/csv/input.csv +3 -0
- data/spec/unit/csv/test_reader.rb +66 -0
- data/spec/unit/csv/test_renderer.rb +73 -0
- data/spec/unit/lispy/test_relation.rb +37 -0
- data/spec/unit/lispy/test_run.rb +40 -0
- data/spec/unit/lispy/test_tuple.rb +36 -0
- data/spec/unit/logs/apache_combined.log +5 -0
- data/spec/unit/logs/postgresql.log +29 -0
- data/spec/unit/logs/test_reader.rb +56 -0
- data/spec/unit/operator/non_relational/compact/{buffer_based.rb → test_buffer_based.rb} +0 -0
- data/spec/unit/operator/non_relational/test_clip.rb +1 -1
- data/spec/unit/operator/non_relational/test_coerce.rb +35 -0
- data/spec/unit/operator/non_relational/test_defaults.rb +15 -2
- data/spec/unit/operator/non_relational/test_generator.rb +78 -0
- data/spec/unit/operator/relational/join/test_hash_based.rb +4 -4
- data/spec/unit/operator/relational/matching/test_hash_based.rb +6 -6
- data/spec/unit/operator/relational/not_matching/test_hash_based.rb +4 -4
- data/spec/unit/operator/relational/summarize/test_hash_based.rb +10 -6
- data/spec/unit/operator/relational/summarize/test_sort_based.rb +18 -7
- data/spec/unit/operator/relational/test_group.rb +8 -8
- data/spec/unit/operator/relational/test_intersect.rb +3 -3
- data/spec/unit/operator/relational/test_minus.rb +3 -3
- data/spec/unit/operator/relational/test_project.rb +12 -2
- data/spec/unit/operator/relational/test_quota.rb +5 -6
- data/spec/unit/operator/relational/test_summarize.rb +9 -11
- data/spec/unit/operator/relational/test_union.rb +1 -1
- data/spec/unit/operator/relational/test_wrap.rb +1 -1
- data/spec/unit/operator/signature/test_collect_on.rb +45 -0
- data/spec/unit/operator/signature/test_initialize.rb +17 -0
- data/spec/unit/operator/signature/test_install.rb +56 -0
- data/spec/unit/operator/signature/test_option_parser.rb +36 -0
- data/spec/unit/operator/signature/test_parse_args.rb +60 -0
- data/spec/unit/operator/signature/test_parse_argv.rb +87 -0
- data/spec/unit/operator/signature/test_to_lispy.rb +102 -0
- data/spec/unit/operator/signature/test_to_shell.rb +103 -0
- data/spec/unit/operator/test_non_relational.rb +3 -1
- data/spec/unit/relation/test_relops.rb +20 -15
- data/spec/unit/sequel/alf.db +0 -0
- data/spec/unit/sequel/test_environment.rb +54 -0
- data/spec/unit/test_aggregator.rb +32 -22
- data/spec/unit/test_environment.rb +5 -0
- data/spec/unit/test_lispy.rb +4 -0
- data/spec/unit/test_relation.rb +5 -0
- data/spec/unit/text/test_cell.rb +6 -6
- data/spec/unit/text/test_row.rb +3 -3
- data/spec/unit/text/test_table.rb +6 -6
- data/spec/unit/tools/test_coalesce.rb +15 -0
- data/spec/unit/tools/test_coerce.rb +10 -0
- data/spec/unit/tools/test_to_lispy.rb +138 -0
- data/spec/unit/tools/test_to_ruby_literal.rb +10 -0
- data/spec/unit/tools/test_tuple_handle.rb +1 -59
- data/spec/unit/types/test_attr_list.rb +106 -0
- data/spec/unit/types/test_attr_name.rb +52 -0
- data/spec/unit/{test_heading.rb → types/test_heading.rb} +10 -0
- data/spec/unit/types/test_ordering.rb +127 -0
- data/spec/unit/types/test_renaming.rb +55 -0
- data/spec/unit/types/test_summarization.rb +63 -0
- data/spec/unit/types/test_tuple_computation.rb +60 -0
- data/spec/unit/types/test_tuple_expression.rb +64 -0
- data/spec/unit/types/test_tuple_predicate.rb +79 -0
- data/tasks/debug_mail.rake +1 -1
- data/tasks/debug_mail.txt +5 -0
- data/tasks/gh-pages.rake +63 -0
- metadata +325 -52
- data/spec/unit/operator/test_command_methods.rb +0 -38
- data/spec/unit/tools/test_ordering_key.rb +0 -94
- data/spec/unit/tools/test_parse_commandline_args.rb +0 -47
- data/spec/unit/tools/test_projection_key.rb +0 -83
|
@@ -0,0 +1,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
|