When trying to run BITOP on keys that contain empty strings and put the result in the dest_key, for some reason the dest_key gets deleted. I am not sure if this is an issue or a design choice.
set dest_key "some_value"
OK
set key1 ""
OK
set key2 ""
OK
bitop and dest_key key1 key2
(integer) 0
exists dest_key
(integer) 0
Info server:
redis_version:3.2.4
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:114b37021fc87cd9
redis_mode:standalone
os:Linux 4.19.76-linuxkit x86_64
arch_bits:64
multiplexing_api:epoll
gcc_version:5.3.0
Comment From: madolson
That seems like a bug, but isn't that weird of behavior. Empty strings are different non-existent keys, but it looks like bitops treats them the same. @ajokanovic is this a usecase you ran into?
Comment From: mmalanchuk
@madolson, I have the same problem with bitops. My use cases require some operations with possibly empty bit strings, and it's not clear how to distinguish them from non-existent ones. Are there any updates here? btw, the bug occurs when there are only empty strings in src keys.
Comment From: madolson
@mmalanchuk To clarify your expectation. If you were to do a BITOP AND with two zero length strings you would expect the result to be a zero length string and not delete the key? I think that is reasonable.
Comment From: madolson
If that is the case, it looks like the bug is here https://github.com/redis/redis/blob/bcc519fa7cef85adf182af0cfa4aa67a71ad90b9/src/bitops.c#L768. I think that we probably need to move this check to be a short circuit of checking if all the input keys are nil. I'll take a stab at implementation tomorrow morning if no one else takes a look.
Comment From: mmalanchuk
@mmalanchuk To clarify your expectation. If you were to do a
BITOP ANDwith two zero length strings you would expect the result to be a zero length string and not delete the key? I think that is reasonable.
yes, exactly. And if BITOP has a single src key arg as a zero-length string, I'd expect the result to be a zero-length string as well
Comment From: huangzhw
@madolson I will take a look.
Comment From: oranagra
I don't think this is a bug, i think it's a design choice: missing keys and empty string keys are considered the same.
It's similar to an SINTERSTORE on a missing key, it's considered an empty set, and since there are no empty sets, it deletes the destination key.
If the command's response on an empty result was nil then maybe we can consider a case of responding with 0 and creating an empty key.
But since it currently returns 0 when deleting the dest key, i wouldn't like to have one response (0) that represents two different outcomes.
@mmalanchuk can you please better describe your use case? maybe there's another solution or we find another way too change the command to cover it.
Comment From: madolson
Empty length strings are different from missing keys though.
Comment From: oranagra
Yes, I know (unlike empty zetes and list, empty string keys are valid), but the argument is that for the purpose of BITOP a non-existing key and an empty one are identical (that's the design). And I think that changing that, would require to also change the response (respond with nil when not creating a key, and with 0 when creating an empty one), I think this would be very odd and also a breaking change .
@madolson , Please correct me if I'm missing something, your last post in the PR was a bit unclear to me.
Comment From: madolson
Sure, I can elaborate a bit more. It actually comes up all over the place that people want to be able to differentiate an "empty object" with a non-existent object. This is especially true for strings as people are often using them for caching use cases. Unlike all of the other collection objects, there is an empty string option, the zero length string. It seems like if someone intentionally set it we should be respecting it in some capacity.