SETBIT key offset value

Sets or clears the bit at offset in the string value stored at key.

The bit is either set or cleared depending on value, which can be either 0 or 1.

When key does not exist, a new string value is created. The string is grown to make sure it can hold a bit at offset. The offset argument is required to be greater than or equal to 0, and smaller than 2^32 (this limits bitmaps to 512MB). When the string at key is grown, added bits are set to 0.

Warning: When setting the last possible bit (offset equal to 2^32 -1) and the string value stored at key does not yet hold a string value, or holds a small string value, Redis needs to allocate all intermediate memory which can block the server for some time. On a 2010 MacBook Pro, setting bit number 2^32 -1 (512MB allocation) takes ~300ms, setting bit number 2^30 -1 (128MB allocation) takes ~80ms, setting bit number 2^28 -1 (32MB allocation) takes ~30ms and setting bit number 2^26 -1 (8MB allocation) takes ~8ms. Note that once this first allocation is done, subsequent calls to SETBIT for the same key will not have the allocation overhead.

@return

@integer-reply: the original bit value stored at offset.

@examples

redis> SETBIT mykey 7 1
TBD
redis> SETBIT mykey 7 0
TBD
redis> GET mykey
TBD
redis> ```
TBD
redis> ## Pattern: accessing the entire bitmap
TBD
redis> There are cases when you need to set all the bits of single bitmap at once, for
TBD
redis> example when initializing it to a default non-zero value. It is possible to do
TBD
redis> this with multiple calls to the [`SETBIT`](/commands/setbit) command, one for each bit that needs to
TBD
redis> be set. However, so as an optimization you can use a single [`SET`](/commands/set) command to set
TBD
redis> the entire bitmap.
TBD
redis> Bitmaps are not an actual data type, but a set of bit-oriented operations
TBD
redis> defined on the String type (for more information refer to the
TBD
redis> [Bitmaps section of the Data Types Introduction page][ti]). This means that
TBD
redis> bitmaps can be used with string commands, and most importantly with [`SET`](/commands/set) and
TBD
redis> [`GET`](/commands/get).
TBD
redis> Because Redis' strings are binary-safe, a bitmap is trivially encoded as a bytes
TBD
redis> stream. The first byte of the string corresponds to offsets 0..7 of
TBD
redis> the bitmap, the second byte to the 8..15 range, and so forth.
TBD
redis> For example, after setting a few bits, getting the string value of the bitmap
TBD
redis> would look like this:
TBD
redis> ```
TBD
redis> > SETBIT bitmapsarestrings 2 1
TBD
redis> > SETBIT bitmapsarestrings 3 1
TBD
redis> > SETBIT bitmapsarestrings 5 1
TBD
redis> > SETBIT bitmapsarestrings 10 1
TBD
redis> > SETBIT bitmapsarestrings 11 1
TBD
redis> > SETBIT bitmapsarestrings 14 1
TBD
redis> > GET bitmapsarestrings
TBD
redis> "42"
TBD
redis> ```
TBD
redis> By getting the string representation of a bitmap, the client can then parse the
TBD
redis> response's bytes by extracting the bit values using native bit operations in its
TBD
redis> native programming language. Symmetrically, it is also possible to set an entire
TBD
redis> bitmap by performing the bits-to-bytes encoding in the client and calling [`SET`](/commands/set)
TBD
redis> with the resultant string.
TBD
redis> [ti]: /topics/data-types-intro#bitmaps
TBD
redis> ## Pattern: setting multiple bits
TBD
redis> [`SETBIT`](/commands/setbit) excels at setting single bits, and can be called several times when
TBD
redis> multiple bits need to be set. To optimize this operation you can replace
TBD
redis> multiple [`SETBIT`](/commands/setbit) calls with a single call to the variadic [`BITFIELD`](/commands/bitfield) command
TBD
redis> and the use of fields of type `u1`.
TBD
redis> For example, the example above could be replaced by:
TBD
redis> ```
TBD
redis> > BITFIELD bitsinabitmap SET u1 2 1 SET u1 3 1 SET u1 5 1 SET u1 10 1 SET u1 11 1 SET u1 14 1
TBD
redis> ```
TBD
redis> ## Advanced Pattern: accessing bitmap ranges
TBD
redis> It is also possible to use the [`GETRANGE`](/commands/getrange) and [`SETRANGE`](/commands/setrange) string commands to
TBD
redis> efficiently access a range of bit offsets in a bitmap. Below is a sample
TBD
redis> implementation in idiomatic Redis Lua scripting that can be run with the [`EVAL`](/commands/eval)
TBD
redis> command:
TBD
redis> ```
TBD
redis> --[[
TBD
redis> Sets a bitmap range
TBD
redis> Bitmaps are stored as Strings in Redis. A range spans one or more bytes,
TBD
redis> so we can call [`SETRANGE`](/commands/setrange) when entire bytes need to be set instead of flipping
TBD
redis> individual bits. Also, to avoid multiple internal memory allocations in
TBD
redis> Redis, we traverse in reverse.
TBD
redis> Expected input:
TBD
redis> KEYS[1] - bitfield key
TBD
redis> ARGV[1] - start offset (0-based, inclusive)
TBD
redis> ARGV[2] - end offset (same, should be bigger than start, no error checking)
TBD
redis> ARGV[3] - value (should be 0 or 1, no error checking)
TBD
redis> ]]--
TBD
redis> -- A helper function to stringify a binary string to semi-binary format
TBD
redis> local function tobits(str)
TBD
redis> local r = ''
TBD
redis> for i = 1, string.len(str) do
TBD
redis> local c = string.byte(str, i)
TBD
redis> local b = ' '
TBD
redis> for j = 0, 7 do
TBD
redis> b = tostring(bit.band(c, 1)) .. b
TBD
redis> c = bit.rshift(c, 1)
TBD
redis> end
TBD
redis> r = r .. b
TBD
redis> end
TBD
redis> return r
TBD
redis> end
TBD
redis> -- Main
TBD
redis> local k = KEYS[1]
TBD
redis> local s, e, v = tonumber(ARGV[1]), tonumber(ARGV[2]), tonumber(ARGV[3])
TBD
redis> -- First treat the dangling bits in the last byte
TBD
redis> local ms, me = s % 8, (e + 1) % 8
TBD
redis> if me > 0 then
TBD
redis> local t = math.max(e - me + 1, s)
TBD
redis> for i = e, t, -1 do
TBD
redis> redis.call('SETBIT', k, i, v)
TBD
redis> end
TBD
redis> e = t
TBD
redis> end
TBD
redis> -- Then the danglings in the first byte
TBD
redis> if ms > 0 then
TBD
redis> local t = math.min(s - ms + 7, e)
TBD
redis> for i = s, t, 1 do
TBD
redis> redis.call('SETBIT', k, i, v)
TBD
redis> end
TBD
redis> s = t + 1
TBD
redis> end
TBD
redis> -- Set a range accordingly, if at all
TBD
redis> local rs, re = s / 8, (e + 1) / 8
TBD
redis> local rl = re - rs
TBD
redis> if rl > 0 then
TBD
redis> local b = '\255'
TBD
redis> if 0 == v then
TBD
redis> b = '\0'
TBD
redis> end
TBD
redis> redis.call('SETRANGE', k, rs, string.rep(b, rl))
TBD
redis> end

Note: the implementation for getting a range of bit offsets from a bitmap is left as an exercise to the reader.