1
1
#[ macro_use]
2
2
extern crate redismodule;
3
3
4
- use redismodule:: { Context , RedisResult , NextArg , REDIS_OK } ;
4
+ use redismodule:: { Context , RedisResult , NextArg , REDIS_OK , RedisError } ;
5
5
use redismodule:: native_types:: RedisType ;
6
6
7
7
mod redisjson;
@@ -10,26 +10,45 @@ use crate::redisjson::RedisJSON;
10
10
11
11
static REDIS_JSON_TYPE : RedisType = RedisType :: new ( "RedisJSON" ) ;
12
12
13
+ #[ derive( Debug , PartialEq ) ]
14
+ pub enum SetOptions {
15
+ NotExists ,
16
+ AlreadyExists ,
17
+ }
18
+
13
19
fn json_set ( ctx : & Context , args : Vec < String > ) -> RedisResult {
14
20
let mut args = args. into_iter ( ) . skip ( 1 ) ;
15
21
16
22
let key = args. next_string ( ) ?;
17
23
let _path = args. next_string ( ) ?; // TODO handle this path
18
24
let value = args. next_string ( ) ?;
19
25
26
+ let set_option = args. next ( )
27
+ . map ( |op| {
28
+ match op. to_uppercase ( ) . as_str ( ) {
29
+ "NX" => Ok ( SetOptions :: NotExists ) ,
30
+ "XX" => Ok ( SetOptions :: AlreadyExists ) ,
31
+ _ => Err ( RedisError :: Str ( "ERR syntax error" ) ) ,
32
+ }
33
+ } )
34
+ . transpose ( ) ?;
35
+
20
36
let key = ctx. open_key_writable ( & key) ;
37
+ let current = key. get_value :: < RedisJSON > ( & REDIS_JSON_TYPE ) ?;
21
38
22
- match key. get_value :: < RedisJSON > ( & REDIS_JSON_TYPE ) ? {
23
- Some ( doc) => {
39
+ match ( current, set_option) {
40
+ ( Some ( _) , Some ( SetOptions :: NotExists ) ) => Ok ( ( ) . into ( ) ) ,
41
+ ( Some ( ref mut doc) , _) => {
24
42
doc. set_value ( & value) ?;
43
+ REDIS_OK
25
44
}
26
- None => {
45
+ ( None , Some ( SetOptions :: AlreadyExists ) ) => Ok ( ( ) . into ( ) ) ,
46
+ ( None , _) => {
27
47
let doc = RedisJSON :: from_str ( & value) ?;
28
48
key. set_value ( & REDIS_JSON_TYPE , doc) ?;
49
+ REDIS_OK
29
50
}
30
51
}
31
-
32
- REDIS_OK
33
52
}
34
53
35
54
fn json_get ( ctx : & Context , args : Vec < String > ) -> RedisResult {
0 commit comments