From 86722e4ceab2bdd114700ca0cdf0653aee79c5ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20M=C4=99drek?= Date: Thu, 12 Sep 2024 15:40:00 +0200 Subject: [PATCH] treewide: Return create statement optionally in describe functions We add a new parameter in functions used to generate instances of `cql3::description` for types related to situations where we might not need a create statement. An example of such a scenario could be `DESCRIBE TYPES`. --- cql3/description.hh | 25 +++++++++++++++++++++++++ cql3/functions/aggregate_fcts.cc | 15 ++++++++++++--- cql3/functions/user_aggregate.hh | 2 +- cql3/functions/user_function.cc | 15 ++++++++++++--- cql3/functions/user_function.hh | 2 +- data_dictionary/data_dictionary.cc | 14 +++++++++++--- data_dictionary/keyspace_metadata.hh | 2 +- schema/schema.cc | 8 +++++--- schema/schema.hh | 2 +- types/types.cc | 14 +++++++++++--- types/user.hh | 2 +- 11 files changed, 81 insertions(+), 20 deletions(-) diff --git a/cql3/description.hh b/cql3/description.hh index 7b09e3ccfb..8d97c56623 100644 --- a/cql3/description.hh +++ b/cql3/description.hh @@ -9,6 +9,7 @@ #pragma once #include +#include #include "bytes_fwd.hh" @@ -19,6 +20,30 @@ using namespace seastar; namespace cql3 { +/// Tag indicating whether a describe function should return a `cql3::description` +/// with a `create_statement` or not. +using with_create_statement = bool_class; + +/// An option type that functions generating instances of `cql3::description` +/// can be parameterized with. +/// +/// In some cases, the user doesn't need a create statement, so producing it +/// is a waste of time. An example of that could be `DESCRIBE TYPES`. +/// +/// In some other cases, we may want to produce either a less, or a more detailed +/// create statement depending on the context. An example of that is +/// `DESCRIBE SCHEMA [WITH INTERNALS]` that may print additional details of tables +/// when the `WITH INTERNALS` option is used. +/// +/// Some entities can generate `cql3::description`s parameterized by those two +/// characteristics and this type embodies the choice of the user. +enum class describe_option { + NO_STMTS, /// Describe an entity, but don't generate a create statement. + STMTS, /// Describe an entity and generate a create statement. + STMTS_AND_INTERNALS /// Describe an entity and generate a create statement, + /// including internal details. +}; + /// Type representing an entity that can be restored by performing /// a SINGLE CQL query. It can correspond to a tangible object such as /// a keyspace, a table, or a role, as well as to a more abstract concept diff --git a/cql3/functions/aggregate_fcts.cc b/cql3/functions/aggregate_fcts.cc index 19612e6f10..99da8ccee4 100644 --- a/cql3/functions/aggregate_fcts.cc +++ b/cql3/functions/aggregate_fcts.cc @@ -9,6 +9,7 @@ */ #include "bytes.hh" +#include "cql3/description.hh" #include "types/types.hh" #include "types/tuple.hh" #include "cql3/functions/scalar_function.hh" @@ -355,7 +356,12 @@ user_aggregate::user_aggregate(function_name fname, bytes_opt initcond, ::shared bool user_aggregate::has_finalfunc() const { return _agg.state_to_result_function != nullptr; } -description user_aggregate::describe() const { +description user_aggregate::describe(with_create_statement with_stmt) const { + auto maybe_create_statement = std::invoke([&] -> std::optional { + if (!with_stmt) { + return std::nullopt; + } + auto ks = cql3::util::maybe_quote(name().keyspace); auto na = cql3::util::maybe_quote(name().name); @@ -384,16 +390,19 @@ description user_aggregate::describe() const { } os << ";"; + return std::move(os).str(); + }); + return description { .keyspace = name().keyspace, .type = "aggregate", .name = name().name, - .create_statement = std::move(os).str() + .create_statement = std::move(maybe_create_statement) }; } std::ostream& user_aggregate::describe(std::ostream& os) const { - auto desc = describe(); + auto desc = describe(with_create_statement::yes); os << *desc.create_statement; return os; } diff --git a/cql3/functions/user_aggregate.hh b/cql3/functions/user_aggregate.hh index cda109fa85..93b2071b35 100644 --- a/cql3/functions/user_aggregate.hh +++ b/cql3/functions/user_aggregate.hh @@ -27,7 +27,7 @@ public: virtual sstring element_type() const override { return "aggregate"; } virtual std::ostream& describe(std::ostream& os) const override; - description describe() const; + description describe(with_create_statement) const; seastar::shared_ptr sfunc() const { return _agg.aggregation_function; diff --git a/cql3/functions/user_function.cc b/cql3/functions/user_function.cc index 119718b6e3..647ece1b30 100644 --- a/cql3/functions/user_function.cc +++ b/cql3/functions/user_function.cc @@ -7,6 +7,7 @@ */ #include "user_function.hh" +#include "cql3/description.hh" #include "cql3/util.hh" #include "log.hh" #include "lang/wasm.hh" @@ -66,7 +67,12 @@ bytes_opt user_function::execute(std::span parameters) { }); } -description user_function::describe() const { +description user_function::describe(with_create_statement with_stmt) const { + auto maybe_create_statement = std::invoke([&] -> std::optional { + if (!with_stmt) { + return std::nullopt; + } + auto ks = cql3::util::maybe_quote(name().keyspace); auto na = cql3::util::maybe_quote(name().name); @@ -93,16 +99,19 @@ description user_function::describe() const { << _body << "\n" << "$$;"; + return std::move(os).str(); + }); + return description { .keyspace = name().keyspace, .type = "function", .name = name().name, - .create_statement = std::move(os).str() + .create_statement = std::move(maybe_create_statement) }; } std::ostream& user_function::describe(std::ostream& os) const { - auto desc = describe(); + auto desc = describe(with_create_statement::yes); os << *desc.create_statement; return os; } diff --git a/cql3/functions/user_function.hh b/cql3/functions/user_function.hh index e75d26596c..0834bf00f2 100644 --- a/cql3/functions/user_function.hh +++ b/cql3/functions/user_function.hh @@ -67,7 +67,7 @@ public: virtual sstring element_type() const override { return "function"; } virtual std::ostream& describe(std::ostream& os) const override; - description describe() const; + description describe(with_create_statement) const; }; } diff --git a/data_dictionary/data_dictionary.cc b/data_dictionary/data_dictionary.cc index 1c805ad400..e081a63809 100644 --- a/data_dictionary/data_dictionary.cc +++ b/data_dictionary/data_dictionary.cc @@ -352,7 +352,12 @@ no_such_column_family::no_such_column_family(std::string_view ks_name, const tab { } -cql3::description keyspace_metadata::describe(const replica::database& db) const { +cql3::description keyspace_metadata::describe(const replica::database& db, cql3::with_create_statement with_create_statement) const { + auto maybe_create_statement = std::invoke([&] -> std::optional { + if (!with_create_statement) { + return std::nullopt; + } + std::ostringstream os; os << "CREATE KEYSPACE " << cql3::util::maybe_quote(_name) @@ -376,16 +381,19 @@ cql3::description keyspace_metadata::describe(const replica::database& db) const } os << ";"; + return std::move(os).str(); + }); + return cql3::description { .keyspace = name(), .type = "keyspace", .name = name(), - .create_statement = std::move(os).str() + .create_statement = std::move(maybe_create_statement) }; } std::ostream& keyspace_metadata::describe(replica::database& db, std::ostream& os, bool with_internals) const { - auto desc = describe(db); + auto desc = describe(db, cql3::with_create_statement::yes); os << *desc.create_statement; return os; } diff --git a/data_dictionary/keyspace_metadata.hh b/data_dictionary/keyspace_metadata.hh index 01c817e1a5..82425980dd 100644 --- a/data_dictionary/keyspace_metadata.hh +++ b/data_dictionary/keyspace_metadata.hh @@ -101,7 +101,7 @@ public: virtual sstring element_type() const override { return "keyspace"; } virtual std::ostream& describe(replica::database& db, std::ostream& os, bool with_internals) const override; - cql3::description describe(const replica::database& db) const; + cql3::description describe(const replica::database& db, cql3::with_create_statement) const; }; } diff --git a/schema/schema.cc b/schema/schema.cc index 36b14e93cb..c8a8be2fed 100644 --- a/schema/schema.cc +++ b/schema/schema.cc @@ -977,7 +977,7 @@ sstring schema::get_create_statement(const replica::database& db, bool with_inte return std::move(os).str(); } -cql3::description schema::describe(const replica::database& db, bool with_internals) const { +cql3::description schema::describe(const replica::database& db, cql3::describe_option desc_opt) const { const sstring type = std::invoke([&] { if (is_view()) { return is_index(db, view_info()->base_id(), *this) @@ -991,12 +991,14 @@ cql3::description schema::describe(const replica::database& db, bool with_intern .keyspace = ks_name(), .type = std::move(type), .name = cf_name(), - .create_statement = get_create_statement(db, with_internals) + .create_statement = desc_opt == cql3::describe_option::NO_STMTS + ? std::nullopt + : std::make_optional(get_create_statement(db, desc_opt == cql3::describe_option::STMTS_AND_INTERNALS)) }; } std::ostream& schema::describe(replica::database& db, std::ostream& os, bool with_internals) const { - auto desc = describe(db, with_internals); + auto desc = describe(db, with_internals ? cql3::describe_option::STMTS_AND_INTERNALS : cql3::describe_option::STMTS); os << *desc.create_statement; return os; } diff --git a/schema/schema.hh b/schema/schema.hh index d413816791..2e34e23f31 100644 --- a/schema/schema.hh +++ b/schema/schema.hh @@ -921,7 +921,7 @@ public: */ virtual std::ostream& describe(replica::database& db, std::ostream& os, bool with_internals) const override; - cql3::description describe(const replica::database& db, bool with_internals) const; + cql3::description describe(const replica::database& db, cql3::describe_option) const; // Generate ALTER TABLE/MATERIALIZED VIEW statement containing all properties with current values. // The method cannot be used on index, as indexes don't support alter statement. diff --git a/types/types.cc b/types/types.cc index 6a3c900024..b66b108fa6 100644 --- a/types/types.cc +++ b/types/types.cc @@ -3235,7 +3235,12 @@ sstring user_type_impl::get_name_as_cql_string() const { return cql3::util::maybe_quote(get_name_as_string()); } -cql3::description user_type_impl::describe() const { +cql3::description user_type_impl::describe(cql3::with_create_statement with_create_statement) const { + auto maybe_create_statement = std::invoke([&] -> std::optional { + if (!with_create_statement) { + return std::nullopt; + } + std::ostringstream os; os << "CREATE TYPE " << cql3::util::maybe_quote(_keyspace) << "." << get_name_as_cql_string() << " (\n"; @@ -3248,16 +3253,19 @@ cql3::description user_type_impl::describe() const { } os << ");"; + return std::move(os).str(); + }); + return cql3::description { .keyspace = _keyspace, .type = "type", .name = get_name_as_string(), - .create_statement = std::move(os).str() + .create_statement = std::move(maybe_create_statement) }; } std::ostream& user_type_impl::describe(std::ostream& os) const { - auto desc = describe(); + auto desc = describe(cql3::with_create_statement::yes); os << *desc.create_statement; return os; } diff --git a/types/user.hh b/types/user.hh index f9c3ab7841..89336d9886 100644 --- a/types/user.hh +++ b/types/user.hh @@ -65,7 +65,7 @@ public: virtual sstring element_type() const override { return "type"; } virtual std::ostream& describe(std::ostream& os) const override; - cql3::description describe() const; + cql3::description describe(cql3::with_create_statement) const; private: static sstring make_name(sstring keyspace,