From 93d72131bcc24ccb5536bec672d2dac94f8de651 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 24 Mar 2014 16:26:09 -0700 Subject: add the casting node to the AST at build time If we add the casting node to the ast at build time, then we can avoid doing the lookup at visit time. --- lib/arel/nodes.rb | 32 ++++++++++++++++++++++++++++++++ lib/arel/nodes/node.rb | 2 ++ lib/arel/predications.rb | 8 ++++---- lib/arel/update_manager.rb | 4 ++-- lib/arel/visitors/mysql.rb | 4 +++- lib/arel/visitors/to_sql.rb | 40 ++++++++++++++++++++++++++-------------- 6 files changed, 69 insertions(+), 21 deletions(-) (limited to 'lib/arel') diff --git a/lib/arel/nodes.rb b/lib/arel/nodes.rb index 54caea69a1..3642958cf8 100644 --- a/lib/arel/nodes.rb +++ b/lib/arel/nodes.rb @@ -50,3 +50,35 @@ require 'arel/nodes/outer_join' require 'arel/nodes/string_join' require 'arel/nodes/sql_literal' + +module Arel + module Nodes + class Casted < Arel::Nodes::Node # :nodoc: + attr_reader :val, :attribute + def initialize val, attribute + @val = val + @attribute = attribute + super() + end + + def nil?; @val.nil?; end + end + + class Quoted < Arel::Nodes::Unary # :nodoc: + end + + def self.build_quoted other, attribute = nil + case other + when Arel::Nodes::Node, Arel::Attributes::Attribute + other + else + case attribute + when Arel::Attributes::Attribute + Casted.new other, attribute + else + Quoted.new other + end + end + end + end +end diff --git a/lib/arel/nodes/node.rb b/lib/arel/nodes/node.rb index 36e7628612..a3eadf7170 100644 --- a/lib/arel/nodes/node.rb +++ b/lib/arel/nodes/node.rb @@ -51,6 +51,8 @@ module Arel ::Arel::Visitors::DepthFirst.new(block).accept self end + + def cast_reference?; false; end # :nodoc: end end end diff --git a/lib/arel/predications.rb b/lib/arel/predications.rb index c485de07e3..fb98f0a383 100644 --- a/lib/arel/predications.rb +++ b/lib/arel/predications.rb @@ -13,7 +13,7 @@ module Arel end def eq other - Nodes::Equality.new self, other + Nodes::Equality.new self, Nodes.build_quoted(other, self) end def eq_any others @@ -21,7 +21,7 @@ module Arel end def eq_all others - grouping_all :eq, others + grouping_all :eq, others.map { |x| Nodes.build_quoted(x, self) } end def in other @@ -93,7 +93,7 @@ module Arel end def matches other - Nodes::Matches.new self, other + Nodes::Matches.new self, Nodes.build_quoted(other, self) end def matches_any others @@ -105,7 +105,7 @@ module Arel end def does_not_match other - Nodes::DoesNotMatch.new self, other + Nodes::DoesNotMatch.new self, Nodes.build_quoted(other, self) end def does_not_match_any others diff --git a/lib/arel/update_manager.rb b/lib/arel/update_manager.rb index 56e219040c..db8cf05f76 100644 --- a/lib/arel/update_manager.rb +++ b/lib/arel/update_manager.rb @@ -7,12 +7,12 @@ module Arel end def take limit - @ast.limit = Nodes::Limit.new(limit) if limit + @ast.limit = Nodes::Limit.new(Nodes.build_quoted(limit)) if limit self end def key= key - @ast.key = key + @ast.key = Nodes.build_quoted(key) end def key diff --git a/lib/arel/visitors/mysql.rb b/lib/arel/visitors/mysql.rb index 4db5a94019..ec9d91f8ce 100644 --- a/lib/arel/visitors/mysql.rb +++ b/lib/arel/visitors/mysql.rb @@ -32,7 +32,9 @@ module Arel # :'( # http://dev.mysql.com/doc/refman/5.0/en/select.html#id3482214 def visit_Arel_Nodes_SelectStatement o, a - o.limit = Arel::Nodes::Limit.new(18446744073709551615) if o.offset && !o.limit + if o.offset && !o.limit + o.limit = Arel::Nodes::Limit.new(Nodes.build_quoted(18446744073709551615)) + end super end diff --git a/lib/arel/visitors/to_sql.rb b/lib/arel/visitors/to_sql.rb index 236f0354b1..69c82e792a 100644 --- a/lib/arel/visitors/to_sql.rb +++ b/lib/arel/visitors/to_sql.rb @@ -116,6 +116,14 @@ module Arel o.alias ? " AS #{visit o.alias, a}" : ''}" end + def visit_Arel_Nodes_Casted o, a + quoted o.val, o.attribute + end + + def visit_Arel_Nodes_Quoted o, a + quoted o.expr, nil + end + def visit_Arel_Nodes_True o, a "TRUE" end @@ -562,20 +570,24 @@ module Arel quote(o, column_for(a)) end - alias :visit_ActiveSupport_Multibyte_Chars :quoted - alias :visit_ActiveSupport_StringInquirer :quoted - alias :visit_BigDecimal :quoted - alias :visit_Class :quoted - alias :visit_Date :quoted - alias :visit_DateTime :quoted - alias :visit_FalseClass :quoted - alias :visit_Float :quoted - alias :visit_Hash :quoted - alias :visit_NilClass :quoted - alias :visit_String :quoted - alias :visit_Symbol :quoted - alias :visit_Time :quoted - alias :visit_TrueClass :quoted + def unsupported o, a + raise "unsupported: #{o.class.name}" + end + + 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, a "#{visit o.left, a} #{o.operator} #{visit o.right, a}" -- cgit v1.2.3