The iterator doesn't really allow modifying unserlying component.
This change enables using the iterator with boost::make_iterator_range() and
boost::range::join(), which get utterly confused otherwise.
For simplicity, we want to have keys serializable and deserializable
without schema for now. We will serialize keys in a generic form of a
vector of components where the format of components is specified by
CQL binary protocol. So conversion between keys and vector of
components needs to be possible to do without schema.
We may want to make keys schema-dependent back in the future to apply
space optimizations specific to column types. Existing code should
still pass schema& to construct and access the key when possible.
One optimization had to be reverted in this change - avoidance of
storing key length (2 bytes) for single-component partition keys. One
consequence of this, in addition to a bit larger keys, is that we can
no longer avoid copy when constructing single-component partition keys
from a ready "bytes" object.
I haven't noticed any significant performance difference in:
tests/perf/perf_simple_query -c1 --write
It does ~130K tps on my machine.
All components of prefixable compound type are preceeded by their
length what makes them not byte order comparable.
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
We use boost::any to convert to and from database values (stored in
serlialized form) and native C++ values. boost::any captures information
about the data type (how to copy/move/delete etc.) and stores it inside
the boost::any instance. We later retrieve the real value using
boost::any_cast.
However, data_value (which has a boost::any member) already has type
information as a data_type instance. By teaching data_type intances about
the corresponding native type, we can elimiante the use of boost::any.
While boost::any is evil and eliminating it improves efficiency somewhat,
the real goal is growing native type support in data_type. We will use that
later to store native types in the cache, enabling O(log n) access to
collections, O(1) access to tuples, and more efficient large blob support.
_v.begin() points to the next element. If the size of last element
in a compound is zero then iterators pointing to second to last and
last element would seem equal. To fix this we also have to compare
_types_left.
Signed-off-by: Paweł Dziepak <pdziepak@cloudius-systems.com>
reversed types can be byte_comparable, but in this case we should
invert the order of the comparation.
One alternative here, of course, would be to just declare all reversed types
non-byte comparable. That would definitely be safer, but at the expense of
always having more expensive comparisons for inverted orders.
Signed-off-by: Glauber Costa <glommer@cloudius-systems.com>
Also replace derived types (map_type, collection_type, etc.).
As we'll change data_type's definition, this reduces the number of places
that need to be modified later, and is more readable.
We didn't handle properly the case when the last component of a
prefixable compound was empty. Because we do not encode component's
length, we did not distinguish a compound with last element empty from
a compound without the last element.
The fix is to always encode lengths in prefixable tuples.