aboutsummaryrefslogtreecommitdiffstats
path: root/lib/arel
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2014-09-22 11:01:03 -0700
committerAaron Patterson <aaron.patterson@gmail.com>2014-09-22 11:01:03 -0700
commitb57a11cb8abfca345f63084ce841c6f412c1156e (patch)
treec58702c92ba90e121a4556bc4053a0e6b790873f /lib/arel
parentc903c6b28933a041d42d943c6c83f98aaa81f42a (diff)
downloadrails-b57a11cb8abfca345f63084ce841c6f412c1156e.tar.gz
rails-b57a11cb8abfca345f63084ce841c6f412c1156e.tar.bz2
rails-b57a11cb8abfca345f63084ce841c6f412c1156e.zip
move the dispatch table to be per-instance
visitors are not shared among threads, so any mutations to the cache should be OK. The cache is also pre-populated on construction, but we should pull that out so we can share the cache among visitors in the future.
Diffstat (limited to 'lib/arel')
-rw-r--r--lib/arel/visitors/depth_first.rb4
-rw-r--r--lib/arel/visitors/dot.rb1
-rw-r--r--lib/arel/visitors/reduce.rb8
-rw-r--r--lib/arel/visitors/to_sql.rb10
-rw-r--r--lib/arel/visitors/visitor.rb31
-rw-r--r--lib/arel/visitors/where_sql.rb2
6 files changed, 37 insertions, 19 deletions
diff --git a/lib/arel/visitors/depth_first.rb b/lib/arel/visitors/depth_first.rb
index eab20ac831..a434f404c7 100644
--- a/lib/arel/visitors/depth_first.rb
+++ b/lib/arel/visitors/depth_first.rb
@@ -3,6 +3,7 @@ module Arel
class DepthFirst < Arel::Visitors::Visitor
def initialize block = nil
@block = block || Proc.new
+ super()
end
private
@@ -86,6 +87,7 @@ module Arel
alias :visit_Arel_Nodes_RightOuterJoin :binary
alias :visit_Arel_Nodes_TableAlias :binary
alias :visit_Arel_Nodes_Values :binary
+ alias :visit_Arel_Nodes_Union :binary
def visit_Arel_Nodes_StringJoin o
visit o.left
@@ -116,6 +118,8 @@ module Arel
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
diff --git a/lib/arel/visitors/dot.rb b/lib/arel/visitors/dot.rb
index 12cce1e266..e0c02d717a 100644
--- a/lib/arel/visitors/dot.rb
+++ b/lib/arel/visitors/dot.rb
@@ -15,6 +15,7 @@ module Arel
end
def initialize
+ super()
@nodes = []
@edges = []
@node_stack = []
diff --git a/lib/arel/visitors/reduce.rb b/lib/arel/visitors/reduce.rb
index 9670cad27c..1d74934fe5 100644
--- a/lib/arel/visitors/reduce.rb
+++ b/lib/arel/visitors/reduce.rb
@@ -10,14 +10,14 @@ module Arel
private
def visit object, collector
- send dispatch[object.class], object, collector
+ send dispatch[object.class.name], object, collector
rescue NoMethodError => e
- raise e if respond_to?(dispatch[object.class], true)
+ raise e if respond_to?(dispatch[object.class.name], true)
superklass = object.class.ancestors.find { |klass|
- respond_to?(dispatch[klass], true)
+ respond_to?(dispatch[klass.name], true)
}
raise(TypeError, "Cannot visit #{object.class}") unless superklass
- dispatch[object.class] = dispatch[superklass]
+ dispatch[object.class.name] = dispatch[superklass.name]
retry
end
end
diff --git a/lib/arel/visitors/to_sql.rb b/lib/arel/visitors/to_sql.rb
index dea6830e8f..7bef8feded 100644
--- a/lib/arel/visitors/to_sql.rb
+++ b/lib/arel/visitors/to_sql.rb
@@ -59,8 +59,8 @@ module Arel
DISTINCT = 'DISTINCT' # :nodoc:
def initialize connection
+ super()
@connection = connection
- @schema_cache = connection.schema_cache
end
def compile node, &block
@@ -69,6 +69,10 @@ module Arel
private
+ def schema_cache
+ @connection.schema_cache
+ end
+
def visit_Arel_Nodes_DeleteStatement o, collector
collector << "DELETE FROM "
collector = visit o.relation, collector
@@ -160,7 +164,7 @@ module Arel
end
def table_exists? name
- @schema_cache.table_exists? name
+ schema_cache.table_exists? name
end
def column_for attr
@@ -174,7 +178,7 @@ module Arel
end
def column_cache(table)
- @schema_cache.columns_hash(table)
+ schema_cache.columns_hash(table)
end
def visit_Arel_Nodes_Values o, collector
diff --git a/lib/arel/visitors/visitor.rb b/lib/arel/visitors/visitor.rb
index 0730c15794..2317d0c95f 100644
--- a/lib/arel/visitors/visitor.rb
+++ b/lib/arel/visitors/visitor.rb
@@ -1,32 +1,39 @@
module Arel
module Visitors
class Visitor
+ def initialize
+ @dispatch = Hash.new do |hash, class_name|
+ raise if class_name == 'Arel::Nodes::Union'
+ hash[class_name] = "visit_#{(class_name || '').gsub('::', '_')}"
+ end
+
+ # pre-populate cache. FIXME: this should be passed in to each
+ # instance, but we can do that later.
+ self.class.private_instance_methods.sort.each do |name|
+ next unless name =~ /^visit_(.*)$/
+ @dispatch[$1.gsub('_', '::')] = name
+ end
+ end
+
def accept object
visit object
end
private
- DISPATCH = Hash.new do |hash, visitor_class|
- hash[visitor_class] =
- Hash.new do |method_hash, node_class|
- method_hash[node_class] = "visit_#{(node_class.name || '').gsub('::', '_')}"
- end
- end
-
def dispatch
- DISPATCH[self.class]
+ @dispatch
end
def visit object
- send dispatch[object.class], object
+ send dispatch[object.class.name], object
rescue NoMethodError => e
- raise e if respond_to?(dispatch[object.class], true)
+ raise e if respond_to?(dispatch[object.class.name], true)
superklass = object.class.ancestors.find { |klass|
- respond_to?(dispatch[klass], true)
+ respond_to?(dispatch[klass.name], true)
}
raise(TypeError, "Cannot visit #{object.class}") unless superklass
- dispatch[object.class] = dispatch[superklass]
+ dispatch[object.class.name] = dispatch[superklass.name]
retry
end
end
diff --git a/lib/arel/visitors/where_sql.rb b/lib/arel/visitors/where_sql.rb
index 27dde73673..afde15a6c5 100644
--- a/lib/arel/visitors/where_sql.rb
+++ b/lib/arel/visitors/where_sql.rb
@@ -1,6 +1,8 @@
module Arel
module Visitors
class WhereSql < Arel::Visitors::ToSql
+ private
+
def visit_Arel_Nodes_SelectCore o, collector
collector << "WHERE "
inject_join o.wheres, collector, ' AND '