bmg 0.18.2 → 0.18.7

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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -0
  3. data/lib/bmg/algebra.rb +18 -0
  4. data/lib/bmg/algebra/shortcuts.rb +8 -0
  5. data/lib/bmg/error.rb +3 -0
  6. data/lib/bmg/operator.rb +2 -0
  7. data/lib/bmg/operator/allbut.rb +1 -0
  8. data/lib/bmg/operator/autosummarize.rb +1 -0
  9. data/lib/bmg/operator/autowrap.rb +1 -0
  10. data/lib/bmg/operator/constants.rb +1 -0
  11. data/lib/bmg/operator/extend.rb +1 -0
  12. data/lib/bmg/operator/group.rb +1 -0
  13. data/lib/bmg/operator/image.rb +10 -4
  14. data/lib/bmg/operator/join.rb +1 -0
  15. data/lib/bmg/operator/matching.rb +1 -0
  16. data/lib/bmg/operator/not_matching.rb +1 -0
  17. data/lib/bmg/operator/page.rb +1 -0
  18. data/lib/bmg/operator/project.rb +1 -0
  19. data/lib/bmg/operator/rename.rb +6 -5
  20. data/lib/bmg/operator/restrict.rb +1 -0
  21. data/lib/bmg/operator/rxmatch.rb +1 -0
  22. data/lib/bmg/operator/summarize.rb +2 -17
  23. data/lib/bmg/operator/transform.rb +1 -0
  24. data/lib/bmg/operator/ungroup.rb +61 -0
  25. data/lib/bmg/operator/union.rb +1 -0
  26. data/lib/bmg/operator/unwrap.rb +47 -0
  27. data/lib/bmg/reader/csv.rb +29 -10
  28. data/lib/bmg/reader/excel.rb +23 -4
  29. data/lib/bmg/relation.rb +6 -0
  30. data/lib/bmg/relation/in_memory.rb +0 -1
  31. data/lib/bmg/sequel/relation.rb +1 -0
  32. data/lib/bmg/sequel/translator.rb +9 -2
  33. data/lib/bmg/sql.rb +4 -1
  34. data/lib/bmg/sql/processor.rb +1 -0
  35. data/lib/bmg/sql/processor/transform.rb +105 -0
  36. data/lib/bmg/sql/relation.rb +20 -6
  37. data/lib/bmg/summarizer.rb +36 -1
  38. data/lib/bmg/summarizer/avg.rb +3 -3
  39. data/lib/bmg/summarizer/by_proc.rb +41 -0
  40. data/lib/bmg/summarizer/distinct.rb +36 -0
  41. data/lib/bmg/summarizer/multiple.rb +46 -0
  42. data/lib/bmg/summarizer/percentile.rb +79 -0
  43. data/lib/bmg/summarizer/value_by.rb +62 -0
  44. data/lib/bmg/support/keys.rb +5 -0
  45. data/lib/bmg/support/tuple_transformer.rb +23 -1
  46. data/lib/bmg/type.rb +19 -1
  47. data/lib/bmg/version.rb +1 -1
  48. data/lib/bmg/writer.rb +16 -0
  49. data/lib/bmg/writer/csv.rb +2 -12
  50. data/lib/bmg/writer/xlsx.rb +68 -0
  51. metadata +25 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c9b490328160c9816102f7dd34b3ee46207ab4362cd2af6d8623c9fc5d4b87a
4
- data.tar.gz: d113dc14ae1811f2b5565af9e84a0ffbc82b7842c46284af7fcad3bc9f3b7470
3
+ metadata.gz: b7b4d39e83f04ee58369bef32ce396893d5ac98d357fd8c497d309fa17cc93b2
4
+ data.tar.gz: b36344887bb1142c4ddd3de0eb4419c0ba1821490a9c8c336668c37008e59156
5
5
  SHA512:
