Class: Mxrb::Oql::Translator

Inherits:
Object
  • Object
show all
Defined in:
lib/mxrb/oql.rb

Overview

Converts the deliberately small, safe OQL read subset into inspectable SQL. rubocop:disable Metrics/ClassLength

Defined Under Namespace

Classes: Token

Constant Summary collapse

DIALECTS =
%i[ansi postgresql sql_server].freeze
SPACE =
/\s/
WORD_START =
/[A-Za-z_]/
WORD_BODY =
/[A-Za-z0-9_$]/
TAIL_CLAUSES =
%w[ORDER LIMIT OFFSET UNION].freeze
ALIAS_STOP_WORDS =
%w[
  FULL GROUP HAVING INNER JOIN LEFT LIMIT OFFSET ON ORDER OUTER RIGHT
  SELECT UNION WHERE
].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dialect: :postgresql) ⇒ Translator

Returns a new instance of Translator.

Raises:

  • (ArgumentError)


145
146
147
148
# File 'lib/mxrb/oql.rb', line 145

def initialize(dialect: :postgresql)
  @dialect = dialect.to_sym
  raise ArgumentError, "unsupported SQL dialect #{@dialect.inspect}" unless DIALECTS.include?(@dialect)
end

Class Method Details

.parameters(source) ⇒ Object



150
151
152
153
154
# File 'lib/mxrb/oql.rb', line 150

def self.parameters(source)
  new.send(:tokenize, source).filter_map do |token|
    token.text.delete_prefix('$') if token.type == :parameter
  end.uniq.freeze
end

Instance Method Details

#translate(query) ⇒ Object

rubocop:disable Metrics/AbcSize, Metrics/MethodLength



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/mxrb/oql.rb', line 166

def translate(query)
  tokens = tokenize(query.oql)
  warning = validation_warning(tokens)
  return unsupported(query, warning) if warning

  tokens = reorder_from_first(tokens)
  association = association_path(tokens)
  return unsupported(query, association) if association

  aliases = translate_entities!(tokens)
  translate_attributes!(tokens, aliases)
  translate_parameters!(tokens)
  sql = tokens.map(&:text).join.strip
  SqlView.new(
    query, sql.freeze, @dialect, :logical,
    [physical_mapping_warning].freeze, query.parameters
  )
end

#translate_source(source, name: 'AdHoc') ⇒ Object



156
157
158
159
160
161
162
163
# File 'lib/mxrb/oql.rb', line 156

def translate_source(source, name: 'AdHoc')
  text = source.to_s
  query = Query.new(
    'adhoc', name, name, :oql, text.freeze, nil, [].freeze,
    'Oql$AdHoc', self.class.parameters(text)
  )
  translate(query)
end