in in {fmt} before v10, it provides the specialization of `fmt::formatter<..>`
for `std::string_view` as well as the specialization of `fmt::formatter<..>`
for `fmt::string_view` which is an implementation builtin in {fmt} for
compatibility of pre-C++17. and this type is used even if the code is
compiled with C++ stadandard greater or equal to C++17. also, before v10,
the `fmt::formatter<std::string_view>::format()` is defined so it accepts
`std::string_view`. after v10, `fmt::formatter<std::string_view>` still
exists, but it is now defined using `format_as()` machinery, so it's
`format()` method does not actually accept `std::string_view`, it
accepts `fmt::string_view`, as the former can be converted to
`fmt::string_view`.
this is why we can inherit from `fmt::formatter<std::string_view>` and
use `formatter<std::string_view>::format(foo, ctx);` to implement the
`format()` method with {fmt} v9, but we cannot do this with {fmt} v10,
and we would have following compilation failure:
```
FAILED: service/CMakeFiles/service.dir/RelWithDebInfo/topology_state_machine.cc.o
/home/kefu/.local/bin/clang++ -DFMT_DEPRECATED_OSTREAM -DFMT_SHARED -DSCYLLA_BUILD_MODE=release -DSEASTAR_API_LEVEL=7 -DSEASTAR_LOGGER_COMPILE_TIME_FMT -DSEASTAR_LOGGER_TYPE_STDOUT -DSEASTAR_SCHEDULING_GROUPS_COUNT=16 -DSEASTAR_SSTRING -DXXH_PRIVATE_API -DCMAKE_INTDIR=\"RelWithDebInfo\" -I/home/kefu/dev/scylladb -I/home/kefu/dev/scylladb/build/gen -I/home/kefu/dev/scylladb/seastar/include -I/home/kefu/dev/scylladb/build/seastar/gen/include -I/home/kefu/dev/scylladb/build/seastar/gen/src -ffunction-sections -fdata-sections -O3 -g -gz -std=gnu++20 -fvisibility=hidden -Wall -Werror -Wextra -Wno-error=deprecated-declarations -Wimplicit-fallthrough -Wno-c++11-narrowing -Wno-deprecated-copy -Wno-mismatched-tags -Wno-missing-field-initializers -Wno-overloaded-virtual -Wno-unsupported-friend -Wno-enum-constexpr-conversion -Wno-unused-parameter -ffile-prefix-map=/home/kefu/dev/scylladb=. -march=westmere -mllvm -inline-threshold=2500 -fno-slp-vectorize -U_FORTIFY_SOURCE -Werror=unused-result -MD -MT service/CMakeFiles/service.dir/RelWithDebInfo/topology_state_machine.cc.o -MF service/CMakeFiles/service.dir/RelWithDebInfo/topology_state_machine.cc.o.d -o service/CMakeFiles/service.dir/RelWithDebInfo/topology_state_machine.cc.o -c /home/kefu/dev/scylladb/service/topology_state_machine.cc
/home/kefu/dev/scylladb/service/topology_state_machine.cc:254:41: error: no matching member function for call to 'format'
254 | return formatter<std::string_view>::format(it->second, ctx);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
/usr/include/fmt/core.h:2759:22: note: candidate function template not viable: no known conversion from 'seastar::basic_sstring<char, unsigned int, 15>' to 'const fmt::basic_string_view<char>' for 1st argument
2759 | FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) const
| ^ ~~~~~~~~~~~~
```
because the inherited `format()` method actually comes from
`fmt::formatter<fmt::string_view>`. to reduce the confusion, in this
change, we just inherit from `fmt::format<string_view>`, where
`string_view` is actually `fmt::string_view`. this follows
the document at
https://fmt.dev/latest/api.html#formatting-user-defined-types,
and since there is less indirection under the hood -- we do not
use the specialization created by `FMT_FORMAT_AS` which inherit
from `formatter<fmt::string_view>`, hopefully this can improve
the compilation speed a little bit. also, this change addresses
the build failure with {fmt} v10.
Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
Closes scylladb/scylladb#18299
172 lines
6.9 KiB
C++
172 lines
6.9 KiB
C++
/*
|
|
* Copyright (C) 2022-present ScyllaDB
|
|
*/
|
|
|
|
/*
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "cql3/expr/expression.hh"
|
|
#include "cql3/expr/evaluate.hh"
|
|
#include "cql3/query_options.hh"
|
|
#include "cql3/selection/selection.hh"
|
|
#include "data_dictionary/data_dictionary.hh"
|
|
#include "data_dictionary/impl.hh"
|
|
#include "data_dictionary/keyspace_metadata.hh"
|
|
#include "db/config.hh"
|
|
#include "types/list.hh"
|
|
#include "types/map.hh"
|
|
#include "types/set.hh"
|
|
|
|
namespace cql3 {
|
|
namespace expr {
|
|
namespace test_utils {
|
|
|
|
raw_value make_empty_raw();
|
|
raw_value make_bool_raw(bool val);
|
|
raw_value make_tinyint_raw(int8_t val);
|
|
raw_value make_smallint_raw(int16_t val);
|
|
raw_value make_int_raw(int32_t val);
|
|
raw_value make_bigint_raw(int64_t val);
|
|
raw_value make_text_raw(const sstring_view& text);
|
|
raw_value make_float_raw(float val);
|
|
raw_value make_double_raw(double val);
|
|
|
|
constant make_empty_const(data_type type);
|
|
constant make_bool_const(bool val);
|
|
constant make_tinyint_const(int8_t val);
|
|
constant make_smallint_const(int16_t val);
|
|
constant make_int_const(int32_t val);
|
|
constant make_bigint_const(int64_t val);
|
|
constant make_text_const(const sstring_view& text);
|
|
constant make_float_const(float val);
|
|
constant make_double_const(double val);
|
|
|
|
untyped_constant make_int_untyped(const char* raw_text);
|
|
untyped_constant make_float_untyped(const char* raw_text);
|
|
untyped_constant make_string_untyped(const char* raw_text);
|
|
untyped_constant make_bool_untyped(const char* raw_text);
|
|
untyped_constant make_duration_untyped(const char* raw_text);
|
|
untyped_constant make_uuid_untyped(const char* raw_text);
|
|
untyped_constant make_hex_untyped(const char* raw_text);
|
|
untyped_constant make_null_untyped();
|
|
|
|
// This function implements custom serialization of collection values.
|
|
// Some tests require the collection to contain unset_value or an empty value,
|
|
// which is impossible to express using the existing code.
|
|
cql3::raw_value make_collection_raw(size_t size_to_write, const std::vector<cql3::raw_value>& elements_to_write);
|
|
|
|
raw_value make_list_raw(const std::vector<raw_value>& values);
|
|
raw_value make_set_raw(const std::vector<raw_value>& values);
|
|
raw_value make_map_raw(const std::vector<std::pair<raw_value, raw_value>>& values);
|
|
|
|
// This function implements custom serialization of tuples.
|
|
// Some tests require the tuple to contain unset_value or an empty value,
|
|
// which is impossible to express using the existing code.
|
|
raw_value make_tuple_raw(const std::vector<raw_value>& values);
|
|
|
|
constant make_list_const(const std::vector<raw_value>& vals, data_type elements_type);
|
|
constant make_list_const(const std::vector<constant>& vals, data_type elements_type);
|
|
|
|
constant make_set_const(const std::vector<raw_value>& vals, data_type elements_type);
|
|
constant make_set_const(const std::vector<constant>& vals, data_type elements_type);
|
|
|
|
constant make_map_const(const std::vector<std::pair<raw_value, raw_value>>& vals,
|
|
data_type key_type,
|
|
data_type value_type);
|
|
|
|
constant make_map_const(const std::vector<std::pair<constant, constant>>& vals,
|
|
data_type key_type,
|
|
data_type value_type);
|
|
|
|
constant make_tuple_const(const std::vector<raw_value>& vals, const std::vector<data_type>& element_types);
|
|
constant make_tuple_const(const std::vector<constant>& vals, const std::vector<data_type>& element_types);
|
|
|
|
raw_value make_int_list_raw(const std::vector<std::optional<int32_t>>& values);
|
|
raw_value make_int_set_raw(const std::vector<int32_t>& values);
|
|
|
|
raw_value make_int_int_map_raw(const std::vector<std::pair<int32_t, int32_t>>& values);
|
|
|
|
constant make_int_list_const(const std::vector<std::optional<int32_t>>& values);
|
|
constant make_int_set_const(const std::vector<int32_t>& values);
|
|
constant make_int_int_map_const(const std::vector<std::pair<int32_t, int32_t>>& values);
|
|
|
|
collection_constructor make_list_constructor(std::vector<expression> elements, data_type elements_type);
|
|
collection_constructor make_set_constructor(std::vector<expression> elements, data_type elements_type);
|
|
collection_constructor make_map_constructor(const std::vector<expression> elements,
|
|
data_type key_type,
|
|
data_type element_type);
|
|
collection_constructor make_map_constructor(const std::vector<std::pair<expression, expression>>& elements,
|
|
data_type key_type,
|
|
data_type element_type);
|
|
tuple_constructor make_tuple_constructor(std::vector<expression> elements, std::vector<data_type> element_types);
|
|
usertype_constructor make_usertype_constructor(std::vector<std::pair<sstring_view, constant>> field_values);
|
|
|
|
::lw_shared_ptr<column_specification> make_receiver(data_type receiver_type, sstring name = "receiver_name");
|
|
|
|
bind_variable make_bind_variable(int32_t index, data_type type);
|
|
|
|
struct evaluation_inputs_data {
|
|
std::vector<bytes> partition_key;
|
|
std::vector<bytes> clustering_key;
|
|
std::vector<managed_bytes_opt> static_and_regular_columns;
|
|
::shared_ptr<selection::selection> selection;
|
|
query_options options;
|
|
std::vector<api::timestamp_type> timestamps;
|
|
std::vector<int32_t> ttls;
|
|
};
|
|
|
|
struct mutation_column_value {
|
|
mutation_column_value(cql3::raw_value v, api::timestamp_type ts, int32_t ttl)
|
|
: value(std::move(v)), timestamp(ts), ttl(ttl) {}
|
|
// Convenience constructor when timestamp/ttl are not interesting
|
|
mutation_column_value(cql3::raw_value v)
|
|
: value(std::move(v))
|
|
, timestamp(value.is_null() ? api::missing_timestamp : 12345)
|
|
, ttl(-1) {
|
|
}
|
|
|
|
cql3::raw_value value;
|
|
api::timestamp_type timestamp;
|
|
int32_t ttl;
|
|
};
|
|
|
|
using column_values = std::map<sstring, mutation_column_value>;
|
|
|
|
// Creates evaluation_inputs that can be used to evaluate columns and bind variables using evaluate()
|
|
std::pair<evaluation_inputs, std::unique_ptr<evaluation_inputs_data>> make_evaluation_inputs(
|
|
const schema_ptr& table_schema,
|
|
const column_values& column_vals,
|
|
const std::vector<raw_value>& bind_marker_values = {});
|
|
|
|
// Creates a mock implementation of data_dictionary::database, useful in tests.
|
|
std::pair<data_dictionary::database, std::unique_ptr<data_dictionary::impl>> make_data_dictionary_database(
|
|
const schema_ptr& table_schema);
|
|
|
|
raw_value evaluate_with_bind_variables(const expression& e, std::vector<raw_value> bind_variable_values);
|
|
|
|
|
|
} // namespace test_utils
|
|
} // namespace expr
|
|
} // namespace cql3
|
|
|
|
template <> struct fmt::formatter<cql3::expr::test_utils::mutation_column_value> : fmt::formatter<string_view> {
|
|
auto format(const cql3::expr::test_utils::mutation_column_value& mcv, fmt::format_context& ctx) const {
|
|
return fmt::format_to(ctx.out(), "{{{}/ts={}/ttl={}}}", mcv.value, mcv.timestamp, mcv.ttl);
|
|
|
|
}
|
|
};
|
|
|
|
namespace cql3::expr::test_utils {
|
|
|
|
inline
|
|
std::ostream&
|
|
operator<<(std::ostream& os, const mutation_column_value& mcv) {
|
|
fmt::print(os, "{}", mcv);
|
|
return os;
|
|
}
|
|
|
|
}
|