bmg 0.23.6 → 0.24.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a4cb86461e5f53734d08dcb3668bd2a99630680d7213bb946fa5a13cbf0f86f2
4
- data.tar.gz: f9a80e014cb2769d6d8da8cea581b18c7601c2d1015db18e1eac6333f8e08876
3
+ metadata.gz: 1cf55d89350451dc43a50e85413570b8525fdb1af1467cf33c854d65cd885324
4
+ data.tar.gz: a0a665602f3e4deceacfa6bc1bf301dd91e9344d96d93f3cc1df462e3b364fb1
5
5
  SHA512:
6
- metadata.gz: 7621e13e58615206096b3f2d2799a79aa4e662592688b295329bf09626efe86b9a8f4f6f01aba5432513e6054c7568894f13dfccd86d8932f28fa1e9b0892a28
7
- data.tar.gz: 9cfc8e393267db43d44764db894b47639d6cfc445b3e7d80e1287929e02cf8ec4d7e541432f52905002953ac727770b5c30b3c4c850ff1a039d98beba2811469
6
+ metadata.gz: 2cf7cfe088705ba0ac9b90aaa47c457d2f5fbd7dc9d28f8dc246b91e8dbd4d492ff6ef0e892385d2fb6098998e9d07859d355b68f833154d4c4dbd2f6db87149
7
+ data.tar.gz: bd120334a2e20ff7b20cd15d4d96ac3c3651fac5011aadc3dc6f3acf301f9b5f1245fc8e46571f7ab67ed8db4a45d463728605172c0e8d4213b753289d64959e
@@ -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
@@ -48,3 +48,4 @@ require_relative "nodes/inner_join"
48
48
  require_relative "nodes/left_join"
49
49
  require_relative "nodes/summarizer"
50
50
  require_relative "nodes/func_call"
51
+ require_relative "nodes/case_when"
@@ -81,6 +81,9 @@ rules:
81
81
  - summarizer
82
82
  - func_call
83
83
  - literal
84
+ - case_when
85
+ case_when:
86
+ - [ scalar_exp, literal+ ]
84
87
  a_name:
85
88
  - qualified_name
86
89
  - column_name
@@ -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
@@ -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
- raise NotSupportedError
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
@@ -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
@@ -1,8 +1,8 @@
1
1
  module Bmg
2
2
  module Version
3
3
  MAJOR = 0
4
- MINOR = 23
5
- TINY = 6
4
+ MINOR = 24
5
+ TINY = 0
6
6
  end
7
7
  VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::TINY}"
8
8
  end
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.23.6
4
+ version: 0.24.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernard Lambeau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-10-04 00:00:00.000000000 Z
11
+ date: 2026-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: predicate
@@ -233,6 +233,7 @@ files:
233
233
  - lib/bmg/sql/ext/predicate/tautology.rb
234
234
  - lib/bmg/sql/grammar.rb
235
235
  - lib/bmg/sql/grammar.sexp.yml
236
+ - lib/bmg/sql/nodes/case_when.rb
236
237
  - lib/bmg/sql/nodes/column_name.rb
237
238
  - lib/bmg/sql/nodes/cross_join.rb
238
239
  - lib/bmg/sql/nodes/except.rb