diff --git a/cql3/statements/describe_statement.cc b/cql3/statements/describe_statement.cc index f964f6ca91..d84a8b9f4f 100644 --- a/cql3/statements/describe_statement.cc +++ b/cql3/statements/describe_statement.cc @@ -51,6 +51,7 @@ #include "utils/overloaded_functor.hh" #include "db/system_keyspace.hh" #include "db/extensions.hh" +#include "utils/chunked_vector.hh" #include "utils/sorting.hh" #include "replica/database.hh" #include "cql3/description.hh" @@ -72,8 +73,8 @@ namespace { template requires std::is_invocable_r_v> -future> generate_descriptions(Range&& range, const Describer& describer, bool sort_by_name = true) { - std::vector result{}; +future> generate_descriptions(Range&& range, const Describer& describer, bool sort_by_name = true) { + utils::chunked_vector result{}; if constexpr (std::ranges::sized_range) { result.reserve(std::ranges::size(range)); } @@ -93,8 +94,8 @@ future> generate_descriptions(Range&& range, const Desc // `cql3::description` is a move-only type at the moment, and so we cannot initialize a vector passing // its instances as elements of an initializer list. This function serves as an intermediary to avoid // unnecessarily bloating some parts of the code below. -std::vector wrap_in_vector(description desc) { - std::vector result{}; +utils::chunked_vector wrap_in_vector(description desc) { + utils::chunked_vector result{}; result.reserve(1); result.push_back(std::move(desc)); return result; @@ -151,7 +152,7 @@ future> get_sorted_types(const lw_shared_ptr> types(replica::database& db, const lw_shared_ptr& ks, with_create_statement with_stmt) { +future> types(replica::database& db, const lw_shared_ptr& ks, with_create_statement with_stmt) { auto udts = co_await get_sorted_types(ks); auto describer = [with_stmt] (const user_type udt) -> cql3::description { return udt->describe(with_stmt); @@ -159,7 +160,7 @@ future> types(replica::database& db, const lw_shared_pt co_return co_await generate_descriptions(udts, describer, false); } -future> function(replica::database& db, const sstring& ks, const sstring& name) { +future> function(replica::database& db, const sstring& ks, const sstring& name) { auto fs = functions::instance().find(functions::function_name(ks, name)); if (fs.empty()) { throw exceptions::invalid_request_exception(format("Function '{}' not found in keyspace '{}'", name, ks)); @@ -181,7 +182,7 @@ future> function(replica::database& db, const sstring& co_return co_await generate_descriptions(udfs, describer, true); } -future> functions(replica::database& db,const sstring& ks, with_create_statement with_stmt) { +future> functions(replica::database& db,const sstring& ks, with_create_statement with_stmt) { auto udfs = cql3::functions::instance().get_user_functions(ks); auto describer = [with_stmt] (shared_ptr udf) { return udf->describe(with_stmt); @@ -189,7 +190,7 @@ future> functions(replica::database& db,const sstring& co_return co_await generate_descriptions(udfs, describer, true); } -future> aggregate(replica::database& db, const sstring& ks, const sstring& name) { +future> aggregate(replica::database& db, const sstring& ks, const sstring& name) { auto fs = functions::instance().find(functions::function_name(ks, name)); if (fs.empty()) { throw exceptions::invalid_request_exception(format("Aggregate '{}' not found in keyspace '{}'", name, ks)); @@ -210,7 +211,7 @@ future> aggregate(replica::database& db, const sstring& co_return co_await generate_descriptions(udas, describer, true); } -future> aggregates(replica::database& db, const sstring& ks, with_create_statement with_stmt) { +future> aggregates(replica::database& db, const sstring& ks, with_create_statement with_stmt) { auto udas = functions::instance().get_user_aggregates(ks); auto describer = [with_stmt] (shared_ptr uda) { return uda->describe(with_stmt); @@ -298,7 +299,7 @@ std::optional describe_cdc_log_table(const data_dictionary::databas return schema_desc; } -future> table(const data_dictionary::database& db, const sstring& ks, const sstring& name, bool with_internals) { +future> table(const data_dictionary::database& db, const sstring& ks, const sstring& name, bool with_internals) { auto table = db.try_find_table(ks, name); if (!table) { throw exceptions::invalid_request_exception(format("Table '{}' not found in keyspace '{}'", name, ks)); @@ -312,7 +313,7 @@ future> table(const data_dictionary::database& db, cons auto schema = table->schema(); auto idxs = table->get_index_manager().list_indexes(); auto views = table->views(); - std::vector result; + utils::chunked_vector result; // table auto table_desc = schema->describe(replica::make_schema_describe_helper(schema, db), with_internals ? describe_option::STMTS_AND_INTERNALS : describe_option::STMTS); @@ -374,7 +375,7 @@ future> table(const data_dictionary::database& db, cons co_return result; } -future> tables(const data_dictionary::database& db, const lw_shared_ptr& ks, std::optional with_internals = std::nullopt) { +future> tables(const data_dictionary::database& db, const lw_shared_ptr& ks, std::optional with_internals = std::nullopt) { auto& replica_db = db.real_database(); auto tables = ks->tables() | std::views::filter([&replica_db] (const schema_ptr& s) { return !cdc::is_log_for_some_table(replica_db, s->ks_name(), s->cf_name()) && !service::paxos::paxos_store::try_get_base_table(s->cf_name()); @@ -382,7 +383,7 @@ future> tables(const data_dictionary::database& db, con std::ranges::sort(tables, std::ranges::less(), std::mem_fn(&schema::cf_name)); if (with_internals) { - std::vector result; + utils::chunked_vector result; for (const auto& t: tables) { auto tables_desc = co_await table(db, ks->name(), t->cf_name(), *with_internals); result.insert(result.end(), std::make_move_iterator(tables_desc.begin()), std::make_move_iterator(tables_desc.end())); @@ -394,7 +395,7 @@ future> tables(const data_dictionary::database& db, con co_return tables | std::views::transform([&db] (auto&& t) { return t->describe(replica::make_schema_describe_helper(t, db), describe_option::NO_STMTS); - }) | std::ranges::to(); + }) | std::ranges::to>(); } // DESCRIBE UTILITY @@ -422,7 +423,7 @@ lw_shared_ptr get_keyspace_metadata(const data_dictionary::da Descriptions don't contain create_statements. * @throw `invalid_request_exception` if there is no such keyspace */ -future> list_elements(const data_dictionary::database& db, const sstring& ks, element_type element) { +future> list_elements(const data_dictionary::database& db, const sstring& ks, element_type element) { auto ks_meta = get_keyspace_metadata(db, ks); auto& replica_db = db.real_database(); @@ -446,7 +447,7 @@ future> list_elements(const data_dictionary::database& Description contains create_statement. * @throw `invalid_request_exception` if there is no such keyspace or there is no element with given name */ -future> describe_element(const data_dictionary::database& db, const sstring& ks, element_type element, const sstring& name, bool with_internals) { +future> describe_element(const data_dictionary::database& db, const sstring& ks, element_type element, const sstring& name, bool with_internals) { auto ks_meta = get_keyspace_metadata(db, ks); auto& replica_db = db.real_database(); @@ -470,12 +471,12 @@ future> describe_element(const data_dictionary::databas Descriptions contain create_statements. * @throw `invalid_request_exception` if there is no such keyspace or there is no element with given name */ -future> describe_all_keyspace_elements(const data_dictionary::database& db, const sstring& ks, bool with_internals) { +future> describe_all_keyspace_elements(const data_dictionary::database& db, const sstring& ks, bool with_internals) { auto ks_meta = get_keyspace_metadata(db, ks); auto& replica_db = db.real_database(); - std::vector result; + utils::chunked_vector result; - auto inserter = [&result] (std::vector&& elements) mutable { + auto inserter = [&result] (utils::chunked_vector&& elements) mutable { result.insert(result.end(), std::make_move_iterator(elements.begin()), std::make_move_iterator(elements.end())); }; @@ -506,7 +507,7 @@ std::vector> get_element_column_specificatio return col_specs; } -std::vector> serialize_descriptions(std::vector&& descs, bool serialize_create_statement = true) { +std::vector> serialize_descriptions(utils::chunked_vector&& descs, bool serialize_create_statement = true) { return descs | std::views::as_rvalue | std::views::transform([serialize_create_statement] (description desc) { return std::move(desc).serialize(serialize_create_statement); }) | std::ranges::to(); @@ -651,7 +652,7 @@ future>> schema_describe_statement::d auto db = qp.db(); auto result = co_await std::visit(overloaded_functor{ - [&] (const schema_desc& config) -> future> { + [&] (const schema_desc& config) -> future> { auto& auth_service = *client_state.get_auth_service(); if (config.with_hashed_passwords) { @@ -662,7 +663,7 @@ future>> schema_describe_statement::d } auto keyspaces = config.full_schema ? db.get_all_keyspaces() : db.get_user_keyspaces(); - std::vector schema_result; + utils::chunked_vector schema_result; for (auto&& ks: keyspaces) { if (!config.full_schema && db.extensions().is_extension_internal_keyspace(ks)) { @@ -686,7 +687,7 @@ future>> schema_describe_statement::d co_return schema_result; }, - [&] (const keyspace_desc& config) -> future> { + [&] (const keyspace_desc& config) -> future> { auto ks = client_state.get_raw_keyspace(); if (config.keyspace) { ks = *config.keyspace; @@ -730,7 +731,7 @@ future>> listing_describe_statement:: std::ranges::sort(keyspaces); } - std::vector result; + utils::chunked_vector result; for (auto&& ks: keyspaces) { auto ks_result = co_await list_elements(db, ks, _element); result.insert(result.end(), std::make_move_iterator(ks_result.begin()), std::make_move_iterator(ks_result.end()));