Skip to content

Commit

Permalink
Merge pull request #1048 from fatkodima/copy-command
Browse files Browse the repository at this point in the history
[Redis 6.2] Add COPY command
  • Loading branch information
byroot authored Nov 5, 2021
2 parents bc7ed4b + 9065443 commit 0c43a51
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 0 deletions.
35 changes: 35 additions & 0 deletions lib/redis.rb
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,41 @@ def move(key, db)
end
end

# Copy a value from one key to another.
#
# @example Copy a value to another key
# redis.set "foo", "value"
# # => "OK"
# redis.copy "foo", "bar"
# # => true
# redis.get "bar"
# # => "value"
#
# @example Copy a value to a key in another database
# redis.set "foo", "value"
# # => "OK"
# redis.copy "foo", "bar", db: 2
# # => true
# redis.select 2
# # => "OK"
# redis.get "bar"
# # => "value"
#
# @param [String] source
# @param [String] destination
# @param [Integer] db
# @param [Boolean] replace removes the `destination` key before copying value to it
# @return [Boolean] whether the key was copied or not
def copy(source, destination, db: nil, replace: false)
command = [:copy, source, destination]
command << "DB" << db if db
command << "REPLACE" if replace

synchronize do |client|
client.call(command, &Boolify)
end
end

def object(*args)
synchronize do |client|
client.call([:object] + args)
Expand Down
7 changes: 7 additions & 0 deletions lib/redis/distributed.rb
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,13 @@ def move(key, db)
node_for(key).move(key, db)
end

# Copy a value from one key to another.
def copy(source, destination, **options)
ensure_same_node(:copy, [source, destination]) do |node|
node.copy(source, destination, **options)
end
end

# Return a random key from the keyspace.
def randomkey
raise CannotDistribute, :randomkey
Expand Down
4 changes: 4 additions & 0 deletions test/cluster_commands_on_value_types_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,8 @@ class TestClusterCommandsOnValueTypes < Minitest::Test
def test_move
assert_raises(Redis::CommandError) { super }
end

def test_copy
assert_raises(Redis::CommandError) { super }
end
end
8 changes: 8 additions & 0 deletions test/distributed_commands_on_value_types_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,12 @@ def test_migrate
r.migrate("foo", {})
end
end

def test_copy
r.set("foo", "s1")

assert_raises Redis::Distributed::CannotDistribute do
r.copy("foo", "bar")
end
end
end
5 changes: 5 additions & 0 deletions test/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,11 @@ def target_version(target)
end
end

def with_db(index)
r.select(index)
yield
end

def omit_version(min_ver)
skip("Requires Redis > #{min_ver}") if version < min_ver
end
Expand Down
36 changes: 36 additions & 0 deletions test/lint/value_types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -162,5 +162,41 @@ def test_move
assert_equal "s1", r.get("foo")
assert_equal "s3", r.get("bar")
end

def test_copy
target_version("6.2") do
with_db(14) do
r.flushdb

r.set "foo", "s1"
r.set "bar", "s2"

assert r.copy("foo", "baz")
assert_equal "s1", r.get("baz")

assert !r.copy("foo", "bar")
assert r.copy("foo", "bar", replace: true)
assert_equal "s1", r.get("bar")
end

with_db(15) do
r.set "foo", "s3"
r.set "bar", "s4"
end

with_db(14) do
assert r.copy("foo", "baz", db: 15)
assert_equal "s1", r.get("foo")

assert !r.copy("foo", "bar", db: 15)
assert r.copy("foo", "bar", db: 15, replace: true)
end

with_db(15) do
assert_equal "s1", r.get("baz")
assert_equal "s1", r.get("bar")
end
end
end
end
end

0 comments on commit 0c43a51

Please sign in to comment.