diff --git a/src/commands.def b/src/commands.def index 837e7b73e..54a5322a5 100644 --- a/src/commands.def +++ b/src/commands.def @@ -3335,6 +3335,7 @@ struct COMMAND_ARG HEXPIRE_Args[] = { {MAKE_ARG("key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("seconds",ARG_TYPE_INTEGER,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("condition",ARG_TYPE_ONEOF,-1,NULL,NULL,NULL,CMD_ARG_OPTIONAL,4,NULL),.subargs=HEXPIRE_condition_Subargs}, +{MAKE_ARG("fields",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("numfields",ARG_TYPE_INTEGER,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("field",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_MULTIPLE,0,NULL)}, }; @@ -3371,6 +3372,7 @@ struct COMMAND_ARG HEXPIREAT_Args[] = { {MAKE_ARG("key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("unix-time-seconds",ARG_TYPE_UNIX_TIME,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("condition",ARG_TYPE_ONEOF,-1,NULL,NULL,NULL,CMD_ARG_OPTIONAL,4,NULL),.subargs=HEXPIREAT_condition_Subargs}, +{MAKE_ARG("fields",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("numfields",ARG_TYPE_INTEGER,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("field",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_MULTIPLE,0,NULL)}, }; @@ -3398,6 +3400,7 @@ keySpec HEXPIRETIME_Keyspecs[1] = { struct COMMAND_ARG HEXPIRETIME_Args[] = { {MAKE_ARG("key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("numfields",ARG_TYPE_INTEGER,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, +{MAKE_ARG("fields",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("field",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_MULTIPLE,0,NULL)}, }; @@ -3678,6 +3681,7 @@ keySpec HPERSIST_Keyspecs[1] = { /* HPERSIST argument table */ struct COMMAND_ARG HPERSIST_Args[] = { {MAKE_ARG("key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, +{MAKE_ARG("fields",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("numfields",ARG_TYPE_INTEGER,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("field",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_MULTIPLE,0,NULL)}, }; @@ -3714,6 +3718,7 @@ struct COMMAND_ARG HPEXPIRE_Args[] = { {MAKE_ARG("key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("milliseconds",ARG_TYPE_INTEGER,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("condition",ARG_TYPE_ONEOF,-1,NULL,NULL,NULL,CMD_ARG_OPTIONAL,4,NULL),.subargs=HPEXPIRE_condition_Subargs}, +{MAKE_ARG("fields",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("numfields",ARG_TYPE_INTEGER,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("field",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_MULTIPLE,0,NULL)}, }; @@ -3750,6 +3755,7 @@ struct COMMAND_ARG HPEXPIREAT_Args[] = { {MAKE_ARG("key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("unix-time-milliseconds",ARG_TYPE_UNIX_TIME,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("condition",ARG_TYPE_ONEOF,-1,NULL,NULL,NULL,CMD_ARG_OPTIONAL,4,NULL),.subargs=HPEXPIREAT_condition_Subargs}, +{MAKE_ARG("fields",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("numfields",ARG_TYPE_INTEGER,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("field",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_MULTIPLE,0,NULL)}, }; @@ -3777,6 +3783,7 @@ keySpec HPEXPIRETIME_Keyspecs[1] = { struct COMMAND_ARG HPEXPIRETIME_Args[] = { {MAKE_ARG("key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("numfields",ARG_TYPE_INTEGER,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, +{MAKE_ARG("fields",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("field",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_MULTIPLE,0,NULL)}, }; @@ -3802,6 +3809,7 @@ keySpec HPTTL_Keyspecs[1] = { /* HPTTL argument table */ struct COMMAND_ARG HPTTL_Args[] = { {MAKE_ARG("key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, +{MAKE_ARG("fields",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("numfields",ARG_TYPE_INTEGER,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("field",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_MULTIPLE,0,NULL)}, }; @@ -4042,6 +4050,7 @@ keySpec HTTL_Keyspecs[1] = { /* HTTL argument table */ struct COMMAND_ARG HTTL_Args[] = { {MAKE_ARG("key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, +{MAKE_ARG("fields",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("numfields",ARG_TYPE_INTEGER,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, {MAKE_ARG("field",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_MULTIPLE,0,NULL)}, }; @@ -11097,30 +11106,30 @@ struct COMMAND_STRUCT redisCommandTable[] = { /* hash */ {MAKE_CMD("hdel","Deletes one or more fields and their values from a hash. Deletes the hash if no fields remain.","O(N) where N is the number of fields to be removed.","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HDEL_History,1,HDEL_Tips,0,hdelCommand,-3,CMD_WRITE|CMD_FAST,ACL_CATEGORY_HASH,HDEL_Keyspecs,1,NULL,2),.args=HDEL_Args}, {MAKE_CMD("hexists","Determines whether a field exists in a hash.","O(1)","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HEXISTS_History,0,HEXISTS_Tips,0,hexistsCommand,3,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HEXISTS_Keyspecs,1,NULL,2),.args=HEXISTS_Args}, -{MAKE_CMD("hexpire","Set expiry for hash field using relative time to expire (seconds)","O(N) where N is the number of arguments to the command","8.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HEXPIRE_History,0,HEXPIRE_Tips,0,hexpireCommand,-5,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HEXPIRE_Keyspecs,1,NULL,5),.args=HEXPIRE_Args}, -{MAKE_CMD("hexpireat","Set expiry for hash field using an absolute Unix timestamp (seconds)","O(N) where N is the number of arguments to the command","8.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HEXPIREAT_History,0,HEXPIREAT_Tips,0,hexpireatCommand,-5,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HEXPIREAT_Keyspecs,1,NULL,5),.args=HEXPIREAT_Args}, -{MAKE_CMD("hexpiretime","Returns the expiration time of a hash field as a Unix timestamp, in seconds.","O(N) where N is the number of arguments to the command","8.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HEXPIRETIME_History,0,HEXPIRETIME_Tips,0,hexpiretimeCommand,-4,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HEXPIRETIME_Keyspecs,1,NULL,3),.args=HEXPIRETIME_Args}, +{MAKE_CMD("hexpire","Set expiry for hash field using relative time to expire (seconds)","O(N) where N is the number of specified fields","7.4.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HEXPIRE_History,0,HEXPIRE_Tips,0,hexpireCommand,-6,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HEXPIRE_Keyspecs,1,NULL,6),.args=HEXPIRE_Args}, +{MAKE_CMD("hexpireat","Set expiry for hash field using an absolute Unix timestamp (seconds)","O(N) where N is the number of specified fields","7.4.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HEXPIREAT_History,0,HEXPIREAT_Tips,0,hexpireatCommand,-6,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HEXPIREAT_Keyspecs,1,NULL,6),.args=HEXPIREAT_Args}, +{MAKE_CMD("hexpiretime","Returns the expiration time of a hash field as a Unix timestamp, in seconds.","O(N) where N is the number of specified fields","7.4.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HEXPIRETIME_History,0,HEXPIRETIME_Tips,0,hexpiretimeCommand,-5,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HEXPIRETIME_Keyspecs,1,NULL,4),.args=HEXPIRETIME_Args}, {MAKE_CMD("hget","Returns the value of a field in a hash.","O(1)","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HGET_History,0,HGET_Tips,0,hgetCommand,3,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HGET_Keyspecs,1,NULL,2),.args=HGET_Args}, {MAKE_CMD("hgetall","Returns all fields and values in a hash.","O(N) where N is the size of the hash.","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HGETALL_History,0,HGETALL_Tips,1,hgetallCommand,2,CMD_READONLY,ACL_CATEGORY_HASH,HGETALL_Keyspecs,1,NULL,1),.args=HGETALL_Args}, -{MAKE_CMD("hgetf","For each specified field: get its value and optionally set the field's remaining time to live / UNIX expiration timestamp in seconds / milliseconds","O(N) where N is the number of arguments to the command","8.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HGETF_History,0,HGETF_Tips,0,hgetfCommand,-5,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HGETF_Keyspecs,1,NULL,6),.args=HGETF_Args}, +{MAKE_CMD("hgetf","For each specified field: get its value and optionally set the field's remaining time to live / UNIX expiration timestamp in seconds / milliseconds","O(N) where N is the number of specified fields","7.4.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HGETF_History,0,HGETF_Tips,0,hgetfCommand,-5,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HGETF_Keyspecs,1,NULL,6),.args=HGETF_Args}, {MAKE_CMD("hincrby","Increments the integer value of a field in a hash by a number. Uses 0 as initial value if the field doesn't exist.","O(1)","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HINCRBY_History,0,HINCRBY_Tips,0,hincrbyCommand,4,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HINCRBY_Keyspecs,1,NULL,3),.args=HINCRBY_Args}, {MAKE_CMD("hincrbyfloat","Increments the floating point value of a field by a number. Uses 0 as initial value if the field doesn't exist.","O(1)","2.6.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HINCRBYFLOAT_History,0,HINCRBYFLOAT_Tips,0,hincrbyfloatCommand,4,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HINCRBYFLOAT_Keyspecs,1,NULL,3),.args=HINCRBYFLOAT_Args}, {MAKE_CMD("hkeys","Returns all fields in a hash.","O(N) where N is the size of the hash.","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HKEYS_History,0,HKEYS_Tips,1,hkeysCommand,2,CMD_READONLY,ACL_CATEGORY_HASH,HKEYS_Keyspecs,1,NULL,1),.args=HKEYS_Args}, {MAKE_CMD("hlen","Returns the number of fields in a hash.","O(1)","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HLEN_History,0,HLEN_Tips,0,hlenCommand,2,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HLEN_Keyspecs,1,NULL,1),.args=HLEN_Args}, {MAKE_CMD("hmget","Returns the values of all fields in a hash.","O(N) where N is the number of fields being requested.","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HMGET_History,0,HMGET_Tips,0,hmgetCommand,-3,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HMGET_Keyspecs,1,NULL,2),.args=HMGET_Args}, {MAKE_CMD("hmset","Sets the values of multiple fields.","O(N) where N is the number of fields being set.","2.0.0",CMD_DOC_DEPRECATED,"`HSET` with multiple field-value pairs","4.0.0","hash",COMMAND_GROUP_HASH,HMSET_History,0,HMSET_Tips,0,hsetCommand,-4,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HMSET_Keyspecs,1,NULL,2),.args=HMSET_Args}, -{MAKE_CMD("hpersist","Removes the expiration time for each specified field","O(N) where N is the number of arguments to the command","8.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HPERSIST_History,0,HPERSIST_Tips,0,hpersistCommand,-4,CMD_WRITE|CMD_FAST,ACL_CATEGORY_HASH,HPERSIST_Keyspecs,1,NULL,3),.args=HPERSIST_Args}, -{MAKE_CMD("hpexpire","Set expiry for hash field using relative time to expire (milliseconds)","O(N) where N is the number of arguments to the command","8.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HPEXPIRE_History,0,HPEXPIRE_Tips,0,hpexpireCommand,-5,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HPEXPIRE_Keyspecs,1,NULL,5),.args=HPEXPIRE_Args}, -{MAKE_CMD("hpexpireat","Set expiry for hash field using an absolute Unix timestamp (milliseconds)","O(N) where N is the number of arguments to the command","8.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HPEXPIREAT_History,0,HPEXPIREAT_Tips,0,hpexpireatCommand,-5,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HPEXPIREAT_Keyspecs,1,NULL,5),.args=HPEXPIREAT_Args}, -{MAKE_CMD("hpexpiretime","Returns the expiration time of a hash field as a Unix timestamp, in msec.","O(N) where N is the number of arguments to the command","8.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HPEXPIRETIME_History,0,HPEXPIRETIME_Tips,0,hpexpiretimeCommand,-4,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HPEXPIRETIME_Keyspecs,1,NULL,3),.args=HPEXPIRETIME_Args}, -{MAKE_CMD("hpttl","Returns the TTL in milliseconds of a hash field.","O(N) where N is the number of arguments to the command","8.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HPTTL_History,0,HPTTL_Tips,0,hpttlCommand,-4,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HPTTL_Keyspecs,1,NULL,3),.args=HPTTL_Args}, +{MAKE_CMD("hpersist","Removes the expiration time for each specified field","O(N) where N is the number of specified fields","7.4.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HPERSIST_History,0,HPERSIST_Tips,0,hpersistCommand,-5,CMD_WRITE|CMD_FAST,ACL_CATEGORY_HASH,HPERSIST_Keyspecs,1,NULL,4),.args=HPERSIST_Args}, +{MAKE_CMD("hpexpire","Set expiry for hash field using relative time to expire (milliseconds)","O(N) where N is the number of specified fields","7.4.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HPEXPIRE_History,0,HPEXPIRE_Tips,0,hpexpireCommand,-6,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HPEXPIRE_Keyspecs,1,NULL,6),.args=HPEXPIRE_Args}, +{MAKE_CMD("hpexpireat","Set expiry for hash field using an absolute Unix timestamp (milliseconds)","O(N) where N is the number of specified fields","7.4.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HPEXPIREAT_History,0,HPEXPIREAT_Tips,0,hpexpireatCommand,-6,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HPEXPIREAT_Keyspecs,1,NULL,6),.args=HPEXPIREAT_Args}, +{MAKE_CMD("hpexpiretime","Returns the expiration time of a hash field as a Unix timestamp, in msec.","O(N) where N is the number of specified fields","7.4.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HPEXPIRETIME_History,0,HPEXPIRETIME_Tips,0,hpexpiretimeCommand,-5,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HPEXPIRETIME_Keyspecs,1,NULL,4),.args=HPEXPIRETIME_Args}, +{MAKE_CMD("hpttl","Returns the TTL in milliseconds of a hash field.","O(N) where N is the number of specified fields","7.4.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HPTTL_History,0,HPTTL_Tips,0,hpttlCommand,-5,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HPTTL_Keyspecs,1,NULL,4),.args=HPTTL_Args}, {MAKE_CMD("hrandfield","Returns one or more random fields from a hash.","O(N) where N is the number of fields returned","6.2.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HRANDFIELD_History,0,HRANDFIELD_Tips,1,hrandfieldCommand,-2,CMD_READONLY,ACL_CATEGORY_HASH,HRANDFIELD_Keyspecs,1,NULL,2),.args=HRANDFIELD_Args}, {MAKE_CMD("hscan","Iterates over fields and values of a hash.","O(1) for every call. O(N) for a complete iteration, including enough command calls for the cursor to return back to 0. N is the number of elements inside the collection.","2.8.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HSCAN_History,0,HSCAN_Tips,1,hscanCommand,-3,CMD_READONLY,ACL_CATEGORY_HASH,HSCAN_Keyspecs,1,NULL,5),.args=HSCAN_Args}, {MAKE_CMD("hset","Creates or modifies the value of a field in a hash.","O(1) for each field/value pair added, so O(N) to add N field/value pairs when the command is called with multiple field/value pairs.","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HSET_History,1,HSET_Tips,0,hsetCommand,-4,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HSET_Keyspecs,1,NULL,2),.args=HSET_Args}, -{MAKE_CMD("hsetf","For each specified field value pair: set field to value and optionally set the field's remaining time to live / UNIX expiration timestamp in seconds / milliseconds","O(N) where N is the number of arguments to the command","8.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HSETF_History,0,HSETF_Tips,0,hsetfCommand,-6,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HSETF_Keyspecs,1,NULL,9),.args=HSETF_Args}, +{MAKE_CMD("hsetf","For each specified field value pair: set field to value and optionally set the field's remaining time to live / UNIX expiration timestamp in seconds / milliseconds","O(N) where N is the number of specified fields","7.4.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HSETF_History,0,HSETF_Tips,0,hsetfCommand,-6,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HSETF_Keyspecs,1,NULL,9),.args=HSETF_Args}, {MAKE_CMD("hsetnx","Sets the value of a field in a hash only when the field doesn't exist.","O(1)","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HSETNX_History,0,HSETNX_Tips,0,hsetnxCommand,4,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HSETNX_Keyspecs,1,NULL,3),.args=HSETNX_Args}, {MAKE_CMD("hstrlen","Returns the length of the value of a field.","O(1)","3.2.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HSTRLEN_History,0,HSTRLEN_Tips,0,hstrlenCommand,3,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HSTRLEN_Keyspecs,1,NULL,2),.args=HSTRLEN_Args}, -{MAKE_CMD("httl","Returns the TTL in seconds of a hash field.","O(N) where N is the number of arguments to the command","8.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HTTL_History,0,HTTL_Tips,0,httlCommand,-4,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HTTL_Keyspecs,1,NULL,3),.args=HTTL_Args}, +{MAKE_CMD("httl","Returns the TTL in seconds of a hash field.","O(N) where N is the number of specified fields","7.4.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HTTL_History,0,HTTL_Tips,0,httlCommand,-5,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HTTL_Keyspecs,1,NULL,4),.args=HTTL_Args}, {MAKE_CMD("hvals","Returns all values in a hash.","O(N) where N is the size of the hash.","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HVALS_History,0,HVALS_Tips,1,hvalsCommand,2,CMD_READONLY,ACL_CATEGORY_HASH,HVALS_Keyspecs,1,NULL,1),.args=HVALS_Args}, /* hyperloglog */ {MAKE_CMD("pfadd","Adds elements to a HyperLogLog key. Creates the key if it doesn't exist.","O(1) to add every element.","2.8.9",CMD_DOC_NONE,NULL,NULL,"hyperloglog",COMMAND_GROUP_HYPERLOGLOG,PFADD_History,0,PFADD_Tips,0,pfaddCommand,-2,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HYPERLOGLOG,PFADD_Keyspecs,1,NULL,2),.args=PFADD_Args}, diff --git a/src/commands/hexpire.json b/src/commands/hexpire.json index 1fcdbc096..b12b53bd3 100644 --- a/src/commands/hexpire.json +++ b/src/commands/hexpire.json @@ -1,10 +1,10 @@ { "HEXPIRE": { "summary": "Set expiry for hash field using relative time to expire (seconds)", - "complexity": "O(N) where N is the number of arguments to the command", + "complexity": "O(N) where N is the number of specified fields", "group": "hash", - "since": "8.0.0", - "arity": -5, + "since": "7.4.0", + "arity": -6, "function": "hexpireCommand", "history": [], "command_flags": [ @@ -106,6 +106,10 @@ } ] }, + { + "name": "FIELDS", + "type": "string" + }, { "name": "numfields", "type": "integer" diff --git a/src/commands/hexpireat.json b/src/commands/hexpireat.json index 4e1c7f433..08a68a2f1 100644 --- a/src/commands/hexpireat.json +++ b/src/commands/hexpireat.json @@ -1,10 +1,10 @@ { "HEXPIREAT": { "summary": "Set expiry for hash field using an absolute Unix timestamp (seconds)", - "complexity": "O(N) where N is the number of arguments to the command", + "complexity": "O(N) where N is the number of specified fields", "group": "hash", - "since": "8.0.0", - "arity": -5, + "since": "7.4.0", + "arity": -6, "function": "hexpireatCommand", "history": [], "command_flags": [ @@ -106,6 +106,10 @@ } ] }, + { + "name": "FIELDS", + "type": "string" + }, { "name": "numfields", "type": "integer" diff --git a/src/commands/hexpiretime.json b/src/commands/hexpiretime.json index 74d13ed20..54492aff4 100644 --- a/src/commands/hexpiretime.json +++ b/src/commands/hexpiretime.json @@ -1,10 +1,10 @@ { "HEXPIRETIME": { "summary": "Returns the expiration time of a hash field as a Unix timestamp, in seconds.", - "complexity": "O(N) where N is the number of arguments to the command", + "complexity": "O(N) where N is the number of specified fields", "group": "hash", - "since": "8.0.0", - "arity": -4, + "since": "7.4.0", + "arity": -5, "function": "hexpiretimeCommand", "history": [], "command_flags": [ @@ -75,6 +75,10 @@ "name": "numfields", "type": "integer" }, + { + "name": "FIELDS", + "type": "string" + }, { "name": "field", "type": "string", diff --git a/src/commands/hgetf.json b/src/commands/hgetf.json index 398560ad5..9124da8a8 100644 --- a/src/commands/hgetf.json +++ b/src/commands/hgetf.json @@ -1,9 +1,9 @@ { "HGETF": { "summary": "For each specified field: get its value and optionally set the field's remaining time to live / UNIX expiration timestamp in seconds / milliseconds", - "complexity": "O(N) where N is the number of arguments to the command", + "complexity": "O(N) where N is the number of specified fields", "group": "hash", - "since": "8.0.0", + "since": "7.4.0", "arity": -5, "function": "hgetfCommand", "history": [], diff --git a/src/commands/hpersist.json b/src/commands/hpersist.json index 07b04408b..3b5ba6c55 100644 --- a/src/commands/hpersist.json +++ b/src/commands/hpersist.json @@ -1,10 +1,10 @@ { "HPERSIST": { "summary": "Removes the expiration time for each specified field", - "complexity": "O(N) where N is the number of arguments to the command", + "complexity": "O(N) where N is the number of specified fields", "group": "hash", - "since": "8.0.0", - "arity": -4, + "since": "7.4.0", + "arity": -5, "function": "hpersistCommand", "history": [], "command_flags": [ @@ -70,6 +70,10 @@ "type": "key", "key_spec_index": 0 }, + { + "name": "FIELDS", + "type": "string" + }, { "name": "numfields", "type": "integer" diff --git a/src/commands/hpexpire.json b/src/commands/hpexpire.json index 42a2dfb41..728b9b1ca 100644 --- a/src/commands/hpexpire.json +++ b/src/commands/hpexpire.json @@ -1,10 +1,10 @@ { "HPEXPIRE": { "summary": "Set expiry for hash field using relative time to expire (milliseconds)", - "complexity": "O(N) where N is the number of arguments to the command", + "complexity": "O(N) where N is the number of specified fields", "group": "hash", - "since": "8.0.0", - "arity": -5, + "since": "7.4.0", + "arity": -6, "function": "hpexpireCommand", "history": [], "command_flags": [ @@ -106,6 +106,10 @@ } ] }, + { + "name": "FIELDS", + "type": "string" + }, { "name": "numfields", "type": "integer" diff --git a/src/commands/hpexpireat.json b/src/commands/hpexpireat.json index 9a983da2c..50cbb773e 100644 --- a/src/commands/hpexpireat.json +++ b/src/commands/hpexpireat.json @@ -1,10 +1,10 @@ { "HPEXPIREAT": { "summary": "Set expiry for hash field using an absolute Unix timestamp (milliseconds)", - "complexity": "O(N) where N is the number of arguments to the command", + "complexity": "O(N) where N is the number of specified fields", "group": "hash", - "since": "8.0.0", - "arity": -5, + "since": "7.4.0", + "arity": -6, "function": "hpexpireatCommand", "history": [], "command_flags": [ @@ -106,6 +106,10 @@ } ] }, + { + "name": "FIELDS", + "type": "string" + }, { "name": "numfields", "type": "integer" diff --git a/src/commands/hpexpiretime.json b/src/commands/hpexpiretime.json index 3c13db340..b1eacb9ac 100644 --- a/src/commands/hpexpiretime.json +++ b/src/commands/hpexpiretime.json @@ -1,10 +1,10 @@ { "HPEXPIRETIME": { "summary": "Returns the expiration time of a hash field as a Unix timestamp, in msec.", - "complexity": "O(N) where N is the number of arguments to the command", + "complexity": "O(N) where N is the number of specified fields", "group": "hash", - "since": "8.0.0", - "arity": -4, + "since": "7.4.0", + "arity": -5, "function": "hpexpiretimeCommand", "history": [], "command_flags": [ @@ -75,6 +75,10 @@ "name": "numfields", "type": "integer" }, + { + "name": "FIELDS", + "type": "string" + }, { "name": "field", "type": "string", diff --git a/src/commands/hpttl.json b/src/commands/hpttl.json index 3524981f7..fa2da4547 100644 --- a/src/commands/hpttl.json +++ b/src/commands/hpttl.json @@ -1,10 +1,10 @@ { "HPTTL": { "summary": "Returns the TTL in milliseconds of a hash field.", - "complexity": "O(N) where N is the number of arguments to the command", + "complexity": "O(N) where N is the number of specified fields", "group": "hash", - "since": "8.0.0", - "arity": -4, + "since": "7.4.0", + "arity": -5, "function": "hpttlCommand", "history": [], "command_flags": [ @@ -41,7 +41,7 @@ "type": "null" }, { - "description": "The keyname, popped member, and its score.", + "description": "Array of results", "type": "array", "minItems": 1, "maxItems": 4294967295, @@ -71,6 +71,10 @@ "type": "key", "key_spec_index": 0 }, + { + "name": "FIELDS", + "type": "string" + }, { "name": "numfields", "type": "integer" diff --git a/src/commands/hsetf.json b/src/commands/hsetf.json index b70c10f56..d7e42f967 100644 --- a/src/commands/hsetf.json +++ b/src/commands/hsetf.json @@ -1,9 +1,9 @@ { "HSETF": { "summary": "For each specified field value pair: set field to value and optionally set the field's remaining time to live / UNIX expiration timestamp in seconds / milliseconds", - "complexity": "O(N) where N is the number of arguments to the command", + "complexity": "O(N) where N is the number of specified fields", "group": "hash", - "since": "8.0.0", + "since": "7.4.0", "arity": -6, "function": "hsetfCommand", "history": [], diff --git a/src/commands/httl.json b/src/commands/httl.json index 662e013ce..3e8b610a7 100644 --- a/src/commands/httl.json +++ b/src/commands/httl.json @@ -1,10 +1,10 @@ { "HTTL": { "summary": "Returns the TTL in seconds of a hash field.", - "complexity": "O(N) where N is the number of arguments to the command", + "complexity": "O(N) where N is the number of specified fields", "group": "hash", - "since": "8.0.0", - "arity": -4, + "since": "7.4.0", + "arity": -5, "function": "httlCommand", "history": [], "command_flags": [ @@ -71,6 +71,10 @@ "type": "key", "key_spec_index": 0 }, + { + "name": "FIELDS", + "type": "string" + }, { "name": "numfields", "type": "integer" diff --git a/src/t_hash.c b/src/t_hash.c index 36240a646..dfa509bb6 100644 --- a/src/t_hash.c +++ b/src/t_hash.c @@ -2719,19 +2719,24 @@ static ExpireMeta *hashGetExpireMeta(const eItem hash) { serverPanic("Unknown encoding: %d", hashObj->encoding); } } - +/* HTTL key */ static void httlGenericCommand(client *c, const char *cmd, long long basetime, int unit) { UNUSED(cmd); robj *hashObj; - long numFields = 0, numFieldsAt = 2; + long numFields = 0, numFieldsAt = 3; /* Read the hash object */ if ((hashObj = lookupKeyReadOrReply(c, c->argv[1], shared.null[c->resp])) == NULL || checkType(c, hashObj, OBJ_HASH)) return; + if (strcasecmp(c->argv[numFieldsAt-1]->ptr, "FIELDS")) { + addReplyError(c, "Mandatory argument FIELDS is missing or not at the right position"); + return; + } + /* Read number of fields */ if (getRangeLongFromObjectOrReply(c, c->argv[numFieldsAt], 1, LONG_MAX, - &numFields, "Parameter `numFileds` should be greater than 0") != C_OK) + &numFields, "Number of fields must be a positive integer") != C_OK) return; /* Verify `numFields` is consistent with number of arguments */ @@ -2745,7 +2750,7 @@ static void httlGenericCommand(client *c, const char *cmd, long long basetime, i addReplyArrayLen(c, numFields); for (int i = 0 ; i < numFields ; i++) { - sds field = c->argv[3+i]->ptr; + sds field = c->argv[numFieldsAt+1+i]->ptr; void *fptr = lpFirst(lp); if (fptr != NULL) fptr = lpFind(lp, fptr, (unsigned char *) field, sdslen(field), 1); @@ -2762,7 +2767,7 @@ static void httlGenericCommand(client *c, const char *cmd, long long basetime, i addReplyArrayLen(c, numFields); for (int i = 0 ; i < numFields ; i++) { long long expire; - sds field = c->argv[3+i]->ptr; + sds field = c->argv[numFieldsAt+1+i]->ptr; void *fptr = lpFirst(lpt->lp); if (fptr != NULL) fptr = lpFind(lpt->lp, fptr, (unsigned char *) field, sdslen(field), 2); @@ -2800,7 +2805,7 @@ static void httlGenericCommand(client *c, const char *cmd, long long basetime, i addReplyArrayLen(c, numFields); for (int i = 0 ; i < numFields ; i++) { - sds field = c->argv[3+i]->ptr; + sds field = c->argv[numFieldsAt+1+i]->ptr; dictEntry *de = dictFind(d, field); if (de == NULL) { addReplyLongLong(c, HFE_GET_NO_FIELD); @@ -2840,7 +2845,7 @@ static void httlGenericCommand(client *c, const char *cmd, long long basetime, i * * Additional flags are supported and parsed via parseExtendedExpireArguments */ static void hexpireGenericCommand(client *c, const char *cmd, long long basetime, int unit) { - long numFields = 0, numFieldsAt = 3; + long numFields = 0, numFieldsAt = 4; long long expire; /* unix time in msec */ int expireSetCond = 0; robj *hashObj, *keyArg = c->argv[1], *expireArg = c->argv[2]; @@ -2890,6 +2895,11 @@ static void hexpireGenericCommand(client *c, const char *cmd, long long basetime expireSetCond = HFE_LT; ++numFieldsAt; } + if (strcasecmp(c->argv[numFieldsAt-1]->ptr, "FIELDS")) { + addReplyError(c, "Mandatory argument FIELDS is missing or not at the right position"); + return; + } + /* Read number of fields */ if (getRangeLongFromObjectOrReply(c, c->argv[numFieldsAt], 1, LONG_MAX, &numFields, "Parameter `numFields` should be greater than 0") != C_OK) @@ -2961,16 +2971,21 @@ void hpexpiretimeCommand(client *c) { /* HPERSIST key */ void hpersistCommand(client *c) { robj *hashObj; - long numFields = 0, numFieldsAt = 2; + long numFields = 0, numFieldsAt = 3; int changed = 0; /* Used to determine whether to send a notification. */ /* Read the hash object */ if ((hashObj = lookupKeyReadOrReply(c, c->argv[1], shared.null[c->resp])) == NULL || checkType(c, hashObj, OBJ_HASH)) return; + if (strcasecmp(c->argv[numFieldsAt-1]->ptr, "FIELDS")) { + addReplyError(c, "Mandatory argument FIELDS is missing or not at the right position"); + return; + } + /* Read number of fields */ if (getRangeLongFromObjectOrReply(c, c->argv[numFieldsAt], 1, LONG_MAX, - &numFields, "Parameter `numFileds` should be greater than 0") != C_OK) + &numFields, "Number of fields must be a positive integer") != C_OK) return; /* Verify `numFields` is consistent with number of arguments */ @@ -2982,7 +2997,7 @@ void hpersistCommand(client *c) { if (hashObj->encoding == OBJ_ENCODING_LISTPACK) { addReplyArrayLen(c, numFields); for (int i = 0 ; i < numFields ; i++) { - sds field = c->argv[3 + i]->ptr; + sds field = c->argv[numFieldsAt + 1 + i]->ptr; unsigned char *fptr, *zl = hashObj->ptr; fptr = lpFirst(zl); @@ -3002,7 +3017,7 @@ void hpersistCommand(client *c) { addReplyArrayLen(c, numFields); for (int i = 0 ; i < numFields ; i++) { - sds field = c->argv[3 + i]->ptr; + sds field = c->argv[numFieldsAt + 1 + i]->ptr; fptr = lpFirst(lpt->lp); if (fptr != NULL) @@ -3040,7 +3055,7 @@ void hpersistCommand(client *c) { addReplyArrayLen(c, numFields); for (int i = 0 ; i < numFields ; i++) { - sds field = c->argv[3+i]->ptr; + sds field = c->argv[numFieldsAt + 1 + i]->ptr; dictEntry *de = dictFind(d, field); if (de == NULL) { addReplyLongLong(c, HFE_PERSIST_NO_FIELD); diff --git a/tests/unit/memefficiency.tcl b/tests/unit/memefficiency.tcl index d04f0de4c..37f322d69 100644 --- a/tests/unit/memefficiency.tcl +++ b/tests/unit/memefficiency.tcl @@ -503,7 +503,7 @@ run_solo {defrag} { $rd_pubsub close } - test "Active defrag HFE: $type" { + test "Active Defrag HFE: $type" { r flushdb r config resetstat r config set hz 100 @@ -526,7 +526,7 @@ run_solo {defrag} { for {set i 0} {$i < $n} {incr i} { for {set j 0} {$j < $fields} {incr j} { $rd hset h$i f$j $dummy_field - $rd hexpire h$i 9999999 1 f$j + $rd hexpire h$i 9999999 FIELDS 1 f$j $rd set "k$i$j" $dummy_field } } @@ -538,7 +538,7 @@ run_solo {defrag} { # Coverage for listpackex. r hset h_lpex f0 $dummy_field - r hexpire h_lpex 9999999 1 f0 + r hexpire h_lpex 9999999 FIELDS 1 f0 assert_encoding listpackex h_lpex after 120 ;# serverCron only updates the info once in 100ms diff --git a/tests/unit/pubsub.tcl b/tests/unit/pubsub.tcl index ac8c553ed..5e911e843 100644 --- a/tests/unit/pubsub.tcl +++ b/tests/unit/pubsub.tcl @@ -362,10 +362,10 @@ start_server {tags {"pubsub network"}} { assert_equal {1} [psubscribe $rd1 *] r hmset myhash yes 1 no 0 r hincrby myhash yes 10 - r hexpire myhash 999999 1 yes - r hexpireat myhash [expr {[clock seconds] + 999999}] NX 1 no - r hpexpire myhash 5 1 yes - r hpersist myhash 1 yes + r hexpire myhash 999999 FIELDS 1 yes + r hexpireat myhash [expr {[clock seconds] + 999999}] NX FIELDS 1 no + r hpexpire myhash 5 FIELDS 1 yes + r hpersist myhash FIELDS 1 yes assert_encoding $type myhash assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read] assert_equal "pmessage * __keyspace@${db}__:myhash hincrby" [$rd1 read] diff --git a/tests/unit/type/hash-field-expire.tcl b/tests/unit/type/hash-field-expire.tcl index 8843fd38a..949f729fa 100644 --- a/tests/unit/type/hash-field-expire.tcl +++ b/tests/unit/type/hash-field-expire.tcl @@ -65,8 +65,8 @@ proc hrandfieldTest {activeExpireConfig} { set factorValgrind [expr {$::valgrind ? 2 : 1}] # Set expiration time for field1 and field2 such that field1 expires first - r hpexpire myhash 1 NX 1 field1 - r hpexpire myhash 100 NX 1 field2 + r hpexpire myhash 1 NX FIELDS 1 field1 + r hpexpire myhash 100 NX FIELDS 1 field2 # On call hrandfield command lazy expire deletes field1 first wait_for_condition 8 10 { @@ -99,76 +99,76 @@ start_server {tags {"external:skip needs:debug"}} { test "HPEXPIRE(AT) - Test 'NX' flag ($type)" { r del myhash r hset myhash field1 value1 field2 value2 field3 value3 - assert_equal [r hpexpire myhash 1000 NX 1 field1] [list $E_OK] - assert_equal [r hpexpire myhash 1000 NX 2 field1 field2] [list $E_FAIL $E_OK] + assert_equal [r hpexpire myhash 1000 NX FIELDS 1 field1] [list $E_OK] + assert_equal [r hpexpire myhash 1000 NX FIELDS 2 field1 field2] [list $E_FAIL $E_OK] r del myhash r hset myhash field1 value1 field2 value2 field3 value3 - assert_equal [r hpexpireat myhash [expr {([clock seconds]+1000)*1000}] NX 1 field1] [list $E_OK] - assert_equal [r hpexpireat myhash [expr {([clock seconds]+1000)*1000}] NX 2 field1 field2] [list $E_FAIL $E_OK] + assert_equal [r hpexpireat myhash [expr {([clock seconds]+1000)*1000}] NX FIELDS 1 field1] [list $E_OK] + assert_equal [r hpexpireat myhash [expr {([clock seconds]+1000)*1000}] NX FIELDS 2 field1 field2] [list $E_FAIL $E_OK] } test "HPEXPIRE(AT) - Test 'XX' flag ($type)" { r del myhash r hset myhash field1 value1 field2 value2 field3 value3 - assert_equal [r hpexpire myhash 1000 NX 2 field1 field2] [list $E_OK $E_OK] - assert_equal [r hpexpire myhash 1000 XX 2 field1 field3] [list $E_OK $E_FAIL] + assert_equal [r hpexpire myhash 1000 NX FIELDS 2 field1 field2] [list $E_OK $E_OK] + assert_equal [r hpexpire myhash 1000 XX FIELDS 2 field1 field3] [list $E_OK $E_FAIL] r del myhash r hset myhash field1 value1 field2 value2 field3 value3 - assert_equal [r hpexpireat myhash [expr {([clock seconds]+1000)*1000}] NX 2 field1 field2] [list $E_OK $E_OK] - assert_equal [r hpexpireat myhash [expr {([clock seconds]+1000)*1000}] XX 2 field1 field3] [list $E_OK $E_FAIL] + assert_equal [r hpexpireat myhash [expr {([clock seconds]+1000)*1000}] NX FIELDS 2 field1 field2] [list $E_OK $E_OK] + assert_equal [r hpexpireat myhash [expr {([clock seconds]+1000)*1000}] XX FIELDS 2 field1 field3] [list $E_OK $E_FAIL] } test "HPEXPIRE(AT) - Test 'GT' flag ($type)" { r del myhash r hset myhash field1 value1 field2 value2 - assert_equal [r hpexpire myhash 1000 NX 1 field1] [list $E_OK] - assert_equal [r hpexpire myhash 2000 NX 1 field2] [list $E_OK] - assert_equal [r hpexpire myhash 1500 GT 2 field1 field2] [list $E_OK $E_FAIL] + assert_equal [r hpexpire myhash 1000 NX FIELDS 1 field1] [list $E_OK] + assert_equal [r hpexpire myhash 2000 NX FIELDS 1 field2] [list $E_OK] + assert_equal [r hpexpire myhash 1500 GT FIELDS 2 field1 field2] [list $E_OK $E_FAIL] r del myhash r hset myhash field1 value1 field2 value2 - assert_equal [r hpexpireat myhash [expr {([clock seconds]+1000)*1000}] NX 1 field1] [list $E_OK] - assert_equal [r hpexpireat myhash [expr {([clock seconds]+2000)*1000}] NX 1 field2] [list $E_OK] - assert_equal [r hpexpireat myhash [expr {([clock seconds]+1500)*1000}] GT 2 field1 field2] [list $E_OK $E_FAIL] + assert_equal [r hpexpireat myhash [expr {([clock seconds]+1000)*1000}] NX FIELDS 1 field1] [list $E_OK] + assert_equal [r hpexpireat myhash [expr {([clock seconds]+2000)*1000}] NX FIELDS 1 field2] [list $E_OK] + assert_equal [r hpexpireat myhash [expr {([clock seconds]+1500)*1000}] GT FIELDS 2 field1 field2] [list $E_OK $E_FAIL] } test "HPEXPIRE(AT) - Test 'LT' flag ($type)" { r del myhash r hset myhash field1 value1 field2 value2 - assert_equal [r hpexpire myhash 1000 NX 1 field1] [list $E_OK] - assert_equal [r hpexpire myhash 2000 NX 1 field2] [list $E_OK] - assert_equal [r hpexpire myhash 1500 LT 2 field1 field2] [list $E_FAIL $E_OK] + assert_equal [r hpexpire myhash 1000 NX FIELDS 1 field1] [list $E_OK] + assert_equal [r hpexpire myhash 2000 NX FIELDS 1 field2] [list $E_OK] + assert_equal [r hpexpire myhash 1500 LT FIELDS 2 field1 field2] [list $E_FAIL $E_OK] r del myhash r hset myhash field1 value1 field2 value2 - assert_equal [r hpexpireat myhash [expr {([clock seconds]+1000)*1000}] NX 1 field1] [list $E_OK] - assert_equal [r hpexpireat myhash [expr {([clock seconds]+2000)*1000}] NX 1 field2] [list $E_OK] - assert_equal [r hpexpireat myhash [expr {([clock seconds]+1500)*1000}] LT 2 field1 field2] [list $E_FAIL $E_OK] + assert_equal [r hpexpireat myhash [expr {([clock seconds]+1000)*1000}] NX FIELDS 1 field1] [list $E_OK] + assert_equal [r hpexpireat myhash [expr {([clock seconds]+2000)*1000}] NX FIELDS 1 field2] [list $E_OK] + assert_equal [r hpexpireat myhash [expr {([clock seconds]+1500)*1000}] LT FIELDS 2 field1 field2] [list $E_FAIL $E_OK] } test "HPEXPIREAT - field not exists or TTL is in the past ($type)" { r del myhash r hset myhash f1 v1 f2 v2 f4 v4 - r hexpire myhash 1000 NX 1 f4 - assert_equal [r hpexpireat myhash [expr {([clock seconds]-1)*1000}] NX 4 f1 f2 f3 f4] "$E_DELETED $E_DELETED $E_NO_FIELD $E_FAIL" + r hexpire myhash 1000 NX FIELDS 1 f4 + assert_equal [r hpexpireat myhash [expr {([clock seconds]-1)*1000}] NX FIELDS 4 f1 f2 f3 f4] "$E_DELETED $E_DELETED $E_NO_FIELD $E_FAIL" assert_equal [r hexists myhash field1] 0 } test "HPEXPIRE - wrong number of arguments ($type)" { r del myhash r hset myhash f1 v1 - assert_error {*Parameter `numFields` should be greater than 0} {r hpexpire myhash 1000 NX 0 f1 f2 f3} - assert_error {*Parameter `numFileds` is more than number of arguments} {r hpexpire myhash 1000 NX 4 f1 f2 f3} + assert_error {*Parameter `numFields` should be greater than 0} {r hpexpire myhash 1000 NX FIELDS 0 f1 f2 f3} + assert_error {*Parameter `numFileds` is more than number of arguments} {r hpexpire myhash 1000 NX FIELDS 4 f1 f2 f3} } test "HPEXPIRE - parameter expire-time near limit of 2^48 ($type)" { r del myhash r hset myhash f1 v1 # below & above - assert_equal [r hpexpire myhash [expr (1<<48) - [clock milliseconds] - 1000 ] 1 f1] [list $E_OK] - assert_error {*invalid expire time*} {r hpexpire myhash [expr (1<<48) - [clock milliseconds] + 100 ] 1 f1} + assert_equal [r hpexpire myhash [expr (1<<48) - [clock milliseconds] - 1000 ] FIELDS 1 f1] [list $E_OK] + assert_error {*invalid expire time*} {r hpexpire myhash [expr (1<<48) - [clock milliseconds] + 100 ] FIELDS 1 f1} } test "Lazy - doesn't delete hash that all its fields got expired ($type)" { @@ -180,17 +180,17 @@ start_server {tags {"external:skip needs:debug"}} { for {set i 1} {$i <= $h} {incr i} { # random expiration time r hset hrand$h f$i v$i - r hpexpire hrand$h [expr {50 + int(rand() * 50)}] 1 f$i + r hpexpire hrand$h [expr {50 + int(rand() * 50)}] FIELDS 1 f$i assert_equal 1 [r HEXISTS hrand$h f$i] # same expiration time r hset same$h f$i v$i - r hpexpire same$h 100 1 f$i + r hpexpire same$h 100 FIELDS 1 f$i assert_equal 1 [r HEXISTS same$h f$i] # same expiration time r hset mix$h f$i v$i fieldWithoutExpire$i v$i - r hpexpire mix$h 100 1 f$i + r hpexpire mix$h 100 FIELDS 1 f$i assert_equal 1 [r HEXISTS mix$h f$i] } } @@ -218,17 +218,17 @@ start_server {tags {"external:skip needs:debug"}} { for {set i 1} {$i <= $h} {incr i} { # random expiration time r hset hrand$h f$i v$i - r hpexpire hrand$h [expr {50 + int(rand() * 50)}] 1 f$i + r hpexpire hrand$h [expr {50 + int(rand() * 50)}] FIELDS 1 f$i assert_equal 1 [r HEXISTS hrand$h f$i] # same expiration time r hset same$h f$i v$i - r hpexpire same$h 100 1 f$i + r hpexpire same$h 100 FIELDS 1 f$i assert_equal 1 [r HEXISTS same$h f$i] # same expiration time r hset mix$h f$i v$i fieldWithoutExpire$i v$i - r hpexpire mix$h 100 1 f$i + r hpexpire mix$h 100 FIELDS 1 f$i assert_equal 1 [r HEXISTS mix$h f$i] } } @@ -255,74 +255,74 @@ start_server {tags {"external:skip needs:debug"}} { test "HPEXPIRE - Flushall deletes all pending expired fields ($type)" { r del myhash r hset myhash field1 value1 field2 value2 - r hpexpire myhash 10000 NX 1 field1 - r hpexpire myhash 10000 NX 1 field2 + r hpexpire myhash 10000 NX FIELDS 1 field1 + r hpexpire myhash 10000 NX FIELDS 1 field2 r flushall r del myhash r hset myhash field1 value1 field2 value2 - r hpexpire myhash 10000 NX 1 field1 - r hpexpire myhash 10000 NX 1 field2 + r hpexpire myhash 10000 NX FIELDS 1 field1 + r hpexpire myhash 10000 NX FIELDS 1 field2 r flushall async } test "HTTL/HPTTL - Input validation gets failed on nonexists field or field without expire ($type)" { r del myhash r HSET myhash field1 value1 field2 value2 - r HPEXPIRE myhash 1000 NX 1 field1 + r HPEXPIRE myhash 1000 NX FIELDS 1 field1 foreach cmd {HTTL HPTTL} { - assert_equal [r $cmd non_exists_key 1 f] {} - assert_equal [r $cmd myhash 2 field2 non_exists_field] "$T_NO_EXPIRY $T_NO_FIELD" + assert_equal [r $cmd non_exists_key FIELDS 1 f] {} + assert_equal [r $cmd myhash FIELDS 2 field2 non_exists_field] "$T_NO_EXPIRY $T_NO_FIELD" # Set numFields less than actual number of fields. Fine. - assert_equal [r $cmd myhash 1 non_exists_field1 non_exists_field2] "$T_NO_FIELD" + assert_equal [r $cmd myhash FIELDS 1 non_exists_field1 non_exists_field2] "$T_NO_FIELD" } } test "HTTL/HPTTL - returns time to live in seconds/msillisec ($type)" { r del myhash r HSET myhash field1 value1 field2 value2 - r HPEXPIRE myhash 2000 NX 2 field1 field2 - set ttlArray [r HTTL myhash 2 field1 field2] + r HPEXPIRE myhash 2000 NX FIELDS 2 field1 field2 + set ttlArray [r HTTL myhash FIELDS 2 field1 field2] assert_range [lindex $ttlArray 0] 1 2 - set ttl [r HPTTL myhash 1 field1] + set ttl [r HPTTL myhash FIELDS 1 field1] assert_range $ttl 1000 2000 } test "HEXPIRETIME - returns TTL in Unix timestamp ($type)" { r del myhash r HSET myhash field1 value1 - r HPEXPIRE myhash 1000 NX 1 field1 + r HPEXPIRE myhash 1000 NX FIELDS 1 field1 set lo [expr {[clock seconds] + 1}] set hi [expr {[clock seconds] + 2}] - assert_range [r HEXPIRETIME myhash 1 field1] $lo $hi - assert_range [r HPEXPIRETIME myhash 1 field1] [expr $lo*1000] [expr $hi*1000] + assert_range [r HEXPIRETIME myhash FIELDS 1 field1] $lo $hi + assert_range [r HPEXPIRETIME myhash FIELDS 1 field1] [expr $lo*1000] [expr $hi*1000] } test "HTTL/HPTTL - Verify TTL progress until expiration ($type)" { r del myhash r hset myhash field1 value1 field2 value2 - r hpexpire myhash 1000 NX 1 field1 - assert_range [r HPTTL myhash 1 field1] 100 1000 - assert_range [r HTTL myhash 1 field1] 0 1 + r hpexpire myhash 1000 NX FIELDS 1 field1 + assert_range [r HPTTL myhash FIELDS 1 field1] 100 1000 + assert_range [r HTTL myhash FIELDS 1 field1] 0 1 after 100 - assert_range [r HPTTL myhash 1 field1] 1 901 + assert_range [r HPTTL myhash FIELDS 1 field1] 1 901 after 910 - assert_equal [r HPTTL myhash 1 field1] $T_NO_FIELD - assert_equal [r HTTL myhash 1 field1] $T_NO_FIELD + assert_equal [r HPTTL myhash FIELDS 1 field1] $T_NO_FIELD + assert_equal [r HTTL myhash FIELDS 1 field1] $T_NO_FIELD } test "HPEXPIRE - DEL hash with non expired fields (valgrind test) ($type)" { r del myhash r hset myhash field1 value1 field2 value2 - r hpexpire myhash 10000 NX 1 field1 + r hpexpire myhash 10000 NX FIELDS 1 field1 r del myhash } test "HEXPIREAT - Set time in the past ($type)" { r del myhash r hset myhash field1 value1 - assert_equal [r hexpireat myhash [expr {[clock seconds] - 1}] NX 1 field1] $E_DELETED + assert_equal [r hexpireat myhash [expr {[clock seconds] - 1}] NX FIELDS 1 field1] $E_DELETED assert_equal [r hexists myhash field1] 0 } @@ -330,19 +330,19 @@ start_server {tags {"external:skip needs:debug"}} { r del myhash r hset myhash field1 value1 - r hexpireat myhash [expr {[clock seconds] + 2}] NX 1 field1 - assert_range [r hpttl myhash 1 field1] 1000 2000 - assert_range [r httl myhash 1 field1] 1 2 + r hexpireat myhash [expr {[clock seconds] + 2}] NX FIELDS 1 field1 + assert_range [r hpttl myhash FIELDS 1 field1] 1000 2000 + assert_range [r httl myhash FIELDS 1 field1] 1 2 - r hexpireat myhash [expr {[clock seconds] + 5}] XX 1 field1 - assert_range [r httl myhash 1 field1] 4 5 + r hexpireat myhash [expr {[clock seconds] + 5}] XX FIELDS 1 field1 + assert_range [r httl myhash FIELDS 1 field1] 4 5 } test "Lazy expire - delete hash with expired fields ($type)" { r del myhash r debug set-active-expire 0 r hset myhash k v - r hpexpire myhash 1 NX 1 k + r hpexpire myhash 1 NX FIELDS 1 k after 5 r del myhash r debug set-active-expire 1 @@ -358,7 +358,7 @@ start_server {tags {"external:skip needs:debug"}} { r debug set-active-expire 0 r del myhash r hset myhash f1 v1 f2 v2 f3 v3 f4 v4 f5 v5 - r hpexpire myhash 1 NX 4 f1 f2 f3 f4 + r hpexpire myhash 1 NX FIELDS 4 f1 f2 f3 f4 after 5 set res [cmp_hrandfield_result myhash "f1 f2 f3 f4 f5"] assert {$res == 1} @@ -372,18 +372,18 @@ start_server {tags {"external:skip needs:debug"}} { r del h1 h4 h18 h20 r hset h1 k1 v1 - r hpexpire h1 1 NX 1 k1 + r hpexpire h1 1 NX FIELDS 1 k1 r hset h4 k1 v1 k2 v2 k3 v3 k4 v4 - r hpexpire h4 1 NX 3 k1 k3 k4 + r hpexpire h4 1 NX FIELDS 3 k1 k3 k4 # beyond 16 fields: HFE DS (ebuckets) converts from list to rax r hset h18 k1 v1 k2 v2 k3 v3 k4 v4 k5 v5 k6 v6 k7 v7 k8 v8 k9 v9 k10 v10 k11 v11 k12 v12 k13 v13 k14 v14 k15 v15 k16 v16 k17 v17 k18 v18 - r hpexpire h18 1 NX 18 k1 k2 k3 k4 k5 k6 k7 k8 k9 k10 k11 k12 k13 k14 k15 k16 k17 k18 + r hpexpire h18 1 NX FIELDS 18 k1 k2 k3 k4 k5 k6 k7 k8 k9 k10 k11 k12 k13 k14 k15 k16 k17 k18 r hset h20 k1 v1 k2 v2 k3 v3 k4 v4 k5 v5 k6 v6 k7 v7 k8 v8 k9 v9 k10 v10 k11 v11 k12 v12 k13 v13 k14 v14 k15 v15 k16 v16 k17 v17 k18 v18 k19 v19 k20 v20 - r hpexpire h20 1 NX 2 k1 k2 + r hpexpire h20 1 NX FIELDS 2 k1 k2 after 10 @@ -401,18 +401,18 @@ start_server {tags {"external:skip needs:debug"}} { r del h1 h20 h4 h18 h20 r hset h1 01 01 - r hpexpire h1 1 NX 1 01 + r hpexpire h1 1 NX FIELDS 1 01 r hset h4 01 01 02 02 03 03 04 04 - r hpexpire h4 1 NX 3 01 03 04 + r hpexpire h4 1 NX FIELDS 3 01 03 04 # beyond 16 fields hash-field expiration DS (ebuckets) converts from list to rax r hset h18 01 01 02 02 03 03 04 04 05 05 06 06 07 07 08 08 09 09 10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 - r hpexpire h18 1 NX 18 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 + r hpexpire h18 1 NX FIELDS 18 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 r hset h20 01 01 02 02 03 03 04 04 05 05 06 06 07 07 08 08 09 09 10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 19 20 20 - r hpexpire h20 1 NX 2 01 02 + r hpexpire h20 1 NX FIELDS 2 01 02 after 10 @@ -433,7 +433,7 @@ start_server {tags {"external:skip needs:debug"}} { for {set i 1} {$i <= 1000} {incr i} { r hset myhash field$i value$i if {$i > 1} { - r hpexpire myhash 1 NX 1 field$i + r hpexpire myhash 1 NX FIELDS 1 field$i } } after 3 @@ -467,14 +467,14 @@ start_server {tags {"external:skip needs:debug"}} { r hset h5 1 1 2 22 3 333 4 4444 5 55555 r hset h6 01 01 02 02 03 03 04 04 05 05 06 06 r hset h18 01 01 02 02 03 03 04 04 05 05 06 06 07 07 08 08 09 09 10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 - r hpexpire h1 100 NX 1 01 - r hpexpire h2 100 NX 1 01 - r hpexpire h2 100 NX 1 02 - r hpexpire h3 100 NX 1 01 - r hpexpire h4 100 NX 1 2 - r hpexpire h5 100 NX 1 3 - r hpexpire h6 100 NX 1 05 - r hpexpire h18 100 NX 17 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 + r hpexpire h1 100 NX FIELDS 1 01 + r hpexpire h2 100 NX FIELDS 1 01 + r hpexpire h2 100 NX FIELDS 1 02 + r hpexpire h3 100 NX FIELDS 1 01 + r hpexpire h4 100 NX FIELDS 1 2 + r hpexpire h5 100 NX FIELDS 1 3 + r hpexpire h6 100 NX FIELDS 1 05 + r hpexpire h18 100 NX FIELDS 17 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 after 150 @@ -507,32 +507,32 @@ start_server {tags {"external:skip needs:debug"}} { test "A field with TTL overridden with another value (TTL discarded) ($type)" { r del myhash r hset myhash field1 value1 field2 value2 field3 value3 - r hpexpire myhash 10000 NX 1 field1 - r hpexpire myhash 1 NX 1 field2 + r hpexpire myhash 10000 NX FIELDS 1 field1 + r hpexpire myhash 1 NX FIELDS 1 field2 # field2 TTL will be discarded r hset myhash field2 value4 after 5 # Expected TTL will be discarded assert_equal [r hget myhash field2] "value4" - assert_equal [r httl myhash 2 field2 field3] "$T_NO_EXPIRY $T_NO_EXPIRY" - assert_not_equal [r httl myhash 1 field1] "$T_NO_EXPIRY" + assert_equal [r httl myhash FIELDS 2 field2 field3] "$T_NO_EXPIRY $T_NO_EXPIRY" + assert_not_equal [r httl myhash FIELDS 1 field1] "$T_NO_EXPIRY" } test "Modify TTL of a field ($type)" { r del myhash r hset myhash field1 value1 - r hpexpire myhash 200000 NX 1 field1 - r hpexpire myhash 1000000 XX 1 field1 + r hpexpire myhash 200000 NX FIELDS 1 field1 + r hpexpire myhash 1000000 XX FIELDS 1 field1 after 15 assert_equal [r hget myhash field1] "value1" - assert_range [r hpttl myhash 1 field1] 900000 1000000 + assert_range [r hpttl myhash FIELDS 1 field1] 900000 1000000 } test "Test return value of set operation ($type)" { r del myhash r hset myhash f1 v1 f2 v2 - r hexpire myhash 100000 1 f1 + r hexpire myhash 100000 FIELDS 1 f1 assert_equal [r hset myhash f2 v2] 0 assert_equal [r hset myhash f3 v3] 1 assert_equal [r hset myhash f3 v3 f4 v4] 1 @@ -544,7 +544,7 @@ start_server {tags {"external:skip needs:debug"}} { r debug set-active-expire 0 r del myhash r hset myhash1 f1 v1 f2 v2 f3 v3 f4 v4 f5 v5 f6 v6 - r hpexpire myhash1 1 NX 3 f2 f4 f6 + r hpexpire myhash1 1 NX FIELDS 3 f2 f4 f6 after 10 assert_equal [lsort [r hgetall myhash1]] "f1 f3 f5 v1 v3 v5" @@ -552,7 +552,7 @@ start_server {tags {"external:skip needs:debug"}} { r del myhash for {set i 1} {$i <= 600} {incr i} { r hset myhash f$i v$i - if {$i > 3} { r hpexpire myhash 1 NX 1 f$i } + if {$i > 3} { r hpexpire myhash 1 NX FIELDS 1 f$i } } after 10 assert_equal [lsort [r hgetall myhash]] [lsort "f1 f2 f3 v1 v2 v3"] @@ -563,10 +563,10 @@ start_server {tags {"external:skip needs:debug"}} { r debug set-active-expire 0 r del myhash r hset myhash field1 value1 - r hpexpire myhash 20 NX 1 field1 + r hpexpire myhash 20 NX FIELDS 1 field1 r rename myhash myhash2 assert_equal [r exists myhash] 0 - assert_range [r hpttl myhash2 1 field1] 1 20 + assert_range [r hpttl myhash2 FIELDS 1 field1] 1 20 after 25 # Verify the renamed key exists assert_equal [r exists myhash2] 1 @@ -579,7 +579,7 @@ start_server {tags {"external:skip needs:debug"}} { r select 9 r flushall r hset myhash field1 value1 - r hpexpire myhash 100 NX 1 field1 + r hpexpire myhash 100 NX FIELDS 1 field1 r move myhash 10 assert_equal [r exists myhash] 0 assert_equal [r dbsize] 0 @@ -598,8 +598,8 @@ start_server {tags {"external:skip needs:debug"}} { r flushall r hset h1 f1 v1 f2 v2 r hset h2 f1 v1 f2 v2 f3 v3 f4 v4 f5 v5 f6 v6 f7 v7 f8 v8 f9 v9 f10 v10 f11 v11 f12 v12 f13 v13 f14 v14 f15 v15 f16 v16 f17 v17 f18 v18 - r hpexpire h1 100 NX 1 f1 - r hpexpire h2 100 NX 18 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 f16 f17 f18 + r hpexpire h1 100 NX FIELDS 1 f1 + r hpexpire h2 100 NX FIELDS 18 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 f16 f17 f18 r COPY h1 h1copy r COPY h2 h2copy assert_equal [r hget h1 f1] "v1" @@ -622,7 +622,7 @@ start_server {tags {"external:skip needs:debug"}} { r select 9 r flushall r hset myhash field1 value1 - r hpexpire myhash 50 NX 1 field1 + r hpexpire myhash 50 NX FIELDS 1 field1 r swapdb 9 10 @@ -643,33 +643,33 @@ start_server {tags {"external:skip needs:debug"}} { # HPERSIST key r del myhash r hset myhash f1 v1 f2 v2 - r hexpire myhash 1000 NX 1 f1 + r hexpire myhash 1000 NX FIELDS 1 f1 assert_error {*wrong number of arguments*} {r hpersist myhash} - assert_error {*wrong number of arguments*} {r hpersist myhash 1} - assert_equal [r hpersist not-exists-key 1 f1] {} - assert_equal [r hpersist myhash 2 f1 not-exists-field] "$P_OK $P_NO_FIELD" - assert_equal [r hpersist myhash 1 f2] "$P_NO_EXPIRY" + assert_error {*wrong number of arguments*} {r hpersist myhash FIELDS 1} + assert_equal [r hpersist not-exists-key FIELDS 1 f1] {} + assert_equal [r hpersist myhash FIELDS 2 f1 not-exists-field] "$P_OK $P_NO_FIELD" + assert_equal [r hpersist myhash FIELDS 1 f2] "$P_NO_EXPIRY" } test "HPERSIST - verify fields with TTL are persisted ($type)" { r del myhash r hset myhash f1 v1 f2 v2 - r hexpire myhash 20 NX 2 f1 f2 - r hpersist myhash 2 f1 f2 + r hexpire myhash 20 NX FIELDS 2 f1 f2 + r hpersist myhash FIELDS 2 f1 f2 after 25 assert_equal [r hget myhash f1] "v1" assert_equal [r hget myhash f2] "v2" - assert_equal [r HTTL myhash 2 f1 f2] "$T_NO_EXPIRY $T_NO_EXPIRY" + assert_equal [r HTTL myhash FIELDS 2 f1 f2] "$T_NO_EXPIRY $T_NO_EXPIRY" } test "HTTL/HPERSIST - Test expiry commands with non-volatile hash ($type)" { r del myhash r hset myhash field1 value1 field2 value2 field3 value3 - assert_equal [r httl myhash 1 field1] $T_NO_EXPIRY - assert_equal [r httl myhash 1 fieldnonexist] $E_NO_FIELD + assert_equal [r httl myhash FIELDS 1 field1] $T_NO_EXPIRY + assert_equal [r httl myhash FIELDS 1 fieldnonexist] $E_NO_FIELD - assert_equal [r hpersist myhash 1 field1] $P_NO_EXPIRY - assert_equal [r hpersist myhash 1 fieldnonexist] $P_NO_FIELD + assert_equal [r hpersist myhash FIELDS 1 field1] $P_NO_EXPIRY + assert_equal [r hpersist myhash FIELDS 1 fieldnonexist] $P_NO_FIELD } test "HGETF - input validation ($type)" { @@ -745,15 +745,15 @@ start_server {tags {"external:skip needs:debug"}} { r hset myhash field1 value1 field2 value2 field3 value3 assert_equal [r hgetf myhash EX 1000 NX FIELDS 1 field1] [list "value1"] assert_equal [r hgetf myhash EX 10000 NX FIELDS 2 field1 field2] [list "value1" "value2"] - assert_range [r httl myhash 1 field1] 1 1000 - assert_range [r httl myhash 1 field2] 5000 10000 + assert_range [r httl myhash FIELDS 1 field1] 1 1000 + assert_range [r httl myhash FIELDS 1 field2] 5000 10000 # A field with no expiration is treated as an infinite expiration. # LT should set the expire time if field has no TTL. r del myhash r hset myhash field1 value1 assert_equal [r hgetf myhash EX 1500 LT FIELDS 1 field1] [list "value1"] - assert_not_equal [r httl myhash 1 field1] "$T_NO_EXPIRY" + assert_not_equal [r httl myhash FIELDS 1 field1] "$T_NO_EXPIRY" } test "HGETF - Test 'XX' flag ($type)" { @@ -761,8 +761,8 @@ start_server {tags {"external:skip needs:debug"}} { r hset myhash field1 value1 field2 value2 field3 value3 assert_equal [r hgetf myhash EX 1000 NX FIELDS 1 field1] [list "value1"] assert_equal [r hgetf myhash EX 10000 XX FIELDS 2 field1 field2] [list "value1" "value2"] - assert_range [r httl myhash 1 field1] 9900 10000 - assert_equal [r httl myhash 1 field2] "$T_NO_EXPIRY" + assert_range [r httl myhash FIELDS 1 field1] 9900 10000 + assert_equal [r httl myhash FIELDS 1 field2] "$T_NO_EXPIRY" } test "HGETF - Test 'GT' flag ($type)" { @@ -771,8 +771,8 @@ start_server {tags {"external:skip needs:debug"}} { assert_equal [r hgetf myhash EX 1000 NX FIELDS 1 field1] [list "value1"] assert_equal [r hgetf myhash EX 2000 NX FIELDS 1 field2] [list "value2"] assert_equal [r hgetf myhash EX 1500 GT FIELDS 2 field1 field2] [list "value1" "value2"] - assert_range [r httl myhash 1 field1] 1400 1500 - assert_range [r httl myhash 1 field2] 1900 2000 + assert_range [r httl myhash FIELDS 1 field1] 1400 1500 + assert_range [r httl myhash FIELDS 1 field2] 1900 2000 } test "HGETF - Test 'LT' flag ($type)" { @@ -781,36 +781,36 @@ start_server {tags {"external:skip needs:debug"}} { assert_equal [r hgetf myhash EX 1000 NX FIELDS 1 field1] [list "value1"] assert_equal [r hgetf myhash EX 2000 NX FIELDS 1 field2] [list "value2"] assert_equal [r hgetf myhash EX 1500 LT FIELDS 2 field1 field2] [list "value1" "value2"] - assert_range [r httl myhash 1 field1] 1 1000 - assert_range [r httl myhash 1 field2] 1000 1500 + assert_range [r httl myhash FIELDS 1 field1] 1 1000 + assert_range [r httl myhash FIELDS 1 field2] 1000 1500 } test "HGETF - Test 'EX' flag ($type)" { r del myhash r hset myhash field1 value1 field2 value2 field3 value3 assert_equal [r hgetf myhash EX 1000 FIELDS 1 field3] [list "value3"] - assert_range [r httl myhash 1 field3] 1 1000 + assert_range [r httl myhash FIELDS 1 field3] 1 1000 } test "HGETF - Test 'EXAT' flag ($type)" { r del myhash r hset myhash field1 value1 field2 value2 field3 value3 assert_equal [r hgetf myhash EXAT 4000000000 FIELDS 1 field3] [list "value3"] - assert_range [expr [r httl myhash 1 field3] + [clock seconds]] 3900000000 4000000000 + assert_range [expr [r httl myhash FIELDS 1 field3] + [clock seconds]] 3900000000 4000000000 } test "HGETF - Test 'PX' flag ($type)" { r del myhash r hset myhash field1 value1 field2 value2 field3 value3 assert_equal [r hgetf myhash PX 1000000 FIELDS 1 field3] [list "value3"] - assert_range [r httl myhash 1 field3] 900 1000 + assert_range [r httl myhash FIELDS 1 field3] 900 1000 } test "HGETF - Test 'PXAT' flag ($type)" { r del myhash r hset myhash field1 value1 field2 value2 field3 value3 assert_equal [r hgetf myhash PXAT 4000000000000 FIELDS 1 field3] [list "value3"] - assert_range [expr [r httl myhash 1 field3] + [clock seconds]] 3900000000 4000000000 + assert_range [expr [r httl myhash FIELDS 1 field3] + [clock seconds]] 3900000000 4000000000 } test "HGETF - Test 'PERSIST' flag ($type)" { @@ -819,15 +819,15 @@ start_server {tags {"external:skip needs:debug"}} { r hset myhash f1 v1 f2 v2 f3 v3 r hgetf myhash PX 5000 FIELDS 3 f1 f2 f3 - assert_not_equal [r httl myhash 1 f1] "$T_NO_EXPIRY" - assert_not_equal [r httl myhash 1 f2] "$T_NO_EXPIRY" - assert_not_equal [r httl myhash 1 f3] "$T_NO_EXPIRY" + assert_not_equal [r httl myhash FIELDS 1 f1] "$T_NO_EXPIRY" + assert_not_equal [r httl myhash FIELDS 1 f2] "$T_NO_EXPIRY" + assert_not_equal [r httl myhash FIELDS 1 f3] "$T_NO_EXPIRY" assert_equal [r hgetf myhash PERSIST FIELDS 1 f1] "v1" - assert_equal [r httl myhash 1 f1] "$T_NO_EXPIRY" + assert_equal [r httl myhash FIELDS 1 f1] "$T_NO_EXPIRY" assert_equal [r hgetf myhash PERSIST FIELDS 2 f2 f3] "v2 v3" - assert_equal [r httl myhash 2 f2 f3] "$T_NO_EXPIRY $T_NO_EXPIRY" + assert_equal [r httl myhash FIELDS 2 f2 f3] "$T_NO_EXPIRY $T_NO_EXPIRY" } test "HGETF - Test setting expired ttl deletes key ($type)" { @@ -836,7 +836,7 @@ start_server {tags {"external:skip needs:debug"}} { # hgetf without setting ttl assert_equal [lsort [r hgetf myhash fields 3 f1 f2 f3]] [lsort "v1 v2 v3"] - assert_equal [r httl myhash 3 f1 f2 f3] "$T_NO_EXPIRY $T_NO_EXPIRY $T_NO_EXPIRY" + assert_equal [r httl myhash FIELDS 3 f1 f2 f3] "$T_NO_EXPIRY $T_NO_EXPIRY $T_NO_EXPIRY" # set expired ttl and verify key is deleted r hgetf myhash PXAT 1 fields 3 f1 f2 f3 @@ -865,10 +865,10 @@ start_server {tags {"external:skip needs:debug"}} { # Expected TTL will be discarded assert_equal [r hget myhash field2] "value4" - assert_equal [r httl myhash 2 field2 field3] "$T_NO_EXPIRY $T_NO_EXPIRY" + assert_equal [r httl myhash FIELDS 2 field2 field3] "$T_NO_EXPIRY $T_NO_EXPIRY" # Other field is not affected. - assert_not_equal [r httl myhash 1 field1] "$T_NO_EXPIRY" + assert_not_equal [r httl myhash FIELDS 1 field1] "$T_NO_EXPIRY" } test "HSETF - input validation ($type)" { @@ -979,8 +979,8 @@ start_server {tags {"external:skip needs:debug"}} { r hset myhash f1 v1 f2 v2 f3 v3 assert_equal [r hsetf myhash EX 1000 NX FVS 1 f1 n1] "$S_FIELD_AND_TTL" assert_equal [r hsetf myhash EX 10000 NX FVS 2 f1 n1 f2 n2] "$S_FIELD $S_FIELD_AND_TTL" - assert_range [r httl myhash 1 f1] 990 1000 - assert_range [r httl myhash 1 f2] 9990 10000 + assert_range [r httl myhash FIELDS 1 f1] 990 1000 + assert_range [r httl myhash FIELDS 1 f2] 9990 10000 } test "HSETF - Test 'XX' flag ($type)" { @@ -988,8 +988,8 @@ start_server {tags {"external:skip needs:debug"}} { r hset myhash f1 v1 f2 v2 f3 v3 assert_equal [r hsetf myhash EX 1000 NX FVS 1 f1 n1] "$S_FIELD_AND_TTL" assert_equal [r hsetf myhash EX 10000 XX FVS 2 f1 n1 f2 n2] "$S_FIELD_AND_TTL $S_FIELD" - assert_range [r httl myhash 1 f1] 9900 10000 - assert_equal [r httl myhash 1 f2] "$T_NO_EXPIRY" + assert_range [r httl myhash FIELDS 1 f1] 9900 10000 + assert_equal [r httl myhash FIELDS 1 f2] "$T_NO_EXPIRY" } test "HSETF - Test 'GT' flag ($type)" { @@ -998,8 +998,8 @@ start_server {tags {"external:skip needs:debug"}} { assert_equal [r hsetf myhash EX 1000 NX FVS 1 f1 n1] "$S_FIELD_AND_TTL" assert_equal [r hsetf myhash EX 2000 NX FVS 1 f2 n2] "$S_FIELD_AND_TTL" assert_equal [r hsetf myhash EX 1500 GT FVS 2 f1 n1 f2 n2] "$S_FIELD_AND_TTL $S_FIELD" - assert_range [r httl myhash 1 f1] 1400 1500 - assert_range [r httl myhash 1 f2] 1600 2000 + assert_range [r httl myhash FIELDS 1 f1] 1400 1500 + assert_range [r httl myhash FIELDS 1 f2] 1600 2000 } test "HSETF - Test 'LT' flag ($type)" { @@ -1008,8 +1008,8 @@ start_server {tags {"external:skip needs:debug"}} { assert_equal [r hsetf myhash EX 1000 NX FVS 1 f1 v1] "$S_FIELD_AND_TTL" assert_equal [r hsetf myhash EX 2000 NX FVS 1 f2 v2] "$S_FIELD_AND_TTL" assert_equal [r hsetf myhash EX 1500 LT FVS 2 f1 v1 f2 v2] "$S_FIELD $S_FIELD_AND_TTL" - assert_range [r httl myhash 1 f1] 900 1000 - assert_range [r httl myhash 1 f2] 1400 1500 + assert_range [r httl myhash FIELDS 1 f1] 900 1000 + assert_range [r httl myhash FIELDS 1 f2] 1400 1500 # A field with no expiration is treated as an infinite expiration. # LT should set the expire time if field has no TTL. @@ -1022,27 +1022,27 @@ start_server {tags {"external:skip needs:debug"}} { r del myhash r hset myhash f1 v1 f2 v2 assert_equal [r hsetf myhash EX 1000 FVS 1 f3 v3 ] "$S_FIELD_AND_TTL" - assert_range [r httl myhash 1 f3] 900 1000 + assert_range [r httl myhash FIELDS 1 f3] 900 1000 } test "HSETF - Test 'EXAT' flag ($type)" { r del myhash r hset myhash f1 v1 f2 v2 assert_equal [r hsetf myhash EXAT 4000000000 FVS 1 f3 v3] "$S_FIELD_AND_TTL" - assert_range [expr [r httl myhash 1 f3] + [clock seconds]] 3900000000 4000000000 + assert_range [expr [r httl myhash FIELDS 1 f3] + [clock seconds]] 3900000000 4000000000 } test "HSETF - Test 'PX' flag ($type)" { r del myhash assert_equal [r hsetf myhash PX 1000000 FVS 1 f3 v3] "$S_FIELD_AND_TTL" - assert_range [r httl myhash 1 f3] 990 1000 + assert_range [r httl myhash FIELDS 1 f3] 990 1000 } test "HSETF - Test 'PXAT' flag ($type)" { r del myhash r hset myhash f1 v2 f2 v2 f3 v3 assert_equal [r hsetf myhash PXAT 4000000000000 FVS 1 f2 v2] "$S_FIELD_AND_TTL" - assert_range [expr [r httl myhash 1 f2] + [clock seconds]] 3900000000 4000000000 + assert_range [expr [r httl myhash FIELDS 1 f2] + [clock seconds]] 3900000000 4000000000 } test "HSETF - Test 'KEEPTTL' flag ($type)" { @@ -1052,14 +1052,14 @@ start_server {tags {"external:skip needs:debug"}} { r hsetf myhash PX 5000 FVS 1 f2 v2 # f1 does not have ttl - assert_equal [r httl myhash 1 f1] "$T_NO_EXPIRY" + assert_equal [r httl myhash FIELDS 1 f1] "$T_NO_EXPIRY" # f2 has ttl - assert_not_equal [r httl myhash 1 f2] "$T_NO_EXPIRY" + assert_not_equal [r httl myhash FIELDS 1 f2] "$T_NO_EXPIRY" # Validate KEEPTTL preserve TTL assert_equal [r hsetf myhash KEEPTTL FVS 1 f2 n2] "$S_FIELD" - assert_not_equal [r httl myhash 1 f2] "$T_NO_EXPIRY" + assert_not_equal [r httl myhash FIELDS 1 f2] "$T_NO_EXPIRY" assert_equal [r hget myhash f2] "n2" } @@ -1070,7 +1070,7 @@ start_server {tags {"external:skip needs:debug"}} { r hsetf myhash PX 5000 FVS 1 f2 v2 assert_equal [r hsetf myhash FVS 2 f1 v1 f2 v2] "$S_FIELD $S_FIELD_AND_TTL" - assert_not_equal [r httl myhash 1 f1 f2] "$T_NO_EXPIRY $T_NO_EXPIRY" + assert_not_equal [r httl myhash FIELDS 1 f1 f2] "$T_NO_EXPIRY $T_NO_EXPIRY" } test "HSETF - Test 'GETNEW/GETOLD' flag ($type)" { @@ -1136,7 +1136,7 @@ start_server {tags {"external:skip needs:debug"}} { test "Test listpack memory usage" { r hset myhash f1 v1 f2 v2 f3 v3 f4 v4 f5 v5 - r hpexpire myhash 5 2 f2 f4 + r hpexpire myhash 5 FIELDS 2 f2 f4 # Just to have code coverage for the new listpack encoding r memory usage myhash @@ -1144,7 +1144,7 @@ start_server {tags {"external:skip needs:debug"}} { test "Test listpack object encoding" { r hset myhash f1 v1 f2 v2 f3 v3 f4 v4 f5 v5 - r hpexpire myhash 5 2 f2 f4 + r hpexpire myhash 5 FIELDS 2 f2 f4 # Just to have code coverage for the listpackex encoding assert_equal [r object encoding myhash] "listpackex" @@ -1163,7 +1163,7 @@ start_server {tags {"external:skip needs:debug"}} { r debug set-active-expire 0 r hset myhash f1 v1 f2 v2 f3 v3 f4 v4 f5 v5 - r hpexpire myhash 5 2 f2 f4 + r hpexpire myhash 5 FIELDS 2 f2 f4 for {set i 6} {$i < 11} {incr i} { r hset myhash f$i v$i @@ -1179,14 +1179,14 @@ start_server {tags {"external:skip needs:debug"}} { r debug set-active-expire 0 r hset myhash f1 v1 f2 v2 f3 v3 f4 v4 f5 v5 - r hpexpire myhash 10 1 f1 + r hpexpire myhash 10 FIELDS 1 f1 for {set i 0} {$i < 2048} {incr i} { r hset myhash f$i v$i } for {set i 0} {$i < 2048} {incr i} { - r hpexpire myhash 10 1 f$i + r hpexpire myhash 10 FIELDS 1 f$i } r debug set-active-expire 1 @@ -1225,11 +1225,11 @@ start_server {tags {"external:skip needs:debug"}} { # Test with multiple items r hset myhash f1 $payload2 f2 v2 f3 $payload1 f4 v4 - r hexpire myhash 100000 1 f3 - r hpersist myhash 1 f3 - assert_equal [r hpersist myhash 1 f3] $P_NO_EXPIRY + r hexpire myhash 100000 FIELDS 1 f3 + r hpersist myhash FIELDS 1 f3 + assert_equal [r hpersist myhash FIELDS 1 f3] $P_NO_EXPIRY - r hpexpire myhash 10 1 f1 + r hpexpire myhash 10 FIELDS 1 f1 after 20 assert_equal [lsort [r hgetall myhash]] [lsort "f2 f3 f4 v2 $payload1 v4"]