123456789_123456789_123456789_123456789_123456789_

Class: Arel::Visitors::ToSql

Do not use. This class is for internal use only.
Relationships & Source Files
Extension / Inclusion / Inheritance Descendants
Subclasses:
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Visitor
Instance Chain:
self, Visitor
Inherits: Arel::Visitors::Visitor
Defined in: activerecord/lib/arel/visitors/to_sql.rb

Constant Summary

Class Method Summary

Instance Attribute Summary

Visitor - Inherited

Instance Method Summary

Visitor - Inherited

Constructor Details

.new(connection) ⇒ ToSql

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 12

def initialize(connection)
  super()
  @connection = connection
end

Instance Method Details

#aggregate(name, o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 996

def aggregate(name, o, collector)
  collector << "#{name}("
  if o.distinct
    collector << "DISTINCT "
  end
  collector = inject_join(o.expressions, collector, ", ") << ")"
  if o.alias
    collector << " AS "
    visit o.alias, collector
  else
    collector
  end
end

#bind_block (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 754

def bind_block; BIND_BLOCK; end

#build_subselect(key, o) (private)

FIXME: we should probably have a 2-pass visitor for this

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 943

def build_subselect(key, o)
  stmt             = Nodes::SelectStatement.new
  core             = stmt.cores.first
  core.froms       = o.relation
  core.wheres      = o.wheres
  core.projections = [key]
  core.groups      = o.groups unless o.groups.empty?
  core.havings     = o.havings unless o.havings.empty?
  stmt.limit       = o.limit
  stmt.offset      = o.offset
  stmt.orders      = o.orders
  stmt
end

#collect_ctes(children, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 1023

def collect_ctes(children, collector)
  children.each_with_index do |child, i|
    collector << ", " unless i == 0
    visit child.to_cte, collector
  end

  collector
end

#collect_nodes_for(nodes, collector, spacer, connector = ", ") (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 179

def collect_nodes_for(nodes, collector, spacer, connector = ", ")
  unless nodes.empty?
    collector << spacer
    inject_join nodes, collector, connector
  end
end

#collect_optimizer_hints(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 887

def collect_optimizer_hints(o, collector)
  maybe_visit o.optimizer_hints, collector
end

#compile(node, collector = Arel::Collectors::SQLString.new)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 17

def compile(node, collector = Arel::Collectors::SQLString.new)
  accept(node, collector).value
end

#grouping_parentheses(o, collector, always_wrap_selects = true) (private)

Used by some visitors to enclose select queries in parentheses

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 981

def grouping_parentheses(o, collector, always_wrap_selects = true)
  if o.is_a?(Nodes::SelectStatement) && (always_wrap_selects || require_parentheses?(o))
    collector << "("
    visit o, collector
    collector << ")"
    collector
  else
    visit o, collector
  end
end

#has_group_by_and_having?(o) ⇒ Boolean (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 917

def has_group_by_and_having?(o)
  !o.groups.empty? && !o.havings.empty?
end

#has_join_sources?(o) ⇒ Boolean (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 909

def has_join_sources?(o)
  o.relation.is_a?(Nodes::JoinSource) && !o.relation.right.empty?
end

#has_limit_or_offset_or_orders?(o) ⇒ Boolean (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 913

def has_limit_or_offset_or_orders?(o)
  o.limit || o.offset || !o.orders.empty?
end

#infix_value(o, collector, value) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 957

def infix_value(o, collector, value)
  collector = visit o.left, collector
  collector << value
  visit o.right, collector
end

#infix_value_with_paren(o, collector, value, suppress_parens = false) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 963

def infix_value_with_paren(o, collector, value, suppress_parens = false)
  collector << "( " unless suppress_parens
  collector = if o.left.class == o.class
    infix_value_with_paren(o.left, collector, value, true)
  else
    grouping_parentheses o.left, collector, false
  end
  collector << value
  collector = if o.right.class == o.class
    infix_value_with_paren(o.right, collector, value, true)
  else
    grouping_parentheses o.right, collector, false
  end
  collector << " )" unless suppress_parens
  collector
end

#inject_join(list, collector, join_str) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 897

def inject_join(list, collector, join_str)
  list.each_with_index do |x, i|
    collector << join_str unless i == 0
    collector = visit(x, collector)
  end
  collector
end

#is_distinct_from(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 1010

