bmg 0.24.1 → 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/sql/processor/join.rb +1 -15
- data/lib/bmg/support/tuple_algebra.rb +18 -0
- data/lib/bmg/version.rb +3 -3
- data/lib/bmg.rb +0 -3
- metadata +76 -14
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) ]
|
|
@@ -15,7 +15,7 @@ module Bmg
|
|
|
15
15
|
def call(sexpr)
|
|
16
16
|
if unjoinable?(sexpr)
|
|
17
17
|
call(builder.from_self(sexpr))
|
|
18
|
-
elsif unjoinable?(right)
|
|
18
|
+
elsif unjoinable?(right)
|
|
19
19
|
Join.new(builder.from_self(right), on, options, builder).call(sexpr)
|
|
20
20
|
else
|
|
21
21
|
super(sexpr)
|
|
@@ -37,20 +37,6 @@ module Bmg
|
|
|
37
37
|
sexpr.set_operator? or sexpr.limit_or_offset? or sexpr.group_by?
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
# A restriction carried by the right operand of a left join may not be
|
|
41
|
-
# merged into the WHERE of the whole expression: there it would also
|
|
42
|
-
# have to hold of the tuples the left join fills with nulls, which is an
|
|
43
|
-
# inner join and loses exactly what the left join is for. Kept inside a
|
|
44
|
-
# derived table instead, where it applies to the right operand alone.
|
|
45
|
-
#
|
|
46
|
-
# The join condition would hold it just as well, and with less SQL, but
|
|
47
|
-
# it is the one place a restriction may be anything -- `>`, `IN`, a
|
|
48
|
-
# negation -- while the from clause orderer models a join condition as
|
|
49
|
-
# equalities between two qualified names.
|
|
50
|
-
def left_join_over_restricted_right?
|
|
51
|
-
left_join? && !right.select_exp.predicate.nil?
|
|
52
|
-
end
|
|
53
|
-
|
|
54
40
|
def join_set_quantifiers(left, right)
|
|
55
41
|
left_q, right_q = left.set_quantifier, right.set_quantifier
|
|
56
42
|
left_q == right_q ? left_q : builder.distinct
|
|
@@ -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,13 +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
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: predicate
|
|
@@ -36,6 +36,9 @@ dependencies:
|
|
|
36
36
|
- - ">="
|
|
37
37
|
- !ruby/object:Gem::Version
|
|
38
38
|
version: '2.0'
|
|
39
|
+
- - "<"
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '3.0'
|
|
39
42
|
type: :runtime
|
|
40
43
|
prerelease: false
|
|
41
44
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -43,6 +46,9 @@ dependencies:
|
|
|
43
46
|
- - ">="
|
|
44
47
|
- !ruby/object:Gem::Version
|
|
45
48
|
version: '2.0'
|
|
49
|
+
- - "<"
|
|
50
|
+
- !ruby/object:Gem::Version
|
|
51
|
+
version: '3.0'
|
|
46
52
|
- !ruby/object:Gem::Dependency
|
|
47
53
|
name: rake
|
|
48
54
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -78,6 +84,9 @@ dependencies:
|
|
|
78
84
|
- - ">="
|
|
79
85
|
- !ruby/object:Gem::Version
|
|
80
86
|
version: '2.8'
|
|
87
|
+
- - "<"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '4.0'
|
|
81
90
|
type: :development
|
|
82
91
|
prerelease: false
|
|
83
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -85,6 +94,9 @@ dependencies:
|
|
|
85
94
|
- - ">="
|
|
86
95
|
- !ruby/object:Gem::Version
|
|
87
96
|
version: '2.8'
|
|
97
|
+
- - "<"
|
|
98
|
+
- !ruby/object:Gem::Version
|
|
99
|
+
version: '4.0'
|
|
88
100
|
- !ruby/object:Gem::Dependency
|
|
89
101
|
name: write_xlsx
|
|
90
102
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -103,44 +115,90 @@ dependencies:
|
|
|
103
115
|
name: sequel
|
|
104
116
|
requirement: !ruby/object:Gem::Requirement
|
|
105
117
|
requirements:
|
|
106
|
-
- - "
|
|
118
|
+
- - "~>"
|
|
107
119
|
- !ruby/object:Gem::Version
|
|
108
|
-
version: '0'
|
|
120
|
+
version: '5.0'
|
|
109
121
|
type: :development
|
|
110
122
|
prerelease: false
|
|
111
123
|
version_requirements: !ruby/object:Gem::Requirement
|
|
112
124
|
requirements:
|
|
113
|
-
- - "
|
|
125
|
+
- - "~>"
|
|
114
126
|
- !ruby/object:Gem::Version
|
|
115
|
-
version: '0'
|
|
127
|
+
version: '5.0'
|
|
116
128
|
- !ruby/object:Gem::Dependency
|
|
117
129
|
name: sqlite3
|
|
118
130
|
requirement: !ruby/object:Gem::Requirement
|
|
119
131
|
requirements:
|
|
120
132
|
- - ">="
|
|
121
133
|
- !ruby/object:Gem::Version
|
|
122
|
-
version: '
|
|
134
|
+
version: '1.4'
|
|
135
|
+
- - "<"
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: '3.0'
|
|
123
138
|
type: :development
|
|
124
139
|
prerelease: false
|
|
125
140
|
version_requirements: !ruby/object:Gem::Requirement
|
|
126
141
|
requirements:
|
|
127
142
|
- - ">="
|
|
128
143
|
- !ruby/object:Gem::Version
|
|
129
|
-
version: '
|
|
144
|
+
version: '1.4'
|
|
145
|
+
- - "<"
|
|
146
|
+
- !ruby/object:Gem::Version
|
|
147
|
+
version: '3.0'
|
|
130
148
|
- !ruby/object:Gem::Dependency
|
|
131
149
|
name: activesupport
|
|
132
150
|
requirement: !ruby/object:Gem::Requirement
|
|
133
151
|
requirements:
|
|
134
152
|
- - ">="
|
|
135
153
|
- !ruby/object:Gem::Version
|
|
136
|
-
version: '0'
|
|
154
|
+
version: '6.0'
|
|
155
|
+
- - "<"
|
|
156
|
+
- !ruby/object:Gem::Version
|
|
157
|
+
version: '9.0'
|
|
137
158
|
type: :development
|
|
138
159
|
prerelease: false
|
|
139
160
|
version_requirements: !ruby/object:Gem::Requirement
|
|
140
161
|
requirements:
|
|
141
162
|
- - ">="
|
|
142
163
|
- !ruby/object:Gem::Version
|
|
143
|
-
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'
|
|
144
202
|
description: Bmg is Alf's relational algebra for ruby, but much simpler and lighter
|
|
145
203
|
than Alf itself
|
|
146
204
|
email: blambeau@gmail.com
|
|
@@ -328,10 +386,14 @@ files:
|
|
|
328
386
|
- lib/bmg/xlsx.rb
|
|
329
387
|
- tasks/gem.rake
|
|
330
388
|
- tasks/test.rake
|
|
331
|
-
homepage:
|
|
389
|
+
homepage: https://github.com/enspirit/bmg
|
|
332
390
|
licenses:
|
|
333
391
|
- MIT
|
|
334
|
-
metadata:
|
|
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/
|
|
335
397
|
rdoc_options: []
|
|
336
398
|
require_paths:
|
|
337
399
|
- lib
|
|
@@ -339,14 +401,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
339
401
|
requirements:
|
|
340
402
|
- - ">="
|
|
341
403
|
- !ruby/object:Gem::Version
|
|
342
|
-
version: '
|
|
404
|
+
version: '2.7'
|
|
343
405
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
344
406
|
requirements:
|
|
345
407
|
- - ">="
|
|
346
408
|
- !ruby/object:Gem::Version
|
|
347
409
|
version: '0'
|
|
348
410
|
requirements: []
|
|
349
|
-
rubygems_version: 3.6.
|
|
411
|
+
rubygems_version: 3.6.9
|
|
350
412
|
specification_version: 4
|
|
351
413
|
summary: Bmg is Alf's successor.
|
|
352
414
|
test_files: []
|