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 93
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 34
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 o.key && has_join_sources?(o) && !has_group_by_and_having?(o) && !has_limit_or_offset_or_orders?(o)
    # Join clauses cannot reference the target table, so alias the
    # updated table, place the entire relation in the FROM clause, and
    # add a self-join (which requires the primary key)
    stmt = o.clone
    stmt.relation, stmt.wheres = o.relation.clone, o.wheres.clone
    stmt.relation.right = [stmt.relation.left, *stmt.relation.right]
    stmt.relation.left = stmt.relation.left.alias("__active_record_update_alias")
    Array.wrap(o.key).each do |key|
      stmt.wheres << key.eq(stmt.relation.left[key.name])
    end
    stmt
  else
    super
  end
end

#visit_Arel_Nodes_False(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/sqlite.rb', line 75
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 85
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 79
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 62
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 66
def visit_Arel_Nodes_SelectStatement(o, collector)
  o.limit = Arel::Nodes::Limit.new(-1) if o.offset && !o.limit
  super
end

#visit_Arel_Nodes_TableAlias(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/sqlite.rb', line 54
def visit_Arel_Nodes_TableAlias(o, collector)
  # "AS" is not optional in "{UPDATE | DELETE} table AS alias ..."
  collector = visit o.relation, collector
  collector << " AS "
  collector << quote_table_name(o.name)
end

#visit_Arel_Nodes_True(o, collector) (private)

[ GitHub ]

  
# File 'activerecord/lib/arel/visitors/sqlite.rb', line 71
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 AS __active_record_update_alias
  #   SET ..
  #   FROM t1 JOIN t2 ON t2.join_id = t1.join_id ..
  #   WHERE t1.id = __active_record_update_alias.id AND ..
  if has_join_sources?(o)
    collector = visit o.relation.left, collector
    collect_nodes_for o.values, collector, " SET "
    collector << " FROM "
    collector = inject_join o.relation.right, collector, " "
  else
    collector = visit o.relation, collector
    collect_nodes_for o.values, collector, " SET "
  end

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