Commit Graph

30209 Commits

Author SHA1 Message Date
Piotr Dulikowski
dd860c70ce abstract_read_executor::reconcile: resultise handling of data_resolver->done()
Now, the logic of handling exceptions returned in reconcile() from
data_resolver->done() was changed so that the failed result does not
need to be converted to an exceptional future.
2022-02-22 16:08:52 +01:00
Piotr Dulikowski
5accfd8dae abstract_read_executor::execute: resultify handling of data_resolver->done()
Now, the logic of handling exceptions returned in execute() from
data_resolver->done() was changed so that the failed result does not
need to be converted to an exceptional future.
2022-02-22 16:08:52 +01:00
Piotr Dulikowski
a304fbfed3 result_combinators: add result_discard_value
Adds a utils::result_discard_value, which is an alternative to
future::discard_result which just ignores the "success" value of the
provided result and does not ignore the exception.
2022-02-22 16:08:52 +01:00
Piotr Dulikowski
ee2c4725c3 abstract_read_executor: resultify _result_promise
Adjusts the type of _result_promise so that it holds a result.
2022-02-22 16:08:52 +01:00
Piotr Dulikowski
e7f960d041 abstract_read_executor: return result from done() 2022-02-22 16:08:52 +01:00
Piotr Dulikowski
28d562ddf6 abstract_read_resolver: fail promises by passing exception as value
Now, on read timeouts and failures, _cl_promise and _done_promise is set
to a failed result instead of an exceptional promise.
2022-02-22 16:08:52 +01:00
Piotr Dulikowski
5438973c9d abstract_read_resolver: resultify promises
Changes the types of _done_promise and _cl_promise so that they hold a
result.
2022-02-22 16:08:52 +01:00
Piotr Dulikowski
4c58683102 exceptions: make it possible to return read_{timeout,failure}_exception as value
Adds read_timeout_exception and read_failure exception to the list of
exceptions supported by the coordinator_exception_container.

Those exceptions are not yet returned-as-value anywhere, but they will
be in the commits that follow.
2022-02-22 16:08:52 +01:00
Piotr Dulikowski
1e1f5b4a48 result_try: add as_inner/clone_inner to handle types
Adds two methods to result_try's exception handles:

- as_inner: returns a {l,r}-value reference either to the exception
  container, or the exception_ptr. This allows to use them in operations
  which work on both types, e.g. logging.
- clone_inner: returns a copy of the underlying exception container or
  exception ptr.
2022-02-22 16:08:52 +01:00
Piotr Dulikowski
1ed416906e result_try: relax ConvertWithTo constraint
Currently, the catch handlers in result_futurize_try are required to
return a future, although they are always being called with
seastar::futurize_invoke, so if their result is not future it could be
converted to one anyway. This commit relaxes the ConvertsWithTo
constraint in order to allow this conversion.
2022-02-22 16:08:52 +01:00
Piotr Dulikowski
e87cf08591 exception_container: switch impl to std::shared_ptr and make copyable
The exception_container is supposed to be a cheaper, but possibly harder
to use alternative to std::exception_ptr. Before this commit, the
exception was kept behind foreign_ptr<std::unique_ptr<>> so that moving
the container is very cheap. However, the original std::exception_ptr
supports copying in a thread-safe manner, and it turns out that some of
the read coordinator logic intentionally copies the pointer in order to
be able to fail two different promises with the same exception.

The pointer type is changed to std::shared_ptr. Although it uses atomics
for reference counting, this is also probably what std::exception_ptr
does, so the performance should not be worse. The exception stored
inside the container is immutable, so this allows for a non-throwing
implementation of copying.

