uqa_sql/semantics/partition/
identity.rs1use super::PartitionCatalog;
8use crate::SQLError;
9use std::collections::BTreeSet;
10pub fn partition_hierarchy_root(
11 catalog: &dyn PartitionCatalog,
12 table: &str,
13) -> Result<Option<String>, SQLError> {
14 let mut current = catalog
15 .try_resolve_table_name(table)
16 .map_err(|error| SQLError::Internal(format!("resolve table `{table}`: {error}")))?
17 .ok_or_else(|| SQLError::UnknownTable(table.to_string()))?;
18 let mut visited = BTreeSet::new();
19 let mut participates = false;
20 loop {
21 if !visited.insert(current.clone()) {
22 return Err(SQLError::Internal(format!(
23 "partition hierarchy cycle reaches `{current}`"
24 )));
25 }
26 let hierarchy = catalog
27 .try_table_hierarchy(¤t)
28 .map_err(|error| SQLError::Internal(format!("read partition hierarchy: {error}")))?;
29 participates |= hierarchy.partition_spec.is_some() || hierarchy.is_partition();
30 if !hierarchy.is_partition() {
31 return Ok(participates.then_some(current));
32 }
33 current = hierarchy
34 .parents
35 .first()
36 .cloned()
37 .ok_or_else(|| SQLError::Internal("partition has no parent relation".into()))?;
38 }
39}
40
41pub fn partition_identity_owner(
43 catalog: &dyn PartitionCatalog,
44 table: &str,
45) -> Result<String, SQLError> {
46 if let Some(root) = partition_hierarchy_root(catalog, table)? {
47 return Ok(root);
48 }
49 catalog
50 .try_resolve_table_name(table)
51 .map_err(|error| SQLError::Internal(format!("resolve table `{table}`: {error}")))?
52 .ok_or_else(|| SQLError::UnknownTable(table.to_string()))
53}