Class: Bmg::Sequel::Translator
- Inherits:
-
Sexpr::Processor
- Object
- Sexpr::Processor
- Bmg::Sequel::Translator
- Includes:
- Predicate::ToSequel::Methods
- Defined in:
- lib/bmg/sequel/translator.rb
Instance Attribute Summary collapse
-
#sequel_db ⇒ Object
readonly
Returns the value of attribute sequel_db.
Instance Method Summary collapse
- #compile_predicate(predicate) ⇒ Object
-
#initialize(sequel_db) ⇒ Translator
constructor
A new instance of Translator.
- #on_column_name(sexpr) ⇒ Object
- #on_from_clause(sexpr) ⇒ Object
- #on_func_call(sexpr) ⇒ Object
- #on_group_by_clause(sexpr) ⇒ Object
- #on_limit_clause(sexpr) ⇒ Object
- #on_native_table_as(sexpr) ⇒ Object
- #on_offset_clause(sexpr) ⇒ Object
- #on_order_by_clause(sexpr) ⇒ Object
- #on_order_by_term(sexpr) ⇒ Object
- #on_qualified_name(sexpr) ⇒ Object
- #on_select_exp(sexpr) ⇒ Object
- #on_select_item(sexpr) ⇒ Object
- #on_select_list(sexpr) ⇒ Object
- #on_select_star(sexpr) ⇒ Object
- #on_set_operator(sexpr) ⇒ Object (also: #on_union, #on_intersect, #on_except)
- #on_subquery_as(sexpr) ⇒ Object
- #on_summarizer(sexpr) ⇒ Object
- #on_table_as(sexpr) ⇒ Object
- #on_table_name(sexpr) ⇒ Object
- #on_with_exp(sexpr) ⇒ Object
- #on_with_spec(sexpr) ⇒ Object
Constructor Details
#initialize(sequel_db) ⇒ Translator
Returns a new instance of Translator.
6 7 8 |
# File 'lib/bmg/sequel/translator.rb', line 6 def initialize(sequel_db) @sequel_db = sequel_db end |
Instance Attribute Details
#sequel_db ⇒ Object (readonly)
Returns the value of attribute sequel_db.
9 10 11 |
# File 'lib/bmg/sequel/translator.rb', line 9 def sequel_db @sequel_db end |
Instance Method Details
#compile_predicate(predicate) ⇒ Object
184 185 186 |
# File 'lib/bmg/sequel/translator.rb', line 184 def compile_predicate(predicate) PredicateTranslator.new(self).call(predicate) end |
#on_column_name(sexpr) ⇒ Object
111 112 113 |
# File 'lib/bmg/sequel/translator.rb', line 111 def on_column_name(sexpr) ::Sequel.expr(sexpr.last.to_sym) end |
#on_from_clause(sexpr) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/bmg/sequel/translator.rb', line 115 def on_from_clause(sexpr) orderer = Sql::Support::FromClauseOrderer.new ordering = orderer.call(sexpr) ordering.inject(nil) do |ds,(kind,table,on)| if ds.nil? dataset(apply(table)) elsif kind == :cross_join ds.cross_join(apply(table)) elsif kind == :inner_join = { qualify: false, table_alias: false } ds.join_table(:inner, apply(table), nil, ){|*args| compile_predicate(on) } elsif kind == :left_join = { qualify: false, table_alias: false } ds.join_table(:left, apply(table), nil, ){|*args| compile_predicate(on) } else raise IllegalArgumentError, "Unrecognized from clause: `#{sexpr}`" end end end |
#on_func_call(sexpr) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/bmg/sequel/translator.rb', line 80 def on_func_call(sexpr) case sexpr.func_name when :cast to_cast = apply(sexpr.func_args.first) to_cast = ::Sequel.expr(nil) if to_cast.nil? type = sexpr.func_args.last.last to_cast.cast(type) else args = sexpr.func_args.map{|fa| apply(fa) } ::Sequel.function(sexpr.func_name, *args) end end |
#on_group_by_clause(sexpr) ⇒ Object
161 162 163 164 |
# File 'lib/bmg/sequel/translator.rb', line 161 def on_group_by_clause(sexpr) return nil unless sexpr.size > 1 sexpr.sexpr_body.map{|c| apply(c)} end |
#on_limit_clause(sexpr) ⇒ Object
174 175 176 |
# File 'lib/bmg/sequel/translator.rb', line 174 def on_limit_clause(sexpr) sexpr.last end |
#on_native_table_as(sexpr) ⇒ Object
143 144 145 |
# File 'lib/bmg/sequel/translator.rb', line 143 def on_native_table_as(sexpr) sexpr[1].from_self(:alias => sexpr.as_name) end |
#on_offset_clause(sexpr) ⇒ Object
178 179 180 |
# File 'lib/bmg/sequel/translator.rb', line 178 def on_offset_clause(sexpr) sexpr.last end |
#on_order_by_clause(sexpr) ⇒ Object
166 167 168 |
# File 'lib/bmg/sequel/translator.rb', line 166 def on_order_by_clause(sexpr) sexpr.sexpr_body.map{|c| apply(c)} end |
#on_order_by_term(sexpr) ⇒ Object
170 171 172 |
# File 'lib/bmg/sequel/translator.rb', line 170 def on_order_by_term(sexpr) ::Sequel.send(sexpr.direction, apply(sexpr.qualified_name)) end |
#on_qualified_name(sexpr) ⇒ Object
107 108 109 |
# File 'lib/bmg/sequel/translator.rb', line 107 def on_qualified_name(sexpr) apply(sexpr.last).qualify(sexpr.qualifier) end |
#on_select_exp(sexpr) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/bmg/sequel/translator.rb', line 39 def on_select_exp(sexpr) dataset = sequel_db.select(1) dataset = apply(sexpr.from_clause) if sexpr.from_clause # selection = apply(sexpr.select_list) predicate = compile_predicate(sexpr.predicate) if sexpr.predicate grouping = apply(sexpr.group_by_clause) if sexpr.group_by_clause order = apply(sexpr.order_by_clause) if sexpr.order_by_clause limit = apply(sexpr.limit_clause) if sexpr.limit_clause offset = apply(sexpr.offset_clause) if sexpr.offset_clause # dataset = dataset.select(*selection) dataset = dataset.distinct if sexpr.distinct? dataset = dataset.where(predicate) if predicate dataset = dataset.group(*grouping) if grouping dataset = dataset.order_by(*order) if order dataset = dataset.limit(limit, offset == 0 ? nil : offset) if limit or offset dataset end |
#on_select_item(sexpr) ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/bmg/sequel/translator.rb', line 67 def on_select_item(sexpr) left = apply(sexpr.left) right = apply(sexpr.right) case kind = sexpr.left.first when :qualified_name left.column == right.value ? left : ::Sequel.as(left, right) when :literal, :summarizer, :func_call ::Sequel.as(left, right) else raise NotImplementedError, "Unexpected select item `#{kind}`" end end |
#on_select_list(sexpr) ⇒ Object
59 60 61 |
# File 'lib/bmg/sequel/translator.rb', line 59 def on_select_list(sexpr) sexpr.sexpr_body.map{|c| apply(c) } end |
#on_select_star(sexpr) ⇒ Object
63 64 65 |
# File 'lib/bmg/sequel/translator.rb', line 63 def on_select_star(sexpr) ::Sequel.lit('*') end |
#on_set_operator(sexpr) ⇒ Object Also known as: on_union, on_intersect, on_except
30 31 32 33 34 |
# File 'lib/bmg/sequel/translator.rb', line 30 def on_set_operator(sexpr) sexpr.tail_exprs.inject(apply(sexpr.head_expr)) do |left,right| left.send(sexpr.first, apply(right), all: sexpr.all?, from_self: false) end end |
#on_subquery_as(sexpr) ⇒ Object
157 158 159 |
# File 'lib/bmg/sequel/translator.rb', line 157 def on_subquery_as(sexpr) ::Sequel.as(apply(sexpr.subquery), ::Sequel.identifier(sexpr.as_name)) end |
#on_summarizer(sexpr) ⇒ Object
93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/bmg/sequel/translator.rb', line 93 def on_summarizer(sexpr) func, distinct = if sexpr.summary_func == :distinct_count [:count, true] else [sexpr.summary_func, false] end f = if sexpr.summary_expr ::Sequel.function(func, apply(sexpr.summary_expr)) else ::Sequel.function(func).* end distinct ? f.distinct : f end |
#on_table_as(sexpr) ⇒ Object
147 148 149 150 151 152 153 154 155 |
# File 'lib/bmg/sequel/translator.rb', line 147 def on_table_as(sexpr) table_name = case sexpr.table_name when String, Symbol then ::Sequel.expr(sexpr.table_name.to_sym) when ::Sequel::SQL::QualifiedIdentifier then sexpr.table_name else raise ArgumentError, "Invalid table name `#{sexpr.table_name}`" end ::Sequel.as(table_name, ::Sequel.identifier(sexpr.as_name)) end |
#on_table_name(sexpr) ⇒ Object
139 140 141 |
# File 'lib/bmg/sequel/translator.rb', line 139 def on_table_name(sexpr) ::Sequel.expr(sexpr.last.to_sym) end |
#on_with_exp(sexpr) ⇒ Object
11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/bmg/sequel/translator.rb', line 11 def on_with_exp(sexpr) if sequel_db.select(1).supports_cte? dataset = apply(sexpr.select_exp) apply(sexpr.with_spec).each_pair do |name, subquery| dataset = dataset.with(name, subquery) end dataset else apply(Sql::Processor::Flatten.new(Sql::Builder.new).call(sexpr)) end end |
#on_with_spec(sexpr) ⇒ Object
23 24 25 26 27 28 |
# File 'lib/bmg/sequel/translator.rb', line 23 def on_with_spec(sexpr) sexpr.each_with_object({}){|child,hash| next if child == :with_spec hash[apply(child.table_name)] = apply(child.subquery) } end |