Class: Ronin::Code::SQL::Emitter Private

Inherits:
Object
  • Object
show all
Defined in:
lib/ronin/code/sql/emitter.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Generates raw SQL.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(space: ' ', quotes: :single, syntax: nil, comment: nil, **kwargs) ⇒ Emitter

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Initializes the SQL Emitter.

Parameters:

  • space (String) (defaults to: ' ')

    String to use for white-space.

  • quotes (:single, :double) (defaults to: :single)

    Type of quotes to use for Strings.

  • syntax (nil, :mysql, :postgres, :oracle, :mssql) (defaults to: nil)

    Syntax used during code-generation

  • comment (nil, String) (defaults to: nil)

    String to use as the comment when terminating injection string

  • kwargs (Hash{Symbol => Object})

    Emitter options.

Options Hash (**kwargs):

  • :case (:lower, :upper, :random, nil)

    Case for keywords.



79
80
81
82
83
84
85
# File 'lib/ronin/code/sql/emitter.rb', line 79

def initialize(space: ' ', quotes: :single, syntax: nil, comment: nil, **kwargs)
  @case    = kwargs[:case] # HACK: because `case` is a ruby keyword
  @syntax  = syntax
  @comment = comment
  @space   = space
  @quotes  = quotes
end

Instance Attribute Details

#case:lower, ... (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The case to use when emitting keywords

Returns:

  • (:lower, :upper, :random, nil)


36
37
38
# File 'lib/ronin/code/sql/emitter.rb', line 36

def case
  @case
end

#commentString? (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

String to use as 'comment' or nil to let the emitter decide

Returns:

  • (String, nil)


56
57
58
# File 'lib/ronin/code/sql/emitter.rb', line 56

def comment
  @comment
end

#quotes:single, :double (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Type of String quotes to use

Returns:

  • (:single, :double)


46
47
48
# File 'lib/ronin/code/sql/emitter.rb', line 46

def quotes
  @quotes
end

#spaceString (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

String to use for white-space

Returns:

  • (String)


41
42
43
# File 'lib/ronin/code/sql/emitter.rb', line 41

def space
  @space
end

#syntaxnil, ... (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generate DB-specific code

Returns:

  • (nil, :mysql, :postgres, :oracle, :mssql)


51
52
53
# File 'lib/ronin/code/sql/emitter.rb', line 51

def syntax
  @syntax
end

Instance Method Details

#emit(object) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits a SQL object.

