bmg 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|