Skip to main content

common_meta/
key.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! This mod defines all the keys used in the metadata store (Metasrv).
16//! Specifically, there are these kinds of keys:
17//!
18//! 1. Datanode table key: `__dn_table/{datanode_id}/{table_id}`
19//!     - The value is a [DatanodeTableValue] struct; it contains `table_id` and the regions that
20//!       belong to this Datanode.
21//!     - This key is primary used in the startup of Datanode, to let Datanode know which tables
22//!       and regions it should open.
23//!
24//! 2. Table info key: `__table_info/{table_id}`
25//!     - The value is a [TableInfoValue] struct; it contains the whole table info (like column
26//!       schemas).
27//!     - This key is mainly used in constructing the table in Datanode and Frontend.
28//!
29//! 3. Catalog name key: `__catalog_name/{catalog_name}`
30//!     - Indices all catalog names
31//!
32//! 4. Schema name key: `__schema_name/{catalog_name}/{schema_name}`
33//!     - Indices all schema names belong to the {catalog_name}
34//!
35//! 5. Table name key: `__table_name/{catalog_name}/{schema_name}/{table_name}`
36//!     - The value is a [TableNameValue] struct; it contains the table id.
37//!     - Used in the table name to table id lookup.
38//!
39//! 6. Flow info key: `__flow/info/{flow_id}`
40//!     - Stores metadata of the flow.
41//!
42//! 7. Flow route key: `__flow/route/{flow_id}/{partition_id}`
43//!     - Stores route of the flow.
44//!
45//! 8. Flow name key: `__flow/name/{catalog}/{flow_name}`
46//!     - Mapping {catalog}/{flow_name} to {flow_id}
47//!
48//! 9. Flownode flow key: `__flow/flownode/{flownode_id}/{flow_id}/{partition_id}`
49//!     - Mapping {flownode_id} to {flow_id}
50//!
51//! 10. Table flow key: `__flow/source_table/{table_id}/{flownode_id}/{flow_id}/{partition_id}`
52//!     - Mapping source table's {table_id} to {flownode_id}
53//!     - Used in `Flownode` booting.
54//!
55//! 11. View info key: `__view_info/{view_id}`
56//!     - The value is a [ViewInfoValue] struct; it contains the encoded logical plan.
57//!     - This key is mainly used in constructing the view in Datanode and Frontend.
58//!
59//! 12. Kafka topic key: `__topic_name/kafka/{topic_name}`
60//!     - The key is used to track existing topics in Kafka.
61//!     - The value is a [TopicNameValue](crate::key::topic_name::TopicNameValue) struct; it contains the `pruned_entry_id` which represents
62//!       the highest entry id that has been pruned from the remote WAL.
63//!     - When a region uses this topic, it should start replaying entries from `pruned_entry_id + 1` (minimum available entry id).
64//!
65//! 13. Topic name to region map key `__topic_region/{topic_name}/{region_id}`
66//!     - Mapping {topic_name} to {region_id}
67//!
68//! 14. Datanode epoch key: `__datanode_epoch/{datanode_id}`
69//!     - The highest `node_epoch` the metasrv leader has accepted from the datanode
70//!
71//! All keys have related managers. The managers take care of the serialization and deserialization
72//! of keys and values, and the interaction with the underlying KV store backend.
73//!
74//! To simplify the managers used in struct fields and function parameters, we define "unify"
75//! table metadata manager: [TableMetadataManager]
76//! and flow metadata manager: [FlowMetadataManager](crate::key::flow::FlowMetadataManager).
77//! It contains all the managers defined above. It's recommended to just use this manager only.
78//!
79//! The whole picture of flow keys will be like this:
80//!
81//! __flow/
82//!   info/
83//!     {flow_id}
84//!   route/
85//!     {flow_id}/
86//!      {partition_id}
87//!
88//!    name/
89//!      {catalog_name}
90//!        {flow_name}
91//!
92//!    flownode/
93//!      {flownode_id}/
94//!        {flow_id}/
95//!          {partition_id}
96//!
97//!    source_table/
98//!      {table_id}/
99//!        {flownode_id}/
100//!          {flow_id}/
101//!            {partition_id}
102
103pub mod catalog_name;
104pub mod datanode_epoch;
105pub mod datanode_table;
106pub mod flow;
107pub mod node_address;
108pub mod runtime_switch;
109mod schema_metadata_manager;
110pub mod schema_name;
111pub mod table_info;
112pub mod table_name;
113pub mod table_repart;
114pub mod table_route;
115#[cfg(any(test, feature = "testing"))]
116pub mod test_utils;
117pub mod tombstone;
118pub mod topic_name;
119pub mod topic_region;
120pub mod txn_helper;
121pub mod view_info;
122
123use std::collections::{BTreeMap, HashMap, HashSet};
124use std::fmt::Debug;
125use std::ops::{Deref, DerefMut};
126use std::sync::Arc;
127
128use bytes::Bytes;
129use common_base::regex_pattern::NAME_PATTERN;
130use common_catalog::consts::{
131    DEFAULT_CATALOG_NAME, DEFAULT_PRIVATE_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, INFORMATION_SCHEMA_NAME,
132};
133use common_telemetry::warn;
134use common_wal::options::WalOptions;
135use datanode_table::{DatanodeTableKey, DatanodeTableManager, DatanodeTableValue};
136use flow::flow_route::FlowRouteValue;
137use flow::table_flow::TableFlowValue;
138use futures_util::TryStreamExt;
139use futures_util::stream::BoxStream;
140use lazy_static::lazy_static;
141use regex::Regex;
142pub use schema_metadata_manager::{SchemaMetadataManager, SchemaMetadataManagerRef};
143use serde::de::DeserializeOwned;
144use serde::{Deserialize, Serialize};
145use snafu::{OptionExt, ResultExt, ensure};
146use store_api::storage::RegionNumber;
147use table::metadata::{TableId, TableInfo};
148use table::table_name::TableName;
149use table_info::{TableInfoKey, TableInfoManager, TableInfoValue};
150use table_name::{TableNameKey, TableNameManager, TableNameValue};
151use topic_name::TopicNameManager;
152use topic_region::{TopicRegionKey, TopicRegionManager};
153use view_info::{ViewInfoKey, ViewInfoManager, ViewInfoValue};
154
155use self::catalog_name::{CatalogManager, CatalogNameKey, CatalogNameValue};
156use self::datanode_epoch::DatanodeEpochValue;
157use self::datanode_table::RegionInfo;
158use self::flow::flow_info::FlowInfoValue;
159use self::flow::flow_name::FlowNameValue;
160use self::schema_name::{SchemaManager, SchemaNameKey, SchemaNameValue};
161use self::table_route::{TableRouteManager, TableRouteValue};
162use self::tombstone::TombstoneManager;
163use crate::DatanodeId;
164use crate::error::{self, Result, SerdeJsonSnafu};
165use crate::key::flow::flow_state::FlowStateValue;
166use crate::key::node_address::NodeAddressValue;
167use crate::key::table_repart::{TableRepartKey, TableRepartManager};
168use crate::key::table_route::TableRouteKey;
169use crate::key::topic_region::TopicRegionValue;
170use crate::key::txn_helper::TxnOpGetResponseSet;
171use crate::kv_backend::KvBackendRef;
172use crate::kv_backend::txn::{Txn, TxnOp};
173use crate::rpc::KeyValue;
174use crate::rpc::router::{LeaderState, RegionRoute, region_distribution};
175use crate::rpc::store::{BatchDeleteRequest, PutRequest};
176use crate::state_store::PoisonValue;
177use crate::wal_provider::RegionWalOptions;
178
179pub const TOPIC_NAME_PATTERN: &str = r"[a-zA-Z0-9_:-][a-zA-Z0-9_:\-\.@#]*";
180pub const LEGACY_MAINTENANCE_KEY: &str = "__maintenance";
181pub const MAINTENANCE_KEY: &str = "__switches/maintenance";
182pub const REPARTITION_GC_REQUIRED_KEY: &str = "__requirements/gc/repartition";
183pub const PAUSE_PROCEDURE_KEY: &str = "__switches/pause_procedure";
184pub const RECOVERY_MODE_KEY: &str = "__switches/recovery";
185
186pub const DATANODE_TABLE_KEY_PREFIX: &str = "__dn_table";
187pub const DATANODE_EPOCH_KEY_PREFIX: &str = "__datanode_epoch";
188pub const TABLE_INFO_KEY_PREFIX: &str = "__table_info";
189pub const VIEW_INFO_KEY_PREFIX: &str = "__view_info";
190pub const TABLE_NAME_KEY_PREFIX: &str = "__table_name";
191pub const CATALOG_NAME_KEY_PREFIX: &str = "__catalog_name";
192pub const SCHEMA_NAME_KEY_PREFIX: &str = "__schema_name";
193pub const TABLE_ROUTE_PREFIX: &str = "__table_route";
194pub const TABLE_REPART_PREFIX: &str = "__table_repart";
195pub const NODE_ADDRESS_PREFIX: &str = "__node_address";
196pub const KAFKA_TOPIC_KEY_PREFIX: &str = "__topic_name/kafka";
197// The legacy topic key prefix is used to store the topic name in previous versions.
198pub const LEGACY_TOPIC_KEY_PREFIX: &str = "__created_wal_topics/kafka";
199pub const TOPIC_REGION_PREFIX: &str = "__topic_region";
200
201/// The election key.
202pub const ELECTION_KEY: &str = "__metasrv_election";
203/// The root key of metasrv election candidates.
204pub const CANDIDATES_ROOT: &str = "__metasrv_election_candidates/";
205
206/// The keys with these prefixes will be loaded into the cache when the leader starts.
207pub const CACHE_KEY_PREFIXES: [&str; 6] = [
208    TABLE_NAME_KEY_PREFIX,
209    CATALOG_NAME_KEY_PREFIX,
210    SCHEMA_NAME_KEY_PREFIX,
211    TABLE_ROUTE_PREFIX,
212    NODE_ADDRESS_PREFIX,
213    DATANODE_EPOCH_KEY_PREFIX,
214];
215
216/// A set of regions with the same role.
217#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
218pub struct RegionRoleSet {
219    /// Leader regions.
220    pub leader_regions: Vec<RegionNumber>,
221    /// Follower regions.
222    pub follower_regions: Vec<RegionNumber>,
223}
224
225impl<'de> Deserialize<'de> for RegionRoleSet {
226    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
227    where
228        D: serde::Deserializer<'de>,
229    {
230        #[derive(Deserialize)]
231        #[serde(untagged)]
232        enum RegionRoleSetOrLeaderOnly {
233            Full {
234                leader_regions: Vec<RegionNumber>,
235                follower_regions: Vec<RegionNumber>,
236            },
237            LeaderOnly(Vec<RegionNumber>),
238        }
239        match RegionRoleSetOrLeaderOnly::deserialize(deserializer)? {
240            RegionRoleSetOrLeaderOnly::Full {
241                leader_regions,
242                follower_regions,
243            } => Ok(RegionRoleSet::new(leader_regions, follower_regions)),
244            RegionRoleSetOrLeaderOnly::LeaderOnly(leader_regions) => {
245                Ok(RegionRoleSet::new(leader_regions, vec![]))
246            }
247        }
248    }
249}
250
251impl RegionRoleSet {
252    /// Create a new region role set.
253    pub fn new(leader_regions: Vec<RegionNumber>, follower_regions: Vec<RegionNumber>) -> Self {
254        Self {
255            leader_regions,
256            follower_regions,
257        }
258    }
259
260    /// Add a leader region to the set.
261    pub fn add_leader_region(&mut self, region_number: RegionNumber) {
262        self.leader_regions.push(region_number);
263    }
264
265    /// Add a follower region to the set.
266    pub fn add_follower_region(&mut self, region_number: RegionNumber) {
267        self.follower_regions.push(region_number);
268    }
269
270    /// Sort the regions.
271    pub fn sort(&mut self) {
272        self.follower_regions.sort();
273        self.leader_regions.sort();
274    }
275}
276
277/// The distribution of regions.
278///
279/// The key is the datanode id, the value is the region role set.
280pub type RegionDistribution = BTreeMap<DatanodeId, RegionRoleSet>;
281
282/// The id of flow.
283pub type FlowId = u32;
284/// The partition of flow.
285pub type FlowPartitionId = u32;
286
287lazy_static! {
288    pub static ref TOPIC_NAME_PATTERN_REGEX: Regex = Regex::new(TOPIC_NAME_PATTERN).unwrap();
289}
290
291lazy_static! {
292    static ref TABLE_INFO_KEY_PATTERN: Regex =
293        Regex::new(&format!("^{TABLE_INFO_KEY_PREFIX}/([0-9]+)$")).unwrap();
294}
295
296lazy_static! {
297    static ref VIEW_INFO_KEY_PATTERN: Regex =
298        Regex::new(&format!("^{VIEW_INFO_KEY_PREFIX}/([0-9]+)$")).unwrap();
299}
300
301lazy_static! {
302    static ref TABLE_ROUTE_KEY_PATTERN: Regex =
303        Regex::new(&format!("^{TABLE_ROUTE_PREFIX}/([0-9]+)$")).unwrap();
304}
305
306lazy_static! {
307    pub(crate) static ref TABLE_REPART_KEY_PATTERN: Regex =
308        Regex::new(&format!("^{TABLE_REPART_PREFIX}/([0-9]+)$")).unwrap();
309}
310
311lazy_static! {
312    static ref DATANODE_TABLE_KEY_PATTERN: Regex =
313        Regex::new(&format!("^{DATANODE_TABLE_KEY_PREFIX}/([0-9]+)/([0-9]+)$")).unwrap();
314}
315
316lazy_static! {
317    static ref TABLE_NAME_KEY_PATTERN: Regex = Regex::new(&format!(
318        "^{TABLE_NAME_KEY_PREFIX}/({NAME_PATTERN})/({NAME_PATTERN})/({NAME_PATTERN})$"
319    ))
320    .unwrap();
321}
322
323lazy_static! {
324    /// CATALOG_NAME_KEY: {CATALOG_NAME_KEY_PREFIX}/{catalog_name}
325    static ref CATALOG_NAME_KEY_PATTERN: Regex = Regex::new(&format!(
326        "^{CATALOG_NAME_KEY_PREFIX}/({NAME_PATTERN})$"
327    ))
328        .unwrap();
329}
330
331lazy_static! {
332    /// SCHEMA_NAME_KEY: {SCHEMA_NAME_KEY_PREFIX}/{catalog_name}/{schema_name}
333    static ref SCHEMA_NAME_KEY_PATTERN:Regex=Regex::new(&format!(
334        "^{SCHEMA_NAME_KEY_PREFIX}/({NAME_PATTERN})/({NAME_PATTERN})$"
335    ))
336        .unwrap();
337}
338
339lazy_static! {
340    static ref NODE_ADDRESS_PATTERN: Regex =
341        Regex::new(&format!("^{NODE_ADDRESS_PREFIX}/([0-9]+)/([0-9]+)$")).unwrap();
342}
343
344lazy_static! {
345    pub static ref KAFKA_TOPIC_KEY_PATTERN: Regex =
346        Regex::new(&format!("^{KAFKA_TOPIC_KEY_PREFIX}/(.*)$")).unwrap();
347}
348
349lazy_static! {
350    pub static ref TOPIC_REGION_PATTERN: Regex = Regex::new(&format!(
351        "^{TOPIC_REGION_PREFIX}/({TOPIC_NAME_PATTERN})/([0-9]+)$"
352    ))
353    .unwrap();
354}
355
356/// The key of metadata.
357pub trait MetadataKey<'a, T> {
358    fn to_bytes(&self) -> Vec<u8>;
359
360    fn from_bytes(bytes: &'a [u8]) -> Result<T>;
361}
362
363#[derive(Debug, Clone, PartialEq)]
364pub struct BytesAdapter(Vec<u8>);
365
366impl From<Vec<u8>> for BytesAdapter {
367    fn from(value: Vec<u8>) -> Self {
368        Self(value)
369    }
370}
371
372impl<'a> MetadataKey<'a, BytesAdapter> for BytesAdapter {
373    fn to_bytes(&self) -> Vec<u8> {
374        self.0.clone()
375    }
376
377    fn from_bytes(bytes: &'a [u8]) -> Result<BytesAdapter> {
378        Ok(BytesAdapter(bytes.to_vec()))
379    }
380}
381
382pub(crate) trait MetadataKeyGetTxnOp {
383    fn build_get_op(
384        &self,
385    ) -> (
386        TxnOp,
387        impl for<'a> FnMut(&'a mut TxnOpGetResponseSet) -> Option<Vec<u8>>,
388    );
389}
390
391pub trait MetadataValue {
392    fn try_from_raw_value(raw_value: &[u8]) -> Result<Self>
393    where
394        Self: Sized;
395
396    fn try_as_raw_value(&self) -> Result<Vec<u8>>;
397}
398
399pub type TableMetadataManagerRef = Arc<TableMetadataManager>;
400
401pub struct TableMetadataManager {
402    table_name_manager: TableNameManager,
403    table_info_manager: TableInfoManager,
404    view_info_manager: ViewInfoManager,
405    datanode_table_manager: DatanodeTableManager,
406    catalog_manager: CatalogManager,
407    schema_manager: SchemaManager,
408    table_route_manager: TableRouteManager,
409    table_repart_manager: TableRepartManager,
410    tombstone_manager: TombstoneManager,
411    topic_name_manager: TopicNameManager,
412    topic_region_manager: TopicRegionManager,
413    kv_backend: KvBackendRef,
414}
415
416#[macro_export]
417macro_rules! ensure_values {
418    ($got:expr, $expected_value:expr, $name:expr) => {
419        ensure!(
420            $got == $expected_value,
421            error::UnexpectedSnafu {
422                err_msg: format!(
423                    "Reads the different value: {:?} during {}, expected: {:?}",
424                    $got, $name, $expected_value
425                )
426            }
427        );
428    };
429}
430
431/// A struct containing a deserialized value(`inner`) and an original bytes.
432///
433/// - Serialize behaviors:
434///
435/// The `inner` field will be ignored.
436///
437/// - Deserialize behaviors:
438///
439/// The `inner` field will be deserialized from the `bytes` field.
440pub struct DeserializedValueWithBytes<T: DeserializeOwned + Serialize> {
441    // The original bytes of the inner.
442    bytes: Bytes,
443    // The value was deserialized from the original bytes.
444    inner: T,
445}
446
447#[derive(Debug, Clone, PartialEq, Eq)]
448pub struct DroppedTableName {
449    /// Table id stored in the tombstoned table-name mapping.
450    pub table_id: TableId,
451    /// Original fully qualified table name.
452    pub table_name: TableName,
453    /// Unix timestamp in milliseconds when this table was soft-dropped.
454    pub dropped_at: Option<i64>,
455    /// Fixed automatic-GC deadline in Unix milliseconds.
456    pub retention_expires_at: Option<i64>,
457    /// Unique identity of this soft-drop generation.
458    pub drop_generation: Option<String>,
459    /// Whether an automatic purge has durably claimed this dropped table.
460    pub purging: bool,
461}
462
463#[derive(Debug, Clone)]
464pub struct DroppedTableMetadata {
465    /// Table id of the dropped table.
466    pub table_id: TableId,
467    /// Original fully qualified table name.
468    pub table_name: TableName,
469    /// Tombstoned table info value.
470    pub table_info_value: TableInfoValue,
471    /// Tombstoned table route value.
472    pub table_route_value: TableRouteValue,
473    /// Per-region WAL options recovered from tombstoned datanode metadata.
474    pub region_wal_options: HashMap<RegionNumber, WalOptions>,
475    /// Unix timestamp in milliseconds when this table was soft-dropped.
476    pub dropped_at: Option<i64>,
477    /// Fixed automatic-GC deadline in Unix milliseconds.
478    pub retention_expires_at: Option<i64>,
479    /// Unique identity of this soft-drop generation.
480    pub drop_generation: Option<String>,
481}
482
483/// Lifecycle markers stored with a logically deleted table.
484pub struct DroppedTableLifecycle<'a> {
485    pub dropped_at: Option<i64>,
486    pub retention_expires_at: Option<i64>,
487    pub drop_generation: Option<&'a str>,
488}
489
490const DROPPED_AT_KEY_PREFIX: &str = "__dropped_at";
491const RETENTION_EXPIRES_AT_KEY_PREFIX: &str = "__retention_expires_at";
492const DROP_GENERATION_KEY_PREFIX: &str = "__drop_generation";
493const PURGING_KEY_PREFIX: &str = "__purging";
494
495pub(crate) fn dropped_at_key(table_id: TableId) -> Vec<u8> {
496    format!("{DROPPED_AT_KEY_PREFIX}/{table_id}").into_bytes()
497}
498
499pub(crate) fn retention_expires_at_key(table_id: TableId) -> Vec<u8> {
500    format!("{RETENTION_EXPIRES_AT_KEY_PREFIX}/{table_id}").into_bytes()
501}
502
503pub(crate) fn drop_generation_key(table_id: TableId) -> Vec<u8> {
504    format!("{DROP_GENERATION_KEY_PREFIX}/{table_id}").into_bytes()
505}
506
507pub(crate) fn purging_key(table_id: TableId) -> Vec<u8> {
508    format!("{PURGING_KEY_PREFIX}/{table_id}").into_bytes()
509}
510
511impl<T: DeserializeOwned + Serialize> Deref for DeserializedValueWithBytes<T> {
512    type Target = T;
513
514    fn deref(&self) -> &Self::Target {
515        &self.inner
516    }
517}
518
519impl<T: DeserializeOwned + Serialize> DerefMut for DeserializedValueWithBytes<T> {
520    fn deref_mut(&mut self) -> &mut Self::Target {
521        &mut self.inner
522    }
523}
524
525impl<T: DeserializeOwned + Serialize + Debug> Debug for DeserializedValueWithBytes<T> {
526    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
527        write!(
528            f,
529            "DeserializedValueWithBytes(inner: {:?}, bytes: {:?})",
530            self.inner, self.bytes
531        )
532    }
533}
534
535impl<T: DeserializeOwned + Serialize> Serialize for DeserializedValueWithBytes<T> {
536    /// - Serialize behaviors:
537    ///
538    /// The `inner` field will be ignored.
539    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
540    where
541        S: serde::Serializer,
542    {
543        // Safety: The original bytes are always JSON encoded.
544        // It's more efficiently than `serialize_bytes`.
545        serializer.serialize_str(&String::from_utf8_lossy(&self.bytes))
546    }
547}
548
549impl<'de, T: DeserializeOwned + Serialize + MetadataValue> Deserialize<'de>
550    for DeserializedValueWithBytes<T>
551{
552    /// - Deserialize behaviors:
553    ///
554    /// The `inner` field will be deserialized from the `bytes` field.
555    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
556    where
557        D: serde::Deserializer<'de>,
558    {
559        let buf = String::deserialize(deserializer)?;
560        let bytes = Bytes::from(buf);
561
562        let value = DeserializedValueWithBytes::from_inner_bytes(bytes)
563            .map_err(|err| serde::de::Error::custom(err.to_string()))?;
564
565        Ok(value)
566    }
567}
568
569impl<T: Serialize + DeserializeOwned + Clone> Clone for DeserializedValueWithBytes<T> {
570    fn clone(&self) -> Self {
571        Self {
572            bytes: self.bytes.clone(),
573            inner: self.inner.clone(),
574        }
575    }
576}
577
578impl<T: Serialize + DeserializeOwned + MetadataValue> DeserializedValueWithBytes<T> {
579    /// Returns a struct containing a deserialized value and an original `bytes`.
580    /// It accepts original bytes of inner.
581    pub fn from_inner_bytes(bytes: Bytes) -> Result<Self> {
582        let inner = T::try_from_raw_value(&bytes)?;
583        Ok(Self { bytes, inner })
584    }
585
586    /// Returns a struct containing a deserialized value and an original `bytes`.
587    /// It accepts original bytes of inner.
588    pub fn from_inner_slice(bytes: &[u8]) -> Result<Self> {
589        Self::from_inner_bytes(Bytes::copy_from_slice(bytes))
590    }
591
592    pub fn into_inner(self) -> T {
593        self.inner
594    }
595
596    pub fn get_inner_ref(&self) -> &T {
597        &self.inner
598    }
599
600    /// Returns original `bytes`
601    pub fn get_raw_bytes(&self) -> Vec<u8> {
602        self.bytes.to_vec()
603    }
604
605    #[cfg(any(test, feature = "testing"))]
606    pub fn from_inner(inner: T) -> Self {
607        let bytes = serde_json::to_vec(&inner).unwrap();
608
609        Self {
610            bytes: Bytes::from(bytes),
611            inner,
612        }
613    }
614}
615
616impl TableMetadataManager {
617    pub fn new(kv_backend: KvBackendRef) -> Self {
618        TableMetadataManager {
619            table_name_manager: TableNameManager::new(kv_backend.clone()),
620            table_info_manager: TableInfoManager::new(kv_backend.clone()),
621            view_info_manager: ViewInfoManager::new(kv_backend.clone()),
622            datanode_table_manager: DatanodeTableManager::new(kv_backend.clone()),
623            catalog_manager: CatalogManager::new(kv_backend.clone()),
624            schema_manager: SchemaManager::new(kv_backend.clone()),
625            table_route_manager: TableRouteManager::new(kv_backend.clone()),
626            table_repart_manager: TableRepartManager::new(kv_backend.clone()),
627            tombstone_manager: TombstoneManager::new(kv_backend.clone()),
628            topic_name_manager: TopicNameManager::new(kv_backend.clone()),
629            topic_region_manager: TopicRegionManager::new(kv_backend.clone()),
630            kv_backend,
631        }
632    }
633
634    /// Creates a new `TableMetadataManager` with a custom tombstone prefix.
635    pub fn new_with_custom_tombstone_prefix(
636        kv_backend: KvBackendRef,
637        tombstone_prefix: &str,
638    ) -> Self {
639        Self {
640            table_name_manager: TableNameManager::new(kv_backend.clone()),
641            table_info_manager: TableInfoManager::new(kv_backend.clone()),
642            view_info_manager: ViewInfoManager::new(kv_backend.clone()),
643            datanode_table_manager: DatanodeTableManager::new(kv_backend.clone()),
644            catalog_manager: CatalogManager::new(kv_backend.clone()),
645            schema_manager: SchemaManager::new(kv_backend.clone()),
646            table_route_manager: TableRouteManager::new(kv_backend.clone()),
647            table_repart_manager: TableRepartManager::new(kv_backend.clone()),
648            tombstone_manager: TombstoneManager::new_with_prefix(
649                kv_backend.clone(),
650                tombstone_prefix,
651            ),
652            topic_name_manager: TopicNameManager::new(kv_backend.clone()),
653            topic_region_manager: TopicRegionManager::new(kv_backend.clone()),
654            kv_backend,
655        }
656    }
657
658    pub async fn init(&self) -> Result<()> {
659        let catalog_name = CatalogNameKey::new(DEFAULT_CATALOG_NAME);
660
661        self.catalog_manager().create(catalog_name, true).await?;
662
663        let internal_schemas = [
664            DEFAULT_SCHEMA_NAME,
665            INFORMATION_SCHEMA_NAME,
666            DEFAULT_PRIVATE_SCHEMA_NAME,
667        ];
668
669        for schema_name in internal_schemas {
670            let schema_key = SchemaNameKey::new(DEFAULT_CATALOG_NAME, schema_name);
671
672            self.schema_manager().create(schema_key, None, true).await?;
673        }
674
675        Ok(())
676    }
677
678    pub fn table_name_manager(&self) -> &TableNameManager {
679        &self.table_name_manager
680    }
681
682    pub fn table_info_manager(&self) -> &TableInfoManager {
683        &self.table_info_manager
684    }
685
686    pub fn view_info_manager(&self) -> &ViewInfoManager {
687        &self.view_info_manager
688    }
689
690    pub fn datanode_table_manager(&self) -> &DatanodeTableManager {
691        &self.datanode_table_manager
692    }
693
694    pub fn catalog_manager(&self) -> &CatalogManager {
695        &self.catalog_manager
696    }
697
698    pub fn schema_manager(&self) -> &SchemaManager {
699        &self.schema_manager
700    }
701
702    pub fn table_route_manager(&self) -> &TableRouteManager {
703        &self.table_route_manager
704    }
705
706    pub fn table_repart_manager(&self) -> &TableRepartManager {
707        &self.table_repart_manager
708    }
709
710    pub fn topic_name_manager(&self) -> &TopicNameManager {
711        &self.topic_name_manager
712    }
713
714    pub fn topic_region_manager(&self) -> &TopicRegionManager {
715        &self.topic_region_manager
716    }
717
718    pub fn kv_backend(&self) -> &KvBackendRef {
719        &self.kv_backend
720    }
721
722    pub async fn get_full_table_info(
723        &self,
724        table_id: TableId,
725    ) -> Result<(
726        Option<DeserializedValueWithBytes<TableInfoValue>>,
727        Option<DeserializedValueWithBytes<TableRouteValue>>,
728    )> {
729        let table_info_key = TableInfoKey::new(table_id);
730        let table_route_key = TableRouteKey::new(table_id);
731        let (table_info_txn, table_info_filter) = table_info_key.build_get_op();
732        let (table_route_txn, table_route_filter) = table_route_key.build_get_op();
733
734        let txn = Txn::new().and_then(vec![table_info_txn, table_route_txn]);
735        let mut res = self.kv_backend.txn(txn).await?;
736        let mut set = TxnOpGetResponseSet::from(&mut res.responses);
737        let table_info_value = TxnOpGetResponseSet::decode_with(table_info_filter)(&mut set)?;
738        let mut table_route_value = TxnOpGetResponseSet::decode_with(table_route_filter)(&mut set)?;
739        if let Some(table_route_value) = &mut table_route_value {
740            self.table_route_manager()
741                .table_route_storage()
742                .remap_table_route(table_route_value)
743                .await?;
744        }
745        Ok((table_info_value, table_route_value))
746    }
747
748    /// Creates metadata for view and returns an error if different metadata exists.
749    /// The caller MUST ensure it has the exclusive access to `TableNameKey`.
750    /// Parameters include:
751    /// - `view_info`: the encoded logical plan
752    /// - `table_names`: the resolved fully table names in logical plan
753    /// - `columns`: the view columns
754    /// - `plan_columns`: the original plan columns
755    /// - `definition`: The SQL to create the view
756    ///
757    pub async fn create_view_metadata(
758        &self,
759        view_info: TableInfo,
760        raw_logical_plan: Vec<u8>,
761        table_names: HashSet<TableName>,
762        columns: Vec<String>,
763        plan_columns: Vec<String>,
764        definition: String,
765    ) -> Result<()> {
766        let view_id = view_info.ident.table_id;
767
768        // Creates view name.
769        let view_name = TableNameKey::new(
770            &view_info.catalog_name,
771            &view_info.schema_name,
772            &view_info.name,
773        );
774        let create_table_name_txn = self
775            .table_name_manager()
776            .build_create_txn(&view_name, view_id)?;
777
778        // Creates table info.
779        let table_info_value = TableInfoValue::new(view_info);
780
781        let (create_table_info_txn, on_create_table_info_failure) = self
782            .table_info_manager()
783            .build_create_txn(view_id, &table_info_value)?;
784
785        // Creates view info
786        let view_info_value = ViewInfoValue::new(
787            raw_logical_plan.into(),
788            table_names,
789            columns,
790            plan_columns,
791            definition,
792        );
793        let (create_view_info_txn, on_create_view_info_failure) = self
794            .view_info_manager()
795            .build_create_txn(view_id, &view_info_value)?;
796
797        let txn = Txn::merge_all(vec![
798            create_table_name_txn,
799            create_table_info_txn,
800            create_view_info_txn,
801        ]);
802
803        let mut r = self.kv_backend.txn(txn).await?;
804
805        // Checks whether metadata was already created.
806        if !r.succeeded {
807            let mut set = TxnOpGetResponseSet::from(&mut r.responses);
808            let remote_table_info = on_create_table_info_failure(&mut set)?
809                .context(error::UnexpectedSnafu {
810                    err_msg: "Reads the empty table info in comparing operation of creating table metadata",
811                })?
812                .into_inner();
813
814            let remote_view_info = on_create_view_info_failure(&mut set)?
815                .context(error::UnexpectedSnafu {
816                    err_msg: "Reads the empty view info in comparing operation of creating view metadata",
817                })?
818                .into_inner();
819
820            let op_name = "the creating view metadata";
821            ensure_values!(remote_table_info, table_info_value, op_name);
822            ensure_values!(remote_view_info, view_info_value, op_name);
823        }
824
825        Ok(())
826    }
827
828    /// Creates metadata for table and returns an error if different metadata exists.
829    /// The caller MUST ensure it has the exclusive access to `TableNameKey`.
830    pub async fn create_table_metadata(
831        &self,
832        table_info: TableInfo,
833        table_route_value: TableRouteValue,
834        region_wal_options: RegionWalOptions,
835    ) -> Result<()> {
836        let table_id = table_info.ident.table_id;
837        let engine = table_info.meta.engine.clone();
838
839        // Creates table name.
840        let table_name = TableNameKey::new(
841            &table_info.catalog_name,
842            &table_info.schema_name,
843            &table_info.name,
844        );
845        let create_table_name_txn = self
846            .table_name_manager()
847            .build_create_txn(&table_name, table_id)?;
848
849        let region_options = table_info.to_region_options();
850        // Creates table info.
851        let table_info_value = TableInfoValue::new(table_info);
852        let (create_table_info_txn, on_create_table_info_failure) = self
853            .table_info_manager()
854            .build_create_txn(table_id, &table_info_value)?;
855
856        let (create_table_route_txn, on_create_table_route_failure) = self
857            .table_route_manager()
858            .table_route_storage()
859            .build_create_txn(table_id, &table_route_value)?;
860
861        let create_topic_region_txn = self
862            .topic_region_manager
863            .build_create_txn(table_id, &region_wal_options)?;
864
865        let mut txn = Txn::merge_all(vec![
866            create_table_name_txn,
867            create_table_info_txn,
868            create_table_route_txn,
869            create_topic_region_txn,
870        ]);
871
872        if let TableRouteValue::Physical(x) = &table_route_value {
873            let region_storage_path = table_info_value.region_storage_path();
874            let create_datanode_table_txn = self.datanode_table_manager().build_create_txn(
875                table_id,
876                &engine,
877                &region_storage_path,
878                region_options,
879                region_wal_options,
880                region_distribution(&x.region_routes),
881            )?;
882            txn = txn.merge(create_datanode_table_txn);
883        }
884
885        let mut r = self.kv_backend.txn(txn).await?;
886
887        // Checks whether metadata was already created.
888        if !r.succeeded {
889            let mut set = TxnOpGetResponseSet::from(&mut r.responses);
890            let remote_table_info = on_create_table_info_failure(&mut set)?
891                .context(error::UnexpectedSnafu {
892                    err_msg: "Reads the empty table info in comparing operation of creating table metadata",
893                })?
894                .into_inner();
895
896            let remote_table_route = on_create_table_route_failure(&mut set)?
897                .context(error::UnexpectedSnafu {
898                    err_msg: "Reads the empty table route in comparing operation of creating table metadata",
899                })?
900                .into_inner();
901
902            let op_name = "the creating table metadata";
903            ensure_values!(remote_table_info, table_info_value, op_name);
904            ensure_values!(remote_table_route, table_route_value, op_name);
905        }
906
907        Ok(())
908    }
909
910    pub fn create_logical_tables_metadata_chunk_size(&self) -> usize {
911        // The batch size is max_txn_size / 3 because the size of the `tables_data`
912        // is 3 times the size of the `tables_data`.
913        self.kv_backend.max_txn_ops() / 3
914    }
915
916    /// Creates metadata for multiple logical tables and return an error if different metadata exists.
917    pub async fn create_logical_tables_metadata(
918        &self,
919        tables_data: Vec<(TableInfo, TableRouteValue)>,
920    ) -> Result<()> {
921        let len = tables_data.len();
922        let mut txns = Vec::with_capacity(3 * len);
923        struct OnFailure<F1, R1, F2, R2>
924        where
925            F1: FnOnce(&mut TxnOpGetResponseSet) -> R1,
926            F2: FnOnce(&mut TxnOpGetResponseSet) -> R2,
927        {
928            table_info_value: TableInfoValue,
929            on_create_table_info_failure: F1,
930            table_route_value: TableRouteValue,
931            on_create_table_route_failure: F2,
932        }
933        let mut on_failures = Vec::with_capacity(len);
934        for (table_info, table_route_value) in tables_data {
935            let table_id = table_info.ident.table_id;
936
937            // Creates table name.
938            let table_name = TableNameKey::new(
939                &table_info.catalog_name,
940                &table_info.schema_name,
941                &table_info.name,
942            );
943            let create_table_name_txn = self
944                .table_name_manager()
945                .build_create_txn(&table_name, table_id)?;
946            txns.push(create_table_name_txn);
947
948            // Creates table info.
949            let table_info_value = TableInfoValue::new(table_info);
950            let (create_table_info_txn, on_create_table_info_failure) =
951                self.table_info_manager()
952                    .build_create_txn(table_id, &table_info_value)?;
953            txns.push(create_table_info_txn);
954
955            let (create_table_route_txn, on_create_table_route_failure) = self
956                .table_route_manager()
957                .table_route_storage()
958                .build_create_txn(table_id, &table_route_value)?;
959            txns.push(create_table_route_txn);
960
961            on_failures.push(OnFailure {
962                table_info_value,
963                on_create_table_info_failure,
964                table_route_value,
965                on_create_table_route_failure,
966            });
967        }
968
969        let txn = Txn::merge_all(txns);
970        let mut r = self.kv_backend.txn(txn).await?;
971
972        // Checks whether metadata was already created.
973        if !r.succeeded {
974            let mut set = TxnOpGetResponseSet::from(&mut r.responses);
975            for on_failure in on_failures {
976                let remote_table_info = (on_failure.on_create_table_info_failure)(&mut set)?
977                    .context(error::UnexpectedSnafu {
978                        err_msg: "Reads the empty table info in comparing operation of creating table metadata",
979                    })?
980                    .into_inner();
981
982                let remote_table_route = (on_failure.on_create_table_route_failure)(&mut set)?
983                    .context(error::UnexpectedSnafu {
984                        err_msg: "Reads the empty table route in comparing operation of creating table metadata",
985                    })?
986                    .into_inner();
987
988                let op_name = "the creating logical tables metadata";
989                ensure_values!(remote_table_info, on_failure.table_info_value, op_name);
990                ensure_values!(remote_table_route, on_failure.table_route_value, op_name);
991            }
992        }
993
994        Ok(())
995    }
996
997    fn table_metadata_keys(
998        &self,
999        table_id: TableId,
1000        table_name: &TableName,
1001        table_route_value: &TableRouteValue,
1002        region_wal_options: &HashMap<RegionNumber, WalOptions>,
1003    ) -> Result<Vec<Vec<u8>>> {
1004        // Builds keys
1005        let datanode_ids = if table_route_value.is_physical() {
1006            region_distribution(table_route_value.region_routes()?)
1007                .into_keys()
1008                .collect()
1009        } else {
1010            vec![]
1011        };
1012        let mut keys = Vec::with_capacity(3 + datanode_ids.len());
1013        let table_name = TableNameKey::new(
1014            &table_name.catalog_name,
1015            &table_name.schema_name,
1016            &table_name.table_name,
1017        );
1018        let table_info_key = TableInfoKey::new(table_id);
1019        let table_route_key = TableRouteKey::new(table_id);
1020        let table_repart_key = TableRepartKey::new(table_id);
1021        let datanode_table_keys = datanode_ids
1022            .into_iter()
1023            .map(|datanode_id| DatanodeTableKey::new(datanode_id, table_id))
1024            .collect::<HashSet<_>>();
1025        let topic_region_map = self
1026            .topic_region_manager
1027            .get_topic_region_mapping(table_id, region_wal_options);
1028        let topic_region_keys = topic_region_map
1029            .iter()
1030            .map(|(region_id, topic)| TopicRegionKey::new(*region_id, topic))
1031            .collect::<Vec<_>>();
1032        keys.push(table_name.to_bytes());
1033        keys.push(table_info_key.to_bytes());
1034        keys.push(table_route_key.to_bytes());
1035        keys.push(table_repart_key.to_bytes());
1036        for key in &datanode_table_keys {
1037            keys.push(key.to_bytes());
1038        }
1039        for key in topic_region_keys {
1040            keys.push(key.to_bytes());
1041        }
1042        Ok(keys)
1043    }
1044
1045    /// Deletes metadata for table **logically**.
1046    /// The caller MUST ensure it has the exclusive access to `TableNameKey`.
1047    pub async fn delete_table_metadata(
1048        &self,
1049        table_id: TableId,
1050        table_name: &TableName,
1051        table_route_value: &TableRouteValue,
1052        region_wal_options: &HashMap<RegionNumber, WalOptions>,
1053        dropped_at: Option<i64>,
1054    ) -> Result<()> {
1055        self.delete_table_metadata_with_retention(
1056            table_id,
1057            table_name,
1058            table_route_value,
1059            region_wal_options,
1060            dropped_at,
1061            None,
1062        )
1063        .await
1064    }
1065
1066    /// Deletes metadata logically and stores fixed soft-drop lifecycle markers.
1067    pub async fn delete_table_metadata_with_retention(
1068        &self,
1069        table_id: TableId,
1070        table_name: &TableName,
1071        table_route_value: &TableRouteValue,
1072        region_wal_options: &HashMap<RegionNumber, WalOptions>,
1073        dropped_at: Option<i64>,
1074        retention_expires_at: Option<i64>,
1075    ) -> Result<()> {
1076        self.delete_table_metadata_with_retention_and_generation(
1077            table_id,
1078            table_name,
1079            table_route_value,
1080            region_wal_options,
1081            DroppedTableLifecycle {
1082                dropped_at,
1083                retention_expires_at,
1084                drop_generation: None,
1085            },
1086        )
1087        .await
1088    }
1089
1090    /// Deletes metadata logically and stores fixed soft-drop lifecycle markers.
1091    pub async fn delete_table_metadata_with_retention_and_generation(
1092        &self,
1093        table_id: TableId,
1094        table_name: &TableName,
1095        table_route_value: &TableRouteValue,
1096        region_wal_options: &HashMap<RegionNumber, WalOptions>,
1097        lifecycle: DroppedTableLifecycle<'_>,
1098    ) -> Result<()> {
1099        let keys =
1100            self.table_metadata_keys(table_id, table_name, table_route_value, region_wal_options)?;
1101        if let Some(dropped_at) = lifecycle.dropped_at {
1102            let mut markers = vec![(
1103                dropped_at_key(table_id),
1104                dropped_at.to_string().into_bytes(),
1105            )];
1106            if let Some(retention_expires_at) = lifecycle.retention_expires_at {
1107                markers.push((
1108                    retention_expires_at_key(table_id),
1109                    retention_expires_at.to_string().into_bytes(),
1110                ));
1111            }
1112            if let Some(drop_generation) = lifecycle.drop_generation {
1113                markers.push((
1114                    drop_generation_key(table_id),
1115                    drop_generation.as_bytes().to_vec(),
1116                ));
1117            }
1118            self.tombstone_manager
1119                .create_with_markers(keys, markers)
1120                .await
1121                .map(|_| ())
1122        } else {
1123            self.tombstone_manager.create(keys).await.map(|_| ())
1124        }
1125    }
1126
1127    /// Lists dropped tables from tombstoned table-name entries.
1128    pub async fn list_dropped_tables(&self) -> Result<Vec<DroppedTableName>> {
1129        self.collect_dropped_tables(self.tombstone_manager.tombstoned_table_names())
1130            .await
1131    }
1132
1133    /// Lists dropped tables from tombstoned table-name entries in the provided catalog.
1134    pub async fn list_dropped_tables_by_catalog(
1135        &self,
1136        catalog: &str,
1137    ) -> Result<Vec<DroppedTableName>> {
1138        self.collect_dropped_tables(
1139            self.tombstone_manager
1140                .tombstoned_table_names_by_catalog(catalog),
1141        )
1142        .await
1143    }
1144
1145    async fn collect_dropped_tables(
1146        &self,
1147        mut stream: BoxStream<'static, Result<KeyValue>>,
1148    ) -> Result<Vec<DroppedTableName>> {
1149        let mut dropped_tables = Vec::new();
1150
1151        while let Some(kv) = stream.try_next().await? {
1152            let raw_key = self.tombstone_manager.strip_tombstone_prefix(&kv.key)?;
1153            let table_name = TableNameKey::from_bytes(raw_key)?.into();
1154            let table_id = TableNameValue::try_from_raw_value(&kv.value)?.table_id();
1155            dropped_tables.push(DroppedTableName {
1156                table_id,
1157                table_name,
1158                dropped_at: None,
1159                retention_expires_at: None,
1160                drop_generation: None,
1161                purging: false,
1162            });
1163        }
1164        if dropped_tables.is_empty() {
1165            return Ok(dropped_tables);
1166        }
1167
1168        let marker_keys = dropped_tables
1169            .iter()
1170            .flat_map(|table| {
1171                vec![
1172                    dropped_at_key(table.table_id),
1173                    retention_expires_at_key(table.table_id),
1174                    drop_generation_key(table.table_id),
1175                    purging_key(table.table_id),
1176                ]
1177            })
1178            .collect::<Vec<_>>();
1179        let marker_values = self.tombstone_manager.batch_get(&marker_keys).await?;
1180        for table in &mut dropped_tables {
1181            table.dropped_at = Self::parse_dropped_at(
1182                table.table_id,
1183                marker_values.get(&dropped_at_key(table.table_id)),
1184            )?;
1185            table.retention_expires_at = Self::parse_retention_expires_at(
1186                table.table_id,
1187                marker_values.get(&retention_expires_at_key(table.table_id)),
1188            )?;
1189            table.drop_generation = Self::parse_drop_generation(
1190                marker_values.get(&drop_generation_key(table.table_id)),
1191            );
1192            table.purging = marker_values.contains_key(&purging_key(table.table_id));
1193        }
1194
1195        Ok(dropped_tables)
1196    }
1197
1198    /// Gets dropped table metadata by its original full table name.
1199    pub async fn get_dropped_table(
1200        &self,
1201        table_name: &TableName,
1202    ) -> Result<Option<DroppedTableMetadata>> {
1203        let table_name_key = TableNameKey::from(table_name);
1204        let Some(kv) = self
1205            .tombstone_manager
1206            .get(&table_name_key.to_bytes())
1207            .await?
1208        else {
1209            return Ok(None);
1210        };
1211
1212        let table_id = TableNameValue::try_from_raw_value(&kv.value)?.table_id();
1213        self.get_dropped_table_metadata(table_id, table_name.clone())
1214            .await
1215    }
1216
1217    /// Gets dropped table metadata by table id.
1218    pub async fn get_dropped_table_by_id(
1219        &self,
1220        table_id: TableId,
1221    ) -> Result<Option<DroppedTableMetadata>> {
1222        self.get_dropped_table_metadata(table_id, None).await
1223    }
1224
1225    /// Returns whether an automatic purge has durably claimed the dropped table.
1226    pub async fn is_dropped_table_purging(&self, table_id: TableId) -> Result<bool> {
1227        self.dropped_table_purge_claim(table_id)
1228            .await
1229            .map(|claim| claim.is_some())
1230    }
1231
1232    /// Returns the soft-drop generation claimed by an automatic purge.
1233    pub async fn dropped_table_purge_claim(&self, table_id: TableId) -> Result<Option<String>> {
1234        self.tombstone_manager
1235            .get(&purging_key(table_id))
1236            .await
1237            .map(|marker| marker.map(|marker| String::from_utf8_lossy(&marker.value).into_owned()))
1238    }
1239
1240    /// Durably claims a dropped table before automatic purge starts cleaning its regions.
1241    /// The caller MUST hold the table lock and revalidate the tombstone before calling this.
1242    pub async fn mark_dropped_table_purging(
1243        &self,
1244        table_id: TableId,
1245        drop_generation: Option<&str>,
1246    ) -> Result<()> {
1247        self.kv_backend
1248            .put(
1249                PutRequest::new()
1250                    .with_key(self.tombstone_manager.to_tombstone(&purging_key(table_id)))
1251                    .with_value(drop_generation.unwrap_or_default()),
1252            )
1253            .await?;
1254        Ok(())
1255    }
1256
1257    /// Deletes metadata tombstone for table **permanently**.
1258    /// The caller MUST ensure it has the exclusive access to `TableNameKey`.
1259    pub async fn delete_table_metadata_tombstone(
1260        &self,
1261        table_id: TableId,
1262        table_name: &TableName,
1263        table_route_value: &TableRouteValue,
1264        region_wal_options: &HashMap<RegionNumber, WalOptions>,
1265    ) -> Result<()> {
1266        let table_metadata_keys =
1267            self.table_metadata_keys(table_id, table_name, table_route_value, region_wal_options)?;
1268        self.tombstone_manager
1269            .delete_with_markers(
1270                table_metadata_keys,
1271                vec![
1272                    dropped_at_key(table_id),
1273                    retention_expires_at_key(table_id),
1274                    drop_generation_key(table_id),
1275                    purging_key(table_id),
1276                ],
1277            )
1278            .await
1279            .map(|_| ())
1280    }
1281
1282    /// Restores metadata for table.
1283    /// The caller MUST ensure it has the exclusive access to `TableNameKey`.
1284    pub async fn restore_table_metadata(
1285        &self,
1286        table_id: TableId,
1287        table_name: &TableName,
1288        table_route_value: &TableRouteValue,
1289        region_wal_options: &HashMap<RegionNumber, WalOptions>,
1290    ) -> Result<()> {
1291        let keys =
1292            self.table_metadata_keys(table_id, table_name, table_route_value, region_wal_options)?;
1293        self.tombstone_manager
1294            .restore_with_markers(
1295                keys,
1296                vec![
1297                    dropped_at_key(table_id),
1298                    retention_expires_at_key(table_id),
1299                    drop_generation_key(table_id),
1300                ],
1301            )
1302            .await
1303            .map(|_| ())
1304    }
1305
1306    /// Deletes metadata for table **permanently**.
1307    /// The caller MUST ensure it has the exclusive access to `TableNameKey`.
1308    pub async fn destroy_table_metadata(
1309        &self,
1310        table_id: TableId,
1311        table_name: &TableName,
1312        table_route_value: &TableRouteValue,
1313        region_wal_options: &HashMap<RegionNumber, WalOptions>,
1314    ) -> Result<()> {
1315        let keys =
1316            self.table_metadata_keys(table_id, table_name, table_route_value, region_wal_options)?;
1317        let _ = self
1318            .kv_backend
1319            .batch_delete(BatchDeleteRequest::new().with_keys(keys))
1320            .await?;
1321        Ok(())
1322    }
1323
1324    /// Rebuilds dropped table metadata from tombstoned keys.
1325    async fn get_dropped_table_metadata<T>(
1326        &self,
1327        table_id: TableId,
1328        table_name: T,
1329    ) -> Result<Option<DroppedTableMetadata>>
1330    where
1331        T: Into<Option<TableName>>,
1332    {
1333        let table_info_key = TableInfoKey::new(table_id);
1334        let Some(table_info_kv) = self
1335            .tombstone_manager
1336            .get(&table_info_key.to_bytes())
1337            .await?
1338        else {
1339            return Ok(None);
1340        };
1341
1342        let table_info_value = TableInfoValue::try_from_raw_value(&table_info_kv.value)?;
1343        let table_name = table_name
1344            .into()
1345            .unwrap_or_else(|| table_info_value.table_name());
1346
1347        let table_route_key = TableRouteKey::new(table_id);
1348        let table_route_kv = self
1349            .tombstone_manager
1350            .get(&table_route_key.to_bytes())
1351            .await?
1352            .with_context(|| error::UnexpectedSnafu {
1353                err_msg: format!("Missing tombstoned table route metadata for table id {table_id}"),
1354            })?;
1355        let mut table_route_value = TableRouteValue::try_from_raw_value(&table_route_kv.value)?;
1356        self.table_route_manager
1357            .table_route_storage()
1358            .remap_table_route(&mut table_route_value)
1359            .await?;
1360
1361        let region_wal_options = self
1362            .dropped_region_wal_options(table_id, &table_route_value)
1363            .await?;
1364        let dropped_at_key = dropped_at_key(table_id);
1365        let retention_expires_at_key = retention_expires_at_key(table_id);
1366        let drop_generation_key = drop_generation_key(table_id);
1367        let marker_values = self
1368            .tombstone_manager
1369            .batch_get(&[
1370                dropped_at_key.clone(),
1371                retention_expires_at_key.clone(),
1372                drop_generation_key.clone(),
1373            ])
1374            .await?;
1375        let dropped_at = Self::parse_dropped_at(table_id, marker_values.get(&dropped_at_key))?;
1376        let retention_expires_at = Self::parse_retention_expires_at(
1377            table_id,
1378            marker_values.get(&retention_expires_at_key),
1379        )?;
1380        let drop_generation = Self::parse_drop_generation(marker_values.get(&drop_generation_key));
1381
1382        Ok(Some(DroppedTableMetadata {
1383            table_id,
1384            table_name,
1385            table_info_value,
1386            table_route_value,
1387            region_wal_options,
1388            dropped_at,
1389            retention_expires_at,
1390            drop_generation,
1391        }))
1392    }
1393
1394    fn parse_dropped_at(table_id: TableId, kv: Option<&KeyValue>) -> Result<Option<i64>> {
1395        Self::parse_timestamp_marker(table_id, "dropped timestamp", kv)
1396    }
1397
1398    fn parse_retention_expires_at(table_id: TableId, kv: Option<&KeyValue>) -> Result<Option<i64>> {
1399        Self::parse_timestamp_marker(table_id, "retention deadline", kv)
1400    }
1401
1402    fn parse_drop_generation(kv: Option<&KeyValue>) -> Option<String> {
1403        kv.map(|kv| String::from_utf8_lossy(&kv.value).into_owned())
1404    }
1405
1406    fn parse_timestamp_marker(
1407        table_id: TableId,
1408        description: &str,
1409        kv: Option<&KeyValue>,
1410    ) -> Result<Option<i64>> {
1411        let Some(kv) = kv else {
1412            return Ok(None);
1413        };
1414        let value = String::from_utf8_lossy(&kv.value);
1415        value.parse().map(Some).map_err(|err| {
1416            error::UnexpectedSnafu {
1417                err_msg: format!("Invalid {description} '{value}' for table id {table_id}: {err}"),
1418            }
1419            .build()
1420        })
1421    }
1422
1423    /// Rebuilds region WAL options from tombstoned datanode-table entries.
1424    async fn dropped_region_wal_options(
1425        &self,
1426        table_id: TableId,
1427        table_route_value: &TableRouteValue,
1428    ) -> Result<HashMap<RegionNumber, WalOptions>> {
1429        let mut region_wal_options = HashMap::new();
1430        let Some(region_routes) = table_route_value.region_routes().ok() else {
1431            return Ok(region_wal_options);
1432        };
1433        let datanode_table_keys = region_distribution(region_routes)
1434            .into_keys()
1435            .map(|datanode_id| DatanodeTableKey::new(datanode_id, table_id))
1436            .collect::<Vec<_>>();
1437        let datanode_table_key_bytes = datanode_table_keys
1438            .iter()
1439            .map(|key| key.to_bytes())
1440            .collect::<Vec<_>>();
1441        let datanode_table_values = self
1442            .tombstone_manager
1443            .batch_get(&datanode_table_key_bytes)
1444            .await?;
1445
1446        for datanode_table_key in datanode_table_keys {
1447            let Some(kv) = datanode_table_values.get(&datanode_table_key.to_bytes()) else {
1448                continue;
1449            };
1450
1451            let datanode_table_value = DatanodeTableValue::try_from_raw_value(&kv.value)?;
1452            for (region_number, wal_options) in &datanode_table_value.region_info.region_wal_options
1453            {
1454                region_wal_options.insert(*region_number, wal_options.clone());
1455            }
1456        }
1457
1458        Ok(region_wal_options)
1459    }
1460
1461    fn view_info_keys(&self, view_id: TableId, view_name: &TableName) -> Result<Vec<Vec<u8>>> {
1462        let mut keys = Vec::with_capacity(3);
1463        let view_name = TableNameKey::new(
1464            &view_name.catalog_name,
1465            &view_name.schema_name,
1466            &view_name.table_name,
1467        );
1468        let table_info_key = TableInfoKey::new(view_id);
1469        let view_info_key = ViewInfoKey::new(view_id);
1470        keys.push(view_name.to_bytes());
1471        keys.push(table_info_key.to_bytes());
1472        keys.push(view_info_key.to_bytes());
1473
1474        Ok(keys)
1475    }
1476
1477    /// Deletes metadata for view **permanently**.
1478    /// The caller MUST ensure it has the exclusive access to `ViewNameKey`.
1479    pub async fn destroy_view_info(&self, view_id: TableId, view_name: &TableName) -> Result<()> {
1480        let keys = self.view_info_keys(view_id, view_name)?;
1481        let _ = self
1482            .kv_backend
1483            .batch_delete(BatchDeleteRequest::new().with_keys(keys))
1484            .await?;
1485        Ok(())
1486    }
1487
1488    /// Renames the table name and returns an error if different metadata exists.
1489    /// The caller MUST ensure it has the exclusive access to old and new `TableNameKey`s,
1490    /// and the new `TableNameKey` MUST be empty.
1491    pub async fn rename_table(
1492        &self,
1493        current_table_info_value: &DeserializedValueWithBytes<TableInfoValue>,
1494        new_table_name: String,
1495    ) -> Result<()> {
1496        let current_table_info = &current_table_info_value.table_info;
1497        let table_id = current_table_info.ident.table_id;
1498
1499        let table_name_key = TableNameKey::new(
1500            &current_table_info.catalog_name,
1501            &current_table_info.schema_name,
1502            &current_table_info.name,
1503        );
1504
1505        let new_table_name_key = TableNameKey::new(
1506            &current_table_info.catalog_name,
1507            &current_table_info.schema_name,
1508            &new_table_name,
1509        );
1510
1511        // Updates table name.
1512        let update_table_name_txn = self.table_name_manager().build_update_txn(
1513            &table_name_key,
1514            &new_table_name_key,
1515            table_id,
1516        )?;
1517
1518        let new_table_info_value = current_table_info_value
1519            .inner
1520            .with_update(move |table_info| {
1521                table_info.name = new_table_name;
1522            });
1523
1524        // Updates table info.
1525        let (update_table_info_txn, on_update_table_info_failure) = self
1526            .table_info_manager()
1527            .build_update_txn(table_id, current_table_info_value, &new_table_info_value)?;
1528
1529        let txn = Txn::merge_all(vec![update_table_name_txn, update_table_info_txn]);
1530
1531        let mut r = self.kv_backend.txn(txn).await?;
1532
1533        // Checks whether metadata was already updated.
1534        if !r.succeeded {
1535            let mut set = TxnOpGetResponseSet::from(&mut r.responses);
1536            let remote_table_info = on_update_table_info_failure(&mut set)?
1537                .context(error::UnexpectedSnafu {
1538                    err_msg: "Reads the empty table info in comparing operation of the rename table metadata",
1539                })?
1540                .into_inner();
1541
1542            let op_name = "the renaming table metadata";
1543            ensure_values!(remote_table_info, new_table_info_value, op_name);
1544        }
1545
1546        Ok(())
1547    }
1548
1549    /// Updates table info and returns an error if different metadata exists.
1550    /// And cascade-ly update all redundant table options for each region
1551    /// if region_distribution is present.
1552    pub async fn update_table_info(
1553        &self,
1554        current_table_info_value: &DeserializedValueWithBytes<TableInfoValue>,
1555        region_distribution: Option<RegionDistribution>,
1556        new_table_info: TableInfo,
1557    ) -> Result<()> {
1558        let table_id = current_table_info_value.table_info.ident.table_id;
1559        let new_table_info_value = current_table_info_value.update(new_table_info);
1560
1561        // Updates table info.
1562        let (update_table_info_txn, on_update_table_info_failure) = self
1563            .table_info_manager()
1564            .build_update_txn(table_id, current_table_info_value, &new_table_info_value)?;
1565
1566        let txn = if let Some(region_distribution) = region_distribution {
1567            // region options induced from table info.
1568            let new_region_options = new_table_info_value.table_info.to_region_options();
1569            let update_datanode_table_options_txn = self
1570                .datanode_table_manager
1571                .build_update_table_options_txn(table_id, region_distribution, new_region_options)
1572                .await?;
1573            Txn::merge_all([update_table_info_txn, update_datanode_table_options_txn])
1574        } else {
1575            update_table_info_txn
1576        };
1577
1578        let mut r = self.kv_backend.txn(txn).await?;
1579        // Checks whether metadata was already updated.
1580        if !r.succeeded {
1581            let mut set = TxnOpGetResponseSet::from(&mut r.responses);
1582            let remote_table_info = on_update_table_info_failure(&mut set)?
1583                .context(error::UnexpectedSnafu {
1584                    err_msg: "Reads the empty table info in comparing operation of the updating table info",
1585                })?
1586                .into_inner();
1587
1588            let op_name = "the updating table info";
1589            ensure_values!(remote_table_info, new_table_info_value, op_name);
1590        }
1591        Ok(())
1592    }
1593
1594    /// Updates view info and returns an error if different metadata exists.
1595    /// Parameters include:
1596    /// - `view_id`: the view id
1597    /// - `current_view_info_value`: the current view info for CAS checking
1598    /// - `new_view_info`: the encoded logical plan
1599    /// - `table_names`: the resolved fully table names in logical plan
1600    /// - `columns`: the view columns
1601    /// - `plan_columns`: the original plan columns
1602    /// - `definition`: The SQL to create the view
1603    ///
1604    #[allow(clippy::too_many_arguments)]
1605    pub async fn update_view_info(
1606        &self,
1607        view_id: TableId,
1608        current_view_info_value: &DeserializedValueWithBytes<ViewInfoValue>,
1609        new_view_info: Vec<u8>,
1610        table_names: HashSet<TableName>,
1611        columns: Vec<String>,
1612        plan_columns: Vec<String>,
1613        definition: String,
1614    ) -> Result<()> {
1615        let new_view_info_value = current_view_info_value.update(
1616            new_view_info.into(),
1617            table_names,
1618            columns,
1619            plan_columns,
1620            definition,
1621        );
1622
1623        // Updates view info.
1624        let (update_view_info_txn, on_update_view_info_failure) = self
1625            .view_info_manager()
1626            .build_update_txn(view_id, current_view_info_value, &new_view_info_value)?;
1627
1628        let mut r = self.kv_backend.txn(update_view_info_txn).await?;
1629
1630        // Checks whether metadata was already updated.
1631        if !r.succeeded {
1632            let mut set = TxnOpGetResponseSet::from(&mut r.responses);
1633            let remote_view_info = on_update_view_info_failure(&mut set)?
1634                .context(error::UnexpectedSnafu {
1635                    err_msg: "Reads the empty view info in comparing operation of the updating view info",
1636                })?
1637                .into_inner();
1638
1639            let op_name = "the updating view info";
1640            ensure_values!(remote_view_info, new_view_info_value, op_name);
1641        }
1642        Ok(())
1643    }
1644
1645    pub fn batch_update_table_info_value_chunk_size(&self) -> usize {
1646        self.kv_backend.max_txn_ops()
1647    }
1648
1649    pub async fn batch_update_table_info_values(
1650        &self,
1651        table_info_value_pairs: Vec<(DeserializedValueWithBytes<TableInfoValue>, TableInfo)>,
1652    ) -> Result<()> {
1653        let len = table_info_value_pairs.len();
1654        let mut txns = Vec::with_capacity(len);
1655        struct OnFailure<F, R>
1656        where
1657            F: FnOnce(&mut TxnOpGetResponseSet) -> R,
1658        {
1659            table_info_value: TableInfoValue,
1660            on_update_table_info_failure: F,
1661        }
1662        let mut on_failures = Vec::with_capacity(len);
1663
1664        for (table_info_value, new_table_info) in table_info_value_pairs {
1665            let table_id = table_info_value.table_info.ident.table_id;
1666
1667            let new_table_info_value = table_info_value.update(new_table_info);
1668
1669            let (update_table_info_txn, on_update_table_info_failure) =
1670                self.table_info_manager().build_update_txn(
1671                    table_id,
1672                    &table_info_value,
1673                    &new_table_info_value,
1674                )?;
1675
1676            txns.push(update_table_info_txn);
1677
1678            on_failures.push(OnFailure {
1679                table_info_value: new_table_info_value,
1680                on_update_table_info_failure,
1681            });
1682        }
1683
1684        let txn = Txn::merge_all(txns);
1685        let mut r = self.kv_backend.txn(txn).await?;
1686
1687        if !r.succeeded {
1688            let mut set = TxnOpGetResponseSet::from(&mut r.responses);
1689            for on_failure in on_failures {
1690                let remote_table_info = (on_failure.on_update_table_info_failure)(&mut set)?
1691                    .context(error::UnexpectedSnafu {
1692                        err_msg: "Reads the empty table info in comparing operation of the updating table info",
1693                    })?
1694                    .into_inner();
1695
1696                let op_name = "the batch updating table info";
1697                ensure_values!(remote_table_info, on_failure.table_info_value, op_name);
1698            }
1699        }
1700
1701        Ok(())
1702    }
1703
1704    pub async fn update_table_route(
1705        &self,
1706        table_id: TableId,
1707        region_info: RegionInfo,
1708        current_table_route_value: &DeserializedValueWithBytes<TableRouteValue>,
1709        new_region_routes: Vec<RegionRoute>,
1710        new_region_options: &HashMap<String, String>,
1711        new_region_wal_options: &RegionWalOptions,
1712    ) -> Result<()> {
1713        // Updates the datanode table key value pairs.
1714        let current_region_distribution =
1715            region_distribution(current_table_route_value.region_routes()?);
1716        let new_region_distribution = region_distribution(&new_region_routes);
1717
1718        let update_topic_region_txn = self.topic_region_manager.build_update_txn(
1719            table_id,
1720            &region_info.region_wal_options,
1721            new_region_wal_options,
1722        )?;
1723        let update_datanode_table_txn = self.datanode_table_manager().build_update_txn(
1724            table_id,
1725            region_info,
1726            current_region_distribution,
1727            new_region_distribution,
1728            new_region_options,
1729            new_region_wal_options,
1730        )?;
1731
1732        // Updates the table_route.
1733        let new_table_route_value = current_table_route_value.update(new_region_routes)?;
1734        let (update_table_route_txn, on_update_table_route_failure) = self
1735            .table_route_manager()
1736            .table_route_storage()
1737            .build_update_txn(table_id, current_table_route_value, &new_table_route_value)?;
1738
1739        let txn = Txn::merge_all(vec![
1740            update_datanode_table_txn,
1741            update_table_route_txn,
1742            update_topic_region_txn,
1743        ]);
1744
1745        let mut r = self.kv_backend.txn(txn).await?;
1746
1747        // Checks whether metadata was already updated.
1748        if !r.succeeded {
1749            let mut set = TxnOpGetResponseSet::from(&mut r.responses);
1750            let remote_table_route = on_update_table_route_failure(&mut set)?
1751                .context(error::UnexpectedSnafu {
1752                    err_msg: "Reads the empty table route in comparing operation of the updating table route",
1753                })?
1754                .into_inner();
1755
1756            let op_name = "the updating table route";
1757            ensure_values!(remote_table_route, new_table_route_value, op_name);
1758        }
1759
1760        Ok(())
1761    }
1762
1763    /// Updates the leader status of the [RegionRoute].
1764    pub async fn update_leader_region_status<F>(
1765        &self,
1766        table_id: TableId,
1767        current_table_route_value: &DeserializedValueWithBytes<TableRouteValue>,
1768        next_region_route_status: F,
1769    ) -> Result<()>
1770    where
1771        F: Fn(&RegionRoute) -> Option<Option<LeaderState>>,
1772    {
1773        let mut new_region_routes = current_table_route_value.region_routes()?.clone();
1774
1775        let mut updated = 0;
1776        for route in &mut new_region_routes {
1777            if let Some(state) = next_region_route_status(route)
1778                && route.set_leader_state(state)
1779            {
1780                updated += 1;
1781            }
1782        }
1783
1784        if updated == 0 {
1785            warn!("No leader status updated");
1786            return Ok(());
1787        }
1788
1789        // Updates the table_route.
1790        let new_table_route_value = current_table_route_value.update(new_region_routes)?;
1791
1792        let (update_table_route_txn, on_update_table_route_failure) = self
1793            .table_route_manager()
1794            .table_route_storage()
1795            .build_update_txn(table_id, current_table_route_value, &new_table_route_value)?;
1796
1797        let mut r = self.kv_backend.txn(update_table_route_txn).await?;
1798
1799        // Checks whether metadata was already updated.
1800        if !r.succeeded {
1801            let mut set = TxnOpGetResponseSet::from(&mut r.responses);
1802            let remote_table_route = on_update_table_route_failure(&mut set)?
1803                .context(error::UnexpectedSnafu {
1804                    err_msg: "Reads the empty table route in comparing operation of the updating leader region status",
1805                })?
1806                .into_inner();
1807
1808            let op_name = "the updating leader region status";
1809            ensure_values!(remote_table_route, new_table_route_value, op_name);
1810        }
1811
1812        Ok(())
1813    }
1814}
1815
1816#[macro_export]
1817macro_rules! impl_metadata_value {
1818    ($($val_ty: ty), *) => {
1819        $(
1820            impl $crate::key::MetadataValue for $val_ty {
1821                fn try_from_raw_value(raw_value: &[u8]) -> Result<Self> {
1822                    serde_json::from_slice(raw_value).context(SerdeJsonSnafu)
1823                }
1824
1825                fn try_as_raw_value(&self) -> Result<Vec<u8>> {
1826                    serde_json::to_vec(self).context(SerdeJsonSnafu)
1827                }
1828            }
1829        )*
1830    }
1831}
1832
1833macro_rules! impl_metadata_key_get_txn_op {
1834    ($($key: ty), *) => {
1835        $(
1836            impl $crate::key::MetadataKeyGetTxnOp for $key {
1837                /// Returns a [TxnOp] to retrieve the corresponding value
1838                /// and a filter to retrieve the value from the [TxnOpGetResponseSet]
1839                fn build_get_op(
1840                    &self,
1841                ) -> (
1842                    TxnOp,
1843                    impl for<'a> FnMut(
1844                        &'a mut TxnOpGetResponseSet,
1845                    ) -> Option<Vec<u8>>,
1846                ) {
1847                    let raw_key = self.to_bytes();
1848                    (
1849                        TxnOp::Get(raw_key.clone()),
1850                        TxnOpGetResponseSet::filter(raw_key),
1851                    )
1852                }
1853            }
1854        )*
1855    }
1856}
1857
1858impl_metadata_key_get_txn_op! {
1859    TableNameKey<'_>,
1860    TableInfoKey,
1861    ViewInfoKey,
1862    TableRouteKey,
1863    DatanodeTableKey
1864}
1865
1866#[macro_export]
1867macro_rules! impl_optional_metadata_value {
1868    ($($val_ty: ty), *) => {
1869        $(
1870            impl $val_ty {
1871                pub fn try_from_raw_value(raw_value: &[u8]) -> Result<Option<Self>> {
1872                    serde_json::from_slice(raw_value).context(SerdeJsonSnafu)
1873                }
1874
1875                pub fn try_as_raw_value(&self) -> Result<Vec<u8>> {
1876                    serde_json::to_vec(self).context(SerdeJsonSnafu)
1877                }
1878            }
1879        )*
1880    }
1881}
1882
1883impl_metadata_value! {
1884    TableNameValue,
1885    TableInfoValue,
1886    ViewInfoValue,
1887    DatanodeTableValue,
1888    FlowInfoValue,
1889    FlowNameValue,
1890    FlowRouteValue,
1891    TableFlowValue,
1892    NodeAddressValue,
1893    SchemaNameValue,
1894    FlowStateValue,
1895    PoisonValue,
1896    TopicRegionValue,
1897    DatanodeEpochValue
1898}
1899
1900impl_optional_metadata_value! {
1901    CatalogNameValue,
1902    SchemaNameValue
1903}
1904
1905#[cfg(test)]
1906mod tests {
1907    use std::collections::{BTreeMap, HashMap, HashSet};
1908    use std::sync::Arc;
1909    use std::sync::atomic::{AtomicUsize, Ordering};
1910
1911    use bytes::Bytes;
1912    use common_catalog::consts::{DEFAULT_CATALOG_NAME, DEFAULT_SCHEMA_NAME};
1913    use common_time::util::current_time_millis;
1914    use common_wal::options::{KafkaWalOptions, WalOptions};
1915    use futures::TryStreamExt;
1916    use store_api::storage::{RegionId, RegionNumber};
1917    use table::metadata::{TableId, TableInfo};
1918    use table::table_name::TableName;
1919
1920    use super::datanode_table::DatanodeTableKey;
1921    use super::test_utils;
1922    use crate::ddl::allocator::wal_options::WalOptionsAllocator;
1923    use crate::ddl::test_util::create_table::test_create_table_task;
1924    use crate::ddl::utils::region_storage_path;
1925    use crate::error::{Error, Result};
1926    use crate::key::datanode_table::RegionInfo;
1927    use crate::key::node_address::{NodeAddressKey, NodeAddressValue};
1928    use crate::key::table_info::TableInfoValue;
1929    use crate::key::table_name::TableNameKey;
1930    use crate::key::table_route::TableRouteValue;
1931    use crate::key::topic_region::TopicRegionKey;
1932    use crate::key::{
1933        DeserializedValueWithBytes, DroppedTableMetadata, MetadataValue, RegionDistribution,
1934        RegionRoleSet, TOPIC_REGION_PREFIX, TableMetadataManager, ViewInfoValue,
1935    };
1936    use crate::kv_backend::KvBackend;
1937    use crate::kv_backend::memory::MemoryKvBackend;
1938    use crate::kv_backend::read_only::ReadOnlyKvBackend;
1939    use crate::kv_backend::test_util::MockKvBackend;
1940    use crate::peer::Peer;
1941    use crate::rpc::router::{LeaderState, Region, RegionRoute, region_distribution};
1942    use crate::rpc::store::{BatchGetResponse, PutRequest, RangeRequest, RangeResponse};
1943    use crate::wal_provider::{RegionWalOptions, WalProvider};
1944
1945    #[test]
1946    fn test_deserialized_value_with_bytes() {
1947        let region_route = new_test_region_route();
1948        let region_routes = vec![region_route.clone()];
1949
1950        let expected_region_routes =
1951            TableRouteValue::physical(vec![region_route.clone(), region_route.clone()]);
1952        let expected = serde_json::to_vec(&expected_region_routes).unwrap();
1953
1954        // Serialize behaviors:
1955        // The inner field will be ignored.
1956        let value = DeserializedValueWithBytes {
1957            // ignored
1958            inner: TableRouteValue::physical(region_routes.clone()),
1959            bytes: Bytes::from(expected.clone()),
1960        };
1961
1962        let encoded = serde_json::to_vec(&value).unwrap();
1963
1964        // Deserialize behaviors:
1965        // The inner field will be deserialized from the bytes field.
1966        let decoded: DeserializedValueWithBytes<TableRouteValue> =
1967            serde_json::from_slice(&encoded).unwrap();
1968
1969        assert_eq!(decoded.inner, expected_region_routes);
1970        assert_eq!(decoded.bytes, expected);
1971    }
1972
1973    fn new_test_region_route() -> RegionRoute {
1974        new_region_route(1, 2)
1975    }
1976
1977    fn new_region_route(region_id: u64, datanode: u64) -> RegionRoute {
1978        RegionRoute {
1979            region: Region {
1980                id: region_id.into(),
1981                name: "r1".to_string(),
1982                attrs: BTreeMap::new(),
1983                partition_expr: Default::default(),
1984            },
1985            leader_peer: Some(Peer::new(datanode, "a2")),
1986            follower_peers: vec![],
1987            leader_state: None,
1988            leader_down_since: None,
1989            write_route_policy: None,
1990        }
1991    }
1992
1993    fn new_test_table_info() -> TableInfo {
1994        test_utils::new_test_table_info(10)
1995    }
1996
1997    fn new_test_table_names() -> HashSet<TableName> {
1998        let mut set = HashSet::new();
1999        set.insert(TableName {
2000            catalog_name: "greptime".to_string(),
2001            schema_name: "public".to_string(),
2002            table_name: "a_table".to_string(),
2003        });
2004        set.insert(TableName {
2005            catalog_name: "greptime".to_string(),
2006            schema_name: "public".to_string(),
2007            table_name: "b_table".to_string(),
2008        });
2009        set
2010    }
2011
2012    async fn create_physical_table_metadata(
2013        table_metadata_manager: &TableMetadataManager,
2014        table_info: TableInfo,
2015        region_routes: Vec<RegionRoute>,
2016        region_wal_options: RegionWalOptions,
2017    ) -> Result<()> {
2018        table_metadata_manager
2019            .create_table_metadata(
2020                table_info,
2021                TableRouteValue::physical(region_routes),
2022                region_wal_options,
2023            )
2024            .await
2025    }
2026
2027    fn create_mock_region_wal_options() -> HashMap<RegionNumber, WalOptions> {
2028        let topics = (0..2)
2029            .map(|i| format!("greptimedb_topic{}", i))
2030            .collect::<Vec<_>>();
2031        let wal_options = topics
2032            .iter()
2033            .map(|topic| WalOptions::Kafka(KafkaWalOptions::new(topic.clone())))
2034            .collect::<Vec<_>>();
2035
2036        (0..16)
2037            .enumerate()
2038            .map(|(i, region_number)| (region_number, wal_options[i % wal_options.len()].clone()))
2039            .collect()
2040    }
2041
2042    fn create_mixed_region_wal_options() -> HashMap<RegionNumber, WalOptions> {
2043        HashMap::from([
2044            (
2045                0,
2046                WalOptions::Kafka(KafkaWalOptions::new("greptimedb_topic0".to_string())),
2047            ),
2048            (1, WalOptions::RaftEngine),
2049            (2, WalOptions::Noop),
2050            (
2051                3,
2052                WalOptions::Kafka(KafkaWalOptions::new("greptimedb_topic1".to_string())),
2053            ),
2054        ])
2055    }
2056
2057    fn test_physical_region_route(
2058        table_id: TableId,
2059        region_number: RegionNumber,
2060        leader_peer: u64,
2061        follower_peers: Vec<u64>,
2062    ) -> RegionRoute {
2063        RegionRoute {
2064            region: Region::new_test(RegionId::new(table_id, region_number)),
2065            leader_peer: Some(Peer::empty(leader_peer)),
2066            follower_peers: follower_peers.into_iter().map(Peer::empty).collect(),
2067            leader_state: None,
2068            leader_down_since: None,
2069            write_route_policy: None,
2070        }
2071    }
2072
2073    async fn create_dropped_physical_table_metadata(
2074        table_id: TableId,
2075        table_name: &str,
2076        region_routes: Vec<RegionRoute>,
2077        region_wal_options: HashMap<RegionNumber, WalOptions>,
2078    ) -> (
2079        Arc<MemoryKvBackend<Error>>,
2080        TableMetadataManager,
2081        TableName,
2082        TableInfo,
2083        Vec<RegionRoute>,
2084        HashMap<RegionNumber, WalOptions>,
2085    ) {
2086        let mem_kv = Arc::new(MemoryKvBackend::default());
2087        let table_metadata_manager = TableMetadataManager::new(mem_kv.clone());
2088        let task = test_create_table_task(table_name, table_id);
2089        let table_info = task.table_info.clone();
2090        table_metadata_manager
2091            .create_table_metadata(
2092                table_info.clone(),
2093                TableRouteValue::physical(region_routes),
2094                region_wal_options.clone(),
2095            )
2096            .await
2097            .unwrap();
2098
2099        let table_route_value = table_metadata_manager
2100            .table_route_manager
2101            .table_route_storage()
2102            .get_with_raw_bytes(table_id)
2103            .await
2104            .unwrap()
2105            .unwrap();
2106        let region_routes = table_route_value.region_routes().unwrap().clone();
2107        let table_name = TableName::new(DEFAULT_CATALOG_NAME, DEFAULT_SCHEMA_NAME, table_name);
2108        let table_route_value = TableRouteValue::physical(region_routes.clone());
2109        table_metadata_manager
2110            .delete_table_metadata(
2111                table_id,
2112                &table_name,
2113                &table_route_value,
2114                &region_wal_options,
2115                None,
2116            )
2117            .await
2118            .unwrap();
2119
2120        (
2121            mem_kv,
2122            table_metadata_manager,
2123            table_name,
2124            table_info,
2125            region_routes,
2126            region_wal_options,
2127        )
2128    }
2129
2130    fn assert_dropped_table_metadata(
2131        dropped_table: &DroppedTableMetadata,
2132        table_id: TableId,
2133        table_name: &TableName,
2134        table_info: &TableInfo,
2135        region_routes: &[RegionRoute],
2136        region_wal_options: &HashMap<RegionNumber, WalOptions>,
2137    ) {
2138        assert_eq!(dropped_table.table_id, table_id);
2139        assert_eq!(&dropped_table.table_name, table_name);
2140        assert_eq!(&dropped_table.table_info_value.table_info, table_info);
2141        assert_eq!(
2142            dropped_table.table_route_value.region_routes().unwrap(),
2143            region_routes
2144        );
2145        assert_eq!(&dropped_table.region_wal_options, region_wal_options);
2146    }
2147
2148    #[tokio::test]
2149    async fn test_raft_engine_topic_region_map() {
2150        let mem_kv = Arc::new(MemoryKvBackend::default());
2151        let table_metadata_manager = TableMetadataManager::new(mem_kv.clone());
2152        let region_route = new_test_region_route();
2153        let region_routes = &vec![region_route.clone()];
2154        let table_info = new_test_table_info();
2155        let wal_provider = WalProvider::RaftEngine;
2156        let regions: Vec<_> = (0..16).collect();
2157        let region_wal_options = wal_provider.allocate(&regions, false).await.unwrap();
2158        create_physical_table_metadata(
2159            &table_metadata_manager,
2160            table_info.clone(),
2161            region_routes.clone(),
2162            region_wal_options.clone(),
2163        )
2164        .await
2165        .unwrap();
2166
2167        let topic_region_key = TOPIC_REGION_PREFIX.to_string();
2168        let range_req = RangeRequest::new().with_prefix(topic_region_key);
2169        let resp = mem_kv.range(range_req).await.unwrap();
2170        // Should be empty because the topic region map is empty for raft engine.
2171        assert!(resp.kvs.is_empty());
2172    }
2173
2174    #[tokio::test]
2175    async fn test_create_table_metadata() {
2176        let mem_kv = Arc::new(MemoryKvBackend::default());
2177        let table_metadata_manager = TableMetadataManager::new(mem_kv);
2178        let region_route = new_test_region_route();
2179        let region_routes = &vec![region_route.clone()];
2180        let table_info = new_test_table_info();
2181        let region_wal_options = create_mock_region_wal_options();
2182
2183        // creates metadata.
2184        create_physical_table_metadata(
2185            &table_metadata_manager,
2186            table_info.clone(),
2187            region_routes.clone(),
2188            region_wal_options.clone(),
2189        )
2190        .await
2191        .unwrap();
2192
2193        // if metadata was already created, it should be ok.
2194        assert!(
2195            create_physical_table_metadata(
2196                &table_metadata_manager,
2197                table_info.clone(),
2198                region_routes.clone(),
2199                region_wal_options.clone(),
2200            )
2201            .await
2202            .is_ok()
2203        );
2204
2205        let mut modified_region_routes = region_routes.clone();
2206        modified_region_routes.push(region_route.clone());
2207        // if remote metadata was exists, it should return an error.
2208        assert!(
2209            create_physical_table_metadata(
2210                &table_metadata_manager,
2211                table_info.clone(),
2212                modified_region_routes,
2213                region_wal_options.clone(),
2214            )
2215            .await
2216            .is_err()
2217        );
2218
2219        let (remote_table_info, remote_table_route) = table_metadata_manager
2220            .get_full_table_info(10)
2221            .await
2222            .unwrap();
2223
2224        assert_eq!(
2225            remote_table_info.unwrap().into_inner().table_info,
2226            table_info
2227        );
2228        assert_eq!(
2229            remote_table_route
2230                .unwrap()
2231                .into_inner()
2232                .region_routes()
2233                .unwrap(),
2234            region_routes
2235        );
2236
2237        for i in 0..2 {
2238            let region_number = i as u32;
2239            let region_id = RegionId::new(table_info.ident.table_id, region_number);
2240            let topic = format!("greptimedb_topic{}", i);
2241            let regions = table_metadata_manager
2242                .topic_region_manager
2243                .regions(&topic)
2244                .await
2245                .unwrap()
2246                .into_keys()
2247                .collect::<Vec<_>>();
2248            assert_eq!(regions.len(), 8);
2249            assert!(regions.contains(&region_id));
2250        }
2251    }
2252
2253    #[tokio::test]
2254    async fn test_get_full_table_info_remaps_route_address() {
2255        let mem_kv = Arc::new(MemoryKvBackend::default());
2256        let table_metadata_manager = TableMetadataManager::new(mem_kv.clone());
2257
2258        let mut region_route = new_test_region_route();
2259        region_route.follower_peers = vec![Peer::empty(3)];
2260        let region_routes = vec![region_route];
2261        let table_info = new_test_table_info();
2262        let table_id = table_info.ident.table_id;
2263
2264        create_physical_table_metadata(
2265            &table_metadata_manager,
2266            table_info,
2267            region_routes,
2268            HashMap::new(),
2269        )
2270        .await
2271        .unwrap();
2272
2273        mem_kv
2274            .put(PutRequest {
2275                key: NodeAddressKey::with_datanode(2).to_string().into_bytes(),
2276                value: NodeAddressValue::new(Peer::new(2, "new-a2"))
2277                    .try_as_raw_value()
2278                    .unwrap(),
2279                ..Default::default()
2280            })
2281            .await
2282            .unwrap();
2283        mem_kv
2284            .put(PutRequest {
2285                key: NodeAddressKey::with_datanode(3).to_string().into_bytes(),
2286                value: NodeAddressValue::new(Peer::new(3, "new-a3"))
2287                    .try_as_raw_value()
2288                    .unwrap(),
2289                ..Default::default()
2290            })
2291            .await
2292            .unwrap();
2293
2294        let (_, table_route) = table_metadata_manager
2295            .get_full_table_info(table_id)
2296            .await
2297            .unwrap();
2298        let table_route = table_route.unwrap().into_inner();
2299        let region_routes = table_route.region_routes().unwrap();
2300
2301        assert_eq!(
2302            region_routes[0].leader_peer.as_ref().unwrap().addr,
2303            "new-a2"
2304        );
2305        assert_eq!(region_routes[0].follower_peers[0].addr, "new-a3");
2306    }
2307
2308    #[tokio::test]
2309    async fn test_get_full_table_info_with_read_only_kv_backend() {
2310        let mem_kv = Arc::new(MemoryKvBackend::default());
2311        let writable_manager = TableMetadataManager::new(mem_kv.clone());
2312
2313        let region_routes = vec![new_test_region_route()];
2314        let table_info = new_test_table_info();
2315        let table_id = table_info.ident.table_id;
2316
2317        create_physical_table_metadata(
2318            &writable_manager,
2319            table_info.clone(),
2320            region_routes.clone(),
2321            HashMap::new(),
2322        )
2323        .await
2324        .unwrap();
2325
2326        let read_only_kv = Arc::new(ReadOnlyKvBackend::new(mem_kv));
2327        let read_only_manager = TableMetadataManager::new(read_only_kv);
2328
2329        let (remote_table_info, remote_table_route) = read_only_manager
2330            .get_full_table_info(table_id)
2331            .await
2332            .unwrap();
2333
2334        assert_eq!(
2335            remote_table_info.unwrap().into_inner().table_info,
2336            table_info
2337        );
2338        assert_eq!(
2339            remote_table_route
2340                .unwrap()
2341                .into_inner()
2342                .region_routes()
2343                .unwrap(),
2344            &region_routes
2345        );
2346    }
2347
2348    #[tokio::test]
2349    async fn test_create_logic_tables_metadata() {
2350        let mem_kv = Arc::new(MemoryKvBackend::default());
2351        let table_metadata_manager = TableMetadataManager::new(mem_kv);
2352        let region_route = new_test_region_route();
2353        let region_routes = vec![region_route.clone()];
2354        let table_info = new_test_table_info();
2355        let table_id = table_info.ident.table_id;
2356        let table_route_value = TableRouteValue::physical(region_routes.clone());
2357
2358        let tables_data = vec![(table_info.clone(), table_route_value.clone())];
2359        // creates metadata.
2360        table_metadata_manager
2361            .create_logical_tables_metadata(tables_data.clone())
2362            .await
2363            .unwrap();
2364
2365        // if metadata was already created, it should be ok.
2366        assert!(
2367            table_metadata_manager
2368                .create_logical_tables_metadata(tables_data)
2369                .await
2370                .is_ok()
2371        );
2372
2373        let mut modified_region_routes = region_routes.clone();
2374        modified_region_routes.push(new_region_route(2, 3));
2375        let modified_table_route_value = TableRouteValue::physical(modified_region_routes.clone());
2376        let modified_tables_data = vec![(table_info.clone(), modified_table_route_value)];
2377        // if remote metadata was exists, it should return an error.
2378        assert!(
2379            table_metadata_manager
2380                .create_logical_tables_metadata(modified_tables_data)
2381                .await
2382                .is_err()
2383        );
2384
2385        let (remote_table_info, remote_table_route) = table_metadata_manager
2386            .get_full_table_info(table_id)
2387            .await
2388            .unwrap();
2389
2390        assert_eq!(
2391            remote_table_info.unwrap().into_inner().table_info,
2392            table_info
2393        );
2394        assert_eq!(
2395            remote_table_route
2396                .unwrap()
2397                .into_inner()
2398                .region_routes()
2399                .unwrap(),
2400            &region_routes
2401        );
2402    }
2403
2404    #[tokio::test]
2405    async fn test_create_many_logical_tables_metadata() {
2406        let kv_backend = Arc::new(MemoryKvBackend::default());
2407        let table_metadata_manager = TableMetadataManager::new(kv_backend);
2408
2409        let mut tables_data = vec![];
2410        for i in 0..128 {
2411            let table_id = i + 1;
2412            let regin_number = table_id * 3;
2413            let region_id = RegionId::new(table_id, regin_number);
2414            let region_route = new_region_route(region_id.as_u64(), 2);
2415            let region_routes = vec![region_route.clone()];
2416            let table_info = test_utils::new_test_table_info_with_name(
2417                table_id,
2418                &format!("my_table_{}", table_id),
2419            );
2420            let table_route_value = TableRouteValue::physical(region_routes.clone());
2421
2422            tables_data.push((table_info, table_route_value));
2423        }
2424
2425        // creates metadata.
2426        table_metadata_manager
2427            .create_logical_tables_metadata(tables_data)
2428            .await
2429            .unwrap();
2430    }
2431
2432    #[tokio::test]
2433    async fn test_delete_table_metadata() {
2434        let mem_kv = Arc::new(MemoryKvBackend::default());
2435        let table_metadata_manager = TableMetadataManager::new(mem_kv);
2436        let region_route = new_test_region_route();
2437        let region_routes = &vec![region_route.clone()];
2438        let table_info = new_test_table_info();
2439        let table_id = table_info.ident.table_id;
2440        let datanode_id = 2;
2441        let region_wal_options = create_mock_region_wal_options();
2442        let serialized_region_wal_options = region_wal_options.clone();
2443
2444        // creates metadata.
2445        create_physical_table_metadata(
2446            &table_metadata_manager,
2447            table_info.clone(),
2448            region_routes.clone(),
2449            serialized_region_wal_options,
2450        )
2451        .await
2452        .unwrap();
2453
2454        let table_name = TableName::new(
2455            table_info.catalog_name,
2456            table_info.schema_name,
2457            table_info.name,
2458        );
2459        let table_route_value = &TableRouteValue::physical(region_routes.clone());
2460        // deletes metadata.
2461        table_metadata_manager
2462            .delete_table_metadata(
2463                table_id,
2464                &table_name,
2465                table_route_value,
2466                &region_wal_options,
2467                None,
2468            )
2469            .await
2470            .unwrap();
2471        // Should be ignored.
2472        table_metadata_manager
2473            .delete_table_metadata(
2474                table_id,
2475                &table_name,
2476                table_route_value,
2477                &region_wal_options,
2478                None,
2479            )
2480            .await
2481            .unwrap();
2482        assert!(
2483            table_metadata_manager
2484                .table_info_manager()
2485                .get(table_id)
2486                .await
2487                .unwrap()
2488                .is_none()
2489        );
2490        assert!(
2491            table_metadata_manager
2492                .table_route_manager()
2493                .table_route_storage()
2494                .get(table_id)
2495                .await
2496                .unwrap()
2497                .is_none()
2498        );
2499        assert!(
2500            table_metadata_manager
2501                .datanode_table_manager()
2502                .tables(datanode_id)
2503                .try_collect::<Vec<_>>()
2504                .await
2505                .unwrap()
2506                .is_empty()
2507        );
2508        // Checks removed values
2509        let table_info = table_metadata_manager
2510            .table_info_manager()
2511            .get(table_id)
2512            .await
2513            .unwrap();
2514        assert!(table_info.is_none());
2515        let table_route = table_metadata_manager
2516            .table_route_manager()
2517            .table_route_storage()
2518            .get(table_id)
2519            .await
2520            .unwrap();
2521        assert!(table_route.is_none());
2522        // Logical delete removes the topic region mapping as well.
2523        let regions = table_metadata_manager
2524            .topic_region_manager
2525            .regions("greptimedb_topic0")
2526            .await
2527            .unwrap();
2528        assert_eq!(regions.len(), 0);
2529        let regions = table_metadata_manager
2530            .topic_region_manager
2531            .regions("greptimedb_topic1")
2532            .await
2533            .unwrap();
2534        assert_eq!(regions.len(), 0);
2535    }
2536
2537    #[tokio::test]
2538    async fn test_rename_table() {
2539        let mem_kv = Arc::new(MemoryKvBackend::default());
2540        let table_metadata_manager = TableMetadataManager::new(mem_kv);
2541        let region_route = new_test_region_route();
2542        let region_routes = vec![region_route.clone()];
2543        let table_info = new_test_table_info();
2544        let table_id = table_info.ident.table_id;
2545        // creates metadata.
2546        create_physical_table_metadata(
2547            &table_metadata_manager,
2548            table_info.clone(),
2549            region_routes.clone(),
2550            HashMap::new(),
2551        )
2552        .await
2553        .unwrap();
2554
2555        let new_table_name = "another_name".to_string();
2556        let table_info_value =
2557            DeserializedValueWithBytes::from_inner(TableInfoValue::new(table_info.clone()));
2558
2559        table_metadata_manager
2560            .rename_table(&table_info_value, new_table_name.clone())
2561            .await
2562            .unwrap();
2563        // if remote metadata was updated, it should be ok.
2564        table_metadata_manager
2565            .rename_table(&table_info_value, new_table_name.clone())
2566            .await
2567            .unwrap();
2568        let mut modified_table_info = table_info.clone();
2569        modified_table_info.name = "hi".to_string();
2570        let modified_table_info_value =
2571            DeserializedValueWithBytes::from_inner(table_info_value.update(modified_table_info));
2572        // if the table_info_value is wrong, it should return an error.
2573        // The ABA problem.
2574        assert!(
2575            table_metadata_manager
2576                .rename_table(&modified_table_info_value, new_table_name.clone())
2577                .await
2578                .is_err()
2579        );
2580
2581        let old_table_name = TableNameKey::new(
2582            &table_info.catalog_name,
2583            &table_info.schema_name,
2584            &table_info.name,
2585        );
2586        let new_table_name = TableNameKey::new(
2587            &table_info.catalog_name,
2588            &table_info.schema_name,
2589            &new_table_name,
2590        );
2591
2592        assert!(
2593            table_metadata_manager
2594                .table_name_manager()
2595                .get(old_table_name)
2596                .await
2597                .unwrap()
2598                .is_none()
2599        );
2600
2601        assert_eq!(
2602            table_metadata_manager
2603                .table_name_manager()
2604                .get(new_table_name)
2605                .await
2606                .unwrap()
2607                .unwrap()
2608                .table_id(),
2609            table_id
2610        );
2611    }
2612
2613    #[tokio::test]
2614    async fn test_update_table_info() {
2615        let mem_kv = Arc::new(MemoryKvBackend::default());
2616        let table_metadata_manager = TableMetadataManager::new(mem_kv);
2617        let region_route = new_test_region_route();
2618        let region_routes = vec![region_route.clone()];
2619        let table_info = new_test_table_info();
2620        let table_id = table_info.ident.table_id;
2621        // creates metadata.
2622        create_physical_table_metadata(
2623            &table_metadata_manager,
2624            table_info.clone(),
2625            region_routes.clone(),
2626            HashMap::new(),
2627        )
2628        .await
2629        .unwrap();
2630
2631        let mut new_table_info = table_info.clone();
2632        new_table_info.name = "hi".to_string();
2633        let current_table_info_value =
2634            DeserializedValueWithBytes::from_inner(TableInfoValue::new(table_info.clone()));
2635        // should be ok.
2636        table_metadata_manager
2637            .update_table_info(&current_table_info_value, None, new_table_info.clone())
2638            .await
2639            .unwrap();
2640        // if table info was updated, it should be ok.
2641        table_metadata_manager
2642            .update_table_info(&current_table_info_value, None, new_table_info.clone())
2643            .await
2644            .unwrap();
2645
2646        // updated table_info should equal the `new_table_info`
2647        let updated_table_info = table_metadata_manager
2648            .table_info_manager()
2649            .get(table_id)
2650            .await
2651            .unwrap()
2652            .unwrap()
2653            .into_inner();
2654        assert_eq!(updated_table_info.table_info, new_table_info);
2655
2656        let mut wrong_table_info = table_info.clone();
2657        wrong_table_info.name = "wrong".to_string();
2658        let wrong_table_info_value = DeserializedValueWithBytes::from_inner(
2659            current_table_info_value.update(wrong_table_info),
2660        );
2661        // if the current_table_info_value is wrong, it should return an error.
2662        // The ABA problem.
2663        assert!(
2664            table_metadata_manager
2665                .update_table_info(&wrong_table_info_value, None, new_table_info)
2666                .await
2667                .is_err()
2668        )
2669    }
2670
2671    #[tokio::test]
2672    async fn test_update_table_leader_region_status() {
2673        let mem_kv = Arc::new(MemoryKvBackend::default());
2674        let table_metadata_manager = TableMetadataManager::new(mem_kv);
2675        let datanode = 1;
2676        let region_routes = vec![
2677            RegionRoute {
2678                region: Region {
2679                    id: 1.into(),
2680                    name: "r1".to_string(),
2681                    attrs: BTreeMap::new(),
2682                    partition_expr: Default::default(),
2683                },
2684                leader_peer: Some(Peer::new(datanode, "a2")),
2685                leader_state: Some(LeaderState::Downgrading),
2686                follower_peers: vec![],
2687                leader_down_since: Some(current_time_millis()),
2688                write_route_policy: None,
2689            },
2690            RegionRoute {
2691                region: Region {
2692                    id: 2.into(),
2693                    name: "r2".to_string(),
2694                    attrs: BTreeMap::new(),
2695                    partition_expr: Default::default(),
2696                },
2697                leader_peer: Some(Peer::new(datanode, "a1")),
2698                leader_state: None,
2699                follower_peers: vec![],
2700                leader_down_since: None,
2701                write_route_policy: None,
2702            },
2703        ];
2704        let table_info = new_test_table_info();
2705        let table_id = table_info.ident.table_id;
2706        let current_table_route_value = DeserializedValueWithBytes::from_inner(
2707            TableRouteValue::physical(region_routes.clone()),
2708        );
2709
2710        // creates metadata.
2711        create_physical_table_metadata(
2712            &table_metadata_manager,
2713            table_info.clone(),
2714            region_routes.clone(),
2715            HashMap::new(),
2716        )
2717        .await
2718        .unwrap();
2719
2720        table_metadata_manager
2721            .update_leader_region_status(table_id, &current_table_route_value, |region_route| {
2722                if region_route.leader_state.is_some() {
2723                    None
2724                } else {
2725                    Some(Some(LeaderState::Downgrading))
2726                }
2727            })
2728            .await
2729            .unwrap();
2730
2731        let updated_route_value = table_metadata_manager
2732            .table_route_manager()
2733            .table_route_storage()
2734            .get(table_id)
2735            .await
2736            .unwrap()
2737            .unwrap();
2738
2739        assert_eq!(
2740            updated_route_value.region_routes().unwrap()[0].leader_state,
2741            Some(LeaderState::Downgrading)
2742        );
2743
2744        assert!(
2745            updated_route_value.region_routes().unwrap()[0]
2746                .leader_down_since
2747                .is_some()
2748        );
2749
2750        assert_eq!(
2751            updated_route_value.region_routes().unwrap()[1].leader_state,
2752            Some(LeaderState::Downgrading)
2753        );
2754        assert!(
2755            updated_route_value.region_routes().unwrap()[1]
2756                .leader_down_since
2757                .is_some()
2758        );
2759    }
2760
2761    async fn assert_datanode_table(
2762        table_metadata_manager: &TableMetadataManager,
2763        table_id: u32,
2764        region_routes: &[RegionRoute],
2765    ) {
2766        let region_distribution = region_distribution(region_routes);
2767        for (datanode, regions) in region_distribution {
2768            let got = table_metadata_manager
2769                .datanode_table_manager()
2770                .get(&DatanodeTableKey::new(datanode, table_id))
2771                .await
2772                .unwrap()
2773                .unwrap();
2774
2775            assert_eq!(got.regions, regions.leader_regions);
2776            assert_eq!(got.follower_regions, regions.follower_regions);
2777        }
2778    }
2779
2780    #[tokio::test]
2781    async fn test_update_table_route() {
2782        let mem_kv = Arc::new(MemoryKvBackend::default());
2783        let table_metadata_manager = TableMetadataManager::new(mem_kv);
2784        let region_route = new_test_region_route();
2785        let region_routes = vec![region_route.clone()];
2786        let table_info = new_test_table_info();
2787        let table_id = table_info.ident.table_id;
2788        let engine = table_info.meta.engine.as_str();
2789        let region_storage_path =
2790            region_storage_path(&table_info.catalog_name, &table_info.schema_name);
2791        let current_table_route_value = DeserializedValueWithBytes::from_inner(
2792            TableRouteValue::physical(region_routes.clone()),
2793        );
2794
2795        // creates metadata.
2796        create_physical_table_metadata(
2797            &table_metadata_manager,
2798            table_info.clone(),
2799            region_routes.clone(),
2800            HashMap::new(),
2801        )
2802        .await
2803        .unwrap();
2804
2805        assert_datanode_table(&table_metadata_manager, table_id, &region_routes).await;
2806        let new_region_routes = vec![
2807            new_region_route(1, 1),
2808            new_region_route(2, 2),
2809            new_region_route(3, 3),
2810        ];
2811        // it should be ok.
2812        table_metadata_manager
2813            .update_table_route(
2814                table_id,
2815                RegionInfo {
2816                    engine: engine.to_string(),
2817                    region_storage_path: region_storage_path.clone(),
2818                    region_options: HashMap::new(),
2819                    region_wal_options: HashMap::new(),
2820                },
2821                &current_table_route_value,
2822                new_region_routes.clone(),
2823                &HashMap::new(),
2824                &HashMap::new(),
2825            )
2826            .await
2827            .unwrap();
2828        assert_datanode_table(&table_metadata_manager, table_id, &new_region_routes).await;
2829
2830        // if the table route was updated. it should be ok.
2831        table_metadata_manager
2832            .update_table_route(
2833                table_id,
2834                RegionInfo {
2835                    engine: engine.to_string(),
2836                    region_storage_path: region_storage_path.clone(),
2837                    region_options: HashMap::new(),
2838                    region_wal_options: HashMap::new(),
2839                },
2840                &current_table_route_value,
2841                new_region_routes.clone(),
2842                &HashMap::new(),
2843                &HashMap::new(),
2844            )
2845            .await
2846            .unwrap();
2847
2848        let current_table_route_value = DeserializedValueWithBytes::from_inner(
2849            current_table_route_value
2850                .inner
2851                .update(new_region_routes.clone())
2852                .unwrap(),
2853        );
2854        let new_region_routes = vec![new_region_route(2, 4), new_region_route(5, 5)];
2855        // it should be ok.
2856        table_metadata_manager
2857            .update_table_route(
2858                table_id,
2859                RegionInfo {
2860                    engine: engine.to_string(),
2861                    region_storage_path: region_storage_path.clone(),
2862                    region_options: HashMap::new(),
2863                    region_wal_options: HashMap::new(),
2864                },
2865                &current_table_route_value,
2866                new_region_routes.clone(),
2867                &HashMap::new(),
2868                &HashMap::new(),
2869            )
2870            .await
2871            .unwrap();
2872        assert_datanode_table(&table_metadata_manager, table_id, &new_region_routes).await;
2873
2874        // if the current_table_route_value is wrong, it should return an error.
2875        // The ABA problem.
2876        let wrong_table_route_value = DeserializedValueWithBytes::from_inner(
2877            current_table_route_value
2878                .update(vec![
2879                    new_region_route(1, 1),
2880                    new_region_route(2, 2),
2881                    new_region_route(3, 3),
2882                    new_region_route(4, 4),
2883                ])
2884                .unwrap(),
2885        );
2886        assert!(
2887            table_metadata_manager
2888                .update_table_route(
2889                    table_id,
2890                    RegionInfo {
2891                        engine: engine.to_string(),
2892                        region_storage_path: region_storage_path.clone(),
2893                        region_options: HashMap::new(),
2894                        region_wal_options: HashMap::new(),
2895                    },
2896                    &wrong_table_route_value,
2897                    new_region_routes,
2898                    &HashMap::new(),
2899                    &HashMap::new(),
2900                )
2901                .await
2902                .is_err()
2903        );
2904    }
2905
2906    #[tokio::test]
2907    async fn test_update_table_route_with_topic_region_mapping() {
2908        let mem_kv = Arc::new(MemoryKvBackend::default());
2909        let table_metadata_manager = TableMetadataManager::new(mem_kv.clone());
2910        let region_route = new_test_region_route();
2911        let region_routes = vec![region_route.clone()];
2912        let table_info = new_test_table_info();
2913        let table_id = table_info.ident.table_id;
2914        let engine = table_info.meta.engine.as_str();
2915        let region_storage_path =
2916            region_storage_path(&table_info.catalog_name, &table_info.schema_name);
2917
2918        // Create initial metadata with Kafka WAL options
2919        let old_region_wal_options: RegionWalOptions = vec![
2920            (
2921                1,
2922                WalOptions::Kafka(KafkaWalOptions::new("topic_1".to_string())),
2923            ),
2924            (
2925                2,
2926                WalOptions::Kafka(KafkaWalOptions::new("topic_2".to_string())),
2927            ),
2928        ]
2929        .into_iter()
2930        .collect();
2931
2932        create_physical_table_metadata(
2933            &table_metadata_manager,
2934            table_info.clone(),
2935            region_routes.clone(),
2936            old_region_wal_options.clone(),
2937        )
2938        .await
2939        .unwrap();
2940
2941        let current_table_route_value = DeserializedValueWithBytes::from_inner(
2942            TableRouteValue::physical(region_routes.clone()),
2943        );
2944
2945        // Verify initial topic region mappings exist
2946        let region_id_1 = RegionId::new(table_id, 1);
2947        let region_id_2 = RegionId::new(table_id, 2);
2948        let topic_1_key = TopicRegionKey::new(region_id_1, "topic_1");
2949        let topic_2_key = TopicRegionKey::new(region_id_2, "topic_2");
2950        assert!(
2951            table_metadata_manager
2952                .topic_region_manager
2953                .get(topic_1_key.clone())
2954                .await
2955                .unwrap()
2956                .is_some()
2957        );
2958        assert!(
2959            table_metadata_manager
2960                .topic_region_manager
2961                .get(topic_2_key.clone())
2962                .await
2963                .unwrap()
2964                .is_some()
2965        );
2966
2967        // Test 1: Add new region with new topic
2968        let new_region_routes = vec![
2969            new_region_route(1, 1),
2970            new_region_route(2, 2),
2971            new_region_route(3, 3), // New region
2972        ];
2973        let new_region_wal_options: RegionWalOptions = vec![
2974            (
2975                1,
2976                WalOptions::Kafka(KafkaWalOptions::new("topic_1".to_string())), // Unchanged
2977            ),
2978            (
2979                2,
2980                WalOptions::Kafka(KafkaWalOptions::new("topic_2".to_string())), // Unchanged
2981            ),
2982            (
2983                3,
2984                WalOptions::Kafka(KafkaWalOptions::new("topic_3".to_string())), // New topic
2985            ),
2986        ]
2987        .into_iter()
2988        .collect();
2989        let current_table_route_value_updated = DeserializedValueWithBytes::from_inner(
2990            current_table_route_value
2991                .inner
2992                .update(new_region_routes.clone())
2993                .unwrap(),
2994        );
2995        table_metadata_manager
2996            .update_table_route(
2997                table_id,
2998                RegionInfo {
2999                    engine: engine.to_string(),
3000                    region_storage_path: region_storage_path.clone(),
3001                    region_options: HashMap::new(),
3002                    region_wal_options: old_region_wal_options.clone(),
3003                },
3004                &current_table_route_value,
3005                new_region_routes.clone(),
3006                &HashMap::new(),
3007                &new_region_wal_options,
3008            )
3009            .await
3010            .unwrap();
3011        // Verify new topic region mapping was created
3012        let region_id_3 = RegionId::new(table_id, 3);
3013        let topic_3_key = TopicRegionKey::new(region_id_3, "topic_3");
3014        assert!(
3015            table_metadata_manager
3016                .topic_region_manager
3017                .get(topic_3_key)
3018                .await
3019                .unwrap()
3020                .is_some()
3021        );
3022        // Test 2: Remove a region and change topic for another
3023        let newer_region_routes = vec![
3024            new_region_route(1, 1),
3025            // Region 2 removed
3026            // Region 3 now has different topic
3027        ];
3028        let newer_region_wal_options: RegionWalOptions = vec![
3029            (
3030                1,
3031                WalOptions::Kafka(KafkaWalOptions::new("topic_1".to_string())), // Unchanged
3032            ),
3033            (
3034                3,
3035                WalOptions::Kafka(KafkaWalOptions::new("topic_3_new".to_string())), // Changed topic
3036            ),
3037        ]
3038        .into_iter()
3039        .collect();
3040        table_metadata_manager
3041            .update_table_route(
3042                table_id,
3043                RegionInfo {
3044                    engine: engine.to_string(),
3045                    region_storage_path: region_storage_path.clone(),
3046                    region_options: HashMap::new(),
3047                    region_wal_options: new_region_wal_options.clone(),
3048                },
3049                &current_table_route_value_updated,
3050                newer_region_routes.clone(),
3051                &HashMap::new(),
3052                &newer_region_wal_options,
3053            )
3054            .await
3055            .unwrap();
3056        // Verify region 2 mapping was deleted
3057        let topic_2_key_new = TopicRegionKey::new(region_id_2, "topic_2");
3058        assert!(
3059            table_metadata_manager
3060                .topic_region_manager
3061                .get(topic_2_key_new)
3062                .await
3063                .unwrap()
3064                .is_none()
3065        );
3066        // Verify region 3 old topic mapping was deleted
3067        let topic_3_key_old = TopicRegionKey::new(region_id_3, "topic_3");
3068        assert!(
3069            table_metadata_manager
3070                .topic_region_manager
3071                .get(topic_3_key_old)
3072                .await
3073                .unwrap()
3074                .is_none()
3075        );
3076        // Verify region 3 new topic mapping was created
3077        let topic_3_key_new = TopicRegionKey::new(region_id_3, "topic_3_new");
3078        assert!(
3079            table_metadata_manager
3080                .topic_region_manager
3081                .get(topic_3_key_new)
3082                .await
3083                .unwrap()
3084                .is_some()
3085        );
3086        // Verify region 1 mapping still exists (unchanged)
3087        assert!(
3088            table_metadata_manager
3089                .topic_region_manager
3090                .get(topic_1_key)
3091                .await
3092                .unwrap()
3093                .is_some()
3094        );
3095    }
3096
3097    #[tokio::test]
3098    async fn test_destroy_table_metadata() {
3099        let mem_kv = Arc::new(MemoryKvBackend::default());
3100        let table_metadata_manager = TableMetadataManager::new(mem_kv.clone());
3101        let table_id = 1025;
3102        let table_name = "foo";
3103        let task = test_create_table_task(table_name, table_id);
3104        let options = create_mixed_region_wal_options();
3105        let serialized_options = options.clone();
3106        table_metadata_manager
3107            .create_table_metadata(
3108                task.table_info,
3109                TableRouteValue::physical(vec![
3110                    RegionRoute {
3111                        region: Region::new_test(RegionId::new(table_id, 1)),
3112                        leader_peer: Some(Peer::empty(1)),
3113                        follower_peers: vec![Peer::empty(5)],
3114                        leader_state: None,
3115                        leader_down_since: None,
3116                        write_route_policy: None,
3117                    },
3118                    RegionRoute {
3119                        region: Region::new_test(RegionId::new(table_id, 2)),
3120                        leader_peer: Some(Peer::empty(2)),
3121                        follower_peers: vec![Peer::empty(4)],
3122                        leader_state: None,
3123                        leader_down_since: None,
3124                        write_route_policy: None,
3125                    },
3126                    RegionRoute {
3127                        region: Region::new_test(RegionId::new(table_id, 3)),
3128                        leader_peer: Some(Peer::empty(3)),
3129                        follower_peers: vec![],
3130                        leader_state: None,
3131                        leader_down_since: None,
3132                        write_route_policy: None,
3133                    },
3134                ]),
3135                serialized_options,
3136            )
3137            .await
3138            .unwrap();
3139        let table_name = TableName::new(DEFAULT_CATALOG_NAME, DEFAULT_SCHEMA_NAME, table_name);
3140        let table_route_value = table_metadata_manager
3141            .table_route_manager
3142            .table_route_storage()
3143            .get_with_raw_bytes(table_id)
3144            .await
3145            .unwrap()
3146            .unwrap();
3147        table_metadata_manager
3148            .destroy_table_metadata(table_id, &table_name, &table_route_value, &options)
3149            .await
3150            .unwrap();
3151        assert!(mem_kv.is_empty());
3152    }
3153
3154    #[tokio::test]
3155    async fn test_restore_table_metadata() {
3156        let mem_kv = Arc::new(MemoryKvBackend::default());
3157        let table_metadata_manager = TableMetadataManager::new(mem_kv.clone());
3158        let table_id = 1025;
3159        let table_name = "foo";
3160        let task = test_create_table_task(table_name, table_id);
3161        let options = create_mixed_region_wal_options();
3162        let serialized_options = options.clone();
3163        table_metadata_manager
3164            .create_table_metadata(
3165                task.table_info,
3166                TableRouteValue::physical(vec![
3167                    RegionRoute {
3168                        region: Region::new_test(RegionId::new(table_id, 1)),
3169                        leader_peer: Some(Peer::empty(1)),
3170                        follower_peers: vec![Peer::empty(5)],
3171                        leader_state: None,
3172                        leader_down_since: None,
3173                        write_route_policy: None,
3174                    },
3175                    RegionRoute {
3176                        region: Region::new_test(RegionId::new(table_id, 2)),
3177                        leader_peer: Some(Peer::empty(2)),
3178                        follower_peers: vec![Peer::empty(4)],
3179                        leader_state: None,
3180                        leader_down_since: None,
3181                        write_route_policy: None,
3182                    },
3183                    RegionRoute {
3184                        region: Region::new_test(RegionId::new(table_id, 3)),
3185                        leader_peer: Some(Peer::empty(3)),
3186                        follower_peers: vec![],
3187                        leader_state: None,
3188                        leader_down_since: None,
3189                        write_route_policy: None,
3190                    },
3191                ]),
3192                serialized_options,
3193            )
3194            .await
3195            .unwrap();
3196        let expected_result = mem_kv.dump();
3197        let table_route_value = table_metadata_manager
3198            .table_route_manager
3199            .table_route_storage()
3200            .get_with_raw_bytes(table_id)
3201            .await
3202            .unwrap()
3203            .unwrap();
3204        let region_routes = table_route_value.region_routes().unwrap();
3205        let table_name = TableName::new(DEFAULT_CATALOG_NAME, DEFAULT_SCHEMA_NAME, table_name);
3206        let table_route_value = TableRouteValue::physical(region_routes.clone());
3207        table_metadata_manager
3208            .delete_table_metadata(table_id, &table_name, &table_route_value, &options, None)
3209            .await
3210            .unwrap();
3211        table_metadata_manager
3212            .restore_table_metadata(table_id, &table_name, &table_route_value, &options)
3213            .await
3214            .unwrap();
3215        let kvs = mem_kv.dump();
3216        assert_eq!(kvs, expected_result);
3217        // Should be ignored.
3218        table_metadata_manager
3219            .restore_table_metadata(table_id, &table_name, &table_route_value, &options)
3220            .await
3221            .unwrap();
3222        let kvs = mem_kv.dump();
3223        assert_eq!(kvs, expected_result);
3224    }
3225
3226    #[tokio::test]
3227    async fn test_dropped_table_metadata_enumeration_and_lookup() {
3228        let table_id = 1025;
3229        let table_name = "foo";
3230        let (_, table_metadata_manager, table_name, table_info, region_routes, options) =
3231            create_dropped_physical_table_metadata(
3232                table_id,
3233                table_name,
3234                vec![
3235                    test_physical_region_route(table_id, 1, 1, vec![5]),
3236                    test_physical_region_route(table_id, 2, 2, vec![4]),
3237                    test_physical_region_route(table_id, 3, 3, vec![]),
3238                ],
3239                create_mixed_region_wal_options(),
3240            )
3241            .await;
3242
3243        let dropped_tables = table_metadata_manager.list_dropped_tables().await.unwrap();
3244        assert_eq!(dropped_tables.len(), 1);
3245        assert_eq!(dropped_tables[0].table_id, table_id);
3246        assert_eq!(dropped_tables[0].table_name, table_name);
3247
3248        let dropped_table = table_metadata_manager
3249            .get_dropped_table(&table_name)
3250            .await
3251            .unwrap()
3252            .unwrap();
3253        assert_dropped_table_metadata(
3254            &dropped_table,
3255            table_id,
3256            &table_name,
3257            &table_info,
3258            &region_routes,
3259            &options,
3260        );
3261
3262        let dropped_table_by_id = table_metadata_manager
3263            .get_dropped_table_by_id(table_id)
3264            .await
3265            .unwrap()
3266            .unwrap();
3267        assert_dropped_table_metadata(
3268            &dropped_table_by_id,
3269            table_id,
3270            &table_name,
3271            &table_info,
3272            &region_routes,
3273            &options,
3274        );
3275    }
3276
3277    #[tokio::test]
3278    async fn test_list_dropped_tables_batches_timestamp_lookup() {
3279        let mem_kv = Arc::new(MemoryKvBackend::default());
3280        let table_metadata_manager = TableMetadataManager::new(mem_kv.clone());
3281        for (table_id, table_name, dropped_at) in
3282            [(1025, "legacy", None), (1026, "marked", Some(1234))]
3283        {
3284            let task = test_create_table_task(table_name, table_id);
3285            let table_name = task.table_name();
3286            let table_route = TableRouteValue::physical(vec![]);
3287            table_metadata_manager
3288                .create_table_metadata(task.table_info, table_route.clone(), HashMap::new())
3289                .await
3290                .unwrap();
3291            table_metadata_manager
3292                .delete_table_metadata(
3293                    table_id,
3294                    &table_name,
3295                    &table_route,
3296                    &HashMap::new(),
3297                    dropped_at,
3298                )
3299                .await
3300                .unwrap();
3301        }
3302        let all_tombstones = mem_kv
3303            .range(RangeRequest::new().with_prefix("__tombstone/"))
3304            .await
3305            .unwrap()
3306            .kvs;
3307        let range_calls = Arc::new(AtomicUsize::new(0));
3308        let batch_get_calls = Arc::new(AtomicUsize::new(0));
3309        let mock = MockKvBackend {
3310            range_fn: Some({
3311                let all_tombstones = all_tombstones.clone();
3312                let range_calls = range_calls.clone();
3313                Arc::new(move |req| {
3314                    range_calls.fetch_add(1, Ordering::Relaxed);
3315                    let kvs = all_tombstones
3316                        .iter()
3317                        .filter(|kv| {
3318                            if req.range_end.is_empty() {
3319                                kv.key == req.key
3320                            } else {
3321                                kv.key >= req.key && kv.key < req.range_end
3322                            }
3323                        })
3324                        .cloned()
3325                        .collect();
3326                    Ok(RangeResponse { kvs, more: false })
3327                })
3328            }),
3329            range_async_fn: None,
3330            batch_get_fn: Some({
3331                let batch_get_calls = batch_get_calls.clone();
3332                Arc::new(move |req| {
3333                    batch_get_calls.fetch_add(1, Ordering::Relaxed);
3334                    let kvs = all_tombstones
3335                        .iter()
3336                        .filter(|kv| req.keys.contains(&kv.key))
3337                        .cloned()
3338                        .collect();
3339                    Ok(BatchGetResponse { kvs })
3340                })
3341            }),
3342            put_fn: None,
3343            batch_put_fn: None,
3344            delete_range_fn: None,
3345            batch_delete_fn: None,
3346            txn: None,
3347            max_txn_ops: None,
3348        };
3349        let table_metadata_manager = TableMetadataManager::new(Arc::new(mock));
3350
3351        let dropped_tables = table_metadata_manager.list_dropped_tables().await.unwrap();
3352
3353        assert_eq!(
3354            dropped_tables
3355                .iter()
3356                .map(|table| (table.table_id, table.dropped_at))
3357                .collect::<Vec<_>>(),
3358            vec![(1025, None), (1026, Some(1234))]
3359        );
3360        assert_eq!(range_calls.load(Ordering::Relaxed), 1);
3361        assert_eq!(batch_get_calls.load(Ordering::Relaxed), 1);
3362    }
3363
3364    #[tokio::test]
3365    async fn test_dropped_table_lookup_survives_live_name_recreation() {
3366        let dropped_table_id = 1025;
3367        let recreated_table_id = 1026;
3368        let table_name = "foo";
3369        let (
3370            _,
3371            table_metadata_manager,
3372            dropped_table_name,
3373            dropped_table_info,
3374            region_routes,
3375            options,
3376        ) = create_dropped_physical_table_metadata(
3377            dropped_table_id,
3378            table_name,
3379            vec![
3380                test_physical_region_route(dropped_table_id, 1, 1, vec![5]),
3381                test_physical_region_route(dropped_table_id, 2, 2, vec![4]),
3382            ],
3383            create_mock_region_wal_options(),
3384        )
3385        .await;
3386
3387        let recreated_task = test_create_table_task(table_name, recreated_table_id);
3388        table_metadata_manager
3389            .create_table_metadata(
3390                recreated_task.table_info,
3391                TableRouteValue::physical(vec![test_physical_region_route(
3392                    recreated_table_id,
3393                    1,
3394                    4,
3395                    vec![],
3396                )]),
3397                HashMap::new(),
3398            )
3399            .await
3400            .unwrap();
3401
3402        assert_eq!(
3403            table_metadata_manager
3404                .table_name_manager()
3405                .get(TableNameKey::from(&dropped_table_name))
3406                .await
3407                .unwrap()
3408                .unwrap()
3409                .table_id(),
3410            recreated_table_id
3411        );
3412
3413        let dropped_table = table_metadata_manager
3414            .get_dropped_table(&dropped_table_name)
3415            .await
3416            .unwrap()
3417            .unwrap();
3418        assert_dropped_table_metadata(
3419            &dropped_table,
3420            dropped_table_id,
3421            &dropped_table_name,
3422            &dropped_table_info,
3423            &region_routes,
3424            &options,
3425        );
3426
3427        let dropped_tables = table_metadata_manager.list_dropped_tables().await.unwrap();
3428        assert_eq!(dropped_tables.len(), 1);
3429        assert_eq!(dropped_tables[0].table_id, dropped_table_id);
3430        assert_eq!(dropped_tables[0].table_name, dropped_table_name);
3431    }
3432
3433    #[tokio::test]
3434    async fn test_dropped_table_exact_lookup_ignores_unrelated_malformed_table_name_tombstone() {
3435        let table_id = 1025;
3436        let table_name = "foo";
3437        let (mem_kv, table_metadata_manager, table_name, table_info, region_routes, options) =
3438            create_dropped_physical_table_metadata(
3439                table_id,
3440                table_name,
3441                vec![
3442                    test_physical_region_route(table_id, 1, 1, vec![5]),
3443                    test_physical_region_route(table_id, 2, 2, vec![4]),
3444                ],
3445                create_mixed_region_wal_options(),
3446            )
3447            .await;
3448
3449        mem_kv
3450            .put(
3451                PutRequest::new()
3452                    .with_key("__tombstone/__table_name/not-a-table-name-key")
3453                    .with_value("malformed"),
3454            )
3455            .await
3456            .unwrap();
3457
3458        let dropped_table = table_metadata_manager
3459            .get_dropped_table(&table_name)
3460            .await
3461            .unwrap()
3462            .unwrap();
3463        assert_dropped_table_metadata(
3464            &dropped_table,
3465            table_id,
3466            &table_name,
3467            &table_info,
3468            &region_routes,
3469            &options,
3470        );
3471    }
3472
3473    #[tokio::test]
3474    async fn test_dropped_table_exact_lookup_tracks_reused_name_after_purge() {
3475        let old_table_id = 1025;
3476        let new_table_id = 1026;
3477        let (_, manager, table_name, _, old_routes, old_options) =
3478            create_dropped_physical_table_metadata(
3479                old_table_id,
3480                "foo",
3481                vec![test_physical_region_route(old_table_id, 1, 1, vec![])],
3482                HashMap::new(),
3483            )
3484            .await;
3485
3486        manager
3487            .delete_table_metadata_tombstone(
3488                old_table_id,
3489                &table_name,
3490                &TableRouteValue::physical(old_routes),
3491                &old_options,
3492            )
3493            .await
3494            .unwrap();
3495        let new_task = test_create_table_task("foo", new_table_id);
3496        let new_info = new_task.table_info.clone();
3497        let new_route =
3498            TableRouteValue::physical(vec![test_physical_region_route(new_table_id, 1, 1, vec![])]);
3499        manager
3500            .create_table_metadata(new_task.table_info, new_route.clone(), HashMap::new())
3501            .await
3502            .unwrap();
3503        manager
3504            .delete_table_metadata(new_table_id, &table_name, &new_route, &HashMap::new(), None)
3505            .await
3506            .unwrap();
3507
3508        let dropped = manager
3509            .get_dropped_table(&table_name)
3510            .await
3511            .unwrap()
3512            .unwrap();
3513        assert_eq!(new_table_id, dropped.table_id);
3514        assert_eq!(new_info, dropped.table_info_value.table_info);
3515    }
3516
3517    #[tokio::test]
3518    async fn test_dropped_table_exact_lookup_missing() {
3519        let manager = TableMetadataManager::new(Arc::new(MemoryKvBackend::default()));
3520
3521        assert!(
3522            manager
3523                .get_dropped_table(&TableName::new("greptime", "public", "missing"))
3524                .await
3525                .unwrap()
3526                .is_none()
3527        );
3528    }
3529
3530    #[tokio::test]
3531    async fn test_create_update_view_info() {
3532        let mem_kv = Arc::new(MemoryKvBackend::default());
3533        let table_metadata_manager = TableMetadataManager::new(mem_kv);
3534
3535        let view_info = new_test_table_info();
3536
3537        let view_id = view_info.ident.table_id;
3538
3539        let logical_plan: Vec<u8> = vec![1, 2, 3];
3540        let columns = vec!["a".to_string()];
3541        let plan_columns = vec!["number".to_string()];
3542        let table_names = new_test_table_names();
3543        let definition = "CREATE VIEW test AS SELECT * FROM numbers";
3544
3545        // Create metadata
3546        table_metadata_manager
3547            .create_view_metadata(
3548                view_info.clone(),
3549                logical_plan.clone(),
3550                table_names.clone(),
3551                columns.clone(),
3552                plan_columns.clone(),
3553                definition.to_string(),
3554            )
3555            .await
3556            .unwrap();
3557
3558        {
3559            // assert view info
3560            let current_view_info = table_metadata_manager
3561                .view_info_manager()
3562                .get(view_id)
3563                .await
3564                .unwrap()
3565                .unwrap()
3566                .into_inner();
3567            assert_eq!(current_view_info.view_info, logical_plan);
3568            assert_eq!(current_view_info.table_names, table_names);
3569            assert_eq!(current_view_info.definition, definition);
3570            assert_eq!(current_view_info.columns, columns);
3571            assert_eq!(current_view_info.plan_columns, plan_columns);
3572            // assert table info
3573            let current_table_info = table_metadata_manager
3574                .table_info_manager()
3575                .get(view_id)
3576                .await
3577                .unwrap()
3578                .unwrap()
3579                .into_inner();
3580            assert_eq!(current_table_info.table_info, view_info);
3581        }
3582
3583        let new_logical_plan: Vec<u8> = vec![4, 5, 6];
3584        let new_table_names = {
3585            let mut set = HashSet::new();
3586            set.insert(TableName {
3587                catalog_name: "greptime".to_string(),
3588                schema_name: "public".to_string(),
3589                table_name: "b_table".to_string(),
3590            });
3591            set.insert(TableName {
3592                catalog_name: "greptime".to_string(),
3593                schema_name: "public".to_string(),
3594                table_name: "c_table".to_string(),
3595            });
3596            set
3597        };
3598        let new_columns = vec!["b".to_string()];
3599        let new_plan_columns = vec!["number2".to_string()];
3600        let new_definition = "CREATE VIEW test AS SELECT * FROM b_table join c_table";
3601
3602        let current_view_info_value = DeserializedValueWithBytes::from_inner(ViewInfoValue::new(
3603            logical_plan.clone().into(),
3604            table_names,
3605            columns,
3606            plan_columns,
3607            definition.to_string(),
3608        ));
3609        // should be ok.
3610        table_metadata_manager
3611            .update_view_info(
3612                view_id,
3613                &current_view_info_value,
3614                new_logical_plan.clone(),
3615                new_table_names.clone(),
3616                new_columns.clone(),
3617                new_plan_columns.clone(),
3618                new_definition.to_string(),
3619            )
3620            .await
3621            .unwrap();
3622        // if table info was updated, it should be ok.
3623        table_metadata_manager
3624            .update_view_info(
3625                view_id,
3626                &current_view_info_value,
3627                new_logical_plan.clone(),
3628                new_table_names.clone(),
3629                new_columns.clone(),
3630                new_plan_columns.clone(),
3631                new_definition.to_string(),
3632            )
3633            .await
3634            .unwrap();
3635
3636        // updated view_info should equal the `new_logical_plan`
3637        let updated_view_info = table_metadata_manager
3638            .view_info_manager()
3639            .get(view_id)
3640            .await
3641            .unwrap()
3642            .unwrap()
3643            .into_inner();
3644        assert_eq!(updated_view_info.view_info, new_logical_plan);
3645        assert_eq!(updated_view_info.table_names, new_table_names);
3646        assert_eq!(updated_view_info.definition, new_definition);
3647        assert_eq!(updated_view_info.columns, new_columns);
3648        assert_eq!(updated_view_info.plan_columns, new_plan_columns);
3649
3650        let wrong_view_info = logical_plan.clone();
3651        let wrong_definition = "wrong_definition";
3652        let wrong_view_info_value =
3653            DeserializedValueWithBytes::from_inner(current_view_info_value.update(
3654                wrong_view_info.into(),
3655                new_table_names.clone(),
3656                new_columns.clone(),
3657                new_plan_columns.clone(),
3658                wrong_definition.to_string(),
3659            ));
3660        // if the current_view_info_value is wrong, it should return an error.
3661        // The ABA problem.
3662        assert!(
3663            table_metadata_manager
3664                .update_view_info(
3665                    view_id,
3666                    &wrong_view_info_value,
3667                    new_logical_plan.clone(),
3668                    new_table_names.clone(),
3669                    vec!["c".to_string()],
3670                    vec!["number3".to_string()],
3671                    wrong_definition.to_string(),
3672                )
3673                .await
3674                .is_err()
3675        );
3676
3677        // The view_info is not changed.
3678        let current_view_info = table_metadata_manager
3679            .view_info_manager()
3680            .get(view_id)
3681            .await
3682            .unwrap()
3683            .unwrap()
3684            .into_inner();
3685        assert_eq!(current_view_info.view_info, new_logical_plan);
3686        assert_eq!(current_view_info.table_names, new_table_names);
3687        assert_eq!(current_view_info.definition, new_definition);
3688        assert_eq!(current_view_info.columns, new_columns);
3689        assert_eq!(current_view_info.plan_columns, new_plan_columns);
3690    }
3691
3692    #[test]
3693    fn test_region_role_set_deserialize() {
3694        let s = r#"{"leader_regions": [1, 2, 3], "follower_regions": [4, 5, 6]}"#;
3695        let region_role_set: RegionRoleSet = serde_json::from_str(s).unwrap();
3696        assert_eq!(region_role_set.leader_regions, vec![1, 2, 3]);
3697        assert_eq!(region_role_set.follower_regions, vec![4, 5, 6]);
3698
3699        let s = r#"[1, 2, 3]"#;
3700        let region_role_set: RegionRoleSet = serde_json::from_str(s).unwrap();
3701        assert_eq!(region_role_set.leader_regions, vec![1, 2, 3]);
3702        assert!(region_role_set.follower_regions.is_empty());
3703    }
3704
3705    #[test]
3706    fn test_region_distribution_deserialize() {
3707        let s = r#"{"1": [1,2,3], "2": {"leader_regions": [7, 8, 9], "follower_regions": [10, 11, 12]}}"#;
3708        let region_distribution: RegionDistribution = serde_json::from_str(s).unwrap();
3709        assert_eq!(region_distribution.len(), 2);
3710        assert_eq!(region_distribution[&1].leader_regions, vec![1, 2, 3]);
3711        assert!(region_distribution[&1].follower_regions.is_empty());
3712        assert_eq!(region_distribution[&2].leader_regions, vec![7, 8, 9]);
3713        assert_eq!(region_distribution[&2].follower_regions, vec![10, 11, 12]);
3714    }
3715}