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