Skip to content

Commit ad5d6f1

Browse files
authored
Enable JSON.CLEAR on numeric scalars (RedisJSON#605)
* Fixes for updated RedisJsonHdt (2) * Fix keyspace notifications test
1 parent 9e149c7 commit ad5d6f1

File tree

7 files changed

+58
-8
lines changed

7 files changed

+58
-8
lines changed

src/commands.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1882,8 +1882,11 @@ pub fn command_json_clear<M: Manager>(
18821882
.get_value()?
18831883
.ok_or_else(RedisError::nonexistent_key)?;
18841884

1885-
let paths = find_paths(path, root, |v| {
1886-
v.get_type() == SelectValueType::Array || v.get_type() == SelectValueType::Object
1885+
let paths = find_paths(path, root, |v| match v.get_type() {
1886+
SelectValueType::Array | SelectValueType::Object => v.len().unwrap() > 0,
1887+
SelectValueType::Long => v.get_long() != 0,
1888+
SelectValueType::Double => v.get_double() != 0.0,
1889+
_ => false,
18871890
})?;
18881891
let mut cleared = 0;
18891892
if !paths.is_empty() {

src/ivalue_manager.rs

+4
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,10 @@ impl<'a> WriteHolder<IValue, IValue> for IValueKeyHolderWrite<'a> {
446446
cleared += 1;
447447
Ok(Some(v))
448448
}
449+
ValueType::Number => {
450+
cleared += 1;
451+
Ok(Some(IValue::from(0)))
452+
}
449453
_ => Ok(Some(v)),
450454
})?;
451455
Ok(cleared)

src/lib.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@ pub mod redisjson;
3030

3131
pub const GIT_SHA: Option<&'static str> = std::option_env!("GIT_SHA");
3232
pub const GIT_BRANCH: Option<&'static str> = std::option_env!("GIT_BRANCH");
33+
pub const MODULE_NAME: &'static str = "ReJSON";
34+
pub const MODULE_TYPE_NAME: &'static str = "ReJSON-RL";
3335

3436
pub const REDIS_JSON_TYPE_VERSION: i32 = 3;
3537

3638
pub static REDIS_JSON_TYPE: RedisType = RedisType::new(
37-
"ReJSON-RL",
39+
MODULE_TYPE_NAME,
3840
REDIS_JSON_TYPE_VERSION,
3941
RedisModuleTypeMethods {
4042
version: redis_module::TYPE_METHOD_VERSION,
@@ -456,7 +458,7 @@ macro_rules! redis_json_module_create {(
456458
}
457459

458460
redis_module! {
459-
name: "ReJSON",
461+
name: crate::MODULE_NAME,
460462
version: $version,
461463
data_types: [$($data_type,)*],
462464
init: json_init_config,

src/manager.rs

+4
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,10 @@ impl<'a> WriteHolder<Value, Value> for KeyHolderWrite<'a> {
506506
cleared += 1;
507507
Ok(Some(Value::from(arr)))
508508
}
509+
Value::Number(mut _num) => {
510+
cleared += 1;
511+
Ok(Some(Value::from(0)))
512+
}
509513
_ => Ok(Some(v)),
510514
})?;
511515
Ok(cleared)

tests/pytest/test.py

+30-1
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ def testClear(env):
475475
r.expect('JSON.CLEAR', 'test', '$.arr[2].n').equal(1)
476476
r.expect('JSON.CLEAR', 'test', '$.arr[3].n2.n').equal(1)
477477

478-
# Fail clear on inappropriate path (not obj or arr)
478+
# No clear on inappropriate path (not obj or arr or numeric)
479479
r.expect('JSON.CLEAR', 'test', '$.arr[1]').equal(0)
480480

481481
# Make sure specific obj content was cleared
@@ -516,6 +516,35 @@ def testClear(env):
516516
# Key doesn't exist
517517
r.expect('JSON.CLEAR', 'not_test_key', '$').raiseError()
518518

519+
def testClearScalar(env):
520+
"""Test JSON.CLEAR command for scalars"""
521+
522+
r = env
523+
r.assertOk(r.execute_command('JSON.SET', 'test', '$', json.dumps(docs['basic'])))
524+
# Clear numeric values
525+
r.assertEqual(r.execute_command('JSON.CLEAR', 'test', '$.int'), 1)
526+
r.assertEqual(r.execute_command('JSON.GET', 'test', '$.int'), '[0]')
527+
528+
r.assertEqual(r.execute_command('JSON.CLEAR', 'test', '$.num'), 1)
529+
r.assertEqual(r.execute_command('JSON.GET', 'test', '$.num'), '[0]')
530+
531+
r.assertEqual(r.execute_command('JSON.CLEAR', 'test', '$..a'), 1)
532+
r.assertEqual(r.execute_command('JSON.GET', 'test', '$..a'), '[0]')
533+
534+
r.assertOk(r.execute_command('JSON.SET', 'test', '$', json.dumps(docs['scalars'])))
535+
r.assertEqual(r.execute_command('JSON.CLEAR', 'test', '$.*'), 2)
536+
res = r.execute_command('JSON.GET', 'test', '$.*')
537+
r.assertEqual(json.loads(res), ['string value', None, True,0, 0])
538+
539+
# Do not clear already cleared values
540+
r.assertEqual(r.execute_command('JSON.CLEAR', 'test', '$.*'), 0)
541+
542+
# Do not clear other scalars
543+
r.assertEqual(r.execute_command('JSON.CLEAR', 'test', '$.none'), 0)
544+
r.assertEqual(r.execute_command('JSON.CLEAR', 'test', '$.bool'), 0)
545+
r.assertEqual(r.execute_command('JSON.CLEAR', 'test', '$.string'), 0)
546+
547+
519548
def testArrayCRUD(env):
520549
"""Test JSON Array CRUDness"""
521550

tests/pytest/test_keyspace_notifications.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ def test_keyspace_arr(env):
101101
assert_msg(env, pubsub.get_message(timeout=1), 'pmessage', 'json.clear')
102102
assert_msg(env, pubsub.get_message(timeout=1), 'pmessage', 'test_key_arr')
103103

104+
env.assertEqual(1, r.execute_command('JSON.CLEAR', 'test_key_arr', '$.bar')) # Not an array
105+
assert_msg(env, pubsub.get_message(timeout=1), 'pmessage', 'json.clear')
106+
assert_msg(env, pubsub.get_message(timeout=1), 'pmessage', 'test_key_arr')
107+
104108
env.assertEqual([None], r.execute_command('JSON.ARRPOP', 'test_key_arr', '$.foo')) # Empty array
105109
env.assertEqual(None, pubsub.get_message(timeout=1))
106110
env.assertEqual([None], r.execute_command('JSON.ARRPOP', 'test_key_arr', '$')) # Not an array
@@ -114,9 +118,7 @@ def test_keyspace_arr(env):
114118
env.assertEqual([None], r.execute_command('JSON.ARRAPPEND', 'test_key_arr', '$.bar', '"barian"')) # Not an array
115119
env.assertEqual(None, pubsub.get_message(timeout=1))
116120
env.assertEqual([None], r.execute_command('JSON.ARRPOP', 'test_key_arr', '$.bar')) # Not an array
117-
env.assertEqual(None, pubsub.get_message(timeout=1))
118-
env.assertEqual(0, r.execute_command('JSON.CLEAR', 'test_key_arr', '$.bar')) # Not an array
119-
env.assertEqual(None, pubsub.get_message(timeout=1))
121+
env.assertEqual(None, pubsub.get_message(timeout=1))
120122

121123

122124
def test_keyspace_del(env):

tests/pytest/test_multi.py

+6
Original file line numberDiff line numberDiff line change
@@ -742,13 +742,19 @@ def testClearCommand(env):
742742
r.assertEqual(res, 3)
743743
res = r.execute_command('JSON.GET', 'doc1', '$')
744744
r.assertEqual(json.loads(res), [{"nested1": {"a": {}}, "a": [], "nested2": {"a": "claro"}, "nested3": {"a": {}}}])
745+
# Not clearing already cleared values
746+
res = r.execute_command('JSON.CLEAR', 'doc1', '$..a')
747+
r.assertEqual(res, 0)
745748

746749
# Test single
747750
r.assertOk(r.execute_command('JSON.SET', 'doc1', '$', '{"nested1": {"a": {"foo": 10, "bar": 20}}, "a":["foo"], "nested2": {"a": "claro"}, "nested3": {"a": {"baz":50}}}'))
748751
res = r.execute_command('JSON.CLEAR', 'doc1', '$.nested1.a')
749752
r.assertEqual(res, 1)
750753
res = r.execute_command('JSON.GET', 'doc1', '$')
751754
r.assertEqual(json.loads(res), [{"nested1": {"a": {}}, "a": ["foo"], "nested2": {"a": "claro"}, "nested3": {"a": {"baz": 50}}}])
755+
# Not clearing already cleared values
756+
res = r.execute_command('JSON.CLEAR', 'doc1', '$.nested1.a')
757+
r.assertEqual(res, 0)
752758

753759
# Test missing path (defaults to root)
754760
res = r.execute_command('JSON.CLEAR', 'doc1')

0 commit comments

Comments
 (0)