123456789_123456789_123456789_123456789_123456789_

Class: Arel::Visitors::MySQL

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

Constant Summary

ToSql - Inherited

BIND_BLOCK

Class Method Summary

ToSql - Inherited

Visitor - Inherited

Instance Attribute Summary

Visitor - Inherited

Instance Method Summary

ToSql - Inherited

#compile, #aggregate, #bind_block,
#build_subselect

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

#collect_ctes, #collect_nodes_for, #collect_optimizer_hints,
#grouping_parentheses

Used by some visitors to enclose select queries in parentheses.

#has_group_by_and_having?, #has_join_sources?, #has_limit_or_offset_or_orders?, #infix_value, #infix_value_with_paren, #inject_join, #is_distinct_from, #maybe_visit,
#prepare_delete_statement
#prepare_update_statement

The default strategy for an UPDATE with joins is to use a subquery.

#quote, #quote_column_name, #quote_table_name, #require_parentheses?, #sanitize_as_sql_comment, #unboundable?, #unsupported, #visit_ActiveModel_Attribute,
#visit_ActiveSupport_Multibyte_Chars
#visit_ActiveSupport_StringInquirer
#visit_Arel_Attributes_Attribute, #visit_Arel_Nodes_And, #visit_Arel_Nodes_As, #visit_Arel_Nodes_Ascending, #visit_Arel_Nodes_Assignment, #visit_Arel_Nodes_Avg, #visit_Arel_Nodes_Between, #visit_Arel_Nodes_Bin, #visit_Arel_Nodes_BindParam, #visit_Arel_Nodes_BoundSqlLiteral, #visit_Arel_Nodes_Case, #visit_Arel_Nodes_Casted, #visit_Arel_Nodes_Comment, #visit_Arel_Nodes_Count, #visit_Arel_Nodes_Cte, #visit_Arel_Nodes_CurrentRow, #visit_Arel_Nodes_DeleteStatement, #visit_Arel_Nodes_Descending, #visit_Arel_Nodes_Distinct, #visit_Arel_Nodes_DistinctOn, #visit_Arel_Nodes_DoesNotMatch, #visit_Arel_Nodes_Else, #visit_Arel_Nodes_Equality, #visit_Arel_Nodes_Except, #visit_Arel_Nodes_Exists, #visit_Arel_Nodes_Extract, #visit_Arel_Nodes_False, #visit_Arel_Nodes_Filter, #visit_Arel_Nodes_Following, #visit_Arel_Nodes_Fragments, #visit_Arel_Nodes_FullOuterJoin, #visit_Arel_Nodes_GreaterThan, #visit_Arel_Nodes_GreaterThanOrEqual, #visit_Arel_Nodes_Group, #visit_Arel_Nodes_Grouping, #visit_Arel_Nodes_HomogeneousIn, #visit_Arel_Nodes_In, #visit_Arel_Nodes_InfixOperation, #visit_Arel_Nodes_InnerJoin, #visit_Arel_Nodes_InsertStatement, #visit_Arel_Nodes_Intersect, #visit_Arel_Nodes_IsDistinctFrom, #visit_Arel_Nodes_IsNotDistinctFrom, #visit_Arel_Nodes_JoinSource, #visit_Arel_Nodes_LessThan, #visit_Arel_Nodes_LessThanOrEqual, #visit_Arel_Nodes_Limit, #visit_Arel_Nodes_Lock, #visit_Arel_Nodes_Matches, #visit_Arel_Nodes_Max, #visit_Arel_Nodes_Min, #visit_Arel_Nodes_NamedFunction, #visit_Arel_Nodes_NamedWindow, #visit_Arel_Nodes_Not, #visit_Arel_Nodes_NotEqual, #visit_Arel_Nodes_NotIn, #visit_Arel_Nodes_NotRegexp,
#visit_Arel_Nodes_NullsFirst

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

#visit_Arel_Nodes_NullsLast, #visit_Arel_Nodes_Offset, #visit_Arel_Nodes_On, #visit_Arel_Nodes_OptimizerHints, #visit_Arel_Nodes_Or, #visit_Arel_Nodes_OuterJoin, #visit_Arel_Nodes_Over, #visit_Arel_Nodes_Preceding,
#visit_Arel_Nodes_Quoted
#visit_Arel_Nodes_Range, #visit_Arel_Nodes_Regexp, #visit_Arel_Nodes_RightOuterJoin, #visit_Arel_Nodes_Rows, #visit_Arel_Nodes_SelectCore,
#visit_Arel_Nodes_SelectOptions

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