def is_distinct_from(o, collector)
  collector << "CASE WHEN "
  collector = visit o.left, collector
  collector << " = "
  collector = visit o.right, collector
  collector << " OR ("
  collector = visit o.left, collector
  collector << " IS NULL AND "
  collector = visit o.right, collector
  collector << " IS NULL)"
  collector << " THEN 0 ELSE 1 END"
end

#maybe_visit(thing, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 891

def maybe_visit(thing, collector)
  return collector unless thing
  collector << " "
  visit thing, collector
end

#prepare_delete_statement(o) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 940

alias :prepare_delete_statement :prepare_update_statement

#prepare_update_statement(o) (private) Also known as: #prepare_delete_statement

The default strategy for an UPDATE with joins is to use a subquery. This doesn’t work on MySQL (even when aliasing the tables), but MySQL allows using JOIN directly in an UPDATE statement, so in the MySQL visitor we redefine this to do that.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 924

def prepare_update_statement(o)
  if o.key && (has_limit_or_offset_or_orders?(o) || has_join_sources?(o))
    stmt = o.clone
    stmt.limit = nil
    stmt.offset = nil
    stmt.orders = []
    columns = Arel::Nodes::Grouping.new(o.key)
    stmt.wheres = [Nodes::In.new(columns, [build_subselect(o.key, o)])]
    stmt.relation = o.relation.left if has_join_sources?(o)
    stmt.groups = o.groups unless o.groups.empty?
    stmt.havings = o.havings unless o.havings.empty?
    stmt
  else
    o
  end
end

#quote(value) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 867

def quote(value)
  return value if Arel::Nodes::SqlLiteral === value
  @connection.quote value
end

#quote_column_name(name) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 877

def quote_column_name(name)
  return name if Arel::Nodes::SqlLiteral === name
  @connection.quote_column_name(name)
end

#quote_table_name(name) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 872

def quote_table_name(name)
  return name if Arel::Nodes::SqlLiteral === name
  @connection.quote_table_name(name)
end

#require_parentheses?(o) ⇒ Boolean (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 992

def require_parentheses?(o)
  !o.orders.empty? || o.limit || o.offset
end

#sanitize_as_sql_comment(value) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 882

def sanitize_as_sql_comment(value)
  return value if Arel::Nodes::SqlLiteral === value
  @connection.sanitize_as_sql_comment(value)
end

#unboundable?(value) ⇒ Boolean (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 905

def unboundable?(value)
  value.respond_to?(:unboundable?) && value.unboundable?
end

#unsupported(o, collector) (private) Also known as: #visit_ActiveSupport_Multibyte_Chars, #visit_ActiveSupport_StringInquirer, #visit_BigDecimal, #visit_Class, #visit_Date, #visit_DateTime, #visit_FalseClass, #visit_Float, #visit_Hash, #visit_NilClass, #visit_String, #visit_Symbol, #visit_Time, #visit_TrueClass

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 828

def unsupported(o, collector)
  raise UnsupportedVisitError.new(o)
end

#visit_ActiveModel_Attribute(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 756

def visit_ActiveModel_Attribute(o, collector)
  collector.add_bind(o, &bind_block)
end

#visit_ActiveSupport_Multibyte_Chars(o, collector) (private)

Alias for #unsupported.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 832

alias :visit_ActiveSupport_Multibyte_Chars :unsupported

#visit_ActiveSupport_StringInquirer(o, collector) (private)

Alias for #unsupported.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 833

alias :visit_ActiveSupport_StringInquirer  :unsupported

#visit_Arel_Attributes_Attribute(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 746

def visit_Arel_Attributes_Attribute(o, collector)
  join_name = o.relation.table_alias || o.relation.name
  collector << quote_table_name(join_name) << "." << quote_column_name(o.name)
end

#visit_Arel_Nodes_And(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 622

def visit_Arel_Nodes_And(o, collector)
  inject_join o.children, collector, " AND "
end

#visit_Arel_Nodes_As(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 693

def visit_Arel_Nodes_As(o, collector)
  collector = visit o.left, collector
  collector << " AS "
  visit o.right, collector
end

#visit_Arel_Nodes_Ascending(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 363

def visit_Arel_Nodes_Ascending(o, collector)
  visit(o.expr, collector) << " ASC"
end

#visit_Arel_Nodes_Assignment(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 630

