123456789_123456789_123456789_123456789_123456789_

Class: Arel::Visitors::SQLite

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/sqlite.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

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

Queries used in UNION should not be wrapped by parentheses, because it is an invalid syntax in SQLite.

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/sqlite.rb', line 106

def infix_value_with_paren(o, collector, value, suppress_parens = false)
  collector << "( " unless suppress_parens

  left = o.left.is_a?(Nodes::Grouping) ? o.left.expr : o.left
  collector = if left.class == o.class
    infix_value_with_paren(left, collector, value, true)
  else
    grouping_parentheses left, collector, false
  end

  collector << value

  right = o.right.is_a?(Nodes::Grouping) ? o.right.expr : o.right
  collector = if right.class == o.class
    infix_value_with_paren(right, collector, value, true)
  else
    grouping_parentheses right, collector, false
  end

  collector << " )" unless suppress_parens
  collector
end

#prepare_update_statement(o) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/sqlite.rb', line 60

def prepare_update_statement(o)
  # Sqlite need to be built with the SQLITE_ENABLE_UPDATE_DELETE_LIMIT compile-time option
  # to support LIMIT/OFFSET/ORDER in UPDATE and DELETE statements.
  if has_join_sources?(o) && !has_limit_or_offset_or_orders?(o) && !has_group_by_and_having?(o) &&
    # The SQLite3 dialect isn't flexible enough to allow anything other than a inner join
    # for the first join:
    #   UPDATE table SET .. FROM joined_table WHERE ...
    (o.relation.right.all? { |join| join.is_a?(Arel::Nodes::InnerJoin) || join.right.expr.right.relation != o.relation.left })
    o
  else
    super
  end
end

#visit_Arel_Nodes_False(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/sqlite.rb', line 88

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

#visit_Arel_Nodes_IsDistinctFrom(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/sqlite.rb', line 98

def visit_Arel_Nodes_IsDistinctFrom(o, collector)
  collector = visit o.left, collector
  collector << " IS NOT "
  visit o.right, collector
end

#visit_Arel_Nodes_IsNotDistinctFrom(o, collector) (private)

[ GitHub ]

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

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

#visit_Arel_Nodes_Lock(o, collector) (private)

Locks are not supported in SQLite

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/sqlite.rb', line 75

def visit_Arel_Nodes_Lock(o, collector)
  collector
end

#visit_Arel_Nodes_SelectStatement(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/sqlite.rb', line 79

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

#visit_Arel_Nodes_True(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/sqlite.rb', line 84

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

#visit_Arel_Nodes_UpdateStatement(o, collector) (private)

[ GitHub ]

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

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

  collector << "UPDATE "

  # UPDATE with JOIN is in the form of:
  #
  #   UPDATE t1
  #   SET ..
  #   FROM t2
  #   WHERE t1.join_id = t2.join_id
  #
  # Or if more than one join is present:
  #
  #   UPDATE t1
  #   SET ..
  #   FROM t2
  #   JOIN t3 ON t2.join_id = t3.join_id
  #   WHERE t1.join_id = t2.join_id
  if has_join_sources?(o)
    visit o.relation.left, collector
    collect_nodes_for o.values, collector, " SET "

    collector << " FROM "
    first_join, *remaining_joins = o.relation.right
    from_items = remaining_joins.extract! do |join|
      join.right.expr.right.relation == o.relation.left
    end

    from_where = [first_join.left] + from_items.map(&:left)
    collect_nodes_for from_where, collector, " ", ", "

    if remaining_joins && !remaining_joins.empty?
      collector << " "
      remaining_joins.each do |join|
        visit join, collector
        collector << " "
      end
    end

    from_where = [first_join.right.expr] + from_items.map { |i| i.right.expr }
    collect_nodes_for from_where + o.wheres, collector, " WHERE ", " AND "
  else
    collector = visit o.relation, collector
    collect_nodes_for o.values, collector, " SET "
    collect_nodes_for o.wheres, collector, " WHERE ", " AND "
  end

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