1use crate::storage::{RegionId, RegionNumber, TableId};
19
20pub const WAL_DIR: &str = "wal/";
22
23pub const DATA_DIR: &str = "data/";
25
26pub const CLUSTER_DIR: &str = "cluster/";
28
29#[inline]
31pub fn region_name(table_id: TableId, region_number: RegionNumber) -> String {
32 format!("{table_id}_{region_number:010}")
33}
34
35#[inline]
36pub fn table_dir(path: &str, table_id: TableId) -> String {
37 format!("{DATA_DIR}{path}/{table_id}/")
38}
39
40pub fn region_dir(path: &str, region_id: RegionId) -> String {
41 format!(
42 "{}{}/",
43 table_dir(path, region_id.table_id()),
44 region_name(region_id.table_id(), region_id.region_number())
45 )
46}
47
48pub fn get_storage_path(region_dir: &str, region_id: RegionId) -> Option<String> {
61 if !region_dir.starts_with(DATA_DIR) {
62 return None;
63 }
64
65 let parts = format!(
67 "{}/{}",
68 region_id.table_id(),
69 region_name(region_id.table_id(), region_id.region_number())
70 );
71
72 let pos = region_dir.rfind(&parts)? - 1;
74
75 if pos < DATA_DIR.len() {
76 return None;
77 }
78
79 Some(region_dir[DATA_DIR.len()..pos].to_string())
80}
81
82#[cfg(test)]
83mod tests {
84 use common_meta::ddl::utils::{get_catalog_and_schema, region_storage_path};
85
86 use super::*;
87
88 fn catalog_and_schema(region_dir: &str, region_id: RegionId) -> Option<(String, String)> {
89 get_catalog_and_schema(&get_storage_path(region_dir, region_id)?)
90 }
91
92 #[test]
93 fn test_region_dir() {
94 let region_id = RegionId::new(42, 1);
95 assert_eq!(
96 region_dir("my_catalog/my_schema", region_id),
97 "data/my_catalog/my_schema/42/42_0000000001/"
98 );
99 }
100
101 #[test]
102 fn test_get_catalog_and_schema_from_region_dir() {
103 let tests = [
104 (RegionId::new(42, 1), "my_catalog", "my_schema"),
105 (RegionId::new(1234, 1), "my_catalog_1234", "my_schema_1234"),
106 (RegionId::new(5678, 1), "my_catalog_5678", "my_schema"),
107 (RegionId::new(5678, 1), "my_catalog", "my_schema_5678"),
108 ];
109
110 for (region_id, test_catalog, test_schema) in tests.iter() {
111 let region_dir = region_dir(
112 region_storage_path(test_catalog, test_schema).as_str(),
113 *region_id,
114 );
115 let (catalog, schema) = catalog_and_schema(®ion_dir, *region_id).unwrap();
116 assert_eq!(catalog, *test_catalog);
117 assert_eq!(schema, *test_schema);
118 }
119 }
120
121 #[test]
122 fn test_get_catalog_and_schema_from_invalid_region_dir() {
123 assert_eq!(
124 catalog_and_schema("invalid_data", RegionId::new(42, 1)),
125 None
126 );
127 }
128}