To encourage moves instead of copying, the copy constructor is deleted
and instead the `clone()` method should be used if it is really
necessary.
2022-02-22 16:08:52 +01:00
Piotr Dulikowski
7afea88dfc result_loop: add result_repeat
Adds a result-aware counterpart to seastar::repeat. The new function
does not base on seastar::repeat, but rather is a rewrite of the
original (using a coroutine instead of an open-coded task). The main
consequence of using a coroutine is that exceptions from AsyncAction
need to be thrown once more.
2022-02-22 16:08:52 +01:00
Piotr Dulikowski
32cbc89779 result_loop: add result_do_until
Adds a result-aware counterpart to seastar::do_until. The new function
does not base on seastar::do_until, but rather is a rewrite of the
original (using a coroutine instead of an open-coded task). The main
consequence of using a coroutine is that exceptions from StopCondition
or AsyncAction need to be thrown once more.
2022-02-22 16:08:52 +01:00
Piotr Dulikowski
4f0a98a829 result_loop: add result_map_reduce
Adds result-aware counterparts to all seastar::map_reduce overloads.

Fortunately, it was possible to implement the functions by basing them
on seastar::map_reduce and get the same number of allocation. The only
exception happens when reducer::get() returns a non-ready future, which
doesn't seem to happen on the read coordinator path.
2022-02-22 16:08:52 +01:00
Piotr Dulikowski
b3a0480439 utils/result: add utilities for checking/creating rebindable results
Adds:

- ResultRebindableTo<L, R>: concept which is satisfied by a pair of
  results which do not necessarily share the same value, but have the
  same error and policy types; a failed result L can be converted to a
  failed result R.
- rebind_result<T, R>: given a value type T and another result R,
  returns a result which can hold T as value and both the same error and
  policy as R.
2022-02-22 16:08:45 +01:00
Botond Dénes
10880fb0a7 tools/scylla-sstable: fix description template
Quote '{' and '}' used in CQL example, so format doesn't try to
interpret it.

Signed-off-by: Botond Dénes <bdenes@scylladb.com>
Message-Id: <20220221140652.173015-1-bdenes@scylladb.com>
2022-02-21 17:14:41 +02:00
Nadav Har'El
7181a6757a test/cql-pytest: add a couple of tests for static columns
This patch adds two tests for two interesting edge cases in the behavior
of static columns in Scylla. We already have a lot of tests for static
columns in other frameworks (C++ unit tests, cql and dtest), but the two
cases here are issues where specifically we weren't sure how Cassandra
behaves in those cases - and this can most easily be checked in the
test/cql-pytest framework.

The first test, test_static_not_selected, is a reproducer for issue #10091.
This issue was reported by a user @aohotnik, who was surprised by the
fact that Scylla returns empty values, instead of nothing, when selecting
regular columns of a non-existent row if the partition has a static
column set. The test demonstrates a difference between Scylla and
Cassandra, so it is marked "xfail" - it passes on Cassandra and fails on
Scylla. If later we decide that both Scylla's and Cassandra's behaviours
are reasonable and both can be considered "correct", we can change this
test to except Scylla's result as well and it will beging to pass.

The second test, test_missing_row_with_static, shows that SELECT of a
non-existent row returns nothing - even if the partition has a static
column. The behavior in this case is identical in Scylla and Cassandra,
so this test passes. This contrasts with the analogous situation in LWT
UPDATE from issue #10081, where the IF condition is expected to see the
static column value.

Refs #10081
Refs #10091

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
Message-Id: <20220220120418.831540-1-nyh@scylladb.com>
2022-02-21 16:04:57 +02:00
Avi Kivity
adc08d0ab9 Merge "Drop v1 input support for mutation compactor" from Botond
"
Currently the mutation compactor supports v1 and v2 output and has a v1
output. The next step is to add a v2 output but this would lead to a
full conversion matrix which we want to avoid. So in preparation we drop
the v1 input support. Most inputs were already v2, but there were some
notable exceptions: tests, the compacting reader and the multishard
query code. The former two was a simple mechanical update but the latter
required some further work because it turned out the v2 version of
evictable reader wasn't used yet and thus it managed to hide some bugs
and dropped features. While at it, we migrate all evictable and
multishard reader users to the v2 variant of the respective readers and
drop the v1 variant completely.
With this the road is open to a v2 compactor output and therefore to a
v2 sstable writer.

