aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/arel.rb1
-rw-r--r--lib/arel/crud.rb13
-rw-r--r--lib/arel/nodes/update_statement.rb4
-rw-r--r--lib/arel/update_manager.rb18
-rw-r--r--lib/arel/visitors/to_sql.rb4
-rw-r--r--lib/arel/visitors/update_sql.rb26
-rw-r--r--spec/arel/crud_spec.rb5
-rw-r--r--spec/arel/select_manager_spec.rb6
8 files changed, 64 insertions, 13 deletions
diff --git a/lib/arel.rb b/lib/arel.rb
index 989ed12c87..7d870ec17e 100644
--- a/lib/arel.rb
+++ b/lib/arel.rb
@@ -26,6 +26,7 @@ require 'arel/sql_literal'
####
require 'arel/visitors/to_sql'
+require 'arel/visitors/update_sql'
require 'arel/visitors/join_sql'
require 'arel/visitors/order_clauses'
require 'arel/visitors/dot'
diff --git a/lib/arel/crud.rb b/lib/arel/crud.rb
index e060a82941..640189fbe9 100644
--- a/lib/arel/crud.rb
+++ b/lib/arel/crud.rb
@@ -13,16 +13,9 @@ module Arel
end
um.table relation
um.set values
-
- if @head.orders.empty? && @head.limit.nil?
- um.wheres = @ctx.wheres
- else
- head = @head.clone
- core = head.cores.first
- core.projections = [relation.primary_key]
-
- um.wheres = [Nodes::In.new(relation.primary_key, [head])]
- end
+ um.take @head.limit
+ um.order(*@head.orders)
+ um.wheres = @ctx.wheres
@engine.connection.update um.to_sql, 'AREL'
end
diff --git a/lib/arel/nodes/update_statement.rb b/lib/arel/nodes/update_statement.rb
index 7a1ce9a7b1..6f21187eb1 100644
--- a/lib/arel/nodes/update_statement.rb
+++ b/lib/arel/nodes/update_statement.rb
@@ -1,12 +1,14 @@
module Arel
module Nodes
class UpdateStatement
- attr_accessor :relation, :wheres, :values
+ attr_accessor :relation, :wheres, :values, :orders, :limit
def initialize
@relation = nil
@wheres = []
@values = []
+ @orders = []
+ @limit = nil
end
def initialize_copy other
diff --git a/lib/arel/update_manager.rb b/lib/arel/update_manager.rb
index 484230c4e1..c6a053aaa8 100644
--- a/lib/arel/update_manager.rb
+++ b/lib/arel/update_manager.rb
@@ -5,6 +5,16 @@ module Arel
@head = Nodes::UpdateStatement.new
end
+ def take limit
+ @head.limit = limit
+ self
+ end
+
+ def order *expr
+ @head.orders = expr
+ self
+ end
+
###
# UPDATE +table+
def table table
@@ -34,5 +44,13 @@ module Arel
end
self
end
+
+ def to_sql
+ viz = Visitors::ToSql.new @engine
+ unless @engine.connection_pool.spec.config[:adapter] == 'mysql'
+ viz.extend(Visitors::UpdateSql)
+ end
+ viz.accept @head
+ end
end
end
diff --git a/lib/arel/visitors/to_sql.rb b/lib/arel/visitors/to_sql.rb
index d6a9a3697f..710b6143ec 100644
--- a/lib/arel/visitors/to_sql.rb
+++ b/lib/arel/visitors/to_sql.rb
@@ -25,7 +25,9 @@ module Arel
[
"UPDATE #{visit o.relation}",
("SET #{o.values.map { |value| visit value }.join ', '}" unless o.values.empty?),
- ("WHERE #{o.wheres.map { |x| visit x }.join ' AND '}" unless o.wheres.empty?)
+ ("WHERE #{o.wheres.map { |x| visit x }.join ' AND '}" unless o.wheres.empty?),
+ ("ORDER BY #{o.orders.map { |x| visit x }.join(', ')}" unless o.orders.empty?),
+ ("LIMIT #{o.limit}" if o.limit),
].compact.join ' '
end
diff --git a/lib/arel/visitors/update_sql.rb b/lib/arel/visitors/update_sql.rb
new file mode 100644
index 0000000000..02196a0fb0
--- /dev/null
+++ b/lib/arel/visitors/update_sql.rb
@@ -0,0 +1,26 @@
+module Arel
+ module Visitors
+ module UpdateSql
+ def visit_Arel_Nodes_UpdateStatement o
+ if o.orders.empty? && o.limit.nil?
+ wheres = o.wheres
+ else
+ stmt = Nodes::SelectStatement.new
+ core = stmt.cores.first
+ core.froms = o.relation
+ core.projections = [o.relation.primary_key]
+ stmt.limit = o.limit
+ stmt.orders = o.orders
+
+ wheres = [Nodes::In.new(o.relation.primary_key, [stmt])]
+ end
+
+ [
+ "UPDATE #{visit o.relation}",
+ ("SET #{o.values.map { |value| visit value }.join ', '}" unless o.values.empty?),
+ ("WHERE #{wheres.map { |x| visit x }.join ' AND '}" unless wheres.empty?)
+ ].compact.join ' '
+ end
+ end
+ end
+end
diff --git a/spec/arel/crud_spec.rb b/spec/arel/crud_spec.rb
index cc58b8dbce..5c03857284 100644
--- a/spec/arel/crud_spec.rb
+++ b/spec/arel/crud_spec.rb
@@ -1,10 +1,13 @@
module Arel
class FakeCrudder < SelectManager
class FakeEngine
- attr_reader :calls
+ attr_reader :calls, :connection_pool, :spec, :config
def initialize
@calls = []
+ @connection_pool = self
+ @spec = self
+ @config = { :adapter => 'sqlite3' }
end
def connection; self end
diff --git a/spec/arel/select_manager_spec.rb b/spec/arel/select_manager_spec.rb
index e309286eba..f301e3afd0 100644
--- a/spec/arel/select_manager_spec.rb
+++ b/spec/arel/select_manager_spec.rb
@@ -3,10 +3,16 @@ require 'spec_helper'
module Arel
class EngineProxy
attr_reader :executed
+ attr_reader :connection_pool
+ attr_reader :spec
+ attr_reader :config
def initialize engine
@engine = engine
@executed = []
+ @connection_pool = self
+ @spec = self
+ @config = { :adapter => 'sqlite3' }
end
def connection