- Notifications
You must be signed in to change notification settings - Fork 43
Add logical types. Minor improvements. #34
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
Conversation
can you give us a rational for implementing this into velocypack ? I feel this is a sbustantial change and we need to understand this better |
seems to me like the application should know the schema ahead of time, no ? |
The use case for this is applications where schema is not explicitly defined or is defined only partially, so the database driver will need additional information to deserialize the values properly. The timestamp issue given above is a classical example. It can be solved either by having a dedicated type (like VelocyPack has) or by having a tag that signals that the integer that has been stored is a timestamp. The latter way also allows defining application-specific types and types that would not be very useful at a format level (like an age or a height type). This is highly useful in simpler applications where one can get away with not explicitly specifying the schema and different abstractions, basically the MongoDB use case. But it assumes that what goes into the database comes out of there with the exact same classes, otherwise it will get very clumsy. Regarding immutable buffers, I checked and turns out I don't have a use case for them any more, not sure what exactly they were for. I will update the pull request accordingly. |
Any updates on this? |
@siilike : sorry, all blame is on me, because I forgot to have a look at this PR. |
Great, there are some changes still missing to make it work with the latest changes in master. |
Now it is all updated. The only downside of the current implementation is that Slice supports transparency for only one level of tags, otherwise every access to _start would require iteration. |
src/Collection.cpp Outdated
return false; | ||
} | ||
| ||
bool Collection::containsObject(Slice const& slice, Slice const& other) { |
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.
should this be renamed to containsSubobject
?
include/velocypack/Collection.h Outdated
| ||
static bool contains(Slice const& slice, Slice const& other); | ||
| ||
static bool containsObject(Slice const& slice, Slice const& other); |
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.
should this be renamed to containsSubobject
?
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.
I checked and I actually don't have any use for this method, so I removed it for now.
I was also thinking that it is rather confusing to have array and object methods in the same class as they are not compatible, e.g. it is not possible to filter() or concat() an object, so it would make sense to either add support for objects to all methods or create an entire separate class for handling the same operations for objects.
In general, I think the idea of tags makes sense for some applications. |
And finally, we must add tests for tagged values and for the new method in |
if it helps, I am also happy to split up this multi-purpose PR into multiple small single-purpose PRs. That way we can already merge the following bits quickly, without having to wait for the bigger tags change:
|
Thank you for reviewing. The idea of making the tags transparent by default was that it makes working with the values a lot simpler. Otherwise there would need to be a method that returns the value if tagged and otherwise the object itself which would clutter the code and be an easy source of errors if the value initially isn't tagged, but becomes at some point. But the important part is that is* and get* methods apply to the value of the tagged value, not the tagged value itself, so start(), end() and others can be reverted to apply to the whole value. This way we'll have enough compatibility with existing solutions and convenient access to values. |
Fix first issues Co-Authored-By: Jan <jsteemann@users.noreply.github.com>
I removed the exception from Slice.tagOffset, because the only time when there can be an error is when a new tagged type is added to SliceStaticData.TypeMap and that method is not updated. This removes all the headache of noexcept. I now updated the transparency logic as follows:
If that is fine I'll also update Slice.cpp and any references elsewhere. |
ping |
include/velocypack/Slice.h Outdated
constexpr inline bool isType(ValueType t) const noexcept { | ||
return SliceStaticData::TypeMap[*start()] == t; | ||
constexpr inline bool isType(ValueType t) const { | ||
return SliceStaticData::TypeMap[*valueStart()] == t; |
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.
If this should include tags, then I think it should be
return SliceStaticData::TypeMap[*start()] == t;
include/velocypack/Slice.h Outdated
// get the type for the slice (excluding tags) | ||
constexpr inline ValueType type() const noexcept { | ||
return SliceStaticData::TypeMap[head()]; | ||
return type(valueHead()); |
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.
The changed implementation in the PR changes the behavior of this method to return the type after jumping over the tag. This will make it non-downwards compatible. I think it should be reverted to:
return type(valueHead()); | |
return SliceStaticData::TypeMap[head()]; |
include/velocypack/Slice.h Outdated
return SliceStaticData::TypeMap[h]; | ||
| ||
// get the type for the slice (including tags) | ||
constexpr inline ValueType rawType() const noexcept { |
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.
This should probably be renamed to valueType
and return the type of the tagged value.
include/velocypack/Slice.h Outdated
| ||
// check if slice is the Boolean value true | ||
constexpr bool isTrue() const noexcept { return head() == 0x1a; } | ||
constexpr bool isTrue() const noexcept { return valueHead() == 0x1a; } |
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.
I think this should still operate on head()
and not on valueHead()
.
If a client application needs to peek into the value behind the tag, I think it should explicitly resolve the tag.
include/velocypack/Slice.h Outdated
// return the value for a String object | ||
char const* getString(ValueLength& length) const { | ||
uint8_t const h = head(); | ||
uint8_t const h = valueHead(); |
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.
I think this should still operate on head()
and not on valueHead()
.
If a client application needs to peek into the value behind the tag, I think it should explicitly resolve the tag.
include/velocypack/Slice.h Outdated
if (h == 0xbf) { | ||
// long UTF-8 String | ||
length = readIntegerFixed<ValueLength, 8>(_start + 1); | ||
length = readIntegerFixed<ValueLength, 8>(valueStart() + 1); |
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.
I think this should still operate on start()
and not on valueStart()
.
If a client application needs to peek into the value behind the tag, I think it should explicitly resolve the tag.
include/velocypack/Slice.h Outdated
length = readIntegerFixed<ValueLength, 8>(valueStart() + 1); | ||
checkOverflow(length); | ||
return reinterpret_cast<char const*>(_start + 1 + 8); | ||
return reinterpret_cast<char const*>(valueStart() + 1 + 8); |
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.
I think this should still operate on start()
and not on valueStart()
.
If a client application needs to peek into the value behind the tag, I think it should explicitly resolve the tag.
include/velocypack/Slice.h Outdated
| ||
char const* getStringUnchecked(ValueLength& length) const noexcept { | ||
uint8_t const h = head(); | ||
uint8_t const h = valueHead(); |
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.
I think this should still operate on head()
and not on valueHead()
.
If a client application needs to peek into the value behind the tag, I think it should explicitly resolve the tag.
include/velocypack/Slice.h Outdated
// short UTF-8 String | ||
length = h - 0x40; | ||
return reinterpret_cast<char const*>(_start + 1); | ||
return reinterpret_cast<char const*>(valueStart() + 1); |
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.
I feel I am repeating the same sentence here over and over 😄
The same argument applies for most of the following functions.
Pushed the third take on this:
If this is fine I'll also update Builder. |
Turns out this overriding idea does not work. The start() method would have to be virtual which would mean the removal of constexpr and sizeof(arangodb::velocypack::Slice) != sizeof(void*). |
OK, I got rid of ValueSlice for now as I can temporarily give up the convenience until I find the time to resolve this. So, please review the tests and merge if everything is fine. |
Hi @siilike Many thanks for contributing. We are obliged by law to have a signed scanned copy of a Contributor License Agreement (CLA) to be able to accept pull requests to the official ArangoDB repository - We use an Apache 2 CLA for ArangoDB and its companion projects, which can be found here: https://www.arangodb.com/documents/cla.pdf Thank you |
CLA available |
Ping |
Still waiting. |
Yet another week has gone by. |
@siilike : Hi, sorry for the delay. I am currently busy with lots of other things as we are preparing a release. I will make time to look into this on either Wed or Thu this week. Sorry again! |
Great, thanks. I made a separate pull request for the specification change, so we can continue with arangodb/java-velocypack#15 in the meantime. |
@siilike : thanks for your patience! I left a few comments, but apart from these small issues I think it is good to go now. |
Great, thank you. I made the fixes. |
Thanks a lot for the patch! |
What's new:
From the documentation:
Tagging is implemented transparently -- operations on a Slice are unaffected and performed on the value of the tagged type, not on the type itself.
Looking forward to having this merged quickly.