bmg 0.23.6 → 0.24.1
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/lib/bmg/sequel/translator.rb +9 -1
- data/lib/bmg/sql/grammar.rb +1 -0
- data/lib/bmg/sql/grammar.sexp.yml +3 -0
- data/lib/bmg/sql/nodes/case_when.rb +33 -0
- data/lib/bmg/sql/processor/join.rb +15 -1
- data/lib/bmg/sql/processor/transform.rb +27 -1
- data/lib/bmg/sql/relation.rb +2 -1
- data/lib/bmg/version.rb +2 -2
- metadata +4 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ff9e5fa48bb225feaeee07ddbfb15f8616e7943be2304113d727d7b8fd71dda2
|
|
4
|
+
data.tar.gz: b8924512fc6e1b4d8cdb6d86ab40e5e5f317850839ae6d8bc3f02ddd8534e578
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dc7c8dde953a4792a17177abe5a3decd4a3aac156cda87c7ad8854382d2248b03a272a6d318a348fbcba255ba5302e5adbaa4f3764c6db04b61924e9d11e50f4
|
|
7
|
+
data.tar.gz: 5148e32c981959c62eedae0f8b15cd8816d9afc01f7e1e00e94cc4d7086892e22dc4b6da0a3bb07a57ec138e91060b3c2a839c9f6e4ef5b6af053df08382c20e
|
|
@@ -70,13 +70,21 @@ module Bmg
|
|
|
70
70
|
case kind = sexpr.left.first
|
|
71
71
|
when :qualified_name
|
|
72
72
|
left.column == right.value ? left : ::Sequel.as(left, right)
|
|
73
|
-
when :literal, :summarizer, :func_call
|
|
73
|
+
when :literal, :summarizer, :func_call, :case_when
|
|
74
74
|
::Sequel.as(left, right)
|
|
75
75
|
else
|
|
76
76
|
raise NotImplementedError, "Unexpected select item `#{kind}`"
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
+
def on_case_when(sexpr)
|
|
81
|
+
operand = apply(sexpr[1])
|
|
82
|
+
mapping = sexpr[2..-1].each_slice(2).each_with_object({}){|(w, t), h|
|
|
83
|
+
h[w.last] = t.last
|
|
84
|
+
}
|
|
85
|
+
::Sequel.case(mapping, nil, operand)
|
|
86
|
+
end
|
|
87
|
+
|
|
80
88
|
def on_func_call(sexpr)
|
|
81
89
|
case sexpr.func_name
|
|
82
90
|
when :cast
|
data/lib/bmg/sql/grammar.rb
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Bmg
|
|
2
|
+
module Sql
|
|
3
|
+
module CaseWhen
|
|
4
|
+
include Expr
|
|
5
|
+
|
|
6
|
+
def operand
|
|
7
|
+
self[1]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def whens
|
|
11
|
+
self[2..-1].each_slice(2).to_a
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def is_computed?
|
|
15
|
+
true
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def to_sql(buffer, dialect)
|
|
19
|
+
buffer << "CASE "
|
|
20
|
+
operand.to_sql(buffer, dialect)
|
|
21
|
+
whens.each do |(when_val, then_val)|
|
|
22
|
+
buffer << " WHEN "
|
|
23
|
+
when_val.to_sql(buffer, dialect)
|
|
24
|
+
buffer << " THEN "
|
|
25
|
+
then_val.to_sql(buffer, dialect)
|
|
26
|
+
end
|
|
27
|
+
buffer << " END"
|
|
28
|
+
buffer
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end # module CaseWhen
|
|
32
|
+
end # module Sql
|
|
33
|
+
end # module Bmg
|
|
@@ -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) || left_join_over_restricted_right?
|
|
19
19
|
Join.new(builder.from_self(right), on, options, builder).call(sexpr)
|
|
20
20
|
else
|
|
21
21
|
super(sexpr)
|
|
@@ -37,6 +37,20 @@ 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
|
+
|
|
40
54
|
def join_set_quantifiers(left, right)
|
|
41
55
|
left_q, right_q = left.set_quantifier, right.set_quantifier
|
|
42
56
|
left_q == right_q ? left_q : builder.distinct
|
|
@@ -50,6 +50,14 @@ module Bmg
|
|
|
50
50
|
SplitSupported.split_supported(*args, &bl)
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
+
# An SQL-able element the transform can emit verbatim: an object that
|
|
54
|
+
# carries its own SQL (the predicate gem's `:sql`/`:sql_literal`
|
|
55
|
+
# convention) or a Sequel expression (rendered through `Sequel.expr`).
|
|
56
|
+
def self.sql_expr?(x)
|
|
57
|
+
x.respond_to?(:sql_literal) || x.respond_to?(:sql) ||
|
|
58
|
+
(defined?(::Sequel::SQL::Expression) && x.is_a?(::Sequel::SQL::Expression))
|
|
59
|
+
end
|
|
60
|
+
|
|
53
61
|
def on_select_list(sexpr)
|
|
54
62
|
sexpr.each_with_index.map{|child,index|
|
|
55
63
|
index == 0 ? child : apply(child)
|
|
@@ -66,8 +74,17 @@ module Bmg
|
|
|
66
74
|
func_call_node(sexpr, Array(t).reverse),
|
|
67
75
|
sexpr[2]
|
|
68
76
|
])
|
|
77
|
+
when Hash
|
|
78
|
+
sexpr([:select_item,
|
|
79
|
+
case_when_node(sexpr, t),
|
|
80
|
+
sexpr[2]
|
|
81
|
+
])
|
|
69
82
|
else
|
|
70
|
-
|
|
83
|
+
# An SQL-able value (e.g. a Sequel expression) carries its own SQL
|
|
84
|
+
# — including the column reference — so it rides through as a
|
|
85
|
+
# literal, which the Sequel translator emits verbatim.
|
|
86
|
+
raise NotSupportedError unless Transform.sql_expr?(t)
|
|
87
|
+
sexpr([:select_item, [:literal, t], sexpr[2]])
|
|
71
88
|
end
|
|
72
89
|
end
|
|
73
90
|
|
|
@@ -89,6 +106,15 @@ module Bmg
|
|
|
89
106
|
[ :literal, head ] ]
|
|
90
107
|
end
|
|
91
108
|
|
|
109
|
+
def case_when_node(sexpr, mapping)
|
|
110
|
+
node = [:case_when, sexpr[1]]
|
|
111
|
+
mapping.each do |when_val, then_val|
|
|
112
|
+
node << [:literal, when_val]
|
|
113
|
+
node << [:literal, then_val]
|
|
114
|
+
end
|
|
115
|
+
node
|
|
116
|
+
end
|
|
117
|
+
|
|
92
118
|
def transformation_for(as)
|
|
93
119
|
case t = transformation
|
|
94
120
|
when Class then t
|
data/lib/bmg/sql/relation.rb
CHANGED
|
@@ -167,7 +167,8 @@ module Bmg
|
|
|
167
167
|
def _transform(type, transformation, options)
|
|
168
168
|
expr = before_use(self.expr)
|
|
169
169
|
sup, unsup = Processor::Transform.split_supported(transformation){|x|
|
|
170
|
-
[String, Integer, Float, Date, DateTime].include?(x)
|
|
170
|
+
[String, Integer, Float, Date, DateTime].include?(x) || x.is_a?(Hash) ||
|
|
171
|
+
Processor::Transform.sql_expr?(x)
|
|
171
172
|
}
|
|
172
173
|
return super if sup.nil?
|
|
173
174
|
expr = Processor::Transform.new(sup, options, builder).call(expr)
|
data/lib/bmg/version.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: 0.24.1
|
|
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: 2026-10-03 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: predicate
|
|
@@ -233,6 +232,7 @@ files:
|
|
|
233
232
|
- lib/bmg/sql/ext/predicate/tautology.rb
|
|
234
233
|
- lib/bmg/sql/grammar.rb
|
|
235
234
|
- lib/bmg/sql/grammar.sexp.yml
|
|
235
|
+
- lib/bmg/sql/nodes/case_when.rb
|
|
236
236
|
- lib/bmg/sql/nodes/column_name.rb
|
|
237
237
|
- lib/bmg/sql/nodes/cross_join.rb
|
|
238
238
|
- lib/bmg/sql/nodes/except.rb
|
|
@@ -332,7 +332,6 @@ homepage: http://github.com/enspirit/bmg
|
|
|
332
332
|
licenses:
|
|
333
333
|
- MIT
|
|
334
334
|
metadata: {}
|
|
335
|
-
post_install_message:
|
|
336
335
|
rdoc_options: []
|
|
337
336
|
require_paths:
|
|
338
337
|
- lib
|
|
@@ -347,8 +346,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
347
346
|
- !ruby/object:Gem::Version
|
|
348
347
|
version: '0'
|
|
349
348
|
requirements: []
|
|
350
|
-
rubygems_version: 3.
|
|
351
|
-
signing_key:
|
|
349
|
+
rubygems_version: 3.6.2
|
|
352
350
|
specification_version: 4
|
|
353
351
|
summary: Bmg is Alf's successor.
|
|
354
352
|
test_files: []
|