bmg 0.18.0 → 0.18.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f1ce59d00b630f644e5716eaff17a83116c1342ea0b6ba7d9174b1f5f4eadd6e
4
- data.tar.gz: 2156d1a8eb88999e749f434a8e94d2b4e70c636fadb10470493f19bb805a19a3
3
+ metadata.gz: 1e47d2972990cc85ae0a3b99fa6a79caf97176e46c7d70cdbbbb35ffdb3df21a
4
+ data.tar.gz: dd7ddf0c123a9347f517da44cc923ec9664c8a1fd12b9e8f0ed08677be2dcdd4
5
5
  SHA512:
6
- metadata.gz: 8e3e714d698ff7c47c2f61b4056c73acaa39983306402eeb54d1957b90959af51fcf20a543c5c17242d260fe835b33c19dd960e3cd4920a66d49ea81a22ee4b0
7
- data.tar.gz: 89fe1cc4c3157adf7373fb755e0cf7eb5dd8d93f7061558454d27649b44aca558f936f006e3238dce410ffdfe29821d59feac3b31b5d64241ffc76192bba149f
6
+ metadata.gz: 929f4c67a01d756b484e9ae27e5465173a4a1850686a173a8ab293dbe1e1ba01899c1ab21a8e2f29251378d0354287e379e7573ae551d3aef0583a0690640375
7
+ data.tar.gz: 3a92ab6c7708badf0464a94c496000eb55d233fb979bfd7128b71f3229347fa56c38be381815dbbc7eb0f741b58138f89551080e7670b3b044dfbba6571ac892
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] }]
@@ -63,12 +63,34 @@ module Bmg
63
63
 
64
64
  protected ### optimization
65
65
 
66
+ def _allbut(type, butlist)
67
+ operand.allbut(self.butlist|butlist)
68
+ end
69
+
70
+ def _matching(type, right, on)
71
+ # Always possible to push the matching, since by construction
72
+ # `on` can only use attributes that have not been trown away,
73
+ # hence they exist on `operand` too.
74
+ operand.matching(right, on).allbut(butlist)
75
+ end
76
+
66
77
  def _restrict(type, predicate)
67
78
  operand.restrict(predicate).allbut(butlist)
68
79
  end
69
80
 
81
+ def _page(type, ordering, page_index, options)
82
+ return super unless self.preserving_key?
83
+ operand.page(ordering, page_index, options).allbut(butlist)
84
+ end
85
+
70
86
  protected ### inspect
71
87
 
88
+ def preserving_key?
89
+ operand.type.knows_keys? && operand.type.keys.find{|k|
90
+ (k & butlist).empty?
91
+ }
92
+ end
93
+
72
94
  def args
73
95
  [ butlist ]
74
96
  end
@@ -24,6 +24,22 @@ 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)
28
44
  h = {}
29
45
  @operand.each do |tuple|
@@ -175,11 +191,11 @@ module Bmg
175
191
  end
176
192
 
177
193
  def init(v)
178
- [v]
194
+ v.nil? ? [] : [v]
179
195
  end
180
196
 
181
197
  def sum(v1, v2)
182
- v1 << v2
198
+ v2.nil? ? v1 : (v1 << v2)
183
199
  end
184
200
 
185
201
  def term(v)
@@ -211,11 +227,11 @@ module Bmg
211
227
  end
212
228
 
213
229
  def init(v)
214
- [v]
230
+ v.nil? ? [] : [v]
215
231
  end
216
232
 
217
233
  def sum(v1, v2)
218
- v1 << v2
234
+ v2.nil? ? v1 : (v1 << v2)
219
235
  end
220
236
 
221
237
  def term(v)
@@ -86,6 +86,14 @@ module Bmg
86
86
  false
87
87
  end
88
88
 
89
+ def _matching(type, right, on)
90
+ if (wrapped_roots! & on).empty?
91
+ operand.matching(right, on).autowrap(options)
92
+ else
93
+ super
94
+ end
95
+ end
96
+
89
97
  def _page(type, ordering, page_index, opts)
90
98
  attrs = ordering.map{|(a,d)| a }
91
99
  if (wrapped_roots! & attrs).empty?
@@ -99,9 +99,10 @@ module Bmg
99
99
  key = tuple_project(t, on)
100
100
  index[key].operand << tuple_image(t, on)
101
101
  end
102
- if options[:array]
102
+ if opt = options[:array]
103
+ sorter = to_sorter(opt)
103
104
  index = index.each_with_object({}) do |(k,v),ix|
104
- ix[k] = v.to_a
105
+ ix[k] = sorter ? v.to_a.sort(&sorter) : v.to_a
105
106
  end
106
107
  end
107
108
  index
@@ -156,6 +157,24 @@ module Bmg
156
157
 
157
158
  protected ### optimization
158
159
 
