alf 0.9.0 → 0.9.1
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 +64 -0
- data/Gemfile.lock +4 -4
- data/README.md +257 -171
- data/TODO.md +4 -4
- data/alf.gemspec +3 -3
- data/alf.noespec +11 -6
- data/examples/pseudo-with.alf +7 -0
- data/examples/runall.sh +2 -2
- data/examples/unwrap.alf +4 -0
- data/examples/wrap.alf +2 -0
- data/lib/alf/relation.rb +118 -0
- data/lib/alf/version.rb +1 -1
- data/lib/alf.rb +320 -169
- data/spec/integration/src/test_minus.alf +5 -0
- data/spec/integration/src/test_project.alf +9 -0
- data/spec/{alf_spec.rb → integration/test_alf.rb} +8 -21
- data/spec/integration/test_alf_specs.rb +37 -0
- data/spec/{examples_spec.rb → integration/test_examples.rb} +1 -1
- data/spec/spec_helper.rb +19 -1
- data/spec/unit/environment/examples/suppliers.rash +5 -0
- data/spec/{environment/explicit_spec.rb → unit/environment/test_explicit.rb} +0 -0
- data/spec/{environment/folder_spec.rb → unit/environment/test_folder.rb} +1 -1
- data/spec/{operator → unit/operator}/non_relational/compact/buffer_based.rb +0 -0
- data/spec/{operator/non_relational/compact/sort_based_spec.rb → unit/operator/non_relational/compact/test_sort_based.rb} +0 -0
- data/spec/{operator/non_relational/autonum_spec.rb → unit/operator/non_relational/test_autonum.rb} +0 -0
- data/spec/{operator/non_relational/clip_spec.rb → unit/operator/non_relational/test_clip.rb} +0 -0
- data/spec/{operator/non_relational/compact_spec.rb → unit/operator/non_relational/test_compact.rb} +0 -0
- data/spec/{operator/non_relational/defaults_spec.rb → unit/operator/non_relational/test_defaults.rb} +0 -0
- data/spec/{operator/non_relational/sort_spec.rb → unit/operator/non_relational/test_sort.rb} +0 -0
- data/spec/{operator/relational/join/hash_based_spec.rb → unit/operator/relational/join/test_hash_based.rb} +0 -0
- data/spec/unit/operator/relational/summarize/test_hash_based.rb +38 -0
- data/spec/{operator/relational/summarize/sort_based_spec.rb → unit/operator/relational/summarize/test_sort_based.rb} +0 -0
- data/spec/{operator/relational/extend_spec.rb → unit/operator/relational/test_extend.rb} +0 -0
- data/spec/{operator/relational/group_spec.rb → unit/operator/relational/test_group.rb} +3 -2
- data/spec/{operator/relational/intersect_spec.rb → unit/operator/relational/test_intersect.rb} +0 -0
- data/spec/unit/operator/relational/test_join.rb +36 -0
- data/spec/{operator/relational/minus_spec.rb → unit/operator/relational/test_minus.rb} +0 -0
- data/spec/{operator/relational/project_spec.rb → unit/operator/relational/test_project.rb} +0 -0
- data/spec/{operator/relational/quota_spec.rb → unit/operator/relational/test_quota.rb} +0 -0
- data/spec/{operator/relational/rename_spec.rb → unit/operator/relational/test_rename.rb} +0 -0
- data/spec/{operator/relational/restrict_spec.rb → unit/operator/relational/test_restrict.rb} +0 -0
- data/spec/unit/operator/relational/test_summarize.rb +64 -0
- data/spec/{operator/relational/ungroup_spec.rb → unit/operator/relational/test_ungroup.rb} +0 -0
- data/spec/{operator/relational/union_spec.rb → unit/operator/relational/test_union.rb} +0 -0
- data/spec/{operator/relational/unnest_spec.rb → unit/operator/relational/test_unwrap.rb} +5 -5
- data/spec/{operator/relational/nest_spec.rb → unit/operator/relational/test_wrap.rb} +5 -5
- data/spec/{operator/command_methods_spec.rb → unit/operator/test_command_methods.rb} +0 -0
- data/spec/unit/operator/test_non_relational.rb +18 -0
- data/spec/unit/operator/test_relational.rb +27 -0
- data/spec/{reader → unit/reader}/input.rb +0 -0
- data/spec/unit/reader/test_alf_file.rb +27 -0
- data/spec/{reader/rash_spec.rb → unit/reader/test_rash.rb} +0 -0
- data/spec/unit/relation/test_coerce.rb +53 -0
- data/spec/unit/relation/test_inspect.rb +20 -0
- data/spec/unit/relation/test_relops.rb +46 -0
- data/spec/{renderer/text/cell_spec.rb → unit/renderer/text/test_cell.rb} +0 -0
- data/spec/{renderer/text/row_spec.rb → unit/renderer/text/test_row.rb} +0 -0
- data/spec/{renderer/text/table_spec.rb → unit/renderer/text/test_table.rb} +0 -0
- data/spec/{aggregator_spec.rb → unit/test_aggregator.rb} +6 -6
- data/spec/{assumptions_spec.rb → unit/test_assumptions.rb} +0 -0
- data/spec/{lispy_spec.rb → unit/test_lispy.rb} +0 -0
- data/spec/unit/test_operator.rb +16 -0
- data/spec/{reader_spec.rb → unit/test_reader.rb} +4 -0
- data/spec/unit/test_relation.rb +40 -0
- data/spec/{renderer_spec.rb → unit/test_renderer.rb} +0 -0
- data/spec/{tools/ordering_key_spec.rb → unit/tools/test_ordering_key.rb} +0 -0
- data/spec/{tools/projection_key_spec.rb → unit/tools/test_projection_key.rb} +0 -0
- data/spec/{tools/tools_spec.rb → unit/tools/test_tools.rb} +0 -0
- data/spec/{tools/tuple_handle_spec.rb → unit/tools/test_tuple_handle.rb} +0 -0
- data/tasks/clean.rake +3 -0
- data/tasks/spec_test.rake +1 -1
- metadata +143 -114
- data/examples/nest.alf +0 -2
- data/examples/unnest.alf +0 -4
- data/examples/with.alf +0 -23
- data/spec/operator/relational/summarize_spec.rb +0 -41
- data/spec/reader/alf_file_spec.rb +0 -15
data/alf.noespec
CHANGED
|
@@ -7,19 +7,22 @@ variables:
|
|
|
7
7
|
upper:
|
|
8
8
|
Alf
|
|
9
9
|
version:
|
|
10
|
-
0.9.
|
|
10
|
+
0.9.1
|
|
11
11
|
summary: |-
|
|
12
|
-
|
|
12
|
+
Relational Algebra at your fingertips
|
|
13
13
|
description: |-
|
|
14
|
-
Alf
|
|
15
|
-
|
|
14
|
+
Alf brings the relational algebra both in Shell and in Ruby. In Shell, because
|
|
15
|
+
manipulating any relation-like data source should be as straightforward as a
|
|
16
|
+
one-liner. In Ruby, because I've never understood why programming languages
|
|
17
|
+
provide data structures like arrays, hashes, sets, trees and graphs but not
|
|
18
|
+
_relations_... Let's stop the segregation ;-)
|
|
16
19
|
authors:
|
|
17
20
|
- {name: Bernard Lambeau, email: blambeau@gmail.com}
|
|
18
21
|
links:
|
|
19
22
|
- http://rubydoc.info/github/blambeau/alf/master/frames
|
|
20
23
|
- http://github.com/blambeau/alf
|
|
21
24
|
dependencies:
|
|
22
|
-
- {name: rake, version: "~> 0.
|
|
25
|
+
- {name: rake, version: "~> 0.9.2", groups: [development]}
|
|
23
26
|
- {name: bundler, version: "~> 1.0", groups: [development]}
|
|
24
27
|
- {name: rspec, version: "~> 2.6.0", groups: [development]}
|
|
25
28
|
- {name: yard, version: "~> 0.7.2", groups: [development]}
|
|
@@ -27,4 +30,6 @@ variables:
|
|
|
27
30
|
- {name: wlang, version: "~> 0.10.1", groups: [development]}
|
|
28
31
|
- {name: noe, version: "~> 1.3.0", groups: [development]}
|
|
29
32
|
- {name: quickl, version: "~> 0.2.1", groups: [runtime]}
|
|
30
|
-
|
|
33
|
+
rake_tasks:
|
|
34
|
+
spec_test:
|
|
35
|
+
pattern: "spec/**/test_*.rb"
|
data/examples/runall.sh
CHANGED
|
@@ -13,8 +13,8 @@ alf --text extend supplies -- sp 'sid + "/" + pid' big "qty > 100 ?
|
|
|
13
13
|
alf --text rename suppliers -- name supplier_name city supplier_city
|
|
14
14
|
alf --text restrict suppliers -- "status > 20"
|
|
15
15
|
alf --text restrict suppliers -- city "'London'"
|
|
16
|
-
alf --text
|
|
17
|
-
alf --text
|
|
16
|
+
alf --text wrap suppliers -- city status loc_and_status
|
|
17
|
+
alf --text unwrap suppliers -- loc_and_status
|
|
18
18
|
alf --text group supplies -- pid qty supplying
|
|
19
19
|
alf --text group --allbut supplies -- sid supplying
|
|
20
20
|
alf --text ungroup group -- supplying
|
data/examples/unwrap.alf
ADDED
data/examples/wrap.alf
ADDED
data/lib/alf/relation.rb
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
module Alf
|
|
2
|
+
#
|
|
3
|
+
# Defines an in-memory relation
|
|
4
|
+
#
|
|
5
|
+
class Relation
|
|
6
|
+
include Iterator
|
|
7
|
+
|
|
8
|
+
protected
|
|
9
|
+
|
|
10
|
+
# @return [Set] the set of tuples
|
|
11
|
+
attr_reader :tuples
|
|
12
|
+
|
|
13
|
+
public
|
|
14
|
+
|
|
15
|
+
#
|
|
16
|
+
# Creates a Relation instance.
|
|
17
|
+
#
|
|
18
|
+
# @param [Set] tuples a set of tuples
|
|
19
|
+
#
|
|
20
|
+
def initialize(tuples)
|
|
21
|
+
raise ArgumentError unless tuples.is_a?(Set)
|
|
22
|
+
@tuples = tuples
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
# Coerces `val` to a relation
|
|
27
|
+
#
|
|
28
|
+
def self.coerce(val)
|
|
29
|
+
case val
|
|
30
|
+
when Relation
|
|
31
|
+
val
|
|
32
|
+
when Set
|
|
33
|
+
Relation.new(val)
|
|
34
|
+
when Array
|
|
35
|
+
Relation.new val.to_set
|
|
36
|
+
when Iterator
|
|
37
|
+
Relation.new val.to_set
|
|
38
|
+
else
|
|
39
|
+
raise ArgumentError, "Unable to coerce #{val} to a Relation"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# (see Relation.coerce)
|
|
44
|
+
def self.[](*tuples)
|
|
45
|
+
coerce(tuples)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
#
|
|
49
|
+
# (see Iterator#each)
|
|
50
|
+
#
|
|
51
|
+
def each(&block)
|
|
52
|
+
tuples.each(&block)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
#
|
|
56
|
+
# Returns relation's cardinality (number of tuples)
|
|
57
|
+
#
|
|
58
|
+
def cardinality
|
|
59
|
+
tuples.size
|
|
60
|
+
end
|
|
61
|
+
alias :size :cardinality
|
|
62
|
+
alias :count :cardinality
|
|
63
|
+
|
|
64
|
+
#
|
|
65
|
+
# Install the DSL through iteration over defined operators
|
|
66
|
+
#
|
|
67
|
+
Operator::each do |op_class|
|
|
68
|
+
meth_name = Tools.ruby_case(Tools.class_name(op_class)).to_sym
|
|
69
|
+
if op_class.unary?
|
|
70
|
+
define_method(meth_name) do |*args|
|
|
71
|
+
op = op_class.new(*args).pipe(self)
|
|
72
|
+
Relation.coerce(op)
|
|
73
|
+
end
|
|
74
|
+
elsif op_class.binary?
|
|
75
|
+
define_method(meth_name) do |right, *args|
|
|
76
|
+
op = op_class.new(*args).pipe([self, Iterator.coerce(right)])
|
|
77
|
+
Relation.coerce(op)
|
|
78
|
+
end
|
|
79
|
+
else
|
|
80
|
+
raise "Unexpected operator #{op_class}"
|
|
81
|
+
end
|
|
82
|
+
end # Operators::each
|
|
83
|
+
|
|
84
|
+
alias :+ :union
|
|
85
|
+
alias :- :minus
|
|
86
|
+
|
|
87
|
+
#
|
|
88
|
+
# (see Object#hash)
|
|
89
|
+
#
|
|
90
|
+
def hash
|
|
91
|
+
@tuples.hash
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
#
|
|
95
|
+
# (see Object#==)
|
|
96
|
+
#
|
|
97
|
+
def ==(other)
|
|
98
|
+
return nil unless other.is_a?(Relation)
|
|
99
|
+
other.tuples == self.tuples
|
|
100
|
+
end
|
|
101
|
+
alias :eql? :==
|
|
102
|
+
|
|
103
|
+
#
|
|
104
|
+
# Returns a textual representation of this relation
|
|
105
|
+
#
|
|
106
|
+
def to_s
|
|
107
|
+
Alf::Renderer.text(self).execute("")
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
#
|
|
111
|
+
# Returns a literal representation of this relation
|
|
112
|
+
#
|
|
113
|
+
def inspect
|
|
114
|
+
"Alf::Relation[" << @tuples.collect{|t| t.inspect}.join(',') << "]"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
end # class Relation
|
|
118
|
+
end # module Alf
|