bmg 0.24.0 → 1.0.0
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 +45 -2
- data/lib/bmg/operator/allbut.rb +1 -1
- data/lib/bmg/operator/autosummarize.rb +4 -6
- data/lib/bmg/operator/group.rb +5 -0
- data/lib/bmg/operator/image.rb +10 -10
- data/lib/bmg/operator/join.rb +5 -4
- data/lib/bmg/operator/matching.rb +5 -4
- data/lib/bmg/operator/not_matching.rb +5 -4
- data/lib/bmg/operator/project.rb +2 -1
- data/lib/bmg/operator/summarize.rb +2 -1
- data/lib/bmg/support/tuple_algebra.rb +18 -0
- data/lib/bmg/version.rb +2 -2
- data/lib/bmg.rb +0 -3
- metadata +76 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b73ed9026efe140b3d55eb59a1949db5fad0ac04ff401f3c44199d39274108ca
|
|
4
|
+
data.tar.gz: 1d375d5ca7638e43d21c6bc27a34b3df47f6947d7d853158fa0bdc90db0754cc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f55dba1dc2db2ef68beaf1d0f58c0c84fd2ff7c4bb2c1b883ad5726fcdd6b44588529f602876783d6d14823e3cb6494bb9335490c6b214cc725a1e55d93d4181
|
|
7
|
+
data.tar.gz: ba1fe4d29f70002410ddb0d7afe7fd63555a87746cbfac7c85bc1ca0c3af5c796a3f4245928e8c1f841dfc847ad375518728c1f3ad225c434bb2c8420f8e4a2b
|
data/README.md
CHANGED
|
@@ -31,6 +31,7 @@ further down this README.
|
|
|
31
31
|
* [How is this different?](#how-is-this-different)
|
|
32
32
|
* [... from similar libraries](#-from-similar-libraries)
|
|
33
33
|
* [... from Alf](#-from-alf)
|
|
34
|
+
* [Stability and versioning](#stability-and-versioning)
|
|
34
35
|
* [Contribute](#contribute)
|
|
35
36
|
* [License](#license)
|
|
36
37
|
|
|
@@ -202,7 +203,7 @@ documentation.
|
|
|
202
203
|
|
|
203
204
|
### Connecting to Redis databases
|
|
204
205
|
|
|
205
|
-
Bmg currently requires `bmg-redis` and `redis >= 4.
|
|
206
|
+
Bmg currently requires `bmg-redis` and `redis >= 4.0` to connect
|
|
206
207
|
to Redis databases. You also need to require `bmg/redis`.
|
|
207
208
|
|
|
208
209
|
```Gemfile
|
|
@@ -360,7 +361,7 @@ db.to_xlsx('path/to/file.xlsx')
|
|
|
360
361
|
```ruby
|
|
361
362
|
r.allbut([:a, :b, ...]) # remove specified attributes
|
|
362
363
|
r.autowrap(split: '_') # structure a flat relation, split: '_' is the default
|
|
363
|
-
r.autosummarize([:a, :b, ...], x: :sum) #
|
|
364
|
+
r.autosummarize([:a, :b, ...], x: :sum) # usual summarizers supported
|
|
364
365
|
r.constants(x: 12, ...) # add constant attributes (sometimes useful in unions)
|
|
365
366
|
r.cross_product(right) # cross product, alias `cross_join`
|
|
366
367
|
r.extend(x: ->(t){ ... }, ...) # add computed attributes
|
|
@@ -536,12 +537,54 @@ probably never be.
|
|
|
536
537
|
building an AST internally first. Strictly speaking this makes Bmg less
|
|
537
538
|
powerful than Alf since optimizations cannot be turned off for now.
|
|
538
539
|
|
|
540
|
+
## Stability and versioning
|
|
541
|
+
|
|
542
|
+
As of 1.0, Bmg follows [semantic versioning](https://semver.org). Breaking
|
|
543
|
+
changes to the API described below only happen on a major version.
|
|
544
|
+
|
|
545
|
+
The following is public, and covered by that promise:
|
|
546
|
+
|
|
547
|
+
* the factory methods on `Bmg` and `Bmg::Relation` (`in_memory`, `sequel`,
|
|
548
|
+
`csv`, `json`, `yaml`, `excel`, `text_file`, `generate`, `mutable`, ...);
|
|
549
|
+
* the relational operators listed under [Supported
|
|
550
|
+
operators](#supported-operators), their arguments and their documented
|
|
551
|
+
options;
|
|
552
|
+
* the predicates and summarizers listed under [Supported
|
|
553
|
+
predicates](#supported-predicates) and [Supported
|
|
554
|
+
summaries](#supported-summaries);
|
|
555
|
+
* `Bmg::Relation` as an interface to include, with `each` yielding symbolized
|
|
556
|
+
tuples, as shown in [Your own relations](#your-own-relations);
|
|
557
|
+
* `Bmg::Type`, `Bmg::Database`, and the reader/writer output preferences.
|
|
558
|
+
|
|
559
|
+
The following is explicitly *not* covered, and may change in a minor version:
|
|
560
|
+
|
|
561
|
+
* the underscored optimization hooks (`_restrict`, `_project`, ...). They are
|
|
562
|
+
documented in [Your own relations](#your-own-relations) because adapters
|
|
563
|
+
need them, but the protocol evolves as new optimizations are added. If you
|
|
564
|
+
override them, pin a minor version and read the CHANGELOG.
|
|
565
|
+
* the shape of the ASTs returned by `to_ast`, and the SQL actually generated
|
|
566
|
+
for a given query tree. Both are observable, and both are expected to
|
|
567
|
+
change as the compiler improves; only the *semantics* of a relation is
|
|
568
|
+
guaranteed.
|
|
569
|
+
* anything under `Bmg::Sql`, `Bmg::Sequel::Translator` and the sexpr grammar,
|
|
570
|
+
which are compiler internals.
|
|
571
|
+
|
|
539
572
|
## Contribute
|
|
540
573
|
|
|
541
574
|
Please use github issues and pull requests for all questions, bug reports,
|
|
542
575
|
and contributions. Don't hesitate to get in touch with us with an early code
|
|
543
576
|
spike if you plan to add non trivial features.
|
|
544
577
|
|
|
578
|
+
The `bench/` folder holds benchmarks for the in-memory operators and for the
|
|
579
|
+
SQL compiler. Run one with `bundle exec ruby bench/operators.rb`. To compare
|
|
580
|
+
two versions of the code, point `BMG_LIB` at another checkout and alternate
|
|
581
|
+
between the two — benchmarking both in one batch, then the other, mostly
|
|
582
|
+
measures how busy your machine was:
|
|
583
|
+
|
|
584
|
+
```
|
|
585
|
+
BMG_LIB=/path/to/other/lib bundle exec ruby bench/operators.rb
|
|
586
|
+
```
|
|
587
|
+
|
|
545
588
|
## Licence
|
|
546
589
|
|
|
547
590
|
This software is distributed by Enspirit SRL under a MIT Licence. Please
|
data/lib/bmg/operator/allbut.rb
CHANGED
|
@@ -5,9 +5,6 @@ module Bmg
|
|
|
5
5
|
#
|
|
6
6
|
# Autosummarize helps structuring the results of a big flat join.
|
|
7
7
|
#
|
|
8
|
-
# This operator is still largely experimental and should be used with
|
|
9
|
-
# care...
|
|
10
|
-
#
|
|
11
8
|
class Autosummarize
|
|
12
9
|
include Operator::Unary
|
|
13
10
|
|
|
@@ -294,10 +291,11 @@ module Bmg
|
|
|
294
291
|
v = v.reject{|tuple| tuple[@x].nil? }
|
|
295
292
|
v = v.sort(&@sorter) if @sorter
|
|
296
293
|
v.each do |tuple|
|
|
297
|
-
h[tuple[@x]] ||= []
|
|
298
|
-
h[tuple[@x]] << tuple[@y]
|
|
299
|
-
h[tuple[@x]].uniq!
|
|
294
|
+
(h[tuple[@x]] ||= []) << tuple[@y]
|
|
300
295
|
end
|
|
296
|
+
# deduplicating once at the end, instead of on every append,
|
|
297
|
+
# keeps this linear in the number of observed `y`s
|
|
298
|
+
h.each_value(&:uniq!)
|
|
301
299
|
h
|
|
302
300
|
end
|
|
303
301
|
|
data/lib/bmg/operator/group.rb
CHANGED
|
@@ -34,6 +34,7 @@ module Bmg
|
|
|
34
34
|
def each(&bl)
|
|
35
35
|
return to_enum unless block_given?
|
|
36
36
|
index = Hash.new{|h,k| h[k] = k.merge(as => empty_group) }
|
|
37
|
+
attrs = attrs_index
|
|
37
38
|
operand.each do |tuple|
|
|
38
39
|
key = TupleAlgebra.allbut(tuple, attrs)
|
|
39
40
|
sub = TupleAlgebra.project(tuple, attrs)
|
|
@@ -76,6 +77,10 @@ module Bmg
|
|
|
76
77
|
|
|
77
78
|
private
|
|
78
79
|
|
|
80
|
+
def attrs_index
|
|
81
|
+
@attrs_index ||= TupleAlgebra.membership(attrs)
|
|
82
|
+
end
|
|
83
|
+
|
|
79
84
|
def empty_group
|
|
80
85
|
Relation::InMemory.new(group_type, Set.new)
|
|
81
86
|
end
|
data/lib/bmg/operator/image.rb
CHANGED
|
@@ -34,6 +34,8 @@ module Bmg
|
|
|
34
34
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
EMPTY_BUTLIST = [].freeze
|
|
38
|
+
|
|
37
39
|
def initialize(type, left, right, as, on, options = {})
|
|
38
40
|
@type = type
|
|
39
41
|
@left = left
|
|
@@ -91,8 +93,9 @@ module Bmg
|
|
|
91
93
|
index = build_right_index(right_rel)
|
|
92
94
|
|
|
93
95
|
# each left with image from right index
|
|
96
|
+
on = on_index
|
|
94
97
|
left_rel.each do |tuple|
|
|
95
|
-
key =
|
|
98
|
+
key = TupleAlgebra.project(tuple, on)
|
|
96
99
|
image = index[key] || (options[:array] ? [] : empty_image)
|
|
97
100
|
yield tuple.merge(as => image)
|
|
98
101
|
end
|
|
@@ -100,10 +103,11 @@ module Bmg
|
|
|
100
103
|
|
|
101
104
|
def build_right_index(right)
|
|
102
105
|
index = Hash.new{|h,k| h[k] = empty_image }
|
|
103
|
-
|
|
106
|
+
on = on_index
|
|
107
|
+
butlist = options[:preserve] ? EMPTY_BUTLIST : on
|
|
104
108
|
right.each_with_object(index) do |t, index|
|
|
105
|
-
key =
|
|
106
|
-
index[key].operand <<
|
|
109
|
+
key = TupleAlgebra.project(t, on)
|
|
110
|
+
index[key].operand << TupleAlgebra.allbut(t, butlist)
|
|
107
111
|
end
|
|
108
112
|
if opt = options[:array]
|
|
109
113
|
sorter = to_sorter(opt)
|
|
@@ -252,12 +256,8 @@ module Bmg
|
|
|
252
256
|
|
|
253
257
|
private
|
|
254
258
|
|
|
255
|
-
def
|
|
256
|
-
TupleAlgebra.
|
|
257
|
-
end
|
|
258
|
-
|
|
259
|
-
def tuple_allbut(tuple, butlist)
|
|
260
|
-
TupleAlgebra.allbut(tuple, butlist)
|
|
259
|
+
def on_index
|
|
260
|
+
@on_index ||= TupleAlgebra.membership(on)
|
|
261
261
|
end
|
|
262
262
|
|
|
263
263
|
def image_type
|
data/lib/bmg/operator/join.rb
CHANGED
|
@@ -27,13 +27,14 @@ module Bmg
|
|
|
27
27
|
def each
|
|
28
28
|
return to_enum unless block_given?
|
|
29
29
|
index = Hash.new
|
|
30
|
+
on = on_index
|
|
30
31
|
right.each_with_object(index) do |t, index|
|
|
31
|
-
key =
|
|
32
|
+
key = TupleAlgebra.project(t, on)
|
|
32
33
|
index[key] ||= []
|
|
33
34
|
index[key] << t
|
|
34
35
|
end
|
|
35
36
|
left.each do |tuple|
|
|
36
|
-
key =
|
|
37
|
+
key = TupleAlgebra.project(tuple, on)
|
|
37
38
|
if to_join = index[key]
|
|
38
39
|
to_join.each do |right|
|
|
39
40
|
yield right.merge(tuple)
|
|
@@ -113,8 +114,8 @@ module Bmg
|
|
|
113
114
|
|
|
114
115
|
private
|
|
115
116
|
|
|
116
|
-
def
|
|
117
|
-
TupleAlgebra.
|
|
117
|
+
def on_index
|
|
118
|
+
@on_index ||= TupleAlgebra.membership(on)
|
|
118
119
|
end
|
|
119
120
|
|
|
120
121
|
end # class Join
|
|
@@ -25,12 +25,13 @@ module Bmg
|
|
|
25
25
|
def each
|
|
26
26
|
return to_enum unless block_given?
|
|
27
27
|
index = Hash.new
|
|
28
|
+
on = on_index
|
|
28
29
|
right.each_with_object(index) do |t, index|
|
|
29
|
-
key =
|
|
30
|
+
key = TupleAlgebra.project(t, on)
|
|
30
31
|
index[key] = true
|
|
31
32
|
end
|
|
32
33
|
left.each do |tuple|
|
|
33
|
-
key =
|
|
34
|
+
key = TupleAlgebra.project(tuple, on)
|
|
34
35
|
yield tuple if index.has_key?(key)
|
|
35
36
|
end
|
|
36
37
|
end
|
|
@@ -73,8 +74,8 @@ module Bmg
|
|
|
73
74
|
|
|
74
75
|
private
|
|
75
76
|
|
|
76
|
-
def
|
|
77
|
-
TupleAlgebra.
|
|
77
|
+
def on_index
|
|
78
|
+
@on_index ||= TupleAlgebra.membership(on)
|
|
78
79
|
end
|
|
79
80
|
|
|
80
81
|
end # class Matching
|
|
@@ -25,12 +25,13 @@ module Bmg
|
|
|
25
25
|
def each
|
|
26
26
|
return to_enum unless block_given?
|
|
27
27
|
index = Hash.new
|
|
28
|
+
on = on_index
|
|
28
29
|
right.each_with_object(index) do |t, index|
|
|
29
|
-
key =
|
|
30
|
+
key = TupleAlgebra.project(t, on)
|
|
30
31
|
index[key] = true
|
|
31
32
|
end
|
|
32
33
|
left.each do |tuple|
|
|
33
|
-
key =
|
|
34
|
+
key = TupleAlgebra.project(tuple, on)
|
|
34
35
|
yield tuple unless index.has_key?(key)
|
|
35
36
|
end
|
|
36
37
|
end
|
|
@@ -57,8 +58,8 @@ module Bmg
|
|
|
57
58
|
|
|
58
59
|
private
|
|
59
60
|
|
|
60
|
-
def
|
|
61
|
-
TupleAlgebra.
|
|
61
|
+
def on_index
|
|
62
|
+
@on_index ||= TupleAlgebra.membership(on)
|
|
62
63
|
end
|
|
63
64
|
|
|
64
65
|
end # class NotMatching
|
data/lib/bmg/operator/project.rb
CHANGED
|
@@ -80,7 +80,8 @@ module Bmg
|
|
|
80
80
|
private
|
|
81
81
|
|
|
82
82
|
def tuple_project(tuple)
|
|
83
|
-
|
|
83
|
+
attrs = (@attrs_index ||= TupleAlgebra.membership(@attrlist))
|
|
84
|
+
tuple.dup.delete_if{|k,_| !attrs.include?(k) }
|
|
84
85
|
end
|
|
85
86
|
|
|
86
87
|
def valid_tuple!(tuple)
|
|
@@ -51,8 +51,9 @@ module Bmg
|
|
|
51
51
|
}]
|
|
52
52
|
}
|
|
53
53
|
# iterate each tuple
|
|
54
|
+
by_index = TupleAlgebra.membership(@by)
|
|
54
55
|
@operand.each do |tuple|
|
|
55
|
-
key = TupleAlgebra.project(tuple,
|
|
56
|
+
key = TupleAlgebra.project(tuple, by_index)
|
|
56
57
|
# apply them all and create a new memo
|
|
57
58
|
result[key] = Hash[@summarization.map{|k,v|
|
|
58
59
|
[ k, v.happens(result[key][k], tuple) ]
|
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
module Bmg
|
|
2
|
+
#
|
|
3
|
+
# Tuple-level counterparts of the relational operators.
|
|
4
|
+
#
|
|
2
5
|
module TupleAlgebra
|
|
3
6
|
|
|
7
|
+
# `allbut` and `project` below test every attribute of every tuple for
|
|
8
|
+
# membership in an attribute list, so the cost of that lookup is paid
|
|
9
|
+
# `tuples x attributes` times. Converting the list to a Set is worth it,
|
|
10
|
+
# but only past a few elements: below that an Array scan wins, on every
|
|
11
|
+
# ruby (measured in bench/set_vs_array.rb). Join keys, in particular,
|
|
12
|
+
# are usually one or two attributes and are better left alone.
|
|
13
|
+
#
|
|
14
|
+
# Callers that iterate are expected to hoist this out of their loop.
|
|
15
|
+
SET_FROM = 3
|
|
16
|
+
|
|
17
|
+
def membership(attrlist)
|
|
18
|
+
attrlist.size < SET_FROM ? attrlist : attrlist.to_set
|
|
19
|
+
end
|
|
20
|
+
module_function :membership
|
|
21
|
+
|
|
4
22
|
def allbut(tuple, butlist)
|
|
5
23
|
tuple.reject{|k,v| butlist.include?(k) }
|
|
6
24
|
end
|
data/lib/bmg/version.rb
CHANGED
data/lib/bmg.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bmg
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bernard Lambeau
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: predicate
|
|
@@ -37,6 +36,9 @@ dependencies:
|
|
|
37
36
|
- - ">="
|
|
38
37
|
- !ruby/object:Gem::Version
|
|
39
38
|
version: '2.0'
|
|
39
|
+
- - "<"
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '3.0'
|
|
40
42
|
type: :runtime
|
|
41
43
|
prerelease: false
|
|
42
44
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -44,6 +46,9 @@ dependencies:
|
|
|
44
46
|
- - ">="
|
|
45
47
|
- !ruby/object:Gem::Version
|
|
46
48
|
version: '2.0'
|
|
49
|
+
- - "<"
|
|
50
|
+
- !ruby/object:Gem::Version
|
|
51
|
+
version: '3.0'
|
|
47
52
|
- !ruby/object:Gem::Dependency
|
|
48
53
|
name: rake
|
|
49
54
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -79,6 +84,9 @@ dependencies:
|
|
|
79
84
|
- - ">="
|
|
80
85
|
- !ruby/object:Gem::Version
|
|
81
86
|
version: '2.8'
|
|
87
|
+
- - "<"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '4.0'
|
|
82
90
|
type: :development
|
|
83
91
|
prerelease: false
|
|
84
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -86,6 +94,9 @@ dependencies:
|
|
|
86
94
|
- - ">="
|
|
87
95
|
- !ruby/object:Gem::Version
|
|
88
96
|
version: '2.8'
|
|
97
|
+
- - "<"
|
|
98
|
+
- !ruby/object:Gem::Version
|
|
99
|
+
version: '4.0'
|
|
89
100
|
- !ruby/object:Gem::Dependency
|
|
90
101
|
name: write_xlsx
|
|
91
102
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -104,44 +115,90 @@ dependencies:
|
|
|
104
115
|
name: sequel
|
|
105
116
|
requirement: !ruby/object:Gem::Requirement
|
|
106
117
|
requirements:
|
|
107
|
-
- - "
|
|
118
|
+
- - "~>"
|
|
108
119
|
- !ruby/object:Gem::Version
|
|
109
|
-
version: '0'
|
|
120
|
+
version: '5.0'
|
|
110
121
|
type: :development
|
|
111
122
|
prerelease: false
|
|
112
123
|
version_requirements: !ruby/object:Gem::Requirement
|
|
113
124
|
requirements:
|
|
114
|
-
- - "
|
|
125
|
+
- - "~>"
|
|
115
126
|
- !ruby/object:Gem::Version
|
|
116
|
-
version: '0'
|
|
127
|
+
version: '5.0'
|
|
117
128
|
- !ruby/object:Gem::Dependency
|
|
118
129
|
name: sqlite3
|
|
119
130
|
requirement: !ruby/object:Gem::Requirement
|
|
120
131
|
requirements:
|
|
121
132
|
- - ">="
|
|
122
133
|
- !ruby/object:Gem::Version
|
|
123
|
-
version: '
|
|
134
|
+
version: '1.4'
|
|
135
|
+
- - "<"
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: '3.0'
|
|
124
138
|
type: :development
|
|
125
139
|
prerelease: false
|
|
126
140
|
version_requirements: !ruby/object:Gem::Requirement
|
|
127
141
|
requirements:
|
|
128
142
|
- - ">="
|
|
129
143
|
- !ruby/object:Gem::Version
|
|
130
|
-
version: '
|
|
144
|
+
version: '1.4'
|
|
145
|
+
- - "<"
|
|
146
|
+
- !ruby/object:Gem::Version
|
|
147
|
+
version: '3.0'
|
|
131
148
|
- !ruby/object:Gem::Dependency
|
|
132
149
|
name: activesupport
|
|
133
150
|
requirement: !ruby/object:Gem::Requirement
|
|
134
151
|
requirements:
|
|
135
152
|
- - ">="
|
|
136
153
|
- !ruby/object:Gem::Version
|
|
137
|
-
version: '0'
|
|
154
|
+
version: '6.0'
|
|
155
|
+
- - "<"
|
|
156
|
+
- !ruby/object:Gem::Version
|
|
157
|
+
version: '9.0'
|
|
138
158
|
type: :development
|
|
139
159
|
prerelease: false
|
|
140
160
|
version_requirements: !ruby/object:Gem::Requirement
|
|
141
161
|
requirements:
|
|
142
162
|
- - ">="
|
|
143
163
|
- !ruby/object:Gem::Version
|
|
144
|
-
version: '0'
|
|
164
|
+
version: '6.0'
|
|
165
|
+
- - "<"
|
|
166
|
+
- !ruby/object:Gem::Version
|
|
167
|
+
version: '9.0'
|
|
168
|
+
- !ruby/object:Gem::Dependency
|
|
169
|
+
name: ostruct
|
|
170
|
+
requirement: !ruby/object:Gem::Requirement
|
|
171
|
+
requirements:
|
|
172
|
+
- - ">="
|
|
173
|
+
- !ruby/object:Gem::Version
|
|
174
|
+
version: '0.2'
|
|
175
|
+
- - "<"
|
|
176
|
+
- !ruby/object:Gem::Version
|
|
177
|
+
version: '1.0'
|
|
178
|
+
type: :development
|
|
179
|
+
prerelease: false
|
|
180
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
181
|
+
requirements:
|
|
182
|
+
- - ">="
|
|
183
|
+
- !ruby/object:Gem::Version
|
|
184
|
+
version: '0.2'
|
|
185
|
+
- - "<"
|
|
186
|
+
- !ruby/object:Gem::Version
|
|
187
|
+
version: '1.0'
|
|
188
|
+
- !ruby/object:Gem::Dependency
|
|
189
|
+
name: benchmark-ips
|
|
190
|
+
requirement: !ruby/object:Gem::Requirement
|
|
191
|
+
requirements:
|
|
192
|
+
- - "~>"
|
|
193
|
+
- !ruby/object:Gem::Version
|
|
194
|
+
version: '2.14'
|
|
195
|
+
type: :development
|
|
196
|
+
prerelease: false
|
|
197
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
198
|
+
requirements:
|
|
199
|
+
- - "~>"
|
|
200
|
+
- !ruby/object:Gem::Version
|
|
201
|
+
version: '2.14'
|
|
145
202
|
description: Bmg is Alf's relational algebra for ruby, but much simpler and lighter
|
|
146
203
|
than Alf itself
|
|
147
204
|
email: blambeau@gmail.com
|
|
@@ -329,11 +386,14 @@ files:
|
|
|
329
386
|
- lib/bmg/xlsx.rb
|
|
330
387
|
- tasks/gem.rake
|
|
331
388
|
- tasks/test.rake
|
|
332
|
-
homepage:
|
|
389
|
+
homepage: https://github.com/enspirit/bmg
|
|
333
390
|
licenses:
|
|
334
391
|
- MIT
|
|
335
|
-
metadata:
|
|
336
|
-
|
|
392
|
+
metadata:
|
|
393
|
+
source_code_uri: https://github.com/enspirit/bmg
|
|
394
|
+
changelog_uri: https://github.com/enspirit/bmg/blob/master/CHANGELOG.md
|
|
395
|
+
bug_tracker_uri: https://github.com/enspirit/bmg/issues
|
|
396
|
+
documentation_uri: https://www.relational-algebra.dev/
|
|
337
397
|
rdoc_options: []
|
|
338
398
|
require_paths:
|
|
339
399
|
- lib
|
|
@@ -341,15 +401,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
341
401
|
requirements:
|
|
342
402
|
- - ">="
|
|
343
403
|
- !ruby/object:Gem::Version
|
|
344
|
-
version: '
|
|
404
|
+
version: '2.7'
|
|
345
405
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
346
406
|
requirements:
|
|
347
407
|
- - ">="
|
|
348
408
|
- !ruby/object:Gem::Version
|
|
349
409
|
version: '0'
|
|
350
410
|
requirements: []
|
|
351
|
-
rubygems_version: 3.
|
|
352
|
-
signing_key:
|
|
411
|
+
rubygems_version: 3.6.9
|
|
353
412
|
specification_version: 4
|
|
354
413
|
summary: Bmg is Alf's successor.
|
|
355
414
|
test_files: []
|