aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Mendonça França <rafaelmfranca@gmail.com>2015-02-23 22:16:50 -0300
committerRafael Mendonça França <rafaelmfranca@gmail.com>2015-02-23 22:16:50 -0300
commitb91dcb23af5917d8a62afc8a5a72780aaf11f64b (patch)
treeb0fd958a2a7cdb947ffb8ce1e933c531941fea3a
parentaac9da257f291ad8d2d4f914528881c240848bb2 (diff)
parentd86e20ccbea226bb6e42da508bc040fd03ab473f (diff)
downloadrails-b91dcb23af5917d8a62afc8a5a72780aaf11f64b.tar.gz
rails-b91dcb23af5917d8a62afc8a5a72780aaf11f64b.tar.bz2
rails-b91dcb23af5917d8a62afc8a5a72780aaf11f64b.zip
Merge pull request #356 from tamird/limited-delete
Limited delete
-rw-r--r--lib/arel/crud.rb1
-rw-r--r--lib/arel/delete_manager.rb5
-rw-r--r--lib/arel/nodes/delete_statement.rb2
-rw-r--r--lib/arel/visitors/mssql.rb17
-rw-r--r--lib/arel/visitors/to_sql.rb10
-rw-r--r--test/test_delete_manager.rb8
-rw-r--r--test/visitors/test_mssql.rb9
7 files changed, 47 insertions, 5 deletions
diff --git a/lib/arel/crud.rb b/lib/arel/crud.rb
index 2dfe27445c..d310c7381f 100644
--- a/lib/arel/crud.rb
+++ b/lib/arel/crud.rb
@@ -31,6 +31,7 @@ module Arel
def compile_delete
dm = DeleteManager.new
+ dm.take @ast.limit.expr if @ast.limit
dm.wheres = @ctx.wheres
dm.from @ctx.froms
dm
diff --git a/lib/arel/delete_manager.rb b/lib/arel/delete_manager.rb
index af33c60740..20e988e01f 100644
--- a/lib/arel/delete_manager.rb
+++ b/lib/arel/delete_manager.rb
@@ -11,6 +11,11 @@ module Arel
self
end
+ def take limit
+ @ast.limit = Nodes::Limit.new(Nodes.build_quoted(limit)) if limit
+ self
+ end
+
def wheres= list
@ast.wheres = list
end
diff --git a/lib/arel/nodes/delete_statement.rb b/lib/arel/nodes/delete_statement.rb
index 3bac8225ec..8aaf8ca0b6 100644
--- a/lib/arel/nodes/delete_statement.rb
+++ b/lib/arel/nodes/delete_statement.rb
@@ -1,6 +1,8 @@
module Arel
module Nodes
class DeleteStatement < Arel::Nodes::Binary
+ attr_accessor :limit
+
alias :relation :left
alias :relation= :left=
alias :wheres :right
diff --git a/lib/arel/visitors/mssql.rb b/lib/arel/visitors/mssql.rb
index 7c65ad33f2..92362a0c5f 100644
--- a/lib/arel/visitors/mssql.rb
+++ b/lib/arel/visitors/mssql.rb
@@ -66,6 +66,23 @@ module Arel
end
end
+ def visit_Arel_Nodes_DeleteStatement o, collector
+ collector << 'DELETE '
+ if o.limit
+ collector << 'TOP ('
+ visit o.limit.expr, collector
+ collector << ') '
+ end
+ collector << 'FROM '
+ collector = visit o.relation, collector
+ if o.wheres.any?
+ collector << ' WHERE '
+ inject_join o.wheres, collector, AND
+ else
+ collector
+ end
+ end
+
def determine_order_by orders, x
if orders.any?
orders
diff --git a/lib/arel/visitors/to_sql.rb b/lib/arel/visitors/to_sql.rb
index 7dfa86a575..ba176a552c 100644
--- a/lib/arel/visitors/to_sql.rb
+++ b/lib/arel/visitors/to_sql.rb
@@ -74,14 +74,14 @@ module Arel
end
def visit_Arel_Nodes_DeleteStatement o, collector
- collector << "DELETE FROM "
+ collector << 'DELETE FROM '
collector = visit o.relation, collector
if o.wheres.any?
- collector << " WHERE "
- inject_join o.wheres, collector, AND
- else
- collector
+ collector << ' WHERE '
+ collector = inject_join o.wheres, collector, AND
end
+
+ maybe_visit o.limit, collector
end
# FIXME: we should probably have a 2-pass visitor for this
diff --git a/test/test_delete_manager.rb b/test/test_delete_manager.rb
index b16b52cb9e..ece2389d88 100644
--- a/test/test_delete_manager.rb
+++ b/test/test_delete_manager.rb
@@ -8,6 +8,14 @@ module Arel
end
end
+ it 'handles limit properly' do
+ table = Table.new(:users)
+ dm = Arel::DeleteManager.new
+ dm.take 10
+ dm.from table
+ assert_match(/LIMIT 10/, dm.to_sql)
+ end
+
describe 'from' do
it 'uses from' do
table = Table.new(:users)
diff --git a/test/visitors/test_mssql.rb b/test/visitors/test_mssql.rb
index 7574aeb0a2..fe228bce4b 100644
--- a/test/visitors/test_mssql.rb
+++ b/test/visitors/test_mssql.rb
@@ -45,6 +45,15 @@ module Arel
connection.verify
end
+ it 'should use TOP for limited deletes' do
+ stmt = Nodes::DeleteStatement.new
+ stmt.relation = @table
+ stmt.limit = Nodes::Limit.new(10)
+ sql = compile(stmt)
+
+ sql.must_be_like "DELETE TOP (10) FROM \"users\""
+ end
+
it 'should go over query ORDER BY if .order()' do
stmt = Nodes::SelectStatement.new
stmt.limit = Nodes::Limit.new(10)