bmg 0.18.0 → 0.18.1

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