-
Notifications
You must be signed in to change notification settings - Fork 353
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unintuitive bound handling on multiindex - failing test #429
Conversation
13a3009
to
4cbecbe
Compare
No, this is correct, because you're setting the max value of the full key.
To make it work, you need to set a value greater than the (current) full key, either inclusively or exclusively, i.e. Also notice that this is limited / poor, as to include the full range inclusively in all cases it is not enough with setting "z". You would have to build some string with the max possible length of the key, will all Now, if you want to keep the first element of the index fixed, it's just simple / better to use a let items: Vec<_> = map
.idx
.secondary
.prefix(U64Key::new(1))
.range(
&store,
None,
None,
Order::Ascending,
)
.collect::<Result<_, _>>()
.unwrap(); |
None, | ||
Some(Bound::inclusive((U64Key::new(1), vec![]).joined_key())), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
None, | |
Some(Bound::inclusive((U64Key::new(1), vec![]).joined_key())), | |
Some(Bound::inclusive((U64Key::new(1), vec![]).joined_key())), | |
None, |
or
None, | |
Some(Bound::inclusive((U64Key::new(1), vec![]).joined_key())), | |
None, | |
Some(Bound::inclusive((U64Key::new(2), vec![]).joined_key())), |
are both correct. And "intuitive".
I think you misunderstood me - I exactly understand why it works such way. The problem is, that I find it faulty, that there is no proper tool to set exclusive upper bound for the secondary key while iterating over range. In most cases if I need this kind of upper bound I have no idea about the upper bound of primary index, as if I know - I iterate over secondary index, because I know nothing about the primary one and I don't care about it. And I cannot fix the prefix of the index - I have no knowledge about primary key at all, I want to fully disregard it. Basically my point is: I would really appreciate atom which behaves like Also the second point is: there is no usecase for using |
I agree it's a limited / poor implementation. I've said it above. But it's a working one (as far as I can tell). One thing is for it to be poor / limited / unintuitive, and another is for it to be broken. That said, I would very much like to get rid of the pk as part of the key. I tried and failed to do it in the past. See #211. Finally after a lot of work and attempts we settled with the currrent impl. The pk should be used internally. But that requires using some generics magic (something like nested generics / types) that I don't know how to do yet. Or even, if it's possible to do.
Perhaps a helper like |
Now that we'll have deserialized keys (see #432 ) we can probably use them in the We wouldn"t handle them fully internally, but at least there will be a way to avoid dealing with their internal representation. |
After reflecting on this a bit more, I agree this is an error calling the wrong function. The big hint is you using
However, this PR demonstrates that we have a missing method in the API: If we have My reasoning for bounds, when translating them to &[u8] for the underlying storage are:
actually, that is only for Order::Ascending. Maybe for Order::Descending these must change?? Happy if you want to try implementing such a function, so we could just: let items: Vec<_> = map.idx.secondary.range(&store, None, Some(Bound::inclusive(U64Key::new(1))), Order::Ascending).collect(); |
I agree this will make things nicer for the caller and would be a good issue. But is a bit orthogonal issue to the issue with bounds. |
This is resolved with #446 |
Prove test, the simplest I managed to provide.
The test scenario logic:
Have a multi index map indexed with some arbitrary index (
&str
in the example), and mapped to some value (u64
in the test). The map can be however indexed by value itself - the secondary multiindex is created for this case. On range call I want to take all items with secondary items up to particular value, but it won't work - as it requires to provide second part of key, which is also a part of a bound. In practice if I call range this way, I don't know the "upper bound" of the primary index (it would be basically the highest index in the map), and it makesBound::inclusive
unuseable with many multi-index cases. Obviously in this very test I can fix it by changingvec![]
tob"one".to_owned()
, or evenb"z".to_owned()
, but it is a trap, as there is no guarantee in real world, that there is no item of index"Zumba"
which should be inlcuded in range.Currently the only workaround I see is never use
Bound::inclusive
for multi-index, and always useBound::exclusive(key+1)
but it is completely unintuitive, and even possibly not easy for more complex multi-keys.