Tests: unit(dev, release), dtest(paging_additional_test.py)
"

* 'compact-mutation-v2-only-input/v5' of https://github.com/denesb/scylla:
  test/lib/test_utils: return OK from check() variants
  repair/row_level: use evictable reader v2
  db/view/view_updating_consumer: migrate to v2
  test/boost/mutation_reader_test: add v2 specific evictable reader tests
  test: migrate to evictable reader v2 and multishard combining reader v2
  compact_mutation: drop support for v1 input
  test: pass v2 input to mutation_compaction
  test/boost/mutation_test: simplify test_compaction_data_stream_split test
  mutation_partition: do_compact(): do drop row tombstones covered by higher order tombstones
  multishard_mutation_query: migrate to v2
  mutation_fragment_v2: range_tombstone_change: add memory_usage()
  evictable_reader_v2: terminate active range tombstones on reader recreation
  evictable_reader_v2: restore handling of non-monotonically increasing positions
  evictable_reader_v2: simplify handling of reader recreation
  mutation: counter_write_query: use v2 reader
  mutation: migrate consume() to v2
  mutation_fragment_v2,flat_mutation_reader_v2: mirror v1 concept organization
  mutation_reader: compacting_reader: require a v2 input reader
  db/view/view_builder: use v2 reader
  test/lib/flat_mutation_reader_assertions: adjust has_monotonic_positions() to v2 spec
2022-02-21 14:32:55 +02:00
Botond Dénes
841b982e51 test/lib/test_utils: return OK from check() variants
The various require() and check() methods in test_utils.hh were
introduced to replace BOOST_REQUIRE() and BOOST_CHECK() respectively in
multi-shard concurrent tests, specifically those in
tests/boost/multishard_mutation_query_test.cc.
This was done literally, just replacing BOOST_REQUIRE() with require()
and BOOST_CHECK() with check(). The problem is that check() is missing a
feature BOOST_CHECK() had: while BOOST_CHECK() doesn't cause an
immediate test failure, just logging an error if the condition fails, it
remembers this failure and will fail the test in the end. check() did
not have this feature and this caused potential errors to just be logged
while the test could still pass fine, causing false-positive tests
passes. This patch fixes this by returning a [[nodiscard]] bool from the
check() methods. The caller can & these together over all calls to
check() methods and manually fail the test in the end. We choose this
method over a hidden global (like BOOST_CHECK() does) for simplicity
sake.
2022-02-21 12:29:25 +02:00
Botond Dénes
4aa9b90ba9 repair/row_level: use evictable reader v2 2022-02-21 12:29:24 +02:00
Botond Dénes
05c48ee0cc db/view/view_updating_consumer: migrate to v2
Not a completely mechanical transition. The consumer has to generate its
mutation via a mutation_rebuilder_v2 as mutation fragment v2 cannot be
applied to mutations directly yet.
2022-02-21 12:29:24 +02:00
Botond Dénes
014a23bf2a test/boost/mutation_reader_test: add v2 specific evictable reader tests
One is a reincarnation of the recently removed
test_multishard_combining_reader_non_strictly_monotonic_positions. The
latter was actually targeting the evictable reader but through the
multishard reader, probably for historic reasons (evictable reader was
part of the multishard reader family).
The other one checks that active range tombstones changes are properly
terminated when the partition ends abruptly after recreating the reader.
2022-02-21 12:29:24 +02:00
Botond Dénes
e3c618beba test: migrate to evictable reader v2 and multishard combining reader v2
All reads are now using the v2 version of these readers, test them
instead of the old v1.
2022-02-21 12:29:24 +02:00
Botond Dénes
f1e9e3b3b7 compact_mutation: drop support for v1 input 2022-02-21 12:29:24 +02:00
Botond Dénes
284ed9154f test: pass v2 input to mutation_compaction 2022-02-21 12:29:24 +02:00
Botond Dénes
dec4e5659b test/boost/mutation_test: simplify test_compaction_data_stream_split test
This test has very elaborate infrastructure essentially duplicating
mutation, mutation::apply() and mutation::operator==. Drop all this
extra code and use mutations directly instead. This makes migrating the
test to v2 easier.
2022-02-21 12:29:24 +02:00
Botond Dénes
2941803da0 mutation_partition: do_compact(): do drop row tombstones covered by higher order tombstones
The comment on the public methods calling said method promises to do so
but doesn't actually follows through. This patch fixes this for row
tombstones, to mirror the behaviour of the mutation compactor. This is
especially important for tests that compare mutations compacted with
different methods.
2022-02-21 12:29:24 +02:00
Botond Dénes
f2e2b84038 multishard_mutation_query: migrate to v2
Mostly mechanical transformation. The main difference is in the detached
compaction state, from which we now get the range tombstone change,
instead of the range tombstone list. The code around this is a bit
awkward, will become simpler when compactor drops v1 support.
2022-02-21 12:29:24 +02:00
Botond Dénes
b330cba792 mutation_fragment_v2: range_tombstone_change: add memory_usage() 2022-02-21 12:29:24 +02:00
Botond Dénes
9e48237b86 evictable_reader_v2: terminate active range tombstones on reader recreation
Reader recreation messes with the continuity of the mutation fragment
stream because it breaks snapshot isolation. We cannot guarantee that a
range tombstone or even the partition started before will continue after
too. So we have to make sure to wrap up all loose threads when
recreating the reader. We already close uncontinued partitions. This
commit also takes care of closing any range tombstone started by
unconditionally emitting a null range tombstone. This is legal to do,
even if no range tombstone was in effect.
2022-02-21 12:29:24 +02:00
Botond Dénes
6db08ddeb2 evictable_reader_v2: restore handling of non-monotonically increasing positions
We thought that unlike v1, v2 will not need this. But it does.
Handled similarly to how v1 did it: we ensure each buffer represents
forward progress, when the last fragment in the buffer is a range
tombstone change:
* Ensure the content of the buffer represents progress w.r.t.
  _next_position_in_partition, thus ensuring the next time we recreate
  the reader it will continue from a later position.
