bmg 0.18.7 → 0.18.11
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 +5 -5
- data/lib/bmg/operator/autowrap.rb +21 -7
- data/lib/bmg/reader/excel.rb +2 -1
- data/lib/bmg/sequel/translator.rb +9 -3
- data/lib/bmg/sql/processor/summarize.rb +2 -2
- data/lib/bmg/sql/relation.rb +1 -1
- data/lib/bmg/sql/support/from_clause_orderer.rb +1 -2
- data/lib/bmg/summarizer/distinct_count.rb +36 -0
- data/lib/bmg/summarizer/first.rb +25 -0
- data/lib/bmg/summarizer/last.rb +25 -0
- data/lib/bmg/summarizer/positional.rb +33 -0
- data/lib/bmg/summarizer.rb +8 -1
- data/lib/bmg/support/ordering.rb +5 -1
- data/lib/bmg/version.rb +1 -1
- metadata +16 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: eda140880e29f5e083ad334176579ed2dfad9090
|
4
|
+
data.tar.gz: 444a8cc5f96b80ba3bbf6d807be1438c2d26abd7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96ecc393e90d3ae413655d70c4b1676fa2f9831e519ef61cbd25139b873efcd75a825745cce0597e083fc59bc331b08d30b5717b1e5b42adacb5297147a044bd
|
7
|
+
data.tar.gz: dc687db5b22f9f3fc53b2ccf0916722065ca7d25b8ad04b0a042c6d79fd66f40c22f2d05461da8019db8b70f54c4c104658f3dce3862f9a37b2af44c6ee25d61
|
@@ -22,6 +22,7 @@ module Bmg
|
|
22
22
|
|
23
23
|
DEFAULT_OPTIONS = {
|
24
24
|
:postprocessor => :none,
|
25
|
+
:postprocessor_condition => :all,
|
25
26
|
:split => "_"
|
26
27
|
}
|
27
28
|
|
@@ -167,7 +168,7 @@ module Bmg
|
|
167
168
|
|
168
169
|
def normalize_options(options)
|
169
170
|
opts = DEFAULT_OPTIONS.merge(options)
|
170
|
-
opts[:postprocessor] = NoLeftJoinNoise.new(opts[:postprocessor])
|
171
|
+
opts[:postprocessor] = NoLeftJoinNoise.new(opts[:postprocessor], opts[:postprocessor_condition])
|
171
172
|
opts
|
172
173
|
end
|
173
174
|
|
@@ -209,17 +210,17 @@ module Bmg
|
|
209
210
|
class NoLeftJoinNoise
|
210
211
|
|
211
212
|
REMOVERS = {
|
212
|
-
nil:
|
213
|
-
delete:
|
214
|
-
none:
|
213
|
+
nil: ->(t,k){ t[k] = nil },
|
214
|
+
delete: ->(t,k){ t.delete(k) },
|
215
|
+
none: ->(t,k){ t }
|
215
216
|
}
|
216
217
|
|
217
|
-
def self.new(remover)
|
218
|
+
def self.new(remover, remover_condition = :all)
|
218
219
|
return remover if remover.is_a?(NoLeftJoinNoise)
|
219
220
|
super
|
220
221
|
end
|
221
222
|
|
222
|
-
def initialize(remover)
|
223
|
+
def initialize(remover, remover_condition = :all)
|
223
224
|
@remover_to_s = remover
|
224
225
|
@remover = case remover
|
225
226
|
when NilClass then REMOVERS[:none]
|
@@ -229,22 +230,35 @@ module Bmg
|
|
229
230
|
else
|
230
231
|
raise "Invalid remover `#{remover}`"
|
231
232
|
end
|
233
|
+
@remover_condition = case remover_condition
|
234
|
+
when :all then ->(tuple){ all_nil?(tuple) }
|
235
|
+
when :id then ->(tuple){ id_nil?(tuple) }
|
236
|
+
else
|
237
|
+
raise "Invalid remover condition `#{remover_condition}`"
|
238
|
+
end
|
232
239
|
end
|
233
240
|
attr_reader :remover
|
234
241
|
|
235
242
|
def call(tuple)
|
236
243
|
tuple.each_key do |k|
|
237
244
|
call(tuple[k]) if tuple[k].is_a?(Hash)
|
238
|
-
@remover.call(tuple, k) if tuple[k].is_a?(Hash) &&
|
245
|
+
@remover.call(tuple, k) if tuple[k].is_a?(Hash) && @remover_condition.call(tuple[k])
|
239
246
|
end
|
240
247
|
tuple
|
241
248
|
end
|
242
249
|
|
243
250
|
def all_nil?(tuple)
|
244
251
|
return false unless tuple.is_a?(Hash)
|
252
|
+
|
245
253
|
tuple.all?{|(k,v)| v.nil? || all_nil?(tuple[k]) }
|
246
254
|
end
|
247
255
|
|
256
|
+
def id_nil?(tuple)
|
257
|
+
return false unless tuple.is_a?(Hash)
|
258
|
+
|
259
|
+
tuple[:id].nil?
|
260
|
+
end
|
261
|
+
|
248
262
|
def inspect
|
249
263
|
@remover_to_s.inspect
|
250
264
|
end
|
data/lib/bmg/reader/excel.rb
CHANGED
@@ -4,6 +4,7 @@ module Bmg
|
|
4
4
|
include Reader
|
5
5
|
|
6
6
|
DEFAULT_OPTIONS = {
|
7
|
+
sheet: 0,
|
7
8
|
skip: 0,
|
8
9
|
row_num: true
|
9
10
|
}
|
@@ -19,7 +20,7 @@ module Bmg
|
|
19
20
|
require 'roo'
|
20
21
|
xlsx = Roo::Spreadsheet.open(@path, @options)
|
21
22
|
headers = nil
|
22
|
-
xlsx.sheet(
|
23
|
+
xlsx.sheet(@options[:sheet])
|
23
24
|
.each
|
24
25
|
.drop(@options[:skip])
|
25
26
|
.each_with_index
|
@@ -90,11 +90,17 @@ module Bmg
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def on_summarizer(sexpr)
|
93
|
-
if sexpr.
|
94
|
-
|
93
|
+
func, distinct = if sexpr.summary_func == :distinct_count
|
94
|
+
[:count, true]
|
95
95
|
else
|
96
|
-
|
96
|
+
[sexpr.summary_func, false]
|
97
97
|
end
|
98
|
+
f = if sexpr.summary_expr
|
99
|
+
::Sequel.function(func, apply(sexpr.summary_expr))
|
100
|
+
else
|
101
|
+
::Sequel.function(func).*
|
102
|
+
end
|
103
|
+
distinct ? f.distinct : f
|
98
104
|
end
|
99
105
|
|
100
106
|
def on_qualified_name(sexpr)
|
@@ -36,10 +36,10 @@ module Bmg
|
|
36
36
|
[:select_item,
|
37
37
|
[ :summarizer,
|
38
38
|
summarizer.to_summarizer_name,
|
39
|
-
sexpr.desaliaser[
|
39
|
+
sexpr.desaliaser[summarizer.functor] ],
|
40
40
|
[:column_name, attr.to_s] ]
|
41
41
|
}
|
42
|
-
[:select_list] + by_list + group_list
|
42
|
+
([:select_list] + by_list + group_list)
|
43
43
|
end
|
44
44
|
|
45
45
|
end # class Summarize
|
data/lib/bmg/sql/relation.rb
CHANGED
@@ -160,7 +160,7 @@ module Bmg
|
|
160
160
|
|
161
161
|
def can_compile_summarization?(summarization)
|
162
162
|
summarization.values.all?{|s|
|
163
|
-
[:avg, :count, :max, :min, :sum].include?(s.to_summarizer_name)
|
163
|
+
[:avg, :count, :max, :min, :sum, :distinct_count].include?(s.to_summarizer_name)
|
164
164
|
}
|
165
165
|
end
|
166
166
|
|
@@ -213,8 +213,7 @@ module Bmg
|
|
213
213
|
def _collect_joins(sexpr, joins)
|
214
214
|
case sexpr.first
|
215
215
|
when :and
|
216
|
-
|
217
|
-
_collect_joins(sexpr[2], joins)
|
216
|
+
sexpr[1..-1].each{ |term| _collect_joins(term, joins) }
|
218
217
|
when :eq
|
219
218
|
joins << sexpr
|
220
219
|
else
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Bmg
|
2
|
+
class Summarizer
|
3
|
+
#
|
4
|
+
# Collect the count of distinct values.
|
5
|
+
#
|
6
|
+
# Example:
|
7
|
+
#
|
8
|
+
# # direct ruby usage
|
9
|
+
# Bmg::Summarizer.distinct_count(:qty).summarize(...)
|
10
|
+
#
|
11
|
+
class DistinctCount < Summarizer
|
12
|
+
|
13
|
+
# Returns [] as least value.
|
14
|
+
def least()
|
15
|
+
{}
|
16
|
+
end
|
17
|
+
|
18
|
+
# Adds val to the memo array
|
19
|
+
def _happens(memo, val)
|
20
|
+
memo[val] = true
|
21
|
+
memo
|
22
|
+
end
|
23
|
+
|
24
|
+
def finalize(memo)
|
25
|
+
memo.keys.size
|
26
|
+
end
|
27
|
+
|
28
|
+
end # class DistinctCount
|
29
|
+
|
30
|
+
# Factors a distinct count summarizer
|
31
|
+
def self.distinct_count(*args, &bl)
|
32
|
+
DistinctCount.new(*args, &bl)
|
33
|
+
end
|
34
|
+
|
35
|
+
end # class Summarizer
|
36
|
+
end # module Bmg
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Bmg
|
2
|
+
class Summarizer
|
3
|
+
#
|
4
|
+
# First summarizer.
|
5
|
+
#
|
6
|
+
# Example:
|
7
|
+
#
|
8
|
+
# # direct ruby usage
|
9
|
+
# Bmg::Summarizer.first(:qty, :order => [:id]).summarize(...)
|
10
|
+
#
|
11
|
+
class First < Positional
|
12
|
+
|
13
|
+
def choose(t1, t2)
|
14
|
+
t1
|
15
|
+
end
|
16
|
+
|
17
|
+
end # class First
|
18
|
+
|
19
|
+
# Factors a first summarizer
|
20
|
+
def self.first(*args, &bl)
|
21
|
+
First.new(*args, &bl)
|
22
|
+
end
|
23
|
+
|
24
|
+
end # class Summarizer
|
25
|
+
end # module Bmg
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Bmg
|
2
|
+
class Summarizer
|
3
|
+
#
|
4
|
+
# Last summarizer.
|
5
|
+
#
|
6
|
+
# Example:
|
7
|
+
#
|
8
|
+
# # direct ruby usage
|
9
|
+
# Bmg::Summarizer.last(:qty, :order => [:id]).summarize(...)
|
10
|
+
#
|
11
|
+
class Last < Positional
|
12
|
+
|
13
|
+
def choose(t1, t2)
|
14
|
+
t2
|
15
|
+
end
|
16
|
+
|
17
|
+
end # class Last
|
18
|
+
|
19
|
+
# Factors a last summarizer
|
20
|
+
def self.last(*args, &bl)
|
21
|
+
Last.new(*args, &bl)
|
22
|
+
end
|
23
|
+
|
24
|
+
end # class Summarizer
|
25
|
+
end # module Bmg
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Bmg
|
2
|
+
class Summarizer
|
3
|
+
# See First and Last
|
4
|
+
class Positional < Summarizer
|
5
|
+
|
6
|
+
def initialize(*args, &block)
|
7
|
+
super
|
8
|
+
raise ArgumentError, "Missing order" unless options[:order]
|
9
|
+
@ordering = Ordering.new(options[:order])
|
10
|
+
end
|
11
|
+
attr_reader :ordering
|
12
|
+
|
13
|
+
def least
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def happens(memo, tuple)
|
18
|
+
if memo.nil?
|
19
|
+
tuple
|
20
|
+
else
|
21
|
+
c = ordering.call(memo, tuple)
|
22
|
+
c <= 0 ? choose(memo, tuple) : choose(tuple, memo)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def finalize(memo)
|
27
|
+
return nil if memo.nil?
|
28
|
+
extract_value(memo)
|
29
|
+
end
|
30
|
+
|
31
|
+
end # class Positional
|
32
|
+
end # class Summarizer
|
33
|
+
end # module Bmg
|
data/lib/bmg/summarizer.rb
CHANGED
@@ -131,7 +131,10 @@ module Bmg
|
|
131
131
|
|
132
132
|
# Returns the canonical summarizer name
|
133
133
|
def to_summarizer_name
|
134
|
-
self.class.name
|
134
|
+
self.class.name
|
135
|
+
.gsub(/[a-z][A-Z]/){|x| x.split('').join('_') }
|
136
|
+
.downcase[/::([a-z_]+)$/, 1]
|
137
|
+
.to_sym
|
135
138
|
end
|
136
139
|
|
137
140
|
protected
|
@@ -161,7 +164,11 @@ require_relative 'summarizer/stddev'
|
|
161
164
|
require_relative 'summarizer/percentile'
|
162
165
|
require_relative 'summarizer/collect'
|
163
166
|
require_relative 'summarizer/distinct'
|
167
|
+
require_relative 'summarizer/distinct_count'
|
164
168
|
require_relative 'summarizer/concat'
|
165
169
|
require_relative 'summarizer/by_proc'
|
166
170
|
require_relative 'summarizer/multiple'
|
167
171
|
require_relative 'summarizer/value_by'
|
172
|
+
require_relative 'summarizer/positional'
|
173
|
+
require_relative 'summarizer/first'
|
174
|
+
require_relative 'summarizer/last'
|
data/lib/bmg/support/ordering.rb
CHANGED
@@ -6,8 +6,12 @@ module Bmg
|
|
6
6
|
end
|
7
7
|
attr_reader :attrs
|
8
8
|
|
9
|
+
def call(t1, t2)
|
10
|
+
comparator.call(t1, t2)
|
11
|
+
end
|
12
|
+
|
9
13
|
def comparator
|
10
|
-
->(t1, t2) {
|
14
|
+
@comparator ||= ->(t1, t2) {
|
11
15
|
attrs.each do |(attr,direction)|
|
12
16
|
c = t1[attr] <=> t2[attr]
|
13
17
|
return (direction == :desc ? -c : c) unless c==0
|
data/lib/bmg/version.rb
CHANGED
metadata
CHANGED
@@ -1,35 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bmg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.18.
|
4
|
+
version: 0.18.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bernard Lambeau
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: predicate
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 2.5.0
|
20
17
|
- - "~>"
|
21
18
|
- !ruby/object:Gem::Version
|
22
|
-
version: '2.
|
19
|
+
version: '2.6'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.6.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
|
-
- - ">="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 2.5.0
|
30
27
|
- - "~>"
|
31
28
|
- !ruby/object:Gem::Version
|
32
|
-
version: '2.
|
29
|
+
version: '2.6'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.6.0
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: path
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -273,10 +273,14 @@ files:
|
|
273
273
|
- lib/bmg/summarizer/concat.rb
|
274
274
|
- lib/bmg/summarizer/count.rb
|
275
275
|
- lib/bmg/summarizer/distinct.rb
|
276
|
+
- lib/bmg/summarizer/distinct_count.rb
|
277
|
+
- lib/bmg/summarizer/first.rb
|
278
|
+
- lib/bmg/summarizer/last.rb
|
276
279
|
- lib/bmg/summarizer/max.rb
|
277
280
|
- lib/bmg/summarizer/min.rb
|
278
281
|
- lib/bmg/summarizer/multiple.rb
|
279
282
|
- lib/bmg/summarizer/percentile.rb
|
283
|
+
- lib/bmg/summarizer/positional.rb
|
280
284
|
- lib/bmg/summarizer/stddev.rb
|
281
285
|
- lib/bmg/summarizer/sum.rb
|
282
286
|
- lib/bmg/summarizer/value_by.rb
|
@@ -313,7 +317,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
313
317
|
- !ruby/object:Gem::Version
|
314
318
|
version: '0'
|
315
319
|
requirements: []
|
316
|
-
|
320
|
+
rubyforge_project:
|
321
|
+
rubygems_version: 2.6.14.4
|
317
322
|
signing_key:
|
318
323
|
specification_version: 4
|
319
324
|
summary: Bmg is Alf's successor.
|