#visit_Arel_Nodes_SelectStatement, #visit_Arel_Nodes_SqlLiteral, #visit_Arel_Nodes_StringJoin, #visit_Arel_Nodes_Sum, #visit_Arel_Nodes_TableAlias, #visit_Arel_Nodes_True, #visit_Arel_Nodes_UnaryOperation, #visit_Arel_Nodes_Union, #visit_Arel_Nodes_UnionAll, #visit_Arel_Nodes_UnqualifiedColumn, #visit_Arel_Nodes_UpdateStatement, #visit_Arel_Nodes_ValuesList, #visit_Arel_Nodes_When, #visit_Arel_Nodes_Window, #visit_Arel_Nodes_With, #visit_Arel_Nodes_WithRecursive, #visit_Arel_SelectManager, #visit_Arel_Table, #visit_Array,
#visit_BigDecimal
#visit_Class
#visit_Date
#visit_DateTime
#visit_FalseClass
#visit_Float
#visit_Hash
#visit_Integer,
#visit_NilClass
#visit_Set
#visit_String
#visit_Symbol
#visit_Time
#visit_TrueClass

Visitor - Inherited

Constructor Details

This class inherits a constructor from Arel::Visitors::ToSql

Instance Method Details

#build_subselect(key, o) (private)

MySQL doesn’t automatically create a temporary table for use subquery, so we have to give it some prompting in the form of a subsubquery.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/mysql.rb', line 93

def build_subselect(key, o)
  subselect = super

  # Materialize subquery by adding distinct
  # to work with MySQL 5.7.6 which sets optimizer_switch='derived_merge=on'
  unless has_limit_or_offset_or_orders?(subselect)
    core = subselect.cores.last
    core.set_quantifier = Arel::Nodes::Distinct.new
  end

  Nodes::SelectStatement.new.tap do |stmt|
    core = stmt.cores.last
    core.froms = Nodes::Grouping.new(subselect).as("__active_record_temp")
    core.projections = [Arel.sql(quote_column_name(key.name), retryable: true)]
  end
end

#prepare_delete_statement(o) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/mysql.rb', line 89

alias :prepare_delete_statement :prepare_update_statement

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

In the simple case, MySQL allows us to place JOINs directly into the UPDATE query. However, this does not allow for LIMIT, OFFSET and ORDER. To support these, we must use a subquery.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/mysql.rb', line 81

def prepare_update_statement(o)
  if o.offset || has_group_by_and_having?(o) ||
    has_join_sources?(o) && has_limit_or_offset_or_orders?(o)
    super
  else
    o
  end
end

#visit_Arel_Nodes_Bin(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/mysql.rb', line 7

def visit_Arel_Nodes_Bin(o, collector)
  collector << "CAST("
  visit o.expr, collector
  collector << " AS BINARY)"
end

#visit_Arel_Nodes_Concat(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/mysql.rb', line 34

def visit_Arel_Nodes_Concat(o, collector)
  collector << " CONCAT("
  visit o.left, collector
  collector << ", "
  visit o.right, collector
  collector << ") "
  collector
end

#visit_Arel_Nodes_Cte(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/mysql.rb', line 72

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

#visit_Arel_Nodes_IsDistinctFrom(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/mysql.rb', line 49

def visit_Arel_Nodes_IsDistinctFrom(o, collector)
  collector << "NOT "
  visit_Arel_Nodes_IsNotDistinctFrom o, collector
end

#visit_Arel_Nodes_IsNotDistinctFrom(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/mysql.rb', line 43

def visit_Arel_Nodes_IsNotDistinctFrom(o, collector)
  collector = visit o.left, collector
  collector << " <=> "
  visit o.right, collector
end

#visit_Arel_Nodes_NotRegexp(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/mysql.rb', line 58

def visit_Arel_Nodes_NotRegexp(o, collector)
  infix_value o, collector, " NOT REGEXP "
end

#visit_Arel_Nodes_NullsFirst(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/mysql.rb', line 62

def visit_Arel_Nodes_NullsFirst(o, collector)
  visit(o.expr.expr, collector) << " IS NOT NULL, "
  visit(o.expr, collector)
end

#visit_Arel_Nodes_NullsLast(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/mysql.rb', line 67

def visit_Arel_Nodes_NullsLast(o, collector)
  visit(o.expr.expr, collector) << " IS NULL, "
  visit(o.expr, collector)
end

#visit_Arel_Nodes_Regexp(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/mysql.rb', line 54

def visit_Arel_Nodes_Regexp(o, collector)
  infix_value o, collector, " REGEXP "
end

#visit_Arel_Nodes_SelectCore(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/mysql.rb', line 29

def visit_Arel_Nodes_SelectCore(o, collector)
  o.froms ||= Arel.sql("DUAL", retryable: true)
  super
end

#visit_Arel_Nodes_SelectStatement(o, collector) (private)

:‘( To retrieve all rows from a certain offset up to the end of the result set, you can use some large number for the second parameter. dev.mysql.com/doc/refman/en/select.html

[ GitHub ]

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

def visit_Arel_Nodes_SelectStatement(o, collector)
  if o.offset && !o.limit
    o.limit = Arel::Nodes::Limit.new(18446744073709551615)
  end
  super
end

#visit_Arel_Nodes_UnqualifiedColumn(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/mysql.rb', line 13

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