/* * Modified by ScyllaDB * Copyright (C) 2015-present ScyllaDB */ /* * SPDX-License-Identifier: (LicenseRef-ScyllaDB-Source-Available-1.0 and Apache-2.0) */ #pragma once #include "cql3/functions/functions.hh" #include "mutation/mutation.hh" #include "schema/schema_fwd.hh" #include "schema_features.hh" #include "utils/hashing.hh" #include "schema/schema_mutations.hh" #include "types/map.hh" #include "query/query-result-set.hh" #include "db/view/base_info.hh" #include #include #include namespace data_dictionary { class keyspace_metadata; class user_types_storage; } using keyspace_metadata = data_dictionary::keyspace_metadata; namespace replica { class database; } namespace query { class result_set; } namespace service { class storage_service; class storage_proxy; } namespace gms { class feature_service; } namespace cql3::functions { class user_function; class user_aggregate; } namespace db { class system_keyspace; class extensions; class config; class schema_ctxt { public: schema_ctxt(const config&, std::shared_ptr uts, const gms::feature_service&, replica::database* = nullptr); schema_ctxt(replica::database&); schema_ctxt(sharded&); schema_ctxt(sharded&); const db::extensions& extensions() const { return _extensions; } unsigned murmur3_partitioner_ignore_msb_bits() const { return _murmur3_partitioner_ignore_msb_bits; } uint32_t schema_registry_grace_period() const { return _schema_registry_grace_period; } const data_dictionary::user_types_storage& user_types() const noexcept { return *_user_types; } const gms::feature_service& features() const { return _features; } replica::database* get_db() const { return _db; } private: replica::database* _db; const gms::feature_service& _features; const db::extensions& _extensions; const unsigned _murmur3_partitioner_ignore_msb_bits; const uint32_t _schema_registry_grace_period; const std::shared_ptr _user_types; }; namespace schema_tables { extern logging::logger slogger; using schema_result = std::map>; using schema_result_value_type = std::pair>; const std::string COMMITLOG_FILENAME_PREFIX("SchemaLog-"); namespace v3 { static constexpr auto NAME = "system_schema"; static constexpr auto KEYSPACES = "keyspaces"; static constexpr auto SCYLLA_KEYSPACES = "scylla_keyspaces"; static constexpr auto TABLES = "tables"; static constexpr auto SCYLLA_TABLES = "scylla_tables"; static constexpr auto COLUMNS = "columns"; static constexpr auto DROPPED_COLUMNS = "dropped_columns"; static constexpr auto TRIGGERS = "triggers"; static constexpr auto VIEWS = "views"; static constexpr auto TYPES = "types"; static constexpr auto FUNCTIONS = "functions"; static constexpr auto AGGREGATES = "aggregates"; static constexpr auto SCYLLA_AGGREGATES = "scylla_aggregates"; static constexpr auto INDEXES = "indexes"; static constexpr auto VIEW_VIRTUAL_COLUMNS = "view_virtual_columns"; // Scylla specific static constexpr auto COMPUTED_COLUMNS = "computed_columns"; // Scylla specific static constexpr auto SCYLLA_TABLE_SCHEMA_HISTORY = "scylla_table_schema_history"; // Scylla specific; schema_ptr keyspaces(); schema_ptr columns(); schema_ptr view_virtual_columns(); schema_ptr dropped_columns(); schema_ptr indexes(); schema_ptr tables(); schema_ptr scylla_tables(schema_features features = schema_features::full()); schema_ptr views(); schema_ptr types(); schema_ptr functions(); schema_ptr aggregates(); schema_ptr computed_columns(); // Belongs to the "system" keyspace schema_ptr scylla_table_schema_history(); // Returns table ids of all schema tables which contribute to schema_mutations, // i.e. those which are used to define schema of a table or a view. // All such tables have a clustering key whose first column is the table name. const std::unordered_set& schema_tables_holding_schema_mutations(); } struct qualified_name { sstring keyspace_name; sstring table_name; qualified_name(sstring keyspace_name, sstring table_name) : keyspace_name(std::move(keyspace_name)) , table_name(std::move(table_name)) { } qualified_name(const schema_ptr& s) : keyspace_name(s->ks_name()) , table_name(s->cf_name()) { } auto operator<=>(const qualified_name&) const = default; }; future read_table_mutations(sharded& proxy, const qualified_name& table, schema_ptr s); using namespace v3; // Change on non-backwards compatible changes of schema mutations. // Replication of schema between nodes with different version is inhibited. extern const sstring version; // Returns schema_ptrs for all schema tables supported by given schema_features. std::vector all_tables(schema_features); // Like all_tables(), but returns table_info of each table. std::vector all_table_infos(schema_features); // saves/creates all the system objects in the appropriate keyspaces; // deletes them first, so they will be effectively overwritten. future<> save_system_schema(cql3::query_processor& qp); future calculate_schema_digest(sharded& proxy, schema_features, noncopyable_function accept_keyspace); // Calculates schema digest for all non-system keyspaces future calculate_schema_digest(sharded& proxy, schema_features); // Must be called on shard 0. future> hold_merge_lock() noexcept; future<> with_merge_lock(noncopyable_function ()> func); future<> update_schema_version_and_announce(sharded& sys_ks, sharded& proxy, schema_features features, std::optional version_from_group0); future> get_group0_schema_version(db::system_keyspace& sys_ks); // Recalculates the local schema version. // // It is safe to call concurrently with recalculate_schema_version() and merge_schema() in which case it // is guaranteed that the schema version we end up with after all calls will reflect the most recent state // of feature_service and schema tables. future<> recalculate_schema_version(sharded& sys_ks, sharded& proxy, gms::feature_service& feat); future> convert_schema_to_mutations(sharded& proxy, schema_features); utils::chunked_vector adjust_schema_for_schema_features(utils::chunked_vector schema, schema_features features); future read_schema_partition_for_keyspace(sharded& proxy, sstring schema_table_name, sstring keyspace_name); future read_keyspace_mutation(sharded&, const sstring& keyspace_name); utils::chunked_vector make_create_keyspace_mutations(schema_features features, lw_shared_ptr keyspace, api::timestamp_type timestamp, bool with_tables_and_types_and_functions = true); utils::chunked_vector make_drop_keyspace_mutations(schema_features features, lw_shared_ptr keyspace, api::timestamp_type timestamp); future> create_keyspace_metadata(const schema_result_value_type& partition, lw_shared_ptr scylla_specific_rs); future> extract_scylla_specific_keyspace_info(sharded& proxy, const schema_result_value_type& partition); utils::chunked_vector make_create_type_mutations(lw_shared_ptr keyspace, user_type type, api::timestamp_type timestamp); // Given a set of rows that is sorted by keyspace, create types for each keyspace. // The topological sort in each keyspace is necessary when creating types, since we can only create a type when the // types it reference have already been created. future> create_types(replica::database& db, const std::vector& rows, std::map>& new_keyspaces); future> create_types_from_schema_partition(keyspace_metadata& ks, lw_shared_ptr result); std::vector read_arg_types(const query::result_set_row& row, const sstring& keyspace, const data_dictionary::user_types_storage& user_types); future> create_func(replica::database& db, const query::result_set_row& row, const data_dictionary::user_types_storage& user_types); seastar::future>> create_functions_from_schema_partition(replica::database& db, lw_shared_ptr result); shared_ptr create_aggregate(replica::database& db, const query::result_set_row& row, const query::result_set_row* scylla_row, cql3::functions::change_batch& batch, const data_dictionary::user_types_storage& user_types); std::vector> create_aggregates_from_schema_partition(replica::database& db, lw_shared_ptr result, lw_shared_ptr scylla_result, cql3::functions::change_batch& batch); utils::chunked_vector make_create_function_mutations(shared_ptr func, api::timestamp_type timestamp); utils::chunked_vector make_drop_function_mutations(shared_ptr func, api::timestamp_type timestamp); utils::chunked_vector make_create_aggregate_mutations(schema_features features, shared_ptr func, api::timestamp_type timestamp); utils::chunked_vector make_drop_aggregate_mutations(schema_features features, shared_ptr aggregate, api::timestamp_type timestamp); utils::chunked_vector make_drop_type_mutations(lw_shared_ptr keyspace, user_type type, api::timestamp_type timestamp); void add_type_to_schema_mutation(user_type type, api::timestamp_type timestamp, utils::chunked_vector& mutations); utils::chunked_vector make_create_table_mutations(schema_ptr table, api::timestamp_type timestamp); utils::chunked_vector make_update_table_mutations( service::storage_proxy& sp, lw_shared_ptr keyspace, schema_ptr old_table, schema_ptr new_table, api::timestamp_type timestamp); future> create_tables_from_tables_partition(sharded& proxy, const schema_result::mapped_type& result); utils::chunked_vector make_drop_table_mutations(lw_shared_ptr keyspace, schema_ptr table, api::timestamp_type timestamp); schema_ptr create_table_from_mutations(const schema_ctxt&, schema_mutations, const data_dictionary::user_types_storage& user_types, schema_ptr cdc_schema, std::optional version = {}); view_ptr create_view_from_mutations(const schema_ctxt&, schema_mutations, const data_dictionary::user_types_storage&, schema_ptr, std::optional version = {}); view_ptr create_view_from_mutations(const schema_ctxt&, schema_mutations, const data_dictionary::user_types_storage&, std::optional = {}, std::optional version = {}); future> create_views_from_schema_partition(sharded& proxy, const schema_result::mapped_type& result); schema_mutations make_schema_mutations(schema_ptr s, api::timestamp_type timestamp, bool with_columns); mutation make_scylla_tables_mutation(schema_ptr, api::timestamp_type timestamp); void add_table_or_view_to_schema_mutation(schema_ptr view, api::timestamp_type timestamp, bool with_columns, utils::chunked_vector& mutations); utils::chunked_vector make_create_view_mutations(lw_shared_ptr keyspace, view_ptr view, api::timestamp_type timestamp); utils::chunked_vector make_update_view_mutations(lw_shared_ptr keyspace, view_ptr old_view, view_ptr new_view, api::timestamp_type timestamp, bool include_base); utils::chunked_vector make_drop_view_mutations(lw_shared_ptr keyspace, view_ptr view, api::timestamp_type timestamp); void check_no_legacy_secondary_index_mv_schema(replica::database& db, const view_ptr& v, schema_ptr base_schema); bool view_should_exist(const index_metadata& im); sstring serialize_kind(column_kind kind); column_kind deserialize_kind(sstring kind); data_type parse_type(sstring str); sstring serialize_index_kind(index_metadata_kind kind); index_metadata_kind deserialize_index_kind(sstring kind); mutation compact_for_schema_digest(const mutation& m); void feed_hash_for_schema_digest(hasher&, const mutation&, schema_features); template std::optional> get_map(const query::result_set_row& row, const sstring& name) { if (auto values = row.get(name)) { std::map map; for (auto&& entry : *values) { map.emplace(value_cast(entry.first), value_cast(entry.second)); }; return map; } return std::nullopt; } /// Stores the column mapping for the table being created or altered in the system table /// which holds a history of schema versions alongside with their column mappings. /// Can be used to insert entries with TTL (equal to DEFAULT_GC_GRACE_SECONDS) in case we are /// overwriting an existing column mapping to garbage collect obsolete entries. future<> store_column_mapping(sharded& proxy, schema_ptr s, bool with_ttl); /// Query column mapping for a given version of the table locally. future get_column_mapping(db::system_keyspace& sys_ks, table_id table_id, table_schema_version version); /// Check that column mapping exists for a given version of the table future column_mapping_exists(db::system_keyspace& sys_ks, table_id table_id, table_schema_version version); /// Delete matching column mapping entries from the `system.scylla_table_schema_history` table future<> drop_column_mapping(db::system_keyspace& sys_ks, table_id table_id, table_schema_version version); } // namespace schema_tables } // namespace db