lib/sequel/adapters/shared/mysql.rb in sequel-5.77.0 vs lib/sequel/adapters/shared/mysql.rb in sequel-5.78.0

- old
+ new

@@ -195,9 +195,44 @@ def rename_tables(*renames) execute_ddl(rename_tables_sql(renames)) renames.each{|from,| remove_cached_schema(from)} end + # Attempt to acquire an exclusive advisory lock with the given lock_id (which will be + # converted to a string). If successful, yield to the block, then release the advisory lock + # when the block exits. If unsuccessful, raise a Sequel::AdvisoryLockError. + # + # DB.with_advisory_lock(1357){DB.get(1)} + # # SELECT GET_LOCK('1357', 0) LIMIT 1 + # # SELECT 1 AS v LIMIT 1 + # # SELECT RELEASE_LOCK('1357') LIMIT 1 + # + # Options: + # :wait :: Do not raise an error, instead, wait until the advisory lock can be acquired. + def with_advisory_lock(lock_id, opts=OPTS) + lock_id = lock_id.to_s + ds = dataset + if server = opts[:server] + ds = ds.server(server) + end + + # MariaDB doesn't support negative values for infinite wait. A wait of 34 years + # should be reasonably similar to infinity for this case. + timeout = opts[:wait] ? 1073741823 : 0 + + synchronize(server) do |c| + begin + unless locked = ds.get{GET_LOCK(lock_id, timeout)} == 1 + raise AdvisoryLockError, "unable to acquire advisory lock #{lock_id.inspect}" + end + + yield + ensure + ds.get{RELEASE_LOCK(lock_id)} if locked + end + end + end + private def alter_table_add_column_sql(table, op) pos = if after_col = op[:after] " AFTER #{quote_identifier(after_col)}"