mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Allow database specific locking clauses to be used
This commit is contained in:
parent
dae7a245f8
commit
6c65b01762
6 changed files with 38 additions and 12 deletions
|
@ -1,6 +1,10 @@
|
||||||
module Arel
|
module Arel
|
||||||
module Nodes
|
module Nodes
|
||||||
class Lock < Arel::Nodes::Node
|
class Lock < Arel::Nodes::Node
|
||||||
|
attr_reader :locking
|
||||||
|
def initialize locking = true
|
||||||
|
@locking = locking
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -40,7 +40,7 @@ module Arel
|
||||||
def lock locking = true
|
def lock locking = true
|
||||||
# FIXME: do we even need to store this? If locking is +false+ shouldn't
|
# FIXME: do we even need to store this? If locking is +false+ shouldn't
|
||||||
# we just remove the node from the AST?
|
# we just remove the node from the AST?
|
||||||
@ast.lock = Nodes::Lock.new
|
@ast.lock = Nodes::Lock.new(locking)
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,12 @@ module Arel
|
||||||
class MySQL < Arel::Visitors::ToSql
|
class MySQL < Arel::Visitors::ToSql
|
||||||
private
|
private
|
||||||
def visit_Arel_Nodes_Lock o
|
def visit_Arel_Nodes_Lock o
|
||||||
|
if o.locking.is_a?(String)
|
||||||
|
o.locking
|
||||||
|
else
|
||||||
"FOR UPDATE"
|
"FOR UPDATE"
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
###
|
###
|
||||||
# :'(
|
# :'(
|
||||||
|
|
|
@ -3,8 +3,12 @@ module Arel
|
||||||
class PostgreSQL < Arel::Visitors::ToSql
|
class PostgreSQL < Arel::Visitors::ToSql
|
||||||
private
|
private
|
||||||
def visit_Arel_Nodes_Lock o
|
def visit_Arel_Nodes_Lock o
|
||||||
|
if o.locking.is_a?(String)
|
||||||
|
o.locking
|
||||||
|
else
|
||||||
"FOR UPDATE"
|
"FOR UPDATE"
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def visit_Arel_Nodes_SelectStatement o
|
def visit_Arel_Nodes_SelectStatement o
|
||||||
if !o.orders.empty? && using_distinct_on?(o)
|
if !o.orders.empty? && using_distinct_on?(o)
|
||||||
|
|
|
@ -29,11 +29,16 @@ module Arel
|
||||||
sql.must_be_like "SELECT FROM DUAL"
|
sql.must_be_like "SELECT FROM DUAL"
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'uses FOR UPDATE when locking' do
|
describe 'locking' do
|
||||||
stmt = Nodes::SelectStatement.new
|
it 'defaults to FOR UPDATE when locking' do
|
||||||
stmt.lock = Nodes::Lock.new
|
node = Nodes::Lock.new
|
||||||
sql = @visitor.accept(stmt)
|
@visitor.accept(node).must_be_like "FOR UPDATE"
|
||||||
sql.must_be_like "SELECT FROM DUAL FOR UPDATE"
|
end
|
||||||
|
|
||||||
|
it 'allows a custom string to be used as a lock' do
|
||||||
|
node = Nodes::Lock.new('LOCK IN SHARE MODE')
|
||||||
|
@visitor.accept(node).must_be_like "LOCK IN SHARE MODE"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,12 +7,21 @@ module Arel
|
||||||
@visitor = PostgreSQL.new Table.engine
|
@visitor = PostgreSQL.new Table.engine
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should produce a lock value' do
|
describe 'locking' do
|
||||||
|
it 'defaults to FOR UPDATE' do
|
||||||
@visitor.accept(Nodes::Lock.new).must_be_like %{
|
@visitor.accept(Nodes::Lock.new).must_be_like %{
|
||||||
FOR UPDATE
|
FOR UPDATE
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'allows a custom string to be used as a lock' do
|
||||||
|
node = Nodes::Lock.new('FOR SHARE')
|
||||||
|
@visitor.accept(node).must_be_like %{
|
||||||
|
FOR SHARE
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it "should escape LIMIT" do
|
it "should escape LIMIT" do
|
||||||
sc = Arel::Nodes::SelectStatement.new
|
sc = Arel::Nodes::SelectStatement.new
|
||||||
sc.limit = Nodes::Limit.new("omg")
|
sc.limit = Nodes::Limit.new("omg")
|
||||||
|
|
Loading…
Reference in a new issue