def visit_Arel_Nodes_Assignment(o, collector)
  case o.right
  when Arel::Nodes::Node, Arel::Attributes::Attribute, ActiveModel::Attribute
    collector = visit o.left, collector
    collector << " = "
    visit o.right, collector
  else
    collector = visit o.left, collector
    collector << " = "
    collector << quote(o.right).to_s
  end
end

#visit_Arel_Nodes_Avg(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 421

def visit_Arel_Nodes_Avg(o, collector)
  aggregate "AVG", o, collector
end

#visit_Arel_Nodes_Between(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 431

def visit_Arel_Nodes_Between(o, collector)
  collector = visit o.left, collector
  collector << " BETWEEN "
  visit o.right, collector
end

#visit_Arel_Nodes_Bin(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 186

def visit_Arel_Nodes_Bin(o, collector)
  visit o.expr, collector
end

#visit_Arel_Nodes_BindParam(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 760

def visit_Arel_Nodes_BindParam(o, collector)
  collector.add_bind(o.value, &bind_block)
end

#visit_Arel_Nodes_BoundSqlLiteral(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 770

def visit_Arel_Nodes_BoundSqlLiteral(o, collector)
  collector.retryable = false
  bind_index = 0

  new_bind = lambda do |value|
    if Arel.arel_node?(value)
      visit value, collector
    elsif value.is_a?(Array)
      if value.empty?
        collector << @connection.quote(nil)
      else
        if value.none? { |v| Arel.arel_node?(v) }
          collector.add_binds(value.map { |v| @connection.cast_bound_value(v) }, &bind_block)
        else
          value.each_with_index do |v, i|
            collector << ", " unless i == 0
            if Arel.arel_node?(v)
              visit v, collector
            else
              collector.add_bind(@connection.cast_bound_value(v), &bind_block)
            end
          end
        end
      end
    else
      collector.add_bind(@connection.cast_bound_value(value), &bind_block)
    end
  end

  if o.positional_binds
    o.sql_with_placeholders.scan(/\?|([^?]+)/) do
      if $1
        collector << $1
      else
        value = o.positional_binds[bind_index]
        bind_index += 1

        new_bind.call(value)
      end
    end
  else
    o.sql_with_placeholders.scan(/:(?<!::)([a-zA-Z]\w*)|([^:]+|.)/) do
      if $2
        collector << $2
      else
        value = o.named_binds[$1.to_sym]
        new_bind.call(value)
      end
    end
  end

  collector
end

#visit_Arel_Nodes_Case(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 699

def visit_Arel_Nodes_Case(o, collector)
  collector << "CASE "
  if o.case
    visit o.case, collector
    collector << " "
  end
  o.conditions.each do |condition|
    visit condition, collector
    collector << " "
  end
  if o.default
    visit o.default, collector
    collector << " "
  end
  collector << "END"
end

#visit_Arel_Nodes_Casted(o, collector) (private) Also known as: #visit_Arel_Nodes_Quoted

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 87

def visit_Arel_Nodes_Casted(o, collector)
  collector << quote(o.value_for_database).to_s
end

#visit_Arel_Nodes_Comment(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 175

def visit_Arel_Nodes_Comment(o, collector)
  collector << o.values.map { |v| "/* #{sanitize_as_sql_comment(v)} */" }.join(" ")
end

#visit_Arel_Nodes_Count(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 405

def visit_Arel_Nodes_Count(o, collector)
  aggregate "COUNT", o, collector
end

#visit_Arel_Nodes_Cte(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 732

def visit_Arel_Nodes_Cte(o, collector)
  collector << quote_table_name(o.name)
  collector << " AS "

  case o.materialized
  when true
    collector << "MATERIALIZED "
  when false
    collector << "NOT MATERIALIZED "
  end

  visit o.relation, collector
end

#visit_Arel_Nodes_CurrentRow(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 296

def visit_Arel_Nodes_CurrentRow(o, collector)
  collector << "CURRENT ROW"
end

#visit_Arel_Nodes_DeleteStatement(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 22

def visit_Arel_Nodes_DeleteStatement(o, collector)
  collector.retryable = false
  o = prepare_delete_statement(o)

  if has_join_sources?(o)
    collector << "DELETE "
    visit o.relation.left, collector
    collector << " FROM "
  else
    collector << "DELETE FROM "
  end
  collector = visit o.relation, collector

  collect_nodes_for o.wheres, collector, " WHERE ", " AND "
  collect_nodes_for o.orders, collector, " ORDER BY "
  maybe_visit o.limit, collector
