mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Added lock to Arel, allowing a locking read if required.
This commit is contained in:
parent
3ea68bc6bd
commit
b339caca2f
6 changed files with 70 additions and 3 deletions
|
@ -13,3 +13,4 @@ require 'arel/algebra/relations/operations/project'
|
|||
require 'arel/algebra/relations/operations/where'
|
||||
require 'arel/algebra/relations/operations/skip'
|
||||
require 'arel/algebra/relations/operations/take'
|
||||
require 'arel/algebra/relations/operations/lock'
|
||||
|
|
12
lib/arel/algebra/relations/operations/lock.rb
Normal file
12
lib/arel/algebra/relations/operations/lock.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
module Arel
|
||||
class Lock < Compound
|
||||
attributes :relation, :locked
|
||||
deriving :initialize, :==
|
||||
|
||||
def initialize(relation, locked, &block)
|
||||
@relation = relation
|
||||
@locked = locked.blank? ? " FOR UPDATE" : locked
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -51,6 +51,10 @@ module Arel
|
|||
OPERATION
|
||||
end
|
||||
|
||||
def lock(locking = nil)
|
||||
Lock.new(self, locking)
|
||||
end
|
||||
|
||||
def alias
|
||||
Alias.new(self)
|
||||
end
|
||||
|
@ -131,6 +135,7 @@ module Arel
|
|||
def taken; nil end
|
||||
def skipped; nil end
|
||||
def sources; [] end
|
||||
def locked; [] end
|
||||
end
|
||||
include DefaultOperations
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@ module Arel
|
|||
class Compound < Relation
|
||||
attr_reader :relation
|
||||
delegate :joins, :join?, :inserts, :taken, :skipped, :name, :externalizable?,
|
||||
:column_for, :engine, :sources,
|
||||
:column_for, :engine, :sources, :locked,
|
||||
:to => :relation
|
||||
|
||||
[:attributes, :wheres, :groupings, :orders].each do |operation_name|
|
||||
|
|
|
@ -16,7 +16,8 @@ module Arel
|
|||
"FROM #{from_clauses}",
|
||||
(joins(self) unless joins(self).blank? ),
|
||||
("WHERE #{where_clauses.join("\n\tAND ")}" unless wheres.blank? ),
|
||||
("GROUP BY #{group_clauses.join(', ')}" unless groupings.blank? )
|
||||
("GROUP BY #{group_clauses.join(', ')}" unless groupings.blank? ),
|
||||
("#{locked}" unless locked.blank? )
|
||||
|
||||
build_query \
|
||||
"SELECT * FROM (#{query}) AS id_list",
|
||||
|
@ -33,7 +34,8 @@ module Arel
|
|||
("GROUP BY #{group_clauses.join(', ')}" unless groupings.blank? ),
|
||||
("ORDER BY #{order_clauses.join(', ')}" unless orders.blank? ),
|
||||
("LIMIT #{taken}" unless taken.blank? ),
|
||||
("OFFSET #{skipped}" unless skipped.blank? )
|
||||
("OFFSET #{skipped}" unless skipped.blank? ),
|
||||
("#{locked}" unless locked.blank? )
|
||||
end
|
||||
end
|
||||
|
||||
|
|
47
spec/arel/engines/sql/unit/relations/lock_spec.rb
Normal file
47
spec/arel/engines/sql/unit/relations/lock_spec.rb
Normal file
|
@ -0,0 +1,47 @@
|
|||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Lock do
|
||||
before do
|
||||
@relation = Table.new(:users)
|
||||
end
|
||||
|
||||
describe '#to_sql' do
|
||||
it "manufactures a simple select query lock" do
|
||||
sql = @relation.lock.to_sql
|
||||
|
||||
adapter_is :mysql do
|
||||
sql.should be_like(%Q{
|
||||
SELECT `users`.`id`, `users`.`name`
|
||||
FROM `users` FOR UPDATE
|
||||
})
|
||||
end
|
||||
|
||||
adapter_is_not :mysql do
|
||||
sql.should be_like(%Q{
|
||||
SELECT "users"."id", "users"."name"
|
||||
FROM "users" FOR UPDATE
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
it "manufactures a select query locking with a given lock" do
|
||||
sql = @relation.lock("LOCK IN SHARE MODE").to_sql
|
||||
|
||||
adapter_is :mysql do
|
||||
sql.should be_like(%Q{
|
||||
SELECT `users`.`id`, `users`.`name`
|
||||
FROM `users` LOCK IN SHARE MODE
|
||||
})
|
||||
end
|
||||
|
||||
adapter_is_not :mysql do
|
||||
sql.should be_like(%Q{
|
||||
SELECT "users"."id", "users"."name"
|
||||
FROM "users" LOCK IN SHARE MODE
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue