bmg 0.18.2 → 0.18.7

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