Serializer requires class to be defined, so it has to be in .h file. It
also does not support nested types yet, so move it outside of containing
class.
Refs #752
Paged aggregate queries will re-use the partition_slice object,
thus when setting a specific ck range for "last pk", we will hit
an exception case.
Allow removing entries (actually only the one), and overwriting
(using schema equality for keys), so we maintain the interface
while allowing the pager code to re-set the ck range for previous
page pass.
[tgrabiec: commit log cleanup, fixed issue ref]
Message-Id: <1452616259-23751-1-git-send-email-calle@scylladb.com>
The intent is to make data returned by queries always conform to a
single schema version, which is requested by the client. For CQL
queries, for example, we want to use the same schema which was used to
compile the query. The other node expects to receive data conforming
to the requested schema.
Interface on shard level accepts schema_ptr, across nodes we use
table_schema_version UUID. To transfer schema_ptr across shards, we
use global_schema_ptr.
Because schema is identified with UUID across nodes, requestors must
be prepared for being queried for the definition of the schema. They
must hold a live schema_ptr around the request. This guarantees that
schema_registry will always know about the requested version. This is
not an issue because for queries the requestor needs to hold on to the
schema anyway to be able to interpret the results. But care must be
taken to always use the same schema version for making the request and
parsing the results.
Schema requesting across nodes is currently stubbed (throws runtime
exception).
Allows for having more than one clustering row range set, depending on
PK queried (although right now limited to one - which happens to be exactly
the number of mutiplexing paging needs... What a coincidence...)
Encapsulates the row_ranges member in a query function, and if needed holds
ranges outside the default one in an extra object.
Query result::builder::add_partition now fetches the correct row range for
the partition, and this is the range used in subsequent iteration.
Use C++11's std::declval<T>() instead of my ad-hoc scary-looking
idiom *(T*)nullptr.
Both techniques produce an object of type T which is only useful for
unevaluated contexts, only inspecting an object's type and not is value.
For example, in decltype() expressions.
Signed-off-by: Nadav Har'El <nyh@cloudius-systems.com>
Amazing how many errors a short of piece of code can have, without the
compiler complaining at all. The magic of templates :-)
Signed-off-by: Nadav Har'El <nyh@cloudius-systems.com>
Some methods in storage_service.cc want to return an
unordered_set<query::range<dht::token>>. This patch adds the missing
hash function for a query::range<T> to make it usable as a hash-table key.
The hash function we used is a trivial linear combination of the range's
start and end hash function - the same function used by Cassandra's
AbstractBounds.hashCode() so it is probably "good enough".
Signed-off-by: Nadav Har'El <nyh@cloudius-systems.com>
In Origin, dht.Range() with equal values is considered a full wrap
around. Make our range<> recognize this.
So we have:
]x; x] - wrap around, full ring
[x; x[ - wrap around, full ring
]x; x[ - wrap around, excluding x
[x; x] - not wrap around, only x included
It should be moved to i_partitioner.hh, but to do that range<> has to
be first moved out of query-request.hh to break cyclic dependency.
I didn't want to cause conflicts with in-flight patches to range<>.
range::is_wrap_around() and range::contains() rely on total ordering
on values to work properly. Current ring_position_comparator was only
imposing a weak ordering (token positions equal to all key positions
with that token).
range::before() and range::after() can't work for weak ordering. If
the bound is exclusive, we don't know if user-provided token position
is inside or outside.
Also, is_wrap_around() can't properly detect wrap around in all
cases. Consider this case:
(1) ]A; B]
(2) [A; B]
For A = (tok1) and B = (tok1, key1), (1) is a wrap around and (2) is
not. Without total ordering between A and B, range::is_wrap_around() can't
tell that.
I think the simplest soution is to define a total ordering on
ring_position by making token positions positioned either before or
after all keys with that token.
Singular range is a range of the form [x; x]. Internally such ranges
are optimized to avoid storing the value twice, so _end is empty.
Client shouldn't have to special case for it if it's not interested,
so make end() and split() work for singular ranges too.
query::range::serialized_size() calls a template method (also
called serialized_size()) within a lambda, however it is called with
a const 'this' while the template is non-const-qualified. gcc 5
rightly rejects it (nicely annotating the template as a near miss).
Fix by making the template static; it doesn't need 'this' anyway.
This change abstracts reading from on-disk data sources behind a single
reader which is then composed with memtable readers. This change also
abstracts all data sources behind a single reader obtained via
column_family::make_reader(). That reader is then used by algorithms
like column_family::for_all_partitions() or
column_family::query(). Having those abstractions will make it easier
to add row cache, because it will be encapsulated in a single place.
Current model was not really correct because Origin doesn't support
querying of partition ranges by their value. We can query slices
according to dht::decorated_key ordering, which orders partitions
first by token then by key value.
ring_position encapsulates range constraint. Key value is optional, in
which case only token is constrained.
partitions_ranges will be manipulated upon to be split for different
destination, so provide it separately from read_command to not copy the
later for each destination.