bmg 0.18.0 → 0.18.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/lib/bmg/algebra.rb +1 -0
- data/lib/bmg/algebra/shortcuts.rb +6 -0
- data/lib/bmg/error.rb +3 -0
- data/lib/bmg/operator/allbut.rb +27 -0
- data/lib/bmg/operator/autosummarize.rb +27 -4
- data/lib/bmg/operator/autowrap.rb +27 -0
- data/lib/bmg/operator/constants.rb +7 -0
- data/lib/bmg/operator/extend.rb +7 -0
- data/lib/bmg/operator/group.rb +1 -0
- data/lib/bmg/operator/image.rb +41 -2
- data/lib/bmg/operator/join.rb +1 -0
- data/lib/bmg/operator/matching.rb +1 -0
- data/lib/bmg/operator/not_matching.rb +1 -0
- data/lib/bmg/operator/page.rb +2 -7
- data/lib/bmg/operator/project.rb +3 -2
- data/lib/bmg/operator/rename.rb +12 -5
- data/lib/bmg/operator/restrict.rb +1 -0
- data/lib/bmg/operator/rxmatch.rb +1 -0
- data/lib/bmg/operator/summarize.rb +2 -17
- data/lib/bmg/operator/transform.rb +39 -1
- data/lib/bmg/operator/union.rb +1 -0
- data/lib/bmg/reader/csv.rb +29 -10
- data/lib/bmg/reader/excel.rb +23 -4
- data/lib/bmg/relation.rb +18 -0
- data/lib/bmg/relation/empty.rb +4 -0
- data/lib/bmg/relation/in_memory.rb +10 -1
- data/lib/bmg/relation/materialized.rb +6 -0
- data/lib/bmg/relation/spied.rb +5 -0
- data/lib/bmg/sequel/relation.rb +5 -0
- data/lib/bmg/sql/relation.rb +2 -3
- data/lib/bmg/summarizer.rb +36 -1
- data/lib/bmg/summarizer/avg.rb +3 -3
- data/lib/bmg/summarizer/by_proc.rb +41 -0
- data/lib/bmg/summarizer/distinct.rb +36 -0
- data/lib/bmg/summarizer/multiple.rb +46 -0
- data/lib/bmg/summarizer/percentile.rb +79 -0
- data/lib/bmg/summarizer/value_by.rb +62 -0
- data/lib/bmg/support.rb +1 -0
- data/lib/bmg/support/ordering.rb +20 -0
- data/lib/bmg/support/tuple_transformer.rb +10 -1
- data/lib/bmg/version.rb +1 -1
- data/lib/bmg/writer.rb +16 -0
- data/lib/bmg/writer/csv.rb +2 -12
- data/lib/bmg/writer/xlsx.rb +68 -0
- metadata +23 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6569e9038c83dda887da734d97ef58f9ff6e94984c78e8eae993561cde3bbfcc
|
4
|
+
data.tar.gz: 85d65ca717992a132e94ae17dbdf2cc671a161c495eb5be240c3d4e342e90c3f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fbeb5215e5942626dd5115d95c091602daa57128014bc0833c38c3460697ef9dbc59b4ccd7566d4d3604e8d7a8c5e7e4812159a5bb89d3dad477e6a7b75545d8
|
7
|
+
data.tar.gz: 9e8a9eaaf3699d28890cb15faef5b12360f9bf26c5bb0e9bf42ccedba0b7b5a3c8c2eb627f8b1a4e154c8d992426f47ed82153e9f110634f0ba6aa7ceddd1353
|
data/README.md
CHANGED
@@ -213,6 +213,7 @@ r.extend(x: ->(t){ ... }, ...) # add computed attributes
|
|
213
213
|
r.exclude(predicate) # shortcut for restrict(!predicate)
|
214
214
|
r.group([:a, :b, ...], :x) # relation-valued attribute from attributes
|
215
215
|
r.image(right, :x, [:a, :b, ...]) # relation-valued attribute from another relation
|
216
|
+
r.images({:x => r1, :y => r2}, [:a, ...]) # shortcut over image(r1, :x, ...).image(r2, :y, ...)
|
216
217
|
r.join(right, [:a, :b, ...]) # natural join on a join key
|
217
218
|
r.join(right, :a => :x, :b => :y, ...) # natural join after right reversed renaming
|
218
219
|
r.left_join(right, [:a, :b, ...], {...}) # left join with optional default right tuple
|
data/lib/bmg/algebra.rb
CHANGED
@@ -174,6 +174,7 @@ module Bmg
|
|
174
174
|
|
175
175
|
def transform(transformation = nil, options = {}, &proc)
|
176
176
|
transformation, options = proc, (transformation || {}) unless proc.nil?
|
177
|
+
return self if transformation.is_a?(Hash) && transformation.empty?
|
177
178
|
_transform(self.type.transform(transformation, options), transformation, options)
|
178
179
|
end
|
179
180
|
|
@@ -39,6 +39,12 @@ module Bmg
|
|
39
39
|
self.image(right.rename(renaming), as, on.keys, options)
|
40
40
|
end
|
41
41
|
|
42
|
+
def images(rights, on = [], options = {})
|
43
|
+
rights.each_pair.inject(self){|memo,(as,right)|
|
44
|
+
memo.image(right, as, on, options)
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
42
48
|
def join(right, on = [])
|
43
49
|
return super unless on.is_a?(Hash)
|
44
50
|
renaming = Hash[on.map{|k,v| [v,k] }]
|
data/lib/bmg/error.rb
CHANGED
data/lib/bmg/operator/allbut.rb
CHANGED
@@ -30,6 +30,7 @@ module Bmg
|
|
30
30
|
public
|
31
31
|
|
32
32
|
def each
|
33
|
+
return to_enum unless block_given?
|
33
34
|
seen = {}
|
34
35
|
@operand.each do |tuple|
|
35
36
|
allbuted = tuple_allbut(tuple)
|
@@ -63,12 +64,38 @@ module Bmg
|
|
63
64
|
|
64
65
|
protected ### optimization
|
65
66
|
|
67
|
+
def _allbut(type, butlist)
|
68
|
+
operand.allbut(self.butlist|butlist)
|
69
|
+
end
|
70
|
+
|
71
|
+
def _matching(type, right, on)
|
72
|
+
# Always possible to push the matching, since by construction
|
73
|
+
# `on` can only use attributes that have not been trown away,
|
74
|
+
# hence they exist on `operand` too.
|
75
|
+
operand.matching(right, on).allbut(butlist)
|
76
|
+
end
|
77
|
+
|
78
|
+
def _page(type, ordering, page_index, options)
|
79
|
+
return super unless self.preserving_key?
|
80
|
+
operand.page(ordering, page_index, options).allbut(butlist)
|
81
|
+
end
|
82
|
+
|
83
|
+
def _project(type, attrlist)
|
84
|
+
operand.project(attrlist)
|
85
|
+
end
|
86
|
+
|
66
87
|
def _restrict(type, predicate)
|
67
88
|
operand.restrict(predicate).allbut(butlist)
|
68
89
|
end
|
69
90
|
|
70
91
|
protected ### inspect
|
71
92
|
|
93
|
+
def preserving_key?
|
94
|
+
operand.type.knows_keys? && operand.type.keys.find{|k|
|
95
|
+
(k & butlist).empty?
|
96
|
+
}
|
97
|
+
end
|
98
|
+
|
72
99
|
def args
|
73
100
|
[ butlist ]
|
74
101
|
end
|
@@ -24,7 +24,24 @@ module Bmg
|
|
24
24
|
|
25
25
|
public
|
26
26
|
|
27
|
+
def self.same(*args)
|
28
|
+
Same.new(*args)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.group(*args)
|
32
|
+
Group.new(*args)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.y_by_x(*args)
|
36
|
+
YByX.new(*args)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.ys_by_x(*args)
|
40
|
+
YsByX.new(*args)
|
41
|
+
end
|
42
|
+
|
27
43
|
def each(&bl)
|
44
|
+
return to_enum unless block_given?
|
28
45
|
h = {}
|
29
46
|
@operand.each do |tuple|
|
30
47
|
key = key(tuple)
|
@@ -41,6 +58,12 @@ module Bmg
|
|
41
58
|
[:autosummarize, operand.to_ast, by.dup, sums.dup]
|
42
59
|
end
|
43
60
|
|
61
|
+
public ### for internal reasons
|
62
|
+
|
63
|
+
def _count
|
64
|
+
operand._count
|
65
|
+
end
|
66
|
+
|
44
67
|
protected
|
45
68
|
|
46
69
|
def _restrict(type, predicate)
|
@@ -175,11 +198,11 @@ module Bmg
|
|
175
198
|
end
|
176
199
|
|
177
200
|
def init(v)
|
178
|
-
[v]
|
201
|
+
v.nil? ? [] : [v]
|
179
202
|
end
|
180
203
|
|
181
204
|
def sum(v1, v2)
|
182
|
-
v1 << v2
|
205
|
+
v2.nil? ? v1 : (v1 << v2)
|
183
206
|
end
|
184
207
|
|
185
208
|
def term(v)
|
@@ -211,11 +234,11 @@ module Bmg
|
|
211
234
|
end
|
212
235
|
|
213
236
|
def init(v)
|
214
|
-
[v]
|
237
|
+
v.nil? ? [] : [v]
|
215
238
|
end
|
216
239
|
|
217
240
|
def sum(v1, v2)
|
218
|
-
v1 << v2
|
241
|
+
v2.nil? ? v1 : (v1 << v2)
|
219
242
|
end
|
220
243
|
|
221
244
|
def term(v)
|
@@ -43,6 +43,7 @@ module Bmg
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def each
|
46
|
+
return to_enum unless block_given?
|
46
47
|
@operand.each do |tuple|
|
47
48
|
yield autowrap_tuple(tuple)
|
48
49
|
end
|
@@ -52,6 +53,12 @@ module Bmg
|
|
52
53
|
[ :autowrap, operand.to_ast, @original_options.dup ]
|
53
54
|
end
|
54
55
|
|
56
|
+
public ### for internal reasons
|
57
|
+
|
58
|
+
def _count
|
59
|
+
operand._count
|
60
|
+
end
|
61
|
+
|
55
62
|
protected ### optimization
|
56
63
|
|
57
64
|
def _autowrap(type, opts)
|
@@ -86,6 +93,16 @@ module Bmg
|
|
86
93
|
false
|
87
94
|
end
|
88
95
|
|
96
|
+
def _matching(type, right, on)
|
97
|
+
if (wrapped_roots! & on).empty?
|
98
|
+
operand.matching(right, on).autowrap(options)
|
99
|
+
else
|
100
|
+
super
|
101
|
+
end
|
102
|
+
rescue UnknownAttributesError
|
103
|
+
super
|
104
|
+
end
|
105
|
+
|
89
106
|
def _page(type, ordering, page_index, opts)
|
90
107
|
attrs = ordering.map{|(a,d)| a }
|
91
108
|
if (wrapped_roots! & attrs).empty?
|
@@ -97,6 +114,16 @@ module Bmg
|
|
97
114
|
super
|
98
115
|
end
|
99
116
|
|
117
|
+
def _project(type, attrlist)
|
118
|
+
if (wrapped_roots! & attrlist).empty?
|
119
|
+
operand.project(attrlist).autowrap(options)
|
120
|
+
else
|
121
|
+
super
|
122
|
+
end
|
123
|
+
rescue UnknownAttributesError
|
124
|
+
super
|
125
|
+
end
|
126
|
+
|
100
127
|
def _rename(type, renaming)
|
101
128
|
# 1. Can't optimize if renaming applies to a wrapped one
|
102
129
|
return super unless (wrapped_roots! & renaming.keys).empty?
|
@@ -23,6 +23,7 @@ module Bmg
|
|
23
23
|
public
|
24
24
|
|
25
25
|
def each
|
26
|
+
return to_enum unless block_given?
|
26
27
|
@operand.each do |tuple|
|
27
28
|
yield extend_it(tuple)
|
28
29
|
end
|
@@ -54,6 +55,12 @@ module Bmg
|
|
54
55
|
[ :constants, operand.to_ast, constants.dup ]
|
55
56
|
end
|
56
57
|
|
58
|
+
public ### for internal reasons
|
59
|
+
|
60
|
+
def _count
|
61
|
+
operand._count
|
62
|
+
end
|
63
|
+
|
57
64
|
protected ### optimization
|
58
65
|
|
59
66
|
def _page(type, ordering, page_index, options)
|
data/lib/bmg/operator/extend.rb
CHANGED
@@ -26,6 +26,7 @@ module Bmg
|
|
26
26
|
public
|
27
27
|
|
28
28
|
def each
|
29
|
+
return to_enum unless block_given?
|
29
30
|
@operand.each do |tuple|
|
30
31
|
yield extend_it(tuple)
|
31
32
|
end
|
@@ -53,6 +54,12 @@ module Bmg
|
|
53
54
|
[ :extend, operand.to_ast, extension.dup ]
|
54
55
|
end
|
55
56
|
|
57
|
+
public ### for internal reasons
|
58
|
+
|
59
|
+
def _count
|
60
|
+
operand._count
|
61
|
+
end
|
62
|
+
|
56
63
|
protected ### optimization
|
57
64
|
|
58
65
|
def _allbut(type, butlist)
|
data/lib/bmg/operator/group.rb
CHANGED
data/lib/bmg/operator/image.rb
CHANGED
@@ -46,6 +46,7 @@ module Bmg
|
|
46
46
|
public
|
47
47
|
|
48
48
|
def each(*args, &bl)
|
49
|
+
return to_enum unless block_given?
|
49
50
|
(options[:jit_optimized] ? self : jit_optimize)._each(*args, &bl)
|
50
51
|
end
|
51
52
|
|
@@ -99,9 +100,10 @@ module Bmg
|
|
99
100
|
key = tuple_project(t, on)
|
100
101
|
index[key].operand << tuple_image(t, on)
|
101
102
|
end
|
102
|
-
if options[:array]
|
103
|
+
if opt = options[:array]
|
104
|
+
sorter = to_sorter(opt)
|
103
105
|
index = index.each_with_object({}) do |(k,v),ix|
|
104
|
-
ix[k] = v.to_a
|
106
|
+
ix[k] = sorter ? v.to_a.sort(&sorter) : v.to_a
|
105
107
|
end
|
106
108
|
end
|
107
109
|
index
|
@@ -154,8 +156,32 @@ module Bmg
|
|
154
156
|
end
|
155
157
|
end
|
156
158
|
|
159
|
+
public ### for internal reasons
|
160
|
+
|
161
|
+
def _count
|
162
|
+
left._count
|
163
|
+
end
|
164
|
+
|
157
165
|
protected ### optimization
|
158
166
|
|
167
|
+
def _allbut(type, butlist)
|
168
|
+
if butlist.include?(as)
|
169
|
+
left.allbut(butlist - [as])
|
170
|
+
elsif (butlist & on).empty?
|
171
|
+
left.allbut(butlist).image(right, as, on, options)
|
172
|
+
else
|
173
|
+
super
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def _matching(type, m_right, m_on)
|
178
|
+
if m_on.include?(as)
|
179
|
+
super
|
180
|
+
else
|
181
|
+
left.matching(m_right, m_on).image(right, as, on, options)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
159
185
|
def _page(type, ordering, page_index, opts)
|
160
186
|
if ordering.map{|(k,v)| k}.include?(as)
|
161
187
|
super
|
@@ -166,6 +192,14 @@ module Bmg
|
|
166
192
|
end
|
167
193
|
end
|
168
194
|
|
195
|
+
def _project(type, attrlist)
|
196
|
+
if attrlist.include?(as)
|
197
|
+
super
|
198
|
+
else
|
199
|
+
left.project(attrlist)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
169
203
|
def _restrict(type, predicate)
|
170
204
|
on_as, rest = predicate.and_split([as])
|
171
205
|
if rest.tautology?
|
@@ -227,6 +261,11 @@ module Bmg
|
|
227
261
|
Relation::InMemory.new(image_type, Set.new)
|
228
262
|
end
|
229
263
|
|
264
|
+
def to_sorter(opt)
|
265
|
+
return nil unless opt.is_a?(Array)
|
266
|
+
Ordering.new(opt).comparator
|
267
|
+
end
|
268
|
+
|
230
269
|
public
|
231
270
|
|
232
271
|
def to_s
|
data/lib/bmg/operator/join.rb
CHANGED
data/lib/bmg/operator/page.rb
CHANGED
@@ -30,6 +30,7 @@ module Bmg
|
|
30
30
|
public
|
31
31
|
|
32
32
|
def each(&bl)
|
33
|
+
return to_enum unless block_given?
|
33
34
|
page_size = options[:page_size]
|
34
35
|
@operand.to_a
|
35
36
|
.sort(&comparator)
|
@@ -45,13 +46,7 @@ module Bmg
|
|
45
46
|
protected ### inspect
|
46
47
|
|
47
48
|
def comparator
|
48
|
-
|
49
|
-
ordering.each do |(attr,direction)|
|
50
|
-
c = t1[attr] <=> t2[attr]
|
51
|
-
return (direction == :desc ? -c : c) unless c==0
|
52
|
-
end
|
53
|
-
0
|
54
|
-
}
|
49
|
+
Ordering.new(@ordering).comparator
|
55
50
|
end
|
56
51
|
|
57
52
|
def args
|
data/lib/bmg/operator/project.rb
CHANGED
@@ -29,9 +29,10 @@ module Bmg
|
|
29
29
|
public
|
30
30
|
|
31
31
|
def each
|
32
|
+
return to_enum unless block_given?
|
32
33
|
seen = {}
|
33
34
|
@operand.each do |tuple|
|
34
|
-
projected =
|
35
|
+
projected = tuple_project(tuple)
|
35
36
|
unless seen.has_key?(projected)
|
36
37
|
yield(projected)
|
37
38
|
seen[projected] = true
|
@@ -74,7 +75,7 @@ module Bmg
|
|
74
75
|
|
75
76
|
private
|
76
77
|
|
77
|
-
def
|
78
|
+
def tuple_project(tuple)
|
78
79
|
tuple.dup.delete_if{|k,_| !@attrlist.include?(k) }
|
79
80
|
end
|
80
81
|
|
data/lib/bmg/operator/rename.rb
CHANGED
@@ -29,16 +29,17 @@ module Bmg
|
|
29
29
|
public
|
30
30
|
|
31
31
|
def each
|
32
|
+
return to_enum unless block_given?
|
32
33
|
@operand.each do |tuple|
|
33
|
-
yield
|
34
|
+
yield rename_tuple(tuple, renaming)
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
37
38
|
def insert(arg)
|
38
39
|
case arg
|
39
|
-
when Hash then operand.insert(
|
40
|
+
when Hash then operand.insert(rename_tuple(arg, reverse_renaming))
|
40
41
|
when Relation then operand.insert(arg.rename(reverse_renaming))
|
41
|
-
when Enumerable then operand.insert(arg.map{|t|
|
42
|
+
when Enumerable then operand.insert(arg.map{|t| rename_tuple(t, reverse_renaming) })
|
42
43
|
else
|
43
44
|
super
|
44
45
|
end
|
@@ -46,7 +47,7 @@ module Bmg
|
|
46
47
|
|
47
48
|
def update(arg)
|
48
49
|
case arg
|
49
|
-
when Hash then operand.update(
|
50
|
+
when Hash then operand.update(rename_tuple(arg, reverse_renaming))
|
50
51
|
else
|
51
52
|
super
|
52
53
|
end
|
@@ -60,6 +61,12 @@ module Bmg
|
|
60
61
|
[ :rename, operand.to_ast, renaming.dup ]
|
61
62
|
end
|
62
63
|
|
64
|
+
public ### for internal reasons
|
65
|
+
|
66
|
+
def _count
|
67
|
+
operand._count
|
68
|
+
end
|
69
|
+
|
63
70
|
protected ### optimization
|
64
71
|
|
65
72
|
def _page(type, ordering, page_index, options)
|
@@ -82,7 +89,7 @@ module Bmg
|
|
82
89
|
|
83
90
|
private
|
84
91
|
|
85
|
-
def
|
92
|
+
def rename_tuple(tuple, renaming)
|
86
93
|
tuple.each_with_object({}){|(k,v),h|
|
87
94
|
h[renaming[k] || k] = v
|
88
95
|
h
|