* Continue reading until the next (peeked) fragment has a strictly
  larger position.

The code is just much nicer because it uses coroutines.
2022-02-21 12:29:24 +02:00
Botond Dénes
498d03836b evictable_reader_v2: simplify handling of reader recreation
The evictable reader has a handful of flags dictating what to do after
the reader is recreated: what to validate, what to drop, etc. We
actually need a single flag telling us if the reader was recreated or
not, all other things can be derived from existing fields.
This patch does exactly that. Furthermore it folds do_fill_buffer() into
fill_buffer() and replaces the awkward to use `should_drop_fragment()`
with `examine_first_fragments()`, which does a much better job of
encapsulating all validation and fragment dropping logic.
This code reorganization also fixes two bugs introduced by the v2
conversion:
* The loop in `do_fill_buffer()` could become infinite in certain
  circumstances due to a difference between the v1 and v2 versions of
  `is_end_of_stream()`.
* The position of the first non-dropped fragment is was not validated
  (this was integrated into the range tombstone trimming which was
  thrown out by the conversion).
2022-02-21 12:29:24 +02:00
Botond Dénes
d4ac473f7d mutation: counter_write_query: use v2 reader 2022-02-21 12:27:55 +02:00
Botond Dénes
fcda35d08e mutation: migrate consume() to v2
The underlying mutation format is still v1, so consume() ends up doing
an online conversion. This allows converting all downstream code to v2,
leaving the conversion close to the code that is yet to be migrated to
v2 native: the mutation itself.
2022-02-21 12:27:55 +02:00
Botond Dénes
1fa6537a2f mutation_fragment_v2,flat_mutation_reader_v2: mirror v1 concept organization
Currently all concepts are in mutation_fragment_v2.hh and
flat_mutation_reader_v2.hh. Organize concepts similar to how the v1 ones
are: move high-level consume concepts into
mutation_consumer_concepts.hh.
2022-02-21 12:27:55 +02:00
Botond Dénes
fb0e0ec7c1 mutation_reader: compacting_reader: require a v2 input reader
Before we add a v2 output option to the compactor, we want to get rid of
all the v1 inputs to make it simpler. This means that for a while the
compacting reader will be in a strange place of having a v2 input and a
v1 output. Hopefully, not for long.
2022-02-21 12:27:55 +02:00
Botond Dénes
45b36d91c6 db/view/view_builder: use v2 reader 2022-02-21 12:27:55 +02:00
Botond Dénes
bba20f5cce test/lib/flat_mutation_reader_assertions: adjust has_monotonic_positions() to v2 spec
The v2 spec allows for non-strictly monotonically increasing positions,
but has_monotonic_positions() tried to enforce it. Relax the check so it
conforms to the spec.
2022-02-21 12:27:55 +02:00
Benny Halevy
f5259e048c test: sstable_compaction_test: stop compaction manager and test table using deferred action
To make sure they are properly stopped also on exception.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
Message-Id: <20220220120939.2362590-2-bhalevy@scylladb.com>
2022-02-21 12:06:32 +02:00
Benny Halevy
9a308bc496 test: lib: register_compaction: do not allow null table
Require to pass the table to be compacted so
register_compaction finds the real compaction state
rather than making a bogus one.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
Message-Id: <20220220120939.2362590-1-bhalevy@scylladb.com>
2022-02-21 12:06:32 +02:00
Yaron Kaikov
23bb0761bf SCYLLA-VERSION-GEN:set release-version value length
Noticed this issue during my debug sessions while building Scylla on x86 and Arm (https://jenkins.scylladb.com/job/scylla-master/job/releng-testing/job/build/670/artifact/)

from x86 log (https://jenkins.scylladb.com/job/scylla-master/job/releng-testing/job/build/670/artifact/output-build-x86_64.txt)
```
[883/2823] cd tools/python3 && ./reloc/build_reloc.sh --version $(<../../build/SCYLLA-PRODUCT-FILE)-$(<../../build/SCYLLA-VERSION-FILE)-$(<../../build/SCYLLA-RELEASE-FILE) --nodeps --packages "python3-pyyaml python3-urwid python3-pyparsing python3-requests python3-pyudev python3-setuptools python3-psutil python3-distro python3-click python3-six" --pip-packages "scylla-driver geomet"
5.1.dev-0.20220209.23da2b58796
```
from arm log (https://jenkins.scylladb.com/job/scylla-master/job/releng-testing/job/build/670/artifact/output-build-aarch64.txt)
```
[244/2823] cd tools/python3 && ./reloc/build_reloc.sh --version $(<../../build/SCYLLA-PRODUCT-FILE)-$(<../../build/SCYLLA-VERSION-FILE)-$(<../../build/SCYLLA-RELEASE-FILE) --nodeps --packages "python3-pyyaml python3-urwid python3-pyparsing python3-requests python3-pyudev python3-setuptools python3-psutil python3-distro python3-click python3-six" --pip-packages "scylla-driver geomet"
5.1.dev-0.20220209.23da2b587
```

Related to git config parameter core.abbrev which is not defined so default is set for auto (based: https://git-scm.com/docs/git-config#Documentation/git-config.txt-coreabbrev)

Fixes: https://github.com/scylladb/scylla/issues/10108

Closes #10109
2022-02-21 13:28:04 +02:00
Pavel Emelyanov
49c5d5b7e8 Merge 'lister: add directory_lister' from Benny Halevy
directory_lister provides a simpler interface compared to lister.

After creating the directory_lister,
its async get() method should be called repeatedly,
returning a std::optional<directory_entry> each call,
until it returns a disengaged entry or an error.

This is especially suitable for coroutines
as demonstrated in the unit tests that were added.

For example:
```c++
        auto dl = directory_lister(path);
        while (auto de = co_await dl.get()) {
            co_await process(*de);
        }
```

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>

Closes #9835

* github.com:scylladb/scylla:
  sstable_directory: process_sstable_dir: use directory_lister
  sstable_directory: process_sstable_dir: fixup indentation
  sstable_directory: coroutinize process_sstable_dir
  lister: add directory_lister
2022-02-21 12:24:28 +03:00
Nadav Har'El
4349514064 test/alternator: add smaller reproducer for Limit-less reverse query
The regression test we have for Alternator's issue #9487 (where a reverse
query without a Limit given was broken into 100MB pages instead of the
expected 1MB) is test_query.py::test_query_reverse_long. But this is a
very long test requiring a 100MB partition, and because of its slowness
isn't run by default.

This patch adds another version of that test, test_query_reverse_longish,
which reproduces the same issue #9487 with a partition 50 times shorter
(2MB) so it only takes a fraction of a second and can be enabled by
default. It also requires much less network traffic which is important
when running these tests non-locally.

We leave the original test test_query_reverse_long behind, it can be
still useful to stress Scylla even beyond the 100MB boundary, but it
remains in @veryslow mode so won't run in default test runs.

Refs #9487
Refs #7586

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
Message-Id: <20220220161905.852994-1-nyh@scylladb.com>
2022-02-21 09:12:16 +01:00
Avi Kivity
8eb5d6ed31 frozen_schema: avoid allocating contiguous memory
A frozen schema can be quite large (in #10071 we measured 500 bytes per
column, and there can be thousands of columns in extreme tables). This
can cause large contiguous allocations and therefor memory stalls or
even failures to allocate.

Switch to bytes_ostream as the internal representation. Fortunately
frozen_schema is internally implemented as bytes_ostream, so the
change is minimal.

Ref #10071.

Test: unit (dev)

Closes #10105
2022-02-21 01:39:02 +01:00
Amnon Heiman
c764f0d0f8 gms/gossiper.cc: Add gauge for live and unreachable nodes
this patch adds two gauges:
scylla_gossip_live - how many live nodes the gossiper sees
scylla_gossip_unreachable - how many nodes the gossiper tries to connect
to but cannot.

Both metrics are reported once per node (i.e., per node, not per shard) it
gives visibility to how a specific node sees the cluster.

For example, a split-brain 6 nodes cluster (3 and 3). Each node would
report that it sees 2 nodes, but the monitoring system would see that
there are, in fact, 6 nodes.

Example of two nodes cluster, both running:
``
scylla_gossip_live{shard="0"} 1.000000
scylla_gossip_unreachable{shard="0"} 0.000000
``

Example of two nodes cluster, one is down:
``
scylla_gossip_live{shard="0"} 0.000000
scylla_gossip_unreachable{shard="0"} 1.000000
``

Fixes #10102

Signed-off-by: Amnon Heiman <amnon@scylladb.com>

Closes #10103

[avi: remove whitespace change and correct spelling]
2022-02-20 19:42:58 +02:00
Nadav Har'El
6476a64185 test/cql-pytest: reproducer for JSON scientific-notation integer problem
The JSON standard specifies numbers without making a distinction of what
is "an integer" and what is "floating point". The value 1e6 is a valid
number, and although it is customary in C that 1e6 is a floating-point
constant, as a JSON constant there is nothing inherently "non-integer" about
it - it is a whole number. This is why I believe CQL commands such as

    CREATE TABLE t(pk int PRIMARY KEY, v int);
    INSERT INTO t JSON '{"pk": 1, "v": 1e6}';

should be allowed, as 1e6 is a whole number and fits in the range of
Scylla's int.

The included tests show that, unfortunately, 1e6 is *not* currently
allowed to be assigned to an integer. The test currently fail on both
Scylla and Cassandra - and we believe this failure to be a bug in both,
so the test is marked with xfail (known to fail) and cassandra-bug
(known failure on Cassandra considered to be a bug).

Refs #10100

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
Message-Id: <20220220141602.843783-1-nyh@scylladb.com>
2022-02-20 17:01:22 +02:00
Nadav Har'El
d3ac9a5790 Merge 'cql3: expr: Fix expr::visit so that it works with references' from Jan Ciołek
There is a bug in `expr::visit`. When trying to return a reference from a visitor it actually returns a reference to some temporary location.
So trying to do something like:
```c++
const expression e = new_bind_variable(123);

const bind_variable& ref = visit(overloaded_functor {
    [](const bind_variable& bv) -> const bind_variable& { return bv; },
    [](const auto&) -> const bind_variable& { throw std::runtime_error("Unreachable"); }
}, e);

std::cout << ref << std::endl;
 ```
 Would actually print a random stack location instead of the value inside of `e`.
 Additionally trying to return a non-const reference doesn't compile.

 Current implementation of `expr::visit` is:
 ```c++
 auto visit(invocable_on_expression auto&& visitor, const expression& e) {
    return std::visit(visitor, e._v->v);
}
 ```

For reference, `std::visit` looks like this:
 ```c++
template<typename _Res, typename _Visitor, typename... _Variants>
constexpr _Res
visit(_Visitor&& __visitor, _Variants&&... __variants)
{
  return std::__do_visit<_Res>(std::forward<_Visitor>(__visitor),
                               std::forward<_Variants>(__variants)...);
}
 ```

 The problem is that `auto` can evaluate to `int` or `float`, but not to `int&`.
 It has now been changed to `decltype(auto)`, which is able to express references.
 I also added a missing `std::forward` on the visitor argument.

The new version looks like this:
 ```c++
template <invocable_on_expression Visitor>
decltype(auto) visit(Visitor&& visitor, const expression& e) {
    return std::visit(std::forward<Visitor>(visitor), e._v->v);
}
```

I added some tests of `expr::visit` in `boost/expr_test`, but sadly they are not as throughout as they could be, Ideally I could return a refernce from `std::visit` and `expr::visit` and then check that they both point to the same address in memory.
I can't do this because it would require to access a private field of `expression`.
Some test pass before the fix, even though they shouldn't, but I'm not sure how to make them better without making field of expression public.

 I played around with some code, it can be found here: https://github.com/cvybhu/attached-files/blob/main/visit/visit_playground.cpp

Closes #10073

* github.com:scylladb/scylla:
  cql3: expr: Add a test to show that std::forward is needed in expr::visit
  cql3: expr: add std::forward in expr::visit
  cql3: expr: Add tests for expr::visit
  cql3: expr: Fix expr::visit so that it works with references
2022-02-20 12:09:57 +02:00
Jan Ciolek
353ab8f438 cql3: expr: Add a test to show that std::forward is needed in expr::visit
Adds a test with a vistior that can only be used as a rvalue.
Without std::forward in expr::visit this test doesn't compile.

Signed-off-by: Jan Ciolek <jan.ciolek@scylladb.com>
2022-02-18 14:19:49 +01:00
Jan Ciolek
7234cc851c cql3: expr: add std::forward in expr::visit
expr::visit was missing std::forward on the visitor.
In cases where the visitor was passed as an rvalue it wouldn't
be properly forwarded to std::visit.

Signed-off-by: Jan Ciolek <jan.ciolek@scylladb.com>
2022-02-18 14:19:49 +01:00
Jan Ciolek
46367eec55 cql3: expr: Add tests for expr::visit
Add tests for new expr::visit to ensure that it is working correctly.

expr::visit had a hidden bug where trying to return a reference
actually returned a reference to freed location on the stack,
so now there are tests to ensure that everything works.

Sadly the test `expr_visit_const_ref` also passes
before the fix, but at lest expr_visit_ref doesn't compile before the fix.
It would be better to test this by taking references returned
by std::visit and expr::visit and checking that they point
to the same address in memory, but I can't do this
because I would have to access private field of expression.

Signed-off-by: Jan Ciolek <jan.ciolek@scylladb.com>
2022-02-18 14:16:55 +01:00