end

#visit_Arel_Nodes_Descending(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 367

def visit_Arel_Nodes_Descending(o, collector)
  visit(o.expr, collector) << " DESC"
end

#visit_Arel_Nodes_Distinct(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 190

def visit_Arel_Nodes_Distinct(o, collector)
  collector << "DISTINCT"
end

#visit_Arel_Nodes_DistinctOn(o, collector) (private)

Raises:

  • (NotImplementedError)
[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 194

def visit_Arel_Nodes_DistinctOn(o, collector)
  raise NotImplementedError, "DISTINCT ON not implemented for this db"
end

#visit_Arel_Nodes_DoesNotMatch(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 497

def visit_Arel_Nodes_DoesNotMatch(o, collector)
  collector = visit o.left, collector
  collector << " NOT LIKE "
  collector = visit o.right, collector
  if o.escape
    collector << " ESCAPE "
    visit o.escape, collector
  else
    collector
  end
end

#visit_Arel_Nodes_Else(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 723

def visit_Arel_Nodes_Else(o, collector)
  collector << "ELSE "
  visit o.expr, collector
end

#visit_Arel_Nodes_Equality(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 643

def visit_Arel_Nodes_Equality(o, collector)
  right = o.right

  return collector << "1=0" if unboundable?(right)

  collector = visit o.left, collector

  if right.nil?
    collector << " IS NULL"
  else
    collector << " = "
    visit right, collector
  end
end

#visit_Arel_Nodes_Except(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 221

def visit_Arel_Nodes_Except(o, collector)
  collector << "( "
  infix_value(o, collector, " EXCEPT ") << " )"
end

#visit_Arel_Nodes_Exists(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 76

def visit_Arel_Nodes_Exists(o, collector)
  collector << "EXISTS ("
  collector = visit(o.expressions, collector) << ")"
  if o.alias
    collector << " AS "
    visit o.alias, collector
  else
    collector
  end
end

#visit_Arel_Nodes_Extract(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 400

def visit_Arel_Nodes_Extract(o, collector)
  collector << "EXTRACT(#{o.field.to_s.upcase} FROM "
  visit(o.expr, collector) << ")"
end

#visit_Arel_Nodes_False(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 96

def visit_Arel_Nodes_False(o, collector)
  collector << "FALSE"
end

#visit_Arel_Nodes_Filter(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 251

def visit_Arel_Nodes_Filter(o, collector)
  visit o.left, collector
  collector << " FILTER (WHERE "
  visit o.right, collector
  collector << ")"
end

#visit_Arel_Nodes_Following(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 286

def visit_Arel_Nodes_Following(o, collector)
  collector = if o.expr
    visit o.expr, collector
  else
    collector << "UNBOUNDED"
  end

  collector << " FOLLOWING"
end

#visit_Arel_Nodes_Fragments(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 863

def visit_Arel_Nodes_Fragments(o, collector)
  inject_join o.values, collector, " "
end

#visit_Arel_Nodes_FullOuterJoin(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 532

def visit_Arel_Nodes_FullOuterJoin(o, collector)
  collector << "FULL OUTER JOIN "
  collector = visit o.left, collector
  collector << " "
  visit o.right, collector
end

#visit_Arel_Nodes_GreaterThan(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 449

def visit_Arel_Nodes_GreaterThan(o, collector)
  case unboundable?(o.right)
  when 1
    return collector << "1=0"
  when -1
    return collector << "1=1"
  end
  collector = visit o.left, collector
  collector << " > "
  visit o.right, collector
end

#visit_Arel_Nodes_GreaterThanOrEqual(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 437

def visit_Arel_Nodes_GreaterThanOrEqual(o, collector)
  case unboundable?(o.right)
  when 1
    return collector << "1=0"
  when -1
    return collector << "1=1"
  end
  collector = visit o.left, collector
  collector << " >= "
  visit o.right, collector
end

#visit_Arel_Nodes_Group(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 382

def visit_Arel_Nodes_Group(o, collector)
  visit o.expr, collector
end

#visit_Arel_Nodes_Grouping(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 327

def visit_Arel_Nodes_Grouping(o, collector)
  if o.expr.is_a? Nodes::Grouping
    visit(o.expr, collector)
  else
    collector << "("
    visit(o.expr, collector) << ")"
  end
end

#visit_Arel_Nodes_HomogeneousIn(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 336

def visit_Arel_Nodes_HomogeneousIn(o, collector)
  collector.preparable = false

  visit o.left, collector

  if o.type == :in
    collector << " IN ("
  else
    collector << " NOT IN ("
  end

  values = o.casted_values

  if values.empty?
    collector << @connection.quote(nil)
  else
    collector.add_binds(values, o.proc_for_binds, &bind_block)
  end

  collector << ")"
end

#visit_Arel_Nodes_In(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 588

def visit_Arel_Nodes_In(o, collector)
  attr, values = o.left, o.right

  if Array === values
    collector.preparable = false

    unless values.empty?
      values.delete_if { |value| unboundable?(value) }
    end

    return collector << "1=0" if values.empty?
  end

  visit(attr, collector) << " IN ("
  visit(values, collector) << ")"
end

#visit_Arel_Nodes_InfixOperation(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 847

def visit_Arel_Nodes_InfixOperation(o, collector)
  collector = visit o.left, collector
  collector << " #{o.operator} "
  visit o.right, collector
end

#visit_Arel_Nodes_InnerJoin(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 553

def visit_Arel_Nodes_InnerJoin(o, collector)
  collector << "INNER JOIN "
  collector = visit o.left, collector
  if o.right
    collector << " "
    visit(o.right, collector)
  else
    collector
  end
end

#visit_Arel_Nodes_InsertStatement(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 53

def visit_Arel_Nodes_InsertStatement(o, collector)
  collector.retryable = false
  collector << "INSERT INTO "
  collector = visit o.relation, collector

  unless o.columns.empty?
    collector << " ("
    o.columns.each_with_index do |x, i|
      collector << ", " unless i == 0
      collector << quote_column_name(x.name)
    end
    collector << ")"
  end

  if o.values
    maybe_visit o.values, collector
  elsif o.select
    maybe_visit o.select, collector
  else
    collector
  end
end

#visit_Arel_Nodes_Intersect(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 216

def visit_Arel_Nodes_Intersect(o, collector)
  collector << "( "
  infix_value(o, collector, " INTERSECT ") << " )"
end

#visit_Arel_Nodes_IsDistinctFrom(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 668

def visit_Arel_Nodes_IsDistinctFrom(o, collector)
  if o.right.nil?
    collector = visit o.left, collector
    collector << " IS NOT NULL"
  else
    collector = is_distinct_from(o, collector)
    collector << " = 1"
  end
end

#visit_Arel_Nodes_IsNotDistinctFrom(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 658

def visit_Arel_Nodes_IsNotDistinctFrom(o, collector)
  if o.right.nil?
    collector = visit o.left, collector
    collector << " IS NULL"
  else
    collector = is_distinct_from(o, collector)
    collector << " = 0"
  end
end

#visit_Arel_Nodes_JoinSource(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 509

def visit_Arel_Nodes_JoinSource(o, collector)
  if o.left
    collector = visit o.left, collector
  end
  if o.right.any?
    collector << " " if o.left
    collector = inject_join o.right, collector, " "
  end
  collector
end

#visit_Arel_Nodes_LessThan(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 473

def visit_Arel_Nodes_LessThan(o, collector)
  case unboundable?(o.right)
  when 1
    return collector << "1=1"
  when -1
    return collector << "1=0"
  end
  collector = visit o.left, collector
  collector << " < "
  visit o.right, collector
end

#visit_Arel_Nodes_LessThanOrEqual(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 461

def visit_Arel_Nodes_LessThanOrEqual(o, collector)
  case unboundable?(o.right)
  when 1
    return collector << "1=1"
  when -1
    return collector << "1=0"
  end
  collector = visit o.left, collector
  collector << " <= "
  visit o.right, collector
end

#visit_Arel_Nodes_Limit(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 318

def visit_Arel_Nodes_Limit(o, collector)
  collector << "LIMIT "
  visit o.expr, collector
end

#visit_Arel_Nodes_Lock(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 323

def visit_Arel_Nodes_Lock(o, collector)
  visit o.expr, collector
end

#visit_Arel_Nodes_Matches(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 485

def visit_Arel_Nodes_Matches(o, collector)
  collector = visit o.left, collector
  collector << " LIKE "
  collector = visit o.right, collector
  if o.escape
    collector << " ESCAPE "
    visit o.escape, collector
  else
    collector
  end
end

#visit_Arel_Nodes_Max(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 413

def visit_Arel_Nodes_Max(o, collector)
  aggregate "MAX", o, collector
end

#visit_Arel_Nodes_Min(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 417

def visit_Arel_Nodes_Min(o, collector)
  aggregate "MIN", o, collector
end

#visit_Arel_Nodes_NamedFunction(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 386

def visit_Arel_Nodes_NamedFunction(o, collector)
  collector.retryable = false
  collector << o.name
  collector << "("
  collector << "DISTINCT " if o.distinct
  collector = inject_join(o.expressions, collector, ", ") << ")"
  if o.alias
    collector << " AS "
    visit o.alias, collector
  else
    collector
  end
end

#visit_Arel_Nodes_NamedWindow(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 226

def visit_Arel_Nodes_NamedWindow(o, collector)
  collector << quote_column_name(o.name)
  collector << " AS "
  visit_Arel_Nodes_Window o, collector
end

#visit_Arel_Nodes_Not(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 569

def visit_Arel_Nodes_Not(o, collector)
  collector << "NOT ("
  visit(o.expr, collector) << ")"
end

#visit_Arel_Nodes_NotEqual(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 678

def visit_Arel_Nodes_NotEqual(o, collector)
  right = o.right

  return collector << "1=1" if unboundable?(right)

  collector = visit o.left, collector

  if right.nil?
    collector << " IS NOT NULL"
  else
    collector << " != "
    visit right, collector
  end
end

#visit_Arel_Nodes_NotIn(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 605

def visit_Arel_Nodes_NotIn(o, collector)
  attr, values = o.left, o.right

  if Array === values
    collector.preparable = false

    unless values.empty?
      values.delete_if { |value| unboundable?(value) }
    end

    return collector << "1=1" if values.empty?
  end

  visit(attr, collector) << " NOT IN ("
  visit(values, collector) << ")"
end

#visit_Arel_Nodes_NotRegexp(o, collector) (private)

Raises:

  • (NotImplementedError)
[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 524

def visit_Arel_Nodes_NotRegexp(o, collector)
  raise NotImplementedError, "!~ not implemented for this db"
end

#visit_Arel_Nodes_NullsFirst(o, collector) (private)

NullsFirst is available on all but MySQL, where it is redefined.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 372

def visit_Arel_Nodes_NullsFirst(o, collector)
  visit o.expr, collector
  collector << " NULLS FIRST"
end

#visit_Arel_Nodes_NullsLast(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 377

def visit_Arel_Nodes_NullsLast(o, collector)
  visit o.expr, collector
  collector << " NULLS LAST"
end

#visit_Arel_Nodes_Offset(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 313

def visit_Arel_Nodes_Offset(o, collector)
  collector << "OFFSET "
  visit o.expr, collector
end

#visit_Arel_Nodes_On(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 564

def visit_Arel_Nodes_On(o, collector)
  collector << "ON "
  visit o.expr, collector
end

#visit_Arel_Nodes_OptimizerHints(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 170

def visit_Arel_Nodes_OptimizerHints(o, collector)
  hints = o.expr.map { |v| sanitize_as_sql_comment(v) }.join(" ")
  collector << "/*+ #{hints} */"
end

#visit_Arel_Nodes_Or(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 626

def visit_Arel_Nodes_Or(o, collector)
  inject_join o.children, collector, " OR "
end

#visit_Arel_Nodes_OuterJoin(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 539

def visit_Arel_Nodes_OuterJoin(o, collector)
  collector << "LEFT OUTER JOIN "
  collector = visit o.left, collector
  collector << " "
  visit o.right, collector
end

#visit_Arel_Nodes_Over(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 300

def visit_Arel_Nodes_Over(o, collector)
  case o.right
  when nil
    visit(o.left, collector) << " OVER ()"
  when Arel::Nodes::SqlLiteral
    infix_value o, collector, " OVER "
  when String, Symbol
    visit(o.left, collector) << " OVER #{quote_column_name o.right.to_s}"
  else
    infix_value o, collector, " OVER "
  end
end

#visit_Arel_Nodes_Preceding(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 276

def visit_Arel_Nodes_Preceding(o, collector)
  collector = if o.expr
    visit o.expr, collector
  else
    collector << "UNBOUNDED"
  end

  collector << " PRECEDING"
end

#visit_Arel_Nodes_Quoted(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 90

alias :visit_Arel_Nodes_Quoted :visit_Arel_Nodes_Casted

#visit_Arel_Nodes_Range(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 267

def visit_Arel_Nodes_Range(o, collector)
  if o.expr
    collector << "RANGE "
    visit o.expr, collector
  else
    collector << "RANGE"
  end
end

#visit_Arel_Nodes_Regexp(o, collector) (private)

Raises:

  • (NotImplementedError)
[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 520

def visit_Arel_Nodes_Regexp(o, collector)
  raise NotImplementedError, "~ not implemented for this db"
end

#visit_Arel_Nodes_RightOuterJoin(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 546

def visit_Arel_Nodes_RightOuterJoin(o, collector)
  collector << "RIGHT OUTER JOIN "
  collector = visit o.left, collector
  collector << " "
  visit o.right, collector
end

#visit_Arel_Nodes_Rows(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 258

def visit_Arel_Nodes_Rows(o, collector)
  if o.expr
    collector << "ROWS "
    visit o.expr, collector
  else
    collector << "ROWS"
  end
end

#visit_Arel_Nodes_SelectCore(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 149

def visit_Arel_Nodes_SelectCore(o, collector)
  collector << "SELECT"

  collector = collect_optimizer_hints(o, collector)
  collector = maybe_visit o.set_quantifier, collector

  collect_nodes_for o.projections, collector, " "

  if o.source && !o.source.empty?
    collector << " FROM "
    collector = visit o.source, collector
  end

  collect_nodes_for o.wheres, collector, " WHERE ", " AND "
  collect_nodes_for o.groups, collector, " GROUP BY "
  collect_nodes_for o.havings, collector, " HAVING ", " AND "
  collect_nodes_for o.windows, collector, " WINDOW "

  maybe_visit o.comment, collector
end

#visit_Arel_Nodes_SelectOptions(o, collector) (private)

The Oracle enhanced adapter uses this private method, see github.com/rsim/oracle-enhanced/issues/2186

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 143

def visit_Arel_Nodes_SelectOptions(o, collector)
  collector = maybe_visit o.limit, collector
  collector = maybe_visit o.offset, collector
  maybe_visit o.lock, collector
end

#visit_Arel_Nodes_SelectStatement(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 120

def visit_Arel_Nodes_SelectStatement(o, collector)
  if o.with
    collector = visit o.with, collector
    collector << " "
  end

  collector = o.cores.inject(collector) { |c, x|
    visit_Arel_Nodes_SelectCore(x, c)
  }

  unless o.orders.empty?
    collector << " ORDER BY "
    o.orders.each_with_index do |x, i|
      collector << ", " unless i == 0
      collector = visit(x, collector)
    end
  end

  visit_Arel_Nodes_SelectOptions(o, collector)
end

#visit_Arel_Nodes_SqlLiteral(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 764

def visit_Arel_Nodes_SqlLiteral(o, collector)
  collector.preparable = false
  collector.retryable = o.retryable
  collector << o.to_s
end

#visit_Arel_Nodes_StringJoin(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 528

def visit_Arel_Nodes_StringJoin(o, collector)
  visit o.left, collector
end

#visit_Arel_Nodes_Sum(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 409

def visit_Arel_Nodes_Sum(o, collector)
  aggregate "SUM", o, collector
end

#visit_Arel_Nodes_TableAlias(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 425

def visit_Arel_Nodes_TableAlias(o, collector)
  collector = visit o.relation, collector
  collector << " "
  collector << quote_table_name(o.name)
end

#visit_Arel_Nodes_True(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 92

def visit_Arel_Nodes_True(o, collector)
  collector << "TRUE"
end

#visit_Arel_Nodes_UnaryOperation(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 853

def visit_Arel_Nodes_UnaryOperation(o, collector)
  collector << " #{o.operator} "
  visit o.expr, collector
end

#visit_Arel_Nodes_Union(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 208

def visit_Arel_Nodes_Union(o, collector)
  infix_value_with_paren(o, collector, " UNION ")
end

#visit_Arel_Nodes_UnionAll(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 212

def visit_Arel_Nodes_UnionAll(o, collector)
  infix_value_with_paren(o, collector, " UNION ALL ")
end

#visit_Arel_Nodes_UnqualifiedColumn(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 728

def visit_Arel_Nodes_UnqualifiedColumn(o, collector)
  collector << quote_column_name(o.name)
end

#visit_Arel_Nodes_UpdateStatement(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 40

def visit_Arel_Nodes_UpdateStatement(o, collector)
  collector.retryable = false
  o = prepare_update_statement(o)

  collector << "UPDATE "
  collector = visit o.relation, collector
  collect_nodes_for o.values, collector, " SET "

  collect_nodes_for o.wheres, collector, " WHERE ", " AND "
  collect_nodes_for o.orders, collector, " ORDER BY "
  maybe_visit o.limit, collector
end

#visit_Arel_Nodes_ValuesList(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 100

def visit_Arel_Nodes_ValuesList(o, collector)
  collector << "VALUES "

  o.rows.each_with_index do |row, i|
    collector << ", " unless i == 0
    collector << "("
    row.each_with_index do |value, k|
      collector << ", " unless k == 0
      case value
      when Nodes::SqlLiteral, Nodes::BindParam, ActiveModel::Attribute
        collector = visit(value, collector)
      else
        collector << quote(value).to_s
      end
    end
    collector << ")"
  end
  collector
end

#visit_Arel_Nodes_When(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 716

def visit_Arel_Nodes_When(o, collector)
  collector << "WHEN "
  visit o.left, collector
  collector << " THEN "
  visit o.right, collector
end

#visit_Arel_Nodes_Window(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 232

def visit_Arel_Nodes_Window(o, collector)
  collector << "("

  collect_nodes_for o.partitions, collector, "PARTITION BY "

  if o.orders.any?
    collector << " " if o.partitions.any?
    collector << "ORDER BY "
    collector = inject_join o.orders, collector, ", "
  end

  if o.framing
    collector << " " if o.partitions.any? || o.orders.any?
    collector = visit o.framing, collector
  end

  collector << ")"
end

#visit_Arel_Nodes_With(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 198

def visit_Arel_Nodes_With(o, collector)
  collector << "WITH "
  collect_ctes(o.children, collector)
end

#visit_Arel_Nodes_WithRecursive(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 203

def visit_Arel_Nodes_WithRecursive(o, collector)
  collector << "WITH RECURSIVE "
  collect_ctes(o.children, collector)
end

#visit_Arel_SelectManager(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 358

def visit_Arel_SelectManager(o, collector)
  collector << "("
  visit(o.ast, collector) << ")"
end

#visit_Arel_Table(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 574

def visit_Arel_Table(o, collector)
  if Arel::Nodes::Node === o.name
    visit o.name, collector
  else
    collector << quote_table_name(o.name)
  end

  if o.table_alias
    collector << " " << quote_table_name(o.table_alias)
  end

  collector
end

#visit_Array(o, collector) (private) Also known as: #visit_Set

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 858

def visit_Array(o, collector)
  inject_join o, collector, ", "
end

#visit_BigDecimal(o, collector) (private)

Alias for #unsupported.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 834

alias :visit_BigDecimal                    :unsupported

#visit_Class(o, collector) (private)

Alias for #unsupported.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 835

alias :visit_Class                         :unsupported

#visit_Date(o, collector) (private)

Alias for #unsupported.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 836

alias :visit_Date                          :unsupported

#visit_DateTime(o, collector) (private)

Alias for #unsupported.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 837

alias :visit_DateTime                      :unsupported

#visit_FalseClass(o, collector) (private)

Alias for #unsupported.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 838

alias :visit_FalseClass                    :unsupported

#visit_Float(o, collector) (private)

Alias for #unsupported.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 839

alias :visit_Float                         :unsupported

#visit_Hash(o, collector) (private)

Alias for #unsupported.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 840

alias :visit_Hash                          :unsupported

#visit_Integer(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 824

def visit_Integer(o, collector)
  collector << o.to_s
end

#visit_NilClass(o, collector) (private)

Alias for #unsupported.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 841

alias :visit_NilClass                      :unsupported

#visit_Set(o, collector) (private)

Alias for #visit_Array.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 861

alias :visit_Set :visit_Array

#visit_String(o, collector) (private)

Alias for #unsupported.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 842

alias :visit_String                        :unsupported

#visit_Symbol(o, collector) (private)

Alias for #unsupported.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 843

alias :visit_Symbol                        :unsupported

#visit_Time(o, collector) (private)

Alias for #unsupported.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 844

alias :visit_Time                          :unsupported

#visit_TrueClass(o, collector) (private)

Alias for #unsupported.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/to_sql.rb', line 845

alias :visit_TrueClass                     :unsupported