From 4c0a3d48804a363c7e9272519665a21f601b5248 Mon Sep 17 00:00:00 2001 From: Matthew Draper Date: Sat, 24 Feb 2018 17:15:50 +1030 Subject: Arel: rubocop -a --- activerecord/lib/arel.rb | 55 +- activerecord/lib/arel/alias_predication.rb | 5 +- activerecord/lib/arel/attributes.rb | 5 +- activerecord/lib/arel/attributes/attribute.rb | 1 + activerecord/lib/arel/collectors/bind.rb | 4 +- activerecord/lib/arel/collectors/composite.rb | 6 +- activerecord/lib/arel/collectors/plain_string.rb | 5 +- activerecord/lib/arel/collectors/sql_string.rb | 6 +- .../lib/arel/collectors/substitute_binds.rb | 7 +- activerecord/lib/arel/compatibility/wheres.rb | 3 +- activerecord/lib/arel/crud.rb | 6 +- activerecord/lib/arel/delete_manager.rb | 7 +- activerecord/lib/arel/errors.rb | 1 + activerecord/lib/arel/expressions.rb | 6 +- activerecord/lib/arel/factory_methods.rb | 17 +- activerecord/lib/arel/insert_manager.rb | 11 +- activerecord/lib/arel/math.rb | 1 + activerecord/lib/arel/nodes.rb | 87 +- activerecord/lib/arel/nodes/and.rb | 5 +- activerecord/lib/arel/nodes/ascending.rb | 3 +- activerecord/lib/arel/nodes/binary.rb | 7 +- activerecord/lib/arel/nodes/bind_param.rb | 1 + activerecord/lib/arel/nodes/case.rb | 13 +- activerecord/lib/arel/nodes/casted.rb | 23 +- activerecord/lib/arel/nodes/count.rb | 3 +- activerecord/lib/arel/nodes/delete_statement.rb | 7 +- activerecord/lib/arel/nodes/descending.rb | 3 +- activerecord/lib/arel/nodes/equality.rb | 1 + activerecord/lib/arel/nodes/extract.rb | 5 +- activerecord/lib/arel/nodes/false.rb | 3 +- activerecord/lib/arel/nodes/full_outer_join.rb | 1 + activerecord/lib/arel/nodes/function.rb | 8 +- activerecord/lib/arel/nodes/grouping.rb | 1 + activerecord/lib/arel/nodes/in.rb | 1 + activerecord/lib/arel/nodes/infix_operation.rb | 26 +- activerecord/lib/arel/nodes/inner_join.rb | 1 + activerecord/lib/arel/nodes/insert_statement.rb | 5 +- activerecord/lib/arel/nodes/join_source.rb | 3 +- activerecord/lib/arel/nodes/matches.rb | 1 + activerecord/lib/arel/nodes/named_function.rb | 5 +- activerecord/lib/arel/nodes/node.rb | 9 +- activerecord/lib/arel/nodes/node_expression.rb | 2 + activerecord/lib/arel/nodes/outer_join.rb | 1 + activerecord/lib/arel/nodes/over.rb | 7 +- activerecord/lib/arel/nodes/regexp.rb | 1 + activerecord/lib/arel/nodes/right_outer_join.rb | 1 + activerecord/lib/arel/nodes/select_core.rb | 7 +- activerecord/lib/arel/nodes/select_statement.rb | 7 +- activerecord/lib/arel/nodes/sql_literal.rb | 1 + activerecord/lib/arel/nodes/string_join.rb | 3 +- activerecord/lib/arel/nodes/table_alias.rb | 3 +- activerecord/lib/arel/nodes/terminal.rb | 3 +- activerecord/lib/arel/nodes/true.rb | 3 +- activerecord/lib/arel/nodes/unary.rb | 5 +- activerecord/lib/arel/nodes/unary_operation.rb | 6 +- activerecord/lib/arel/nodes/unqualified_column.rb | 1 + activerecord/lib/arel/nodes/update_statement.rb | 5 +- activerecord/lib/arel/nodes/values.rb | 3 +- activerecord/lib/arel/nodes/values_list.rb | 3 +- activerecord/lib/arel/nodes/window.rb | 17 +- activerecord/lib/arel/nodes/with.rb | 2 +- activerecord/lib/arel/order_predications.rb | 3 +- activerecord/lib/arel/predications.rb | 117 +- activerecord/lib/arel/select_manager.rb | 81 +- activerecord/lib/arel/table.rb | 29 +- activerecord/lib/arel/tree_manager.rb | 7 +- activerecord/lib/arel/update_manager.rb | 17 +- activerecord/lib/arel/visitors.rb | 27 +- activerecord/lib/arel/visitors/depth_first.rb | 373 +++--- activerecord/lib/arel/visitors/dot.rb | 447 +++---- activerecord/lib/arel/visitors/ibm_db.rb | 12 +- activerecord/lib/arel/visitors/informix.rb | 82 +- activerecord/lib/arel/visitors/mssql.rb | 177 +-- activerecord/lib/arel/visitors/mysql.rb | 127 +- activerecord/lib/arel/visitors/oracle.rb | 250 ++-- activerecord/lib/arel/visitors/oracle12.rb | 87 +- activerecord/lib/arel/visitors/postgresql.rb | 155 +-- activerecord/lib/arel/visitors/sqlite.rb | 30 +- activerecord/lib/arel/visitors/to_sql.rb | 1239 ++++++++++---------- activerecord/lib/arel/visitors/visitor.rb | 43 +- activerecord/lib/arel/visitors/where_sql.rb | 15 +- activerecord/lib/arel/window_predications.rb | 5 +- 82 files changed, 1916 insertions(+), 1856 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/arel.rb b/activerecord/lib/arel.rb index c327caeac0..2d5cfa4d5c 100644 --- a/activerecord/lib/arel.rb +++ b/activerecord/lib/arel.rb @@ -1,38 +1,39 @@ # frozen_string_literal: true -require 'arel/errors' - -require 'arel/crud' -require 'arel/factory_methods' - -require 'arel/expressions' -require 'arel/predications' -require 'arel/window_predications' -require 'arel/math' -require 'arel/alias_predication' -require 'arel/order_predications' -require 'arel/table' -require 'arel/attributes' -require 'arel/compatibility/wheres' - -require 'arel/visitors' -require 'arel/collectors/sql_string' - -require 'arel/tree_manager' -require 'arel/insert_manager' -require 'arel/select_manager' -require 'arel/update_manager' -require 'arel/delete_manager' -require 'arel/nodes' + +require "arel/errors" + +require "arel/crud" +require "arel/factory_methods" + +require "arel/expressions" +require "arel/predications" +require "arel/window_predications" +require "arel/math" +require "arel/alias_predication" +require "arel/order_predications" +require "arel/table" +require "arel/attributes" +require "arel/compatibility/wheres" + +require "arel/visitors" +require "arel/collectors/sql_string" + +require "arel/tree_manager" +require "arel/insert_manager" +require "arel/select_manager" +require "arel/update_manager" +require "arel/delete_manager" +require "arel/nodes" module Arel - VERSION = '10.0.0' + VERSION = "10.0.0" - def self.sql raw_sql + def self.sql(raw_sql) Arel::Nodes::SqlLiteral.new raw_sql end def self.star - sql '*' + sql "*" end ## Convenience Alias Node = Arel::Nodes::Node diff --git a/activerecord/lib/arel/alias_predication.rb b/activerecord/lib/arel/alias_predication.rb index cb50fb95be..ae44157b9a 100644 --- a/activerecord/lib/arel/alias_predication.rb +++ b/activerecord/lib/arel/alias_predication.rb @@ -1,8 +1,9 @@ # frozen_string_literal: true + module Arel module AliasPredication - def as other + def as(other) Nodes::As.new self, Nodes::SqlLiteral.new(other) end end -end \ No newline at end of file +end diff --git a/activerecord/lib/arel/attributes.rb b/activerecord/lib/arel/attributes.rb index ed4739ebed..c81a7b941b 100644 --- a/activerecord/lib/arel/attributes.rb +++ b/activerecord/lib/arel/attributes.rb @@ -1,11 +1,12 @@ # frozen_string_literal: true -require 'arel/attributes/attribute' + +require "arel/attributes/attribute" module Arel module Attributes ### # Factory method to wrap a raw database +column+ to an Arel Attribute. - def self.for column + def self.for(column) case column.type when :string, :text, :binary then String when :integer then Integer diff --git a/activerecord/lib/arel/attributes/attribute.rb b/activerecord/lib/arel/attributes/attribute.rb index 41bc0c32c7..71f839479a 100644 --- a/activerecord/lib/arel/attributes/attribute.rb +++ b/activerecord/lib/arel/attributes/attribute.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Attributes class Attribute < Struct.new :relation, :name diff --git a/activerecord/lib/arel/collectors/bind.rb b/activerecord/lib/arel/collectors/bind.rb index d816aed90d..8d19e7446d 100644 --- a/activerecord/lib/arel/collectors/bind.rb +++ b/activerecord/lib/arel/collectors/bind.rb @@ -7,11 +7,11 @@ module Arel @binds = [] end - def << str + def <<(str) self end - def add_bind bind + def add_bind(bind) @binds << bind self end diff --git a/activerecord/lib/arel/collectors/composite.rb b/activerecord/lib/arel/collectors/composite.rb index 4f6156fe27..675a819596 100644 --- a/activerecord/lib/arel/collectors/composite.rb +++ b/activerecord/lib/arel/collectors/composite.rb @@ -8,13 +8,13 @@ module Arel @right = right end - def << str + def <<(str) left << str right << str self end - def add_bind bind, &block + def add_bind(bind, &block) left.add_bind bind, &block right.add_bind bind, &block self @@ -26,7 +26,7 @@ module Arel protected - attr_reader :left, :right + attr_reader :left, :right end end end diff --git a/activerecord/lib/arel/collectors/plain_string.rb b/activerecord/lib/arel/collectors/plain_string.rb index 1e8d2a2152..b98802c44a 100644 --- a/activerecord/lib/arel/collectors/plain_string.rb +++ b/activerecord/lib/arel/collectors/plain_string.rb @@ -1,16 +1,17 @@ # frozen_string_literal: true + module Arel module Collectors class PlainString def initialize - @str = ''.dup + @str = "".dup end def value @str end - def << str + def <<(str) @str << str self end diff --git a/activerecord/lib/arel/collectors/sql_string.rb b/activerecord/lib/arel/collectors/sql_string.rb index bcb941f6d4..78c9e48aab 100644 --- a/activerecord/lib/arel/collectors/sql_string.rb +++ b/activerecord/lib/arel/collectors/sql_string.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'arel/collectors/plain_string' +require "arel/collectors/plain_string" module Arel module Collectors @@ -10,13 +10,13 @@ module Arel @bind_index = 1 end - def add_bind bind + def add_bind(bind) self << yield(@bind_index) @bind_index += 1 self end - def compile bvs + def compile(bvs) value end end diff --git a/activerecord/lib/arel/collectors/substitute_binds.rb b/activerecord/lib/arel/collectors/substitute_binds.rb index 99d2215aaa..ee6635f914 100644 --- a/activerecord/lib/arel/collectors/substitute_binds.rb +++ b/activerecord/lib/arel/collectors/substitute_binds.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Collectors class SubstituteBinds @@ -7,12 +8,12 @@ module Arel @delegate = delegate_collector end - def << str + def <<(str) delegate << str self end - def add_bind bind + def add_bind(bind) self << quoter.quote(bind) end @@ -22,7 +23,7 @@ module Arel protected - attr_reader :quoter, :delegate + attr_reader :quoter, :delegate end end end diff --git a/activerecord/lib/arel/compatibility/wheres.rb b/activerecord/lib/arel/compatibility/wheres.rb index 3e60894bd8..2ffb2e0ad8 100644 --- a/activerecord/lib/arel/compatibility/wheres.rb +++ b/activerecord/lib/arel/compatibility/wheres.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Compatibility # :nodoc: class Wheres # :nodoc: @@ -15,7 +16,7 @@ module Arel end end - def initialize engine, collection + def initialize(engine, collection) @engine = engine @collection = collection end diff --git a/activerecord/lib/arel/crud.rb b/activerecord/lib/arel/crud.rb index 2d10432205..e2427b730c 100644 --- a/activerecord/lib/arel/crud.rb +++ b/activerecord/lib/arel/crud.rb @@ -1,9 +1,10 @@ # frozen_string_literal: true + module Arel ### # FIXME hopefully we can remove this module Crud - def compile_update values, pk + def compile_update(values, pk) um = UpdateManager.new if Nodes::SqlLiteral === values @@ -20,7 +21,7 @@ module Arel um end - def compile_insert values + def compile_insert(values) im = create_insert im.insert values im @@ -37,6 +38,5 @@ module Arel dm.from @ctx.froms dm end - end end diff --git a/activerecord/lib/arel/delete_manager.rb b/activerecord/lib/arel/delete_manager.rb index aee4511249..df1f92bd23 100644 --- a/activerecord/lib/arel/delete_manager.rb +++ b/activerecord/lib/arel/delete_manager.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel class DeleteManager < Arel::TreeManager def initialize @@ -7,17 +8,17 @@ module Arel @ctx = @ast end - def from relation + def from(relation) @ast.relation = relation self end - def take limit + def take(limit) @ast.limit = Nodes::Limit.new(Nodes.build_quoted(limit)) if limit self end - def wheres= list + def wheres=(list) @ast.wheres = list end end diff --git a/activerecord/lib/arel/errors.rb b/activerecord/lib/arel/errors.rb index 86fbb80461..8733b7ff5a 100644 --- a/activerecord/lib/arel/errors.rb +++ b/activerecord/lib/arel/errors.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel class ArelError < StandardError end diff --git a/activerecord/lib/arel/expressions.rb b/activerecord/lib/arel/expressions.rb index 612a0942f1..597b861b6c 100644 --- a/activerecord/lib/arel/expressions.rb +++ b/activerecord/lib/arel/expressions.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true + module Arel module Expressions - def count distinct = false + def count(distinct = false) Nodes::Count.new [self], distinct end @@ -21,9 +22,8 @@ module Arel Nodes::Avg.new [self] end - def extract field + def extract(field) Nodes::Extract.new [self], field end - end end diff --git a/activerecord/lib/arel/factory_methods.rb b/activerecord/lib/arel/factory_methods.rb index 6647c5ac44..55aea3ecd7 100644 --- a/activerecord/lib/arel/factory_methods.rb +++ b/activerecord/lib/arel/factory_methods.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel ### # Methods for creating various nodes @@ -11,34 +12,34 @@ module Arel Arel::Nodes::False.new end - def create_table_alias relation, name + def create_table_alias(relation, name) Nodes::TableAlias.new(relation, name) end - def create_join to, constraint = nil, klass = Nodes::InnerJoin + def create_join(to, constraint = nil, klass = Nodes::InnerJoin) klass.new(to, constraint) end - def create_string_join to + def create_string_join(to) create_join to, nil, Nodes::StringJoin end - def create_and clauses + def create_and(clauses) Nodes::And.new clauses end - def create_on expr + def create_on(expr) Nodes::On.new expr end - def grouping expr + def grouping(expr) Nodes::Grouping.new expr end ### # Create a LOWER() function - def lower column - Nodes::NamedFunction.new 'LOWER', [Nodes.build_quoted(column)] + def lower(column) + Nodes::NamedFunction.new "LOWER", [Nodes.build_quoted(column)] end end end diff --git a/activerecord/lib/arel/insert_manager.rb b/activerecord/lib/arel/insert_manager.rb index dcbac6cb43..47b52d6515 100644 --- a/activerecord/lib/arel/insert_manager.rb +++ b/activerecord/lib/arel/insert_manager.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel class InsertManager < Arel::TreeManager def initialize @@ -6,19 +7,19 @@ module Arel @ast = Nodes::InsertStatement.new end - def into table + def into(table) @ast.relation = table self end def columns; @ast.columns end - def values= val; @ast.values = val; end + def values=(val); @ast.values = val; end - def select select + def select(select) @ast.select = select end - def insert fields + def insert(fields) return if fields.empty? if String === fields @@ -37,7 +38,7 @@ module Arel self end - def create_values values, columns + def create_values(values, columns) Nodes::Values.new values, columns end diff --git a/activerecord/lib/arel/math.rb b/activerecord/lib/arel/math.rb index 9e6549b58f..671457efff 100644 --- a/activerecord/lib/arel/math.rb +++ b/activerecord/lib/arel/math.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Math def *(other) diff --git a/activerecord/lib/arel/nodes.rb b/activerecord/lib/arel/nodes.rb index 8c6572dd6a..5af0e532e2 100644 --- a/activerecord/lib/arel/nodes.rb +++ b/activerecord/lib/arel/nodes.rb @@ -1,66 +1,67 @@ # frozen_string_literal: true + # node -require 'arel/nodes/node' -require 'arel/nodes/node_expression' -require 'arel/nodes/select_statement' -require 'arel/nodes/select_core' -require 'arel/nodes/insert_statement' -require 'arel/nodes/update_statement' -require 'arel/nodes/bind_param' +require "arel/nodes/node" +require "arel/nodes/node_expression" +require "arel/nodes/select_statement" +require "arel/nodes/select_core" +require "arel/nodes/insert_statement" +require "arel/nodes/update_statement" +require "arel/nodes/bind_param" # terminal -require 'arel/nodes/terminal' -require 'arel/nodes/true' -require 'arel/nodes/false' +require "arel/nodes/terminal" +require "arel/nodes/true" +require "arel/nodes/false" # unary -require 'arel/nodes/unary' -require 'arel/nodes/grouping' -require 'arel/nodes/ascending' -require 'arel/nodes/descending' -require 'arel/nodes/unqualified_column' -require 'arel/nodes/with' +require "arel/nodes/unary" +require "arel/nodes/grouping" +require "arel/nodes/ascending" +require "arel/nodes/descending" +require "arel/nodes/unqualified_column" +require "arel/nodes/with" # binary -require 'arel/nodes/binary' -require 'arel/nodes/equality' -require 'arel/nodes/in' # Why is this subclassed from equality? -require 'arel/nodes/join_source' -require 'arel/nodes/delete_statement' -require 'arel/nodes/table_alias' -require 'arel/nodes/infix_operation' -require 'arel/nodes/unary_operation' -require 'arel/nodes/over' -require 'arel/nodes/matches' -require 'arel/nodes/regexp' +require "arel/nodes/binary" +require "arel/nodes/equality" +require "arel/nodes/in" # Why is this subclassed from equality? +require "arel/nodes/join_source" +require "arel/nodes/delete_statement" +require "arel/nodes/table_alias" +require "arel/nodes/infix_operation" +require "arel/nodes/unary_operation" +require "arel/nodes/over" +require "arel/nodes/matches" +require "arel/nodes/regexp" # nary -require 'arel/nodes/and' +require "arel/nodes/and" # function # FIXME: Function + Alias can be rewritten as a Function and Alias node. # We should make Function a Unary node and deprecate the use of "aliaz" -require 'arel/nodes/function' -require 'arel/nodes/count' -require 'arel/nodes/extract' -require 'arel/nodes/values' -require 'arel/nodes/values_list' -require 'arel/nodes/named_function' +require "arel/nodes/function" +require "arel/nodes/count" +require "arel/nodes/extract" +require "arel/nodes/values" +require "arel/nodes/values_list" +require "arel/nodes/named_function" # windows -require 'arel/nodes/window' +require "arel/nodes/window" # conditional expressions -require 'arel/nodes/case' +require "arel/nodes/case" # joins -require 'arel/nodes/full_outer_join' -require 'arel/nodes/inner_join' -require 'arel/nodes/outer_join' -require 'arel/nodes/right_outer_join' -require 'arel/nodes/string_join' +require "arel/nodes/full_outer_join" +require "arel/nodes/inner_join" +require "arel/nodes/outer_join" +require "arel/nodes/right_outer_join" +require "arel/nodes/string_join" -require 'arel/nodes/sql_literal' +require "arel/nodes/sql_literal" -require 'arel/nodes/casted' +require "arel/nodes/casted" diff --git a/activerecord/lib/arel/nodes/and.rb b/activerecord/lib/arel/nodes/and.rb index 1e2f61cf43..e76d4f3933 100644 --- a/activerecord/lib/arel/nodes/and.rb +++ b/activerecord/lib/arel/nodes/and.rb @@ -1,10 +1,11 @@ # frozen_string_literal: true + module Arel module Nodes class And < Arel::Nodes::Node attr_reader :children - def initialize children + def initialize(children) super() @children = children end @@ -21,7 +22,7 @@ module Arel children.hash end - def eql? other + def eql?(other) self.class == other.class && self.children == other.children end diff --git a/activerecord/lib/arel/nodes/ascending.rb b/activerecord/lib/arel/nodes/ascending.rb index adadab55e4..7ee531734f 100644 --- a/activerecord/lib/arel/nodes/ascending.rb +++ b/activerecord/lib/arel/nodes/ascending.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true + module Arel module Nodes class Ascending < Ordering - def reverse Descending.new(expr) end @@ -18,7 +18,6 @@ module Arel def descending? false end - end end end diff --git a/activerecord/lib/arel/nodes/binary.rb b/activerecord/lib/arel/nodes/binary.rb index a86d4e4696..e6a5cb63df 100644 --- a/activerecord/lib/arel/nodes/binary.rb +++ b/activerecord/lib/arel/nodes/binary.rb @@ -1,16 +1,17 @@ # frozen_string_literal: true + module Arel module Nodes class Binary < Arel::Nodes::NodeExpression attr_accessor :left, :right - def initialize left, right + def initialize(left, right) super() @left = left @right = right end - def initialize_copy other + def initialize_copy(other) super @left = @left.clone if @left @right = @right.clone if @right @@ -20,7 +21,7 @@ module Arel [self.class, @left, @right].hash end - def eql? other + def eql?(other) self.class == other.class && self.left == other.left && self.right == other.right diff --git a/activerecord/lib/arel/nodes/bind_param.rb b/activerecord/lib/arel/nodes/bind_param.rb index efa4f452d4..1cc1886c2a 100644 --- a/activerecord/lib/arel/nodes/bind_param.rb +++ b/activerecord/lib/arel/nodes/bind_param.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class BindParam < Node diff --git a/activerecord/lib/arel/nodes/case.rb b/activerecord/lib/arel/nodes/case.rb index 50ea1e0be2..22c2da98dd 100644 --- a/activerecord/lib/arel/nodes/case.rb +++ b/activerecord/lib/arel/nodes/case.rb @@ -1,31 +1,32 @@ # frozen_string_literal: true + module Arel module Nodes class Case < Arel::Nodes::Node attr_accessor :case, :conditions, :default - def initialize expression = nil, default = nil + def initialize(expression = nil, default = nil) @case = expression @conditions = [] @default = default end - def when condition, expression = nil + def when(condition, expression = nil) @conditions << When.new(Nodes.build_quoted(condition), expression) self end - def then expression + def then(expression) @conditions.last.right = Nodes.build_quoted(expression) self end - def else expression + def else(expression) @default = Else.new Nodes.build_quoted(expression) self end - def initialize_copy other + def initialize_copy(other) super @case = @case.clone if @case @conditions = @conditions.map { |x| x.clone } @@ -36,7 +37,7 @@ module Arel [@case, @conditions, @default].hash end - def eql? other + def eql?(other) self.class == other.class && self.case == other.case && self.conditions == other.conditions && diff --git a/activerecord/lib/arel/nodes/casted.rb b/activerecord/lib/arel/nodes/casted.rb index f945063dd2..c701e7ff41 100644 --- a/activerecord/lib/arel/nodes/casted.rb +++ b/activerecord/lib/arel/nodes/casted.rb @@ -1,9 +1,10 @@ # frozen_string_literal: true + module Arel module Nodes class Casted < Arel::Nodes::NodeExpression # :nodoc: attr_reader :val, :attribute - def initialize val, attribute + def initialize(val, attribute) @val = val @attribute = attribute super() @@ -15,7 +16,7 @@ module Arel [self.class, val, attribute].hash end - def eql? other + def eql?(other) self.class == other.class && self.val == other.val && self.attribute == other.attribute @@ -28,17 +29,17 @@ module Arel def nil?; val.nil?; end end - def self.build_quoted other, attribute = nil + def self.build_quoted(other, attribute = nil) case other - when Arel::Nodes::Node, Arel::Attributes::Attribute, Arel::Table, Arel::Nodes::BindParam, Arel::SelectManager, Arel::Nodes::Quoted, Arel::Nodes::SqlLiteral - other + when Arel::Nodes::Node, Arel::Attributes::Attribute, Arel::Table, Arel::Nodes::BindParam, Arel::SelectManager, Arel::Nodes::Quoted, Arel::Nodes::SqlLiteral + other + else + case attribute + when Arel::Attributes::Attribute + Casted.new other, attribute else - case attribute - when Arel::Attributes::Attribute - Casted.new other, attribute - else - Quoted.new other - end + Quoted.new other + end end end end diff --git a/activerecord/lib/arel/nodes/count.rb b/activerecord/lib/arel/nodes/count.rb index 4dd9be453f..3f138738ef 100644 --- a/activerecord/lib/arel/nodes/count.rb +++ b/activerecord/lib/arel/nodes/count.rb @@ -1,10 +1,11 @@ # frozen_string_literal: true + module Arel module Nodes class Count < Arel::Nodes::Function include Math - def initialize expr, distinct = false, aliaz = nil + def initialize(expr, distinct = false, aliaz = nil) super(expr, aliaz) @distinct = distinct end diff --git a/activerecord/lib/arel/nodes/delete_statement.rb b/activerecord/lib/arel/nodes/delete_statement.rb index 063a5341e5..1aad4199cd 100644 --- a/activerecord/lib/arel/nodes/delete_statement.rb +++ b/activerecord/lib/arel/nodes/delete_statement.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class DeleteStatement < Arel::Nodes::Node @@ -10,13 +11,13 @@ module Arel alias :wheres :right alias :wheres= :right= - def initialize relation = nil, wheres = [] + def initialize(relation = nil, wheres = []) super() @left = relation @right = wheres end - def initialize_copy other + def initialize_copy(other) super @left = @left.clone if @left @right = @right.clone if @right @@ -26,7 +27,7 @@ module Arel [self.class, @left, @right].hash end - def eql? other + def eql?(other) self.class == other.class && self.left == other.left && self.right == other.right diff --git a/activerecord/lib/arel/nodes/descending.rb b/activerecord/lib/arel/nodes/descending.rb index d7261ab583..afcb6b1b71 100644 --- a/activerecord/lib/arel/nodes/descending.rb +++ b/activerecord/lib/arel/nodes/descending.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true + module Arel module Nodes class Descending < Ordering - def reverse Ascending.new(expr) end @@ -18,7 +18,6 @@ module Arel def descending? true end - end end end diff --git a/activerecord/lib/arel/nodes/equality.rb b/activerecord/lib/arel/nodes/equality.rb index ef44725e24..4ed545ae17 100644 --- a/activerecord/lib/arel/nodes/equality.rb +++ b/activerecord/lib/arel/nodes/equality.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class Equality < Arel::Nodes::Binary diff --git a/activerecord/lib/arel/nodes/extract.rb b/activerecord/lib/arel/nodes/extract.rb index fdf3004c6a..56069cd05a 100644 --- a/activerecord/lib/arel/nodes/extract.rb +++ b/activerecord/lib/arel/nodes/extract.rb @@ -1,10 +1,11 @@ # frozen_string_literal: true + module Arel module Nodes class Extract < Arel::Nodes::Unary attr_accessor :field - def initialize expr, field + def initialize(expr, field) super(expr) @field = field end @@ -13,7 +14,7 @@ module Arel super ^ @field.hash end - def eql? other + def eql?(other) super && self.field == other.field end diff --git a/activerecord/lib/arel/nodes/false.rb b/activerecord/lib/arel/nodes/false.rb index 58132a2f90..1759a323e3 100644 --- a/activerecord/lib/arel/nodes/false.rb +++ b/activerecord/lib/arel/nodes/false.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class False < Arel::Nodes::NodeExpression @@ -6,7 +7,7 @@ module Arel self.class.hash end - def eql? other + def eql?(other) self.class == other.class end alias :== :eql? diff --git a/activerecord/lib/arel/nodes/full_outer_join.rb b/activerecord/lib/arel/nodes/full_outer_join.rb index 12a02d8cd9..3551855201 100644 --- a/activerecord/lib/arel/nodes/full_outer_join.rb +++ b/activerecord/lib/arel/nodes/full_outer_join.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class FullOuterJoin < Arel::Nodes::Join diff --git a/activerecord/lib/arel/nodes/function.rb b/activerecord/lib/arel/nodes/function.rb index b3bf8f3e51..f3415da12b 100644 --- a/activerecord/lib/arel/nodes/function.rb +++ b/activerecord/lib/arel/nodes/function.rb @@ -1,18 +1,19 @@ # frozen_string_literal: true + module Arel module Nodes class Function < Arel::Nodes::NodeExpression include Arel::WindowPredications attr_accessor :expressions, :alias, :distinct - def initialize expr, aliaz = nil + def initialize(expr, aliaz = nil) super() @expressions = expr @alias = aliaz && SqlLiteral.new(aliaz) @distinct = false end - def as aliaz + def as(aliaz) self.alias = SqlLiteral.new(aliaz) self end @@ -21,14 +22,13 @@ module Arel [@expressions, @alias, @distinct].hash end - def eql? other + def eql?(other) self.class == other.class && self.expressions == other.expressions && self.alias == other.alias && self.distinct == other.distinct end alias :== :eql? - end %w{ diff --git a/activerecord/lib/arel/nodes/grouping.rb b/activerecord/lib/arel/nodes/grouping.rb index ffe66654ce..b371b01612 100644 --- a/activerecord/lib/arel/nodes/grouping.rb +++ b/activerecord/lib/arel/nodes/grouping.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class Grouping < Unary diff --git a/activerecord/lib/arel/nodes/in.rb b/activerecord/lib/arel/nodes/in.rb index 30cd771c40..5d24d34528 100644 --- a/activerecord/lib/arel/nodes/in.rb +++ b/activerecord/lib/arel/nodes/in.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class In < Equality diff --git a/activerecord/lib/arel/nodes/infix_operation.rb b/activerecord/lib/arel/nodes/infix_operation.rb index 4eb7c5356f..501da11730 100644 --- a/activerecord/lib/arel/nodes/infix_operation.rb +++ b/activerecord/lib/arel/nodes/infix_operation.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true + module Arel module Nodes - class InfixOperation < Binary include Arel::Expressions include Arel::Predications @@ -11,68 +11,68 @@ module Arel attr_reader :operator - def initialize operator, left, right + def initialize(operator, left, right) super(left, right) @operator = operator end end class Multiplication < InfixOperation - def initialize left, right + def initialize(left, right) super(:*, left, right) end end class Division < InfixOperation - def initialize left, right + def initialize(left, right) super(:/, left, right) end end class Addition < InfixOperation - def initialize left, right + def initialize(left, right) super(:+, left, right) end end class Subtraction < InfixOperation - def initialize left, right + def initialize(left, right) super(:-, left, right) end end class Concat < InfixOperation - def initialize left, right - super('||', left, right) + def initialize(left, right) + super("||", left, right) end end class BitwiseAnd < InfixOperation - def initialize left, right + def initialize(left, right) super(:&, left, right) end end class BitwiseOr < InfixOperation - def initialize left, right + def initialize(left, right) super(:|, left, right) end end class BitwiseXor < InfixOperation - def initialize left, right + def initialize(left, right) super(:^, left, right) end end class BitwiseShiftLeft < InfixOperation - def initialize left, right + def initialize(left, right) super(:<<, left, right) end end class BitwiseShiftRight < InfixOperation - def initialize left, right + def initialize(left, right) super(:>>, left, right) end end diff --git a/activerecord/lib/arel/nodes/inner_join.rb b/activerecord/lib/arel/nodes/inner_join.rb index 4e398267c3..8af99c2dae 100644 --- a/activerecord/lib/arel/nodes/inner_join.rb +++ b/activerecord/lib/arel/nodes/inner_join.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class InnerJoin < Arel::Nodes::Join diff --git a/activerecord/lib/arel/nodes/insert_statement.rb b/activerecord/lib/arel/nodes/insert_statement.rb index 72793bc1ad..206d05e74f 100644 --- a/activerecord/lib/arel/nodes/insert_statement.rb +++ b/activerecord/lib/arel/nodes/insert_statement.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class InsertStatement < Arel::Nodes::Node @@ -12,7 +13,7 @@ module Arel @select = nil end - def initialize_copy other + def initialize_copy(other) super @columns = @columns.clone @values = @values.clone if @values @@ -23,7 +24,7 @@ module Arel [@relation, @columns, @values, @select].hash end - def eql? other + def eql?(other) self.class == other.class && self.relation == other.relation && self.columns == other.columns && diff --git a/activerecord/lib/arel/nodes/join_source.rb b/activerecord/lib/arel/nodes/join_source.rb index 428ce8183e..9d009e8081 100644 --- a/activerecord/lib/arel/nodes/join_source.rb +++ b/activerecord/lib/arel/nodes/join_source.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes ### @@ -7,7 +8,7 @@ module Arel # http://www.sqlite.org/syntaxdiagrams.html#join-source class JoinSource < Arel::Nodes::Binary - def initialize single_source, joinop = [] + def initialize(single_source, joinop = []) super end diff --git a/activerecord/lib/arel/nodes/matches.rb b/activerecord/lib/arel/nodes/matches.rb index 3ad3850a8e..607efe86dc 100644 --- a/activerecord/lib/arel/nodes/matches.rb +++ b/activerecord/lib/arel/nodes/matches.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class Matches < Binary diff --git a/activerecord/lib/arel/nodes/named_function.rb b/activerecord/lib/arel/nodes/named_function.rb index 173838a7fd..1d0baf2885 100644 --- a/activerecord/lib/arel/nodes/named_function.rb +++ b/activerecord/lib/arel/nodes/named_function.rb @@ -1,10 +1,11 @@ # frozen_string_literal: true + module Arel module Nodes class NamedFunction < Arel::Nodes::Function attr_accessor :name - def initialize name, expr, aliaz = nil + def initialize(name, expr, aliaz = nil) super(expr, aliaz) @name = name end @@ -13,7 +14,7 @@ module Arel super ^ @name.hash end - def eql? other + def eql?(other) super && self.name == other.name end alias :== :eql? diff --git a/activerecord/lib/arel/nodes/node.rb b/activerecord/lib/arel/nodes/node.rb index d2e6313dda..e2ce0a676d 100644 --- a/activerecord/lib/arel/nodes/node.rb +++ b/activerecord/lib/arel/nodes/node.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes ### @@ -27,13 +28,13 @@ module Arel ### # Factory method to create a Nodes::Grouping node that has an Nodes::Or # node as a child. - def or right + def or(right) Nodes::Grouping.new Nodes::Or.new(self, right) end ### # Factory method to create an Nodes::And node. - def and right + def and(right) Nodes::And.new [self, right] end @@ -42,14 +43,14 @@ module Arel # can find a node that has a "relation" member. # # Maybe we should just use `Table.engine`? :'( - def to_sql engine = Table.engine + def to_sql(engine = Table.engine) collector = Arel::Collectors::SQLString.new collector = engine.connection.visitor.accept self, collector collector.value end # Iterate through AST, nodes will be yielded depth-first - def each &block + def each(&block) return enum_for(:each) unless block_given? ::Arel::Visitors::DepthFirst.new(block).accept self diff --git a/activerecord/lib/arel/nodes/node_expression.rb b/activerecord/lib/arel/nodes/node_expression.rb index c4d4c8f428..e69e3262d5 100644 --- a/activerecord/lib/arel/nodes/node_expression.rb +++ b/activerecord/lib/arel/nodes/node_expression.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Arel module Nodes class NodeExpression < Arel::Nodes::Node diff --git a/activerecord/lib/arel/nodes/outer_join.rb b/activerecord/lib/arel/nodes/outer_join.rb index c568655fe6..2440be1f03 100644 --- a/activerecord/lib/arel/nodes/outer_join.rb +++ b/activerecord/lib/arel/nodes/outer_join.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class OuterJoin < Arel::Nodes::Join diff --git a/activerecord/lib/arel/nodes/over.rb b/activerecord/lib/arel/nodes/over.rb index 47a34e69ea..57baebe9b3 100644 --- a/activerecord/lib/arel/nodes/over.rb +++ b/activerecord/lib/arel/nodes/over.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true + module Arel module Nodes - class Over < Binary include Arel::AliasPredication @@ -9,8 +9,7 @@ module Arel super(left, right) end - def operator; 'OVER' end + def operator; "OVER" end end - end -end \ No newline at end of file +end diff --git a/activerecord/lib/arel/nodes/regexp.rb b/activerecord/lib/arel/nodes/regexp.rb index 8a76185ef0..a2da51c135 100644 --- a/activerecord/lib/arel/nodes/regexp.rb +++ b/activerecord/lib/arel/nodes/regexp.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class Regexp < Binary diff --git a/activerecord/lib/arel/nodes/right_outer_join.rb b/activerecord/lib/arel/nodes/right_outer_join.rb index 04ab31ebf0..910eb0fa1f 100644 --- a/activerecord/lib/arel/nodes/right_outer_join.rb +++ b/activerecord/lib/arel/nodes/right_outer_join.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class RightOuterJoin < Arel::Nodes::Join diff --git a/activerecord/lib/arel/nodes/select_core.rb b/activerecord/lib/arel/nodes/select_core.rb index fa1c026107..1686761bd5 100644 --- a/activerecord/lib/arel/nodes/select_core.rb +++ b/activerecord/lib/arel/nodes/select_core.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class SelectCore < Arel::Nodes::Node @@ -23,14 +24,14 @@ module Arel @source.left end - def from= value + def from=(value) @source.left = value end alias :froms= :from= alias :froms :from - def initialize_copy other + def initialize_copy(other) super @source = @source.clone if @source @projections = @projections.clone @@ -47,7 +48,7 @@ module Arel ].hash end - def eql? other + def eql?(other) self.class == other.class && self.source == other.source && self.top == other.top && diff --git a/activerecord/lib/arel/nodes/select_statement.rb b/activerecord/lib/arel/nodes/select_statement.rb index 79176d4be5..d1c42dba3b 100644 --- a/activerecord/lib/arel/nodes/select_statement.rb +++ b/activerecord/lib/arel/nodes/select_statement.rb @@ -1,11 +1,12 @@ # frozen_string_literal: true + module Arel module Nodes class SelectStatement < Arel::Nodes::NodeExpression attr_reader :cores attr_accessor :limit, :orders, :lock, :offset, :with - def initialize cores = [SelectCore.new] + def initialize(cores = [SelectCore.new]) super() @cores = cores @orders = [] @@ -15,7 +16,7 @@ module Arel @with = nil end - def initialize_copy other + def initialize_copy(other) super @cores = @cores.map { |x| x.clone } @orders = @orders.map { |x| x.clone } @@ -25,7 +26,7 @@ module Arel [@cores, @orders, @limit, @lock, @offset, @with].hash end - def eql? other + def eql?(other) self.class == other.class && self.cores == other.cores && self.orders == other.orders && diff --git a/activerecord/lib/arel/nodes/sql_literal.rb b/activerecord/lib/arel/nodes/sql_literal.rb index 73575a7d49..1ee496f285 100644 --- a/activerecord/lib/arel/nodes/sql_literal.rb +++ b/activerecord/lib/arel/nodes/sql_literal.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class SqlLiteral < String diff --git a/activerecord/lib/arel/nodes/string_join.rb b/activerecord/lib/arel/nodes/string_join.rb index 21d6845c45..ba3f5f9535 100644 --- a/activerecord/lib/arel/nodes/string_join.rb +++ b/activerecord/lib/arel/nodes/string_join.rb @@ -1,8 +1,9 @@ # frozen_string_literal: true + module Arel module Nodes class StringJoin < Arel::Nodes::Join - def initialize left, right = nil + def initialize(left, right = nil) super end end diff --git a/activerecord/lib/arel/nodes/table_alias.rb b/activerecord/lib/arel/nodes/table_alias.rb index 78deb175b6..37ad786d44 100644 --- a/activerecord/lib/arel/nodes/table_alias.rb +++ b/activerecord/lib/arel/nodes/table_alias.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class TableAlias < Arel::Nodes::Binary @@ -6,7 +7,7 @@ module Arel alias :relation :left alias :table_alias :name - def [] name + def [](name) Attribute.new(self, name) end diff --git a/activerecord/lib/arel/nodes/terminal.rb b/activerecord/lib/arel/nodes/terminal.rb index 3a1cd7f0e1..7cfd2eba4b 100644 --- a/activerecord/lib/arel/nodes/terminal.rb +++ b/activerecord/lib/arel/nodes/terminal.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class Distinct < Arel::Nodes::NodeExpression @@ -6,7 +7,7 @@ module Arel self.class.hash end - def eql? other + def eql?(other) self.class == other.class end alias :== :eql? diff --git a/activerecord/lib/arel/nodes/true.rb b/activerecord/lib/arel/nodes/true.rb index fdb8ed2095..8de1f7522f 100644 --- a/activerecord/lib/arel/nodes/true.rb +++ b/activerecord/lib/arel/nodes/true.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class True < Arel::Nodes::NodeExpression @@ -6,7 +7,7 @@ module Arel self.class.hash end - def eql? other + def eql?(other) self.class == other.class end alias :== :eql? diff --git a/activerecord/lib/arel/nodes/unary.rb b/activerecord/lib/arel/nodes/unary.rb index e458d87ab3..27dd2c1ddf 100644 --- a/activerecord/lib/arel/nodes/unary.rb +++ b/activerecord/lib/arel/nodes/unary.rb @@ -1,11 +1,12 @@ # frozen_string_literal: true + module Arel module Nodes class Unary < Arel::Nodes::NodeExpression attr_accessor :expr alias :value :expr - def initialize expr + def initialize(expr) super() @expr = expr end @@ -14,7 +15,7 @@ module Arel @expr.hash end - def eql? other + def eql?(other) self.class == other.class && self.expr == other.expr end diff --git a/activerecord/lib/arel/nodes/unary_operation.rb b/activerecord/lib/arel/nodes/unary_operation.rb index be4e270e76..a64346d278 100644 --- a/activerecord/lib/arel/nodes/unary_operation.rb +++ b/activerecord/lib/arel/nodes/unary_operation.rb @@ -1,18 +1,18 @@ # frozen_string_literal: true + module Arel module Nodes - class UnaryOperation < Unary attr_reader :operator - def initialize operator, operand + def initialize(operator, operand) super(operand) @operator = operator end end class BitwiseNot < UnaryOperation - def initialize operand + def initialize(operand) super(:~, operand) end end diff --git a/activerecord/lib/arel/nodes/unqualified_column.rb b/activerecord/lib/arel/nodes/unqualified_column.rb index f9017238c8..216a35bc30 100644 --- a/activerecord/lib/arel/nodes/unqualified_column.rb +++ b/activerecord/lib/arel/nodes/unqualified_column.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class UnqualifiedColumn < Arel::Nodes::Unary diff --git a/activerecord/lib/arel/nodes/update_statement.rb b/activerecord/lib/arel/nodes/update_statement.rb index 286f0bd3ce..5cce1e3615 100644 --- a/activerecord/lib/arel/nodes/update_statement.rb +++ b/activerecord/lib/arel/nodes/update_statement.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class UpdateStatement < Arel::Nodes::Node @@ -14,7 +15,7 @@ module Arel @key = nil end - def initialize_copy other + def initialize_copy(other) super @wheres = @wheres.clone @values = @values.clone @@ -24,7 +25,7 @@ module Arel [@relation, @wheres, @values, @orders, @limit, @key].hash end - def eql? other + def eql?(other) self.class == other.class && self.relation == other.relation && self.wheres == other.wheres && diff --git a/activerecord/lib/arel/nodes/values.rb b/activerecord/lib/arel/nodes/values.rb index b32d5063a2..8554440be6 100644 --- a/activerecord/lib/arel/nodes/values.rb +++ b/activerecord/lib/arel/nodes/values.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class Values < Arel::Nodes::Binary @@ -7,7 +8,7 @@ module Arel alias :columns :right alias :columns= :right= - def initialize exprs, columns = [] + def initialize(exprs, columns = []) super end end diff --git a/activerecord/lib/arel/nodes/values_list.rb b/activerecord/lib/arel/nodes/values_list.rb index 89cea1790d..e68518d684 100644 --- a/activerecord/lib/arel/nodes/values_list.rb +++ b/activerecord/lib/arel/nodes/values_list.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class ValuesList < Node @@ -13,7 +14,7 @@ module Arel @rows.hash end - def eql? other + def eql?(other) self.class == other.class && self.rows == other.rows end diff --git a/activerecord/lib/arel/nodes/window.rb b/activerecord/lib/arel/nodes/window.rb index 23a005daba..1f14630c81 100644 --- a/activerecord/lib/arel/nodes/window.rb +++ b/activerecord/lib/arel/nodes/window.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class Window < Arel::Nodes::Node @@ -10,7 +11,7 @@ module Arel @framing = nil end - def order *expr + def order(*expr) # FIXME: We SHOULD NOT be converting these to SqlLiteral automatically @orders.concat expr.map { |x| String === x || Symbol === x ? Nodes::SqlLiteral.new(x.to_s) : x @@ -18,7 +19,7 @@ module Arel self end - def partition *expr + def partition(*expr) # FIXME: We SHOULD NOT be converting these to SqlLiteral automatically @partitions.concat expr.map { |x| String === x || Symbol === x ? Nodes::SqlLiteral.new(x.to_s) : x @@ -46,7 +47,7 @@ module Arel end end - def initialize_copy other + def initialize_copy(other) super @orders = @orders.map { |x| x.clone } end @@ -55,7 +56,7 @@ module Arel [@orders, @framing].hash end - def eql? other + def eql?(other) self.class == other.class && self.orders == other.orders && self.framing == other.framing && @@ -67,12 +68,12 @@ module Arel class NamedWindow < Window attr_accessor :name - def initialize name + def initialize(name) super() @name = name end - def initialize_copy other + def initialize_copy(other) super @name = other.name.clone end @@ -81,7 +82,7 @@ module Arel super ^ @name.hash end - def eql? other + def eql?(other) super && self.name == other.name end alias :== :eql? @@ -104,7 +105,7 @@ module Arel self.class.hash end - def eql? other + def eql?(other) self.class == other.class end alias :== :eql? diff --git a/activerecord/lib/arel/nodes/with.rb b/activerecord/lib/arel/nodes/with.rb index def7840ea3..a0fbf87e8e 100644 --- a/activerecord/lib/arel/nodes/with.rb +++ b/activerecord/lib/arel/nodes/with.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Nodes class With < Arel::Nodes::Unary @@ -8,4 +9,3 @@ module Arel class WithRecursive < With; end end end - diff --git a/activerecord/lib/arel/order_predications.rb b/activerecord/lib/arel/order_predications.rb index d84be82bb6..a0f15cb4d6 100644 --- a/activerecord/lib/arel/order_predications.rb +++ b/activerecord/lib/arel/order_predications.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true + module Arel module OrderPredications - def asc Nodes::Ascending.new self end @@ -9,6 +9,5 @@ module Arel def desc Nodes::Descending.new self end - end end diff --git a/activerecord/lib/arel/predications.rb b/activerecord/lib/arel/predications.rb index 799c7c67b8..1e701586a4 100644 --- a/activerecord/lib/arel/predications.rb +++ b/activerecord/lib/arel/predications.rb @@ -1,31 +1,32 @@ # frozen_string_literal: true + module Arel module Predications - def not_eq other + def not_eq(other) Nodes::NotEqual.new self, quoted_node(other) end - def not_eq_any others + def not_eq_any(others) grouping_any :not_eq, others end - def not_eq_all others + def not_eq_all(others) grouping_all :not_eq, others end - def eq other + def eq(other) Nodes::Equality.new self, quoted_node(other) end - def eq_any others + def eq_any(others) grouping_any :eq, others end - def eq_all others + def eq_all(others) grouping_all :eq, quoted_array(others) end - def between other + def between(other) if equals_quoted?(other.begin, -Float::INFINITY) if equals_quoted?(other.end, Float::INFINITY) not_in([]) @@ -45,7 +46,7 @@ module Arel end end - def in other + def in(other) case other when Arel::SelectManager Arel::Nodes::In.new(self, other.ast) @@ -63,15 +64,15 @@ Passing a range to `#in` is deprecated. Call `#between`, instead. end end - def in_any others + def in_any(others) grouping_any :in, others end - def in_all others + def in_all(others) grouping_all :in, others end - def not_between other + def not_between(other) if equals_quoted?(other.begin, -Float::INFINITY) if equals_quoted?(other.end, Float::INFINITY) self.in([]) @@ -93,7 +94,7 @@ Passing a range to `#in` is deprecated. Call `#between`, instead. end end - def not_in other + def not_in(other) case other when Arel::SelectManager Arel::Nodes::NotIn.new(self, other.ast) @@ -111,130 +112,130 @@ Passing a range to `#not_in` is deprecated. Call `#not_between`, instead. end end - def not_in_any others + def not_in_any(others) grouping_any :not_in, others end - def not_in_all others + def not_in_all(others) grouping_all :not_in, others end - def matches other, escape = nil, case_sensitive = false + def matches(other, escape = nil, case_sensitive = false) Nodes::Matches.new self, quoted_node(other), escape, case_sensitive end - def matches_regexp other, case_sensitive = true + def matches_regexp(other, case_sensitive = true) Nodes::Regexp.new self, quoted_node(other), case_sensitive end - def matches_any others, escape = nil, case_sensitive = false + def matches_any(others, escape = nil, case_sensitive = false) grouping_any :matches, others, escape, case_sensitive end - def matches_all others, escape = nil, case_sensitive = false + def matches_all(others, escape = nil, case_sensitive = false) grouping_all :matches, others, escape, case_sensitive end - def does_not_match other, escape = nil, case_sensitive = false + def does_not_match(other, escape = nil, case_sensitive = false) Nodes::DoesNotMatch.new self, quoted_node(other), escape, case_sensitive end - def does_not_match_regexp other, case_sensitive = true + def does_not_match_regexp(other, case_sensitive = true) Nodes::NotRegexp.new self, quoted_node(other), case_sensitive end - def does_not_match_any others, escape = nil + def does_not_match_any(others, escape = nil) grouping_any :does_not_match, others, escape end - def does_not_match_all others, escape = nil + def does_not_match_all(others, escape = nil) grouping_all :does_not_match, others, escape end - def gteq right + def gteq(right) Nodes::GreaterThanOrEqual.new self, quoted_node(right) end - def gteq_any others + def gteq_any(others) grouping_any :gteq, others end - def gteq_all others + def gteq_all(others) grouping_all :gteq, others end - def gt right + def gt(right) Nodes::GreaterThan.new self, quoted_node(right) end - def gt_any others + def gt_any(others) grouping_any :gt, others end - def gt_all others + def gt_all(others) grouping_all :gt, others end - def lt right + def lt(right) Nodes::LessThan.new self, quoted_node(right) end - def lt_any others + def lt_any(others) grouping_any :lt, others end - def lt_all others + def lt_all(others) grouping_all :lt, others end - def lteq right + def lteq(right) Nodes::LessThanOrEqual.new self, quoted_node(right) end - def lteq_any others + def lteq_any(others) grouping_any :lteq, others end - def lteq_all others + def lteq_all(others) grouping_all :lteq, others end - def when right + def when(right) Nodes::Case.new(self).when quoted_node(right) end - def concat other + def concat(other) Nodes::Concat.new self, other end private - def grouping_any method_id, others, *extras - nodes = others.map {|expr| send(method_id, expr, *extras)} - Nodes::Grouping.new nodes.inject { |memo,node| - Nodes::Or.new(memo, node) - } - end + def grouping_any(method_id, others, *extras) + nodes = others.map { |expr| send(method_id, expr, *extras) } + Nodes::Grouping.new nodes.inject { |memo, node| + Nodes::Or.new(memo, node) + } + end - def grouping_all method_id, others, *extras - nodes = others.map {|expr| send(method_id, expr, *extras)} - Nodes::Grouping.new Nodes::And.new(nodes) - end + def grouping_all(method_id, others, *extras) + nodes = others.map { |expr| send(method_id, expr, *extras) } + Nodes::Grouping.new Nodes::And.new(nodes) + end - def quoted_node(other) - Nodes.build_quoted(other, self) - end + def quoted_node(other) + Nodes.build_quoted(other, self) + end - def quoted_array(others) - others.map { |v| quoted_node(v) } - end + def quoted_array(others) + others.map { |v| quoted_node(v) } + end - def equals_quoted?(maybe_quoted, value) - if maybe_quoted.is_a?(Nodes::Quoted) - maybe_quoted.val == value - else - maybe_quoted == value + def equals_quoted?(maybe_quoted, value) + if maybe_quoted.is_a?(Nodes::Quoted) + maybe_quoted.val == value + else + maybe_quoted == value + end end - end end end diff --git a/activerecord/lib/arel/select_manager.rb b/activerecord/lib/arel/select_manager.rb index 0f3b0dc6a0..dc61447d01 100644 --- a/activerecord/lib/arel/select_manager.rb +++ b/activerecord/lib/arel/select_manager.rb @@ -1,18 +1,19 @@ # frozen_string_literal: true + module Arel class SelectManager < Arel::TreeManager include Arel::Crud STRING_OR_SYMBOL_CLASS = [Symbol, String] - def initialize table = nil + def initialize(table = nil) super() - @ast = Nodes::SelectStatement.new - @ctx = @ast.cores.last + @ast = Nodes::SelectStatement.new + @ctx = @ast.cores.last from table end - def initialize_copy other + def initialize_copy(other) super @ctx = @ast.cores.last end @@ -30,7 +31,7 @@ module Arel @ast.offset && @ast.offset.expr end - def skip amount + def skip(amount) if amount @ast.offset = Nodes::Offset.new(amount) else @@ -46,14 +47,14 @@ module Arel Arel::Nodes::Exists.new @ast end - def as other + def as(other) create_table_alias grouping(@ast), Nodes::SqlLiteral.new(other) end - def lock locking = Arel.sql('FOR UPDATE') + def lock(locking = Arel.sql("FOR UPDATE")) case locking when true - locking = Arel.sql('FOR UPDATE') + locking = Arel.sql("FOR UPDATE") when Arel::Nodes::SqlLiteral when String locking = Arel.sql locking @@ -67,12 +68,12 @@ module Arel @ast.lock end - def on *exprs + def on(*exprs) @ctx.source.right.last.right = Nodes::On.new(collapse(exprs)) self end - def group *columns + def group(*columns) columns.each do |column| # FIXME: backwards compat column = Nodes::SqlLiteral.new(column) if String === column @@ -83,7 +84,7 @@ module Arel self end - def from table + def from(table) table = Nodes::SqlLiteral.new(table) if String === table case table @@ -100,7 +101,7 @@ module Arel @ast.cores.map { |x| x.from }.compact end - def join relation, klass = Nodes::InnerJoin + def join(relation, klass = Nodes::InnerJoin) return self unless relation case relation @@ -113,22 +114,22 @@ module Arel self end - def outer_join relation + def outer_join(relation) join(relation, Nodes::OuterJoin) end - def having expr + def having(expr) @ctx.havings << expr self end - def window name + def window(name) window = Nodes::NamedWindow.new(name) @ctx.windows.push window window end - def project *projections + def project(*projections) # FIXME: converting these to SQLLiterals is probably not good, but # rails tests require it. @ctx.projections.concat projections.map { |x| @@ -141,7 +142,7 @@ module Arel @ctx.projections end - def projections= projections + def projections=(projections) @ctx.projections = projections end @@ -163,7 +164,7 @@ module Arel self end - def order *expr + def order(*expr) # FIXME: We SHOULD NOT be converting these to SqlLiteral automatically @ast.orders.concat expr.map { |x| STRING_OR_SYMBOL_CLASS.include?(x.class) ? Nodes::SqlLiteral.new(x.to_s) : x @@ -175,14 +176,14 @@ module Arel @ast.orders end - def where_sql engine = Table.engine + def where_sql(engine = Table.engine) return if @ctx.wheres.empty? viz = Visitors::WhereSql.new(engine.connection.visitor, engine.connection) Nodes::SqlLiteral.new viz.accept(@ctx, Collectors::SQLString.new).value end - def union operation, other = nil + def union(operation, other = nil) if other node_class = Nodes.const_get("Union#{operation.to_s.capitalize}") else @@ -193,21 +194,21 @@ module Arel node_class.new self.ast, other.ast end - def intersect other + def intersect(other) Nodes::Intersect.new ast, other.ast end - def except other + def except(other) Nodes::Except.new ast, other.ast end alias :minus :except - def lateral table_name = nil + def lateral(table_name = nil) base = table_name.nil? ? ast : as(table_name) Nodes::Lateral.new(base) end - def with *subqueries + def with(*subqueries) if subqueries.first.is_a? Symbol node_class = Nodes.const_get("With#{subqueries.shift.to_s.capitalize}") else @@ -218,7 +219,7 @@ module Arel self end - def take limit + def take(limit) if limit @ast.limit = Nodes::Limit.new(limit) @ctx.top = Nodes::Top.new(limit) @@ -240,7 +241,7 @@ module Arel class Row < Struct.new(:data) # :nodoc: def id - data['id'] + data["id"] end def method_missing(name, *args) @@ -251,22 +252,22 @@ module Arel end private - def collapse exprs, existing = nil - exprs = exprs.unshift(existing.expr) if existing - exprs = exprs.compact.map { |expr| - if String === expr - # FIXME: Don't do this automatically - Arel.sql(expr) + def collapse(exprs, existing = nil) + exprs = exprs.unshift(existing.expr) if existing + exprs = exprs.compact.map { |expr| + if String === expr + # FIXME: Don't do this automatically + Arel.sql(expr) + else + expr + end + } + + if exprs.length == 1 + exprs.first else - expr + create_and exprs end - } - - if exprs.length == 1 - exprs.first - else - create_and exprs end - end end end diff --git a/activerecord/lib/arel/table.rb b/activerecord/lib/arel/table.rb index b3f2d79e5f..2df2c4c514 100644 --- a/activerecord/lib/arel/table.rb +++ b/activerecord/lib/arel/table.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel class Table include Arel::Crud @@ -13,7 +14,7 @@ module Arel alias :table_name :name def initialize(name, as: nil, type_caster: nil) - @name = name.to_s + @name = name.to_s @type_caster = type_caster # Sometime AR sends an :as parameter to table, to let the table know @@ -25,7 +26,7 @@ module Arel @table_alias = as end - def alias name = "#{self.name}_2" + def alias(name = "#{self.name}_2") Nodes::TableAlias.new(self, name) end @@ -33,7 +34,7 @@ module Arel SelectManager.new(self) end - def join relation, klass = Nodes::InnerJoin + def join(relation, klass = Nodes::InnerJoin) return from unless relation case relation @@ -45,39 +46,39 @@ module Arel from.join(relation, klass) end - def outer_join relation + def outer_join(relation) join(relation, Nodes::OuterJoin) end - def group *columns + def group(*columns) from.group(*columns) end - def order *expr + def order(*expr) from.order(*expr) end - def where condition + def where(condition) from.where condition end - def project *things + def project(*things) from.project(*things) end - def take amount + def take(amount) from.take amount end - def skip amount + def skip(amount) from.skip amount end - def having expr + def having(expr) from.having expr end - def [] name + def [](name) ::Arel::Attribute.new self, name end @@ -88,7 +89,7 @@ module Arel @name.hash end - def eql? other + def eql?(other) self.class == other.class && self.name == other.name && self.table_alias == other.table_alias @@ -105,6 +106,6 @@ module Arel protected - attr_reader :type_caster + attr_reader :type_caster end end diff --git a/activerecord/lib/arel/tree_manager.rb b/activerecord/lib/arel/tree_manager.rb index b237bf368d..f6ec1415fa 100644 --- a/activerecord/lib/arel/tree_manager.rb +++ b/activerecord/lib/arel/tree_manager.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel class TreeManager include Arel::FactoryMethods @@ -15,18 +16,18 @@ module Arel collector.value end - def to_sql engine = Table.engine + def to_sql(engine = Table.engine) collector = Arel::Collectors::SQLString.new collector = engine.connection.visitor.accept @ast, collector collector.value end - def initialize_copy other + def initialize_copy(other) super @ast = @ast.clone end - def where expr + def where(expr) if Arel::TreeManager === expr expr = expr.ast end diff --git a/activerecord/lib/arel/update_manager.rb b/activerecord/lib/arel/update_manager.rb index eac414eafb..6e36e82cf9 100644 --- a/activerecord/lib/arel/update_manager.rb +++ b/activerecord/lib/arel/update_manager.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel class UpdateManager < Arel::TreeManager def initialize @@ -7,12 +8,12 @@ module Arel @ctx = @ast end - def take limit + def take(limit) @ast.limit = Nodes::Limit.new(Nodes.build_quoted(limit)) if limit self end - def key= key + def key=(key) @ast.key = Nodes.build_quoted(key) end @@ -20,32 +21,32 @@ module Arel @ast.key end - def order *expr + def order(*expr) @ast.orders = expr self end ### # UPDATE +table+ - def table table + def table(table) @ast.relation = table self end - def wheres= exprs + def wheres=(exprs) @ast.wheres = exprs end - def where expr + def where(expr) @ast.wheres << expr self end - def set values + def set(values) if String === values @ast.values = [values] else - @ast.values = values.map { |column,value| + @ast.values = values.map { |column, value| Nodes::Assignment.new( Nodes::UnqualifiedColumn.new(column), value diff --git a/activerecord/lib/arel/visitors.rb b/activerecord/lib/arel/visitors.rb index a3404cf992..fb44721117 100644 --- a/activerecord/lib/arel/visitors.rb +++ b/activerecord/lib/arel/visitors.rb @@ -1,17 +1,18 @@ # frozen_string_literal: true -require 'arel/visitors/visitor' -require 'arel/visitors/depth_first' -require 'arel/visitors/to_sql' -require 'arel/visitors/sqlite' -require 'arel/visitors/postgresql' -require 'arel/visitors/mysql' -require 'arel/visitors/mssql' -require 'arel/visitors/oracle' -require 'arel/visitors/oracle12' -require 'arel/visitors/where_sql' -require 'arel/visitors/dot' -require 'arel/visitors/ibm_db' -require 'arel/visitors/informix' + +require "arel/visitors/visitor" +require "arel/visitors/depth_first" +require "arel/visitors/to_sql" +require "arel/visitors/sqlite" +require "arel/visitors/postgresql" +require "arel/visitors/mysql" +require "arel/visitors/mssql" +require "arel/visitors/oracle" +require "arel/visitors/oracle12" +require "arel/visitors/where_sql" +require "arel/visitors/dot" +require "arel/visitors/ibm_db" +require "arel/visitors/informix" module Arel module Visitors diff --git a/activerecord/lib/arel/visitors/depth_first.rb b/activerecord/lib/arel/visitors/depth_first.rb index b3bbc9bd40..fb32ef59ad 100644 --- a/activerecord/lib/arel/visitors/depth_first.rb +++ b/activerecord/lib/arel/visitors/depth_first.rb @@ -1,199 +1,200 @@ # frozen_string_literal: true + module Arel module Visitors class DepthFirst < Arel::Visitors::Visitor - def initialize block = nil + def initialize(block = nil) @block = block || Proc.new super() end private - def visit o - super - @block.call o - end - - def unary o - visit o.expr - end - alias :visit_Arel_Nodes_Else :unary - alias :visit_Arel_Nodes_Group :unary - alias :visit_Arel_Nodes_Cube :unary - alias :visit_Arel_Nodes_RollUp :unary - alias :visit_Arel_Nodes_GroupingSet :unary - alias :visit_Arel_Nodes_GroupingElement :unary - alias :visit_Arel_Nodes_Grouping :unary - alias :visit_Arel_Nodes_Having :unary - alias :visit_Arel_Nodes_Lateral :unary - alias :visit_Arel_Nodes_Limit :unary - alias :visit_Arel_Nodes_Not :unary - alias :visit_Arel_Nodes_Offset :unary - alias :visit_Arel_Nodes_On :unary - alias :visit_Arel_Nodes_Ordering :unary - alias :visit_Arel_Nodes_Ascending :unary - alias :visit_Arel_Nodes_Descending :unary - alias :visit_Arel_Nodes_Top :unary - alias :visit_Arel_Nodes_UnqualifiedColumn :unary - - def function o - visit o.expressions - visit o.alias - visit o.distinct - end - alias :visit_Arel_Nodes_Avg :function - alias :visit_Arel_Nodes_Exists :function - alias :visit_Arel_Nodes_Max :function - alias :visit_Arel_Nodes_Min :function - alias :visit_Arel_Nodes_Sum :function - - def visit_Arel_Nodes_NamedFunction o - visit o.name - visit o.expressions - visit o.distinct - visit o.alias - end - - def visit_Arel_Nodes_Count o - visit o.expressions - visit o.alias - visit o.distinct - end - - def visit_Arel_Nodes_Case o - visit o.case - visit o.conditions - visit o.default - end - - def nary o - o.children.each { |child| visit child} - end - alias :visit_Arel_Nodes_And :nary - - def binary o - visit o.left - visit o.right - end - alias :visit_Arel_Nodes_As :binary - alias :visit_Arel_Nodes_Assignment :binary - alias :visit_Arel_Nodes_Between :binary - alias :visit_Arel_Nodes_Concat :binary - alias :visit_Arel_Nodes_DeleteStatement :binary - alias :visit_Arel_Nodes_DoesNotMatch :binary - alias :visit_Arel_Nodes_Equality :binary - alias :visit_Arel_Nodes_FullOuterJoin :binary - alias :visit_Arel_Nodes_GreaterThan :binary - alias :visit_Arel_Nodes_GreaterThanOrEqual :binary - alias :visit_Arel_Nodes_In :binary - alias :visit_Arel_Nodes_InfixOperation :binary - alias :visit_Arel_Nodes_JoinSource :binary - alias :visit_Arel_Nodes_InnerJoin :binary - alias :visit_Arel_Nodes_LessThan :binary - alias :visit_Arel_Nodes_LessThanOrEqual :binary - alias :visit_Arel_Nodes_Matches :binary - alias :visit_Arel_Nodes_NotEqual :binary - alias :visit_Arel_Nodes_NotIn :binary - alias :visit_Arel_Nodes_NotRegexp :binary - alias :visit_Arel_Nodes_Or :binary - alias :visit_Arel_Nodes_OuterJoin :binary - alias :visit_Arel_Nodes_Regexp :binary - alias :visit_Arel_Nodes_RightOuterJoin :binary - alias :visit_Arel_Nodes_TableAlias :binary - alias :visit_Arel_Nodes_Values :binary - alias :visit_Arel_Nodes_When :binary - - def visit_Arel_Nodes_StringJoin o - visit o.left - end - - def visit_Arel_Attribute o - visit o.relation - visit o.name - end - alias :visit_Arel_Attributes_Integer :visit_Arel_Attribute - alias :visit_Arel_Attributes_Float :visit_Arel_Attribute - alias :visit_Arel_Attributes_String :visit_Arel_Attribute - alias :visit_Arel_Attributes_Time :visit_Arel_Attribute - alias :visit_Arel_Attributes_Boolean :visit_Arel_Attribute - alias :visit_Arel_Attributes_Attribute :visit_Arel_Attribute - alias :visit_Arel_Attributes_Decimal :visit_Arel_Attribute - - def visit_Arel_Table o - visit o.name - end - - def terminal o - end - alias :visit_ActiveSupport_Multibyte_Chars :terminal - alias :visit_ActiveSupport_StringInquirer :terminal - alias :visit_Arel_Nodes_Lock :terminal - alias :visit_Arel_Nodes_Node :terminal - alias :visit_Arel_Nodes_SqlLiteral :terminal - alias :visit_Arel_Nodes_BindParam :terminal - alias :visit_Arel_Nodes_Window :terminal - alias :visit_Arel_Nodes_True :terminal - alias :visit_Arel_Nodes_False :terminal - alias :visit_BigDecimal :terminal - alias :visit_Bignum :terminal - alias :visit_Class :terminal - alias :visit_Date :terminal - alias :visit_DateTime :terminal - alias :visit_FalseClass :terminal - alias :visit_Fixnum :terminal - alias :visit_Float :terminal - alias :visit_Integer :terminal - alias :visit_NilClass :terminal - alias :visit_String :terminal - alias :visit_Symbol :terminal - alias :visit_Time :terminal - alias :visit_TrueClass :terminal - - def visit_Arel_Nodes_InsertStatement o - visit o.relation - visit o.columns - visit o.values - end - - def visit_Arel_Nodes_SelectCore o - visit o.projections - visit o.source - visit o.wheres - visit o.groups - visit o.windows - visit o.havings - end - - def visit_Arel_Nodes_SelectStatement o - visit o.cores - visit o.orders - visit o.limit - visit o.lock - visit o.offset - end - - def visit_Arel_Nodes_UpdateStatement o - visit o.relation - visit o.values - visit o.wheres - visit o.orders - visit o.limit - end - - def visit_Array o - o.each { |i| visit i } - end - alias :visit_Set :visit_Array - - def visit_Hash o - o.each { |k,v| visit(k); visit(v) } - end - - DISPATCH = dispatch_cache - - def get_dispatch_cache - DISPATCH - end + def visit(o) + super + @block.call o + end + + def unary(o) + visit o.expr + end + alias :visit_Arel_Nodes_Else :unary + alias :visit_Arel_Nodes_Group :unary + alias :visit_Arel_Nodes_Cube :unary + alias :visit_Arel_Nodes_RollUp :unary + alias :visit_Arel_Nodes_GroupingSet :unary + alias :visit_Arel_Nodes_GroupingElement :unary + alias :visit_Arel_Nodes_Grouping :unary + alias :visit_Arel_Nodes_Having :unary + alias :visit_Arel_Nodes_Lateral :unary + alias :visit_Arel_Nodes_Limit :unary + alias :visit_Arel_Nodes_Not :unary + alias :visit_Arel_Nodes_Offset :unary + alias :visit_Arel_Nodes_On :unary + alias :visit_Arel_Nodes_Ordering :unary + alias :visit_Arel_Nodes_Ascending :unary + alias :visit_Arel_Nodes_Descending :unary + alias :visit_Arel_Nodes_Top :unary + alias :visit_Arel_Nodes_UnqualifiedColumn :unary + + def function(o) + visit o.expressions + visit o.alias + visit o.distinct + end + alias :visit_Arel_Nodes_Avg :function + alias :visit_Arel_Nodes_Exists :function + alias :visit_Arel_Nodes_Max :function + alias :visit_Arel_Nodes_Min :function + alias :visit_Arel_Nodes_Sum :function + + def visit_Arel_Nodes_NamedFunction(o) + visit o.name + visit o.expressions + visit o.distinct + visit o.alias + end + + def visit_Arel_Nodes_Count(o) + visit o.expressions + visit o.alias + visit o.distinct + end + + def visit_Arel_Nodes_Case(o) + visit o.case + visit o.conditions + visit o.default + end + + def nary(o) + o.children.each { |child| visit child } + end + alias :visit_Arel_Nodes_And :nary + + def binary(o) + visit o.left + visit o.right + end + alias :visit_Arel_Nodes_As :binary + alias :visit_Arel_Nodes_Assignment :binary + alias :visit_Arel_Nodes_Between :binary + alias :visit_Arel_Nodes_Concat :binary + alias :visit_Arel_Nodes_DeleteStatement :binary + alias :visit_Arel_Nodes_DoesNotMatch :binary + alias :visit_Arel_Nodes_Equality :binary + alias :visit_Arel_Nodes_FullOuterJoin :binary + alias :visit_Arel_Nodes_GreaterThan :binary + alias :visit_Arel_Nodes_GreaterThanOrEqual :binary + alias :visit_Arel_Nodes_In :binary + alias :visit_Arel_Nodes_InfixOperation :binary + alias :visit_Arel_Nodes_JoinSource :binary + alias :visit_Arel_Nodes_InnerJoin :binary + alias :visit_Arel_Nodes_LessThan :binary + alias :visit_Arel_Nodes_LessThanOrEqual :binary + alias :visit_Arel_Nodes_Matches :binary + alias :visit_Arel_Nodes_NotEqual :binary + alias :visit_Arel_Nodes_NotIn :binary + alias :visit_Arel_Nodes_NotRegexp :binary + alias :visit_Arel_Nodes_Or :binary + alias :visit_Arel_Nodes_OuterJoin :binary + alias :visit_Arel_Nodes_Regexp :binary + alias :visit_Arel_Nodes_RightOuterJoin :binary + alias :visit_Arel_Nodes_TableAlias :binary + alias :visit_Arel_Nodes_Values :binary + alias :visit_Arel_Nodes_When :binary + + def visit_Arel_Nodes_StringJoin(o) + visit o.left + end + + def visit_Arel_Attribute(o) + visit o.relation + visit o.name + end + alias :visit_Arel_Attributes_Integer :visit_Arel_Attribute + alias :visit_Arel_Attributes_Float :visit_Arel_Attribute + alias :visit_Arel_Attributes_String :visit_Arel_Attribute + alias :visit_Arel_Attributes_Time :visit_Arel_Attribute + alias :visit_Arel_Attributes_Boolean :visit_Arel_Attribute + alias :visit_Arel_Attributes_Attribute :visit_Arel_Attribute + alias :visit_Arel_Attributes_Decimal :visit_Arel_Attribute + + def visit_Arel_Table(o) + visit o.name + end + + def terminal(o) + end + alias :visit_ActiveSupport_Multibyte_Chars :terminal + alias :visit_ActiveSupport_StringInquirer :terminal + alias :visit_Arel_Nodes_Lock :terminal + alias :visit_Arel_Nodes_Node :terminal + alias :visit_Arel_Nodes_SqlLiteral :terminal + alias :visit_Arel_Nodes_BindParam :terminal + alias :visit_Arel_Nodes_Window :terminal + alias :visit_Arel_Nodes_True :terminal + alias :visit_Arel_Nodes_False :terminal + alias :visit_BigDecimal :terminal + alias :visit_Bignum :terminal + alias :visit_Class :terminal + alias :visit_Date :terminal + alias :visit_DateTime :terminal + alias :visit_FalseClass :terminal + alias :visit_Fixnum :terminal + alias :visit_Float :terminal + alias :visit_Integer :terminal + alias :visit_NilClass :terminal + alias :visit_String :terminal + alias :visit_Symbol :terminal + alias :visit_Time :terminal + alias :visit_TrueClass :terminal + + def visit_Arel_Nodes_InsertStatement(o) + visit o.relation + visit o.columns + visit o.values + end + + def visit_Arel_Nodes_SelectCore(o) + visit o.projections + visit o.source + visit o.wheres + visit o.groups + visit o.windows + visit o.havings + end + + def visit_Arel_Nodes_SelectStatement(o) + visit o.cores + visit o.orders + visit o.limit + visit o.lock + visit o.offset + end + + def visit_Arel_Nodes_UpdateStatement(o) + visit o.relation + visit o.values + visit o.wheres + visit o.orders + visit o.limit + end + + def visit_Array(o) + o.each { |i| visit i } + end + alias :visit_Set :visit_Array + + def visit_Hash(o) + o.each { |k, v| visit(k); visit(v) } + end + + DISPATCH = dispatch_cache + + def get_dispatch_cache + DISPATCH + end end end end diff --git a/activerecord/lib/arel/visitors/dot.rb b/activerecord/lib/arel/visitors/dot.rb index 9aa22d33f6..2b285ac775 100644 --- a/activerecord/lib/arel/visitors/dot.rb +++ b/activerecord/lib/arel/visitors/dot.rb @@ -1,11 +1,12 @@ # frozen_string_literal: true + module Arel module Visitors class Dot < Arel::Visitors::Visitor class Node # :nodoc: attr_accessor :name, :id, :fields - def initialize name, id, fields = [] + def initialize(name, id, fields = []) @name = name @id = id @fields = fields @@ -24,268 +25,268 @@ module Arel @seen = {} end - def accept object, collector + def accept(object, collector) visit object collector << to_dot end private - def visit_Arel_Nodes_Ordering o - visit_edge o, "expr" - end - - def visit_Arel_Nodes_TableAlias o - visit_edge o, "name" - visit_edge o, "relation" - end + def visit_Arel_Nodes_Ordering(o) + visit_edge o, "expr" + end - def visit_Arel_Nodes_Count o - visit_edge o, "expressions" - visit_edge o, "distinct" - end + def visit_Arel_Nodes_TableAlias(o) + visit_edge o, "name" + visit_edge o, "relation" + end - def visit_Arel_Nodes_Values o - visit_edge o, "expressions" - end + def visit_Arel_Nodes_Count(o) + visit_edge o, "expressions" + visit_edge o, "distinct" + end - def visit_Arel_Nodes_StringJoin o - visit_edge o, "left" - end + def visit_Arel_Nodes_Values(o) + visit_edge o, "expressions" + end - def visit_Arel_Nodes_InnerJoin o - visit_edge o, "left" - visit_edge o, "right" - end - alias :visit_Arel_Nodes_FullOuterJoin :visit_Arel_Nodes_InnerJoin - alias :visit_Arel_Nodes_OuterJoin :visit_Arel_Nodes_InnerJoin - alias :visit_Arel_Nodes_RightOuterJoin :visit_Arel_Nodes_InnerJoin + def visit_Arel_Nodes_StringJoin(o) + visit_edge o, "left" + end - def visit_Arel_Nodes_DeleteStatement o - visit_edge o, "relation" - visit_edge o, "wheres" - end + def visit_Arel_Nodes_InnerJoin(o) + visit_edge o, "left" + visit_edge o, "right" + end + alias :visit_Arel_Nodes_FullOuterJoin :visit_Arel_Nodes_InnerJoin + alias :visit_Arel_Nodes_OuterJoin :visit_Arel_Nodes_InnerJoin + alias :visit_Arel_Nodes_RightOuterJoin :visit_Arel_Nodes_InnerJoin - def unary o - visit_edge o, "expr" - end - alias :visit_Arel_Nodes_Group :unary - alias :visit_Arel_Nodes_Cube :unary - alias :visit_Arel_Nodes_RollUp :unary - alias :visit_Arel_Nodes_GroupingSet :unary - alias :visit_Arel_Nodes_GroupingElement :unary - alias :visit_Arel_Nodes_Grouping :unary - alias :visit_Arel_Nodes_Having :unary - alias :visit_Arel_Nodes_Limit :unary - alias :visit_Arel_Nodes_Not :unary - alias :visit_Arel_Nodes_Offset :unary - alias :visit_Arel_Nodes_On :unary - alias :visit_Arel_Nodes_Top :unary - alias :visit_Arel_Nodes_UnqualifiedColumn :unary - alias :visit_Arel_Nodes_Preceding :unary - alias :visit_Arel_Nodes_Following :unary - alias :visit_Arel_Nodes_Rows :unary - alias :visit_Arel_Nodes_Range :unary - - def window o - visit_edge o, "partitions" - visit_edge o, "orders" - visit_edge o, "framing" - end - alias :visit_Arel_Nodes_Window :window + def visit_Arel_Nodes_DeleteStatement(o) + visit_edge o, "relation" + visit_edge o, "wheres" + end - def named_window o - visit_edge o, "partitions" - visit_edge o, "orders" - visit_edge o, "framing" - visit_edge o, "name" - end - alias :visit_Arel_Nodes_NamedWindow :named_window + def unary(o) + visit_edge o, "expr" + end + alias :visit_Arel_Nodes_Group :unary + alias :visit_Arel_Nodes_Cube :unary + alias :visit_Arel_Nodes_RollUp :unary + alias :visit_Arel_Nodes_GroupingSet :unary + alias :visit_Arel_Nodes_GroupingElement :unary + alias :visit_Arel_Nodes_Grouping :unary + alias :visit_Arel_Nodes_Having :unary + alias :visit_Arel_Nodes_Limit :unary + alias :visit_Arel_Nodes_Not :unary + alias :visit_Arel_Nodes_Offset :unary + alias :visit_Arel_Nodes_On :unary + alias :visit_Arel_Nodes_Top :unary + alias :visit_Arel_Nodes_UnqualifiedColumn :unary + alias :visit_Arel_Nodes_Preceding :unary + alias :visit_Arel_Nodes_Following :unary + alias :visit_Arel_Nodes_Rows :unary + alias :visit_Arel_Nodes_Range :unary + + def window(o) + visit_edge o, "partitions" + visit_edge o, "orders" + visit_edge o, "framing" + end + alias :visit_Arel_Nodes_Window :window - def function o - visit_edge o, "expressions" - visit_edge o, "distinct" - visit_edge o, "alias" - end - alias :visit_Arel_Nodes_Exists :function - alias :visit_Arel_Nodes_Min :function - alias :visit_Arel_Nodes_Max :function - alias :visit_Arel_Nodes_Avg :function - alias :visit_Arel_Nodes_Sum :function - - def extract o - visit_edge o, "expressions" - visit_edge o, "alias" - end - alias :visit_Arel_Nodes_Extract :extract + def named_window(o) + visit_edge o, "partitions" + visit_edge o, "orders" + visit_edge o, "framing" + visit_edge o, "name" + end + alias :visit_Arel_Nodes_NamedWindow :named_window - def visit_Arel_Nodes_NamedFunction o - visit_edge o, "name" - visit_edge o, "expressions" - visit_edge o, "distinct" - visit_edge o, "alias" - end + def function(o) + visit_edge o, "expressions" + visit_edge o, "distinct" + visit_edge o, "alias" + end + alias :visit_Arel_Nodes_Exists :function + alias :visit_Arel_Nodes_Min :function + alias :visit_Arel_Nodes_Max :function + alias :visit_Arel_Nodes_Avg :function + alias :visit_Arel_Nodes_Sum :function + + def extract(o) + visit_edge o, "expressions" + visit_edge o, "alias" + end + alias :visit_Arel_Nodes_Extract :extract - def visit_Arel_Nodes_InsertStatement o - visit_edge o, "relation" - visit_edge o, "columns" - visit_edge o, "values" - end + def visit_Arel_Nodes_NamedFunction(o) + visit_edge o, "name" + visit_edge o, "expressions" + visit_edge o, "distinct" + visit_edge o, "alias" + end - def visit_Arel_Nodes_SelectCore o - visit_edge o, "source" - visit_edge o, "projections" - visit_edge o, "wheres" - visit_edge o, "windows" - end + def visit_Arel_Nodes_InsertStatement(o) + visit_edge o, "relation" + visit_edge o, "columns" + visit_edge o, "values" + end - def visit_Arel_Nodes_SelectStatement o - visit_edge o, "cores" - visit_edge o, "limit" - visit_edge o, "orders" - visit_edge o, "offset" - end + def visit_Arel_Nodes_SelectCore(o) + visit_edge o, "source" + visit_edge o, "projections" + visit_edge o, "wheres" + visit_edge o, "windows" + end - def visit_Arel_Nodes_UpdateStatement o - visit_edge o, "relation" - visit_edge o, "wheres" - visit_edge o, "values" - end + def visit_Arel_Nodes_SelectStatement(o) + visit_edge o, "cores" + visit_edge o, "limit" + visit_edge o, "orders" + visit_edge o, "offset" + end - def visit_Arel_Table o - visit_edge o, "name" - end + def visit_Arel_Nodes_UpdateStatement(o) + visit_edge o, "relation" + visit_edge o, "wheres" + visit_edge o, "values" + end - def visit_Arel_Nodes_Casted o - visit_edge o, 'val' - visit_edge o, 'attribute' - end + def visit_Arel_Table(o) + visit_edge o, "name" + end - def visit_Arel_Attribute o - visit_edge o, "relation" - visit_edge o, "name" - end - alias :visit_Arel_Attributes_Integer :visit_Arel_Attribute - alias :visit_Arel_Attributes_Float :visit_Arel_Attribute - alias :visit_Arel_Attributes_String :visit_Arel_Attribute - alias :visit_Arel_Attributes_Time :visit_Arel_Attribute - alias :visit_Arel_Attributes_Boolean :visit_Arel_Attribute - alias :visit_Arel_Attributes_Attribute :visit_Arel_Attribute + def visit_Arel_Nodes_Casted(o) + visit_edge o, "val" + visit_edge o, "attribute" + end - def nary o - o.children.each_with_index do |x,i| - edge(i) { visit x } + def visit_Arel_Attribute(o) + visit_edge o, "relation" + visit_edge o, "name" end - end - alias :visit_Arel_Nodes_And :nary + alias :visit_Arel_Attributes_Integer :visit_Arel_Attribute + alias :visit_Arel_Attributes_Float :visit_Arel_Attribute + alias :visit_Arel_Attributes_String :visit_Arel_Attribute + alias :visit_Arel_Attributes_Time :visit_Arel_Attribute + alias :visit_Arel_Attributes_Boolean :visit_Arel_Attribute + alias :visit_Arel_Attributes_Attribute :visit_Arel_Attribute + + def nary(o) + o.children.each_with_index do |x, i| + edge(i) { visit x } + end + end + alias :visit_Arel_Nodes_And :nary - def binary o - visit_edge o, "left" - visit_edge o, "right" - end - alias :visit_Arel_Nodes_As :binary - alias :visit_Arel_Nodes_Assignment :binary - alias :visit_Arel_Nodes_Between :binary - alias :visit_Arel_Nodes_Concat :binary - alias :visit_Arel_Nodes_DoesNotMatch :binary - alias :visit_Arel_Nodes_Equality :binary - alias :visit_Arel_Nodes_GreaterThan :binary - alias :visit_Arel_Nodes_GreaterThanOrEqual :binary - alias :visit_Arel_Nodes_In :binary - alias :visit_Arel_Nodes_JoinSource :binary - alias :visit_Arel_Nodes_LessThan :binary - alias :visit_Arel_Nodes_LessThanOrEqual :binary - alias :visit_Arel_Nodes_Matches :binary - alias :visit_Arel_Nodes_NotEqual :binary - alias :visit_Arel_Nodes_NotIn :binary - alias :visit_Arel_Nodes_Or :binary - alias :visit_Arel_Nodes_Over :binary - - def visit_String o - @node_stack.last.fields << o - end - alias :visit_Time :visit_String - alias :visit_Date :visit_String - alias :visit_DateTime :visit_String - alias :visit_NilClass :visit_String - alias :visit_TrueClass :visit_String - alias :visit_FalseClass :visit_String - alias :visit_Integer :visit_String - alias :visit_Fixnum :visit_String - alias :visit_BigDecimal :visit_String - alias :visit_Float :visit_String - alias :visit_Symbol :visit_String - alias :visit_Arel_Nodes_SqlLiteral :visit_String - - def visit_Arel_Nodes_BindParam o; end - - def visit_Hash o - o.each_with_index do |pair, i| - edge("pair_#{i}") { visit pair } + def binary(o) + visit_edge o, "left" + visit_edge o, "right" + end + alias :visit_Arel_Nodes_As :binary + alias :visit_Arel_Nodes_Assignment :binary + alias :visit_Arel_Nodes_Between :binary + alias :visit_Arel_Nodes_Concat :binary + alias :visit_Arel_Nodes_DoesNotMatch :binary + alias :visit_Arel_Nodes_Equality :binary + alias :visit_Arel_Nodes_GreaterThan :binary + alias :visit_Arel_Nodes_GreaterThanOrEqual :binary + alias :visit_Arel_Nodes_In :binary + alias :visit_Arel_Nodes_JoinSource :binary + alias :visit_Arel_Nodes_LessThan :binary + alias :visit_Arel_Nodes_LessThanOrEqual :binary + alias :visit_Arel_Nodes_Matches :binary + alias :visit_Arel_Nodes_NotEqual :binary + alias :visit_Arel_Nodes_NotIn :binary + alias :visit_Arel_Nodes_Or :binary + alias :visit_Arel_Nodes_Over :binary + + def visit_String(o) + @node_stack.last.fields << o + end + alias :visit_Time :visit_String + alias :visit_Date :visit_String + alias :visit_DateTime :visit_String + alias :visit_NilClass :visit_String + alias :visit_TrueClass :visit_String + alias :visit_FalseClass :visit_String + alias :visit_Integer :visit_String + alias :visit_Fixnum :visit_String + alias :visit_BigDecimal :visit_String + alias :visit_Float :visit_String + alias :visit_Symbol :visit_String + alias :visit_Arel_Nodes_SqlLiteral :visit_String + + def visit_Arel_Nodes_BindParam(o); end + + def visit_Hash(o) + o.each_with_index do |pair, i| + edge("pair_#{i}") { visit pair } + end end - end - def visit_Array o - o.each_with_index do |x,i| - edge(i) { visit x } + def visit_Array(o) + o.each_with_index do |x, i| + edge(i) { visit x } + end end - end - alias :visit_Set :visit_Array + alias :visit_Set :visit_Array - def visit_edge o, method - edge(method) { visit o.send(method) } - end + def visit_edge(o, method) + edge(method) { visit o.send(method) } + end - def visit o - if node = @seen[o.object_id] - @edge_stack.last.to = node - return + def visit(o) + if node = @seen[o.object_id] + @edge_stack.last.to = node + return + end + + node = Node.new(o.class.name, o.object_id) + @seen[node.id] = node + @nodes << node + with_node node do + super + end end - node = Node.new(o.class.name, o.object_id) - @seen[node.id] = node - @nodes << node - with_node node do - super + def edge(name) + edge = Edge.new(name, @node_stack.last) + @edge_stack.push edge + @edges << edge + yield + @edge_stack.pop end - end - def edge name - edge = Edge.new(name, @node_stack.last) - @edge_stack.push edge - @edges << edge - yield - @edge_stack.pop - end + def with_node(node) + if edge = @edge_stack.last + edge.to = node + end - def with_node node - if edge = @edge_stack.last - edge.to = node + @node_stack.push node + yield + @node_stack.pop end - @node_stack.push node - yield - @node_stack.pop - end - - def quote string - string.to_s.gsub('"', '\"') - end + def quote(string) + string.to_s.gsub('"', '\"') + end - def to_dot - "digraph \"Arel\" {\nnode [width=0.375,height=0.25,shape=record];\n" + - @nodes.map { |node| - label = "#{node.name}" + def to_dot + "digraph \"Arel\" {\nnode [width=0.375,height=0.25,shape=record];\n" + + @nodes.map { |node| + label = "#{node.name}" - node.fields.each_with_index do |field, i| - label += "|#{quote field}" - end + node.fields.each_with_index do |field, i| + label += "|#{quote field}" + end - "#{node.id} [label=\"#{label}\"];" - }.join("\n") + "\n" + @edges.map { |edge| - "#{edge.from.id} -> #{edge.to.id} [label=\"#{edge.name}\"];" - }.join("\n") + "\n}" - end + "#{node.id} [label=\"#{label}\"];" + }.join("\n") + "\n" + @edges.map { |edge| + "#{edge.from.id} -> #{edge.to.id} [label=\"#{edge.name}\"];" + }.join("\n") + "\n}" + end end end end diff --git a/activerecord/lib/arel/visitors/ibm_db.rb b/activerecord/lib/arel/visitors/ibm_db.rb index e85a5a08a7..0291e434c9 100644 --- a/activerecord/lib/arel/visitors/ibm_db.rb +++ b/activerecord/lib/arel/visitors/ibm_db.rb @@ -1,15 +1,15 @@ # frozen_string_literal: true + module Arel module Visitors class IBM_DB < Arel::Visitors::ToSql private - def visit_Arel_Nodes_Limit o, collector - collector << "FETCH FIRST " - collector = visit o.expr, collector - collector << " ROWS ONLY" - end - + def visit_Arel_Nodes_Limit(o, collector) + collector << "FETCH FIRST " + collector = visit o.expr, collector + collector << " ROWS ONLY" + end end end end diff --git a/activerecord/lib/arel/visitors/informix.rb b/activerecord/lib/arel/visitors/informix.rb index 44b18b550e..9df5a60bc2 100644 --- a/activerecord/lib/arel/visitors/informix.rb +++ b/activerecord/lib/arel/visitors/informix.rb @@ -1,55 +1,55 @@ # frozen_string_literal: true + module Arel module Visitors class Informix < Arel::Visitors::ToSql private - def visit_Arel_Nodes_SelectStatement o, collector - collector << "SELECT " - collector = maybe_visit o.offset, collector - collector = maybe_visit o.limit, collector - collector = o.cores.inject(collector) { |c,x| - visit_Arel_Nodes_SelectCore x, c - } - if o.orders.any? - collector << "ORDER BY " - collector = inject_join o.orders, collector, ", " - end - collector = maybe_visit o.lock, collector - end - def visit_Arel_Nodes_SelectCore o, collector - collector = inject_join o.projections, collector, ", " - if o.source && !o.source.empty? - collector << " FROM " - collector = visit o.source, collector + def visit_Arel_Nodes_SelectStatement(o, collector) + collector << "SELECT " + collector = maybe_visit o.offset, collector + collector = maybe_visit o.limit, collector + collector = o.cores.inject(collector) { |c, x| + visit_Arel_Nodes_SelectCore x, c + } + if o.orders.any? + collector << "ORDER BY " + collector = inject_join o.orders, collector, ", " + end + collector = maybe_visit o.lock, collector end + def visit_Arel_Nodes_SelectCore(o, collector) + collector = inject_join o.projections, collector, ", " + if o.source && !o.source.empty? + collector << " FROM " + collector = visit o.source, collector + end - if o.wheres.any? - collector << " WHERE " - collector = inject_join o.wheres, collector, " AND " - end + if o.wheres.any? + collector << " WHERE " + collector = inject_join o.wheres, collector, " AND " + end - if o.groups.any? - collector << "GROUP BY " - collector = inject_join o.groups, collector, ", " - end + if o.groups.any? + collector << "GROUP BY " + collector = inject_join o.groups, collector, ", " + end - if o.havings.any? - collector << " HAVING " - collector = inject_join o.havings, collector, " AND " + if o.havings.any? + collector << " HAVING " + collector = inject_join o.havings, collector, " AND " + end + collector end - collector - end - def visit_Arel_Nodes_Offset o, collector - collector << "SKIP " - visit o.expr, collector - end - def visit_Arel_Nodes_Limit o, collector - collector << "FIRST " - visit o.expr, collector - collector << " " - end + def visit_Arel_Nodes_Offset(o, collector) + collector << "SKIP " + visit o.expr, collector + end + def visit_Arel_Nodes_Limit(o, collector) + collector << "FIRST " + visit o.expr, collector + collector << " " + end end end end - diff --git a/activerecord/lib/arel/visitors/mssql.rb b/activerecord/lib/arel/visitors/mssql.rb index 8347d05d06..4f2945e3a4 100644 --- a/activerecord/lib/arel/visitors/mssql.rb +++ b/activerecord/lib/arel/visitors/mssql.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Visitors class MSSQL < Arel::Visitors::ToSql @@ -11,114 +12,114 @@ module Arel private - # `top` wouldn't really work here. I.e. User.select("distinct first_name").limit(10) would generate - # "select top 10 distinct first_name from users", which is invalid query! it should be - # "select distinct top 10 first_name from users" - def visit_Arel_Nodes_Top o - "" - end - - def visit_Arel_Visitors_MSSQL_RowNumber o, collector - collector << "ROW_NUMBER() OVER (ORDER BY " - inject_join(o.children, collector, ', ') << ") as _row_num" - end + # `top` wouldn't really work here. I.e. User.select("distinct first_name").limit(10) would generate + # "select top 10 distinct first_name from users", which is invalid query! it should be + # "select distinct top 10 first_name from users" + def visit_Arel_Nodes_Top(o) + "" + end - def visit_Arel_Nodes_SelectStatement o, collector - if !o.limit && !o.offset - return super + def visit_Arel_Visitors_MSSQL_RowNumber(o, collector) + collector << "ROW_NUMBER() OVER (ORDER BY " + inject_join(o.children, collector, ", ") << ") as _row_num" end - is_select_count = false - o.cores.each { |x| - core_order_by = row_num_literal determine_order_by(o.orders, x) - if select_count? x - x.projections = [core_order_by] - is_select_count = true - else - x.projections << core_order_by + def visit_Arel_Nodes_SelectStatement(o, collector) + if !o.limit && !o.offset + return super end - } - if is_select_count - # fixme count distinct wouldn't work with limit or offset - collector << "SELECT COUNT(1) as count_id FROM (" - end + is_select_count = false + o.cores.each { |x| + core_order_by = row_num_literal determine_order_by(o.orders, x) + if select_count? x + x.projections = [core_order_by] + is_select_count = true + else + x.projections << core_order_by + end + } + + if is_select_count + # fixme count distinct wouldn't work with limit or offset + collector << "SELECT COUNT(1) as count_id FROM (" + end - collector << "SELECT _t.* FROM (" - collector = o.cores.inject(collector) { |c,x| - visit_Arel_Nodes_SelectCore x, c - } - collector << ") as _t WHERE #{get_offset_limit_clause(o)}" + collector << "SELECT _t.* FROM (" + collector = o.cores.inject(collector) { |c, x| + visit_Arel_Nodes_SelectCore x, c + } + collector << ") as _t WHERE #{get_offset_limit_clause(o)}" - if is_select_count - collector << ") AS subquery" - else - collector + if is_select_count + collector << ") AS subquery" + else + collector + end end - end - def get_offset_limit_clause o - first_row = o.offset ? o.offset.expr.to_i + 1 : 1 - last_row = o.limit ? o.limit.expr.to_i - 1 + first_row : nil - if last_row - " _row_num BETWEEN #{first_row} AND #{last_row}" - else - " _row_num >= #{first_row}" + def get_offset_limit_clause(o) + first_row = o.offset ? o.offset.expr.to_i + 1 : 1 + last_row = o.limit ? o.limit.expr.to_i - 1 + first_row : nil + if last_row + " _row_num BETWEEN #{first_row} AND #{last_row}" + else + " _row_num >= #{first_row}" + end end - end - def visit_Arel_Nodes_DeleteStatement o, collector - collector << 'DELETE ' - if o.limit - collector << 'TOP (' - visit o.limit.expr, collector - collector << ') ' - end - collector << 'FROM ' - collector = visit o.relation, collector - if o.wheres.any? - collector << ' WHERE ' - inject_join o.wheres, collector, AND - else - collector + def visit_Arel_Nodes_DeleteStatement(o, collector) + collector << "DELETE " + if o.limit + collector << "TOP (" + visit o.limit.expr, collector + collector << ") " + end + collector << "FROM " + collector = visit o.relation, collector + if o.wheres.any? + collector << " WHERE " + inject_join o.wheres, collector, AND + else + collector + end end - end - def determine_order_by orders, x - if orders.any? - orders - elsif x.groups.any? - x.groups - else - pk = find_left_table_pk(x.froms) - pk ? [pk] : [] + def determine_order_by(orders, x) + if orders.any? + orders + elsif x.groups.any? + x.groups + else + pk = find_left_table_pk(x.froms) + pk ? [pk] : [] + end end - end - def row_num_literal order_by - RowNumber.new order_by - end + def row_num_literal(order_by) + RowNumber.new order_by + end - def select_count? x - x.projections.length == 1 && Arel::Nodes::Count === x.projections.first - end + def select_count?(x) + x.projections.length == 1 && Arel::Nodes::Count === x.projections.first + end - # FIXME raise exception of there is no pk? - def find_left_table_pk o - if o.kind_of?(Arel::Nodes::Join) - find_left_table_pk(o.left) - elsif o.instance_of?(Arel::Table) - find_primary_key(o) + # FIXME raise exception of there is no pk? + def find_left_table_pk(o) + if o.kind_of?(Arel::Nodes::Join) + find_left_table_pk(o.left) + elsif o.instance_of?(Arel::Table) + find_primary_key(o) + end end - end - def find_primary_key(o) - @primary_keys[o.name] ||= begin - primary_key_name = @connection.primary_key(o.name) - # some tables might be without primary key - primary_key_name && o[primary_key_name] + def find_primary_key(o) + @primary_keys[o.name] ||= begin + primary_key_name = @connection.primary_key(o.name) + # some tables might be without primary key + primary_key_name && o[primary_key_name] + end end - end end end end diff --git a/activerecord/lib/arel/visitors/mysql.rb b/activerecord/lib/arel/visitors/mysql.rb index 4c734f6292..7b32988be6 100644 --- a/activerecord/lib/arel/visitors/mysql.rb +++ b/activerecord/lib/arel/visitors/mysql.rb @@ -1,86 +1,87 @@ # frozen_string_literal: true + module Arel module Visitors class MySQL < Arel::Visitors::ToSql private - def visit_Arel_Nodes_Union o, collector, suppress_parens = false - unless suppress_parens - collector << "( " - end + def visit_Arel_Nodes_Union(o, collector, suppress_parens = false) + unless suppress_parens + collector << "( " + end - collector = case o.left - when Arel::Nodes::Union - visit_Arel_Nodes_Union o.left, collector, true - else - visit o.left, collector - end + collector = case o.left + when Arel::Nodes::Union + visit_Arel_Nodes_Union o.left, collector, true + else + visit o.left, collector + end - collector << " UNION " + collector << " UNION " - collector = case o.right - when Arel::Nodes::Union - visit_Arel_Nodes_Union o.right, collector, true - else - visit o.right, collector - end + collector = case o.right + when Arel::Nodes::Union + visit_Arel_Nodes_Union o.right, collector, true + else + visit o.right, collector + end - if suppress_parens - collector - else - collector << " )" + if suppress_parens + collector + else + collector << " )" + end end - end - def visit_Arel_Nodes_Bin o, collector - collector << "BINARY " - visit o.expr, collector - end + def visit_Arel_Nodes_Bin(o, collector) + collector << "BINARY " + visit o.expr, collector + end - ### - # :'( - # http://dev.mysql.com/doc/refman/5.0/en/select.html#id3482214 - def visit_Arel_Nodes_SelectStatement o, collector - if o.offset && !o.limit - o.limit = Arel::Nodes::Limit.new(18446744073709551615) + ### + # :'( + # http://dev.mysql.com/doc/refman/5.0/en/select.html#id3482214 + def visit_Arel_Nodes_SelectStatement(o, collector) + if o.offset && !o.limit + o.limit = Arel::Nodes::Limit.new(18446744073709551615) + end + super end - super - end - def visit_Arel_Nodes_SelectCore o, collector - o.froms ||= Arel.sql('DUAL') - super - end + def visit_Arel_Nodes_SelectCore(o, collector) + o.froms ||= Arel.sql("DUAL") + super + end - def visit_Arel_Nodes_UpdateStatement o, collector - collector << "UPDATE " - collector = visit o.relation, collector + def visit_Arel_Nodes_UpdateStatement(o, collector) + collector << "UPDATE " + collector = visit o.relation, collector - unless o.values.empty? - collector << " SET " - collector = inject_join o.values, collector, ', ' - end + unless o.values.empty? + collector << " SET " + collector = inject_join o.values, collector, ", " + end - unless o.wheres.empty? - collector << " WHERE " - collector = inject_join o.wheres, collector, ' AND ' - end + unless o.wheres.empty? + collector << " WHERE " + collector = inject_join o.wheres, collector, " AND " + end - unless o.orders.empty? - collector << " ORDER BY " - collector = inject_join o.orders, collector, ', ' - end + unless o.orders.empty? + collector << " ORDER BY " + collector = inject_join o.orders, collector, ", " + end - maybe_visit o.limit, collector - end + maybe_visit o.limit, collector + end - def visit_Arel_Nodes_Concat o, collector - collector << " CONCAT(" - visit o.left, collector - collector << ", " - visit o.right, collector - collector << ") " - collector - end + def visit_Arel_Nodes_Concat(o, collector) + collector << " CONCAT(" + visit o.left, collector + collector << ", " + visit o.right, collector + collector << ") " + collector + end end end end diff --git a/activerecord/lib/arel/visitors/oracle.rb b/activerecord/lib/arel/visitors/oracle.rb index d4749bbae3..7811c18a8c 100644 --- a/activerecord/lib/arel/visitors/oracle.rb +++ b/activerecord/lib/arel/visitors/oracle.rb @@ -1,153 +1,153 @@ # frozen_string_literal: true + module Arel module Visitors class Oracle < Arel::Visitors::ToSql private - def visit_Arel_Nodes_SelectStatement o, collector - o = order_hacks(o) + def visit_Arel_Nodes_SelectStatement(o, collector) + o = order_hacks(o) - # if need to select first records without ORDER BY and GROUP BY and without DISTINCT - # then can use simple ROWNUM in WHERE clause - if o.limit && o.orders.empty? && o.cores.first.groups.empty? && !o.offset && o.cores.first.set_quantifier.class.to_s !~ /Distinct/ - o.cores.last.wheres.push Nodes::LessThanOrEqual.new( - Nodes::SqlLiteral.new('ROWNUM'), o.limit.expr - ) - return super - end + # if need to select first records without ORDER BY and GROUP BY and without DISTINCT + # then can use simple ROWNUM in WHERE clause + if o.limit && o.orders.empty? && o.cores.first.groups.empty? && !o.offset && o.cores.first.set_quantifier.class.to_s !~ /Distinct/ + o.cores.last.wheres.push Nodes::LessThanOrEqual.new( + Nodes::SqlLiteral.new("ROWNUM"), o.limit.expr + ) + return super + end + + if o.limit && o.offset + o = o.dup + limit = o.limit.expr + offset = o.offset + o.offset = nil + collector << " + SELECT * FROM ( + SELECT raw_sql_.*, rownum raw_rnum_ + FROM (" + + collector = super(o, collector) + + if offset.expr.is_a? Nodes::BindParam + collector << ") raw_sql_ WHERE rownum <= (" + collector = visit offset.expr, collector + collector << " + " + collector = visit limit, collector + collector << ") ) WHERE raw_rnum_ > " + collector = visit offset.expr, collector + return collector + else + collector << ") raw_sql_ + WHERE rownum <= #{offset.expr.to_i + limit} + ) + WHERE " + return visit(offset, collector) + end + end - if o.limit && o.offset - o = o.dup - limit = o.limit.expr - offset = o.offset - o.offset = nil - collector << " - SELECT * FROM ( - SELECT raw_sql_.*, rownum raw_rnum_ - FROM (" - - collector = super(o, collector) - - if offset.expr.is_a? Nodes::BindParam - collector << ') raw_sql_ WHERE rownum <= (' - collector = visit offset.expr, collector - collector << ' + ' - collector = visit limit, collector - collector << ") ) WHERE raw_rnum_ > " - collector = visit offset.expr, collector - return collector - else + if o.limit + o = o.dup + limit = o.limit.expr + collector << "SELECT * FROM (" + collector = super(o, collector) + collector << ") WHERE ROWNUM <= " + return visit limit, collector + end + + if o.offset + o = o.dup + offset = o.offset + o.offset = nil + collector << "SELECT * FROM ( + SELECT raw_sql_.*, rownum raw_rnum_ + FROM (" + collector = super(o, collector) collector << ") raw_sql_ - WHERE rownum <= #{offset.expr.to_i + limit} - ) - WHERE " - return visit(offset, collector) + ) + WHERE " + return visit offset, collector end - end - if o.limit - o = o.dup - limit = o.limit.expr - collector << "SELECT * FROM (" - collector = super(o, collector) - collector << ") WHERE ROWNUM <= " - return visit limit, collector + super end - if o.offset - o = o.dup - offset = o.offset - o.offset = nil - collector << "SELECT * FROM ( - SELECT raw_sql_.*, rownum raw_rnum_ - FROM (" - collector = super(o, collector) - collector << ") raw_sql_ - ) - WHERE " - return visit offset, collector + def visit_Arel_Nodes_Limit(o, collector) + collector end - super - end - - def visit_Arel_Nodes_Limit o, collector - collector - end - - def visit_Arel_Nodes_Offset o, collector - collector << "raw_rnum_ > " - visit o.expr, collector - end - - def visit_Arel_Nodes_Except o, collector - collector << "( " - collector = infix_value o, collector, " MINUS " - collector << " )" - end - - def visit_Arel_Nodes_UpdateStatement o, collector - # Oracle does not allow ORDER BY/LIMIT in UPDATEs. - if o.orders.any? && o.limit.nil? - # However, there is no harm in silently eating the ORDER BY clause if no LIMIT has been provided, - # otherwise let the user deal with the error - o = o.dup - o.orders = [] + def visit_Arel_Nodes_Offset(o, collector) + collector << "raw_rnum_ > " + visit o.expr, collector end - super - end + def visit_Arel_Nodes_Except(o, collector) + collector << "( " + collector = infix_value o, collector, " MINUS " + collector << " )" + end - ### - # Hacks for the order clauses specific to Oracle - def order_hacks o - return o if o.orders.empty? - return o unless o.cores.any? do |core| - core.projections.any? do |projection| - /FIRST_VALUE/ === projection + def visit_Arel_Nodes_UpdateStatement(o, collector) + # Oracle does not allow ORDER BY/LIMIT in UPDATEs. + if o.orders.any? && o.limit.nil? + # However, there is no harm in silently eating the ORDER BY clause if no LIMIT has been provided, + # otherwise let the user deal with the error + o = o.dup + o.orders = [] end + + super end - # Previous version with join and split broke ORDER BY clause - # if it contained functions with several arguments (separated by ','). - # - # orders = o.orders.map { |x| visit x }.join(', ').split(',') - orders = o.orders.map do |x| - string = visit(x, Arel::Collectors::SQLString.new).value - if string.include?(',') - split_order_string(string) - else - string + + ### + # Hacks for the order clauses specific to Oracle + def order_hacks(o) + return o if o.orders.empty? + return o unless o.cores.any? do |core| + core.projections.any? do |projection| + /FIRST_VALUE/ === projection + end end - end.flatten - o.orders = [] - orders.each_with_index do |order, i| - o.orders << - Nodes::SqlLiteral.new("alias_#{i}__#{' DESC' if /\bdesc$/i === order}") - end - o - end - - # Split string by commas but count opening and closing brackets - # and ignore commas inside brackets. - def split_order_string(string) - array = [] - i = 0 - string.split(',').each do |part| - if array[i] - array[i] << ',' << part - else - # to ensure that array[i] will be String and not Arel::Nodes::SqlLiteral - array[i] = part.to_s + # Previous version with join and split broke ORDER BY clause + # if it contained functions with several arguments (separated by ','). + # + # orders = o.orders.map { |x| visit x }.join(', ').split(',') + orders = o.orders.map do |x| + string = visit(x, Arel::Collectors::SQLString.new).value + if string.include?(",") + split_order_string(string) + else + string + end + end.flatten + o.orders = [] + orders.each_with_index do |order, i| + o.orders << + Nodes::SqlLiteral.new("alias_#{i}__#{' DESC' if /\bdesc$/i === order}") end - i += 1 if array[i].count('(') == array[i].count(')') + o end - array - end - def visit_Arel_Nodes_BindParam o, collector - collector.add_bind(o.value) { |i| ":a#{i}" } - end + # Split string by commas but count opening and closing brackets + # and ignore commas inside brackets. + def split_order_string(string) + array = [] + i = 0 + string.split(",").each do |part| + if array[i] + array[i] << "," << part + else + # to ensure that array[i] will be String and not Arel::Nodes::SqlLiteral + array[i] = part.to_s + end + i += 1 if array[i].count("(") == array[i].count(")") + end + array + end + def visit_Arel_Nodes_BindParam(o, collector) + collector.add_bind(o.value) { |i| ":a#{i}" } + end end end end diff --git a/activerecord/lib/arel/visitors/oracle12.rb b/activerecord/lib/arel/visitors/oracle12.rb index 648047ae61..e312ba96bb 100644 --- a/activerecord/lib/arel/visitors/oracle12.rb +++ b/activerecord/lib/arel/visitors/oracle12.rb @@ -1,60 +1,61 @@ # frozen_string_literal: true + module Arel module Visitors class Oracle12 < Arel::Visitors::ToSql private - def visit_Arel_Nodes_SelectStatement o, collector - # Oracle does not allow LIMIT clause with select for update - if o.limit && o.lock - raise ArgumentError, <<-MSG + def visit_Arel_Nodes_SelectStatement(o, collector) + # Oracle does not allow LIMIT clause with select for update + if o.limit && o.lock + raise ArgumentError, <<-MSG 'Combination of limit and lock is not supported. because generated SQL statements `SELECT FOR UPDATE and FETCH FIRST n ROWS` generates ORA-02014.` MSG + end + super + end + + def visit_Arel_Nodes_SelectOptions(o, collector) + collector = maybe_visit o.offset, collector + collector = maybe_visit o.limit, collector + collector = maybe_visit o.lock, collector end - super - end - - def visit_Arel_Nodes_SelectOptions o, collector - collector = maybe_visit o.offset, collector - collector = maybe_visit o.limit, collector - collector = maybe_visit o.lock, collector - end - - def visit_Arel_Nodes_Limit o, collector - collector << "FETCH FIRST " - collector = visit o.expr, collector - collector << " ROWS ONLY" - end - - def visit_Arel_Nodes_Offset o, collector - collector << "OFFSET " - visit o.expr, collector - collector << " ROWS" - end - - def visit_Arel_Nodes_Except o, collector - collector << "( " - collector = infix_value o, collector, " MINUS " - collector << " )" - end - - def visit_Arel_Nodes_UpdateStatement o, collector - # Oracle does not allow ORDER BY/LIMIT in UPDATEs. - if o.orders.any? && o.limit.nil? - # However, there is no harm in silently eating the ORDER BY clause if no LIMIT has been provided, - # otherwise let the user deal with the error - o = o.dup - o.orders = [] + + def visit_Arel_Nodes_Limit(o, collector) + collector << "FETCH FIRST " + collector = visit o.expr, collector + collector << " ROWS ONLY" end - super - end + def visit_Arel_Nodes_Offset(o, collector) + collector << "OFFSET " + visit o.expr, collector + collector << " ROWS" + end - def visit_Arel_Nodes_BindParam o, collector - collector.add_bind(o.value) { |i| ":a#{i}" } - end + def visit_Arel_Nodes_Except(o, collector) + collector << "( " + collector = infix_value o, collector, " MINUS " + collector << " )" + end + + def visit_Arel_Nodes_UpdateStatement(o, collector) + # Oracle does not allow ORDER BY/LIMIT in UPDATEs. + if o.orders.any? && o.limit.nil? + # However, there is no harm in silently eating the ORDER BY clause if no LIMIT has been provided, + # otherwise let the user deal with the error + o = o.dup + o.orders = [] + end + + super + end + + def visit_Arel_Nodes_BindParam(o, collector) + collector.add_bind(o.value) { |i| ":a#{i}" } + end end end end diff --git a/activerecord/lib/arel/visitors/postgresql.rb b/activerecord/lib/arel/visitors/postgresql.rb index 047f71aaa6..e7ed888ed8 100644 --- a/activerecord/lib/arel/visitors/postgresql.rb +++ b/activerecord/lib/arel/visitors/postgresql.rb @@ -1,103 +1,104 @@ # frozen_string_literal: true + module Arel module Visitors class PostgreSQL < Arel::Visitors::ToSql - CUBE = 'CUBE' - ROLLUP = 'ROLLUP' - GROUPING_SET = 'GROUPING SET' - LATERAL = 'LATERAL' + CUBE = "CUBE" + ROLLUP = "ROLLUP" + GROUPING_SET = "GROUPING SET" + LATERAL = "LATERAL" private - def visit_Arel_Nodes_Matches o, collector - op = o.case_sensitive ? ' LIKE ' : ' ILIKE ' - collector = infix_value o, collector, op - if o.escape - collector << ' ESCAPE ' - visit o.escape, collector - else - collector + def visit_Arel_Nodes_Matches(o, collector) + op = o.case_sensitive ? " LIKE " : " ILIKE " + collector = infix_value o, collector, op + if o.escape + collector << " ESCAPE " + visit o.escape, collector + else + collector + end end - end - def visit_Arel_Nodes_DoesNotMatch o, collector - op = o.case_sensitive ? ' NOT LIKE ' : ' NOT ILIKE ' - collector = infix_value o, collector, op - if o.escape - collector << ' ESCAPE ' - visit o.escape, collector - else - collector + def visit_Arel_Nodes_DoesNotMatch(o, collector) + op = o.case_sensitive ? " NOT LIKE " : " NOT ILIKE " + collector = infix_value o, collector, op + if o.escape + collector << " ESCAPE " + visit o.escape, collector + else + collector + end end - end - def visit_Arel_Nodes_Regexp o, collector - op = o.case_sensitive ? ' ~ ' : ' ~* ' - infix_value o, collector, op - end + def visit_Arel_Nodes_Regexp(o, collector) + op = o.case_sensitive ? " ~ " : " ~* " + infix_value o, collector, op + end - def visit_Arel_Nodes_NotRegexp o, collector - op = o.case_sensitive ? ' !~ ' : ' !~* ' - infix_value o, collector, op - end + def visit_Arel_Nodes_NotRegexp(o, collector) + op = o.case_sensitive ? " !~ " : " !~* " + infix_value o, collector, op + end - def visit_Arel_Nodes_DistinctOn o, collector - collector << "DISTINCT ON ( " - visit(o.expr, collector) << " )" - end + def visit_Arel_Nodes_DistinctOn(o, collector) + collector << "DISTINCT ON ( " + visit(o.expr, collector) << " )" + end - def visit_Arel_Nodes_BindParam o, collector - collector.add_bind(o.value) { |i| "$#{i}" } - end + def visit_Arel_Nodes_BindParam(o, collector) + collector.add_bind(o.value) { |i| "$#{i}" } + end - def visit_Arel_Nodes_GroupingElement o, collector - collector << "( " - visit(o.expr, collector) << " )" - end + def visit_Arel_Nodes_GroupingElement(o, collector) + collector << "( " + visit(o.expr, collector) << " )" + end - def visit_Arel_Nodes_Cube o, collector - collector << CUBE - grouping_array_or_grouping_element o, collector - end + def visit_Arel_Nodes_Cube(o, collector) + collector << CUBE + grouping_array_or_grouping_element o, collector + end - def visit_Arel_Nodes_RollUp o, collector - collector << ROLLUP - grouping_array_or_grouping_element o, collector - end + def visit_Arel_Nodes_RollUp(o, collector) + collector << ROLLUP + grouping_array_or_grouping_element o, collector + end - def visit_Arel_Nodes_GroupingSet o, collector - collector << GROUPING_SET - grouping_array_or_grouping_element o, collector - end + def visit_Arel_Nodes_GroupingSet(o, collector) + collector << GROUPING_SET + grouping_array_or_grouping_element o, collector + end - def visit_Arel_Nodes_Lateral o, collector - collector << LATERAL - collector << SPACE - grouping_parentheses o, collector - end + def visit_Arel_Nodes_Lateral(o, collector) + collector << LATERAL + collector << SPACE + grouping_parentheses o, collector + end - # Used by Lateral visitor to enclose select queries in parentheses - def grouping_parentheses o, collector - if o.expr.is_a? Nodes::SelectStatement - collector << "(" - visit o.expr, collector - collector << ")" - else - visit o.expr, collector + # Used by Lateral visitor to enclose select queries in parentheses + def grouping_parentheses(o, collector) + if o.expr.is_a? Nodes::SelectStatement + collector << "(" + visit o.expr, collector + collector << ")" + else + visit o.expr, collector + end end - end - # Utilized by GroupingSet, Cube & RollUp visitors to - # handle grouping aggregation semantics - def grouping_array_or_grouping_element o, collector - if o.expr.is_a? Array - collector << "( " - visit o.expr, collector - collector << " )" - else - visit o.expr, collector + # Utilized by GroupingSet, Cube & RollUp visitors to + # handle grouping aggregation semantics + def grouping_array_or_grouping_element(o, collector) + if o.expr.is_a? Array + collector << "( " + visit o.expr, collector + collector << " )" + else + visit o.expr, collector + end end - end end end end diff --git a/activerecord/lib/arel/visitors/sqlite.rb b/activerecord/lib/arel/visitors/sqlite.rb index 4ae093968b..8d4152c428 100644 --- a/activerecord/lib/arel/visitors/sqlite.rb +++ b/activerecord/lib/arel/visitors/sqlite.rb @@ -1,27 +1,27 @@ # frozen_string_literal: true + module Arel module Visitors class SQLite < Arel::Visitors::ToSql private - # Locks are not supported in SQLite - def visit_Arel_Nodes_Lock o, collector - collector - end - - def visit_Arel_Nodes_SelectStatement o, collector - o.limit = Arel::Nodes::Limit.new(-1) if o.offset && !o.limit - super - end + # Locks are not supported in SQLite + def visit_Arel_Nodes_Lock(o, collector) + collector + end - def visit_Arel_Nodes_True o, collector - collector << "1" - end + def visit_Arel_Nodes_SelectStatement(o, collector) + o.limit = Arel::Nodes::Limit.new(-1) if o.offset && !o.limit + super + end - def visit_Arel_Nodes_False o, collector - collector << "0" - end + def visit_Arel_Nodes_True(o, collector) + collector << "1" + end + def visit_Arel_Nodes_False(o, collector) + collector << "0" + end end end end diff --git a/activerecord/lib/arel/visitors/to_sql.rb b/activerecord/lib/arel/visitors/to_sql.rb index 2b5c43b173..24db04200a 100644 --- a/activerecord/lib/arel/visitors/to_sql.rb +++ b/activerecord/lib/arel/visitors/to_sql.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Visitors class UnsupportedVisitError < StandardError @@ -51,796 +52,796 @@ module Arel # specialized for specific databases when necessary. # - WHERE = ' WHERE ' # :nodoc: - SPACE = ' ' # :nodoc: - COMMA = ', ' # :nodoc: - GROUP_BY = ' GROUP BY ' # :nodoc: - ORDER_BY = ' ORDER BY ' # :nodoc: - WINDOW = ' WINDOW ' # :nodoc: - AND = ' AND ' # :nodoc: + WHERE = " WHERE " # :nodoc: + SPACE = " " # :nodoc: + COMMA = ", " # :nodoc: + GROUP_BY = " GROUP BY " # :nodoc: + ORDER_BY = " ORDER BY " # :nodoc: + WINDOW = " WINDOW " # :nodoc: + AND = " AND " # :nodoc: - DISTINCT = 'DISTINCT' # :nodoc: + DISTINCT = "DISTINCT" # :nodoc: - def initialize connection + def initialize(connection) super() - @connection = connection + @connection = connection end - def compile node, &block + def compile(node, &block) accept(node, Arel::Collectors::SQLString.new, &block).value end private - def visit_Arel_Nodes_DeleteStatement o, collector - collector << 'DELETE FROM ' - collector = visit o.relation, collector - if o.wheres.any? - collector << WHERE - collector = inject_join o.wheres, collector, AND + def visit_Arel_Nodes_DeleteStatement(o, collector) + collector << "DELETE FROM " + collector = visit o.relation, collector + if o.wheres.any? + collector << WHERE + collector = inject_join o.wheres, collector, AND + end + + maybe_visit o.limit, collector end - maybe_visit o.limit, collector - end + # FIXME: we should probably have a 2-pass visitor for this + def build_subselect(key, o) + stmt = Nodes::SelectStatement.new + core = stmt.cores.first + core.froms = o.relation + core.wheres = o.wheres + core.projections = [key] + stmt.limit = o.limit + stmt.orders = o.orders + stmt + end - # FIXME: we should probably have a 2-pass visitor for this - def build_subselect key, o - stmt = Nodes::SelectStatement.new - core = stmt.cores.first - core.froms = o.relation - core.wheres = o.wheres - core.projections = [key] - stmt.limit = o.limit - stmt.orders = o.orders - stmt - end + def visit_Arel_Nodes_UpdateStatement(o, collector) + if o.orders.empty? && o.limit.nil? + wheres = o.wheres + else + wheres = [Nodes::In.new(o.key, [build_subselect(o.key, o)])] + end - def visit_Arel_Nodes_UpdateStatement o, collector - if o.orders.empty? && o.limit.nil? - wheres = o.wheres - else - wheres = [Nodes::In.new(o.key, [build_subselect(o.key, o)])] - end + collector << "UPDATE " + collector = visit o.relation, collector + unless o.values.empty? + collector << " SET " + collector = inject_join o.values, collector, ", " + end - collector << "UPDATE " - collector = visit o.relation, collector - unless o.values.empty? - collector << " SET " - collector = inject_join o.values, collector, ", " - end + unless wheres.empty? + collector << " WHERE " + collector = inject_join wheres, collector, " AND " + end - unless wheres.empty? - collector << " WHERE " - collector = inject_join wheres, collector, " AND " + collector end - collector - end + def visit_Arel_Nodes_InsertStatement(o, collector) + collector << "INSERT INTO " + collector = visit o.relation, collector + if o.columns.any? + collector << " (#{o.columns.map { |x| + quote_column_name x.name + }.join ', '})" + end - def visit_Arel_Nodes_InsertStatement o, collector - collector << "INSERT INTO " - collector = visit o.relation, collector - if o.columns.any? - collector << " (#{o.columns.map { |x| - quote_column_name x.name - }.join ', '})" + if o.values + maybe_visit o.values, collector + elsif o.select + maybe_visit o.select, collector + else + collector + end end - if o.values - maybe_visit o.values, collector - elsif o.select - maybe_visit o.select, collector - else - collector + 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 - end - 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 + def visit_Arel_Nodes_Casted(o, collector) + collector << quoted(o.val, o.attribute).to_s end - end - def visit_Arel_Nodes_Casted o, collector - collector << quoted(o.val, o.attribute).to_s - end + def visit_Arel_Nodes_Quoted(o, collector) + collector << quoted(o.expr, nil).to_s + end - def visit_Arel_Nodes_Quoted o, collector - collector << quoted(o.expr, nil).to_s - end + def visit_Arel_Nodes_True(o, collector) + collector << "TRUE" + end - def visit_Arel_Nodes_True o, collector - collector << "TRUE" - end + def visit_Arel_Nodes_False(o, collector) + collector << "FALSE" + end - def visit_Arel_Nodes_False o, collector - collector << "FALSE" - end + def visit_Arel_Nodes_ValuesList(o, collector) + collector << "VALUES " - def visit_Arel_Nodes_ValuesList o, collector - collector << "VALUES " + len = o.rows.length - 1 + o.rows.each_with_index { |row, i| + collector << "(" + row_len = row.length - 1 + row.each_with_index do |value, k| + case value + when Nodes::SqlLiteral, Nodes::BindParam + collector = visit(value, collector) + else + collector << quote(value) + end + collector << COMMA unless k == row_len + end + collector << ")" + collector << COMMA unless i == len + } + collector + end + + def visit_Arel_Nodes_Values(o, collector) + collector << "VALUES (" - len = o.rows.length - 1 - o.rows.each_with_index { |row, i| - collector << '(' - row_len = row.length - 1 - row.each_with_index do |value, k| + len = o.expressions.length - 1 + o.expressions.each_with_index { |value, i| case value when Nodes::SqlLiteral, Nodes::BindParam - collector = visit(value, collector) + collector = visit value, collector else - collector << quote(value) + collector << quote(value).to_s end - collector << COMMA unless k == row_len - end - collector << ')' - collector << COMMA unless i == len - } - collector - end + unless i == len + collector << COMMA + end + } - def visit_Arel_Nodes_Values o, collector - collector << "VALUES (" + collector << ")" + end - len = o.expressions.length - 1 - o.expressions.each_with_index { |value, i| - case value - when Nodes::SqlLiteral, Nodes::BindParam - collector = visit value, collector - else - collector << quote(value).to_s + def visit_Arel_Nodes_SelectStatement(o, collector) + if o.with + collector = visit o.with, collector + collector << SPACE end - unless i == len - collector << COMMA + + collector = o.cores.inject(collector) { |c, x| + visit_Arel_Nodes_SelectCore(x, c) + } + + unless o.orders.empty? + collector << ORDER_BY + len = o.orders.length - 1 + o.orders.each_with_index { |x, i| + collector = visit(x, collector) + collector << COMMA unless len == i + } end - } - collector << ")" - end + visit_Arel_Nodes_SelectOptions(o, collector) - def visit_Arel_Nodes_SelectStatement o, collector - if o.with - collector = visit o.with, collector - collector << SPACE + collector end - collector = o.cores.inject(collector) { |c,x| - visit_Arel_Nodes_SelectCore(x, c) - } - - unless o.orders.empty? - collector << ORDER_BY - len = o.orders.length - 1 - o.orders.each_with_index { |x, i| - collector = visit(x, collector) - collector << COMMA unless len == i - } + def visit_Arel_Nodes_SelectOptions(o, collector) + collector = maybe_visit o.limit, collector + collector = maybe_visit o.offset, collector + collector = maybe_visit o.lock, collector end - visit_Arel_Nodes_SelectOptions(o, collector) + def visit_Arel_Nodes_SelectCore(o, collector) + collector << "SELECT" - collector - end + collector = maybe_visit o.top, collector - def visit_Arel_Nodes_SelectOptions o, collector - collector = maybe_visit o.limit, collector - collector = maybe_visit o.offset, collector - collector = maybe_visit o.lock, collector - end + collector = maybe_visit o.set_quantifier, collector - def visit_Arel_Nodes_SelectCore o, collector - collector << "SELECT" + collect_nodes_for o.projections, collector, SPACE - collector = maybe_visit o.top, collector + if o.source && !o.source.empty? + collector << " FROM " + collector = visit o.source, collector + end - collector = maybe_visit o.set_quantifier, collector + collect_nodes_for o.wheres, collector, WHERE, AND + collect_nodes_for o.groups, collector, GROUP_BY + unless o.havings.empty? + collector << " HAVING " + inject_join o.havings, collector, AND + end + collect_nodes_for o.windows, collector, WINDOW - collect_nodes_for o.projections, collector, SPACE + collector + end - if o.source && !o.source.empty? - collector << " FROM " - collector = visit o.source, collector + def collect_nodes_for(nodes, collector, spacer, connector = COMMA) + unless nodes.empty? + collector << spacer + len = nodes.length - 1 + nodes.each_with_index do |x, i| + collector = visit(x, collector) + collector << connector unless len == i + end + end end - collect_nodes_for o.wheres, collector, WHERE, AND - collect_nodes_for o.groups, collector, GROUP_BY - unless o.havings.empty? - collector << " HAVING " - inject_join o.havings, collector, AND + def visit_Arel_Nodes_Bin(o, collector) + visit o.expr, collector end - collect_nodes_for o.windows, collector, WINDOW - collector - end + def visit_Arel_Nodes_Distinct(o, collector) + collector << DISTINCT + end - def collect_nodes_for nodes, collector, spacer, connector = COMMA - unless nodes.empty? - collector << spacer - len = nodes.length - 1 - nodes.each_with_index do |x, i| - collector = visit(x, collector) - collector << connector unless len == i - end + def visit_Arel_Nodes_DistinctOn(o, collector) + raise NotImplementedError, "DISTINCT ON not implemented for this db" end - end - def visit_Arel_Nodes_Bin o, collector - visit o.expr, collector - end + def visit_Arel_Nodes_With(o, collector) + collector << "WITH " + inject_join o.children, collector, COMMA + end - def visit_Arel_Nodes_Distinct o, collector - collector << DISTINCT - end + def visit_Arel_Nodes_WithRecursive(o, collector) + collector << "WITH RECURSIVE " + inject_join o.children, collector, COMMA + end - def visit_Arel_Nodes_DistinctOn o, collector - raise NotImplementedError, 'DISTINCT ON not implemented for this db' - end + def visit_Arel_Nodes_Union(o, collector) + collector << "( " + infix_value(o, collector, " UNION ") << " )" + end - def visit_Arel_Nodes_With o, collector - collector << "WITH " - inject_join o.children, collector, COMMA - end + def visit_Arel_Nodes_UnionAll(o, collector) + collector << "( " + infix_value(o, collector, " UNION ALL ") << " )" + end - def visit_Arel_Nodes_WithRecursive o, collector - collector << "WITH RECURSIVE " - inject_join o.children, collector, COMMA - end + def visit_Arel_Nodes_Intersect(o, collector) + collector << "( " + infix_value(o, collector, " INTERSECT ") << " )" + end - def visit_Arel_Nodes_Union o, collector - collector << "( " - infix_value(o, collector, " UNION ") << " )" - end + def visit_Arel_Nodes_Except(o, collector) + collector << "( " + infix_value(o, collector, " EXCEPT ") << " )" + end - def visit_Arel_Nodes_UnionAll o, collector - collector << "( " - infix_value(o, collector, " UNION ALL ") << " )" - end + def visit_Arel_Nodes_NamedWindow(o, collector) + collector << quote_column_name(o.name) + collector << " AS " + visit_Arel_Nodes_Window o, collector + end - def visit_Arel_Nodes_Intersect o, collector - collector << "( " - infix_value(o, collector, " INTERSECT ") << " )" - end + def visit_Arel_Nodes_Window(o, collector) + collector << "(" - def visit_Arel_Nodes_Except o, collector - collector << "( " - infix_value(o, collector, " EXCEPT ") << " )" - end + if o.partitions.any? + collector << "PARTITION BY " + collector = inject_join o.partitions, collector, ", " + end - def visit_Arel_Nodes_NamedWindow o, collector - collector << quote_column_name(o.name) - collector << " AS " - visit_Arel_Nodes_Window o, collector - end + if o.orders.any? + collector << SPACE if o.partitions.any? + collector << "ORDER BY " + collector = inject_join o.orders, collector, ", " + end - def visit_Arel_Nodes_Window o, collector - collector << "(" + if o.framing + collector << SPACE if o.partitions.any? || o.orders.any? + collector = visit o.framing, collector + end - if o.partitions.any? - collector << "PARTITION BY " - collector = inject_join o.partitions, collector, ", " + collector << ")" end - if o.orders.any? - collector << SPACE if o.partitions.any? - collector << "ORDER BY " - collector = inject_join o.orders, collector, ", " + def visit_Arel_Nodes_Rows(o, collector) + if o.expr + collector << "ROWS " + visit o.expr, collector + else + collector << "ROWS" + end end - if o.framing - collector << SPACE if o.partitions.any? or o.orders.any? - collector = visit o.framing, collector + def visit_Arel_Nodes_Range(o, collector) + if o.expr + collector << "RANGE " + visit o.expr, collector + else + collector << "RANGE" + end end - collector << ")" - end - - def visit_Arel_Nodes_Rows o, collector - if o.expr - collector << "ROWS " - visit o.expr, collector - else - collector << "ROWS" - end - end + def visit_Arel_Nodes_Preceding(o, collector) + collector = if o.expr + visit o.expr, collector + else + collector << "UNBOUNDED" + end - def visit_Arel_Nodes_Range o, collector - if o.expr - collector << "RANGE " - visit o.expr, collector - else - collector << "RANGE" + collector << " PRECEDING" end - end - def visit_Arel_Nodes_Preceding o, collector - collector = if o.expr - visit o.expr, collector - else - collector << "UNBOUNDED" - end - - collector << " PRECEDING" - end + def visit_Arel_Nodes_Following(o, collector) + collector = if o.expr + visit o.expr, collector + else + collector << "UNBOUNDED" + end - def visit_Arel_Nodes_Following o, collector - collector = if o.expr - visit o.expr, collector - else - collector << "UNBOUNDED" - end + collector << " FOLLOWING" + end - collector << " FOLLOWING" - end + def visit_Arel_Nodes_CurrentRow(o, collector) + collector << "CURRENT ROW" + end - def visit_Arel_Nodes_CurrentRow o, collector - collector << "CURRENT ROW" - end + 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 - 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 " + def visit_Arel_Nodes_Offset(o, collector) + collector << "OFFSET " + visit o.expr, collector end - end - def visit_Arel_Nodes_Offset o, collector - collector << "OFFSET " - visit o.expr, collector - end + def visit_Arel_Nodes_Limit(o, collector) + collector << "LIMIT " + visit o.expr, collector + end - def visit_Arel_Nodes_Limit o, collector - collector << "LIMIT " - visit o.expr, collector - end + # FIXME: this does nothing on most databases, but does on MSSQL + def visit_Arel_Nodes_Top(o, collector) + collector + end - # FIXME: this does nothing on most databases, but does on MSSQL - def visit_Arel_Nodes_Top o, collector - collector - end + def visit_Arel_Nodes_Lock(o, collector) + visit o.expr, collector + end - def visit_Arel_Nodes_Lock o, collector - visit o.expr, collector - end + 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 - def visit_Arel_Nodes_Grouping o, collector - if o.expr.is_a? Nodes::Grouping - visit(o.expr, collector) - else + def visit_Arel_SelectManager(o, collector) collector << "(" - visit(o.expr, collector) << ")" + visit(o.ast, collector) << ")" end - end - - def visit_Arel_SelectManager o, collector - collector << '(' - visit(o.ast, collector) << ')' - end - - def visit_Arel_Nodes_Ascending o, collector - visit(o.expr, collector) << " ASC" - end - def visit_Arel_Nodes_Descending o, collector - visit(o.expr, collector) << " DESC" - end - - def visit_Arel_Nodes_Group o, collector - visit o.expr, collector - end + def visit_Arel_Nodes_Ascending(o, collector) + visit(o.expr, collector) << " ASC" + end - def visit_Arel_Nodes_NamedFunction o, collector - 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 + def visit_Arel_Nodes_Descending(o, collector) + visit(o.expr, collector) << " DESC" end - end - def visit_Arel_Nodes_Extract o, collector - collector << "EXTRACT(#{o.field.to_s.upcase} FROM " - visit(o.expr, collector) << ")" - end + def visit_Arel_Nodes_Group(o, collector) + visit o.expr, collector + end - def visit_Arel_Nodes_Count o, collector - aggregate "COUNT", o, collector - end + def visit_Arel_Nodes_NamedFunction(o, collector) + 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 - def visit_Arel_Nodes_Sum o, collector - aggregate "SUM", o, collector - end + def visit_Arel_Nodes_Extract(o, collector) + collector << "EXTRACT(#{o.field.to_s.upcase} FROM " + visit(o.expr, collector) << ")" + end - def visit_Arel_Nodes_Max o, collector - aggregate "MAX", o, collector - end + def visit_Arel_Nodes_Count(o, collector) + aggregate "COUNT", o, collector + end - def visit_Arel_Nodes_Min o, collector - aggregate "MIN", o, collector - end + def visit_Arel_Nodes_Sum(o, collector) + aggregate "SUM", o, collector + end - def visit_Arel_Nodes_Avg o, collector - aggregate "AVG", o, collector - end + def visit_Arel_Nodes_Max(o, collector) + aggregate "MAX", o, collector + end - def visit_Arel_Nodes_TableAlias o, collector - collector = visit o.relation, collector - collector << " " - collector << quote_table_name(o.name) - end + def visit_Arel_Nodes_Min(o, collector) + aggregate "MIN", o, collector + end - def visit_Arel_Nodes_Between o, collector - collector = visit o.left, collector - collector << " BETWEEN " - visit o.right, collector - end + def visit_Arel_Nodes_Avg(o, collector) + aggregate "AVG", o, collector + end - def visit_Arel_Nodes_GreaterThanOrEqual o, collector - collector = visit o.left, collector - collector << " >= " - visit o.right, collector - end + def visit_Arel_Nodes_TableAlias(o, collector) + collector = visit o.relation, collector + collector << " " + collector << quote_table_name(o.name) + end - def visit_Arel_Nodes_GreaterThan o, collector - collector = visit o.left, collector - collector << " > " - visit o.right, collector - end + def visit_Arel_Nodes_Between(o, collector) + collector = visit o.left, collector + collector << " BETWEEN " + visit o.right, collector + end - def visit_Arel_Nodes_LessThanOrEqual o, collector - collector = visit o.left, collector - collector << " <= " - visit o.right, collector - end + def visit_Arel_Nodes_GreaterThanOrEqual(o, collector) + collector = visit o.left, collector + collector << " >= " + visit o.right, collector + end - def visit_Arel_Nodes_LessThan o, collector - collector = visit o.left, collector - collector << " < " - visit o.right, collector - end + def visit_Arel_Nodes_GreaterThan(o, collector) + collector = visit o.left, collector + collector << " > " + visit o.right, collector + end - 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 + def visit_Arel_Nodes_LessThanOrEqual(o, collector) + collector = visit o.left, collector + collector << " <= " + visit o.right, collector end - end - 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 + def visit_Arel_Nodes_LessThan(o, collector) + collector = visit o.left, collector + collector << " < " + visit o.right, collector end - end - def visit_Arel_Nodes_JoinSource o, collector - if o.left + 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 - if o.right.any? - collector << SPACE if o.left - collector = inject_join o.right, collector, SPACE + + 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 - collector - end - def visit_Arel_Nodes_Regexp o, collector - raise NotImplementedError, '~ not implemented for this db' - end + def visit_Arel_Nodes_JoinSource(o, collector) + if o.left + collector = visit o.left, collector + end + if o.right.any? + collector << SPACE if o.left + collector = inject_join o.right, collector, SPACE + end + collector + end - def visit_Arel_Nodes_NotRegexp o, collector - raise NotImplementedError, '!~ not implemented for this db' - end + def visit_Arel_Nodes_Regexp(o, collector) + raise NotImplementedError, "~ not implemented for this db" + end - def visit_Arel_Nodes_StringJoin o, collector - visit o.left, collector - end + def visit_Arel_Nodes_NotRegexp(o, collector) + raise NotImplementedError, "!~ not implemented for this db" + end - def visit_Arel_Nodes_FullOuterJoin o, collector - collector << "FULL OUTER JOIN " - collector = visit o.left, collector - collector << SPACE - visit o.right, collector - end + def visit_Arel_Nodes_StringJoin(o, collector) + visit o.left, collector + end - def visit_Arel_Nodes_OuterJoin o, collector - collector << "LEFT OUTER JOIN " - collector = visit o.left, collector - collector << " " - visit o.right, collector - end + def visit_Arel_Nodes_FullOuterJoin(o, collector) + collector << "FULL OUTER JOIN " + collector = visit o.left, collector + collector << SPACE + visit o.right, collector + end - def visit_Arel_Nodes_RightOuterJoin o, collector - collector << "RIGHT OUTER JOIN " - collector = visit o.left, collector - collector << SPACE - visit o.right, collector - end + def visit_Arel_Nodes_OuterJoin(o, collector) + collector << "LEFT OUTER JOIN " + collector = visit o.left, collector + collector << " " + visit o.right, collector + end - def visit_Arel_Nodes_InnerJoin o, collector - collector << "INNER JOIN " - collector = visit o.left, collector - if o.right + def visit_Arel_Nodes_RightOuterJoin(o, collector) + collector << "RIGHT OUTER JOIN " + collector = visit o.left, collector collector << SPACE - visit(o.right, collector) - else - collector + visit o.right, collector end - end - def visit_Arel_Nodes_On o, collector - collector << "ON " - visit o.expr, collector - end + def visit_Arel_Nodes_InnerJoin(o, collector) + collector << "INNER JOIN " + collector = visit o.left, collector + if o.right + collector << SPACE + visit(o.right, collector) + else + collector + end + end - def visit_Arel_Nodes_Not o, collector - collector << "NOT (" - visit(o.expr, collector) << ")" - end + def visit_Arel_Nodes_On(o, collector) + collector << "ON " + visit o.expr, collector + end - def visit_Arel_Table o, collector - if o.table_alias - collector << "#{quote_table_name o.name} #{quote_table_name o.table_alias}" - else - collector << quote_table_name(o.name) + def visit_Arel_Nodes_Not(o, collector) + collector << "NOT (" + visit(o.expr, collector) << ")" end - end - def visit_Arel_Nodes_In o, collector - if Array === o.right && o.right.empty? - collector << '1=0' - else - collector = visit o.left, collector - collector << " IN (" - visit(o.right, collector) << ")" + def visit_Arel_Table(o, collector) + if o.table_alias + collector << "#{quote_table_name o.name} #{quote_table_name o.table_alias}" + else + collector << quote_table_name(o.name) + end end - end - def visit_Arel_Nodes_NotIn o, collector - if Array === o.right && o.right.empty? - collector << '1=1' - else - collector = visit o.left, collector - collector << " NOT IN (" - collector = visit o.right, collector - collector << ")" + def visit_Arel_Nodes_In(o, collector) + if Array === o.right && o.right.empty? + collector << "1=0" + else + collector = visit o.left, collector + collector << " IN (" + visit(o.right, collector) << ")" + end end - end - def visit_Arel_Nodes_And o, collector - inject_join o.children, collector, " AND " - end + def visit_Arel_Nodes_NotIn(o, collector) + if Array === o.right && o.right.empty? + collector << "1=1" + else + collector = visit o.left, collector + collector << " NOT IN (" + collector = visit o.right, collector + collector << ")" + end + end - def visit_Arel_Nodes_Or o, collector - collector = visit o.left, collector - collector << " OR " - visit o.right, collector - end + def visit_Arel_Nodes_And(o, collector) + inject_join o.children, collector, " AND " + end - def visit_Arel_Nodes_Assignment o, collector - case o.right - when Arel::Nodes::UnqualifiedColumn, Arel::Attributes::Attribute, Arel::Nodes::BindParam + def visit_Arel_Nodes_Or(o, collector) collector = visit o.left, collector - collector << " = " + collector << " OR " visit o.right, collector - else - collector = visit o.left, collector - collector << " = " - collector << quote(o.right).to_s end - end - def visit_Arel_Nodes_Equality o, collector - right = o.right + def visit_Arel_Nodes_Assignment(o, collector) + case o.right + when Arel::Nodes::UnqualifiedColumn, Arel::Attributes::Attribute, Arel::Nodes::BindParam + 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 + + def visit_Arel_Nodes_Equality(o, collector) + right = o.right - collector = visit o.left, collector + collector = visit o.left, collector - if right.nil? - collector << " IS NULL" - else - collector << " = " - visit right, collector + if right.nil? + collector << " IS NULL" + else + collector << " = " + visit right, collector + end end - end - def visit_Arel_Nodes_NotEqual o, collector - right = o.right + def visit_Arel_Nodes_NotEqual(o, collector) + right = o.right - collector = visit o.left, collector + collector = visit o.left, collector - if right.nil? - collector << " IS NOT NULL" - else - collector << " != " - visit right, collector + if right.nil? + collector << " IS NOT NULL" + else + collector << " != " + visit right, collector + end end - end - def visit_Arel_Nodes_As o, collector - collector = visit o.left, collector - collector << " AS " - visit o.right, collector - end + def visit_Arel_Nodes_As(o, collector) + collector = visit o.left, collector + collector << " AS " + visit o.right, collector + end - def visit_Arel_Nodes_Case o, collector - collector << "CASE " - if o.case - visit o.case, collector - collector << " " + 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 - o.conditions.each do |condition| - visit condition, collector - collector << " " + + def visit_Arel_Nodes_When(o, collector) + collector << "WHEN " + visit o.left, collector + collector << " THEN " + visit o.right, collector end - if o.default - visit o.default, collector - collector << " " + + def visit_Arel_Nodes_Else(o, collector) + collector << "ELSE " + visit o.expr, collector end - collector << "END" - end - def visit_Arel_Nodes_When o, collector - collector << "WHEN " - visit o.left, collector - collector << " THEN " - visit o.right, collector - end + def visit_Arel_Nodes_UnqualifiedColumn(o, collector) + collector << "#{quote_column_name o.name}" + collector + end - def visit_Arel_Nodes_Else o, collector - collector << "ELSE " - visit o.expr, collector - end + 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 + alias :visit_Arel_Attributes_Integer :visit_Arel_Attributes_Attribute + alias :visit_Arel_Attributes_Float :visit_Arel_Attributes_Attribute + alias :visit_Arel_Attributes_Decimal :visit_Arel_Attributes_Attribute + alias :visit_Arel_Attributes_String :visit_Arel_Attributes_Attribute + alias :visit_Arel_Attributes_Time :visit_Arel_Attributes_Attribute + alias :visit_Arel_Attributes_Boolean :visit_Arel_Attributes_Attribute - def visit_Arel_Nodes_UnqualifiedColumn o, collector - collector << "#{quote_column_name o.name}" - collector - end + def literal(o, collector); collector << o.to_s; end - 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 - alias :visit_Arel_Attributes_Integer :visit_Arel_Attributes_Attribute - alias :visit_Arel_Attributes_Float :visit_Arel_Attributes_Attribute - alias :visit_Arel_Attributes_Decimal :visit_Arel_Attributes_Attribute - alias :visit_Arel_Attributes_String :visit_Arel_Attributes_Attribute - alias :visit_Arel_Attributes_Time :visit_Arel_Attributes_Attribute - alias :visit_Arel_Attributes_Boolean :visit_Arel_Attributes_Attribute + def visit_Arel_Nodes_BindParam(o, collector) + collector.add_bind(o.value) { "?" } + end - def literal o, collector; collector << o.to_s; end + alias :visit_Arel_Nodes_SqlLiteral :literal + alias :visit_Bignum :literal + alias :visit_Fixnum :literal + alias :visit_Integer :literal - def visit_Arel_Nodes_BindParam o, collector - collector.add_bind(o.value) { "?" } - end + def quoted(o, a) + if a && a.able_to_type_cast? + quote(a.type_cast_for_database(o)) + else + quote(o) + end + end + + def unsupported(o, collector) + raise UnsupportedVisitError.new(o) + end - alias :visit_Arel_Nodes_SqlLiteral :literal - alias :visit_Bignum :literal - alias :visit_Fixnum :literal - alias :visit_Integer :literal + alias :visit_ActiveSupport_Multibyte_Chars :unsupported + alias :visit_ActiveSupport_StringInquirer :unsupported + alias :visit_BigDecimal :unsupported + alias :visit_Class :unsupported + alias :visit_Date :unsupported + alias :visit_DateTime :unsupported + alias :visit_FalseClass :unsupported + alias :visit_Float :unsupported + alias :visit_Hash :unsupported + alias :visit_NilClass :unsupported + alias :visit_String :unsupported + alias :visit_Symbol :unsupported + alias :visit_Time :unsupported + alias :visit_TrueClass :unsupported - def quoted o, a - if a && a.able_to_type_cast? - quote(a.type_cast_for_database(o)) - else - quote(o) + def visit_Arel_Nodes_InfixOperation(o, collector) + collector = visit o.left, collector + collector << " #{o.operator} " + visit o.right, collector end - end - def unsupported o, collector - raise UnsupportedVisitError.new(o) - end + alias :visit_Arel_Nodes_Addition :visit_Arel_Nodes_InfixOperation + alias :visit_Arel_Nodes_Subtraction :visit_Arel_Nodes_InfixOperation + alias :visit_Arel_Nodes_Multiplication :visit_Arel_Nodes_InfixOperation + alias :visit_Arel_Nodes_Division :visit_Arel_Nodes_InfixOperation - alias :visit_ActiveSupport_Multibyte_Chars :unsupported - alias :visit_ActiveSupport_StringInquirer :unsupported - alias :visit_BigDecimal :unsupported - alias :visit_Class :unsupported - alias :visit_Date :unsupported - alias :visit_DateTime :unsupported - alias :visit_FalseClass :unsupported - alias :visit_Float :unsupported - alias :visit_Hash :unsupported - alias :visit_NilClass :unsupported - alias :visit_String :unsupported - alias :visit_Symbol :unsupported - alias :visit_Time :unsupported - alias :visit_TrueClass :unsupported - - def visit_Arel_Nodes_InfixOperation o, collector - collector = visit o.left, collector - collector << " #{o.operator} " - visit o.right, collector - end + def visit_Arel_Nodes_UnaryOperation(o, collector) + collector << " #{o.operator} " + visit o.expr, collector + end - alias :visit_Arel_Nodes_Addition :visit_Arel_Nodes_InfixOperation - alias :visit_Arel_Nodes_Subtraction :visit_Arel_Nodes_InfixOperation - alias :visit_Arel_Nodes_Multiplication :visit_Arel_Nodes_InfixOperation - alias :visit_Arel_Nodes_Division :visit_Arel_Nodes_InfixOperation + def visit_Array(o, collector) + inject_join o, collector, ", " + end + alias :visit_Set :visit_Array - def visit_Arel_Nodes_UnaryOperation o, collector - collector << " #{o.operator} " - visit o.expr, collector - end + def quote(value) + return value if Arel::Nodes::SqlLiteral === value + @connection.quote value + end - def visit_Array o, collector - inject_join o, collector, ", " - end - alias :visit_Set :visit_Array + def quote_table_name(name) + return name if Arel::Nodes::SqlLiteral === name + @connection.quote_table_name(name) + end - def quote value - return value if Arel::Nodes::SqlLiteral === value - @connection.quote value - end + def quote_column_name(name) + return name if Arel::Nodes::SqlLiteral === name + @connection.quote_column_name(name) + end - def quote_table_name name - return name if Arel::Nodes::SqlLiteral === name - @connection.quote_table_name(name) - end + def maybe_visit(thing, collector) + return collector unless thing + collector << " " + visit thing, collector + end - def quote_column_name name - return name if Arel::Nodes::SqlLiteral === name - @connection.quote_column_name(name) - end + def inject_join(list, collector, join_str) + len = list.length - 1 + list.each_with_index.inject(collector) { |c, (x, i)| + if i == len + visit x, c + else + visit(x, c) << join_str + end + } + end - def maybe_visit thing, collector - return collector unless thing - collector << " " - visit thing, collector - end + def infix_value(o, collector, value) + collector = visit o.left, collector + collector << value + visit o.right, collector + end - def inject_join list, collector, join_str - len = list.length - 1 - list.each_with_index.inject(collector) { |c, (x,i)| - if i == len - visit x, c + 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 - visit(x, c) << join_str + collector end - } - end - - def infix_value o, collector, value - collector = visit o.left, collector - collector << value - visit o.right, collector - end - - 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 end end end diff --git a/activerecord/lib/arel/visitors/visitor.rb b/activerecord/lib/arel/visitors/visitor.rb index f156be9a0a..6cbe5caf8c 100644 --- a/activerecord/lib/arel/visitors/visitor.rb +++ b/activerecord/lib/arel/visitors/visitor.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Visitors class Visitor @@ -6,36 +7,36 @@ module Arel @dispatch = get_dispatch_cache end - def accept object, *args + def accept(object, *args) visit object, *args end private - attr_reader :dispatch + attr_reader :dispatch - def self.dispatch_cache - Hash.new do |hash, klass| - hash[klass] = "visit_#{(klass.name || '').gsub('::', '_')}" + def self.dispatch_cache + Hash.new do |hash, klass| + hash[klass] = "visit_#{(klass.name || '').gsub('::', '_')}" + end end - end - def get_dispatch_cache - self.class.dispatch_cache - end + def get_dispatch_cache + self.class.dispatch_cache + end - def visit object, *args - dispatch_method = dispatch[object.class] - send dispatch_method, object, *args - rescue NoMethodError => e - raise e if respond_to?(dispatch_method, true) - superklass = object.class.ancestors.find { |klass| - respond_to?(dispatch[klass], true) - } - raise(TypeError, "Cannot visit #{object.class}") unless superklass - dispatch[object.class] = dispatch[superklass] - retry - end + def visit(object, *args) + dispatch_method = dispatch[object.class] + send dispatch_method, object, *args + rescue NoMethodError => e + raise e if respond_to?(dispatch_method, true) + superklass = object.class.ancestors.find { |klass| + respond_to?(dispatch[klass], true) + } + raise(TypeError, "Cannot visit #{object.class}") unless superklass + dispatch[object.class] = dispatch[superklass] + retry + end end end end diff --git a/activerecord/lib/arel/visitors/where_sql.rb b/activerecord/lib/arel/visitors/where_sql.rb index 55e6ca9a21..d9c87f0130 100644 --- a/activerecord/lib/arel/visitors/where_sql.rb +++ b/activerecord/lib/arel/visitors/where_sql.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Arel module Visitors class WhereSql < Arel::Visitors::ToSql @@ -9,14 +10,14 @@ module Arel private - def visit_Arel_Nodes_SelectCore o, collector - collector << "WHERE " - wheres = o.wheres.map do |where| - Nodes::SqlLiteral.new(@inner_visitor.accept(where, collector.class.new).value) - end + def visit_Arel_Nodes_SelectCore(o, collector) + collector << "WHERE " + wheres = o.wheres.map do |where| + Nodes::SqlLiteral.new(@inner_visitor.accept(where, collector.class.new).value) + end - inject_join wheres, collector, ' AND ' - end + inject_join wheres, collector, " AND " + end end end end diff --git a/activerecord/lib/arel/window_predications.rb b/activerecord/lib/arel/window_predications.rb index f93dede036..60d8f05b3c 100644 --- a/activerecord/lib/arel/window_predications.rb +++ b/activerecord/lib/arel/window_predications.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true + module Arel module WindowPredications - def over(expr = nil) Nodes::Over.new(self, expr) end - end -end \ No newline at end of file +end -- cgit v1.2.3