160
+ def _allbut(type, butlist)
161
+ if butlist.include?(as)
162
+ left.allbut(butlist - [as])
163
+ elsif (butlist & on).empty?
164
+ left.allbut(butlist).image(right, as, on, options)
165
+ else
166
+ super
167
+ end
168
+ end
169
+
170
+ def _matching(type, m_right, m_on)
171
+ if m_on.include?(as)
172
+ super
173
+ else
174
+ left.matching(m_right, m_on).image(right, as, on, options)
175
+ end
176
+ end
177
+
159
178
  def _page(type, ordering, page_index, opts)
160
179
  if ordering.map{|(k,v)| k}.include?(as)
161
180
  super
@@ -227,6 +246,11 @@ module Bmg
227
246
  Relation::InMemory.new(image_type, Set.new)
228
247
  end
229
248
 
249
+ def to_sorter(opt)
250
+ return nil unless opt.is_a?(Array)
251
+ Ordering.new(opt).comparator
252
+ end
253
+
230
254
  public
231
255
 
232
256
  def to_s
@@ -45,13 +45,7 @@ module Bmg
45
45
  protected ### inspect
46
46
 
47
47
  def comparator
48
- ->(t1, t2) {
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
- }
48
+ Ordering.new(@ordering).comparator
55
49
  end
56
50
 
57
51
  def args
@@ -23,7 +23,7 @@ module Bmg
23
23
 
24
24
  protected
25
25
 
26
- attr_reader :transformation
26
+ attr_reader :transformation, :options
27
27
 
28
28
  public
29
29
 
@@ -40,6 +40,43 @@ module Bmg
40
40
 
41
41
  protected ### optimization
42
42
 
43
+ def _allbut(type, butlist)
44
+ # `allbut` can always be pushed down the tree. unlike
45
+ # `extend` the Proc that might be used cannot use attributes
46
+ # in butlist, so it's safe to strip them away.
47
+ if transformer.knows_attrlist?
48
+ # We just need to clean the transformation
49
+ attrlist = transformer.to_attrlist
50
+ thrown = attrlist & butlist
51
+ t = transformation.dup.reject{|k,v| thrown.include?(k) }
52
+ operand.allbut(butlist).transform(t, options)
53
+ else
54
+ operand.allbut(butlist).transform(transformation, options)
55
+ end
56
+ end
57
+
58
+ def _project(type, attrlist)
59
+ if transformer.knows_attrlist?
60
+ t = transformation.dup.select{|k,v| attrlist.include?(k) }
61
+ operand.project(attrlist).transform(t, options)
62
+ else
63
+ operand.project(attrlist).transform(transformation, options)
64
+ end
65
+ end
66
+
67
+ def _restrict(type, predicate)
68
+ return super unless transformer.knows_attrlist?
69
+ top, bottom = predicate.and_split(transformer.to_attrlist)
70
+ if top == predicate
71
+ super
72
+ else
73
+ operand
74
+ .restrict(bottom)
75
+ .transform(transformation, options)
76
+ .restrict(top)
77
+ end
78
+ end
79
+
43
80
  protected ### inspect
44
81
 
45
82
  def args
@@ -10,7 +10,6 @@ module Bmg
10
10
  end
11
11
 
12
12
  attr_accessor :type
13
- protected :type=
14
13
 
15
14
  protected
16
15
 
data/lib/bmg/support.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require_relative 'support/tuple_algebra'
2
2
  require_relative 'support/tuple_transformer'
3
3
  require_relative 'support/keys'
4
+ require_relative 'support/ordering'
4
5
  require_relative 'support/output_preferences'
@@ -0,0 +1,20 @@
1
+ module Bmg
2
+ class Ordering
3
+
4
+ def initialize(attrs)
5
+ @attrs = attrs
6
+ end
7
+ attr_reader :attrs
8
+
9
+ def comparator
10
+ ->(t1, t2) {
11
+ attrs.each do |(attr,direction)|
12
+ c = t1[attr] <=> t2[attr]
13
+ return (direction == :desc ? -c : c) unless c==0
14
+ end
15
+ 0
16
+ }
17
+ end
18
+
19
+ end # class Ordering
20
+ end # module Bmg
data/lib/bmg/version.rb CHANGED
@@ -2,7 +2,7 @@ module Bmg
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 18
5
- TINY = 0
5
+ TINY = 1
6
6
  end
7
7
  VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::TINY}"
8
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bmg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.0
4
+ version: 0.18.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernard Lambeau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-12 00:00:00.000000000 Z
11
+ date: 2021-04-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: predicate
@@ -261,6 +261,7 @@ files:
261
261
  - lib/bmg/summarizer/variance.rb
262
262
  - lib/bmg/support.rb
263
263
  - lib/bmg/support/keys.rb
264
+ - lib/bmg/support/ordering.rb
264
265
  - lib/bmg/support/output_preferences.rb
265
266
  - lib/bmg/support/tuple_algebra.rb
266
267
  - lib/bmg/support/tuple_transformer.rb