// Copyright 2024 PingCAP, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace DB { StorageSystemDTLocalIndexes::StorageSystemDTLocalIndexes(const std::string & name_) : name(name_) { setColumns(ColumnsDescription({ {"database", std::make_shared()}, {"table", std::make_shared()}, {"tidb_database", std::make_shared()}, {"tidb_table", std::make_shared()}, {"keyspace_id", std::make_shared(std::make_shared())}, {"table_id", std::make_shared()}, {"belonging_table_id", std::make_shared()}, {"column_id", std::make_shared()}, {"index_id", std::make_shared()}, {"index_kind", std::make_shared()}, {"rows_stable_indexed", std::make_shared()}, // Total rows {"rows_stable_not_indexed", std::make_shared()}, // Total rows {"rows_delta_indexed", std::make_shared()}, // Total rows {"rows_delta_not_indexed", std::make_shared()}, // Total rows // Fatal message when building local index // when this is not an empty string, it means the build job of this local is aborted {"error_message", std::make_shared()}, })); } std::optional getLocalIndexesStatsFromStorage(const StorageDeltaMergePtr & dm_storage) { if (dm_storage->isTombstone()) return std::nullopt; const auto & table_info = dm_storage->getTableInfo(); if (auto store = dm_storage->getStoreIfInited(); store) return store->getLocalIndexStats(); // Check whether there exist any local index without initiating the store return DM::DeltaMergeStore::genLocalIndexStatsByTableInfo(table_info); } KeyspaceID parseKeyspaceID(const SelectQueryInfo & query_info) { const auto & select = typeid_cast(*query_info.query); const auto & where_expression = select.where_expression; const auto * func = typeid_cast(where_expression.get()); // TODO: support other functions. if (!func || func->name != "equals" || func->arguments->children.size() != 2) return NullspaceID; const auto * identifier = typeid_cast(func->arguments->children[0].get()); if (!identifier || identifier->name != "keyspace_id") return NullspaceID; const auto * literal = typeid_cast(func->arguments->children[1].get()); if (!literal) return NullspaceID; return literal->value.get(); } BlockInputStreams StorageSystemDTLocalIndexes::read( const Names & column_names, const SelectQueryInfo & query_info, const Context & context, QueryProcessingStage::Enum & processed_stage, const size_t /*max_block_size*/, const unsigned /*num_streams*/) { check(column_names); processed_stage = QueryProcessingStage::FetchColumns; MutableColumns res_columns = getSampleBlock().cloneEmptyColumns(); SchemaNameMapper mapper; auto databases = context.getDatabases(); const auto parsed_keyspace_id = parseKeyspaceID(query_info); for (const auto & d : databases) { String database_name = d.first; const auto & database = d.second; const DatabaseTiFlash * db_tiflash = typeid_cast(database.get()); if (!db_tiflash) continue; const auto keyspace_id = db_tiflash->getDatabaseInfo().keyspace_id; if (parsed_keyspace_id != NullspaceID && keyspace_id != parsed_keyspace_id) continue; auto it = database->getIterator(context); for (; it->isValid(); it->next()) { const auto & table_name = it->name(); auto & storage = it->table(); if (storage->getName() != MutableSupport::delta_tree_storage_name) continue; auto dm_storage = std::dynamic_pointer_cast(storage); const auto & table_info = dm_storage->getTableInfo(); const auto table_id = table_info.id; const auto index_stats = getLocalIndexesStatsFromStorage(dm_storage); if (!index_stats) continue; for (const auto & stat : *index_stats) { size_t j = 0; res_columns[j++]->insert(database_name); res_columns[j++]->insert(table_name); String tidb_db_name; tidb_db_name = db_tiflash->getDatabaseInfo().name; res_columns[j++]->insert(tidb_db_name); String tidb_table_name = table_info.name; res_columns[j++]->insert(tidb_table_name); if (keyspace_id == NullspaceID) res_columns[j++]->insert(Field()); else res_columns[j++]->insert(static_cast(keyspace_id)); res_columns[j++]->insert(table_id); res_columns[j++]->insert(table_info.belonging_table_id); res_columns[j++]->insert(stat.column_id); res_columns[j++]->insert(stat.index_id); res_columns[j++]->insert(stat.index_kind); res_columns[j++]->insert(stat.rows_stable_indexed); res_columns[j++]->insert(stat.rows_stable_not_indexed); res_columns[j++]->insert(stat.rows_delta_indexed); res_columns[j++]->insert(stat.rows_delta_not_indexed); res_columns[j++]->insert(stat.error_message); } } } return BlockInputStreams( 1, std::make_shared(getSampleBlock().cloneWithColumns(std::move(res_columns)))); } } // namespace DB