aboutsummaryrefslogtreecommitdiffstats
path: root/lib/arel
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2010-08-18 16:32:32 -0700
committerAaron Patterson <aaron.patterson@gmail.com>2010-08-18 16:32:32 -0700
commit6b851c686faefe54efce0857f8b7b7b0c04bb673 (patch)
treec95e779ce383412519a06b4b455d31df53ea3c4d /lib/arel
parent0403efa4c6ad926a61dd0d134d63d962238e2c4f (diff)
downloadrails-6b851c686faefe54efce0857f8b7b7b0c04bb673.tar.gz
rails-6b851c686faefe54efce0857f8b7b7b0c04bb673.tar.bz2
rails-6b851c686faefe54efce0857f8b7b7b0c04bb673.zip
joins can be created
Diffstat (limited to 'lib/arel')
-rw-r--r--lib/arel/nodes.rb3
-rw-r--r--lib/arel/nodes/inner_join.rb13
-rw-r--r--lib/arel/nodes/on.rb11
-rw-r--r--lib/arel/nodes/table_alias.rb20
-rw-r--r--lib/arel/select_manager.rb9
-rw-r--r--lib/arel/table.rb13
-rw-r--r--lib/arel/visitors/to_sql.rb25
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