From 3da714887486cb4c67aadde34521653586dc1796 Mon Sep 17 00:00:00 2001 From: Alexander Vershilov Date: Sat, 10 Jun 2023 18:38:28 +0200 Subject: [PATCH] Redis7 support for exising commands Use NonEmpty list for all functions that requires it. User code can migrate using OverloadedLists, though it doesn't play well with overloaded list,. Add documentation to the existing functions. --- benchmark/Benchmark.hs | 2 +- src/Database/Redis/Commands.hs | 994 ++++++++++++++++++--------- src/Database/Redis/ManualCommands.hs | 214 +++++- src/Database/Redis/Types.hs | 9 + test/ClusterMain.hs | 7 +- test/Tests.hs | 40 +- 6 files changed, 892 insertions(+), 374 deletions(-) diff --git a/benchmark/Benchmark.hs b/benchmark/Benchmark.hs index a41dce7d..74b5eeb4 100644 --- a/benchmark/Benchmark.hs +++ b/benchmark/Benchmark.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE OverloadedStrings, LambdaCase #-} +{-# LANGUAGE OverloadedStrings, LambdaCase, OverloadedLists #-} module Main where diff --git a/src/Database/Redis/Commands.hs b/src/Database/Redis/Commands.hs index a8e29647..90aeb6b2 100644 --- a/src/Database/Redis/Commands.hs +++ b/src/Database/Redis/Commands.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE OverloadedStrings, FlexibleContexts #-} +{-# LANGUAGE OverloadedStrings, FlexibleContexts, OverloadedLists #-} module Database.Redis.Commands ( @@ -6,232 +6,249 @@ module Database.Redis.Commands ( -- *** auth -- $auth -auth, +auth, authOpts, AuthOpts(..), defaultAuthOpts, -- *** Other commands -echo, -- |Echo the given string (). Since Redis 1.0.0 -ping, -- |Ping the server (). Since Redis 1.0.0 -quit, -- |Close the connection (). Since Redis 1.0.0 -select, -- |Change the selected database for the current connection (). Since Redis 1.0.0 +echo, +ping, +quit, +select, -- ** Keys del, -dump, -- |Return a serialized version of the value stored at the specified key (). Since Redis 2.6.0 -exists, -- |Determine if a key exists (). Since Redis 1.0.0 -expire, -- |Set a key's time to live in seconds (). Since Redis 1.0.0 -expireat, -- |Set the expiration for a key as a UNIX timestamp (). Since Redis 1.2.0 -keys, -- |Find all keys matching the given pattern (). Since Redis 1.0.0 +dump, +exists, +expire, +ExpireOpts(..), +expireOpts, +expireat, +expireatOpts, +keys, MigrateOpts(..), defaultMigrateOpts, -migrate, -- |Atomically transfer a key from a Redis instance to another one (). The Redis command @MIGRATE@ is split up into 'migrate', 'migrateMultiple'. Since Redis 2.6.0 -migrateMultiple, -- |Atomically transfer a key from a Redis instance to another one (). The Redis command @MIGRATE@ is split up into 'migrate', 'migrateMultiple'. Since Redis 2.6.0 -move, -- |Move a key to another database (). Since Redis 1.0.0 -objectRefcount, -- |Inspect the internals of Redis objects (). The Redis command @OBJECT@ is split up into 'objectRefcount', 'objectEncoding', 'objectIdletime'. Since Redis 2.2.3 -objectEncoding, -- |Inspect the internals of Redis objects (). The Redis command @OBJECT@ is split up into 'objectRefcount', 'objectEncoding', 'objectIdletime'. Since Redis 2.2.3 -objectIdletime, -- |Inspect the internals of Redis objects (). The Redis command @OBJECT@ is split up into 'objectRefcount', 'objectEncoding', 'objectIdletime'. Since Redis 2.2.3 -persist, -- |Remove the expiration from a key (). Since Redis 2.2.0 -pexpire, -- |Set a key's time to live in milliseconds (). Since Redis 2.6.0 -pexpireat, -- |Set the expiration for a key as a UNIX timestamp specified in milliseconds (). Since Redis 2.6.0 -pttl, -- |Get the time to live for a key in milliseconds (). Since Redis 2.6.0 -randomkey, -- |Return a random key from the keyspace (). Since Redis 1.0.0 -rename, -- |Rename a key (). Since Redis 1.0.0 -renamenx, -- |Rename a key, only if the new key does not exist (). Since Redis 1.0.0 -restore, -- |Create a key using the provided serialized value, previously obtained using DUMP (). The Redis command @RESTORE@ is split up into 'restore', 'restoreReplace'. Since Redis 2.6.0 -restoreReplace, -- |Create a key using the provided serialized value, previously obtained using DUMP (). The Redis command @RESTORE@ is split up into 'restore', 'restoreReplace'. Since Redis 2.6.0 +migrate, +migrateMultiple, +move, +objectRefcount, +objectEncoding, +objectIdletime, +persist, +pexpire, +pexpireat, +pexpireatOpts, +pttl, +randomkey, +rename, +renamenx, +restore, +restoreReplace, Cursor, cursor0, ScanOpts(..), defaultScanOpts, -scan, -- |Incrementally iterate the keys space (). The Redis command @SCAN@ is split up into 'scan', 'scanOpts'. Since Redis 2.8.0 -scanOpts, -- |Incrementally iterate the keys space (). The Redis command @SCAN@ is split up into 'scan', 'scanOpts'. Since Redis 2.8.0 +scan, +scanOpts, SortOpts(..), defaultSortOpts, SortOrder(..), -sort, -- |Sort the elements in a list, set or sorted set (). The Redis command @SORT@ is split up into 'sort', 'sortStore'. Since Redis 1.0.0 -sortStore, -- |Sort the elements in a list, set or sorted set (). The Redis command @SORT@ is split up into 'sort', 'sortStore'. Since Redis 1.0.0 -ttl, -- |Get the time to live for a key (). Since Redis 1.0.0 +sort, +sortStore, +ttl, RedisType(..), -getType, -- |Determine the type stored at key (). Since Redis 1.0.0 -wait, -- |Wait for the synchronous replication of all the write commands sent in the context of the current connection (). Since Redis 3.0.0 +getType, +wait, -- ** Hashes -hdel, -- |Delete one or more hash fields (). Since Redis 2.0.0 -hexists, -- |Determine if a hash field exists (). Since Redis 2.0.0 -hget, -- |Get the value of a hash field (). Since Redis 2.0.0 -hgetall, -- |Get all the fields and values in a hash (). Since Redis 2.0.0 -hincrby, -- |Increment the integer value of a hash field by the given number (). Since Redis 2.0.0 -hincrbyfloat, -- |Increment the float value of a hash field by the given amount (). Since Redis 2.6.0 -hkeys, -- |Get all the fields in a hash (). Since Redis 2.0.0 -hlen, -- |Get the number of fields in a hash (). Since Redis 2.0.0 -hmget, -- |Get the values of all the given hash fields (). Since Redis 2.0.0 -hmset, -- |Set multiple hash fields to multiple values (). Since Redis 2.0.0 -hscan, -- |Incrementally iterate hash fields and associated values (). The Redis command @HSCAN@ is split up into 'hscan', 'hscanOpts'. Since Redis 2.8.0 -hscanOpts, -- |Incrementally iterate hash fields and associated values (). The Redis command @HSCAN@ is split up into 'hscan', 'hscanOpts'. Since Redis 2.8.0 -hset, -- |Set the string value of a hash field (). Since Redis 2.0.0 -hsetnx, -- |Set the value of a hash field, only if the field does not exist (). Since Redis 2.0.0 -hstrlen, -- |Get the length of the value of a hash field (). Since Redis 3.2.0 -hvals, -- |Get all the values in a hash (). Since Redis 2.0.0 +hdel, +hexists, +hget, +hgetall, +hincrby, +hincrbyfloat, +hkeys, +hlen, +hmget, +hmset, +hscan, +hscanOpts, +hset, +hsetnx, +hstrlen, +hvals, -- ** HyperLogLogs -pfadd, -- |Adds all the elements arguments to the HyperLogLog data structure stored at the variable name specified as first argument (). Since Redis 2.8.9 -pfcount, -- |Return the approximated cardinality of the set(s) observed by the HyperLogLog at key(s) (). Since Redis 2.8.9 -pfmerge, -- |Merge N different HyperLogLogs into a single one (). Since Redis 2.8.9 +pfadd, +pfcount, +pfmerge, -- ** Lists -blpop, -- |Remove and get the first element in a list, or block until one is available (). Since Redis 2.0.0 -brpop, -- |Remove and get the last element in a list, or block until one is available (). Since Redis 2.0.0 -brpoplpush, -- |Pop a value from a list, push it to another list and return it; or block until one is available (). Since Redis 2.2.0 -lindex, -- |Get an element from a list by its index (). Since Redis 1.0.0 -linsertBefore, -- |Insert an element before or after another element in a list (). The Redis command @LINSERT@ is split up into 'linsertBefore', 'linsertAfter'. Since Redis 2.2.0 -linsertAfter, -- |Insert an element before or after another element in a list (). The Redis command @LINSERT@ is split up into 'linsertBefore', 'linsertAfter'. Since Redis 2.2.0 -llen, -- |Get the length of a list (). Since Redis 1.0.0 -lpop, -- |Remove and get the first element in a list (). Since Redis 1.0.0 -lpush, -- |Prepend one or multiple values to a list (). Since Redis 1.0.0 -lpushx, -- |Prepend a value to a list, only if the list exists (). Since Redis 2.2.0 -lrange, -- |Get a range of elements from a list (). Since Redis 1.0.0 -lrem, -- |Remove elements from a list (). Since Redis 1.0.0 -lset, -- |Set the value of an element in a list by its index (). Since Redis 1.0.0 -ltrim, -- |Trim a list to the specified range (). Since Redis 1.0.0 -rpop, -- |Remove and get the last element in a list (). Since Redis 1.0.0 -rpoplpush, -- |Remove the last element in a list, prepend it to another list and return it (). Since Redis 1.2.0 -rpush, -- |Append one or multiple values to a list (). Since Redis 1.0.0 -rpushx, -- |Append a value to a list, only if the list exists (). Since Redis 2.2.0 +blpop, +blpopFloat, +brpop, +brpopFloat, +brpoplpush, +lindex, +linsertBefore, +linsertAfter, +llen, +lpop, +lpopCount, +lpush, +lpushx, +lrange, +lrem, +lset, +ltrim, +rpop, +rpopCount, +rpoplpush, +rpush, +rpushx, -- ** Scripting -eval, -- |Execute a Lua script server side (). Since Redis 2.6.0 -evalsha, -- |Execute a Lua script server side (). Since Redis 2.6.0 +eval, +evalsha, DebugMode, -scriptDebug, -- |Set the debug mode for executed scripts (). Since Redis 3.2.0 -scriptExists, -- |Check existence of scripts in the script cache (). Since Redis 2.6.0 -scriptFlush, -- |Remove all the scripts from the script cache (). Since Redis 2.6.0 -scriptKill, -- |Kill the script currently in execution (). Since Redis 2.6.0 -scriptLoad, -- |Load the specified Lua script into the script cache (). Since Redis 2.6.0 +scriptDebug, +scriptExists, +scriptFlush, +scriptKill, +scriptLoad, -- ** Server -bgrewriteaof, -- |Asynchronously rewrite the append-only file (). Since Redis 1.0.0 -bgsave, -- |Asynchronously save the dataset to disk (). Since Redis 1.0.0 -clientGetname, -- |Get the current connection name (). Since Redis 2.6.9 -clientId, -- |Get the current connection ID (). Since Redis 5.0.0 -clientList, -- |Get the list of client connections (). Since Redis 2.4.0 -clientPause, -- |Stop processing commands from clients for some time (). Since Redis 2.9.50 +bgrewriteaof, +bgsave, +bgsaveSchedule, +clientGetname, +clientId, +clientList, +clientPause, ReplyMode, -clientReply, -- |Instruct the server whether to reply to commands (). Since Redis 3.2 -clientSetname, -- |Set the current connection name (). Since Redis 2.6.9 -commandCount, -- |Get total number of Redis commands (). Since Redis 2.8.13 -commandInfo, -- |Get array of specific Redis command details (). Since Redis 2.8.13 -configGet, -- |Get the value of a configuration parameter (). Since Redis 2.0.0 -configResetstat, -- |Reset the stats returned by INFO (). Since Redis 2.0.0 -configRewrite, -- |Rewrite the configuration file with the in memory configuration (). Since Redis 2.8.0 -configSet, -- |Set a configuration parameter to the given value (). Since Redis 2.0.0 -dbsize, -- |Return the number of keys in the selected database (). Since Redis 1.0.0 -debugObject, -- |Get debugging information about a key (). Since Redis 1.0.0 -flushall, -- |Remove all keys from all databases (). Since Redis 1.0.0 -flushdb, -- |Remove all keys from the current database (). Since Redis 1.0.0 +clientReply, +clientSetname, +commandCount, +commandInfo, +configGet, +configResetstat, +configRewrite, +configSet, +dbsize, +debugObject, +flushall, +flushallOpts, +FlushOpts(..), +flushdb, +flushdbOpts, info, -- |Get information and statistics about the server (). The Redis command @INFO@ is split up into 'info', 'infoSection'. Since Redis 1.0.0 infoSection, -- |Get information and statistics about the server (). The Redis command @INFO@ is split up into 'info', 'infoSection'. Since Redis 1.0.0 lastsave, -- |Get the UNIX time stamp of the last successful save to disk (). Since Redis 1.0.0 -save, -- |Synchronously save the dataset to disk (). Since Redis 1.0.0 -slaveof, -- |Make the server a slave of another instance, or promote it as master (). Since Redis 1.0.0 +save, +slaveof, Slowlog(..), slowlogGet, -- |Manages the Redis slow queries log (). The Redis command @SLOWLOG@ is split up into 'slowlogGet', 'slowlogLen', 'slowlogReset'. Since Redis 2.2.12 slowlogLen, -- |Manages the Redis slow queries log (). The Redis command @SLOWLOG@ is split up into 'slowlogGet', 'slowlogLen', 'slowlogReset'. Since Redis 2.2.12 slowlogReset, -- |Manages the Redis slow queries log (). The Redis command @SLOWLOG@ is split up into 'slowlogGet', 'slowlogLen', 'slowlogReset'. Since Redis 2.2.12 -time, -- |Return the current server time (). Since Redis 2.6.0 +time, -- ** Sets sadd, -scard, -- |Get the number of members in a set (). Since Redis 1.0.0 -sdiff, -- |Subtract multiple sets (). Since Redis 1.0.0 -sdiffstore, -- |Subtract multiple sets and store the resulting set in a key (). Since Redis 1.0.0 -sinter, -- |Intersect multiple sets (). Since Redis 1.0.0 -sinterstore, -- |Intersect multiple sets and store the resulting set in a key (). Since Redis 1.0.0 -sismember, -- |Determine if a given value is a member of a set (). Since Redis 1.0.0 -smembers, -- |Get all the members in a set (). Since Redis 1.0.0 -smove, -- |Move a member from one set to another (). Since Redis 1.0.0 -spop, -- |Remove and return one or multiple random members from a set (). The Redis command @SPOP@ is split up into 'spop', 'spopN'. Since Redis 1.0.0 -spopN, -- |Remove and return one or multiple random members from a set (). The Redis command @SPOP@ is split up into 'spop', 'spopN'. Since Redis 1.0.0 -srandmember, -- |Get one or multiple random members from a set (). The Redis command @SRANDMEMBER@ is split up into 'srandmember', 'srandmemberN'. Since Redis 1.0.0 -srandmemberN, -- |Get one or multiple random members from a set (). The Redis command @SRANDMEMBER@ is split up into 'srandmember', 'srandmemberN'. Since Redis 1.0.0 +scard, +sdiff, +sdiffstore, +sinter, +sinterstore, +sismember, +smembers, +smove, +spop, +spopN, +srandmember, +srandmemberN, srem, -sscan, -- |Incrementally iterate Set elements (). The Redis command @SSCAN@ is split up into 'sscan', 'sscanOpts'. Since Redis 2.8.0 -sscanOpts, -- |Incrementally iterate Set elements (). The Redis command @SSCAN@ is split up into 'sscan', 'sscanOpts'. Since Redis 2.8.0 -sunion, -- |Add multiple sets (). Since Redis 1.0.0 -sunionstore, -- |Add multiple sets and store the resulting set in a key (). Since Redis 1.0.0 +sscan, +sscanOpts, +sunion, +sunionstore, -- ** Sorted Sets ZaddOpts(..), defaultZaddOpts, -zadd, -- |Add one or more members to a sorted set, or update its score if it already exists (). The Redis command @ZADD@ is split up into 'zadd', 'zaddOpts'. Since Redis 1.2.0 -zaddOpts, -- |Add one or more members to a sorted set, or update its score if it already exists (). The Redis command @ZADD@ is split up into 'zadd', 'zaddOpts'. Since Redis 1.2.0 +zadd, +zaddOpts, SizeCondition(..), -zcard, -- |Get the number of members in a sorted set (). Since Redis 1.2.0 -zcount, -- |Count the members in a sorted set with scores within the given values (). Since Redis 2.0.0 -zincrby, -- |Increment the score of a member in a sorted set (). Since Redis 1.2.0 +zcard, +zcount, +zincrby, Aggregate(..), -zinterstore, -- |Intersect multiple sorted sets and store the resulting sorted set in a new key (). The Redis command @ZINTERSTORE@ is split up into 'zinterstore', 'zinterstoreWeights'. Since Redis 2.0.0 -zinterstoreWeights, -- |Intersect multiple sorted sets and store the resulting sorted set in a new key (). The Redis command @ZINTERSTORE@ is split up into 'zinterstore', 'zinterstoreWeights'. Since Redis 2.0.0 -zlexcount, -- |Count the number of members in a sorted set between a given lexicographical range (). Since Redis 2.8.9 -zrange, -- |Return a range of members in a sorted set, by index (). The Redis command @ZRANGE@ is split up into 'zrange', 'zrangeWithscores'. Since Redis 1.2.0 -zrangeWithscores, -- |Return a range of members in a sorted set, by index (). The Redis command @ZRANGE@ is split up into 'zrange', 'zrangeWithscores'. Since Redis 1.2.0 +zinterstore, +zinterstoreWeights, +zlexcount, +zrange, +zrangeWithscores, RangeLex(..), -zrangebylex, zrangebylexLimit, -- |Return a range of members in a sorted set, by lexicographical range (). Since Redis 2.8.9 +zrangebylex, zrangebylexLimit, zrangebyscore, -- |Return a range of members in a sorted set, by score (). The Redis command @ZRANGEBYSCORE@ is split up into 'zrangebyscore', 'zrangebyscoreWithscores', 'zrangebyscoreLimit', 'zrangebyscoreWithscoresLimit'. Since Redis 1.0.5 zrangebyscoreWithscores, -- |Return a range of members in a sorted set, by score (). The Redis command @ZRANGEBYSCORE@ is split up into 'zrangebyscore', 'zrangebyscoreWithscores', 'zrangebyscoreLimit', 'zrangebyscoreWithscoresLimit'. Since Redis 1.0.5 zrangebyscoreLimit, -- |Return a range of members in a sorted set, by score (). The Redis command @ZRANGEBYSCORE@ is split up into 'zrangebyscore', 'zrangebyscoreWithscores', 'zrangebyscoreLimit', 'zrangebyscoreWithscoresLimit'. Since Redis 1.0.5 zrangebyscoreWithscoresLimit, -- |Return a range of members in a sorted set, by score (). The Redis command @ZRANGEBYSCORE@ is split up into 'zrangebyscore', 'zrangebyscoreWithscores', 'zrangebyscoreLimit', 'zrangebyscoreWithscoresLimit'. Since Redis 1.0.5 -zrank, -- |Determine the index of a member in a sorted set (). Since Redis 2.0.0 -zrem, -- |Remove one or more members from a sorted set (). Since Redis 1.2.0 -zremrangebylex, -- |Remove all members in a sorted set between the given lexicographical range (). Since Redis 2.8.9 -zremrangebyrank, -- |Remove all members in a sorted set within the given indexes (). Since Redis 2.0.0 -zremrangebyscore, -- |Remove all members in a sorted set within the given scores (). Since Redis 1.2.0 +zrank, +zrankWithScore, +zrem, +zremrangebylex, +zremrangebyrank, +zremrangebyscore, zrevrange, -- |Return a range of members in a sorted set, by index, with scores ordered from high to low (). The Redis command @ZREVRANGE@ is split up into 'zrevrange', 'zrevrangeWithscores'. Since Redis 1.2.0 zrevrangeWithscores, -- |Return a range of members in a sorted set, by index, with scores ordered from high to low (). The Redis command @ZREVRANGE@ is split up into 'zrevrange', 'zrevrangeWithscores'. Since Redis 1.2.0 zrevrangebyscore, -- |Return a range of members in a sorted set, by score, with scores ordered from high to low (). The Redis command @ZREVRANGEBYSCORE@ is split up into 'zrevrangebyscore', 'zrevrangebyscoreWithscores', 'zrevrangebyscoreLimit', 'zrevrangebyscoreWithscoresLimit'. Since Redis 2.2.0 zrevrangebyscoreWithscores, -- |Return a range of members in a sorted set, by score, with scores ordered from high to low (). The Redis command @ZREVRANGEBYSCORE@ is split up into 'zrevrangebyscore', 'zrevrangebyscoreWithscores', 'zrevrangebyscoreLimit', 'zrevrangebyscoreWithscoresLimit'. Since Redis 2.2.0 zrevrangebyscoreLimit, -- |Return a range of members in a sorted set, by score, with scores ordered from high to low (). The Redis command @ZREVRANGEBYSCORE@ is split up into 'zrevrangebyscore', 'zrevrangebyscoreWithscores', 'zrevrangebyscoreLimit', 'zrevrangebyscoreWithscoresLimit'. Since Redis 2.2.0 zrevrangebyscoreWithscoresLimit, -- |Return a range of members in a sorted set, by score, with scores ordered from high to low (). The Redis command @ZREVRANGEBYSCORE@ is split up into 'zrevrangebyscore', 'zrevrangebyscoreWithscores', 'zrevrangebyscoreLimit', 'zrevrangebyscoreWithscoresLimit'. Since Redis 2.2.0 -zrevrank, -- |Determine the index of a member in a sorted set, with scores ordered from high to low (). Since Redis 2.0.0 +zrevrank, +zrevrankWithScore, zscan, -- |Incrementally iterate sorted sets elements and associated scores (). The Redis command @ZSCAN@ is split up into 'zscan', 'zscanOpts'. Since Redis 2.8.0 zscanOpts, -- |Incrementally iterate sorted sets elements and associated scores (). The Redis command @ZSCAN@ is split up into 'zscan', 'zscanOpts'. Since Redis 2.8.0 -zscore, -- |Get the score associated with the given member in a sorted set (). Since Redis 1.2.0 +zscore, zunionstore, -- |Add multiple sorted sets and store the resulting sorted set in a new key (). The Redis command @ZUNIONSTORE@ is split up into 'zunionstore', 'zunionstoreWeights'. Since Redis 2.0.0 zunionstoreWeights, -- |Add multiple sorted sets and store the resulting sorted set in a new key (). The Redis command @ZUNIONSTORE@ is split up into 'zunionstore', 'zunionstoreWeights'. Since Redis 2.0.0 -- ** Strings -append, -- |Append a value to a key (). Since Redis 2.0.0 +append, bitcount, -- |Count set bits in a string (). The Redis command @BITCOUNT@ is split up into 'bitcount', 'bitcountRange'. Since Redis 2.6.0 bitcountRange, -- |Count set bits in a string (). The Redis command @BITCOUNT@ is split up into 'bitcount', 'bitcountRange'. Since Redis 2.6.0 bitopAnd, -- |Perform bitwise operations between strings (). The Redis command @BITOP@ is split up into 'bitopAnd', 'bitopOr', 'bitopXor', 'bitopNot'. Since Redis 2.6.0 bitopOr, -- |Perform bitwise operations between strings (). The Redis command @BITOP@ is split up into 'bitopAnd', 'bitopOr', 'bitopXor', 'bitopNot'. Since Redis 2.6.0 bitopXor, -- |Perform bitwise operations between strings (). The Redis command @BITOP@ is split up into 'bitopAnd', 'bitopOr', 'bitopXor', 'bitopNot'. Since Redis 2.6.0 bitopNot, -- |Perform bitwise operations between strings (). The Redis command @BITOP@ is split up into 'bitopAnd', 'bitopOr', 'bitopXor', 'bitopNot'. Since Redis 2.6.0 -bitpos, -- |Find first bit set or clear in a string (). Since Redis 2.8.7 -decr, -- |Decrement the integer value of a key by one (). Since Redis 1.0.0 -decrby, -- |Decrement the integer value of a key by the given number (). Since Redis 1.0.0 -get, -- |Get the value of a key (). Since Redis 1.0.0 -getbit, -- |Returns the bit value at offset in the string value stored at key (). Since Redis 2.2.0 -getrange, -- |Get a substring of the string stored at a key (). Since Redis 2.4.0 -getset, -- |Set the string value of a key and return its old value (). Since Redis 1.0.0 -incr, -- |Increment the integer value of a key by one (). Since Redis 1.0.0 -incrby, -- |Increment the integer value of a key by the given amount (). Since Redis 1.0.0 -incrbyfloat, -- |Increment the float value of a key by the given amount (). Since Redis 2.6.0 -mget, -- |Get the values of all the given keys (). Since Redis 1.0.0 -mset, -- |Set multiple keys to multiple values (). Since Redis 1.0.1 -msetnx, -- |Set multiple keys to multiple values, only if none of the keys exist (). Since Redis 1.0.1 -psetex, -- |Set the value and expiration in milliseconds of a key (). Since Redis 2.6.0 +bitpos, +bitposOpts, +BitposOpts(..), +BitposType(..), +decr, +decrby, +get, +getbit, +getrange, +getset, +incr, +incrby, +incrbyfloat, +mget, +mset, +msetnx, +psetex, Condition(..), SetOpts(..), set, -- |Set the string value of a key (). The Redis command @SET@ is split up into 'set', 'setOpts', 'setGet', 'setGetOpts'. Since Redis 1.0.0 setOpts, -- |Set the string value of a key (). The Redis command @SET@ is split up into 'set', 'setOpts', 'setGet', 'setGetOpts'. Since Redis 1.0.0 setGet, -- |Set the string value of a key (). The Redis command @SET@ is split up into 'set', 'setOpts', 'setGet', 'setGetOpts'. Since Redis 1.0.0 setGetOpts, -- |Set the string value of a key (). The Redis command @SET@ is split up into 'set', 'setOpts', 'setGet', 'setGetOpts'. Since Redis 1.0.0 -setbit, -- |Sets or clears the bit at offset in the string value stored at key (). Since Redis 2.2.0 -setex, -- |Set the value and expiration of a key (). Since Redis 2.0.0 -setnx, -- |Set the value of a key, only if the key does not exist (). Since Redis 1.0.0 -setrange, -- |Overwrite part of a string at key starting at the specified offset (). Since Redis 2.2.0 -strlen, -- |Get the length of the value stored in a key (). Since Redis 2.2.0 +setbit, +setex, +setnx, +setrange, +strlen, -- ** Streams @@ -241,7 +258,7 @@ XReadResponse(..), StreamsRecord(..), TrimOpts(..), xadd, -xaddOpts, +xaddOpts, XAddOpts(..), defaultXAddOpts, TrimStrategy(..), @@ -305,14 +322,14 @@ xautoclaimJustIds, xautoclaimJustIdsOpts, XAutoclaimJustIdsResult, XInfoConsumersResponse(..), -xinfoConsumers, -- |Get info about consumers in a group. The Redis command @XINFO@ is split into 'xinfoConsumers', 'xinfoGroups', and 'xinfoStream'. Since Redis 5.0.0 +xinfoConsumers, XInfoGroupsResponse(..), -xinfoGroups, -- |Get info about groups consuming from a stream. The Redis command @XINFO@ is split into 'xinfoConsumers', 'xinfoGroups', and 'xinfoStream'. Since Redis 5.0.0 +xinfoGroups, XInfoStreamResponse(..), -xinfoStream, -- |Get info about a stream. The Redis command @XINFO@ is split into 'xinfoConsumers', 'xinfoGroups', and 'xinfoStream'. Since Redis 5.0.0 -xdel, -- |Delete messages from a stream. Since Redis 5.0.0 -xtrim, -- |Set the upper bound for number of messages in a stream. Since Redis 5.0.0 -inf, -- |Constructor for `inf` Redis argument values +xinfoStream, +xdel, +xtrim, +inf, ClusterNodesResponse(..), ClusterNodesResponseEntry(..), ClusterNodesResponseSlotSpec(..), @@ -368,160 +385,287 @@ command ) where import Prelude hiding (min,max) +import Data.Int import Data.ByteString (ByteString) -import Data.List.NonEmpty (NonEmpty) +import Data.List.NonEmpty (NonEmpty(..)) import qualified Data.List.NonEmpty as NE import Database.Redis.ManualCommands import Database.Redis.Types import Database.Redis.Core(sendRequest, RedisCtx) +-- | /O(1)/ +-- Get the time to live for a key (). +-- Since Redis 1.0.0 +-- +-- This command returns: +-- * -2 if the key does not exist +-- * -1 if the key exists but has no associated value +-- ttl :: (RedisCtx m f) - => ByteString -- ^ key + => ByteString -- ^ Key to check. -> m (f Integer) -ttl key = sendRequest (["TTL"] ++ [encode key] ) +ttl key = sendRequest ["TTL", encode key] +-- | /O(1)/ +-- Sets the value of a key, only if the key does not exist (). +-- +-- Returns a result if a value was set. +-- +-- Since Redis 1.0.0 setnx :: (RedisCtx m f) - => ByteString -- ^ key - -> ByteString -- ^ value + => ByteString -- ^ Key to set. + -> ByteString -- ^ Value to set. -> m (f Bool) -setnx key value = sendRequest (["SETNX"] ++ [encode key] ++ [encode value] ) +setnx key value = sendRequest ["SETNX", encode key, encode value] +-- | /O(1)/ +-- Get the time to live for a key in milliseconds (). +-- Since Redis 2.6.0 +-- +-- This command returns @-2@ if the key does not exist. +-- This command returns @-1@ if the key exists but has no associated value pttl :: (RedisCtx m f) - => ByteString -- ^ key + => ByteString -- ^ Key. -> m (f Integer) -pttl key = sendRequest (["PTTL"] ++ [encode key] ) +pttl key = sendRequest ["PTTL", encode key] +-- | /O(1)/ +-- Get total number of Redis commands (). +-- Since Redis 2.8.13 commandCount :: (RedisCtx m f) => m (f Integer) -commandCount = sendRequest (["COMMAND","COUNT"] ) +commandCount = sendRequest ["COMMAND","COUNT"] +-- | Set the current connection name (). +-- Since Redis 2.6.9 clientSetname :: (RedisCtx m f) - => ByteString -- ^ connectionName + => ByteString -- ^ Connection Name. -> m (f Status) -clientSetname connectionName = sendRequest (["CLIENT","SETNAME"] ++ [encode connectionName] ) +clientSetname connectionName = sendRequest ["CLIENT","SETNAME",encode connectionName] +-- | Determine the index of a member in a sorted set (). +-- +-- Since Redis 2.0.0 zrank :: (RedisCtx m f) - => ByteString -- ^ key - -> ByteString -- ^ member + => ByteString -- ^ Key.of the set. + -> ByteString -- ^ Member -> m (f (Maybe Integer)) -zrank key member = sendRequest (["ZRANK"] ++ [encode key] ++ [encode member] ) +zrank key member = sendRequest ["ZRANK", encode key, encode member] +-- | +-- Since Redis 7.2.0: fails on earlier versions +zrankWithScore + :: (RedisCtx m f) + => ByteString -- ^ Key of the set. + -> ByteString -- ^ Member. + -> m (f (Maybe (Integer,Double))) +zrankWithScore key member = sendRequest ["ZRANK", encode key, encode member, "WITHSCORE"] + +-- | /O(log(N)+M)/ with @N@ number of elements in the set, @M@ number of elements to be removed. +-- +-- Remove all members in a sorted set within the given scores (). +-- +-- Returns a number of elements that were removed. +-- +-- Since Redis 1.2.0 zremrangebyscore :: (RedisCtx m f) => ByteString -- ^ key -> Double -- ^ min -> Double -- ^ max -> m (f Integer) -zremrangebyscore key min max = sendRequest (["ZREMRANGEBYSCORE"] ++ [encode key] ++ [encode min] ++ [encode max] ) +zremrangebyscore key min max = + sendRequest ["ZREMRANGEBYSCORE",encode key,encode min,encode max] +-- | /O(N)/ where @N@ is size of the hash. +-- Get all the fields in a hash (). +-- Since Redis 2.0.0 hkeys :: (RedisCtx m f) => ByteString -- ^ key -> m (f [ByteString]) -hkeys key = sendRequest (["HKEYS"] ++ [encode key] ) +hkeys key = sendRequest ["HKEYS",encode key] +-- |Make the server a slave of another instance, or promote it as master (). +-- Deprecated in Redis, can be replaced by replicaif since redis 5.0 +-- Since Redis 1.0.0 slaveof :: (RedisCtx m f) => ByteString -- ^ host -> ByteString -- ^ port -> m (f Status) -slaveof host port = sendRequest (["SLAVEOF"] ++ [encode host] ++ [encode port] ) +slaveof host port = sendRequest ["SLAVEOF",encode host,encode port] +-- | /O(1)/ for each element added. +-- Append a value to a list, only if the list exists (). +-- Since Redis 2.2.0 rpushx :: (RedisCtx m f) => ByteString -- ^ key - -> ByteString -- ^ value + -> NonEmpty ByteString -- ^ value -> m (f Integer) -rpushx key value = sendRequest (["RPUSHX"] ++ [encode key] ++ [encode value] ) +rpushx key (value:|values) = sendRequest ("RPUSHX":encode key:value:values) +-- |Get debugging information about a key (). Since Redis 1.0.0 debugObject :: (RedisCtx m f) => ByteString -- ^ key -> m (f ByteString) -debugObject key = sendRequest (["DEBUG","OBJECT"] ++ [encode key] ) +debugObject key = sendRequest ["DEBUG","OBJECT",encode key] +-- |Asynchronously save the dataset to disk (). +-- +-- Since Redis 1.0.0 bgsave :: (RedisCtx m f) => m (f Status) -bgsave = sendRequest (["BGSAVE"] ) +bgsave = sendRequest ["BGSAVE"] + +-- |Asynchronously save the dataset to disk (). +-- +-- Immediately returns OK when an AOF rewrite is in progress and schedule the background save +-- to run at the next opportunity. +-- +-- A client may bee able to check if the operation succeeded using the 'lastsave' command +-- +-- Since Redis 3.2.2 +bgsaveSchedule + :: (RedisCtx m f) + => m (f Status) +bgsaveSchedule = sendRequest ["BGSAVE", "SCHEDULE"] + +-- | /O(1)/ Get the number of fields in a hash (). +-- +-- Since Redis 2.0.0 hlen :: (RedisCtx m f) => ByteString -- ^ key -> m (f Integer) -hlen key = sendRequest (["HLEN"] ++ [encode key] ) +hlen key = sendRequest ["HLEN", key] +-- |Remove the last element in a list, prepend it to another list and return that +-- element f it existed (). +-- Since Redis 1.2.0 rpoplpush :: (RedisCtx m f) => ByteString -- ^ source -> ByteString -- ^ destination -> m (f (Maybe ByteString)) -rpoplpush source destination = sendRequest (["RPOPLPUSH"] ++ [encode source] ++ [encode destination] ) +rpoplpush source destination = sendRequest ["RPOPLPUSH",encode source,encode destination] +-- | /O(N)/ +-- Remove and get the last element in a list, or block until one is available (). +-- +-- Since Redis 2.0.0 brpop :: (RedisCtx m f) - => [ByteString] -- ^ key + => NonEmpty ByteString -- ^ key -> Integer -- ^ timeout -> m (f (Maybe (ByteString,ByteString))) -brpop key timeout = sendRequest (["BRPOP"] ++ map encode key ++ [encode timeout] ) +brpop (key:|rest) timeout = sendRequest (("BRPOP":key:rest) ++ [encode timeout]) + +-- | /O(N)/ +-- Remove and get the last element in a list, or block until one is available (). +-- +-- Since Redis 2.0.0 +brpopFloat + :: (RedisCtx m f) + => [ByteString] -- ^ key + -> Double -- ^ timeout + -> m (f (Maybe (ByteString,ByteString))) +brpopFloat key timeout = sendRequest (["BRPOP"] ++ map encode key ++ [encode timeout]) +-- |Asynchronously rewrite the append-only file (). Since Redis 1.0.0 bgrewriteaof :: (RedisCtx m f) => m (f Status) -bgrewriteaof = sendRequest (["BGREWRITEAOF"] ) +bgrewriteaof = sendRequest ["BGREWRITEAOF"] +-- | /O(log(N))/ +-- +-- Increment the score of a member in a sorted set (). +-- +-- Returns new score of the element. +-- +-- Since Redis 1.2.0 zincrby :: (RedisCtx m f) => ByteString -- ^ key -> Integer -- ^ increment -> ByteString -- ^ member -> m (f Double) -zincrby key increment member = sendRequest (["ZINCRBY"] ++ [encode key] ++ [encode increment] ++ [encode member] ) +zincrby key increment member = sendRequest ["ZINCRBY",encode key,encode increment,encode member] +-- | Get all the fields and values in a hash (). +-- +-- Since Redis 2.0.0. hgetall :: (RedisCtx m f) => ByteString -- ^ key -> m (f [(ByteString,ByteString)]) -hgetall key = sendRequest (["HGETALL"] ++ [encode key] ) +hgetall key = sendRequest ["HGETALL", encode key] + +-- | Set multiple hash fields to multiple values (). +-- +-- Deprecated by Redis, consider using 'hset' with multiple field-value pairs. +-- +-- Since Redis 2.0.0 hmset :: (RedisCtx m f) => ByteString -- ^ key - -> [(ByteString,ByteString)] -- ^ fieldValue + -> NonEmpty (ByteString,ByteString) -- ^ fieldValue -> m (f Status) -hmset key fieldValue = sendRequest (["HMSET"] ++ [encode key] ++ concatMap (\(x,y) -> [encode x,encode y])fieldValue ) +hmset key ((field,value):|fieldValues) = + sendRequest ("HMSET":key:field:value: concatMap (\(x,y) -> [x,y]) fieldValues) +-- |Intersect multiple sets (). +-- Since Redis 1.0.0 sinter :: (RedisCtx m f) - => [ByteString] -- ^ key + => NonEmpty ByteString -- ^ Keys. -> m (f [ByteString]) -sinter key = sendRequest (["SINTER"] ++ map encode key ) +sinter (key:|keys_) = sendRequest ("SINTER":key:keys_) +-- | /O(1)/ +-- Adds all the elements arguments to the HyperLogLog data structure stored at the variable name specified as first argument (). +-- Since Redis 2.8.9 pfadd :: (RedisCtx m f) - => ByteString -- ^ key - -> [ByteString] -- ^ value + => ByteString -- ^ Key. + -> NonEmpty ByteString -- ^ Value. -> m (f Integer) -pfadd key value = sendRequest (["PFADD"] ++ [encode key] ++ map encode value ) +pfadd key (value:|values) = sendRequest ("PFADD":key:value:values) +-- | /O(log(N)+M/ with @N@ being the number of elements in the sorted set and @M@ the number of elemnts removed by the operation. +-- +-- Remove all members in a sorted set within the given indexes (). +-- +-- Returns a number of elements that were removed. +-- +-- Since Redis 2.0.0 zremrangebyrank :: (RedisCtx m f) => ByteString -- ^ key -> Integer -- ^ start -> Integer -- ^ stop -> m (f Integer) -zremrangebyrank key start stop = sendRequest (["ZREMRANGEBYRANK"] ++ [encode key] ++ [encode start] ++ [encode stop] ) +zremrangebyrank key start stop = + sendRequest ["ZREMRANGEBYRANK",encode key,encode start,encode stop] +-- |Remove all keys from the current database (). +-- Since Redis 1.0.0 flushdb :: (RedisCtx m f) => m (f Status) -flushdb = sendRequest (["FLUSHDB"] ) +flushdb = sendRequest ["FLUSHDB"] -- | /O(1)/ for each element added. -- Add one or more members to a set (). @@ -531,176 +675,242 @@ sadd => ByteString -- ^ Key where set is stored. -> NonEmpty ByteString -- ^ Member to add to the set. -> m (f Integer) -sadd key member = sendRequest (["SADD"] ++ [encode key] ++ NE.toList (fmap encode member)) +sadd key member = sendRequest ("SADD":encode key:NE.toList (fmap encode member)) +-- |Get an element from a list by its index (). +-- Since Redis 1.0.0 lindex :: (RedisCtx m f) - => ByteString -- ^ key - -> Integer -- ^ index + => ByteString -- ^ Key. + -> Integer -- ^ Index -> m (f (Maybe ByteString)) -lindex key index = sendRequest (["LINDEX"] ++ [encode key] ++ [encode index] ) +lindex key index = sendRequest ["LINDEX",encode key,encode index] +-- | Prepend one or multiple values to a list (). +-- Since Redis 1.0.0 lpush :: (RedisCtx m f) - => ByteString -- ^ key - -> [ByteString] -- ^ value + => ByteString -- ^ Key + -> NonEmpty ByteString -- ^ Value -> m (f Integer) -lpush key value = sendRequest (["LPUSH"] ++ [encode key] ++ map encode value ) +lpush key (value:|values) = sendRequest ("LPUSH":key:value:values) +-- |Get the length of the value of a hash field (). +-- Since Redis 3.2.0 hstrlen :: (RedisCtx m f) => ByteString -- ^ key -> ByteString -- ^ field -> m (f Integer) -hstrlen key field = sendRequest (["HSTRLEN"] ++ [encode key] ++ [encode field] ) +hstrlen key field = sendRequest ["HSTRLEN", key, field] +-- | +-- Move a member from one set to another (). +-- Since Redis 1.0.0 smove :: (RedisCtx m f) => ByteString -- ^ source -> ByteString -- ^ destination -> ByteString -- ^ member -> m (f Bool) -smove source destination member = sendRequest (["SMOVE"] ++ [encode source] ++ [encode destination] ++ [encode member] ) +smove source destination member = + sendRequest ["SMOVE", source, destination, member] +-- |Get the score associated with the given member in a sorted set (). +-- Since Redis 1.2.0 zscore :: (RedisCtx m f) - => ByteString -- ^ key - -> ByteString -- ^ member + => ByteString -- ^ Key. + -> ByteString -- ^ Member. -> m (f (Maybe Double)) -zscore key member = sendRequest (["ZSCORE"] ++ [encode key] ++ [encode member] ) +zscore key member = sendRequest ["ZSCORE",encode key,encode member] +-- |Reset the stats returned by INFO (). +-- Since Redis 2.0.0 configResetstat :: (RedisCtx m f) => m (f Status) -configResetstat = sendRequest (["CONFIG","RESETSTAT"] ) +configResetstat = sendRequest ["CONFIG","RESETSTAT"] +-- | +-- Return the approximated cardinality of the set(s) observed by the HyperLogLog at key(s) (). +-- Since Redis 2.8.9 pfcount :: (RedisCtx m f) - => [ByteString] -- ^ key + => NonEmpty ByteString -- ^ key -> m (f Integer) -pfcount key = sendRequest (["PFCOUNT"] ++ map encode key ) +pfcount (key:|keys_) = sendRequest ("PFCOUNT": key: keys_) +-- | Delete one or more hash fields (). +-- Since Redis 2.0.0 hdel :: (RedisCtx m f) => ByteString -- ^ key - -> [ByteString] -- ^ field + -> NonEmpty ByteString -- ^ field -> m (f Integer) -hdel key field = sendRequest (["HDEL"] ++ [encode key] ++ map encode field ) +hdel key (field:|fields) = sendRequest ("HDEL":key:field:fields) +-- |Increment the float value of a key by the given amount (). +-- Since Redis 2.6.0 incrbyfloat :: (RedisCtx m f) - => ByteString -- ^ key - -> Double -- ^ increment + => ByteString -- ^ Key. + -> Double -- ^ Increment. -> m (f Double) -incrbyfloat key increment = sendRequest (["INCRBYFLOAT"] ++ [encode key] ++ [encode increment] ) +incrbyfloat key increment = sendRequest ["INCRBYFLOAT", key, encode increment] +-- |Sets or clears the bit at offset in the string value stored at key (). +-- Since Redis 2.2.0 setbit :: (RedisCtx m f) => ByteString -- ^ key -> Integer -- ^ offset -> ByteString -- ^ value -> m (f Integer) -setbit key offset value = sendRequest (["SETBIT"] ++ [encode key] ++ [encode offset] ++ [encode value] ) +setbit key offset value = sendRequest ["SETBIT", key, encode offset, value] +-- | Remove all keys from all databases (). Since Redis 1.0.0 flushall :: (RedisCtx m f) => m (f Status) -flushall = sendRequest (["FLUSHALL"] ) +flushall = sendRequest ["FLUSHALL"] +-- |Increment the integer value of a key by the given amount (). +-- Since Redis 1.0.0 incrby :: (RedisCtx m f) => ByteString -- ^ key -> Integer -- ^ increment -> m (f Integer) -incrby key increment = sendRequest (["INCRBY"] ++ [encode key] ++ [encode increment] ) +incrby key increment = sendRequest ["INCRBY", key, encode increment] +-- | Return the current server time (). +-- Since Redis 2.6.0 time :: (RedisCtx m f) => m (f (Integer,Integer)) -time = sendRequest (["TIME"] ) +time = sendRequest ["TIME"] +-- |Get all the members in a set (). Since Redis 1.0.0 smembers :: (RedisCtx m f) => ByteString -- ^ key -> m (f [ByteString]) -smembers key = sendRequest (["SMEMBERS"] ++ [encode key] ) +smembers key = sendRequest ["SMEMBERS", key] +-- |Count the number of members in a sorted set between a given lexicographical range (). +-- Since Redis 2.8.9 zlexcount :: (RedisCtx m f) => ByteString -- ^ key -> ByteString -- ^ min -> ByteString -- ^ max -> m (f Integer) -zlexcount key min max = sendRequest (["ZLEXCOUNT"] ++ [encode key] ++ [encode min] ++ [encode max] ) +zlexcount key min max = sendRequest ["ZLEXCOUNT", key, min, max] +-- |Add multiple sets (). +-- Since Redis 1.0.0 sunion :: (RedisCtx m f) - => [ByteString] -- ^ key + => NonEmpty ByteString -- ^ key -> m (f [ByteString]) -sunion key = sendRequest (["SUNION"] ++ map encode key ) +sunion (key:|keys_) = sendRequest ("SUNION":key:keys_) +-- |Intersect multiple sets and store the resulting set in a key (). +-- Since Redis 1.0.0 sinterstore :: (RedisCtx m f) => ByteString -- ^ destination - -> [ByteString] -- ^ key + -> NonEmpty ByteString -- ^ key -> m (f Integer) -sinterstore destination key = sendRequest (["SINTERSTORE"] ++ [encode destination] ++ map encode key ) +sinterstore destination (key:|keys_) = + sendRequest ("SINTERSTORE":destination:key:keys_) +-- | Get all the values in a hash (). +-- Since Redis 2.0.0 hvals :: (RedisCtx m f) => ByteString -- ^ key -> m (f [ByteString]) -hvals key = sendRequest (["HVALS"] ++ [encode key] ) +hvals key = sendRequest ["HVALS", key] +-- |Set a configuration parameter to the given value (). +-- Since Redis 2.0.0 configSet :: (RedisCtx m f) => ByteString -- ^ parameter -> ByteString -- ^ value -> m (f Status) -configSet parameter value = sendRequest (["CONFIG","SET"] ++ [encode parameter] ++ [encode value] ) +configSet parameter value = sendRequest ["CONFIG","SET", parameter, value] +-- |Remove all the scripts from the script cache (). +-- Since Redis 2.6.0 scriptFlush :: (RedisCtx m f) => m (f Status) -scriptFlush = sendRequest (["SCRIPT","FLUSH"] ) +scriptFlush = sendRequest ["SCRIPT","FLUSH"] +-- |Return the number of keys in the selected database (). +-- Since Redis 1.0.0 dbsize :: (RedisCtx m f) => m (f Integer) -dbsize = sendRequest (["DBSIZE"] ) +dbsize = sendRequest ["DBSIZE"] +-- |Wait for the synchronous replication of all the write commands sent in the context of the current connection (). +-- Since Redis 3.0.0 wait :: (RedisCtx m f) => Integer -- ^ numslaves -> Integer -- ^ timeout -> m (f Integer) -wait numslaves timeout = sendRequest (["WAIT"] ++ [encode numslaves] ++ [encode timeout] ) +wait numslaves timeout = sendRequest ["WAIT", encode numslaves, encode timeout] +-- |Remove and get the first element in a list (). Since Redis 1.0.0 lpop :: (RedisCtx m f) => ByteString -- ^ key -> m (f (Maybe ByteString)) -lpop key = sendRequest (["LPOP"] ++ [encode key] ) +lpop key = sendRequest ["LPOP", encode key] +-- | +-- Remove and get the first element in a list (). +-- The reply will consist of up to count elements, depending on the list's length. +-- Since Redis 1.0.0 +lpopCount + :: (RedisCtx m f) + => ByteString -- ^ key + -> Integer + -> m (f [ByteString]) +lpopCount key count = sendRequest ["LPOP", key, encode count] + +-- |Stop processing commands from clients for some time (). +-- Since Redis 2.9.50 clientPause :: (RedisCtx m f) => Integer -- ^ timeout -> m (f Status) -clientPause timeout = sendRequest (["CLIENT","PAUSE"] ++ [encode timeout] ) +clientPause timeout = sendRequest ["CLIENT","PAUSE", encode timeout] +-- |Set a key's time to live in seconds (). Since Redis 1.0.0 expire :: (RedisCtx m f) => ByteString -- ^ key -> Integer -- ^ seconds -> m (f Bool) -expire key seconds = sendRequest (["EXPIRE"] ++ [encode key] ++ [encode seconds] ) +expire key seconds = sendRequest ["EXPIRE", key, encode seconds] +-- |Get the values of all the given keys (). +-- Since Redis 1.0.0 mget :: (RedisCtx m f) - => [ByteString] -- ^ key + => NonEmpty ByteString -- ^ key -> m (f [Maybe ByteString]) -mget key = sendRequest (["MGET"] ++ map encode key ) +mget (key:|keys_) = sendRequest ("MGET":key:keys_) +-- | +-- Find first bit set or clear in a string (). +-- Since Redis 2.8.7 bitpos :: (RedisCtx m f) => ByteString -- ^ key @@ -708,228 +918,290 @@ bitpos -> Integer -- ^ start -> Integer -- ^ end -> m (f Integer) -bitpos key bit start end = sendRequest (["BITPOS"] ++ [encode key] ++ [encode bit] ++ [encode start] ++ [encode end] ) +bitpos key bit start end = sendRequest ["BITPOS", key, encode bit, encode start, encode end] lastsave :: (RedisCtx m f) => m (f Integer) lastsave = sendRequest (["LASTSAVE"] ) +-- | Set a key's time to live in milliseconds (). +-- Since Redis 2.6.0 pexpire :: (RedisCtx m f) => ByteString -- ^ key -> Integer -- ^ milliseconds -> m (f Bool) -pexpire key milliseconds = sendRequest (["PEXPIRE"] ++ [encode key] ++ [encode milliseconds] ) +pexpire key milliseconds = sendRequest ["PEXPIRE", key, encode milliseconds] +-- |Get the list of client connections (). Since Redis 2.4.0 clientList :: (RedisCtx m f) => m (f [ByteString]) clientList = sendRequest (["CLIENT","LIST"] ) +-- |Rename a key, only if the new key does not exist (). Since Redis 1.0.0 renamenx :: (RedisCtx m f) => ByteString -- ^ key -> ByteString -- ^ newkey -> m (f Bool) -renamenx key newkey = sendRequest (["RENAMENX"] ++ [encode key] ++ [encode newkey] ) +renamenx key newkey = sendRequest ["RENAMENX", key, newkey] +-- |Merge N different HyperLogLogs into a single one (). Since Redis 2.8.9 pfmerge :: (RedisCtx m f) => ByteString -- ^ destkey -> [ByteString] -- ^ sourcekey -> m (f ByteString) -pfmerge destkey sourcekey = sendRequest (["PFMERGE"] ++ [encode destkey] ++ map encode sourcekey ) +pfmerge destkey sourcekey = sendRequest ("PFMERGE": destkey: sourcekey) +-- | Remove elements from a list (). Since Redis 1.0.0 lrem :: (RedisCtx m f) => ByteString -- ^ key -> Integer -- ^ count -> ByteString -- ^ value -> m (f Integer) -lrem key count value = sendRequest (["LREM"] ++ [encode key] ++ [encode count] ++ [encode value] ) +lrem key count value = sendRequest ["LREM", key, encode count, value] +-- |Subtract multiple sets (). Since Redis 1.0.0 sdiff :: (RedisCtx m f) - => [ByteString] -- ^ key + => NonEmpty ByteString -- ^ key -> m (f [ByteString]) -sdiff key = sendRequest (["SDIFF"] ++ map encode key ) +sdiff (key_:|keys_) = sendRequest ("SDIFF":key_:keys_) +-- |Get the value of a key (). Since Redis 1.0.0 get :: (RedisCtx m f) => ByteString -- ^ key -> m (f (Maybe ByteString)) get key = sendRequest (["GET"] ++ [encode key] ) +-- |Get a substring of the string stored at a key (). +-- Since Redis 2.4.0 getrange :: (RedisCtx m f) => ByteString -- ^ key -> Integer -- ^ start -> Integer -- ^ end -> m (f ByteString) -getrange key start end = sendRequest (["GETRANGE"] ++ [encode key] ++ [encode start] ++ [encode end] ) +getrange key start end = sendRequest ["GETRANGE", key, encode start, encode end] +-- |Subtract multiple sets and store the resulting set in a key (). Since Redis 1.0.0 sdiffstore :: (RedisCtx m f) => ByteString -- ^ destination - -> [ByteString] -- ^ key + -> NonEmpty ByteString -- ^ key -> m (f Integer) -sdiffstore destination key = sendRequest (["SDIFFSTORE"] ++ [encode destination] ++ map encode key ) +sdiffstore destination (key_:|keys_) = sendRequest ("SDIFFSTORE": destination: key_: keys_) +-- |Count the members in a sorted set with scores within the given values (). Since Redis 2.0.0 zcount :: (RedisCtx m f) => ByteString -- ^ key -> Double -- ^ min -> Double -- ^ max -> m (f Integer) -zcount key min max = sendRequest (["ZCOUNT"] ++ [encode key] ++ [encode min] ++ [encode max] ) +zcount key min max = sendRequest ["ZCOUNT", key, encode min, encode max] +-- |Load the specified Lua script into the script cache (). Since Redis 2.6.0 scriptLoad :: (RedisCtx m f) => ByteString -- ^ script -> m (f ByteString) -scriptLoad script = sendRequest (["SCRIPT","LOAD"] ++ [encode script] ) +scriptLoad script = sendRequest ["SCRIPT","LOAD", encode script] +-- |Set the string value of a key and return its old value (). Since Redis 1.0.0 getset :: (RedisCtx m f) => ByteString -- ^ key -> ByteString -- ^ value -> m (f (Maybe ByteString)) -getset key value = sendRequest (["GETSET"] ++ [encode key] ++ [encode value] ) +getset key value = sendRequest ["GETSET", key, value] +-- |Return a serialized version of the value stored at the specified key (). Since Redis 2.6.0 dump :: (RedisCtx m f) => ByteString -- ^ key -> m (f ByteString) -dump key = sendRequest (["DUMP"] ++ [encode key] ) +dump key = sendRequest ["DUMP", key] +-- |Find all keys matching the given pattern (). Since Redis 1.0.0 keys :: (RedisCtx m f) => ByteString -- ^ pattern -> m (f [ByteString]) -keys pattern = sendRequest (["KEYS"] ++ [encode pattern] ) +keys pattern = sendRequest ["KEYS", pattern] +-- |Get the value of a configuration parameter (). Since Redis 2.0.0 configGet :: (RedisCtx m f) - => ByteString -- ^ parameter + => NonEmpty ByteString -- ^ parameter -> m (f [(ByteString,ByteString)]) -configGet parameter = sendRequest (["CONFIG","GET"] ++ [encode parameter] ) +configGet (parameter:|parameters) = sendRequest ("CONFIG":"GET":parameter:parameters) +-- |Append one or multiple values to a list (). Since Redis 1.0.0 rpush :: (RedisCtx m f) => ByteString -- ^ key - -> [ByteString] -- ^ value + -> NonEmpty ByteString -- ^ value -> m (f Integer) -rpush key value = sendRequest (["RPUSH"] ++ [encode key] ++ map encode value ) +rpush key (value:|values) = sendRequest ("RPUSH": encode key:value:values) +-- |Return a random key from the keyspace (). Since Redis 1.0.0 randomkey :: (RedisCtx m f) => m (f (Maybe ByteString)) -randomkey = sendRequest (["RANDOMKEY"] ) +randomkey = sendRequest ["RANDOMKEY"] +-- |Set the value of a hash field, only if the field does not exist (). Since Redis 2.0.0 hsetnx :: (RedisCtx m f) => ByteString -- ^ key -> ByteString -- ^ field -> ByteString -- ^ value -> m (f Bool) -hsetnx key field value = sendRequest (["HSETNX"] ++ [encode key] ++ [encode field] ++ [encode value] ) +hsetnx key field value = sendRequest ["HSETNX", key, field, value] +-- |Set multiple keys to multiple values (). Since Redis 1.0.1 mset :: (RedisCtx m f) - => [(ByteString,ByteString)] -- ^ keyValue + => NonEmpty (ByteString,ByteString) -- ^ keyValue -> m (f Status) -mset keyValue = sendRequest (["MSET"] ++ concatMap (\(x,y) -> [encode x,encode y])keyValue ) +mset ((key_,value):|keyValue) = + sendRequest ("MSET":key_:value: concatMap (\(x,y) -> [encode x,encode y]) keyValue) +-- |Set the value and expiration of a key (). +-- Regarded as deprected since 2.6 as it can be replaced by SET with the EX argument when +-- migrating or writing new code. +-- Since Redis 2.0.0 setex :: (RedisCtx m f) => ByteString -- ^ key -> Integer -- ^ seconds -> ByteString -- ^ value -> m (f Status) -setex key seconds value = sendRequest (["SETEX"] ++ [encode key] ++ [encode seconds] ++ [encode value] ) +setex key seconds value = sendRequest ["SETEX", key, encode seconds, value] +-- |Set the value and expiration in milliseconds of a key (). +-- Condidered deprecated since it can be replaced by SET with the PX argument when migrating or writing new code +-- Since Redis 2.6.0 psetex :: (RedisCtx m f) => ByteString -- ^ key -> Integer -- ^ milliseconds -> ByteString -- ^ value -> m (f Status) -psetex key milliseconds value = sendRequest (["PSETEX"] ++ [encode key] ++ [encode milliseconds] ++ [encode value] ) +psetex key milliseconds value = sendRequest ["PSETEX", key, encode milliseconds, value] +-- |Get the number of members in a set (). Since Redis 1.0.0 scard :: (RedisCtx m f) => ByteString -- ^ key -> m (f Integer) -scard key = sendRequest (["SCARD"] ++ [encode key] ) +scard key = sendRequest ["SCARD", key] +-- |Check existence of scripts in the script cache (). Since Redis 2.6.0 scriptExists :: (RedisCtx m f) - => [ByteString] -- ^ script + => NonEmpty ByteString -- ^ script -> m (f [Bool]) -scriptExists script = sendRequest (["SCRIPT","EXISTS"] ++ map encode script ) +scriptExists (script:|scripts) = sendRequest ("SCRIPT":"EXISTS":script:scripts) +-- |Add multiple sets and store the resulting set in a key (). Since Redis 1.0.0 sunionstore :: (RedisCtx m f) => ByteString -- ^ destination - -> [ByteString] -- ^ key + -> NonEmpty ByteString -- ^ key -> m (f Integer) -sunionstore destination key = sendRequest (["SUNIONSTORE"] ++ [encode destination] ++ map encode key ) +sunionstore destination (key_:|keys_) = + sendRequest ("SUNIONSTORE":destination:key_:keys_) +-- |Remove the expiration from a key (). Since Redis 2.2.0 persist :: (RedisCtx m f) => ByteString -- ^ key -> m (f Bool) -persist key = sendRequest (["PERSIST"] ++ [encode key] ) +persist key = sendRequest ["PERSIST", key] +-- |Get the length of the value stored in a key (). Since Redis 2.2.0 strlen :: (RedisCtx m f) => ByteString -- ^ key -> m (f Integer) -strlen key = sendRequest (["STRLEN"] ++ [encode key] ) +strlen key = sendRequest ["STRLEN", encode key] +-- |Prepend a value to a list, only if the list exists (). Since Redis 2.2.0 lpushx :: (RedisCtx m f) => ByteString -- ^ key - -> ByteString -- ^ value + -> NonEmpty ByteString -- ^ value -> m (f Integer) -lpushx key value = sendRequest (["LPUSHX"] ++ [encode key] ++ [encode value] ) +lpushx key (value:|values) = sendRequest ("LPUSHX":key:value:values) +-- |Set the string value of a hash field (). +-- +-- This command oveerides keys if they exist in the hash. +-- +-- Since Redis 2.0.0 hset :: (RedisCtx m f) => ByteString -- ^ key - -> ByteString -- ^ field - -> ByteString -- ^ value + -> NonEmpty (ByteString, ByteString) -- ^ Values. -> m (f Integer) -hset key field value = sendRequest (["HSET"] ++ [encode key] ++ [encode field] ++ [encode value] ) +hset key ((field,value):|fieldValues) = + sendRequest ("HSET":encode key:encode field:encode value:concatMap (\(f,v) ->[f,v]) fieldValues) +-- |Pop a value from a list, push it to another list and return it; or block until one is available (). +-- +-- Since Redis 6.0 this command considered deprecated: it can be replaced by BLMOVE with the RIGHT and LEFT arguments when migrating or writing new code. +-- +-- Since Redis 2.2.0 brpoplpush :: (RedisCtx m f) => ByteString -- ^ source -> ByteString -- ^ destination -> Integer -- ^ timeout -> m (f (Maybe ByteString)) -brpoplpush source destination timeout = sendRequest (["BRPOPLPUSH"] ++ [encode source] ++ [encode destination] ++ [encode timeout] ) +brpoplpush source destination timeout = + sendRequest ["BRPOPLPUSH", source, destination, encode timeout] +-- |Determine the index of a member in a sorted set, with scores ordered from high to low (). +-- Since Redis 2.0.0 zrevrank :: (RedisCtx m f) => ByteString -- ^ key -> ByteString -- ^ member -> m (f (Maybe Integer)) -zrevrank key member = sendRequest (["ZREVRANK"] ++ [encode key] ++ [encode member] ) +zrevrank key member = sendRequest ["ZREVRANK", key, member] +zrevrankWithScore + :: (RedisCtx m f) + => ByteString -- ^ key + -> ByteString -- ^ member + -> m (f (Maybe (Integer, Double))) +zrevrankWithScore key member = sendRequest ["ZREVRANK", key, member] + +-- |Kill the script currently in execution (). Since Redis 2.6.0 scriptKill :: (RedisCtx m f) => m (f Status) -scriptKill = sendRequest (["SCRIPT","KILL"] ) +scriptKill = sendRequest ["SCRIPT","KILL"] +-- |Overwrite part of a string at key starting at the specified offset (). +-- +-- Returns the lenght of the string after it was modified. +-- +-- Since Redis 2.2.0 setrange :: (RedisCtx m f) => ByteString -- ^ key -> Integer -- ^ offset -> ByteString -- ^ value -> m (f Integer) -setrange key offset value = sendRequest (["SETRANGE"] ++ [encode key] ++ [encode offset] ++ [encode value] ) +setrange key offset value = sendRequest ["SETRANGE", key, encode offset, value] -- | Delete a key (). -- Returns a number of keys that were removed. @@ -938,24 +1210,35 @@ del :: (RedisCtx m f) => NonEmpty ByteString -- ^ List of keys to delete. -> m (f Integer) -del key = sendRequest (["DEL"] ++ (NE.toList (fmap encode key))) +del (key:|rest) = sendRequest ("DEL":key:rest) +-- |Increment the float value of a hash field by the given amount (). +-- Since Redis 2.6.0 hincrbyfloat :: (RedisCtx m f) => ByteString -- ^ key -> ByteString -- ^ field -> Double -- ^ increment -> m (f Double) -hincrbyfloat key field increment = sendRequest (["HINCRBYFLOAT"] ++ [encode key] ++ [encode field] ++ [encode increment] ) +hincrbyfloat key field increment = sendRequest ["HINCRBYFLOAT", key, field, encode increment] +-- | Increment the integer value of a hash field by the given number (). Since Redis 2.0.0 hincrby :: (RedisCtx m f) => ByteString -- ^ key -> ByteString -- ^ field - -> Integer -- ^ increment - -> m (f Integer) -hincrby key field increment = sendRequest (["HINCRBY"] ++ [encode key] ++ [encode field] ++ [encode increment] ) + -> Int64 -- ^ increment + -> m (f Int64) +hincrby key field increment = sendRequest ["HINCRBY", encode key, encode field, encode increment] +-- | O(log(N)+M) with @N@ being thee number of elements in thee sorted set and @M@ the number +-- of elements removed by the operation. +-- +-- Remove all members in a sorted set between the given lexicographical range (). +-- +-- Returns number of elements that were removed. +-- +-- Since Redis 2.8.9 zremrangebylex :: (RedisCtx m f) => ByteString -- ^ key @@ -964,180 +1247,251 @@ zremrangebylex -> m (f Integer) zremrangebylex key min max = sendRequest (["ZREMRANGEBYLEX"] ++ [encode key] ++ [encode min] ++ [encode max] ) +-- |Remove and get the last element in a list (). +-- Since Redis 1.0.0 rpop :: (RedisCtx m f) => ByteString -- ^ key -> m (f (Maybe ByteString)) -rpop key = sendRequest (["RPOP"] ++ [encode key] ) +rpop key = sendRequest ["RPOP", encode key] +-- |Remove and get the last element in a list (). +-- +-- Result will have no more than @N@ arguments. +-- +-- Since Redis 1.0.0 +rpopCount + :: (RedisCtx m f) + => ByteString -- ^ key + -> Integer + -> m (f (Maybe ByteString)) +rpopCount key count = sendRequest (["RPOP",key, encode count] ) + +-- |Rename a key (). Since Redis 1.0.0 +-- +-- Does not return a error even if newkey existed. rename :: (RedisCtx m f) => ByteString -- ^ key -> ByteString -- ^ newkey -> m (f Status) -rename key newkey = sendRequest (["RENAME"] ++ [encode key] ++ [encode newkey] ) +rename key newkey = sendRequest ["RENAME", encode key, encode newkey] +-- | /O(M*log(N))/ with @N@ number of elements in the sorted set, @M@ number of elements to be +-- removed. +-- +-- Removes one or more members from a sorted set (). +-- +-- Since Redis 1.2.0 zrem :: (RedisCtx m f) => ByteString -- ^ key - -> [ByteString] -- ^ member + -> NonEmpty ByteString -- ^ member -> m (f Integer) -zrem key member = sendRequest (["ZREM"] ++ [encode key] ++ map encode member ) +zrem key (member:|members) = sendRequest ("ZREM":encode key:encode member:members) +-- |Determine if a hash field exists (). +-- Since Redis 2.0.0 hexists :: (RedisCtx m f) => ByteString -- ^ key -> ByteString -- ^ field -> m (f Bool) -hexists key field = sendRequest (["HEXISTS"] ++ [encode key] ++ [encode field] ) +hexists key field = sendRequest ["HEXISTS", key, field] +-- |Get the current connection ID (). Since Redis 5.0.0 clientId :: (RedisCtx m f) => m (f Integer) -clientId = sendRequest (["CLIENT","ID"] ) +clientId = sendRequest ["CLIENT","ID"] +-- |Get the current connection name (). Since Redis 2.6.9 clientGetname :: (RedisCtx m f) => m (f (Maybe ByteString)) -clientGetname = sendRequest (["CLIENT","GETNAME"] ) +clientGetname = sendRequest ["CLIENT","GETNAME"] +-- |Rewrite the configuration file with the in memory configuration (). Since Redis 2.8.0 configRewrite :: (RedisCtx m f) => m (f Status) -configRewrite = sendRequest (["CONFIG","REWRITE"] ) +configRewrite = sendRequest ["CONFIG","REWRITE"] +-- |Decrement the integer value of a key by one (). +-- Since Redis 1.0.0 decr :: (RedisCtx m f) => ByteString -- ^ key -> m (f Integer) -decr key = sendRequest (["DECR"] ++ [encode key] ) +decr key = sendRequest ["DECR", key] +-- |Get the values of all the given hash fields (). +-- Since Redis 2.0.0 hmget :: (RedisCtx m f) => ByteString -- ^ key - -> [ByteString] -- ^ field + -> NonEmpty ByteString -- ^ field -> m (f [Maybe ByteString]) -hmget key field = sendRequest (["HMGET"] ++ [encode key] ++ map encode field ) +hmget key (field:|fields) = sendRequest ("HMGET":key:field:fields) +-- |Get a range of elements from a list (). Since Redis 1.0.0 lrange :: (RedisCtx m f) => ByteString -- ^ key -> Integer -- ^ start -> Integer -- ^ stop -> m (f [ByteString]) -lrange key start stop = sendRequest (["LRANGE"] ++ [encode key] ++ [encode start] ++ [encode stop] ) +lrange key start stop = sendRequest ["LRANGE", key, encode start, encode stop] +-- |Decrement the integer value of a key by the given number (). +-- Since Redis 1.0.0 decrby :: (RedisCtx m f) => ByteString -- ^ key -> Integer -- ^ decrement -> m (f Integer) -decrby key decrement = sendRequest (["DECRBY"] ++ [encode key] ++ [encode decrement] ) +decrby key decrement = sendRequest ["DECRBY",key, encode decrement] +-- |Get the length of a list (). Since Redis 1.0.0 llen :: (RedisCtx m f) => ByteString -- ^ key -> m (f Integer) -llen key = sendRequest (["LLEN"] ++ [encode key] ) +llen key = sendRequest ["LLEN", encode key] +-- | /O(1)/ Append a value to a key (). Since Redis 2.0.0 append :: (RedisCtx m f) => ByteString -- ^ key -> ByteString -- ^ value -> m (f Integer) -append key value = sendRequest (["APPEND"] ++ [encode key] ++ [encode value] ) +append key value = sendRequest ["APPEND", key, value] +-- |Increment the integer value of a key by one (). Since Redis 1.0.0 incr :: (RedisCtx m f) => ByteString -- ^ key -> m (f Integer) -incr key = sendRequest (["INCR"] ++ [encode key] ) +incr key = sendRequest ["INCR", key] +-- |Get the value of a hash field (). Since Redis 2.0.0 hget :: (RedisCtx m f) => ByteString -- ^ key -> ByteString -- ^ field -> m (f (Maybe ByteString)) -hget key field = sendRequest (["HGET"] ++ [encode key] ++ [encode field] ) +hget key field = sendRequest ["HGET",key,field] +-- |Set the expiration for a key as a UNIX timestamp specified in milliseconds (). Since Redis 2.6.0 pexpireat :: (RedisCtx m f) => ByteString -- ^ key -> Integer -- ^ millisecondsTimestamp -> m (f Bool) -pexpireat key millisecondsTimestamp = sendRequest (["PEXPIREAT"] ++ [encode key] ++ [encode millisecondsTimestamp] ) +pexpireat key millisecondsTimestamp = sendRequest ["PEXPIREAT", key, encode millisecondsTimestamp] +-- | Trim a list to the specified range (). +-- Since Redis 1.0.0 ltrim :: (RedisCtx m f) => ByteString -- ^ key -> Integer -- ^ start -> Integer -- ^ stop -> m (f Status) -ltrim key start stop = sendRequest (["LTRIM"] ++ [encode key] ++ [encode start] ++ [encode stop] ) +ltrim key start stop = sendRequest ["LTRIM", key, encode start, encode stop] +-- | /O(1)/ +-- Get the number of members in a sorted set (). +-- Since Redis 1.2.0 zcard :: (RedisCtx m f) => ByteString -- ^ key -> m (f Integer) -zcard key = sendRequest (["ZCARD"] ++ [encode key] ) +zcard key = sendRequest ["ZCARD", key] +-- | Set the value of an element in a list by its index (). +-- Since Redis 1.0.0 lset :: (RedisCtx m f) => ByteString -- ^ key -> Integer -- ^ index -> ByteString -- ^ value -> m (f Status) -lset key index value = sendRequest (["LSET"] ++ [encode key] ++ [encode index] ++ [encode value] ) +lset key index value = sendRequest ["LSET", key, encode index, value] +-- | Set the expiration for a key as a UNIX timestamp (). +-- Since Redis 1.2.0 expireat :: (RedisCtx m f) => ByteString -- ^ key -> Integer -- ^ timestamp -> m (f Bool) -expireat key timestamp = sendRequest (["EXPIREAT"] ++ [encode key] ++ [encode timestamp] ) +expireat key timestamp = sendRequest ["EXPIREAT", key, encode timestamp] +-- | Synchronously save the dataset to disk (). +-- Since Redis 1.0.0 save :: (RedisCtx m f) => m (f Status) -save = sendRequest (["SAVE"] ) +save = sendRequest ["SAVE"] +-- | +-- Move a key to another database (). +-- Since Redis 1.0.0 move :: (RedisCtx m f) => ByteString -- ^ key -> Integer -- ^ db -> m (f Bool) -move key db = sendRequest (["MOVE"] ++ [encode key] ++ [encode db] ) +move key db = sendRequest ["MOVE", key, encode db] +-- | +-- Returns the bit value at offset in the string value stored at key (). Since Redis 2.2.0 getbit :: (RedisCtx m f) - => ByteString -- ^ key - -> Integer -- ^ offset + => ByteString -- ^ Key. + -> Integer -- ^ Offset. -> m (f Integer) -getbit key offset = sendRequest (["GETBIT"] ++ [encode key] ++ [encode offset] ) +getbit key offset = sendRequest ["GETBIT", key, encode offset] +-- |Set multiple keys to multiple values, only if none of the keys exist (). +-- Since Redis 1.0.1 msetnx :: (RedisCtx m f) - => [(ByteString,ByteString)] -- ^ keyValue + => NonEmpty (ByteString,ByteString) -- ^ keyValue -> m (f Bool) -msetnx keyValue = sendRequest (["MSETNX"] ++ concatMap (\(x,y) -> [encode x,encode y])keyValue ) +msetnx ((key,value):|keysValues) = + sendRequest ("MSETNX":key:value:concatMap (\(x,y) -> [encode x,encode y]) keysValues) +-- |Get array of specific Redis command details (). +-- Since Redis 2.8.13 commandInfo :: (RedisCtx m f) => [ByteString] -- ^ commandName -> m (f [ByteString]) -commandInfo commandName = sendRequest (["COMMAND","INFO"] ++ map encode commandName ) +commandInfo commandName = sendRequest ("COMMAND":"INFO":map encode commandName ) +-- | Close the connection (). Since Redis 1.0.0 quit :: (RedisCtx m f) => m (f Status) -quit = sendRequest (["QUIT"] ) +quit = sendRequest ["QUIT"] +-- |Remove and get the first element in a list, or block until one is available (). Since Redis 2.0.0 blpop :: (RedisCtx m f) => [ByteString] -- ^ key -> Integer -- ^ timeout -> m (f (Maybe (ByteString,ByteString))) -blpop key timeout = sendRequest (["BLPOP"] ++ map encode key ++ [encode timeout] ) +blpop keys_ timeout = sendRequest ("BLPOP":keys_ ++ [encode timeout] ) + +-- |Remove and get the first element in a list, or block until one is available (). Since Redis 6.0.0 +blpopFloat + :: (RedisCtx m f) + => [ByteString] -- ^ key + -> Integer -- ^ timeout + -> m (f (Maybe (ByteString,ByteString))) +blpopFloat keys_ timeout = sendRequest ("BLPOP":keys_ ++ [encode timeout] ) -- | /O(N)/ where @N@ is the number of members to be removed. -- Remove one or more members from a set (). @@ -1151,20 +1505,23 @@ srem => ByteString -- ^ Key of the set. -> NonEmpty ByteString -- ^ List of members to be removed. -> m (f Integer) -srem key member = sendRequest (["SREM"] ++ [encode key] ++ NE.toList (fmap encode member)) +srem key (member:|members) = sendRequest ("SREM":key:member:members) +-- |Echo the given string (). Since Redis 1.0.0 echo :: (RedisCtx m f) => ByteString -- ^ message -> m (f ByteString) -echo message = sendRequest (["ECHO"] ++ [encode message] ) +echo message = sendRequest ["ECHO", encode message] +-- |Determine if a given value is a member of a set (). +-- Since Redis 1.0.0 sismember :: (RedisCtx m f) - => ByteString -- ^ key + => ByteString -- ^ Key. -> ByteString -- ^ member -> m (f Bool) -sismember key member = sendRequest (["SISMEMBER"] ++ [encode key] ++ [encode member] ) +sismember key member = sendRequest ["SISMEMBER",key, member] -- $autoclaim -- @@ -1192,3 +1549,4 @@ sismember key member = sendRequest (["SISMEMBER"] ++ [encode key] ++ [encode mem -- $auth -- Authenticate to the server (). Since Redis 1.0.0 + diff --git a/src/Database/Redis/ManualCommands.hs b/src/Database/Redis/ManualCommands.hs index a7ef63e0..37999cef 100644 --- a/src/Database/Redis/ManualCommands.hs +++ b/src/Database/Redis/ManualCommands.hs @@ -6,6 +6,8 @@ import Prelude hiding (min, max) import Data.ByteString (ByteString, empty, append) import qualified Data.ByteString.Char8 as Char8 import qualified Data.ByteString as BS +import Data.List.NonEmpty (NonEmpty(..)) +import qualified Data.List.NonEmpty as NE import Data.Maybe (maybeToList, catMaybes) #if __GLASGOW_HASKELL__ < 808 import Data.Semigroup ((<>)) @@ -18,25 +20,27 @@ import Database.Redis.Protocol import Database.Redis.Types import qualified Database.Redis.Cluster.Command as CMD - +-- |Inspect the internals of Redis objects (). The Redis command @OBJECT@ is split up into 'objectRefcount', 'objectEncoding', 'objectIdletime'. Since Redis 2.2.3 objectRefcount :: (RedisCtx m f) => ByteString -- ^ key -> m (f Integer) -objectRefcount key = sendRequest ["OBJECT", "refcount", encode key] +objectRefcount key = sendRequest ["OBJECT", "refcount", key] objectIdletime :: (RedisCtx m f) => ByteString -- ^ key -> m (f Integer) -objectIdletime key = sendRequest ["OBJECT", "idletime", encode key] +objectIdletime key = sendRequest ["OBJECT", "idletime", key] +-- |Inspect the internals of Redis objects (). The Redis command @OBJECT@ is split up into 'objectRefcount', 'objectEncoding', 'objectIdletime'. Since Redis 2.2.3 objectEncoding :: (RedisCtx m f) => ByteString -- ^ key -> m (f ByteString) -objectEncoding key = sendRequest ["OBJECT", "encoding", encode key] +objectEncoding key = sendRequest ["OBJECT", "encoding", key] +-- |Insert an element before or after another element in a list (). The Redis command @LINSERT@ is split up into 'linsertBefore', 'linsertAfter'. Since Redis 2.2.0 linsertBefore :: (RedisCtx m f) => ByteString -- ^ key @@ -44,8 +48,9 @@ linsertBefore -> ByteString -- ^ value -> m (f Integer) linsertBefore key pivot value = - sendRequest ["LINSERT", encode key, "BEFORE", encode pivot, encode value] + sendRequest ["LINSERT", key, "BEFORE", pivot, value] +-- |Insert an element before or after another element in a list (). The Redis command @LINSERT@ is split up into 'linsertBefore', 'linsertAfter'. Since Redis 2.2.0 linsertAfter :: (RedisCtx m f) => ByteString -- ^ key @@ -55,11 +60,12 @@ linsertAfter linsertAfter key pivot value = sendRequest ["LINSERT", encode key, "AFTER", encode pivot, encode value] +-- |Determine the type stored at key (). Since Redis 1.0.0 getType :: (RedisCtx m f) => ByteString -- ^ key -> m (f RedisType) -getType key = sendRequest ["TYPE", encode key] +getType key = sendRequest ["TYPE", key] -- |A single entry from the slowlog. data Slowlog = Slowlog @@ -106,6 +112,7 @@ slowlogLen = sendRequest ["SLOWLOG", "LEN"] slowlogReset :: (RedisCtx m f) => m (f Status) slowlogReset = sendRequest ["SLOWLOG", "RESET"] +-- |Return a range of members in a sorted set, by index (). The Redis command @ZRANGE@ is split up into 'zrange', 'zrangeWithscores'. Since Redis 1.2.0 zrange :: (RedisCtx m f) => ByteString -- ^ key @@ -115,6 +122,7 @@ zrange zrange key start stop = sendRequest ["ZRANGE", encode key, encode start, encode stop] +-- |Return a range of members in a sorted set, by index (). The Redis command @ZRANGE@ is split up into 'zrange', 'zrangeWithscores'. Since Redis 1.2.0 zrangeWithscores :: (RedisCtx m f) => ByteString -- ^ key @@ -261,6 +269,7 @@ defaultSortOpts = SortOpts data SortOrder = Asc | Desc deriving (Show, Eq) +-- |Sort the elements in a list, set or sorted set (). The Redis command @SORT@ is split up into 'sort', 'sortStore'. Since Redis 1.0.0 sortStore :: (RedisCtx m f) => ByteString -- ^ key @@ -269,6 +278,7 @@ sortStore -> m (f Integer) sortStore key dest = sortInternal key (Just dest) +-- |Sort the elements in a list, set or sorted set (). The Redis command @SORT@ is split up into 'sort', 'sortStore'. Since Redis 1.0.0 sort :: (RedisCtx m f) => ByteString -- ^ key @@ -314,23 +324,25 @@ zunionstoreWeights dest kws = let (keys,weights) = unzip kws in zstoreInternal "ZUNIONSTORE" dest keys weights +-- |Intersect multiple sorted sets and store the resulting sorted set in a new key (). The Redis command @ZINTERSTORE@ is split up into 'zinterstore', 'zinterstoreWeights'. Since Redis 2.0.0 zinterstore :: (RedisCtx m f) => ByteString -- ^ destination - -> [ByteString] -- ^ keys + -> NonEmpty ByteString -- ^ keys -> Aggregate -> m (f Integer) -zinterstore dest keys = - zstoreInternal "ZINTERSTORE" dest keys [] +zinterstore dest (key_:|keys_) = + zstoreInternal "ZINTERSTORE" dest (key_:keys_) [] +-- |Intersect multiple sorted sets and store the resulting sorted set in a new key (). The Redis command @ZINTERSTORE@ is split up into 'zinterstore', 'zinterstoreWeights'. Since Redis 2.0.0 zinterstoreWeights :: (RedisCtx m f) => ByteString -- ^ destination - -> [(ByteString,Double)] -- ^ weighted keys + -> NonEmpty (ByteString,Double) -- ^ weighted keys -> Aggregate -> m (f Integer) zinterstoreWeights dest kws = - let (keys,weights) = unzip kws + let (keys,weights) = unzip (NE.toList kws) in zstoreInternal "ZINTERSTORE" dest keys weights zstoreInternal @@ -342,7 +354,7 @@ zstoreInternal -> Aggregate -> m (f Integer) zstoreInternal cmd dest keys weights aggregate = sendRequest $ - concat [ [cmd, dest, encode . toInteger $ length keys], keys + concat [ [cmd, dest, encode . toInteger $ length keys ], keys , if null weights then [] else "WEIGHTS" : map encode weights , ["AGGREGATE", aggregate'] ] @@ -352,6 +364,7 @@ zstoreInternal cmd dest keys weights aggregate = sendRequest $ Min -> "MIN" Max -> "MAX" +-- |Execute a Lua script server side (). Since Redis 2.6.0 eval :: (RedisCtx m f, RedisResult a) => ByteString -- ^ script @@ -426,10 +439,7 @@ bitop -> m (f Integer) bitop op ks = sendRequest $ "BITOP" : op : ks --- setRange --- :: --- setRange = sendRequest (["SET"] ++ [encode key] ++ [encode value] ++ ) - +-- |Atomically transfer a key from a Redis instance to another one (). The Redis command @MIGRATE@ is split up into 'migrate', 'migrateMultiple'. Since Redis 2.6.0 migrate :: (RedisCtx m f) => ByteString -- ^ host @@ -441,11 +451,16 @@ migrate migrate host port key destinationDb timeout = sendRequest ["MIGRATE", host, port, key, encode destinationDb, encode timeout] +data MigrateAuth + = MigrateAuth ByteString + | MigrateAuth2 ByteString ByteString + deriving (Show, Eq) -- |Options for the 'migrate' command. data MigrateOpts = MigrateOpts { migrateCopy :: Bool , migrateReplace :: Bool + , migrateAuth :: Maybe MigrateAuth } deriving (Show, Eq) -- |Redis default 'MigrateOpts'. Equivalent to omitting all optional parameters. @@ -454,6 +469,7 @@ data MigrateOpts = MigrateOpts -- MigrateOpts -- { migrateCopy = False -- remove the key from the local instance -- , migrateReplace = False -- don't replace existing key on the remote instance +-- , migrateAuth = Nothing -- } -- @ -- @@ -461,8 +477,10 @@ defaultMigrateOpts :: MigrateOpts defaultMigrateOpts = MigrateOpts { migrateCopy = False , migrateReplace = False + , migrateAuth = Nothing } +-- |Atomically transfer a key from a Redis instance to another one (). The Redis command @MIGRATE@ is split up into 'migrate', 'migrateMultiple'. Since Redis 2.6.0 migrateMultiple :: (RedisCtx m f) => ByteString -- ^ host @@ -475,12 +493,17 @@ migrateMultiple migrateMultiple host port destinationDb timeout MigrateOpts{..} keys = sendRequest $ concat [["MIGRATE", host, port, empty, encode destinationDb, encode timeout], - copy, replace, keys] + auth_, copy, replace, keys] where copy = ["COPY" | migrateCopy] replace = ["REPLACE" | migrateReplace] + auth_ = case migrateAuth of + Nothing -> [] + Just (MigrateAuth pass) -> ["AUTH", pass] + Just (MigrateAuth2 user pass) -> ["AUTH2", user, pass] +-- |Create a key using the provided serialized value, previously obtained using DUMP (). The Redis command @RESTORE@ is split up into 'restore', 'restoreReplace'. Since Redis 2.6.0 restore :: (RedisCtx m f) => ByteString -- ^ key @@ -490,6 +513,30 @@ restore restore key timeToLive serializedValue = sendRequest ["RESTORE", key, encode timeToLive, serializedValue] +data RestoreOpts = RestoreOpts + { restoreOptsReplace :: Bool + , restoreOptsAbsTTL :: Bool + , restoreOptsIdle :: Maybe Integer + , restoreOptsFreq :: Maybe Integer + } + +-- |Create a key using the provided serialized value, previously obtained using DUMP (). The Redis command @RESTORE@ is split up into 'restore', 'restoreReplace'. Since Redis 2.6.0 +restoreOpts + :: (RedisCtx m f) + => ByteString -- ^ key + -> Integer -- ^ timeToLive + -> ByteString -- ^ serializedValue + -> RestoreOpts -- ^ restore options + -> m (f Status) +restoreOpts key timeToLive serializedValue RestoreOpts{..} = + sendRequest ("RESTORE": key: encode timeToLive: serializedValue:rest) where + rest = replace <> absttl <> idle <> freq + replace = ["REPLACE" | restoreOptsReplace] + absttl = ["ABSTTL" | restoreOptsAbsTTL] + idle = maybe [] (\i -> ["IDLE", encode i]) restoreOptsIdle + freq = maybe [] (\f -> ["FREQ", encode f]) restoreOptsFreq + +-- |Create a key using the provided serialized value, previously obtained using DUMP (). The Redis command @RESTORE@ is split up into 'restore', 'restoreReplace'. Since Redis 2.6.0 restoreReplace :: (RedisCtx m f) @@ -581,7 +628,7 @@ instance RedisArg DebugMode where encode Sync = "SYNC" encode No = "NO" - +-- |Set the debug mode for executed scripts (). Since Redis 3.2.0 scriptDebug :: (RedisCtx m f) => DebugMode @@ -589,7 +636,7 @@ scriptDebug scriptDebug mode = sendRequest ["SCRIPT DEBUG", encode mode] - +-- |Add one or more members to a sorted set, or update its score if it already exists (). The Redis command @ZADD@ is split up into 'zadd', 'zaddOpts'. Since Redis 1.2.0 zadd :: (RedisCtx m f) => ByteString -- ^ key @@ -608,6 +655,7 @@ instance RedisArg SizeCondition where encode CGT = "GT" encode CLT = "LT" +-- |Add one or more members to a sorted set, or update its score if it already exists (). The Redis command @ZADD@ is split up into 'zadd', 'zaddOpts'. Since Redis 1.2.0 data ZaddOpts = ZaddOpts { zaddCondition :: Maybe Condition -- ^ Add on condition , zaddSizeCondition :: Maybe SizeCondition @@ -663,7 +711,7 @@ instance RedisArg ReplyMode where encode Off = "OFF" encode Skip = "SKIP" - +-- |Instruct the server whether to reply to commands (). Since Redis 3.2 clientReply :: (RedisCtx m f) => ReplyMode @@ -671,7 +719,7 @@ clientReply clientReply mode = sendRequest ["CLIENT REPLY", encode mode] - +-- |Get one or multiple random members from a set (). The Redis command @SRANDMEMBER@ is split up into 'srandmember', 'srandmemberN'. Since Redis 1.0.0 srandmember :: (RedisCtx m f) => ByteString -- ^ key @@ -679,6 +727,7 @@ srandmember srandmember key = sendRequest ["SRANDMEMBER", key] +-- |Get one or multiple random members from a set (). The Redis command @SRANDMEMBER@ is split up into 'srandmember', 'srandmemberN'. Since Redis 1.0.0 srandmemberN :: (RedisCtx m f) => ByteString -- ^ key @@ -686,14 +735,14 @@ srandmemberN -> m (f [ByteString]) srandmemberN key count = sendRequest ["SRANDMEMBER", key, encode count] - +-- |Remove and return one or multiple random members from a set (). The Redis command @SPOP@ is split up into 'spop', 'spopN'. Since Redis 1.0.0 spop :: (RedisCtx m f) => ByteString -- ^ key -> m (f (Maybe ByteString)) spop key = sendRequest ["SPOP", key] - +-- |Remove and return one or multiple random members from a set (). The Redis command @SPOP@ is split up into 'spop', 'spopN'. Since Redis 1.0.0 spopN :: (RedisCtx m f) => ByteString -- ^ key @@ -714,7 +763,7 @@ infoSection -> m (f ByteString) infoSection section = sendRequest ["INFO", section] - +-- |Determine if a key exists (). Since Redis 1.0.0 exists :: (RedisCtx m f) => ByteString -- ^ key @@ -736,12 +785,12 @@ instance RedisResult Cursor where cursor0 :: Cursor cursor0 = Cursor "0" - +-- |Incrementally iterate the keys space (). The Redis command @SCAN@ is split up into 'scan', 'scanOpts'. Since Redis 2.8.0 scan :: (RedisCtx m f) => Cursor -> m (f (Cursor, [ByteString])) -- ^ next cursor and values -scan cursor = scanOpts cursor defaultScanOpts +scan cursor = scanOpts cursor defaultScanOpts Nothing data ScanOpts = ScanOpts @@ -765,13 +814,15 @@ defaultScanOpts = ScanOpts , scanCount = Nothing } - +-- | Incrementally iterate the keys space (). The Redis command @SCAN@ is split up into 'scan', 'scanOpts'. Since Redis 2.8.0 scanOpts :: (RedisCtx m f) => Cursor -> ScanOpts + -> Maybe ByteString -- ^ types of the object to scan -> m (f (Cursor, [ByteString])) -- ^ next cursor and values -scanOpts cursor opts = sendRequest $ addScanOpts ["SCAN", encode cursor] opts +scanOpts cursor opts mtype_ = sendRequest $ addScanOpts ["SCAN", encode cursor] opts + ++ maybe [] (\type_ -> ["TYPE", type_]) mtype_ addScanOpts @@ -785,6 +836,7 @@ addScanOpts cmd ScanOpts{..} = match = maybe [] (prepend "MATCH") scanMatch count = maybe [] ((prepend "COUNT").encode) scanCount +-- |Incrementally iterate Set elements (). The Redis command @SSCAN@ is split up into 'sscan', 'sscanOpts'. Since Redis 2.8.0 sscan :: (RedisCtx m f) => ByteString -- ^ key @@ -792,7 +844,7 @@ sscan -> m (f (Cursor, [ByteString])) -- ^ next cursor and values sscan key cursor = sscanOpts key cursor defaultScanOpts - +-- |Incrementally iterate Set elements (). The Redis command @SSCAN@ is split up into 'sscan', 'sscanOpts'. Since Redis 2.8.0 sscanOpts :: (RedisCtx m f) => ByteString -- ^ key @@ -801,7 +853,7 @@ sscanOpts -> m (f (Cursor, [ByteString])) -- ^ next cursor and values sscanOpts key cursor opts = sendRequest $ addScanOpts ["SSCAN", key, encode cursor] opts - +-- |Incrementally iterate hash fields and associated values (). The Redis command @HSCAN@ is split up into 'hscan', 'hscanOpts'. Since Redis 2.8.0 hscan :: (RedisCtx m f) => ByteString -- ^ key @@ -809,7 +861,7 @@ hscan -> m (f (Cursor, [(ByteString, ByteString)])) -- ^ next cursor and values hscan key cursor = hscanOpts key cursor defaultScanOpts - +-- |Incrementally iterate hash fields and associated values (). The Redis command @HSCAN@ is split up into 'hscan', 'hscanOpts'. Since Redis 2.8.0 hscanOpts :: (RedisCtx m f) => ByteString -- ^ key @@ -843,6 +895,7 @@ instance RedisArg a => RedisArg (RangeLex a) where encode Minr = "-" encode Maxr = "+" +-- |Return a range of members in a sorted set, by lexicographical range (). Since Redis 2.8.9 zrangebylex::(RedisCtx m f) => ByteString -- ^ key -> RangeLex ByteString -- ^ min @@ -1703,26 +1756,32 @@ instance RedisResult XInfoStreamResponse where , ..} decodeRedis7 a = Left a +-- | Get info about a stream. The Redis command @XINFO@ is split into 'xinfoConsumers', 'xinfoGroups', and 'xinfoStream'. +-- Since Redis 5.0.0 xinfoStream :: (RedisCtx m f) => ByteString -- ^ stream -> m (f XInfoStreamResponse) xinfoStream stream = sendRequest ["XINFO", "STREAM", stream] +-- | Delete messages from a stream. +-- Since Redis 5.0.0 xdel :: (RedisCtx m f) => ByteString -- ^ stream - -> [ByteString] -- ^ message IDs + -> NonEmpty ByteString -- ^ message IDs -> m (f Integer) -xdel stream messageIds = sendRequest $ ["XDEL", stream] ++ messageIds +xdel stream (messageId:|messageIds) = sendRequest ("XDEL":stream:messageId: messageIds) +-- |Set the upper bound for number of messages in a stream. Since Redis 5.0.0 xtrim :: (RedisCtx m f) => ByteString -- ^ stream -> TrimOpts -> m (f Integer) -xtrim stream opts = sendRequest $ ["XTRIM", stream] ++ internalTrimArgToList opts +xtrim stream opts = sendRequest ("XTRIM":stream:internalTrimArgToList opts) +-- |Constructor for `inf` Redis argument values inf :: RealFloat a => a inf = 1 / 0 @@ -1768,14 +1827,14 @@ authOpts authOpts password AuthOpts{..} = sendRequest $ ["AUTH"] <> maybe [] (:[]) authOptsUsername <> [password] --- the select command. used in 'connect'. +-- |Change the selected database for the current connection (). Since Redis 1.0.0 select :: RedisCtx m f => Integer -- ^ index -> m (f Status) select ix = sendRequest ["SELECT", encode ix] --- the ping command. used in 'checkedconnect'. +-- |Ping the server (). Since Redis 1.0.0 ping :: (RedisCtx m f) => m (f Status) @@ -1940,3 +1999,86 @@ clusterGetKeysInSlot slot count = sendRequest ["CLUSTER", "GETKEYSINSLOT", (enco command :: (RedisCtx m f) => m (f [CMD.CommandInfo]) command = sendRequest ["COMMAND"] + +data ExpireOpts + = ExpireOptsTime Condition + | ExpireOptsValue SizeCondition + +instance RedisArg ExpireOpts where + encode (ExpireOptsTime c) = encode c + encode (ExpireOptsValue c) = encode c + +-- |Set the expiration for a key as a UNIX timestamp specified in milliseconds (). +-- Since Redis 7.0 +pexpireatOpts + :: (RedisCtx m f) + => ByteString -- ^ key + -> Integer -- ^ millisecondsTimestamp + -> ExpireOpts + -> m (f Bool) +pexpireatOpts key millisecondsTimestamp opts = + sendRequest ["PEXPIREAT", key, encode millisecondsTimestamp, encode opts] + +expireOpts + :: (RedisCtx m f) + => ByteString -- ^ key + -> Integer -- ^ seconds + -> ExpireOpts + -> m (f Bool) +expireOpts key seconds opts = sendRequest ["EXPIRE", key, encode seconds, encode opts] + +-- | Set the expiration for a key as a UNIX timestamp (). +-- Since Redis 1.2.0 +expireatOpts + :: (RedisCtx m f) + => ByteString -- ^ key + -> Integer -- ^ timestamp + -> ExpireOpts + -> m (f Bool) +expireatOpts key timestamp opts = sendRequest ["EXPIREAT", key, encode timestamp, encode opts] + +data FlushOpts + = FlushOptsSync + | FlushOptsAsync + +instance RedisArg FlushOpts where + encode FlushOptsSync = "SYNC" + encode FlushOptsAsync = "ASYNC" + +-- |Remove all keys from the current database (). +-- Since Redis 6.2 +flushdbOpts + :: (RedisCtx m f) + => FlushOpts + -> m (f Status) +flushdbOpts opts = sendRequest ["FLUSHDB", encode opts] + +-- |Remove all keys from the current database (). +-- Since Redis 6.2 +flushallOpts + :: (RedisCtx m f) + => FlushOpts + -> m (f Status) +flushallOpts opts = sendRequest ["FLUSHALL", encode opts] + +data BitposType = Byte | Bit + +instance RedisArg BitposType where + encode Byte = "BYTE" + encode Bit = "BIT" + +data BitposOpts + = BitposOptsStart Integer + | BitposOptsStartEnd Integer Integer (Maybe BitposType) + +bitposOpts + :: (RedisCtx m f) + => ByteString + -> Integer + -> BitposOpts + -> m (f Integer) +bitposOpts key_ bit opts = sendRequest ("BITPOS": key_:encode bit: rest) where + rest = case opts of + BitposOptsStart s -> [encode s] + BitposOptsStartEnd start end bits -> + [encode start, encode end] ++ [ encode bits_ | Just bits_ <- pure bits] diff --git a/src/Database/Redis/Types.hs b/src/Database/Redis/Types.hs index 989e4d68..b33ba067 100644 --- a/src/Database/Redis/Types.hs +++ b/src/Database/Redis/Types.hs @@ -11,6 +11,7 @@ module Database.Redis.Types where #if __GLASGOW_HASKELL__ < 710 import Control.Applicative #endif +import Data.Int import Control.DeepSeq import Data.ByteString.Char8 (ByteString, pack) import qualified Data.ByteString.Lex.Fractional as F (readSigned, readExponential) @@ -38,6 +39,9 @@ instance RedisArg ByteString where instance RedisArg Integer where encode = pack . show +instance RedisArg Int64 where + encode = pack . show + instance RedisArg Double where encode a | isInfinite a && a > 0 = "+inf" @@ -68,6 +72,11 @@ instance RedisResult Integer where decode r = maybe (Left r) (Right . fst) . I.readSigned I.readDecimal =<< decode r +instance RedisResult Int64 where + decode (Integer n) = Right (fromInteger n) + decode r = + maybe (Left r) (Right . fst) . I.readSigned I.readDecimal =<< decode r + instance RedisResult Double where decode r = maybe (Left r) (Right . fst) . F.readSigned F.readExponential =<< decode r diff --git a/test/ClusterMain.hs b/test/ClusterMain.hs index 3854f42c..9770a24c 100644 --- a/test/ClusterMain.hs +++ b/test/ClusterMain.hs @@ -1,9 +1,12 @@ {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE OverloadedLists #-} +{-# LANGUAGE TypeApplications #-} module Main (main) where import qualified Test.Framework as Test +import Data.ByteString (ByteString) import Database.Redis import Tests @@ -18,7 +21,7 @@ main = do Test.defaultMain (tests conn) tests :: Connection -> [Test.Test] -tests conn = map ($conn) $ concat +tests conn = map ($conn) $ concat @[] [ testsMisc, testsKeys, testsStrings, [testHashes], testsLists, testsSets, [testHyperLogLog] , testsZSets, [testTransaction], [testScripting] , testsConnection, testsClient, testsServer, [testSScan, testHScan, testZScan], [testZrangelex] @@ -43,7 +46,7 @@ testsKeys = [ testKeys, testExpireAt, testSortCluster, testGetType, testObject ] testSortCluster :: Test testSortCluster = testCase "sort" $ do - lpush "{same}ids" ["1","2","3"] >>=? 3 + lpush "{same}ids" ["1"::ByteString,"2","3"] >>=? 3 sort "{same}ids" defaultSortOpts >>=? ["1","2","3"] sortStore "{same}ids" "{same}anotherKey" defaultSortOpts >>=? 3 let opts = defaultSortOpts { sortOrder = Desc, sortAlpha = True diff --git a/test/Tests.hs b/test/Tests.hs index 914688f7..f1e69e96 100644 --- a/test/Tests.hs +++ b/test/Tests.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE CPP, OverloadedStrings, RecordWildCards, LambdaCase #-} +{-# LANGUAGE CPP, OverloadedStrings, RecordWildCards, LambdaCase, OverloadedLists, TypeApplications #-} module Tests where @@ -11,6 +11,7 @@ import Control.Exception (try) import Control.Concurrent import Control.Monad import Control.Monad.Trans +import Data.ByteString (ByteString) import Data.Either (isRight) import qualified Data.List as L import qualified Data.List.NonEmpty as NE @@ -139,11 +140,11 @@ testKeys = testCase "keys" $ do ttl "{same}key" >>= \case Left _ -> error "error" Right t -> do - assert $ t `elem` [0..1] + assert $ elem @[] t [0..1] pttl "{same}key" >>= \case Left _ -> error "error" Right pt -> do - assert $ pt `elem` [990..1000] + assert $ elem @[] pt [990..1000] persist "{same}key" >>=? True dump "{same}key" >>= \case Left _ -> error "impossible" @@ -196,15 +197,15 @@ testSort = testCase "sort" $ do testGetType :: Test testGetType = testCase "getType" $ do getType "key" >>=? None - forM_ ts $ \(setKey, typ) -> do + forM_ @[] ts $ \(setKey, typ) -> do setKey getType "key" >>=? typ del (NE.fromList ["key"]) >>=? 1 where ts = [ (set "key" "value" >>=? Ok, String) - , (hset "key" "field" "value" >>=? 1, Hash) + , (hset "key" [("field"::ByteString, "value"::ByteString)] >>=? 1, Hash) , (lpush "key" ["value"] >>=? 1, List) - , (sadd "key" (NE.fromList ["member"]) >>=? 1, Set) + , (sadd "key" ["member"] >>=? 1, Set) , (zadd "key" [(42,"member"),(12.3,"value")] >>=? 2, ZSet) ] @@ -261,9 +262,9 @@ testBitops = testCase "bitops" $ do -- testHashes :: Test testHashes = testCase "hashes" $ do - hset "key" "field" "another" >>=? 1 - hset "key" "field" "another" >>=? 0 - hset "key" "field" "value" >>=? 0 + hset "key" [("field"::ByteString, "another"::ByteString)] >>=? 1 + hset "key" [("field"::ByteString, "another"::ByteString)] >>=? 0 + hset "key" [("field"::ByteString, "value"::ByteString)] >>=? 0 hsetnx "key" "field" "value" >>=? False hexists "key" "field" >>=? True hlen "key" >>=? 1 @@ -286,8 +287,8 @@ testsLists = testLists :: Test testLists = testCase "lists" $ do - lpushx "notAKey" "-" >>=? 0 - rpushx "notAKey" "-" >>=? 0 + lpushx "notAKey" ["-" :: ByteString] >>=? 0 + rpushx "notAKey" ["-" :: ByteString] >>=? 0 lpush "key" ["value"] >>=? 1 lpop "key" >>=? Just "value" rpush "key" ["value"] >>=? 1 @@ -373,10 +374,15 @@ testZSets = testCase "sorted sets" $ do zrevrangebyscoreLimit "key" 2.5 0.5 0 1 >>=? ["v2"] zrevrangebyscoreWithscoresLimit "key" 2.5 0.5 0 1 >>=? [("v2",2)] - zrem "key" ["v2"] >>=? 1 + zrem "key" (NE.fromList ["v2"]) >>=? 1 zremrangebyscore "key" 10 100 >>=? 1 zremrangebyrank "key" 0 0 >>=? 1 +-- testZSets7 :: Test +-- testZSets7 = testCase "sorted sets: redis 7" $ do +-- zadd "key" [(2,"v1"),(0,"v2"),(40,"v3")] >>=? 3 +-- zrankWithScore "key" "v1" >>=? Just (1, 2) + testZStore :: Test testZStore = testCase "zunionstore/zinterstore" $ do zadd "{same}k1" [(1, "v1"), (2, "v2")] >>= \case @@ -664,7 +670,7 @@ testBgrewriteaof = testCase "bgrewriteaof/bgsave/save" $ do testConfig :: Test testConfig = testCase "config/auth" $ do - configGet "requirepass" >>=? [("requirepass", "")] + configGet ["requirepass"] >>=? [("requirepass", "")] configSet "requirepass" "pass" >>=? Ok auth "pass" >>=? Ok configSet "requirepass" "" >>=? Ok @@ -705,8 +711,8 @@ testScans :: Test testScans = testCase "scans" $ do set "key" "value" >>=? Ok scan cursor0 >>=? (cursor0, ["key"]) - scanOpts cursor0 sOpts1 >>=? (cursor0, ["key"]) - scanOpts cursor0 sOpts2 >>=? (cursor0, []) + scanOpts cursor0 sOpts1 Nothing >>=? (cursor0, ["key"]) + scanOpts cursor0 sOpts2 Nothing >>=? (cursor0, []) where sOpts1 = defaultScanOpts { scanMatch = Just "k*" } sOpts2 = defaultScanOpts { scanMatch = Just "not*"} @@ -717,8 +723,8 @@ testSScan = testCase "sscan" $ do testHScan :: Test testHScan = testCase "hscan" $ do - hset "hash" "k" "v" >>=? 1 - hscan "hash" cursor0 >>=? (cursor0, [("k", "v")]) + hset "hash" [("k"::ByteString, "v"::ByteString)] >>=? 1 + hscan "hash" cursor0 >>=? (cursor0, [("k", "v")]) testZScan :: Test testZScan = testCase "zscan" $ do