bmg 0.5.0 → 0.6.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.
- checksums.yaml +4 -4
- data/Gemfile +0 -2
- data/lib/bmg.rb +35 -13
- data/lib/bmg/algebra.rb +27 -1
- data/lib/bmg/operator.rb +61 -0
- data/lib/bmg/operator/allbut.rb +8 -3
- data/lib/bmg/operator/autosummarize.rb +28 -3
- data/lib/bmg/operator/autowrap.rb +14 -3
- data/lib/bmg/operator/constants.rb +8 -3
- data/lib/bmg/operator/extend.rb +8 -3
- data/lib/bmg/operator/image.rb +9 -4
- data/lib/bmg/operator/project.rb +8 -3
- data/lib/bmg/operator/rename.rb +8 -3
- data/lib/bmg/operator/restrict.rb +8 -3
- data/lib/bmg/operator/union.rb +8 -3
- data/lib/bmg/reader.rb +2 -3
- data/lib/bmg/reader/csv.rb +11 -1
- data/lib/bmg/reader/excel.rb +11 -1
- data/lib/bmg/relation.rb +33 -16
- data/lib/bmg/relation/empty.rb +8 -0
- data/lib/bmg/relation/in_memory.rb +32 -0
- data/lib/bmg/relation/spied.rb +72 -0
- data/lib/bmg/sequel.rb +1 -1
- data/lib/bmg/sequel/relation.rb +7 -2
- data/lib/bmg/version.rb +1 -1
- metadata +3 -2
- data/lib/bmg/leaf.rb +0 -22
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8485745f67f9a5f3b481e8f8121e57c30f404661
|
|
4
|
+
data.tar.gz: 010a318d9896ae6514c96798230ab564540c788d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5aae26e7caca19cf4ae627cde3eb8de7278b48f881d40b6ff72fcb7f67ff9f571246e5bc8220e4576b2e8f25cddfb4ae1cd92f7670fe856d9ef6399b3c0a679b
|
|
7
|
+
data.tar.gz: ff68734d5b561543224dc66c5731f0f89cd9456a3ff94891ce207f18799ceef5d27150b6c848301c0987f7a7a02488d0c9e270a47d01f60689744efc03393a47
|
data/Gemfile
CHANGED
data/lib/bmg.rb
CHANGED
|
@@ -2,23 +2,45 @@ require 'path'
|
|
|
2
2
|
require 'predicate'
|
|
3
3
|
module Bmg
|
|
4
4
|
|
|
5
|
-
def
|
|
6
|
-
Relation
|
|
5
|
+
def in_memory(enumerable, type = Type::ANY)
|
|
6
|
+
Relation::InMemory.new(type, enumerable).spied(main_spy)
|
|
7
|
+
end
|
|
8
|
+
module_function :in_memory
|
|
9
|
+
|
|
10
|
+
def csv(path, options = {}, type = Type::ANY)
|
|
11
|
+
Reader::Csv.new(type, path, options).spied(main_spy)
|
|
7
12
|
end
|
|
8
13
|
module_function :csv
|
|
9
14
|
|
|
10
|
-
def excel(path, options = {})
|
|
11
|
-
|
|
15
|
+
def excel(path, options = {}, type = Type::ANY)
|
|
16
|
+
Reader::Excel.new(type, path, options).spied(main_spy)
|
|
12
17
|
end
|
|
13
18
|
module_function :excel
|
|
14
19
|
|
|
20
|
+
def main_spy
|
|
21
|
+
@main_spy
|
|
22
|
+
end
|
|
23
|
+
module_function :main_spy
|
|
24
|
+
|
|
25
|
+
def main_spy=(spy)
|
|
26
|
+
@main_spy = spy
|
|
27
|
+
end
|
|
28
|
+
module_function :main_spy=
|
|
29
|
+
|
|
30
|
+
require_relative 'bmg/version'
|
|
31
|
+
require_relative 'bmg/error'
|
|
32
|
+
require_relative 'bmg/support'
|
|
33
|
+
require_relative 'bmg/algebra'
|
|
34
|
+
require_relative 'bmg/type'
|
|
35
|
+
require_relative 'bmg/relation'
|
|
36
|
+
require_relative 'bmg/operator'
|
|
37
|
+
|
|
38
|
+
require_relative 'bmg/reader'
|
|
39
|
+
|
|
40
|
+
require_relative 'bmg/relation/empty'
|
|
41
|
+
require_relative 'bmg/relation/in_memory'
|
|
42
|
+
require_relative 'bmg/relation/spied'
|
|
43
|
+
|
|
44
|
+
# Deprecated
|
|
45
|
+
Leaf = Relation::InMemory
|
|
15
46
|
end
|
|
16
|
-
require_relative 'bmg/version'
|
|
17
|
-
require_relative 'bmg/error'
|
|
18
|
-
require_relative 'bmg/support'
|
|
19
|
-
require_relative 'bmg/algebra'
|
|
20
|
-
require_relative 'bmg/type'
|
|
21
|
-
require_relative 'bmg/relation'
|
|
22
|
-
require_relative 'bmg/leaf'
|
|
23
|
-
require_relative 'bmg/operator'
|
|
24
|
-
require_relative 'bmg/reader'
|
data/lib/bmg/algebra.rb
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
module Bmg
|
|
2
2
|
module Algebra
|
|
3
3
|
|
|
4
|
+
METHODS = [
|
|
5
|
+
:allbut,
|
|
6
|
+
:autowrap,
|
|
7
|
+
:autosummarize,
|
|
8
|
+
:constants,
|
|
9
|
+
:extend,
|
|
10
|
+
:image,
|
|
11
|
+
:project,
|
|
12
|
+
:rename,
|
|
13
|
+
:restrict,
|
|
14
|
+
:union
|
|
15
|
+
]
|
|
16
|
+
|
|
4
17
|
def allbut(butlist = [])
|
|
5
18
|
_allbut self.type.allbut(butlist), butlist
|
|
6
19
|
end
|
|
@@ -82,7 +95,11 @@ module Bmg
|
|
|
82
95
|
if predicate.contradiction?
|
|
83
96
|
Relation.empty(type)
|
|
84
97
|
else
|
|
85
|
-
|
|
98
|
+
begin
|
|
99
|
+
_restrict type, predicate
|
|
100
|
+
rescue Predicate::NotSupportedError
|
|
101
|
+
Operator::Restrict.new(type, self, predicate)
|
|
102
|
+
end
|
|
86
103
|
end
|
|
87
104
|
end
|
|
88
105
|
end
|
|
@@ -101,5 +118,14 @@ module Bmg
|
|
|
101
118
|
end
|
|
102
119
|
protected :_union
|
|
103
120
|
|
|
121
|
+
def spied(spy)
|
|
122
|
+
return self if spy.nil?
|
|
123
|
+
Relation::Spied.new(self, spy)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def unspied
|
|
127
|
+
self
|
|
128
|
+
end
|
|
129
|
+
|
|
104
130
|
end # module Algebra
|
|
105
131
|
end # module Bmg
|
data/lib/bmg/operator.rb
CHANGED
|
@@ -2,6 +2,67 @@ module Bmg
|
|
|
2
2
|
module Operator
|
|
3
3
|
include Relation
|
|
4
4
|
|
|
5
|
+
def to_s
|
|
6
|
+
str = "(#{self.class.name.split('::').last.downcase}\n"
|
|
7
|
+
str << operands.map{|op| op.to_s.gsub(/^/m, " ") }.join("\n")
|
|
8
|
+
str << "\n"
|
|
9
|
+
str << args.map{|a| a.to_s.gsub(/^/m, " ") }.join("\n")
|
|
10
|
+
str << ")"
|
|
11
|
+
str
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def inspect
|
|
15
|
+
str = "(#{self.class.name.split('::').last.downcase}\n"
|
|
16
|
+
str << operands.map{|op| op.inspect.gsub(/^/m, " ") }.join("\n")
|
|
17
|
+
str << "\n"
|
|
18
|
+
str << args.map{|a| a.inspect.gsub(/^/m, " ") }.join("\n")
|
|
19
|
+
str << ")"
|
|
20
|
+
str
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module Unary
|
|
24
|
+
include Operator
|
|
25
|
+
|
|
26
|
+
attr_reader :type, :operand
|
|
27
|
+
|
|
28
|
+
def _visit(parent, visitor)
|
|
29
|
+
visitor.call(self, parent)
|
|
30
|
+
operand._visit(self, visitor)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def operands
|
|
34
|
+
[operand]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
module Binary
|
|
40
|
+
include Operator
|
|
41
|
+
|
|
42
|
+
attr_reader :type, :left, :right
|
|
43
|
+
|
|
44
|
+
def _visit(parent, visitor)
|
|
45
|
+
visitor.call(self, parent)
|
|
46
|
+
left._visit(self, visitor)
|
|
47
|
+
right._visit(self, visitor)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def operands
|
|
51
|
+
[left, right]
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
module Nary
|
|
56
|
+
include Operator
|
|
57
|
+
|
|
58
|
+
attr_reader :type, :operands
|
|
59
|
+
|
|
60
|
+
def _visit(parent, visitor)
|
|
61
|
+
visitor.call(self, parent)
|
|
62
|
+
operands.each{|op| op._visit(self, visitor) }
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
5
66
|
end
|
|
6
67
|
end
|
|
7
68
|
require_relative 'operator/allbut'
|
data/lib/bmg/operator/allbut.rb
CHANGED
|
@@ -15,18 +15,17 @@ module Bmg
|
|
|
15
15
|
# input tuples.
|
|
16
16
|
#
|
|
17
17
|
class Allbut
|
|
18
|
-
include Operator
|
|
18
|
+
include Operator::Unary
|
|
19
19
|
|
|
20
20
|
def initialize(type, operand, butlist)
|
|
21
21
|
@type = type
|
|
22
22
|
@operand = operand
|
|
23
23
|
@butlist = butlist
|
|
24
24
|
end
|
|
25
|
-
attr_reader :type
|
|
26
25
|
|
|
27
26
|
protected
|
|
28
27
|
|
|
29
|
-
attr_reader :
|
|
28
|
+
attr_reader :butlist
|
|
30
29
|
|
|
31
30
|
public
|
|
32
31
|
|
|
@@ -68,6 +67,12 @@ module Bmg
|
|
|
68
67
|
operand.restrict(predicate).allbut(butlist)
|
|
69
68
|
end
|
|
70
69
|
|
|
70
|
+
protected ### inspect
|
|
71
|
+
|
|
72
|
+
def args
|
|
73
|
+
[ butlist ]
|
|
74
|
+
end
|
|
75
|
+
|
|
71
76
|
private
|
|
72
77
|
|
|
73
78
|
def tuple_allbut(tuple)
|
|
@@ -9,7 +9,7 @@ module Bmg
|
|
|
9
9
|
# care...
|
|
10
10
|
#
|
|
11
11
|
class Autosummarize
|
|
12
|
-
include Operator
|
|
12
|
+
include Operator::Unary
|
|
13
13
|
|
|
14
14
|
def initialize(type, operand, by, sums)
|
|
15
15
|
@type = type
|
|
@@ -17,11 +17,10 @@ module Bmg
|
|
|
17
17
|
@by = by
|
|
18
18
|
@sums = sums.each_with_object({}){|(k,v),h| h[k] = to_summarizer(v) }
|
|
19
19
|
end
|
|
20
|
-
attr_reader :type
|
|
21
20
|
|
|
22
21
|
protected
|
|
23
22
|
|
|
24
|
-
attr_reader :
|
|
23
|
+
attr_reader :by, :sums
|
|
25
24
|
|
|
26
25
|
public
|
|
27
26
|
|
|
@@ -57,6 +56,12 @@ module Bmg
|
|
|
57
56
|
end
|
|
58
57
|
end
|
|
59
58
|
|
|
59
|
+
protected ### inspect
|
|
60
|
+
|
|
61
|
+
def args
|
|
62
|
+
[ by, sums ]
|
|
63
|
+
end
|
|
64
|
+
|
|
60
65
|
private
|
|
61
66
|
|
|
62
67
|
# Returns the tuple determinant.
|
|
@@ -118,6 +123,11 @@ module Bmg
|
|
|
118
123
|
v
|
|
119
124
|
end
|
|
120
125
|
|
|
126
|
+
def inspect
|
|
127
|
+
":same"
|
|
128
|
+
end
|
|
129
|
+
alias :to_s :inspect
|
|
130
|
+
|
|
121
131
|
end # class Same
|
|
122
132
|
|
|
123
133
|
#
|
|
@@ -145,6 +155,11 @@ module Bmg
|
|
|
145
155
|
v
|
|
146
156
|
end
|
|
147
157
|
|
|
158
|
+
def inspect
|
|
159
|
+
":group"
|
|
160
|
+
end
|
|
161
|
+
alias :to_s :inspect
|
|
162
|
+
|
|
148
163
|
end # class DistinctList
|
|
149
164
|
|
|
150
165
|
#
|
|
@@ -176,6 +191,11 @@ module Bmg
|
|
|
176
191
|
h
|
|
177
192
|
end
|
|
178
193
|
|
|
194
|
+
def inspect
|
|
195
|
+
":#{y}_by_#{x}"
|
|
196
|
+
end
|
|
197
|
+
alias :to_s :inspect
|
|
198
|
+
|
|
179
199
|
end # class YByX
|
|
180
200
|
|
|
181
201
|
#
|
|
@@ -210,6 +230,11 @@ module Bmg
|
|
|
210
230
|
h
|
|
211
231
|
end
|
|
212
232
|
|
|
233
|
+
def inspect
|
|
234
|
+
":#{y}s_by_#{x}"
|
|
235
|
+
end
|
|
236
|
+
alias :to_s :inspect
|
|
237
|
+
|
|
213
238
|
end # class YsByX
|
|
214
239
|
|
|
215
240
|
end # class Autosummarize
|
|
@@ -18,7 +18,7 @@ module Bmg
|
|
|
18
18
|
# - `split: String` the seperator to use to split keys, defaults to `_`
|
|
19
19
|
#
|
|
20
20
|
class Autowrap
|
|
21
|
-
include Operator
|
|
21
|
+
include Operator::Unary
|
|
22
22
|
|
|
23
23
|
DEFAULT_OPTIONS = {
|
|
24
24
|
:postprocessor => :none,
|
|
@@ -32,11 +32,10 @@ module Bmg
|
|
|
32
32
|
@options = DEFAULT_OPTIONS.merge(options)
|
|
33
33
|
@options[:postprocessor] = NoLeftJoinNoise.new(@options[:postprocessor])
|
|
34
34
|
end
|
|
35
|
-
attr_reader :type
|
|
36
35
|
|
|
37
36
|
private
|
|
38
37
|
|
|
39
|
-
attr_reader :
|
|
38
|
+
attr_reader :options
|
|
40
39
|
|
|
41
40
|
public
|
|
42
41
|
|
|
@@ -50,6 +49,12 @@ module Bmg
|
|
|
50
49
|
[ :autowrap, operand.to_ast, @original_options.dup ]
|
|
51
50
|
end
|
|
52
51
|
|
|
52
|
+
protected ### inspect
|
|
53
|
+
|
|
54
|
+
def args
|
|
55
|
+
[ options ]
|
|
56
|
+
end
|
|
57
|
+
|
|
53
58
|
private
|
|
54
59
|
|
|
55
60
|
def autowrap(tuple)
|
|
@@ -93,6 +98,7 @@ module Bmg
|
|
|
93
98
|
}
|
|
94
99
|
|
|
95
100
|
def initialize(remover)
|
|
101
|
+
@remover_to_s = remover
|
|
96
102
|
@remover = case remover
|
|
97
103
|
when NilClass then REMOVERS[:none]
|
|
98
104
|
when Proc then remover
|
|
@@ -115,6 +121,11 @@ module Bmg
|
|
|
115
121
|
tuple.all?{|(k,v)| v.nil? || all_nil?(tuple[k]) }
|
|
116
122
|
end
|
|
117
123
|
|
|
124
|
+
def inspect
|
|
125
|
+
@remover_to_s.inspect
|
|
126
|
+
end
|
|
127
|
+
alias :to_s :inspect
|
|
128
|
+
|
|
118
129
|
end # NoLeftJoinNoise
|
|
119
130
|
|
|
120
131
|
end # class Autowrap
|
|
@@ -8,18 +8,17 @@ module Bmg
|
|
|
8
8
|
# statically known.
|
|
9
9
|
#
|
|
10
10
|
class Constants
|
|
11
|
-
include Operator
|
|
11
|
+
include Operator::Unary
|
|
12
12
|
|
|
13
13
|
def initialize(type, operand, constants)
|
|
14
14
|
@type = type
|
|
15
15
|
@operand = operand
|
|
16
16
|
@constants = constants
|
|
17
17
|
end
|
|
18
|
-
attr_reader :type
|
|
19
18
|
|
|
20
19
|
protected
|
|
21
20
|
|
|
22
|
-
attr_reader :
|
|
21
|
+
attr_reader :constants
|
|
23
22
|
|
|
24
23
|
public
|
|
25
24
|
|
|
@@ -94,6 +93,12 @@ module Bmg
|
|
|
94
93
|
super
|
|
95
94
|
end
|
|
96
95
|
|
|
96
|
+
protected ### inspect
|
|
97
|
+
|
|
98
|
+
def args
|
|
99
|
+
[ constants ]
|
|
100
|
+
end
|
|
101
|
+
|
|
97
102
|
private
|
|
98
103
|
|
|
99
104
|
def extend_it(tuple)
|
data/lib/bmg/operator/extend.rb
CHANGED
|
@@ -11,18 +11,17 @@ module Bmg
|
|
|
11
11
|
# [{ a: 1 }] extend { b: ->(t){ 2 } } => [{ a: 1, b: 2 }]
|
|
12
12
|
#
|
|
13
13
|
class Extend
|
|
14
|
-
include Operator
|
|
14
|
+
include Operator::Unary
|
|
15
15
|
|
|
16
16
|
def initialize(type, operand, extension)
|
|
17
17
|
@type = type
|
|
18
18
|
@operand = operand
|
|
19
19
|
@extension = extension
|
|
20
20
|
end
|
|
21
|
-
attr_reader :type
|
|
22
21
|
|
|
23
22
|
protected
|
|
24
23
|
|
|
25
|
-
attr_reader :
|
|
24
|
+
attr_reader :extension
|
|
26
25
|
|
|
27
26
|
public
|
|
28
27
|
|
|
@@ -69,6 +68,12 @@ module Bmg
|
|
|
69
68
|
end
|
|
70
69
|
end
|
|
71
70
|
|
|
71
|
+
protected ### inspect
|
|
72
|
+
|
|
73
|
+
def args
|
|
74
|
+
[ extension ]
|
|
75
|
+
end
|
|
76
|
+
|
|
72
77
|
private
|
|
73
78
|
|
|
74
79
|
def extend_it(tuple)
|
data/lib/bmg/operator/image.rb
CHANGED
|
@@ -6,7 +6,7 @@ module Bmg
|
|
|
6
6
|
# Extends each tuple with its image in right.
|
|
7
7
|
#
|
|
8
8
|
class Image
|
|
9
|
-
include Operator
|
|
9
|
+
include Operator::Binary
|
|
10
10
|
|
|
11
11
|
DEFAULT_OPTIONS = {
|
|
12
12
|
|
|
@@ -24,11 +24,10 @@ module Bmg
|
|
|
24
24
|
@on = on
|
|
25
25
|
@options = DEFAULT_OPTIONS.merge(options)
|
|
26
26
|
end
|
|
27
|
-
attr_reader :type
|
|
28
27
|
|
|
29
28
|
private
|
|
30
29
|
|
|
31
|
-
attr_reader :
|
|
30
|
+
attr_reader :as, :on, :options
|
|
32
31
|
|
|
33
32
|
public
|
|
34
33
|
|
|
@@ -93,6 +92,12 @@ module Bmg
|
|
|
93
92
|
super
|
|
94
93
|
end
|
|
95
94
|
|
|
95
|
+
protected ### inspect
|
|
96
|
+
|
|
97
|
+
def args
|
|
98
|
+
[ as, on, options ]
|
|
99
|
+
end
|
|
100
|
+
|
|
96
101
|
private
|
|
97
102
|
|
|
98
103
|
def tuple_project(tuple, on)
|
|
@@ -108,7 +113,7 @@ module Bmg
|
|
|
108
113
|
end
|
|
109
114
|
|
|
110
115
|
def empty_image
|
|
111
|
-
|
|
116
|
+
Relation::InMemory.new(image_type, Set.new)
|
|
112
117
|
end
|
|
113
118
|
|
|
114
119
|
end # class Project
|
data/lib/bmg/operator/project.rb
CHANGED
|
@@ -14,18 +14,17 @@ module Bmg
|
|
|
14
14
|
# input tuples.
|
|
15
15
|
#
|
|
16
16
|
class Project
|
|
17
|
-
include Operator
|
|
17
|
+
include Operator::Unary
|
|
18
18
|
|
|
19
19
|
def initialize(type, operand, attrlist)
|
|
20
20
|
@type = type
|
|
21
21
|
@operand = operand
|
|
22
22
|
@attrlist = attrlist
|
|
23
23
|
end
|
|
24
|
-
attr_reader :type
|
|
25
24
|
|
|
26
25
|
private
|
|
27
26
|
|
|
28
|
-
attr_reader :
|
|
27
|
+
attr_reader :attrlist
|
|
29
28
|
|
|
30
29
|
public
|
|
31
30
|
|
|
@@ -67,6 +66,12 @@ module Bmg
|
|
|
67
66
|
operand.restrict(predicate).project(attrlist)
|
|
68
67
|
end
|
|
69
68
|
|
|
69
|
+
protected ### inspect
|
|
70
|
+
|
|
71
|
+
def args
|
|
72
|
+
[ attrlist ]
|
|
73
|
+
end
|
|
74
|
+
|
|
70
75
|
private
|
|
71
76
|
|
|
72
77
|
def project(tuple)
|
data/lib/bmg/operator/rename.rb
CHANGED
|
@@ -14,18 +14,17 @@ module Bmg
|
|
|
14
14
|
# attributes of the input tuples.
|
|
15
15
|
#
|
|
16
16
|
class Rename
|
|
17
|
-
include Operator
|
|
17
|
+
include Operator::Unary
|
|
18
18
|
|
|
19
19
|
def initialize(type, operand, renaming)
|
|
20
20
|
@type = type
|
|
21
21
|
@operand = operand
|
|
22
22
|
@renaming = renaming
|
|
23
23
|
end
|
|
24
|
-
attr_reader :type
|
|
25
24
|
|
|
26
25
|
private
|
|
27
26
|
|
|
28
|
-
attr_reader :
|
|
27
|
+
attr_reader :renaming
|
|
29
28
|
|
|
30
29
|
public
|
|
31
30
|
|
|
@@ -67,6 +66,12 @@ module Bmg
|
|
|
67
66
|
operand.restrict(predicate.rename(reverse_renaming)).rename(renaming)
|
|
68
67
|
end
|
|
69
68
|
|
|
69
|
+
protected ### inspect
|
|
70
|
+
|
|
71
|
+
def args
|
|
72
|
+
[ renaming ]
|
|
73
|
+
end
|
|
74
|
+
|
|
70
75
|
private
|
|
71
76
|
|
|
72
77
|
def rename(tuple, renaming)
|
|
@@ -7,18 +7,17 @@ module Bmg
|
|
|
7
7
|
# at construction.
|
|
8
8
|
#
|
|
9
9
|
class Restrict
|
|
10
|
-
include Operator
|
|
10
|
+
include Operator::Unary
|
|
11
11
|
|
|
12
12
|
def initialize(type, operand, predicate)
|
|
13
13
|
@type = type
|
|
14
14
|
@operand = operand
|
|
15
15
|
@predicate = predicate
|
|
16
16
|
end
|
|
17
|
-
attr_reader :type
|
|
18
17
|
|
|
19
18
|
protected
|
|
20
19
|
|
|
21
|
-
attr_reader :
|
|
20
|
+
attr_reader :predicate
|
|
22
21
|
|
|
23
22
|
public
|
|
24
23
|
|
|
@@ -38,6 +37,12 @@ module Bmg
|
|
|
38
37
|
Restrict.new(type, @operand, @predicate & predicate)
|
|
39
38
|
end
|
|
40
39
|
|
|
40
|
+
protected ### inspect
|
|
41
|
+
|
|
42
|
+
def args
|
|
43
|
+
[ predicate ]
|
|
44
|
+
end
|
|
45
|
+
|
|
41
46
|
end # class Restrict
|
|
42
47
|
end # module Operator
|
|
43
48
|
end # module Bmg
|
data/lib/bmg/operator/union.rb
CHANGED
|
@@ -14,7 +14,7 @@ module Bmg
|
|
|
14
14
|
# behavior and save execution time.
|
|
15
15
|
#
|
|
16
16
|
class Union
|
|
17
|
-
include Operator
|
|
17
|
+
include Operator::Nary
|
|
18
18
|
|
|
19
19
|
DEFAULT_OPTIONS = {
|
|
20
20
|
all: false
|
|
@@ -25,11 +25,10 @@ module Bmg
|
|
|
25
25
|
@operands = operands
|
|
26
26
|
@options = DEFAULT_OPTIONS.merge(options)
|
|
27
27
|
end
|
|
28
|
-
attr_reader :type
|
|
29
28
|
|
|
30
29
|
protected
|
|
31
30
|
|
|
32
|
-
attr_reader :
|
|
31
|
+
attr_reader :options
|
|
33
32
|
|
|
34
33
|
public
|
|
35
34
|
|
|
@@ -83,6 +82,12 @@ module Bmg
|
|
|
83
82
|
end
|
|
84
83
|
end
|
|
85
84
|
|
|
85
|
+
protected ### inspect
|
|
86
|
+
|
|
87
|
+
def args
|
|
88
|
+
[ options ]
|
|
89
|
+
end
|
|
90
|
+
|
|
86
91
|
end # class Union
|
|
87
92
|
end # module Operator
|
|
88
93
|
end # module Bmg
|
data/lib/bmg/reader.rb
CHANGED
data/lib/bmg/reader/csv.rb
CHANGED
|
@@ -8,7 +8,8 @@ module Bmg
|
|
|
8
8
|
:return_headers => false
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
def initialize(path, options = {})
|
|
11
|
+
def initialize(type, path, options = {})
|
|
12
|
+
@type = type
|
|
12
13
|
@path = path
|
|
13
14
|
@options = DEFAULT_OPTIONS.merge(options)
|
|
14
15
|
@options[:col_sep] ||= infer_col_sep
|
|
@@ -22,6 +23,15 @@ module Bmg
|
|
|
22
23
|
end
|
|
23
24
|
end
|
|
24
25
|
|
|
26
|
+
def to_ast
|
|
27
|
+
[ :csv, @path, @options ]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_s
|
|
31
|
+
"(csv #{path})"
|
|
32
|
+
end
|
|
33
|
+
alias :inspect :to_s
|
|
34
|
+
|
|
25
35
|
private
|
|
26
36
|
|
|
27
37
|
def tuple(row)
|
data/lib/bmg/reader/excel.rb
CHANGED
|
@@ -7,7 +7,8 @@ module Bmg
|
|
|
7
7
|
skip: 0
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
def initialize(path, options = {})
|
|
10
|
+
def initialize(type, path, options = {})
|
|
11
|
+
@type = type
|
|
11
12
|
@path = path
|
|
12
13
|
@options = DEFAULT_OPTIONS.merge(options)
|
|
13
14
|
end
|
|
@@ -30,6 +31,15 @@ module Bmg
|
|
|
30
31
|
end
|
|
31
32
|
end
|
|
32
33
|
|
|
34
|
+
def to_ast
|
|
35
|
+
[ :excel, @path, @options ]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def to_s
|
|
39
|
+
"(excel #{path})"
|
|
40
|
+
end
|
|
41
|
+
alias :inspect :to_s
|
|
42
|
+
|
|
33
43
|
end # class Excel
|
|
34
44
|
end # module Reader
|
|
35
45
|
end # module Bmg
|
data/lib/bmg/relation.rb
CHANGED
|
@@ -4,13 +4,19 @@ module Bmg
|
|
|
4
4
|
include Algebra
|
|
5
5
|
|
|
6
6
|
def self.new(operand, type = Type::ANY)
|
|
7
|
-
|
|
7
|
+
raise ArgumentError, "Missing type" if type.nil?
|
|
8
|
+
operand.is_a?(Relation) ? operand : Bmg.in_memory(operand, type)
|
|
8
9
|
end
|
|
9
10
|
|
|
10
11
|
def self.empty(type = Type::ANY)
|
|
11
12
|
Relation::Empty.new(type)
|
|
12
13
|
end
|
|
13
14
|
|
|
15
|
+
def empty?
|
|
16
|
+
each{|t| return false }
|
|
17
|
+
true
|
|
18
|
+
end
|
|
19
|
+
|
|
14
20
|
# Private helper to implement `one` and `one_or_nil`
|
|
15
21
|
def one_or_yield(&bl)
|
|
16
22
|
first = nil
|
|
@@ -47,6 +53,30 @@ module Bmg
|
|
|
47
53
|
raise InvalidUpdateError, "Cannot delete from this Relvar"
|
|
48
54
|
end
|
|
49
55
|
|
|
56
|
+
def visit(&visitor)
|
|
57
|
+
_visit(nil, visitor)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def _visit(parent, visitor)
|
|
61
|
+
visitor.call(self, parent)
|
|
62
|
+
end
|
|
63
|
+
protected :_visit
|
|
64
|
+
|
|
65
|
+
def ys_by_x(y, x, options = {})
|
|
66
|
+
ordering = options[:order]
|
|
67
|
+
projection = [y, ordering].compact.uniq
|
|
68
|
+
by_x = each.each_with_object({}) do |tuple,h|
|
|
69
|
+
h[tuple[x]] ||= []
|
|
70
|
+
h[tuple[x]] << TupleAlgebra.project(tuple, projection)
|
|
71
|
+
end
|
|
72
|
+
by_x.each_with_object({}) do |(x,ys),h|
|
|
73
|
+
ys = ys.sort{|y1,y2| y1[ordering] <=> y2[ordering] } if ordering
|
|
74
|
+
ys = ys.map{|t| t[y] }
|
|
75
|
+
ys = ys.uniq if options[:distinct]
|
|
76
|
+
h[x] = ys
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
50
80
|
# Returns a json representation
|
|
51
81
|
def to_json(*args, &bl)
|
|
52
82
|
to_a.to_json(*args, &bl)
|
|
@@ -59,24 +89,11 @@ module Bmg
|
|
|
59
89
|
|
|
60
90
|
# Returns a String representing the query plan
|
|
61
91
|
def debug(max_level = nil, on = STDERR)
|
|
62
|
-
on.puts
|
|
92
|
+
on.puts(self.inspect)
|
|
63
93
|
self
|
|
64
94
|
end
|
|
65
95
|
|
|
66
|
-
private
|
|
67
|
-
|
|
68
|
-
def _debug(ast, level = 1, max_level = nil)
|
|
69
|
-
return ast.inspect if ast.is_a?(Symbol)
|
|
70
|
-
return ast.to_s unless ast.is_a?(Array)
|
|
71
|
-
return ast.to_s unless ast.first.is_a?(Symbol)
|
|
72
|
-
if max_level && level>max_level
|
|
73
|
-
"(#{ast.first} ...)"
|
|
74
|
-
else
|
|
75
|
-
sep = " " * level
|
|
76
|
-
"(#{ast.first}\n" + ast[1..-1].map{|a| _debug(a, 1+level, max_level) }.join("\n").gsub(/^/, sep) + ")"
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
96
|
end # module Relation
|
|
81
97
|
end # module Bmg
|
|
82
98
|
require_relative 'relation/empty'
|
|
99
|
+
require_relative 'relation/in_memory'
|
data/lib/bmg/relation/empty.rb
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Bmg
|
|
2
|
+
module Relation
|
|
3
|
+
class InMemory
|
|
4
|
+
include Relation
|
|
5
|
+
|
|
6
|
+
def initialize(type, operand)
|
|
7
|
+
@operand = operand
|
|
8
|
+
@type = type
|
|
9
|
+
end
|
|
10
|
+
attr_reader :type, :operand
|
|
11
|
+
|
|
12
|
+
public
|
|
13
|
+
|
|
14
|
+
def each(&bl)
|
|
15
|
+
@operand.each(&bl)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def to_ast
|
|
19
|
+
[ :in_memory, operand ]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def to_s
|
|
23
|
+
"(in_memory ...)"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def inspect
|
|
27
|
+
"(in_memory #{operand.inspect})"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end # class InMemory
|
|
31
|
+
end # module Relation
|
|
32
|
+
end # module Bmg
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module Bmg
|
|
2
|
+
module Relation
|
|
3
|
+
class Spied
|
|
4
|
+
include Operator::Unary
|
|
5
|
+
|
|
6
|
+
def initialize(operand, spy)
|
|
7
|
+
@operand = operand
|
|
8
|
+
@spy = spy
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
protected
|
|
12
|
+
|
|
13
|
+
attr_reader :spy
|
|
14
|
+
|
|
15
|
+
public
|
|
16
|
+
|
|
17
|
+
def type
|
|
18
|
+
operand.type
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def each(&bl)
|
|
22
|
+
spy.call(self)
|
|
23
|
+
operand.each(&bl)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_ast
|
|
27
|
+
[ :spied, operand.to_ast, spy ]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
public ### algebra
|
|
31
|
+
|
|
32
|
+
Algebra::METHODS.each do |m|
|
|
33
|
+
define_method(m) do |*args, &bl|
|
|
34
|
+
operand.send(m, *args, &bl).spied(spy)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def image(right, *args)
|
|
39
|
+
operand.image(right.unspied, *args).spied(spy)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def union(right, *args)
|
|
43
|
+
operand.union(right.unspied, *args).spied(spy)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def unspied
|
|
47
|
+
operand
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
public ### update
|
|
51
|
+
|
|
52
|
+
def insert(*args, &bl)
|
|
53
|
+
operand.insert(*args, &bl)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def delete(*args, &bl)
|
|
57
|
+
operand.delete(*args, &bl)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def update(*args, &bl)
|
|
61
|
+
operand.update(*args, &bl)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
protected ### inspect
|
|
65
|
+
|
|
66
|
+
def args
|
|
67
|
+
[ spy ]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
end # class Spied
|
|
71
|
+
end # module Relation
|
|
72
|
+
end # module Bmg
|
data/lib/bmg/sequel.rb
CHANGED
data/lib/bmg/sequel/relation.rb
CHANGED
|
@@ -24,7 +24,7 @@ module Bmg
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def insert(arg)
|
|
27
|
-
dataset.insert(arg)
|
|
27
|
+
dataset.insert(arg.merge(type.predicate.constants))
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def update(arg)
|
|
@@ -32,9 +32,14 @@ module Bmg
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def to_ast
|
|
35
|
-
[:sequel,
|
|
35
|
+
[:sequel, dataset.sql]
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
def to_s
|
|
39
|
+
"(sequel #{dataset.sql})"
|
|
40
|
+
end
|
|
41
|
+
alias :inspect :to_s
|
|
42
|
+
|
|
38
43
|
protected ### optimization
|
|
39
44
|
|
|
40
45
|
def _restrict(type, predicate)
|
data/lib/bmg/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bmg
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bernard Lambeau
|
|
@@ -122,7 +122,6 @@ files:
|
|
|
122
122
|
- lib/bmg.rb
|
|
123
123
|
- lib/bmg/algebra.rb
|
|
124
124
|
- lib/bmg/error.rb
|
|
125
|
-
- lib/bmg/leaf.rb
|
|
126
125
|
- lib/bmg/operator.rb
|
|
127
126
|
- lib/bmg/operator/allbut.rb
|
|
128
127
|
- lib/bmg/operator/autosummarize.rb
|
|
@@ -139,6 +138,8 @@ files:
|
|
|
139
138
|
- lib/bmg/reader/excel.rb
|
|
140
139
|
- lib/bmg/relation.rb
|
|
141
140
|
- lib/bmg/relation/empty.rb
|
|
141
|
+
- lib/bmg/relation/in_memory.rb
|
|
142
|
+
- lib/bmg/relation/spied.rb
|
|
142
143
|
- lib/bmg/sequel.rb
|
|
143
144
|
- lib/bmg/sequel/relation.rb
|
|
144
145
|
- lib/bmg/support.rb
|
data/lib/bmg/leaf.rb
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
module Bmg
|
|
2
|
-
class Leaf
|
|
3
|
-
include Relation
|
|
4
|
-
|
|
5
|
-
def initialize(type, operand)
|
|
6
|
-
@operand = operand
|
|
7
|
-
@type = type
|
|
8
|
-
end
|
|
9
|
-
attr_reader :type, :operand
|
|
10
|
-
|
|
11
|
-
public
|
|
12
|
-
|
|
13
|
-
def each(&bl)
|
|
14
|
-
@operand.each(&bl)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def to_ast
|
|
18
|
-
[:leaf, operand]
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
end
|
|
22
|
-
end
|