bmg 0.21.2 → 0.21.3
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 +9 -9
- data/lib/bmg/reader/csv.rb +3 -1
- data/lib/bmg/support/ordering.rb +11 -1
- data/lib/bmg/support/output_preferences.rb +27 -1
- data/lib/bmg/version.rb +1 -1
- data/lib/bmg/writer/csv.rb +3 -1
- data/lib/bmg/writer/xlsx.rb +9 -7
- data/lib/bmg/writer.rb +11 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 83f3d7ebfe5587af85b9823b7ab5a9d11d6e9b30
|
4
|
+
data.tar.gz: 34418e3d5ccfe156c3b0320e6821030a09ba1cdc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1e68f36ad0cd1a5c9ba2d2dd5fdcd8f02220c3588e5ef995439db58c46dab2bb6fa91ff249f3541ae2096e9d12f3c0d9a9d424c99310c7e90fef7cd4f460994
|
7
|
+
data.tar.gz: 0c9c97791462f47799be4ae510d5be7b0aa3c30360592899fbfb336f31c25762d8fe5d35d87202413f85916ce8fc9199c48d40a26a22b480fc72d497edbe1f1d
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Bmg, a relational algebra (Alf's successor)!
|
2
2
|
|
3
|
-
Bmg is a relational algebra implemented as a
|
3
|
+
Bmg is a relational algebra implemented as a Ruby library. It implements the
|
4
4
|
[Relation as First-Class Citizen](http://www.try-alf.org/blog/2013-10-21-relations-as-first-class-citizen)
|
5
5
|
paradigm contributed with [Alf](http://www.try-alf.org/) a few years ago.
|
6
6
|
|
@@ -15,7 +15,7 @@ further down this README.
|
|
15
15
|
* [Where are base relations coming from?](#where-are-base-relations-coming-from)
|
16
16
|
* [Memory relations](#memory-relations)
|
17
17
|
* [Connecting to SQL databases](#connecting-to-sql-databases)
|
18
|
-
* [Reading files (csv,
|
18
|
+
* [Reading files (csv, Excel, text)](#reading-files-csv-excel-text)
|
19
19
|
* [Connecting to Redis databases](#connecting-to-redis-databases)
|
20
20
|
* [Your own relations](#your-own-relations)
|
21
21
|
* [List of supported operators](#supported-operators)
|
@@ -117,7 +117,7 @@ Bmg.sequel(:suppliers, sequel_db)
|
|
117
117
|
# {:array=>false})
|
118
118
|
```
|
119
119
|
|
120
|
-
### Reading files (csv,
|
120
|
+
### Reading files (csv, Excel, text)
|
121
121
|
|
122
122
|
Bmg provides simple adapters to read files and reach Relationland as soon as
|
123
123
|
possible.
|
@@ -129,7 +129,7 @@ csv_options = { col_sep: ",", quote_char: '"' }
|
|
129
129
|
r = Bmg.csv("path/to/a/file.csv", csv_options)
|
130
130
|
```
|
131
131
|
|
132
|
-
Options are directly transmitted to `::CSV.new`, check
|
132
|
+
Options are directly transmitted to `::CSV.new`, check Ruby's standard
|
133
133
|
library.
|
134
134
|
|
135
135
|
#### Excel files
|
@@ -302,7 +302,7 @@ r.where(predicate) # alias for restrict(predicate)
|
|
302
302
|
.where(...)
|
303
303
|
```
|
304
304
|
|
305
|
-
2. Bmg supports in
|
305
|
+
2. Bmg supports in-memory relations, JSON relations, csv relations, SQL
|
306
306
|
relations and so on. It's not tight to SQL generation, and supports
|
307
307
|
queries accross multiple data sources.
|
308
308
|
|
@@ -312,8 +312,8 @@ r.where(predicate) # alias for restrict(predicate)
|
|
312
312
|
4. Bmg supports various *structuring* operators (group, image, autowrap,
|
313
313
|
autosummarize, etc.) and allows building 'non flat' relations.
|
314
314
|
|
315
|
-
5. Bmg can use full
|
316
|
-
WHERE clauses or
|
315
|
+
5. Bmg can use full Ruby power when that helps (e.g. regular expressions in
|
316
|
+
WHERE clauses or Ruby code in EXTEND clauses). This may prevent Bmg from
|
317
317
|
delegating work to underlying data sources (e.g. SQL server) and should
|
318
318
|
therefore be used with care though.
|
319
319
|
|
@@ -323,14 +323,14 @@ If you use Alf (or used it in the past), below are the main differences between
|
|
323
323
|
Bmg and Alf. Bmg has NOT been written to be API-compatible with Alf and will
|
324
324
|
probably never be.
|
325
325
|
|
326
|
-
1. Bmg's implementation is much simpler than Alf and uses no
|
326
|
+
1. Bmg's implementation is much simpler than Alf and uses no Ruby core
|
327
327
|
extention.
|
328
328
|
|
329
329
|
2. We are confident using Bmg in production. Systematic inspection of query
|
330
330
|
plans is advised though. Alf was a bit too experimental to be used on
|
331
331
|
(critical) production systems.
|
332
332
|
|
333
|
-
3. Alf exposes a functional syntax, command
|
333
|
+
3. Alf exposes a functional syntax, command-line tool, restful tools and
|
334
334
|
many more. Bmg is limited to the core algebra, main Relation abstraction
|
335
335
|
and SQL generation.
|
336
336
|
|
data/lib/bmg/reader/csv.rb
CHANGED
data/lib/bmg/support/ordering.rb
CHANGED
@@ -2,7 +2,13 @@ module Bmg
|
|
2
2
|
class Ordering
|
3
3
|
|
4
4
|
def initialize(attrs)
|
5
|
-
@attrs = attrs
|
5
|
+
@attrs = if attrs.empty?
|
6
|
+
[]
|
7
|
+
elsif attrs.first.is_a?(Symbol)
|
8
|
+
attrs.map{|a| [a, :asc] }
|
9
|
+
else
|
10
|
+
attrs
|
11
|
+
end
|
6
12
|
end
|
7
13
|
attr_reader :attrs
|
8
14
|
|
@@ -33,5 +39,9 @@ module Bmg
|
|
33
39
|
0
|
34
40
|
end
|
35
41
|
|
42
|
+
def to_a
|
43
|
+
attrs.to_a
|
44
|
+
end
|
45
|
+
|
36
46
|
end # class Ordering
|
37
47
|
end # module Bmg
|
@@ -3,6 +3,7 @@ module Bmg
|
|
3
3
|
|
4
4
|
DEFAULT_PREFS = {
|
5
5
|
attributes_ordering: nil,
|
6
|
+
tuple_ordering: nil,
|
6
7
|
extra_attributes: :after
|
7
8
|
}
|
8
9
|
|
@@ -17,6 +18,12 @@ module Bmg
|
|
17
18
|
new(arg)
|
18
19
|
end
|
19
20
|
|
21
|
+
def tuple_ordering
|
22
|
+
return nil unless to = options[:tuple_ordering]
|
23
|
+
|
24
|
+
@tuple_ordering = Ordering.new(to)
|
25
|
+
end
|
26
|
+
|
20
27
|
def attributes_ordering
|
21
28
|
options[:attributes_ordering]
|
22
29
|
end
|
@@ -25,10 +32,29 @@ module Bmg
|
|
25
32
|
options[:extra_attributes]
|
26
33
|
end
|
27
34
|
|
35
|
+
def grouping_attributes
|
36
|
+
options[:grouping_attributes]
|
37
|
+
end
|
38
|
+
|
39
|
+
def erase_redundance_in_group(before, current)
|
40
|
+
return [nil, current] unless ga = grouping_attributes
|
41
|
+
return [current, current] unless before
|
42
|
+
|
43
|
+
new_before, new_current = current.dup, current.dup
|
44
|
+
ga.each do |attr|
|
45
|
+
return [new_before, new_current] unless before[attr] == current[attr]
|
46
|
+
new_current[attr] = nil
|
47
|
+
end
|
48
|
+
[new_before, new_current]
|
49
|
+
end
|
50
|
+
|
28
51
|
def order_attrlist(attrlist)
|
29
52
|
return attrlist if attributes_ordering.nil?
|
53
|
+
|
30
54
|
index = Hash[attributes_ordering.each_with_index.to_a]
|
31
|
-
attrlist
|
55
|
+
base = attrlist
|
56
|
+
base = attrlist & attributes_ordering if extra_attributes == :ignored
|
57
|
+
base.sort{|a,b|
|
32
58
|
ai, bi = index[a], index[b]
|
33
59
|
if ai && bi
|
34
60
|
ai <=> bi
|
data/lib/bmg/version.rb
CHANGED
data/lib/bmg/writer/csv.rb
CHANGED
@@ -16,12 +16,14 @@ module Bmg
|
|
16
16
|
require 'csv'
|
17
17
|
string_or_io, to_s = string_or_io.nil? ? [StringIO.new, true] : [string_or_io, false]
|
18
18
|
headers, csv = infer_headers(relation.type), nil
|
19
|
-
|
19
|
+
previous = nil
|
20
|
+
each_tuple(relation) do |tuple,i|
|
20
21
|
if csv.nil?
|
21
22
|
headers = infer_headers(tuple) if headers.nil?
|
22
23
|
csv_opts = csv_options.merge(headers: headers)
|
23
24
|
csv = CSV.new(string_or_io, **csv_opts)
|
24
25
|
end
|
26
|
+
previous, tuple = output_preferences.erase_redundance_in_group(previous, tuple)
|
25
27
|
csv << headers.map{|h| tuple[h] }
|
26
28
|
end
|
27
29
|
to_s ? string_or_io.string : string_or_io
|
data/lib/bmg/writer/xlsx.rb
CHANGED
@@ -6,11 +6,11 @@ module Bmg
|
|
6
6
|
DEFAULT_OPTIONS = {
|
7
7
|
}
|
8
8
|
|
9
|
-
def initialize(
|
10
|
-
@
|
9
|
+
def initialize(xlsx_options, output_preferences = nil)
|
10
|
+
@xlsx_options = DEFAULT_OPTIONS.merge(xlsx_options)
|
11
11
|
@output_preferences = OutputPreferences.dress(output_preferences)
|
12
12
|
end
|
13
|
-
attr_reader :
|
13
|
+
attr_reader :xlsx_options, :output_preferences
|
14
14
|
|
15
15
|
def call(relation, path)
|
16
16
|
require 'write_xlsx'
|
@@ -21,22 +21,24 @@ module Bmg
|
|
21
21
|
attr_reader :workbook, :worksheet
|
22
22
|
|
23
23
|
def _call(relation, path)
|
24
|
-
@workbook = WriteXLSX.new(path)
|
25
|
-
@worksheet = workbook.add_worksheet
|
24
|
+
@workbook = xlsx_options[:workbook] || WriteXLSX.new(path)
|
25
|
+
@worksheet = xlsx_options[:worksheet] || workbook.add_worksheet
|
26
26
|
|
27
27
|
headers = infer_headers(relation.type)
|
28
|
-
|
28
|
+
before = nil
|
29
|
+
each_tuple(relation) do |tuple,i|
|
29
30
|
headers = infer_headers(tuple) if headers.nil?
|
30
31
|
headers.each_with_index do |h,i|
|
31
32
|
worksheet.write_string(0, i, h)
|
32
33
|
end if i == 0
|
34
|
+
before, tuple = output_preferences.erase_redundance_in_group(before, tuple)
|
33
35
|
headers.each_with_index do |h,j|
|
34
36
|
meth, *args = write_pair(tuple[h])
|
35
37
|
worksheet.send(meth, 1+i, j, *args)
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
39
|
-
workbook.close
|
41
|
+
workbook.close unless xlsx_options[:workbook]
|
40
42
|
path
|
41
43
|
end
|
42
44
|
|
data/lib/bmg/writer.rb
CHANGED
@@ -12,6 +12,17 @@ module Bmg
|
|
12
12
|
attrlist ? output_preferences.order_attrlist(attrlist) : nil
|
13
13
|
end
|
14
14
|
|
15
|
+
def each_tuple(relation, &bl)
|
16
|
+
if ordering = output_preferences.tuple_ordering
|
17
|
+
relation
|
18
|
+
.to_a
|
19
|
+
.sort{|t1,t2| ordering.compare_attrs(t1, t2) }
|
20
|
+
.each_with_index(&bl)
|
21
|
+
else
|
22
|
+
relation.each_with_index(&bl)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
15
26
|
end # module Writer
|
16
27
|
end # module Bmg
|
17
28
|
require_relative 'writer/csv'
|
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.21.
|
4
|
+
version: 0.21.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bernard Lambeau
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: predicate
|