Skip to content

Commit

Permalink
add STRPOP (RedisLabsModules#12)
Browse files Browse the repository at this point in the history
Includes test and documentation.
  • Loading branch information
neomantra committed Jul 17, 2017
1 parent a9c79cb commit 0a650a5
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 0 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ Credit: Meni Katz

**Reply:** Integer, the length of the String after it was modified.

## `STRPOP key`

Gets the value at `key`, deletes `key`, then returns the value.
It is equivalent to an atomic [GET](https://redis.io/commands/get) and [DEL](https://redis.io/commands/del).

* An error is returned if the key exists and does not hold a string.

**Reply:** String, the value at `key` or NULL if `key` didn't exist.

# rxhashes

This module provides extended Redis Hashes commands.
Expand Down
64 changes: 64 additions & 0 deletions src/rxstrings.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,49 @@ int SetRangeRandCommand(RedisModuleCtx *ctx, RedisModuleString **argv,
return REDISMODULE_OK;
}

/*
* STRPOP key
* Gets the value at key, deletes the key, then return the value.
* Equivalent to an atomic GET and DEL.
* An error is returned if there is a value stored that is not a string.
* String Reply: the value of key, or nil if key does not exist.
*/
int StrPopCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if (argc != 2) {
return RedisModule_WrongArity(ctx);
}
RedisModule_AutoMemory(ctx);

/* Obtain key */
RedisModuleKey *key =
RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ | REDISMODULE_WRITE);

if (RedisModule_KeyType(key) == REDISMODULE_KEYTYPE_EMPTY) {
RedisModule_ReplyWithNull(ctx);
return REDISMODULE_OK;
}

/* Key must be a string */
if (RedisModule_KeyType(key) != REDISMODULE_KEYTYPE_STRING) {
RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
return REDISMODULE_ERR;
}

/* GET the string */
size_t dmaLen;
char* valPtr = RedisModule_StringDMA(key, &dmaLen, REDISMODULE_READ);
RedisModuleString* valStr = RedisModule_CreateString(ctx, valPtr, dmaLen);

/* DELete the key */
if (RedisModule_DeleteKey(key) != REDISMODULE_OK) {
RedisModule_ReplyWithError(ctx, "ERR DeleteKey failed");
return REDISMODULE_ERR;
}

RedisModule_ReplyWithString(ctx, valStr);
return REDISMODULE_OK;
}

int testCheckAnd(RedisModuleCtx *ctx) {
RedisModuleCallReply *r;

Expand Down Expand Up @@ -549,6 +592,22 @@ int testSetRangeRand(RedisModuleCtx *ctx) {
return 0;
}

int testStrPop(RedisModuleCtx *ctx) {
RedisModuleCallReply *r;

r = RedisModule_Call(ctx, "set", "cc", "foo", "abcdef");
RMUtil_AssertReplyEquals(r,"OK");
r = RedisModule_Call(ctx, "strpop", "c", "foo");
RMUtil_AssertReplyEquals(r,"abcdef");
r = RedisModule_Call(ctx, "exists", "c", "foo");
RMUtil_Assert(RedisModule_CallReplyInteger(r) == 0);
r = RedisModule_Call(ctx, "strpop", "c", "bar");
RMUtil_Assert(RedisModule_CallReplyType(r) == REDISMODULE_REPLY_NULL);
r = RedisModule_Call(ctx, "FLUSHALL", "");

return 0;
}

int TestModule(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
RedisModule_AutoMemory(ctx);

Expand All @@ -564,6 +623,7 @@ int TestModule(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
RMUtil_Test(testChop);
RMUtil_Test(testPrepend);
RMUtil_Test(testSetRangeRand);
RMUtil_Test(testStrPop);

RedisModule_ReplyWithSimpleString(ctx, "PASS");
return REDISMODULE_OK;
Expand All @@ -589,6 +649,10 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx) {
"write fast deny-oom", 1, 1,
1) == REDISMODULE_ERR)
return REDISMODULE_ERR;
if (RedisModule_CreateCommand(ctx, "strpop", StrPopCommand,
"fast deny-oom", 1, 1,
1) == REDISMODULE_ERR)
return REDISMODULE_ERR;
if (RedisModule_CreateCommand(ctx, "rxstrings.test", TestModule, "write", 0,
0, 0) == REDISMODULE_ERR)
return REDISMODULE_ERR;
Expand Down

0 comments on commit 0a650a5

Please sign in to comment.