Parameters:

  • object (#to_sql)

    The SQL object.

Returns:

  • (String)

    The raw SQL.

Raises:

  • (ArgumentError)

    Could not emit an unknown SQL object.



336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
# File 'lib/ronin/code/sql/emitter.rb', line 336

def emit(object)
  case object
  when NilClass              then emit_null
  when TrueClass             then emit_true
  when FalseClass            then emit_false
  when Integer               then emit_integer(object)
  when Float                 then emit_decimal(object)
  when String                then emit_string(object)
  when Literal               then emit(object.value)
  when Symbol                then emit_keyword(object)
  when Field                 then emit_field(object)
  when Array                 then emit_list(object)
  when Hash                  then emit_assignments(object)
  when BinaryExpr, UnaryExpr then emit_expression(object)
  when Function              then emit_function(object)
  when Clause                then emit_clause(object)
  when Statement             then emit_statement(object)
  when StatementList         then emit_statement_list(object)
  else
    if object.respond_to?(:to_sql)
      object.to_sql
    else
      raise(ArgumentError,"cannot emit #{object.class}")
    end
  end
end

#emit_argument(operand) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits a value used in an expression.

Parameters:

  • operand (Statement, #to_sql)

    The operand to emit.

Returns:

  • (String)

    The raw SQL.

Since:

  • 1.1.0



270
271
272
273
274
275
# File 'lib/ronin/code/sql/emitter.rb', line 270

def emit_argument(operand)
  case operand
  when Statement then "(#{emit_statement(operand)})"
  else                emit(operand)
  end
end

#emit_assignments(values) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits a list of columns and assigned values.

Parameters:

  • values (Hash{Field,Symbol => Object})

    The column names and values.

Returns:

  • (String)

    The raw SQL.



253
254
255
256
257
# File 'lib/ronin/code/sql/emitter.rb', line 253

def emit_assignments(values)
  values.map { |key,value|
    "#{emit_keyword(key)}=#{emit(value)}"
  }.join(',')
end

#emit_clause(clause) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits a SQL Clause.

Parameters:

  • clause (Clause)

    The SQL Clause.

Returns:

  • (String)

    The raw SQL.



372
373
374
375
376
377
378
379
380
# File 'lib/ronin/code/sql/emitter.rb', line 372

def emit_clause(clause)
  sql = emit_keyword(clause.keyword)

  unless clause.argument.nil?
    sql << @space << emit_argument(clause.argument)
  end

  return sql
end

#emit_clauses(clauses) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits multiple SQL Clauses.

Parameters:

  • clauses (Array<Clause>)

    The clauses to emit.

Returns:

  • (String)

    The emitted clauses.



391
392
393
# File 'lib/ronin/code/sql/emitter.rb', line 391

def emit_clauses(clauses)
  clauses.map { |clause| emit_clause(clause) }.join(@space)
end

#emit_commentString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits a SQL comment.

Returns:

  • (String)

    The raw SQL.

Since:

  • 2.1.0



168
169
170
171
# File 'lib/ronin/code/sql/emitter.rb', line 168

def emit_comment
  # Return chosen comment or default one which works everywhere
  @comment || '-- '
end

#emit_decimal(decimal) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits a SQL Decimal.

Parameters:

  • decimal (Float)

    The decimal.

Returns:

  • (String)

    The raw SQL.



195
196
197
# File 'lib/ronin/code/sql/emitter.rb', line 195

def emit_decimal(decimal)
  decimal.to_s
end

#emit_expression(expr) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits a SQL expression.

Parameters:

Returns:

  • (String)

    The raw SQL.



286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/ronin/code/sql/emitter.rb', line 286

def emit_expression(expr)
  op = emit_operator(expr.operator)

  case expr
  when BinaryExpr
    left  = emit_argument(expr.left)
    right = emit_argument(expr.right)

    case op
    when /^\W+$/ then "#{left}#{op}#{right}"
    else              [left, op, right].join(@space)
    end
  when UnaryExpr
    operand = emit_argument(expr.operand)

    case expr.operator
    when /^\W+$/ then "#{op}#{operand}"
    else              [op, operand].join(@space)
    end
  end
end

#emit_falseString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits a false value.

Returns:

  • (String)

    The raw SQL.



146
147
148
# File 'lib/ronin/code/sql/emitter.rb', line 146

def emit_false
  "1=0"
end

#emit_field(field) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits a SQL field.

Parameters:

  • field (Field, Symbol, String)

    The SQL field.

Returns:

  • (String)

    The raw SQL.



221
222
223
224
225
226
227
228
229
# File 'lib/ronin/code/sql/emitter.rb', line 221

def emit_field(field)
  name = emit_keyword(field.name)

  if field.parent
    name = "#{emit_field(field.parent)}.#{name}"
  end

  return name
end

#emit_function(function) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits a SQL function.

Parameters:

  • function (Function)

    The SQL function.

Returns:

  • (String)

    The raw SQL.



317
318
319
320
321
322
# File 'lib/ronin/code/sql/emitter.rb', line 317

def emit_function(function)
  name      = emit_keyword(function.name)
  arguments = function.arguments.map { |value| emit_argument(value) }

  return "#{name}(#{arguments.join(',')})"
end

#emit_integer(int) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits a SQL Integer.

Parameters:

  • int (Integer)

    The Integer.

Returns:

  • (String)

    The raw SQL.



182
183
184
# File 'lib/ronin/code/sql/emitter.rb', line 182

def emit_integer(int)
  int.to_s
end

#emit_keyword(keyword) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits a SQL keyword.

Parameters:

  • keyword (Symbol, Array<Symbol>)

    The SQL keyword.

Returns:

  • (String)

    The raw SQL.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/ronin/code/sql/emitter.rb', line 96

def emit_keyword(keyword)
  string = Array(keyword).join(@space)

  case @case
  when :upper  then string.upcase
  when :lower  then string.downcase
  when :random
    string.tap do
      (string.length / 2).times do
        index = rand(string.length)

        string[index] = string[index].swapcase
      end
    end
  else
    string
  end
end

#emit_list(list) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits a list of elements.

Parameters:

  • list (#map)

    The list of elements.

Returns:

  • (String)

    The raw SQL.



240
241
242
# File 'lib/ronin/code/sql/emitter.rb', line 240

def emit_list(list)
  "(#{list.map { |element| emit(element) }.join(',')})"
end

#emit_nullString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits the NULL value.

Returns:

  • (String)


136
137
138
# File 'lib/ronin/code/sql/emitter.rb', line 136

def emit_null
  emit_keyword(:NULL)
end

#emit_operator(operator) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits a SQL operator.

Parameters:

  • operator (Array<Symbol>, Symbol)

    The operator symbol.

Returns:

  • (String)

    The raw SQL.



124
125
126
127
128
129
# File 'lib/ronin/code/sql/emitter.rb', line 124

def emit_operator(operator)
  case operator
  when /^\W+$/ then operator.to_s
  else              emit_keyword(operator)
  end
end

#emit_statement(stmt) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits a SQL Statement.

Parameters:

Returns:

  • (String)

    The raw SQL.



404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
# File 'lib/ronin/code/sql/emitter.rb', line 404

def emit_statement(stmt)
  sql = emit_keyword(stmt.keyword)

  unless stmt.argument.nil?
    sql << @space << case stmt.argument
                     when Array
                       if stmt.argument.length == 1
                         emit_argument(stmt.argument[0])
                       else
                         emit_list(stmt.argument)
                       end
                     else
                       emit_argument(stmt.argument)
                     end
  end

  unless stmt.clauses.empty?
    sql << @space << emit_clauses(stmt.clauses)
  end

  return sql
end

#emit_statement_list(list) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits a full SQL statement list.

Parameters:

Returns:

  • (String)

    The raw SQL.



436
437
438
439
440
# File 'lib/ronin/code/sql/emitter.rb', line 436

def emit_statement_list(list)
  list.statements.map { |stmt|
    emit_statement(stmt)
  }.join(";#{@space}")
end

#emit_string(string) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits a SQL String.

Parameters:

  • string (String)

    The String.

Returns:

  • (String)

    The raw SQL.



208
209
210
# File 'lib/ronin/code/sql/emitter.rb', line 208

def emit_string(string)
  Support::Encoding::SQL.escape(string, quotes: @quotes)
end

#emit_trueString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Emits a true value.

Returns:

  • (String)

    The raw SQL.



156
157
158
# File 'lib/ronin/code/sql/emitter.rb', line 156

def emit_true
  "1=1"
end