6
- metadata.gz: fd42b8787cc093c6452386760744d7480c64c8be186ab73b87a548a1b853643b46a6ad48cf019da9d77fddbb38c824eb0e0bef3ef5fa2f333f1d1240f5a0bd84
7
- data.tar.gz: 7bd0cd32a28963123b03b59152fa03d6470bbdf1a3c6cfe0b17a6667a80d97e65d5309def4e31ec9cbb47353d409ad9ad2a6d1fbc9c2ec10797460852836ce35
6
+ metadata.gz: c21cc2eb5c0e0e93cb8c4afc823855140051112f6ac5bd896181634edb67f87fca9b88f4a16c0ec70da36c8ce937e3265ade2506e7077f103e4fb46409b8dded
7
+ data.tar.gz: b40c206ad43a6ec36e4951c8ff8d531872154e0e855f055f62059ff3af9f0d35e7d96f2443e8046bd107741c4df481aa4ebc2b680ccf1fc88181b988add1d2d6
data/README.md CHANGED
@@ -234,7 +234,11 @@ t.transform(:to_s) # all-attrs transformation
234
234
  t.transform(&:to_s) # similar, but Proc-driven
235
235
  t.transform(:foo => :upcase, ...) # specific-attrs tranformation
236
236
  t.transform([:to_s, :upcase]) # chain-transformation
237
+ r.ungroup([:a, :b, ...]) # ungroup relation-valued attributes within parent tuple
238
+ r.ungroup(:a) # shortcut over ungroup([:a])
237
239
  r.union(right) # relational union
240
+ r.unwrap([:a, :b, ...]) # merge tuple-valued attributes within parent tuple
241
+ r.unwrap(:a) # shortcut over unwrap([:a])
238
242
  r.where(predicate) # alias for restrict(predicate)
