bmg 0.17.5 → 0.17.6
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 +4 -4
- data/README.md +4 -0
- data/lib/bmg.rb +1 -0
- data/lib/bmg/algebra.rb +10 -0
- data/lib/bmg/operator.rb +1 -0
- data/lib/bmg/operator/transform.rb +57 -0
- data/lib/bmg/relation/proxy.rb +63 -0
- data/lib/bmg/support.rb +1 -0
- data/lib/bmg/support/keys.rb +4 -0
- data/lib/bmg/support/tuple_transformer.rb +62 -0
- data/lib/bmg/type.rb +25 -0
- data/lib/bmg/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e67d11656619195bfaa20a9d55fff49d593ccaa3ad558d0876c82534977d4e04
|
4
|
+
data.tar.gz: 7ecd9b926d4289feb0fec3efcafcf7b14c483b70f8c4e47b87e3ba038db64774
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d99c96391c73c096e3e981155cbe53e637c909854a0e3fe92bae991eb7da1be7cf78188c87f9fb53cdbb90e5dd0d92b4fec0501f8d1fcf7f1cdb1900828d575
|
7
|
+
data.tar.gz: f8ff33a830852b1e0c5648596ef5f11cae7fc5f7bd817c1ed30a73ce3da81a92bfb42871eecd928a3ce7b717499fb9a975ee8f174a1b013054af506ed056b825
|
data/README.md
CHANGED
@@ -132,6 +132,10 @@ r.restrict(a: "foo", b: "bar", ...) # relational restriction, aka where
|
|
132
132
|
r.rxmatch([:a, :b, ...], /xxx/) # regex match kind of restriction
|
133
133
|
r.summarize([:a, :b, ...], x: :sum) # relational summarization
|
134
134
|
r.suffix(:_foo, but: [:a, ...]) # suffix kind of renaming
|
135
|
+
t.transform(:to_s) # all-attrs transformation
|
136
|
+
t.transform(&:to_s) # similar, but Proc-driven
|
137
|
+
t.transform(:foo => :upcase, ...) # specific-attrs tranformation
|
138
|
+
t.transform([:to_s, :upcase]) # chain-transformation
|
135
139
|
r.union(right) # relational union
|
136
140
|
```
|
137
141
|
|
data/lib/bmg.rb
CHANGED
data/lib/bmg/algebra.rb
CHANGED
@@ -172,6 +172,16 @@ module Bmg
|
|
172
172
|
end
|
173
173
|
protected :_summarize
|
174
174
|
|
175
|
+
def transform(transformation = nil, options = {}, &proc)
|
176
|
+
transformation, options = proc, (transformation || {}) unless proc.nil?
|
177
|
+
_transform(self.type.transform(transformation, options), transformation, options)
|
178
|
+
end
|
179
|
+
|
180
|
+
def _transform(type, transformation, options)
|
181
|
+
Operator::Transform.new(type, self, transformation, options)
|
182
|
+
end
|
183
|
+
protected :_transform
|
184
|
+
|
175
185
|
def union(other, options = {})
|
176
186
|
return self if other.is_a?(Relation::Empty)
|
177
187
|
_union self.type.union(other.type), other, options
|
data/lib/bmg/operator.rb
CHANGED
@@ -0,0 +1,57 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Operator
|
3
|
+
#
|
4
|
+
# Transform operator.
|
5
|
+
#
|
6
|
+
# Transforms existing attributes through computations
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
#
|
10
|
+
# [{ a: 1 }] transform { a: ->(t){ t[:a]*2 } } => [{ a: 4 }]
|
11
|
+
#
|
12
|
+
class Transform
|
13
|
+
include Operator::Unary
|
14
|
+
|
15
|
+
DEFAULT_OPTIONS = {}
|
16
|
+
|
17
|
+
def initialize(type, operand, transformation, options = {})
|
18
|
+
@type = type
|
19
|
+
@operand = operand
|
20
|
+
@transformation = transformation
|
21
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
attr_reader :transformation
|
27
|
+
|
28
|
+
public
|
29
|
+
|
30
|
+
def each
|
31
|
+
t = transformer
|
32
|
+
@operand.each do |tuple|
|
33
|
+
yield t.call(tuple)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_ast
|
38
|
+
[ :transform, operand.to_ast, transformation.dup ]
|
39
|
+
end
|
40
|
+
|
41
|
+
protected ### optimization
|
42
|
+
|
43
|
+
protected ### inspect
|
44
|
+
|
45
|
+
def args
|
46
|
+
[ transformation ]
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def transformer
|
52
|
+
@transformer ||= TupleTransformer.new(transformation)
|
53
|
+
end
|
54
|
+
|
55
|
+
end # class Transform
|
56
|
+
end # module Operator
|
57
|
+
end # module Bmg
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Relation
|
3
|
+
#
|
4
|
+
# This module can be used to create typed collection on top
|
5
|
+
# of Bmg relations. Algebra methods will be delegated to the
|
6
|
+
# decorated relation, and results wrapped in a new instance
|
7
|
+
# of the class.
|
8
|
+
#
|
9
|
+
module Proxy
|
10
|
+
|
11
|
+
def initialize(relation)
|
12
|
+
@relation = relation
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_missing(name, *args, &bl)
|
16
|
+
if @relation.respond_to?(name)
|
17
|
+
res = @relation.send(name, *args, &bl)
|
18
|
+
res.is_a?(Relation) ? _proxy(res) : res
|
19
|
+
else
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def respond_to?(name, *args)
|
25
|
+
@relation.respond_to?(name) || super
|
26
|
+
end
|
27
|
+
|
28
|
+
[
|
29
|
+
:extend
|
30
|
+
].each do |name|
|
31
|
+
define_method(name) do |*args, &bl|
|
32
|
+
res = @relation.send(name, *args, &bl)
|
33
|
+
res.is_a?(Relation) ? _proxy(res) : res
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
[
|
38
|
+
:one,
|
39
|
+
:one_or_nil
|
40
|
+
].each do |meth|
|
41
|
+
define_method(meth) do |*args, &bl|
|
42
|
+
res = @relation.send(meth, *args, &bl)
|
43
|
+
res.nil? ? nil : _proxy_tuple(res)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_json(*args, &bl)
|
48
|
+
@relation.to_json(*args, &bl)
|
49
|
+
end
|
50
|
+
|
51
|
+
protected
|
52
|
+
|
53
|
+
def _proxy(relation)
|
54
|
+
self.class.new(relation)
|
55
|
+
end
|
56
|
+
|
57
|
+
def _proxy_tuple(tuple)
|
58
|
+
tuple
|
59
|
+
end
|
60
|
+
|
61
|
+
end # module Proxy
|
62
|
+
end # class Relation
|
63
|
+
end # module Bmg
|
data/lib/bmg/support.rb
CHANGED
data/lib/bmg/support/keys.rb
CHANGED
@@ -0,0 +1,62 @@
|
|
1
|
+
module Bmg
|
2
|
+
class TupleTransformer
|
3
|
+
|
4
|
+
def initialize(transformation)
|
5
|
+
@transformation = transformation
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.new(arg)
|
9
|
+
return arg if arg.is_a?(TupleTransformer)
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(tuple)
|
14
|
+
transform_tuple(tuple, @transformation)
|
15
|
+
end
|
16
|
+
|
17
|
+
def knows_attrlist?
|
18
|
+
@transformation.is_a?(Hash)
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_attrlist
|
22
|
+
@transformation.keys
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def transform_tuple(tuple, with)
|
28
|
+
case with
|
29
|
+
when Symbol
|
30
|
+
tuple.each_with_object({}){|(k,v),dup|
|
31
|
+
dup[k] = transform_attr(v, with)
|
32
|
+
}
|
33
|
+
when Proc
|
34
|
+
tuple.each_with_object({}){|(k,v),dup|
|
35
|
+
dup[k] = transform_attr(v, with)
|
36
|
+
}
|
37
|
+
when Hash
|
38
|
+
with.each_with_object(tuple.dup){|(k,v),dup|
|
39
|
+
dup[k] = transform_attr(dup[k], v)
|
40
|
+
}
|
41
|
+
when Array
|
42
|
+
with.inject(tuple){|dup,on|
|
43
|
+
transform_tuple(dup, on)
|
44
|
+
}
|
45
|
+
else
|
46
|
+
raise ArgumentError, "Unexpected transformation `#{with.inspect}`"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def transform_attr(value, with)
|
51
|
+
case with
|
52
|
+
when Symbol
|
53
|
+
value.send(with)
|
54
|
+
when Proc
|
55
|
+
with.call(value)
|
56
|
+
else
|
57
|
+
raise ArgumentError, "Unexpected transformation `#{with.inspect}`"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end # module TupleTransformer
|
62
|
+
end # module Bmg
|
data/lib/bmg/type.rb
CHANGED
@@ -241,6 +241,31 @@ module Bmg
|
|
241
241
|
}
|
242
242
|
end
|
243
243
|
|
244
|
+
def transform(transformation, options = {})
|
245
|
+
transformer = TupleTransformer.new(transformation)
|
246
|
+
if typechecked? && knows_attrlist? && transformer.knows_attrlist?
|
247
|
+
known_attributes!(transformer.to_attrlist)
|
248
|
+
end
|
249
|
+
keys = if options[:key_preserving]
|
250
|
+
self._keys
|
251
|
+
elsif transformer.knows_attrlist? && knows_keys?
|
252
|
+
touched_attrs = transformer.to_attrlist
|
253
|
+
keys = self._keys.select{|k| (k & touched_attrs).empty? }
|
254
|
+
else
|
255
|
+
nil
|
256
|
+
end
|
257
|
+
pred = if transformer.knows_attrlist?
|
258
|
+
attr_list = transformer.to_attrlist
|
259
|
+
predicate.and_split(attr_list).last
|
260
|
+
else
|
261
|
+
Predicate.tautology
|
262
|
+
end
|
263
|
+
dup.tap{|x|
|
264
|
+
x.keys = keys
|
265
|
+
x.predicate = pred
|
266
|
+
}
|
267
|
+
end
|
268
|
+
|
244
269
|
def union(other)
|
245
270
|
if typechecked? && knows_attrlist? && other.knows_attrlist?
|
246
271
|
missing = self.attrlist - other.attrlist
|
data/lib/bmg/version.rb
CHANGED
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.17.
|
4
|
+
version: 0.17.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bernard Lambeau
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-08-
|
11
|
+
date: 2020-08-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: predicate
|
@@ -149,6 +149,7 @@ files:
|
|
149
149
|
- lib/bmg/operator/shared/nary.rb
|
150
150
|
- lib/bmg/operator/shared/unary.rb
|
151
151
|
- lib/bmg/operator/summarize.rb
|
152
|
+
- lib/bmg/operator/transform.rb
|
152
153
|
- lib/bmg/operator/union.rb
|
153
154
|
- lib/bmg/reader.rb
|
154
155
|
- lib/bmg/reader/csv.rb
|
@@ -157,6 +158,7 @@ files:
|
|
157
158
|
- lib/bmg/relation/empty.rb
|
158
159
|
- lib/bmg/relation/in_memory.rb
|
159
160
|
- lib/bmg/relation/materialized.rb
|
161
|
+
- lib/bmg/relation/proxy.rb
|
160
162
|
- lib/bmg/relation/spied.rb
|
161
163
|
- lib/bmg/sequel.rb
|
162
164
|
- lib/bmg/sequel/ext.rb
|
@@ -259,6 +261,7 @@ files:
|
|
259
261
|
- lib/bmg/support.rb
|
260
262
|
- lib/bmg/support/keys.rb
|
261
263
|
- lib/bmg/support/tuple_algebra.rb
|
264
|
+
- lib/bmg/support/tuple_transformer.rb
|
262
265
|
- lib/bmg/type.rb
|
263
266
|
- lib/bmg/version.rb
|
264
267
|
- lib/bmg/writer.rb
|