diff options
author | Aaron Patterson <aaron.patterson@gmail.com> | 2010-08-18 16:32:32 -0700 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2010-08-18 16:32:32 -0700 |
commit | 6b851c686faefe54efce0857f8b7b7b0c04bb673 (patch) | |
tree | c95e779ce383412519a06b4b455d31df53ea3c4d /lib | |
parent | 0403efa4c6ad926a61dd0d134d63d962238e2c4f (diff) | |
download | rails-6b851c686faefe54efce0857f8b7b7b0c04bb673.tar.gz rails-6b851c686faefe54efce0857f8b7b7b0c04bb673.tar.bz2 rails-6b851c686faefe54efce0857f8b7b7b0c04bb673.zip |
joins can be created
Diffstat (limited to 'lib')
-rw-r--r-- | lib/arel/nodes.rb | 3 | ||||
-rw-r--r-- | lib/arel/nodes/inner_join.rb | 13 | ||||
-rw-r--r-- | lib/arel/nodes/on.rb | 11 | ||||
-rw-r--r-- | lib/arel/nodes/table_alias.rb | 20 | ||||
-rw-r--r-- | lib/arel/select_manager.rb | 9 | ||||
-rw-r--r-- | lib/arel/table.rb | 13 | ||||
-rw-r--r-- | lib/arel/visitors/to_sql.rb | 25 |
7 files changed, 87 insertions, 7 deletions
diff --git a/lib/arel/nodes.rb b/lib/arel/nodes.rb index 4d6db39aec..7183a60591 100644 --- a/lib/arel/nodes.rb +++ b/lib/arel/nodes.rb @@ -10,3 +10,6 @@ require 'arel/nodes/insert_statement' require 'arel/nodes/update_statement' require 'arel/nodes/delete_statement' require 'arel/nodes/unqualified_column' +require 'arel/nodes/table_alias' +require 'arel/nodes/inner_join' +require 'arel/nodes/on' diff --git a/lib/arel/nodes/inner_join.rb b/lib/arel/nodes/inner_join.rb new file mode 100644 index 0000000000..a39ded9f1c --- /dev/null +++ b/lib/arel/nodes/inner_join.rb @@ -0,0 +1,13 @@ +module Arel + module Nodes + class InnerJoin + attr_accessor :left, :right, :constraint + + def initialize left, right, constraint + @left = left + @right = right + @constraint = constraint + end + end + end +end diff --git a/lib/arel/nodes/on.rb b/lib/arel/nodes/on.rb new file mode 100644 index 0000000000..4cc76b70db --- /dev/null +++ b/lib/arel/nodes/on.rb @@ -0,0 +1,11 @@ +module Arel + module Nodes + class On + attr_accessor :expr + + def initialize expr + @expr = expr + end + end + end +end diff --git a/lib/arel/nodes/table_alias.rb b/lib/arel/nodes/table_alias.rb new file mode 100644 index 0000000000..4f1d70ee54 --- /dev/null +++ b/lib/arel/nodes/table_alias.rb @@ -0,0 +1,20 @@ +module Arel + module Nodes + class TableAlias + attr_reader :name, :relation, :columns + + def initialize name, relation + @name = name + @relation = relation + @columns = relation.columns.map { |column| + column.dup.tap { |col| col.relation = self } + } + end + + def [] name + name = name.to_s + columns.find { |column| column.name == name } + end + end + end +end diff --git a/lib/arel/select_manager.rb b/lib/arel/select_manager.rb index f278465c51..533911e635 100644 --- a/lib/arel/select_manager.rb +++ b/lib/arel/select_manager.rb @@ -8,12 +8,21 @@ module Arel @ctx = @head.cores.last end + def on expr + @ctx.froms.last.constraint = Nodes::On.new(expr) + self + end + def from table @ctx.froms << table self end def project projection + projection = ::String == projection.class ? + Nodes::SqlLiteral.new(projection) : + projection + @ctx.projections << projection self end diff --git a/lib/arel/table.rb b/lib/arel/table.rb index 2df20e50e8..5a66db0627 100644 --- a/lib/arel/table.rb +++ b/lib/arel/table.rb @@ -5,19 +5,30 @@ module Arel @engine = nil class << self; attr_accessor :engine; end - attr_reader :name, :engine + attr_reader :name, :engine, :aliases def initialize name, engine = Table.engine @name = name @engine = engine @engine = engine[:engine] if Hash === engine @columns = nil + @aliases = [] + end + + def alias + Nodes::TableAlias.new("#{name}_2", self).tap do |node| + @aliases << node + end end def tm SelectManager.new(@engine).from(self) end + def join relation + SelectManager.new(@engine).from(Nodes::InnerJoin.new(self, relation, nil)) + end + def where condition tm.where condition end diff --git a/lib/arel/visitors/to_sql.rb b/lib/arel/visitors/to_sql.rb index 0e5998c573..3b0a0dc5df 100644 --- a/lib/arel/visitors/to_sql.rb +++ b/lib/arel/visitors/to_sql.rb @@ -36,7 +36,7 @@ module Arel }.join ', '})" unless o.columns.empty?), ("VALUES (#{o.values.map { |value| - value ? quote(visit(value)) : 'NULL' + value ? visit(value) : 'NULL' }.join ', '})" unless o.values.empty?), ].compact.join ' ' @@ -57,12 +57,24 @@ module Arel ].compact.join ' ' end + def visit_Arel_Nodes_TableAlias o + "#{visit o.relation} #{quote_table_name o.name}" + end + + def visit_Arel_Nodes_InnerJoin o + "#{visit o.left} INNER JOIN #{visit o.right} #{visit o.constraint}" + end + + def visit_Arel_Nodes_On o + "ON #{visit o.expr}" + end + def visit_Arel_Table o quote_table_name o.name end def visit_Arel_Nodes_In o - "#{visit o.left} IN (#{o.right.map { |x| quote visit x }.join ', '})" + "#{visit o.left} IN (#{o.right.map { |x| visit x }.join ', '})" end def visit_Arel_Nodes_Or o @@ -71,7 +83,7 @@ module Arel def visit_Arel_Nodes_Equality o right = o.right - right = right ? quote(visit(right)) : 'NULL' + right = right ? visit(right) : 'NULL' "#{visit o.left} = #{right}" end @@ -87,12 +99,13 @@ module Arel alias :visit_Arel_Attributes_Time :visit_Arel_Attributes_Attribute def visit_Fixnum o; o end - alias :visit_Time :visit_Fixnum - alias :visit_String :visit_Fixnum - alias :visit_TrueClass :visit_Fixnum alias :visit_Arel_Nodes_SqlLiteral :visit_Fixnum alias :visit_Arel_SqlLiteral :visit_Fixnum # This is deprecated + def visit_TrueClass o; quote(o) end + def visit_String o; quote(o) end + def visit_Time o; quote(o) end + DISPATCH = {} def visit object send "visit_#{object.class.name.gsub('::', '_')}", object |