239
243
  ```
240
244
 
data/lib/bmg/algebra.rb CHANGED
@@ -183,6 +183,15 @@ module Bmg
183
183
  end
184
184
  protected :_transform
185
185
 
186
+ def ungroup(attrs)
187
+ _ungroup self.type.ungroup(attrs), attrs
188
+ end
189
+
190
+ def _ungroup(type, attrs)
191
+ Operator::Ungroup.new(type, self, attrs)
192
+ end
193
+ protected :_ungroup
194
+
186
195
  def union(other, options = {})
187
196
  return self if other.is_a?(Relation::Empty)
188
197
  _union self.type.union(other.type), other, options
@@ -193,6 +202,15 @@ module Bmg
193
202
  end
194
203
  protected :_union
195
204
 
205
+ def unwrap(attrs)
206
+ _unwrap self.type.unwrap(attrs), attrs
207
+ end
208
+
209
+ def _unwrap(type, attrs)
210
+ Operator::Unwrap.new(type, self, attrs)
211
+ end
212
+ protected :_unwrap
213
+
196
214
  def spied(spy)
197
215
  return self if spy.nil?
198
216
  Relation::Spied.new(self, spy)
@@ -69,6 +69,14 @@ module Bmg
69
69
  self.not_matching(right.rename(renaming), on.keys)
70
70
  end
71
71
 
72
+ def ungroup(attr)
73
+ super(attr.is_a?(Symbol) ? [attr] : attr)
74
+ end
75
+
76
+ def unwrap(attr)
77
+ super(attr.is_a?(Symbol) ? [attr] : attr)
78
+ end
79
+
72
80
  end # module Shortcuts
73
81
  end # module Algebra
74
82
  end # module Bmg
data/lib/bmg/error.rb CHANGED
@@ -16,4 +16,7 @@ module Bmg
16
16
  # while unknown
17
17
  class UnknownAttributesError < Error; end
18
18
 
19
+ # Raised when an operator is badly used
20
+ class MisuseError < Error; end
21
+
19
22
  end
data/lib/bmg/operator.rb CHANGED
@@ -47,4 +47,6 @@ require_relative 'operator/restrict'
47
47
  require_relative 'operator/rxmatch'
48
48
  require_relative 'operator/summarize'
49
49
  require_relative 'operator/transform'
50
+ require_relative 'operator/ungroup'
50
51
  require_relative 'operator/union'
52
+ require_relative 'operator/unwrap'
@@ -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)
@@ -41,6 +41,7 @@ module Bmg
41
41
  end
42
42
 
43
43
  def each(&bl)
44
+ return to_enum unless block_given?
44
45
  h = {}
45
46
  @operand.each do |tuple|
46
47
  key = key(tuple)
@@ -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
@@ -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
@@ -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
@@ -32,6 +32,7 @@ module Bmg
32
32
  public
33
33
 
34
34
  def each(&bl)
35
+ return to_enum unless block_given?
35
36
  index = Hash.new{|h,k| h[k] = k.merge(as => empty_group) }
36
37
  operand.each do |tuple|
37
38
  key = TupleAlgebra.allbut(tuple, attrs)
@@ -26,7 +26,11 @@ module Bmg
26
26
  # resulting operabds. This option only applies when (optimized) `on`
27
27
  # contains one attribute only. ; it fallbacks on :index_right
28
28
  # otherwise.
29
- strategy: :refilter_right
29
+ strategy: :refilter_right,
30
+
31
+ # Whether the attributes on which the join is made should be kept
32
+ # in the result or not
33
+ preserve: false
30
34
 
31
35
  }
32
36
 
@@ -46,6 +50,7 @@ module Bmg
46
50
  public
47
51
 
48
52
  def each(*args, &bl)
53
+ return to_enum unless block_given?
49
54
  (options[:jit_optimized] ? self : jit_optimize)._each(*args, &bl)
50
55
  end
51
56
 
@@ -95,9 +100,10 @@ module Bmg
95
100
 
96
101
  def build_right_index(right)
97
102
  index = Hash.new{|h,k| h[k] = empty_image }
103
+ butlist = options[:preserve] ? [] : on
98
104
  right.each_with_object(index) do |t, index|
99
105
  key = tuple_project(t, on)
100
- index[key].operand << tuple_image(t, on)
106
+ index[key].operand << tuple_allbut(t, butlist)
101
107
  end
102
108
  if opt = options[:array]
103
109
  sorter = to_sorter(opt)
@@ -248,8 +254,8 @@ module Bmg
248
254
  TupleAlgebra.project(tuple, on)
249
255
  end
250
256
 
251
- def tuple_image(tuple, on)
252
- TupleAlgebra.allbut(tuple, on)
257
+ def tuple_allbut(tuple, butlist)
258
+ TupleAlgebra.allbut(tuple, butlist)
253
259
  end
254
260
 
255
261
  def image_type
@@ -25,6 +25,7 @@ module Bmg
25
25
  public
26
26
 
27
27
  def each
28
+ return to_enum unless block_given?
28
29
  index = Hash.new
29
30
  right.each_with_object(index) do |t, index|
30
31
  key = tuple_project(t, on)
@@ -23,6 +23,7 @@ module Bmg
23
23
  public
24
24
 
25
25
  def each
26
+ return to_enum unless block_given?
26
27
  index = Hash.new
27
28
  right.each_with_object(index) do |t, index|
28
29
  key = tuple_project(t, on)
@@ -23,6 +23,7 @@ module Bmg
23
23
  public
24
24
 
25
25
  def each
26
+ return to_enum unless block_given?
26
27
  index = Hash.new
27
28
  right.each_with_object(index) do |t, index|
28
29
  key = tuple_project(t, on)
@@ -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)
@@ -29,6 +29,7 @@ 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
35
  projected = tuple_project(tuple)
@@ -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 rename(tuple, renaming)
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(rename(arg, reverse_renaming))
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| rename(t, reverse_renaming) })
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(rename(arg, reverse_renaming))
50
+ when Hash then operand.update(rename_tuple(arg, reverse_renaming))
50
51
  else
51
52
  super
52
53
  end
@@ -88,7 +89,7 @@ module Bmg
88
89
 
89
90
  private
90
91
 
91
- def rename(tuple, renaming)
92
+ def rename_tuple(tuple, renaming)
92
93
  tuple.each_with_object({}){|(k,v),h|
93
94
  h[renaming[k] || k] = v
94
95
  h
@@ -26,6 +26,7 @@ module Bmg
26
26
  end
27
27
 
28
28
  def each
29
+ return to_enum unless block_given?
29
30
  @operand.each do |tuple|
30
31
  yield(tuple) if @predicate.evaluate(tuple)
31
32
  end
@@ -32,6 +32,7 @@ module Bmg
32
32
  public
33
33
 
34
34
  def each
35
+ return to_enum unless block_given?
35
36
  @operand.each do |tuple|
36
37
  against = attrs.map{|a| tuple[a] }.join(" ")
37
38
  matcher = self.matcher
@@ -13,7 +13,7 @@ module Bmg
13
13
  @type = type
14
14
  @operand = operand
15
15
  @by = by
16
- @summarization = Summarize.compile(summarization)
16
+ @summarization = Summarizer.summarization(summarization)
17
17
  end
18
18
 
19
19
  protected
@@ -23,6 +23,7 @@ module Bmg
23
23
  public
24
24
 
25
25
  def each
26
+ return to_enum unless block_given?
26
27
  # summary key => summarization memo, starting with least
27
28
  result = Hash.new{|h,k|
28
29
  h[k] = Hash[@summarization.map{|k,v|
@@ -56,22 +57,6 @@ module Bmg
56
57
  [ by, summarization ]
57
58
  end
58
59
 
59
- private
60
-
61
- # Compile a summarization hash so that every value is a Summarizer
62
- # instance
63
- def self.compile(summarization)
64
- Hash[summarization.map{|k,v|
65
- summarizer = case v
66
- when Summarizer then v
67
- when Symbol then Summarizer.send(v, k)
68
- else
69
- raise ArgumentError, "Unexpected summarizer #{k} => #{v}"
70
- end
71
- [ k, summarizer ]
72
- }]
73
- end
74
-
75
60
  end # class Summarize
76
61
  end # module Operator
77
62
  end # module Bmg
@@ -28,6 +28,7 @@ module Bmg
28
28
  public
29
29
 
30
30
  def each
31
+ return to_enum unless block_given?
31
32
  t = transformer
32
33
  @operand.each do |tuple|
33
34
  yield t.call(tuple)
@@ -0,0 +1,61 @@
1
+ module Bmg
2
+ module Operator
3
+ class Ungroup
4
+ include Operator::Unary
5
+
6
+ def initialize(type, operand, attrs)
7
+ @type = type
8
+ @operand = operand
9
+ @attrs = attrs
10
+ end
11
+
12
+ protected
13
+
14
+ attr_reader :attrs
15
+
16
+ public
17
+
18
+ def each(&bl)
19
+ return to_enum unless block_given?
20
+ if type.knows_keys? && type.keys.any?{|k| (k & attrs).empty? }
21
+ operand.each do |tuple|
22
+ _each(tuple, attrs[0], attrs[1..-1], &bl)
23
+ end
24
+ else
25
+ with_dups = []
26
+ operand.each do |tuple|
27
+ _each(tuple, attrs[0], attrs[1..-1]){|t|
28
+ with_dups << t
29
+ }
30
+ end
31
+ with_dups.uniq.each(&bl)
32
+ end
33
+ end
34
+
35
+ def _each(tuple, attr, attrs, &bl)
36
+ rva = tuple[attr] || []
37
+ rva.each do |rvt|
38
+ t = tuple.merge(rvt).tap{|t| t.delete(attr) }
39
+ if attrs.empty?
40
+ yield(t)
41
+ else
42
+ _each(t, attrs[0], attrs[1..-1], &bl)
43
+ end
44
+ end
45
+ end
46
+
47
+ def to_ast
48
+ [ :ungroup, operand.to_ast, attrs ]
49
+ end
50
+
51
+ protected
52
+
53
+ protected ### inspect
54
+
55
+ def args
56
+ [ attrs ]
57
+ end
58
+
59
+ end # class Ungroup
60
+ end # module Operator
61
+ end # module Bmg
@@ -37,6 +37,7 @@ module Bmg
37
37
  end
38
38
 
39
39
  def each(&bl)
40
+ return to_enum unless block_given?
40
41
  if all?
41
42
  operands.each do |op|
42
43
  op.each(&bl)
@@ -0,0 +1,47 @@
1
+ module Bmg
2
+ module Operator
3
+ class Unwrap
4
+ include Operator::Unary
5
+
6
+ def initialize(type, operand, attrs)
7
+ @type = type
8
+ @operand = operand
9
+ @attrs = attrs
10
+ end
11
+
12
+ protected
13
+
14
+ attr_reader :attrs
15
+
16
+ public
17
+
18
+ def each(&bl)
19
+ return to_enum unless block_given?
20
+ operand.each do |tuple|
21
+ yield tuple_unwrap(tuple)
22
+ end
23
+ end
24
+
25
+ def to_ast
26
+ [ :unwrap, operand.to_ast, attrs ]
27
+ end
28
+
29
+ protected
30
+
31
+ def tuple_unwrap(tuple)
32
+ attrs.inject(tuple.dup){|t,attr|
33
+ t.merge(tuple[attr]).tap{|t2|
34
+ t2.delete(attr)
35
+ }
36
+ }
37
+ end
38
+
39
+ protected ### inspect
40
+
41
+ def args
42
+ [ attrs ]
43
+ end
44
+
45
+ end # class Unwrap
46
+ end # module Operator
47
+ end # module Bmg