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

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.

#prepare_update_statement_with_self_join

Used by dialects that support UPDATE ...

#quote, #quote_column_name, #quote_table_name, #require_parentheses?, #sanitize_as_sql_comment, #unboundable?, #unsupported, #visit_ActiveModel_Attribute, #visit_ActiveRecord_PredicateBuilder_ComparisonAttribute, #visit_ActiveRecord_PredicateBuilder_ComparisonValue,
#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_CaseInsensitiveEquality, #visit_Arel_Nodes_CaseSensitiveEquality, #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 https://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 97

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::SelectManager::DISTINCT
  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 93

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 85

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 11

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 38

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 76

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 53

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 47

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 62

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 66

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 71

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 58

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 33

def visit_Arel_Nodes_SelectCore(o, collector)
  o.froms ||= DUAL
  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. https://dev.mysql.com/doc/refman/en/select.html

[ GitHub ]

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

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 17

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