aerospike / aerospike-client-rust

Rust client for the Aerospike database
https://www.aerospike.com/
Other
82 stars 26 forks source link

`expressions::cond` with `cdt_context::ctx_map_key` not working as expected #109

Closed databasedav closed 2 years ago

databasedav commented 2 years ago

this is a repost from https://github.com/aerospike/aerospike-client-rust/issues/104#issuecomment-873337144 since it's a more specific issue about the expressions branch PR https://github.com/aerospike/aerospike-client-rust/pull/100

here's a repro with aerospike:ce-5.6.0.13

#[test]
fn test2() {
    use aerospike::{self, expressions, operations::{self, maps, cdt_context, lists}};

    let ac = aerospike::Client::new(
        &aerospike::ClientPolicy::default(), &"0.0.0.0:3000".to_string()
    ).unwrap();
    let key = aerospike::as_key!("test", "test", "test");
    ac.put(
        &aerospike::WritePolicy::default(),
        &key,
        &[aerospike::as_bin!("bin", aerospike::as_map!())]
    ).unwrap();
    ac.operate(
        &aerospike::WritePolicy::default(),
        &key,
        &[
            operations::exp::write_exp(
                "bin",
                &expressions::cond(
                    vec![
                        expressions::eq(
                            expressions::maps::get_by_key(
                                maps::MapReturnType::Count,
                                expressions::ExpType::INT,
                                expressions::string_val("key".to_string()),
                                expressions::map_bin("bin".to_string()),
                                &[]
                            ),
                            expressions::int_val(0)
                        ),
                        expressions::maps::put(
                            &maps::MapPolicy::default(),
                            expressions::string_val("key".to_string()),
                            expressions::list_val(vec![]),
                            expressions::map_bin("bin".to_string()),
                            &[]
                        ),
                        expressions::unknown(),
                    ]
                ),
                operations::exp::ExpWriteFlags::Default
            ),
            operations::lists::append(
                &operations::lists::ListPolicy::new(
                    operations::lists::ListOrderType::Ordered,
                    operations::lists::ListWriteFlags::Default
                ),
                "bin",
                &aerospike::as_val!("val")
            )
            .set_context(&[
                cdt_context::ctx_map_key(aerospike::as_val!("key")),
            ])
        ]
    ).unwrap();
    println!("{:?}", ac.get(&aerospike::ReadPolicy::default(), &key, aerospike::Bins::All).unwrap().bins);
    ac.operate(
        &aerospike::WritePolicy::default(),
        &key,
        &[
            operations::lists::remove_by_value(
                "bin", &aerospike::as_val!("val"), operations::lists::ListReturnType::None
            ).set_context(&[operations::cdt_context::ctx_map_key(aerospike::as_val!("key"))]),
        ]
    ).unwrap();
    println!("{:?}", ac.get(&aerospike::ReadPolicy::default(), &key, aerospike::Bins::All).unwrap().bins);
    ac.operate(
        &aerospike::WritePolicy::default(),
        &key,
        &[
            operations::exp::write_exp(
                "bin",
                &expressions::cond(vec![
                    expressions::eq(
                        expressions::lists::size(
                            expressions::map_bin("bin".to_string()),
                            &[operations::cdt_context::ctx_map_key(aerospike::as_val!("key"))]
                        ),
                        expressions::int_val(0)
                    ),
                    expressions::maps::remove_by_key(
                        expressions::string_val("key".to_string()),
                        expressions::map_bin("bin".to_string()),
                        &[]
                    ),
                    expressions::unknown()
                ]),
                operations::exp::ExpWriteFlags::EvalNoFail
            )
        ]
    ).unwrap();
    println!("{:?}", ac.get(&aerospike::ReadPolicy::default(), &key, aerospike::Bins::All).unwrap().bins);
}

output:

{"bin": HashMap({String("key"): List([String("val")])})}
{"bin": HashMap({String("key"): List([])})}
thread 'tests::store::test2' panicked at 'index out of bounds: the len is 125 but the index is 125', .../.cargo/git/checkouts/aerospike-client-rust-34a63ba2784a38de/231a73e/src/commands/buffer.rs:1330:9

the failing removal write expression works fine using the python client

import aerospike
from aerospike_helpers import cdt_ctx, expressions
from aerospike_helpers.operations import expression_operations

ac = aerospike.client({'hosts': [('localhost', 3000)]})
ac.connect()
key = ('test', 'test', 'test')
ac.put(key, {'bin': {'key': []}})
print(ac.get(key)[2])
ac.operate(
    key,
    [
        expression_operations.expression_write(
            'bin',
            expressions.Cond(
                expressions.Eq(expressions.ListSize([cdt_ctx.cdt_ctx_map_key('key')], expressions.MapBin('bin')), 0),
                expressions.MapRemoveByKey(None, 'key', 'bin'),
                expressions.Unknown()
            ).compile(),
            aerospike.EXP_WRITE_EVAL_NO_FAIL
        )
    ]
)
print(ac.get(key)[2])
{'bin': {'key': []}}
{'bin': {}}

so this isn't a problem with expressions::cond in general since the initial map put works fine and replacing

expressions::lists::size(
    expressions::map_bin("bin".to_string()),
    &[operations::cdt_context::ctx_map_key(aerospike::as_val!("key"))]
)

with expressions::int_val(0) (a trivial equality) works as expected

{"bin": HashMap({String("key"): List([String("val")])})}
{"bin": HashMap({String("key"): List([])})}
{"bin": HashMap({})}

and cdt_context::ctx_map_key works in different contexts (like the initial list append) so i'm lead to believe it's something about the combo of the two

jonas32 commented 2 years ago

Sorry for the delay, i found the problem. Its fixed on my PR branch on #100 I forgot to resize the buffer when writing contexts in expressions. There is a second bug related to contexts thats fixed by #111 in case you run into that problem. Its only related to ctx_map_key_create.